The AHA Model  Revision: 12809
Reference implementation 04 (HEDG02_04)
the_population Module Reference

Define the population of agents object, its properties and functions. More...

Data Types

type  member_population
 Definition of individual member of a population. More...
 
type  population
 Definition of the population object. More...
 

Functions/Subroutines

subroutine set_individual_id (this, idnumber)
 Set integer ID number to individual member of the population object. More...
 
integer function get_individual_id (this)
 Get integer ID number to individual member of the population object. More...
 
subroutine individ_posit_in_environ_uniform (this, environ)
 Places the individual agent, a member of the population, within a specific environment at random with a uniform distribution. The agents can be positioned with respect to their initial depth. More...
 
subroutine genome_individual_set_dead_non_pure (this, non_debug_log)
 Set the individual to be dead. Note that this function does not deallocate the individual agent object, this may be a separate destructor function. More...
 
subroutine init_population_random (this, pop_size, pop_number_here, pop_name_here)
 Initialise the population object. More...
 
subroutine population_destroy_deallocate_objects (this)
 Destroys this population and deallocates the array of individual member objects. More...
 
subroutine population_birth_mortality_init (this, energy_mean, energy_sd)
 Impose selective mortality at birth on the agents. Selective mortality sets a fixed limit on uncontrolled evolution of the energy reserves in newborn agents. If some newborn has too high energy at birth (genetically fixed), such a deviating agent is killed at once. More...
 
integer function population_get_popsize (this)
 Accessor get-function for the size of this population. More...
 
integer function population_get_pop_number (this)
 Accessor get-function for the population number ID. More...
 
character(len=label_length) function population_get_pop_name (this)
 Accessor get-function for the population character label ID. More...
 
subroutine reset_population_id_random (this, pop_number_here, pop_name_here)
 Reset individual IDs of the population members. More...
 
subroutine sex_initialise_from_genome (this)
 Determine the sex for each member of the population. More...
 
subroutine position_individuals_uniform (this, environ)
 Position each member of the population randomly within a bounding environment. More...
 
elemental subroutine sort_population_by_fitness (this)
 This subroutine sorts the population individual object by their %fitness components. More...
 
subroutine population_rwalk3d_all_agents_step (this, dist_array, cv_array, dist_all, cv_all, environment_limits, n_walks)
 Perform one or several steps of random walk by all agents. More...
 
subroutine population_rwalk25d_all_agents_step (this, dist_array_xy, cv_array_xy, dist_array_depth, cv_array_depth, dist_all_xy, cv_all_xy, dist_all_depth, cv_all_depth, environment_limits, n_walks)
 Perform one or several steps of random walk by all agents. More...
 
subroutine population_subject_predator_attack (this, this_predator, time_step_model)
 Subject the population to an attack by a specific predator. The predator acts on agents in its proximity and takes account of the predation confusion and dilution effects (see the_environment::predator::risk_fish_group()). More...
 
subroutine population_subject_other_risks (this)
 Subject the population to mortality caused by habitat-specific mortality risk. Each agent is affected by the risk associated with the habitat it is currently in. More...
 
subroutine population_subject_individual_risk_mortality (this)
 Subject all members of this population to their individual mortality risks. More...
 
subroutine population_lifecycle_step_preevol (this)
 This procedure performs a single step of the life cycle of the whole population, the agents for the step are selected in a random order. More...
 
subroutine population_lifecycle_step_eatonly_preevol (this)
 This procedure performs a single step of the life cycle of the whole population, the agents for the step are selected in a random order. More...
 
subroutine population_save_data_all_agents_csv (this, csv_file_name, save_header, is_logging, is_success)
 Save data for all agents within the population into a CSV file. More...
 
subroutine population_save_data_all_genomes (this, csv_file_name, is_success)
 Save the genome data of all agents in this population to a CSV file. More...
 
subroutine population_load_data_all_genomes (this, pop_size, pop_number_here, pop_name_here, csv_file_name, missing_random, is_success)
 Load the genome data of all agents in this population from a CSV file. Note that the procedure implements several error correcting measures, e.g. checks for minimum number of rows in the file and minimum row length. The input CSV file therefore can include short text notes that are then ignored when reading data. More...
 
subroutine population_save_data_memory (this, csv_file_name, is_success)
 Save the perceptual and emotional memory stack data of all agents in this population to a CSV file. More...
 
subroutine population_save_data_movements (this, csv_file_name, is_success)
 Save the latest movement history of all agents. This method makes use of the the_environment::spatial_moving::history structure that saves latest movements of each agent. More...
 
subroutine population_save_data_behaviours (this, csv_file_name, is_success)
 Save the behaviours history stack the_neurobio::behaviour::history_behave for all agents. More...
 
pure subroutine population_preevol_fitness_calc (this)
 Calculate fitness for the pre-evolution phase of the genetic algorithm. Pre-evolution is based on selection for a simple criterion without explicit reproduction etc. The criterion for selection at this phase is set by the integer the_individual::individual_agent::fitness component. This procedure provides a whole-population wrapper for the the_individual::individual_agent::fitness_calc() function. More...
 
pure integer function population_ga_reproduce_max (this)
 Determine the number of parents that have fitness higher than the minimum acceptable value. Also, only alive agents are included into the reproducing number. More...
 
real(srp) function population_ga_mutation_rate_adaptive (this, baseline, maxvalue)
 This function implements adaptive mutation rate that increases as the population size reduces. More...
 

Variables

character(len= *), parameter, private modname = "(THE_POPULATION)"
 
integer, public global_ind_n_eaten_by_predators
 Global indicator variable that keeps the number of agents that have died as a consequence of predatory attacks. All other dies are therefore caused by starvation. More...
 

Detailed Description

Define the population of agents object, its properties and functions.

THE_POPULATION module

The population is in the simplest case an array of individual agent objects. Individual properties of the population members can be referred as, e.g. proto_parentsindividual(i)fitness .

