Changed adaptive stepping and non-saving Flow simulations no longer store frames
This commit is contained in:
parent
4b472d2200
commit
48e5ff5015
@ -56,7 +56,7 @@ There are currently three simulation modes, and the configuration changes slight
|
||||
Flow
|
||||
""""
|
||||
|
||||
This mode simulates the relaxing of the objects to its equilibrium. The threshold is the sufficient condition where the gradient is sufficiently close to zero. Specifically, the simulation stops when the L1 norm of the gradient divided by the number of objects is less than the threshold. The `step-size` parameter only represents the *initial* step size. If ``accel`` is set to ``true``, then adaptive step size is used to make convergence faster.
|
||||
This mode simulates the relaxing of the objects to its equilibrium. The threshold is the sufficient condition where the gradient is sufficiently close to zero. Specifically, the simulation stops when the L1 norm of the gradient divided by the number of objects is less than the threshold. The `step-size` parameter only represents the *initial* step size. If ``adaptive`` is set to ``true``, then adaptive step size is used to make convergence faster.
|
||||
|
||||
|
||||
.. code-block:: json
|
||||
@ -68,7 +68,7 @@ This mode simulates the relaxing of the objects to its equilibrium. The threshol
|
||||
"mode": "flow",
|
||||
"step_size": 0.05,
|
||||
"threshold": 0.0001,
|
||||
"accel": true
|
||||
"adaptive": true
|
||||
},
|
||||
...
|
||||
}
|
||||
@ -87,7 +87,7 @@ This mode searches for equilibrium until `eq_stop_count` equilibria are found. A
|
||||
"mode": "search",
|
||||
"step_size": 0.05,
|
||||
"threshold": 0.0001,
|
||||
"accel": true,
|
||||
"adaptive": true,
|
||||
"eq_stop_count": 100,
|
||||
"manifold_step_size": 0.1
|
||||
},
|
||||
@ -109,7 +109,7 @@ This mode simulates the the change in the equilibrium as the width is decreased.
|
||||
"mode": "shrink",
|
||||
"step_size": 0.05,
|
||||
"threshold": 0.0001,
|
||||
"accel": true,
|
||||
"adaptive": true,
|
||||
"width_change": 1,
|
||||
"width_stop": 0.3
|
||||
},
|
||||
|
||||
@ -10,6 +10,7 @@ import squish.ordered as order
|
||||
from squish import Simulation, DomainParams
|
||||
from squish.common import OUTPUT_DIR
|
||||
|
||||
|
||||
def order_process(domain: DomainParams) -> Tuple[float, float, float]:
|
||||
energies = []
|
||||
configs = order.configurations(domain)
|
||||
|
||||
@ -658,24 +658,7 @@ cdef class VoronoiContainer:
|
||||
).gradient
|
||||
|
||||
return (step/2)*(k1+k2), k1
|
||||
# k1 = self.gradient
|
||||
|
||||
# k2 = self.__class__(self.n, self.w, self.h, self.r,
|
||||
# self.add_sites(step*k1/2)
|
||||
# ).gradient
|
||||
|
||||
# lower = step*(-k1+ 2*k2)
|
||||
# k3 = self.__class__(self.n, self.w, self.h, self.r,
|
||||
# self.add_sites(lower)
|
||||
# ).gradient
|
||||
|
||||
# higher = (step/6)*(k1+2*k2+k3)
|
||||
|
||||
|
||||
#new_sites = self.add_sites(higher)
|
||||
#error = higher - lower
|
||||
|
||||
#return higher, k1
|
||||
|
||||
def hessian(self, d: float) -> np.ndarray:
|
||||
"""
|
||||
|
||||
@ -2,6 +2,7 @@ from __future__ import annotations
|
||||
from typing import Optional
|
||||
|
||||
import pickle, numpy as np
|
||||
from math import log10
|
||||
from scipy.linalg import null_space
|
||||
from timeit import default_timer as timer
|
||||
|
||||
@ -149,18 +150,18 @@ class Flow(Simulation):
|
||||
frames (List[VoronoiContainer]): stores frames of the simulation.
|
||||
step_size (float): size fo step by for each iteration.
|
||||
thres (float): threshold for the stopping condition.
|
||||
accel (bool): set to True if accelerated stepping is desired.
|
||||
adaptive (bool): set to True if adaptive stepping is desired.
|
||||
|
||||
"""
|
||||
|
||||
__slots__ = ['step_size', 'thres', 'accel']
|
||||
__slots__ = ['step_size', 'thres', 'adaptive']
|
||||
attr_str = "flow"
|
||||
title_str = "Flow"
|
||||
|
||||
def __init__(self, domain: DomainParams, energy: Energy, step_size: float, thres: float,
|
||||
accel: bool, name: Optional[str] = None) -> None:
|
||||
adaptive: bool, name: Optional[str] = None) -> None:
|
||||
super().__init__(domain, energy, name=name)
|
||||
self.step_size, self.thres, self.accel = step_size, thres, accel
|
||||
self.step_size, self.thres, self.adaptive = step_size, thres, adaptive
|
||||
|
||||
|
||||
@property
|
||||
@ -171,7 +172,7 @@ class Flow(Simulation):
|
||||
"energy": self.energy.attr_str,
|
||||
"step_size": self.step_size,
|
||||
"thres": self.thres,
|
||||
"accel": self.accel
|
||||
"adaptive": self.adaptive
|
||||
}
|
||||
return info
|
||||
|
||||
@ -181,49 +182,40 @@ class Flow(Simulation):
|
||||
if save: self.save(self.initial_data, True)
|
||||
if len(self) == 0: self.add_frame()
|
||||
|
||||
i, grad_norm = 0, float('inf')
|
||||
i, stop = 0, False
|
||||
|
||||
trial = 2
|
||||
while grad_norm > self.thres: # Get to threshold.
|
||||
if save: self.save(self.frame_data(i))
|
||||
while not stop: # Get to threshold.
|
||||
if save:
|
||||
self.save(self.frame_data(i))
|
||||
frame = self[i]
|
||||
else:
|
||||
frame = self[0]
|
||||
|
||||
# Iterate and generate next frame using RK-2
|
||||
start = timer()
|
||||
change, grad = self[i].iterate(self.step_size)
|
||||
new_frame = self.energy.mode(*self.domain, self[i].add_sites(change))
|
||||
change, grad = frame.iterate(self.step_size)
|
||||
|
||||
new_frame = self.energy.mode(*self.domain, frame.add_sites(change))
|
||||
grad_norm = np.linalg.norm(grad)
|
||||
end = timer()
|
||||
|
||||
if self.accel:
|
||||
if new_frame.energy < self[i].energy: # If energy decreases.
|
||||
if trial < 10: # Try increasing step size for 10 times.
|
||||
factor = 1 + .1**trial
|
||||
if self.adaptive:
|
||||
error = change - grad*self.step_size
|
||||
tol = 10**min(-3, -2+log10(grad_norm))
|
||||
|
||||
test_frame = self.energy.mode(*self.domain,
|
||||
self[i].add_sites(change*factor))
|
||||
# If increased step has less energy than original step.
|
||||
if test_frame.energy < new_frame.energy:
|
||||
self.step_size *= factor
|
||||
trial = max(2, trial-1)
|
||||
new_frame = test_frame
|
||||
else: # Otherwise, increases trials, and use original.
|
||||
trial += 1
|
||||
else: # Step size too large, decrease and reset trial counter.
|
||||
trial = 2
|
||||
shrink_factor = 1.5
|
||||
new_frame = self.energy.mode(*self.domain,
|
||||
self[i].add_sites(change/shrink_factor))
|
||||
self.step_size /= shrink_factor
|
||||
self.step_size *= (tol/np.linalg.norm(error))**.5
|
||||
|
||||
self.step_size = max(10e-6, self.step_size)
|
||||
if not save:
|
||||
del self.frames[0]
|
||||
|
||||
self.frames.append(new_frame)
|
||||
stop = grad_norm < self.thres
|
||||
|
||||
i += 1
|
||||
if(log and i % log_steps == 0):
|
||||
print(f'Iteration: {i:05} | Energy: {self[i].energy: .5f}' + \
|
||||
f' | Gradient: {grad_norm:.8f} | Step: {self.step_size: .5f} | ' + \
|
||||
f'Time: {end-start: .3f}', flush=True)
|
||||
if (log and i % log_steps == 0) or stop:
|
||||
print(f'Iteration: {i:05} | Energy: {frame.energy: .5f}' + \
|
||||
f' | Gradient: {grad_norm:.8f} | Step: {self.step_size: .5f} | ' + \
|
||||
f'Time: {end-start: .3f} |', flush=True)
|
||||
|
||||
|
||||
|
||||
@ -237,21 +229,21 @@ class Search(Simulation):
|
||||
frames (List[VoronoiContainer]): stores frames of the simulation.
|
||||
step_size (float): size fo step by for each iteration.
|
||||
thres (float): threshold for the stopping condition.
|
||||
accel (bool): set to True if accelerated stepping is desired.
|
||||
adaptive (bool): set to True if adaptive stepping is desired.
|
||||
kernel_step (float): size to step on manifold if nullity of hessian > 2.
|
||||
count (int): number of equilibria to find.
|
||||
|
||||
"""
|
||||
|
||||
__slots__ = ['step_size', 'thres', 'accel', 'kernel_step', 'count']
|
||||
__slots__ = ['step_size', 'thres', 'adaptive', 'kernel_step', 'count']
|
||||
attr_str = "search"
|
||||
title_str = "Search"
|
||||
|
||||
def __init__(self, domain: DomainParams, energy: Energy, step_size: float, thres: float,
|
||||
accel: bool, kernel_step: float, count: int,
|
||||
adaptive: bool, kernel_step: float, count: int,
|
||||
name: Optional[str] = None) -> None:
|
||||
super().__init__(domain, energy, name=name)
|
||||
self.step_size, self.thres, self.accel = step_size, thres, accel
|
||||
self.step_size, self.thres, self.adaptive = step_size, thres, adaptive
|
||||
self.kernel_step, self.count = kernel_step, count
|
||||
|
||||
|
||||
@ -263,7 +255,7 @@ class Search(Simulation):
|
||||
"energy": self.energy.attr_str,
|
||||
"step_size": self.step_size,
|
||||
"thres": self.thres,
|
||||
"accel": self.accel,
|
||||
"adaptive": self.adaptive,
|
||||
"kernel_step": self.kernel_step,
|
||||
"count": self.count
|
||||
}
|
||||
@ -282,7 +274,7 @@ class Search(Simulation):
|
||||
|
||||
for i in range(self.count):
|
||||
# Get to equilibrium.
|
||||
sim = Flow(self.domain, self.energy, self.step_size, self.thres, self.accel)
|
||||
sim = Flow(self.domain, self.energy, self.step_size, self.thres, self.adaptive)
|
||||
sim.add_frame(new_sites)
|
||||
sim.run(False, log, log_steps)
|
||||
|
||||
@ -317,22 +309,22 @@ class Shrink(Simulation):
|
||||
frames (List[VoronoiContainer]): stores frames of the simulation.
|
||||
step_size (float): size fo step by for each iteration.
|
||||
thres (float): threshold for the stopping condition.
|
||||
accel (bool): set to True if accelerated stepping is desired.
|
||||
adaptive (bool): set to True if adaptive stepping is desired.
|
||||
delta (float): percent to change w each iteration.
|
||||
stop_width (float): percent at which to stop iterating.
|
||||
|
||||
"""
|
||||
|
||||
__slots__ = ['step_size', 'thres', 'accel', 'delta', 'stop_width']
|
||||
__slots__ = ['step_size', 'thres', 'adaptive', 'delta', 'stop_width']
|
||||
attr_str = "shrink"
|
||||
title_str = "Shrink"
|
||||
|
||||
|
||||
def __init__(self, domain: DomainParams, energy: Energy, step_size: float, thres: float,
|
||||
accel: bool, delta: float, stop_width: float,
|
||||
adaptive: bool, delta: float, stop_width: float,
|
||||
name: Optional[str] = None) -> None:
|
||||
super().__init__(domain, energy, name=name)
|
||||
self.step_size, self.thres, self.accel = step_size, thres, accel
|
||||
self.step_size, self.thres, self.adaptive = step_size, thres, adaptive
|
||||
self.delta, self.stop_width = self.domain.w*delta/100, self.domain.w*stop_width
|
||||
|
||||
|
||||
@ -344,7 +336,7 @@ class Shrink(Simulation):
|
||||
"energy": self.energy.attr_str,
|
||||
"step_size": self.step_size,
|
||||
"thres": self.thres,
|
||||
"accel": self.accel,
|
||||
"adaptive": self.adaptive,
|
||||
"delta": self.delta,
|
||||
"stop_width": self.stop_width
|
||||
}
|
||||
@ -366,7 +358,7 @@ class Shrink(Simulation):
|
||||
while width >= self.stop_width:
|
||||
# Get to equilibrium.
|
||||
new_domain = DomainParams(self.domain.n, width, self.domain.h, self.domain.r)
|
||||
sim = Flow(new_domain, self.energy, self.step_size, self.thres, self.accel)
|
||||
sim = Flow(new_domain, self.energy, self.step_size, self.thres, self.adaptive)
|
||||
sim.add_frame(new_sites)
|
||||
sim.run(False, log, log_steps)
|
||||
new_sites = sim[-1].site_arr
|
||||
|
||||
@ -96,28 +96,28 @@ def config_sim(args):
|
||||
else:
|
||||
points = np.asarray(dmn_params["points"])
|
||||
|
||||
check_params(sim_params, ["mode", "step_size", "threshold", "save_sim", "accel"], {
|
||||
check_params(sim_params, ["mode", "step_size", "threshold", "save_sim", "adaptive"], {
|
||||
"mode": ["flow", "search", "shrink"], "step_size": "positive", "threshold": "positive",
|
||||
})
|
||||
mode, step, thres, accel, save_sim = sim_params["mode"], sim_params["step_size"], \
|
||||
sim_params["threshold"], sim_params["accel"], \
|
||||
mode, step, thres, adaptive, save_sim = sim_params["mode"], sim_params["step_size"], \
|
||||
sim_params["threshold"], sim_params["adaptive"], \
|
||||
sim_params["save_sim"]
|
||||
|
||||
name = sim_params.get("name")
|
||||
|
||||
if mode == "flow":
|
||||
sim = Flow(domain, energy, step, thres, accel, name=name)
|
||||
sim = Flow(domain, energy, step, thres, adaptive, name=name)
|
||||
elif mode == "search":
|
||||
check_params(sim_params, ["manifold_step_size", "eq_stop_count"], {
|
||||
"manifold_step_size": "positive", "eq_stop_count": "positive"
|
||||
})
|
||||
sim = Search(domain, energy, step, thres, accel, sim_params["manifold_step_size"],
|
||||
sim = Search(domain, energy, step, thres, adaptive, sim_params["manifold_step_size"],
|
||||
sim_params["eq_stop_count"], name=name)
|
||||
elif mode == "shrink":
|
||||
check_params(sim_params, ["width_change", "width_stop"], {
|
||||
"width_change": "positive", "width_stop": "positive"
|
||||
})
|
||||
sim = Shrink(domain, energy, step, thres, accel, sim_params["width_change"],
|
||||
sim = Shrink(domain, energy, step, thres, adaptive, sim_params["width_change"],
|
||||
sim_params["width_stop"], name=name)
|
||||
|
||||
save_diagram = False
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user