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:
objectBase 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 rewardsdr (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 everyinitialize_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.
- 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()