F#でいろんな乱数を作りたい

掲題の件、System.Randomを使うと言うという手もありますが、やはり一様乱数だけだと不便なので、統計系に強いライブラリの助けを借りて作業したい、そういうことです。
それにはMath.NET Numerics

を使うと良い。とりあえず、NuGetなりでインストール後、

  • MathNet.Numerics.dll
  • MathNet.Numerics.FSharp.dll

に参照は通して置く。あと、名前空間いちいち全部タイプするのめんどいので、openしておく。

open MathNet.Numerics.Random
open MathNet.Numerics.Distributions

これで乱数の使用が可能になる。実行結果は張り付けるのめんどくなったので、省略。
この辺、ドキュメンテーション系のライブラリGitHub - fsprojects/FSharp.Formatting: F# tools for generating documentation (Markdown processor and F# code formatter)あたりを使いこなせるようになっておいた方がよいかもしれない。

//一様乱数の生成の例
let mt = new MersenneTwister(100)
val mt : MersenneTwister
//[0,1)な一様分布
[1..4] |> List.map (fun i -> mt.NextDouble())
//[0, 1, 2]な一様分布
[1..4] |> List.map (fun i -> mt.Next(3))

次は正規乱数生成の例。その他の分布に従う乱数も同様に生成可能。
個人的には前者(withRandom使ってる方)の方が使い勝手が良いのでこちらでいきたい所存。

//正規乱数生成の2例。どちらも結果は同じ
//withRandomはMathNet.Numerics.FSharp.dllに参照通しておかないと使えない。
let mt1 = new MersenneTwister(100)
let mt2 = new MersenneTwister(100)
let x1 = Normal.WithMeanVariance(0.0, 1.0) |> withRandom mt1
x1.Sample()
Normal.Sample(mt2, 0.0, 1.0)

このx1を通せば、確率分布の値も計算してもらえるので、便利便利。

//確率密度関数の値
x1.Density(0.0) 
//確率密度関数の値のlog(自然対数)
x1.DensityLn(0.0) 
//累積分布関数
x1.CumulativeDistribution(0.0)
//累積分布関数の逆関数
x1.InverseCumulativeDistribution(0.5)
x1.InverseCumulativeDistribution(0.1)

クラス構造の全体像は把握し切れてないが、要するに以下のコードに乱数用の機能を型拡張したものが、上のx1に相当しているのだろう。

let x2 = new MathNet.Numerics.Distributions.Normal(0.0,1.0)
x2.Density(0.0)