cadCAD/documentation/sys_model_config.md

221 lines
8.4 KiB
Markdown

System Model Configuration
==
#### Introduction
Given System Model Configurations, cadCAD produces system event datasets that conform to specified system metrics. Each
event / record is of [Enogenous State variables](link) produced by user defined [Partial State Updates](link) (PSU /
functions that update state); A sequence of event / record subsets that comprises the resulting system event dataset is
produced by a [Partial State Update Block](link) (PSUB / a Tensor Field for which State, Policy, and Time are dimensions
and PSU functions are values).
A **System Model Configuration** is comprised of a simulation configuration, initial endogenous states, Partial State
Update Blocks, environmental process, and a user defined policy aggregation function.
Execution:
#### Simulation Properties
###### System Metrics
The following system metrics determine the size of resulting system event datasets:
* `run` - the number of simulations in the resulting dataset
* `timestep` - the number of timestamps in the resulting dataset
* `substep` - the number of PSUs per `timestep` / within PSUBS
* Number of events / records: `run` x `timestep` x `substep`
###### Simulation Configuration
For the following dictionary, `T` is assigned a `timestep` range, `N` is assigned the number of simulation runs, and
`params` is assigned the [**Parameter Sweep**](link) dictionary.
```python
from cadCAD.configuration.utils import config_sim
sim_config = config_sim({
"N": 2,
"T": range(5),
"M": params, # Optional
})
```
#### Initial Endogenous States
**Enogenous State variables** are read-only variables defined to capture the shape and property of the network and
represent internal input and signal.
The PSUB tensor field is applied to the following states to produce a resulting system event
dataset.
```python
genesis_states = {
's1': 0.0,
's2': 0.0,
's3': 1.0,
'timestamp': '2018-10-01 15:16:24'
}
```
#### Partial State Update Block:
- ***Partial State Update Block(PSUB)*** ***(Define ?)*** Tensor Field for which State, Policy, Time are dimensions
and Partial State Update functions are values.
- ***Partial State Update (PSU)*** are user defined functions that encodes state updates and are executed in
a specified order PSUBs. PSUs update states given the most recent set of states and PSU policies.
- ***Mechanism*** ***(Define)***
The PSUBs is a list of PSU dictionaries of the structure within the code block below. PSUB elements (PSU dictionaries)
are listed / defined in order of `substeps` and **identity functions** (returning a previous state's value) are assigned
to unreferenced states within PSUs. The number of records produced produced per `timestep` is the number of `substeps`.
```python
partial_state_update_block = [
{
"policies": {
"b1": p1_psu1,
"b2": p2_psu1
},
"variables": {
"s1": s1_psu1,
"s2": s2_psu1
}
},
{
"policies": {
"b1": p1_psu2,
},
"variables": {
"s2": s2_psu2
}
},
{...}
]
```
*Notes:*
1. An identity function (returning the previous state value) is assigned to `s1` in the second PSU.
2. Currently the only names that need not correspond to the convention below are `'b1'` and `'b2'`.
#### Policies
- ***Policies*** ***(Define)*** When are policies behavior ?
- ***Behaviors*** 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.
Policies accept parameter sweep variables [see link] `_g` (`dict`), the most recent
`substep` integer, the state history[see link] (`sH`), the most recent state record `s` (`dict) as inputs and returns a
set of actions (`dict`).
Policy functions return dictionaries as actions. Policy functions provide access to parameter sweep variables [see link]
via dictionary `_g`.
```python
def p1_psu1(_g, substep, sH, s):
return {'policy1': 1}
def p2_psu1(_g, substep, sH, s):
return {'policy1': 1, 'policy2': 4}
```
For each PSU, multiple policy dictionaries are aggregated into a single dictionary to be imputted into
all state functions using an initial reduction function (default: `lambda a, b: a + b`) and optional subsequent map
functions.
Example Result: `{'policy1': 2, 'policy2': 4}`
#### State Updates
State update functions provide access to parameter sweep variables [see link] `_g` (`dict`), the most recent `substep`
integer, the state history[see link] (`sH`), the most recent state record as a dictionary (`s`), the policies of a
PSU (`_input`), and returns a tuple of the state variable's name and the resulting new value of the variable.
```python
def state_update(_g, substep, sH, s, _input):
...
return state, update
```
**Note:** Each state update function updates one state variable at a time. Changes to multiple state variables requires
separate state update functions. A generic example of a PSU is as follows.
* ##### Endogenous State Updates
They are only updated by PSUs and can be used as inputs to a PSUs.
```python
def s1_update(_g, substep, sH, s, _input):
x = _input['policy1'] + 1
return 's1', x
def s2_update(_g, substep, sH, s, _input):
x = _input['policy2']
return 's2', x
```
* ##### Exogenous State Updates
***Exogenous State variables*** ***(Review)*** are read-only variables that represent external input and signal. They
update endogenous states and are only updated by environmental processes. Exgoneous variables can be used
as an input to a PSU that impacts state variables. ***(Expand upon Exogenous state updates)***
```python
from datetime import timedelta
from cadCAD.configuration.utils import time_step
def es3_update(_g, substep, sH, s, _input):
x = ...
return 's3'
def es4_update(_g, substep, sH, s, _input):
x = ...
return 's4', x
def update_timestamp(_g, substep, sH, s, _input):
x = time_step(dt_str=s[y], dt_format='%Y-%m-%d %H:%M:%S', _timedelta=timedelta(days=0, minutes=0, seconds=1))
return 'timestamp', x
```
Exogenous state update functions (`es3_update`, `es4_update` and `es5_update`) update once per timestamp and should be
included as a part of the first PSU in the PSUB.
```python
partial_state_update_block['psu1']['variables']['s3'] = es3_update
partial_state_update_block['psu1']['variables']['s4'] = es4_update
partial_state_update_block['psu1']['variables']['timestamp'] = update_timestamp
```
* #### Environmental Process
- ***Environmental processes*** model external changes that directly impact exogenous states at given specific
conditions such as market shocks at specific timestamps.
Create a dictionary like `env_processes` below for which the keys are exogenous states and the values are lists of user
defined **Environment Update** functions to be composed (e.g. `[f(params, x), g(params, x)]` becomes
`f(params, g(params, x))`).
Environment Updates accept the [**Parameter Sweep**](link) dictionary `params` and a state as a result of a PSU.
```python
def env_update(params, state):
. . .
return updated_state
# OR
env_update = lambda params, state: state + 5
```
The `env_trigger` function is used to apply composed environment update functions to a list of specific exogenous state
update results. `env_trigger` accepts the total number of `substeps` for the simulation / `end_substep` and returns a
function accepting `trigger_field`, `trigger_vals`, and `funct_list`.
In the following example functions are used to add `5` to every `s3` update and assign `10` to `s4` at
`timestamp`s `'2018-10-01 15:16:25'`, `'2018-10-01 15:16:27'`, and `'2018-10-01 15:16:29'`.
```python
from cadCAD.configuration.utils import env_trigger
trigger_timestamps = ['2018-10-01 15:16:25', '2018-10-01 15:16:27', '2018-10-01 15:16:29']
env_processes = {
"s3": [lambda params, x: x + 5],
"s4": env_trigger(end_substep=3)(
trigger_field='timestamp', trigger_vals=trigger_timestamps, funct_list=[lambda params, x: 10]
)
}
```
#### System Model Configuration
`append_configs`, stores a **System Model Configuration** to be (Executed)[url] as
simulations producing system event dataset(s)
```python
from cadCAD.configuration import append_configs
append_configs(
sim_configs=sim_config,
initial_state=genesis_states,
env_processes=env_processes,
partial_state_update_blocks=partial_state_update_block,
policy_ops=[lambda a, b: a + b]
)
```
#### [System Simulation Execution](link)