2026-07-30 18:57:10 +02:00

33 lines
1.2 KiB
Python

"""Stake distribution generation.
Total stake is held FIXED across distributions (via renormalisation) so that accuracy
comparisons between ``uniform`` and ``pareto`` isolate the *shape* effect on the lottery
(winner multiplicity / forking), not a difference in aggregate stake.
"""
from __future__ import annotations
import numpy as np
from .config import SimConfig
def make_stake(config: SimConfig, rng: np.random.Generator) -> np.ndarray:
"""Return an ``(n_nodes,)`` non-negative stake vector summing to ``total_stake``."""
n = config.n_nodes
if config.stake_dist == "uniform":
if config.uniform_random:
w = rng.random(n)
else:
w = np.ones(n)
elif config.stake_dist == "pareto":
# numpy.pareto draws Lomax = Pareto(shape) - 1, heavy-tailed for small shape.
w = rng.pareto(config.pareto_shape, n) + 1.0
else: # pragma: no cover - guarded by Literal typing
raise ValueError(f"unknown stake_dist: {config.stake_dist}")
total = w.sum()
if total <= 0: # pragma: no cover - degenerate
raise ValueError("stake vector summed to zero")
return w * (config.total_stake / total)