Function/Subroutine Documentation

◆ set_individual_id()

subroutine the_population::set_individual_id ( class(member_population), intent(inout)  this,
integer, intent(in)  idnumber 
)

Set integer ID number to individual member of the population object.

Note
Note that this subroutine is private as setting individual IDs makes sense only during the initialisation phase of the population.
Parameters
[in,out]thisclass, member of population.
[in]idnumberid, integer id number assigned.

person_number is assigned the idnumber

Definition at line 191 of file m_popul.f90.

◆ get_individual_id()

integer function the_population::get_individual_id ( class(member_population), intent(in)  this)

Get integer ID number to individual member of the population object.

Note
Note that this is public, so we can retrieve individual IDs but not set them (id's are always set at initialisation)
Parameters
[in]thisclass, member of population.
Returns
Parameters
id,integerid number retreived.

person_number is assigned the idnumber

Definition at line 205 of file m_popul.f90.

◆ individ_posit_in_environ_uniform()

subroutine the_population::individ_posit_in_environ_uniform ( class(member_population), intent(inout)  this,
class(environment), intent(in)  environ 
)

Places the individual agent, a member of the population, within a specific environment at random with a uniform distribution. The agents can be positioned with respect to their initial depth.

Parameters
[in]environenviron sets the environment object where the agent is placed randomly

Definition at line 223 of file m_popul.f90.

Here is the call graph for this function:

◆ genome_individual_set_dead_non_pure()

subroutine the_population::genome_individual_set_dead_non_pure ( class(member_population), intent(inout)  this,
logical, intent(in), optional  non_debug_log 
)

Set the individual to be dead. Note that this function does not deallocate the individual agent object, this may be a separate destructor function.

Note
This is a non-pure function logging some extended diagnostics about the dying agent. See dies procedure from the_genome and all its overrides:
Warning
This function should be normally used only while debugging. In normal runs use the pure subroutine dies from ÌNDIVIDUAL_GENOME.

Local flag to do show log.

Local parameter showing how many latest memory values to log out.

Don't show log by default.

This is a pure function from THE_GENOME level.

Turn on output logging only if in the DEBUG mode or if non_debug_log is explicitly set to TRUE.

Just exit back if no logging.

Note
Note that TOSTR accepts arrays including (concatenated) character arrays.

Definition at line 261 of file m_popul.f90.

◆ init_population_random()

subroutine the_population::init_population_random ( class(population), intent(inout)  this,
integer, intent(in)  pop_size,
integer, intent(in), optional  pop_number_here,
character (len=*), intent(in), optional  pop_name_here 
)

Initialise the population object.

Initialise the population object, init it with random individuals (function init on individuals), and assign sequential person_number`s.

Parameters
[in,out]thisclass, This – member of population class (this)).
[in]pop_sizepop_size, The size of the population.
[in]pop_number_hereid, Optional numeric population ID.
[in]pop_name_heredescriptor, Optional population string descriptor.

Set population size from input parameter.

Allocate the population

Initialise all individuals of the population

first, call `init to object individual(i)

Set optional descriptors for the whole population. Numeric ID and a short text description.

If optional ID is absent, ID is set to a random integer value from 1 to the maximum integer allowed for the pop_number type (minus 1).

If optional text description string of the population is absent, it is set to the string representation of its numeric ID.

Log the initial location of the agents.

Warning
The logic of the logger constructs here must coincide with that in the population::individ_posit_in_environ_uniform().

Definition at line 318 of file m_popul.f90.

◆ population_destroy_deallocate_objects()

subroutine the_population::population_destroy_deallocate_objects ( class(population), intent(inout)  this)

Destroys this population and deallocates the array of individual member objects.

Definition at line 391 of file m_popul.f90.

◆ population_birth_mortality_init()

subroutine the_population::population_birth_mortality_init ( class(population), intent(inout)  this,
real(srp), intent(in), optional  energy_mean,
real(srp), intent(in), optional  energy_sd 
)

Impose selective mortality at birth on the agents. Selective mortality sets a fixed limit on uncontrolled evolution of the energy reserves in newborn agents. If some newborn has too high energy at birth (genetically fixed), such a deviating agent is killed at once.

The values of the risk are chosen such that it is zero at the fixed population mean (agent does not deviate) and reaches 1.0 if the agent's energy reserves are 3.0 standard deviations higher than the fixed mean value (agent strongly deviates).

Parameters
[in]energy_meanenergy_mean optional mean energy at birth, if absent, is calculated from the population data.
[in]energy_sdenergy_sd optional mean energy at birth, if absent, is calculated from the population data.
  • MORTALITY_BIRTH_INIT_ENERG_ABSCISSA is the baseline abscissa for the nonparametric interpolation function grid, in units of the standard deviation (sigma) of the energy reserves in the newborn population, i.e. the_body::condition::energy_birth.
  • MORTALITY_BIRTH_INIT_ENERG_ORDINATE is the ordinate for the nonparametric interpolation function grid: sets the probability of the agent's death given its energy reserves deviate from the fixed mean by the number of standard deviations set by MORTALITY_BIRTH_INIT_ENERG_ABSCISSA.

Selective mortality sets a fixed limit on uncontrolled evolution of the energy reserves in newborn agents. All newborn agents that have the energy reserves exceeding some point may die with the probability determined by the grid arrays:

  • MORTALITY_BIRTH_INIT_ENERG_ABSCISSA;
  • MORTALITY_BIRTH_INIT_ENERG_ORDINATE.

The probability of death (mortality risk) is determined by the nonparametric nonlinear function defined by DDPINTERPOL, where the actual grid abscissa is the energy reserve of the agent in and grid ordinate is the mortality risk.

The values of the risk are chosen such that it is zero at the fixed population mean (agent does not deviate) and reaches 1.0 if the agent's energy reserves are 3.0 standard deviations higher than the mean value.

Interpolation plots can be saved in the debug mode using this plotting command: commondata::debug_interpolate_plot_save().

Warning
Involves huge number of plots, should normally be disabled.

Definition at line 411 of file m_popul.f90.

Here is the call graph for this function:

◆ population_get_popsize()

integer function the_population::population_get_popsize ( class(population), intent(in)  this)

Accessor get-function for the size of this population.

Definition at line 510 of file m_popul.f90.

◆ population_get_pop_number()

integer function the_population::population_get_pop_number ( class(population), intent(in)  this)

Accessor get-function for the population number ID.

Definition at line 520 of file m_popul.f90.

◆ population_get_pop_name()

character(len=label_length) function the_population::population_get_pop_name ( class(population), intent(in)  this)

Accessor get-function for the population character label ID.

Definition at line 530 of file m_popul.f90.

◆ reset_population_id_random()

subroutine the_population::reset_population_id_random ( class(population), intent(inout)  this,
integer, intent(in), optional  pop_number_here,
character (len=*), intent(in), optional  pop_name_here 
)

Reset individual IDs of the population members.

Makes new random individual IDs for the population members.

Parameters
[in,out]thisclass, This – member of population class (this)).
[in]pop_number_hereid, Optional numeric population ID.
[in]pop_name_heredescriptor, Optional population string descriptor.

