Run.py - Running the Genetic Algorithm

In this article, we will look at how to run the genetic algorithm. This program is run though the Run.py script, which includes all the information on what cluster to globally optimise and the genetic algorithm settings to use. You can find other examples of Run.py files at github.com/GardenGroupUO/Organisms under Examples\Playground and Examples\Example_Run_Files. Also, you can try out this program by running an example script through a Jupyter notebook. See Examples of Running the Organisms Program with Run.py to get access to examples of running Organisms through this Jupyter notebook!

Running the Genetic Algorithm Program

We will explain how the Run.py code works by running though the example shown below:

Run.py
 1from Organisms import GA_Program
 2
 3# This details the elemental and number of atom composition of cluster that the user would like to investigate
 4cluster_makeup = {"Cu": 37}
 5
 6# Surface details
 7surface_details = None #{'surface': 'surface.xyz', 'place_cluster_where': 'center'}
 8
 9# These are the main variables of the genetic algorithm that with changes could affect the results of the Genetic Algorithm.
10pop_size = 20
11generations = 2000
12no_offspring_per_generation = 16
13
14# These setting indicate how offspring should be made using the Mating and Mutation Proceedures
15creating_offspring_mode = "Either_Mating_and_Mutation" 
16crossover_type = "CAS_weighted"
17mutation_types = [['random', 1.0]]
18chance_of_mutation = 0.1
19
20# This parameter will tell the Organisms program if an epoch is desired, and how the user would like to proceed.
21epoch_settings = {'epoch mode': 'same population', 'max repeat': 5}
22
23# These are variables used by the algorithm to make and place clusters in.
24r_ij = 3.4
25cell_length = r_ij * (sum([float(noAtoms) for noAtoms in list(cluster_makeup.values())]) ** (1.0/3.0))
26vacuum_to_add_length = 10.0
27
28# The RunMinimisation.py algorithm is one set by the user. It contain the def Minimisation_Function
29# That is used for local optimisations. This can be written in whatever way the user wants to perform
30# the local optimisations. This is meant to be as free as possible.
31from RunMinimisation import Minimisation_Function
32
33# This dictionary includes the information required to prevent clusters being placed in the population if they are too similar to clusters in this memory_operator
34memory_operator_information = {'Method': 'Off'}
35
36# This switch tells the genetic algorithm the type of predation scheme they want to place on the genetic algoithm.
37#predation_information = {'Predation Operator':'Off'}
38predation_information = {'Predation Operator':'Energy', 'mode': 'simple', 'round_energy': 2}
39#predation_information = {'Predation Operator':'Energy', 'mode': 'comprehensive', 'minimum_energy_diff': 0.025, 'type_of_comprehensive_scheme': 'energy'}
40#predation_information = {'Predation Operator':'Energy', 'mode': 'comprehensive', 'minimum_energy_diff': 0.025, 'type_of_comprehensive_scheme': 'fitness'}
41#predation_information = {'Predation Operator': 'IDCM', 'percentage_diff': 5.0}
42#predation_information = {'Predation Operator': 'SCM', 'SCM Scheme': 'T-SCM', 'rCut_high': 3.2, 'rCut_low': 2.9, 'rCut_resolution': 0.05}
43
44# This switch tells the genetic algorithm the type of fitness scheme they want to place on the genetic algoithm.
45energy_fitness_function = {'function': 'exponential', 'alpha': 3.0}
46#SCM_fitness_function = {'function': 'exponential', 'alpha': 1.0}
47fitness_information = {'Fitness Operator': 'Energy', 'fitness_function': energy_fitness_function}
48#fitness_information = {'Fitness Operator': 'SCM + Energy', 'Use Predation Information': True, 'SCM_fitness_contribution': 0.5, 'normalise_similarities': False, 'Dynamic Mode': False, 'energy_fitness_function': energy_fitness_function, 'SCM_fitness_function': SCM_fitness_function}
49#fitness_information = {'Fitness Operator': 'SCM + Energy', 'SCM Scheme': 'T-SCM', 'rCut_high': 3.2, 'rCut_low': 2.9, 'rCut_resolution': 0.05, 'SCM_fitness_contribution': 0.5, 'normalise_similarities': False, 'Dynamic Mode': False, 'energy_fitness_function': energy_fitness_function, 'SCM_fitness_function': SCM_fitness_function}
50#fitness_information = {'Fitness Operator': 'SCM + Energy', 'SCM Scheme': 'T-SCM', 'rCut': 3.05, 'SCM_fitness_contribution': 0.5, 'normalise_similarities': False, 'Dynamic Mode': False, 'energy_fitness_function': energy_fitness_function, 'SCM_fitness_function': SCM_fitness_function}
51
52# Variables required for the Recording_Cluster.py class/For recording the history as required of the genetic algorithm.
53ga_recording_information = {}
54ga_recording_information['ga_recording_scheme'] = 'Limit_energy_height' # float('inf')
55ga_recording_information['limit_number_of_clusters_recorded'] = 5 # float('inf')
56ga_recording_information['limit_energy_height_of_clusters_recorded'] = 1.5 #eV
57ga_recording_information['exclude_recording_cluster_screened_by_diversity_scheme'] = True
58ga_recording_information['record_initial_population'] = True
59ga_recording_information['saving_points_of_GA'] = [3,5]
60
61# These are last techinical points that the algorithm is designed in mind
62force_replace_pop_clusters_with_offspring = True
63user_initialised_population_folder = None 
64rounding_criteria = 10
65print_details = False
66no_of_cpus = 2
67finish_algorithm_if_found_cluster_energy = None
68total_length_of_running_time = 70.0
69
70''' ---------------- '''
71# This will execute the genetic algorithm program
72GA_Program(cluster_makeup=cluster_makeup,
73    pop_size=pop_size,
74    generations=generations,
75    no_offspring_per_generation=no_offspring_per_generation,
76    creating_offspring_mode=creating_offspring_mode,
77    crossover_type=crossover_type,
78    mutation_types=mutation_types,
79    chance_of_mutation=chance_of_mutation,
80    r_ij=r_ij,
81    vacuum_to_add_length=vacuum_to_add_length,
82    Minimisation_Function=Minimisation_Function,
83    surface_details=surface_details,
84    epoch_settings=epoch_settings,
85    cell_length=cell_length,
86    memory_operator_information=memory_operator_information,
87    predation_information=predation_information,
88    fitness_information=fitness_information,
89    ga_recording_information=ga_recording_information,
90    force_replace_pop_clusters_with_offspring=force_replace_pop_clusters_with_offspring,
91    user_initialised_population_folder=user_initialised_population_folder,
92    rounding_criteria=rounding_criteria,
93    print_details=print_details,
94    no_of_cpus=no_of_cpus,
95    finish_algorithm_if_found_cluster_energy=finish_algorithm_if_found_cluster_energy,
96    total_length_of_running_time=total_length_of_running_time)
97''' ---------------- '''

Lets go through each part of the Run.py file one by one to understand how to use it.

1) The elemental makeup of the cluster

The first part of Run.py specifies the type of cluster you will be testing. Here, the makeup of the cluster is described using a dictionary in the format, {element: number of that element in the cluster, …}. An example of this is shown below:

3# This details the elemental and number of atom composition of cluster that the user would like to investigate
4cluster_makeup = {"Cu": 37}

2) Details if the cluster lies on a surface

This feature allows the user to include a surface to place a cluster upon. This feature is still being developed and does not currently work.

6# Surface details
7surface_details = None #{'surface': 'surface.xyz', 'place_cluster_where': 'center'}

3) The main details of the genetic algorithm

Here, the components of the genetic algorithm are described below:

  • pop_size (int): The number of clusters in the population.

  • generations (int): The number of generations that will be carried out by the genetic algorithm.

  • no_offspring_per_generation (int): The number of offspring generated per generation.

It is recommended that for a particular test case that one try a few variations for pop_size and no_offspring_per_generation. From the literature, an pop_size = 30 or 40 and no_offspring_per_generation set to 0.8*pop_size is common.

An example of these parameters in Run.py is given below:

 9# These are the main variables of the genetic algorithm that with changes could affect the results of the Genetic Algorithm.
10pop_size = 20
11generations = 2000
12no_offspring_per_generation = 16

4) Details concerning the Mating and Mutation Proceedure

