Source code for networkx.utils.random_sequence

"""
生成随机数、随机序列和随机选择的实用工具。
"""

import networkx as nx
from networkx.utils import py_random_state

__all__ = [
    "powerlaw_sequence",
    "zipf_rv",
    "cumulative_distribution",
    "discrete_sequence",
    "random_weighted_sample",
    "weighted_choice",
]


# The same helpers for choosing random sequences from distributions
# uses Python's random module
# https://docs.python.org/3/library/random.html


[docs] @py_random_state(2) def powerlaw_sequence(n, exponent=2.0, seed=None): """ 返回从幂律分布中抽取的长度为n的样本序列。 """ return [seed.paretovariate(exponent - 1) for i in range(n)]
[docs] @py_random_state(2) def zipf_rv(alpha, xmin=1, seed=None): r"""返回从Zipf分布中随机选择的值。 返回值是从概率分布中抽取的整数 .. math:: p(x)=\frac{x^{-\alpha}}{\zeta(\alpha, x_{\min})}, 其中$\zeta(\alpha, x_{\min})$是Hurwitz zeta函数。 Parameters ---------- alpha : float 分布的指数值 xmin : int 最小值 seed : integer, random_state, 或 None (默认) 随机数生成状态的指示器。 参见 :ref:`随机性<randomness>` 。 Returns ------- x : int Zipf分布的随机值 Raises ------ ValueError: 如果 xmin < 1 或 如果 alpha <= 1 Notes ----- 拒绝算法生成依赖于参数的均匀有界预期时间的幂律分布的随机值。有关其操作的详细信息,请参见[1]_。 Examples -------- >>> nx.utils.zipf_rv(alpha=2, xmin=3, seed=42) 8 References ---------- .. [1] Luc Devroye, 非均匀随机变量生成, Springer-Verlag, 纽约, 1986. """ if xmin < 1: raise ValueError("xmin < 1") if alpha <= 1: raise ValueError("a <= 1.0") a1 = alpha - 1.0 b = 2**a1 while True: u = 1.0 - seed.random() # u in (0,1] v = seed.random() # v in [0,1) x = int(xmin * u ** -(1.0 / a1)) t = (1.0 + (1.0 / x)) ** a1 if v * x * (t - 1.0) / (b - 1.0) <= t / b: break return x
[docs] def cumulative_distribution(distribution): """返回从离散分布归一化的累积分布。""" cdf = [0.0] psum = sum(distribution) for i in range(len(distribution)): cdf.append(cdf[i] + distribution[i] / psum) return cdf
[docs] @py_random_state(3) def discrete_sequence(n, distribution=None, cdistribution=None, seed=None): """返回从给定离散分布或离散累积分布中抽取的长度为 n 的样本序列。 必须指定以下之一: distribution = 值的直方图,将被归一化 cdistribution = 归一化的离散累积分布 """ import bisect if cdistribution is not None: cdf = cdistribution elif distribution is not None: cdf = cumulative_distribution(distribution) else: raise nx.NetworkXError( "discrete_sequence: distribution or cdistribution missing" ) # get a uniform random number inputseq = [seed.random() for i in range(n)] # choose from CDF seq = [bisect.bisect_left(cdf, s) - 1 for s in inputseq] return seq
[docs] @py_random_state(2) def random_weighted_sample(mapping, k, seed=None): """返回从加权样本中无放回地抽取的k个项目。 输入是一个以项目为键、权重为值的字典。 """ if k > len(mapping): raise ValueError("sample larger than population") sample = set() while len(sample) < k: sample.add(weighted_choice(mapping, seed)) return list(sample)
[docs] @py_random_state(1) def weighted_choice(mapping, seed=None): """从加权样本中返回一个单一元素。 输入是一个以权重为值的项的字典。 """ # use roulette method rnd = seed.random() * sum(mapping.values()) for k, w in mapping.items(): rnd -= w if rnd < 0: return k