Probabilidade

Definições iniciais

  • Experimento: uma ocorrência com um resultado incerto. Também pode ser chamado "processo". Exemplo: rolar um dado.
  • Resultado: o resultado de um experimento; um "estado" particular do mundo (ambiente). Também pode ser chamado "caso". Exemplo: 4
  • Espaço amostral: o conjunto de todos os resultados possíveis para um experimento. Exemplo: $\{1, 2, 3, 4, 5, 6\}$
  • Evento: um subconjunto do espaço amostral. Exemplo: o evento "dado com face par" é o conjunto dos resultados $\{2, 4, 6\}$
  • Probabilidade: a probabilidade de um evento em relação a um espaço amostral é a quantidade de resultados no evento dividida pela quantidade de resultados no espaço amostral. Como é uma razão, o valor de uma probabilidade será será um número entre $0$ (um evento impossível) e $1$ (um evento certo). Exemplo: a probabilidade do evento "dado com face par" é $3/6 = 1/2 = 0.5$

Código para P

$P()$ é o nome tradicional para a função Probabilidade:


In [187]:
from fractions import Fraction

def P(evento, espaco):
    "A probabilidade de um evento, dado o espaco amostral"
    return Fraction(len(evento & espaco), len(espaco))

O código implementa o conceito "Probabilidade é simplemente uma fração cujo numerador é o número de casos favorávels e cujo denominador é o número de todos os casos possíveis" (Laplace).

Aquecimento: Rolar um dado

Qual é a probabilidade de rolar um dado e a face superior ser um número par? Consideramos, para isso, um dado com seis faces.

Podemos definir o espaço amostral $A$, o evento $par$ e calcular a probabilidade:


In [188]:
A = {1, 2, 3, 4, 5, 6}
par = {2, 4, 6}
P(par, A)


Out[188]:
Fraction(1, 2)

Você pode perguntar: "por que não usar len(evento) ao invés de len(evento & espaco)? Isso é necessário porque não podem ser considerados resultados que não estejam presentes no espaço amostral. Veja só:


In [189]:
par = {2, 4, 6, 8, 10, 12}
P(par, A)


Out[189]:
Fraction(1, 2)

Se considerasse apenas len(evento), o retorno seria outro:


In [190]:
Fraction(len(par), len(A))


Out[190]:
Fraction(1, 1)

Os "casos favoráveis", da definição de Laplace, são a interseção entre par e A, ou seja, $\mbox{evento} \cap A$. Em Python, isso é feito usando o operador &, por isso len(evento & espaco).

Sobre Fraction em Python

O tipo Fraction do Python é usado para representar valores na forma de frações (racional). Por exemplo:


In [191]:
print(Fraction(0.5))
print(Fraction(0.3))
print(Fraction(0.3).limit_denominator()) # usa limit_denominator() para encontrar a fração mais aproximada
print(Fraction(3, 10)) 
print(Fraction(0.3333333))
print(Fraction(0.3333333).limit_denominator()) # limitando o denominador (padrão é max=1000000)
print(float(Fraction(0.3333333))) # convertendo o valor de Fraction() para float()


1/2
5404319552844595/18014398509481984
3/10
3/10
6004798902680711/18014398509481984
1/3
0.3333333

Problemas com urnas

Não estou falando de política! (ok, essa piada foi péssima)

Problemas com urnas surgiram por volta de 1700, com o matemático Jacob Bernoulli. Por exemplo:

  • Uma urna contém 23 bolas: 8 brancas, 6 azuis e 9 vermelhas. Selecionamos seis bolas aleatoriamente (cada seleção com a mesma chance de acontecer). Qual é a probabilidade desses três resultados possíveis:
  1. todas as bolas são vermelhas
  2. 3 são azuis, 2 são vermelhas e 1 é branca
  3. 4 são brancas

