Utopia 2
Framework for studying models of complex & adaptive systems.
Loading...
Searching...
No Matches
Public Types | Public Member Functions | Private Member Functions | Private Attributes | List of all members
Utopia::Models::SimpleEG::SimpleEG Class Reference

Simple model of evolutionary games on grids. More...

#include <SimpleEG.hh>

Inheritance diagram for Utopia::Models::SimpleEG::SimpleEG:
Inheritance graph
[legend]
Collaboration diagram for Utopia::Models::SimpleEG::SimpleEG:
Collaboration graph
[legend]

Public Types

using Base = Model< SimpleEG, ModelTypes >
 The base model.
 
using Config = typename Base::Config
 Data type that holds the configuration.
 
using DataSet = typename Base::DataSet
 Data type for a dataset.
 
using CellManager = Utopia::CellManager< CellTraits, SimpleEG >
 Type of the CellManager to use.
 
using RuleFunc = typename CellManager::RuleFunc
 Extract the type of the rule function from the CellManager.
 
using RNG = typename Base::RNG
 Data type of the shared RNG.
 
using IAMatrixType = typename std::array< std::array< double, 2 >, 2 >
 Type of the interaction matrix.
 
- Public Types inherited from Utopia::Model< SimpleEG, ModelTypes >
using Config = typename ModelTypes::Config
 Data type that holds the configuration.
 
using DataManager = DataIO::Default::DefaultDataManager< SimpleEG >
 The data manager to use, specialized with the derived model.
 
using DataGroup = typename ModelTypes::DataGroup
 Data type that is used for storing datasets.
 
using DataSet = typename ModelTypes::DataSet
 Data type that is used for storing data.
 
using RNG = typename ModelTypes::RNG
 Data type of the shared RNG.
 
using Space = typename ModelTypes::Space
 Data type of the space this model resides in.
 
using Time = typename ModelTypes::Time
 Data type for the model time.
 
using Monitor = typename ModelTypes::Monitor
 Data type for the monitor.
 
using MonitorManager = typename ModelTypes::MonitorManager
 Data type for the monitor manager.
 
using Level = typename ModelTypes::Level
 Data type for the hierarchical level.
 

Public Member Functions

template<class ParentModel >
 SimpleEG (const std::string &name, ParentModel &parent_model, const DataIO::Config &custom_cfg={})
 Construct the SimpleEG model.
 
void perform_step ()
 Iterate a single step.
 
void monitor ()
 Monitor model information.
 
void write_data ()
 Write data: the strategy and payoff of each cell.
 
- Public Member Functions inherited from Utopia::Model< SimpleEG, ModelTypes >
 Model (const std::string &name, const ParentModel &parent_model, const Config &custom_cfg={}, std::tuple< WriterArgs... > w_args={}, const DataIO::Default::DefaultDecidermap< SimpleEG > &w_deciders=DataIO::Default::default_deciders< SimpleEG >, const DataIO::Default::DefaultTriggermap< SimpleEG > &w_triggers=DataIO::Default::default_triggers< SimpleEG >)
 Constructs a Model instance.
 
const std::shared_ptr< Space > & get_space () const
 Return the space this model resides in.
 
Time get_time () const
 Return the current time of this model.
 
Time get_time_max () const
 Return the maximum time possible for this model.
 
Config get_cfg () const
 Return the config node of this model.
 
std::string get_name () const
 Return the name of this model instance.
 
std::string get_full_name () const
 Return the full name of this model within the model hierarchy.
 
std::shared_ptr< DataGroupget_hdfgrp () const
 Return a pointer to the HDF group this model stores data in.
 
Time get_write_start () const
 Return the parameter that controls when write_data is called first.
 
Time get_write_every () const
 Return the parameter that controls how often write_data is called.
 
DataManager get_datamanager () const
 return the datamanager
 
hsize_t get_remaining_num_writes () const
 Return the number of remaining write_data calls this model will make.
 
