Itertools创建一个列表并计算出概率

时间:2013-11-28 23:46:52

标签: python probability itertools

我正试图找出'苏西'赢得比赛的可能性。

'苏西'赢得比赛的可能性= 0.837
“鲍勃”赢得比赛的可能性= 0.163

如果第一个赢得n场比赛的人赢了一场比赛,那么苏的最小值是多少,以便有超过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'赢得比赛的机会就越大。

3 个答案:

答案 0 :(得分: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函数使用第一个参数中给出的函数累积列表的所有元素 - 这里我们通过乘法累加它们。

这为您提供了每个事件序列的概率。从这里你可以很容易地选择哪一个是“苏西赢得比赛”,并总结概率。这样做的一种可能性是:

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个游戏:)

答案 1 :(得分:1)

您还需要循环n的值。另请注意,“首先n”与“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)

答案 2 :(得分:0)

我被@ 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)。