MakeTrials.py - Creating Multiple, Repeated Genetic Algorithm Trials

Typically, it is common that one will not run just one genetic algorithm run, but multiple genetic algorithm runs with the same parameters. This can a pain to set up all the files to make the multiple runs and run them all. It can also be very hard to analyse all the data together, since there is just so much! Therefore, we have developed a set of scripts to make this experience less painful for the user.

In this article, we will look at how to use some of the tools that have been developed to create and run many genetic algorithm runs on slurm. Slurm (Slurm Workload Manager) is a Linux resource management system for running a computer cluster system. See Slurm Workload Manager for more information about slurm.

In the next article (Helpful Programs for Gathering data and Post-processing Data) we describe a set of scripts to analyse the data from the multiple genetic algorithms.

What to make sure is done before running the MakeTrials.py program.

If you installed Organisms through pip3

If you installed the Organisms program with pip3, these scripts will be installed in your bin. You do not need to add anything into your ~/.bashrc. You are all good to go.

If you performed a Manual installation

If you have manually added this program to your computer (such as cloning this program from Github), you will need to make sure that you have included the Helpful_Programs folder into your PATH in your ~/.bashrc file. All of these program can be found in the Helpful_Programs folder. To execute some of these programs from the Helpful_Programs folder, you must include the following in your ~/.bashrc:

export PATH_TO_GA="<Path_to_Organisms>"

where <Path_to_Organisms>" is the path to get to the genetic algorithm program. Also include somewhere before this in your ~/.bashrc:

export PATH="$PATH_TO_GA"/Organisms/Helpful_Programs:$PATH

See more about this in Installation of the Genetic Algorithm.

How does MakeTrials.py work?

MakeTrials.py is a script which uses the MakeTrialsProgram class in Organisms.SubsidiaryPrograms.MakeTrialsProgram (found in Organisms/SubsidiaryPrograms/MakeTrialsProgram.py) to make all the files that one would need to make to perform a set of repeated the genetic algorithm upon a cluster system. This will create lots of the same genetic algorithm files (Run.py and RunMinimisation.py) and put them into folders called Trials.

You can find another example of a MakeTrials.py file and other associated files at github.com/GardenGroupUO/Organisms under Examples\CreateSets.

Setting up MakeTrials.py

MakeTrials.py is designed to make all the trials desired for a specific cluster system. This is designed to be as customisable as possible. A typical MakeTrials.py script will look as follows:

MakeTrials.py
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
from Organisms import MakeTrialsProgram

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

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

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

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

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

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

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

# 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
memory_operator_information = {'Method': 'Off'}

# This dictionary includes the information required by the predation scheme
predation_information = {'Predation Operator': 'SCM', 'SCM Scheme': 'TC-SRA', 'rCut_high': 3.2, 'rCut_low': 2.9, 'rCut_resolution': 0.05}

# This dictionary includes the information required by the fitness scheme
energy_fitness_function = {'function': 'exponential', 'alpha': 3.0}
SCM_fitness_function = {'function': 'exponential', 'alpha': 1.0}
fitness_information = {'Fitness Operator': 'SCM + Energy', 'Use Predation Information': True, 'SCM_fitness_contribution': 0.5, 'Dynamic Mode': False, 'energy_fitness_function': energy_fitness_function, 'SCM_fitness_function': SCM_fitness_function}

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

# These are last techinical points that the algorithm is designed in mind
force_replace_pop_clusters_with_offspring = True
user_initialised_population_folder = None 
rounding_criteria = 10
print_details = False
no_of_cpus = 2
finish_algorithm_if_found_cluster_energy = None
total_length_of_running_time = None

# These are the details that will be used to create all the Trials for this set of genetic algorithm experiments.
dir_name = 'ThisIsTheFolderThatScriptsWillBeWrittenTo'
NoOfTrials = 100
Condense_Single_Mention_Experiments = True
making_files_for = 'slurm_JobArrays_full'
finish_algorithm_if_found_cluster_energy = None
total_length_of_running_time = 6.0

