Construction

The primary method of constructing a distribution is by supplying both the outcomes and the probability mass function. Each outcome is an indexable sequence whose length is the number of random variables:

In [1]: from dit import Distribution

In [2]: outcomes = ['000', '011', '101', '110']

In [3]: pmf = [1/4]*4

In [4]: xor = Distribution(outcomes, pmf)

In [5]: print(xor)
Class:    Distribution
Alphabet: (('0', '1'), ('0', '1'), ('0', '1'))
Base:     linear

x                 p(X0,X1,X2)
('0', '0', '0')   0.25
('0', '1', '1')   0.25
('1', '0', '1')   0.25
('1', '1', '0')   0.25

A dictionary mapping outcomes to probabilities is equivalent:

In [6]: xor2 = Distribution({'000': 1/4, '011': 1/4, '101': 1/4, '110': 1/4})

In [7]: xor.is_approx_equal(xor2)
Out[7]: True

An ndarray is interpreted as a dense pmf, with each axis a random variable and the index along that axis the variable’s value:

In [8]: pmf = [[0.5, 0.25], [0.25, 0]]

In [9]: d = Distribution.from_ndarray(pmf)

In [10]: print(d)
Class:    Distribution
Alphabet: ((0, 1), (0, 1))
Base:     linear

x        p(X0,X1)
(0, 0)   0.5
(0, 1)   0.25
(1, 0)   0.25

An DataArray can be passed directly, which is the native storage format. Dimension names become random-variable names:

In [11]: import numpy as np

In [12]: import xarray as xr

In [13]: arr = np.zeros((2, 2, 2))

In [14]: arr[0, 0, 0] = arr[0, 1, 1] = arr[1, 0, 1] = arr[1, 1, 0] = 0.25

In [15]: data = xr.DataArray(arr, dims=['X', 'Y', 'Z'], coords={'X': ['0', '1'], 'Y': ['0', '1'], 'Z': ['0', '1']})

In [16]: dx = Distribution(data)

In [17]: xor.set_rv_names('XYZ')

In [18]: dx.is_approx_equal(xor)
Out[18]: True

Distribution.from_array() is the same idea with an explicit alphabet list. Distribution.from_factors() rebuilds a joint from a marginal and a compatible conditional (the inverse of chain-rule multiplication; see Algebra). Distribution.from_rv_discrete() wraps a frozen scipy.stats.rv_discrete.

Sparse vs dense

Zero-probability outcomes can be dropped from the printed table (make_sparse()) or filled back in (make_dense()). validate() checks that free-variable slices are normalized.

Symbolic probabilities are constructed with dit.symbolic; see Symbolic.

API

Distribution.__init__(data, pmf=None, rv_names=None, free_vars=None, given_vars=None, base='linear', sample_space=None, sparse=True, trim=True, sort=True, validate=True, prng=None)[source]

Initialize an Distribution.

There are three construction modes:

  1. DataArray – pass an xr.DataArray directly (original API).

  2. Outcomes + pmf – pass a sequence of outcomes and a sequence of probabilities, matching the dit.Distribution signature.

  3. Dict – pass a dict mapping outcomes to probabilities.

Parameters:
  • data (xr.DataArray, sequence, or dict) – If an xr.DataArray, used directly as the probability data. If a dict, keys are outcomes and values are probabilities. Otherwise, treated as a sequence of outcomes (each outcome is an indexable container whose length equals the number of random variables).

  • pmf (sequence of float, optional) – Probability values corresponding to data when data is a sequence of outcomes. Ignored when data is a DataArray or dict.

  • rv_names (list of str, optional) – Names for each random variable. Only used when data is outcomes or a dict. Defaults to 'X0', 'X1', …

  • free_vars (set-like of str, optional) – Names of the free (joint) variables. If both free_vars and given_vars are None, all dimensions are treated as free.

  • given_vars (set-like of str, optional) – Names of the conditioned variables.

  • base (str, float, or None) – The probability base. 'linear' (default) for raw probabilities, 2, 'e', or any positive float for log probabilities. If None, auto-detected (linear if the pmf sums to ~1, else ditParams['base']).

  • sample_space (sequence or CartesianProduct, optional) – Explicit sample space. If provided, used to determine the full set of possible outcomes.

  • sparse (bool) – If True, outcomes and pmf only report non-zero entries.

  • trim (bool) – Ignored (kept for API compatibility).

  • sort (bool) – Ignored (alphabets are always sorted).

  • validate (bool) – If True, validate normalisation after construction.

  • prng (random state, optional) – Pseudo-random number generator. Defaults to dit.math.prng.

Examples

From outcomes and pmf (like dit.Distribution):

>>> xrd = Distribution(['00','01','10','11'],
...                      [.25, .25, .25, .25],
...                      rv_names=['X', 'Y'])

From a dict:

>>> xrd = Distribution({'00': .5, '11': .5}, rv_names=['X', 'Y'])

From a DataArray (original API):

>>> xrd = Distribution(my_dataarray, free_vars={'X', 'Y'})
classmethod Distribution.from_ndarray(ndarray, base=None, prng=None)[source]

Construct from a multi-dimensional numpy ndarray interpreted as a pmf.

Each axis represents a random variable, and the index along that axis is the variable’s value. For example, a (2, 3) array has two variables with alphabet sizes 2 and 3 respectively.

Parameters:
  • ndarray (np.ndarray)

  • base (str or float, optional)

  • prng (random state, optional)

classmethod Distribution.from_array(arr, dim_names, alphabets, free_vars=None, given_vars=None, base='linear')[source]

Create an Distribution from a numpy array.

Parameters:
  • arr (np.ndarray) – The probability array.

  • dim_names (list of str) – Names for each dimension.

  • alphabets (list of list) – The alphabet (coordinate values) for each dimension.

  • free_vars (set-like of str, optional) – Names of the free variables.

  • given_vars (set-like of str, optional) – Names of the conditioned variables.

  • base (str or float) – Probability base ('linear', 2, 'e', …).

Returns:

xrd

Return type:

Distribution

classmethod Distribution.from_factors(marginal, conditional)[source]

Build a joint distribution from a marginal and a conditional.

p(X,Y) = p(X) * p(Y|X)

Parameters:
  • marginal (Distribution) – The marginal distribution, e.g. p(X).

  • conditional (Distribution) – The conditional distribution, e.g. p(Y|X).

Returns:

joint – The resulting joint distribution.

Return type:

Distribution

classmethod Distribution.from_rv_discrete(ssrv, base=None, prng=None)[source]

Construct from a scipy.stats.rv_discrete instance.

Parameters:
  • ssrv (scipy.stats.rv_discrete) – A frozen discrete random variable with .xk and .pk attributes (as produced by rv_discrete(values=...)).

  • base (str or float, optional) – Probability base. Defaults to 'linear'.

  • prng (random state, optional)

Distribution.is_approx_equal(other, atol=1e-09, rtol=None)[source]

Check approximate equality of two distributions.

Compares by sample space and per-outcome probabilities, ignoring dimension names. This matches the old dit.Distribution behavior.

Parameters:
  • other (Distribution) – Distribution to compare against.

  • atol (float, optional) – Absolute tolerance for value comparison (default: 1e-9).

  • rtol (float, optional) – Ignored (kept for signature compatibility).

Returns:

eq

Return type:

bool