Então, um resultado é um conjunto com 6 bolas, enquanto o espaço amostral é o conjunto de todas as possíveis combinações (também conjuntos) com 6 bolas. Antes de continuar a solução, duas questões:

  1. há múltiplas bolas da mesma cor (ex: 8 bolas brancas)
  2. um resultado é um conjunto de bolas, então a ordem dos seus elementos não importa (diferentemente da lista -- ou sequência -- para a qual a ordem importa)

Para a primeira questão, vamos nomear as bolas usando uma letra e um número, assim:

  • as 8 bolas brancas serão chamadas W1 até W8
  • as 6 bolas azuis serão chamadas B1 até B6
  • as 9 bolas vermelhas serão chamadas R1 até R9

Para a segunda questão teremos que trabalhar com permutações e então encontrar combinações, dividindo o número de permutações por $c!$, onde $c$ é o número de bolas em uma combinação.

Por exemplo, se eu precisar escolher 2 bolas de 8 disponíveis, há 8 formas de escolher a primeira, e 7 formas de escolher a segunda. Sendo assim, há $8 \times 7 = 56$ permutações, mas $52/2 = 26$ combinações. Tudo isso porque $\{W1, W2\} = \{W2, W1\}$.

Vamos lá. O código a seguir define o conteúdo da urna:


In [192]:
def cross(A, B):
    "O conjunto de formas de concatenar os itens de A e B (produto cartesiano)"
    return {a + b
            for a in A for b in B
           }

urna = cross('W', '12345678') | cross('B', '123456') | cross('R', '123456789')

urna


Out[192]:
{'B1',
 'B2',
 'B3',
 'B4',
 'B5',
 'B6',
 'R1',
 'R2',
 'R3',
 'R4',
 'R5',
 'R6',
 'R7',
 'R8',
 'R9',
 'W1',
 'W2',
 'W3',
 'W4',
 'W5',
 'W6',
 'W7',
 'W8'}

In [193]:
len(urna)


Out[193]:
23

Agora, vamos definir o espaço amostral, chamado U6, o conjunto de todas as combinações com 6 bolas:


In [194]:
import itertools

def combos(items, n):
    "Todas as combinações de n items; cada combinação concatenada em uma string"
    return {' '.join(combo)
            for combo in itertools.combinations(items, n)
           }

U6 = combos(urna, 6)

len(U6)


Out[194]:
100947

Para não mostrar todos os conjuntos, vamos mostrar uma pequena amostra:


In [195]:
import random

random.sample(U6, 10)


Out[195]:
['W2 W3 W6 R7 W1 W8',
 'B4 R9 W5 B2 R4 R5',
 'W5 R6 R3 W8 W7 R5',
 'W4 W5 R6 W7 R5 B6',
 'B1 W5 R8 W8 R4 W7',
 'B4 R9 B1 B5 R3 B2',
 'W2 W6 R7 R3 W8 B2',
 'W1 R3 W8 R4 R5 B6',
 'B4 R9 W1 B2 B3 B6',
 'R9 W3 W5 R3 B2 B3']

Mas será que o $100,947$ é a quantidade correta de formas de escolher 6 de 23 bolas? Bem, o raciocínio é esse:

  • Escolha uma de 23 (sobram 22)
  • Escolha uma de 22 (sobram 21)
  • ...
  • Escolha seis de 18

Como não ligamos para a ordem (enfim, é um conjunto), então dividimos por $6!$. Isso dá:

\begin{align*} 23 \mbox{ escolha } 6 = \frac{23 \times 22 \times 21 \times 20 \times 19 \times 18}{6!} = 100947 \end{align*}

Note que $23 \times 22 \times 21 \times 20 \times 19 \times 18 = 23!/17!$, então, podemos generalizar:

\begin{align*} n \mbox{ escolha } c = \frac{n!}{c!\times(n - c)!} = \binom{n}{c} \end{align*}

Podemos traduzir isso para código, assim:


In [196]:
from math import factorial

