distributions

distributions

Define random-number-safe distributions.

Classes

Name Description
Dist Base class for tracking one random number generator associated with one distribution,
Dists Class for managing a collection of Dist objects
multi_random A class for holding two or more ss.random() distributions, and generating
scale_types Define how distributions scale

Dist

distributions.Dist(
    self,
    dist=None,
    distname=None,
    name=None,
    unit=None,
    seed=None,
    offset=None,
    strict=True,
    auto=True,
    sim=None,
    module=None,
    mock=False,
    debug=False,
    **kwargs,
)

Base class for tracking one random number generator associated with one distribution, i.e. one decision per timestep.

See ss.dist_list for a full list of supported distributions. Parameter inputs tend to follow SciPy’s, rather than NumPy’s, definitions (although in most cases they’re the same). See also ss.distributions.scale_types for more information on how different distributions scale by time.

Note: by default, ss.Dist is initialized with an ss.Sim object to ensure random number reproducibility. You can override this with either ss.Dist(strict=False) on creation, or dist.init(force=True) after creation.

Although it’s possible in theory to define a custom distribution (i.e., not one from NumPy or SciPy), in practice this is difficult. The distribution needs to have both a way to return random variates (easy), as well as the probability point function (inverse CDF). In addition, the distribution must be able to take a NumPy RNG as its bit generator. It’s easier to just use a default Dist (e.g., ss.random()), and then take its output as input (i.e., quantiles) for whatever custom distribution you want to create.

Parameters

Name Type Description Default
dist rv_generic optional; a scipy.stats distribution (frozen or not) to get the ppf from None
distname str the name for this class of distribution (e.g. “uniform”) None
name str the name for this particular distribution (e.g. “age_at_death”) None
unit str/ss.TimePar if provided, convert the output of the distribution to a timepar (e.g. rate or duration); can also be inferred from distribution parameters (see examples below) None
seed int the user-chosen random seed (e.g. 3) None
offset int the seed offset; will be automatically assigned (based on hashing the name) if None None
strict bool if True, require initialization and invalidate after each call to rvs() True
auto bool whether to auto-reset the state after each draw True
sim Sim usually determined on initialization; the sim to use as input to callable parameters None
module Module usually determined on initialization; the module to use as input to callable parameters None
mock int if provided, then initialize with a mock Sim object (of size mock) for debugging purposes False
debug bool print out additional detail False
kwargs dict parameters of the distribution {}

Examples:

# Create a Bernoulli distribution
p_death = ss.bernoulli(p=0.1).init(force=True)
p_death.rvs(50) # Create 50 draws

# Create a normal distribution that's also a timepar
dur_infection = ss.normal(loc=12, scale=2, unit='years')
dur_infection = ss.years(ss.normal(loc=12, scale=2)) # Same as above
dur_infection = ss.normal(loc=ss.years(12), scale=2)) # Same as above
dur_infection = ss.normal(loc=ss.years(12), scale=ss.months(24)) # Same as above, perform time unit conversion internally
dur_infection.init(force=True).plot_hist() # Show results

# Create a distribution manually
dist = ss.Dist(dist=sps.norm, loc=3).init(force=True)
dist.rvs(10) # Return 10 normally distributed random numbers

Attributes

Name Description
state Get the current state
state_int Get the integer corresponding to the current state

Methods

Name Description
call_par Check if this parameter needs to be called to be turned into an array; not for the user
call_pars Check if any parameters need to be called to be turned into arrays; not for the user
convert_callable Method to handle how callable parameters are processed; not for the user
convert_timepars Convert time parameters (durations and rates) to scalars
disp Return full display of object
get_state Return a copy of the state
init Calculate the starting seed and create the RNG
jump Advance the RNG, e.g. to timestep “to”, by jumping
jump_dt Automatically jump on the next value of dt
link_module Shortcut for linking the module
link_sim Shortcut for linking the sim, only overwriting an existing one if overwrite=True; not for the user
make_history Store the current state in history
make_rvs Return default random numbers for scalar parameters; not for the user
mock Create a distribution using a mock sim for testing purposes
plot_hist Plot the current state of the RNG as a histogram
ppf Return default random numbers for array parameters; not for the user
process_dist Ensure the distribution works; not for the user
process_pars Ensure the supplied dist and parameters are valid, and initialize them; not for the user
process_seed Obtain the seed offset by hashing the path to this distribution; not for the user
process_size Handle an input of either size or UIDs and calculate size, UIDs, and slots; not for the user
rand Simple way to get simple random numbers
randround Round the values up or down to an integer stochastically; usually called via dist.rvs(round=True)
reset Restore state, allowing the same numbers to be resampled
rvs Get random variates – use this!
set Set (change) the distribution type, or one or more parameters of the distribution
show_state Show the state of the object
shrink Shrink the size of the module for saving to disk
sync_pars Perform any necessary synchronizations or transformations on distribution parameters; not for the user
to_json Return a dictionary representation of the Dist
update_dist_pars Update SciPy distribution parameters; not for the user
validate_pars Check if parameters are valid; only used for non-SciPy distributions
call_par
distributions.Dist.call_par(key, val, size, uids)