# These are the details that are used to create the Job Array for slurm
JobArraysDetails = {}
JobArraysDetails['mode'] = 'JobArray'
JobArraysDetails['project'] = 'uoo00084'
JobArraysDetails['time'] = '8:00:00'
JobArraysDetails['nodes'] = 1
JobArraysDetails['ntasks_per_node'] = no_of_cpus
JobArraysDetails['mem'] = '1G'
JobArraysDetails['email'] = "geoffreywealslurmnotifications@gmail.com"
JobArraysDetails['python version'] = 'Python/3.6.3-gimkl-2017a'

''' ---------------- '''
# Write all the trials that the user desires
MakeTrialsProgram(cluster_makeup=cluster_makeup,
    pop_size=pop_size,
    generations=generations,
    no_offspring_per_generation=no_offspring_per_generation,
    creating_offspring_mode=creating_offspring_mode,
    crossover_type=crossover_type,
    mutation_types=mutation_types,
    chance_of_mutation=chance_of_mutation,
    r_ij=r_ij,
    vacuum_to_add_length=vacuum_to_add_length,
    Minimisation_Function=Minimisation_Function,
    surface_details=surface_details,
    epoch_settings=epoch_settings,
    cell_length=cell_length,
    memory_operator_information=memory_operator_information,
    predation_information=predation_information,
    fitness_information=fitness_information,
    ga_recording_information=ga_recording_information,
    force_replace_pop_clusters_with_offspring=force_replace_pop_clusters_with_offspring,
    user_initialised_population_folder=user_initialised_population_folder,
    rounding_criteria=rounding_criteria,
    print_details=print_details,
    no_of_cpus=no_of_cpus,
    dir_name=dir_name,
    NoOfTrials=NoOfTrials,
    Condense_Single_Mention_Experiments=Condense_Single_Mention_Experiments,
    JobArraysDetails=JobArraysDetails,
    making_files_for=making_files_for,
    finish_algorithm_if_found_cluster_energy=finish_algorithm_if_found_cluster_energy,
    total_length_of_running_time=total_length_of_running_time)
''' ---------------- '''

We will now explain the components of this script. Many of the variable have been explained in Run.py - Using the Genetic Algorithm. These are cluster_makeup, surface_details, pop_size, generations, no_offspring_per_generation, creating_offspring_mode, crossover_type, mutation_types, chance_of_mutation, epoch_settings, r_ij, cell_length, vacuum_to_add_length, Minimisation_Function, memory_operator_information, predation_information, fitness_information, ga_recording_information, force_replace_pop_clusters_with_offspring, user_initilised_population_folder, rounding_criteria, print_details, no_of_cpus, finish_algorithm_if_found_cluster_energy and total_length_of_running_time.

Here, we will cover the meaning for variables dir_name, NoOfTrials, Condense_Single_Mention_Experiments, making_files_for and JobArraysDetails.

1) Details to create all the desired trials

These include the details needed for this program to make the trials desired. These variables are:

  • dir_name (str.): This is the name of the folder to put the trials into.

  • NoOfTrials (int.): This is the number of trials you would like to create.

  • Condense_Single_Mention_Experiments (bool.): This program is designed to place the trials in a ordered system. If this is set to true, the trials will be put in a folder called XN_P_p_O_o, where XN is the cluster makeup, p is the size of the population, and o is the number of offspring make per generations. If this is set to False, the directory that will be made will be X/XN/Pop_p/Off_o, where X are the elements that make up the cluster, XN is the cluster makeup, p is the size of the population, and o is the number of offspring make per generations.

  • making_files_for (str.): This tells how the MakeTrials program will write files for performing multiple genetic algorithm trials. See How files are created for running multiple genetic algorithm trials for more information about this.

  • no_of_packets_to_make (int): If making_files_for = 'slurm_JobArrays_packets', then this tells the MakeTrials program how to split the NoOfTrials number of genetic algorithm trials into packets. See How files are created for running multiple genetic algorithm trials for more information about this.

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

62
63
64
65
66
67
68
# These are the details that will be used to create all the Trials for this set of genetic algorithm experiments.
dir_name = 'ThisIsTheFolderThatScriptsWillBeWrittenTo'
NoOfTrials = 100
Condense_Single_Mention_Experiments = True
making_files_for = 'slurm_JobArrays_full'
finish_algorithm_if_found_cluster_energy = None
total_length_of_running_time = 6.0

1.1) making_files_for: How files are created for running multiple genetic algorithm trials

This option is designed to write the submit.sl or mass_submit.sl scripts that you need for running multiple genetic algorithm trial jobs on slurm. There are three options for this setting. These options for JobArraysDetails['mode'] are 'individual', 'slurm_JobArrays_full', and 'slurm_JobArrays_packets'.

If 'individual', MakeTrials will create a slurm.sl file for each individual genetic algorithm trial.

If 'slurm_JobArrays_full', MakeTrials will create a mass_slurm.sl file will submit an array job that performs NoOfTrials genetic algorithm trials. An example of this shown below.

mass_submit_full.sl
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#!/bin/bash -e
#SBATCH -J Data_fitness_changed_in_epoch_max_repeat_5_try2_Epoch_D_Energy_F_1rCut_SCM_alpha_3_fitness_normalised_F_SCM_0.0_1rCut_Ne38_P20_O16
#SBATCH -A uoo00084         # Project Account

#SBATCH --array=1-1000

#SBATCH --time=72:00:00     # Walltime
#SBATCH --nodes=1
#SBATCH --ntasks-per-node=1
#SBATCH --mem=300MB

#SBATCH --partition=large
#SBATCH --output=arrayJob_%A_%a.out
#SBATCH --error=arrayJob_%A_%a.err
#SBATCH --mail-user=geoffreywealslurmnotifications@gmail.com
#SBATCH --mail-type=ALL

######################
# Begin work section #
######################

# Print this sub-job's task ID
echo "My SLURM_ARRAY_JOB_ID: "${SLURM_ARRAY_JOB_ID}
echo "My SLURM_ARRAY_TASK_ID: "${SLURM_ARRAY_TASK_ID}

module load Python/3.6.3-gimkl-2017a

if [ ! -d Trial${SLURM_ARRAY_TASK_ID} ]; then
    mkdir Trial${SLURM_ARRAY_TASK_ID}
fi
cp Run.py Trial${SLURM_ARRAY_TASK_ID}
cp RunMinimisation_LJ.py Trial${SLURM_ARRAY_TASK_ID}
cd Trial${SLURM_ARRAY_TASK_ID}
python Run.py
cd ..
cp arrayJob_${SLURM_ARRAY_JOB_ID}_${SLURM_ARRAY_TASK_ID}.out Trial${SLURM_ARRAY_TASK_ID}
cp arrayJob_${SLURM_ARRAY_JOB_ID}_${SLURM_ARRAY_TASK_ID}.err Trial${SLURM_ARRAY_TASK_ID}

If 'slurm_JobArrays_packets', MakeTrials will create a mass_slurm.sl file will submit an array job that performs NoOfTrials genetic algorithm trials. However, these will be run as no_of_packets_to_make number of packets that are running on slurm, where each packet is made up of \(\frac{\rm{NoOfTrials}}{\rm{no\_of\_packets\_to\_make}}\) genetic algorithm trials that are run in series. Use the 'slurm_JobArrays_packets' setting if you think each individual genetic algorithm trial will run for only a short amount of time (less than 5-10 minutes on average). The reason for using this setting rather than 'slurm_JobArrays_full' is because running lots of short jobs on slurm can cause issues for the slurm controller that controls the queue on slurm.

IMPORTANT: Make sure that the amount of time you have given for JobArraysDetails['time'] is much greater than the maximum amount of time you think each trial will be completed in times no_of_packets_to_make, i.e.

\[\rm{maximum\,amount\,of\,time\,to\,run\,one\,GA\,trial} \times \frac{\rm{NoOfTrials}}{\rm{no\_of\_packets\_to\_make}} << \rm{JobArraysDetails['time']}\]

If the below is not true, then it is recommended to use a partition on slurm that allows you to set :math:{rm{JobArraysDetails[‘time’]}} to as long as possible so that the above equation is true. If you cant do this, consider breaking up running all your GA trials with a greater value of no_of_packets_to_make (up to :math:{rm{no_of_packets_to_make} = frac{rm{NoOfTrials}}{2}}). If you cant do this as well, lower your value of NoOfTrials and do all your trials bit by bit (for example, if performing 1,000,000 trials, first run trials 1-1000, then trials 1001-2000, then trials 2001-3000, so on …).

Avoid using 'slurm_JobArrays_full' if possible as performing lots of small jobs on slurm can break slurm. If you cant avoid it, use 'slurm_JobArrays_full' with caution.

As a guideline, set JobArraysDetails['time'] to as large a wall time as possible for the partition you are using on your slurm cluster.

An example of this shown below.

mass_submit_packets.sl
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#!/bin/bash -e
#SBATCH -J Data_fitness_changed_in_epoch_max_repeat_5_try2_Epoch_D_Energy_F_1rCut_SCM_alpha_3_fitness_normalised_F_SCM_0.0_1rCut_Ne38_P20_O16
#SBATCH -A uoo00084         # Project Account

#SBATCH --array=1-50

#SBATCH --time=72:00:00     # Walltime
#SBATCH --nodes=1
#SBATCH --ntasks-per-node=1
#SBATCH --mem=300MB

#SBATCH --partition=large
#SBATCH --output=arrayJob_%A_%a.out
#SBATCH --error=arrayJob_%A_%a.err
#SBATCH --mail-user=geoffreywealslurmnotifications@gmail.com
#SBATCH --mail-type=ALL

######################
# Begin work section #
######################

# Print this sub-job's task ID
echo "My SLURM_ARRAY_JOB_ID: "${SLURM_ARRAY_JOB_ID}
echo "My SLURM_ARRAY_TASK_ID: "${SLURM_ARRAY_TASK_ID}

module load Python/3.6.3-gimkl-2017a

number_of_divides=20
for i in $( eval echo {1..${number_of_divides}} ); do

trial_no=$(( $(( $(( ${SLURM_ARRAY_TASK_ID} - 1)) * ${number_of_divides} )) + $i ))
echo Currently performing caluclation on trial: $trial_no

if [ ! -d Trial${trial_no} ]; then
    mkdir Trial${trial_no}
fi
cp Run.py Trial${trial_no}
cp RunMinimisation_LJ.py Trial${trial_no}
cd Trial${trial_no}
python Run.py
cd ..
cp arrayJob_${SLURM_ARRAY_JOB_ID}_${SLURM_ARRAY_TASK_ID}.out Trial${trial_no}/arrayJob_${SLURM_ARRAY_JOB_ID}_${trial_no}.out
cp arrayJob_${SLURM_ARRAY_JOB_ID}_${SLURM_ARRAY_TASK_ID}.err Trial${trial_no}/arrayJob_${SLURM_ARRAY_JOB_ID}_${trial_no}.err
echo -n "" > arrayJob_${SLURM_ARRAY_JOB_ID}_${SLURM_ARRAY_TASK_ID}.out
echo -n "" > arrayJob_${SLURM_ARRAY_JOB_ID}_${SLURM_ARRAY_TASK_ID}.err

done

2) Slurm Details

