diff --git a/src/FSharp/FSharp.fsproj b/src/FSharp/FSharp.fsproj
index b1b485eb..7711a025 100644
--- a/src/FSharp/FSharp.fsproj
+++ b/src/FSharp/FSharp.fsproj
@@ -61,7 +61,7 @@
-
+
diff --git a/src/FSharp/RandomVariableMonad.fs b/src/FSharp/RandomVariable.fs
similarity index 50%
rename from src/FSharp/RandomVariableMonad.fs
rename to src/FSharp/RandomVariable.fs
index da2842ec..9bbd1e09 100644
--- a/src/FSharp/RandomVariableMonad.fs
+++ b/src/FSharp/RandomVariable.fs
@@ -1,56 +1,57 @@
-namespace MathNet.Numerics
+module MathNet.Numerics.Probability
#nowarn "40"
open System
open System.Collections
open System.Collections.Generic
+open MathNet.Numerics
-module RandomVariable =
-
- type 'a Outcome = {
- Value: 'a
- Probability : BigRational }
-
- type 'a RandomVariable = 'a Outcome seq
-
- // P(A AND B) = P(A | B) * P(B)
- let bind (f: 'a -> 'b RandomVariable) (dist:'a RandomVariable) =
- dist
- |> Seq.map (fun p1 ->
- f p1.Value
- |> Seq.map (fun p2 ->
- { Value = p2.Value;
- Probability =
- p1.Probability * p2.Probability}))
- |> Seq.concat : 'b RandomVariable
-
- /// Sequentially compose two actions, passing any value produced by the first as an argument to the second.
- let inline (>>=) dist f = bind f dist
- /// Flipped >>=
- let inline (=<<) f dist = bind f dist
-
- /// Inject a value into the RandomVariable type
- let returnM (value:'a) =
- Seq.singleton { Value = value ; Probability = 1N/1N }
- : 'a RandomVariable
-
- type RandomVariableMonadBuilder() =
- member this.Bind (r, f) = bind f r
- member this.Return x = returnM x
- member this.ReturnFrom x = x
-
- let randomVariable = RandomVariableMonadBuilder()
-
+type Outcome<'T> = {
+ Value: 'T
+ Probability : BigRational }
+
+type RandomVariable<'T> = Outcome<'T> seq
+
+// P(A AND B) = P(A | B) * P(B)
+let private bind f dist =
+ dist
+ |> Seq.map (fun p1 ->
+ f p1.Value
+ |> Seq.map (fun p2 ->
+ { Value = p2.Value;
+ Probability =
+ p1.Probability * p2.Probability}))
+ |> Seq.concat
+
+/// Inject a value into the RandomVariable type
+let private returnM value =
+ Seq.singleton { Value = value ; Probability = 1N/1N }
+
+type RandomVariableBuilder() =
+ member this.Bind (r, f) = bind f r
+ member this.Return x = returnM x
+ member this.ReturnFrom x = x
+
+let randomVariable = RandomVariableBuilder()
+
+type CoinSide =
+ | Heads
+ | Tails
+
+[]
+[]
+module RandomVariable =
+
// Create some helpers
- let toUniformDistribution seq : 'a RandomVariable =
+ let toUniformDistribution seq =
let l = Seq.length seq
seq
|> Seq.map (fun e ->
{ Value = e;
Probability = 1N / bignum.FromInt l })
- let probability (dist:'a RandomVariable) =
+ let probability dist =
dist
|> Seq.map (fun o -> o.Probability)
|> Seq.sum
@@ -60,13 +61,9 @@ module RandomVariable =
let fairDice sides = toUniformDistribution [1..sides]
- type CoinSide =
- | Heads
- | Tails
-
let fairCoin = toUniformDistribution [Heads; Tails]
- let filter predicate (dist:'a RandomVariable) : 'a RandomVariable =
+ let filter predicate dist =
dist |> Seq.filter (fun o -> predicate o.Value)
let filterInAnyOrder items dist =
@@ -74,7 +71,7 @@ module RandomVariable =
|> Seq.fold (fun d item -> filter (Seq.exists ((=) (item))) d) dist
/// Transforms a RandomVariable value by using a specified mapping function.
- let map f (dist:'a RandomVariable) : 'b RandomVariable =
+ let map f dist =
dist
|> Seq.map (fun o -> { Value = f o.Value; Probability = o.Probability })
diff --git a/src/FSharpPortable/FSharpPortable.fsproj b/src/FSharpPortable/FSharpPortable.fsproj
index 481ad7d9..63aaba14 100644
--- a/src/FSharpPortable/FSharpPortable.fsproj
+++ b/src/FSharpPortable/FSharpPortable.fsproj
@@ -78,8 +78,8 @@
q.fs
-
- RandomVariableMonad.fs
+
+ RandomVariable.fs
diff --git a/src/FSharpUnitTests/PokerTests.fs b/src/FSharpUnitTests/PokerTests.fs
index 4276d06b..48382db9 100644
--- a/src/FSharpUnitTests/PokerTests.fs
+++ b/src/FSharpUnitTests/PokerTests.fs
@@ -1,7 +1,7 @@
module MathNet.Numerics.Tests.PokerTests
open MathNet.Numerics
-open MathNet.Numerics.RandomVariable
+open MathNet.Numerics.Probability
open NUnit.Framework
open FsUnit
@@ -30,67 +30,69 @@ let isConnected c1 c2 =
[]
let ``When drawing from a full deck, then the probability for an Ace should equal 4/52``() =
completeDeck
- |> selectOne |> map fst
- |> filter (fun card -> value card = A)
- |> probability
+ |> RandomVariable.selectOne
+ |> RandomVariable.map fst
+ |> RandomVariable.filter (fun card -> value card = A)
+ |> RandomVariable.probability
|> should equal (4N/52N)
[]
let ``When drawing from a full deck, then the probability should equal 1/52``() =
completeDeck
- |> selectOne |> map fst
- |> filter ((=) (A,Spades))
- |> probability
+ |> RandomVariable.selectOne
+ |> RandomVariable.map fst
+ |> RandomVariable.filter ((=) (A,Spades))
+ |> RandomVariable.probability
|> should equal (1N/52N)
[]
let ``When drawing from a full deck, then the probability for the Ace of Clubs and Ace of Spaces (in order) should equal 1/52 * 1/51``() =
completeDeck
- |> select 2
- |> filter ((=) [A,Clubs; A,Spades])
- |> probability
+ |> RandomVariable.select 2
+ |> RandomVariable.filter ((=) [A,Clubs; A,Spades])
+ |> RandomVariable.probability
|> should equal (1N/52N * 1N/51N)
[]
let ``When drawing from a full deck, then the probability for the Ace of Clubs and Ace of Spaces (in any order) should equal (1/52 * 1/51) * 2``() =
completeDeck
- |> select 2
- |> filterInAnyOrder [A,Clubs; A,Spades]
- |> probability
+ |> RandomVariable.select 2
+ |> RandomVariable.filterInAnyOrder [A,Clubs; A,Spades]
+ |> RandomVariable.probability
|> should equal ((1N/52N * 1N/51N) * 2N)
[]
let ``When drawing the Ace of Spades and the Ace of Clubs, then the probability for drawing another Ace should equal 2/50``() =
completeDeck
- |> remove [A,Clubs; A,Spades]
- |> toUniformDistribution
- |> filter (fun card -> value card = A)
- |> probability
+ |> RandomVariable.remove [A,Clubs; A,Spades]
+ |> RandomVariable.toUniformDistribution
+ |> RandomVariable.filter (fun card -> value card = A)
+ |> RandomVariable.probability
|> should equal (2N/50N)
[]
let ``When drawing from the full deck, then the probability for drawing a Pair preflop should equal 1/17``() =
completeDeck
- |> select 2
- |> filter (fun (c1::c2::_) -> isPair c1 c2)
- |> probability
+ |> RandomVariable.select 2
+ |> RandomVariable.filter (fun (c1::c2::_) -> isPair c1 c2)
+ |> RandomVariable.probability
|> should equal (1N/17N)
[]
let ``When drawing from the full deck, then the probability for drawing Suited Connectors should equal 1/25``() =
completeDeck
- |> select 2
- |> filter (fun (c1::c2::_) -> isSuited c1 c2 && isConnected c1 c2)
- |> probability
+ |> RandomVariable.select 2
+ |> RandomVariable.filter (fun (c1::c2::_) -> isSuited c1 c2 && isConnected c1 c2)
+ |> RandomVariable.probability
|> should equal (2N/51N)
[]
let ``When holding 3 Spades after the flop, than the probability for drawing a flush should equal 10/47*9/46``() =
completeDeck
- |> remove [A,Clubs; A,Spades] // preflop
- |> remove [2,Clubs; 3,Spades; 7,Spades] // flop
- |> select 2
- |> filter (fun (c1::c2::_) -> suit c1 = Spades && suit c2 = Spades)
- |> probability
+ |> RandomVariable.remove [A,Clubs; A,Spades] // preflop
+ |> RandomVariable.remove [2,Clubs; 3,Spades; 7,Spades] // flop
+ |> RandomVariable.select 2
+ |> RandomVariable.filter (fun (c1::c2::_) -> suit c1 = Spades && suit c2 = Spades)
+ |> RandomVariable.probability
|> should equal (10N/47N*9N/46N)
\ No newline at end of file
diff --git a/src/FSharpUnitTests/RandomVariableTests.fs b/src/FSharpUnitTests/RandomVariableTests.fs
index e9a80f20..93305aab 100644
--- a/src/FSharpUnitTests/RandomVariableTests.fs
+++ b/src/FSharpUnitTests/RandomVariableTests.fs
@@ -1,44 +1,44 @@
module MathNet.Numerics.Tests.RandomVariableTests
open MathNet.Numerics
-open MathNet.Numerics.RandomVariable
+open MathNet.Numerics.Probability
open NUnit.Framework
open FsUnit
[]
let ``When creating a empty randomVariable, then the probability should be 1``() =
let actual = randomVariable { return () }
- probability actual |> should equal (1N/1N)
+ RandomVariable.probability actual |> should equal (1N/1N)
let sumOfTwoFairDices = randomVariable {
- let! d1 = fairDice 6
- let! d2 = fairDice 6
+ 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
- |> filter ((=) 7)
- |> probability
+ |> RandomVariable.filter ((=) 7)
+ |> RandomVariable.probability
|> should equal (1N/6N)
let fairCoinAndDice = randomVariable {
- let! d = fairDice 6
- let! c = fairCoin
+ 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
- |> filter (fun (_,c) -> c = Heads)
- |> probability
+ |> RandomVariable.filter (fun (_,c) -> c = Heads)
+ |> RandomVariable.probability
|> should equal (1N/2N)
[]
let ``When creating a fair coin and a fair dice, then P(Heads and dice > 3) should be 1/4``() =
fairCoinAndDice
- |> filter (fun (d,c) -> c = Heads && d > 3)
- |> probability
+ |> RandomVariable.filter (fun (d,c) -> c = Heads && d > 3)
+ |> RandomVariable.probability
|> should equal (1N/4N)
// MontyHall Problem
@@ -49,22 +49,22 @@ type Outcome =
| Car
| Goat
-let firstChoice = toUniformDistribution [Car; Goat; 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
- certainly Goat
+ RandomVariable.certainly Goat
| Goat ->
// If you had the goat, the host has to take out another goat ==> you win
- certainly Car
+ RandomVariable.certainly Car
[]
let ``When making the first choice in a MontyHall situation, the chances to win should be 1/3``() =
firstChoice
- |> filter ((=) Car)
- |> probability
+ |> RandomVariable.filter ((=) Car)
+ |> RandomVariable.probability
|> should equal (1N/3N)
let montyHallWithSwitch = randomVariable {
@@ -74,6 +74,6 @@ let montyHallWithSwitch = randomVariable {
[]
let ``When switching in a MontyHall situation, the chances to win should be 2/3``() =
montyHallWithSwitch
- |> filter ((=) Car)
- |> probability
+ |> RandomVariable.filter ((=) Car)
+ |> RandomVariable.probability
|> should equal (2N/3N)
\ No newline at end of file