std::shared_ptr< RNGget_rng () const
 Return a pointer to the shared RNG.
 
std::shared_ptr< spdlog::logger > get_logger () const
 Return a pointer to the logger of this model.
 
Monitor get_monitor () const
 Return the monitor of this model.
 
std::shared_ptr< MonitorManagerget_monitor_manager () const
 Get the monitor manager of the root model.
 
Level get_level () const
 Return the hierarchical level within the model hierarchy.
 
virtual void prolog ()
 A function that is called before starting model iteration.
 
virtual void epilog ()
 A function that is called after the last iteration of a model.
 
void iterate ()
 Iterate one (time) step of this model.
 
void run ()
 Run the model from the current time to the maximum time.
 
std::shared_ptr< DataSetcreate_dset (const std::string name, const std::shared_ptr< DataGroup > &hdfgrp, std::vector< hsize_t > add_write_shape, const std::size_t compression_level=1, const std::vector< hsize_t > chunksize={})
 Create a new dataset within the given group.
 
std::shared_ptr< DataSetcreate_dset (const std::string name, const std::vector< hsize_t > add_write_shape, const std::size_t compression_level=1, const std::vector< hsize_t > chunksize={})
 Create a new dataset within the model's base data group.
 
std::shared_ptr< DataSetcreate_cm_dset (const std::string name, const CellManager &cm, const std::size_t compression_level=1, const std::vector< hsize_t > chunksize={})
 Create a dataset storing data from a CellManager.
 
std::shared_ptr< DataSetcreate_am_dset (const std::string name, const AgentManager &am, const std::size_t compression_level=1, const std::vector< hsize_t > chunksize={})
 Create a dataset storing data from a AgentManager.
 

Private Member Functions

void initialize_cells ()
 Initialize the cells according to initial_state config parameter.
 
IAMatrixType extract_ia_matrix () const
 Extract the interaction matrix from the config file.
 

Private Attributes

CellManager _cm
 The cell manager.
 
const IAMatrixType _ia_matrix
 The interaction matrix (extracted during initialization)
 
CellContainer< typename CellManager::Cell_fittest_cells_in_nbhood
 A container to temporarily accumulate the fittest neighbor cells in.
 
std::uniform_real_distribution< double_prob_distr
 Uniform real distribution in [0., 1.) used for evaluating probabilities.
 
std::shared_ptr< DataSet_dset_strategy
 Stores cell strategies over time.
 
std::shared_ptr< DataSet_dset_payoff
 Stores cell payoffs over time.
 
RuleFunc _interaction
 The interaction between players.
 
RuleFunc _update
 The update rule.
 

Additional Inherited Members

- Protected Member Functions inherited from Utopia::Model< SimpleEG, ModelTypes >
void __perform_step ()
 Perform the computation of a step.
 
void __monitor ()
 Monitor information in the terminal.
 
void __write_data ()
 Write data; calls the implementation's write_data method.
 
void __write_initial_state ()
 Write the initial state.
 
void increment_time (const Time dt=1)
 Increment time.
 
void __prolog ()
 The default prolog of a model.
 
void __epilog ()
 The default epilog of a model.
 
SimpleEG & impl ()
 cast to the derived class
 
const SimpleEG & impl () const
 const cast to the derived interface
 
- Protected Attributes inherited from Utopia::Model< SimpleEG, ModelTypes >
const std::string _name
 Name of the model instance.
 
const std::string _full_name
 The full name within the model hierarchy.
 
const Level _level
 The level within the model hierarchy.
 
const Config _cfg
 Config node belonging to this model instance.
 
const std::shared_ptr< RNG_rng
 The RNG shared between models.
 
const std::shared_ptr< spdlog::logger > _log
 The (model) logger.
 
std::shared_ptr< Space_space
 The space this model resides in.
 
Time _time
 Model-internal current time stamp.
 
const Time _time_max
 Model-internal maximum time stamp.
 
