Model
agent-based modeling, system dynamics, bptk, bptk-py, python, business prototyping
Model
Model Constructor
Model(starttime=0, stoptime=0, dt=1, name=’’, scheduler=None, data_collector=None)
This is the main agent base / System dynamics / Hybrid model class
It can run manually generated SD models, AB Models or define hybrid models.
Parameters
name – String. Name of the model.
scheduler – Scheduler. Scheduler object (e.g. simultaneousScheduler). This is configurable, so that you can add your own scheduling algorithms.
data_collector – DataCollector Instance of DataCollector. This is configurable, so that you can add your own data collection algorithms.
Model.add_equation
add_equation(equation, lambda_method)
Add an equation by name, computed by a function of the time. This is how a hand-written hybrid model gives its System Dynamics side an equation without building it from stocks, flows and converters.
Parameters
equation – String. The name of the equation. If the model already has an equation of that name, the new one replaces it and a warning is logged.
lambda_method – Callable. A function of the time
tthat returns the equation’s value, for examplelambda t: 2 * t.
Model.agent
agent(agent_id)
Get an agent by ID.
Retrieve one agent by its ID
Parameters
agent_id – Integer. ID of agent that is to be retrieved.
Returns
Agent object
Model.agent_count
agent_count(agent_type) Get count of agents of a given type.
Parameters
agent_type – String. Agent type to get count for
Returns
Integer. Number of agents (Integer)
Model.agent_count_per_state
agent_count_per_state(agent_type, state)
Get number of agents in a specific state
Parameters
agent_type – String. Agent type to get count for
state – String. The state of agents to get count for
Returns
Integer.
Model.agent_ids
agent_ids(agent_type)
Get agent IDs.
Retrieve agent IDs for all agents of type agent_type.
Parameters
agent_type – String. Agent type to get IDs for
Returns
List of IDs
Model.begin_episode
begin_episode(episode_no)
Called at beginning of an episode.
When running a simulation repeatedly in episodes (e.g. because you are training the model using reinforcement learning), this method is called by the framework to allow tidy up at the beginning of an episode, e.g. a “soft” reset of the simulation.
The default implementation calls begin_episode on each agent.
Parameters
episode_no – Integer. The number of the episode
Model.begin_round
begin_round(time, sim_round, step)
Called at the beginning of a simulation round.
Should be called by the Scheduler at the beginning of each round, before the agents act methods are called. Add any logic here that is needed to update dynamic properties.
Parameters
time – Integer. The current timestep of the simulation, i.e.(round+step*dt)
sim_round – Integer The current round of the simulation.
step – Integer. The step number of round
Model.biflow
biflow(name) Create a System Dynamics biflow
Parameters
name – String. Name of the biflow
Returns
A Biflow object
Model.broadcast_event
broadcast_event(agent_type, event_factory)
Broadcast an event to all agents of a particular agent_type
Parameters
agent_type – String. Agent type that is to receive the event
num_agents – Integer. Number of random agents that should receive the event
event_factory – Function. The factory (typicalla a lambda function) that generates the desired event for a given target agent type. The function receives the agent_id as its parameter.
Model.configure
configure(config)
Called to configure the model using a dictionary. This method is called by the framework if you instantiate models from scenario files. But you can also call the method directly.
It replaces the agents of an earlier configuration, together with the events still queued for them, so a model can be configured and run again.
Parameters
config – Dict. Dictionary containing the config: {“runspecs”:
,”properties”: ,”agents”: - }.
Model.constant
constant(name)
Returns a Constant object with the given name - if a Constant with the given name already exists within the model, this one is returned. Else a new Constant object is created, stored and returned.
Parameters
name – String. Name of the constant
Returns: Constant.
A Constant object
Model.converter
converter(name)
Returns a Converter object with the given name - if a Converter with the given name already exists within the model, this one is returned, else a new Converter object is created, stored and returned.
Parameters
name – String. Name of the converter
Returns
A Converter object
Model.create_agent
create_agent(agent_type, agent_properties) Create one agent of the given type and with the given properties.
Internally this method then uses the registered agent factories to actually create an agent.
Parameters
agent_type – String. Type of agent
agent_properties – Dict. The properties to initialize the agent with.
Model.create_agents
create_agents(agent_spec)
Create agents according to the agent specificaction.
The agent specification is a dictionary containing the agent name and properties. Internally, this method then uses the registered agent factories to actually create the agents.
Parameters
agent_spec – Dict. Specification of an agent using a dictionary with format {“name”:
, “count”: }
Model.delete_agent
delete_agent(agent_id)
Remove one agent from the model, while it runs or before.
Parameters
agent_id – Integer. The id of the agent to remove.
Model.delete_agents
delete_agents(agent_ids)
Remove several agents from the model at once.
Parameters
agent_ids – List. The ids of the agents to remove.
Model.end_episode
end_episode(episode_no)
Called at the end of an episode.
When running a simulation repeatedly in episodes, this method is called by the framework to allow tidy up at the end of an episode.
The default implementation calls end_episode on each agent.
Parameters
episode_no – Integer. The number of the episode
Model.end_round
end_round(time, sim_round, step)
Called at end of a simulation round.
Should be called by the Scheduler at the end of each round, before the agents act methods are called. Add any logic here that is needed to update dynamic properties.
Parameters
time – Integer. The current timestep of the simulation, i.e.(round+step*dt)
sim_round – Integer The current round of the simulation.
step – Integer. The step number of round
Model.enqueue_event
enqueue_event(event)
Called by the framework to enqueue events.
In general you don’t need to override this method or call it directly.
Parameters
event – Event. Instance of the event.
Model.equation_prefix
property equation_prefix()
An id that is unique within this model that can be used to generate unique equation names.
This method is useful when auto-generating equations.
Returns
Integer. An id that is unique within the model.
Model.evaluate_equation
evaluate_equation(name, t)
Evaluate an System Dynamics element’s equation at timestep t.
Parameters
name – String. Name of the equation.
t – Float. Timestep to evaluate for
Return: Float
The value of the equation at time t.
Model.flow
flow(name)
Returns a Flow object with the given name - if a Flow with the given name already exists within the model, this one is returned, else a new Flow object is created, stored and returned.
Parameters
name – String. Name of the flow
Returns
A Flow object
Model.function
function(name, fn, elementwise=True)
Returns a Lambda function that wraps the function fn. A function of that name defined earlier is replaced, and the equations that call it compute with the new one.
The document User Defined Functions illustrates how such functions can be used.
Parameters
name – String. Name of the function.
fn – Function A function that will be used within a SD DSL model. The function must accept at least a model parameter and a time t parameter.
elementwise – Boolean (Default=True). What an arrayed argument means.
Truecalls the function once per index, so the result is an array of the same shape - the rule every operator follows.Falsehands the whole array over instead: a list for an unnamed array, a dict keyed by the labels for a named one, nested for a matrix, and the result is a single value. The element-wise form runs on the Rust engine.elementwise=Falsedoes not: a run that asks for the Rust backend raisesRustBackendError, and a run that does not stays on the Python engine.
Returns: A function which wraps the user defined function for use within SD DSL models.
Model.get_property
get_property(name)
Get a property of the model by name.
The value of the model properties can also be accessed directly as a model attribute, i.e. as self.
Parameters
name – String. Name of property
Returns
Dictionary for property
Model.get_property_value
get_property_value(name) Get a property of the model by name.
The value of the model properties can also be accessed directly as a model attribute, i.e. as self.
Parameters
name – String. Name of property
Returns
Value of the property.
Model.get_random_integer
static get_random_integer(min_value, max_value)
A random integer within bounds
This method is useful for simulating random behaviour.
Parameters
min_value – Integer. Min value for random integer
max_value – Integer. max value for random integer
Returns
Random integer.
Model.instantiate_model
instantiate_model()
Set properties during model initialization.
This method does nothing in the parent class and can be overriden in child classes. It is called by the frame directly after the model is instantiated.
Implement this method in your model to perform any kind of initialization you may need. Typically you would register your agent factories hier and set up model properties.
Model.next_agent
next_agent(agent_type, state)
Get the next agent by type and state.
Runs through the internal agent store and retrieves the first agent that matches in type and state.
Parameters
agent_type – String. Agent type
state – String. State the agent is in
Returns
The first agent object that matches the criterian None otherwise.
Model.plot_lookup
plot_lookup(lookup_names, config=None, format=“plot”, matplotlib_rc_settings=None)
Plots lookup functions for the given list of lookup names.
Parameters
lookup_names – String or List. A name or list of names of lookup functions. The list can be passed as a Python list or a comma separated string.
format – String (Default “plot”). What to return: “plot” draws the diagram and returns nothing, “axes” returns the matplotlib Axes, “df” returns the underlying dataframe. “plot” relies on the notebook displaying the figure as a side effect, which only Jupyter’s inline backend does — in marimo, and in a plain script, use “axes”.
matplotlib_rc_settings – Dict (Default None). matplotlib settings for this one plot, laid over the central plotting configuration rather than replacing it.
Model.random_agents
random_agents(agent_type, num_agents)
Retreive a number of random agents
Parameters
agent_type – String. Type of agent to retrieve.
num_agents – Number of agents of this type to retreive.
Returns
List of agent IDs. The number of IDs might be less then num_agents if fewer agents are available.
Model.random_events
random_events(agent_type, num_agents, event_factory)
Distribute events to a number of random agents
Parameters
agent_type – String. Agent type that is to receive the event
num_agents – Integer. Number of random agents that should receive the event
event_factory – Function. The factory (typicalla a lambda function) that generates the desired event for a given target agent type. The function receives the agent_id as its parameter.
Model.register_agent_factory
register_agent_factory(agent_type, agent_factory)
Register an agent factory.
Agent factories are used at run-time to populate the model with agents. This method is used to register an agent factory, which is typically just a lambda function which returns an agent.
Parameters
agent_type – String. Type of agent to register
agent_factory – Function. Function that returns an agent given an id and the model. Typically a lambda, but not limited to that. Input: agent_id, model -> Output: Agent of agent_type
Model.reset
reset()
Reset the model.
Clear out all agents, agent and event statistics and resets the cache of SD equations.
The agent factories are kept though, so you could directly reconfigure the model using the configure method.
Model.reset_cache
reset_cache()
Reset cache of all System Dynamics equations and call the reset_cache method on all agents. Clear the agent statistics.
Model.run
run(show_progress_widget=False, collect_data=True)
Run the simulation.
This esssentially just calls the run method of the models scheduler. Only relevant for agent-based models, does nothing on pure SD DSL models.
Parameters
show_progress_widget – Boolean (Default=False). If True, shows a progress bar while the simulation runs. It is built on tqdm, so it works in a terminal, in marimo and in Jupyter alike.
collect_data – Boolean (Default=True). If True, data is automatically collected in the models DataCollector, e.g. for plotting the model behaviour. If you are training the model e.g. using reinforcement learning, it might be useful to turn data collection of.
Model.run_specs
run_specs(starttime, stoptime, dt)
Configure the runspecs of the model.
Parameters
starttime – Integer. The starttime of the model.
stoptime – Integer. The stoptime of the model.
dt – The dt of the model.
Model.run_step
run_step(step, show_progress_widget=False, collect_data=True)
Run a simulation step.
This esssentially just calls the run method of the models scheduler.
Parameters
step – Int. The step to run
show_progress_widget – Boolean (Default=False). If True, shows a progress bar while the simulation runs. It is built on tqdm, so it works in a terminal, in marimo and in Jupyter alike.
collect_data – Boolean (Default=True). If True, data is automatically collected in the models DataCollector, e.g. for plotting the model behaviour. If you are training the model e.g. using reinforcement learning, it might be useful to turn data collection off.
Model.set_property
set_property(name, property_spec)
Configure a property of the model itself, as opposed to the properties of individual agents.
Properties set via this mechanism are stored internally in a dictionary of properties, the value of the property directly can be access directly as an object attribute, i.e. as self.
A property set this way is not collected by the standard data collector and cannot be plotted directly - collect_agent_statistics sees the agents, not the model. Reading it back through get_property, or as an attribute, is what it is for.
Parameters
name – String. Name of the property to set.
property_spec – Dict. Specification of property: {“type”:<type of property, free form string>,”value”:
}. In principle the property can store any kind of value, the type is currently not evaluated by the framework
Model.set_property_value
set_property_value(name, value)
Set the value of a model property by name.
Model properties can also be set directly via the model attributes, i.e. as self.
Parameters
name – String. Name of property.
value – Any. Value of the property to set.
Model.set_scenario_manager
set_scenario_manager(scenario_manager)
Set the name of the scenario manager that is handling this model. Used by the bptk class during scenario registration.
Parameters
scenario_manager – String. Name of the scenario manager.
Model.simulate
simulate(equations, backend=“python”)
Run the model once, without a scenario manager, and return the results.
Parameters
equations – List. The equations to include in the results.
backend – String (Default “python”).
"python"or"rust".Returns
A Pandas DataFrame with the time as index (named
"t") and one column per equation.Raises
RustBackendErrorifbackend="rust"was asked for and the model cannot run on the engine. It is not computed on the Python engine instead.
Model.statistics
statistics()
Get statistics from DataCollector.
Returns
The DataCollector used to collect the simulation statistics.
Model.to_json
to_json()
Serialise the model to the JSON format the Rust engine loads.
You rarely need to call this — run_scenarios(backend="rust") does it for you. It is useful when you want to know whether a model can run on the Rust engine, because this is where the answer is decided: it raises ValueError for anything the engine cannot express, naming what it tripped over.
Returns
A JSON string.
Raises
ValueErrorfor anything the engine cannot express - a user-defined function registered withelementwise=False, or one in a model that also has agents. An ordinary user-defined function serialises: it becomes a node the engine answers by calling back into Python. In a run, thatValueErrorbecomes aRustBackendError; see Execution Backends.
Model.stock
stock(name)
Returns a Stock object with the given name - if a Stock with the given name already exists within the model, this one is returned, else a new Stock object is created, stored and returned.
Parameters
name – String. Name of the stock.
Returns
The Stock object.