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

Simulator is 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, sample_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. If block declares any entity classes, this must also give how many instances each has, under a key equal to the entity’s name – so a block declaring Entity("firm") needs a "firm" key here.

  • 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

  • sample_count (int) – The number of independent trajectories to simulate. This is the replication axis of the histories, not a population: the trajectories do not interact, so a cross-sectional statistic taken over it is a Monte Carlo estimate whose error falls as sample_count rises.

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

clear_history()

Clears the histories.

A variable’s history carries the period axis, then the sample axis, then its entity axes: (T_sim, sample_count) for an axis-free variable and (T_sim, sample_count, size) for an attribute of a class with size instances. A block declaring no entity therefore keeps the (T_sim, sample_count) histories it has always had.

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.

Restarts the sample path: the shocks are re-grounded on a generator freshly seeded from self.seed, and the initial distributions are pointed at the same one. Called on every initialize_sim(), so a re-run of one simulator repeats its draws.

sim_birth(which_agents)

Makes new agents for the simulation.

Parameters:

which_agents (np.array(Bool)) – Boolean array of size self.sample_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.

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

  • rng (Generator | None) – Random number generator to draw from. Each shock is pointed at it before the draw, as is every distribution the shock draws through, so the draw is reproducible from the generator’s seed. Omitted, each shock draws from the generator it already holds.

  • 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},
    sample_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},
    sample_count=1000,
    T_sim=50,
)

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