Simulation name now also being saved as metadata

This commit is contained in:
Andreas Tsouchlos 2022-11-23 12:55:35 +01:00
parent 8913246600
commit e5934d9948
11 changed files with 133 additions and 86 deletions

View File

@ -1,53 +1,63 @@
import numpy as np import numpy as np
from pathlib import Path
from decoders import proximal, maximum_likelihood from decoders import proximal, maximum_likelihood
from utility import simulation, codes from utility import simulation, codes
def main(): def start_new_simulation(sim_mgr: simulation.SimulationManager):
Path("sim_results").mkdir(parents=True, exist_ok=True)
sim_name = "test" sim_name = "test"
sim_mgr = simulation.SimulationManager(results_dir="sim_results", # H = codes.read_alist_file("res/204.3.486.alist")
save_dir="sim_saves") # H = codes.read_alist_file("res/204.55.187.alist")
H = codes.read_alist_file("res/96.3.965.alist")
# H = codes.read_alist_file("res/408.33.844.alist")
# H = codes.read_alist_file("res/PEGReg252x504.alist")
# H = codes.read_alist_file("res/999.111.3.5543.alist")
# H = codes.read_alist_file("res/999.111.3.5565.alist")
# H = codes.read_alist_file("res/816.1A4.845.alist")
k, n = H.shape
if sim_mgr.unfinished_simulation_present(sim_name): decoders = [
proximal.ProximalDecoder(H, gamma=0.01),
proximal.ProximalDecoder(H, gamma=0.05),
proximal.ProximalDecoder(H, gamma=0.15)
]
labels = [
"proximal $\\gamma = 0.01$",
"proximal $\\gamma = 0.05$",
"proximal $\\gamma = 0.15$"
]
sim = simulation.Simulator(n=n, k=k, decoders=decoders,
target_frame_errors=100,
SNRs=np.arange(1, 6, 0.5))
sim_mgr.configure_simulation(simulator=sim, name=sim_name,
column_labels=labels)
sim_mgr.simulate()
def main():
# Perform necessary initialization
results_dir = "sim_results"
saves_dir = "sim_saves"
sim_mgr = simulation.SimulationManager(results_dir=results_dir,
saves_dir=saves_dir)
# Calculate BERs
unfinished_sims = sim_mgr.get_unfinished()
if len(unfinished_sims) > 0:
print("Found unfinished simulation. Picking up where it was left of") print("Found unfinished simulation. Picking up where it was left of")
sim_mgr.load_unfinished(sim_name=sim_name) sim_mgr.load_unfinished(unfinished_sims[0])
sim_mgr.simulate() sim_mgr.simulate()
else: else:
# H = codes.read_alist_file("res/204.3.486.alist") start_new_simulation(sim_mgr)
# H = codes.read_alist_file("res/204.55.187.alist")
# H = codes.read_alist_file("res/96.3.965.alist")
# H = codes.read_alist_file("res/408.33.844.alist")
# H = codes.read_alist_file("res/PEGReg252x504.alist")
# H = codes.read_alist_file("res/999.111.3.5543.alist")
# H = codes.read_alist_file("res/999.111.3.5565.alist")
H = codes.read_alist_file("res/816.1A4.845.alist")
k, n = H.shape
decoders = [
proximal.ProximalDecoder(H, gamma=0.01),
proximal.ProximalDecoder(H, gamma=0.05),
proximal.ProximalDecoder(H, gamma=0.15)
]
labels = [
"proximal $\\gamma = 0.01$",
"proximal $\\gamma = 0.05$",
"proximal $\\gamma = 0.15$"
]
sim = simulation.Simulator(n=n, k=k, decoders=decoders,
target_frame_errors=3,
SNRs=np.arange(1, 6, 0.5))
sim_mgr.configure_simulation(simulator=sim, name=sim_name,
column_labels=labels)
sim_mgr.simulate()
if __name__ == "__main__": if __name__ == "__main__":

View File

