简体   繁体   English

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

[英]How to generate random numbers with each random number having a difference of at least x with all other elements?

I know this goes against the definition of random numbers, but still I require this for my project. 我知道这违反了随机数的定义,但我仍然需要这个项目。 For instance, I want to generate an array with 5 random elements in range(0, 200) . 例如,我想生成一个在range(0, 200)有5个随机元素的数组。

Now, I want each of the elements to have a difference of at least 15 between them. 现在,我希望每个元素之间的差异至少为15。 So the random array should look something like this: 所以随机数组看起来应该是这样的:

[15, 45, 99, 132, 199]

I can generate random numbers using numpy: 我可以使用numpy生成随机数:

np.random.uniform(low=0, high=200, size=5)

However, I am not able to keep a consistent difference of at least 15. 但是,我无法保持至少15的一致差异。

It would be nice if the question showed more effort towards solving the problem (ie from the Stack Overflow Tour : "Don't ask about... Questions you haven't tried to find an answer for (show your work!)"), but sometimes a question triggers an itch you just have to scratch... 如果问题显示出更多努力来解决问题(例如来自Stack Overflow Tour :“不要问...问题,你没有试图找到答案(显示你的工作!)”,这将是很好的。) ,但有时候一个问题会引发痒,你只需要刮开......

Here's one way you could do it, written as the function random_spaced : 这是你可以做到的一种方式,写成函数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)

For example, 例如,

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])

The size argument lets you generate more than one sample at a time: 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]])

This code generates a histogram for each component using 100000 samples, and plots the corresponding theoretical marginal PDFs of each component: 此代码使用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()

Here's the plot that it generates: 这是它生成的情节:

情节

As can be seen in the plot, the marginal distributions are beta distributions . 从图中可以看出,边际分布是β分布 The modes of the marginal distributions correspond to the positions of n evenly spaced points on the interval [low, high] . 边际分布的模式对应于区间[low, high]上的n均匀间隔点的位置。

By fiddling with how u is generated in random_spaced , distributions with different marginals can be generated (an old version of this answer had an example), but the distribution that random_spaced currently generates seems to be a natural choice. 通过摆弄在random_spaced生成u方式,可以生成具有不同边缘的分布(这个答案的旧版本有一个例子),但random_spaced当前生成的分布似乎是一个自然的选择。 As mentioned above, the modes of the marginals occur in "meaningful" positions. 如上所述,边缘的模式出现在“有意义”的位置。 Moreover, in the trivial case where n is 1, the distribution simplifies to the uniform distribution on [ low , high ]. 此外,在n为1的平凡情况下,分布简化为[ lowhigh ]上的均匀分布。

How about trial-and-error? 反复试验怎么样? eg throw some random numbers, sort, compute differences... and if too small repeat? 例如,抛出一些随机数,排序,计算差异......如果重复得太小?

import random as r

def spreadRandom(theRange, howMany, minSpacing):
    while True:
        candidate = sorted([r.randint(*theRange) for _ in range(howMany)])
        minDiff = min([ candidate[i+1]-candidate[i] for i, _ in enumerate(candidate[:-1])])
        if minDiff >= minSpacing:
            return candidate

spreadRandom([0,200], 5, 15)

You're not guaranteed to ever get an answer, but you're not biasing your numbers at all as you might be by enforcing ranges based on neighboring numbers. 您无法保证得到答案,但您根本不会偏离您的数字,因为您可能会强制执行基于相邻数字的范围。

Try shuffling the numbers 0-200: 尝试改组数字0-200:

import random
numbers = list(range(200))
random.shuffle(numbers)
distant_numbers = [numbers[0]]
for number in numbers:
    if any(abs(number - x) < 15 for x in distant_numbers):
        continue
    distant_numbers.append(number)
    if len(distant_numbers) >= 5: break

Edit: 编辑:

Here's a solution that uses z3 for massive overkill: 这是一个使用z3进行大规模过度z3的解决方案:

def spaced_randoms(n, d, R, first=None):
    solver = z3.SolverFor("QF_FD")
    numbers = [z3.Int("x{}".format(x)) for x in range(n)]
    for number in numbers:
        solver.add(number >= 0)
        solver.add(number <= R)
    for ii in range(n):
        for jj in range(ii+1,n):
            solver.add(z3.Or(numbers[ii] - numbers[jj] > d, numbers[ii] - numbers[jj] < -d))
    if first is not None:
        solver.add(numbers[0] == first)
    result = solver.check()
    if str(result) != "sat":
        raise Exception("Unsatisfiable")
    model = solver.model()
    return [model.get_interp(number) for number in numbers]

Call it like this for a random result: 像这样称它为随机结果:

import random
spaced_randoms(n, d, R, random.randint(0,R))

I think this code might help for your specific needs: 我认为此代码可能有助于满足您的特定需求:

import random
import numpy as np
five_list = np.asarray([])
end = False
number = random.randint(0,200)
five_list = np.append(five_list,number)
while True:
    new_number = random.randint(0,200)
    if all(np.absolute(np.subtract(five_list, new_number)) >= 15):
        five_list = np.append(five_list,new_number)
    if np.size(five_list) == 5:
        break
print(np.sort(five_list)) 

Try it with "brute force": 尝试“蛮力”:

l= [ i for i in range(201) ]
rslt= []
for i in range(5): 
    n=random.choice(l) 
    rslt.append(n) 
    l=[ k for k in l if abs(k-n)>=15 ]
    #if not l:
    #   break

Or smartly: 或巧妙地:

sgmnts= [(0,200)]
diff= 15
rslt= []

for i in range(5):

    start,stop= sgmnts.pop( random.choice(range(len(sgmnts))) )
    n= random.choice(range(start,stop+1))
    rslt.append(n)
    if n-diff > start:
        sgmnts.append( (start,n-diff) )
    if n+diff < stop:
        sgmnts.append( (n+diff,stop) )
    if not sgmnts:
        break

"sgmnts" stores the suitable ranges. “sgmnts”存储合适的范围。 We select a range randomly, too, by index. 我们也通过索引随机选择一个范围。

This will generate 5 random values between 200 with a step of 5 这将在200之间生成5个随机值,步长为5

import random

array = []

randomRange = 200
arrayRange = 5
valueStep = 15

for loop in range(arrayRange):
    randomMaxValue = randomRange - valueStep * (arrayRange - loop) # First loop will the first randomMaxValue be 125 next will be 140, 155, 170, 185, 200
    if not array: # Checks if the array is empty
        array.append(random.randint(0, randomMaxValue)) # Appends a value between 0 and 125 (First will be 125 because 200 - 15 * 5)
    else:
        array.append(random.randint(array[-1] + 15, randomMaxValue)) # Appends the 4 next values

print(array)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何生成一定数量的随机整数,它们加起来等于一定数量并且至少是一定数量或更多? - How to generate a certain number of random whole numbers that add up to a certain number and are at least a certain number or more? 如何生成一些全为奇数的随机数 - How do I generate a number of random numbers that are all odd 我需要在1到x的间隔中生成x个随机数,但是每个数字只能出现一次 - I need to generate x random numbers in an interval from 1 to x but each number have to occur only once 生成一个包含 100 个元素的列表,每个元素有 50% 的可能性为 0,有 50% 的可能性为 0 到 1 之间的随机数 - Generate a list of 100 elements, with each element having a 50% chance of being 0, and a 50% chance of being a random number between 0 and 1 如何生成一个随机数,使其不是 2 的幂? 输出需要是 8 个随机数的列表 - How to generate a random number such that it is not a power of 2? The output needs to be a list of 8 random numbers 从给定的元素列表生成随机的numpy数组,每个元素至少重复一次 - Generate random numpy array from a given list of elements with at least one repetition of each element 如何使用 Python 为每个 SNP 生成随机浮点数 - How to generate random float numbers for each SNP using Python 生成N个随机整数的数组,介于1和K之间,但每个数字至少包含一个 - Generate an array of N random integers, between 1 and K, but containing at least one of each number 从多个列表中选择随机数,它必须至少包含每个列表中的一个数字 - Choose random numbers from multiple lists and it must contain at least one number from each list 如何生成一个不以 0 开头且具有唯一数字的随机 4 位数字? - How to generate a random 4 digit number not starting with 0 and having unique digits?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM