具有常数和的加权随机数的数组

时间:2018-06-17 20:45:22

标签: python random statistics

是否有任何众所周知的算法可以生成具有相同常数和的加权随机数阵列?

这个问题可以用另一种方式说明:比方说,我的总值是20.应该分成3个部分,每个部分的权重分别为2,4,3。 因此,我需要3个随机数,其总和为20,但分布将遵循权重。

我试过了:

Range=20
W=[2,4,3]
Prob=[i/float(sum(W)) for i in W]
Weighted_array=np.random.multinomial(Range, Prob)

还有更好的选择吗?

1 个答案:

答案 0 :(得分:0)

<强>符号:

这是n=3变量的线性丢番图方程。要在python中解析它,你可以sympy使用from random import randint from sympy.solvers.diophantine import diop_linear from sympy.abc import x, y, z # Our original equation is 2 * x + 4 * y + 3 * z = 20 # Re-arrange to 2 * x + 4 * y + 3 * z - 20 = 0, and input the left side to sympy general_solution = diop_linear(2 * x + 4 * y + 3 * z - 20) def get_random_valid_triple(): t0,t1 = general_solution[2].free_symbols # You can pick whatever bounds you want here a = randint(-100, 100) b = randint(-100, 100) solution = [s.subs({t0: a, t1:b}) for s in general_solution] print(solution) # Get a random solution get_random_valid_triple()

n

蛮力:

或者,至少对于每个变量的小random.choice和紧密边界,您可以预先计算所有可能的解决方案,并使用[0, 20 / coefficient]每次选择一个。例如,我们将所有变量限制为正数,然后它们被强制放在import random import itertools n = 20 coefficients = [2, 4, 3] valid_solutions = [] ranges = [range(0, n // k + 1) for k in coefficients] for value in itertools.product(*ranges): if sum(value[j] * i for j, i in enumerate(coefficients)) == n: valid_solutions.append(value) print("All solutions:") print("\n".join(str(i) for i in valid_solutions)) print("Random solution:") print(random.choice(valid_solutions)) 中,并且只有14个解。我们可以在python中生成如下:

All solutions:
(0, 2, 4)
(0, 5, 0)
(1, 0, 6)
(1, 3, 2)
(2, 1, 4)
(2, 4, 0)
(3, 2, 2)
(4, 0, 4)
(4, 3, 0)
(5, 1, 2)
(6, 2, 0)
(7, 0, 2)
(8, 1, 0)
(10, 0, 0)
Random solution:
(10, 0, 0)

这会产生:

list1 = [5,1,5,5,5,1,5,5,1,5,5,5,5]
list2 = []

templist = []

for idx,val in enumerate(list1):
    if (idx+1) <= (len(list1)-1):
        if list1[idx+1] == 5 and list1[idx] == 5:
            templist.append(val)
            templist.append(1)
            list2.append(val)
            list2.append(42)
        else:
            templist.append(val)
            list2.append(val)