The JobArraysDetails dictionary contains all the information that will be needed to write the submit.sl or mass_submit.sl scripts that you need for running multiple genetic algorithm trial jobs on slurm. The parameters to be entered into the JobArraysDetails dictionary are:

  • project (str.): The name of the project to run this on.

  • partition (str.): The partition to run this on.

  • time (str.): The length of time to give these jobs. This is given in ‘HH:MM:SS’, where HH is the number of hours, MM is the number of minutes, and SS is the number of seconds to run the genetic algorithm for.

  • nodes (int): The number of nodes to use. Best to set this to 1.

  • ntasks_per_node (int): The number of cpus to run these jobs across on a node. It is best to set this to the same value as no_of_cpus in the MakeTrials.py file.

  • mem (str.): This is the memory that is used in total by the job.

  • email (str.): This is the email address to send slurm messages to about this job. If you do not want to give an email, write here either None or ''.

  • python version (str.): This give the submit script the version of python to load when submitting this job on slurm. The default is 'Python/3.6.3-gimkl-2017a'. However, if instead you want to use Python 3.7, you could write here JobArraysDetails['python version'] = 'Python/3.7.3-gimkl-2018b'. In slurm write module avail python to find out what versions of python you have available on your computer cluster system.

See sbatch - Slurm Workload Manager - SchedMD and The Slurm job scheduler to learn more about these parameters in the submit.sl script for slurm.

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

70
71
72
73
74
75
76
77
78
79
# These are the details that are used to create the Job Array for slurm
JobArraysDetails = {}
JobArraysDetails['mode'] = 'JobArray'
JobArraysDetails['project'] = 'uoo00084'
JobArraysDetails['time'] = '8:00:00'
JobArraysDetails['nodes'] = 1
JobArraysDetails['ntasks_per_node'] = no_of_cpus
JobArraysDetails['mem'] = '1G'
JobArraysDetails['email'] = "geoffreywealslurmnotifications@gmail.com"
JobArraysDetails['python version'] = 'Python/3.6.3-gimkl-2017a'

3) Time to Run the MakeTrials Program

Now all there is to do is to run this program!

 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
# Write all the trials that the user desires
MakeTrialsProgram(cluster_makeup=cluster_makeup,
    pop_size=pop_size,
    generations=generations,
    no_offspring_per_generation=no_offspring_per_generation,
    creating_offspring_mode=creating_offspring_mode,
    crossover_type=crossover_type,
    mutation_types=mutation_types,
    chance_of_mutation=chance_of_mutation,
    r_ij=r_ij,
    vacuum_to_add_length=vacuum_to_add_length,
    Minimisation_Function=Minimisation_Function,
    surface_details=surface_details,
    epoch_settings=epoch_settings,
    cell_length=cell_length,
    memory_operator_information=memory_operator_information,
    predation_information=predation_information,
    fitness_information=fitness_information,
    ga_recording_information=ga_recording_information,
    force_replace_pop_clusters_with_offspring=force_replace_pop_clusters_with_offspring,
    user_initialised_population_folder=user_initialised_population_folder,
    rounding_criteria=rounding_criteria,
    print_details=print_details,
    no_of_cpus=no_of_cpus,
    dir_name=dir_name,
    NoOfTrials=NoOfTrials,
    Condense_Single_Mention_Experiments=Condense_Single_Mention_Experiments,
    JobArraysDetails=JobArraysDetails,
    making_files_for=making_files_for,
    finish_algorithm_if_found_cluster_energy=finish_algorithm_if_found_cluster_energy,
    total_length_of_running_time=total_length_of_running_time)

Can I make writing trials easily for many types of system.

The answer is yes. This program has been designed to be as flexible as possible. For example, the following MakeTrials script will make 100 trials for various types of cluster systems, and for various population and offspring per generation sizes.

MakeTrials_Multiple.py
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
from Organisms import MakeTrialsProgram

from RunMinimisation_Cu import Minimisation_Function as Minimisation_Function_Cu
from RunMinimisation_Au import Minimisation_Function as Minimisation_Function_Au
from RunMinimisation_AuPd import Minimisation_Function as Minimisation_Function_AuPd

cluster_makeups = [({"Cu": 37}, Minimisation_Function_Cu), ({"Au": 55}, Minimisation_Function_Au), ({"Au": 21, "Pd": 17}, Minimisation_Function_AuPd)]
genetic_algorithm_systems = [(20,16), (100,80), (50,1)]