const std::shared_ptr< DataGroup_hdfgrp
 The HDF group this model instance should write its data to.
 
const Time _write_start
 First time at which write_data is called.
 
const Time _write_every
 How often to call write_data from iterate.
 
Monitor _monitor
 The monitor.
 
DataManager _datamanager
 Manager object for handling data output; see DataManager.
 
- Static Protected Attributes inherited from Utopia::Model< SimpleEG, ModelTypes >
static constexpr WriteMode _write_mode
 Which data-writing mode the base model should use.
 

Detailed Description

Simple model of evolutionary games on grids.

In this model, cells have an internal strategy, which determines their success in the interactions with their neighboring cells. The success is given by an interaction matrix. In one interaction step, every cell interacts with all its neighboring cells (interaction lambda function). Afterwards, all cells are updated synchronously (update lambda function). From a cells perspective, the mechanism is as follows: Look around in you neighborhood for the cell, which had the highest payoff from the interactions. Change your state to this fittest neighboring cell's state. If multiple cells within a neighborhood have the same payoff choose randomly between their strategies.

Member Typedef Documentation

◆ Base

The base model.

◆ CellManager

Type of the CellManager to use.

◆ Config

Data type that holds the configuration.

◆ DataSet

Data type for a dataset.

◆ IAMatrixType

Type of the interaction matrix.

◆ RNG

Data type of the shared RNG.

◆ RuleFunc

Extract the type of the rule function from the CellManager.

This is a function that receives a reference to a cell and returns the new cell state. For more details, check out Utopia::CellManager

Note
Whether the cell state gets applied directly or requires a synchronous update depends on the update mode specified in the cell traits.

Constructor & Destructor Documentation

◆ SimpleEG()

template<class ParentModel >
Utopia::Models::SimpleEG::SimpleEG::SimpleEG ( const std::string &  name,
ParentModel parent_model,
const DataIO::Config custom_cfg = {} 
)
inline

Construct the SimpleEG model.

Parameters
nameName of this model instance; is used to extract the configuration from the parent model and set up a HDFGroup for this instance
parent_modelThe parent model this model instance resides in
custom_cfgA custom configuration to use instead of the one extracted from the parent model using the instance name
147 {}
148 )
149 :
150 // Initialize first via base model
152
153 // Now initialize the cell manager
154 _cm(*this),
155
156 // Initialize model parameters
158
159 // ... and helpers objects
161 _prob_distr(0., 1.),
162
163 // And open datasets for strategy and payoff
164 _dset_strategy(this->create_cm_dset("strategy", _cm)),
166 {
167 // Initialize cells
168 this->initialize_cells();
169
170 // Write calculated _ia_matrix to _hdfgrp attribute
171 this->_hdfgrp->add_attribute("ia_matrix", _ia_matrix);
172 }
std::shared_ptr< DataSet > create_cm_dset(const std::string name, const CellManager &cm, const std::size_t compression_level=1, const std::vector< hsize_t > chunksize={})
Create a dataset storing data from a CellManager.
Definition model.hh:849
const std::shared_ptr< DataGroup > _hdfgrp
The HDF group this model instance should write its data to.
Definition model.hh:176
CellManager _cm
The cell manager.
Definition SimpleEG.hh:110
std::shared_ptr< DataSet > _dset_payoff
Stores cell payoffs over time.
Definition SimpleEG.hh:129
std::shared_ptr< DataSet > _dset_strategy
Stores cell strategies over time.
Definition SimpleEG.hh:126
IAMatrixType extract_ia_matrix() const
Extract the interaction matrix from the config file.
Definition SimpleEG.hh:356
void initialize_cells()
Initialize the cells according to initial_state config parameter.
Definition SimpleEG.hh:183
Model< SimpleEG, ModelTypes > Base
The base model.
Definition SimpleEG.hh:75
std::uniform_real_distribution< double > _prob_distr
Uniform real distribution in [0., 1.) used for evaluating probabilities.
Definition SimpleEG.hh:121
const IAMatrixType _ia_matrix
The interaction matrix (extracted during initialization)
Definition SimpleEG.hh:113
CellContainer< typename CellManager::Cell > _fittest_cells_in_nbhood
A container to temporarily accumulate the fittest neighbor cells in.
Definition SimpleEG.hh:118
Container select_entities(const Manager &mngr, const DataIO::Config &sel_cfg)
Select entities according to parameters specified in a configuration.
Definition select.hh:213

