繁体   English   中英

如何更快地迭代十个列表(每个十个元素)的笛卡尔积? (概率和骰子)

[英]How to iterate through the Cartesian product of ten lists (ten elements each) faster? (Probability and Dice)

我正在努力解决这个任务 我为此编写了function ,它使用 itertools.product() 作为输入迭代的笛卡尔积:

def probability(dice_number, sides, target):
    from itertools import product
    from decimal import Decimal
    FOUR_PLACES = Decimal('0.0001')
    total_number_of_experiment_outcomes = sides ** dice_number
    target_hits = 0
    sides_combinations = product(range(1, sides+1), repeat=dice_number)
    for side_combination in sides_combinations:
        if sum(side_combination) == target:
            target_hits += 1
    p = Decimal(str(target_hits / total_number_of_experiment_outcomes)).quantize(FOUR_PLACES)
    return float(p)

当调用probability(2, 6, 3)输出为0.0556 ,所以工作正常。 但是调用probability(10, 10, 50)计算的时间很长(小时?),但必须有更好的方法:)
for side_combination in sides_combinations:需要很长时间才能遍历大量的sides_combinations

拜托,你能帮我找出如何加快计算结果,我今晚太想睡觉了..

我想问题是要找到骰子总和的分布。 一种有效的方法是通过离散卷积。 变量总和的分布是它们的概率质量函数(或密度,在连续情况下)的卷积。 卷积是一个 n 元运算符,因此您可以方便地一次计算两个 pmf(到目前为止总数的当前分布,以及列表中的下一个)。 然后从最终结果中,您可以读出每个可能总数的概率。 结果中的第一个元素是最小可能总数的概率,最后一个元素是最大可能总数的概率。 在两者之间,您可以找出哪一个对应于您正在寻找的特定总和。

最难的部分是卷积,所以首先要处理它。 这只是一个简单的求和,但要使求和的限制正确,则有点棘手。 我的建议是使用整数或有理数,以便您可以进行精确的算术运算。

之后,您只需要为每个输入骰子构建一个合适的 pmf。 如果您使用整数(最终必须归一化)或 [1/n, 1/n, 1/n, ..., 1] ,则输入仅为 [1, 1, 1, ... 1] /n] 如果有理数,其中 n = 面数。 此外,您还需要正确标记输出的索引——同样,要正确地做到这一点有点棘手。

卷积是一种非常通用的变量求和方法。 由于 FFT(conv(A, B)) = FFT(A) FFT(B),因此可以通过快速傅立叶变换实现卷积来提高效率。 但在这一点上,我认为你不需要担心。

如果有人仍然对通过所有 itertools.product 笛卡尔积避免非常非常长的迭代过程的解决方案感兴趣,这里是:

def probability(dice_number, sides, target):
    if dice_number == 1:
        return (1 <= target <= sides**dice_number) / sides
    return sum([probability(dice_number-1, sides, target-x) \
                        for x in range(1,sides+1)]) / sides

但是你应该添加probability函数结果的缓存,如果你不这样做 - 概率的计算也需要非常非常非常长的时间)

PS 这个代码 100% 不是我的,我从互联网上拿来的,我自己制作它不是那么聪明,希望你和我一样喜欢它。

暂无
暂无

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM