Simulation

This section contains the API documentation for simulation tools and analysis functions.

Monte Carlo Simulation

The simulation module provides Monte Carlo simulation engines for block-based models.

Simulator

The base Monte Carlo simulation engine. It makes no assumptions about aging or mortality; demographic features are expressed declaratively as blocks (see the mortality example below).

class skagent.simulation.monte_carlo.Simulator(calibration, block, dr, initial, seed=0, agent_count=1, T_sim=10)

Bases: object

Base class for Monte Carlo simulation engines.

Provides common functionality for simulation including: - RNG management and seeding - State variable tracking - History management - Simulation loop structure

Parameters:
  • calibration (Mapping[str, Any]) – Model calibration parameters

  • block (Union[DBlock, RBlock]) – Has shocks, dynamics, and rewards

  • dr (Mapping[str, Callable]) – Decision rules for control variables

  • initial (dict) – Initial state distributions

  • seed (int) – A seed for this instance’s random number generator

  • agent_count (int) – The number of agents to simulate

  • T_sim (int) – The number of periods to simulate

clear_history()

Clears the histories.

initialize_sim()

Prepares for a new simulation. Resets the internal random number generator, makes initial states for all agents, clears histories of tracked variables.

reset_rng()

Reset the random number generator for this type.

sim_birth(which_agents)

Makes new agents for the simulation.

Parameters:

which_agents (np.array(Bool)) – Boolean array of size self.agent_count indicating which agents should be “born”.

sim_one_period()

Simulates one period for this type. Subclasses may override to add mortality/aging logic.

simulate(sim_periods=None)

Simulates this agent type for a given number of periods. Defaults to self.T_sim if no input.

Parameters:

sim_periods (int, optional) – Number of periods to simulate.

Returns:

history – The history tracked during the simulation.

Return type:

dict

state_vars = []

Note

MonteCarloSimulator is an alias for Simulator, kept for backward compatibility. The examples below use the alias because it is what skagent.__init__ exports.

Simulation Utility Functions

Drawing Shocks

skagent.simulation.monte_carlo.draw_shocks(shocks, conditions=(), n=None, rng=None)

Draw from each shock distribution values, subject to given conditions.

Parameters:
  • Mapping[str (shocks) – A dictionary-like mapping from shock names to distributions from which to draw

  • Distribution] – A dictionary-like mapping from shock names to distributions from which to draw

  • conditions (Sequence[int]) – An array of conditions, one for each agent. Typically these will be agent ages. # TODO: generalize this to wider range of inputs.

  • n (int (optional)) – Number of draws to do. An alternative to a conditions sequence.

  • rng (Generator | None) – Random number generator to use for drawing. If provided, will be used for distributions that support it.

  • shocks (Mapping[str, Distribution])

Returns:

draws – A mapping from shock names to drawn shock values.

Return type:

Mapping[str, Sequence]

Example Usage

Basic Simulation

import skagent as ska
from skagent.models.consumer import consumption_block, calibration

# Set up decision rules (simplified example)
dr = {"c": lambda m: 0.9 * m}

# Initialize simulation
simulator = ska.MonteCarloSimulator(
    calibration=calibration,
    block=consumption_block,
    dr=dr,
    initial={"k": 1.0, "p": 1.0},
    agent_count=1000,
    T_sim=50,
)

# Run simulation
simulator.initialize_sim()
results = simulator.simulate()

Simulation with Mortality

Mortality is expressed declaratively as a block rather than baked into the simulator. The mortality_block in skagent.models.consumer resets an agent’s state to a newborn draw whenever the live shock is zero, so the base MonteCarloSimulator is sufficient:

import skagent as ska
from skagent.distributions import Lognormal
from skagent.models.consumer import calibration, mortal_cons_problem

simulator = ska.MonteCarloSimulator(
    calibration=calibration,
    block=mortal_cons_problem,
    dr={"c": lambda m: m / 3},
    # Initial states may be scalars or distributions. Lognormal takes the
    # distribution's mean and standard deviation in levels; newborns draw
    # their starting capital from it.
    initial={"k": Lognormal(1.0, 0.5), "p": 1.0, "age": 0},
    agent_count=1000,
    T_sim=50,
)

simulator.initialize_sim()
results = simulator.simulate()