簡體   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