如何生成随机数,每个随机数至少与所有其他元素相差x?

use*_*506 6 python random numpy

我知道这违反了随机数的定义,但我仍然需要这个项目.例如,我想生成一个包含5个随机元素的数组range(0, 200).

现在,我希望每个元素之间的差异至少为15.所以随机数组看起来应该是这样的:

[15, 45, 99, 132, 199]
Run Code Online (Sandbox Code Playgroud)

我可以使用numpy生成随机数:

np.random.uniform(low=0, high=200, size=5)
Run Code Online (Sandbox Code Playgroud)

但是,我无法保持至少15的一致差异.

War*_*ser 5

如果问题表现出更多的努力来解决问题,那就太好了(即来自Stack Overflow Tour:“不要问......你还没有尝试找到答案的问题(展示你的工作!)”) ,但有时一个问题会引发你不得不抓挠的痒......

这是一种可以实现的方法,写为函数random_spaced

import numpy as np


def random_spaced(low, high, delta, n, size=None):
    """
    Choose n random values between low and high, with minimum spacing delta.

    If size is None, one sample is returned.
    Set size=m (an integer) to return m samples.

    The values in each sample returned by random_spaced are in increasing
    order.
    """
    empty_space = high - low - (n-1)*delta
    if empty_space < 0:
        raise ValueError("not possible")

    if size is None:
        u = np.random.rand(n)
    else:
        u = np.random.rand(size, n)
    x = empty_space * np.sort(u, axis=-1)
    return low + x + delta * np.arange(n)
Run Code Online (Sandbox Code Playgroud)

例如,

In [27]: random_spaced(0, 200, 15, 5)
Out[27]: array([ 30.3524969 ,  97.4773284 , 140.38221631, 161.9276264 , 189.3404236 ])

In [28]: random_spaced(0, 200, 15, 5)
Out[28]: array([ 81.01616136, 103.11710522, 118.98018499, 141.68196775, 169.02965952])
Run Code Online (Sandbox Code Playgroud)

size参数允许您一次生成多个样本:

In [29]: random_spaced(0, 200, 15, 5, size=3)
Out[29]: 
array([[ 52.62401348,  80.04494534,  96.21983265, 138.68552066, 178.14784825],
       [  7.57714106,  33.05818556,  62.59831316,  81.86507168, 180.30946733],
       [ 24.16367913,  40.37480075,  86.71321297, 148.24263974, 195.89405713]])
Run Code Online (Sandbox Code Playgroud)

此代码使用 100000 个样本为每个组件生成直方图,并绘制每个组件相应的理论边际 PDF:

import matplotlib.pyplot as plt
from scipy.stats import beta

low = 0
high = 200
delta = 15 
n = 5
s = random_spaced(low, high, delta, n, size=100000)

for k in range(s.shape[1]):
    plt.hist(s[:, k], bins=100, density=True, alpha=0.25)
plt.title("Normalized marginal histograms and marginal PDFs")
plt.grid(alpha=0.2)

# Plot the PDFs of the marginal distributions of each component.
# These are beta distributions.
for k in range(n):
    left = low + k*delta
    right = high - (n - k - 1)*delta
    xx = np.linspace(left, right, 400)
    yy = beta.pdf(xx, k + 1, n - k, loc=left, scale=right - left)
    plt.plot(xx, yy, 'k--', linewidth=1, alpha=0.25)
    if n > 1:
        # Mark the mode with a dot.
        mode0 = k/(n-1)
        mode = (right-left)*mode0 + left
        plt.plot(mode, beta.pdf(mode, k + 1, n - k, loc=left, scale=right - left),
                 'k.', alpha=0.25)

plt.show()
Run Code Online (Sandbox Code Playgroud)

这是它生成的图:

阴谋

从图中可以看出,边际分布是beta 分布n边际分布的众数对应于区间 上均匀分布的点的位置[low, high]

通过摆弄如何u生成random_spaced,可以生成具有不同边际的分布(这个答案的旧版本有一个例子),但当前生成的分布random_spaced似乎是一个自然的选择。如上所述,边际众数出现在“有意义”的位置。此外,在 为 1 的平凡情况下n,分布简化为 [ low, high] 上的均匀分布。

  • 下次一定会在提出的问题中添加尝试的解决方案。谢谢您的回答。 (2认同)