我一直在使用SAGE提供的random_element()
函数为给定的整数(N
)生成特定长度(S
)的随机整数分区。我正在尝试从给定值N
和S
的所有分区集合中生成无偏的随机样本。 SAGE的函数快速返回N的随机分区(即Partitions(N).random_element()
)。
但是,在添加S
(即Partitions(N,length=S).random_element()
)时,它会大幅减速。同样,过滤掉N
长度为S
的随机分区的速度非常慢。
然而,我希望这有助于某些人,我发现在函数返回N
的分区与长度S
不匹配的情况下,共轭分区通常很长那是:
S = 10
N = 100
part = list(Partitions(N).random_element())
if len(part) != S:
SAD = list(Partition(part).conjugate())
if len(SAD) != S:
continue
这增加了找到长度为S
的分区并且看起来产生无偏样本的速率(我已针对N
和{{1}的各种值检查了整个分区集的结果}})。
然而,我使用的是N(例如S
)和S(例如10,000
)的值,这使得这种方法实际上很慢。与SAGE的300
函数相关的评论承认有足够的优化空间。那么,有没有办法更快速地生成与random_element()
和N
的给定值匹配的整数分区的无偏(即随机统一)样本,可能是因为没有生成不匹配{{1}的分区}?此外,在许多情况下使用共轭分区可以很好地生成无偏差的样本,但我不能说我完全理解为什么。
答案 0 :(得分:4)
最后,我有一个明确无偏的方法,拒绝率为零。当然,我已对其进行了测试,以确保结果是整个可行集的代表性样本。它非常快速且完全无偏见。享受。
from sage.all import *
import random
首先,找到具有s部分的n分区的最小最大加数的函数
def min_max(n,s):
_min = int(floor(float(n)/float(s)))
if int(n%s) > 0:
_min +=1
return _min
接下来,使用缓存和memoiziation查找分区数的函数 n为具有x作为最大部分的s部分。这很快,但我认为有 一个更优雅的解决方案。例如,经常:P(N,S,max = K)= P(N-K,S-1) 感谢ante(https://stackoverflow.com/users/494076/ante)帮助我: Finding the number of integer partitions given a total, a number of parts, and a maximum summand 强>
D = {}
def P(n,s,x):
if n > s*x or x <= 0: return 0
if n == s*x: return 1
if (n,s,x) not in D:
D[(n,s,x)] = sum(P(n-i*x, s-i, x-1) for i in xrange(s))
return D[(n,s,x)]
最后,找一个带有s部分的n个均匀随机分区的函数,没有拒绝率!每个随机选择的数字代码为具有s部分的n的特定分区。
def random_partition(n,s):
S = s
partition = []
_min = min_max(n,S)
_max = n-S+1
total = number_of_partitions(n,S)
which = random.randrange(1,total+1) # random number
while n:
for k in range(_min,_max+1):
count = P(n,S,k)
if count >= which:
count = P(n,S,k-1)
break
partition.append(k)
n -= k
if n == 0: break
S -= 1
which -= count
_min = min_max(n,S)
_max = k
return partition
答案 1 :(得分:1)
简单方法:随机分配整数:
def random_partition(n, s):
partition = [0] * s
for x in range(n):
partition[random.randrange(s)] += 1
return partition
答案 2 :(得分:0)
当我试图计算强生日问题的可能性时,我遇到了类似的问题。
首先,当给出适量的数字时,分区功能会爆炸。你会回来很多信息。无论你使用哪种方法N = 10000而S = 300都会产生大量的数据。它会很慢。机会是你使用的任何纯python实现同样慢或慢。期待制作一个CModule。
如果你想尝试python我采用的方法,作为itertools和生成器的组合,以减少内存使用量。我似乎不再有我的代码了,但这是一个很好的实施:
http://wordaligned.org/articles/partitioning-with-python
编辑:
找到我的代码:
def partition(a, b=-1, limit=365):
if (b == -1):
b = a
if (a == 2 or a == 3):
if (b >= a and limit):
yield [a]
else:
return
elif (a > 3):
if (a <= b):
yield [a]
c = 0
if b > a-2:
c = a-2
else:
c = b
for i in xrange(c, 1, -1):
if (limit):
for j in partition(a-i, i, limit-1):
yield [i] + j