简体   繁体   English

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

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

I'm trying to solve this task .我正在努力解决这个任务 I wrote function for this purpose which uses itertools.product() for Cartesian product of input iterables:我为此编写了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)

When calling probability(2, 6, 3) output is 0.0556 , so works fine.当调用probability(2, 6, 3)输出为0.0556 ,所以工作正常。 But calling probability(10, 10, 50) calculates veeery long (hours?), but there must be a better way:)但是调用probability(10, 10, 50)计算的时间很长(小时?),但必须有更好的方法:)
for side_combination in sides_combinations: takes to long to iterate through huge number of sides_combinations . for side_combination in sides_combinations:需要很长时间才能遍历大量的sides_combinations

Please, can you help me to find out how to speed up calculation of result, i want too sleep tonight..拜托,你能帮我找出如何加快计算结果,我今晚太想睡觉了..

I guess the problem is to find the distribution of the sum of dice.我想问题是要找到骰子总和的分布。 An efficient way to do that is via discrete convolution.一种有效的方法是通过离散卷积。 The distribution of the sum of variables is the convolution of their probability mass functions (or densities, in the continuous case).变量总和的分布是它们的概率质量函数(或密度,在连续情况下)的卷积。 Convolution is an n-ary operator, so you can compute it conveniently just two pmf's at a time (the current distribution of the total so far, and the next one in the list).卷积是一个 n 元运算符,因此您可以方便地一次计算两个 pmf(到目前为止总数的当前分布,以及列表中的下一个)。 Then from the final result, you can read off the probabilities for each possible total.然后从最终结果中,您可以读出每个可能总数的概率。 The first element in the result is the probability of the smallest possible total, and the last element is the probability of the largest possible total.结果中的第一个元素是最小可能总数的概率,最后一个元素是最大可能总数的概率。 In between you can figure out which one corresponds to the particular sum you're looking for.在两者之间,您可以找出哪一个对应于您正在寻找的特定总和。

The hard part of this is the convolution, so work on that first.最难的部分是卷积,所以首先要处理它。 It's just a simple summation, but it's just a little tricky to get the limits of the summation correct.这只是一个简单的求和,但要使求和的限制正确,则有点棘手。 My advice is to work with integers or rationals so you can do exact arithmetic.我的建议是使用整数或有理数,以便您可以进行精确的算术运算。

After that you just need to construct an appropriate pmf for each input die.之后,您只需要为每个输入骰子构建一个合适的 pmf。 The input is just [1, 1, 1, ... 1] if you're using integers (you'll have to normalize eventually) or [1/n, 1/n, 1/n, ..., 1/n] if rationals, where n = number of faces.如果您使用整数(最终必须归一化)或 [1/n, 1/n, 1/n, ..., 1] ,则输入仅为 [1, 1, 1, ... 1] /n] 如果有理数,其中 n = 面数。 Also you'll need to label the indices of the output correctly -- again this is just a little tricky to get it right.此外,您还需要正确标记输出的索引——同样,要正确地做到这一点有点棘手。

Convolution is a very general approach for summations of variables.卷积是一种非常通用的变量求和方法。 It can be made even more efficient by implementing convolution via the fast Fourier transform, since FFT(conv(A, B)) = FFT(A) FFT(B).由于 FFT(conv(A, B)) = FFT(A) FFT(B),因此可以通过快速傅立叶变换实现卷积来提高效率。 But at this point I don't think you need to worry about that.但在这一点上,我认为你不需要担心。

If someone still interested in solution which avoids very-very-very long iteration process through all itertools.product Cartesian products, here it is:如果有人仍然对通过所有 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

But you should add caching of probability function results, if you won't - calculation of probability will takes very-very-very long time as well)但是你应该添加probability函数结果的缓存,如果你不这样做 - 概率的计算也需要非常非常非常长的时间)

PS this code is 100% not mine, i took it from the internet, i'm not such smart to product it by myself, hope you'll enjoy it as much as i. PS 这个代码 100% 不是我的,我从互联网上拿来的,我自己制作它不是那么聪明,希望你和我一样喜欢它。

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

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