Browse Source

F#: add modules for random numbers and distributions

pull/61/merge
Christoph Ruegg 14 years ago
parent
commit
88b07acaf7
  1. 9
      src/FSharp/AssemblyInfo.fs
  2. 49
      src/FSharp/Distributions.fs
  3. 4
      src/FSharp/FSharp.fsproj
  4. 6
      src/FSharp/LinearAlgebra.Double.fs
  5. 85
      src/FSharp/Random.fs
  6. 11
      src/FSharpExamples/DenseVector.fs
  7. 1
      src/FSharpExamples/FSharpExamples.fsproj
  8. 77
      src/FSharpExamples/RandomAndDistributions.fs
  9. 10
      src/FSharpPortable/FSharpPortable.fsproj
  10. 3
      src/FSharpUnitTests/Program.fs

9
src/FSharp/AssemblyInfo.fs

@ -43,9 +43,14 @@ open System.Runtime.InteropServices
[<assembly: AssemblyCopyright("Copyright © Math.NET Project")>]
[<assembly: AssemblyTrademark("")>]
[<assembly: AssemblyCulture("")>]
[<assembly: ComVisible(false)>]
[<assembly: Guid("048BC4EB-CE2B-4040-9967-4784F5405B0F")>]
[<assembly: NeutralResourcesLanguage("en")>]
[<assembly: AssemblyVersion("1.0.0.0")>]
[<assembly: AssemblyFileVersion("1.0.0.0")>]
#if PORTABLE
#else
[<assembly: ComVisible(false)>]
[<assembly: Guid("048BC4EB-CE2B-4040-9967-4784F5405B0F")>]
#endif
()

49
src/FSharp/Distributions.fs