The following set of parameters are focused on settings that involve the Mating and Mutation Procedures of the genetic algorithm. These are processes that affect how new offspring are created during the genetic algorithm. There are four sets of parameters involving the Mating and Mutation Procedures. Firstly, below is a parameter that affects both the Mating and Mutation Procedures:

  • creating_offspring_mode (str.): This indicates how you want these procedures to work when making an offspring. There are two options:

    • "Either_Mating_and_Mutation" - the genetic algorithm will perform either a mating or mutation proceedure to obtain the offspring.

    • "Both_Mating_and_Mutation" - the genetic algorithm will perform both a mating and mutation proceedure to obtain the offspring. Here, the mating scheme will always occur, however there is only a chance that the mutation scheme will occur.

  • crossover_type (str.): The mating method will use the spatial information of two parent clusters to create a new cluster from the two of them. This variable determines which mating proceedure the genetic algorithm will perform.

    • "CAS_weighted": Deavon and Ho Weighted Cut and Splice Method - The cut and splice method, weighted by fitness of parents.

    • "CAS_half": Deavon and Ho Half Cut and Splice Method - The cut and splice method, where poth parents are in half (recommended from experience).

    • "CAS_random": Deavon and Ho Random Cut and Splice Method - The cut and splice method, where one parent is cut a random percent x%, while the other parent is cut by (100-x)%. The value of x changes each time it is used to a random number between 0% and 100% (recommended for LJ98 clusters).

    • "CAS_custom_XX": Deavon and Ho Custom Cut and Splice Method - The cut and splice method, where one parent cut a set percent XX% and the other parent is cut by (100-XX)%. Here, XX is a value that is set by the user. To use this, set crossType = CAS_custom_XX, where XX is a float of your choice between 0 and 100.

  • mutation_types ([[str.,float],…]): The mutation method will change the structure of a cluster to give a new cluster as a result. The type of mutation method the user would like to use. This can one of the following:

    • "random": This will completely erase the previous cluster and generated a new cluster, where atoms have been placed randomly within the cluster

    • "random_XX": This will randomly place XX percent of the atoms in the cluster to new positions in the cluster. (Make this more clear what is going on later)

    • "move": This will move all the atoms in the cluster from their original positions by a maximum default distance equal to r_ij*0.5 Å.

    • "move_XX": This will move all the atoms in the cluster from their original positions by a maximum distance XX Å.

    • "homotop": This will swap the positions of two atoms that are of a different element. This mutation method can not be used for monometallic clusters.

    It is possible for more than one mutation method to be used. For this reason, the format for mutTypes is [[Type of Mutation,chance of mutation],…]. Here, all the chances of mutations should add up to 1.0. For example, “mutTypes = [[random, 0.45], [move, 0.225], [random_33.33, 0.325]]” is acceptable as all the chances of mutations add up to 1.0 (0.45 + 0.225 + 0.325 = 1.0).

  • chance_of_mutation (float): The chance that a mutation will occur. How the genetic algorithm uses this variable depends on the input for creating_offspring_mode. If:

    • creating_offspring_mode = "Either_Mating_and_Mutation" - chance_of_mutation is the chance that a mutation will occur rather than a mating scheme.

    • creating_offspring_mode = "Both_Mating_and_Mutation" - chance_of_mutation is the chance that a mutation will occur. The mating scheme will always occur when creating_offspring_mode = "Both_Mating_and_Mutation".

An example of these parameters used in the Run.py file is given below:

14# These setting indicate how offspring should be made using the Mating and Mutation Proceedures
15creating_offspring_mode = "Either_Mating_and_Mutation" 
16crossover_type = "CAS_weighted"
17mutation_types = [['random', 1.0]]
18chance_of_mutation = 0.1

5) Epoch Settings

It is possible to include a epoch in this version of the genetic algorithm. An epoch is a feature that allows the population to be reset with new, randomly generated clusters. See Using Epoch Methods for more information on epoch methods, including the various types of epoches and settings.

An example of the epoch parameters used in the Run.py file is given below:

20# This parameter will tell the Organisms program if an epoch is desired, and how the user would like to proceed.
21epoch_settings = {'epoch mode': 'same population', 'max repeat': 5}

6) Other Details

