domingo, 31 de outubro de 2010

Problema 4.15

Este problema coloca basicamente a questão de saber como é que simulamos os lançamentos. A resposta, simples, consiste em usar o método randint do módulo random. O resto é o padrão básico de repetição um número de vezes fixo e conhecido, que se traduz pelo uso de um ciclo for.

def moeda_ao_ar(n):
"""Avalia o número de caras e coroas após n lançamentos de uma moeda. """
conta_caras = 0
conta_coroas = 0
for i in range(n):
valor = random.randint(0,1)
if valor == 0:
conta_caras = conta_caras + 1
else:
conta_coroas = conta_coroas + 1
return (conta_caras, conta_coroas)

Existe uma coisa que todos sabemos. Se a moeda não estiver enviesada, então podemos contar com 50% de probabilidades para num lançamento sair caras. Mas será mesmo assim? Para o saber façamos uma pequena experiência. Lançamos a moeda ao ar um certo número de vezes e contamos quantas vezes saiu caras. Mas repetimos esta experiência várias vezes e, de cada vez, anotamos o número de caras que saiu.

Com estes valores guardados podemos fazer um gráfico com a frequência dos valores obtidos. Se tudo bater certo com a teoria, esperamos obter uma distribuição em que o valor médio é o número que a teoria nos indica. Assim, se atiramos a moeda ao ar 10 vezes, repetindo a experiência 100 vezes, esperamos ter visto no final de toda a experiência 5 caras a maior parte das vezes. É claro que algumas vezes será menos e noutras mais. Vamos ver.

Caso de 100 experiências com 10 lançamentos em cada uma.



Agora 5000 experiências com 1000 lançamentos em cada uma.




Como se vê claramente, no primeiro caso temos um valor médio de 5 e, no segundo, de 500. Além disso, reparamos na forma da curva da distribuição, a forma de um sino. É isso mesmo, estamos perante uma distribuição normal, ou gaussiana!

Mas como obtivemos as imagens? Com o Python, claro! Para já mostro o código. Nas próximas aulas vão perceber o que ele significa e como podem começar a resolver questões semelhantes.

from operator import itemgetter
from pylab import *
import random


def moeda(vezes, numero):
# calcula
caras = {}
for i in range(vezes):
ca, co = moeda_ao_ar(numero)
caras[ca]= caras.get(ca,0) + 1
# visualiza
chaves, valores = split_dic(caras)
ver(chaves,valores)

def moeda_ao_ar(n):
"""Avalia o número de caras e coroas após n lançamentos de uma moeda. """
conta_caras = 0
conta_coroas = 0
for i in range(n):
valor = random.randint(0,1)
if valor == 0:
conta_caras = conta_caras + 1
else:
conta_coroas = conta_coroas + 1
return (conta_caras, conta_coroas)

def split_dic(dicio):
"""
Separa um dicionário numa lista com duas listas: chaves e valores.
A separação é feita de modo a ter as listas ordenadas pelas chaves.
"""
lista = dicio.items()
lista.sort(key=itemgetter(0))
chaves = [ chave for chave,valor in lista]
valores = [ valor for chave,valor in lista]
return chaves,valores


def ver(x,y):
"""Faz um plot simples."""
title('Distrib. Caras')
xlabel('Valor')
ylabel('Freq.')
plot(x,y)
show()

7 comentários:

  1. É natural que não mostre nada. É que o código apresentado apenas define a solução. Você não está a CHAMAR/USAR nenhuma função. Para que funcione tem que adicionar no final ao código a chamada. Por exemplo,

    moeda(100,20)

    Neste caso vai ver o resultado de repetir 100 vezes o lançamento de 20 moedas.

    Note ainda que usei Python 2.7. Se usar Python 3 (3.2, por exemplo) terá que alterar a definição de split_dic para:

    def split_dic(dicio):
    """
    Separa um dicionário numa lista com duas listas: chaves e valores.
    A separação é feita de modo a ter as listas ordenadas pelas chaves.
    """
    lista = list(dicio.items()) # <--- Aqui está a diferença de 2.7 para 3.2.
    lista.sort(key=itemgetter(0))
    chaves = [ chave for chave,valor in lista]
    valores = [ valor for chave,valor in lista]
    return chaves,valores

    espero que tente de novo e ... funcione.

    ResponderEliminar
    Respostas
    1. Este comentário foi removido pelo autor.

      Eliminar
    2. Como o código não está indentado não dá para perceber bem. pode enviar o ficheiro mesmo em anexo num email (.py) para eu ver? Já agora: que versão de Python esta a usar e com que sistema operativo (Windows, Linux, Mac)?

      Eliminar
  2. agora plota, mas plota varias vezes, tantas quanto for colocado dentro do atributo da moeda. ex moeda(10,20), fecho o gráfico e ele continua plotando, ou seja tenho que fechar 10 vezes o gráfico.

    ResponderEliminar
    Respostas
    1. Isso não faz muito sentido. Pode enviar-me o código por email para ernesto@dei.uc.pt para eu analisar?

      Eliminar
    2. Como disse no email o seu erro foi colocar a chamada da função que visualiza dentro do ciclo for na função moeda.

      Eliminar