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 ///Generate games and audit up to the first 100. Once the number of games gets into 10s of ///millions the audit option becomesnoticeably slower. ///number of games to simulate 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 = snd auditedGames writeAudit newAudit |> ignore if (fst(fst(auditedGames)) + snd(fst(auditedGames)) > 100) then Console.WriteLine("first 100 games audited") fst(auditedGames) ///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. ///number of games to simulate 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 [] 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
Console.WriteLine(value: string) : unit
Console.WriteLine(value: obj) : unit
Console.WriteLine(value: uint64) : unit
Console.WriteLine(value: int64) : unit
Console.WriteLine(value: uint32) : unit
Console.WriteLine(value: int) : unit
Console.WriteLine(value: float32) : unit
Console.WriteLine(value: float) : unit
Console.WriteLine(value: decimal) : unit
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