def escolha(n, c):
    "Número de formas de escolher c itens de uma lista com n items"
    return factorial(n) // (factorial(c) * factorial(n - c))

escolha(23, 6)


Out[196]:
100947

Agora podemos resolver vários problemas.

Problema 1: qual a probabilidade de selecionar 6 bolas vermelhas?


In [197]:
red6 = {s for s in U6 if s.count('R') == 6}

P(red6, U6)


Out[197]:
Fraction(4, 4807)

ou


In [198]:
len(red6)


Out[198]:
84

Por que 84 formas? Por que há 9 bolas vermelhas na urna, então estamos querendo saber quantas são as formas de escolher 6 delas:


In [199]:
escolha(9, 6)


Out[199]:
84

Então a probabilidade de selecionar 6 bolas vermelhas da urna é escolha(9, 6) dividido pelo tamanho do espaço amostral:


In [200]:
P(red6, U6) == Fraction(escolha(9, 6), len(U6))


Out[200]:
True

Problema 2: qual a probabilidade de escolher 3 azuis, 2 brancas 1 vermelha?


In [201]:
b3w2r1 = {s for s in U6 if s.count('B') == 3 and s.count('W') == 2 and s.count('R') == 1}

P(b3w2r1, U6)


Out[201]:
Fraction(240, 4807)

Podemos encontrar o mesmo resultado contando de quantas formas podemos escolher 3 de 6 azuis, 2 de 8 brancas, 1 de 9 vermelhas e dividindo o resultado pelo tamanho do espaço amostral:


In [202]:
P(b3w2r1, U6) == Fraction(escolha(6, 3) * escolha(8, 2) * escolha(9, 1), len(U6))


Out[202]:
True

O raciocínio seguinte também é válido:

  • há 6 formas de encontrar a primeira bola azul
  • há 5 formas de encontrar a segunda azul
  • há 4 formas de encontrar a terceira azul
  • há 8 formas de encontrar a primeira bola branca
  • há 7 formas de encontrar a segunda branca
  • há 9 formas de encontrar a bola vermelha

Como $\{B1, B2, B3\} = \{B3, B2, B1\}$ e $\{W1, W2\} = \{W2, W1\}$, teríamos:

\begin{align*} \frac{(6 \times 5 \times 4) \times (8 \times 7) \times (9)}{3! \times 2! \times |A|} \end{align*}

In [203]:
P(b3w2r1, U6) == Fraction((6 * 5 * 4) * (8 * 7) * 9, 
                           factorial(3) * factorial(2) * len(U6))


Out[203]:
True

Problema 3: Qual a probabilidade de termos exatamente 4 bolas brancas?

Podemos encontrar a resposta usando os mesmos raciocínios anteriores:


In [204]:
w4 = {s for s in U6 if
      s.count('W') == 4}

P(w4, U6)


Out[204]:
Fraction(350, 4807)

In [205]:
P(w4, U6) == Fraction(escolha(8, 4) * escolha(15, 2),
                      len(U6))


Out[205]:
True

In [206]:
P(w4, U6) == Fraction((8 * 7 * 6 * 5) * (15 * 14),
                      factorial(4) * factorial(2) * len(U6))


Out[206]:
True

Esse último raciocínio, em particular, é interpretado assim:

  • 8 escolhas para a primeira bola
  • 7 escolhas para a segunda
  • 6 escolhas para a terceira
  • 5 escolhas para a segunda
  • 15 escolhas para as outras bolas (não brancas)
  • 14 escolhas para as outras bolas (não brancas restantes)

Ou seja:

\begin{align*} \frac{(8 \times 7 \times 6) \times (15 \times 14)}{4! \times 2! \times |A|} \end{align*}

Revisando a função P, com eventos mais gerais

Até o momento, para calcular a probabilidade de um dado com face par, usamos:

par = {2, 4, 6}

Mas enumerar um conjunto pequeno é fácil, o difícil seria enumerar um conjunto maior. Assim:


In [207]:
def P(evento, espaco):
    """A probabilidade de um evento, dado um espaco amostral. 
    evento pode ser um conjunto ou um predicado"""
    if callable(evento):
        evento = tal_que(evento, espaco)
    return Fraction(len(evento & espaco), len(espaco))

def tal_que(predicado, colecao):
    "O subconjunto de elementos da colecao para os quais o predicado é verdadeiro"
    return {e for e in colecao if predicado(e)}

Vamos verificar como isso se comporta.


In [208]:
def eh_par(n):
    return n % 2 == 0

P(eh_par, A)


Out[208]:
Fraction(1, 2)

In [209]:
D12 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}

tal_que(eh_par, D12)


Out[209]:
{2, 4, 6, 8, 10, 12}

In [210]:
P(eh_par, D12)


Out[210]:
Fraction(1, 2)

Isso permite coisas interessantes. Por exemplo, como determinar a probabilidade de que a soma de três dados é um número primo?


In [211]:
A3 = {(a1, a2, a3) for a1 in A for a2 in A for a3 in A}

def soma_eh_primo(r): return eh_primo(sum(r))

def eh_primo(n): return n > 1 and not any(n % i == 0 for i in range(2, n))

P(soma_eh_primo, A3)


Out[211]:
Fraction(73, 216)

Problemas com cartas

Definimos o problema assim:

  • 4 naipes: copas (C), ouro (O), paus (P) e espadas (E) (no inglês: hearts (H), diamond (D), clubs (C) and spades (S))
  • 13 graus: Ás, 2, 3, 4, 5, 6, 7, 8, 9, 10 (ou T), J, Q, K

O baralho possui 52 cartas.


In [212]:
naipes = 'SHDC'
graus = 'A23456789TJQK'
baralho  = cross(graus, naipes)
len(baralho)


Out[212]:
52

Qual a quantidade de jogadas (mãos) com 5 cartas?


In [213]:
jogadas = combos(baralho, 5)

print(len(jogadas) == escolha(52, 5))

random.sample(jogadas, 5)


True
Out[213]:
['3C 3H 8H 2H AC',
 '8C KS 5C 2H 3S',
 'JS 6C JD KH JC',
 '7H 7C 9D 9H KH',
 '5S TC 5D 5C 4C']

Qual a probabilidade de dar 'flush' (5 cartas do mesmo naipe)?


In [214]:
def flush(jogada):
    return any(jogada.count(n) == 5 for n in naipes)

P(flush, jogadas)


Out[214]:
Fraction(33, 16660)

Ou... qual a probabilidade de dar 'four of a kind'?


In [215]:
def four_kind(jogada):
    return any(jogada.count(g) == 4 for g in graus)

P(four_kind, jogadas)


Out[215]:
Fraction(1, 4165)

Fermat e Pascal: Apostas, Triângulos e o nascimento da Probabilidade

Considere um jogo de apostas, consistindo do [simples] fato de jogar uma moeda. Dois jogadores: H aposta em cara; e T aposta em coroa. Ganha o jogador que conseguir 10 acertos primeiro. Se o jogo for interrompido quando H tiver acertado 8 e T, acertado 7? Como dividir o pote de dinheiro? Fermat e Pascam trocaram correspondências sobre esse problema, o que pode ser lido aqui.

Podemos resolver o problema com as ferramentas que temos:


In [216]:
def ganhar_jogo_incompleto(h_pontos, t_pontos):
    "A probabilidade de que H vai ganhar o jogo não terminado, dados os pontos necessários para H e T ganharem."
    def h_ganha(r): return r.count('h') >= h_pontos
    return P(h_ganha, continuacoes(h_pontos, t_pontos))

def continuacoes(h_pontos, t_pontos):
    "Todas as continuações possíveis quando H precisa de `h_pontos` e T precisa de `t_pontos`"
    rodadas = ['ht' for _ in range(h_pontos + t_pontos - 1)]
    return set(itertools.product(*rodadas))

