Browse Source

Samples: extend F# distribution samples to Sample module, random walk

optimization-1
Christoph Ruegg 13 years ago
parent
commit
fadc4c87a0
  1. 8
      src/FSharp/Distributions.fs
  2. 37
      src/FSharpExamples/RandomAndDistributions.fsx

8
src/FSharp/Distributions.fs

@ -35,6 +35,14 @@ open MathNet.Numerics.Random
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
module Sample =
let transform f dist : System.Random -> 'T = fun rng -> f (dist rng)
let transform2 f dist1 dist2 : System.Random -> 'T = fun rng -> f (dist1 rng) (dist2 rng)
let transform3 f dist1 dist2 dist3 : System.Random -> 'T = fun rng -> f (dist1 rng) (dist2 rng) (dist3 rng)
let transformSeq f dist : System.Random -> 'T seq = fun rng -> dist rng |> Seq.map f
let transformSeq2 f dist1 dist2 : System.Random -> 'T seq = fun rng -> Seq.zip (dist1 rng) (dist2 rng) |> Seq.map (fun (d1, d2) -> f d1 d2)
let transformSeq3 f dist1 dist2 dist3 : System.Random -> 'T seq = fun rng -> Seq.zip3 (dist1 rng) (dist2 rng) (dist3 rng) |> Seq.map (fun (d1, d2, d3) -> f d1 d2 d3)
/// Bernoulli with probability (p).
let bernoulli p rng = Bernoulli.Sample(rng, p)
let bernoulliSeq p rng = Bernoulli.Samples(rng, p)

37
src/FSharpExamples/RandomAndDistributions.fsx

@ -71,7 +71,7 @@ boolean argument at creation, or by setting `Control.ThreadSafeRandomNumberGener
*)
let a = Random.system ()
let b = Random.systemSeed (Random.timeSeed())
let b = Random.systemSeed (RandomSeed.Time())
let b2 = Random.systemSeed someGuidSeed
let c = Random.crypto ()
let d = Random.mersenneTwister ()
@ -134,6 +134,41 @@ let x = Hypergeometric.Sample(h, 100, 20, 5)
(**
Specifically for F# there is also a `Sample` module that allow a somewhat
more functional view on the distributions by allowing them to be curried such that
the random source is passed in as last arguments. This way distributions can
be combined and transformed arbitrarily:
*)
/// Transform a sample distribution
let s1 rng = tanh (Sample.normal 2.0 0.5 rng)
/// Alternative way where we transform the function instead of its result
let s1alt rng = Sample.transform tanh (Sample.normal 2.0 0.5) rng
/// Alternative way that works exactly the same but operates on functions generating sequences
let s1seq rng = Sample.transformSeq tanh (Sample.normalSeq 2.0 0.5) rng
/// The same with multiple distributions:
let s2 rng = (Sample.normal 2.0 1.5 rng) * (Sample.cauchy 2.0 0.5 rng)
let s2alt rng = Sample.transform2 (*) (Sample.normal 2.0 1.5) (Sample.cauchy 2.0 0.5) rng
let s2seq rng = Sample.transformSeq2 (*) (Sample.normalSeq 2.0 1.5) (Sample.cauchySeq 2.0 0.5) rng
Seq.take 10 (s2seq (Random.system())) |> Seq.toArray
(**
Let's do some random walks, using distributions and random sources defined above:
*)
Seq.scan (+) 0.0 (normal.Samples()) |> Seq.take 10 |> Seq.toArray
Seq.scan (+) 0.0 (Sample.normalSeq 0.0 0.5 a) |> Seq.take 10 |> Seq.toArray
Seq.scan (+) 0.0 (s1seq a) |> Seq.take 10 |> Seq.toArray
(**
Distributions can not just be used to generate random samples.
You can use them to evaluate distribution properties or functions
with the given parametrization.

Loading…
Cancel
Save