Simulacion de problema de Monty Hall

Buenas, en esta ocasión presento una simulación del conocido problema de Monty Hall. En los últimos días este problema ocupó mucho tiempo de mi cabeza porque si bien no tengo duda sobre el me confundian algunas cosas. Para aclararlas decidí hacer esta simulación y me dio algunas nociones interesantes.

Una simulación es una forma de encontrar una respuesta a un problema que depende de muchas variables, los tiempos humanos y/o computacionales implicados en el cálculo son muy extensos o simplemente no se conoce una resolución efectiva y se aproxima mediante esta técnica.

En este caso no seguí ningún modelo específico de simulación pero podríamos decir que se aproxima mucho al método de Montecarlo.

El problema de Monty Hall lo pueden leer en wikipedia: Monty Hall

Hasta hace unos días no tenía duda alguna con este problema hasta que me lo puse a pensar detenidamente, hice los cálculos mediante Bayes y empezó a darme algunos valores que me parecieron interesantes así que me dispuse a hacer este programa.

Las variables a simular son:

  • El orden de las puertas (puertas[]).
  • La primer elección (eleccion1).
  • La segunda elección (cambia eleccion)
Todas con una distribución uniforme, es decir la misma probabilidad para todos los valores posibles.

Los valores finales se recogen en las siguientes variables y seguidamente se calculan los estimadores finales:

  • Cantidad de aciertos con la primer eleccion (quedaconprimerpuerta).
  • Cantidad de aciertos con la segunda eleccion (eligesegundaopcion).
  • Cantidad de desaciertos con la primer eleccion (err1).
  • Cantidad de desaciertos con la segunda eleccion (err2)
La cantidad de itearaciones esta definida por la variable iteraciones y el número de puerta ganadora esta definido con la variable puerta.

Este es el codigo:

# Simulacion de problema de Monty Hall
# Por Mariano Maccarrone
# http://10mp.net

import os
import random


#Numero de puerta ganadora
numero = 2
#Cantidad de aciertos en primer eleccion
quedaconprimerpuerta = 0
#Cantidad de aciertos en segunda eleccion
eligesegundaopcion = 0
#Cantidad de desaciertos de primer eleccion
err1 = 0
#Cantidad de desaciertos de segunda eleccion
err2 = 0
#Cantidad de iteraciones
iteraciones = 1000000

for i in range(iteraciones):

        #Define puertas
        puertas = [1,2,3]

        #Mezcla puertas
        random.seed(ord(os.urandom(1)))
        random.shuffle(puertas)

        #Primera eleccino
        eleccion = random.randint(0,2)

        #Define si cambia de eleccion. Notar que es una probabilidad de .5 para las dos opciones
        cambiaeleccion = random.randint(0,1)

        #Si cambia de eleccion
        if cambiaeleccion == 0:

                #En el while se elige una puerta que no tenga el premio y no sea la elegida en la
                #primer eleccion para mostrarla. Seguidamente se igualan a 5 la puerta mostrada y
                #primer eleccion para comparar la que queda si es igual a numero
                condicion = True
                while condicion:
                        puertavista = random.randint(0,2)
                        if puertavista != eleccion and puertas[puertavista] != numero:
                                puertas[puertavista] = 5
                                puertas[eleccion] = 5
                                condicion = False
                hayerror=0

                #revisa si la puerta que no tiene 5 es igual a numero, setea hay error en 1 si
                #x == numero y suma el contador de aciertos
                for x in puertas:
                        if x == numero:
                                eligesegundaopcion += 1
                                hayerror = 1
                #si hay error suma el contador de errores
                if hayerror != 1:
                        err2 += 1


        #si no cambia de eleccion
        else:
                #si la eleccion es igual a numero suma el contador de aciertos si no suma el de 
                #errores
                if puertas[eleccion] == numero:
                        quedaconprimerpuerta += 1
                else:
                        err1 += 1

#calcula e imprime porcentajes, probabilidades y resultados totales
print "Solo Acertadas:\n   Primer opcion:",str(quedaconprimerpuerta*100.00/(quedaconprimerpuerta+eligesegundaopcion))+"%\n Segunda opcion:",str(eligesegundaopcion*100.00/(quedaconprimerpuerta+eligesegundaopcion))+"%"

print "Acertadas/Perdidas parciales:\n   Acertada Primer opcion:",str(quedaconprimerpuerta*100.00/(quedaconprimerpuerta+err1))+"%\n   Acertada Segunda opcion:", str(eligesegundaopcion*100.00/(eligesegundaopcion+err2))+"%\n   Perdida Primer opcion:",str(err1*100.00/(quedaconprimerpuerta+err1))+"%\n   Perdida Segunda opcion:", str(err2*100.00/(eligesegundaopcion+err2))+"%"

print "Acertadas + Perdidas:\n   Primer opcion:",str(quedaconprimerpuerta*100.00/(quedaconprimerpuerta+eligesegundaopcion+err1+err2))+"%\n   Segunda opcion:",str(eligesegundaopcion*100.00/(quedaconprimerpuerta+eligesegundaopcion+err1+err2))+"%\n   Perdidas:",str((err1+err2)*100.00/(quedaconprimerpuerta+eligesegundaopcion+err1+err2))+"%\n   Perdidas 1:",str(err1*100.00/(quedaconprimerpuerta+eligesegundaopcion+err1+err2))+"%\n   Perdidas 2:",str(err2*100.00/(quedaconprimerpuerta+eligesegundaopcion+err1+err2))+"%"

print "Totales:\n   Primer opcion:" , str(quedaconprimerpuerta) + "\n   Segunda opcion:" , str(eligesegundaopcion) +"\n   Perdidas:", str(err1+err2)

El código esta bien comentado, no hace falta hacer más explicaciones

Cuando se ejecuta con un millón de iteraciones se obtiene una salida similar a esta:

$ python montyhall.py 
Solo Acertadas:
   Primer opcion: 33.1199784205%
   Segunda opcion: 66.8800215795%
Acertadas/Perdidas parciales:
   Acertada Primer opcion: 37.6000997443%
   Acertada Segunda opcion: 63.9451320945%
   Perdida Primer opcion: 62.3999002557%
   Perdida Segunda opcion: 36.0548679055%
Acertadas + Perdidas:
   Primer opcion: 17.1896%
   Segunda opcion: 34.7114%
   Perdidas: 48.099%
   Perdidas 1: 28.5273%
   Perdidas 2: 19.5717%
Totales:
   Primer opcion: 171896
   Segunda opcion: 347114
   Perdidas: 480990

Conclusiones:

  • Se observa que la probabilidad de ganar manteniendo la primer elección es 0,33 y cambiando es 0,66

  • Si tomamos las acertadas más los errores de cada elección (parciales) vemos que cuando se elige cambiar de puerta practicamente se intercambian las probabilidades (en la primer puerta la probabilidad de ganar/perder es 0,37/0,62 pero si cambiamos de puerta es 0,63/0,36)

  • Los números anteriores pueden confundir, la progabilidad general de ganar el juego con la primer puerta son 0.17, con la segunda 0.34, la probabilidad de perder es 0,48.

  • La probabilidad general de ganar es 0.52, lo cual es un aumento considerable comparado con un juego en el que solo se puede elegir una puerta, donde la probabilidad de ganar es 0.33 y 0.66 de perder

Espero que les haya parecido interesante, si tienen duda, comentario, correcciones o algo dejen un comentario más abajo

Comentarios