There are three other variables which are important to include in your Run.py file. These are:

  • r_ij (float): This is the maximum bond distance that we would expect in this cluster. This parameter is used when clusters are created using either or both the mating or mutation schemes. This parameter is used to determine if a cluster has stayed in one piece after the local minimisation, as it is possible for the cluster to break into multiple pieces. This should be a reasonable distance, but not excessively large. For example, for Au, which has a FCC lattice constant of 4.078 Å. Therefore it has a first nearest neighbour of 2.884 Å and a second nearest neighbour of 4.078 Å. Therefore r_ij should be set to some value between 2.884 Å and 4.078 Å. For example, r_ij = 3.5 Å or r_ij = 4.0 Å would probably be appropriate, however I have been able to get away with r_ij = 3.0 Å. r_ij is given in Å.

  • cell_length (float): If you are wanting to create randomly generated clusters, either at the start of the genetic algorithm or using the ‘random’ mutation method, then you will want to specify the length of the box that you want to add atoms to. boxtoplaceinlength is the length of this box. Don’t make this too big, or else it is likely atoms will be too far apart and a cluster will be broken into multiple pieces. cell_length is given in Å.

  • vacuum_to_add_length (float): The length of vacuum added around the cluster. This variable is only used to aesthetics reasons. How the genetic algorithm records clusters for databases is to take the locally optimised cluster and measure its radius. A new cell is then created with cell length that is twice the radius of the cluster. The cluster is then placed in this new cell, and a vacumm of vacuum_to_add_length is then added to this new cell. The reason for taking the radius of the cluster to make a cell is so that no matter if and how you rotate the cluster for post processing, you can be assurred that the cluster will always have a vacuum of at least vacuum_to_add_length Å. This is important especially if you reoptimise the cluster with periodic potential such as VASP where it is vital that a minimum vacuum is given to prevent reoptimisation issues from occurring. vacuum_to_add_length is given in Å.

An example of these parameters used in the Run.py file is given below:

23# These are variables used by the algorithm to make and place clusters in.
24r_ij = 3.4
25cell_length = r_ij * (sum([float(noAtoms) for noAtoms in list(cluster_makeup.values())]) ** (1.0/3.0))
26vacuum_to_add_length = 10.0

7) Minimisation Scheme

This component of Run.py focuses on the function/method that the genetic algorithm uses for performing local minimisations. This is used by the genetic algorithm as a def type (i.e. as a function). This means that, rather than a variable being passed into the algorithm, a function is passed into the algorithm.

One can write this function into the Run.py file, however it is usually easier and nicer to view this function in a different python file. I typically call this something like RunMinimisation.py, and the function in this file is called Minimisation_Function. Minimisation_Function will contain the algorithm for performing a local optimisation.

Because of the flexibility, it is possible to use any type of calculator from ASE, ASAP, GWAP, LAMMPS, etc. It is even possible for the user to design this to use with non-python user-interface based local optimisers, such as VASP or Quantum Espresso!

To see an example of how to write Minimisation_Function, see Writing a Local Minimisation Function for the Genetic Algorithm.

The algorithm is imported into Run.py as follows:

28# The RunMinimisation.py algorithm is one set by the user. It contain the def Minimisation_Function
29# That is used for local optimisations. This can be written in whatever way the user wants to perform
30# the local optimisations. This is meant to be as free as possible.
31from RunMinimisation import Minimisation_Function

8) The Memory Operator

This operator is designed to prevent clusters from being in the population that resemble any cluster in this memory operator in some way. This operator uses the SCM to determine how structurally similar cluster are. See Using the Memory Operator for more information on how to use the memory operator. An example of how the memory operator is written in the Run.py file is shown below.

33# This dictionary includes the information required to prevent clusters being placed in the population if they are too similar to clusters in this memory_operator
34memory_operator_information = {'Method': 'Off'}

9) Predation Operators

This component of Run.py specifies all the information concerning the predation operator. You can see more about how the predation operators works at Using Predation Operators with the Genetic Algorithm.

In terms of the Run.py file, there is only one variable that we need to deal with, predation_information. This variable is a dictionary type, {}, which holds all the information that would been needed for the predation operator that the user wishes to use. For example:

predation_information = {'Predation_Switch': 'SCM', 'SCM Scheme': 'T-SCM', 'rCut_high': 3.2, 'rCut_low': 2.9, 'rCut_resolution': 0.05}

There are a variety of predation operators that are inbuilt currently into the genetic algorithm. You can find out more about what they do, and how to use them in your Run.py file, at Using Predation Operators with the Genetic Algorithm.

Below are some other examples of the inputs required for the other types of predation operators available. Please see Using Predation Operators with the Genetic Algorithm before using these predation operators.

