diff --git a/reproduction/python_scripts/Experiment3.py b/reproduction/python_scripts/Experiment3.py index fe18aa0..e42774c 100644 --- a/reproduction/python_scripts/Experiment3.py +++ b/reproduction/python_scripts/Experiment3.py @@ -15,6 +15,7 @@ file = '10-prescreened.txt' runs = 1 objectiveTypes = [False, True, False] +upperBounds = [60, 60, 60, 60] # Path to save results experimentFolder = '../python_outputs/experiment3' @@ -51,7 +52,8 @@ 'population': scenario['population'], 'generations': scenario['generations'], 'objectiveTypes': objectiveTypes, - 'solutionpath': scenario['solutionpath']} + 'solutionpath': scenario['solutionpath'], + 'upperBounds': upperBounds} for scenario in scenarios ] diff --git a/reproduction/python_scripts/Experiment4.py b/reproduction/python_scripts/Experiment4.py new file mode 100644 index 0000000..4489e75 --- /dev/null +++ b/reproduction/python_scripts/Experiment4.py @@ -0,0 +1,70 @@ +# Experiment 4 (Figure 9) +# Tri-objective model with 1, 2 or 3 greeters/line managers + +# Run time: TODO add runtime +# (Intel Core i9-13900K with 81GB RAM running Pop!_OS 22.04 Linux) + +from os import listdir +from os.path import isfile, join +import datetime +from multiprocessing import Pool +from main import wrapper + +# Set to default +mypath = r'../inputs' +file = '10-prescreened.txt' +runs = 1 +objectiveTypes = [False, True, False] +population = 50 +generations = 25 + +# Path to save results +experimentFolder = '../python_outputs/experiment4' + +# Scenarios to run for this experiment +scenarios = [ + { + 'upperBounds': [1, 60, 60, 60], + 'solutionpath': join(experimentFolder, '1_line_manager') + }, + { + 'upperBounds': [2, 60, 60, 60], + 'solutionpath': join(experimentFolder, '2_line_managers') + }, + { + 'upperBounds': [3, 60, 60, 60], + 'solutionpath': join(experimentFolder, '3_line_managers') + } +] + +# Start timer +startTime = datetime.datetime.now() + +# Create parameter list for each experiment +params = [ + {'mypath': mypath, + 'experimentFolder': experimentFolder, + 'file': file, + 'runs': runs, + 'population': population, + 'generations': generations, + 'objectiveTypes': objectiveTypes, + 'solutionpath': scenario['solutionpath'], + 'upperBounds': scenario['upperBounds']} + for scenario in scenarios +] + +# Create a process pool that uses all CPUs +pool = Pool() +try: + # Map the run_scenario function to the experiment files + results = pool.map(wrapper, params) +finally: + # Close the pool and wait for the worker processes to finish + pool.close() + pool.join() + +# End timer and save time for that result +endTime = datetime.datetime.now() +with open(join(experimentFolder, "time.txt"), "w") as text_file: + text_file.write("{0}".format(endTime - startTime)) diff --git a/reproduction/python_scripts/ExperimentRunner.py b/reproduction/python_scripts/ExperimentRunner.py index 45e97fa..6141f94 100644 --- a/reproduction/python_scripts/ExperimentRunner.py +++ b/reproduction/python_scripts/ExperimentRunner.py @@ -20,7 +20,7 @@ class ExperimentRunner: - def __init__(self, seeds, parameterReader, objectiveTypes): + def __init__(self, seeds, parameterReader, objectiveTypes, upperBounds): self.archiver = inspyred.ec.archivers.best_archiver self.seeds = seeds self.prng = random.Random() @@ -28,6 +28,7 @@ def __init__(self, seeds, parameterReader, objectiveTypes): self.parameterReader = parameterReader # Defines whether it is a bi-objective or tri-objective model self.objectiveTypes = objectiveTypes + self.upperBounds = upperBounds def run(self, runs, population, generations): solutions = []#store several solutions @@ -36,7 +37,8 @@ def run(self, runs, population, generations): problem = StaffAllocationProblem.StaffAllocationProblem( seeds=self.seeds, parameterReader=self.parameterReader, - objectiveTypes=self.objectiveTypes) + objectiveTypes=self.objectiveTypes, + upperBounds=self.upperBounds) for i in xrange(1, runs + 1): print "Experiment Runner", i diff --git a/reproduction/python_scripts/StaffAllocationProblem.py b/reproduction/python_scripts/StaffAllocationProblem.py index c599be0..312391f 100644 --- a/reproduction/python_scripts/StaffAllocationProblem.py +++ b/reproduction/python_scripts/StaffAllocationProblem.py @@ -23,7 +23,8 @@ def set_results_analyzer(self, resultsAnalyzer): def get_results_analyzer(self): return self.resultsAnalyzer class StaffAllocationProblem(): - def __init__(self, seeds, parameterReader, objectiveTypes): + def __init__(self, seeds, parameterReader, objectiveTypes, upperBounds): + # Defines whether it is a bi-objective or tri-objective model # E.g. objective types [False, True, False] #minimize Waiting time, minimize Resources, maximize throughput @@ -43,7 +44,7 @@ def __init__(self, seeds, parameterReader, objectiveTypes): #self.upperBounds = [8, 8, 25, 8] #self.upperBounds = [1, 60, 60, 5] self.lowerBounds = [1, 1, 1, 1] - self.upperBounds = [60, 60, 60, 60] + self.upperBounds = upperBounds #self.bounder = inspyred.ec.Bounder(1, 4) self.bounder = inspyred.ec.Bounder(self.lowerBounds, self.upperBounds) diff --git a/reproduction/python_scripts/main.py b/reproduction/python_scripts/main.py index 4b40519..409f053 100644 --- a/reproduction/python_scripts/main.py +++ b/reproduction/python_scripts/main.py @@ -10,7 +10,7 @@ def run_scenario(mypath, experimentFolder, file, runs, population, - generations, objectiveTypes, solutionpath=None): + generations, objectiveTypes, upperBounds, solutionpath=None): ''' Run algorithm using the pre-screened percentage from the provided file. @@ -30,6 +30,9 @@ def run_scenario(mypath, experimentFolder, file, runs, population, Number of generations objectiveTypes : list List of booleans which define whether maximise/minimise 2/3 objectives + upperBounds : list of int + Maximum numbers of each staff type allowed - [greeter/line + manager, screener, dispenser, medic] solutionpath : string Optional, path to save solution to ''' @@ -41,7 +44,8 @@ def run_scenario(mypath, experimentFolder, file, runs, population, file)) experimentRunner = ExperimentRunner.ExperimentRunner(seeds, parameterReader, - objectiveTypes) + objectiveTypes, + upperBounds) experimentRunner.run(runs=runs, population=population, generations=generations) @@ -75,7 +79,8 @@ def wrapper(d): def run_experiment(mypath, experimentFolder, experimentFiles, runs, population, - generations, objectiveTypes, solutionpath=None): + generations, objectiveTypes, solutionpath=None, + upperBounds=[60, 60, 60, 60]): ''' Run set of scenarios using parallel processing, and record time elapsed @@ -100,6 +105,9 @@ def run_experiment(mypath, experimentFolder, experimentFiles, runs, population, List of booleans which define whether maximise/minimise 2/3 objectives solutionpath : string Optional, path to save solution to + upperBounds : list of int + Optional, maximum numbers of each staff type allowed - [greeter/line + manager, screener, dispenser, medic] ''' # Start timer startTime = datetime.datetime.now() @@ -113,7 +121,8 @@ def run_experiment(mypath, experimentFolder, experimentFiles, runs, population, 'population': population, 'generations': generations, 'objectiveTypes': objectiveTypes, - 'solutionpath': solutionpath} + 'solutionpath': solutionpath, + 'upperBounds': upperBounds} for file in experimentFiles ]