Skip to content

Commit 34649a3

Browse files
committed
Refactor saving functionality with simulation ID system
1 parent ea1ffc2 commit 34649a3

File tree

3 files changed

+81
-54
lines changed

3 files changed

+81
-54
lines changed

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
.vscode
22
__pycache__
33
*.code-workspace
4-
experiments/
4+
results/
55
*.txt
66
python.py

config.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
'''
2-
This is a sample configuration file. You can modify the parameters and strategy as needed.
3-
Copy this file as config.py to each of your working directories.
2+
This is where you can set configuration options and the strategy for the prisoners.
43
'''
54

65
CONFIG = { # Settings for the simulation

main.py

Lines changed: 79 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
import importlib.util
22
import sys
33
import random
4+
import inspect
45
import os
56
import pickle
67
import time
78
from matplotlib import pyplot as plt
89

910
class plots_stats:
1011
def printWinPercentage():
11-
results = saving.loadResults()
12+
results = results_manager.loadResults()
1213
total_sims = len(results)
1314
wins = sum(1 for result in results if result["escaped"])
1415

@@ -17,7 +18,7 @@ def printWinPercentage():
1718
print(f"\nWin percentage: {winStr}%")
1819

1920
def printAvgBoxChecks():
20-
results = saving.loadResults()
21+
results = results_manager.loadResults()
2122
total_sims = len(results)
2223
num_prisoners = len(results[0]["prisoners"])
2324
checksPerPrisoner = {i: 0 for i in range(num_prisoners)}
@@ -38,7 +39,7 @@ def printAvgBoxChecks():
3839
plt.show()
3940

4041
def printPctFinds():
41-
results = saving.loadResults()
42+
results = results_manager.loadResults()
4243
total_sims = len(results)
4344
num_prisoners = len(results[0]["prisoners"])
4445
findsPerPrisoner = {i: 0 for i in range(num_prisoners)}
@@ -85,7 +86,7 @@ def run():
8586
else:
8687
print("Invalid choice. Please select a valid option.")
8788

88-
class saving:
89+
class results_manager:
8990
def save(results, checkpoint):
9091
with open(resultsPath + '.tmp', 'wb') as file:
9192
pickle.dump(results, file)
@@ -122,59 +123,82 @@ def loadCheckpoint():
122123
checkpoint = pickle.load(file)
123124
return checkpoint
124125
return None
125-
126-
def importConfigModule():
127-
configPath = os.path.join(working_dir, "config.py")
128-
spec = importlib.util.spec_from_file_location("config", configPath)
129-
if spec is None or spec.loader is None:
130-
raise FileNotFoundError(f"Could not load config.py from {working_dir}")
131-
config = importlib.util.module_from_spec(spec)
132-
sys.modules["config"] = config
133-
spec.loader.exec_module(config)
134-
return config
135-
136-
def getWorkingDir():
137-
global working_dir
138-
global resultsPath
139-
global checkpointPath
140-
while True:
141-
working_dir = os.path.abspath(input("Enter the working directory: ").strip())
142-
if os.path.isdir(working_dir):
143-
resultsPath = os.path.join(working_dir, 'results.pkl')
144-
checkpointPath = os.path.join(working_dir, 'checkpoint.pkl')
145-
return working_dir
146-
else:
147-
print(f"Directory {working_dir} does not exist. Please try again.")
126+
127+
def createNewSimulation():
128+
global working_dir
129+
global resultsPath
130+
global checkpointPath
131+
global configPath
132+
global prisonerStrategy
133+
global config
134+
while True:
135+
simID = input("Enter new simulation ID: ").strip()
136+
working_dir = os.path.join(base_dir, "results", simID)
137+
resultsPath = os.path.join(working_dir, "results.pkl")
138+
checkpointPath = os.path.join(working_dir, "checkpoint.pkl")
139+
configPath = os.path.join(working_dir, "config.pkl")
140+
if not os.path.exists(working_dir):
141+
os.makedirs(working_dir)
142+
break
143+
print("Simulation ID already exists. Please choose a different ID.")
144+
import config as baseConfig
145+
prisonerStrategy = baseConfig.prisonerStrategy
146+
prisonerStrategy_string = inspect.getsource(baseConfig.prisonerStrategy)
147+
config = {"CONFIG": baseConfig.getConfig(), "prisonerStrategy": prisonerStrategy_string}
148+
with open(configPath, 'wb') as file:
149+
pickle.dump(config, file)
150+
151+
def loadSimulation():
152+
global working_dir
153+
global resultsPath
154+
global checkpointPath
155+
global configPath
156+
global prisonerStrategy
157+
global config
158+
while True:
159+
simID = input("Enter simulation ID: ").strip()
160+
working_dir = os.path.join(base_dir, "results", simID)
161+
resultsPath = os.path.join(working_dir, "results.pkl")
162+
checkpointPath = os.path.join(working_dir, "checkpoint.pkl")
163+
configPath = os.path.join(working_dir, "config.pkl")
164+
if os.path.exists(configPath):
165+
break
166+
print("Invalid simulation ID. Please try again.")
167+
with open(configPath, 'rb') as file:
168+
config = pickle.load(file)
169+
namespace = {}
170+
exec(config["prisonerStrategy"], namespace)
171+
prisonerStrategy = namespace["prisonerStrategy"]
148172

149173
def simulatePrisoners():
150-
results = saving.loadResults()
151-
checkpoint = saving.loadCheckpoint()
174+
results = results_manager.loadResults()
175+
checkpoint = results_manager.loadCheckpoint()
152176
if checkpoint and results:
153177
startSim = checkpoint.get("last_simulation") + 1
154-
rng = random.Random(cfg.get("seed", None))
178+
rng = random.Random(config["CONFIG"].get("seed", None))
155179
rng.setstate(checkpoint.get("rng_state"))
156180
print(f"Resuming from simulation {startSim}.")
157181
else:
158182
startSim = 0
159183
results = []
160-
rng = random.Random(cfg.get("seed", None))
184+
rng = random.Random(config["CONFIG"].get("seed", None))
161185
checkpoint = {"last_simulation": -1, "rng_state": rng.getstate()}
162186
print("Starting new simulations.")
163187

164-
if startSim >= cfg["num_simulations"]:
188+
if startSim >= config["CONFIG"]["num_simulations"]:
165189
print("All simulations have already been completed.")
166190
return
167191

168-
for sim in range(startSim, cfg["num_simulations"]):
169-
prisoners = {i: [0, False] for i in range(cfg["num_prisoners"])}
192+
for sim in range(startSim, config["CONFIG"]["num_simulations"]):
193+
prisoners = {i: [0, False] for i in range(config["CONFIG"]["num_prisoners"])}
170194
boxes = list(prisoners.keys())
171195
rng.shuffle(boxes)
172196
results.append({"escaped": None, "prisoners": []})
173197

174198
for prisonerId in prisoners:
175199
checkedBoxes = {}
176-
for _ in range(cfg["total_box_checks"]):
177-
choice = config.prisonerStrategy(rng, prisonerId, prisoners, cfg["total_box_checks"], checkedBoxes)
200+
for _ in range(config["CONFIG"]["total_box_checks"]):
201+
choice = prisonerStrategy(rng, prisonerId, prisoners, config["CONFIG"]["total_box_checks"], checkedBoxes)
178202
if boxes[choice] == prisonerId:
179203
checkedBoxes[choice] = boxes[choice]
180204
prisoners[prisonerId] = (checkedBoxes, True)
@@ -187,31 +211,35 @@ def simulatePrisoners():
187211
for prisoner in prisoners:
188212
results[-1]["prisoners"].append({"found": prisoners[prisoner][1], "checked_boxes": prisoners[prisoner][0]})
189213

190-
saving.save(results, {"last_simulation": sim, "rng_state": rng.getstate()})
214+
results_manager.save(results, {"last_simulation": sim, "rng_state": rng.getstate()})
191215
print("All simulations completed.")
192216

193217
if __name__ == "__main__":
194218
base_dir = os.path.dirname(os.path.abspath(__file__))
195-
working_dir = getWorkingDir()
196-
config = importConfigModule()
197-
cfg = config.getConfig()
198-
199219
while True:
200-
print(f"\nWorking directory: {working_dir}")
201220
print(f"\nChoose an option:")
202-
print(f"1. Change working directory")
203-
print(f"2. Run simulations")
204-
print(f"3. Plot results")
205-
print(f"4. Exit")
206-
choice = input("Make a selection (1-4): ").strip()
221+
print(f"1. Create new simulation")
222+
print(f"2. Load simulation")
223+
print(f"3. Simulate prisoners (load or create simulation first)")
224+
print(f"4. Show plots and statistics (load or create simulation first)")
225+
print(f"5. Exit")
226+
choice = input("Make a selection (1-5): ").strip()
207227
if choice == '1':
208-
getWorkingDir()
228+
results_manager.createNewSimulation()
209229
elif choice == '2':
210-
simulatePrisoners()
230+
results_manager.loadSimulation()
211231
elif choice == '3':
212-
plots_stats.run()
232+
if config is None:
233+
print("\nPlease create or load a simulation first.")
234+
else:
235+
simulatePrisoners()
213236
elif choice == '4':
237+
if config is None:
238+
print("\nPlease create or load a simulation first.")
239+
else:
240+
plots_stats.run()
241+
elif choice == '5':
214242
print("Exiting.")
215-
break
243+
sys.exit(0)
216244
else:
217245
print("Invalid choice. Please select a valid option.")

0 commit comments

Comments
 (0)