5 people like it.

Bayesian Monte Carlo of Let's Make a Deal

This code illustrates Bayes' Theorem in action on the Let's Make a Deal problem (aka Monty Hall Problem), which several authors have used to illustrate Bayes' Theorem. (It's easy to search the internet for further explanation.) Run with the audit option to audit up to the first 100 games. Running without audit is faster and can simulate a couple billion games.

  1: 
  2: 
  3: 
  4: 
  5: 
  6: 
  7: 
  8: 
  9: 
 10: 
 11: 
 12: 
 13: 
 14: 
 15: 
 16: 
 17: 
 18: 
 19: 
 20: 
 21: 
 22: 
 23: 
 24: 
 25: 
 26: 
 27: 
 28: 
 29: 
 30: 
 31: 
 32: 
 33: 
 34: 
 35: 
 36: 
 37: 
 38: 
 39: 
 40: 
 41: 
 42: 
 43: 
 44: 
 45: 
 46: 
 47: 
 48: 
 49: 
 50: 
 51: 
 52: 
 53: 
 54: 
 55: 
 56: 
 57: 
 58: 
 59: 
 60: 
 61: 
 62: 
 63: 
 64: 
 65: 
 66: 
 67: 
 68: 
 69: 
 70: 
 71: 
 72: 
 73: 
 74: 
 75: 
 76: 
 77: 
 78: 
 79: 
 80: 
 81: 
 82: 
 83: 
 84: 
 85: 
 86: 
 87: 
 88: 
 89: 
 90: 
 91: 
 92: 
 93: 
 94: 
 95: 
 96: 
 97: 
 98: 
 99: 
100: 
101: 
102: 
103: 
104: 
105: 
106: 
107: 
108: 
(*Bayesian Monte Carlo of Let's Make a Deal
This code illustrates Bayes' Theorem in action on the Let's Make a Deal problem, which several authors 
have used to illustrate Bayes' Theorem. (It's easy to search the internet for further explanation.) 
Run with the audit option to audit up to the first 100 games. Running without audit is faster and can 
simulate a couple billion games.*)
//module game =
type game(doorWithPrize: int, fstChoice: int, revealedDoor: int) = 
    member x.winFstChoice = (doorWithPrize = fstChoice)
    member x.winSwitch = (not(doorWithPrize = fstChoice)&&(not(doorWithPrize = revealedDoor)))
    member x.revealed = revealedDoor
    member x.ToString = "Prize Door: " + doorWithPrize.ToString() + ";  " 
                            + "First Choice: " + fstChoice.ToString() + ";  " 
                            + "Revealed Door: " + revealedDoor.ToString() + ";  " 
                            + "Wins 1st Choice: " + x.winFstChoice.ToString() + ";  " 
                            + "Wins Switch: " + x.winSwitch.ToString()