Reset all individual IDs of the population members

Set optional descriptors for the whole population. Numeric ID and a short text description.

If optional ID is absent, ID is set to a random integer value from 1 to the maximum integer allowed for the pop_number type (minus 1).

If optional text description string of the population is absent, it is set to the string representation of its numeric ID.

Definition at line 541 of file m_popul.f90.

◆ sex_initialise_from_genome()

subroutine the_population::sex_initialise_from_genome ( class(population), intent(inout)  this)

Determine the sex for each member of the population.

Definition at line 579 of file m_popul.f90.

◆ position_individuals_uniform()

subroutine the_population::position_individuals_uniform ( class(population), intent(inout)  this,
class(environment), intent(in), optional  environ 
)

Position each member of the population randomly within a bounding environment.

Note
Moved the positioning procedure into a separate procedure as initialising population may involve different spatial positioning, e.g. uniform within the bounding environment or gaussian localised.
Parameters
[in]environenviron the environment where we place the population
Warning
Even though this parameter is optional, the bounding environment should in most cases (almost?) be fixed, and provided as a parameter. In most cases, unlimited environment is useful for debugging only. TODO: convert to class

Local object representing the bounding environment for this population

Local counter

Check if the bounding environment is provided, if not, place agents without limits

Warning
The bounding environment should in most cases be fixed, and provided as a parameter.

Position agents randomly (uniform distribution) within the bounding environment.

Definition at line 596 of file m_popul.f90.

◆ sort_population_by_fitness()

elemental subroutine the_population::sort_population_by_fitness ( class(population), intent(inout)  this)

This subroutine sorts the population individual object by their %fitness components.

The two subroutines qsort and qs_partition_fitness are a variant of the recursive quick sort algorithm adapted for MEMBER_POPULATION integer fitness component

Parameters
[in,out]thisclass, This – member of population class (this)).

This is the array component we sort.

Definition at line 637 of file m_popul.f90.

Here is the call graph for this function:

◆ population_rwalk3d_all_agents_step()

subroutine the_population::population_rwalk3d_all_agents_step ( class(population), intent(inout)  this,
real(srp), dimension(:), intent(in), optional  dist_array,
real(srp), dimension(:), intent(in), optional  cv_array,
real(srp), intent(in), optional  dist_all,
real(srp), intent(in), optional  cv_all,
class(environment), intent(in), optional  environment_limits,
integer, intent(in), optional  n_walks 
)

Perform one or several steps of random walk by all agents.

Note
This procedure was used for debugging.
Parameters
[in]dist_arraystep_size_array an array of step sizes for each individual.
[in]cv_arraycv_array Coefficients of variation for the walk.
[in]dist_alldist_all the value of the walk step size that is identical in all agents within the population.
[in]cv_allcv_all the value of the walk coefficient of variation that is identical in all agents within the population.
[in]environment_limitsenvironment_limits Limits of the environment area available for the random walk. The moving object cannot get beyond this limit. If this parameter is not provided, the environmental limits are obtained automatically from the global array the_environment::global_habitats_available.
[in]n_walksn_walk optional number of walk steps that should be performed, default just one.

Implementation details

  • Calculate the distance array size.

calculate the step size along the axes from the distance array.

  • Calculate the random permutation of individual indices.
    Warning
    Random order here is a prototype for testing for use in behaviour selection by population members.
  • Perform Gaussian random walks for each of the individuals in a random order that is set by the pop_permutation array.

Definition at line 725 of file m_popul.f90.

◆ population_rwalk25d_all_agents_step()

subroutine the_population::population_rwalk25d_all_agents_step ( class(population), intent(inout)  this,
real(srp), dimension(:), intent(in), optional  dist_array_xy,
real(srp), dimension(:), intent(in), optional  cv_array_xy,
real(srp), dimension(:), intent(in), optional  dist_array_depth,
real(srp), dimension(:), intent(in), optional  cv_array_depth,
real(srp), intent(in), optional  dist_all_xy,
real(srp), intent(in), optional  cv_all_xy,
real(srp), intent(in), optional  dist_all_depth,
real(srp), intent(in), optional  cv_all_depth,
class(environment), intent(in), optional  environment_limits,
integer, intent(in), optional  n_walks 
)

Perform one or several steps of random walk by all agents.

