Sympy具有Die和Coin对象,它们对于理解概率概念非常有用。例如
from sympy.stats import P, Die, density
from sympy import Eq
D = Die('D', 6)
density(D).dict
# {1: 1/6, 2: 1/6, 3: 1/6, 4: 1/6, 5: 1/6, 6: 1/6}
P(D > 3)
# 1/2
我希望能够使用一副纸牌进行类似的计算,例如
deck = DeckOfCards('Cards')
P(Eq(deck, 'AceOfSpades'))
# 1/52
如何用sympy做到这一点?我猜一个选择是
deck = DiscreteUniform('Cards', list(range(52)))
def lookup_card_id(name):
# encode the list, e.g.
# 0 = Ace of Clubs
# 1 = 2 of Clubs
# 2 = 3 of Clubs
# and so on ...
return card_id
P(Eq(deck, lookup_card_id('AceOfClubs'))
# 1/52
这将使我走到现在,但它不支持以下查询:
P(Eq(deck, lookup_card_id('Ace'))
# 1/13
答案 0 :(得分:1)
不幸的是DiscreteUniform似乎无法处理类似的情况
P(Eq(deck, [0, 1, 2]))
or
P(deck in [0, 1, 2])
但是你可以自己做。
from sympy import Eq
from sympy.stats import P, DiscreteUniform
suits = ('Clubs', 'Diamonds', 'Hearts', 'Spades')
numbers = ('Ace', 'Two', 'Three', 'Four', 'Five', 'Six', 'Seven', 'Eight', 'Nine', 'Ten', 'Jack', 'Queen', 'King')
colors = {
'Black': ['Clubs', 'Spades'],
'Red': ['Diamonds', 'Hearts']
}
def get_card_name(suit, number):
return '{number}Of{suit}'.format(number=number, suit=suit)
cards = {}
for sidx, suit in enumerate(suits):
for nidx, number in enumerate(numbers):
name = get_card_name(suit, number)
cards[name] = sidx * 13 + (nidx + 1)
def flatten(list):
return reduce(lambda l, l2: l + l2, list, [])
def lookup_card_id(names):
if isinstance(names, list) or isinstance(names, tuple):
return flatten([lookup_card_id(x) for x in names])
if names in suits:
names_in_suits = [get_card_name(names, x) for x in numbers]
return lookup_card_id(names_in_suits)
if names in numbers:
names_in_numbers = [get_card_name(x, names) for x in suits]
return lookup_card_id(names_in_numbers)
if names in colors:
return lookup_card_id(colors[names])
return [cards[names]]
def prob_pick_card(name):
deck = DiscreteUniform('Cards', list(range(1, 53)))
card_id = lookup_card_id(name)
return sum([P(Eq(deck, x)) for x in card_id])
print(prob_pick_card('AceOfClubs')) # 1/52
print(prob_pick_card('Ace')) # 1/13
print(prob_pick_card('Clubs')) # 1/4
print(prob_pick_card('Black')) # 1/2