python产生随机整数数组_生成随机整数数组

这是一个精确的(每个合法的和都有相同的概率)解。它使用所有合法和的枚举,并不是说我们要遍历每个和,而是给定一个数字n,我们可以直接计算枚举中的第n个和。由于我们也知道合法和的总数,我们可以简单地画出统一的整数并对其进行转换:import numpy as np

import functools as ft

#partition count

@ft.lru_cache(None)

def capped_pc(N,k,m):

if N < 0:

return 0

if k == 0:

return int(N<=m)

return sum(capped_pc(N-i,k-1,m) for i in range(m+1))

capped_pc_v = np.vectorize(capped_pc)

def random_capped_partition(low,high,n,total,size=1):

total = total - n*low

high = high - low

if total > n*high or total < 0:

raise ValueError

idx = np.random.randint(0,capped_pc(total,n-1,high),size)

total = np.broadcast_to(total,(size,1))

out = np.empty((size,n),int)

for j in range(n-1):

freqs = capped_pc_v(total-np.arange(high+1),n-2-j,high)

freqs_ps = np.c_[np.zeros(size,int),freqs.cumsum(axis=1)]

out[:,j] = [f.searchsorted(i,"right") for f,i in zip(freqs_ps[:,1:],idx)]

idx = idx - np.take_along_axis(freqs_ps,out[:,j,None],1).ravel()

total = total - out[:,j,None]

out[:,-1] = total.ravel()

return out + low

演示:

^{pr2}$

简要说明:

我们使用一个简单的递归来计算封顶分区的总数。我们在第一个箱子上分开,也就是说,我们固定第一个箱子里的数量,然后通过重复的方法来检索填充剩余箱子的方法的数量。然后我们简单地总结不同的第一个箱子选项。我们使用缓存装饰器来控制递归。这个decorator会记住我们已经完成的所有参数组合,所以当我们通过不同的递归路径得到相同的参数时,我们就不必再做同样的计算了。在

枚举的工作原理类似。假设字典顺序。如何找到第n个分区?再次,在第一个箱子上分开。因为我们知道对于每个值,第一个bin可以采用填充剩余bin的方法的总数,所以我们可以形成累积和,然后看看n在哪里适合。如果n位于第i个和第i+1个部分和之间,则第一个索引为i+low,我们从n中减去第i个和,然后重新开始剩余的bin。在

你可能感兴趣的:(python产生随机整数数组)