Note
This procedure was used for debugging.
Parameters
[in]dist_array_xydist_array_xy an array of step sizes for each individual.
[in]cv_array_xycv_array_xy Coefficients of variation for the walk.
[in]dist_array_depthdist_array_depth an array of step sizes for each individual.
[in]cv_array_depthcv_array_depth Coefficients of variation for the walk.
[in]dist_all_xydist_all_xy the value of the walk step size for horizontal plane that is identical in all agents within the population.
[in]cv_all_xycv_all_xy the value of the walk coefficient of variation in the horizontal plane that is identical in all agents within the population.
[in]dist_all_depthdist_all_depth the value of the walk step size for the depth plane that is identical in all agents within the population.
[in]cv_all_depthcv_all_depth the value of the walk coefficient of variation in the depth plane that is identical in all agents within the population.
[in]environment_limitsenvironment_limits Limits of the environment area available for the random walk. The moving object cannot get beyond this limit. If this parameter is not provided, the environmental limits are obtained automatically from the global array the_environment::global_habitats_available.
[in]n_walksn_walk optional number of walk steps that should be performed, default just one.

Implementation details

  • Calculate the distance array size.

If the depth walk step distance is not provided as a parameter, 1/2 of the agent body size is used as the default value. Thus, it is assumed that the extent of random movements of the agents in the horizontal plane is greater than vertical movements.

  • Calculate the step size along the axes from the distance array.
  • Calculate the random permutation of individual indices.
    Warning
    Random order here is a prototype for testing for use in behaviour selection by population members.
  • Perform Gaussian random walks for each of the individuals in a random order that is set by the pop_permutation array.

Definition at line 838 of file m_popul.f90.

◆ population_subject_predator_attack()

subroutine the_population::population_subject_predator_attack ( class(population), intent(inout)  this,
class(predator), intent(in)  this_predator,
integer, intent(in), optional  time_step_model 
)

Subject the population to an attack by a specific predator. The predator acts on agents in its proximity and takes account of the predation confusion and dilution effects (see the_environment::predator::risk_fish_group()).

Notable variables

prey_index is the partial index of the prey agents that are in proximity of this predator.

Implementation notes

Preparations: Check optional time step parameter. If not provided, use global commondata::global_time_step_model_current parameter value.

First, calculate the risk of predation from this specific predator to each of the agents in the population using the the_environment::predator::risk_fish_group() method. The "raw" indexed output scheme is used here to avoid multiple cycling over the whole large population of agents, only the agents that are closest to the predator are processed and attacked (maximum number is equal to the index limit commondata::predator_risk_group_select_index_partial).

Second, cycle through all the agents in close proximity of the predator, up to the maximum size of partial indexing parameter commondata::predator_risk_group_select_index_partial. The predator then stochastically attacks each of these agents with the probability equal to the risk of predation. If the attack is successful, the agent the_genome::individual_genome::dies() and loop is exited because the predator is assumed to catch only one agent at a time.

Definition at line 1008 of file m_popul.f90.

Here is the call graph for this function:

◆ population_subject_other_risks()

subroutine the_population::population_subject_other_risks ( class(population), intent(inout)  this)

Subject the population to mortality caused by habitat-specific mortality risk. Each agent is affected by the risk associated with the habitat it is currently in.

Note
Note that there is no such a function for a single agent as it does not seem to be necessary.

Implementation notes

All agents in the population are randomly subjected to the mortality risk the_environment::habitat::risk_mortality that is linked to the habitat object the agent is currently in in a loop.

If the agent is unhappy and is subjected to mortality event, it immediately the_genome::individual_genome::dies().

Definition at line 1102 of file m_popul.f90.

Here is the call graph for this function:

◆ population_subject_individual_risk_mortality()

subroutine the_population::population_subject_individual_risk_mortality ( class(population), intent(inout)  this)

Subject all members of this population to their individual mortality risks.

Implementation notes

The procedure is simple, loop over all individual agents in the population and stochastically call the_genome::individual_genome::dies() method with probability equal to individual mortality of the agent.

Definition at line 1138 of file m_popul.f90.

◆ population_lifecycle_step_preevol()

subroutine the_population::population_lifecycle_step_preevol ( class(population), intent(inout)  this)

This procedure performs a single step of the life cycle of the whole population, the agents for the step are selected in a random order.

Notable variables

  • inds_order is an array that sets the order in which the agents are being drawn out of the population to perform the step.

ind_seq is the sequential number of the agent as drawn from the population; it is the loop control counter variable.

  • ind_real is the real sequential number of the agent in the population; this real id is obtained from the order array inds_order.

Implementation notes

First, an ordering array inds_order is calculated that sets the order in which the agents are drawn from the population. In the simplest case, the order of the agents is random, so this array is actually an array of random integers. The procedure PERMUTE_RANDOM from HEDTOOLS is used here then.

The agents can also be processed in any non-random order. This would require invoking an array indexing procedure ARRAY_INDEX instead of PERMUTE_RANDOM.

For example, to process the agents in the order of the body mass, the ordering array can be obtained obtained as below:

call ARRAY_INDEX(this%individual%get_mass(), inds_order)

But this code would rank the agents in an increasing order of their body mass. If this is not what is expected, e.g. if the non-random selection is used to mimic a competitive advantage for bigger and heavier agents, a reverse of the ordering is obtained like this:

inds_order = inds_order(this%population_size:1:-1)

Second, the agents are drawn from the population, one by one, in the named loop construct INDIVIDUALS.

  • One individual is then drawn from the inds_order ordering array.

Initialisations

  • First, a check is done if the agent is dead or starved to death; if yes, no further processing is done. Also, in the former case the individual_genome::dies() method is called.

agent_in index calculates the habitat number where the selected agent is currently in, calling the the_environment::spatial::find_environment() method.

Get perceptions

Simple environmental perceptions are obtained: light, depth: the_neurobio::perception::perceptions_environ().

Appraisal: Produce motivations

Then, primary motivation values are calculated from the perception components: the_neurobio::appraisal::motivations_primary_calc().

Determine the Global Organismic State

The population-wise maximum motivation value that is used for rescaling is calculated now.