continuacoes(2, 3)


Out[216]:
{('h', 'h', 'h', 'h'),
 ('h', 'h', 'h', 't'),
 ('h', 'h', 't', 'h'),
 ('h', 'h', 't', 't'),
 ('h', 't', 'h', 'h'),
 ('h', 't', 'h', 't'),
 ('h', 't', 't', 'h'),
 ('h', 't', 't', 't'),
 ('t', 'h', 'h', 'h'),
 ('t', 'h', 'h', 't'),
 ('t', 'h', 't', 'h'),
 ('t', 'h', 't', 't'),
 ('t', 't', 'h', 'h'),
 ('t', 't', 'h', 't'),
 ('t', 't', 't', 'h'),
 ('t', 't', 't', 't')}

In [217]:
ganhar_jogo_incompleto(2, 3)


Out[217]:
Fraction(11, 16)

O resultado foi confirma o encontrado por Pascal e Fermat.

Resultados não equiprováveis: Distribuições de probabilidade

Até aqui, lidamos com casos em que a probabilidade de um retorno no espaço amostral é a mesma (uniforme). No mundo real, isso não é sempre verdade. Por exemplo, a probabilidade de uma criança ser uma menina não é exatamente 1/2, e a probabilidade é um pouco diferente para a segunda criança. Uma pesquisa encontrou as seguintes contagens de famílias com dois filhos na Dinamarca (GB significa uma família em que o primeiro filho é uma garota e o segundo filho é um menino):

GG: 121801     GB: 126840
BG: 127123     BB: 135138

Vamos introduzir mais três definições:

  • Frequência: um número que descreve o quão frequente um resultado ocorre. Pode ser uma contagem, como 121801, ou uma razão, como 0,515
  • Distribuição: um mapeamento de resultado para frequência, para cada resultado no espaço amostral.
  • Distribuição de Probabilidade: uma distribuição que foi normalizada de tal forma que a soma das frequências é 1

Definimos a classe ProbDist (um subtipo do dict do Python):


In [218]:
class ProbDist(dict):
    "Uma distribuição de probablidade; um mapeamento {resultado: probabilidade}"
    def __init__(self, mapping=(), **kwargs):
        self.update(mapping, **kwargs)
        total = sum(self.values())
        for outcome in self:
            self[outcome] = self[outcome]/total
            assert self[outcome] >= 0

Também redefinimos as funções P e tal_que:


In [219]:
def P(evento, espaco):
    """A probabilidade de um evento, dado um espaço amostral de resultados equiprováveis.
    evento: uma coleção de resultados, ou um predicado.
    espaco: um conjunto de resultados ou a distribuicao de probabilidade na forma de pares {resultado: frequencia}.
    """
    if callable(evento):
        evento = tal_que(evento, espaco)
    if isinstance(espaco, ProbDist):
        return sum(espaco[o] for o in espaco if o in evento)
    else:
        return Fraction(len(evento & espaco), len(espaco))
    
def tal_que(predicado, espaco):
    """Os resultados no espaço amostral para os quais o predicado é verdadeiro.
    Se espaco é um conjunto, retorna um subconjunto {resultado, ...}
    Se espaco é ProbDist, retorna um ProbDist{resultado, frequencia}"""
    if isinstance(espaco, ProbDist):
        return ProbDist({o:espaco[o] for o in espaco if predicado(o)})
    else:
        return {o for o in espaco if predicado(o)}

Aqui está a distribuição de probabilidade para as famílias Dinamarquesas com dois filhos:


In [220]:
DK = ProbDist(GG=121801, GB=126840, BG=127123, BB=135138)

DK


Out[220]:
{'BB': 0.2645086533229465,
 'BG': 0.24882071317004043,
 'GB': 0.24826679089140383,
 'GG': 0.23840384261560926}

