module MathNet.Numerics.Tests.RandomVariableTests open NUnit.Framework open FsUnitTyped open MathNet.Numerics open MathNet.Numerics.Probability [] let ``When creating a empty randomVariable, then the probability should be 1``() = let actual = randomVariable { return () } RandomVariable.probability actual |> shouldEqual (1N/1N) let sumOfTwoFairDices = randomVariable { let! d1 = RandomVariable.fairDice 6 let! d2 = RandomVariable.fairDice 6 return d1 + d2 } [] let ``When creating two fair dices, then P(Sum of 2 dices = 7) should be 1/6``() = sumOfTwoFairDices |> RandomVariable.filter ((=) 7) |> RandomVariable.probability |> shouldEqual (1N/6N) let fairCoinAndDice = randomVariable { let! d = RandomVariable.fairDice 6 let! c = RandomVariable.fairCoin return d,c } [] let ``When creating a fair coin and a fair dice, then P(Heads) should be 1/2``() = fairCoinAndDice |> RandomVariable.filter (fun (_,c) -> c = Heads) |> RandomVariable.probability |> shouldEqual (1N/2N) [] let ``When creating a fair coin and a fair dice, then P(Heads and dice > 3) should be 1/4``() = fairCoinAndDice |> RandomVariable.filter (fun (d,c) -> c = Heads && d > 3) |> RandomVariable.probability |> shouldEqual (1N/4N) // MontyHall Problem // See Martin Erwig and Steve Kollmansberger's paper // "Functional Pearls: Probabilistic functional programming in Haskell" type Outcome = | Car | Goat let firstChoice = RandomVariable.toUniformDistribution [Car; Goat; Goat] let switch firstCoice = match firstCoice with | Car -> // If you had the car and you switch ==> you lose since there are only goats left RandomVariable.certainly Goat | Goat -> // If you had the goat, the host has to take out another goat ==> you win RandomVariable.certainly Car [] let ``When making the first choice in a MontyHall situation, the chances to win should be 1/3``() = firstChoice |> RandomVariable.filter ((=) Car) |> RandomVariable.probability |> shouldEqual (1N/3N) let montyHallWithSwitch = randomVariable { let! firstDoor = firstChoice return! switch firstDoor } [] let ``When switching in a MontyHall situation, the chances to win should be 2/3``() = montyHallWithSwitch |> RandomVariable.filter ((=) Car) |> RandomVariable.probability |> shouldEqual (2N/3N)