Member Function Documentation

◆ extract_ia_matrix()

IAMatrixType Utopia::Models::SimpleEG::SimpleEG::extract_ia_matrix ( ) const
inlineprivate

Extract the interaction matrix from the config file.

In the model config file there are three different ways to specify the interaction: 1) Explicitly setting the interaction matrix ia_matrix S0 S1 S0 [ia_00 ia_01] S1 [ia_10 ia_11]

2) Setting a benefit and cost pair bc_pair S0 S1 S0 [b-c -c] S1 [b 0]

3) Setting the benefit parameter b following the paper of Nowak&May1992 S0 S1 S0 [1 0] S1 [b(>1) 0]

If 1) is set, 2) and 3) will be ignored. The function returns the explicitly given ia_matrix. If 1) is not set, then the interaction matrix of 2) will be returned. If 1) and 2) are not set, the interaction matrix of 3) will be returned.

Returns
IAMatrixType The interaction matrix
356 {
357 // Return the ia_matrix if it is explicitly given in the config
358 if (this->_cfg["ia_matrix"]) {
359 return get_as<IAMatrixType>("ia_matrix", this->_cfg);
360 }
361 else if (this->_cfg["bc_pair"]) {
362 // If ia_matrix is not provided in the config, get the ia_matrix
363 // from the bc-pair
364 const auto [b, c] = get_as<std::pair<double, double>>("bc_pair",
365 this->_cfg);
366 const double ia_00 = b - c;
367 const double ia_01 = -c;
368 const double ia_10 = b;
369 const double ia_11 = 0.;
370
371 const std::array<double,2> row0({{ia_00, ia_01}});
372 const std::array<double,2> row1({{ia_10, ia_11}});
373
374 return IAMatrixType({{row0, row1}});
375 }
376 else if (this->_cfg["b"]) {
377 // If both previous cases are not provided, then return the
378 // ia_matrix given by the parameter "b"
379 const auto b = get_as<double>("b", this->_cfg);
380
381 if (b <= 1.) {
382 throw std::invalid_argument("Parameter `b` needs to be >1, "
383 "but was: " + std::to_string(b));
384 }
385
386 const double ia_00 = 1;
387 const double ia_01 = 0;
388 const double ia_10 = b;
389 const double ia_11 = 0.;
390
391 const std::array<double, 2> row0({{ia_00, ia_01}});
392 const std::array<double, 2> row1({{ia_10, ia_11}});
393
394 return IAMatrixType({{row0, row1}});;
395 }
396
397 // If we reach this point, not enough parameters were provided
398 throw std::invalid_argument("No interaction matrix given! Check that "
399 "at least one of the following config "
400 "entries is available: `ia_matrix`, "
401 "`bc_pair`, `b`");
402 }
const Config _cfg
Config node belonging to this model instance.
Definition model.hh:158
typename std::array< std::array< double, 2 >, 2 > IAMatrixType
Type of the interaction matrix.
Definition SimpleEG.hh:101

◆ initialize_cells()

void Utopia::Models::SimpleEG::SimpleEG::initialize_cells ( )
inlineprivate

Initialize the cells according to initial_state config parameter.

The cell initialization for most cases is done directly at cell construction. However, some initialization options depend on the position of the cell on the grid. Only these cases are dealt with in this initialization function.