Determine and execute the optimal behaviour

  • Once the GOS is determined for this agent, it selects the individually optimal behaviour that minimises its expected arousal; this behaviour is then executed. Both steps are implemented in the the_neurobio::behaviour::do_behave() method.

Update characteristics of the agent

Finally, the age of the agent is incremented to one time step.

Definition at line 1158 of file m_popul.f90.

Here is the call graph for this function:

◆ population_lifecycle_step_eatonly_preevol()

subroutine the_population::population_lifecycle_step_eatonly_preevol ( class(population), intent(inout)  this)

This procedure performs a single step of the life cycle of the whole population, the agents for the step are selected in a random order.

Warning
This version of the life cycle step includes only optimal food selection and eating and does not include the full fledged behaviour selection cascade of procedures ::do_behave().

Notable variables

  • inds_order is an array that sets the order in which the agents are being drawn out of the population to perform the step.

ind_seq is the sequential number of the agent as drawn from the population; it is the loop control counter variable.

  • ind_real is the real sequential number of the agent in the population; this real id is obtained from the order array inds_order.

Implementation notes

First, an ordering array inds_order is calculated that sets the order in which the agents are drawn from the population. In the simplest case, the order of the agents is random, so this array is actually an array of random integers. The procedure PERMUTE_RANDOM from HEDTOOLS is used here then.

The agents can also be processed in any non-random order. This would require invoking an array indexing procedure ARRAY_INDEX instead of PERMUTE_RANDOM.

For example, to process the agents in the order of the body mass, the ordering array can be obtained obtained as below:

call ARRAY_INDEX(this%individual%get_mass(), inds_order)

But this code would rank the agents in an *increasing *order of their of their body mass. If this is not what is expected, e.g. if the non-random selection is used to mimic a competitive advantage for bigger and heavier agents, a reverse of the ordering is obtained like this:

inds_order = inds_order(this%population_size:1:-1)

Second, the agents are drawn from the population, one by one, in the named loop construct INDIVIDUALS.

  • One individual is then drawn from the inds_order ordering array.

Initialisations

  • First, a check is done if the agent is dead or starved to death; if yes, no further processing is done. Also, in the former case the individual_genome::dies() method is called.

agent_in index calculates the habitat number where the selected agent is currently in, calling the the_environment::spatial::find_environment() method.

Get perceptions

Simple environmental perceptions are obtained: light, depth: the_neurobio::perception::perceptions_environ().

Appraisal: Produce motivations

Then, primary motivation values are calculated from the perception components: the_neurobio::appraisal::motivations_primary_calc().

Determine the Global Organismic State

The population-wise maximum motivation value that is used for rescaling is calculated now.

Determine and execute the optimal behaviour

  • Once the GOS is determined for this agent, it selects the optimal food item that minimises its expected arousal and then tries to eat this food item. However, if the agent has no food in its perception a default random walk is executed.

Update characteristics of the agent

  • Finally, characteristics of this agent are updated depending on the consequences of the behaviour. For example, hormone levels are updated and the living cost of the agent is subtracted. Note that the agent characteristics that directly follow from the behaviour unit that has been executed (e.g. food gain if the agent decided to eat a food item or travel cost if the agent migrated) are processed and updated in the respective behaviour execution method.

Finally, the age of the agent is incremented to one time step.

Definition at line 1356 of file m_popul.f90.

◆ population_save_data_all_agents_csv()

subroutine the_population::population_save_data_all_agents_csv ( class(population), intent(in)  this,
character(len=*), intent(in)  csv_file_name,
logical, intent(in), optional  save_header,
logical, intent(in), optional  is_logging,
logical, intent(out), optional  is_success 
)

Save data for all agents within the population into a CSV file.

Note
Note that this procedure is not using the file_io wrappers.
Parameters
[in]csv_file_namecsv_file_name is the name of the CSV output file.
[in]save_headersave_header turn ON/OFF of the descriptive file header. Header is saved into the first row of the CSV output file If not present, default is FALSE.
[in]is_loggingis_logging turn ON/OFF writing the file name and data into the logger. If not present, default is TRUE if it is the debug mode.
[out]is_successis_success Flag showing that data save was successful (if TRUE).

Implementation notes

Local variables for CSV backend

  • handle_csv is the CSV file handle object defining the file name, Fortran unit and error descriptor, see HEDTOOLS manual for details.

csv_record_tmp is the temporary character string that keeps the whole record of the file, i.e. the whole row of the spreadsheet table.

  • COLUMNS is a parameter array that keeps all column headers; its size is equal to the total number of variables (columns) in the data spreadsheet file.

Save data in CSV file

Note
Note that this subroutine does not use the object oriented wrappers from the file_io module.
  • Define the file name %name component of the CSV file handle. The file handle object handle_csv is now used as the file identifier.

Open the output file defined by the handle_csv handle object for writing.

  • Possible error status of the latest file operation is obtained by the %status component of the file handle. Check if there were any errors opening the file and report in the logger with the error tag.
  • If the save_header flag is set to TRUE, save the CSV file header.
  • Prepare the character string variable csv_record_tmp that keeps the whole record (row) of data in the output CSV data file. The length of this string should be enough to fit all the record data, otherwise the record is truncated.
  • Produce the first record containing the column headers (variable names). Note that CSV_RECORD_APPEND() accepts both arrays and scalar values for appending. Also, write the first record physically to the file.
  • The actual data are written to the CSV file in a loop over all the individual members of the population. One record (row) of the data file then represents a single individual.
  • the csv_record_tmp character string variable is produced such that it can fit the whole record;
  • the actual data for the individual is appended to the current record one by one. Note that logical values are converted to integers using commondata::conv_l2r() function.
  • after all data are appended to the record, this record is physically written to the disk using CSV_RECORD_WRITE().
  • When all the records are saved, the CSV file is closed with CSV_CLOSE().
  • This is finally sent to the logger (if logging_enabled is TRUE).

