33import random
44import os
55import csv
6+ import pickle
67from matplotlib import pyplot as plt
78
89class 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
153140def importConfigModule ():
154141 configPath = os .path .join (working_dir , "config.py" )
@@ -161,43 +148,65 @@ def importConfigModule():
161148 return config
162149
163150def 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
196202if __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"\n Working directory: { working_dir } " )
203212 print (f"\n Choose 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