aosabook/500lines · error · ValueError

outcome probabilities do not sum to 1

Error message

outcome probabilities do not sum to 1

What it means

Raised by MultinomialDistribution.__init__ when np.sum(p) is not close to 1.0 (np.isclose default tolerances: rtol=1e-05, atol=1e-08). The constructor treats a normalized probability vector as a hard precondition because sampling, log_pmf, and pmf all assume a valid distribution. A vector summing to anything else is treated as a programming/data error, not tolerated input.

Source

Thrown at sampler/code/multinomial.py:24

    def __init__(self, p, rso=np.random):
        """Initialize the multinomial random variable.

        Parameters
        ----------
        p: numpy array of length `k`
            The outcome probabilities
        rso: numpy RandomState object (default: np.random)
            The random number generator

        """

        # Check that the probabilities sum to 1. If they don't, then
        # something is wrong! We use `np.isclose` rather than checking
        # for exact equality because in many cases, we won't have
        # exact equality due to floating-point error.
        if not np.isclose(np.sum(p), 1.0):
            raise ValueError("outcome probabilities do not sum to 1")

        # Store the parameters that were passed in
        self.p = p
        self.rso = rso

        # Precompute log probabilities, for use by the log-PMF, for
        # each element of `self.p` (the function `np.log` operates
        # elementwise over NumPy arrays, as well as on scalars.)
        self.logp = np.log(self.p)

    def sample(self, n):
        """Samples draws of `n` events from a multinomial distribution with
        outcome probabilities `self.p`.

        Parameters
        ----------
        n: integer
            The number of total events

View on GitHub (pinned to fba689d101)

Solutions

  1. Normalize p before constructing: p = np.asarray(p, dtype=float); p = p / p.sum().
  2. Recheck each probability and the category count for missing/extra entries.
  3. Ensure p is non-negative and 1-dimensional.
  4. If a tiny deviation is expected, normalize it away rather than loosening the library's check.

Example fix

// before
dist = MultinomialDistribution(np.array([0.2, 0.5, 0.2]))   # sums to 0.9 -> ValueError
// after
p = np.array([0.2, 0.5, 0.2])
p = p / p.sum()
dist = MultinomialDistribution(p)
Defensive patterns

Strategy: validation

Validate before calling

import numpy as np

def valid_prob_vector(p):
    p = np.asarray(p, dtype=float)
    return (p.ndim == 1 and p.size > 0
            and np.all(p >= 0)
            and np.isclose(np.sum(p), 1.0))

if not valid_prob_vector(p):
    p = np.asarray(p, dtype=float)
    p = p / p.sum()

Type guard

def is_probability_vector(p):
    p = np.asarray(p, dtype=float)
    return (isinstance(p, np.ndarray) and p.ndim == 1
            and np.all(np.isfinite(p)) and np.all(p >= 0)
            and np.isclose(p.sum(), 1.0))

Try / catch

try:
    dist = MultinomialDistribution(p)
except ValueError:
    p = np.asarray(p, dtype=float) / np.sum(p)
    dist = MultinomialDistribution(p)

Prevention

When it happens

Trigger: Constructing MultinomialDistribution(p=...) where p does not sum to 1, e.g. np.array([0.2, 0.5]) sums to 0.7; probabilities loaded from a misconfigured source; forgetting to normalize; rounding on a large k that pushes the sum outside np.isclose tolerance.

Common situations: Hand-coded probabilities that miscount; loading counts instead of probabilities; integer arrays; floating-point accumulation error on many categories exceeding the default tolerance.


AI-assisted analysis of aosabook/500lines@fba689d101 (2026-08-13). Data as JSON: /api/errors/be827c50895fd990. Report an issue: GitHub.