183 {
184 static_assert(Base::Space::dim == 2, "Only 2D space is supported.");
185
186 // Extract the mode that determines the initial strategy
187 auto initial_state = get_as<std::string>("initial_state", this->_cfg);
188
189 this->_log->info("Initializing cells in '{}' mode ...", initial_state);
190
191 // Distinguish according to the mode, which strategy to choose
192 if (initial_state == "random") {
193 // Get the threshold probability value
194 const auto s1_prob = get_as<double>("s1_prob", this->_cfg);
195
196 // Define the update rule
197 auto set_random_strategy = [this, &s1_prob](const auto cell) {
198 auto state = cell->state();
199
200 // Draw a random number and compare it to the threshold
201 if (this->_prob_distr(*this->_rng) < s1_prob) {
202 state.strategy = Strategy::S1;
203 }
204 else {
205 state.strategy = Strategy::S0;
206 }
207
208 return state;
209 };
210
211 // Apply the rule to all cells
213 }
214
215 else if (initial_state == "fraction") {
216 // Get the value for the fraction of cells to have strategy 1
217 const auto s1_fraction = get_as<double>("s1_fraction", this->_cfg);
218
219 if (s1_fraction > 1. or s1_fraction < 0.) {
220 throw std::invalid_argument("Need `s1_fraction` in [0, 1], "
221 "but got value: " + std::to_string(s1_fraction));
222 }
223
224 // Calculate the number of cells that should have that strategy
225 const auto num_cells = _cm.cells().size();
226 const std::size_t num_s1 = s1_fraction * num_cells;
227 // NOTE this is a flooring calculation!
228
229 this->_log->debug("Cells with strategy 1: {} of {}",
230 num_s1, num_cells);
231
232 // TODO Optionally, can add some logic here to make more clever
233 // assignments, i.e. starting out with all S1 if the number
234 // to set is higher than half ...
235
236 // Need a counter of cells that were set to S1
237 std::size_t num_set = 0;
238
239 // Get a copy of the cells container... and shuffle them.
240 auto random_cells = _cm.cells();
241 std::shuffle(random_cells.begin(), random_cells.end(),
242 *this->_rng);
243
244 // Make num_s1 cells use strategy 1
245 for (const auto& cell : random_cells) {
246 // If the desired number of cells using strategy 1 is not yet reached change another cell's strategy
247 if (num_set < num_s1) {
248 // Check if it already has strategy 1.
249 if (cell->state().strategy == Strategy::S1) {
250 // Already has strategy 1, don't set it again
251 continue;
252 }
253 // else: has strategy 0 -> set to S1 and increment counter
254 cell->state_new().strategy = Strategy::S1;
255 cell->update();
256
257 num_set++;
258 }
259 // Break, if fraction of strategy 1 is reached
260 else break;
261 }
262 }
263
264 else if (initial_state == "single_s0" or initial_state == "single_s1"){
265 // Get the grid shape and perform checks on it
266 const auto& grid_shape = _cm.grid()->shape();
267
268 // Need to throw an error for non-odd-valued grid shape
269 if (grid_shape[0] % 2 == 0 or grid_shape[1] % 2 == 0) {
270 throw std::invalid_argument("In mode '" + initial_state + "', "
271 "odd grid extensions are required to calculate the "
272 "central cell! Either adapt your grid resolution or the "
273 "space's extent in order to have a different shape. "
274 );
275 }
276 // FIXME This and the below is rather fragile and should be
277 // improved. Better approach: calculate the central point
278 // (here!) and find the cell beneath that point, setting it
279 // to single_strategy. Then use rule application to set
280 // default_strategy.
281
282 // Determine which strategy is the common default strategy
283 // and which one is the single strategy in the center of the grid
285 if (initial_state == "single_s0") {
288 }
289 else {
292 }
293
294 // Define the rule function
295 auto set_initial_strategy = [&](const auto& cell) {
296 // Get the state of this cell
297 auto state = cell->state();
298
299 // Get the multi index to find out if this cell is central
300 const auto midx = _cm.midx_of(cell);
301
302 if ( midx[0] == grid_shape[0] / 2
303 and midx[1] == grid_shape[1] / 2) {
304 // The cell _is_ in the center of the grid
305 state.strategy = single_strategy;
306 }
307 else {
308 // The cell _is not_ in the center of the grid
309 state.strategy = default_strategy;
310 }
311
312 return state;
313 };
314
315 // Apply the rule
317 }
318 else {
319 throw std::invalid_argument("Invalid value '" + initial_state
320 + "' for parameter `initial_state`! Allowed values: random, "
321 "fraction, single_s0, single_s1.");
322 }
323
324 // Done.
325 this->_log->info("Initialized all {} cells.", _cm.cells().size());
326 }
MultiIndex midx_of(const Cell &cell) const
Returns the multi-index of the given cell.
Definition cell_manager.hh:236
const std::shared_ptr< GridType > & grid() const
Return const reference to the grid.
Definition cell_manager.hh:214
const CellContainer< Cell > & cells() const
Return const reference to the managed CA cells.
Definition cell_manager.hh:219
const std::shared_ptr< spdlog::logger > _log
The (model) logger.
Definition model.hh:164
const std::shared_ptr< RNG > _rng
The RNG shared between models.
Definition model.hh:161
void apply_rule(Rule &&rule, const ContTarget &cont_target, ContArgs &&... cont_args)
Sequential overload.
Definition apply.hh:133
Strategy
Strategy enum.
Definition SimpleEG.hh:19
@ S1
Definition SimpleEG.hh:19
@ S0
Definition SimpleEG.hh:19