The CSV output data file can be optionally compressed with the commondata::cmd_zip_output command if commondata::is_zip_outputs is set to TRUE.

Definition at line 1554 of file m_popul.f90.

◆ population_save_data_all_genomes()

subroutine the_population::population_save_data_all_genomes ( class(population), intent(in)  this,
character(len=*), intent(in)  csv_file_name,
logical, intent(out), optional  is_success 
)

Save the genome data of all agents in this population to a CSV file.

Parameters
[in]csv_file_namecsv_file_name is the name of the CSV output file.
[out]is_successis_success Flag showing that data save was successful (if TRUE).

Implementation notes

Build column names

First, determine the number of columns in the data file. The number of columns is calculated by unwinding the whole data structure

  • chromosome(j,k)allele(l)allele_value(m)

See the_genome for more details on the data structure.

The array of the column names is then allocated to the above number.

The column names are built again by unwinding the whole genome data structure into a linear sequence. The column names are like this:

CRO_1_1_ALE_01_AC_1, CRO_1_1_ALE_01_AC_2, CRO_1_1_ALE_01_AC_3, ...

Write data to the file

First, the file is opened for writing.

The first record of the data that contains the column names is then "appended" into the complete record and written to the file. The length of this record is calculated based on the length of the columns and their number.

  • The remaining columns contain the chromosome and gene labels (see above);

This first line consisting of column names is then written to the output file.

The maximum length of the data record is calculated as the maximum string length of a single data value multiplied by the number of columns. Because the record also adds separators, the number of columns multiplied by three is added to this value.

Finally, cycle over all individuals in this population and save the genome data. The first two columns are the_genome::individual_genome::person_number and the_genome::individual_genome::genome_label. The other columns "unwind" the genome data structure over the inner loops for chromosomes, homologues, alleles and allele components.

  • - chromosome(j,k)allele(l)allele_value(m)

See the_genome for more details on the data structure.

Once all individuals are saved, the file is closed.

The CSV output data file can be optionally compressed with the commondata::cmd_zip_output command if commondata::is_zip_outputs is set to TRUE.

Definition at line 1841 of file m_popul.f90.

◆ population_load_data_all_genomes()

subroutine the_population::population_load_data_all_genomes ( class(population), intent(inout)  this,
integer, intent(in)  pop_size,
integer, intent(in), optional  pop_number_here,
character (len=*), intent(in), optional  pop_name_here,
character(len=*), intent(in)  csv_file_name,
logical, intent(in), optional  missing_random,
logical, intent(out), optional  is_success 
)

Load the genome data of all agents in this population from a CSV file. Note that the procedure implements several error correcting measures, e.g. checks for minimum number of rows in the file and minimum row length. The input CSV file therefore can include short text notes that are then ignored when reading data.

Parameters
[in]pop_sizepop_size, The size of the population.
[in]pop_number_hereid, Optional numeric population ID.
[in]pop_name_heredescriptor, Optional population string descriptor.
[in]csv_file_namecsv_file_name is the name of the CSV output file.
[in]missing_randommissing_random Flag dictating to generate random genomes if the commondata::popsize parameter exceeds the population size in the CSV genome data size. TRUE = generate random genome, FALSE = leave empty data commondata::unknown
[out]is_successis_success Flag showing that data save was successful (if TRUE).
  • handle_csv is the CSV file handle object defining the file name, Fortran unit and error descriptor, see HEDTOOLS manual for details.
  • line_data_buff is the input data buffer that is being read via the CSV_IO procedure READLINE()
  • n_rows_in is the number of rows in the input CSV file excluding the first row containing the variable names.
  • N_ROWS_MIN is the minimum number of readable rows in the CSV genome data file, if there are less in the file, data are considered invalid.
  • MIN_FILE_INP_LEN is the minimum length of the data row to be included in the read genome.
  • line_data_substrings - an array of row string data values after parding the whole input raw data.
  • matrix_row – array representing the genome data for a single row after parsing the input data file row.

Implementation notes

Genome data are obtained from the CSV data file provided by the intent(in) parameter csv_file_name.

  • First, calculate the number of records in the input CSV file and check that this number is greater than the minimum value set by the local parameter N_ROWS_MIN. Also check if the file can be read at all. If either of these conditions hold, exit from the procedure with
  • Second, open the input data file for reading
    • Define the file name %name component of the CSV file handle. The file handle object handle_csv is now used as the file identifier.
  • Open the output file defined by the handle_csv handle object for reading.
  • Possible error status of the latest file operation is obtained by the %status component of the file handle. Check if there were any errors opening the file and report in the logger with the error tag.
  • Third, read the variable names line of the CSV file. Note that they are not used here.
  • HAVE_POP check if the population is allocated and the population size is set, if not, allocate and set to commondata::popsize.
  • Check and reset population IDs if present
  • Initialise population with the size from input parameter.
  • Note that if the population is not allocated, all individuals that are not obtained from the data file are initialised random.
  • Check and reset population IDs if present
  • MAIN_READ: Cycle through the data lines using the non-advancing READLINE function and get the numerical genome data.
  • All input file lines that contain data shorter than MIN_FILE_INP_LEN characters are ignored.
  • Stripe away single and double quotes if any.
  • An approximate upper bound for the number of data fields in the current record is len_trim(line_data_buff)/MIN_FIELD), so we can now allocate the temporary array of substrings. This is also the total number of variables including the first two non-data records.
  • Split the input string buffer line_data_buff into an array of individual strings representing each file data field. The number of such non-empty strings (fields) is given by line_data_nflds.
  • N_GCOLS: Check if line_data_nflds obtained from CSV data coincides with the model (this data structure) as defined by the number of chromosomes, ploidy, chromosome length and N of additive components:
  • We have to allocate the array of row values and initialise it for correct processing by the VALUE subroutine.
  • first value from the file row is ID_NUM
  • second value from the file row is AGENT_NAME.
  • now read a single row of the genome data for this (icase) individual agent, note that if any data in the file are abridged, random values are generated within the appropriate genome limits (commondata::allelerange_min, commondata::allelerange_max).
  • Finally, split (parse) the single line array for the icase-s individual into the genome data structure.
  • FILL_EXTRA: If the number of rows in the data file read is smaller than the population size commondata::popsize, the remaining data may need to be filled with some default values. The flag missing_random determines to initialise all the remaining individuals in the population as random.

