The AHA Model
Revision: 12809
Reference implementation 04 (HEDG02_04)
|
Implementation of the genetic algorithm. More...
Functions/Subroutines | |
subroutine | init_environment_objects () |
Initialise the environmental objects. Most of the environmental objects, such as the environment, habitats etc. are kept static throughout the model running. There are, however, patterned and stochastic changes in the environment, such as diurnal variation of the illumination level. More... | |
integer function, public | preevol_steps_adaptive (generation) |
Calculate the adaptive number of time steps for the fixed fitness preevolution stage of the genetic algorithm. More... | |
subroutine, public | preevol_steps_adaptive_save_csv (csv_file_name, is_success) |
This is a diagnostic subroutine to save the number of time steps for the adaptive GA. More... | |
subroutine | generations_swap () |
Swap generation pointers between parents and offspring. More... | |
subroutine | selection () |
Select reproducing agents, the best commondata::ga_reproduce_pr portion of agents. More... | |
subroutine | mate_reproduce () |
Mate, reproduce and mutate. More... | |
subroutine, public | generations_loop_ga () |
This procedure implements the main Genetic Algorithm for evolving the agents. More... | |
Variables | |
character(len= *), parameter, private | modname = "(THE_EVOLUTION)" |
type(timer_cpu), public | stopwatch_global |
Model-global stopwatch objects. More... | |
type(timer_cpu), public | stopwatch_generation |
type(timer_cpu), public | stopwatch_op_current |
type(timer_cpu), public | single |
type(timer_cpu), public | operation |
type(habitat), public | habitat_safe |
We have an environment composed of two habitats, safe and a dangerous. More... | |
type(habitat), public | habitat_dangerous |
type(population), target, public | generation_one |
Here we create instances for two populations which will then serve as parents and offspring. And then we declare pointers that will point to parents and offspring. More... | |
type(population), target, public | generation_two |
type(population), pointer, public | proto_parents |
type(population), pointer, public | proto_offspring |
Implementation of the genetic algorithm.
The Genetic Algorithm is implemented here
|
private |
Initialise the environmental objects. Most of the environmental objects, such as the environment, habitats etc. are kept static throughout the model running. There are, however, patterned and stochastic changes in the environment, such as diurnal variation of the illumination level.
Build the overall environment "universe". It can be used for the whole-environment placement of objects, e.g. random walks of an agent crossing the borders between the habitats.
Build the habitats.
Define and allocate the global array of all habitats available to the agents. See the_environment::global_habitats_available for details of this global array. This is now made using the the_environment::assemble() procedure.
Allocation of the the_environment::global_habitats_available is checked. If it turns out not allocated, a critical error is signalled in the logger and the program calls commondata::system_halt().
Output the number of the habitats in the global array the_environment::global_habitats_available and their labels into the logger.
Certain data are also saved. Their names start from the init_
prefix.
Save predators' data.
If the plotting is enabled (see commondata::is_plotting), some plots of the initialisation data are also saved.
Definition at line 62 of file m_evolut.f90.
integer function, public the_evolution::preevol_steps_adaptive | ( | integer, intent(in), optional | generation | ) |
Calculate the adaptive number of time steps for the fixed fitness preevolution stage of the genetic algorithm.
The number of time steps in the fixed-fitness pre-evolution genetic algorithm is calculated using an adaptive algorithm. Briefly, the number of time steps (total lifespan) at the early stages of evolution (the first generations) is very short and increases as the evolution proceeds towards the maximum set by commondata::preevol_tsteps.
[in] | generation | generation optional current generation number, if not provided, set to commondata::global_generation_number_current. |
The number of time steps in this fixed fitness pre-evol adaptive GA algorithm is calculated based on a linear interpolation from a grid defined by the two arrays:
STEPS_ABSCISSA
– grid abscissa, from the first generation to the total number of generations commondata::generations.STEPS_ORDINATE
– grid ordinate, ranging from the number of time steps in one diel cycle to the total number of time steps in the fixed fitness pre-evolution stage commondata::preevol_tsteps.
However, for debugging purposes, evolution time steps can be set to a specific fixed value. This value is set by commondata::preevol_tsteps_force_debug integer parameter and for this fixed value to be forced, commondata::preevol_tsteps_force_debug_enabled must be TRUE.
Then, the total (adaptive) number of time steps is determined by the integer lower limit (floor) of the linear interpolation DDPINTERPOL() procedure, with further limitation that its result value must be within the range of [t,T], where t is the length of a single diel cycle, T is the number of time steps in the pre-evolution stage.
htintrpl.exe [1 50 75 101] [0 0.8 0.95 1] [1] [nonlinear]
Definition at line 211 of file m_evolut.f90.
subroutine, public the_evolution::preevol_steps_adaptive_save_csv | ( | character(len=*), intent(in) | csv_file_name, |
logical, intent(out), optional | is_success | ||
) |
This is a diagnostic subroutine to save the number of time steps for the adaptive GA.
[in] | csv_file_name | csv_file_name the name of the CSV file to save the arrays. |
[out] | is_success | is_success Flag showing that data save was successful (if TRUE). |
Definition at line 289 of file m_evolut.f90.
|
private |
Swap generation pointers between parents and offspring.
Definition at line 318 of file m_evolut.f90.
|
private |
Select reproducing agents, the best commondata::ga_reproduce_pr portion of agents.
The best (sorted) parents are copied to the offspring population object. Note that the number of such reproducing parents is determined by the the_population::population::ga_reproduce_max() method.
Old fixed proportion implementation:
The best parents (elite group) are then re-initialised from the genome for the next generation using the_individual::individual_agent::init() method.
Definition at line 333 of file m_evolut.f90.
|
private |
Mate, reproduce and mutate.
Calculate adaptive mutation rate
Loop through all the non-elite population members. These individuals are created from the genomes of the elite group. The non-elite individuals are from commondata::ga_reproduce_n+1 to commondata::popsize.
proto_offspring
agents. The mother and the father exchange their genetic material using the the_genome::individual_genome::recombine_random() method. Note that the mother must be the_genome::individual_genome::is_female() and the father, the_genome::individual_genome::is_male().Finally, loop through the elite group and introduce random mutations there too with the_genome::individual_genome::mutate().
Definition at line 364 of file m_evolut.f90.
subroutine, public the_evolution::generations_loop_ga |
This procedure implements the main Genetic Algorithm for evolving the agents.
energy_mean_gen1_birth_mort
– average value of the birth energy reserves, for forced selective birth mortality. See the_population::population::mortality_birth().energy_sd_gen1_birth_mort
– standard deviationof the birth energy reserves, for forced selective birth mortality. See the_population::population::mortality_birth().
The definitions below are for the objects that are used to write generation-wise statistics in the generation_stats_record_write() sub-procedure.
csv_file_generstats
: CSV_IO
File handle object for generation-wise statistics. See CSV_IO
module for details. file_stats_gener_record
: Record for the generation-wise statistics file.
FILE_STATS_GENER_COLS
: an array of column names for the generation-wise statistics file.FILE_STATS_RECORD_LEN
: The maximum length of the CSV record assuming the maximum length of a single field is commondata::label_length; the number of fields is equal to the size of the columns array FILE_STATS_GENER_COLS
.Parameters determining the stopping rule for the fixed fitness genetic algorithm. These are based on the values obtained in the first generation. If in any succeeding generation, they fall below the first generation values, evolution is considered unsuccessful and the main GA loop stops. The number of alive agents at the first random generation.
The number of agents that have increased their body mass at the first random generation.
Global_Generation_Number_Current
is the global generation number. It is first initialised to 1.
commondata::Global_Rescale_Maximum_Motivation is the global maximum motivation value, it is fixed at the start of the simulation to an arbitrary high value but is automatically updated from the maximum motivation value across all agents after each time step.
The stopping rule parameters based on the first generation values are initialised to some values allowing the first generation to occur safely, i.e. with sufficiently large number of randomly created pre-optimal agents.
The number of agents growing is set to a large negative value commondata::unknown,so initial zero is always larger, so evolution is allowed to start.
All environmental objects are initialised with init_environment_objects().
New populations of agents are now built and initialised: (a) generation_one
, (b) generation_two
These population objects serve as targets for two pointer objects: (a) proto_parents
, (b) proto_offspring
.
generation_one
of the agents, commondata::popsize is the size of the population.generation_two
, that will then take parents' values.Calculate initial fitness of the agents in the generation_one
for the pre-evolution phase. At this stage fitness is equal to the maximum value (note that fitness is actually a reverse of fitness) and is not very interesting.
Place all the agents that have been initialised to random spatial positions in the safe habitat (habitat_safe
), they have just the uniformly distributed spatial positions at start.
See the_population::individ_posit_in_environ_uniform() for details.
Allocate the first proto_parents
and proto_offspring
population objects, they are pointers to generation_one
and generation_two
target objects.
Calculate statistical parameters of the initial generation for selective birth mortality. See the_population::population::mortality_birth().
These values are then logged.
Save initialisation data in the debug mode.
SAVE_DATA_INIT block: The random initialisation individual data for the whole parent population are saved to csv files:
init_agents_
;init_genome_
.The generation wise statistics file generations_
is opened for writing ...
... and the first row of column names FILE_STATS_GENER_COLS
is written.
The average distance between the food items is reported to the log. The average distance between the food items is good to know, e.g. to compare it with the agent's random walk step size.
Pre-evolution stage involves the Genetic Algorithm that is based on selection of agents based on an explicit global fitness. It aims to produce a population of agents that can stably sustain for the whole commondata::lifespan
At this stage the main loop of generations evolving is started. The conditions for continuing the main evolution loop are as follows:
The commondata::stop_file file is checked upon each generation. If this stop file exists, the simulation cycle is terminated at this stage and the program then exits from the generation loop.
Stopwatch object for calculating time since generation start is initialised.
Initially, place all the agents in the proto_parents
population randomly uniformly in the safe habitat (habitat_safe
). However, note that the initial vertical position and distribution of the agents depends on these parameters:
See the_population::individ_posit_in_environ_uniform() method for details.
Initialise the global generation-wise counter of the number of agents that die as a consequence of predation the_population::global_ind_n_eaten_by_predators, as opposed to starvation.
If it is not the first generation, replenish all food items (i.e. for all habitats), they are restored to the "available" (non-eaten) state. Two methods can be used here:
The global habitat array the_environment::global_habitats_available is then updated by the_environment::assemble() procedure.
If it is the first generation, it does not make sense doing this as the environment has been already fully initialised in the init_environment_objects() procedure.
Start the loop of the life cycle of all agents of the proto_parents
. It includes commondata::preevol_tsteps time steps. (Note that commondata::preevol_tsteps is less than commondata::lifespan). This is implemented in the lifecycle_preevol() procedure.
Calculate the number of agents alive and agents growing. These values are used later, including as a criterion of GA deterioration.
Report these values in the logger.
After the agents went through their life cycle, their fitness is processed.
proto_parents
agents is recalculated following their performance in the full lifecycle.The agents proto_parents
are sorted by fitness.
If this is the first generation, determine the GA deterioration stopping parameters, evolution "failure"
These Generation one parameters are also reported to the logger.
proto_parents
population are saved using the the_population::population class bound save_
methods:agents_
genome_
memory_
.movements_
.behaviours_
.Select reproducing minority: the_evolution::selection()
A minority of the best parents produces the proto_offspring population object: the_evolution::mate_reproduce().
Reset individual IDs of proto_offspring
Swap populations: proto_offspring
are now proto_parents
: the_evolution::generations_swap().
Finally, the global generation counter commondata::global_generation_number_current is incremented by one.
After all generations were done, the CSV file csv_file_generstats
that saves generation-wise statistics is closed.
Finally, the concluding procedure commondata::system_halt() is called for the normal termination of the model.
Definition at line 445 of file m_evolut.f90.
|
private |
Definition at line 35 of file m_evolut.f90.
type(timer_cpu), public the_evolution::stopwatch_global |
Model-global stopwatch objects.
TIMER:
(LTAG_TIMER) for logging, e.g. call LOG_MSG( LTAG_TIMER // stopwatch_op_currentshow() )
Definition at line 40 of file m_evolut.f90.
type(timer_cpu), public the_evolution::stopwatch_generation |
Definition at line 40 of file m_evolut.f90.
type(timer_cpu), public the_evolution::stopwatch_op_current |
Definition at line 40 of file m_evolut.f90.
type(timer_cpu), public the_evolution::single |
Definition at line 40 of file m_evolut.f90.
type(timer_cpu), public the_evolution::operation |
Definition at line 40 of file m_evolut.f90.
type(habitat), public the_evolution::habitat_safe |
We have an environment composed of two habitats, safe and a dangerous.
Definition at line 45 of file m_evolut.f90.
type(habitat), public the_evolution::habitat_dangerous |
Definition at line 45 of file m_evolut.f90.
type(population), target, public the_evolution::generation_one |
Here we create instances for two populations which will then serve as parents and offspring. And then we declare pointers that will point to parents and offspring.
Definition at line 50 of file m_evolut.f90.
type(population), target, public the_evolution::generation_two |
Definition at line 51 of file m_evolut.f90.
type(population), pointer, public the_evolution::proto_parents |
Definition at line 52 of file m_evolut.f90.
type(population), pointer, public the_evolution::proto_offspring |
Definition at line 53 of file m_evolut.f90.