◆ monitor()

void Utopia::Models::SimpleEG::SimpleEG::monitor ( )
inline

Monitor model information.

526 {
527
528 }

◆ perform_step()

void Utopia::Models::SimpleEG::SimpleEG::perform_step ( )
inline

Iterate a single step.

In the config, the following interaction matrix is stored: S0 S1 S0 ( _ia_matrix[0][0] _ia_matrix[0][1] ) S1 ( _ia_matrix[1][0] _ia_matrix[1][1] )

The interaction payoff is given from the perspective of the left-column- strategy. E.g. if S0 interacts with S1, S0 receives the payoff given by _ia_matrix[0][1] whereas S1 receives the payoff given by _ia_matrix[1][0].

518 {
519 // Apply the rules to all cells
522 }
RuleFunc _update
The update rule.
Definition SimpleEG.hh:458
RuleFunc _interaction
The interaction between players.
Definition SimpleEG.hh:412

◆ write_data()

void Utopia::Models::SimpleEG::SimpleEG::write_data ( )
inline

Write data: the strategy and payoff of each cell.

532 {
533 // strategy
534 _dset_strategy->write(_cm.cells().begin(), _cm.cells().end(),
535 [](const auto& cell) {
536 return static_cast<unsigned short int>(cell->state().strategy);
537 }
538 );
539
540 // payoffs
541 _dset_payoff->write(_cm.cells().begin(), _cm.cells().end(),
542 [](const auto& cell) {
543 return cell->state().payoff;
544 }
545 );
546 }

Member Data Documentation

◆ _cm

CellManager Utopia::Models::SimpleEG::SimpleEG::_cm
private

The cell manager.

◆ _dset_payoff

std::shared_ptr<DataSet> Utopia::Models::SimpleEG::SimpleEG::_dset_payoff
private

Stores cell payoffs over time.

◆ _dset_strategy

std::shared_ptr<DataSet> Utopia::Models::SimpleEG::SimpleEG::_dset_strategy
private

Stores cell strategies over time.

◆ _fittest_cells_in_nbhood

CellContainer<typename CellManager::Cell> Utopia::Models::SimpleEG::SimpleEG::_fittest_cells_in_nbhood
private

A container to temporarily accumulate the fittest neighbor cells in.

◆ _ia_matrix

const IAMatrixType Utopia::Models::SimpleEG::SimpleEG::_ia_matrix
private

