242 lines
11 KiB
Markdown
242 lines
11 KiB
Markdown
Simulation Configuration
|
|
==
|
|
|
|
## Introduction
|
|
|
|
Given a **Simulation Configuration**, cadCAD produces datasets that represent the evolution of the state of a system
|
|
over [discrete time](https://en.wikipedia.org/wiki/Discrete_time_and_continuous_time#Discrete_time). The state of the
|
|
system is described by a set of [State Variables](#State-Variables). The dynamic of the system is described by
|
|
[Policy Functions](#Policy-Functions) and [State Update Functions](#State-Update-Functions), which are evaluated by
|
|
cadCAD according to the definitions set by the user in [Partial State Update Blocks](#Partial-State-Update-Blocks).
|
|
|
|
A Simulation Configuration is comprised of a [System Model](#System-Model) and a set of
|
|
[Simulation Properties](#Simulation-Properties)
|
|
|
|
`append_configs`, stores a **Simulation Configuration** to be [Executed](/JS4Q9oayQASihxHBJzz4Ug) by cadCAD
|
|
|
|
```python
|
|
from cadCAD.configuration import append_configs
|
|
|
|
append_configs(
|
|
initial_state = ..., # System Model
|
|
partial_state_update_blocks = .., # System Model
|
|
policy_ops = ..., # System Model
|
|
sim_configs = ... # Simulation Properties
|
|
)
|
|
```
|
|
Parameters:
|
|
* **initial_state** : _dict_ - [State Variables](#State-Variables) and their initial values
|
|
* **partial_state_update_blocks** : List[dict[dict]] - List of [Partial State Update Blocks](#Partial-State-Update-Blocks)
|
|
* **policy_ops** : List[functions] - See [Policy Aggregation](/63k2ncjITuqOPCUHzK7Viw)
|
|
* **sim_configs** - See [System Model Parameter Sweep](/4oJ_GT6zRWW8AO3yMhFKrg)
|
|
|
|
## Simulation Properties
|
|
|
|
Simulation properties are passed to `append_configs` in the `sim_configs` parameter. To construct this parameter, we
|
|
use the `config_sim` function in `cadCAD.configuration.utils`
|
|
|
|
```python
|
|
from cadCAD.configuration.utils import config_sim
|
|
|
|
c = config_sim({
|
|
"N": ...,
|
|
"T": range(...),
|
|
"M": ...
|
|
})
|
|
|
|
append_configs(
|
|
...
|
|
sim_configs = c # Simulation Properties
|
|
)
|
|
```
|
|
|
|
### T - Simulation Length
|
|
Computer simulations run in discrete time:
|
|
|
|
>Discrete time views values of variables as occurring at distinct, separate "points in time", or equivalently as being
|
|
unchanged throughout each non-zero region of time ("time period")—that is, time is viewed as a discrete variable. (...)
|
|
This view of time corresponds to a digital clock that gives a fixed reading of 10:37 for a while, and then jumps to a
|
|
new fixed reading of 10:38, etc.
|
|
([source: Wikipedia](https://en.wikipedia.org/wiki/Discrete_time_and_continuous_time#Discrete_time))
|
|
|
|
As is common in many simulation tools, in cadCAD too we refer to each discrete unit of time as a **timestep**. cadCAD
|
|
increments a "time counter", and at each step it updates the state variables according to the equations that describe
|
|
the system.
|
|
|
|
The main simulation property that the user must set when creating a Simulation Configuration is the number of timesteps
|
|
in the simulation. In other words, for how long do they want to simulate the system that has been modeled.
|
|
|
|
### N - Number of Runs
|
|
|
|
cadCAD facilitates running multiple simulations of the same system sequentially, reporting the results of all those
|
|
runs in a single dataset. This is especially helpful for running
|
|
[Monte Carlo Simulations](../tutorials/robot-marbles-part-4/robot-marbles-part-4.ipynb).
|
|
|
|
### M - Parameters of the System
|
|
|
|
Parameters of the system, passed to the state update functions and the policy functions in the `params` parameter are
|
|
defined here. See [System Model Parameter Sweep](/4oJ_GT6zRWW8AO3yMhFKrg) for more information.
|
|
|
|
## System Model
|
|
The System Model describes the system that will be simulated in cadCAD. It is comprised of a set of
|
|
[State Variables](###Sate-Variables) and the [State Update Functions](#State-Update-Functions) that determine the
|
|
evolution of the state of the system over time. [Policy Functions](#Policy-Functions) (representations of user policies
|
|
or internal system control policies) may also be part of a System Model.
|
|
|
|
### State Variables
|
|
>A state variable is one of the set of variables that are used to describe the mathematical "state" of a dynamical
|
|
system. Intuitively, the state of a system describes enough about the system to determine its future behaviour in the
|
|
absence of any external forces affecting the system. ([source: Wikipedia](https://en.wikipedia.org/wiki/State_variable))
|
|
|
|
cadCAD can handle state variables of any Python data type, including custom classes. It is up to the user of cadCAD to
|
|
determine the state variables needed to **sufficiently and accurately** describe the system they are interested in.
|
|
|
|
State Variables are passed to `append_configs` along with its initial values, as a Python `dict` where the `dict_keys`
|
|
are the names of the variables and the `dict_values` are their initial values.
|
|
|
|
```python
|
|
from cadCAD.configuration import append_configs
|
|
|
|
genesis_states = {
|
|
'state_variable_1': 0,
|
|
'state_variable_2': 0,
|
|
'state_variable_3': 1.5,
|
|
'timestamp': '2019-01-01 00:00:00'
|
|
}
|
|
|
|
append_configs(
|
|
initial_state = genesis_states,
|
|
...
|
|
)
|
|
```
|
|
### State Update Functions
|
|
State Update Functions represent equations according to which the state variables change over time. Each state update
|
|
function must return a tuple containing a string with the name of the state variable being updated and its new value.
|
|
Each state update function can only modify a single state variable. The general structure of a state update function is:
|
|
```python
|
|
def state_update_function_A(_params, substep, sH, s, _input):
|
|
...
|
|
return 'state_variable_name', new_value
|
|
```
|
|
Parameters:
|
|
* **_params** : _dict_ - [System parameters](/4oJ_GT6zRWW8AO3yMhFKrg)
|
|
* **substep** : _int_ - Current [substep](#Substep)
|
|
* **sH** : _list[list[dict_]] - Historical values of all state variables for the simulation. See
|
|
[Historical State Access](/smiyQTnATtC9xPwvF8KbBQ) for details
|
|
* **s** : _dict_ - Current state of the system, where the `dict_keys` are the names of the state variables and the
|
|
`dict_values` are their current values.
|
|
* **_input** : _dict_ - Aggregation of the signals of all policy functions in the current
|
|
[Partial State Update Block](#Partial-State-Update-Block)
|
|
|
|
Return:
|
|
* _tuple_ containing a string with the name of the state variable being updated and its new value.
|
|
|
|
State update functions should not modify any of the parameters passed to it, as those are mutable Python objects that
|
|
cadCAD relies on in order to run the simulation according to the specifications.
|
|
|
|
### Policy Functions
|
|
A Policy Function computes one or more signals to be passed to [State Update Functions](#State-Update-Functions)
|
|
(via the _\_input_ parameter). Read
|
|
[this article](../tutorials/robot-marbles-part-2/robot-marbles-part-2.ipynb)
|
|
for details on why and when to use policy functions.
|
|
|
|
<!-- We would then expand the tutorials with these kind of concepts
|
|
#### Policies
|
|
Policies consist of the potential action made available through mechanisms. The action taken is expected to be the
|
|
result of a conditional determination of the past state.
|
|
|
|
While executed the same, the modeller can approach policies dependent on the availability of a mechanism to a population.
|
|
|
|
- ***Control Policy***
|
|
When the controlling or deploying entity has the ability to act in order to affect some aspect of the system, this is a
|
|
control policy.
|
|
- ***User Policy*** model agent behaviors in reaction to state variables and exogenous variables. The resulted user
|
|
action will become an input to PSUs. Note that user behaviors should not directly update value of state variables.
|
|
The action taken, as well as the potential to act, through a mechanism is a behavior. -->
|
|
|
|
The general structure of a policy function is:
|
|
```python
|
|
def policy_function_1(_params, substep, sH, s):
|
|
...
|
|
return {'signal_1': value_1, ..., 'signal_N': value_N}
|
|
```
|
|
Parameters:
|
|
* **_params** : _dict_ - [System parameters](/4oJ_GT6zRWW8AO3yMhFKrg)
|
|
* **substep** : _int_ - Current [substep](#Substep)
|
|
* **sH** : _list[list[dict_]] - Historical values of all state variables for the simulation. See
|
|
[Historical State Access](/smiyQTnATtC9xPwvF8KbBQ) for details
|
|
* **s** : _dict_ - Current state of the system, where the `dict_keys` are the names of the state variables and the
|
|
`dict_values` are their current values.
|
|
|
|
Return:
|
|
* _dict_ of signals to be passed to the state update functions in the same
|
|
[Partial State Update Block](#Partial-State-Update-Blocks)
|
|
|
|
Policy functions should not modify any of the parameters passed to it, as those are mutable Python objects that cadCAD
|
|
relies on in order to run the simulation according to the specifications.
|
|
|
|
At each [Partial State Update Block](#Partial-State-Update-Blocks) (PSUB), the `dicts` returned by all policy functions
|
|
within that PSUB dictionaries are aggregated into a single `dict` using an initial reduction function
|
|
(a key-wise operation, default: `dic1['keyA'] + dic2['keyA']`) and optional subsequent map functions. The resulting
|
|
aggregated `dict` is then passed as the `_input` parameter to the state update functions in that PSUB. For more
|
|
information on how to modify the aggregation method, see [Policy Aggregation](/63k2ncjITuqOPCUHzK7Viw).
|
|
|
|
### Partial State Update Blocks
|
|
|
|
A **Partial State Update Block** (PSUB) is a set of State Update Functions and Policy Functions such that State Update
|
|
Functions in the set are independent from each other and Policies in the set are independent from each other and from
|
|
the State Update Functions in the set. In other words, if a state variable is updated in a PSUB, its new value cannot
|
|
impact the State Update Functions and Policy Functions in that PSUB - only those in the next PSUB.
|
|
|
|

|
|
|
|
Partial State Update Blocks are passed to `append_configs` as a List of Python `dicts` where the `dict_keys` are named
|
|
`"policies"` and `"variables"` and the values are also Python `dicts` where the keys are the names of the policy and
|
|
state update functions and the values are the functions.
|
|
|
|
```python
|
|
PSUBs = [
|
|
{
|
|
"policies": {
|
|
"b_1": policy_function_1,
|
|
...
|
|
"b_J": policy_function_J
|
|
},
|
|
"variables": {
|
|
"s_1": state_update_function_1,
|
|
...
|
|
"s_K": state_update_function_K
|
|
}
|
|
}, #PSUB_1,
|
|
{...}, #PSUB_2,
|
|
...
|
|
{...} #PSUB_M
|
|
]
|
|
|
|
append_configs(
|
|
...
|
|
partial_state_update_blocks = PSUBs,
|
|
...
|
|
)
|
|
|
|
```
|
|
|
|
#### Substep
|
|
At each timestep, cadCAD iterates over the `partial_state_update_blocks` list. For each Partial State Update Block,
|
|
cadCAD returns a record containing the state of the system at the end of that PSUB. We refer to that subdivision of a
|
|
timestep as a `substep`.
|
|
|
|
## Result Dataset
|
|
|
|
cadCAD returns a dataset containing the evolution of the state variables defined by the user over time, with three `int`
|
|
indexes:
|
|
* `run` - id of the [run](#N-Number-of-Runs)
|
|
* `timestep` - discrete unit of time (the total number of timesteps is defined by the user in the
|
|
[T Simulation Parameter](#T-Simulation-Length))
|
|
* `substep` - subdivision of timestep (the number of [substeps](#Substeps) is the same as the number of Partial State
|
|
Update Blocks)
|
|
|
|
Therefore, the total number of records in the resulting dataset is `N` x `T` x `len(partial_state_update_blocks)`
|
|
|
|
#### [System Simulation Execution](Simulation_Execution.md)
|