Check if this parameter needs to be called to be turned into an array; not for the user

call_pars
distributions.Dist.call_pars()

Check if any parameters need to be called to be turned into arrays; not for the user

convert_callable
distributions.Dist.convert_callable(parkey, func, size, uids)

Method to handle how callable parameters are processed; not for the user

convert_timepars
distributions.Dist.convert_timepars()

Convert time parameters (durations and rates) to scalars

This function converts time parameters into bare numbers that will be returned by rvs() depending on the timestep of the parent module for this Dist. The conversion for these types is

  • Durations are divided by dt (so the result will be a number of timesteps)
  • Rates are multiplied by dt (so the result will be a number of events, or else the equivalent multiplicate value for the timestep)
disp
distributions.Dist.disp()

Return full display of object

get_state
distributions.Dist.get_state()

Return a copy of the state

init
distributions.Dist.init(
    trace=None,
    seed=None,
    module=None,
    sim=None,
    slots=None,
    force=False,
)

Calculate the starting seed and create the RNG

Typically this is not invoked by the user, although the user can call it with force=True to initialize a distribution manually independently of a ss.Sim object (which is equivalent to setting strict=False when creating the dist).

Parameters
Name Type Description Default
trace str the distribution’s location within the sim None
seed int the base random number seed that other random number seeds will be generated from None
module ss.Module the parent module None
sim ss.Sim the parent sim None
slots array the agent slots of the parent sim None
force bool whether to skip validation (if the dist has already been initialized, and if any inputs are None) False
jump
distributions.Dist.jump(to=None, delta=1, force=False)

Advance the RNG, e.g. to timestep “to”, by jumping

jump_dt
distributions.Dist.jump_dt(ti=None, force=False)

Automatically jump on the next value of dt

Parameters
Name Type Description Default
ti int if specified, jump to this timestep (default: current module timestep plus one) None
make_history
distributions.Dist.make_history(reset=False)

Store the current state in history

make_rvs
distributions.Dist.make_rvs()

Return default random numbers for scalar parameters; not for the user

mock
distributions.Dist.mock(trace='mock', **kwargs)

Create a distribution using a mock sim for testing purposes

Parameters
Name Type Description Default
trace str the “trace” of the distribution (normally, where it would be located in the sim) 'mock'
**kwargs dict passed to ss.mock_sim() as well as ss.mock_module() (typically time args, e.g. dt) {}

Example:

dist = ss.normal(3, 2, unit='years').mock(dt=ss.days(1))
dist.rvs(10)
plot_hist
distributions.Dist.plot_hist(n=1000, bins=None, fig_kw=None, hist_kw=None)

Plot the current state of the RNG as a histogram

ppf
distributions.Dist.ppf(rands)

Return default random numbers for array parameters; not for the user

process_dist
distributions.Dist.process_dist()

Ensure the distribution works; not for the user

process_pars
distributions.Dist.process_pars(call=True)

Ensure the supplied dist and parameters are valid, and initialize them; not for the user

process_seed
distributions.Dist.process_seed(trace=None, seed=None)

Obtain the seed offset by hashing the path to this distribution; not for the user

process_size
distributions.Dist.process_size(n=1)

Handle an input of either size or UIDs and calculate size, UIDs, and slots; not for the user

rand
distributions.Dist.rand(size)

Simple way to get simple random numbers

randround
distributions.Dist.randround(rvs)

Round the values up or down to an integer stochastically; usually called via dist.rvs(round=True)

reset
distributions.Dist.reset(state=0)

Restore state, allowing the same numbers to be resampled

Use 0 for original state, -1 for most recent state.

Example:

dist = ss.random(seed=5).init()
r1 = dist(5)
r2 = dist(5)
dist.reset(-1)
r3 = dist(5)
dist.reset(0)
r4 = dist(5)
assert all(r1 != r2)
assert all(r2 == r3)
assert all(r4 == r1)
rvs
distributions.Dist.rvs(n=1, round=False, reset=False)

Get random variates – use this!

Parameters
Name Type Description Default
n int / tuple / arr if an int or tuple, return this many random variates; if an array, treat as UIDs 1
round bool if True, randomly round up or down based on how close the value is False
reset bool whether to automatically reset the random number distribution state after being called False
set
distributions.Dist.set(*args, dist=None, **kwargs)

Set (change) the distribution type, or one or more parameters of the distribution

show_state
distributions.Dist.show_state(output=False)

Show the state of the object

shrink
distributions.Dist.shrink()

Shrink the size of the module for saving to disk

sync_pars
distributions.Dist.sync_pars()

Perform any necessary synchronizations or transformations on distribution parameters; not for the user

to_json
distributions.Dist.to_json()

Return a dictionary representation of the Dist

update_dist_pars
distributions.Dist.update_dist_pars(pars=None)

