Skip to content

Commit eabf736

Browse files
committed
Added seed customizability and reworked saving/loading system
1 parent 3e4cb82 commit eabf736

File tree

2 files changed

+56
-46
lines changed

2 files changed

+56
-46
lines changed

config.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,19 @@
33
Copy this file as config.py to each of your working directories.
44
'''
55

6-
import random
7-
86
CONFIG = { # Settings for the simulation
97
"num_prisoners": 100,
108
"total_box_checks": 50,
11-
"num_simulations": 10000
9+
"num_simulations": 10000,
10+
"seed": 11 # Set to an integer for reproducible results or None for random seed
1211
}
1312

1413
def getConfig():
1514
return CONFIG
1615

17-
def prisonerStrategy(prisoner_id, prisoners, total_checks, checked_boxes): # Set strategy here
16+
def prisonerStrategy(random, prisoner_id, prisoners, total_checks, checked_boxes): # Set strategy here
17+
# Use random.* for any randomness needed
18+
1819
# Example: Loop strategy
1920
if checked_boxes:
2021
return(next(reversed(checked_boxes.values())))

main.py

Lines changed: 51 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import random
44
import os
55
import csv
6+
import pickle
67
from matplotlib import pyplot as plt
78

89
class plots_stats:
@@ -118,37 +119,23 @@ def run():
118119
else:
119120
print("Invalid choice. Please select a valid option.")
120121

121-
class logging:
122-
def loadLogs():
123-
lastSim = -1
124-
prisonersLog = os.path.join(working_dir, 'results.csv')
125-
if not os.path.exists(prisonersLog) or os.stat(prisonersLog).st_size == 0:
126-
with open(prisonersLog, mode='w', newline='') as file:
127-
writer = csv.writer(file)
128-
writer.writerow(['Simulation', 'PrisonerID', 'CheckedBoxesCount', 'FoundBox'])
129-
print(f"Created new log file at {prisonersLog}")
130-
else:
131-
print(f"Log file {prisonersLog} already exists and is not empty. Appending new results.")
132-
with open(prisonersLog, mode='r', newline='') as file:
133-
reader = csv.reader(file)
134-
next(reader, None) # Skip header
135-
for row in reader:
136-
if row and row[0].isdigit():
137-
lastSim = max(lastSim, int(row[0]))
138-
return lastSim
139-
140-
def logPrisonersResults(simId, results):
141-
prisonersLog = os.path.join(working_dir, 'results.csv')
142-
while True:
143-
try:
144-
with open(prisonersLog, mode='a', newline='') as file:
145-
writer = csv.writer(file)
146-
for prisonerId, (checkedBoxesCount, found) in results.items():
147-
writer.writerow([simId, prisonerId, checkedBoxesCount, found])
148-
break
149-
except Exception as e:
150-
print(f"Error logging prisoner results: {e}")
151-
input("Press Enter to retry or Ctrl+C to abort...")
122+
class saving:
123+
def save(results, checkpoint):
124+
with open(resultsPath + '.tmp', 'wb') as file:
125+
pickle.dump(results, file)
126+
with open(checkpointPath + '.tmp', 'wb') as file:
127+
pickle.dump(checkpoint, file)
128+
os.replace(resultsPath + '.tmp', resultsPath)
129+
os.replace(checkpointPath + '.tmp', checkpointPath)
130+
131+
def load():
132+
if os.path.exists(resultsPath) and os.path.exists(checkpointPath):
133+
with open(resultsPath, 'rb') as file:
134+
results = pickle.load(file)
135+
with open(checkpointPath, 'rb') as file:
136+
checkpoint = pickle.load(file)
137+
return results, checkpoint
138+
return None, None
152139

153140
def importConfigModule():
154141
configPath = os.path.join(working_dir, "config.py")
@@ -161,43 +148,65 @@ def importConfigModule():
161148
return config
162149

163150
def getWorkingDir():
151+
global working_dir
164152
while True:
165153
working_dir = os.path.abspath(input("Enter the working directory: ").strip())
166154
if os.path.isdir(working_dir):
167155
return working_dir
168156
else:
169157
print(f"Directory {working_dir} does not exist. Please try again.")
170158

171-
def simulatePrisoners(cfg):
172-
lastSim = logging.loadLogs()
173-
startSim = lastSim + 1
159+
def simulatePrisoners():
160+
results, checkpoint = saving.load()
161+
if checkpoint:
162+
startSim = checkpoint.get("last_simulation") + 1
163+
rng = random.Random(cfg.get("seed", None))
164+
rng.setstate(checkpoint.get("rng_state"))
165+
print(f"Resuming from simulation {startSim}.")
166+
else:
167+
startSim = 0
168+
results = []
169+
rng = random.Random(cfg.get("seed", None))
170+
checkpoint = {"last_simulation": -1}
171+
print("Starting new simulations.")
172+
174173
if startSim >= cfg["num_simulations"]:
175174
print("All simulations have already been completed.")
176175
return
176+
177177
for sim in range(startSim, cfg["num_simulations"]):
178178
prisoners = {i: [0, False] for i in range(cfg["num_prisoners"])}
179179
boxes = list(prisoners.keys())
180-
random.shuffle(boxes)
180+
rng.shuffle(boxes)
181+
results.append({"escaped": None, "prisoners": []})
181182

182183
for prisonerId in prisoners:
183184
checkedBoxes = {}
184185
for _ in range(cfg["total_box_checks"]):
185-
choice = config.prisonerStrategy(prisonerId, prisoners, cfg["total_box_checks"], checkedBoxes)
186+
choice = config.prisonerStrategy(rng, prisonerId, prisoners, cfg["total_box_checks"], checkedBoxes)
186187
if boxes[choice] == prisonerId:
187-
prisoners[prisonerId] = (len(checkedBoxes) + 1, True)
188+
checkedBoxes[choice] = boxes[choice]
189+
prisoners[prisonerId] = (checkedBoxes, True)
188190
break
189191
else:
190192
checkedBoxes[choice] = boxes[choice]
191-
prisoners[prisonerId] = (len(checkedBoxes), False)
193+
prisoners[prisonerId] = (checkedBoxes, False)
192194

193-
logging.logPrisonersResults(sim, prisoners)
194-
print("All simulations completed.")
195+
results[-1]["escaped"] = all(prisoners[prisoner][1] for prisoner in prisoners)
196+
for prisoner in prisoners:
197+
results[-1]["prisoners"].append({"found": prisoners[prisoner][1], "checked_boxes": prisoners[prisoner][0]})
198+
199+
saving.save(results, {"last_simulation": sim, "rng_state": rng.getstate()})
200+
print("All simulations completed.")
195201

196202
if __name__ == "__main__":
197203
base_dir = os.path.dirname(os.path.abspath(__file__))
198204
working_dir = getWorkingDir()
199205
config = importConfigModule()
200206
cfg = config.getConfig()
207+
resultsPath = os.path.join(working_dir, 'results.pkl')
208+
checkpointPath = os.path.join(working_dir, 'checkpoint.pkl')
209+
201210
while True:
202211
print(f"\nWorking directory: {working_dir}")
203212
print(f"\nChoose an option:")
@@ -207,9 +216,9 @@ def simulatePrisoners(cfg):
207216
print(f"4. Exit")
208217
choice = input("Make a selection (1-4): ").strip()
209218
if choice == '1':
210-
working_dir = getWorkingDir()
219+
getWorkingDir()
211220
elif choice == '2':
212-
simulatePrisoners(cfg)
221+
simulatePrisoners()
213222
elif choice == '3':
214223
plots_stats.run()
215224
elif choice == '4':

0 commit comments

Comments
 (0)