distributions.DistributionRegistry

Registry for probability distribution classes with batch creation

Usage

Source

distributions.DistributionRegistry()

capabilities.

The DistributionRegistry provides a central repository for registering distribution classes and instantiating them from configuration data. This facilitates dynamic creation of distribution objects based on runtime configuration, supporting scenarios like simulation models, statistical analysis, or any application requiring configurable random distributions.

Key features: - Register distribution classes with a simple decorator - Create distribution instances from class names and parameters - Batch create multiple distributions from a dictionary or list - Automatic generation of statistically independent random seeds

Examples

Register distribution classes:

>>> @DistributionRegistry.register()
... class Exponential:
...     def __init__(self, mean, random_seed=None):
...         self.rng = np.random.default_rng(random_seed)
...         self.mean = mean
...
...     def sample(self, size=None):
...         return self.rng.exponential(self.mean, size=size)
...
>>> @DistributionRegistry.register("uniform_dist")  # Custom name
... class Uniform:
...     def __init__(self, low, high, random_seed=None):
...         self.rng = np.random.default_rng(random_seed)
...         self.low = low
...         self.high = high
...
...     def sample(self, size=None):
...         return self.rng.uniform(self.low, self.high, size=size)

Create a distribution with parameters:

>>> exp_dist = DistributionRegistry.create("Exponential", mean=2.0)
>>> exp_dist.sample(5)  # Generate 5 samples

Create multiple distributions from a flat configuration:

>>> config = {
...     "arrivals": {
...         "class_name": "Exponential",
...         "params": {"mean": 5.0}
...     },
...     "service_times": {
...         "class_name": "uniform_dist",
...         "params": {"low": 1.0, "high": 3.0}
...     }
... }
>>> distributions = DistributionRegistry.create_batch(config,
...                                                    main_seed=12345)
>>> arrivals = distributions["arrivals"]
>>> service_times = distributions["service_times"]

Create distributions from a nested configuration:

>>> config = {
...     "call": {
...         "C1": {"class_name": "Exponential", "params": {"mean": 10.0}},
...         "C2": {"class_name": "Exponential", "params": {"mean": 8.0}},
...     },
...     "response_time": {
...         "C1": {
...             "class_name": "Lognormal",
...             "params": {"mean": 30.0, "stdev": 5.0},
...         },
...     },
... }
>>> dists = DistributionRegistry.create_batch(
...     config, main_seed=42, preserve_structure=True
... )
>>> dists["call"]["C1"].sample(5)
>>> dists["response_time"]["C1"].sample(5)

Notes

When creating distributions in batch with a main_seed, each distribution receives its own statistically independent seed derived from the main seed. This ensures proper statistical independence between random number streams while maintaining overall reproducibility through the main seed.

When preserve_structure=True, the output mirrors the shape of the input configuration, so nested configs produce nested dicts of instances. When preserve_structure=False (default), all leaf distributions are flattened into a single dict whose keys are the path components joined by underscores (e.g. "call_C1").

With sort=True (default), keys at every nesting level are sorted alphabetically before seeds are assigned. This ensures that seed assignment is stable even if the insertion order of keys in the config dict changes between runs.

Methods

Name Description
create() Create a distribution instance by name.
create_batch() Create multiple distributions from a configuration dictionary or list.
get() Get a distribution class by name.
get_template() Generate a template configuration containing all registered
register() Decorator to register a distribution class in the registry.

create()

Create a distribution instance by name.

Usage

Source

create(name, **params)
Parameters
name: str

Name of the registered distribution class

**params
Parameters to pass to the distribution constructor
Returns
Any
Instance of the requested distribution class

create_batch()

Create multiple distributions from a configuration dictionary or list.

Usage

Source

create_batch(config, main_seed=None, sort=True, preserve_structure=False)

Accepts both flat and arbitrarily nested dict configurations. Every leaf must be a dict with exactly the keys 'class_name' and 'params'.

Parameters
config: Union[List[Dict], Dict[str, Dict]]

One of:

  • A list of distribution configs, each with 'class_name' and 'params'. Returns a list of instances.

  • A flat dict mapping names to distribution configs:

    {
        "arrivals": {
            "class_name": "Exponential",
            "params": {"mean": 5.0},
        }
    }
  • A nested dict where intermediate keys group distributions and leaves are distribution configs:

    {
        "call": {
            "C1": {
                "class_name": "Exponential",
                "params": {"mean": 10.0},
            }
        }
    }
main_seed: Optional[int] = None

Master seed to generate individual seeds for each distribution. If None, random seeds will still be generated for independence.

sort: Optional[bool] = True

If True, keys at every nesting level are sorted alphabetically before seeds are assigned. This ensures deterministic seed assignment even if config key insertion order changes between runs. Not relevant for top-level lists.

preserve_structure: Optional[bool] = False

Controls the shape of the returned dict when config is a dict.

  • False (default): all distributions are returned in a single flat dict whose keys are the path components of each leaf joined by underscores, e.g. "call_C1".
  • True: the returned dict mirrors the nesting of the input config, so result["call"]["C1"] gives the distribution directly.
Has no effect when config is a list.
Returns
Union[List, Dict]
  • A list of distribution instances if config was a list.
  • A flat dict of distribution instances if config was a dict and preserve_structure=False.
  • A nested dict of distribution instances if config was a dict and preserve_structure=True.
Raises
TypeError

If config is neither a list nor a dictionary.

ValueError
If any distribution config is malformed, if a required key is missing or an unexpected key is present, or if the config contains values that are neither dicts, lists, nor valid distribution configs.

get()

Get a distribution class by name.

Usage

Source

get(name)
Parameters
name: str
Name of the registered distribution class
Returns
type
The registered distribution class
Raises
ValueError
If the distribution name is not found in the registry

get_template()

Generate a template configuration containing all registered

Usage

Source

get_template(format="json", indent=2)

distributions.

This helper method creates a template that includes all registered distribution types with appropriate dummy parameters. Users can modify this template and pass it directly to create_batch() to instantiate their distributions.

Parameters
format: str = "json"

Output format: 'dict' for a Python dictionary or 'json' for a JSON string.

indent: int = 2
Indentation for JSON formatting (only used when format='json').
Returns
Union[Dict, str]
Either a dictionary (ifformat='dict') or a JSON string (if format='json') containing template configurations for all registered distributions.
Examples
>>> template = DistributionRegistry.get_template(format='dict')
>>> print(list(template.keys()))
['Exponential_example', 'Normal_example', 'Uniform_example', ...]
>>> template = DistributionRegistry.get_template(format='json')
>>> print(template[:70])
{
  "Exponential_example": {
    "class_name": "Exponential",
    "params": {

register()

Decorator to register a distribution class in the registry.

Usage

Source

register(name=None)
Parameters
name: Optional[str] = None
Name to register the class under. If None, uses the class name.
Returns
Callable
Decorator function that registers the class