Update SciPy distribution parameters; not for the user

validate_pars
distributions.Dist.validate_pars()

Check if parameters are valid; only used for non-SciPy distributions

Dists

distributions.Dists(self, obj=None, *args, base_seed=None, sim=None)

Class for managing a collection of Dist objects

Methods

Name Description
check_seeds Check that no two distributions share the same seed
copy_to_module Copy the Sim’s Dists object to the specified module
init Set the base seed, find and initialize all distributions in an object
jump Advance all RNGs, e.g. to call “to”, by jumping
jump_dt Advance all RNGs to the next timestep
reset Reset each RNG
check_seeds
distributions.Dists.check_seeds()

Check that no two distributions share the same seed

copy_to_module
distributions.Dists.copy_to_module(module)

Copy the Sim’s Dists object to the specified module

init
distributions.Dists.init(obj=None, base_seed=None, sim=None, force=False)

Set the base seed, find and initialize all distributions in an object

In practice, the object is usually a Sim, but can be anything.

jump
distributions.Dists.jump(to=None, delta=1, force=False)

Advance all RNGs, e.g. to call “to”, by jumping

jump_dt
distributions.Dists.jump_dt(ti=None, force=False)

Advance all RNGs to the next timestep

Parameters
Name Type Description Default
ti int if specified, jump to this timestep (default: current sim timestep) None
reset
distributions.Dists.reset()

Reset each RNG

multi_random

distributions.multi_random(self, names, *args, **kwargs)

A class for holding two or more ss.random() distributions, and generating random numbers linked to each of them. Useful for e.g. pairwise transmission probabilities.

See ss.combine_rands() for the manual version; in almost all cases this class should be used instead.

Usage

multi = ss.multi_random(‘source’, ‘target’) rvs = multi.rvs(source_uids, target_uids)

Methods

Name Description
combine_rvs Combine inputs into one number
init Not usually needed since each dist will handle this automatically; for completeness only
jump Not usually needed since each dist will handle this automatically; for completeness only
reset Not usually needed since each dist will handle this automatically; for completeness only
rvs Get random variates from each of the underlying distributions and combine them efficiently
combine_rvs
distributions.multi_random.combine_rvs(rvs_list, int_type, int_max)

Combine inputs into one number

init
distributions.multi_random.init(*args, **kwargs)

Not usually needed since each dist will handle this automatically; for completeness only

jump
distributions.multi_random.jump(*args, **kwargs)

Not usually needed since each dist will handle this automatically; for completeness only

reset
distributions.multi_random.reset(*args, **kwargs)

Not usually needed since each dist will handle this automatically; for completeness only

rvs
distributions.multi_random.rvs(*args)

Get random variates from each of the underlying distributions and combine them efficiently

scale_types

distributions.scale_types()

Define how distributions scale

Distributions scale in different ways, such as converting between time units. Some distributions can’t be scaled at all (e.g. ss.beta_dist() or ss.choice()). For distributions that can be scaled, some distributions can only be (linearly) scaled before the random numbers are generated (called “predraw”), some can only be scaled after (called “postdraw”), and some can be scaled in either way (“both”).

For example, a normal distribution is “both” since 2Normal(a, b) = Normal(2a, 2b). A Poisson distribution is “predraw” since 2Poisson(λ) ≠ Poisson(2λ), and there is no way to get the correct shape of a different Poisson distribution once the numbers have been drawn. Finally, distributions with unitless shape parameters as well as parameter that can have units (e.g. a gamma distribution with shape and scale parameters) are referred to as “postdraw” since scaling all input parameters is invalid (i.e. 2Gamma(shape, scale) ≠ Gamma(2shape, 2scale)), but they can still be scaled (i.e. 2Gamma(shape, scale) = Gamma(1shape, 2*scale)).

To summarize, options for dist.scaling are:

- 'postdraw' (after the random numbers are drawn, e.g. `ss.weibull()`)
- 'predraw' (before the draw, e.g. `ss.poisson()`)
- 'both' (either pre or post draw, e.g. `ss.normal()`)
- False (not at all, e.g. `ss.beta_dist()`)

Use ss.distributions.scale_types.show() to show how each distribution scales with time.

Methods

Name Description
check_postdraw Check if the supplied distribution supports post-draw (results) scaling
check_predraw Check if the supplied distribution supports pre-draw (parameter) scaling
show Show which distributions have which scale types
check_postdraw
distributions.scale_types.check_postdraw(dist)

Check if the supplied distribution supports post-draw (results) scaling

check_predraw
distributions.scale_types.check_predraw(dist)

Check if the supplied distribution supports pre-draw (parameter) scaling

show
distributions.scale_types.show(to_df=False)

Show which distributions have which scale types

Functions

Name Description
link_dists Link distributions to the sim and the module; used in module.init() and people.init()
make_dist Make a distribution from a dictionary

make_dist

distributions.make_dist(pars=None, **kwargs)

Make a distribution from a dictionary