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)