module games =
    open System

    let seedRnd = new Random()

    let rndReveal doorWithPrize  =
        let rnd = seedRnd.Next(1,3)
        match doorWithPrize with
        |1 -> (rnd + 1)
        |2 -> if rnd = 1 then 1
              else 3  
        |_ -> rnd

    let forcedReveal doorWithPrize fstChoice = 
        match (doorWithPrize + fstChoice) with
        |3 -> 3 
        |4 -> 2  
        |_ -> 1

    ///<summary>Generate games and audit up to the first 100. Once the number of games gets into 10s of  
    ///millions the audit option becomesnoticeably slower.</summary>
    ///<param name="number">number of games to simulate</param>
    let gamesAudit number = 
        let rec recGames acc winsFst winsSwitch audit =
             let doorWithPrize = seedRnd.Next(1,4)
             let fstChoice =  seedRnd.Next(1,4)
             let revealedDoor =
                if (doorWithPrize = fstChoice) then rndReveal doorWithPrize
                else forcedReveal doorWithPrize fstChoice
             let myGame = game(doorWithPrize, fstChoice, revealedDoor)
             let newAudit =
                if (List.length audit) < 100 then (List.append audit [myGame])
                else audit
             if acc = 0 then (winsFst, winsSwitch), audit
             else if myGame.winFstChoice then recGames (acc - 1) (winsFst + 1) winsSwitch newAudit
                  else recGames (acc - 1) winsFst (winsSwitch + 1)  newAudit   
        let auditedGames = recGames number 0 0 List.Empty

        let rec writeAudit audit =
            match audit with
            |myGame:game::tl -> 
                Console.WriteLine(myGame.ToString)
                writeAudit tl
            |_ -> ignore

        let newAudit:List<game> = snd auditedGames
        writeAudit newAudit |> ignore
        if (fst(fst(auditedGames)) + snd(fst(auditedGames)) > 100) then Console.WriteLine("first 100 games audited")
        fst(auditedGames)

    ///<summary>Bare-bones generation of games. Once the number of games gets into 10s of millions this 
    ///is noticeably faster than generation with the audit option.</summary>
    ///<param name="number">number of games to simulate</param> 
    let games number = 
        let rec recGames acc winsFst winsSwitch =
             let doorWithPrize = seedRnd.Next(1,4)
             let fstChoice =  seedRnd.Next(1,4)
             (*The following source statement illustrates the essence of this problem as an example of  
             Bayes' Theorem. There are two posterior situations , in one case there are two possible  
             succeeding events, each with one-half probability. In the other case only one succeeding 
             event is possible with 100% probability.*)
             let revealedDoor =
                if (doorWithPrize = fstChoice) then rndReveal doorWithPrize
                else forcedReveal doorWithPrize fstChoice
             //strangely (on my 32-bit system), measuring large runs with StopWatch it is faster to  
             //instantiate myGame and query the member "winFstChoice" than do the direct 
             //"doorWithPrize = fstChoice" comparison 
             let myGame = game(doorWithPrize, fstChoice, revealedDoor)
             if acc = 0 then winsFst, winsSwitch
             else if myGame.winFstChoice then recGames (acc - 1) (winsFst + 1) winsSwitch 
                  else recGames (acc - 1) winsFst (winsSwitch + 1)     
        recGames number 0 0

    [<EntryPoint>]
    let main argv = 
         Console.WriteLine ("")
         Console.WriteLine ("P(A|B) = P(B|A)P(A) / P(B) //memorize this!")
         Console.WriteLine ("")

         if argv.Length  = 0 then Console.WriteLine ("Enter the number of games to simulate between 0 and 2147483647")
         else

            let myGames = 
                if argv.Length > 1 && argv.[1].ToLower() = "audit" then gamesAudit (Int32.Parse argv.[0])
                else games (Int32.Parse argv.[0])

            Console.WriteLine ((Int32.Parse argv.[0]).ToString("#,##0") + " games played")
            Console.WriteLine ("Wins with first choice: " + fst(myGames).ToString("#,##0") + ";  " 
                + "Wins switching: " + snd(myGames).ToString("#,##0"))
         
         Console.WriteLine ("")
         0 
Multiple items
type game =
  new : doorWithPrize:int * fstChoice:int * revealedDoor:int -> game
  member ToString : string
  member revealed : int
  member winFstChoice : bool
  member winSwitch : bool

Full name: Script.game

--------------------
new : doorWithPrize:int * fstChoice:int * revealedDoor:int -> game
val doorWithPrize : int
Multiple items
val int : value:'T -> int (requires member op_Explicit)

Full name: Microsoft.FSharp.Core.Operators.int

--------------------
type int = int32

Full name: Microsoft.FSharp.Core.int

--------------------
type int<'Measure> = int

Full name: Microsoft.FSharp.Core.int<_>
val fstChoice : int
val revealedDoor : int
val x : game
member game.winFstChoice : bool

Full name: Script.game.winFstChoice
member game.winSwitch : bool

Full name: Script.game.winSwitch
val not : value:bool -> bool

Full name: Microsoft.FSharp.Core.Operators.not
member game.revealed : int

Full name: Script.game.revealed
member game.ToString : string

Full name: Script.game.ToString
System.Int32.ToString() : string
System.Int32.ToString(provider: System.IFormatProvider) : string
System.Int32.ToString(format: string) : string
System.Int32.ToString(format: string, provider: System.IFormatProvider) : string
property game.winFstChoice: bool
System.Boolean.ToString() : string
System.Boolean.ToString(provider: System.IFormatProvider) : string
property game.winSwitch: bool
module games

from Script
namespace System
val seedRnd : Random

Full name: Script.games.seedRnd
Multiple items
type Random =
  new : unit -> Random + 1 overload
  member Next : unit -> int + 2 overloads
  member NextBytes : buffer:byte[] -> unit
  member NextDouble : unit -> float

Full name: System.Random

--------------------
Random() : unit
Random(Seed: int) : unit
val rndReveal : doorWithPrize:int -> int

Full name: Script.games.rndReveal
val rnd : int
Random.Next() : int
Random.Next(maxValue: int) : int
Random.Next(minValue: int, maxValue: int) : int
val forcedReveal : doorWithPrize:int -> fstChoice:int -> int