The interaction matrix (extracted during initialization)

◆ _interaction

RuleFunc Utopia::Models::SimpleEG::SimpleEG::_interaction
private

The interaction between players.

This rule calculates the payoff for a given cell, depending on the interaction matrix and the payoffs of the neighbors.

412 {
413 // Get the state of the current cell and its strategy
414 auto state = cell->state();
415
416 // First, reset payoff to zero
417 state.payoff = 0.;
418
419 // Go through neighboring cells, look at their strategies and add
420 // the corresponding payoff only to the current cell's payoff.
421 // NOTE: Careful! Adding the corresponding payoff to the neighboring
422 // cell would lead to payoffs being added multiple times!
423 for (const auto& nb : this->_cm.neighbors_of(cell)) {
424 const auto nb_strategy = nb->state().strategy;
425
426 // Calculate the payoff depending on this cell's and the other
427 // cell's state
428 if (state.strategy == S0 and nb_strategy == S0) {
429 state.payoff += _ia_matrix[0][0];
430 }
431 else if (state.strategy == S0 and nb_strategy == S1) {
432 state.payoff += _ia_matrix[0][1];
433 }
434 else if (state.strategy == S1 and nb_strategy == S0) {
435 state.payoff += _ia_matrix[1][0];
436 }
437 else if (state.strategy == S1 and nb_strategy == S1) {
438 state.payoff += _ia_matrix[1][1];
439 }
440 }
441
442 // Return the updated state of this cell
443 return state;
444 };

◆ _prob_distr

std::uniform_real_distribution<double> Utopia::Models::SimpleEG::SimpleEG::_prob_distr
private

Uniform real distribution in [0., 1.) used for evaluating probabilities.

◆ _update

RuleFunc Utopia::Models::SimpleEG::SimpleEG::_update
private

The update rule.

Update procedure is as follows:

  • Loop through the neighbors and store all neighbors with the highest payoff.
  • Use the member _fittest_cells_in_nbhood for this, such that the vector does not need to be recreated for each cell.
Note
In most cases the vector will contain only one cell. However, there are parameter regimes where multiple cells can have the same payoff; this approach copes with spatial artifacts regardless of the parameter regime.
458 {
459 // Get the state of the cell
460 auto state = cell->state();
461
462 // Set highest payoff in the neighborhood to the cell's payoff
463 double highest_payoff = state.payoff;
466
467 // Iterate over neighbors of this cell:
468 for (const auto& nb : this->_cm.neighbors_of(cell)){
469 if (nb->state().payoff > highest_payoff) {
470 // Found a new highest payoff
471 highest_payoff = nb->state().payoff;
473 _fittest_cells_in_nbhood.push_back(nb);
474 }
475 else if (nb->state().payoff == highest_payoff) {
476 // Have a payoff equal to that of another cell
477 _fittest_cells_in_nbhood.push_back(nb);
478 }
479 // else: payoff was below highest payoff
480 }
481
482 // Now, update the strategy according to the fittest neighbor
483 if (_fittest_cells_in_nbhood.size() == 1) {
484 // Only one fittest neighbor. -> The state of the current cell
485 // is updated with that of the fittest neighbor.
486 state.strategy = _fittest_cells_in_nbhood[0]->state().strategy;
487 }
488 else if (_fittest_cells_in_nbhood.size() > 1) {
489 // There are multiple nbs with the same (highest) payoff.
490 // -> Choose randomly one of them to pass on its strategy
491 std::uniform_int_distribution<> dist(0, _fittest_cells_in_nbhood.size()-1);
492 state.strategy = _fittest_cells_in_nbhood[dist(*this->_rng)]->state().strategy;
493 }
494 else {
495 // There is no fittest neighbor. This case should never occur!
496 throw std::runtime_error("There was no fittest neighbor in the "
497 "cell update. Should not have occurred!");
498 }
499
500 return state;
501 };

The documentation for this class was generated from the following file: