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
|
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
|
.. code-block:: json
|
||||||
@ -68,7 +68,7 @@ This mode simulates the relaxing of the objects to its equilibrium. The threshol
|
|||||||
"mode": "flow",
|
"mode": "flow",
|
||||||
"step_size": 0.05,
|
"step_size": 0.05,
|
||||||
"threshold": 0.0001,
|
"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",
|
"mode": "search",
|
||||||
"step_size": 0.05,
|
"step_size": 0.05,
|
||||||
"threshold": 0.0001,
|
"threshold": 0.0001,
|
||||||
"accel": true,
|
"adaptive": true,
|
||||||
"eq_stop_count": 100,
|
"eq_stop_count": 100,
|
||||||
"manifold_step_size": 0.1
|
"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",
|
"mode": "shrink",
|
||||||
"step_size": 0.05,
|
"step_size": 0.05,
|
||||||
"threshold": 0.0001,
|
"threshold": 0.0001,
|
||||||
"accel": true,
|
"adaptive": true,
|
||||||
"width_change": 1,
|
"width_change": 1,
|
||||||
"width_stop": 0.3
|
"width_stop": 0.3
|
||||||
},
|
},
|
||||||
|
|||||||
@ -10,6 +10,7 @@ import squish.ordered as order
|
|||||||
from squish import Simulation, DomainParams
|
from squish import Simulation, DomainParams
|
||||||
from squish.common import OUTPUT_DIR
|
from squish.common import OUTPUT_DIR
|
||||||
|
|
||||||
|
|
||||||
def order_process(domain: DomainParams) -> Tuple[float, float, float]:
|
def order_process(domain: DomainParams) -> Tuple[float, float, float]:
|
||||||
energies = []
|
energies = []
|
||||||
configs = order.configurations(domain)
|
configs = order.configurations(domain)
|
||||||
|
|||||||
@ -658,24 +658,7 @@ cdef class VoronoiContainer:
|
|||||||
).gradient
|
).gradient
|
||||||
|
|
||||||
return (step/2)*(k1+k2), k1
|
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:
|
def hessian(self, d: float) -> np.ndarray:
|
||||||
"""
|
"""
|
||||||
|
|||||||
@ -2,6 +2,7 @@ from __future__ import annotations
|
|||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
import pickle, numpy as np
|
import pickle, numpy as np
|
||||||
|
from math import log10
|
||||||
from scipy.linalg import null_space
|
from scipy.linalg import null_space
|
||||||
from timeit import default_timer as timer
|
from timeit import default_timer as timer
|
||||||
|
|
||||||
@ -149,18 +150,18 @@ class Flow(Simulation):
|
|||||||
frames (List[VoronoiContainer]): stores frames of the simulation.
|
frames (List[VoronoiContainer]): stores frames of the simulation.
|
||||||
step_size (float): size fo step by for each iteration.
|
step_size (float): size fo step by for each iteration.
|
||||||
thres (float): threshold for the stopping condition.
|
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"
|
attr_str = "flow"
|
||||||
title_str = "Flow"
|
title_str = "Flow"
|
||||||
|
|
||||||
def __init__(self, domain: DomainParams, energy: Energy, step_size: float, thres: float,
|
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)
|
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
|
@property
|
||||||
@ -171,7 +172,7 @@ class Flow(Simulation):
|
|||||||
"energy": self.energy.attr_str,
|
"energy": self.energy.attr_str,
|
||||||
"step_size": self.step_size,
|
"step_size": self.step_size,
|
||||||
"thres": self.thres,
|
"thres": self.thres,
|
||||||
"accel": self.accel
|
"adaptive": self.adaptive
|
||||||
}
|
}
|
||||||
return info
|
return info
|
||||||
|
|
||||||
@ -181,49 +182,40 @@ class Flow(Simulation):
|
|||||||
if save: self.save(self.initial_data, True)
|
if save: self.save(self.initial_data, True)
|
||||||
if len(self) == 0: self.add_frame()
|
if len(self) == 0: self.add_frame()
|
||||||
|
|
||||||
i, grad_norm = 0, float('inf')
|
i, stop = 0, False
|
||||||
|
|
||||||
trial = 2
|
while not stop: # Get to threshold.
|
||||||
while grad_norm > self.thres: # Get to threshold.
|
if save:
|
||||||
if save: self.save(self.frame_data(i))
|
self.save(self.frame_data(i))
|
||||||
|
frame = self[i]
|
||||||
|
else:
|
||||||
|
frame = self[0]
|
||||||
|
|
||||||
# Iterate and generate next frame using RK-2
|
# Iterate and generate next frame using RK-2
|
||||||
start = timer()
|
start = timer()
|
||||||
change, grad = self[i].iterate(self.step_size)
|
change, grad = frame.iterate(self.step_size)
|
||||||
new_frame = self.energy.mode(*self.domain, self[i].add_sites(change))
|
|
||||||
|
new_frame = self.energy.mode(*self.domain, frame.add_sites(change))
|
||||||
grad_norm = np.linalg.norm(grad)
|
grad_norm = np.linalg.norm(grad)
|
||||||
end = timer()
|
end = timer()
|
||||||
|
|
||||||
if self.accel:
|
if self.adaptive:
|
||||||
if new_frame.energy < self[i].energy: # If energy decreases.
|
error = change - grad*self.step_size
|
||||||
if trial < 10: # Try increasing step size for 10 times.
|
tol = 10**min(-3, -2+log10(grad_norm))
|
||||||
factor = 1 + .1**trial
|
|
||||||
|
|
||||||
test_frame = self.energy.mode(*self.domain,
|
self.step_size *= (tol/np.linalg.norm(error))**.5
|
||||||
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 = max(10e-6, self.step_size)
|
if not save:
|
||||||
|
del self.frames[0]
|
||||||
|
|
||||||
self.frames.append(new_frame)
|
self.frames.append(new_frame)
|
||||||
|
stop = grad_norm < self.thres
|
||||||
|
|
||||||
i += 1
|
i += 1
|
||||||
if(log and i % log_steps == 0):
|
if (log and i % log_steps == 0) or stop:
|
||||||
print(f'Iteration: {i:05} | Energy: {self[i].energy: .5f}' + \
|
print(f'Iteration: {i:05} | Energy: {frame.energy: .5f}' + \
|
||||||
f' | Gradient: {grad_norm:.8f} | Step: {self.step_size: .5f} | ' + \
|
f' | Gradient: {grad_norm:.8f} | Step: {self.step_size: .5f} | ' + \
|
||||||
f'Time: {end-start: .3f}', flush=True)
|
f'Time: {end-start: .3f} |', flush=True)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -237,21 +229,21 @@ class Search(Simulation):
|
|||||||
frames (List[VoronoiContainer]): stores frames of the simulation.
|
frames (List[VoronoiContainer]): stores frames of the simulation.
|
||||||
step_size (float): size fo step by for each iteration.
|
step_size (float): size fo step by for each iteration.
|
||||||
thres (float): threshold for the stopping condition.
|
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.
|
kernel_step (float): size to step on manifold if nullity of hessian > 2.
|
||||||
count (int): number of equilibria to find.
|
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"
|
attr_str = "search"
|
||||||
title_str = "Search"
|
title_str = "Search"
|
||||||
|
|
||||||
def __init__(self, domain: DomainParams, energy: Energy, step_size: float, thres: float,
|
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:
|
name: Optional[str] = None) -> None:
|
||||||
super().__init__(domain, energy, name=name)
|
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
|
self.kernel_step, self.count = kernel_step, count
|
||||||
|
|
||||||
|
|
||||||
@ -263,7 +255,7 @@ class Search(Simulation):
|
|||||||
"energy": self.energy.attr_str,
|
"energy": self.energy.attr_str,
|
||||||
"step_size": self.step_size,
|
"step_size": self.step_size,
|
||||||
"thres": self.thres,
|
"thres": self.thres,
|
||||||
"accel": self.accel,
|
"adaptive": self.adaptive,
|
||||||
"kernel_step": self.kernel_step,
|
"kernel_step": self.kernel_step,
|
||||||
"count": self.count
|
"count": self.count
|
||||||
}
|
}
|
||||||
@ -282,7 +274,7 @@ class Search(Simulation):
|
|||||||
|
|
||||||
for i in range(self.count):
|
for i in range(self.count):
|
||||||
# Get to equilibrium.
|
# 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.add_frame(new_sites)
|
||||||
sim.run(False, log, log_steps)
|
sim.run(False, log, log_steps)
|
||||||
|
|
||||||
@ -317,22 +309,22 @@ class Shrink(Simulation):
|
|||||||
frames (List[VoronoiContainer]): stores frames of the simulation.
|
frames (List[VoronoiContainer]): stores frames of the simulation.
|
||||||
step_size (float): size fo step by for each iteration.
|
step_size (float): size fo step by for each iteration.
|
||||||
thres (float): threshold for the stopping condition.
|
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.
|
delta (float): percent to change w each iteration.
|
||||||
stop_width (float): percent at which to stop iterating.
|
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"
|
attr_str = "shrink"
|
||||||
title_str = "Shrink"
|
title_str = "Shrink"
|
||||||
|
|
||||||
|
|
||||||
def __init__(self, domain: DomainParams, energy: Energy, step_size: float, thres: float,
|
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:
|
name: Optional[str] = None) -> None:
|
||||||
super().__init__(domain, energy, name=name)
|
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
|
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,
|
"energy": self.energy.attr_str,
|
||||||
"step_size": self.step_size,
|
"step_size": self.step_size,
|
||||||
"thres": self.thres,
|
"thres": self.thres,
|
||||||
"accel": self.accel,
|
"adaptive": self.adaptive,
|
||||||
"delta": self.delta,
|
"delta": self.delta,
|
||||||
"stop_width": self.stop_width
|
"stop_width": self.stop_width
|
||||||
}
|
}
|
||||||
@ -366,7 +358,7 @@ class Shrink(Simulation):
|
|||||||
while width >= self.stop_width:
|
while width >= self.stop_width:
|
||||||
# Get to equilibrium.
|
# Get to equilibrium.
|
||||||
new_domain = DomainParams(self.domain.n, width, self.domain.h, self.domain.r)
|
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.add_frame(new_sites)
|
||||||
sim.run(False, log, log_steps)
|
sim.run(False, log, log_steps)
|
||||||
new_sites = sim[-1].site_arr
|
new_sites = sim[-1].site_arr
|
||||||
|
|||||||
@ -96,28 +96,28 @@ def config_sim(args):
|
|||||||
else:
|
else:
|
||||||
points = np.asarray(dmn_params["points"])
|
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": ["flow", "search", "shrink"], "step_size": "positive", "threshold": "positive",
|
||||||
})
|
})
|
||||||
mode, step, thres, accel, save_sim = sim_params["mode"], sim_params["step_size"], \
|
mode, step, thres, adaptive, save_sim = sim_params["mode"], sim_params["step_size"], \
|
||||||
sim_params["threshold"], sim_params["accel"], \
|
sim_params["threshold"], sim_params["adaptive"], \
|
||||||
sim_params["save_sim"]
|
sim_params["save_sim"]
|
||||||
|
|
||||||
name = sim_params.get("name")
|
name = sim_params.get("name")
|
||||||
|
|
||||||
if mode == "flow":
|
if mode == "flow":
|
||||||
sim = Flow(domain, energy, step, thres, accel, name=name)
|
sim = Flow(domain, energy, step, thres, adaptive, name=name)
|
||||||
elif mode == "search":
|
elif mode == "search":
|
||||||
check_params(sim_params, ["manifold_step_size", "eq_stop_count"], {
|
check_params(sim_params, ["manifold_step_size", "eq_stop_count"], {
|
||||||
"manifold_step_size": "positive", "eq_stop_count": "positive"
|
"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)
|
sim_params["eq_stop_count"], name=name)
|
||||||
elif mode == "shrink":
|
elif mode == "shrink":
|
||||||
check_params(sim_params, ["width_change", "width_stop"], {
|
check_params(sim_params, ["width_change", "width_stop"], {
|
||||||
"width_change": "positive", "width_stop": "positive"
|
"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)
|
sim_params["width_stop"], name=name)
|
||||||
|
|
||||||
save_diagram = False
|
save_diagram = False
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user