Full name: Script.games.forcedReveal
val gamesAudit : number:int -> int * int

Full name: Script.games.gamesAudit


<summary>Generate games and audit up to the first 100. Once the number of games gets into 10s of
millions the audit option becomesnoticeably slower.</summary>
<param name="number">number of games to simulate</param>
val number : int
val recGames : (int -> int -> int -> game list -> (int * int) * game list)
val acc : int
val winsFst : int
val winsSwitch : int
val audit : game list
val myGame : game
val newAudit : game list
Multiple items
module List

from Microsoft.FSharp.Collections

--------------------
type List<'T> =
  | ( [] )
  | ( :: ) of Head: 'T * Tail: 'T list
  interface IEnumerable
  interface IEnumerable<'T>
  member Head : 'T
  member IsEmpty : bool
  member Item : index:int -> 'T with get
  member Length : int
  member Tail : 'T list
  static member Cons : head:'T * tail:'T list -> 'T list
  static member Empty : 'T list

Full name: Microsoft.FSharp.Collections.List<_>
val length : list:'T list -> int

Full name: Microsoft.FSharp.Collections.List.length
val append : list1:'T list -> list2:'T list -> 'T list

Full name: Microsoft.FSharp.Collections.List.append
val auditedGames : (int * int) * game list
property List.Empty: 'T list
val writeAudit : (game list -> 'a -> unit)
val tl : game list
type Console =
  static member BackgroundColor : ConsoleColor with get, set
  static member Beep : unit -> unit + 1 overload
  static member BufferHeight : int with get, set
  static member BufferWidth : int with get, set
  static member CapsLock : bool
  static member Clear : unit -> unit
  static member CursorLeft : int with get, set
  static member CursorSize : int with get, set
  static member CursorTop : int with get, set
  static member CursorVisible : bool with get, set
  ...

Full name: System.Console
Console.WriteLine() : unit
   (+0 other overloads)
Console.WriteLine(value: string) : unit
   (+0 other overloads)
Console.WriteLine(value: obj) : unit
   (+0 other overloads)
Console.WriteLine(value: uint64) : unit
   (+0 other overloads)
Console.WriteLine(value: int64) : unit
   (+0 other overloads)
Console.WriteLine(value: uint32) : unit
   (+0 other overloads)
Console.WriteLine(value: int) : unit
   (+0 other overloads)
Console.WriteLine(value: float32) : unit
   (+0 other overloads)
Console.WriteLine(value: float) : unit
   (+0 other overloads)
Console.WriteLine(value: decimal) : unit
   (+0 other overloads)
val ignore : value:'T -> unit

Full name: Microsoft.FSharp.Core.Operators.ignore
val newAudit : List<game>
val snd : tuple:('T1 * 'T2) -> 'T2

Full name: Microsoft.FSharp.Core.Operators.snd
val fst : tuple:('T1 * 'T2) -> 'T1

Full name: Microsoft.FSharp.Core.Operators.fst
val games : number:int -> int * int

Full name: Script.games.games


<summary>Bare-bones generation of games. Once the number of games gets into 10s of millions this
is noticeably faster than generation with the audit option.</summary>
<param name="number">number of games to simulate</param>
val recGames : (int -> int -> int -> int * int)
Multiple items
type EntryPointAttribute =
  inherit Attribute
  new : unit -> EntryPointAttribute

Full name: Microsoft.FSharp.Core.EntryPointAttribute

--------------------
new : unit -> EntryPointAttribute
val main : argv:string [] -> int

Full name: Script.games.main
val argv : string []
property Array.Length: int
val myGames : int * int
type Int32 =
  struct
    member CompareTo : value:obj -> int + 1 overload
    member Equals : obj:obj -> bool + 1 overload
    member GetHashCode : unit -> int
    member GetTypeCode : unit -> TypeCode
    member ToString : unit -> string + 3 overloads
    static val MaxValue : int
    static val MinValue : int
    static member Parse : s:string -> int + 3 overloads
    static member TryParse : s:string * result:int -> bool + 1 overload
  end

Full name: System.Int32
Int32.Parse(s: string) : int
Int32.Parse(s: string, provider: IFormatProvider) : int
Int32.Parse(s: string, style: Globalization.NumberStyles) : int
Int32.Parse(s: string, style: Globalization.NumberStyles, provider: IFormatProvider) : int

More information

Link:http://fssnip.net/bs
Posted:12 years ago
Author:Jack Fox
Tags: bayestheorem , game