for cluster_makeup, Minimisation_Function in cluster_makeups:
    for pop_size, no_offspring_per_generation in genetic_algorithm_systems:
        # Surface details
        surface_details = {}

        # These are the main variables of the genetic algorithm that with changes could affect the results of the Genetic Algorithm.
        generations = 2000

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

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

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

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

        # 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
        memory_operator_information = {'Method': 'Off'}

        # This dictionary includes the information required by the predation scheme
        predation_information = {'Predation Operator':'Energy', 'mode': 'comprehensive', 'minimum_energy_diff': 0.025}

        # This dictionary includes the information required by the fitness scheme
        energy_fitness_function = {'function': 'exponential', 'alpha': 3.0}
        SCM_fitness_function = {'function': 'exponential', 'alpha': 1.0}
        fitness_information = {'Fitness Operator': 'SCM + Energy', 'Use Predation Information': False, 'SCM_fitness_contribution': 0.5, 'Dynamic Mode': False, 'energy_fitness_function': energy_fitness_function, 'SCM_fitness_function': SCM_fitness_function}

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

        # These are last techinical points that the algorithm is designed in mind
        force_replace_pop_clusters_with_offspring = True
        user_initialised_population_folder = None 
        rounding_criteria = 10
        print_details = False
        no_of_cpus = 2
        finish_algorithm_if_found_cluster_energy = None
        total_length_of_running_time = None

        ''' ---------------- '''
        # These are the details that will be used to create all the Trials for this set of genetic algorithm experiments.
        dir_name = 'ThisIsTheFolderThatScriptsWillBeWrittenTo'
        NoOfTrials = 100
        Condense_Single_Mention_Experiments = True
        making_files_for = 'slurm_JobArrays_full'

        ''' ---------------- '''
        # These are the details that are used to create the Job Array for slurm
        JobArraysDetails = {}
        JobArraysDetails['mode'] = 'JobArray'
        JobArraysDetails['project'] = 'uoo00084'
        JobArraysDetails['time'] = '8:00:00'
        JobArraysDetails['nodes'] = 1
        JobArraysDetails['ntasks_per_node'] = no_of_cpus
        JobArraysDetails['mem'] = '1G'
        JobArraysDetails['email'] = "geoffreywealslurmnotifications@gmail.com"
        JobArraysDetails['python version'] = 'Python/3.6.3-gimkl-2017a'

        ''' ---------------- '''
        # Write all the trials that the user desires
        MakeTrialsProgram(cluster_makeup=cluster_makeup,
            pop_size=pop_size,
            generations=generations,
            no_offspring_per_generation=no_offspring_per_generation,
            creating_offspring_mode=creating_offspring_mode,
            crossover_type=crossover_type,
            mutation_types=mutation_types,
            chance_of_mutation=chance_of_mutation,
            r_ij=r_ij,
            vacuum_to_add_length=vacuum_to_add_length,
            Minimisation_Function=Minimisation_Function,
            surface_details=surface_details,
            epoch_settings=epoch_settings,
            cell_length=cell_length,
            memory_operator_information=memory_operator_information,
            predation_information=predation_information,
            fitness_information=fitness_information,
            ga_recording_information=ga_recording_information,
            force_replace_pop_clusters_with_offspring=force_replace_pop_clusters_with_offspring,
            user_initialised_population_folder=user_initialised_population_folder,
            rounding_criteria=rounding_criteria,
            print_details=print_details,
            no_of_cpus=no_of_cpus,
            dir_name=dir_name,
            NoOfTrials=NoOfTrials,
            Condense_Single_Mention_Experiments=Condense_Single_Mention_Experiments,
            JobArraysDetails=JobArraysDetails,
            making_files_for=making_files_for,
            finish_algorithm_if_found_cluster_energy=finish_algorithm_if_found_cluster_energy,
            total_length_of_running_time=total_length_of_running_time)
        ''' ---------------- '''