Added more detail to shrink diagrams and fixed unique equilibria detection for ordered equilibria.

This commit is contained in:
Kenneth Jao 2021-09-19 02:57:30 -04:00
parent a283a31755
commit 61c2862fb9
2 changed files with 74 additions and 57 deletions

View File

@ -1,7 +1,8 @@
from __future__ import annotations
from typing import List
import os, argparse, numpy as np, pickle
import os, math, argparse, numpy as np, pickle
import matplotlib.pyplot as plt
import matplotlib.ticker as mtick
from pathlib import Path
from simulation import Diagram, Simulation
@ -59,38 +60,31 @@ def get_equilibria_data(filepath: Path):
with open(filepath, "rb") as data:
return pickle.load(data)
sims = []
data = {"all": {}, "distinct": {}}
files = list(Path(filepath).iterdir())
for i, file in enumerate(files):
sims.append(Simulation.load(file))
sim = Simulation.load(file)
data["all"][sim.w] = []
for frame in sim.frames:
data["all"][sim.w].append([frame.energy, np.var(frame.stats["avg_radius"]) <= 1e-8])
sim.get_distinct()
data["distinct"][sim.w] = []
for frame in sim.frames:
data["distinct"][sim.w].append([frame.energy,
np.var(frame.stats["avg_radius"]) <= 1e-8])
hashes = int(21*i/len(files))
print(f'Loading simulations... |{"#"*hashes}{" "*(20-hashes)}|' + \
f' {i+1}/{len(files)} simulations loaded.', flush=True, end='\r')
print(flush=True)
sims.sort(key=lambda x: x.w)
widths = np.asarray([sim.w for sim in sims])
pairs_at_widths = []
for sim in sims:
pairs_at_widths.append([(frame.energy, np.var(frame.stats["avg_radius"]) <= 1e-8) \
for frame in sim.frames])
# min_frames = [min(sim.frames, key=lambda x: x.energy) for sim in sims]
# max_frames = [max(sim.frames, key=lambda x: x.energy) for sim in sims]
# min_energies = np.asarray([frame.energy for frame in min_frames])
# max_energies = np.asarray([frame.energy for frame in max_frames])
# min_markers = [np.var(frame.stats["avg_radius"]) <= 1e-8 for frame in min_frames]
# max_markers = [np.var(frame.stats["avg_radius"]) <= 1e-8 for frame in max_frames]
n, h, r, energy = sims[0].n, sims[0].h, sims[0].r, sims[0].energy
widths = np.asarray(sorted(data["all"]))
n, h, r, energy = sim.n, sim.h, sim.r, sim.energy
sim_file = SIM_FOLDER / f"{ENERGY_R_STR[energy]} - EquilibriaData - N{n}.data"
out_tup = (widths, pairs_at_widths, n, h, r, ENERGY_I_STR[energy])
out_tup = (widths, data, n, h, r, ENERGY_I_STR[energy])
with open(sim_file, "wb") as output:
pickle.dump(out_tup, output)
@ -101,6 +95,7 @@ def axis_settings(ax, widths):
ax.grid(zorder=0)
ax.set_xticks([round(w,2) for w in widths[::-2]])
ax.set_xticklabels(ax.get_xticks(), rotation = 90)
plt.subplots_adjust(.05, .12, .97, .9)
def main():
@ -113,7 +108,7 @@ def main():
args = parser.parse_args()
widths, energy_shape_tups, n, h, r, energy = get_equilibria_data(Path(args.sims_path))
widths, data, n, h, r, energy = get_equilibria_data(Path(args.sims_path))
torus_min_energies, torus_max_energies, _, _ = get_torus_config_energies(
n, widths, h, r, energy
@ -123,13 +118,29 @@ def main():
fig_folder.mkdir(exist_ok=True)
# Torus minimum energies used as reference.
plt.tight_layout()
# Basin of attraction diagram.
fig, ax = plt.subplots(figsize=(16, 8))
all_disorder_count = []
for width in widths:
equal_shape = list([c[1] for c in data["all"][width]])
all_disorder_count.append(100*equal_shape.count(False)/len(data["all"][width]))
ax.plot(widths, all_disorder_count)
axis_settings(ax, widths)
ax.yaxis.set_major_formatter(mtick.PercentFormatter())
ax.title.set_text('Basin of Attraction')
ax.set_xlabel("Width")
ax.set_ylabel("Disordered Equilibria")
ax.set_yticks(np.arange(0,105, 5))
fig.savefig(fig_folder / "Basin of Attraction.png")
# Density of States diagram.
fig, ax = plt.subplots(figsize=(16, 8))
distinct_ordered, distinct_unordered = [], []
for energy_shapes in energy_shape_tups:
equal_shape = list([tup[1] for tup in energy_shapes])
for width in widths:
equal_shape = list([c[1] for c in data["distinct"][width]])
distinct_ordered.append(equal_shape.count(True))
distinct_unordered.append(equal_shape.count(False))
@ -140,22 +151,18 @@ def main():
ax.title.set_text('Density of States')
ax.set_xlabel("Width")
ax.set_ylabel("Number of States")
dos_y_max = 1.05*max(distinct_ordered + distinct_unordered)
ax.set_yticks(np.arange(0, dos_y_max, round(dos_y_max/200, 1)*10))
fig.savefig(fig_folder / "Density Of States.png")
# Bifurcation diagram
fig, ax = plt.subplots(figsize=(16, 8))
ordered_energies, unordered_energies = [], []
for energy_shapes in energy_shape_tups:
order_width, unorder_width = [], []
for pair in energy_shapes:
if pair[1]:
order_width.append(pair[0])
else:
unorder_width.append(pair[0])
ordered_energies.append(order_width)
unordered_energies.append(unorder_width)
for width in widths:
ordered_energies.append([c[0] for c in data["distinct"][width] if c[1]])
unordered_energies.append([c[0] for c in data["distinct"][width] if not c[1]])
for i in range(len(torus_min_energies)):
ordered_energies[i].append(torus_min_energies[i])
@ -163,30 +170,29 @@ def main():
null_unorder = []
for i, width in enumerate(unordered_energies):
if len(width) == 0:
for i, energies in enumerate(unordered_energies):
if len(energies) == 0:
null_unorder.append(i)
for x in unordered_energies[i-1]:
width.append(x)
#width = unordered_energies[i-1]
#width.append(max(unordered_energies[i-1]))
energies.append(torus_min_energies[i])
min_order = np.asarray([min(width) for width in ordered_energies])
max_order = np.asarray([max(width) for width in ordered_energies])
min_unorder = np.asarray([min(width) for width in unordered_energies])
max_unorder = np.asarray([max(width) for width in unordered_energies])
min_unorder_off = min_unorder - torus_min_energies
max_unorder_off = max_unorder - torus_min_energies
ax.plot(widths, min_order - torus_min_energies, color='C1')
#ax.plot(widths, max_order - torus_min_energies, color='C1', linestyle='dotted')
ax.plot(widths, min_unorder - torus_min_energies, color='C0')
ax.plot(widths, max_unorder - torus_min_energies, color='C0', linestyle='dotted')
ax.plot(widths, min_unorder_off, color='C0')
ax.plot(widths, max_unorder_off, color='C0', linestyle='dotted')
axis_settings(ax, widths)
for i in null_unorder:
ax.scatter(widths[i], min_unorder[i] - torus_min_energies[i],
marker='X', color="blue", s=50, zorder=4)
ax.scatter(widths[i], max_unorder[i] - torus_min_energies[i],
marker='X', edgecolors="blue", facecolors='none', s=100, zorder=4)
# ax.scatter(widths[i], max_unorder[i] - torus_min_energies[i],
# marker='X', edgecolors="blue", facecolors='none', s=100, zorder=4)
# for i, marker in enumerate(min_markers):
# if marker:
@ -207,9 +213,13 @@ def main():
ax.title.set_text('Reduced Energy vs. Width')
ax.set_xlabel("Width")
ax.set_ylabel("Reduced Energy")
bif_y_max = np.max(np.abs(np.concatenate((min_unorder_off, max_unorder_off))))
ax.set_yticks(np.arange(-bif_y_max, bif_y_max, round(bif_y_max/20, \
-math.floor(math.log10(bif_y_max/20)))))
fig.savefig(fig_folder / "Bifurcation.png")
print(f"Wrote to {fig_folder}.")
if __name__ == "__main__":
os.environ["QT_LOGGING_RULES"] = "*=false"
SIM_FOLDER = Path(f"simulations/ShrinkEnergyComparison")

View File

@ -461,14 +461,21 @@ class Simulation:
def get_distinct(self):
distinct_hists = []
distinct_avg_radii = []
new_frames = []
for frame in self.frames:
new_hist = np.histogram(frame.stats["avg_radius"], bins=10)[0]
if np.var(frame.stats["avg_radius"]) <= 1e-8:
avg_radii = np.average(frame.stats["avg_radius"])
if not np.any(np.isclose(avg_radii, distinct_avg_radii, atol=1e-5)):
distinct_avg_radii.append(avg_radii)
new_frames.append(frame)
else:
new_hist = np.histogram(frame.stats["avg_radius"], bins=8)[0]
is_in = False
for hist in distinct_hists:
if np.allclose(new_hist, hist, atol=1e-8):
if np.all(hist == new_hist):
is_in = True
break