@ -0,0 +1,49 @@
// <copyright file="Random.fs" company="Math.NET">
// Math.NET Numerics, part of the Math.NET Project
// http://numerics.mathdotnet.com
// http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com
//
// Copyright (c) 2009-2012 Math.NET
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
// </copyright>
namespace MathNet.Numerics.Distributions
open MathNet.Numerics.Random
[<AutoOpen>]
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
module Distributions =
let withRandom random (dist:#IDistribution) =
dist.RandomSource <- random
dist
let withSystemRandom dist = dist |> withRandom (Random.system())
let withMersenneTwister dist = dist |> withRandom (Random.mersenneTwister())
#if PORTABLE
#else
let withCryptoRandom dist = dist |> withRandom (Random.crypto())
#endif

4
src/FSharp/FSharp.fsproj

@ -51,10 +51,12 @@
<Import Project="$(MSBuildExtensionsPath32)\FSharp\1.0\Microsoft.FSharp.Targets" Condition="(!Exists('$(MSBuildExtensionsPath32)\..\Microsoft SDKs\F#\3.0\Framework\v4.0\Microsoft.FSharp.Targets')) And (!Exists('$(MSBuildExtensionsPath32)\..\Microsoft F#\v4.0\Microsoft.FSharp.Targets')) And (Exists('$(MSBuildExtensionsPath32)\FSharp\1.0\Microsoft.FSharp.Targets'))" />
<ItemGroup>
<Compile Include="AssemblyInfo.fs" />
<Compile Include="Random.fs" />
<Compile Include="Distributions.fs" />
<Compile Include="LinearAlgebra.fs" />
<Compile Include="LinearAlgebra.Double.Vector.fs" />
<Compile Include="LinearAlgebra.Double.Matrix.fs" />
<Compile Include="Main.fs" />
<Compile Include="LinearAlgebra.Double.fs" />
</ItemGroup>
<ItemGroup>
<Reference Include="FSharp.Core" />

6
src/FSharp/Main.fs → src/FSharp/LinearAlgebra.Double.fs

@ -28,13 +28,13 @@
// OTHER DEALINGS IN THE SOFTWARE.
// </copyright>
namespace MathNet.Numerics
namespace MathNet.Numerics.LinearAlgebra.Double
open MathNet.Numerics.LinearAlgebra.Generic
open MathNet.Numerics.LinearAlgebra.Double
/// A module which implements some F# utility functions.
module FSharp =
[<AutoOpen>]
module Utility =
/// Construct a dense matrix from a list of floating point numbers.
let inline matrix (lst: list<list<float>>) = DenseMatrix.ofList lst :> Matrix<float>

85
src/FSharp/Random.fs

@ -0,0 +1,85 @@
// <copyright file="Random.fs" company="Math.NET">
// Math.NET Numerics, part of the Math.NET Project
// http://numerics.mathdotnet.com
// http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com
//
// Copyright (c) 2009-2012 Math.NET
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
// </copyright>
namespace MathNet.Numerics.Random
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
module Random =
/// Provides a seed based on unique GUIDs
let seed () = System.Guid.NewGuid().GetHashCode()
/// Provides a time-dependent seed value (caution, can produce the same value on quick repeated execution)
let timeSeed () = System.Environment.TickCount
/// Creates a default .Net system pRNG with a custom seed based on uinque GUIDs
let system () = new System.Random(seed())
let systemWith seed = new System.Random(seed)
#if PORTABLE
#else
/// Creates a default .Net cryptographic system pRNG
let crypto () = new SystemCryptoRandomNumberGenerator() :> System.Random
let cryptoWith (threadSafe:bool) = new SystemCryptoRandomNumberGenerator(threadSafe) :> System.Random
#endif
/// Creates a Mersenne Twister 19937 pRNG with a custom seed based on uinque GUIDs
let mersenneTwister () = new MersenneTwister(seed()) :> System.Random
let mersenneTwisterWith seed threadSafe = new MersenneTwister(seed, threadSafe) :> System.Random
/// Creates a multiply-with-carry Xorshift (Xn = a * Xn−3 + c mod 2^32) pRNG with a custom seed based on uinque GUIDs
let xorshift () = new Xorshift(seed()) :> System.Random
let xorshiftWith seed threadSafe = new Xorshift(seed, threadSafe) :> System.Random
let xorshiftCustom seed threadSafe a c x1 x2 = new Xorshift(seed, threadSafe, a, c, x1, x2) :> System.Random
/// Creates a Wichmann-Hill’s 1982 combined multiplicative congruential pRNG with a custom seed based on uinque GUIDs
let wh1982 () = new WH1982(seed()) :> System.Random
let wh1982With seed threadSafe = new WH1982(seed, threadSafe) :> System.Random
/// Creates a Wichmann-Hill’s 2006 combined multiplicative congruential pRNG with a custom seed based on uinque GUIDs
let wh2006 () = new WH2006(seed()) :> System.Random
let wh2006With seed threadSafe = new WH2006(seed, threadSafe) :> System.Random
/// Creates a Parallel Additive Lagged Fibonacci pRNG with a custom seed based on uinque GUIDs
let palf () = new Palf(seed()) :> System.Random
let palfWith seed threadSafe = new Palf(seed, threadSafe, 418, 1279) :> System.Random
let palfCustom seed threadSafe shortLag longLag = new Palf(seed, threadSafe, shortLag, longLag) :> System.Random
/// Creates a Multiplicative congruential generator using a modulus of 2^59 and a multiplier of 13^13 pRNG with a custom seed based on uinque GUIDs
let mcg59 () = new Mcg59(seed()) :> System.Random
let mcg59With seed threadSafe = new Mcg59(seed, threadSafe) :> System.Random
/// Creates a Multiplicative congruential generator using a modulus of 2^31-1 and a multiplier of 1132489760 pRNG with a custom seed based on uinque GUIDs
let mcg31m1 () = new Mcg31m1(seed()) :> System.Random
let mcg31m1With seed threadSafe = new Mcg31m1(seed, threadSafe) :> System.Random
/// Creates a 32-bit combined multiple recursive generator with 2 components of order 3 pRNG with a custom seed based on uinque GUIDs
let mrg32k3a () = new Mrg32k3a(seed()) :> System.Random
let mrg32k3aWith seed threadSafe = new Mrg32k3a(seed, threadSafe) :> System.Random

11
src/FSharpExamples/DenseVector.fs

@ -27,17 +27,17 @@
// </copyright>
module MathNet.Numerics.FSharp.Examples.DenseVector
open MathNet.Numerics.FSharp
open MathNet.Numerics.LinearAlgebra
open MathNet.Numerics.LinearAlgebra.Double
// Create a new 100 dimensional dense vector.
let v = Double.DenseVector.init 100 (fun i -> float i / 100.0)
let v = DenseVector.init 100 (fun i -> float i / 100.0)
// Another way to create a 100 dimensional dense vector is using the vector function.
let w = vector (List.init 100 (fun i -> float i ** 2.0))
// Vectors can also be constructed from sequences.
let t = Double.DenseVector.ofSeq (seq { for i in 1 .. 100 do yield float i })
let t = DenseVector.ofSeq (seq { for i in 1 .. 100 do yield float i })
// We can now add two vectors together ...
let z = v + w
@ -46,9 +46,8 @@ let z = v + w
let x = v + 3.0 * t
// We can create a vector from an integer range (in this case, 5 and 10 inclusive) ...
let s = Double.DenseVector.range 5 10
let s = DenseVector.range 5 10
// ... or we can create a vector from a double range with a particular step size.
let r = Double.DenseVector.rangef 0.0 0.1 10.0
let r = DenseVector.rangef 0.0 0.1 10.0

1
src/FSharpExamples/FSharpExamples.fsproj

@ -64,6 +64,7 @@
<Compile Include="Apply.fs" />
<Compile Include="Histogram.fs" />
<Compile Include="MCMC.fs" />
<Compile Include="RandomAndDistributions.fs" />
</ItemGroup>
<PropertyGroup>
<MinimumVisualStudioVersion Condition="'$(MinimumVisualStudioVersion)' == ''">11</MinimumVisualStudioVersion>

77
src/FSharpExamples/RandomAndDistributions.fs

@ -0,0 +1,77 @@
// <copyright file="RandomAndDistributions.fs" company="Math.NET">
// Math.NET Numerics, part of the Math.NET Project
// http://mathnet.opensourcedotnet.info
//
// Copyright (c) 2009-2012 Math.NET
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
// </copyright>
module RandomAndDistributions
open MathNet.Numerics.Random
open MathNet.Numerics.Distributions
// generate some seeds for random values
let someGuidSeed = Random.seed ()
let someTimeSeed = Random.timeSeed ()
// generate some pseudo random number generators (listing incomplete; all of them are cast to the common base type, System.Random)
let a = Random.system ()
let b = Random.systemWith (Random.timeSeed())
let c = Random.crypto ()
let d = Random.mersenneTwister ()
let e = Random.mersenneTwisterWith 1000 true (* thread-safe *)
let f = Random.xorshift ()
let g = Random.xorshiftCustom someTimeSeed false 916905990L 13579L 362436069L 77465321L
let h = Random.wh2006 ()
let i = Random.palf ()
// generate some uniform random values
let values = (
a.Next(),
b.NextFullRangeInt32(),
c.NextFullRangeInt64(),
d.NextInt64(),
e.NextDouble(),
f.NextDecimal()
)
// generate some probability distributions
let normal = Normal.WithMeanVariance(3.0, 1.5) |> withRandom g
let exponential = new Exponential(2.4)
let gamma = new Gamma(2.0, 1.5) |> withCryptoRandom
let cauchy = new Cauchy() |> withRandom (Random.mrg32k3aWith 10 false)
let poisson = new Poisson(3.0)
let geometric = new Geometric(1.2) |> withSystemRandom
// generate some random samples from these distributions
let continuous = [
yield normal.Sample()
yield exponential.Sample()
yield! gamma.Samples() |> Seq.take 10
]
let discrete = [
poisson.Sample()
poisson.Sample()
geometric.Sample()
]

10
src/FSharpPortable/FSharpPortable.fsproj

@ -44,6 +44,12 @@
<Compile Include="..\FSharp\AssemblyInfo.fs">
<Link>AssemblyInfo.fs</Link>
</Compile>
<Compile Include="..\FSharp\Random.fs">
<Link>Random.fs</Link>
</Compile>
<Compile Include="..\FSharp\Distributions.fs">
<Link>Distributions.fs</Link>
</Compile>
<Compile Include="..\FSharp\LinearAlgebra.fs">
<Link>LinearAlgebra.fs</Link>
</Compile>
@ -53,8 +59,8 @@
<Compile Include="..\FSharp\LinearAlgebra.Double.Vector.fs">
<Link>LinearAlgebra.Double.Vector.fs</Link>
</Compile>
<Compile Include="..\FSharp\Main.fs">
<Link>Main.fs</Link>
<Compile Include="..\FSharp\LinearAlgebra.Double.fs">
<Link>LinearAlgebra.Double.fs</Link>
</Compile>
</ItemGroup>
<ItemGroup>

3
src/FSharpUnitTests/Program.fs

@ -1,7 +1,6 @@
open FsUnit
open MathNet.Numerics.FSharp
open MathNet.Numerics.LinearAlgebra.Double
open MathNet.Numerics.LinearAlgebra.Generic
open MathNet.Numerics.LinearAlgebra.Double
/// Unit tests for the dense vector type.
let DenseVectorTests =

Loading…
Cancel
Save