Vamos entender o resultado por partes. Para isso, alguns predicados:


In [221]:
def primeiro_menina(r): return r[0] == 'G'
def primeiro_menino(r): return r[0] == 'B'
def segundo_menina(r): return r[1] == 'G'
def segundo_menino(r): return r[1] == 'B'
def duas_meninas(r): return r == 'GG'
def dois_meninos(r): return r == 'BB'

In [222]:
P(primeiro_menina, DK)


Out[222]:
0.4866706335070131

In [223]:
P(segundo_menina, DK)


Out[223]:
0.4872245557856497

Isso indica que a probabilidade de uma criança ser menina está entre 48% e 49%, mas isso é um pouco diferente entre o primeiro e o segundo filhos.


In [224]:
P(segundo_menina, tal_que(primeiro_menina, DK)), P(segundo_menina, tal_que(primeiro_menino, DK))


Out[224]:
(0.4898669165584115, 0.48471942072973107)

In [225]:
P(segundo_menino, tal_que(primeiro_menina, DK)), P(segundo_menino, tal_que(primeiro_menino, DK))


Out[225]:
(0.5101330834415885, 0.5152805792702689)

Isso diz que é mais provável que o sexo do segundo filho seja igual ao do primeiro cerca de 50%.

Mais problemas de Urnas: M&Ms e Bayes

Outro problema de urna (Allen Downey):

O M&M azul foi introduzido em 1995. Antes disso, a mistura de cores em um pacote de M&Ms era formado por: 30% marrom, 20% amarelo, 20% vermelho, 10% verde, 10% laranja, 10% tostado. Depois, ficou: 24% azul, 20% verde, 16% laranja, 14% amarelo, 14% vermelho, 13% marrom. Um amigo meu possui dois pacotes de M&Ms e ele me diz que um é de 1994 e outro é de 1996. Ele não me diz qual é qual, mas me dá um M&M de cada pacote. Um é amarelho e outro é verde. Qual a probabilidade de que o M&M amarelo seja do pacote de 1994?

Para resolver esse problema, primeiro representamos as distribuições de probabilidade de cada pacote:


In [226]:
bag94 = ProbDist(brown=30, yellow=20, red=20, green=10, orange=10, tan=10)
bag96 = ProbDist(blue=24, green=20, orange=16, yellow=14, red=13, brown=13)

A seguir, definimos MM como a probabilidade conjunta -- o espaço amostral para escolher um M&M de cada pacote. O resultado yellow green significa que um M&M amarelo foi selecionado do pacote de 1994 e um verde, do pacote de 1996.


In [227]:
def joint(A, B, sep=''):
    """A probabilidade conjunta de duas distribuições de probabilidade independentes. 
    Resultado é todas as entradas da forma {a+sep+b: P(a)*P(b)}"""
    return ProbDist({a + sep + b: A[a] * B[b]
                    for a in A
                    for b in B})

MM = joint(bag94, bag96, ' ')
MM


Out[227]:
{'brown blue': 0.07199999999999998,
 'brown brown': 0.03899999999999999,
 'brown green': 0.059999999999999984,
 'brown orange': 0.04799999999999999,
 'brown red': 0.03899999999999999,
 'brown yellow': 0.041999999999999996,
 'green blue': 0.023999999999999994,
 'green brown': 0.012999999999999998,
 'green green': 0.02,
 'green orange': 0.015999999999999997,
 'green red': 0.012999999999999998,
 'green yellow': 0.013999999999999999,
 'orange blue': 0.023999999999999994,
 'orange brown': 0.012999999999999998,
 'orange green': 0.02,
 'orange orange': 0.015999999999999997,
 'orange red': 0.012999999999999998,
 'orange yellow': 0.013999999999999999,
 'red blue': 0.04799999999999999,
 'red brown': 0.025999999999999995,
 'red green': 0.04,
 'red orange': 0.031999999999999994,
 'red red': 0.025999999999999995,
 'red yellow': 0.027999999999999997,
 'tan blue': 0.023999999999999994,
 'tan brown': 0.012999999999999998,
 'tan green': 0.02,
 'tan orange': 0.015999999999999997,
 'tan red': 0.012999999999999998,
 'tan yellow': 0.013999999999999999,
 'yellow blue': 0.04799999999999999,
 'yellow brown': 0.025999999999999995,
 'yellow green': 0.04,
 'yellow orange': 0.031999999999999994,
 'yellow red': 0.025999999999999995,
 'yellow yellow': 0.027999999999999997}