36# This switch tells the genetic algorithm the type of predation scheme they want to place on the genetic algoithm.
37#predation_information = {'Predation Operator':'Off'}
38predation_information = {'Predation Operator':'Energy', 'mode': 'simple', 'round_energy': 2}
39#predation_information = {'Predation Operator':'Energy', 'mode': 'comprehensive', 'minimum_energy_diff': 0.025, 'type_of_comprehensive_scheme': 'energy'}
40#predation_information = {'Predation Operator':'Energy', 'mode': 'comprehensive', 'minimum_energy_diff': 0.025, 'type_of_comprehensive_scheme': 'fitness'}
41#predation_information = {'Predation Operator': 'IDCM', 'percentage_diff': 5.0}
42#predation_information = {'Predation Operator': 'SCM', 'SCM Scheme': 'T-SCM', 'rCut_high': 3.2, 'rCut_low': 2.9, 'rCut_resolution': 0.05}

10) Fitness Operators

This component of Run.py specified all the information required by the fitness operators. You can find more information about how the fitness operators works at Using Fitness Operators with the Genetic Algorithm.

In the Run.py file, all the setting for the fitness operator are contained in the dictionary called fitness_information. For example:

fitness_information = {'Fitness Operator': 'Energy', 'fitness_function': energy_fitness_function}

There are a variety of fitness scheme available to be used in this implementation of the genetic algorithm. You can find all the information about all the available fitness schemes in Using Fitness Operators with the Genetic Algorithm.

An example of how the fitness scheme is written in the Run.py file is shown below. Please see Using Fitness Operators with the Genetic Algorithm before using these fitness operators.

44# This switch tells the genetic algorithm the type of fitness scheme they want to place on the genetic algoithm.
45energy_fitness_function = {'function': 'exponential', 'alpha': 3.0}
46#SCM_fitness_function = {'function': 'exponential', 'alpha': 1.0}
47fitness_information = {'Fitness Operator': 'Energy', 'fitness_function': energy_fitness_function}
48#fitness_information = {'Fitness Operator': 'SCM + Energy', 'Use Predation Information': True, 'SCM_fitness_contribution': 0.5, 'normalise_similarities': False, 'Dynamic Mode': False, 'energy_fitness_function': energy_fitness_function, 'SCM_fitness_function': SCM_fitness_function}
49#fitness_information = {'Fitness Operator': 'SCM + Energy', 'SCM Scheme': 'T-SCM', 'rCut_high': 3.2, 'rCut_low': 2.9, 'rCut_resolution': 0.05, 'SCM_fitness_contribution': 0.5, 'normalise_similarities': False, 'Dynamic Mode': False, 'energy_fitness_function': energy_fitness_function, 'SCM_fitness_function': SCM_fitness_function}
50#fitness_information = {'Fitness Operator': 'SCM + Energy', 'SCM Scheme': 'T-SCM', 'rCut': 3.05, 'SCM_fitness_contribution': 0.5, 'normalise_similarities': False, 'Dynamic Mode': False, 'energy_fitness_function': energy_fitness_function, 'SCM_fitness_function': SCM_fitness_function}

11) Recording Clusters from the Genetic Algorithm

This input in the Run.py file indicates how the user would like to record clusters that are created during the genetic algorithm. The information is contained in the dictionary called ga_recording_information. There are six parameters that the user can set. These are:

  • ga_recording_scheme

  • limit_number_of_clusters_recorded

  • limit_energy_height_of_clusters_recorded

  • exclude_recording_cluster_screened_by_diversity_scheme

  • saving_points_of_GA

  • record_initial_population

Not all of these parameters need to be entered. If the user does not enter in any of these parameters, the genetic algorithm will not keep a record of the clusters that were obtained.

More information on how to record clusters made during the genetic algorithm can be found at Recording Clusters From The Genetic Algorithm.

An example of the 'ga_recording_information' variable in the Run.py file is shown below. Please see Recording Clusters From The Genetic Algorithm before using this feature to record clusters obtained during the genetic algorithm.

52# Variables required for the Recording_Cluster.py class/For recording the history as required of the genetic algorithm.
53ga_recording_information = {}
54ga_recording_information['ga_recording_scheme'] = 'Limit_energy_height' # float('inf')
55ga_recording_information['limit_number_of_clusters_recorded'] = 5 # float('inf')
56ga_recording_information['limit_energy_height_of_clusters_recorded'] = 1.5 #eV
57ga_recording_information['exclude_recording_cluster_screened_by_diversity_scheme'] = True
58ga_recording_information['record_initial_population'] = True
59ga_recording_information['saving_points_of_GA'] = [3,5]

12) Other details of the Genetic algorithm

