reno.pymc#
Functions for translating a system dynamics model into a PyMC equivalent.
Because an SDM run here is a sequential simulation, the core enabling
functionality is the scan function in PyTensor:
https://pytensor.readthedocs.io/en/latest/library/scan.html
An example for how scan ties into PyMC:
https://www.pymc.io/projects/examples/en/latest/time_series/Time_Series_Generative_Graph.html
The output generated by these translations follows a template that looks something like:
def step_function(*all_stocks_flows_variables):
# this is generated by pt_sim_step() or pt_sim_step_str()
s, ... = all_stocks_flows_variables
# difference/update equations for each stock/flow/variable
s_next = s + ...
...
# return all updated values (pymc/pytensor has specific boilerplate to use)
return [s_next, ...], ...
with pymc.Model() as model:
# define all pymc distributions/variables and initial stock/flow values
# e.g. for stock "s":
s_init = pm.Deterministic("s_init", ...)
...
# run the scan function to generate full sequence data for simulation
[s_seq, ...] = pytensor.scan(fn=step_function, [s_init, ...], ...)
# create pymc containers for the full sequence data (this way they get
# added into any output arviz datasets from pymc sampling operations)
s = pm.Deterministic("s", pt.concatenate([s_init, s_seq], ...)
Reno’s underlying math framework works fairly similarly to PyTensor, (symbolic
tree and numpy-ish) so translation is done by calling the pt() or pt_str()
function that every EquationPart has, which returns the PyTensor equivalent of
that operation/thing.
Note that there are functions to directly create pymc models/operations and functions to create strings of PyMC/PyTensor code (suffixed with _str). These exist for two reasons:
- Debugging - figuring out errors or issues with PyMC models can be an adventure,
and doubly so if you can’t directly see or modify the model code.
to_pymc_model_str()should _in theory_ generate a string of code equivalent to what’s used into_pymc_model(), but can be edited and run separately as needed to test changes.
- Flexibility - if trying to do something beyond what Reno’s PyMC naive translation
can support, the string code output gives a starting point that can be directly incorporated or modified to do more advanced things.
Functions
|
Pytensor scan target functions are called with a very specific ordering of function arguments (see https://pytensor.readthedocs.io/en/latest/library/scan.html). |
|
Get a dictionary of all tracked references in the model used in historical values, and get the associated tap list for each. |
|
Returns a target function for pytensor scan, this equates to a single step in the system dynamics model simulation. |
Get the string of code for the imports needed for |
|
|
Construct a string of python code for the step function for this model that could be used by a pytensor scan operation. |
Get the string of code for the imports needed for |
|
|
Take the set of arguments passed by pytensor to a target scan function, and turn it into a dictionary for passing into reno math components' pt() calls. |
|
Generate a pymc model for bayesian analysis of this system dynamics model. |
|
Construct a string of python code to create a pymc model wrapping this system dynamics model. |