5 people like it.
Like the snippet!
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