首页 > 解决方案 > 如何执行选择两个项目而不替换的乘法规则?

问题描述

我正在尝试用 sympy 来重现一个盒子有三个弹珠的例子:

随机抽取两颗弹珠,不更换。

问:先画红色大理石再画白色大理石的几率是多少?

我已经能够使用乘法规则通过硬编码P() 实例来计算这一点,该实例在选择第一个弹珠之前包装初始分布,然后在选择第二个弹珠之前的分布:

from sympy.stats import DiscreteUniform, density, P
from sympy import symbols, Eq

# Coloured marbles
R, W, B = symbols('R W B') 

# Select first marble without replacement
PFirstSelection  = P(Eq(DiscreteUniform('FirstSeletion',   (R, W, B)), R))

# Select second marble - Red is not longer available because it was selected without replacement
PSecondSelection = P(Eq(DiscreteUniform('SecondSelection', (W, B)   ), W)) 

print(PFirstSelection)
# 1/3

print(PSecondSelection)
# 1/2

# Multiplication rule
print(PFirstSelection * PSecondSelection)
# 1/6

有没有更好的方法可以通过 sympy 实现这一目标?

标签: sympy

解决方案


在这种情况下,您最好使用组合功能。

DiscreteUniform 似乎不适用于在创建后更改元素。

from sympy.functions.combinatorial.numbers import nC, nP

print(1 / nP(3, 2)) # 1/6

如果你不在乎订单,

print(nP(2, 2) / nP(3, 2)) # 1/3

已编辑。(也针对python3进行了修改)

对于 M 件事情中的 N 件,您可以简单地执行以下操作

from sympy.functions.combinatorial.numbers import nC, nP

def pickProb(candidates, picks, ordered=False):
    picks_num = len(picks)
    numerator = nP(picks_num, picks_num) if ordered else 1
    denominator = nP(len(candidates), picks_num)
    return numerator / denominator

print(pickProb('RWB', 'RW')) # 1/6
print(pickProb('RWBrwba', 'Ra')) # 1/42
print(pickProb('RWBrwba', 'RWa')) # 1/210
print(pickProb('RWBrwba', 'RWa', ordered=True)) # 1/35

并且组合函数还可以处理重复项,例如“R”、“R”、“W”、“B”。

from operator import mul
from sympy.functions.combinatorial.numbers import nC, nP

def pickProb(candidates, picks):
    picks_num = len(picks)
    c_counts = {}
    for c in candidates:
        c_counts[c] = c_counts[c] + 1 if c in c_counts else 1
    p_counts = {}
    for p in picks:
        p_counts[p] = p_counts[p] + 1 if p in p_counts else 1
    combinations = reduce(mul, [nP(c_counts[x], p_counts[x]) for x in p_counts.keys()], 1)
    denominator = nP(len(candidates), picks_num) / combinations
    return 1 / denominator

print(pickProb('RWBra', 'RWa')) # 1/60
print(pickProb('RRRWa', 'RWa')) # 1/20
print(pickProb('RRRWa', 'RRa')) # 1/10

DiscreteUniform不能,因为这种情况不是“统一的”。

from sympy.stats import DiscreteUniform, density, P, Hypergeometric
from sympy import Symbol, Eq

deck = DiscreteUniform('M', 'RRWB')
print(density(deck).dict) # {W: 1/4, R: 1/4, B: 1/4}
print(P(Eq(deck, Symbol('R')))) # 1/4

推荐阅读