@ -1,37 +1,49 @@
import numpy as np import typing
import matplotlib.pyplot as plt import matplotlib.pyplot as plt
import seaborn as sns import seaborn as sns
import pandas as pd
import os import os
from utility import visualization, simulation from utility import visualization, simulation
def plot_results(): # TODO: This should be the responsibility of the DeSerializer
sim_names = [ def get_sim_slugs(results_dir: str) -> typing.List[str]:
"96.3965", """Get a list of slugified simulation names."""
"204.3.486", result_files = [f for f in os.listdir(results_dir) if
"204.55.187", os.path.isfile(os.path.join(results_dir, f))]
"408.33.844",
"816.1A4.845",
"999.111.3.5543",
"999.111.3.5565",
"PEGReg252x504"
]
deserializer = simulation.SimulationDeSerializer(save_dir="sim_saves", metadata_files = [f for f in result_files if f.endswith("_metadata.json")]
results_dir="sim_results")
sim_slugs = [f.removesuffix("_metadata.json") for f in metadata_files]
return sim_slugs
def plot_results() -> None:
"""Plot the BER curves for all present simulation results."""
saves_dir = "sim_saves"
results_dir = "sim_results"
slugs = get_sim_slugs(results_dir)
deserializer = simulation.SimulationDeSerializer(save_dir=saves_dir,
results_dir=results_dir)
# Read data
data = [] data = []
for sim_name in sim_names: for slug in slugs:
df, metadata = deserializer.read_results(sim_name) df, metadata = deserializer.read_results(slug)
df = df.loc[:, ~df.columns.str.contains('^Unnamed')] df = df.loc[:, ~df.columns.str.contains('^Unnamed')]
graph_title = sim_name graph_title = metadata["name"]
line_labels = metadata["labels"] line_labels = metadata["labels"]
graph_tuple = (graph_title, df, line_labels) graph_tuple = (graph_title, df, line_labels)
data.append(graph_tuple) data.append(graph_tuple)
# Plot results
sns.set_theme() sns.set_theme()
fig = visualization.plot_BERs( fig = visualization.plot_BERs(
title="Bit-Error-Rates of proximal decoder for different codes", title="Bit-Error-Rates of proximal decoder for different codes",

View File

@ -1,4 +1,5 @@
{ {
"name": "204.3.486",
"labels": [ "labels": [
"proximal $\\gamma = 0.01$", "proximal $\\gamma = 0.01$",
"proximal $\\gamma = 0.05$", "proximal $\\gamma = 0.05$",

View File

@ -1,4 +1,5 @@
{ {
"name": "204.55.187",
"labels": [ "labels": [
"proximal $\\gamma = 0.01$", "proximal $\\gamma = 0.01$",
"proximal $\\gamma = 0.05$", "proximal $\\gamma = 0.05$",

View File

@ -1,4 +1,5 @@
{ {
"name": "408.33.844",
"labels": [ "labels": [
"proximal $\\gamma = 0.01$", "proximal $\\gamma = 0.01$",
"proximal $\\gamma = 0.05$", "proximal $\\gamma = 0.05$",

View File

@ -1,4 +1,5 @@
{ {
"name": "816.1A4.845",
"labels": [ "labels": [
"proximal $\\gamma = 0.01$", "proximal $\\gamma = 0.01$",
"proximal $\\gamma = 0.05$", "proximal $\\gamma = 0.05$",

View File

@ -1,4 +1,5 @@
{ {
"name":"96.3965",
"labels": [ "labels": [
"proximal $\\gamma = 0.01$", "proximal $\\gamma = 0.01$",
"proximal $\\gamma = 0.05$", "proximal $\\gamma = 0.05$",

View File

@ -1,4 +1,5 @@
{ {
"name": "999.111.3.5543",
"labels": [ "labels": [
"proximal $\\gamma = 0.01$", "proximal $\\gamma = 0.01$",
"proximal $\\gamma = 0.05$", "proximal $\\gamma = 0.05$",

View File

@ -1,4 +1,5 @@
{ {
"name": "999.111.3.5565",
"labels": [ "labels": [
"proximal $\\gamma = 0.01$", "proximal $\\gamma = 0.01$",
"proximal $\\gamma = 0.05$", "proximal $\\gamma = 0.05$",

View File

@ -1,4 +1,5 @@
{ {
"name": "PEGReg252x504",
"labels": [ "labels": [
"proximal $\\gamma = 0.01$", "proximal $\\gamma = 0.01$",
"proximal $\\gamma = 0.05$", "proximal $\\gamma = 0.05$",

View File

@ -7,7 +7,7 @@ import typing
from tqdm import tqdm from tqdm import tqdm
import signal import signal
import pickle import pickle
import os.path import os
from pathlib import Path from pathlib import Path
from utility import noise, misc from utility import noise, misc
@ -249,14 +249,14 @@ class SimulationDeSerializer:
Simulator objects.""" Simulator objects."""
def __init__(self, save_dir: str, results_dir: str): def __init__(self, save_dir: str, results_dir: str):
self._save_dir = save_dir self._saves_dir = save_dir
self._results_dir = results_dir self._results_dir = results_dir
Path(self._save_dir).mkdir(parents=True, exist_ok=True) Path(self._saves_dir).mkdir(parents=True, exist_ok=True)
Path(self._results_dir).mkdir(parents=True, exist_ok=True) Path(self._results_dir).mkdir(parents=True, exist_ok=True)
def _get_savefile_path(self, sim_name): def _get_savefile_path(self, sim_name):
return f"{self._save_dir}/{misc.slugify(sim_name)}_sim_state.pickle" return f"{self._saves_dir}/{misc.slugify(sim_name)}_state.pickle"
def _get_metadata_path(self, sim_name): def _get_metadata_path(self, sim_name):
return f"{self._results_dir}/{misc.slugify(sim_name)}_metadata.json" return f"{self._results_dir}/{misc.slugify(sim_name)}_metadata.json"
@ -264,16 +264,41 @@ class SimulationDeSerializer:
def _get_results_path(self, sim_name): def _get_results_path(self, sim_name):
return f"{self._results_dir}/{misc.slugify(sim_name)}.csv" return f"{self._results_dir}/{misc.slugify(sim_name)}.csv"
# TODO: Should this function also check for the metadata file? def _read_metadata(self, sim_name) -> typing.Dict:
# Currently, if the state-savefile is present, but not the metadata, with open(self._get_metadata_path(sim_name), 'r',
# this function will return true but loading the saved state will fail encoding='utf-8') as f:
def unfinished_sim_present(self, sim_name: str): return json.load(f)
"""Check if the savefile of a previously paused simulation is present.
:param sim_name: def _save_metadata(self, sim_name, metadata) -> None:
with open(self._get_metadata_path(sim_name), 'w+',
encoding='utf-8') as f:
json.dump(metadata, f, ensure_ascii=False, indent=4)
def unfinished_sim_present(self, sim_name: str):
"""Check if the savefile of a previously paused simulation is
present.
:param sim_name: Name
:return: True if a paused simulation with the given name is found :return: True if a paused simulation with the given name is found
""" """
return os.path.isfile(self._get_savefile_path(sim_name)) return os.path.isfile(
self._get_savefile_path(sim_name)) and os.path.isfile(
self._get_metadata_path(sim_name))
# TODO: Make the directories configurable in the init function
def get_unfinished_sims(self) -> typing.List[str]:
"""Get a list unfinished simulations."""
result = []
save_files = [f for f in os.listdir(self._saves_dir) if
os.path.isfile(os.path.join(self._saves_dir, f))]
state_files = [f for f in save_files if f.endswith("_state.pickle")]
sim_slugs = [f.removesuffix("_state.pickle") for f in state_files]
sim_names = [self._read_metadata(slug)["name"] for slug in sim_slugs]
return sim_names
def remove_unfinished_sim(self, sim_name): def remove_unfinished_sim(self, sim_name):
"""Remove the savefile of a previously paused simulation. """Remove the savefile of a previously paused simulation.
@ -292,9 +317,7 @@ class SimulationDeSerializer:
:param metadata: Metadata to be saved besides the actual state :param metadata: Metadata to be saved besides the actual state
""" """
# Save metadata # Save metadata
with open(self._get_metadata_path(sim_name), 'w+', self._save_metadata(sim_name, metadata)
encoding='utf-8') as f:
json.dump(metadata, f, ensure_ascii=False, indent=4)
# Save simulation state # Save simulation state
with open(self._get_savefile_path(sim_name), "wb") as file: with open(self._get_savefile_path(sim_name), "wb") as file:
@ -311,9 +334,7 @@ class SimulationDeSerializer:
simulator = None simulator = None
# Read metadata # Read metadata
with open(self._get_metadata_path(sim_name), 'r', metadata = self._read_metadata(sim_name)
encoding='utf-8') as f:
metadata = json.load(f)
# Read simulation state # Read simulation state
with open(self._get_savefile_path(sim_name), "rb") as file: with open(self._get_savefile_path(sim_name), "rb") as file:
@ -332,9 +353,7 @@ class SimulationDeSerializer:
results results
""" """
# Save metadata # Save metadata
with open(self._get_metadata_path(sim_name), 'w+', self._save_metadata(sim_name, metadata)
encoding='utf-8') as f:
json.dump(metadata, f, ensure_ascii=False, indent=4)
# Save results # Save results
df = simulator.get_current_results() df = simulator.get_current_results()
@ -349,9 +368,7 @@ class SimulationDeSerializer:
dataframe and metadata is a dict dataframe and metadata is a dict
""" """
# Read metadata # Read metadata
with open(self._get_metadata_path(sim_name), 'r', metadata = self._read_metadata(sim_name)
encoding='utf-8') as f:
metadata = json.load(f)
# Read results # Read results
results = pd.read_csv(self._get_results_path(sim_name)) results = pd.read_csv(self._get_results_path(sim_name))
@ -369,15 +386,15 @@ class SimulationManager:
All actual work is outsourced to a provided simulator class. All actual work is outsourced to a provided simulator class.
""" """
def __init__(self, save_dir: str, results_dir: str): def __init__(self, saves_dir: str, results_dir: str):
"""Construct a SimulationManager object. """Construct a SimulationManager object.
:param save_dir: Directory in which the simulation state of a paused :param saves_dir: Directory in which the simulation state of a paused
simulation should be stored simulation should be stored
:param results_dir: Directory in which the results of the simulation :param results_dir: Directory in which the results of the simulation
should be stored should be stored
""" """
self._de_serializer = SimulationDeSerializer(save_dir, results_dir) self._de_serializer = SimulationDeSerializer(saves_dir, results_dir)
self._simulator = None self._simulator = None
self._sim_name = None self._sim_name = None
@ -398,19 +415,19 @@ class SimulationManager:
"""Configure a new simulation.""" """Configure a new simulation."""
self._simulator = simulator self._simulator = simulator
self._sim_name = name self._sim_name = name
self._metadata["name"] = name
self._metadata["labels"] = column_labels self._metadata["labels"] = column_labels
def unfinished_simulation_present(self, sim_name: str) -> bool: def get_unfinished(self) -> typing.List[str]:
"""Check whether the savefile of a previously unfinished simulation """Get a list of names of all present unfinished simulations."""
is present.""" return self._de_serializer.get_unfinished_sims()
return self._de_serializer.unfinished_sim_present(sim_name)
def load_unfinished(self, sim_name: str) -> None: def load_unfinished(self, sim_name: str) -> None:
"""Load the state of an unfinished simulation its savefile. """Load the state of an unfinished simulation its savefile.
Warning: This function deletes the savefile after loading. Warning: This function deletes the savefile after loading.
""" """
assert self.unfinished_simulation_present(sim_name) assert self._de_serializer.unfinished_sim_present(sim_name)
self._sim_name = sim_name self._sim_name = sim_name
self._simulator, self._metadata = self._de_serializer.read_state( self._simulator, self._metadata = self._de_serializer.read_state(