These last set of parameters are important, but there is no good appropriate place to put them in the Run.py file. These last parameters are:

  • force_replace_pop_clusters_with_offspring (bool): In the genetic algorithm, the predation operator may find that the an offspring is “identical” to a cluster in the population, but that offspring is more fit than the cluster in the population. In this case, the genetic algorithm can replace the less fit cluster in the population with the “identical” more fit offspring. Set this variable to True if you want this to happen. Set this variable to False if you don’t want this to happen. Default: True.

  • user_initilised_population_folder (str.): This is the name, or the path to, the folder holding the initalised population that you would like to use instead of the program creating a set of randomly generated clusters. If you do not have, or do not want to use, an initialised population, set this to None or ''.

  • rounding_criteria (int): This is the round that will be enforced on the value of the cluster energy. Default: 2

  • print_details (bool): Will print the details of the genetic algotithm, like a verbose.

  • no_of_cpus (int): This is the number of cpus that you would like the algorithm to run on. These extra cores will be used to create the offspring as well as used by the predation and fitness operators if beneficial to use extra cores for the chosen operators.

  • finish_algorithm_if_found_cluster_energy (dict.): This parameter will stop the algorithm if the desired global minimum is found. This parameter is to be used if the user would like to test the performance of the algorithm and knows beforehand what the energy of the global minimum is. This parameter is set as a dictionary as two parameters. ‘cluster energy’ is a float that states the energy of the global minimum. ‘round’ is an interger that you want to set to the same rounding that you gave for the ‘cluster energy’ input. This will round the energy of clusters made, and compare this energy to your ‘cluster energy’ input. An example of this for Au38 using Cleri Gupta parameters are finish_algorithm_if_found_cluster_energy = {'cluster energy': -130.54, 'round': 2}. If you are not testing the performance of the algorithm, or dont know the global minimum of the cluster you are testing, set finish_algorithm_if_found_cluster_energy = None. Default: None

  • total_length_of_running_time (int): This is the maximum amount of time (in hours) that the algorithm is allow to run for. This variable is useful if you are running on a remote computer system like slurm that finishes once a certain time limit is reached. To prevent the algorithm from being incorrectly cancelled when running, set this value to a time limit less than your maximum time limit on slurm. I have been setting this to the slurm job time minus 2 hours. For example, if the genetic algorithm is submitted to slurm for 72 hours, set total_length_of_running_time=70.0. While this algorithm is designed to be able to be restarted even if the program is cancelled during a generation, it is best to prevent any issues from occurring by using this variable to cancel the algorithm safety so that there are absolutely no issues when restarting the genetic algorithm. Is None is given, no time limit will be set. Default: None

An example of how they are written in the Run.py file are show below:

61# These are last techinical points that the algorithm is designed in mind
62force_replace_pop_clusters_with_offspring = True
63user_initialised_population_folder = None 
64rounding_criteria = 10
65print_details = False
66no_of_cpus = 2
67finish_algorithm_if_found_cluster_energy = None
68total_length_of_running_time = 70.0

The Genetic Algorithm!

You have got to the end of all the parameter setting stuff! Now on to the fun stuff! The next part of the Run.py file tells the genetic algorithm to run. This is written as follows in the Run.py:

71# This will execute the genetic algorithm program
72GA_Program(cluster_makeup=cluster_makeup,
73    pop_size=pop_size,
74    generations=generations,
75    no_offspring_per_generation=no_offspring_per_generation,
76    creating_offspring_mode=creating_offspring_mode,
77    crossover_type=crossover_type,
78    mutation_types=mutation_types,
79    chance_of_mutation=chance_of_mutation,
80    r_ij=r_ij,
81    vacuum_to_add_length=vacuum_to_add_length,
82    Minimisation_Function=Minimisation_Function,
83    surface_details=surface_details,
84    epoch_settings=epoch_settings,
85    cell_length=cell_length,
86    memory_operator_information=memory_operator_information,
87    predation_information=predation_information,
88    fitness_information=fitness_information,
89    ga_recording_information=ga_recording_information,
90    force_replace_pop_clusters_with_offspring=force_replace_pop_clusters_with_offspring,
91    user_initialised_population_folder=user_initialised_population_folder,
92    rounding_criteria=rounding_criteria,
93    print_details=print_details,
94    no_of_cpus=no_of_cpus,
95    finish_algorithm_if_found_cluster_energy=finish_algorithm_if_found_cluster_energy,
96    total_length_of_running_time=total_length_of_running_time)