Primeiro, o predicado que trata "um é amarelho e o outro é verde":


In [228]:
def yellow_and_green(r): return 'yellow' in r and 'green' in r

tal_que(yellow_and_green, MM)


Out[228]:
{'green yellow': 0.25925925925925924, 'yellow green': 0.7407407407407408}

Agora podemos responder a pergunta: dado que tivemos amarelo e verde (mas não sabemos sabemos qual vem de qual pacote), qual é a probabilidade de que o amarelo tenha vido do pacote de 1994?


In [229]:
def yellow94(r): return r.startswith('yellow')

P(yellow94, tal_que(yellow_and_green, MM))


Out[229]:
0.7407407407407408

Então, há 74% de chance de que o amarelo tenha vindo do pacote de 1994.

A forma de resolver o problema foi semelhante ao que já vínhamos fazendo: criar um espaço amostral, usar P para escolher a probabilidade do evento em questão, dado que sabemos sobre o retorno.

Poderíamos usar o Teorema de Bayes, mas por que? Porque queremos saber a probabilidade de um evento dada uma evidência, que não está imediatamente disponível; entretanto, a probabilidade da evidência dado o evento está [disponível].

Antes de ver as cores dos M&Ms, há duas hipóteses, A e B, ambas com igual probabilidade:

A: primeiro M&M do pacote de 1994, segundo do pacote de 1996
B: primeiro M&M do pacote de 1996, segundo do pacote de 1994
\begin{align*} P(A) = P(B) = 0.5 \end{align*}

Então, temos uma evidência:

E: primeiro M&M amarelo, depois verde

Queremos saber a probabilidade da hipótese A, dada a evidência E: $P(A \mid E)$.

Isso não é fácil de calcular (exceto numerando o espaço amostral), mas o Teorema de Bayes diz:

\begin{align*} P(A \mid E) = \frac{P(E \mid A) \times P(A)}{P(E)} \end{align*}

As quantidades do lado direito são mais fáceis de calcular:

\begin{align*} P(E \mid A) &= P(Yellow94) \times P(Green96) &= 0.20 \times 0.20 &= 0.04 \\ P(E \mid B) &= P(Yellow96) \times P(Green94) &= 0.10 \times 0.14 &= 0.014 \\ P(A) &= 0.5 \\ P(B) &= 0.5 \\ P(E) &= P(E \mid A) \times P(A) + P(E \mid B) \times P(B) \\ &= 0.04 \times 0.5 + 0.014 \times 0.5 = 0.027 \end{align*}

O resultado final:

\begin{align*} P(A \mid E) &= \frac{P(E \mid A) \times P(A)}{P(E)} \\ &= \frac{0.4 \times 0.5}{0.027} \\ &= 0.7407407407 \end{align*}

Então é isso. Você tem uma escolha: O Teorema de Bayes permite fazer menos cálculos, mas usa mais álgebra; é melhor custo-benefício se você estiver trabalhando com lápis e papel. Por outro lado, enumerar o espaço amostrar usa menos álgebra, pelo custo de requerer mais cálculos; é melhor custo-benefício se você estiver usando um computador. Idependentemente da abordagem utilizada, é importante conhecer o Teorema de Bayes e como ele funciona.

Mais importante ainda: você comeria M&Ms de 20 anos?