Initialise all individuals of the population

  • first, call `init to object individual(i)

Definition at line 2040 of file m_popul.f90.

Here is the call graph for this function:

◆ population_save_data_memory()

subroutine the_population::population_save_data_memory ( class(population), intent(in)  this,
character(len=*), intent(in)  csv_file_name,
logical, intent(out), optional  is_success 
)

Save the perceptual and emotional memory stack data of all agents in this population to a CSV file.

Parameters
[in]csv_file_namecsv_file_name is the name of the CSV output file.
[out]is_successis_success Flag showing that data save was successful (if TRUE).

Implementation details

Notable variables

  • COLUMNS_PERC defines the column names for all components of the perceptual memory stack. They must agree with the components of perceptual memory: the_neurobio::memory_perceptual

COLUMNS_EMOT defines the column name for all components of the emotional memory stack. They must agree with the components of emotional memory: the_neurobio::memory_emotional.

Preliminary

First, the file csv_file_name is opened for writing.

Build column names

The maximum length of the data record is calculated from three components

Note that, because the record also adds separators, such as comma and possibly double quotes, the number of columns multiplied by three is added to this value.

The first record of the data that contains the column names is now being "appended" into the complete record and written to the file. The maximum length of this record is calculated above.

The next portion is composed of the perceptual memory columns from COLUMNS_PERC array for each of the commondata::history_size_perception steps in the memory.

Note
Note that the order of data is: (1) perception component, (2) history steps: PERC_LIGHT01, PERC_LIGHT02, PERC_LIGHT03, ... PERC_DEPTH01, PERC_DEPTH02, PERC_DEPTH03, ...

The third portion is composed of the emotional memory columns from COLUMNS_EMOT array for each of the commondata::history_size_motivation steps in the memory.

Note
Note that the order of data is: (1) motivation component, (2) history steps: MOTIV_HUNGER01, MOTIV_HUNGER02, MOTIV_HUNGER03, ... MOTIV_AVOIDPAS01, MOTIV_AVOIDPAS02, MOTIV_AVOIDPAS03, ....

After this step, the first record of column names is ready to be written to the file.

Write the numerical data

The actual data are written in the same order as above, looping over all individual agents in this population.

The maximum record length record_csv_max_length is here the same as for writing the column headers, it is assumed that any numeric value in the data matrix occupies less than commondata::label_length characters.

So, for each agent, the following data are written with full history:

  • ID data: numeric ID and the string label;
  • Perceptual memory components;
  • Emotional memory components;
  • GOS memory components, note here that gos_main is a text value that is undefined (empty string) at the initialisation stage;

Each complete record is written to the file as it is built.

Once all individuals are saved, the file is closed.

The CSV output data file can be optionally compressed with the commondata::cmd_zip_output command if commondata::is_zip_outputs is set to TRUE.

Definition at line 2420 of file m_popul.f90.

◆ population_save_data_movements()

subroutine the_population::population_save_data_movements ( class(population), intent(in)  this,
character(len=*), intent(in)  csv_file_name,
logical, intent(out), optional  is_success 
)

Save the latest movement history of all agents. This method makes use of the the_environment::spatial_moving::history structure that saves latest movements of each agent.

Parameters
[in]csv_file_namecsv_file_name is the name of the CSV output file.
[out]is_successis_success Flag showing that data save was successful (if TRUE).

Implementation notes

The maximum length of the data record is calculated from three components: (1) commondata::history_size_spatial * 3 columns of X, Y, and depth coordinates plus (2) the same number of separators for these data columns (assuming 3 characters) plus (3) two additional columns that contain the numeric ID of the agent and its string label.

First, the file csv_file_name is opened for writing.

Build column names

The first record of the data that contains the column names is now being built. The maximum length of this record is calculated above. First thing to do is to cleanup the record string.

After this, the first record is built by appending components.

The first two columns contain the identifiers for each agent:

  • numeric ID of the agent
  • test string label ("name") of the agent

All remaining columns are built in a loop, by triplets: "X", "Y", "Depth" for each step of the history, up to commondata::history_size_spatial triplets.

Now the first record of column names is ready to be written to the file.

Write the numerical data

The actual data are written in the same order as above, looping over all individual agents in this population.

  • The record string is cleaned;
  • ID data appended: numeric ID and the string label;
  • Movement history triplets (x, y, depth) for all commondata::history_size_spatial are appended to the record string in a loop.

Each complete record is written to the file as it is built.

Once all individuals are saved, the file is closed.

The CSV output data file can be optionally compressed with the commondata::cmd_zip_output command if commondata::is_zip_outputs is set to TRUE.

Definition at line 2634 of file m_popul.f90.

◆ population_save_data_behaviours()

subroutine the_population::population_save_data_behaviours ( class(population), intent(in)  this,
character(len=*), intent(in)  csv_file_name,
logical, intent(out), optional  is_success 
)

Save the behaviours history stack the_neurobio::behaviour::history_behave for all agents.

Parameters
[in]csv_file_namecsv_file_name is the name of the CSV output file.
[out]is_successis_success Flag showing that data save was successful (if TRUE).

Implementation notes

The maximum length of the data record is calculated from three components: (1) commondata::history_size_behaviours labels of behaviours plus (2) the same number of separators for these data columns (assuming 3 characters) plus (3) two additional columns that contain the numeric ID of the agent and its string label.

First, the file csv_file_name is opened for writing.

Build column names

The first record of the data that contains the column names is now being built. The maximum length of this record is calculated above. First thing to do is to cleanup the record string.

After this, the first record is built by appending components.

The first two columns contain the identifiers for each agent:

  • numeric ID of the agent
  • test string label ("name") of the agent

All remaining columns are built in a loop for each step of the history, up to commondata::history_size_behaviours steps back in history.

Now the first record of column names is ready to be written to the file.

Write the numerical data

The actual data are written in the same order as above, looping over all individual agents in this population.

  • The record string is cleaned;
  • ID data appended: numeric ID and the string label;
  • Behaviour history for all commondata::history_size_behaviours steps is appended to the record string in a loop.

Each complete record is written to the file as it is built.

Once all individuals are saved, the file is closed.

The CSV output data file can be optionally compressed with the commondata::cmd_zip_output command if commondata::is_zip_outputs is set to TRUE.

Definition at line 2761 of file m_popul.f90.

◆ population_preevol_fitness_calc()

pure subroutine the_population::population_preevol_fitness_calc ( class(population), intent(inout)  this)

Calculate fitness for the pre-evolution phase of the genetic algorithm. Pre-evolution is based on selection for a simple criterion without explicit reproduction etc. The criterion for selection at this phase is set by the integer the_individual::individual_agent::fitness component. This procedure provides a whole-population wrapper for the the_individual::individual_agent::fitness_calc() function.

Warning
Note that fitness here is actually an inverse of the fitness: the higher its value, the worse fitting is the agent.

Definition at line 2888 of file m_popul.f90.

◆ population_ga_reproduce_max()

pure integer function the_population::population_ga_reproduce_max ( class(population), intent(in)  this)

Determine the number of parents that have fitness higher than the minimum acceptable value. Also, only alive agents are included into the reproducing number.

Note
This procedure is used in the fixed explicit fitness genetic algorithm, see the_evolution::generations_loop_ga().

Definition at line 2901 of file m_popul.f90.

◆ population_ga_mutation_rate_adaptive()

real(srp) function the_population::population_ga_mutation_rate_adaptive ( class(population), intent(in)  this,
real(srp), intent(in)  baseline,
real(srp), intent(in), optional  maxvalue 
)

This function implements adaptive mutation rate that increases as the population size reduces.

Parameters
[in]baselinebaseline baseline mutation rate
[in]maxvaluemaxvalue maximum mutation rate
Returns
The adjusted adaptive mutation rate.

Implementation notes

Notable variables and parameters

  • mutationrate_max – the maximum limit to the mutation rate. Can be obtained from the optional parameter maxvalue. The function returns its value at the lowest population size.
    Remarks
    It is actually local copy of optional maxvalue parameter.

MUTATIONRATE_MAX_DEF – the default maximum limit to the mutation rate mutationrate_max if maxvalue is not provided.

  • n_base_point – this is the base value for calculation of the adaptive mutation rate. It can be the number of agents alive or the number of agents that have grown.
  • mutation_grid_abscissa and mutation_grid_ordinate are the arrays that define the interpolation grid for the adaptive mutation rate.
  • MIN_GROWING a parameter setting the minimum number of growing agents in the population. If their actual number is smaller, the mutation rate further incremented by a factor set by the parameter
  • NON_GROW_INCREMENT is an increment factor for the mutation rate in case the number of growing agents is below the lower limit MIN_GROWING.

Procedure

First, calculate the base point n_base_point. This value is the base for the calculation of the adaptive mutation rate.

  • If this number reduces, mutation rate increases up to mutationrate_max

The n_base_point can be:

  • Number of agents that are alive: n_base_point = count( thisindividualis_alive() )
  • Number of agents that have grown: n_base_point = count( thisindividualget_mass() > & thisindividualget_mass_birth() )
  • If the mutation rate is based on the number of alive agents, the grid abscissa mutation_grid_abscissa is an array with three elements:
  • If, on the other hand, adaptive mutation rate is based on the number of agents that have grown, abscissa is set to specific arbitrary numbers that seem more or less optimal for the model performance.

The grid ordinate is defined as

  • the maximum mutation rate limit mutationrate_max
  • a small middle value that is calculated as 1/4 of the range between the maximum (MUTATIOlNRATE_MAX) and the minimum (baseline) mutation values; the latter value increments the minimum baseline.
  • the lowest baseline value that is set by the baseline dummy parameter.

Adaptive mutation rate is calculated based on the DDPINTERPOL() procedure with the grid array set by mutation_grid_abscissa and mutation_grid_ordinate and the interpolation value set by the number of agents that are the_genome::individual_genome::is_alive() in the population. An example pattern of the adaptive mutation rate function is plotted below. Here $ P_{max} $ is the maximum mutation rate defined by mutationrate_max and $ P_{b} $ is the baseline (normal, low) mutation rate defined by the baseline parameter.

Adaptive mutation rate

If the number of agents that had grown from their birth mass is less than the minimum number (MIN_GROWING), mutation rate is incremented by a fixed factor NON_GROW_INCREMENT. However, it is still forced to be within the range [ baseline, mutationrate_max ].

Interpolation plots can be saved in the debug mode using this plotting command: commondata::debug_interpolate_plot_save().

Warning
Involves huge number of plots, should normally be disabled.

Definition at line 2936 of file m_popul.f90.

Variable Documentation

◆ modname

character (len=*), parameter, private the_population::modname = "(THE_POPULATION)"
private

Definition at line 25 of file m_popul.f90.

◆ global_ind_n_eaten_by_predators

integer, public the_population::global_ind_n_eaten_by_predators

Global indicator variable that keeps the number of agents that have died as a consequence of predatory attacks. All other dies are therefore caused by starvation.

Note
Note that this variable is initialised to zero at the start of each generation in GENERATIONS_PREEVOL named loop in the_evolution::generations_loop_ga().

Definition at line 183 of file m_popul.f90.