Utopia  2
Framework for studying models of complex & adaptive systems.
CopyMeGrid.hh
Go to the documentation of this file.
1 #ifndef UTOPIA_MODELS_COPYMEGRID_HH
2 #define UTOPIA_MODELS_COPYMEGRID_HH
3 // TODO Adjust above include guard (and at bottom of file)
4 
5 // standard library includes
6 #include <random>
7 
8 // third-party library includes
9 
10 // Utopia-related includes
11 #include <utopia/core/model.hh>
13 #include <utopia/core/apply.hh>
14 
15 
17 
18 // ++ Type definitions ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
19 
21 struct CellState {
23  double some_state;
24 
27 
30 
33  :
34  some_state(get_as<double>("some_state", cfg)),
35  some_trait(get_as<int>("some_trait", cfg)),
36  is_a_vip_cell(false)
37  {}
38 
40  template<class RNG>
41  CellState(const DataIO::Config& cfg, const std::shared_ptr<RNG>& rng)
42  :
43  // Use the config constructor to get the values
44  CellState(cfg)
45  {
46  // Do some more things using the random number generator
47  // There is the possibility to set a random initial trait
48  if (cfg["random_initial_trait"]) {
49  if (not get_as<bool>("random_initial_trait", cfg)) {
50  // Is set, but is false. Just return:
51  return;
52  }
53 
54  // Choose a random value between 0 and the current value
55  some_trait = std::uniform_int_distribution(0, some_trait)(*rng);
56  }
57  // else: the config option was not available
58  }
59 };
60 
61 
63 
69 
70 
73 
74 
75 // ++ Model definition ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
76 
78 
83 class CopyMeGrid:
84  public Model<CopyMeGrid, ModelTypes>
85 {
86 public:
89 
91  using DataGroup = typename Base::DataGroup;
92 
94  using DataSet = typename Base::DataSet;
95 
98  // NOTE that it requires the model's type as second template argument
99 
101 
108  using RuleFunc = typename CellManager::RuleFunc;
109 
110 
111 private:
112  // Base members: _time, _name, _cfg, _hdfgrp, _rng, _monitor, _log, _space
113  // ... but you should definitely check out the documentation ;)
114 
115  // -- Members -------------------------------------------------------------
118 
121 
122  // More parameters here ...
123 
124 
126  std::uniform_real_distribution<double> _prob_distr;
127 
128  // .. Temporary objects ...................................................
129 
130 
131  // .. Datasets ............................................................
132  // NOTE They should be named '_dset_<name>', where <name> is the
133  // dataset's actual name as set in its constructor. If you are using
134  // data groups, prefix them with _dgrp_<groupname>
136  std::shared_ptr<DataSet> _dset_some_state;
137 
139  std::shared_ptr<DataSet> _dset_some_trait;
140 
141 
142 public:
143  // -- Model Setup ---------------------------------------------------------
144 
146 
154  template<class ParentModel>
156  const std::string& name,
157  ParentModel& parent_model,
158  const DataIO::Config& custom_cfg = {}
159  )
160  :
161  // Initialize first via base model
162  Base(name, parent_model, custom_cfg),
163 
164  // Now initialize the cell manager
165  _cm(*this),
166 
167  // Initialize model parameters
168  _some_parameter(get_as<double>("some_parameter", this->_cfg)),
169  // ...
170 
171  // Initialize the uniform real distribution to range [0., 1.]
172  _prob_distr(0., 1.),
173 
174  // Datasets
175  // For setting up datasets that store CellManager data, you can use the
176  // helper functions to take care of setting them up:
177  _dset_some_state(this->create_cm_dset("some_state", _cm)),
178  _dset_some_trait(this->create_cm_dset("some_trait", _cm))
179  // NOTE To set up datasets that have a different shape, we suggest to
180  // use the Model::create_dset helper, which already takes care of
181  // using the correct length into the time dimension (depending on
182  // the num_steps and write_every parameters). The syntax is:
183  //
184  // this->create_dset("mean_state", {}) // 1D {#writes}
185  // this->create_dset("a_vec", {num_cols}) // 2D {#writes, #cols}
186  {
187  // Can do remaining initialization steps here ...
188  // Example:
189  apply_rule([this](const auto& cell){
190  auto state = cell->state();
191 
192  // Every 13th cell (on average) is a VIP cell
193  if (this->_prob_distr(*this->_rng) < (1./13.)) {
194  state.is_a_vip_cell = true;
195  }
196 
197  return state;
198  }, _cm.cells());
199  // NOTE Compare this to the apply_rule calls in the perform_step method
200  // where a _stored_ lambda function is passed to it. For the setup
201  // done here, the function is only used once; thus, it makes more
202  // sense to just use a temporary lambda.
203 
204  this->_log->debug("VIP cells set up.");
205 
206  // NOTE The initial state need and should NOT be written here. The
207  // write_data method is invoked first at time `write_start`.
208  // However, this is a good place to store data that is constant
209  // during the run and needs to be written at some point.
210 
211  // Initialization should be finished here.
212  this->_log->debug("{} model fully set up.", this->_name);
213  }
214 
215 
216 private:
217  // .. Setup functions .....................................................
218  // Can add additional setup functions here ...
219 
220 
221  // .. Helper functions ....................................................
222 
224  double calc_some_state_mean () const {
225  double sum = 0.;
226  for (const auto &cell : _cm.cells()) {
227  sum += cell->state().some_state;
228  }
229  return sum / _cm.cells().size();
230  }
231 
232 
233  // .. Rule functions ......................................................
234  // Rule functions that can be applied to the CellManager's cells
235  // NOTE The below are examples; delete and/or adjust them to your needs!
236  // Ideally, only define those rule functions as members that are used
237  // more than once.
238 
240  const RuleFunc _some_interaction = [this](const auto& cell){
241  // Get the current state of the cell
242  auto state = cell->state();
243 
244  // Increase some_state by one
245  state.some_state += 1;
246 
247  // Iterate over all neighbors of the current cell
248  for (auto& nb : this->_cm.neighbors_of(cell)) {
249  // Obvious thing to do is to increase some_trait by the sum of
250  // some_traits's of the neighbor. Sure thing.
251  state.some_trait += nb->state().some_trait;
252 
253  // Let's add a random number in range [-1, +1] as well
254  state.some_trait += (this->_prob_distr(*this->_rng) * 2. - 1.);
255  }
256 
257  // Ahhh and obviously you need to divide some float by _some_parameter
258  // because that makes totally sense
259  state.some_trait /= this->_some_parameter;
260 
261  // Return the new cell state
262  return state;
263  };
264 
265 
267  const RuleFunc _some_other_rule = [this](const auto& cell){
268  // Get the current state of the cell
269  auto state = cell->state();
270 
271  // With a probability of 0.3 set the cell's state.some_state to 0
272  if (this->_prob_distr(*this->_rng) < 0.3) {
273  state.some_state = 0;
274  }
275 
276  // Return the new cell state
277  return state;
278  };
279 
280 
281 public:
282  // -- Public Interface ----------------------------------------------------
283  // .. Simulation Control ..................................................
284 
286 
289  void perform_step () {
290  // Apply the rules to all cells, first the interaction, then the update
293  }
294 
295 
297 
305  void monitor () {
306  this->_monitor.set_entry("some_value", 42);
307  this->_monitor.set_entry("state_mean", calc_some_state_mean());
308  }
309 
310 
312 
316  void write_data () {
317  // Write out the some_state of all cells
318  _dset_some_state->write(_cm.cells().begin(), _cm.cells().end(),
319  [](const auto& cell) {
320  return cell->state().some_state;
321  });
322 
323  // Write out the some_trait of all cells
324  _dset_some_trait->write(_cm.cells().begin(), _cm.cells().end(),
325  [](const auto& cell) {
326  return cell->state().some_trait;
327  });
328  }
329 
330 
331  // .. Getters and setters .................................................
332  // Add getters and setters here to interface with other models
333 
334 };
335 
336 } // namespace Utopia::Models::CopyMeGrid
337 
338 #endif // UTOPIA_MODELS_COPYMEGRID_HH
const CellContainer< Cell > & cells() const
Return const reference to the managed CA cells.
Definition: cell_manager.hh:219
typename std::function< CellState(const std::shared_ptr< Cell > &)> RuleFunc
The type of a rule function acting on cells of this cell manager.
Definition: cell_manager.hh:84
CellContainer< Cell > neighbors_of(const Cell &cell) const
Retrieve the given cell's neighbors.
Definition: cell_manager.hh:458
Base class interface for Models using the CRT Pattern.
Definition: model.hh:112
Monitor _monitor
The monitor.
Definition: model.hh:188
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
typename ModelTypes::DataSet DataSet
Data type that is used for storing data.
Definition: model.hh:125
const Config _cfg
Config node belonging to this model instance.
Definition: model.hh:158
const std::string _name
Name of the model instance.
Definition: model.hh:149
typename ModelTypes::DataGroup DataGroup
Data type that is used for storing datasets.
Definition: model.hh:122
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
The CopyMeGrid Model; a good start for a CA-based model.
Definition: CopyMeGrid.hh:85
typename CellManager::RuleFunc RuleFunc
Extract the type of the rule function from the CellManager.
Definition: CopyMeGrid.hh:108
const RuleFunc _some_other_rule
Some other rule function.
Definition: CopyMeGrid.hh:267
double _some_parameter
Some parameter.
Definition: CopyMeGrid.hh:120
CellManager _cm
The cell manager.
Definition: CopyMeGrid.hh:117
typename Base::DataGroup DataGroup
Data type of the group to write model data to, holding datasets.
Definition: CopyMeGrid.hh:91
std::uniform_real_distribution< double > _prob_distr
A re-usable uniform real distribution to evaluate probabilities.
Definition: CopyMeGrid.hh:126
void monitor()
Monitor model information.
Definition: CopyMeGrid.hh:305
std::shared_ptr< DataSet > _dset_some_trait
A dataset for storing all cells' some_trait.
Definition: CopyMeGrid.hh:139
std::shared_ptr< DataSet > _dset_some_state
A dataset for storing all cells' some_state.
Definition: CopyMeGrid.hh:136
void write_data()
Write data.
Definition: CopyMeGrid.hh:316
Model< CopyMeGrid, ModelTypes > Base
The type of the Model base class of this derived class.
Definition: CopyMeGrid.hh:88
CopyMeGrid(const std::string &name, ParentModel &parent_model, const DataIO::Config &custom_cfg={})
Construct the CopyMeGrid model.
Definition: CopyMeGrid.hh:155
double calc_some_state_mean() const
Calculate the mean of all cells' some_state.
Definition: CopyMeGrid.hh:224
void perform_step()
Iterate a single step.
Definition: CopyMeGrid.hh:289
const RuleFunc _some_interaction
An interaction function of a single cell with its neighbors.
Definition: CopyMeGrid.hh:240
typename Base::DataSet DataSet
Data type for a dataset.
Definition: CopyMeGrid.hh:94
YAML::Node Config
Type of a variadic dictionary-like data structure used throughout Utopia.
Definition: types.hh:71
ReturnType get_as(const std::string &key, const DataIO::Config &node)
This function is a wrapper around the yaml-cpp YAML::Node::as function.
Definition: cfg_utils.hh:158
void apply_rule(Rule &&rule, const ContTarget &cont_target, ContArgs &&... cont_args)
Sequential overload.
Definition: apply.hh:133
Definition: CopyMeGrid.hh:16
std::mt19937 rng
– Type definitions ----------------------------------------------------—
Definition: test_revision.cc:17
The entity traits struct gathers types to be used for specializing an entity.
Definition: entity.hh:49
Wrapper struct for defining model class data types.
Definition: model.hh:92
The type of a cell's state.
Definition: CopyMeGrid.hh:21
int some_trait
Another useful documentation string, yeah.
Definition: CopyMeGrid.hh:26
double some_state
A useful documentation string.
Definition: CopyMeGrid.hh:23
CellState(const DataIO::Config &cfg, const std::shared_ptr< RNG > &rng)
Construct the cell state from a configuration and an RNG.
Definition: CopyMeGrid.hh:41
CellState(const DataIO::Config &cfg)
Construct the cell state from a configuration.
Definition: CopyMeGrid.hh:32
bool is_a_vip_cell
Whether this cell is very important.
Definition: CopyMeGrid.hh:29