【问题标题】:Itertools to create a list and work out probabilityItertools 创建列表并计算概率
【发布时间】:2013-11-28 23:46:52
【问题描述】:

我正在计算“Susie”赢得比赛的概率。

“Susie”赢得比赛的概率 = 0.837
“鲍勃”赢得比赛的概率 = 0.163

如果第一个赢得 n 场比赛的人赢得比赛,那么 n 的最小值是多少,这样 Susie 赢得比赛的机会大于 0.9?

到目前为止,我有这个代码:

import itertools

W = 0.837
L = 0.163
for product in itertools.product(['W','L'], repeat=3): #3=number of games
    print product

哪些打印:

('W', 'W', 'W')
('W', 'W', 'L')
('W', 'L', 'W')
('W', 'L', 'L')
('L', 'W', 'W')
('L', 'W', 'L')
('L', 'L', 'W')
('L', 'L', 'L')

然后我想使用这些结果来计算“Susie”赢得比赛的总体概率。

我已经在纸上解决了这个问题,玩的游戏越多,“Susie”赢得比赛的机会就越大。

【问题讨论】:

  • 您是尝试解析还是近似求解?

标签: python probability itertools


【解决方案1】:

您可以使用字典来获取概率:

import itertools
import operator

probabilities = {'W':0.837, 'L':0.163}

for product in itertools.product(['W','L'], repeat=3): #3=number of games
    p = reduce(operator.mul,
               [probabilities[p] for p in product])
    print product, ":", p

reduce 函数使用第一个参数中给出的函数累加列表的所有元素 - 这里我们通过乘法累加它们。

这为您提供了每个事件序列的概率。从中您可以轻松选择哪个是“Susie 赢得比赛”,并对概率求和。这样做的一种可能性是:

import itertools
import operator

probabilities = {'W':0.837, 'L':0.163}

winProbability = 0
for product in itertools.product(['W','L'], repeat=3): #3=number of games
    p = reduce(operator.mul,
               [probabilities[p] for p in product])

    if product.count('W') > 1: #works only for 3 games
        winProbability += p
        print "Susie wins:", product, "with probability:", p
    else:
        print "Susie looses:", product, "with probability:", p

print "Total probability of Susie winning:", winProbability 

该条件仅适用于 3 游戏,但我真的要把这个留给你 - 很容易将它推广到 n 游戏:)

【讨论】:

  • 为了便于阅读,您可以使用 operator.mul 代替那个 lambda 表达式。
  • 我不得不说你很聪明。非常感谢您的帮助。
【解决方案2】:

您还需要循环遍历n 的值。另请注意,'first to n'与'best out of 2n-1'相同。所以我们可以说m = 2 * n - 1,看看谁在该盘中赢得了最多的比赛。 max(set(product), key=product.count) 是一种简短但不透明的方式来计算谁赢得了最多的比赛。另外,当您可以将值直接存储在元组中时,为什么还要费心用字符串表示概率然后使用字典来读取它们。

import itertools

pWin = 0 #the probability susie wins the match
n = 0
while pWin<0.9:
    n += 1
    m = 2 * n - 1
    pWin = 0
    for prod in itertools.product([0.837,0.163], repeat=m):
        #test who wins the match
        if max(set(prod), key=prod.count) == 0.837:
            pWin += reduce(lambda total,current: total * current, prod)
print '{} probability that Susie wins the match, with {} games'.format(pWin, n)

【讨论】:

    【解决方案3】:

    我对@desired_login 的观点很感兴趣,但我想我会尝试计算排列而不是遍历它们:

    import sys
    if sys.hexversion >= 0x3000000:
        rng = range     # Python 3.x
    else:
        rng = xrange    # Python 2.x
    
    def P(n, k):
        """
        Calculate permutations of (n choose k) items
        """
        if 2*k > n:
            k = n - k
        res = 1
        for i in rng(k):
            res = res * (n-i) // (i+1)
        return res
    
    Ps = 0.837    # Probability of Susie winning one match
    Px = 0.980    # Target probability
    
    # Probability of Susie winning exactly k of n matches
    win_k         = lambda n,k: P(n, k) * Ps**k * (1.0-Ps)**(n-k)
    # Probability of Susie winning k or more of n matches
    win_k_or_more = lambda n,k: sum(win_k(n, i) for i in rng(k, n+1))
    
    def main():
        # Find lowest k such that the probability of Susie winning k or more of 2*k - 1 matches is at least Px
        k = 0
        while True:
            k += 1
            n = 2*k - 1
            prob = win_k_or_more(n, k)
            print('Susie wins {} or more of {} matches: {}'.format(k, n, prob))
            if prob >= Px:
                print('At first to {} wins, Susie has >= {} chance of winning the match.'.format(k, Px))
                break
    
    if __name__=="__main__":
        main()
    

    对于 Px=0.98,这会导致

    Susie wins 1 or more of 1 matches: 0.837
    Susie wins 2 or more of 3 matches: 0.9289544940000001
    Susie wins 3 or more of 5 matches: 0.9665908247127419
    Susie wins 4 or more of 7 matches: 0.9837066988309756
    At first to 4 wins, Susie has >= 0.98 chance of winning the match.
    

    此算法的运行时间类似于 O(n^3),而其他算法的运行时间为 O(2^n)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多