From 3edd073e4ecc810f4c51c9d9960ad5e5757004ad Mon Sep 17 00:00:00 2001 From: Kevin Schneider Date: Tue, 8 Apr 2025 16:24:13 +0200 Subject: [PATCH 001/121] update to .net 8 in preparation for INumerics core --- build/BasicTasks.fs | 7 +++++-- build/PackageTasks.fs | 4 +++- build/ReleaseNotesTasks.fs | 5 ++--- build/TestTasks.fs | 17 +++++++++------- build/build.fsproj | 20 +++++++++---------- global.json | 2 +- .../FSharp.Stats.Interactive.fsproj | 2 +- src/FSharp.Stats/FSharp.Stats.fsproj | 2 +- .../FSharp.Stats.Tests.fsproj | 2 +- 9 files changed, 34 insertions(+), 27 deletions(-) diff --git a/build/BasicTasks.fs b/build/BasicTasks.fs index 713217b79..65cb69bf2 100644 --- a/build/BasicTasks.fs +++ b/build/BasicTasks.fs @@ -26,6 +26,9 @@ let clean = BuildTask.create "Clean" [] { } let build = BuildTask.create "Build" [clean] { - solutionFile - |> DotNet.build id + solutionFile + |> DotNet.build (fun p -> + { p with MSBuildParams = { p.MSBuildParams with DisableInternalBinLog = true }} + |> DotNet.Options.withCustomParams (Some "-tl") + ) } \ No newline at end of file diff --git a/build/PackageTasks.fs b/build/PackageTasks.fs index d51d99a4c..af6517842 100644 --- a/build/PackageTasks.fs +++ b/build/PackageTasks.fs @@ -17,7 +17,8 @@ let pack = BuildTask.create "Pack" [clean; build; runTests] { -- "src/bin/*" |> Seq.iter (Fake.DotNet.DotNet.pack (fun p -> let msBuildParams = - {p.MSBuildParams with + {p.MSBuildParams with + DisableInternalBinLog = true Properties = ([ "Version",stableVersionTag "PackageReleaseNotes", (release.Notes |> String.concat "\r\n") @@ -40,6 +41,7 @@ let packPrerelease = BuildTask.create "PackPrerelease" [setPrereleaseTag; clean; |> Seq.iter (Fake.DotNet.DotNet.pack (fun p -> let msBuildParams = {p.MSBuildParams with + DisableInternalBinLog = true Properties = ([ "Version", prereleaseTag "PackageReleaseNotes", (release.Notes |> String.toLines ) diff --git a/build/ReleaseNotesTasks.fs b/build/ReleaseNotesTasks.fs index 81e35bbba..ba0a99164 100644 --- a/build/ReleaseNotesTasks.fs +++ b/build/ReleaseNotesTasks.fs @@ -8,9 +8,8 @@ open BlackFox.Fake //} let updateReleaseNotes = BuildTask.createFn "ReleaseNotes" [] (fun config -> - Release.exists() - - Release.update(ProjectInfo.gitOwner, ProjectInfo.project, config) + ReleaseNotes.ensure() + ReleaseNotes.update(ProjectInfo.gitOwner, ProjectInfo.project, config) ) //let githubDraft = BuildTask.createFn "GithubDraft" [] (fun config -> diff --git a/build/TestTasks.fs b/build/TestTasks.fs index 65dc6d6ac..d79c6d935 100644 --- a/build/TestTasks.fs +++ b/build/TestTasks.fs @@ -7,14 +7,16 @@ open ProjectInfo open BasicTasks let runTests = BuildTask.create "RunTests" [clean; build] { - Fake.DotNet.DotNet.test(fun testParams -> - { - testParams with - Logger = Some "console;verbosity=detailed" - Configuration = DotNet.BuildConfiguration.fromString configuration - NoBuild = true + testProject + |> Fake.DotNet.DotNet.test (fun testParams -> + { testParams with + Logger = Some "console;verbosity=detailed" + Configuration = DotNet.BuildConfiguration.fromString configuration + NoBuild = true + MSBuildParams = { testParams.MSBuildParams with DisableInternalBinLog = true } } - ) testProject + |> DotNet.Options.withCustomParams (Some "-tl") + ) } // to do: use this once we have actual tests @@ -25,6 +27,7 @@ let runTestsWithCodeCov = BuildTask.create "RunTestsWithCodeCov" [clean; build] testParams with MSBuildParams = { standardParams with + DisableInternalBinLog = true Properties = [ "AltCover","true" "AltCoverCobertura","../../codeCov.xml" diff --git a/build/build.fsproj b/build/build.fsproj index 82dafd230..b3f0ebf49 100644 --- a/build/build.fsproj +++ b/build/build.fsproj @@ -1,7 +1,7 @@  - net6.0 + net8.0 Exe @@ -20,15 +20,15 @@ - - - - - - - - - + + + + + + + + + diff --git a/global.json b/global.json index d6c2c37f7..501e79a87 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "sdk": { - "version": "6.0.100", + "version": "8.0.100", "rollForward": "latestFeature" } } \ No newline at end of file diff --git a/src/FSharp.Stats.Interactive/FSharp.Stats.Interactive.fsproj b/src/FSharp.Stats.Interactive/FSharp.Stats.Interactive.fsproj index dca322b60..4059d91a0 100644 --- a/src/FSharp.Stats.Interactive/FSharp.Stats.Interactive.fsproj +++ b/src/FSharp.Stats.Interactive/FSharp.Stats.Interactive.fsproj @@ -1,7 +1,7 @@  - netstandard2.1 + net8.0 true true diff --git a/src/FSharp.Stats/FSharp.Stats.fsproj b/src/FSharp.Stats/FSharp.Stats.fsproj index 12bc4e587..c0ee4e4f2 100644 --- a/src/FSharp.Stats/FSharp.Stats.fsproj +++ b/src/FSharp.Stats/FSharp.Stats.fsproj @@ -1,7 +1,7 @@  - netstandard2.0 + .net8.0 true diff --git a/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj b/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj index 0a373c39c..f4295d1f5 100644 --- a/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj +++ b/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj @@ -1,7 +1,7 @@  Exe - net6.0 + net8.0 false From 3a4c8549c58d922463e5f51918d0c5e9cfe59851 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20M=C3=BChlhaus?= Date: Wed, 9 Apr 2025 13:39:26 +0200 Subject: [PATCH 002/121] Remove Algebra types and the Linerar Algebra services --- src/FSharp.Stats/AlgTypes.fs | 2590 ----------------- src/FSharp.Stats/Algebra/ILinearAlgebra.fs | 122 - .../Algebra/LinearAlgebraServiceMKL.fs | 641 ---- .../Algebra/LinearAlgebraServiceManaged.fs | 643 ---- src/FSharp.Stats/Algebra/NativeArray.fs | 106 - .../Algebra/NativeArrayExtensions.fs | 53 - src/FSharp.Stats/Algebra/NativeUtilities.fs | 49 - src/FSharp.Stats/BigRational.fs | 311 -- src/FSharp.Stats/GlobalAssociations.fs | 45 - src/FSharp.Stats/INumeric.fs | 240 -- src/FSharp.Stats/Matrix.fs | 1611 ---------- src/FSharp.Stats/MatrixTopLevelOperators.fs | 10 - src/FSharp.Stats/RowVector.fs | 88 - src/FSharp.Stats/ServiceLocator.fs | 191 -- src/FSharp.Stats/Vector.fs | 880 ------ 15 files changed, 7580 deletions(-) delete mode 100644 src/FSharp.Stats/AlgTypes.fs delete mode 100644 src/FSharp.Stats/Algebra/ILinearAlgebra.fs delete mode 100644 src/FSharp.Stats/Algebra/LinearAlgebraServiceMKL.fs delete mode 100644 src/FSharp.Stats/Algebra/LinearAlgebraServiceManaged.fs delete mode 100644 src/FSharp.Stats/Algebra/NativeArray.fs delete mode 100644 src/FSharp.Stats/Algebra/NativeArrayExtensions.fs delete mode 100644 src/FSharp.Stats/Algebra/NativeUtilities.fs delete mode 100644 src/FSharp.Stats/BigRational.fs delete mode 100644 src/FSharp.Stats/GlobalAssociations.fs delete mode 100644 src/FSharp.Stats/INumeric.fs delete mode 100644 src/FSharp.Stats/Matrix.fs delete mode 100644 src/FSharp.Stats/MatrixTopLevelOperators.fs delete mode 100644 src/FSharp.Stats/RowVector.fs delete mode 100644 src/FSharp.Stats/ServiceLocator.fs delete mode 100644 src/FSharp.Stats/Vector.fs diff --git a/src/FSharp.Stats/AlgTypes.fs b/src/FSharp.Stats/AlgTypes.fs deleted file mode 100644 index ee79a0db2..000000000 --- a/src/FSharp.Stats/AlgTypes.fs +++ /dev/null @@ -1,2590 +0,0 @@ -// (c) Microsoft Corporation 2005-2009. - -//---------------------------------------------------------------------------- -// An implementation of generic dense and sparse matrix types. -// -// Overview and suffix documentation -// _GU = generic unspecialized (Matrix, Vector etc.) -// _GUA = generic unspecialized op on (underlying) array -// _DS = Double specialized (Matrix = matrix, Vector = vector etc.) -// -// DM = dense matrix -// SM = sparse matrix -// V = vector (dense) -// RV = row vector (dense) - - -namespace FSharp.Stats - - #nowarn "60" // implementations in augmentations - #nowarn "69" // implementations in augmentations - - open System - open System.Collections - open System.Collections.Generic - open System.Diagnostics - open Formatting - //type permutation = int -> int - - -//========================================================================= -// (c) Microsoft Corporation 2005-2009. -//========================================================================= - - [] - module Helpers = - let sparseNYI() = failwith "this operation is not supported on sparse matrices" - let sparseNotMutable() = failwith "sparse matrices are not mutable" - - [] - let opsdata<'T> = GlobalAssociations.TryGetNumericAssociation<'T>() - - [] - let DenseMaxDisplay = 50 - [] - let VectorMaxDisplay = 100 - - - /// The value stored for the dictionary of numeric operations. If none is present then this indicates - /// no operations are known for this type. - type OpsData<'T> = INumeric<'T> option - - type DenseMatrix<'T>(opsData : OpsData<'T>, values : 'T[,]) = - member m.OpsData = opsData - member m.Values = values - member m.NumRows = values.GetLength(0) - member m.NumCols = values.GetLength(1) - - member m.ElementOps = - match opsData with - | None -> raise (new System.NotSupportedException("The element type carried by this matrix does not support numeric operations")) - | Some a -> a - - member m.Item - with get (i,j) = values.[i,j] - and set (i,j) x = values.[i,j] <- x - - type SparseMatrix<'T>(opsData : OpsData<'T>, sparseValues : 'T array, sparseRowOffsets : int array, ncols:int, columnValues: int array) = - member m.OpsData = opsData; - member m.NumCols = ncols - member m.NumRows = sparseRowOffsets.Length - 1 - member m.SparseColumnValues = columnValues - member m.SparseRowOffsets = sparseRowOffsets (* nrows + 1 elements *) - member m.SparseValues = sparseValues - - member m.ElementOps = - match opsData with - | None -> raise (new System.NotSupportedException("The element type carried by this matrix does not support numeric operations")) - | Some a -> a - - member m.MinIndexForRow i = m.SparseRowOffsets.[i] - member m.MaxIndexForRow i = m.SparseRowOffsets.[i+1] - - - member m.Item - with get (i,j) = - let imax = m.NumRows - let jmax = m.NumCols - if j < 0 || j >= jmax || i < 0 || i >= imax then raise (new System.ArgumentOutOfRangeException()) else - let kmin = m.MinIndexForRow i - let kmax = m.MaxIndexForRow i - let rec loopRow k = - (* note: could do a binary chop here *) - if k >= kmax then m.ElementOps.Zero else - let j2 = columnValues.[k] - if j < j2 then m.ElementOps.Zero else - if j = j2 then sparseValues.[k] else - loopRow (k+1) - loopRow kmin - -#if FX_NO_DEBUG_DISPLAYS -#else - [] -#endif - [] - [] - //[>)>] - type Matrix<'T> = - | DenseRepr of DenseMatrix<'T> - | SparseRepr of SparseMatrix<'T> - interface System.IComparable - interface IStructuralComparable - interface IStructuralEquatable - interface IEnumerable<'T> - interface IEnumerable - interface IFsiFormattable - interface IMatrixFormattable - - member m.ElementOps = match m with DenseRepr mr -> mr.ElementOps | SparseRepr mr -> mr.ElementOps - member m.NumRows = match m with DenseRepr mr -> mr.NumRows | SparseRepr mr -> mr.NumRows - member m.NumCols = match m with DenseRepr mr -> mr.NumCols | SparseRepr mr -> mr.NumCols - - member m.Item - with get (i,j) = - match m with - | DenseRepr dm -> dm.[i,j] - | SparseRepr sm -> sm.[i,j] - and set (i,j) x = - match m with - | DenseRepr dm -> dm.[i,j] <- x - | SparseRepr _ -> sparseNotMutable() - - -#if FX_NO_DEBUG_DISPLAYS -#else - [] -#endif - member m.IsDense = match m with DenseRepr _ -> true | SparseRepr _ -> false - -#if FX_NO_DEBUG_DISPLAYS -#else - [] -#endif - member m.IsSparse = match m with DenseRepr _ -> false | SparseRepr _ -> true - -#if FX_NO_DEBUG_DISPLAYS -#else - [] -#endif - member m.InternalSparseColumnValues = match m with DenseRepr _ -> invalidOp "not a sparse matrix" | SparseRepr mr -> mr.SparseColumnValues - -#if FX_NO_DEBUG_DISPLAYS -#else - [] -#endif - member m.InternalSparseRowOffsets = match m with DenseRepr _ -> invalidOp "not a sparse matrix" | SparseRepr mr -> mr.SparseRowOffsets - -#if FX_NO_DEBUG_DISPLAYS -#else - [] -#endif - member m.InternalSparseValues = match m with DenseRepr _ -> invalidOp "not a sparse matrix" | SparseRepr mr -> mr.SparseValues - -#if FX_NO_DEBUG_DISPLAYS -#else - [] -#endif - member m.InternalDenseValues = match m with DenseRepr mr -> mr.Values | SparseRepr _ -> invalidOp "not a dense matrix" - -#if FX_NO_DEBUG_DISPLAYS -#else - [] -#endif -#if FX_NO_DEBUG_PROXIES -#else - [>)>] -#endif - [] - [] - type RowVector<'T>(opsRV : INumeric<'T> option, arrRV : 'T array ) = - interface System.IComparable - interface IStructuralComparable - interface IStructuralEquatable - - -#if FX_NO_DEBUG_DISPLAYS -#else - [] -#endif - member x.InternalValues = arrRV - member x.Values = arrRV - member x.OpsData = opsRV - - - interface IEnumerable<'T> with - member x.GetEnumerator() = (arrRV :> seq<_>).GetEnumerator() - interface IEnumerable with - member x.GetEnumerator() = (arrRV :> IEnumerable).GetEnumerator() - - member x.Length = arrRV.Length - member x.NumCols = arrRV.Length - member x.ElementOps = - match opsRV with - | None -> raise (new System.NotSupportedException("The element type carried by this row vector does not support numeric operations")) - | Some a -> a - - member v.Item - with get i = arrRV.[i] - and set i x = arrRV.[i] <- x - - and - [] - RowVectorDebugView<'T>(v: RowVector<'T>) = - -#if FX_NO_DEBUG_DISPLAYS -#else - [] -#endif - member x.Items = v |> Seq.truncate 1 |> Seq.toArray - -#if FX_NO_DEBUG_DISPLAYS -#else - [] -#endif -#if FX_NO_DEBUG_PROXIES -#else - [>)>] -#endif - [] - [] - type Vector<'T>(opsV : INumeric<'T> option, arrV : 'T array) = - -#if FX_NO_DEBUG_DISPLAYS -#else - [] -#endif - member x.InternalValues = arrV - member x.Values = arrV - member x.OpsData = opsV - interface System.IComparable - interface IStructuralComparable - interface IStructuralEquatable - - interface IEnumerable<'T> with - member x.GetEnumerator() = (arrV :> seq<_>).GetEnumerator() - interface IEnumerable with - member x.GetEnumerator() = (arrV :> IEnumerable).GetEnumerator() - - ///Length of vector - member m.Length = arrV.Length - member m.NumRows = arrV.Length - member m.ElementOps = - match opsV with - | None -> raise (new System.NotSupportedException("The element type carried by this vector does not support numeric operations")) - | Some a -> a - member v.Item - with get i = arrV.[i] - and set i x = arrV.[i] <- x - -#if FX_NO_DEBUG_PROXIES -#else - and - [] - VectorDebugView<'T>(v: Vector<'T>) = - - [] - member x.Items = v |> Seq.truncate 1 |> Seq.toArray -#endif - - - /// Implementations of operations that will work for any type - module GenericImpl = - - type OpsData<'T> = INumeric<'T> option - - let opsOfOpsData (d : OpsData<'T>) = - match d with - | None -> raise (new System.NotSupportedException("The element type '"+(typeof<'T>).ToString()+"' carried by this vector or matrix does not support numeric operations (i.e. does not have a registered numeric association)")) - | Some a -> a - - let getNormOps (ops:INumeric<'T>) = - match box ops with - | :? INormFloat<'T> as ops -> ops - | _ -> raise (new System.NotSupportedException("The element type '"+(typeof<'T>.ToString())+"' carried by this vector or matrix does not support the INormFloat<_> operation (i.e. does not have a registered numeric association that supports this type)")) - - let mkDenseMatrixGU ops arr = DenseMatrix(ops,arr) - let mkSparseMatrixGU ops (arr: 'a[,]) = - let length1 = arr |> Array2D.length1 - let length2 = arr |> Array2D.length2 - - let mutable nnz = 0 - let a = FSharp.Collections.ResizeArray<'a>() - let ja = FSharp.Collections.ResizeArray() - let ia = FSharp.Collections.ResizeArray() - ia.Add(0) - for i = 0 to (length1 - 1) do - for j = 0 to (length2 - 1) do - if ((Array2D.get arr i j) |> System.Convert.ToDouble) >= 0.000001 || ((Array2D.get arr i j)|> System.Convert.ToDouble) <= -0.000001 then - a.Add((Array2D.get arr i j)) - ja.Add(j) - nnz <- nnz + 1 - ia.Add(nnz) - SparseMatrix(ops, a.ToArray(), ia.ToArray(), length2, ja.ToArray()) - let mkRowVecGU ops arr = RowVector(ops, arr) - let mkVecGU ops arr = Vector(ops,arr) - - let inline getArray2D (arrDM : _[,]) i j = arrDM.[i,j] - let inline setArray2D (arrDM : _[,]) i j x = arrDM.[i,j] <- x - - let inline createArray m = Array.zeroCreate m - - let inline createArray2D m n = Array2D.zeroCreate m n - - let inline assignArray2D m n f arr = - for i = 0 to m - 1 do - for j = 0 to n - 1 do - (arr : _[,]).[i,j] <- f i j - - let inline assignConstArray2D m n x arr = - for i = 0 to m - 1 do - for j = 0 to n - 1 do - (arr : _[,]).[i,j] <- x - - let inline assignDenseMatrixGU f (a:DenseMatrix<_>) = - assignArray2D a.NumRows a.NumCols f a.Values - - let inline assignArray m f (arr : _[]) = - for i = 0 to m - 1 do - arr.[i] <- f i - - let inline assignConstArray m x (arr : _[]) = - for i = 0 to m - 1 do - arr.[i] <- x - - let inline assignVecGU f (a:Vector<_>) = - assignArray a.NumRows f a.Values - - let inline assignRowVecGU f (a:RowVector<_>) = - assignArray a.NumCols f a.Values - - let createConstDenseMatrixGU ops m n x = - let arr = createArray2D m n - assignConstArray2D m n x arr; - DenseMatrix(ops,arr) - - let createConstRowVecGU ops m x = - let arr = createArray m - assignConstArray m x arr; - mkRowVecGU ops arr - - let createConstVecGU ops m x = - let arr = createArray m - assignConstArray m x arr; - mkVecGU ops arr - - - let inline createDenseMatrixGU ops m n f = (* inline eliminates unknown f call *) - let arr = createArray2D m n - assignArray2D m n f arr; - DenseMatrix(ops,arr) - - let createRowVecGU ops m f = - let arr = createArray m - assignArray m f arr; - mkRowVecGU ops arr - - let inline createVecGU ops m f = (* inline eliminates unknown f call *) - let arr = createArray m - assignArray m f arr; - mkVecGU ops arr - - /// Create a matrix from a sparse sequence - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - let initSparseMatrixGU maxi maxj ops s = - - (* nb. could use sorted dictionary but that is in System.dll *) - let tab = Array.create maxi null - let count = ref 0 - for (i,j,v) in s do - if i < 0 || i >= maxi || j <0 || j >= maxj then failwith "initial value out of range"; - count := !count + 1; - let tab2 = - match tab.[i] with - | null -> - let tab2 = new Dictionary<_,_>(3) - tab.[i] <- tab2; - tab2 - | tab2 -> tab2 - tab2.[j] <- v - // optimize this line.... - let offsA = - let rowsAcc = Array.zeroCreate (maxi + 1) - let mutable acc = 0 - for i = 0 to maxi-1 do - rowsAcc.[i] <- acc; - acc <- match tab.[i] with - | null -> acc - | tab2 -> acc+tab2.Count - rowsAcc.[maxi] <- acc; - rowsAcc - - let colsA,valsA = - let colsAcc = new ResizeArray<_>(!count) - let valsAcc = new ResizeArray<_>(!count) - for i = 0 to maxi-1 do - match tab.[i] with - | null -> () - | tab2 -> tab2 |> Seq.toArray |> Array.sortBy (fun kvp -> kvp.Key) |> Array.iter (fun kvp -> colsAcc.Add(kvp.Key); valsAcc.Add(kvp.Value)); - colsAcc.ToArray(), valsAcc.ToArray() - - SparseMatrix(opsData=ops, sparseValues=valsA, sparseRowOffsets=offsA, ncols=maxj, columnValues=colsA) - - let zeroizeDenseMatrixGUA arr m n : DenseMatrix<'T> = - let opsData = opsdata<'T> - let ops = opsOfOpsData opsData - let zero = ops.Zero - assignArray2D m n (fun _ _ -> zero) arr; - DenseMatrix(opsData,arr) - - let zeroizeArray opsData arr m = - let ops = opsOfOpsData opsData - let zero = ops.Zero - assignArray m (fun _ -> zero) arr - - let zeroizeVecGUA arr m : Vector<'T> = - let opsData = opsdata<'T> - zeroizeArray opsData arr m; - mkVecGU opsData arr - - let zeroizeRowVecGUA arr m : RowVector<'T> = - let opsData = opsdata<'T> - zeroizeArray opsData arr m; - mkRowVecGU opsData arr - - let listDenseMatrixGU ops xss = - let m = List.length xss - match xss with - | [] -> invalidArg "xss" "unexpected empty list" - | h :: t -> - let n = List.length h - if not (List.forall (fun xs -> List.length xs=n) t) then invalidArg "xss" "the lists are not all of the same length"; - let values = Array2D.zeroCreate m n - List.iteri (fun i rw -> List.iteri (fun j x -> values.[i,j] <- x) rw) xss; - DenseMatrix(ops,values) - - let colListDenseMatrixGU ops xss = - let m = List.length xss - match xss with - | [] -> invalidArg "xss" "unexpected empty list" - | h :: t -> - let n = List.length h - if not (List.forall (fun xs -> List.length xs=n) t) then invalidArg "xss" "the lists are not all of the same length"; - let values = Array2D.zeroCreate n m - List.iteri (fun i rw -> List.iteri (fun j x -> values.[j,i] <- x) rw) xss; - DenseMatrix(ops,values) - - let listVecGU ops xs = mkVecGU ops (Array.ofList xs) - let listRowVecGU ops xs = mkRowVecGU ops (Array.ofList xs) - - let seqDenseMatrixGU ops xss = // TM - //listDenseMatrixGU ops (xss |> Seq.toList |> List.map Seq.toList) - let m = Seq.length xss - if m < 1 then invalidArg "xss" "unexpected empty seq" - let n = xss |> Seq.head |> Seq.length - if not (Seq.forall (fun xs -> Seq.length xs=n) xss) then invalidArg "xss" "the sequences are not all of the same length"; - let values = Array2D.zeroCreate m n - Seq.iteri (fun i rw -> Seq.iteri (fun j x -> values.[i,j] <- x) rw) xss; - DenseMatrix(ops,values) - - let colSeqDenseMatrixGU ops xss = // TM - //listDenseMatrixGU ops (xss |> Seq.toList |> List.map Seq.toList) - let m = Seq.length xss - if m < 1 then invalidArg "xss" "unexpected empty seq" - let n = xss |> Seq.head |> Seq.length - if not (Seq.forall (fun xs -> Seq.length xs=n) xss) then invalidArg "xss" "the sequences are not all of the same length"; - let values = Array2D.zeroCreate n m - Seq.iteri (fun i rw -> Seq.iteri (fun j x -> values.[j,i] <- x) rw) xss; - DenseMatrix(ops,values) - - let seqVecGU ops xss = mkVecGU ops (Array.ofSeq xss) - let seqRowVecGU ops xss = mkRowVecGU ops (Array.ofSeq xss) - - let arrayDenseMatrixGU ops xss = // TM - let m = Array.length xss - if m < 1 then invalidArg "xss" "unexpected empty array" - let n = xss.[0] |> Array.length - if not (Array.forall (fun xs -> Array.length xs=n) xss) then invalidArg "xss" "the arrays are not all of the same length"; - let values = Array2D.zeroCreate m n - Array.iteri (fun i rw -> Array.iteri (fun j x -> values.[i,j] <- x) rw) xss; - DenseMatrix(ops,values) - - let colArrayDenseMatrixGU ops xss = // TM - let m = Array.length xss - if m < 1 then invalidArg "xss" "unexpected empty array" - let n = xss.[0] |> Array.length - if not (Array.forall (fun xs -> Array.length xs=n) xss) then invalidArg "xss" "the arrays are not all of the same length"; - let values = Array2D.zeroCreate n m - Array.iteri (fun i rw -> Array.iteri (fun j x -> values.[j,i] <- x) rw) xss; - DenseMatrix(ops,values) - - let inline binaryOpDenseMatrixGU f (a:DenseMatrix<_>) (b:DenseMatrix<_>) = (* pointwise binary operator *) - let nA = a.NumCols - let mA = a.NumRows - let nB = b.NumCols - let mB = b.NumRows - if nA<>nB || mA<>mB then invalidArg "a" "the two matrices do not have compatible dimensions"; - let arrA = a.Values - let arrB = b.Values - createDenseMatrixGU a.OpsData mA nA (fun i j -> f (getArray2D arrA i j) (getArray2D arrB i j)) - - - let nonZeroEntriesSparseMatrixGU (a:SparseMatrix<_>) = - // This is heavily used, and this version is much faster than - // the sequence operators. - let entries = new ResizeArray<_>(a.SparseColumnValues.Length) - let imax = a.NumRows - let ops = a.ElementOps - let zero = ops.Zero - for i in 0 .. imax - 1 do - let kmin = a.MinIndexForRow i - let kmax = a.MaxIndexForRow i - for k in kmin .. kmax - 1 do - let j = a.SparseColumnValues.[k] - let v = a.SparseValues.[k] - if not (ops.Equals(v,zero)) then - entries.Add((i,j,v)) - (entries :> seq<_>) - - let nonzeroEntriesDenseMatrixGU (a:DenseMatrix<_>) = - let imax = a.NumRows - let jmax = a.NumCols - let ops = a.ElementOps - let zero = ops.Zero - seq { for i in 0 .. imax - 1 do - for j in 0 .. jmax - 1 do - let v = a.[i,j] - if not (ops.Equals(v, zero)) then - yield (i,j,v) } - - - // pointwise operation on two sparse matrices. f must be zero-zero-preserving, i.e. (f 0 0 = 0) - let binaryOpSparseMatrixGU f (a:SparseMatrix<_>) (b:SparseMatrix<_>) = - let ops = a.ElementOps - let zero = ops.Zero - let imax1 = a.NumRows - let imax2 = b.NumRows - let jmax1 = a.NumCols - let jmax2 = b.NumCols - if imax1 <> imax2 || jmax1 <> jmax2 then invalidArg "b" "the two matrices do not have compatible dimensions"; - let imin = 0 - let imax = imax1 - let jmax = jmax1 - let rowsR = Array.zeroCreate (imax+1) - let colsR = new ResizeArray<_>(max a.SparseColumnValues.Length b.SparseColumnValues.Length) - let valsR = new ResizeArray<_>(max a.SparseValues.Length b.SparseValues.Length) - let rec loopRows i = - rowsR.[i] <- valsR.Count; - if i >= imax1 then () else - let kmin1 = a.MinIndexForRow i - let kmax1 = a.MaxIndexForRow i - let kmin2 = b.MinIndexForRow i - let kmax2 = b.MaxIndexForRow i - let rec loopRow k1 k2 = - if k1 >= kmax1 && k2 >= kmax2 then () else - let j1 = if k1 >= kmax1 then jmax else a.SparseColumnValues.[k1] - let j2 = if k2 >= kmax2 then jmax else b.SparseColumnValues.[k2] - let v1 = if j1 <= j2 then a.SparseValues.[k1] else zero - let v2 = if j2 <= j1 then b.SparseValues.[k2] else zero - let jR = min j1 j2 - let vR = f v1 v2 - (* if vR <> zero then *) - colsR.Add(jR); - valsR.Add(vR); - loopRow (if j1 <= j2 then k1+1 else k1) (if j2 <= j1 then k2+1 else k2) - loopRow kmin1 kmin2; - loopRows (i+1) - loopRows imin; - SparseMatrix(opsData= a.OpsData, - sparseRowOffsets=rowsR, - ncols= a.NumCols, - columnValues=colsR.ToArray(), - sparseValues=valsR.ToArray()) - - let inline binaryOpRowVecGU f (a:RowVector<_>) (b:RowVector<_>) = (* pointwise binary operator *) - let mA = a.NumCols - let mB = b.NumCols - if mA<>mB then invalidArg "b" "the two vectors do not have compatible dimensions" - createRowVecGU a.OpsData mA (fun i -> f a.[i] b.[i]) - - let inline binaryOpVecGU f (a:Vector<_>) (b:Vector<_>) = (* pointwise binary operator *) - let mA = a.NumRows - let mB = b.NumRows - if mA<>mB then invalidArg "b" "the two vectors do not have compatible dimensions" - createVecGU a.OpsData mA (fun i -> f a.[i] b.[i]) - - let inline unaryOpDenseMatrixGU f (a:DenseMatrix<_>) = - let nA = a.NumCols - let mA = a.NumRows - let arrA = a.Values - createDenseMatrixGU a.OpsData mA nA (fun i j -> f (getArray2D arrA i j)) - - let inline unaryOpRowVecGU f (a:RowVector<_>) = - let mA = a.NumCols - let arrA = a.Values - createRowVecGU a.OpsData mA (fun j -> f arrA.[j]) - - let inline unaryOpVectorGU f (a:Vector<_>) = - let mA = a.NumRows - let arrA = a.Values - createVecGU a.OpsData mA (fun i -> f arrA.[i]) - - let unaryOpSparseGU f (a:SparseMatrix<_>) = (* pointwise zero-zero-preserving binary operator (f 0 = 0) *) - SparseMatrix(opsData=a.OpsData, - sparseRowOffsets=Array.copy a.SparseRowOffsets, - columnValues=Array.copy a.SparseColumnValues, - sparseValues=Array.map f a.SparseValues, - ncols=a.NumCols) - - // Strictly speaking, sparse arrays are non mutable so no copy is ever needed. But implementing it *) - // anyway in case we move to mutability *) - let copySparseGU (a:SparseMatrix<_>) = - SparseMatrix(opsData=a.OpsData, - sparseRowOffsets=Array.copy a.SparseRowOffsets, - columnValues=Array.copy a.SparseColumnValues, - sparseValues=Array.copy a.SparseValues, - ncols=a.NumCols) - - let addDenseMatrixGU (a:DenseMatrix<_>) b = let ops = a.ElementOps in binaryOpDenseMatrixGU (fun x y -> ops.Add(x, y)) a b - let addSparseMatrixGU (a:SparseMatrix<_>) b = let ops = a.ElementOps in binaryOpSparseMatrixGU (fun x y -> ops.Add(x, y)) a b - let addRowVecGU (a:RowVector<_>) b = let ops = a.ElementOps in binaryOpRowVecGU (fun x y -> ops.Add(x, y)) a b - let addVecGU (a:Vector<_>) b = let ops = a.ElementOps in binaryOpVecGU (fun x y -> ops.Add(x, y)) a b - - let subDenseMatrixGU (a:DenseMatrix<_>) b = let ops = a.ElementOps in binaryOpDenseMatrixGU (fun x y -> ops.Subtract(x, y)) a b - let subSparseMatrixGU (a:SparseMatrix<_>) b = let ops = a.ElementOps in binaryOpSparseMatrixGU (fun x y -> ops.Subtract(x, y)) a b - let subRowVecGU (a:RowVector<_>) b = let ops = a.ElementOps in binaryOpRowVecGU (fun x y -> ops.Subtract(x, y)) a b - let subVecGU (a:Vector<_>) b = let ops = a.ElementOps in binaryOpVecGU (fun x y -> ops.Subtract(x, y)) a b - - ///Point-wise multiplication - let cptMulDenseMatrixGU (a:DenseMatrix<_>) b = let ops = a.ElementOps in binaryOpDenseMatrixGU (fun x y -> ops.Multiply(x, y)) a b - let cptMulSparseMatrixGU (a:SparseMatrix<_>) b = let ops = a.ElementOps in binaryOpSparseMatrixGU (fun x y -> ops.Multiply(x, y)) a b - let cptMulRowVecGU (a:RowVector<_>) b = let ops = a.ElementOps in binaryOpRowVecGU (fun x y -> ops.Multiply(x, y)) a b - let cptMulVecGU (a:Vector<_>) b = let ops = a.ElementOps in binaryOpVecGU (fun x y -> ops.Multiply(x, y)) a b - - let cptMaxDenseMatrixGU (a:DenseMatrix<_>) b = binaryOpDenseMatrixGU max a b - let cptMinDenseMatrixGU (a:DenseMatrix<_>) b = binaryOpDenseMatrixGU min a b - let cptMaxSparseMatrixGU (a:SparseMatrix<_>) b = binaryOpSparseMatrixGU max a b - let cptMinSparseMatrixGU (a:SparseMatrix<_>) b = binaryOpSparseMatrixGU min a b - - let cptMaxVecGU (a:Vector<_>) b = binaryOpVecGU max a b - let cptMinVecGU (a:Vector<_>) b = binaryOpVecGU min a b - - let add (ops : INumeric<'T>) x y = ops.Add(x,y) - let sub (ops : INumeric<'T>) x y = ops.Subtract(x,y) - let mul (ops : INumeric<'T>) x y = ops.Multiply(x,y) - - let inline foldR f z (a,b) = - let mutable res = z in - for i = a to b do - res <- f res i - res - - let inline sumfR f (a,b) = - let mutable res = 0.0 - for i = a to b do - res <- res + f i - res - - - let inline sumRGU (ops : INumeric<_>) f r = - let zero = ops.Zero - r |> foldR (fun z k -> add ops z (f k)) zero - - let genericMulDenseMatrix (a:DenseMatrix<_>) (b:DenseMatrix<_>) = - let nA = a.NumCols - let mA = a.NumRows - let nB = b.NumCols - let mB = b.NumRows - if nA<>mB then invalidArg "b" "the two matrices do not have compatible dimensions" - let ops = a.ElementOps - let arrA = a.Values - let arrB = b.Values - createDenseMatrixGU a.OpsData mA nB - (fun i j -> (0,nA - 1) |> sumRGU ops (fun k -> mul ops (getArray2D arrA i k) (getArray2D arrB k j))) - - let debug = false - - let NormalizeOrdering (M:SparseMatrix<_>) = - for i = 0 to M.NumRows-1 do - let index = M.SparseRowOffsets.[i] - let count = M.SparseRowOffsets.[i+1] - index - if count > 1 then - System.Array.Sort(M.SparseColumnValues, M.SparseValues, index, count) - - // Performs an inplace map with function x => X, skipping zero values - let NormalizeZeros (M:SparseMatrix<_>) = - let mutable nonZero = 0 - for row = 0 to M.NumRows - 1 do - let startIndex = M.SparseRowOffsets.[row] - let endIndex = M.SparseRowOffsets.[row + 1] - M.SparseRowOffsets.[row] <- nonZero - for j = startIndex to endIndex - 1 do - let item = M.SparseValues.[j] - if not(M.ElementOps.Equals(item, M.ElementOps.Zero)) then - M.SparseValues.[nonZero] <- item - M.SparseColumnValues.[nonZero] <- M.SparseColumnValues.[j] - nonZero <- nonZero + 1 - Array.truncate nonZero M.SparseColumnValues |> ignore - Array.truncate nonZero M.SparseValues |> ignore - M.SparseRowOffsets.[M.NumRows] <- nonZero - - let Normalize (M:SparseMatrix<_>) = - NormalizeOrdering M - NormalizeZeros M - - // Sparse matrix multiplication algorithm. inline to get specialization at the 'double' type - let inline genericMulSparse zero add mul (a:SparseMatrix<_>) (b:SparseMatrix<_>) = - let ax = a.SparseValues - let ap = a.SparseRowOffsets - let ai = a.SparseColumnValues - - let bx = b.SparseValues - let bp = b.SparseRowOffsets - let bi = b.SparseColumnValues - - let rows = a.NumRows - let cols = b.NumCols - - let cp = Array.zeroCreate (rows+1) - - let marker = Array.create cols -1 - - let mutable count = 0 - for i = 0 to rows - 1 do - for j= ap.[i] to ap.[i + 1]-1 do - // Row number to be added - let a = ai.[j] - for k = bp.[a] to bp.[a + 1] - 1 do - let b = bi.[k] - if not (marker.[b] = i) then - marker.[b] <- i - count <- count + 1 - cp.[i + 1] <- count - - let ci = Array.zeroCreate count - let cx = Array.create count zero - - // Reset marker array - for ib= 0 to cols-1 do - marker.[ib] <- -1 - // Reset count - count <- 0 - - for i = 0 to rows - 1 do - let rowStart = cp.[i] - for j = ap.[i] to ap.[i + 1] - 1 do - let a = ai.[j] - let aEntry = ax.[j] - for k = bp.[a] to bp.[a + 1] - 1 do - let b = bi.[k] - let bEntry = bx.[k] - if marker.[b] < rowStart then - marker.[b] <- count - ci.[marker.[b]] <- b - cx.[marker.[b]] <- mul aEntry bEntry; - count <- count + 1 - else - let prod = mul aEntry bEntry - cx.[marker.[b]] <- add cx.[marker.[b]] prod - - let matrix = SparseMatrix(opsData = a.OpsData, - sparseRowOffsets= cp, - ncols = cols, - columnValues=ci, - sparseValues=cx) - Normalize matrix - matrix - - let mulSparseMatrixGU (a: SparseMatrix<_>) b = - let ops = a.ElementOps - let zero = ops.Zero - genericMulSparse zero (add ops) (mul ops) a b - - - let mulRowVecVecGU (a:RowVector<_>) (b:Vector<_>) = - let mA = a.NumCols - let nB = b.NumRows - if mA<>nB then invalidArg "b" "the two vectors do not have compatible dimensions" - let ops = a.ElementOps - (0,mA - 1) |> sumRGU ops (fun k -> mul ops a.[k] b.[k]) - - let rowvecDenseMatrixGU (x:RowVector<_>) = createDenseMatrixGU x.OpsData 1 x.NumCols (fun _ j -> x.[j]) - let vectorDenseMatrixGU (x:Vector<_>) = createDenseMatrixGU x.OpsData x.NumRows 1 (fun i _ -> x.[i]) - - let mulVecRowVecGU a b = genericMulDenseMatrix (vectorDenseMatrixGU a) (rowvecDenseMatrixGU b) - - let mulRowVecDenseMatrixGU (a:RowVector<_>) (b:DenseMatrix<_>) = - let nA = a.NumCols - let nB = b.NumCols - let mB = b.NumRows - if nA<>mB then invalidArg "b" "the two vectors do not have compatible dimensions" - let ops = a.ElementOps - let arrA = a.Values - let arrB = b.Values - createRowVecGU a.OpsData nB - (fun j -> (0,nA - 1) |> sumRGU ops (fun k -> mul ops arrA.[k] (getArray2D arrB k j))) - - let mulDenseMatrixVecGU (a:DenseMatrix<_>) (b:Vector<_>) = - let nA = a.NumCols - let mA = a.NumRows - let mB = b.NumRows - if nA<>mB then invalidArg "b" "the two inputs do not have compatible dimensions" - let ops = b.ElementOps - let arrA = a.Values - let arrB = b.Values - createVecGU b.OpsData mA - (fun i -> (0,nA - 1) |> sumRGU ops (fun k -> mul ops (getArray2D arrA i k) arrB.[k])) - - let mulSparseVecGU (a:SparseMatrix<_>) (b:Vector<_>) = - let nA = a.NumCols - let mA = a.NumRows - let mB = b.NumRows - if nA<>mB then invalidArg "b" "the two inputs do not have compatible dimensions" - let ops = b.ElementOps - let zero = ops.Zero - createVecGU b.OpsData mA (fun i -> - let mutable acc = zero - for k = a.MinIndexForRow i to a.MaxIndexForRow i - 1 do - let j = a.SparseColumnValues.[k] - let v = a.SparseValues.[k] - acc <- add ops acc (mul ops v b.[j]); - acc) - - let mulRVSparseMatrixGU (a:RowVector<_>) (b:SparseMatrix<_>) = - let nA = b.NumCols - let mA = b.NumRows - let mB = a.NumCols - if mA<>mB then invalidArg "b" "the two inputs do not have compatible dimensions" - let ops = b.ElementOps - let arr = createArray nA - zeroizeArray a.OpsData arr nA; - for i = 0 to mA - 1 do - for k = b.MinIndexForRow i to b.MaxIndexForRow i - 1 do - let j = b.SparseColumnValues.[k] - let v = b.SparseValues.[k] - arr.[j] <- add ops arr.[j] (mul ops a.[i] v) - mkRowVecGU a.OpsData arr - - - let scaleDenseMatrixGU k (a:DenseMatrix<_>) = let ops = a.ElementOps in unaryOpDenseMatrixGU (fun x -> ops.Multiply(k,x)) a - let scaleRowVecGU k (a:RowVector<_>) = let ops = a.ElementOps in unaryOpRowVecGU (fun x -> ops.Multiply(k,x)) a - let scaleVecGU k (a:Vector<_>) = let ops = a.ElementOps in unaryOpVectorGU (fun x -> ops.Multiply(k,x)) a - let scaleSparseMatrixGU k (a:SparseMatrix<_>) = let ops = a.ElementOps in unaryOpSparseGU (fun x -> ops.Multiply(k,x)) a - // add + - let addScalarDenseMatrixGU k (a:DenseMatrix<_>) = let ops = a.ElementOps in unaryOpDenseMatrixGU (fun x -> ops.Add(k,x)) a - let addScalarRowVecGU k (a:RowVector<_>) = let ops = a.ElementOps in unaryOpRowVecGU (fun x -> ops.Add(k,x)) a - let addScalarVecGU k (a:Vector<_>) = let ops = a.ElementOps in unaryOpVectorGU (fun x -> ops.Add(k,x)) a - let addScalarSparseMatrixGU k (a:SparseMatrix<_>) = let ops = a.ElementOps in unaryOpSparseGU (fun x -> ops.Add(k,x)) a - // sub - - let subScalarDenseMatrixGU k (a:DenseMatrix<_>) = let ops = a.ElementOps in unaryOpDenseMatrixGU (fun x -> ops.Subtract(k,x)) a - let subScalarRowVecGU k (a:RowVector<_>) = let ops = a.ElementOps in unaryOpRowVecGU (fun x -> ops.Subtract(k,x)) a - let subScalarVecGU k (a:Vector<_>) = let ops = a.ElementOps in unaryOpVectorGU (fun x -> ops.Subtract(k,x)) a - let subScalarSparseMatrixGU k (a:SparseMatrix<_>) = let ops = a.ElementOps in unaryOpSparseGU (fun x -> ops.Subtract(k,x)) a - - let negDenseMatrixGU (a:DenseMatrix<_>) = let ops = a.ElementOps in unaryOpDenseMatrixGU (fun x -> ops.Negate(x)) a - let negRowVecGU (a:RowVector<_>) = let ops = a.ElementOps in unaryOpRowVecGU (fun x -> ops.Negate(x)) a - let negVecGU (a:Vector<_>) = let ops = a.ElementOps in unaryOpVectorGU (fun x -> ops.Negate(x)) a - let negSparseMatrixGU (a:SparseMatrix<_>) = let ops = a.ElementOps in unaryOpSparseGU (fun x -> ops.Negate(x)) a - - let mapDenseMatrixGU f (a : DenseMatrix<'T>) : DenseMatrix<'T> = - let arrA = a.Values - createDenseMatrixGU a.OpsData a.NumRows a.NumCols (fun i j -> f (getArray2D arrA i j)) - - let mapVecGU f (a:Vector<_>) = - let mA= a.NumRows - createVecGU a.OpsData mA (fun i -> f a.[i]) - - let map2VecGU f (a:Vector<'a>) (b:Vector<'a>) : Vector<'a> = - let mA= if a.NumRows = b.NumRows then a.NumRows else raise (ArgumentException("Vectors of different length.")) - createVecGU a.OpsData mA (fun i -> f a.[i] b.[i]) - - let map3VecGU f (a:Vector<'a>) (b:Vector<'a>) (c:Vector<'a>) : Vector<'a> = - let mA= if a.NumRows = b.NumRows && a.NumRows = c.NumRows then a.NumRows else raise (ArgumentException("Vectors of different length.")) - createVecGU a.OpsData mA (fun i -> f a.[i] b.[i] c.[i]) - - let zipVecGU (a:Vector<'a>) (b:Vector<'b>) : Vector<'a*'b> = - let mA= if a.NumRows = b.NumRows then a.NumRows else raise (ArgumentException("Vectors of different length.")) - createVecGU None mA (fun i -> a.[i],b.[i]) - - let unzipVecGU (a : Vector<'a*'b>) : Vector<'a> * Vector<'b> = - let mA = a.NumRows - createVecGU None mA (fun i -> fst a.[i]),createVecGU None mA (fun i -> snd a.[i]) - - let copyDenseMatrixGU (a : DenseMatrix<'T>) : DenseMatrix<'T> = - let arrA = a.Values - createDenseMatrixGU a.OpsData a.NumRows a.NumCols (fun i j -> getArray2D arrA i j) - - let copyVecGU (a:Vector<_>) = - createVecGU a.OpsData a.NumRows (fun i -> a.[i]) - - let copyRowVecGU (a:RowVector<_>) = - createRowVecGU a.OpsData a.NumCols (fun i -> a.[i]) - - let toDenseSparseMatrixGU (a:SparseMatrix<_>) = - createDenseMatrixGU a.OpsData a.NumRows a.NumCols (fun i j -> a.[i,j]) - - let mapiDenseMatrixGU f (a: DenseMatrix<'T>) : DenseMatrix<'T> = - let arrA = a.Values - createDenseMatrixGU a.OpsData a.NumRows a.NumCols (fun i j -> f i j (getArray2D arrA i j)) - - let mapRowVecGU f (a:RowVector<_>) = - createRowVecGU a.OpsData a.NumCols (fun i -> f a.[i]) - - let mapiRowVecGU f (a:RowVector<_>) = - createRowVecGU a.OpsData a.NumCols (fun i -> f i a.[i]) - - let mapiVecGU f (a:Vector<_>) = - createVecGU a.OpsData a.NumRows (fun i -> f i a.[i]) - - let permuteVecGU (p:permutation) (a:Vector<_>) = - createVecGU a.OpsData a.NumRows (fun i -> a.[p i]) - - let permuteRowVecGU (p:permutation) (a:RowVector<_>) = - createRowVecGU a.OpsData a.NumCols (fun i -> a.[p i]) - - let inline inplace_mapDenseMatrixGU f (a:DenseMatrix<_>) = - let arrA = a.Values - assignDenseMatrixGU (fun i j -> f (getArray2D arrA i j)) a - - let inline inplace_mapRowVecGU f (a:RowVector<_>) = - assignRowVecGU (fun i -> f a.[i]) a - - let inline inplace_mapVecGU f (a:Vector<_>) = - assignVecGU (fun i -> f a.[i]) a - - let inline inplace_mapiDenseMatrixGU f (a:DenseMatrix<_>) = - let arrA = a.Values - assignDenseMatrixGU (fun i j -> f i j (getArray2D arrA i j)) a - - let inline inplace_mapiRowVecGU f (a:RowVector<_>) = - assignRowVecGU (fun i -> f i a.[i]) a - - let inline inplace_mapiVecGU f (a:Vector<_>) = - assignVecGU (fun i -> f i a.[i]) a - - let inline foldDenseMatrixGU f z (a:DenseMatrix<_>) = - let nA = a.NumCols - let mA = a.NumRows - let arrA = a.Values - let mutable acc = z - for i = 0 to mA-1 do - for j = 0 to nA-1 do - acc <- f acc (getArray2D arrA i j) - acc - - let inline foldVecGU f z (a:Vector<_>) = - let mutable acc = z - for i = 0 to a.NumRows-1 do acc <- f acc a.[i] - acc - - let inline foldiDenseMatrixGU f z (a:DenseMatrix<_>) = - let nA = a.NumCols - let mA = a.NumRows - let arrA = a.Values - let mutable acc = z - for i = 0 to mA-1 do - for j = 0 to nA-1 do - acc <- f i j acc (getArray2D arrA i j) - acc - - let inline foldiVecGU f z (a:Vector<_>) = - let mA = a.NumRows - let mutable acc = z - for i = 0 to mA-1 do acc <- f i acc a.[i] - acc - - let rec forallR f (n,m) = (n > m) || (f n && forallR f (n+1,m)) - let rec existsR f (n,m) = (n <= m) && (f n || existsR f (n+1,m)) - - let foralliDenseMatrixGU pred (a:DenseMatrix<_>) = - let nA = a.NumCols - let mA = a.NumRows - let arrA = a.Values - (0,mA-1) |> forallR (fun i -> - (0,nA-1) |> forallR (fun j -> - pred i j (getArray2D arrA i j))) - - let foralliVecGU pred (a:Vector<_>) = - let mA = a.NumRows - (0,mA-1) |> forallR (fun i -> - pred i a.[i]) - - let existsiDenseMatrixGU pred (a:DenseMatrix<_>) = - let nA = a.NumCols - let mA = a.NumRows - let arrA = a.Values - (0,mA-1) |> existsR (fun i -> - (0,nA-1) |> existsR (fun j -> - pred i j (getArray2D arrA i j))) - - let existsiVecGU pred (a:Vector<_>) = - let mA = a.NumRows - (0,mA-1) |> existsR (fun i -> - pred i a.[i]) - - let sumDenseMatrixGU (a:DenseMatrix<_>) = - let ops = a.ElementOps - foldDenseMatrixGU (fun acc aij -> add ops acc aij) ops.Zero a - - let sumSparseMatrixGU (a:SparseMatrix<_>) = - let ops = a.ElementOps - a |> nonZeroEntriesSparseMatrixGU |> Seq.fold (fun acc (_,_,aij) -> add ops acc aij) ops.Zero - - let sumVecGU (a:Vector<_>) = - let ops = a.ElementOps - foldVecGU (fun acc ai -> add ops acc ai) ops.Zero a - - let prodDenseMatrixGU (a:DenseMatrix<_>) = - let ops = a.ElementOps - foldDenseMatrixGU (fun acc aij -> mul ops acc aij) ops.One a - - let prodSparseMatrixGU (a:SparseMatrix<_>) = a |> toDenseSparseMatrixGU |> prodDenseMatrixGU - - let inline fold2DenseMatrixGU f z (a:DenseMatrix<_>) (b:DenseMatrix<_>) = - let nA = a.NumCols - let mA = a.NumRows - let nB = b.NumCols - let mB = b.NumRows - if nA <> nB || mA <> mB then invalidArg "b" "the two matrices do not have compatible dimensions" - let arrA = a.Values - let arrB = b.Values - let mutable acc = z - for i = 0 to mA-1 do - for j = 0 to nA-1 do - acc <- f acc (getArray2D arrA i j) (getArray2D arrB i j) - acc - - let inline fold2VecGU f z (a:Vector<_>) (b:Vector<_>) = - let mA = a.NumRows - let mB = b.NumRows - if mA <> mB then invalidArg "b" "the two vectors do not have compatible dimensions" - let mutable acc = z - for i = 0 to mA-1 do acc <- f acc a.[i] b.[i] - acc - - let dotDenseMatrixGU (a:DenseMatrix<_>) b = - let ops = a.ElementOps - fold2DenseMatrixGU (fun z va vb -> add ops z (mul ops va vb)) ops.Zero a b - - let dotVecGU (a:Vector<_>) b = - let ops = a.ElementOps - let zero = ops.Zero - fold2VecGU (fun z va vb -> add ops z (mul ops va vb)) zero a b - - let normDenseMatrixGU (a:DenseMatrix<_>) = - let normOps = getNormOps a.ElementOps - foldDenseMatrixGU (fun z aij -> z + ((normOps.Norm aij)**2.0)) 0.0 a |> sqrt - - let normSparseMatrixGU (a:SparseMatrix<_>) = - let normOps = getNormOps a.ElementOps - a |> nonZeroEntriesSparseMatrixGU |> Seq.fold (fun acc (_,_,aij) -> acc + ((normOps.Norm aij)**2.0)) 0.0 |> sqrt - - let inplaceAddDenseMatrixGU (a:DenseMatrix<_>) (b:DenseMatrix<_>) = - let ops = a.ElementOps - let arrB = b.Values - inplace_mapiDenseMatrixGU (fun i j x -> add ops x (getArray2D arrB i j)) a - - let inplaceAddVecGU (a:Vector<_>) (b:Vector<_>) = - let ops = a.ElementOps - inplace_mapiVecGU (fun i x -> add ops x b.[i]) a - - let inplaceAddRowVecGU (a:RowVector<_>) (b:Vector<_>) = - let ops = a.ElementOps - inplace_mapiRowVecGU (fun i x -> add ops x b.[i]) a - - let inplaceSubDenseMatrixGU (a:DenseMatrix<_>) (b:DenseMatrix<_>) = - let ops = a.ElementOps - let arrB = b.Values - inplace_mapiDenseMatrixGU (fun i j x -> sub ops x (getArray2D arrB i j)) a - - let inplaceSubVecGU (a:Vector<_>) (b:Vector<_>) = - let ops = a.ElementOps - inplace_mapiVecGU (fun i x -> sub ops x b.[i]) a - - let inplaceSubRowVecGU (a:RowVector<_>) (b:Vector<_>) = - let ops = a.ElementOps - inplace_mapiRowVecGU (fun i x -> sub ops x b.[i] ) a - - let inplaceCptMulDenseMatrixGU (a:DenseMatrix<_>) (b:DenseMatrix<_>) = - let ops = a.ElementOps - let arrB = b.Values - inplace_mapiDenseMatrixGU (fun i j x -> mul ops x (getArray2D arrB i j)) a - - let inplaceCptMulVecGU (a:Vector<_>) (b:Vector<_>) = - let ops = a.ElementOps - inplace_mapiVecGU (fun i x -> mul ops x b.[i]) a - - let inplaceCptMulRowVecGU (a:RowVector<_>) (b:Vector<_>) = - let ops = a.ElementOps - inplace_mapiRowVecGU (fun i x -> mul ops x b.[i] ) a - - let inplaceScaleDenseMatrixGU x (a:DenseMatrix<_>) = - let ops = a.ElementOps - inplace_mapiDenseMatrixGU (fun _ _ y -> ops.Multiply(x,y)) a - - let inplaceScaleVecGU x (a:Vector<_>) = - let ops = a.ElementOps - inplace_mapiVecGU (fun _ y -> ops.Multiply(x,y)) a - - let inplaceScaleRowVecGU x (a:RowVector<_>) = - let ops = a.ElementOps - inplace_mapiRowVecGU (fun _ y -> ops.Multiply(x,y)) a - - - let wrapList (pre,mid,post,trim) show l = - let post = if trim then "; ..." + post else post - match l with - | [] -> [pre;post] - | [x] -> [pre;show x;post] - | x::xs -> [pre;show x] @ (List.collect (fun x -> [mid;show x]) xs) @ [post] - - let showItem opsData x = - try - let ops = opsOfOpsData opsData - ops.ToString(x,"g10",System.Globalization.CultureInfo.InvariantCulture) - with :? System.NotSupportedException -> (box x).ToString() - - let mapR f (n,m) = if m < n then [] else List.init (m-n+1) (fun i -> f (n+i)) - - let primShowDenseMatrixGU (sepX,sepR) (a : DenseMatrix<'e>) = - let nA = min a.NumCols DenseMaxDisplay - let mA = min a.NumRows DenseMaxDisplay - let ops = a.OpsData - let showLine i = wrapList ("[",";","]", a.NumCols > nA) (showItem ops) ((0,nA-1) |> mapR (fun j -> a.[i,j])) |> Array.ofList |> System.String.Concat - wrapList (string nA + " " + string mA + "matrix [",";"+sepX,"]"+sepR, a.NumRows > mA) showLine [0..mA-1] |> Array.ofList |> System.String.Concat - - let showDenseMatrixGU m = primShowDenseMatrixGU ("\n","\n") m - let debugShowDenseMatrixGU m = primShowDenseMatrixGU ("" ,"" ) m - - let showVecGU s (a : Vector<_>) = - let mA = min a.NumRows VectorMaxDisplay - let ops = a.OpsData - wrapList (s+" [",";","]",a.NumRows > mA) (showItem ops) ((0,mA-1) |> mapR (fun i -> a.[i])) |> Array.ofList |> System.String.Concat - - let showRowVecGU s (a : RowVector<_>) = - let mA = min a.NumCols VectorMaxDisplay - let ops = a.OpsData - wrapList (s+" [",";","]",a.NumCols > mA) (showItem ops) ((0,mA-1) |> mapR (fun i -> a.[i])) |> Array.ofList |> System.String.Concat - - - /// Implementations of operations specific to floating point types - module DoubleImpl = - - module GU = GenericImpl - open Instances - - // Element type OpsData - //type elem = float - let zero = 0.0 - let one = 1.0 - let inline sub (x:float) (y:float) = x - y - let inline add (x:float) (y:float) = x + y - let inline mul (x:float) (y:float) = x * y - let inline neg (x:float) = -x - - // Specialized: these know the relevant set of - // ops without doing a table lookup based on runtime type - let FloatOps = Some (FloatNumerics :> INumeric) - let inline initDenseMatrixDS m n f = GU.createDenseMatrixGU FloatOps m n f - let inline createRowVecDS m f = GU.createRowVecGU FloatOps m f - let inline createVecDS m f = GU.createVecGU FloatOps m f - let inline mkDenseMatrixDS arr = GU.mkDenseMatrixGU FloatOps arr - let inline mkRowVecDS arr = GU.mkRowVecGU FloatOps arr - let inline mkVecDS arr = GU.mkVecGU FloatOps arr - let inline listDenseMatrixDS ll = GU.listDenseMatrixGU FloatOps ll - let inline colListDenseMatrixDS ll = GU.colListDenseMatrixGU FloatOps ll - let inline listRowVecDS l = GU.listRowVecGU FloatOps l - let inline listVecDS l = GU.listVecGU FloatOps l - let inline seqDenseMatrixDS ll = GU.seqDenseMatrixGU FloatOps ll - let inline colSeqDenseMatrixDS ll = GU.colSeqDenseMatrixGU FloatOps ll - let inline arrayDenseMatrixDS ll = GU.arrayDenseMatrixGU FloatOps ll - let inline colArrayDenseMatrixDS ll = GU.colArrayDenseMatrixGU FloatOps ll - let inline seqRowVecDS l = GU.seqRowVecGU FloatOps l - let inline seqVecDS l = GU.seqVecGU FloatOps l - - let constDenseMatrixDS m n x = GU.createDenseMatrixGU FloatOps m n (fun _ _ -> x) - let constRowVecDS m x = GU.createRowVecGU FloatOps m (fun _ -> x) - let constVecDS m x = GU.createVecGU FloatOps m (fun _ -> x) - let scalarDenseMatrixDS x = constDenseMatrixDS 1 1 x - let scalarRowVecDS x = constRowVecDS 1 x - let scalarVecDS x = constVecDS 1 x - - // Beware - when compiled with non-generic code createArray2D creates an array of null values, - // not zero values. Hence the optimized version can only be used when compiling with generics. - let inline zeroDenseMatrixDS m n = - let arr = GU.createArray2D m n - GU.mkDenseMatrixGU FloatOps arr - // Specialized: these inline down to the efficient loops we need - let addDenseMatrixDS a b = GU.binaryOpDenseMatrixGU add a b - let addSparseDS a b = GU.binaryOpSparseMatrixGU add a b - let addRowVecDS a b = GU.binaryOpRowVecGU add a b - let addVecDS a b = GU.binaryOpVecGU add a b - let subDenseMatrixDS a b = GU.binaryOpDenseMatrixGU sub a b - let subSparseDS a b = GU.binaryOpSparseMatrixGU sub a b - let mulSparseDS a b = GU.genericMulSparse zero add mul a b - let subRowVecDS a b = GU.binaryOpRowVecGU sub a b - let subVecDS a b = GU.binaryOpVecGU sub a b - let cptMulDenseMatrixDS a b = GU.binaryOpDenseMatrixGU mul a b - let cptMulSparseDS a b = GU.binaryOpSparseMatrixGU mul a b - let cptMulRowVecDS a b = GU.binaryOpRowVecGU mul a b - let cptMulVecDS a b = GU.binaryOpVecGU mul a b - type smatrix = SparseMatrix - type dmatrix = DenseMatrix - type vector = Vector - type rowvec = RowVector - let cptMaxDenseMatrixDS (a:dmatrix) (b:dmatrix) = GU.binaryOpDenseMatrixGU max a b - let cptMinDenseMatrixDS (a:dmatrix) (b:dmatrix) = GU.binaryOpDenseMatrixGU min a b - let cptMaxSparseDS (a:smatrix) (b:smatrix) = GU.binaryOpSparseMatrixGU max a b - let cptMinSparseDS (a:smatrix) (b:smatrix) = GU.binaryOpSparseMatrixGU min a b - let cptMaxVecDS (a:vector) (b:vector) = GU.binaryOpVecGU max a b - let cptMinVecDS (a:vector) (b:vector) = GU.binaryOpVecGU min a b - - // Don't make any mistake about these ones re. performance. - let mulDenseMatrixDS (a:dmatrix) (b:dmatrix) = - let nA = a.NumCols - let mA = a.NumRows - let nB = b.NumCols - let mB = b.NumRows - if nA<>mB then invalidArg "b" "the two matrices do not have compatible dimensions" - let arr = GU.createArray2D mA nB - let arrA = a.Values - let arrB = b.Values - for i = 0 to mA - 1 do - for j = 0 to nB - 1 do - let mutable r = 0.0 - for k = 0 to mB - 1 do - r <- r + mul (GU.getArray2D arrA i k) (GU.getArray2D arrB k j) - GU.setArray2D arr i j r - mkDenseMatrixDS arr - - let mulRowVecDenseMatrixDS (a:rowvec) (b:dmatrix) = - let nA = a.NumCols - let nB = b.NumCols - let mB = b.NumRows - if nA<>mB then invalidArg "b" "the two inputs do not have compatible dimensions" - let arr = Array.zeroCreate nB - let arrA = a.Values - let arrB = b.Values - for j = 0 to nB - 1 do - let mutable r = 0.0 - for k = 0 to mB - 1 do - r <- r + mul arrA.[k] (GU.getArray2D arrB k j) - arr.[j] <- r - mkRowVecDS arr - - let mulDenseMatrixVecDS (a:dmatrix) (b:vector) = - let nA = a.NumCols - let mA = a.NumRows - let mB = b.NumRows - if nA<>mB then invalidArg "b" "the two inputs do not have compatible dimensions" - let arr = Array.zeroCreate mA - let arrA = a.Values - let arrB = b.Values - for i = 0 to mA - 1 do - let mutable r = 0.0 - for k = 0 to nA - 1 do - r <- r + mul (GU.getArray2D arrA i k) arrB.[k] - arr.[i] <- r - mkVecDS arr - - let mulRowVecVecDS (a:rowvec) (b:vector) = - let nA = a.NumCols - let mB = b.NumRows - if nA<>mB then invalidArg "b" "the two vectors do not have compatible dimensions" - let arrA = a.Values - let arrB = b.Values - let mutable r = 0.0 - for k = 0 to nA - 1 do - r <- r + mul arrA.[k] arrB.[k] - r - - let rowvecDenseMatrixDS (x:rowvec) = initDenseMatrixDS 1 x.NumCols (fun _ j -> x.[j]) - let vectorDenseMatrixDS (x:vector) = initDenseMatrixDS x.NumRows 1 (fun i _ -> x.[i]) - let mulVecRowVecDS a b = mulDenseMatrixDS (vectorDenseMatrixDS a) (rowvecDenseMatrixDS b) - - let scaleDenseMatrixDS k m = GU.unaryOpDenseMatrixGU (fun x -> mul k x) m - let scaleSparseDS k m = GU.unaryOpSparseGU (fun x -> mul k x) m - let scaleRowVecDS k m = GU.unaryOpRowVecGU (fun x -> mul k x) m - let scaleVecDS k m = GU.unaryOpVectorGU (fun x -> mul k x) m - // add + - let addScalarDenseMatrixDS k m = GU.unaryOpDenseMatrixGU (fun x -> add k x) m - let addScalarSparseDS k m = GU.unaryOpSparseGU (fun x -> add k x) m - let addScalarRowVecDS k m = GU.unaryOpRowVecGU (fun x -> add k x) m - let addScalarVecDS k m = GU.unaryOpVectorGU (fun x -> add k x) m - // sub - - let subScalarDenseMatrixDS k m = GU.unaryOpDenseMatrixGU (fun x -> sub k x) m - let subScalarSparseDS k m = GU.unaryOpSparseGU (fun x -> sub k x) m - let subScalarRowVecDS k m = GU.unaryOpRowVecGU (fun x -> sub k x) m - let subScalarVecDS k m = GU.unaryOpVectorGU (fun x -> sub k x) m - - let negDenseMatrixDS m = GU.unaryOpDenseMatrixGU (fun x -> neg x) m - let negSparseDS m = GU.unaryOpSparseGU (fun x -> neg x) m - let negRowVecDS m = GU.unaryOpRowVecGU (fun x -> neg x) m - let negVecDS m = GU.unaryOpVectorGU (fun x -> neg x) m - - let traceDenseMatrixDS (a:dmatrix) = - let nA = a.NumCols - let mA = a.NumRows - if nA<>mA then invalidArg "a" "expected a square matrix"; - let arrA = a.Values - (0,nA-1) |> GU.sumfR (fun i -> GU.getArray2D arrA i i) - - let sumDenseMatrixDS a = GU.foldDenseMatrixGU add zero a - let sumVecDS a = GU.foldVecGU add zero a - let prodDenseMatrixDS a = GU.foldDenseMatrixGU mul one a - let prodVecDS a = GU.foldVecGU mul one a - - let dotDenseMatrixDS a b = GU.fold2DenseMatrixGU (fun z va vb -> add z (mul va vb)) zero a b - let dotVecDS a b = GU.fold2VecGU (fun z va vb -> add z (mul va vb)) zero a b - let sumfDenseMatrixDS f m = GU.foldDenseMatrixGU (fun acc aij -> add acc (f aij)) zero m - let normDenseMatrixDS m = sqrt (sumfDenseMatrixDS (fun x -> x*x) m) - - let inplaceAddDenseMatrixDS a (b:DenseMatrix<_>) = let arrB = b.Values in GU.inplace_mapiDenseMatrixGU (fun i j x -> x + GU.getArray2D arrB i j) a - let inplaceAddVecDS a (b:Vector<_>) = let arrB = b.Values in GU.inplace_mapiVecGU (fun i x -> x + arrB.[i]) a - let inplace_addRowVecDS a (b:RowVector<_>) = let arrB = b.Values in GU.inplace_mapiRowVecGU (fun i x -> x + arrB.[i]) a - let inplaceSubDenseMatrixDS a (b:DenseMatrix<_>) = let arrB = b.Values in GU.inplace_mapiDenseMatrixGU (fun i j x -> x - GU.getArray2D arrB i j) a - let inplaceSubVecDS a (b:Vector<_>) = let arrB = b.Values in GU.inplace_mapiVecGU (fun i x -> x - arrB.[i]) a - let inplace_subRowVecDS a (b:RowVector<_>) = let arrB = b.Values in GU.inplace_mapiRowVecGU (fun i x -> x - arrB.[i]) a - let inplaceCptMulDenseMatrixDS a (b:DenseMatrix<_>) = let arrB = b.Values in GU.inplace_mapiDenseMatrixGU (fun i j x -> x * GU.getArray2D arrB i j) a - let inplaceCptMulVecDS a (b:Vector<_>) = let arrB = b.Values in GU.inplace_mapiVecGU (fun i x -> x * arrB.[i]) a - let inplace_cptMulRowVecDS a (b:RowVector<_>) = let arrB = b.Values in GU.inplace_mapiRowVecGU (fun i x -> x * arrB.[i]) a - let inplaceScaleDenseMatrixDS (a:float) b = GU.inplace_mapiDenseMatrixGU (fun _ _ x -> a * x) b - let inplaceScaleVecDS (a:float) b = GU.inplace_mapiVecGU (fun _ x -> a * x) b - let inplace_scaleRowVecDS (a:float) b = GU.inplace_mapiRowVecGU (fun _ x -> a * x) b - - - - /// Generic operations that, when used on floating point types, use the specialized versions in DoubleImpl - module SpecializedGenericImpl = - -// open Microsoft.FSharp.Math.Instances -// open Microsoft.FSharp.Math.GlobalAssociations - open FSharp.Stats.Instances - open FSharp.Stats.GlobalAssociations - - module GU = GenericImpl - module DS = DoubleImpl - - - type smatrix = SparseMatrix - type dmatrix = DenseMatrix - type vector = Vector - type rowvec = RowVector - let inline dense x = DenseRepr(x) - let inline sparse x = SparseRepr(x) - let inline createMx ops rows columns f = GU.createDenseMatrixGU ops rows columns f |> dense - let inline createVx ops m f = GU.createVecGU ops m f - let inline createRVx ops m f = GU.createRowVecGU ops m f - - let nonZeroEntriesM a = - match a with - | DenseRepr a -> GU.nonzeroEntriesDenseMatrixGU a - | SparseRepr a -> GU.nonZeroEntriesSparseMatrixGU a - - /// Merge two sorted sequences - /// - /// - /// - /// - /// - /// - /// - /// - /// - let mergeSorted cf (s1: seq<'T>) (s2: seq<'b>) = - seq { use e1 = s1.GetEnumerator() - use e2 = s2.GetEnumerator() - let havee1 = ref (e1.MoveNext()) - let havee2 = ref (e2.MoveNext()) - while !havee1 || !havee2 do - if !havee1 && !havee2 then - let v1 = e1.Current - let v2 = e2.Current - let c = cf v1 v2 - if c < 0 then - do havee1 := e1.MoveNext() - yield Some(v1),None - elif c = 0 then - do havee1 := e1.MoveNext() - do havee2 := e2.MoveNext() - yield Some(v1),Some(v2) - else - do havee2 := e2.MoveNext() - yield (None,Some(v2)) - elif !havee1 then - let v1 = e1.Current - do havee1 := e1.MoveNext() - yield (Some(v1),None) - else - let v2 = e2.Current - do havee2 := e2.MoveNext() - yield (None,Some(v2)) } - - /// Non-zero entries from two sequences - let mergedNonZeroEntriesM (a:Matrix<_>) (b:Matrix<_>) = - let ops = a.ElementOps - let zero = ops.Zero - mergeSorted (fun (i1,j1,_) (i2,j2,_) -> let c = compare i1 i2 in if c <> 0 then c else compare j1 j2) (nonZeroEntriesM a) (nonZeroEntriesM b) - |> Seq.map (function | Some(i,j,v1),Some(_,_,v2) -> (v1,v2) - | Some(i,j,v1),None -> (v1,zero) - | None, Some(i,j,v2) -> (zero,v2) - | None, None -> failwith "unreachable") - - - - // Creation - let listM xss : Matrix<'T> = GU.listDenseMatrixGU opsdata<'T> xss |> dense - let listV xss : Vector<'T> = GU.listVecGU opsdata<'T> xss - let listRV xss : RowVector<'T> = GU.listRowVecGU opsdata<'T> xss - - let arrayM xss : Matrix<'T> = GU.mkDenseMatrixGU opsdata<'T> (Array2D.copy xss) |> dense - let arraySM xss : Matrix<'T> = GU.mkSparseMatrixGU opsdata<'T> (Array2D.copy xss) |> sparse - let arrayV xss : Vector<'T> = GU.mkVecGU opsdata<'T> (Array.copy xss) - let arrayRV xss : RowVector<'T> = GU.mkRowVecGU opsdata<'T> (Array.copy xss) - - let rowVecM xss: Matrix<'T> = GU.rowvecDenseMatrixGU xss |> dense - let vecM xss: Matrix<'T> = GU.vectorDenseMatrixGU xss |> dense - - let seqM xss : Matrix<'T> = GU.seqDenseMatrixGU opsdata<'T> xss |> dense - let seqCM xss : Matrix<'T> = GU.colSeqDenseMatrixGU opsdata<'T> xss |> dense - let seqV xss : Vector<'T> = GU.seqVecGU opsdata<'T> xss - let seqRV xss : RowVector<'T> = GU.seqRowVecGU opsdata<'T> xss - - let initM m n f : Matrix<'T> = GU.createDenseMatrixGU opsdata<'T> m n f |> dense - let initRV m f : RowVector<'T> = GU.createRowVecGU opsdata<'T> m f - let initV m f : Vector<'T> = GU.createVecGU opsdata<'T> m f - - let constM m n x : Matrix<'T> = GU.createConstDenseMatrixGU opsdata<'T> m n x |> dense - let constRV m x : RowVector<'T> = GU.createConstRowVecGU opsdata<'T> m x - let constV m x : Vector<'T> = GU.createConstVecGU opsdata<'T> m x - - let inline inplaceAssignM f a = - match a with - | SparseRepr _ -> sparseNotMutable() - | DenseRepr a -> GU.assignDenseMatrixGU f a - let inline assignV f a = GU.assignVecGU f a - - let coerce2 x = unbox(box(x)) - let loosenDM (x: dmatrix) : DenseMatrix<_> = coerce2 x - let loosenSM (x: smatrix) : SparseMatrix<_> = coerce2 x - let loosenV (x: vector) : Vector<_> = coerce2 x - let loosenRV (x: rowvec) : RowVector<_> = coerce2 x - let loosenF (x: float) : 'T = coerce2 x - - let tightenDM (x: DenseMatrix<_>) : dmatrix = coerce2 x - let tightenSM (x: SparseMatrix<_>) : smatrix = coerce2 x - let tightenV (x: Vector<_>) : vector = coerce2 x - let tightenRV (x: RowVector<_>) : rowvec = coerce2 x - let tightenF (x: 'T) : float = coerce2 x - - let zeroM m n = - let arr = GU.createArray2D m n - // This is quite performance critical - // Avoid assigining zeros into the array - match box arr with - | :? (float[,]) as arr -> GU.mkDenseMatrixGU DS.FloatOps arr |> loosenDM |> dense - | _ -> - GU.zeroizeDenseMatrixGUA arr m n |> dense - - let zeroV m : Vector<'T> = - let arr = GU.createArray m - // Avoid assigining zeros into the array - match box (arr: 'T[]) with - | :? (float[]) as arr -> GU.mkVecGU DS.FloatOps arr |> loosenV - | _ -> - GU.zeroizeVecGUA arr m - - let zeroRV m : RowVector<'T> = - let arr = GU.createArray m - // Avoid assigining zeros into the array - match box (arr: 'T[]) with - | :? (float[]) as arr -> GU.mkRowVecGU DS.FloatOps arr |> loosenRV - | _ -> - GU.zeroizeRowVecGUA arr m - - let initNumericM m n f = - let arr = GU.createArray2D m n - let opsData = opsdata<'T> - let ops = GU.opsOfOpsData opsData - GU.assignArray2D m n (f ops) arr; - GU.mkDenseMatrixGU opsData arr |> dense - - let identityM m = - let arr = GU.createArray2D m m - // This is quite performance critical - // Avoid assigining zeros into the array - match box arr with - | :? (float[,]) as arr -> - for i = 0 to m - 1 do - arr.[i,i] <- 1.0 - GU.mkDenseMatrixGU DS.FloatOps arr |> loosenDM |> dense - | _ -> - let opsData = opsdata<'T> - let ops = GU.opsOfOpsData opsData - let zero = ops.Zero - let one = ops.One - GU.assignArray2D m m (fun i j -> if i = j then one else zero) arr; - GU.mkDenseMatrixGU opsData arr |> dense - - let createNumericV m f : Vector<'T> = - let arr = GU.createArray m - let opsData = opsdata<'T> - let ops = GU.opsOfOpsData opsData - GU.assignArray m (f ops) arr; - GU.mkVecGU opsData arr - - let scalarM x = constM 1 1 x - let scalarRV x = constRV 1 x - let scalarV x = constV 1 x - - let diagnM (v:Vector<_>) n = - let ops = v.ElementOps - let zero = ops.Zero - let nV = v.NumRows + (if n < 0 then -n else n) - createMx v.OpsData nV nV (fun i j -> if i+n=j then v.[i] else zero) - - let diagM v = diagnM v 0 - - let constDiagM n x : Matrix<'T> = - let opsData = opsdata<'T> - let ops = GU.opsOfOpsData opsData - let zero = ops.Zero - createMx opsData n n (fun i j -> if i=j then x else zero) - - // Note: we drop sparseness on pointwise multiplication of sparse and dense. - let inline binaryOpM opDenseDS opDenseGU opSparseDS opSparseMatrixGU a b = - match a,b with - | DenseRepr a,DenseRepr b -> - match box a with - | (:? dmatrix as a) -> opDenseDS a (tightenDM b) |> loosenDM |> dense - | _ -> opDenseGU a b |> dense - | SparseRepr a,SparseRepr b -> - match box a with - | (:? smatrix as a) -> opSparseDS a (tightenSM b) |> loosenSM |> sparse - | _ -> opSparseMatrixGU a b |> sparse - | SparseRepr a, DenseRepr b -> opDenseGU (GU.toDenseSparseMatrixGU a) b |> dense - | DenseRepr a, SparseRepr b -> opDenseGU a (GU.toDenseSparseMatrixGU b) |> dense - - let inline unaryOpM opDenseDS opDenseGU opSparseDS opSparseMatrixGU b = - match b with - | DenseRepr b -> - match box b with - | (:? dmatrix as b) -> opDenseDS b |> loosenDM |> dense - | _ -> opDenseGU b |> dense - | SparseRepr b -> - match box b with - | (:? smatrix as b) -> opSparseDS b |> loosenSM |> sparse - | _ -> opSparseMatrixGU b |> sparse - - let inline floatUnaryOpM opDenseDS opDenseGU opSparseDS opSparseMatrixGU b = - match b with - | DenseRepr b -> - match box b with - | (:? dmatrix as b) -> opDenseDS b |> loosenF - | _ -> opDenseGU b - | SparseRepr b -> - match box b with - | (:? smatrix as b) -> opSparseDS b |> loosenF - | _ -> opSparseMatrixGU b - - let addM a b = binaryOpM DS.addDenseMatrixDS GU.addDenseMatrixGU DS.addSparseDS GU.addSparseMatrixGU a b - let subM a b = binaryOpM DS.subDenseMatrixDS GU.subDenseMatrixGU DS.subSparseDS GU.subSparseMatrixGU a b - let mulM a b = binaryOpM DS.mulDenseMatrixDS GU.genericMulDenseMatrix DS.mulSparseDS GU.mulSparseMatrixGU a b - let cptMulM a b = binaryOpM DS.cptMulDenseMatrixDS GU.cptMulDenseMatrixGU DS.cptMulSparseDS GU.cptMulSparseMatrixGU a b - let cptMaxM a b = binaryOpM DS.cptMaxDenseMatrixDS GU.cptMaxDenseMatrixGU DS.cptMaxSparseDS GU.cptMaxSparseMatrixGU a b - let cptMinM a b = binaryOpM DS.cptMinDenseMatrixDS GU.cptMinDenseMatrixGU DS.cptMinSparseDS GU.cptMinSparseMatrixGU a b - - let addRV a b = - match box a with - | (:? rowvec as a) -> DS.addRowVecDS a (tightenRV b) |> loosenRV - | _ -> GU.addRowVecGU a b - - let addV a b = - match box a with - | (:? vector as a) -> DS.addVecDS a (tightenV b) |> loosenV - | _ -> GU.addVecGU a b - - let subRV a b = - match box a with - | (:? rowvec as a) -> DS.subRowVecDS a (tightenRV b) |> loosenRV - | _ -> GU.subRowVecGU a b - - let subV a b = - match box a with - | (:? vector as a) -> DS.subVecDS a (tightenV b) |> loosenV - | _ -> GU.subVecGU a b - - let mulRVM a b = - match b with - | DenseRepr b -> - match box a with - | (:? rowvec as a) -> DS.mulRowVecDenseMatrixDS a (tightenDM b) |> loosenRV - | _ -> GU.mulRowVecDenseMatrixGU a b - | SparseRepr b -> GU.mulRVSparseMatrixGU a b - - let mulMV a b = - match a with - | DenseRepr a -> - match box a with - | (:? dmatrix as a) -> DS.mulDenseMatrixVecDS a (tightenV b) |> loosenV - | _ -> GU.mulDenseMatrixVecGU a b - | SparseRepr a -> GU.mulSparseVecGU a b - - let mulRVV a b = - match box a with - | (:? rowvec as a) -> DS.mulRowVecVecDS a (tightenV b) |> loosenF - | _ -> GU.mulRowVecVecGU a b - - let mulVRV a b = - match box a with - | (:? vector as a) -> DS.mulVecRowVecDS a (tightenRV b) |> loosenDM |> dense - | _ -> GU.mulVecRowVecGU a b |> dense - - let cptMulRV a b = - match box a with - | (:? rowvec as a) -> DS.cptMulRowVecDS a (tightenRV b) |> loosenRV - | _ -> GU.cptMulRowVecGU a b - - let cptMulV a b = - match box a with - | (:? vector as a) -> DS.cptMulVecDS a (tightenV b) |> loosenV - | _ -> GU.cptMulVecGU a b - - let cptMaxV a b = - match box a with - | (:? vector as a) -> DS.cptMaxVecDS a (tightenV b) |> loosenV - | _ -> GU.cptMaxVecGU a b - - let cptMinV a b = - match box a with - | (:? vector as a) -> DS.cptMinVecDS a (tightenV b) |> loosenV - | _ -> GU.cptMinVecGU a b - - let scaleM a b = unaryOpM (fun b -> DS.scaleDenseMatrixDS (tightenF a) b) (GU.scaleDenseMatrixGU a) - (fun b -> DS.scaleSparseDS (tightenF a) b) (GU.scaleSparseMatrixGU a) b - - let scaleRV a b = - match box b with - | (:? rowvec as b) -> DS.scaleRowVecDS (tightenF a) b |> loosenRV - | _ -> GU.scaleRowVecGU a b - - let scaleV a b = - match box b with - | (:? vector as b) -> DS.scaleVecDS (tightenF a) b |> loosenV - | _ -> GU.scaleVecGU a b - - let addScalarM a b = unaryOpM (fun b -> DS.addScalarDenseMatrixDS (tightenF a) b) (GU.addScalarDenseMatrixGU a) - (fun b -> DS.addScalarSparseDS (tightenF a) b) (GU.addScalarSparseMatrixGU a) b - - let addScalarRV a b = - match box b with - | (:? rowvec as b) -> DS.addScalarRowVecDS (tightenF a) b |> loosenRV - | _ -> GU.addScalarRowVecGU a b - - let addScalarV a b = - match box b with - | (:? vector as b) -> DS.addScalarVecDS (tightenF a) b |> loosenV - | _ -> GU.addScalarVecGU a b - - let subScalarM a b = unaryOpM (fun b -> DS.subScalarDenseMatrixDS (tightenF a) b) (GU.subScalarDenseMatrixGU a) - (fun b -> DS.subScalarSparseDS (tightenF a) b) (GU.subScalarSparseMatrixGU a) b - - let subScalarRV a b = - match box b with - | (:? rowvec as b) -> DS.subScalarRowVecDS (tightenF a) b |> loosenRV - | _ -> GU.subScalarRowVecGU a b - - let subScalarV a b = - match box b with - | (:? vector as b) -> DS.subScalarVecDS (tightenF a) b |> loosenV - | _ -> GU.subScalarVecGU a b - - let dotM a b = - match a,b with - | DenseRepr a,DenseRepr b -> - match box b with - | (:? dmatrix as b) -> DS.dotDenseMatrixDS (tightenDM a) b |> loosenF - | _ -> GU.dotDenseMatrixGU a b - | _ -> - let ops = a.ElementOps - mergedNonZeroEntriesM a b |> Seq.fold (fun z (va,vb) -> GU.add ops z (GU.mul ops va vb)) ops.Zero - - let dotV a b = - match box b with - | (:? vector as b) -> DS.dotVecDS (tightenV a) b |> loosenF - | _ -> GU.dotVecGU a b - - let negM a = unaryOpM DS.negDenseMatrixDS GU.negDenseMatrixGU DS.negSparseDS GU.negSparseMatrixGU a - - let negRV a = - match box a with - | (:? rowvec as a) -> DS.negRowVecDS a |> loosenRV - | _ -> GU.negRowVecGU a - - let negV a = - match box a with - | (:? vector as a) -> DS.negVecDS a |> loosenV - | _ -> GU.negVecGU a - - let traceMGU (a:Matrix<_>) = - let nA = a.NumCols - let mA = a.NumRows - if nA<>mA then invalidArg "a" "expected a square matrix"; - let ops = a.ElementOps - (0,nA-1) |> GU.sumRGU ops (fun i -> a.[i,i]) - - let traceM a = floatUnaryOpM DS.traceDenseMatrixDS (dense >> traceMGU) (sparse >> traceMGU) (sparse >> traceMGU) a - let sumM a = floatUnaryOpM DS.sumDenseMatrixDS GU.sumDenseMatrixGU GU.sumSparseMatrixGU GU.sumSparseMatrixGU a - let prodM a = floatUnaryOpM DS.prodDenseMatrixDS GU.prodDenseMatrixGU GU.prodSparseMatrixGU GU.prodSparseMatrixGU a - let normM a = floatUnaryOpM DS.normDenseMatrixDS GU.normDenseMatrixGU GU.normSparseMatrixGU GU.normSparseMatrixGU a - - let opsM a = - match a with - | DenseRepr a -> a.OpsData - | SparseRepr a -> a.OpsData - - let transM a = - match a with - | DenseRepr a -> - // rows of transposed matrix = columns of original matrix and vice versa - createMx a.OpsData a.NumCols a.NumRows (fun i j -> a.[j,i]) - | SparseRepr a -> - a |> GU.nonZeroEntriesSparseMatrixGU |> Seq.map (fun (i,j,v) -> (j,i,v)) |> GU.initSparseMatrixGU a.NumCols a.NumRows a.OpsData |> sparse - - let permuteRows (p: permutation) a = - match a with - | DenseRepr a -> - createMx a.OpsData a.NumRows a.NumCols (fun i j -> a.[p i,j]) - | SparseRepr a -> - a |> GU.nonZeroEntriesSparseMatrixGU |> Seq.map (fun (i,j,v) -> (p i,j,v)) |> GU.initSparseMatrixGU a.NumCols a.NumRows a.OpsData |> sparse - - let permuteColumns (p: permutation) a = - match a with - | DenseRepr a -> - createMx a.OpsData a.NumRows a.NumCols (fun i j -> a.[i,p j]) - | SparseRepr a -> - a |> GU.nonZeroEntriesSparseMatrixGU |> Seq.map (fun (i,j,v) -> (i,p j,v)) |> GU.initSparseMatrixGU a.NumCols a.NumRows a.OpsData |> sparse - - let transRV (a:RowVector<_>) = - createVx a.OpsData a.NumCols (fun i -> a.[i]) - - let transV (a:Vector<_>) = - createRVx a.OpsData a.NumRows (fun i -> a.[i]) - - let inplaceAddM a b = - match a,b with - | DenseRepr a,DenseRepr b -> - match box a with - | (:? dmatrix as a) -> DS.inplaceAddDenseMatrixDS a (tightenDM b) - | _ -> GU.inplaceAddDenseMatrixGU a b - | _ -> sparseNotMutable() - - let inplaceAddV a b = - match box a with - | (:? vector as a) -> DS.inplaceAddVecDS a (tightenV b) - | _ -> GU.inplaceAddVecGU a b - - let inplaceSubM a b = - match a,b with - | DenseRepr a,DenseRepr b -> - match box a with - | (:? dmatrix as a) -> DS.inplaceSubDenseMatrixDS a (tightenDM b) - | _ -> GU.inplaceSubDenseMatrixGU a b - | _ -> sparseNotMutable() - - let inplaceSubV a b = - match box a with - | (:? vector as a) -> DS.inplaceSubVecDS a (tightenV b) - | _ -> GU.inplaceSubVecGU a b - - - let inplaceCptMulM a b = - match a,b with - | DenseRepr a,DenseRepr b -> - match box a with - | (:? dmatrix as a) -> DS.inplaceCptMulDenseMatrixDS a (tightenDM b) - | _ -> GU.inplaceCptMulDenseMatrixGU a b - | _ -> sparseNotMutable() - - let inplaceCptMulV a b = - match box a with - | (:? vector as a) -> DS.inplaceCptMulVecDS a (tightenV b) - | _ -> GU.inplaceCptMulVecGU a b - - let inplaceScaleM a b = - match b with - | DenseRepr b -> - match box b with - | (:? dmatrix as b) -> DS.inplaceScaleDenseMatrixDS (tightenF a) b - | _ -> GU.inplaceScaleDenseMatrixGU a b - | _ -> sparseNotMutable() - - let inplaceScaleV a b = - match box b with - | (:? vector as b) -> DS.inplaceScaleVecDS (tightenF a) b - | _ -> GU.inplaceScaleVecGU a b - - let existsM f a = - match a with - | SparseRepr _ -> sparseNYI() // note: martin says "run f on a token element if it's not full" - | DenseRepr a -> GU.existsiDenseMatrixGU (fun _ _ -> f) a - - let existsV f a = GU.existsiVecGU (fun _ -> f) a - - let forallM f a = - match a with - | SparseRepr _ -> sparseNYI() - | DenseRepr a -> GU.foralliDenseMatrixGU (fun _ _ -> f) a - - let forallV f a = GU.foralliVecGU (fun _ -> f) a - - let existsiM f a = - match a with - | SparseRepr _ -> sparseNYI() - | DenseRepr a -> GU.existsiDenseMatrixGU f a - - let existsiV f a = GU.existsiVecGU f a - - let foralliM f a = - match a with - | SparseRepr _ -> sparseNYI() - | DenseRepr a -> GU.foralliDenseMatrixGU f a - - let foralliV f a = GU.foralliVecGU f a - - let mapM f a = - match a with - | SparseRepr _ -> sparseNYI() - | DenseRepr a -> DenseRepr(GU.mapDenseMatrixGU f a) - - let mapV f a = GU.mapVecGU f a - - let map2V f a b = GU.map2VecGU f a b - - let map3V f a b c = GU.map3VecGU f a b c - - let zipV a b = GU.zipVecGU a b - - let unzipV a = GU.unzipVecGU a - - let copyM a = - match a with - | SparseRepr a -> SparseRepr (GU.copySparseGU a) - | DenseRepr a -> DenseRepr (GU.copyDenseMatrixGU a) - - let copyV a = GU.copyVecGU a - - let copyRV a = GU.copyRowVecGU a - - let mapiM f a = - match a with - | SparseRepr _ -> sparseNYI() - | DenseRepr a -> DenseRepr (GU.mapiDenseMatrixGU f a) - - let mapiV f a = GU.mapiVecGU f a - let permuteV p a = GU.permuteVecGU p a - let permuteRV p a = GU.permuteRowVecGU p a - - let mapRV f a = GU.mapRowVecGU f a - - let mapiRV f a = GU.mapiRowVecGU f a - - let toDenseM a = - match a with - | SparseRepr a -> GU.toDenseSparseMatrixGU a |> dense - | DenseRepr _ -> a - let toSparseM (a: Matrix<'T>) = - match a with - | SparseRepr _ -> a - | DenseRepr a -> - let length1 = a.NumRows - let length2 = a.NumCols - - let mutable nnz = 0 - let ar = FSharp.Collections.ResizeArray<'T>() - let ja = FSharp.Collections.ResizeArray() - let ia = FSharp.Collections.ResizeArray() - ia.Add(0) - - for i = 0 to (length1 - 1) do - for j = 0 to (length2 - 1) do - if (a.Item(i, j)|> System.Convert.ToDouble) >= 0.000001 || (a.Item(i, j)|> System.Convert.ToDouble) <= -0.000001 then - ar.Add(a.Item(i, j)) - ja.Add(j) - nnz <- nnz + 1 - ia.Add(nnz) - SparseRepr (SparseMatrix(opsdata<'T>, ar.ToArray(), ia.ToArray(), length2, ja.ToArray())) - - let initSparseM i j x : Matrix<'T> = - let opsData = opsdata<'T> - GU.initSparseMatrixGU i j opsData x |> sparse - - let initDenseM i j x : Matrix<'T> = - let r = zeroM i j - x |> Seq.iter (fun (i,j,v) -> r.[i,j] <- v); - r - - let getDiagnM (a:Matrix<_>) n = - let nA = a.NumCols - let mA = a.NumRows - if nA<>mA then invalidArg "a" "expected a square matrix"; - let ni = if n < 0 then -n else 0 - let nj = if n > 0 then n else 0 - GU.createVecGU (opsM a) (max (nA-abs(n)) 0) (fun i -> a.[i+ni,i+nj]) - - let getDiagM a = getDiagnM a 0 - - let inline inplace_mapM f a = - match a with - | SparseRepr _ -> sparseNotMutable() - | DenseRepr a -> GU.inplace_mapDenseMatrixGU f a - - let inline inplace_mapiM f a = - match a with - | SparseRepr _ -> sparseNotMutable() - | DenseRepr a -> GU.inplace_mapiDenseMatrixGU f a - - let inline inplace_mapV f a = GU.inplace_mapVecGU f a - - let inline inplace_mapiV f a = GU.inplace_mapiVecGU f a - - let inline foldM f z a = - match a with - | SparseRepr _ -> sparseNYI() - | DenseRepr a -> GU.foldDenseMatrixGU f z a - - let inline foldV f z a = GU.foldVecGU f z a - - let inline foldiM f z a = - match a with - | SparseRepr _ -> sparseNYI() - | DenseRepr a -> GU.foldiDenseMatrixGU f z a - - let inline foldiV f z a = GU.foldiVecGU f z a - - let compareM (comp: IComparer) (a:Matrix<'T>) (b:Matrix<'T>) = - let nA = a.NumCols - let mA = a.NumRows - let nB = b.NumCols - let mB = b.NumRows - let c = compare mA mB - if c <> 0 then c else - let c = compare nA nB - if c <> 0 then c else - match a,b with - | DenseRepr a, DenseRepr b -> - let rec go2 i j = - if j < nA then - let c = comp.Compare( a.[i,j], b.[i,j]) - if c <> 0 then c else - go2 i (j+1) - else 0 - let rec go1 i = - if i < mA then - let c = go2 i 0 - if c <> 0 then c - else go1 (i+1) - else 0 - go1 0 - | _ -> - match (mergedNonZeroEntriesM a b |> Seq.tryPick (fun (v1,v2) -> let c = comp.Compare(v1,v2) in if c = 0 then None else Some(c))) with - | None -> 0 - | Some(c) -> c - - let equalsM (comp: IEqualityComparer) (a:Matrix<'T>) (b:Matrix<'T>) = - let nA = a.NumCols - let mA = a.NumRows - let nB = b.NumCols - let mB = b.NumRows - (mA = mB ) && (nA = nB) && - match a,b with - | DenseRepr a, DenseRepr b -> - let rec go2 i j = j >= nA || (comp.Equals( a.[i,j], b.[i,j]) && go2 i (j+1) ) - let rec go1 i = i >= mA || (go2 i 0 && go1 (i+1)) - go1 0 - | _ -> - mergedNonZeroEntriesM a b |> Seq.forall (fun (v1,v2) -> comp.Equals(v1,v2)) - - - let compareV (comp: IComparer) (a:Vector<'T>) (b:Vector<'T>) = - let mA = a.NumRows - let mB = b.NumRows - let c = compare mA mB - if c <> 0 then c else - let rec go2 j = - if j < mA then - let c = comp.Compare(a.[j],b.[j]) - if c <> 0 then c else go2 (j+1) - else 0 - go2 0 - - let equalsV (comp: IEqualityComparer) (a:Vector<'T>) (b:Vector<'T>) = - let mA = a.NumRows - let mB = b.NumRows - (mA = mB) && - let rec go2 j = (j >= mA) || (comp.Equals(a.[j],b.[j]) && go2 (j+1)) - go2 0 - - let equalsRV (comp: IEqualityComparer) (a:RowVector<'T>) (b:RowVector<'T>) = - let mA = a.NumCols - let mB = b.NumCols - (mA = mB) && - let rec go2 j = (j >= mA) || (comp.Equals(a.[j],b.[j]) && go2 (j+1)) - go2 0 - - let compareRV (comp: IComparer) (a:RowVector<'T>) (b:RowVector<'T>) = - let mA = a.NumCols - let mB = b.NumCols - let c = compare mA mB - if c <> 0 then c else - let rec go2 j = - if j < mA then - let c = comp.Compare(a.[j],b.[j]) - if c <> 0 then c else go2 (j+1) - else 0 - go2 0 - - let inline combineHash x y = (x <<< 1) + y + 631 - - let hashM (comp:IEqualityComparer) (a:Matrix<_>) = - let nA = a.NumCols - let mA = a.NumRows - let acc = hash mA + hash nA - a |> nonZeroEntriesM |> Seq.truncate 20 |> Seq.fold (fun z v -> combineHash z (comp.GetHashCode v)) acc - - let hashV (comp:IEqualityComparer) (a:Vector<_>) = - let mA = a.NumRows - hash mA + - (let mutable c = 0 - for i = 0 to mA - 1 do - c <- combineHash c (comp.GetHashCode a.[i]) - c) - - let hashRV (comp:IEqualityComparer) (a:RowVector<_>) = - let mA = a.NumCols - hash mA + - (let mutable c = 0 - for i = 0 to mA - 1 do - c <- combineHash c (comp.GetHashCode a.[i]) - c) - - type range = int * int - - let startR ((a,_) : range) = a - let countR ((a,b) : range) = (b-a)+1 - let idxR ((a,_) : range) i = a+i - let inR ((a,b) : range) i = a <= i && i <= b - ///Returns row of index i of matrix a as a vector - let getRowM (a:Matrix<_>) i = createRVx (opsM a) a.NumCols (fun j -> a.[i,j]) - /// Replaces row of index j of matrix a with values of vector v, if vector length matches rowsize - /// - /// - /// - /// - /// - /// - /// - /// - /// - let setRowM (a:Matrix<_>) i (v:Vector<_>) = - if a.NumCols = v.Length then - let l = v.Length-1 - for j = 0 to l do - a.[i,j] <- v.[j] - elif a.NumCols < v.Length then - failwith ("Can't set row, vector is longer than matrix column number") - else - failwith ("Can't set row, vector is shorter than matrix column number") - ///Returns col of index i of matrix a as a vector - let getColM (a:Matrix<_>) j = createVx (opsM a) a.NumRows (fun i -> a.[i,j]) - /// Replaces column of index i of matrix a with values of vector v, if vector length matches columnsize - /// - /// - /// - /// - /// - /// - /// - /// - /// - let setColM (a:Matrix<_>) j (v:Vector<_>) = - if a.NumRows = v.Length then - let l = v.Length-1 - for i = 0 to l do - a.[i,j] <- v.[i] - elif a.NumCols < v.Length then - failwith ("Can't set column, vector is longer than matrix row number") - else - failwith ("Can't set column, vector is shorter than matrix row number") - let getRegionV (a:Vector<_>) r = createVx a.OpsData (countR r) (fun i -> a.[idxR r i]) - let getRegionRV (a:RowVector<_>) r = createRVx a.OpsData (countR r) (fun i -> a.[idxR r i]) - - let getRegionM a ri rj = - match a with - | DenseRepr a -> createMx a.OpsData (countR ri) (countR rj) (fun i j -> a.[idxR ri i, idxR rj j]) - | _ -> nonZeroEntriesM a - |> Seq.filter (fun (i,j,_) -> inR ri i && inR rj j) - |> Seq.map (fun (i,j,v) -> (i-startR ri,j-startR rj,v)) - |> initSparseM (countR ri) (countR rj) - - let getColsM (a:Matrix<_>) rj = getRegionM a (0,a.NumRows - 1) rj - let getRowsM (a:Matrix<_>) ri = getRegionM a ri (0,a.NumCols - 1) - - let rowvecM (x:RowVector<_>) = initM 1 x.NumCols (fun _ j -> x.[j]) - let vectorM (x:Vector<_>) = initM x.NumRows 1 (fun i _ -> x.[i]) - let toVectorM x = getColM x 0 - let toRowVectorM x = getRowM x 0 - let toScalarM (x:Matrix<_>) = x.[0,0] - - - -//---------------------------------------------------------------------------- -// type Matrix<'T> augmentation -//---------------------------------------------------------------------------- -// Interface implementation - - type Matrix<'T> with - static member ( + )(a: Matrix<'T>,b) = SpecializedGenericImpl.addM a b - static member ( - )(a: Matrix<'T>,b) = SpecializedGenericImpl.subM a b - static member ( * )(a: Matrix<'T>,b) = SpecializedGenericImpl.mulM a b - static member ( * )(a: Matrix<'T>,b : Vector<'T>) = SpecializedGenericImpl.mulMV a b - - static member ( * )((m: Matrix<'T>),k : 'T) = SpecializedGenericImpl.scaleM k m - - static member ( .* )(a: Matrix<'T>,b) = SpecializedGenericImpl.cptMulM a b - static member ( * )(k,m: Matrix<'T>) = SpecializedGenericImpl.scaleM k m - static member ( ~- )(m: Matrix<'T>) = SpecializedGenericImpl.negM m - static member ( ~+ )(m: Matrix<'T>) = m - // add + - static member ( + )(a: Matrix<'T>,k: 'T) = SpecializedGenericImpl.addScalarM k a - static member ( + )(k: 'T,a: Matrix<'T>) = SpecializedGenericImpl.addScalarM k a - // sub - - static member ( - )(a: Matrix<'T>,k: 'T) = SpecializedGenericImpl.subScalarM k a - static member ( - )(k: 'T,a: Matrix<'T>) = SpecializedGenericImpl.subScalarM k a - - member m.GetSlice (start1,finish1,start2,finish2) = - let start1 = match start1 with None -> 0 | Some v -> v - let finish1 = match finish1 with None -> m.NumRows - 1 | Some v -> v - let start2 = match start2 with None -> 0 | Some v -> v - let finish2 = match finish2 with None -> m.NumCols - 1 | Some v -> v - SpecializedGenericImpl.getRegionM m (start1,finish1) (start2,finish2) - - member m.SetSlice (start1,finish1,start2,finish2,vs:Matrix<_>) = - let start1 = match start1 with None -> 0 | Some v -> v - let finish1 = match finish1 with None -> m.NumRows - 1 | Some v -> v - let start2 = match start2 with None -> 0 | Some v -> v - let finish2 = match finish2 with None -> m.NumCols - 1 | Some v -> v - for i = start1 to finish1 do - for j = start2 to finish2 do - m.[i,j] <- vs.[i-start1,j-start2] - - /// RowCount * ColumnCount - member m.Dimensions = m.NumRows,m.NumCols - - member m.Transpose = SpecializedGenericImpl.transM m - member m.PermuteRows (p: permutation) : Matrix<'T> = SpecializedGenericImpl.permuteRows p m - member m.PermuteColumns (p: permutation) : Matrix<'T> = SpecializedGenericImpl.permuteColumns p m - - -// Interface implementation - - interface IEnumerable<'T> with - member m.GetEnumerator() = - (seq { for i in 0 .. m.NumRows-1 do - for j in 0 .. m.NumCols - 1 do - yield m.[i,j] }).GetEnumerator() - - interface IEnumerable with - member m.GetEnumerator() = ((m :> IEnumerable<_>).GetEnumerator() :> IEnumerator) - - interface System.IComparable with - member m.CompareTo(yobj:obj) = SpecializedGenericImpl.compareM LanguagePrimitives.GenericComparer m (yobj :?> Matrix<'T>) - - interface IStructuralComparable with - member m.CompareTo(yobj:obj,comp:System.Collections.IComparer) = SpecializedGenericImpl.compareM comp m (yobj :?> Matrix<'T>) - - override m.GetHashCode() = SpecializedGenericImpl.hashM LanguagePrimitives.GenericEqualityComparer m - override m.Equals(yobj:obj) = - match yobj with - | :? Matrix<'T> as m2 -> SpecializedGenericImpl.equalsM LanguagePrimitives.GenericEqualityComparer m m2 - | _ -> false - - interface IStructuralEquatable with - member m.GetHashCode(comp:System.Collections.IEqualityComparer) = SpecializedGenericImpl.hashM comp m - member m.Equals(yobj:obj,comp:System.Collections.IEqualityComparer) = - match yobj with - | :? Matrix<'T> as m2 -> SpecializedGenericImpl.equalsM comp m m2 - | _ -> false - - /// Returns four chunks of the matrix as strings depending on the respective row/column start/end count, separated by a row and column indicating omitted rows and columns. - member m.FormatStrings(rowStartCount, rowEndCount, columnStartCount, columnEndCount) = - let nRows, nCols = m.Dimensions - let displayRows = rowStartCount + rowEndCount - let displayCols = columnStartCount + columnEndCount - - - if displayRows >= nRows && displayCols >= nCols then // this formats the full matrix without omitted rows/cols - Array.init (nRows+2) (fun rowIndex -> - match rowIndex with - | 0 -> [|"";"";yield! [for i = 0 to nCols-1 do yield string i]|] // column index header row - | 1 -> [|for i in 0 .. nCols+1 do yield ""|] // empty row to distinguish column indices from data in FSI/StructuredDisplay - | _ -> // the rest of the rows contain data - Array.init (nCols+2) (fun colIndex -> - match colIndex with - | 0 -> string (rowIndex-2) // the first column index contains the row index - | 1 -> "->" // the second column index contains a separator to distinguish row indices from data in FSI/StructuredDisplay - | _ -> m.[rowIndex-2,colIndex-2] |> formatValue // the rest is data. sswitches below work the same, only ommiting some of the data. - ) - ) - elif displayRows >= nRows && displayCols < nCols then // this formats the matrix with only ommitted cols - Array.init (nRows+2) (fun rowIndex -> - match rowIndex with - | 0 -> // column index header row - [| - "";""; - yield! [for i in [0 .. columnStartCount-1] do yield string i]; - "..."; - yield! [for i in [nCols - columnEndCount .. nCols - 1] do yield string i] - |] - | 1 -> [|for i in 0 .. (displayCols + 2) do yield ""|] // empty row to distinguish column indices from data in FSI/StructuredDisplay - | _ -> // the rest of the rows contain data - Array.init (columnStartCount+columnEndCount+3) (fun colIndex -> - if (colIndex-2) < columnStartCount then // left - match colIndex with - | 0 -> string (rowIndex-2) - | 1 -> "->" - | _ -> m.[rowIndex-2,colIndex-2] |> formatValue - elif (colIndex-2) > columnStartCount then // right - m[rowIndex-2,(nCols - 3 - columnEndCount + colIndex - columnStartCount)] |> formatValue - else - "..." // separator for signalling ommitted cols - ) - ) - elif displayRows < nRows && displayCols >= nCols then // this formats the matrix with only ommitted rows - Array.init (rowStartCount+rowEndCount+3) (fun rowIndex -> - match rowIndex with - | 0 -> [|"";"";yield! [for i = 0 to nCols-1 do yield string i]|] // column index header row - | 1 -> [|for i in 0 .. nCols+1 do yield ""|] // empty row to distinguish column indices from data in FSI/StructuredDisplay - | _ -> - Array.init (nCols+2) (fun colIndex -> - if (rowIndex-2) < rowStartCount then // upper half - match colIndex with - | 0 -> string (rowIndex-2) - | 1 -> "->" - | _ -> m.[rowIndex-2,colIndex-2] |> formatValue - elif (rowIndex-2) > rowStartCount then // lower half - match colIndex with - | 0 -> string (nRows - 3 - rowEndCount + rowIndex - rowStartCount) - | 1 -> "->" - | _ -> m[(nRows - 3 - rowEndCount + rowIndex - rowStartCount),colIndex - 2] |> formatValue - else - match colIndex with // separator for signalling ommitted rows - | 0 -> ":" - | 1 -> "" - | _ -> "..." - ) - ) - else // this formats the matrix with ommitted rows and cols - Array.init (rowStartCount+rowEndCount+3) (fun rowIndex -> - match rowIndex with - | 0 -> // column index header row - [| - "";""; - yield! [for i in [0 .. columnStartCount-1] do yield string i]; - "..."; - yield! [for i in [nCols - columnEndCount .. nCols - 1] do yield string i] - |] - | 1 -> [|for i in 0 .. (displayCols + 2) do yield ""|] // empty row to distinguish column indices from data in FSI/StructuredDisplay - | _ -> - Array.init (columnStartCount+columnEndCount+3) (fun colIndex -> - if (rowIndex-2) < rowStartCount then // upper half - if (colIndex-2) < columnStartCount then // upper left - match colIndex with - | 0 -> string (rowIndex-2) - | 1 -> "->" - | _ -> m.[rowIndex-2,colIndex-2] |> formatValue - elif (colIndex-2) > columnStartCount then // upper right - m[rowIndex-2,(nCols - 3 - columnEndCount + colIndex - columnStartCount)] |> formatValue - else - "..." - elif (rowIndex-2) > rowStartCount then // lower half - if (colIndex-2) < columnStartCount then // lower left - match colIndex with - | 0 -> string (nRows - 3 - rowEndCount + rowIndex - rowStartCount) - | 1 -> "->" - | _ -> m[(nRows - 3 - rowEndCount + rowIndex - rowStartCount),(colIndex-2)] |> formatValue - elif (colIndex-2) > columnStartCount then // lower right - m[(nRows - 3 - rowEndCount + rowIndex - rowStartCount),(nCols - 3 - columnEndCount + colIndex - columnStartCount)] |> formatValue - else - "..." - else - match colIndex with - | 0 -> ":" - | 1 -> "" - | _ -> "..." - ) - ) - - member m.Format(rowStartCount, rowEndCount, columnStartCount, columnEndCount, showInfo) = - try - let formattedtable = - m.FormatStrings(rowStartCount, rowEndCount, columnStartCount, columnEndCount) - |> array2D - |> Formatting.formatTable - if showInfo then - let matrixInfo = sprintf "Matrix of %i rows x %i columns" m.NumRows m.NumCols - sprintf "%s%s%s" formattedtable System.Environment.NewLine matrixInfo - else - formattedtable - with e -> sprintf "Formatting failed: %A" e - - member m.Format(rowCount, columnCount, showInfo:bool) = - let rowHalf = rowCount / 2 - let colHalf = columnCount / 2 - m.Format(rowHalf, rowHalf, colHalf, colHalf, showInfo) - - member m.Format(showInfo:bool) = - m.Format( - Formatting.Matrix.RowStartItemCount, - Formatting.Matrix.RowEndItemCount, - Formatting.Matrix.ColumnStartItemCount, - Formatting.Matrix.ColumnEndItemCount, - showInfo - ) - - interface IFsiFormattable with - member m.Format() = m.Format(false) - member m.FormatWithInfo() = m.Format(true) - - interface IMatrixFormattable with - member m.InteractiveFormat(rowCount,colCount) = - m.FormatStrings( - (rowCount / 2), - (rowCount / 2), - (colCount / 2), - (colCount / 2) - ) - member m.GetNumRows() = m.NumRows - member m.GetNumCols() = m.NumCols - - override m.ToString() = - match m with - | DenseRepr m -> GenericImpl.showDenseMatrixGU m - | SparseRepr _ -> "" - - member m.DebugDisplay = - let txt = - match m with - | DenseRepr m -> GenericImpl.debugShowDenseMatrixGU m - | SparseRepr _ -> "" - new System.Text.StringBuilder(txt) // return an object with a ToString with the right value, rather than a string. (strings get shown using quotes) - - member m.StructuredDisplayAsFormattedMatrix = - sprintf "%s%s" System.Environment.NewLine (m.Format(true)) - - member m.StructuredDisplayAsArray = - let rec layout m = - match m with - | DenseRepr _ -> box (Array2D.init m.NumRows m.NumCols (fun i j -> m.[i,j])) - | SparseRepr _ -> (if m.NumRows < 20 && m.NumCols < 20 then layout (SpecializedGenericImpl.toDenseM m) else box(SpecializedGenericImpl.nonZeroEntriesM m)) - layout m - - - -//---------------------------------------------------------------------------- -// type Vector<'T> augmentation -//---------------------------------------------------------------------------- -// Interface implementation - - type Vector<'T> with - static member ( + )(a: Vector<'T>,b) = SpecializedGenericImpl.addV a b - static member ( - )(a: Vector<'T>,b) = SpecializedGenericImpl.subV a b - static member ( .* )(a: Vector<'T>,b) = SpecializedGenericImpl.cptMulV a b - - static member ( * )(k,m: Vector<'T>) = SpecializedGenericImpl.scaleV k m - - static member ( * )(a: Vector<'T>,b) = SpecializedGenericImpl.mulVRV a b - - static member ( * )(m: Vector<'T>,k) = SpecializedGenericImpl.scaleV k m - - static member ( ~- )(m: Vector<'T>) = SpecializedGenericImpl.negV m - static member ( ~+ )(m: Vector<'T>) = m - - // add + - static member ( + )(k,m: Vector<'T>) = SpecializedGenericImpl.addScalarV k m - static member ( + )(m: Vector<'T>,k) = SpecializedGenericImpl.addScalarV k m - // sub - - static member ( - )(k,m: Vector<'T>) = SpecializedGenericImpl.subScalarV k m - static member ( - )(m: Vector<'T>,k) = SpecializedGenericImpl.subScalarV k m - - member m.GetSlice (start,finish) = - let start = match start with None -> 0 | Some v -> v - let finish = match finish with None -> m.NumRows - 1 | Some v -> v - SpecializedGenericImpl.getRegionV m (start,finish) - - member m.SetSlice (start,finish,vs:Vector<_>) = - let start = match start with None -> 0 | Some v -> v - let finish = match finish with None -> m.NumRows - 1 | Some v -> v - for i = start to finish do - m.[i] <- vs.[i-start] - - - member m.DebugDisplay = - let txt = GenericImpl.showVecGU "vector" m - new System.Text.StringBuilder(txt) // return an object with a ToString with the right value, rather than a string. (strings get shown using quotes) - - member m.StructuredDisplayAsArray = Array.init m.NumRows (fun i -> m.[i]) - - member m.Details = m.Values - - member m.Transpose = SpecializedGenericImpl.transV m - - member m.Permute (p:permutation) = SpecializedGenericImpl.permuteV p m - - - interface System.IComparable with - member m.CompareTo(y:obj) = SpecializedGenericImpl.compareV LanguagePrimitives.GenericComparer m (y :?> Vector<'T>) - - interface IStructuralComparable with - member m.CompareTo(y:obj,comp:System.Collections.IComparer) = SpecializedGenericImpl.compareV comp m (y :?> Vector<'T>) - - interface IStructuralEquatable with - member x.GetHashCode(comp) = SpecializedGenericImpl.hashV comp x - member x.Equals(yobj,comp) = - match yobj with - | :? Vector<'T> as v2 -> SpecializedGenericImpl.equalsV comp x v2 - | _ -> false - - override x.GetHashCode() = - SpecializedGenericImpl.hashV LanguagePrimitives.GenericEqualityComparer x - - override x.Equals(yobj) = - match yobj with - | :? Vector<'T> as v2 -> SpecializedGenericImpl.equalsV LanguagePrimitives.GenericEqualityComparer x v2 - | _ -> false - - override m.ToString() = GenericImpl.showVecGU "vector" m - -//---------------------------------------------------------------------------- -// type RowVector<'T> augmentation -//---------------------------------------------------------------------------- - - type RowVector<'T> with - static member ( + )(a: RowVector<'T>,b) = SpecializedGenericImpl.addRV a b - static member ( - )(a: RowVector<'T>,b) = SpecializedGenericImpl.subRV a b - static member ( .* )(a: RowVector<'T>,b) = SpecializedGenericImpl.cptMulRV a b - static member ( * )(k,v: RowVector<'T>) = SpecializedGenericImpl.scaleRV k v - - static member ( * )(a: RowVector<'T>,b: Matrix<'T>) = SpecializedGenericImpl.mulRVM a b - static member ( * )(a: RowVector<'T>,b:Vector<'T>) = SpecializedGenericImpl.mulRVV a b - static member ( * )(v: RowVector<'T>,k:'T) = SpecializedGenericImpl.scaleRV k v - - static member ( ~- )(v: RowVector<'T>) = SpecializedGenericImpl.negRV v - static member ( ~+ )(v: RowVector<'T>) = v - - // add + - static member ( + )(v: RowVector<'T>,k:'T) = SpecializedGenericImpl.addScalarRV k v - static member ( + )(k:'T,v: RowVector<'T>) = SpecializedGenericImpl.addScalarRV k v - // sub - - static member ( - )(v: RowVector<'T>,k:'T) = SpecializedGenericImpl.subScalarRV k v - static member ( - )(k:'T,v: RowVector<'T>) = SpecializedGenericImpl.subScalarRV k v - - member m.GetSlice (start,finish) = - let start = match start with None -> 0 | Some v -> v - let finish = match finish with None -> m.NumCols - 1 | Some v -> v - SpecializedGenericImpl.getRegionRV m (start,finish) - - member m.SetSlice (start,finish,vs:RowVector<_>) = - let start = match start with None -> 0 | Some v -> v - let finish = match finish with None -> m.NumCols - 1 | Some v -> v - for i = start to finish do - m.[i] <- vs.[i-start] - - - member m.DebugDisplay = - let txt = GenericImpl.showRowVecGU "rowvec" m - new System.Text.StringBuilder(txt) // return an object with a ToString with the right value, rather than a string. (strings get shown using quotes) - - member m.StructuredDisplayAsArray = Array.init m.NumCols (fun i -> m.[i]) - - member m.Details = m.Values - - member m.Transpose = SpecializedGenericImpl.transRV m - - member m.Permute (p:permutation) = SpecializedGenericImpl.permuteRV p m - - override m.ToString() = GenericImpl.showRowVecGU "rowvec" m - - interface System.IComparable with - member m.CompareTo(y) = SpecializedGenericImpl.compareRV LanguagePrimitives.GenericComparer m (y :?> RowVector<'T>) - - interface IStructuralComparable with - member m.CompareTo(y,comp) = SpecializedGenericImpl.compareRV comp m (y :?> RowVector<'T>) - - interface IStructuralEquatable with - member x.GetHashCode(comp) = SpecializedGenericImpl.hashRV comp x - member x.Equals(yobj,comp) = - match yobj with - | :? RowVector<'T> as rv2 -> SpecializedGenericImpl.equalsRV comp x rv2 - | _ -> false - - override x.GetHashCode() = - SpecializedGenericImpl.hashRV LanguagePrimitives.GenericEqualityComparer x - - override x.Equals(yobj) = - match yobj with - | :? RowVector<'T> as rv2 -> SpecializedGenericImpl.equalsRV LanguagePrimitives.GenericEqualityComparer x rv2 - | _ -> false - - - - - - type matrix = Matrix - type vector = Vector - type rowvec = RowVector - - - - -// type Matrix<'T> with -// member x.ToArray2() = Matrix.Generic.toArray2D x -// member x.ToArray2D() = Matrix.Generic.toArray2D x -// -//#if FX_NO_DEBUG_DISPLAYS -//#else -// [] -//#endif -// -// member x.NonZeroEntries = Matrix.Generic.nonzero_entries x -// member x.ToScalar() = Matrix.Generic.toScalar x -// member x.ToRowVector() = Matrix.Generic.toRowVector x -// member x.ToVector() = Matrix.Generic.toVector x -// -//#if FX_NO_DEBUG_DISPLAYS -//#else -// [] -//#endif -// member x.Norm = Matrix.Generic.norm x -// -// member x.Column(n) = Matrix.Generic.getCol x n -// member x.Row(n) = Matrix.Generic.getRow x n -// member x.Columns (i,ni) = Matrix.Generic.getCols x i ni -// member x.Rows (j,nj) = Matrix.Generic.getRows x j nj -// member x.Region(i,j,ni,nj) = Matrix.Generic.getRegion x i j ni nj -// member x.GetDiagonal(i) = Matrix.Generic.getDiagN x i -// -//#if FX_NO_DEBUG_DISPLAYS -//#else -// [] -//#endif -// member x.Diagonal = Matrix.Generic.getDiag x -// -// member x.Copy () = Matrix.Generic.copy x -// -// -// type Vector<'T> with -// member x.ToArray() = Vector.Generic.toArray x -// member x.Norm = Vector.Generic.norm x -// member x.Copy () = Vector.Generic.copy x -// -// -// type RowVector<'T> with -// member x.ToArray() = RowVector.Generic.toArray x -// member x.Copy () = RowVector.Generic.copy x -// -// [] -// module MatrixTopLevelOperators = -// -// let matrix ll = Matrix.ofSeq ll -// let vector l = Vector.ofSeq l -// let rowvec l = RowVector.ofSeq l - diff --git a/src/FSharp.Stats/Algebra/ILinearAlgebra.fs b/src/FSharp.Stats/Algebra/ILinearAlgebra.fs deleted file mode 100644 index bfbe859b6..000000000 --- a/src/FSharp.Stats/Algebra/ILinearAlgebra.fs +++ /dev/null @@ -1,122 +0,0 @@ -namespace FSharp.Stats.Algebra - -//namespace Microsoft.FSharp.Math // old namespace -open FSharp.Stats - - -///This is an internal interface and not for user usage. -///It exposes a specialised subset of BLAS/LAPACK functionality. -///This functionality is used by us to build the exposed APIs. -///It is those exposed APIs that should be used. -type ILinearAlgebra = - //Matrix-Matrix Multiplication - abstract dgemm_ : Matrix * Matrix -> Matrix - - ////Matrix-Vector Multiplication - //abstract dgemv_ : Matrix * Vector -> Vector - - ////Solve (linear equations) - //abstract dgesv_ : Matrix * Matrix -> Matrix * int array * Matrix - - ////Solve symmetric positive definite matrix (linear equations) - //abstract dposv_ : Matrix * Matrix -> Matrix * Matrix - - ////Solve triangular (linear equations) - //abstract dtrsv_ : char * Matrix * Vector -> Vector - - ////Solve triangular (linear equations) - //abstract dtrsm_ : char * Matrix * Matrix -> Matrix - - ////Solve (linear equations) using LU factorization - //abstract dgesvx_ : - // Matrix * Matrix -> - // Matrix * Matrix * int array * char * double array * double array * - // Matrix * Matrix * float * double array * double array - - ////Compoutes for an N-by-N real nonsymmetric matrix A, the - ////eigenvalue decomposition eigenvalues and right eigenvectors. - ////The right eigenvector v(j) of A satisfies - //// - //// A * v(j) = lambda(j) * v(j) - //// - ////where lambda(j) is its eigenvalue. - ////The computed eigenvectors are normalized to have Euclidean norm - ////equal to 1 and largest component real. Uses the LAPACK subroutine dgeev with arguments JOBVR = 'V' and JOBVL = 'N' - //// - ///Returns the real (first array) and imaginary (second array) parts of the eigenvalues and a matrix containing the corresponding eigenvectors - //abstract dgeev_ : Matrix -> double array * double array * Matrix - - ////Eigen Value of Symmetric Matrix - //abstract dsyev_ : char * char * Matrix -> Matrix * double array - - - ///Computes for a N-by-N real symmetric matrix A, the - ///eigenvalue decomposition of eigenvalues and right eigenvectors. - ///The right eigenvector v(j) of A satisfies - /// - /// A * v(j) = lambda(j) * v(j) - /// - ///where lambda(j) is its eigenvalue. - abstract dsyevd_ : Matrix -> Matrix * Vector - - ////Eigen Value for a pair of general matrices - //abstract dggev_ : - // Matrix * Matrix -> - // Matrix * Matrix * double array * double array * double array * - // double [,] - - ////Solve least-squares/min-norm. - ////Note the dimension requirements on second input to match second output. - //abstract dgels_ : Matrix * Matrix -> Matrix * Matrix - - ////Solve least-squares/min-norm (with linear equality constraint) - //abstract dgglse_ : - // Matrix * Matrix * Vector * Vector -> - // Matrix * Vector * double array - - ////Singular Value Decomposition - //abstract dgesvd_ : - // Matrix -> double array * Matrix * Matrix - - - ///Returns the full Singular Value Decomposition of the input MxN matrix - /// - ///A : A = U * SIGMA * V**T in the tuple (S, U, V**T), - /// - ///where S is an array containing the diagonal elements of SIGMA. - ///uses the LAPACK routine dgesdd with the argument JOBZ = 'A' - abstract dgesdd_ : Matrix -> double array * Matrix * Matrix - - ///rrqr - //abstract dgejsv_ : Matrix -> double array * Matrix * Matrix - - ///Returns the thin Singular Value Decomposition of the input MxN matrix A - /// - ///A = U * SIGMA * V**T in the tuple (S, U, V**T), - /// - ///where S is an array containing the diagonal elements of SIGMA. - ///The first min(M,N) columns of U and the first min(M,N) rows of V**T are returned in the arrays U and VT; - ///uses the LAPACK routine dgesdd with the argument JOBZ = 'S' - abstract dgesdd_thin_ : Matrix -> double array * Matrix * Matrix - - ////Single Value Decomposition for Symmetric Matrices - //abstract dsygv_ : - // Matrix * Matrix -> Matrix * Matrix * double array - - ////Single Value Decomposition for Symetric Matrices Divide and Conquer - //abstract dsygvd_ : - // Matrix * Matrix -> Matrix * Matrix * double array - - ////Cholesky Factorisation - //abstract dpotrf_ : char * Matrix -> Matrix - - //abstract dgetrf_ : matrix -> matrix * int[] - - ////Cholesky Factorisation - Expert - //abstract dposvx_ : - // Matrix * Matrix -> - // Matrix * Matrix * char * double array * Matrix * Matrix * - // float * double array * double array - - ////QR Factorisation - //abstract dgeqrf_ : Matrix -> Matrix * double array diff --git a/src/FSharp.Stats/Algebra/LinearAlgebraServiceMKL.fs b/src/FSharp.Stats/Algebra/LinearAlgebraServiceMKL.fs deleted file mode 100644 index 9eed14cba..000000000 --- a/src/FSharp.Stats/Algebra/LinearAlgebraServiceMKL.fs +++ /dev/null @@ -1,641 +0,0 @@ -namespace FSharp.Stats - -#nowarn "51" - -/// Warning: -/// IMPORTANT WARNING NOTICE: -/// INTEL MATH KERNEL LIBRARY 9.1 FOR WINDOWS IS THIRD PARTY TECHNOLOGY. -/// IT IS CLEARED ONLY FOR USE BY A SPECIFIC MSR RESEARCH TEAM. -/// DO NOT USE IT UNTIL YOU HAVE CLEARED ITS USE FOR YOUR PROJECT WITH YOUR LEGAL CONTACT. -/// -/// The following stubs bind directly to Intel MKL functionality. -/// You should not use them without: -/// a) Intel MKL developer licenses. -/// b) Seeking local legal approval. -module LapackMKLStubs = - - // [] - // [] - type CBLASLAYOUT = - | CblasRowMajor = 101 | CblasColMajor = 102 - - //[] - type CBLASTRANSPOSE = - | CblasNoTrans=111 | CblasTrans=112 | CblasConjTrans=113 - - - [] - //extern void dgemm_(char *transa, char *transb, int *m, int *n, int *k, double *alpha, double *a, int *lda, double *b, int *ldb, double *beta, double *c, int *ldc) - extern void dgemm_(CBLASLAYOUT *layout,CBLASTRANSPOSE *transa, CBLASTRANSPOSE *transb, int *m, int *n, int *k, double *alpha, double *a, int *lda, double *b, int *ldb, double *beta, double *c, int *ldc) - - // [] - // extern void dtrsv_(char *uplo,char *trans,char *diag,int *n,double *a,int *lda,double *x,int *incx) - - [] - extern void dtrsm_(char *side,char *uplo,char *trans,char *diag,int *m,int *n,double *alpha,double *a,int *lda,double *b,int *ldb) - - [] - extern void dgesv_(int *n, int *nrhs, double *a, int *lda, int *ipiv, double *b, int *ldb, int *info) - - [] - extern void dgeev_(char *jobvl, char *jobvr, int *n, double *a, int *lda, double *wr, double *wi, double *vl, int *ldvl, double *vr, int *ldvr, double *work, int *lwork, int *info) - // [] - // extern void dposv_(char *uplo, int *n, int *nrhs, double *a, int *lda, double *b, int *ldb, int *info) - - [] - extern void dgels_(char *trans, int *m,int *n, int *nrhs, double *a, int *lda, double *b, int *ldb, double *work, int *lwork, int *info) - - // [] - // extern void dgglse_(int *m, int *n, int *p, double *a, int *lda, double *b, int *ldb, double *c, double *d, double *x, double *work, int *lwork, int *info) - - [] - extern void dsyev_(char *jobz, char *uplo, int *n, double *a,int *lda, double *w, double *work, int *lwork, int *info) - - // [] - // extern void dsyevd_(char *jobz, char *uplo, int *n, double *a, int *lda, double *w, double *work, int *lwork, int *iwork, int *liwork, int *info) - - // Available - [] - extern void dgesvd_(char *jobu, char *jobvt, int *m, int *n, double *a, int *lda, double *s, double *u, int *ldu, double *vt, int *ldvt, double *work, int *lwork, int *info) - - [] - extern void dgesdd_(char *JOBZ, int *m, int *n, double *a, int *lda, double *s, double *u, int *ldu, double *vt, int *ldvt, double *work, int *lwork,int *iwork, int *info) - - [] - extern void dsygv_(int *itype, char *jobz, char *uplo, int *n, double *a, int *lda, double *b, int *ldb, double *w, double *work, int *lwork, int *info) - - [] - extern void dsygvd_(int *itype, char *jobz, char *uplo, int *n, double *a, int *lda, double *b, int *ldb, double *w, double *work, int *lwork,int *iwork, int *liwork, int *info) - - [] - extern void dggev_( char *jobvl, char *jobvr, int *n, double *a, int *lda, double *b, int *ldb, double *alphar, double *alphai,double *beta,double *vl,int *ldvl,double *vr,int *ldvr,double *work, int *lwork,int *info) - - [] - extern void dgesvx_(char *fact, char *trans, int *n, int *nrhs, double *a, int *lda, double *af, int *ldaf, int *ipiv, char *equed, double *r, double *c, double *b, int *ldb, double *x, int *ldx, double *rcond, double *ferr, double *berr, double *work, int *iwork, int *info) - - [] - extern void dposvx_(char *fact, char *uplo, int *n, int *nrhs, double *a, int *lda, double *af, int *ldaf, char *equed, double *s, double *b, int *ldb, double *x, int *ldx, double *rcond, double *ferr, double *berr, double *work, int *iwork, int *info) - - [] - extern void dpotrf_(char *uplo, int *n, double *a, int *lda, int *info) - - [] - extern void dgetrf_(int *m, int *n, double *a, int *lda, int *ipiv, int *info) - - [] - extern void dgeqrf_(int *m, int *n, double *a, int *lda, double *tau, double *work, int *lwork, int *info) - - [] - extern void dgemv_(int32* trans, int* m, int* n,double* alpha, double* A, int* lda,double* x, int* incx, double* beta,double* y, int* incy) - - -module BlasStubs = - - [] - extern void dgemm_(char *TRANSA, char *TRANSB, int *M, int *N, int *K, double *ALPHA, double *A, int *LDA, double *B, int *LDB, double *BETA, double *C, int *LDC) - - -module LapackStubs = - - [] - extern void dgesvd_(char* JOBU, char* JOBVT, int *M, int *N, double *A, int *LDA, double *S, double *U, int *LDU, double *VT, int *LDVT, double *WORK, int *LWORK, int *INFO) - - [] - extern void dgesdd_(char *JOBZ, int *M, int *N, double *A, int *LDA, double *S, double *U, int *LDU, double *VT, int *LDVT, double *WORK, int *LWORK, int *IWORK, int *INFO) - - //[] - //extern void dgejsv_(char *JOBA, char *JOBU, char *JOBV, char *JOBR, char *JOBT, char *JOBP, int *M, int *N, double *A, int *LDA, double *SVA, double *U, int *LDU, double *V, int *LDV, double *WORK, int *LWORK, int *IWORK, int *INFO) - - [] - extern void dgeev_(char *JOBVL, char *JOBVR, int *N, double *A, int *LDA, double *WR, double *WI, double *VL, int *LDVL, double *VR, int *LDVR, double *WORK, int *LWORK, int *INFO); - - [] - extern void dsyevd_(char *jobz, char *uplo, int *n, double *a, int *lda, double *w, double *work, int *lwork, int *iwork, int *liwork, int *info); - -open Microsoft.FSharp.NativeInterop -open LapackMKLStubs -open FSharp.Stats.Algebra - -/// Internal provider of MKL functionality, not for direct user usage. -type LinearAlgebraMKL() = - interface ILinearAlgebra with - - ///Matrix-Matrix Multiplication - member this.dgemm_ (a,b) = //(a:matrix) (b:matrix) = - // input copies - let a = Matrix.copy a - let b = Matrix.copy b - // dimensions - let m = NativeUtilities.matrixDim1 a in - let k = NativeUtilities.matrixDim2 a in - NativeUtilities.assertDimensions "dgemm_" ("k","Dim1(b)") (k,NativeUtilities.matrixDim1 b); - let n = NativeUtilities.matrixDim2 b in - // allocate results - let c = Matrix.zero (m) (n) - // transpose - let c = Matrix.transpose c - // setup actuals - let mutable arg_layout = CBLASLAYOUT.CblasColMajor //'t' - let mutable arg_transa = CBLASTRANSPOSE.CblasTrans//'t' - let mutable arg_transb = CBLASTRANSPOSE.CblasNoTrans//'t' - let mutable arg_m = m - let mutable arg_n = n - let mutable arg_k = k - let mutable arg_alpha = 1.0 - let arg_a = NativeUtilities.pinM a - let mutable arg_ldk = k - let arg_b = NativeUtilities.pinM b - let mutable arg_ldn = n - let mutable arg_beta = 1.0 - let arg_c = NativeUtilities.pinM c - let mutable arg_ldm = m - // call function - try - LapackMKLStubs.dgemm_(&&arg_layout,&&arg_transa,&&arg_transb,&&arg_m,&&arg_n,&&arg_k,&&arg_alpha,arg_a.Ptr,&&arg_ldk,arg_b.Ptr,&&arg_ldn,&&arg_beta,arg_c.Ptr,&&arg_ldm) - finally - NativeUtilities.freeM arg_a - NativeUtilities.freeM arg_b - NativeUtilities.freeM arg_c - // INFO - // fixups - let c = Matrix.transpose c - // result tuple - c - - - - - ///Singular Value Decomposition Divide- Conquer - member this.dgesdd_ (a:matrix) = - // input copies - let a = Matrix.copy a - // dimensions - let m = NativeUtilities.matrixDim1 a in - let n = NativeUtilities.matrixDim2 a in - // allocate results - let s = Array.zeroCreate (min m n) - let u = Matrix.zero (m) (m) - let vt = Matrix.zero (n) (n) - let work = Array.zeroCreate (1) - let iwork = Array.zeroCreate (8*(min m n)) - // transpose - let a = Matrix.transpose a - let u = Matrix.transpose u - let vt = Matrix.transpose vt - // setup actuals - let mutable arg_JOBZ = 'A' - let mutable arg_m = m - let mutable arg_n = n - let arg_a = NativeUtilities.pinM a - let mutable arg_lda = max 1 m - let arg_s = NativeUtilities.pinA s - let arg_u = NativeUtilities.pinM u - let mutable arg_ldu = m - let arg_vt = NativeUtilities.pinM vt - let mutable arg_ldvt = n - let arg_work = NativeUtilities.pinA work - let mutable arg_lwork = -1 - let arg_iwork = NativeUtilities.pinA iwork - let mutable arg_info = 0 - // ask for work array size - try - LapackMKLStubs.dgesdd_(&&arg_JOBZ,&&arg_m,&&arg_n,arg_a.Ptr,&&arg_lda,arg_s.Ptr,arg_u.Ptr,&&arg_ldu,arg_vt.Ptr,&&arg_ldvt,arg_work.Ptr,&&arg_lwork,arg_iwork.Ptr,&&arg_info) - finally - NativeUtilities.freeA arg_work - - if arg_info = 0 || arg_info=(-12) then - arg_lwork <- int32 work.[0] - else assert(false) - - let arg_work = NativeUtilities.pinA (Array.zeroCreate arg_lwork : float[]) - // call function - try - LapackMKLStubs.dgesdd_(&&arg_JOBZ,&&arg_m,&&arg_n,arg_a.Ptr,&&arg_lda,arg_s.Ptr,arg_u.Ptr,&&arg_ldu,arg_vt.Ptr,&&arg_ldvt,arg_work.Ptr,&&arg_lwork,arg_iwork.Ptr,&&arg_info) - finally - NativeUtilities.freeM arg_a - NativeUtilities.freeA arg_s - NativeUtilities.freeM arg_u - NativeUtilities.freeM arg_vt - NativeUtilities.freeA arg_work - NativeUtilities.freeA arg_iwork - // INFO - match arg_info with - | -1 -> failwith "dgesdd_: JOBZ (argument 1)" - | -2 -> failwith "dgesdd_: m (argument 2)" - | -3 -> failwith "dgesdd_: n (argument 3)" - | -4 -> failwith "dgesdd_: a (argument 4)" - | -5 -> failwith "dgesdd_: lda (argument 5)" - | -6 -> failwith "dgesdd_: s (argument 6)" - | -7 -> failwith "dgesdd_: u (argument 7)" - | -8 -> failwith "dgesdd_: ldu (argument 8)" - | -9 -> failwith "dgesdd_: vt (argument 9)" - | -10 -> failwith "dgesdd_: ldvt (argument 10)" - | -11 -> failwith "dgesdd_: work (argument 11)" - | -12 -> failwith "dgesdd_: lwork (argument 12)" - | -13 -> failwith "dgesdd_: iwork (argument 13)" - | -14 -> failwith "dgesdd_: info (argument 14)" - | 0 -> () - | n -> failwith (sprintf "dgesdd_ : returned %d. The computation failed." n) - // fixups - let u = Matrix.transpose u - let vt = Matrix.transpose vt - // result tuple - s,u,vt - - member this.dgesdd_thin_(a:matrix) = - printfn "Function not implemented yet, use the lapack provider" - ([||],matrix[||],matrix[||]) - - member this.dsyevd_(a:matrix) = - printfn "Function not implemented yet, use the lapack provider" - (matrix[||],vector [||]) - - //member this.dgeev_(a:Matrix) = - // Array.zeroCreate 0, Array.zeroCreate 0, matrix [||] - - -/// Internal provider of Lapack functionality, not for direct user usage. -type LinearAlgebraLAPACK() = - interface ILinearAlgebra with - //Matrix-Matrix Multiplication - member this.dgemm_ (a:Matrix,b:Matrix) = - - // input copies - let a = Matrix.copy a - let b = Matrix.copy b - - // dimensions - let m = NativeUtilities.matrixDim1 a in - let k = NativeUtilities.matrixDim2 a in - NativeUtilities.assertDimensions "dgemm_" ("k","Dim1(b)") (k,NativeUtilities.matrixDim1 b); - let n = NativeUtilities.matrixDim2 b in - - // allocate results - let c = Matrix.zero (m) (n) - - // transpose - let c = Matrix.transpose c - //setup actuals ------------------------------------------------------------ - //computation type and scalars - let mutable arg_TRANSA = 'T' - let mutable arg_TRANSB = 'T' - let mutable arg_alpha = 1. - let mutable arg_beta = 0. - - //dimensions of input arrays - let mutable arg_m = m - let mutable arg_n = n - let mutable arg_k = k - - let mutable arg_lda = max 1 k - let mutable arg_ldb = max 1 n - let mutable arg_ldc = max 1 m - - let arg_a = NativeUtilities.pinM a - let arg_b = NativeUtilities.pinM b - let arg_c = NativeUtilities.pinM c - - try - printfn "calling dgemm ..." - BlasStubs.dgemm_(&&arg_TRANSA,&&arg_TRANSB,&&arg_m,&&arg_n,&&arg_k,&&arg_alpha,arg_a.Ptr,&&arg_lda,arg_b.Ptr,&&arg_ldb,&&arg_beta,arg_c.Ptr,&&arg_ldc) - finally - NativeUtilities.freeM arg_a - NativeUtilities.freeM arg_b - NativeUtilities.freeM arg_c - - let c = Matrix.transpose c - // result tuple - c - //Full SVD - member this.dgesdd_(a:Matrix) = - - // input copies - let a = Matrix.copy a - // dimensions - let m = NativeUtilities.matrixDim1 a in - let n = NativeUtilities.matrixDim2 a in - - let s = Array.zeroCreate (min m n) - let u = Matrix.zero (m) (m) - let vt = Matrix.zero (n) (n) - let work = Array.zeroCreate (1) - let iwork = Array.zeroCreate (8*(min m n)) - - // transpose - let a = Matrix.transpose a - let u = Matrix.transpose u - let vt = Matrix.transpose vt - - //setup actuals ------------------------------------------------------------ - //computation type - let mutable arg_JOBZ = 'A' - - //dimensions of input array a - let mutable arg_m = m - let mutable arg_n = n - - //output matrices and their leading dimensions - let mutable arg_lda = max 1 m - let mutable arg_ldu = m - let mutable arg_ldvt = n - - let arg_s = NativeUtilities.pinA s - let arg_a = NativeUtilities.pinM a - let arg_u = NativeUtilities.pinM u - let arg_vt = NativeUtilities.pinM vt - - //workspaces - let arg_work = NativeUtilities.pinA work - let mutable arg_lwork = -1 - let arg_iwork = NativeUtilities.pinA iwork - let mutable arg_info = 0 - - try - LapackStubs.dgesdd_(&&arg_JOBZ,&&arg_m,&&arg_n,arg_a.Ptr,&&arg_lda,arg_s.Ptr,arg_u.Ptr,&&arg_ldu,arg_vt.Ptr,&&arg_ldvt,arg_work.Ptr,&&arg_lwork,arg_iwork.Ptr,&&arg_info ) - finally - NativeUtilities.freeA arg_work - - //get workspace size - if arg_info = 0 || arg_info=(-12) then - arg_lwork <- int32 work.[0] - else assert(false) - - //assign workspace size to the work array - let arg_work = NativeUtilities.pinA (Array.zeroCreate arg_lwork : float[]) - //call dgesdd_ - try - LapackStubs.dgesdd_(&&arg_JOBZ,&&arg_m,&&arg_n,arg_a.Ptr,&&arg_lda,arg_s.Ptr,arg_u.Ptr,&&arg_ldu,arg_vt.Ptr,&&arg_ldvt,arg_work.Ptr,&&arg_lwork,arg_iwork.Ptr,&&arg_info ) - finally - NativeUtilities.freeM arg_a - NativeUtilities.freeA arg_s - NativeUtilities.freeM arg_u - NativeUtilities.freeM arg_vt - NativeUtilities.freeA arg_work - NativeUtilities.freeA arg_iwork - //fail if info contains an error code - match arg_info with - | -1 -> failwith "dgesdd_: JOBZ (argument 1)" - | -2 -> failwith "dgesdd_: m (argument 2)" - | -3 -> failwith "dgesdd_: n (argument 3)" - | -4 -> failwith "dgesdd_: a (argument 4)" - | -5 -> failwith "dgesdd_: lda (argument 5)" - | -6 -> failwith "dgesdd_: s (argument 6)" - | -7 -> failwith "dgesdd_: u (argument 7)" - | -8 -> failwith "dgesdd_: ldu (argument 8)" - | -9 -> failwith "dgesdd_: vt (argument 9)" - | -10 -> failwith "dgesdd_: ldvt (argument 10)" - | -11 -> failwith "dgesdd_: work (argument 11)" - | -12 -> failwith "dgesdd_: lwork (argument 12)" - | -13 -> failwith "dgesdd_: iwork (argument 13)" - | -14 -> failwith "dgesdd_: info (argument 14)" - | 0 -> () - | n -> failwith (sprintf "dgesdd_ : returned %d. The computation failed." n) - - // fixups - let u = Matrix.transpose u - let vt = Matrix.transpose vt - // result tuple - s,u,vt - - //Thin SVD - member this.dgesdd_thin_(a:Matrix) = - // input copies - let a = Matrix.copy a - // dimensions - let m = NativeUtilities.matrixDim1 a in - let n = NativeUtilities.matrixDim2 a in - - let s = Array.zeroCreate (min m n) - let u = Matrix.zero (m) (n) - let vt = Matrix.zero (n) (n) - let work = Array.zeroCreate (1) - let iwork = Array.zeroCreate (8*(min m n)) - - //setup actuals ------------------------------------------------------------ - //computation type - let mutable arg_JOBZ = 'S' - - //dimensions of input array a - let mutable arg_m = m - let mutable arg_n = n - - //output matrices and their leading dimensions - let mutable arg_ldu = m - let mutable arg_ldvt = n - let mutable arg_lda = max 1 m - - // transpose - let a = Matrix.transpose a - let u = Matrix.transpose u - let vt = Matrix.transpose vt - - let arg_s = NativeUtilities.pinA s - let arg_a = NativeUtilities.pinM a - let arg_u = NativeUtilities.pinM u - let arg_vt = NativeUtilities.pinM vt - - //workspaces - let arg_work = NativeUtilities.pinA work - let mutable arg_lwork = -1 - let arg_iwork = NativeUtilities.pinA iwork - let mutable arg_info = 0 - - try - LapackStubs.dgesdd_(&&arg_JOBZ,&&arg_m,&&arg_n,arg_a.Ptr,&&arg_lda,arg_s.Ptr,arg_u.Ptr,&&arg_ldu,arg_vt.Ptr,&&arg_ldvt,arg_work.Ptr,&&arg_lwork,arg_iwork.Ptr,&&arg_info ) - finally - NativeUtilities.freeA arg_work - - //get workspace size - if arg_info = 0 || arg_info=(-12) then - arg_lwork <- int32 work.[0] - else assert(false) - - //assign workspace size to the work array - let arg_work = NativeUtilities.pinA (Array.zeroCreate arg_lwork : float[]) - //call dgesdd_ - try - LapackStubs.dgesdd_(&&arg_JOBZ,&&arg_m,&&arg_n,arg_a.Ptr,&&arg_lda,arg_s.Ptr,arg_u.Ptr,&&arg_ldu,arg_vt.Ptr,&&arg_ldvt,arg_work.Ptr,&&arg_lwork,arg_iwork.Ptr,&&arg_info ) - finally - NativeUtilities.freeM arg_a - NativeUtilities.freeA arg_s - NativeUtilities.freeM arg_u - NativeUtilities.freeM arg_vt - NativeUtilities.freeA arg_work - NativeUtilities.freeA arg_iwork - //fail if info contains an error code - match arg_info with - | -1 -> failwith "dgesdd_: JOBZ (argument 1)" - | -2 -> failwith "dgesdd_: m (argument 2)" - | -3 -> failwith "dgesdd_: n (argument 3)" - | -4 -> failwith "dgesdd_: a (argument 4)" - | -5 -> failwith "dgesdd_: lda (argument 5)" - | -6 -> failwith "dgesdd_: s (argument 6)" - | -7 -> failwith "dgesdd_: u (argument 7)" - | -8 -> failwith "dgesdd_: ldu (argument 8)" - | -9 -> failwith "dgesdd_: vt (argument 9)" - | -10 -> failwith "dgesdd_: ldvt (argument 10)" - | -11 -> failwith "dgesdd_: work (argument 11)" - | -12 -> failwith "dgesdd_: lwork (argument 12)" - | -13 -> failwith "dgesdd_: iwork (argument 13)" - | -14 -> failwith "dgesdd_: info (argument 14)" - | 0 -> () - | n -> failwith (sprintf "dgesdd_ : returned %d. The computation failed." n) - - // fixups - let u = Matrix.transpose u - let vt = Matrix.transpose vt - // result tuple - s,u,vt - - //Eigenvalue decomposition of a real non-symmetric square matrix - //member this.dgeev_(a:Matrix) = - // // input copies - // let a = Matrix.copy a - // // dimensions - // let n = NativeUtilities.matrixDim1 a in - // NativeUtilities.assertDimensions "dgeev_" ("n","Dim2(a)") (n,NativeUtilities.matrixDim2 a); - // // allocate results - // let wr = Array.zeroCreate (n) - // let wi = Array.zeroCreate (n) - // let vl = Matrix.zero (n) (n) - // let vr = Matrix.zero (n) (n) - // let work = Array.zeroCreate (1) - // // transpose - // let a = Matrix.transpose a - // // setup actuals - // let mutable arg_jobvl = 'N' - // let mutable arg_jobvr = 'V' - // let mutable arg_n = n - // let arg_a = NativeUtilities.pinM a - // let mutable arg_lda = n - // let arg_wr = NativeUtilities.pinA wr - // let arg_wi = NativeUtilities.pinA wi - // let arg_vl = NativeUtilities.pinM vl - // let mutable arg_ldvl = n - // let arg_vr = NativeUtilities.pinM vr - // let mutable arg_ldvr = n - // let arg_work = NativeUtilities.pinA work - // let mutable arg_lwork = -1 - // let mutable arg_info = 0 - // //workspace query - // try - // LapackStubs.dgeev_(&&arg_jobvl,&&arg_jobvr,&&arg_n,arg_a.Ptr,&&arg_lda,arg_wr.Ptr,arg_wi.Ptr,arg_vl.Ptr,&&arg_ldvl,arg_vr.Ptr,&&arg_ldvr,arg_work.Ptr,&&arg_lwork,&&arg_info) - // finally - // NativeUtilities.freeA arg_work - // //get workspace size - // if arg_info = 0 || arg_info=(-12) then - // arg_lwork <- int32 work.[0] - // else assert(false) - // //assign workspace size to the work array - // let arg_work = NativeUtilities.pinA (Array.zeroCreate arg_lwork : float[]) - // //call function - // try - // LapackStubs.dgeev_(&&arg_jobvl,&&arg_jobvr,&&arg_n,arg_a.Ptr,&&arg_lda,arg_wr.Ptr,arg_wi.Ptr,arg_vl.Ptr,&&arg_ldvl,arg_vr.Ptr,&&arg_ldvr,arg_work.Ptr,&&arg_lwork,&&arg_info) - // finally - // NativeUtilities.freeM arg_a - // NativeUtilities.freeA arg_wr - // NativeUtilities.freeA arg_wi - // NativeUtilities.freeM arg_vl - // NativeUtilities.freeM arg_vr - // NativeUtilities.freeA arg_work - // // INFO - // match arg_info with - // | -1 -> failwith "dgeev_: jobvl (argument 1)" - // | -2 -> failwith "dgeev_: jobvr (argument 2)" - // | -3 -> failwith "dgeev_: n (argument 3)" - // | -4 -> failwith "dgeev_: a (argument 4)" - // | -5 -> failwith "dgeev_: lda (argument 5)" - // | -6 -> failwith "dgeev_: wr (argument 6)" - // | -7 -> failwith "dgeev_: wi (argument 7)" - // | -8 -> failwith "dgeev_: vl (argument 8)" - // | -9 -> failwith "dgeev_: ldvl (argument 9)" - // | -10 -> failwith "dgeev_: vr (argument 10)" - // | -11 -> failwith "dgeev_: ldvr (argument 11)" - // | -12 -> failwith "dgeev_: work (argument 12)" - // | -13 -> failwith "dgeev_: lwork (argument 13)" - // | -14 -> failwith "dgeev_: info (argument 14)" - // | 0 -> () - // | n -> failwith (sprintf "dgeev_ : returned %d. The computation failed." n) - // // fixups - // let vr = Matrix.transpose vr - // // result tuple - // wr,wi,vr - - ///Eigen Value Decomposition of Symmetric Matrix - member this.dsyevd_(a:matrix) = - - let jobz = 'V' - let uplo = 'L' - // input copies - let a = Matrix.copy a - // dimensions - let n = NativeUtilities.matrixDim1 a in - NativeUtilities.assertDimensions "dsyevd_" ("n","Dim2(a)") (n,NativeUtilities.matrixDim2 a); - // allocate results - let w = Array.zeroCreate (n) - let work = Array.zeroCreate (1) - let iwork = Array.zeroCreate (1) - // transpose - let a = Matrix.transpose a - // setup actuals - let mutable arg_jobz = jobz - let mutable arg_uplo = uplo - let mutable arg_n = n - let arg_a = NativeUtilities.pinM a - let mutable arg_lda = max 1 n - let arg_w = NativeUtilities.pinA w - let arg_work = NativeUtilities.pinA work - let mutable arg_lwork = -1 - let arg_iwork = NativeUtilities.pinA iwork - let mutable arg_liwork = -1 - let mutable arg_info = 0 - // ask for work array size - try - LapackStubs.dsyevd_(&&arg_jobz,&&arg_uplo,&&arg_n,arg_a.Ptr,&&arg_lda,arg_w.Ptr,arg_work.Ptr,&&arg_lwork,arg_iwork.Ptr,&&arg_liwork,&&arg_info) - finally - NativeUtilities.freeA arg_work - NativeUtilities.freeA arg_iwork - if arg_info = 0 || arg_info=(-8) || arg_info=(-10) then - arg_lwork <- int32 work.[0] - arg_liwork <- iwork.[0] - else assert(false) - let arg_work = NativeUtilities.pinA (Array.zeroCreate arg_lwork : float[]) - let arg_iwork = NativeUtilities.pinA (Array.zeroCreate arg_liwork : int[]) - // call function - try - LapackStubs.dsyevd_(&&arg_jobz,&&arg_uplo,&&arg_n,arg_a.Ptr,&&arg_lda,arg_w.Ptr,arg_work.Ptr,&&arg_lwork,arg_iwork.Ptr,&&arg_liwork,&&arg_info) - finally - NativeUtilities.freeM arg_a - NativeUtilities.freeA arg_w - NativeUtilities.freeA arg_work - NativeUtilities.freeA arg_iwork - // INFO - match arg_info with - | -1 -> failwith "dsyevd_: jobz (argument 1)" - | -2 -> failwith "dsyevd_: uplo (argument 2)" - | -3 -> failwith "dsyevd_: n (argument 3)" - | -4 -> failwith "dsyevd_: a (argument 4)" - | -5 -> failwith "dsyevd_: lda (argument 5)" - | -6 -> failwith "dsyevd_: w (argument 6)" - | -7 -> failwith "dsyevd_: work (argument 7)" - | -8 -> failwith "dsyevd_: lwork (argument 8)" - | -9 -> failwith "dsyevd_: iwork (argument 9)" - | -10 -> failwith "dsyevd_: liwork (argument 10)" - | -11 -> failwith "dsyevd_: info (argument 11)" - | 0 -> () - | n -> failwith (sprintf "dsyevd_ : returned %d. The computation failed." n) - // fixups - let a = Matrix.transpose a - // result tuple - a,vector w - - - -module ProviderService = - let MKLProvider = ServiceLocator.createProviderX64 "MKL" [|"mkl.dll"|] ServiceLocator.OS.Windows (fun () -> new LinearAlgebraMKL() :> ILinearAlgebra) - let LAPACKProvider = ServiceLocator.createProviderX64 "LAPACK" [|"libblas.dll";"liblapack.dll";"libgcc_s_seh-1.dll";"libgfortran-4.dll";"libquadmath-0.dll";"libwinpthread-1.dll"|] ServiceLocator.OS.Windows (fun () -> new LinearAlgebraLAPACK() :> ILinearAlgebra) - - - - - diff --git a/src/FSharp.Stats/Algebra/LinearAlgebraServiceManaged.fs b/src/FSharp.Stats/Algebra/LinearAlgebraServiceManaged.fs deleted file mode 100644 index 5a3c43bde..000000000 --- a/src/FSharp.Stats/Algebra/LinearAlgebraServiceManaged.fs +++ /dev/null @@ -1,643 +0,0 @@ -// (c) Microsoft Corporation 2005-2009. - -namespace FSharp.Stats.Algebra - -open FSharp.Stats -/// This module is for internal use only. -module LinearAlgebraManaged = - open System - - //let a = 1. - - let private matrixDims (m:Matrix<_>) = m.NumRows, m.NumCols - - let NYI () = failwith "Not yet implemented, managed fallback linear algebra ops coming soon" - - //type Permutation = Permutation of int * (int -> int) - - let SVD (a:matrix) = - let (umatrix,s,vmatrix) = SVD.computeInPlace (a.ToArray2D()) - //Matrix.diag - Vector.ofArray s,Matrix.ofArray2D umatrix,Matrix.ofArray2D vmatrix - //(Matrix.ofArray2D umatrix,s,Matrix.ofArray2D vmatrix) - - let symmetricEigenspectrum (a:matrix) = - let (e,v,d) = EVD.symmetricEvd (a.ToArray2D()) - (Matrix.ofArray2D v,vector d) - - - let EigenSpectrum A = NYI() - let Condition A = NYI() - - let eigenvectors m = NYI() - let eigenvalues m = NYI() - let symmetricEigenvalues a = NYI() - let symmetricEigenvectors a = NYI() - - let SolveTriangularLinearSystems K B isLower = - if isLower then - let (nK,mK) = matrixDims K - let (nB,mB) = matrixDims B - if nK<>mK || nB<> nK then invalidArg "Matrix" "Cannot do backward substitution on non-square matrices." - let X = Matrix.zero(max nB nK) (max mB mK) // t - for i=0 to nK-1 do - for k=0 to mB-1 do - let s = ref B.[i,k] - for j=0 to i-1 do - s := !s - K.[i,j] * X.[j,k] - done - X.[i,k] <- !s / K.[i,i] - done - done - X - else - let (nK,mK) = matrixDims K - let (nB,mB) = matrixDims B - if nK<>mK || nB<> nK then invalidArg "Matrix" "Cannot do backward substitution on non-square matrices." - let X = Matrix.zero (max nB nK) (max mB mK) //t - for i=0 to nK-1 do - for k=0 to mB-1 do - let s = ref B.[nK-i-1,k] - for j=0 to i-1 do - s := !s - K.[nK-i-1,nK-j-1] * X.[nK-j-1,k] - done - X.[nK-i-1,k] <- !s / K.[nK-i-1,nK-i-1] - done - done - X - - let SolveTriangularLinearSystem K v isLower = Matrix.getCol (SolveTriangularLinearSystems K (Matrix.ofVector v) isLower) 0 - - type range = int * int - - let inline sumfR f ((a,b):range) = - let mutable res = 0.0 in - for i = a to b do - res <- res + f i - res - - - let Cholesky (a: matrix) = - let nA,mA = a.Dimensions - if nA<>mA then invalidArg "Matrix" "choleskyFactor: not square"; - let lres = Matrix.zero nA nA (* nA=mA *) - for j=0 to nA-1 do - for i=j to nA-1 do (* j <= i *) - (* Consider a_ij = sum(k=0...n-1) (lres_ik . lresT_kj) - * = sum(k=0...n-1) (lres_ik . lres_jk) - * = sum(k=0...j-1) (lres_ik . lres_jk) + lres_ij . lres_jj + (0 when k>j) - * = psum + lres_ij . lres_jj - * This determines lres_ij terms of preceeding terms. - * lres_ij depends on lres_ik and lres_jk (and maybe lres_ii) for k lres.[i,k] * lres.[j,k]) (0,j-1) - let aij = a.[i,j] - if i=j then - let t = (aij - psum) - if t >= 0.0 then lres.[i,i] <- (System.Math.Sqrt t) else invalidArg "Matrix" "choleskyFactor: not symmetric postive definite" - else - lres.[i,j] <- ((aij - psum) / lres.[j,j]) - done - done; - // if not (isLowerTriangular lres) then failwith "choleskyFactor: not lower triangular result"; - lres.Transpose // REVIEW optimize this so we don't have to take transpose ... - - - /// For a matrix A, the LU factorization is a pair of lower triangular matrix L and upper triangular matrix U so that A = L*U.
The pivot function encode a permutation operation such for a matrix P P*A = L*U.
- /// - /// - /// - /// - /// - /// - /// - let LU A = - let (nA,mA) = matrixDims A - if nA<>mA then invalidArg "Matrix" "lu: not square" - let L = Matrix.zero nA nA - let U = Matrix.copy A - let P = [| 0 .. nA-1 |] - let abs (x:float) = System.Math.Abs x - let swapR X i j = // REVIEW should we make this a general method? - let (nX,mX) = matrixDims X - let t = X.[i .. i,0 .. ] - for k=0 to mX-1 do - X.[i,k] <- X.[j,k] - X.[j,k] <- t.[0,k] - done - - for i=0 to nA-2 do - let mutable maxi = i // Find the biggest pivot element. - for k=i+1 to nA-1 do - if abs(U.[maxi,i]) < abs(U.[k,i]) then maxi <- k - done - //let maxi = maxIndex (i+1) (nA-1) (fun k -> abs(U.[k,i])) - - if maxi <> i then - swapR U i maxi // Swap rows if needed. - swapR L i maxi // REVIEW can be made more performant. - let t = P.[i] - P.[i] <- P.[maxi] - P.[maxi] <- t - - for j=i+1 to nA-1 do - L.[j,i] <- U.[j,i] / U.[i,i] - for k=i+1 to nA-1 do - U.[j,k] <- U.[j,k] - L.[j,i] * U.[i,k] - done - U.[j,i] <- 0.0 - done - done - (((*P.Length,*)Permutation.ofArray P),L + Matrix.identity nA,U) - //(P, L + (Matrix.identity nA), U) - - /// Solves a system of linear equations, AX = B, with A LU factorized. - /// - /// - /// - /// - /// - /// - /// - /// - let SolveLinearSystem (A:matrix) (b:vector) = - let (n,m) = matrixDims A - if n <> m then invalidArg "Matrix" "Matrix must be square." - let P,L,U = LU A - (SolveTriangularLinearSystem U (SolveTriangularLinearSystem L (b.Permute P) true) false) - - /// Solves a system of linear equations, Ax = b, with A LU factorized. - /// - /// - /// - /// - /// - /// - /// - /// - let SolveLinearSystems (A:matrix) (B:matrix) = - let (n,m) = matrixDims A - if n <> m then invalidArg "Matrix" "Matrix must be square." - let P,L,U = LU A - (SolveTriangularLinearSystems U (SolveTriangularLinearSystems L (B.PermuteRows P) true) false) - - let Inverse A = - let (n,m) = matrixDims A - if n <> m then invalidArg "Matrix" "Matrix must be square when computing its inverse." - let P,L,U = LU A - (SolveTriangularLinearSystems U (SolveTriangularLinearSystems L ((Matrix.identity n).PermuteRows P) true) false) - - /// Generates a unit vector [1 0 .. 0 ]. - /// - /// - /// - /// - /// - /// - /// - let unitV k = let e = Vector.create k 0.0 in e.[0] <- 1.0; e - - /// Computes the sign of a floating point number. - /// - /// - /// - /// - /// - /// - /// - let sign (f: float) = float (System.Math.Sign f) // REVIEW put in float library. - - /// This method computes and performs a Householder reflection. It will change the
input matrix and return the reflection vector.
- /// - /// - /// - /// - /// - /// - /// - /// - let HouseholderTransform (A:matrix) (i:int) = - // REVIEW do this using views and get rid of the i. - let (n,m) = matrixDims A - //Old: let x = A.[i..,i..i].Column 0 // Get part of the i'th column of the matrix. - let x = Matrix.getCol A.[i..,i..i] 0 // Get part of the i'th column of the matrix. - let nx = Vector.norm x - let vu = x + sign(x.[0]) * nx * (unitV (n-i)) // Compute the reflector. - let v = 1.0/(Vector.norm vu) * vu // Normalize reflector. - - // Perform the reflection. - let v'A = RowVector.init (m-i) (fun j -> v.Transpose * (A.[i..,i+j..i+j].Column 0)) - for l=i to n-1 do - for k=i to m-1 do - A.[l,k] <- A.[l,k] - 2.0 * v.[l-i] * v'A.[k-i] - v // Return reflection vector. - - /// QR factorization function for dense matrices - /// - /// - /// - /// - /// - /// - /// - let QRDense (A:matrix) = - let (n,m) = matrixDims A - let mutable Q = Matrix.identity n // Keeps track of the orthogonal matrix. - let R = Matrix.copy A - - // This method will update the orhogonal transformation fast when given a reflection vector. - let UpdateQ (qm:matrix) (v:vector) = - let n = Vector.length v - let (nQ,mQ) = matrixDims qm - - // Cache the computation of Q*v. - let Qv = Vector.init nQ (fun i -> (qm.[i..i,nQ-n..].Row 0) * v) - - // Update the orthogonal transformation. - for i=0 to nQ-1 do - for j=nQ-n to nQ-1 do - qm.[i,j] <- qm.[i,j] - 2.0 * Qv.[i] * v.[j-nQ+n] - () - - // This QR implementation keeps the unreduced part of A in R. It computes reflectors one at a time - // and reduces R column by column. In the process it keeps track of the Q matrix. - for i=0 to (min n m)-1 do - let v = HouseholderTransform R i - UpdateQ Q v - Q,R - - /// QR factorization function for sparse matrices, returns Q as a product of givens rotations and R as upper triangular - /// - /// - /// - /// - /// - /// - /// - let QRSparse (A:SparseMatrix) = - - /// Copies the row of a Sparsematrix into a Sparsevector - /// - /// - /// - /// - /// - /// - /// - /// - /// - let CopyRow (nnz:int) (offset:int) (A:SparseMatrix) = - let sparseVector = ResizeArray<(int*float)>() - for i=nnz-1 downto 0 do - if(not (A.SparseValues.[i+offset] = 0.0)) then - let entry = (A.SparseColumnValues.[i+offset], A.SparseValues.[i+offset]) - sparseVector.Insert(0, entry) - sparseVector - - /// Returns "value" with the sign of "sign" - /// - /// - /// - /// - /// - /// - /// - /// - let Copysign (value:float) (sign:float) = - if (sign >= 0.0) then - abs(value) - else // sign is negative - if(value < 0.0) then - value - else - value * -1.0 - - let Encode(c:float) (s:float) = - if(abs(s) < c) then - s - else - Copysign (1.0/c) s - - /// Apply the givens rotation on 2 Sparsevectors - /// - /// - /// - /// - /// - /// - /// - let ApplyGivens (x : ResizeArray<(int*float)>) (y : ResizeArray<(int*float)>) = - let a = snd x.[0] - let b = snd y.[0] - - let mutable c = -1.0 - let mutable s = -1.0 - - if (b = 0.0) then - c <- 1.0 - s <- 0.0 - else - if (abs(b) > abs(a)) then - let tau = -a / b - s <- 1.0 / sqrt(1.0 + tau * tau) - c <- s * tau - if (c < 0.0) then - c <- -c - s <- -s - else - let tau = -b/a - c <- 1.0 / sqrt(1.0 + tau * tau) - s <- c * tau - - // Rotate the start of each list - x.[0] <- (fst x.[0], c * a - s * b) - //was return first and remove after, is returned value ever needed? - y.RemoveAt 0 - - // Iterators - let mutable p = 0 - let mutable q = 0 - p <- p + 1 // Skip the first entry since we already handled it above - - while (p < x.Count && q < y.Count) do - if (fst x.[p] = fst y.[q]) then - let xNew = c * snd x.[p] - s * snd y.[q] - let yNew = s * snd x.[p] + c * snd y.[q] - if (not (xNew = 0.0)) then - x.[p] <- (fst x.[p], xNew) - p <- p + 1 - else - x.RemoveAt(p) - if ( not (yNew = 0.0)) then - y.[q] <- (fst y.[q], yNew) - q <- q + 1 - else - y.RemoveAt(q) - else if(fst x.[p] < fst y.[q]) then - let k = fst x.[p] - let xNew = c * snd x.[p] - let yNew = s * snd x.[p] - x.[p] <- (fst x.[p] , xNew) - p <-p + 1 - y.Insert(q,(k, yNew)) - q <- q + 1 - else - let k = fst y.[q] - let xNew= -s * snd y.[q] - let yNew= c * snd y.[q] - x.Insert(p,(k, xNew)) - p <- p + 1 - y.[q] <- (fst y.[q], yNew) - q <- q + 1 - if(p < x.Count) then - while(p < x.Count) do - let k = fst x.[p] - let xNew = c * snd x.[p] - let yNew = s * snd x.[p] - x.[p] <- (fst x.[p], xNew) - p <- p + 1 - y.Insert(q,(k, yNew)) - q <- q + 1 - else if(q < y.Count) then - while(q < y.Count) do - let k = fst y.[q] - let xNew = -s * snd y.[q] - let yNew = c * snd y.[q] - x.Insert(p,(k, xNew)) - p <- p + 1 - y.[q] <- (fst y.[q], yNew) - q <- q + 1 - - Encode c s - - // Run Sparse QR - let m = A.NumRows - let n = A.NumCols - let mutable Q = new ResizeArray>() - let mutable R = new ResizeArray>() - - for i = 0 to m - 1 do - Q.Add(ResizeArray<(int*float)>()) - R.Add(ResizeArray<(int*float)>()) - - for a = 0 to m-1 do - let mutable row = CopyRow (A.SparseRowOffsets.[a+1] - A.SparseRowOffsets.[a]) A.SparseRowOffsets.[a] A - let mutable q = 0 - while((not (row.Count <= 0)) && fst row.[0] < a && fst row.[0] < n) do - let j = fst row.[0] - - if((R.[j].Count <= 0) || fst R.[j].[0] > j) then - let temp = new ResizeArray<(int*float)> (row) - row <- new ResizeArray<(int*float)>(R.[a]) - R.[a] <- new ResizeArray<(int*float)>(temp) - Q.[a].Insert(q, (j, 1.0)) - q <- q + 1 - () - else - let ret = ApplyGivens R.[j] row - Q.[a].Insert(q, (j, ret)) - q <- q + 1 - () - if (a < n) then - let temp = new ResizeArray<(int*float)> (row) - row <- new ResizeArray<(int*float)>(R.[a]) - R.[a] <- new ResizeArray<(int*float)>(temp) - () - - let mutable x = 0 - - let RSeq = seq{ for row in R do - for entry in row do - yield(x, fst entry, snd entry) - x <- x+1 - } - - - let ROut = Matrix.initSparse m n RSeq - - x <- 0 - let QSeq = seq{ for row in Q do - for entry in row do - yield(x, fst entry, snd entry) - x <- x+1 - } - - let QOut = Matrix.initSparse m n QSeq - QOut, ROut - - /// Matches the union type of the matrix and invokes the according QR factorization function - /// - /// - /// - /// - /// - /// - /// - let QR (A:matrix) = - match A with - | SparseRepr A -> QRSparse(A) - | DenseRepr _ -> QRDense(A) - - let Hessenberg (A:matrix) = - // REVIEW we can do with less copying here. - let (n,m) = matrixDims A - if n<>m then invalidArg "Matrix A" "Currently only implemented for square matrices." - let mutable Q = Matrix.identity n // Keeps track of the orthogonal matrix. - let R = A.[1..,*] - - // This method will update the orhogonal transformation fast when given a reflection vector. - let UpdateQ (qm:Matrix) (v:vector) = - let n = Vector.length v - let (nQ,mQ) = matrixDims qm - - // Cache the computation of Q*v. - let Qv = Vector.init nQ (fun i -> (qm.[i..i,nQ-n..].Row 0) * v) - - // Update the orthogonal transformation. - for i=0 to nQ-1 do - for j=nQ-n to nQ-1 do - qm.[i,j] <- qm.[i,j] - 2.0 * Qv.[i] * v.[j-nQ+n] - () - - // This QR implementation keeps the unreduced part of A in R. It computes reflectors one at a time - // and reduces R column by column. In the process it keeps track of the Q matrix. - for i=0 to n-2 do - let v = HouseholderTransform R i - UpdateQ Q v - Q,Matrix.init n m (fun i j -> if i = 0 then A.[i,j] else R.[i-1,j]) - - let leastSquares A (b: vector) = - - // Q.transpose * b for sparse Q - let MultiplyVectorWithTransposeGivensMatrix (q:SparseMatrix, b:vector) = - let outVec = vector b - let m = q.NumRows - for i = 0 to m-1 do - for j = q.SparseRowOffsets.[i] to (q.SparseRowOffsets.[i+1] - 1) do - let k = q.SparseColumnValues.[j] - if(q.SparseValues.[j] = 1.0) then - let temp = outVec.[i] - outVec.[i] <- outVec.[k] - outVec.[k] <- temp - else - let tau = q.SparseValues.[j] - let mutable c = -1.0 - let mutable s = -1.0 - if(abs(tau) < 1.0) then - s <- tau - c <- sqrt(1.0-s*s) - else - c <- 1.0/tau - s <- sqrt(1.0-c*c) - if(c < 0.0) then - c <- -c - s <- -s - let newxk = c * outVec.[k] - s * outVec.[i] - outVec.[i] <- s * outVec.[k] + c * outVec.[i] - outVec.[k] <- newxk - outVec - - let (m,n) = matrixDims A - let Qm, R = QR A - let mutable Qtb = vector [||] - - match Qm with - | DenseRepr _ -> - Qtb <- Qm.Transpose * b - | SparseRepr qm -> - Qtb <- MultiplyVectorWithTransposeGivensMatrix(qm, b) - - // Is this an overdetermined or underdetermined system? - if m > n then - SolveTriangularLinearSystem R.[0..n-1,0..n-1] Qtb.[0..n-1] false - else - let s = SolveTriangularLinearSystem R.[0..m-1,0..m-1] Qtb false - Vector.init n (fun i -> if i < m then s.[i] else 0.0) - - - let leastSquaresCholesky (A: Matrix) (b: Vector) = - // We want to solve AT*A beta = AT * b for beta. - // We compute an upper triangular matrix U such that UT * U = AT * A - // We then solve UT * gamma = AT * b for gamma (note that UT is lower triangular) - // Finally we solve U * beta = gamma - - let AT = Matrix.transpose A - - let upper = (AT * A) |> Cholesky - let gamma = - SolveTriangularLinearSystem(Matrix.transpose upper) (AT * b) true - let beta = - SolveTriangularLinearSystem upper gamma false - beta - - /// computes the hat matrix by the QR decomposition of the designmatrix used in ordinary least squares approaches - /// - /// - /// - /// - /// - /// - /// - let hatMatrix (designMatrix: Matrix) = - let qm,R = QR designMatrix - let q1 = qm.GetSlice ((Some 0),(Some (qm.NumRows-1)),(Some 0),(Some (R.NumCols-1))) - // computes the hatmatrix - q1 * q1.Transpose - - - /// computes the leverages of every dataPoint of a dataSet given by the diagonal of the hat matrix. - /// - /// - /// - /// - /// - /// - /// - let leverageBy (hatMatrix: Matrix) = - hatMatrix.Diagonal - - /// computes the leverage directly by QR decomposition of the designmatrix used in ordinary least squares approaches
and computing of the diagnonal entries of the Hat matrix, known as the leverages of the regressors
- /// - /// - /// - /// - /// - /// - /// - let leverage (designMatrix: Matrix) = - let qm,R = QR designMatrix - let q1 = qm.GetSlice ((Some 0),(Some (qm.NumRows-1)),(Some 0),(Some (R.NumCols-1))) - let leverage = - let diagonal = FSharp.Stats.Vector.create q1.NumRows 0. - diagonal - |> FSharp.Stats.Vector.mapi (fun i x -> - FSharp.Stats.Matrix.foldRow (fun acc x -> acc + (x ** 2.)) 0. q1 i - ) - leverage - - - /// Calculates the pseudo inverse of the matrix - /// - /// - /// - /// - /// - /// - /// - let pseudoInvers (matrix:Matrix) = - let (m,n) = matrixDims matrix - // Is this an overdetermined or underdetermined system? - if m > n then - let qm,R = QR matrix - let i = Matrix.identity m - let Qtb = qm.Transpose * i - SolveTriangularLinearSystems R.[0..n-1,0..n-1] Qtb.[0..n-1,0..m-1] false - else - let qm,R = QR matrix.Transpose - let i = Matrix.identity n - let Qtb = qm.Transpose * i - let s = SolveTriangularLinearSystems R.[0..m-1,0..m-1] Qtb.[0..m-1,0..n-1] false - s.Transpose - - - diff --git a/src/FSharp.Stats/Algebra/NativeArray.fs b/src/FSharp.Stats/Algebra/NativeArray.fs deleted file mode 100644 index 231b5a4ef..000000000 --- a/src/FSharp.Stats/Algebra/NativeArray.fs +++ /dev/null @@ -1,106 +0,0 @@ -// (c) Microsoft Corporation 2005-2009. - -namespace Microsoft.FSharp.NativeInterop - -#nowarn "44" -#nowarn "9" // unverifiable constructs -#nowarn "51" // The address-of operator may result in non-verifiable code. Its use is restricted to passing byrefs to functions that require them - -open System -open System.Runtime.InteropServices -open Microsoft.FSharp.NativeInterop - -module NativeOps = - [] - let inline pinObjUnscoped (obj: obj) = GCHandle.Alloc(obj,GCHandleType.Pinned) - [] - let inline pinObj (obj: obj) f = - let gch = pinObjUnscoped obj - try f gch - finally - gch.Free() - -[] -type NativeArray<'T when 'T : unmanaged>(ptr : nativeptr<'T>, len: int) = - member x.Ptr = ptr - [] - member inline x.Item - with get n = NativePtr.get x.Ptr n - and set n v = NativePtr.set x.Ptr n v - member x.Length = len - -[] -type FortranMatrix<'T when 'T : unmanaged>(ptr : nativeptr<'T>, nrows: int, ncols:int) = - member x.NumCols = ncols - member x.NumRows = nrows - member x.Ptr = ptr - [] - member inline x.Item - with get (row,col) = NativePtr.get x.Ptr (row + col*x.NumRows) - and set (row,col) v = NativePtr.set x.Ptr (row + col*x.NumRows) v - member x.NativeTranspose = new CMatrix<_>(ptr,ncols,nrows) - -and - [] - NativeArray2<'T when 'T : unmanaged>(ptr : nativeptr<'T>, nrows:int, ncols: int) = - member x.Ptr = ptr - member x.NumRows = nrows - member x.NumCols = ncols - [] - member inline x.Item - with get (row,col) = NativePtr.get x.Ptr (row*x.NumCols + col) - and set (row,col) v = NativePtr.set x.Ptr (row*x.NumCols + col) v - member x.NativeTranspose = new FortranMatrix<_>(x.Ptr,ncols,nrows) - -and CMatrix<'T when 'T : unmanaged> = NativeArray2<'T> - -[] -module Ref = - [] - let inline pin (ref: 'T ref) (f : nativeptr<'T> -> 'b) = - NativeOps.pinObj (box ref) (fun gch -> - f (gch.AddrOfPinnedObject() |> NativePtr.ofNativeInt)) - -open Microsoft.FSharp.Math - -[] -type PinnedArray<'T when 'T : unmanaged>(narray: NativeArray<'T>, gch: GCHandle) = - [] - static member inline of_array(arr: 'T[]) = - let gch = NativeOps.pinObjUnscoped (box arr) - let ptr = &&arr.[0] - new PinnedArray<'T>(new NativeArray<_>(ptr,Array.length arr),gch) - - member x.Ptr = narray.Ptr - member x.Free() = gch.Free() - member x.Length = narray.Length - member x.NativeArray = narray - interface System.IDisposable with - member x.Dispose() = gch.Free() - - -[] -type PinnedArray2<'T when 'T : unmanaged>(narray: NativeArray2<'T>, gch: GCHandle) = - - [] - static member inline of_array2(arr: 'T[,]) = - let gch = NativeOps.pinObjUnscoped (box arr) - let ptr = &&arr.[0,0] - new PinnedArray2<'T>(new NativeArray2<_>(ptr,Array2D.length1 arr,Array2D.length2 arr),gch) - - [] - static member inline of_array2D(arr: 'T[,]) = - let gch = NativeOps.pinObjUnscoped (box arr) - let ptr = &&arr.[0,0] - new PinnedArray2<'T>(new NativeArray2<_>(ptr,Array2D.length1 arr,Array2D.length2 arr),gch) - - - member x.Ptr = narray.Ptr - member x.Free() = gch.Free() - member x.NumRows = narray.NumRows - member x.NumCols = narray.NumCols - member x.NativeArray = narray - interface System.IDisposable with - member x.Dispose() = gch.Free() - - diff --git a/src/FSharp.Stats/Algebra/NativeArrayExtensions.fs b/src/FSharp.Stats/Algebra/NativeArrayExtensions.fs deleted file mode 100644 index 918d79e09..000000000 --- a/src/FSharp.Stats/Algebra/NativeArrayExtensions.fs +++ /dev/null @@ -1,53 +0,0 @@ -// (c) Microsoft Corporation 2005-2009. - -namespace Microsoft.FSharp.NativeInterop - -#nowarn "44" -#nowarn "9" // unverifiable constructs -#nowarn "51" // unverifiable constructs - - - -open System -open System.Runtime.InteropServices -open Microsoft.FSharp.NativeInterop -open FSharp.Stats - -[] -module NativArrayExtensionsForMatrix = - - [] - let inline pinObjUnscoped (obj: obj) = GCHandle.Alloc(obj,GCHandleType.Pinned) - [] - let inline pinObj (obj: obj) f = - let gch = pinObjUnscoped obj - try f gch - finally - gch.Free() - - type Microsoft.FSharp.NativeInterop.PinnedArray<'T when 'T : unmanaged> with - - [] - static member inline of_vector(m:Vector<'T>) = - let gch = pinObjUnscoped (box m.InternalValues) - let ptr = &&m.InternalValues.[0] - new PinnedArray<'T>(new NativeArray<_>(ptr,m.Length),gch) - - [] - static member inline of_rowvec(m:RowVector<'T>) = - let gch = pinObjUnscoped (box m.InternalValues) - let ptr = &&m.InternalValues.[0] - new PinnedArray<'T>(new NativeArray<_>(ptr,m.Length),gch) - - - type Microsoft.FSharp.NativeInterop.PinnedArray2<'T when 'T : unmanaged> with - - [] - static member inline of_matrix(m:Matrix<'T>) = - if m.IsDense then - let gch = pinObjUnscoped (box m.InternalDenseValues) - let ptr = && m.InternalDenseValues.[0,0] - new PinnedArray2<'T>(new NativeArray2<_>(ptr,m.NumRows,m.NumCols),gch) - else - invalidArg "m" "cannot pin sparse matrices" - diff --git a/src/FSharp.Stats/Algebra/NativeUtilities.fs b/src/FSharp.Stats/Algebra/NativeUtilities.fs deleted file mode 100644 index d9ea77819..000000000 --- a/src/FSharp.Stats/Algebra/NativeUtilities.fs +++ /dev/null @@ -1,49 +0,0 @@ -namespace Microsoft.FSharp.NativeInterop - -open Microsoft.FSharp.NativeInterop -open FSharp.Stats - - -module NativeUtilities = - - - let nativeArray_as_CMatrix_colvec (arr: 'T NativeArray) = new CMatrix<_>(arr.Ptr,arr.Length,1) - let nativeArray_as_FortranMatrix_colvec (arr: 'T NativeArray) = new FortranMatrix<_>(arr.Ptr,arr.Length,1) - let pinM m = PinnedArray2.of_matrix(m) - let pinV v = PinnedArray.of_vector(v) - let pinA arr = PinnedArray.of_array(arr) - - let pinA2 arr = PinnedArray2.of_array2D(arr) - - let pinMV m1 v2 = pinM m1,pinV v2 - let pinVV v1 v2 = pinV v1,pinV v2 - let pinAA v1 v2 = pinA v1,pinA v2 - let pinMVV m1 v2 m3 = pinM m1,pinV v2,pinV m3 - let pinMM m1 m2 = pinM m1,pinM m2 - let pinMMM m1 m2 m3 = pinM m1,pinM m2,pinM m3 - let freeM (pA: PinnedArray2<'T>) = pA.Free() - let freeV (pA: PinnedArray<'T>) = pA.Free() - let freeA (pA: PinnedArray<'T>) = pA.Free() - - let freeA2 a = freeM a - - let freeMV (pA: PinnedArray2<'T>,pB : PinnedArray<'T>) = pA.Free(); pB.Free() - let freeVV (pA: PinnedArray<'T>,pB : PinnedArray<'T>) = pA.Free(); pB.Free() - let freeAA (pA: PinnedArray<'T>,pB : PinnedArray<'T>) = pA.Free(); pB.Free() - let freeMM (pA: PinnedArray2<'T>,(pB: PinnedArray2<'T>)) = pA.Free();pB.Free() - let freeMMM (pA: PinnedArray2<'T>,(pB: PinnedArray2<'T>),(pC: PinnedArray2<'T>)) = pA.Free();pB.Free();pC.Free() - let freeMVV (pA: PinnedArray2<'T>,(pB: PinnedArray<'T>),(pC: PinnedArray<'T>)) = pA.Free();pB.Free();pC.Free() - - let matrixDims (m:Matrix<_>) = m.NumRows, m.NumCols - let matrixDim1 (m:Matrix<_>) = m.NumRows - let matrixDim2 (m:Matrix<_>) = m.NumCols - let vectorDim (v:Vector<_>) = v.Length - - let assertDimensions functionName (aName,bName) (a,b) = - if a=b then () else - failwith (sprintf "Require %s = %s, but %s = %d and %s = %d in %s" aName bName aName a bName b functionName) - - - - - diff --git a/src/FSharp.Stats/BigRational.fs b/src/FSharp.Stats/BigRational.fs deleted file mode 100644 index b43edc544..000000000 --- a/src/FSharp.Stats/BigRational.fs +++ /dev/null @@ -1,311 +0,0 @@ -// (c) Microsoft Corporation. All rights reserved - -#nowarn "44" // OK to use the "compiler only" function RangeGeneric -#nowarn "52" // The value has been copied to ensure the original is not mutated by this operation - -//namespace Microsoft.FSharp.Math // old namespace -namespace FSharp.Stats - - open System - open System.Numerics - open System.Globalization - - module BigRationalLargeImpl = - let ZeroI = new BigInteger(0) - let OneI = new BigInteger(1) - let bigint (x:int) = new BigInteger(x) - let ToDoubleI (x:BigInteger) = double x - let ToInt32I (x:BigInteger) = int32 x - - open BigRationalLargeImpl - - [] - type BigRationalLarge = - | Q of BigInteger * BigInteger // invariants: (p,q) in lowest form, q >= 0 - - override n.ToString() = - let (Q(p,q)) = n - if q.IsOne then p.ToString() - else p.ToString() + "/" + q.ToString() - - - static member Hash (Q(ap,aq)) = - // This hash code must be identical to the hash for BigInteger when the numbers coincide. - if aq.IsOne then ap.GetHashCode() else (ap.GetHashCode() <<< 3) + aq.GetHashCode() - - - override x.GetHashCode() = BigRationalLarge.Hash(x) - - static member Equals(Q(ap,aq), Q(bp,bq)) = - BigInteger.(=) (ap,bp) && BigInteger.(=) (aq,bq) // normal form, so structural equality - - static member LessThan(Q(ap,aq), Q(bp,bq)) = - BigInteger.(<) (ap * bq,bp * aq) - - // note: performance improvement possible here - static member Compare(p,q) = - if BigRationalLarge.LessThan(p,q) then -1 - elif BigRationalLarge.LessThan(q,p)then 1 - else 0 - - interface System.IComparable with - member this.CompareTo(obj:obj) = - match obj with - | :? BigRationalLarge as that -> BigRationalLarge.Compare(this,that) - | _ -> invalidArg "obj" "the object does not have the correct type" - - override this.Equals(that:obj) = - match that with - | :? BigRationalLarge as that -> BigRationalLarge.Equals(this,that) - | _ -> false - - member x.IsNegative = let (Q(ap,_)) = x in sign ap < 0 - member x.IsPositive = let (Q(ap,_)) = x in sign ap > 0 - - member x.Numerator = let (Q(p,_)) = x in p - member x.Denominator = let (Q(_,q)) = x in q - member x.Sign = (let (Q(p,_)) = x in sign p) - - static member ToDouble (Q(p,q)) = - ToDoubleI p / ToDoubleI q - - static member Normalize (p:BigInteger,q:BigInteger) = - if q.IsZero then - raise (System.DivideByZeroException()) (* throw for any x/0 *) - elif q.IsOne then - Q(p,q) - else - let k = BigInteger.GreatestCommonDivisor(p,q) - let p = p / k - let q = q / k - if sign q < 0 then Q(-p,-q) else Q(p,q) - - static member Rational (p:int,q:int) = BigRationalLarge.Normalize (bigint p,bigint q) - static member RationalZ (p,q) = BigRationalLarge.Normalize (p,q) - - static member Parse (str:string) = - let len = str.Length - if len=0 then invalidArg "str" "empty string"; - let j = str.IndexOf '/' - if j >= 0 then - let p = BigInteger.Parse (str.Substring(0,j)) - let q = BigInteger.Parse (str.Substring(j+1,len-j-1)) - BigRationalLarge.RationalZ (p,q) - else - let p = BigInteger.Parse str - BigRationalLarge.RationalZ (p,OneI) - - static member (~-) (Q(bp,bq)) = Q(-bp,bq) // still coprime, bq >= 0 - static member (+) (Q(ap,aq),Q(bp,bq)) = BigRationalLarge.Normalize ((ap * bq) + (bp * aq),aq * bq) - static member (-) (Q(ap,aq),Q(bp,bq)) = BigRationalLarge.Normalize ((ap * bq) - (bp * aq),aq * bq) - static member (*) (Q(ap,aq),Q(bp,bq)) = BigRationalLarge.Normalize (ap * bp,aq * bq) - static member (/) (Q(ap,aq),Q(bp,bq)) = BigRationalLarge.Normalize (ap * bq,aq * bp) - static member ( ~+ )(n1:BigRationalLarge) = n1 - - - [] - module BigRationalLarge = - open System.Numerics - - let inv (Q(ap,aq)) = BigRationalLarge.Normalize(aq,ap) - - let pown (Q(p,q)) (n:int) = Q(BigInteger.Pow(p,n),BigInteger.Pow (q,n)) // p,q powers still coprime - - let equal (Q(ap,aq)) (Q(bp,bq)) = ap=bp && aq=bq // normal form, so structural equality - let lt a b = BigRationalLarge.LessThan(a,b) - let gt a b = BigRationalLarge.LessThan(b,a) - let lte (Q(ap,aq)) (Q(bp,bq)) = BigInteger.(<=) (ap * bq,bp * aq) - let gte (Q(ap,aq)) (Q(bp,bq)) = BigInteger.(>=) (ap * bq,bp * aq) - - let ofBigInt z = BigRationalLarge.RationalZ(z,OneI ) - let ofInt n = BigRationalLarge.Rational(n,1) - - [] - let of_bigint z = ofBigInt z - [] - let of_int n = ofInt n - - // integer part - let integer (Q(p,q)) = - let mutable r = BigInteger(0) - let d = BigInteger.DivRem (p,q,&r) // have p = d.q + r, |r| < |q| - if r < ZeroI - then d - OneI // p = (d-1).q + (r+q) - else d // p = d.q + r - - - //---------------------------------------------------------------------------- - // BigRational - //-------------------------------------------------------------------------- - - [] - [] - type BigRational = - | Z of BigInteger - | Q of BigRationalLarge - - static member ( + )(n1,n2) = - match n1,n2 with - | Z z ,Z zz -> Z (z + zz) - | Q q ,Q qq -> Q (q + qq) - | Z z ,Q qq -> Q (BigRationalLarge.ofBigInt z + qq) - | Q q ,Z zz -> Q (q + BigRationalLarge.ofBigInt zz) - - static member ( * )(n1,n2) = - match n1,n2 with - | Z z ,Z zz -> Z (z * zz) - | Q q ,Q qq -> Q (q * qq) - | Z z ,Q qq -> Q (BigRationalLarge.ofBigInt z * qq) - | Q q ,Z zz -> Q (q * BigRationalLarge.ofBigInt zz) - - static member ( - )(n1,n2) = - match n1,n2 with - | Z z ,Z zz -> Z (z - zz) - | Q q ,Q qq -> Q (q - qq) - | Z z ,Q qq -> Q (BigRationalLarge.ofBigInt z - qq) - | Q q ,Z zz -> Q (q - BigRationalLarge.ofBigInt zz) - - static member ( / )(n1,n2) = - match n1,n2 with - | Z z ,Z zz -> Q (BigRationalLarge.RationalZ(z,zz)) - | Q q ,Q qq -> Q (q / qq) - | Z z ,Q qq -> Q (BigRationalLarge.ofBigInt z / qq) - | Q q ,Z zz -> Q (q / BigRationalLarge.ofBigInt zz) - - static member ( ~- )(n1) = - match n1 with - | Z z -> Z (-z) - | Q q -> Q (-q) - - static member ( ~+ )(n1:BigRational) = n1 - - // nb. Q and Z hash codes must match up - see notes above - override n.GetHashCode() = - match n with - | Z z -> z.GetHashCode() - | Q q -> q.GetHashCode() - - override this.Equals(obj:obj) = - match obj with - | :? BigRational as that -> BigRational.(=)(this, that) - | _ -> false - - interface System.IComparable with - member n1.CompareTo(obj:obj) = - match obj with - | :? BigRational as n2 -> - if BigRational.(<)(n1, n2) then -1 elif BigRational.(=)(n1, n2) then 0 else 1 - | _ -> invalidArg "obj" "the objects are not comparable" - - static member FromInt (x:int) = Z (bigint x) - static member FromBigInt x = Z x - - static member Zero = BigRational.FromInt(0) - static member One = BigRational.FromInt(1) - - - static member PowN (n,i:int) = - match n with - | Z z -> Z (BigInteger.Pow (z,i)) - | Q q -> Q (BigRationalLarge.pown q i) - - static member op_Equality (n,nn) = - match n,nn with - | Z z ,Z zz -> BigInteger.(=) (z,zz) - | Q q ,Q qq -> (BigRationalLarge.equal q qq) - | Z z ,Q qq -> (BigRationalLarge.equal (BigRationalLarge.ofBigInt z) qq) - | Q q ,Z zz -> (BigRationalLarge.equal q (BigRationalLarge.ofBigInt zz)) - static member op_Inequality (n,nn) = not (BigRational.op_Equality(n,nn)) - - static member op_LessThan (n,nn) = - match n,nn with - | Z z ,Z zz -> BigInteger.(<) (z,zz) - | Q q ,Q qq -> (BigRationalLarge.lt q qq) - | Z z ,Q qq -> (BigRationalLarge.lt (BigRationalLarge.ofBigInt z) qq) - | Q q ,Z zz -> (BigRationalLarge.lt q (BigRationalLarge.ofBigInt zz)) - static member op_GreaterThan (n,nn) = - match n,nn with - | Z z ,Z zz -> BigInteger.(>) (z,zz) - | Q q ,Q qq -> (BigRationalLarge.gt q qq) - | Z z ,Q qq -> (BigRationalLarge.gt (BigRationalLarge.ofBigInt z) qq) - | Q q ,Z zz -> (BigRationalLarge.gt q (BigRationalLarge.ofBigInt zz)) - static member op_LessThanOrEqual (n,nn) = - match n,nn with - | Z z ,Z zz -> BigInteger.(<=) (z,zz) - | Q q ,Q qq -> (BigRationalLarge.lte q qq) - | Z z ,Q qq -> (BigRationalLarge.lte (BigRationalLarge.ofBigInt z) qq) - | Q q ,Z zz -> (BigRationalLarge.lte q (BigRationalLarge.ofBigInt zz)) - static member op_GreaterThanOrEqual (n,nn) = - match n,nn with - | Z z ,Z zz -> BigInteger.(>=) (z,zz) - | Q q ,Q qq -> (BigRationalLarge.gte q qq) - | Z z ,Q qq -> (BigRationalLarge.gte (BigRationalLarge.ofBigInt z) qq) - | Q q ,Z zz -> (BigRationalLarge.gte q (BigRationalLarge.ofBigInt zz)) - - - member n.IsNegative = - match n with - | Z z -> sign z < 0 - | Q q -> q.IsNegative - - member n.IsPositive = - match n with - | Z z -> sign z > 0 - | Q q -> q.IsPositive - - member n.Numerator = - match n with - | Z z -> z - | Q q -> q.Numerator - - member n.Denominator = - match n with - | Z _ -> OneI - | Q q -> q.Denominator - - member n.Sign = - if n.IsNegative then -1 - elif n.IsPositive then 1 - else 0 - - static member Abs(n:BigRational) = - if n.IsNegative then -n else n - - static member ToDouble(n:BigRational) = - match n with - | Z z -> ToDoubleI z - | Q q -> BigRationalLarge.ToDouble q - - static member ToBigInt(n:BigRational) = - match n with - | Z z -> z - | Q q -> BigRationalLarge.integer q - - static member ToInt32(n:BigRational) = - match n with - | Z z -> ToInt32I(z) - | Q q -> ToInt32I(BigRationalLarge.integer q ) - - static member op_Explicit (n:BigRational) = BigRational.ToInt32 n - static member op_Explicit (n:BigRational) = BigRational.ToDouble n - static member op_Explicit (n:BigRational) = BigRational.ToBigInt n - - - override n.ToString() = - match n with - | Z z -> z.ToString() - | Q q -> q.ToString() - - member x.StructuredDisplayString = x.ToString() - - static member Parse(s:string) = Q (BigRationalLarge.Parse s) - - type BigNum = BigRational - type bignum = BigNum - - module NumericLiteralN = - let FromZero () = BigRational.Zero - let FromOne () = BigRational.One - let FromInt32 i = BigRational.FromInt i - let FromInt64 (i64:int64) = BigRational.FromBigInt (new BigInteger(i64)) - let FromString s = BigRational.Parse s diff --git a/src/FSharp.Stats/GlobalAssociations.fs b/src/FSharp.Stats/GlobalAssociations.fs deleted file mode 100644 index 17122e89b..000000000 --- a/src/FSharp.Stats/GlobalAssociations.fs +++ /dev/null @@ -1,45 +0,0 @@ -// (c) Microsoft Corporation 2005-2009. - -//namespace Microsoft.FSharp.Math // old namespace -namespace FSharp.Stats - -module GlobalAssociations = - -// open Microsoft.FSharp.Math -// open Microsoft.FSharp.Math.Instances - open FSharp.Stats.Instances - open System - open System.Numerics - - let ht = - let ht = new System.Collections.Generic.Dictionary() - let optab = - [ typeof, (Some(FloatNumerics :> INumeric) :> obj); - typeof, (Some(Int32Numerics :> INumeric) :> obj); - typeof, (Some(Int64Numerics :> INumeric) :> obj); - typeof, (Some(BigIntNumerics :> INumeric) :> obj); - typeof, (Some(Float32Numerics :> INumeric) :> obj); - typeof, (Some(BigRationalNumerics :> INumeric) :> obj); ] - - List.iter (fun (ty,ops) -> ht.Add(ty,ops)) optab; - ht - - let Put (ty: System.Type, d : obj) = - lock ht (fun () -> - if ht.ContainsKey(ty) then invalidArg "ty" ("the type "+ty.Name+" already has a registered numeric association"); - ht.Add(ty, d)) - - let TryGetNumericAssociation<'a>() = - lock ht (fun () -> - let ty = typeof<'a> - if ht.ContainsKey(ty) then - match ht.[ty] with - | :? (INumeric<'a> option) as r -> r - | _ -> invalidArg "ty" ("The type "+ty.Name+" has a numeric association but it was not of the correct type") - else - None) - - let GetNumericAssociation() = (TryGetNumericAssociation()).Value - let RegisterNumericAssociation (d : INumeric<'a>) = Put(typeof<'a>, box(Some d)) - - diff --git a/src/FSharp.Stats/INumeric.fs b/src/FSharp.Stats/INumeric.fs deleted file mode 100644 index 35a19fab2..000000000 --- a/src/FSharp.Stats/INumeric.fs +++ /dev/null @@ -1,240 +0,0 @@ -// (c) Microsoft Corporation 2005-2009. - -namespace FSharp.Stats - -open System -open System.Numerics -open System.Globalization - -type INumeric<'T> = - abstract Zero: 'T - abstract One: 'T - abstract Add: 'T * 'T -> 'T - abstract Subtract: 'T * 'T -> 'T - abstract Multiply : 'T * 'T -> 'T - abstract Compare : 'T * 'T -> int - abstract Equals : 'T * 'T -> bool - abstract Negate : 'T -> 'T - abstract Sign : 'T -> int - abstract Abs : 'T -> 'T - abstract ToString : 'T * string * System.IFormatProvider -> string - abstract Parse : string * System.Globalization.NumberStyles * System.IFormatProvider -> 'T - -type IIntegral<'T> = - inherit INumeric<'T> - abstract Modulus: 'T * 'T -> 'T - abstract Divide : 'T * 'T -> 'T - abstract DivRem : 'T * 'T -> 'T * 'T - abstract ToBigInt : 'T -> BigInteger - abstract OfBigInt : BigInteger -> 'T - -type IFractional<'T> = - inherit INumeric<'T> - abstract Reciprocal : 'T -> 'T - abstract Divide : 'T * 'T -> 'T - -type IFloating<'T> = - inherit IFractional<'T> - abstract Pi : 'T - abstract Exp : 'T -> 'T - abstract Log : 'T -> 'T - abstract Sqrt : 'T -> 'T - abstract LogN : 'T * 'T -> 'T - abstract Sin : 'T -> 'T - abstract Cos : 'T -> 'T - abstract Tan : 'T -> 'T - abstract Asin : 'T -> 'T - abstract Acos : 'T -> 'T - abstract Atan : 'T -> 'T - abstract Atan2 : 'T * 'T -> 'T - abstract Sinh : 'T -> 'T - abstract Cosh : 'T -> 'T - abstract Tanh : 'T -> 'T - -type IIEEE<'T> = - inherit IFloating<'T> - abstract PositiveInfinity : 'T - abstract NegativeInfinity : 'T - abstract NaN : 'T - abstract EpsilonOne : 'T - abstract IsNaN: 'T -> bool - abstract IsInfinite : 'T -> bool - -type INormFloat<'T> = - abstract Norm : 'T -> float - -module Instances = - let Int32Numerics = - { new IIntegral with - member __.Zero = 0 - member __.One = 1 - member __.Add(a,b) = a + b - member __.Subtract(a,b) = a - b - member __.Multiply(a,b) = a * b - member __.Equals(a,b) = (a = b) - member __.Compare(a,b) = compare a b - member __.Negate(a) = - a - member __.Abs(a) = a - member __.ToBigInt(a) = new BigInteger(a) - member __.OfBigInt(a) = int32 a - member __.Sign(a) = Math.Sign(a) - member __.Modulus(a,b) = a % b - member __.Divide(a,b) = a / b - member __.DivRem(a,b) = (a / b, a % b) - member __.ToString((x:int32),fmt,fmtprovider) = - x.ToString(fmt,fmtprovider) - member __.Parse(s,numstyle,fmtprovider) = - System.Int32.Parse(s,numstyle,fmtprovider) - interface INormFloat with - member __.Norm(x) = float (abs x) - } - let Int64Numerics = - { new IIntegral with - member __.Zero =0L - member __.One = 1L - member __.Add(a,b) = a + b - member __.Subtract(a,b) = a - b - member __.Multiply(a,b) = a * b - member __.Negate(a) = - a - member __.Abs(a) = Math.Abs(a) - member __.ToBigInt(a) = new BigInteger(a) - member __.OfBigInt(a) = int64 a - member __.Sign(a) = Math.Sign(a) - member __.Modulus(a,b) = a % b - member __.Equals(a,b) = (a = b) - member __.Compare(a,b) = compare a b - member __.Divide(a,b) = a / b - member __.DivRem(a,b) = (a / b, a % b) - member __.ToString((x:int64),fmt,fmtprovider) = x.ToString(fmt,fmtprovider) - member __.Parse(s,numstyle,fmtprovider) = System.Int64.Parse(s,numstyle,fmtprovider) - interface INormFloat with - member __.Norm(x) = float (Math.Abs x) - } - let FloatNumerics = - { new IIEEE with - member __.Zero = 0.0 - member __.One = 1.0 - member __.Add(a,b) = a + b - member __.Subtract(a,b) = a - b - member __.Multiply(a,b) = a * b - member __.Equals(a,b) = (a = b) - member __.Compare(a,b) = compare a b - member __.PositiveInfinity = Double.PositiveInfinity - member __.NegativeInfinity = Double.NegativeInfinity - member __.NaN = Double.NaN - member __.EpsilonOne = 0x3CB0000000000000LF - member __.IsInfinite(a) = Double.IsInfinity(a) - member __.IsNaN(a) = Double.IsNaN(a) - member __.Pi = Math.PI - member __.Reciprocal(a) = 1.0/a - member __.Abs(a) = Math.Abs(a) - member __.Sign(a) = Math.Sign(a) - member __.Asin(a) = Math.Asin(a) - member __.Acos(a) = Math.Acos(a) - member __.Atan(a) = Math.Atan(a) - member __.Atan2(a,b) = Math.Atan2(a,b) - member __.Tanh(a) = Math.Tanh(a) - member __.Tan(a) = Math.Tan(a) - member __.Sqrt(a) = Math.Sqrt(a) - member __.Sinh(a) = Math.Sinh(a) - member __.Cosh(a) = Math.Cosh(a) - member __.Sin(a) = Math.Sin(a) - member __.Cos(a) = Math.Cos(a) - member __.LogN(a,n) = -#if FX_NO_LOGN - raise (System.NotSupportedException("this operation is not supported on this platform")) -#else - Math.Log(a,n) -#endif - member __.Log(a) = Math.Log(a) - member __.Exp(a) = Math.Exp(a) - member __.Negate(a) = -a - member __.Divide(a,b) = a / b - member __.ToString((x:float),fmt,fmtprovider) = x.ToString(fmt,fmtprovider) - member __.Parse(s,numstyle,fmtprovider) = System.Double.Parse(s,numstyle,fmtprovider) - interface INormFloat with - member __.Norm(x) = float (Math.Abs x) - } - let Float32Numerics = - { new IFractional with - member __.Zero = 0.0f - member __.One = 1.0f - member __.Add(a,b) = a + b - member __.Subtract(a,b) = a - b - member __.Multiply(a,b) = a * b - member __.Equals(a,b) = (a = b) - member __.Compare(a,b) = compare a b - member __.Negate(a) = -a - member __.Reciprocal(a) = 1.0f/a - member __.Sign(a) = Math.Sign(a) - member __.Abs(a) = Math.Abs(a) - member __.Divide(a,b) = a / b - member __.ToString((x:float32),fmt,fmtprovider) = x.ToString(fmt,fmtprovider) - member __.Parse(s,numstyle,fmtprovider) = System.Single.Parse(s,numstyle,fmtprovider) - interface INormFloat with - member __.Norm(x) = float (Math.Abs x) - } - - let BigRationalNumerics = - { new IFractional with - member __.Zero = BigRational.Zero - member __.One = BigRational.One - member __.Add(a,b) = a + b - member __.Subtract(a,b) = a - b - member __.Multiply(a,b) = a * b - member __.Equals(a,b) = (a = b) - member __.Compare(a,b) = compare a b - member __.Divide(a,b) = a / b - member __.Abs(a) = BigRational.Abs a - member __.Sign(a) = a.Sign - member __.Negate(a) = - a - member __.Reciprocal(a) = BigRational.One / a - // Note, this ignores fmt, fmtprovider - member __.ToString((x:bignum),fmt,fmtprovider) = x.ToString() - // Note, this ignroes numstyle, fmtprovider - member __.Parse(s,numstyle,fmtprovider) = BigRational.Parse(s) - - interface INormFloat with - member __.Norm(x) = float (BigRational.Abs x) - } - - let BigIntNumerics = - let ZeroI = new BigInteger(0) - { new IIntegral<_> with - member __.Zero = BigInteger.Zero - member __.One = BigInteger.One - member __.Add(a,b) = a + b - member __.Subtract(a,b) = a - b - member __.Multiply(a,b) = a * b - member __.Equals(a,b) = (a = b) - member __.Compare(a,b) = compare a b - member __.Divide(a,b) = a / b - member __.Negate(a) = -a - member __.Modulus(a,b) = a % b - member __.DivRem(a,b) = - let mutable r = new BigInteger(0) - (BigInteger.DivRem (a,b,&r),r) - member __.Sign(a) = a.Sign - member __.Abs(a) = abs a - member __.ToBigInt(a) = a - member __.OfBigInt(a) = a - - member __.ToString(x,fmt,fmtprovider) = -#if FX_ATLEAST_40 - x.ToString(fmt,fmtprovider) -#else - // Note: this ignores fmt and fmtprovider - x.ToString() -#endif - // Note: this ignores fmt and fmtprovider - member __.Parse(s,numstyle,fmtprovider) = -#if FX_ATLEAST_40 - BigInteger.Parse(s,numstyle,fmtprovider) -#else - BigInteger.Parse(s) -#endif - - interface INormFloat with - member __.Norm(x) = float (abs x) - } - diff --git a/src/FSharp.Stats/Matrix.fs b/src/FSharp.Stats/Matrix.fs deleted file mode 100644 index cac019ca3..000000000 --- a/src/FSharp.Stats/Matrix.fs +++ /dev/null @@ -1,1611 +0,0 @@ -namespace FSharp.Stats - -#nowarn "60" // implementations in augmentations -#nowarn "69" // implementations in augmentations - -open System -open System.Globalization -open System.Collections -open System.Collections.Generic -open System.Diagnostics - -//type matrix = Matrix -//type vector = Vector -//type rowvec = RowVector - -module MRandom = - let randomGen = new System.Random() - let float f = randomGen.NextDouble() * f - -[] -module Matrix = - - - type Orientation = - | RowWise - | ColWise - member this.Inverse = - match this with - | RowWise -> Orientation.ColWise - | ColWise -> Orientation.RowWise - static member inverse (o:Orientation) = - o.Inverse - - type DataSource = - |Sample - |Population - - module Generic = - - module MS = SpecializedGenericImpl - - // Accessors - let get (matrix:Matrix<_>) indexRow indexCol = matrix.[indexRow,indexCol] - let set (matrix:Matrix<_>) indexRow indexCol value = matrix.[indexRow,indexCol] <- value - // Creation - let ofList lists = MS.listM lists - let ofSeq sources = MS.seqM sources - let ofColSeq sources = MS.seqCM sources - let init lengthRow lengthCol initializer = MS.initM lengthRow lengthCol initializer - let ofArray2D (array: 'T[,]) : Matrix<'T> = MS.arrayM array - /// Creates a sparse matrix based on the CSR format - /// - /// - /// - /// - /// - /// - /// - let sparseOfArray2D (array: 'T[,]) : Matrix<'T> = MS.arraySM array - let toArray2D (matrix:Matrix<_>) = Array2D.init matrix.NumRows matrix.NumCols (fun i j -> get matrix i j) - let toJaggedArray (m:Matrix<_>) = [|for i=0 to m.NumRows-1 do yield (Array.init m.NumCols (fun j -> get m i j))|] - let toJaggedColArray (m:Matrix<_>) = [|for i=0 to m.NumCols-1 do yield (Array.init m.NumRows (fun j -> get m j i))|] - let toJaggedSeq (m: Matrix<'a>) = Seq.init m.NumRows (fun i -> Seq.init m.NumCols (fun j -> get m i j)) - let toJaggedColSeq (m: Matrix<'a>) = Seq.init m.NumCols (fun i -> Seq.init m.NumRows (fun j -> get m j i)) - let initNumeric lengthRow lengthCol initializer = MS.initNumericM lengthRow lengthCol initializer - [] - let zero lengthRow lengthCol = MS.zeroM lengthRow lengthCol - let zeroCreate lengthRow lengthCol = MS.zeroM lengthRow lengthCol - let identity m = MS.identityM m - let create lengthRow lengthCol value = MS.constM lengthRow lengthCol value - let ofScalar scalar = MS.scalarM scalar - let diag v = MS.diagM v - let initDiagonal v = MS.diagM v - let constDiag n x = MS.constDiagM n x - - // Operators - /// Performs a element wise addition of matrices matrix1 and matrix2 (matrix1 + matrix2).
Only usable if both matrices have the same dimensions.
- /// - /// - /// - /// - /// - /// - /// - /// - let add matrix1 matrix2 = MS.addM matrix1 matrix2 - /// Performs a element wise substraction of matrices matrix1 and matrix2 (matrix1 - matrix2).
Only usable if both matrices have the same dimensions.
- /// - /// - /// - /// - /// - /// - /// - /// - let sub matrix1 matrix2 = MS.subM matrix1 matrix2 - /// Performs a left sided matrix multiplication of matrices matrix1 and matrix2 (matrix1 * matrix2).
Only usable if both matrices have the same dimensions.
- /// - /// - /// - /// - /// - /// - /// - /// - let mul matrix1 matrix2 = MS.mulM matrix1 matrix2 - /// Performs a matrix multiplication of the 1*n rowVector and the m*n matrix (rowVector*matrix).
Only usable if column number (n) of the vector equals the row number (m) of the matrix.
- /// - /// - /// - /// - /// - /// - /// - /// - let mulRV rowVector matrix = MS.mulRVM rowVector matrix - /// Performs a matrix multiplication of a m*n matrix and the m*1 vector (matrix*vector).
Only usable if column number (n) of the matrix equals the row number (m) of the vector.
- /// - /// - /// - /// - /// - /// - /// - /// - let mulV matrix vector = MS.mulMV matrix vector - /// Performs a element wise multiplication of matrices matrix1 and matrix2 (matrix1 * matrix2, Hadamard-Product).
Only usable if both matrices have the same dimensions.
- /// - /// - /// - /// - /// - /// - /// - /// - let cptMul matrix1 matrix2 = MS.cptMulM matrix1 matrix2 - /// Performs a element wise comparison of matrices matrix1 and matrix2 always preserving the greater value.
Only usable if both matrices have the same dimensions.
- /// - /// - /// - /// - /// - /// - /// - /// - let cptMax matrix1 matrix2 = MS.cptMaxM matrix1 matrix2 - /// Performs a element wise comparison of matrices matrix1 and matrix2 always preserving the smaller value.
Only usable if both matrices have the same dimensions.
- /// - /// - /// - /// - /// - /// - /// - /// - let cptMin matrix1 matrix2 = MS.cptMinM matrix1 matrix2 - /// Builds a new matrix where the elements are the result of multiplying every element of the given matrix with the given value - /// - /// - /// - /// - /// - /// - /// - /// - let scale value matrix = MS.scaleM value matrix - /// Performs a dot product of matrices matrix1 and matrix2.
Only usable if both matrices have the same dimensions.
- /// - /// - /// - /// - /// - /// - /// - /// - let dot matrix1 matrix2 = MS.dotM matrix1 matrix2 - /// Scales the matrix by element wise mulitplication with minus 1. - /// - /// - /// - /// - /// - /// - /// - let neg matrix = MS.negM matrix - /// Computes the trace of the matrix by summing elements of the diagonal.
Only usable if the matrix is a square matrix (m*m).
- /// - /// - /// - /// - /// - /// - /// - let trace matrix = MS.traceM matrix - /// Computes the sum of all matrix elements. - /// - /// - /// - /// - /// - /// - /// - let sum matrix = MS.sumM matrix - /// Computes the product of all matrix elements. - /// - /// - /// - /// - /// - /// - /// - let prod matrix = MS.prodM matrix - /// Frobenius matrix norm - /// - /// - /// - /// - /// - /// - /// - let norm matrix = MS.normM matrix - /// Returns the transpose of the matrix. - /// - /// - /// - /// - /// - /// - /// - let transpose matrix = MS.transM matrix - /// Performs an element wise addition of matrices matrix1 and matrix2 (matrix1 + matrix2).
Attention: the output overrides matrix1.
Only usable if both matrices have the same dimensions.
- /// - /// - /// - /// - /// - /// - /// - /// - let inplaceAdd matrix1 matrix2 = MS.inplaceAddM matrix1 matrix2 - /// Performs an element wise substraction of matrices matrix1 and matrix2 (matrix1 - matrix2).
Attention: the output overrides matrix1.
Only usable if both matrices have the same dimensions.
- /// - /// - /// - /// - /// - /// - /// - /// - let inplaceSub matrix1 matrix2 = MS.inplaceSubM matrix1 matrix2 - /// Iterates the given Matrix row wise and applies the function predicate element wise.
The iteration stops and returns true if an element satisfies the condition or false when the end of
the matrix is reached.
- /// - /// - /// - /// - /// - /// - /// - /// - let exists predicate matrix = MS.existsM predicate matrix - /// Iterates the given Matrix row wise and applies the function predicate element wise.
The iteration stops and returns false if an element fails the condition or true when the end of
the matrix is reached.
- /// - /// - /// - /// - /// - /// - /// - /// - let forall predicate matrix = MS.forallM predicate matrix - /// Iterates the given Matrix row wise and applies the function predicate element wise.
The iteration stops and returns true if an element satisfies the condition or false when the end of
the matrix is reached.
- /// - /// - /// - /// - /// - /// - /// - /// - let existsi predicate matrix = MS.existsiM predicate matrix - /// Iterates the given Matrix row wise and applies the function predicate element wise.
The iteration stops and returns false if an element fails the condition or true when the end of
the matrix is reached.
- /// - /// - /// - /// - /// - /// - /// - /// - let foralli predicate matrix = MS.foralliM predicate matrix - /// - let map mapping matrix = MS.mapM mapping matrix - /// - let copy matrix = MS.copyM matrix - /// - let mapi mapping matrix = MS.mapiM mapping matrix - /// - //TO_DO: refactor to take an Direction union case and use more descriptive name - let getDiagN a n = MS.getDiagnM a n - /// - let getDiag matrix = MS.getDiagnM matrix 0 - /// - let toDense matrix = MS.toDenseM matrix - /// Creates a sparse matrix based on the CSR format - /// - /// - /// - /// - /// - /// - /// - let toSparse matrix = MS.toSparseM matrix - /// - let initDense lengthRow lengthCol source = MS.initDenseM lengthRow lengthCol source - /// - let initSparse lengthRow lengthCol source = MS.initSparseM lengthRow lengthCol source - /// - let fold folder state matrix = MS.foldM folder state matrix - /// - let foldi folder state matrix = MS.foldiM folder state matrix - /// - let compare matrix1 matrix2 = MS.compareM LanguagePrimitives.GenericComparer matrix1 matrix2 - /// - let hash matrix = MS.hashM LanguagePrimitives.GenericEqualityComparer matrix - /// Returns row of given index of a matrix - /// - /// - /// - /// - /// - /// - /// - /// - let getRow matrix index = MS.getRowM matrix index - /// Replaces row of given index of a matrix with values of a vector, if vector length matches rowsize - /// - /// - /// - /// - /// - /// - /// - /// - /// - let setRow (matrix:Matrix<_>) index (vector:Vector<_>) = MS.setRowM matrix index vector - /// Returns col of given index of a matrix - /// - /// - /// - /// - /// - /// - /// - /// - let getCol matrix index = MS.getColM matrix index - /// Replaces column of given index of a matrix with values of a vector, if vector length matches columnsize - /// - /// - /// - /// - /// - /// - /// - /// - /// - let setCol (matrix:Matrix<_>) index (vector:Vector<_>) = MS.setColM matrix index vector - /// - let getCols matrix column1 column2 = MS.getColsM matrix (column1,column1+column2-1) - /// - let getRows matrix row1 row2 = MS.getRowsM matrix (row1,row1+row2-1) - /// - let getRegion matrix column1 row1 column2 row2 = MS.getRegionM matrix (column1,column1+column2-1) (row1,row1+row2-1) - /// - let ofRowVector rowVector = MS.rowvecM rowVector - /// - let ofVector vector = MS.vectorM vector - /// takes the first column of the matrix as vector - /// - /// - /// - /// - /// - /// - /// - let toVector matrix = MS.toVectorM matrix - /// takes the first row of the matrix as rowvector - /// - /// - /// - /// - /// - /// - /// - let toRowVector matrix = MS.toRowVectorM matrix - /// - let toScalar matrix = MS.toScalarM matrix - /// reads matrix from delimiter separated file - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - let readCSV (path: string) (separator: char) (removeHeaderRow: bool) (removeHeaderCol: bool) (transform: string -> 'a) = - IO.File.ReadAllLines(path) - |> fun x -> - if removeHeaderRow then Array.tail x else x - |> Array.map (fun x -> - let tmp = x.Split separator - if removeHeaderCol then - tmp.[1..] |> Array.map transform - else tmp |> Array.map transform - ) - |> ofSeq - - let inplace_assign f matrix = MS.inplaceAssignM f matrix - let inplace_cptMul matrix1 matrix2 = MS.inplaceCptMulM matrix1 matrix2 - let inplace_scale value matrix = MS.inplaceScaleM value matrix - let inplace_map mapping matrix = MS.inplace_mapM mapping matrix - let inplace_mapi mapping matrix = MS.inplace_mapiM mapping matrix - - [] - let of_rowvec rowVector = ofRowVector rowVector - [] - let of_vector vector = ofVector vector - [] - let to_vector matrix = toVector matrix - [] - let to_rowvec matrix = toRowVector matrix - [] - let to_scalar matrix = toScalar matrix - [] - let inplace_add matrix1 matrix2 = inplaceAdd matrix1 matrix2 - [] - let inplace_sub matrix1 matrix2 = inplaceSub matrix1 matrix2 - [] - let of_scalar scalar = ofScalar scalar - [] - let of_list lists = ofList lists - [] - let of_seq sources = ofSeq sources - [] - let inline of_array2D arrays = ofArray2D arrays - [] - let inline sparse_of_array2D arrays = sparseOfArray2D arrays - [] - let inline to_array2D matrix = toArray2D matrix - [] - let init_diagonal vector = initDiagonal vector - [] - let to_dense matrix = toDense matrix - [] - let to_sparse matrix = toSparse matrix - [] - let init_dense lengthRow lengthCol source = initDense lengthRow lengthCol source - [] - let init_sparse lengthRow lengthCol source = initSparse lengthRow lengthCol source - let nonzeroEntries matrix = MS.nonZeroEntriesM matrix - [] - let nonzero_entries matrix = nonzeroEntries matrix - - - // TM - [] - let enumerateRowWise f (matrix:Matrix<'a>) = - seq [ - for rowi=0 to matrix.NumRows-1 do - yield f (seq [for coli=0 to matrix.NumCols-1 do yield matrix.[rowi,coli]]) - ] - /// Applies mapping function along row axis - /// - /// - /// - /// - /// - /// - /// - /// - let mapRows (mapping: RowVector<'a> -> 'b) (matrix: Matrix<'a>) = - Vector.Generic.init matrix.NumRows (fun rowi -> - mapping (getRow matrix rowi) - ) - - /// Maps every matrix row using the position dependent function - /// - /// - /// - /// - /// - /// - /// - /// - let mapiRows (mapping: int -> RowVector<'a> -> 'b) (matrix: Matrix<'a>) = - Vector.Generic.init matrix.NumRows (fun rowi -> - mapping rowi (getRow matrix rowi) - ) - - // TM - /// Applies function f along column axis - [] - let enumerateColumnWise f (matrix:Matrix<'a>) = - seq [ - for coli=0 to matrix.NumCols-1 do - yield f (seq [for rowi=0 to matrix.NumRows-1 do yield matrix.[rowi,coli]]) - ] - /// Applies mapping function along column axis - /// - /// - /// - /// - /// - /// - /// - /// - let mapCols (mapping: Vector<'a> -> 'b) (matrix: Matrix<'a>) = - RowVector.Generic.init matrix.NumCols (fun coli -> - mapping (getCol matrix coli) - ) - /// Maps every matrix column using the position dependant function - /// - /// - /// - /// - /// - /// - /// - /// - let mapiCols (mapping: int -> Vector<'a> -> 'b) (matrix: Matrix<'a>) = - RowVector.Generic.init matrix.NumCols (fun coli -> - mapping coli (getCol matrix coli) - ) - /// Iterates the given Matrix row wise and places every element in a new vector with length n*m. - /// - /// - /// - /// - /// - /// - /// - let flattenRowWise (matrix: Matrix<'a>) = - let tmp = FSharp.Stats.Vector.Generic.zeroCreate (matrix.NumRows*matrix.NumCols) - for m = 0 to matrix.NumRows-1 do - for n = 0 to matrix.NumCols-1 do - tmp.[m*matrix.NumCols+n] <- matrix.[m,n] - tmp - - /// Iterates the given Matrix column wise and places every element in a new vector with length n*m. - /// - /// - /// - /// - /// - /// - /// - let flattenColWise (matrix: Matrix<'a>) = - matrix.Transpose |> flattenRowWise - - - module MG = Generic - module DS = DoubleImpl - module GU = GenericImpl - module MS = SpecializedGenericImpl - - // Element type OpsData - type elem = float - - // Accessors - let get (a:Matrix<_>) i j = MG.get a i j - let set (a:Matrix<_>) i j x = MG.set a i j x - // Creation - ///returns a dense matrix with m rows and n rows, applying the init function with the two indices as arguments - let init m n f = DS.initDenseMatrixDS m n f |> MS.dense - ///returns a dense matrix with the inner lists of the input jagged list as its rows - let ofJaggedList xss = DS.listDenseMatrixDS xss |> MS.dense - ///returns a dense matrix with the inner lists of the input jagged list as its columns - let ofJaggedColList xss = DS.colListDenseMatrixDS xss |> MS.dense - ///returns a dense matrix with the inner sequences of the input jagged sequences as its rows - let ofJaggedSeq xss = DS.seqDenseMatrixDS xss |> MS.dense - ///returns a dense matrix with the inner sequences of the input jagged sequence as its columns - let ofJaggedColSeq xss = DS.colSeqDenseMatrixDS xss |> MS.dense - ///returns a dense matrix with the inner arrays of the input jagged array as its rows - let ofJaggedArray xss = DS.arrayDenseMatrixDS xss |> MS.dense - /// returns a dense matrix with the inner arrays of the input jagged array as its columns - /// - /// - /// - /// - /// - /// - /// - let ofJaggedColArray xss = DS.colArrayDenseMatrixDS xss |> MS.dense - /// returns a dense matrix with the inner rowvectors of the input vector as its rows - /// - /// - /// - /// - /// - /// - /// - let ofRows (rows: Vector>) = DS.seqDenseMatrixDS rows |> MS.dense - /// returns a dense matrix with the inner vectors of the input rowvector as its columns - /// - /// - /// - /// - /// - /// - /// - let ofCols (cols: RowVector>) = DS.colSeqDenseMatrixDS cols |> MS.dense - /// reads matrix from delimiter separated file - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - let readCSV (path: string) (separator: char) (removeHeaderRow: bool) (removeHeaderCol: bool) = - IO.File.ReadAllLines(path) - |> fun x -> - if removeHeaderRow then Array.tail x else x - |> Array.map (fun x -> - let tmp = x.Split separator - if removeHeaderCol then - tmp.[1..] |> Array.map float - else tmp |> Array.map float - ) - |> DS.arrayDenseMatrixDS - |> MS.dense - - /// - let diag (v:vector) = MG.diag v - /// - //TO-DO: this should do something else as Matrix.diag. E.g. int -> (int -> float) -> Matrix - let initDiagonal (v:vector) = MG.diag v - /// - let constDiag n x : matrix = MG.constDiag n x - /// - //TO-DO: maybe rename to constCreate - let create m n x = DS.constDenseMatrixDS m n x |> MS.dense - /// - let ofScalar x = DS.scalarDenseMatrixDS x |> MS.dense - /// - let ofArray2D arr : matrix = MG.ofArray2D arr - /// Creates a sparse matrix based on the CSR format - /// - /// - /// - /// - /// - /// - /// - let sparseOfArray2D arr : matrix = MG.sparseOfArray2D arr - /// - let toArray2D (m : matrix) = MG.toArray2D m - /// - let toJaggedArray (m: matrix) = MG.toJaggedArray m - /// converts the matrix into an array of column arrays - /// - /// - /// - /// - /// - /// - /// - let toJaggedColArray (m: matrix) = MG.toJaggedColArray m - /// converts the matrix into an seq of row seqs - /// - /// - /// - /// - /// - /// - /// - let toJaggedSeq (m: matrix) = MG.toJaggedSeq m - /// converts the matrix into an seq of column seqs - /// - /// - /// - /// - /// - /// - /// - let toJaggedColSeq (m: matrix) = MG.toJaggedColSeq m - /// - let getDiagN (a:matrix) n = MG.getDiagN a n - /// - let getDiag (a:matrix) = MG.getDiag a - - // Operators - /// Performs a element wise addition of matrices a and b (a+b).
Only usable if both matrices have the same dimensions.
- /// - /// - /// - /// - /// - /// - /// - /// - let add (a:matrix) (b:matrix) = MS.addM a b - /// Performs a element wise substraction of matrices a and b (a-b).
Only usable if both matrices have the same dimensions.
- /// - /// - /// - /// - /// - /// - /// - /// - let sub (a:matrix) (b:matrix) = MS.subM a b - /// Performs a left sided matrix multiplication of a and b (a*b).
Only usable if both matrices have the same dimensions.
- /// - /// - /// - /// - /// - /// - /// - /// - let mul (a:matrix) (b:matrix) = MS.mulM a b - /// Performs a matrix multiplication m*n matrix a and the m*1 vector b (a*b).
Only usable if column number (n) of the matrix equals the row number (m) of the vector.
- /// - /// - /// - /// - /// - /// - /// - /// - let mulV (a:matrix) (b:vector) = MS.mulMV a b - /// Performs a matrix multiplication of the 1*n rowvector a and the m*n matrix b (a*b).
Only usable if column number (n) of the vector equals the row number (m) of the matrix.
- /// - /// - /// - /// - /// - /// - /// - /// - let mulRV (a:rowvec) (b:matrix) = MS.mulRVM a b - /// Performs a element wise multiplication of matrices a and b (a+b, Hadamard-Product).
Only usable if both matrices have the same dimensions.
- /// - /// - /// - /// - /// - /// - /// - /// - let cptMul (a:matrix) (b:matrix) = MS.cptMulM a b - /// Performs a element wise comparison of matrices a and b always preserving the greater value.
Only usable if both matrices have the same dimensions.
- /// - /// - /// - /// - /// - /// - /// - /// - let cptMax (a:matrix) (b:matrix) = MS.cptMaxM a b - /// Performs a element wise comparison of matrices a and b always preserving the smaller value.
Only usable if both matrices have the same dimensions.
- /// - /// - /// - /// - /// - /// - /// - /// - let cptMin (a:matrix) (b:matrix) = MS.cptMinM a b - /// Builds a new matrix where the elements are the result of multiplying every element of the given matrix with the given value - /// - /// - /// - /// - /// - /// - /// - /// - let scale a (b:matrix) = MS.scaleM a b - /// Scales matrix a by element wise mulitplication with minus 1. - /// - /// - /// - /// - /// - /// - /// - let neg (a:matrix) = MS.negM a - /// Computes the trace of matrix a by summing elements of the diagonal.
Only usable if matrices a is a square matrix (m*m).
- /// - /// - /// - /// - /// - /// - /// - let trace (a:matrix) = MS.traceM a - /// Returns the transpose of matrix a - /// - /// - /// - /// - /// - /// - /// - let transpose (a:matrix) = MG.transpose a - /// Iterates the given Matrix row wise and applies function f element wise.
The iteration stops and returns false if an element fails the condition or true when the end of
the matrix is reached.
- /// - /// - /// - /// - /// - /// - /// - /// - let forall f (a:matrix) = MG.forall f a - /// Iterates the given Matrix row wise and applies function f element wise.
The iteration stops and returns true if an element satisfies the condition or false when the end of
the matrix is reached.
- /// - /// - /// - /// - /// - /// - /// - /// - let exists f (a:matrix) = MG.exists f a - /// Iterates the given Matrix row wise and applies function f element wise.
The iteration stops and returns false if an element fails the condition or true when the end of
the matrix is reached.
- /// - /// - /// - /// - /// - /// - /// - /// - let foralli f (a:matrix) = MG.foralli f a - /// Iterates the given Matrix row wise and applies function f element wise.
The iteration stops and returns true if an element satisfies the condition or false when the end of
the matrix is reached.
- /// - /// - /// - /// - /// - /// - /// - /// - let existsi f (a:matrix) = MG.existsi f a - let x = List.fold - /// Builds a new matrix whose elements are the result of row wise applying the given function on each element of a. - /// - /// - /// - /// - /// - /// - /// - /// - let map f (a:matrix) = MG.map f a - /// Builds a new matrix whose elements are identical to the elements of a. - /// - /// - /// - /// - /// - /// - /// - let copy (a:matrix) = MG.copy a - /// Builds a new matrix whose elements are the result of row wise applying the given function on each element of a. The integer index
passed to the function indicates the index (from 0) the of the element being transformed.
- /// - /// - /// - /// - /// - /// - /// - /// - let mapi f (a:matrix) : matrix = MG.mapi f a - /// Applies a function f row wise to each element of the matrix, threading an accumulator argument through the computation.
The fold function takes the second argument, and applies the function f to it and the first element of the matrix.
Then, it feeds this result into the function f along with the second element, and so on. It returns the final result.
If the input function is f and the elements are i0...iN, then this function computes f (... (f s i0) i1 ...) iN.
- /// - /// - /// - /// - /// - /// - /// - /// - /// - let fold f z (a:matrix) = MG.fold f z a - /// Applies a function f row wise to each element of the matrix, threading an accumulator argument through the computation.
The fold function takes the second argument, and applies the function f to it and the first element of the matrix.
Then, it feeds this result into the function f along with the second element, and so on. It returns the final result.
If the input function is f and the elements are i0...iN, then this function computes f (... (f s i0) i1 ...) iN.
The integers indicies passed to the function indicate row and column position (from 0) the of the element being transformed.
- /// - /// - /// - /// - /// - /// - /// - /// - /// - let foldi f z (a:matrix) = MG.foldi f z a - /// Transforms the matrix a to a dense matrix representation - /// - /// - /// - /// - /// - /// - /// - let toDense (a:matrix) = MG.toDense a - /// Transforms the matrix a to a sparse matrix representation - /// - /// - /// - /// - /// - /// - /// - let toSparse (a:matrix) = MG.toSparse a - /// Creates a dense matrix with i rows and j columns. All values are initialized to the value of a. - /// - /// - /// - /// - /// - /// - /// - /// - /// - let initDense i j a : matrix = MG.initDense i j a - /// Creates a sparse matrix with i rows and j columns. All values are initialized to the value of a. - /// - /// - /// - /// - /// - /// - /// - /// - /// - let initSparse i j a : matrix = MG.initSparse i j a - /// Iterates the m*n matrix a row wise and returns a list of tuples (mi,ni,v) containing non zero elements of a
and their row (m) and column (n) indicies.
- /// - /// - /// - /// - /// - /// - /// - let nonzero_entries (a:matrix) = MG.nonzeroEntries a - /// Creates a dense matrix with i rows and j columns. All values are initialized to yero (0.). - /// - /// - /// - /// - /// - /// - /// - /// - let zero m n = DS.zeroDenseMatrixDS m n |> MS.dense - /// Creates a dense identiy m*m matrix. A identity matrix is always squared and the elements are set to zero exept elements
on the diagonal, which are set to 1.
e.g.
[[1.;0.;0.]
[0.;1.;0.]
[0.;0.;1.]]
- /// - /// - /// - /// - /// - /// - /// - let identity m : matrix = MG.identity m - /// Creates a dense matrix with i rows and j columns. All values are initialized to one (1.). - /// - /// - /// - /// - /// - /// - /// - /// - let ones m n = create m n 1.0 - /// Returns row of index i of matrix a - /// - /// - /// - /// - /// - /// - /// - /// - let getRow (a:matrix) i = MG.getRow a i - /// Replaces row of index i of matrix a with values of vector v, if vector length matches rowsize - /// - /// - /// - /// - /// - /// - /// - /// - /// - let setRow (a:Matrix<_>) i (v:Vector<_>) = MG.setRow a i v - /// Returns col of index j of matrix a - /// - /// - /// - /// - /// - /// - /// - /// - let getCol (a:matrix) j = MG.getCol a j - /// Replaces column of index j of matrix a with values of vector v, if vector length matches columnsize - /// - /// - /// - /// - /// - /// - /// - /// - /// - let setCol (a:Matrix<_>) j (v:Vector<_>) = MG.setCol a j v - /// Accesses the m*n matrix a and returns a total of j2 Columns starting from column index j1. The Result is a new
m*j2 matrix.
Only usable if (j1+j2-1) does not exceed n.
- /// - /// - /// - /// - /// - /// - /// - /// - /// - let getCols (a:matrix) j1 j2 = MG.getCols a j1 j2 - /// Accesses the m*n matrix a and returns a total of i2 rows starting from row index i1. The Result is a new
i2*n matrix.
Only usable if (i1+i2-1) does not exceed m.
- /// - /// - /// - /// - /// - /// - /// - /// - /// - let getRows (a:matrix) i1 i2 = MG.getRows a i1 i2 - - let countBy f (a:matrix) = - let n = a.NumCols * a.NumRows - let (r,c) = a.Dimensions - let rec loop ir ic acc = - if ir = r then - if ic = c then - [true,acc;false,n - acc] - else loop ir (ic+1) (if f a.[ir,ic] then acc + 1 else acc) - else - if ic = c then - loop (ir+1) 0 acc - else loop (ir+1) (ic+1) (if f a.[ir,ic] then acc + 1 else acc) - loop 0 0 0 - - /// Accesses the m*n matrix a and returns a total of i2 rows and j2 columns starting from row index i1 and colum index j1. The Result is a new
i2*j2 matrix.
Only usable if (i1+i2-1) does not exceed m and (j1+j2-1) does not exceed n.
- /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - let getRegion (a:matrix) i1 j1 i2 j2 = MG.getRegion a i1 j1 i2 j2 - let rowRange (a:Matrix<_>) = (0,a.NumRows - 1) - let colRange (a:Matrix<_>) = (0,a.NumCols - 1) - let wholeRegion a = (colRange a, rowRange a) - let foldByRow f (z:Vector<'T>) (a:Matrix<_>) = - colRange a |> GU.foldR (fun z j -> MS.mapiV (fun i z -> f z (get a i j)) z) z - let foldByCol f (z:RowVector<'T>) (a:Matrix<_>) = - rowRange a |> GU.foldR (fun z i -> MS.mapiRV (fun j z -> f z (get a i j)) z) z - let foldRow f (z:'T) (a:Matrix<_>) i = - colRange a |> GU.foldR (fun (z:'T) j -> f z (get a i j)) z - let foldCol f (z:'T) (a:Matrix<_>) j = - rowRange a |> GU.foldR (fun (z:'T) i -> f z (get a i j)) z - let sum (a:matrix) = MS.sumM a - let prod (a:matrix) = MS.prodM a - let norm (a:matrix) = MS.normM a - let dot (a:matrix) b = MS.dotM a b - let cptPow a y = map (fun x -> x ** y) a - // Functions that only make sense on this type - let randomize v = map (fun vij -> MRandom.float vij) v (* res_ij = random [0,vij] values *) - let ofRowVector x : matrix = MS.rowvecM x - let ofVector x : matrix = MS.vectorM x - let toVector x : vector = MS.toVectorM x - let toRowVector x : rowvec = MS.toRowVectorM x - let toScalar x : float = MS.toScalarM x - let inplaceAdd (a:matrix) b = MS.inplaceAddM a b - let inplaceSub (a:matrix) b = MS.inplaceSubM a b - // Mutation - let inplace_assign f (a:matrix) = MG.inplace_assign f a - let inplace_mapi f (a:matrix) = MG.inplace_mapi f a - let inplace_cptMul (a:matrix) b = MS.inplaceCptMulM a b - let inplace_scale a (b:matrix) = MS.inplaceScaleM a b - [] - let inplace_add a b = inplaceAdd a b - [] - let inplace_sub a b = inplaceSub a b - [] - let of_rowvec x = ofRowVector x - [] - let of_vector x = ofVector x - [] - let to_vector x = toVector x - [] - let to_rowvec x = toRowVector x - [] - let to_scalar x = toScalar x - [] - let inline of_array2D arr = ofArray2D arr - [] - let inline sparse_of_array2D arr = sparseOfArray2D arr - [] - let inline to_array2D m = toArray2D m - [] - let of_list xss = ofJaggedList xss - [] - let of_seq xss = ofJaggedSeq xss - [] - let init_diagonal v = initDiagonal v - [] - let of_scalar x = ofScalar x - [] - let to_dense x = toDense x - [] - let to_sparse x = toSparse x - [] - let init_dense i j a = initDense i j a - [] - let init_sparse i j a = initSparse i j a - - //---------------------------------------------------------------------------- - // Stats - - /// Returns upper triangular Matrix by setting all values beneath the diagonal to Zero.
Warning: triangular matrices can only be computed for square input matrices.
- /// - /// - /// - /// - /// - /// - /// - let getUpperTriangular (a:Matrix) = - let nA = a.NumCols - let mA = a.NumRows - if nA<>mA then invalidArg "a" "expected a square matrix"; - else - a - |> mapi (fun n m x -> if n > m then 0. else x ) - - /// Returns lower triangular Matrix by setting all values beneath the diagonal to Zero.
Warning: triangular matrices can only be computed for square input matrices.
- /// - /// - /// - /// - /// - /// - /// - let getLowerTriangular (a:Matrix) = - let nA = a.NumCols - let mA = a.NumRows - if nA<>mA then invalidArg "a" "expected a square matrix"; - else - a - |> mapi (fun n m x -> if n < m then 0. else x ) - - /// Returns diagonal matrix by setting all values beneath and above the diagonal to Zero.
Warning: diagonal matrices can only be computed for square input matrices.
- /// - /// - /// - /// - /// - /// - /// - let toDiagonal (a:Matrix) = - getDiag a - |> diag - - /// Computes the row wise sums of a Matrix - /// - /// - /// - /// - /// - /// - /// - let sumRows (a:matrix) = - a - |> foldByRow (fun acc r -> acc + r ) (Vector.zeroCreate a.NumRows) - - /// Computes the column wise sums of a Matrix - /// - /// - /// - /// - /// - /// - /// - let sumColumns (a:matrix) = - a - |> foldByCol (fun acc r -> acc + r ) (RowVector.zero a.NumCols) - - /// Computes the row wise mean of a Matrix - /// - /// - /// - /// - /// - /// - /// - let meanRowWise (a:matrix) = - a - |> sumRows - |> Vector.map (fun sum -> sum / (a.NumCols |> float)) - - /// Computes the Column wise mean of a Matrix - /// - /// - /// - /// - /// - /// - /// - let meanColumnWise (a:matrix) = - a - |> sumColumns - |> RowVector.map (fun sum -> sum / (a.NumRows |> float)) - - ///Computes mean in the specified orientation - /// orientation - "RowWise" or "ColWise" - /// - /// - /// - /// - /// - /// - /// - /// - let meanAsSeq (orientation:Orientation) (a:matrix) = - match orientation with - | RowWise -> meanRowWise a |> seq - | ColWise -> meanColumnWise a |> seq - - /// computes the column specific covariance matrix of a data matrix as described at: - // http://stattrek.com/matrix-algebra/covariance-matrix.aspx - let columnCovarianceMatrixOf df (dataMatrix:Matrix) = - /// Step 1:
contains the deviation scores for the data matrix - let devMatrix = - let ident = ones dataMatrix.NumRows dataMatrix.NumRows - dataMatrix - (ident * dataMatrix |> map (fun elem -> elem / float dataMatrix.NumRows)) - /// Step 2:
Compute devMatrix' * devMatrix, the k x k deviation sums of squares and cross products matrix for x. - let devMTdevM = - devMatrix.Transpose * devMatrix - /// Step 3:
Then, divide each term in the deviation sums of squares and cross product matrix by n to create the variance-covariance matrix. That is: - devMTdevM |> map (fun elem -> elem / (float df)) - - /// computes the column specific population covariance matrix of a data matrix - /// - /// - /// - /// - /// - /// - /// - let columnPopulationCovarianceMatrixOf (dataMatrix:Matrix) = - columnCovarianceMatrixOf dataMatrix.NumRows dataMatrix - - /// computes the column specific sample covariance matrix of a data matrix - /// - /// - /// - /// - /// - /// - /// - let columnSampleCovarianceMatrixOf (dataMatrix:Matrix) = - columnCovarianceMatrixOf (dataMatrix.NumRows-1) dataMatrix - - /// computes the row specific population covariance matrix of a data matrix - /// - /// - /// - /// - /// - /// - /// - let rowPopulationCovarianceMatrixOf (dataMatrix:Matrix) = - columnCovarianceMatrixOf dataMatrix.Transpose.NumRows dataMatrix.Transpose - - /// computes the row specific sample covariance matrix of a data matrix - /// - /// - /// - /// - /// - /// - /// - let rowSampleCovarianceMatrixOf (dataMatrix:Matrix) = - columnCovarianceMatrixOf (dataMatrix.Transpose.NumRows-1) dataMatrix.Transpose - - /// computes the orientation and dataSource specific covariance matrix of a dataMatrix\
dataSource - "Sample" or "Population". \
orientation - "RowWise" or "ColWise"
- /// - /// - /// - /// - /// - /// - /// - /// - /// - let covarianceMatrixOf (dataSource:DataSource) (orientation:Orientation) (dataMatrix:matrix) :matrix = - match dataSource with - |Sample -> - match orientation with - |RowWise ->rowSampleCovarianceMatrixOf dataMatrix - |ColWise ->columnSampleCovarianceMatrixOf dataMatrix - |Population -> - match orientation with - |RowWise ->rowPopulationCovarianceMatrixOf dataMatrix - |ColWise ->columnPopulationCovarianceMatrixOf dataMatrix - //---------------------------------------------------------------------------- - - /// Applies function f along row axis - /// - /// - /// - /// - /// - /// - /// - /// - let mapRows f (m:matrix) = Generic.mapRows f m - /// Applies function f along row axis - [] - let enumerateRowWise f (m:matrix) = Generic.mapRows f m - - /// Maps every matrix row using the position dependant function - /// - /// - /// - /// - /// - /// - /// - /// - let mapiRows (f: int -> rowvec -> 'b) (m:matrix) = Generic.mapiRows f m - - /// Applies function f along column axis - /// - /// - /// - /// - /// - /// - /// - /// - let mapCols f (m:matrix) = Generic.mapCols f m - /// Applies function f along column axis - [] - let enumerateColumnWise f (m:matrix) = Generic.mapCols f m - - /// Maps every matrix column using the position dependant function - /// - /// - /// - /// - /// - /// - /// - /// - let mapiCols (f: int -> vector -> 'b) (m:matrix) = Generic.mapiCols f m - - /// Iterates the given Matrix row wise and places every element in a new vector with length n*m. - /// - /// - /// - /// - /// - /// - /// - let flattenRowWise (a: matrix) = Generic.flattenRowWise a - - /// Iterates the given Matrix column wise and places every element in a new vector with length n*m. - /// - /// - /// - /// - /// - /// - /// - let flattenColWise (a: matrix) = Generic.flattenColWise a - - /// Removes a row at a given index - /// - /// - /// - /// - /// - /// - /// - /// - let removeRowAt (index:int) (m:Matrix<'T>) : Matrix<'T> = - let nRows,nCols = m.Dimensions - //let nm = Matrix.Generic.zero (nRows-1) nCols - let nm = MG.zeroCreate (nRows-1) nCols - let rec loop nRowI rowI = - if rowI < 0 then - nm - else - if rowI <> index then - for colI=0 to nCols-1 do - nm.[nRowI,colI] <- m.[rowI,colI] - loop (nRowI-1) (rowI-1) - else - loop (nRowI) (rowI-1) - - loop (nRows-2) (nRows-1) - - /// - /// Returns a matrix without the rows for which the given predicate returns false

The predicate function based on which the rows should be filtered. The resulting matrix will only contain rows for which this function returns true
The matrix to filter rows from
- /// - /// - /// - /// - /// - /// - /// - let filterRows (rowPredicate: (RowVector<'T> -> bool)) (m:Matrix<'T>) : Matrix<'T> = - let validRows = - [| - for rowIndex in 0..m.NumRows - 1 do - let row = MG.getRow m rowIndex - if rowPredicate row then yield rowIndex - |] - MG.init validRows.Length m.NumCols (fun r c -> - m.[validRows.[r],c] - ) - - /// - /// Returns a matrix without the cols for which the given predicate returns false

The predicate function based on which the cols should be filtered. The resulting matrix will only contain rows for which this function returns true
The matrix to filter cols from
- /// - /// - /// - /// - /// - /// - /// - let filterCols (colPredicate: (Vector<'T> -> bool)) (m:Matrix<'T>) : Matrix<'T> = - let validCols = - [| - for colIndex in 0..m.NumCols - 1 do - let col = MG.getCol m colIndex - if colPredicate col then yield colIndex - |] - MG.init m.NumRows validCols.Length (fun r c -> - m.[r,validCols.[c]] - ) - - /// Removes a column at a given index - /// - /// - /// - /// - /// - /// - /// - /// - let removeColAt index (m:Matrix<_>) = - let nRows,nCols = m.Dimensions - //let nm = Matrix.Generic.zero nRows (nCols-1) - let nm = MG.zeroCreate nRows (nCols-1) - let rec loop nColI colI = - if nColI < 0 then - nm - else - if colI <> index then - for rowI=0 to nRows-1 do - nm.[rowI,nColI] <- m.[rowI,colI] - loop (nColI-1) (colI-1) - else - loop (nColI) (colI-1) - - loop (nRows-2) (nRows-1) - - /// Splits a matrix along row direction according to given indices. Returns (matrix including rows according to indices, rest) - /// - /// - /// - /// - /// - /// - /// - /// - let splitRows (indices:int[]) (m:Matrix<_>) = - - let nRows,nCols = m.Dimensions - //let nm = Matrix.Generic.zero (nRows-indices.Length) nCols - //let nmi = Matrix.Generic.zero indices.Length nCols - let nm = MG.zeroCreate (nRows-indices.Length) nCols - let nmi = MG.zeroCreate indices.Length nCols - indices |> Array.sortInPlace - let rec loop nRowI nRowIi rowI = - match rowI with - | i as rowI when rowI < 0 -> nmi,nm - | i as rowI when nRowIi >= 0 && rowI = indices.[nRowIi] -> - for colI=0 to nCols-1 do - nmi.[nRowIi,colI] <- m.[rowI,colI] - loop (nRowI) (nRowIi-1) (rowI-1) - | _ -> //i as rowI when rowI <> indices.[ii] -> - for colI=0 to nCols-1 do - nm.[nRowI,colI] <- m.[rowI,colI] - loop (nRowI-1) (nRowIi) (rowI-1) - - loop (nRows-1-indices.Length) (indices.Length-1) (nRows-1) - - /// Splits a matrix along column direction according to given indices. Returns (matrix including cols according to indices, rest) - /// - /// - /// - /// - /// - /// - /// - /// - let splitCols (indices:int[]) (m:Matrix<_>) = - let nRows,nCols = m.Dimensions - //let nm = Matrix.Generic.zero nRows (nCols-indices.Length) - //let nmi = Matrix.Generic.zero nRows indices.Length - let nm = MG.zeroCreate nRows (nCols-indices.Length) - let nmi = MG.zeroCreate nRows indices.Length - indices |> Array.sortInPlace - let rec loop nColI nColIi colI = - match colI with - | i as colI when colI < 0 -> nmi,nm - | i as colI when nColIi >= 0 && colI = indices.[nColIi] -> - for rowI=0 to nRows-1 do - nmi.[rowI,nColIi] <- m.[rowI,colI] - loop (nColI) (nColIi-1) (colI-1) - | _ -> //i as rowI when rowI <> indices.[ii] -> - for rowI=0 to nRows-1 do - nm.[rowI,nColI] <- m.[rowI,colI] - loop (nColI-1) (nColIi) (colI-1) - - loop (nCols-1-indices.Length) (indices.Length-1) (nCols-1) - - -[] -module MatrixExtension = - - type Matrix<'T> with - member x.ToArray2() = Matrix.Generic.toArray2D x - member x.ToArray2D() = Matrix.Generic.toArray2D x - - /// Reads generic matrix from file. Requires a function to transform the input strings to the desired type - static member ReadCSV(path,transformValues,?Separator,?RemoveHeaderRow,?RemoveHeaderCol): Matrix<'T> = - - let sep = defaultArg Separator '\t' - let rmr = defaultArg RemoveHeaderRow false - let rmc = defaultArg RemoveHeaderCol false - - Matrix.Generic.readCSV path sep rmr rmc transformValues - -#if FX_NO_DEBUG_DISPLAYS -#else - [] -#endif - - member x.NonZeroEntries = Matrix.Generic.nonzeroEntries x - member x.ToScalar() = Matrix.Generic.toScalar x - member x.ToRowVector() = Matrix.Generic.toRowVector x - member x.ToVector() = Matrix.Generic.toVector x - -#if FX_NO_DEBUG_DISPLAYS -#else - [] -#endif - member x.Norm = Matrix.Generic.norm x - member x.Column(n) = Matrix.Generic.getCol x n - member x.Row(n) = Matrix.Generic.getRow x n - member x.Columns (i,ni) = Matrix.Generic.getCols x i ni - member x.Rows (j,nj) = Matrix.Generic.getRows x j nj - member x.Region(i,j,ni,nj) = Matrix.Generic.getRegion x i j ni nj - member x.GetDiagonal(i) = Matrix.Generic.getDiagN x i - -#if FX_NO_DEBUG_DISPLAYS -#else - [] -#endif - member x.Diagonal = Matrix.Generic.getDiag x - - member x.Copy () = Matrix.Generic.copy x - -// [] -// module MatrixTopLevelOperators = -// -// let matrix ll = Matrix.ofSeq ll -// let vector l = Vector.ofSeq l -// let rowvec l = RowVector.ofSeq l diff --git a/src/FSharp.Stats/MatrixTopLevelOperators.fs b/src/FSharp.Stats/MatrixTopLevelOperators.fs deleted file mode 100644 index b54077d12..000000000 --- a/src/FSharp.Stats/MatrixTopLevelOperators.fs +++ /dev/null @@ -1,10 +0,0 @@ -//namespace Microsoft.FSharp.Math // old namespace -namespace FSharp.Stats - -[] -module MatrixTopLevelOperators = - - let matrix ll = Matrix.ofJaggedSeq ll - let vector l = Vector.ofSeq l - let rowvec l = RowVector.ofSeq l - diff --git a/src/FSharp.Stats/RowVector.fs b/src/FSharp.Stats/RowVector.fs deleted file mode 100644 index 586d45c28..000000000 --- a/src/FSharp.Stats/RowVector.fs +++ /dev/null @@ -1,88 +0,0 @@ -namespace FSharp.Stats - -#nowarn "60" // implementations in augmentations -#nowarn "69" // implementations in augmentations - -open System -open System.Globalization -open System.Collections -open System.Collections.Generic -open System.Diagnostics - -[] -module RowVector = - - module Generic = - - module OpsS = SpecializedGenericImpl - - let get (a:RowVector<_>) i = a.[i] - let set (a:RowVector<_>) i x = a.[i] <- x - let zero n = OpsS.zeroRV n - let length (v:RowVector<_>) = v.Length - let init m f = OpsS.initRV m f - let create m x = OpsS.constRV m x - let transpose a = OpsS.transRV a - let copy a = OpsS.copyRV a - let ofList a = OpsS.listRV a - let ofArray a = OpsS.arrayRV a - let ofSeq a = OpsS.seqRV a - let toArray m = Array.init (length m) (get m) - [] - let of_list a = ofList a - [] - let of_array a = ofArray a - [] - let of_seq a = ofSeq a - [] - let to_array m = toArray m - let map mapping (a:RowVector<_>) = OpsS.mapRV mapping a - - module RVG = Generic - - let get (a:rowvec) i = RVG.get a i - let set (a:rowvec) i x = RVG.set a i x - let length (a:rowvec) = RVG.length a - let ncols (a:rowvec) = RVG.length a - let ofArray arr : rowvec = RVG.ofArray arr - let toArray (m : rowvec) = RVG.toArray m - - let init m f : rowvec = RVG.init m f - let create m f : rowvec = RVG.create m f - let zero n = create n 0.0 - let ofList x : rowvec = RVG.ofList x - let ofSeq x : rowvec = RVG.ofSeq x - let transpose x : vector = RVG.transpose x - let copy x : rowvec = RVG.copy x - - [] - let of_list x = ofList x - [] - let of_seq x = ofSeq x - [] - let of_array arr = ofArray arr - [] - let to_array m = toArray m - /// Builds a new rowvector whose elements are the results of applying the given function to each of the elements of the rowvector. - /// - /// - /// - /// - /// - /// - /// - /// - let map mapping (rowvec:rowvec) = RVG.map mapping rowvec - - - - -[] -module RowVectorExtension = - - type RowVector<'T> with - member x.ToArray() = RowVector.Generic.toArray x - member x.Copy () = RowVector.Generic.copy x - - - diff --git a/src/FSharp.Stats/ServiceLocator.fs b/src/FSharp.Stats/ServiceLocator.fs deleted file mode 100644 index b54bc8eb9..000000000 --- a/src/FSharp.Stats/ServiceLocator.fs +++ /dev/null @@ -1,191 +0,0 @@ -namespace FSharp.Stats - -open System.IO -open System.Collections.Generic - -module ServiceLocator = - - type Architecture = - | X64 - | X86 - - type OS = - | Windows - | Linux - | Mac - - /// Generic provider with unmanaged DLL dependencies. - type Provider<'a> = { - Name : string - RequiredDLLs : string seq - Architecture : Architecture - OS : OS - InitService : unit -> 'a - } - - let createProviderX64<'a> name requiredDLLs os initService : Provider<'a> = - {Name=name;RequiredDLLs=requiredDLLs;Architecture=Architecture.X64;OS=os;InitService=initService} - - let createProviderX86<'a> name requiredDLLs os initService : Provider<'a> = - {Name=name;RequiredDLLs=requiredDLLs;Architecture=Architecture.X86;OS=os;InitService=initService} - - let setEnvironmentPathVariable dllDirectory = - System.Environment.SetEnvironmentVariable("PATH", System.Environment.GetEnvironmentVariable("PATH") + ";" + dllDirectory) - - /// The DLLs search procedure for those DLLs - // - // The default behavior now is to look in all the system locations first, then the current directory, and finally any user-defined paths. - // This will have an impact on your code if you install a DLL in the application's directory because Windows Server 2003 no longer loads - // the 'local' DLL if a DLL of the same name is in the system directory. A common example is if an application won't run with a specific - // version of a DLL, an older version is installed that does work in the application directory. This scenario will fail in Windows Server 2003. - // - // Search order: - // The Windows system directory. The GetSystemDirectory function retrieves the path of this directory. - // The Windows directory. The GetWindowsDirectory function retrieves the path of this directory. - // The directory where the executable module for the current process is located. - // The current directory. - // The directories listed in the PATH environment variable. - let initSearchPaths () = - let noLaterRepeats xs = - let collect (soFar,revXs) x = - if Set.contains x soFar then (soFar,revXs) else (Set.add x soFar,x::revXs) - let (_,revXs) = List.fold collect (Set.empty,[]) xs - revXs - //List.rev revXs - - let windowsSystemDir = System.Environment.SystemDirectory - let windowsDir = - windowsSystemDir - |> System.IO.Path.GetDirectoryName - let currentExeDirs = - // This includes EXE directory, and loaded DLL directories. - // It may be an over-estimate of the search path. - let proc = System.Diagnostics.Process.GetCurrentProcess() - [ for m in proc.Modules do - yield Path.GetDirectoryName m.FileName ] - |> List.distinct - let currentDir = System.Environment.CurrentDirectory - let executingAssembly = System.Reflection.Assembly.GetExecutingAssembly().Location - let pathDirs = - match System.Environment.GetEnvironmentVariable("PATH") with - | null -> [] - | paths -> paths.Split([|';'|]) |> List.ofArray - - windowsSystemDir :: windowsDir :: (currentExeDirs @ [currentDir;executingAssembly] @ pathDirs) - //noLaterRepeats orderedSearchPaths - - // normalizes filename - let normDllFilename (dll:string) = - (Path.GetFileName dll).ToLower() - - let initDllPathTable () : Map = - initSearchPaths () - |> Seq.collect (fun path -> - if not (Directory.Exists path) then - seq [] - else - Directory.GetFiles(path,"*.DLL") - |> Seq.map (fun file -> normDllFilename file,path) - ) - |> Seq.fold (fun state (file,path) -> - if state.ContainsKey file then - let tmp = state.[file] - // rev path order ! - state |> Map.add file (path::tmp) - else - state |> Map.add file ([path]) - ) Map.empty - - - let isLoadableProvider (dllPaths:Map) (provider:Provider<'a>) = - let isAvailable (dll:string) = dllPaths.ContainsKey(normDllFilename dll) - provider.RequiredDLLs |> Seq.forall isAvailable - - - let tryCheckProvider (dllPaths:Map) (provider:Provider<'a>) = - //let isAvailable (dll:string) = dllPaths.ContainsKey(normDllFilename dll) - let availableReason (dll:string) = - dllPaths.[normDllFilename dll] - |> Seq.map (fun path -> sprintf "Required %s seen in %s" dll path ) - |> String.concat "\n" - if isLoadableProvider dllPaths provider then - let justification = - provider.RequiredDLLs - |> Seq.map availableReason - |> String.concat "\n" - Some (provider,("Provider: " + provider.Name + "\n" + justification)) - else - None // "Provider is not loadable" - - - - - type 'a ServiceState = - | ServiceDisabled // service disabled, do not look for it. - | ServiceEnabledUninitialised // service enabled, but no search made yet. - | ServiceEnabledOK of 'a * string // service enabled, and justification string for diagnostics. - | ServiceEnabledFailed // service enabled, but DLLs not found, or load failed. - - - type ServiceProvider<'a>(providers:Provider<'a> seq) = - let mutable providers = Seq.toArray providers // possible providers configuration state - let mutable state = ServiceEnabledUninitialised // service state - let dllPaths = initDllPathTable () - - /// Service Providers - member this.Providers with get() = providers - and set(x) = providers <- x - - /// Disable the service. - member this.Stop() = state <- ServiceDisabled - - /// Use the LAPACK service from the given provider. - /// If the supporting DLLs are not available, this may fail (now or later). - member this.StartWith(p:Provider<'a>) = - let justification = - match tryCheckProvider dllPaths p with - | None -> "The provider DLLs did not appear to be present, the service may fail" - | Some (p,justification) -> justification - state <- ServiceEnabledOK (p.InitService(),justification) - - /// Start the service with the first provider that looks loadable. - member this.Start() = - let candidates = Array.choose (tryCheckProvider dllPaths) providers - if candidates.Length=0 then // guard - state <- ServiceEnabledFailed - false - else - let provider,justification = candidates.[0] - state <- ServiceEnabledOK (provider.InitService(),justification) // index covered by guard above - true - - member this.GetPathMap() = dllPaths - - member this.Service() = - match state with - | ServiceEnabledUninitialised -> this.Start() |> ignore - | _ -> () - match state with - | ServiceDisabled - | ServiceEnabledUninitialised // (The above initialisation call must have failed) - | ServiceEnabledFailed -> None - | ServiceEnabledOK (service,_) -> Some service - - member this.Available() = - match state with - | ServiceDisabled - | ServiceEnabledFailed - | ServiceEnabledUninitialised -> false - | ServiceEnabledOK (_,_) -> true - - member this.Status() = - match state with - | ServiceDisabled -> "Disabled" - | ServiceEnabledFailed -> "Failed to start" - | ServiceEnabledUninitialised -> "Will auto enable on demand" - | ServiceEnabledOK (service,justification) -> "Enabled\n" + justification - - - - - diff --git a/src/FSharp.Stats/Vector.fs b/src/FSharp.Stats/Vector.fs deleted file mode 100644 index b2a2cfbce..000000000 --- a/src/FSharp.Stats/Vector.fs +++ /dev/null @@ -1,880 +0,0 @@ -namespace FSharp.Stats - -#nowarn "60" // implementations in augmentations -#nowarn "69" // implementations in augmentations - -open System -open System.Collections - -//---------------------------------------------------------------------------- -// module Vector -//---------------------------------------------------------------------------- - -[] -//Basic vector operations -module Vector = - - module Generic = - - module OpsS = SpecializedGenericImpl - /// Returns the value of the vector a at the given index i - /// vector to get value for - /// index in the vector to get value for - /// the value at index - let get (vector:Vector<'T>) index = vector.[index] - /// Sets the value to the vector a at the given index - /// vector to set value for - /// index in the vector to set value for - /// value to set in the vector - let set (vector:Vector<'T>) index value = vector.[index] <- value - /// Returns length of vector v - /// - /// - /// - /// - /// - /// - /// - let length (vector:Vector<'T>) = vector.Length - /// Creates vector from list xss - /// - /// - /// - /// - /// - /// - /// - let ofList list = OpsS.listV list - /// Creates vector from seq xss - /// - /// - /// - /// - /// - /// - /// - let ofSeq source = OpsS.seqV source - /// Initializes vector with count members, based on function f - /// - /// - /// - /// - /// - /// - /// - /// - let init count initializer = OpsS.initV count initializer - let initNumeric count f = OpsS.createNumericV count f - let ofArray array = OpsS.arrayV array - let toArray (vector:Vector<'T>) = Array.init vector.Length (get vector) - /// Creates vector of length count and fills it with value - /// - /// - /// - /// - /// - /// - /// - /// - let create count value = OpsS.constV count value - /// Creates a vector of length count and fills it with zeros - /// - /// - /// - /// - /// - /// - /// - let zeroCreate count = OpsS.zeroV count - /// Creates a vector of length count and fills it with ones - /// - /// - /// - /// - /// - /// - /// - let oneCreate count = OpsS.createNumericV count (fun ops _ -> ops.One) - [] - let zero count = OpsS.zeroV count - [] - let ones count = OpsS.createNumericV count (fun ops _ -> ops.One) - let ofScalar x = OpsS.scalarV x - let add vector1 vector2 = OpsS.addV vector1 vector2 - let sub vector1 vector2 = OpsS.subV vector1 vector2 - let mulRVV vector1 vector2 = OpsS.mulRVV vector1 vector2 - let mulVRV vector1 vector2 = OpsS.mulVRV vector1 vector2 - let cptMul vector1 vector2 = OpsS.cptMulV vector1 vector2 - let cptMax vector1 vector2 = OpsS.cptMaxV vector1 vector2 - let cptMin vector1 vector2 = OpsS.cptMinV vector1 vector2 - let scale a b = OpsS.scaleV a b - /// Dot product of the two vectors - /// - /// - /// - /// - /// - /// - /// - /// - let dot vector1 vector2 = OpsS.dotV vector1 vector2 - let neg vector = OpsS.negV vector - let transpose vector = OpsS.transV vector - let inplaceAdd vector1 vector2 = OpsS.inplaceAddV vector1 vector2 - let inplaceSub vector1 vector2 = OpsS.inplaceSubV vector1 vector2 - let inplaceCptMul vector1 vector2 = OpsS.inplaceCptMulV vector1 vector2 - let inplaceScale vector1 vector2 = OpsS.inplaceScaleV vector1 vector2 - [] - let inplace_cptMul v1 v2 = OpsS.inplaceCptMulV v1 v2 - [] - let inplace_scale v1 v2 = OpsS.inplaceScaleV v1 v2 - - - let exists predicate (vector:Vector<'T>) = OpsS.existsV predicate vector - let forall predicate (vector:Vector<'T>) = OpsS.forallV predicate vector - let existsi predicate (vector:Vector<'T>) = OpsS.existsiV predicate vector - let foralli predicate (vector:Vector<'T>) = OpsS.foralliV predicate vector - let map mapping vector = OpsS.mapV mapping vector - let map2 mapping vector1 vector2 = OpsS.map2V mapping vector1 vector2 - let map3 mapping vector1 vector2 vector3 = OpsS.map3V mapping vector1 vector2 vector3 - let zip vector1 vector2 = OpsS.zipV vector1 vector2 - let unzip vector = OpsS.unzipV vector - let mapi mapping vector = OpsS.mapiV mapping vector - let copy vector = OpsS.copyV vector - let inplaceMap f v = OpsS.inplace_mapV f v - let inplaceMapi f v = OpsS.inplace_mapiV f v - [] - let inplace_map f a = OpsS.inplace_mapV f a - [] - let inplace_mapi f a = OpsS.inplace_mapiV f a - let fold (folder:'State -> 'T -> 'State) (state:'State) vector = OpsS.foldV folder state vector - let foldi (folder:int -> 'State -> 'T -> 'State) (state:'State) vector = OpsS.foldiV folder state vector - let compare comparer vector = OpsS.compareV comparer vector - let hash a = OpsS.hashV a - let inplaceAssign f vector = OpsS.assignV f vector - [] - let inplace_assign f a = OpsS.assignV f a - /// Sum of all elements of the vector a - /// - /// - /// - /// - /// - /// - /// - let sum (a:Vector<_>) = let ops = a.ElementOps in fold (fun x y -> ops.Add(x,y)) ops.Zero a - let prod (a:Vector<_>) = let ops = a.ElementOps in fold (fun x y -> ops.Multiply(x,y)) ops.One a - - let norm (a:Vector<_>) = - let normOps = GenericImpl.getNormOps a.ElementOps - sqrt (fold (fun x y -> x + normOps.Norm(y)**2.0) 0.0 a) - - [] - let of_list xss = ofList xss - [] - let of_seq xss = ofSeq xss - [] - let of_array arr = ofArray arr - [] - let to_array v = toArray v - [] - let of_scalar x = ofScalar x - [] - let inplace_add a b = inplaceAdd a b - [] - let inplace_sub a b = inplaceSub a b - - module VG = Generic - module VecDS = DoubleImpl - module VecGU = GenericImpl - /// Returns the value of the vector at the given index - /// - /// - /// - /// - /// - /// - /// - /// - let get (vector:vector) index = VG.get vector index - /// Sets the value to the vector at the given index - /// - /// - /// - /// - /// - /// - /// - /// - /// - let set (vector:vector) index value = VG.set vector index value - /// Returns length of vector - /// - /// - /// - /// - /// - /// - /// - let length (vector:vector) = VG.length vector - /// Returns length of vector - /// - /// - /// - /// - /// - /// - /// - let nRows (vector:vector) = VG.length vector - ///Returns length of vector - [] - let nrows (vector:vector) = VG.length vector - /// Initiates vector of length count and fills it by applying initializer function on indices - /// - /// - /// - /// - /// - /// - /// - /// - let init count initializer = VecDS.createVecDS count initializer - /// Creates vector with values of array - /// - /// - /// - /// - /// - /// - /// - let ofArray array : vector = VG.ofArray array - /// Creates array with values of vector - /// - /// - /// - /// - /// - /// - /// - let toArray (vector : vector) = VG.toArray vector - - type range = int * int - let countR ((a,b) : range) = (b-a)+1 - let idxR ((a,_) : range) i = a+i - type rangef = float * float * float // start, skip, end - let countRF ((a,d,b) : rangef) = System.Convert.ToInt32((b-a)/d) + 1 - let countBy projection (vector:Vector<_>) = - let n = vector.Length - let rec loop i acc = - if i = n then - [true,acc;false,n - acc] - else - if projection vector.[i] then - loop (i+1) (acc+1) - else loop (i+1) acc - loop 0 0 - //let countRF ((a,d,b) : rangef) = Float.to_int((b-a)/d) + 1 - let idxRF ((a,d,b) : rangef) i = System.Math.Min (a + d * float(i),b) - - let range n1 n2 = let r = (n1,n2) in init (countR r) (fun i -> float(idxR r i)) - - let rangef a b c = let r = (a,b,c) in init (countRF r) (fun i -> idxRF r i) - /// Creates vector with values of list - /// - /// - /// - /// - /// - /// - /// - let ofList list = VecDS.listVecDS list - /// Creates vector with values of sequence - /// - /// - /// - /// - /// - /// - /// - let ofSeq source = VecDS.seqVecDS source - ///Creates vector of length count and fills it with value - let create count value = VecDS.constVecDS count value - /// Creates one dimensional vector of value - /// - /// - /// - /// - /// - /// - /// - let ofScalar value = VecDS.scalarVecDS value - /// Builds a new vector whose elements are the results of adding the corresponding elements of the two vectors pairwise. The two input vectors must have the same lengths, otherwise ArgumentException is raised. - /// - /// - /// - /// - /// - /// - /// - /// - let add vector1 vector2 = VecDS.addVecDS vector1 vector2 - /// Builds a new vector whose elements are the results of substracting the corresponding elements of vector2 from vector1. The two input vectors must have the same lengths, otherwise ArgumentException is raised. - /// - /// - /// - /// - /// - /// - /// - /// - let sub vector1 vector2 = VecDS.subVecDS vector1 vector2 - let mulRVV vector1 vector2 = VecDS.mulRowVecVecDS vector1 vector2 - let mulVRV vector1 vector2 = VecDS.mulVecRowVecDS vector1 vector2 - /// Builds a new vector whose elements are the results of multiplying the corresponding elements of the given vectors. The two input vectors must have the same lengths, otherwise ArgumentException is raised. - /// - /// - /// - /// - /// - /// - /// - /// - let cptMul vector1 vector2 = VecDS.cptMulVecDS vector1 vector2 - let cptMax vector1 vector2 = VecDS.cptMaxVecDS vector1 vector2 - let cptMin vector1 vector2 = VecDS.cptMinVecDS vector1 vector2 - /// Builds a new vector whose elements are the results of multiplying the given scalar with each of the elements of the vector. - /// - /// - /// - /// - /// - /// - /// - /// - let scale scalar vector = VecDS.scaleVecDS scalar vector - /// Builds a new vector whose elements are the results of multiplying -1 with each of the elements of the vector. - /// - /// - /// - /// - /// - /// - /// - let neg vector = VecDS.negVecDS vector - /// Dot product of the two vectors - /// - /// - /// - /// - /// - /// - /// - /// - let dot vector1 vector2 = VecDS.dotVecDS vector1 vector2 - let transpose (vector:vector) = VG.transpose vector - let exists predicate (vector:vector) = VG.exists predicate vector - let forall predicate (vector:vector) = VG.forall predicate vector - let existsi predicate (vector:vector) = VG.existsi predicate vector - let foralli predicate (vector:vector) = VG.foralli predicate vector - /// Builds a new vector whose elements are the results of applying the given function to each of the elements of the vector. - /// - /// - /// - /// - /// - /// - /// - /// - let map mapping (vector:vector) = VG.map mapping vector - /// Builds a new vector whose elements are the results of applying the given function to the corresponding elements of the two vectors pairwise. The two input vectors must have the same lengths, otherwise ArgumentException is raised. - /// - /// - /// - /// - /// - /// - /// - /// - /// - let map2 mapping (vector1:vector) (vector2:vector) = VG.map2 mapping vector1 vector2 - /// Builds a new vector whose elements are the results of applying the given function to the corresponding elements of the two vectors pairwise. The two input vectors must have the same lengths, otherwise ArgumentException is raised. - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - let map3 mapping (vector1:vector) (vector2:vector) (vector3:vector) = VG.map3 mapping vector1 vector2 vector3 - /// Builds a new vector that contains the elements of the given vector. - /// - /// - /// - /// - /// - /// - /// - let copy (vector:vector) = VG.copy vector - /// Builds a new vector whose elements are the results of applying the given function to each of the elements of the vector and their corresponding index. - /// - /// - /// - /// - /// - /// - /// - /// - let mapi mapping (vector:vector) : vector = VG.mapi mapping vector - /// Applies a function to each element of the vector, threading an accumulator argument through the computation. - /// - /// - /// - /// - /// - /// - /// - /// - /// - let fold folder (state:'State) (vector:vector) = VG.fold folder state vector - /// Applies a function to each element of the vector and their corresponding index, threading an accumulator argument through the computation. - /// - /// - /// - /// - /// - /// - /// - /// - /// - let foldi folder (state:'State) (vector:vector) = VG.foldi folder state vector - /// Creates a vector of length count and fills it with zeros - /// - /// - /// - /// - /// - /// - /// - let zeroCreate count = create count 0.0 - /// Creates a vector of length count and fills it with ones - /// - /// - /// - /// - /// - /// - /// - let oneCreate count = create count 1.0 - [] - let zero count = create count 0.0 - [] - let ones count = create count 1.0 - /// Sum of all elements of the vector - /// - /// - /// - /// - /// - /// - /// - let sum vector = VecDS.sumVecDS vector - /// Product of all elements of the vector - /// - /// - /// - /// - /// - /// - /// - let prod vector = fold (fun x y -> x * y) 1.0 vector - /// Euklidian norm of the vector - /// - /// - /// - /// - /// - /// - /// - let norm (vector:vector) = sqrt (fold (fun x y -> x + y * y) 0.0 vector) (* fixed *) - /// Builds a new vector whose elements are the results of exponentiating each of the elements of the vector with n. - /// - /// - /// - /// - /// - /// - /// - /// - let toThePower n vector = map (fun x -> x ** n) vector - [] - let cptPow vector y = map (fun x -> x ** y) vector - /// Applies the given function to each of the indexes of the vector. No new vector is created. - /// - /// - /// - /// - /// - /// - /// - /// - let inplaceAssign f (vector:vector) = VG.inplaceAssign f vector - /// Applies the given function to each of the elements of the vector. No new vector is created. - /// - /// - /// - /// - /// - /// - /// - /// - let inplaceMap f (vector:vector) = VG.inplaceMap f vector - /// Applies the given function to each of the elements of the vector and their corresponding index. No new vector is created. - /// - /// - /// - /// - /// - /// - /// - /// - let inplaceMapi f (vector:vector) = VG.inplaceMapi f vector - /// Add values of vector2 to values of vector1. Vector2 stays unchanged. - /// - /// - /// - /// - /// - /// - /// - /// - let inplaceAdd vector1 vector2 = VecDS.inplaceAddVecDS vector1 vector2 - /// Substract values of vector2 from values of vector1. Vector2 stays unchanged. - /// - /// - /// - /// - /// - /// - /// - /// - let inplaceSub vector1 vector2 = VecDS.inplaceSubVecDS vector1 vector2 - /// Multiply values of vector1 with values of vector2. Vector2 stays unchanged. - /// - /// - /// - /// - /// - /// - /// - /// - let inplaceCptMul vector1 vector2 = VecDS.inplaceCptMulVecDS vector1 vector2 - /// Multiply values of vector with scalar. - /// - /// - /// - /// - /// - /// - /// - /// - let inplaceScale scalar vector = VecDS.inplaceScaleVecDS scalar vector - ///Applies the given function to each of the indexes of the vector. - /// Builds vector of Length 1 from value x - /// - /// - /// - /// - /// - /// - /// - let singleton x = ofScalar x - [] - let inplace_assign f (v:vector) = VG.inplaceAssign f v - ///Applies the given function to each of the elements of the vector. - [] - let inplace_map f (v:vector) = VG.inplaceMap f v - ///Applies the given function to each of the elements of the vector and their corresponding index. - [] - let inplace_mapi f (v:vector) = VG.inplaceMapi f v - ///Add values of vector v2 to values of vector v1. Vector v2 stays unchanged - [] - let inplace_add v1 v2 = VecDS.inplaceAddVecDS v1 v2 - ///Substract values of vector v2 from values of vector v1. Vector v2 stays unchanged - [] - let inplace_sub v1 v2 = VecDS.inplaceSubVecDS v1 v2 - ///Multiply values of vector v1 with values of vector v2. Vector v2 stays unchanged. - [] - let inplace_cptMul v1 v2 = VecDS.inplaceCptMulVecDS v1 v2 - ///Multiply values of vector v1 with scalar. - [] - let inplace_scale x v = VecDS.inplaceScaleVecDS x v - ///Builds vector from array - [] - let of_array arr = ofArray arr - ///Builds array from vector - [] - let to_array v = toArray v - ///Builds vector from list - [] - let of_list xs = ofList xs - ///Builds vector from sequence - [] - let of_seq xs = ofSeq xs - ///Builds one dimensional vector from scalar - [] - let of_scalar x = ofScalar x - - - - //---------------------------------------------------------------------------- - // Stats - //---------------------------------------------------------------------------- - - /// Returns the raw data array without copy - /// - /// - /// - /// - /// - /// - /// - let raw (vector:Vector<'T>) = vector.Values - - // - let interval (items:Vector<'T>) = - let rec loop index (minimum) (maximum) = - if index < items.Length then - let current = items.[index] - loop (index+1) (min current minimum) (max current maximum) - else - Interval.CreateClosed<_> (minimum,maximum) - //Init by fist value - if items.Length > 1 then - loop 1 items.[0] items.[0] - else - Interval.Empty - - /// Computes the population mean (Normalized by N) - /// - /// - /// - /// - /// - /// - /// - let inline mean (items:Vector<'T>) = - let ops = items.ElementOps - let zero = ops.Zero - let one = ops.One - let rec loop i c acc = - if i < items.Length then - loop (i+1) (ops.Add(c,one)) (ops.Add(acc,items.[i])) - else - acc / c - loop 0 zero zero - - - /// Computes the sample median - /// - /// - /// - /// - /// - /// - /// - let inline median (items:Vector<'T>) = - items.Values |> Array.median - - /// Median absolute deviation (MAD) - /// - /// - /// - /// - /// - /// - /// - let medianAbsoluteDev (items : vector) = - items.Values |> Array.medianAbsoluteDev - - - /// Returns SummaryStats of vector with N, mean, sum-of-squares, minimum and maximum - /// - /// - /// - /// - /// - /// - /// - let inline stats (items:Vector<'T>) = - let zero = LanguagePrimitives.GenericZero< 'T > - let one = LanguagePrimitives.GenericOne< 'T > - - let rec loop index n (minimum) (maximum) m1 m2 = - if index < items.Length then - let current = items.[index] - let delta = current - m1 - let deltaN = (delta / n) - //let delta_n2 = deltaN * deltaN - let m1' = m1 + deltaN - let m2' = m2 + delta * deltaN * (n-one) - loop (index+1) (n + one) (min current minimum) (max current maximum) m1' m2' - else - SummaryStats.createSummaryStats (n-one) m1 m2 minimum maximum - //Init by fist value - if items.Length > 1 then - loop 0 one items.[0] items.[0] zero zero - else - let uNan = zero / zero - SummaryStats.createSummaryStats zero uNan uNan uNan uNan - - - /// Returns an estimator of the population covariance of two random variables v1 and v2 - /// - /// - /// - /// - /// - /// - /// - /// - let covPopulation (v1:vector) (v2:vector) = - Seq.covPopulation v1 v2 - - /// Returns the sample covariance of two random variables v1 and v2. (Bessel's correction by N-1) - /// - /// - /// - /// - /// - /// - /// - /// - let cov (v1:vector) (v2:vector) = - Seq.cov v1 v2 - - /// calculates the sample means with a given number of replicates present in the sequence - /// - /// - /// - /// - /// - /// - /// - /// - let getMeanOfReplicates rep (data:vector) = - Seq.getMeanOfReplicates rep data - |> ofSeq - - /// calculates the sample standard deviations with a given number of replicates present in the sequence - /// - /// - /// - /// - /// - /// - /// - /// - let getStDevOfReplicates rep (data:vector) = - Seq.getStDevOfReplicates rep data - |> ofSeq - - /// calculates the coefficient of variation based on the sample standard deviations with a given number of replicates present in the sequence - /// - /// - /// - /// - /// - /// - /// - /// - let getCvOfReplicates rep (data:vector) = - Seq.getCvOfReplicates rep data - |> ofSeq - - /// Splits a vector according to given indices. Returns (vector including values according to indices, rest) - /// - /// - /// - /// - /// - /// - /// - /// - let splitVector (indices:int[]) (v:Vector<_>) = - let len = v.Length - //let nv = Vector.Generic.zero (len-indices.Length) - //let nvi = Vector.Generic.zero indices.Length - let nv = VG.zeroCreate (len-indices.Length) - let nvi = VG.zeroCreate indices.Length - indices |> Array.sortInPlace - let rec loop ni nii i = - match i with - | i when i < 0 -> nvi,nv - | i when nii >= 0 && i = indices.[nii] -> - nvi.[nii] <- v.[i] - loop (ni) (nii-1) (i-1) - | _ -> - nv.[ni] <- v.[i] - loop (ni-1) (nii) (i-1) - - loop (len-1-indices.Length) (indices.Length-1) (len-1) - - - /// Module to compute common statistical measure on - module SummaryStats = - - /// Returns SummaryStats of vector with N, mean, sum-of-squares, minimum and maximum - /// - /// - /// - /// - /// - /// - /// - let ofVector (a:Vector<'a>) = stats a - - - - - - - - - -[] -module VectorExtension = - - type Vector<'T> with - member x.ToArray() = Vector.Generic.toArray x - member x.Norm = Vector.Generic.norm x - member x.Copy () = Vector.Generic.copy x - - /// - /// Creates an vector with values between a given interval - /// - /// start value (is included) - /// end value (by default is included) - /// sets the number of elements in the vector. If not set, stepsize = 1. - /// If false, the vector does not contain the stop value - static member linspace(start:float,stop:float,num:int,?IncludeEndpoint:bool) : vector = - - let includeEndpoint = defaultArg IncludeEndpoint true - - Seq.linspace(start,stop,num,includeEndpoint) |> Vector.ofSeq - - /// - /// Creates a geometric vector of floats with values between a given interval. - /// - /// start value (is included) - /// end value (by default is included) - /// sets the number of elements in the vector. Defaults to 50. - /// If false, the vector does not contain the stop value. Defaults to true. - static member geomspace(start:float,stop:float,num:int,?IncludeEndpoint:bool) : vector = - let includeEndpoint = defaultArg IncludeEndpoint true - - Seq.geomspace (start, stop ,num, includeEndpoint) - |> Vector.ofSeq - \ No newline at end of file From f7308245ac3b21b2001cff6928293a83cbfc2e22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20M=C3=BChlhaus?= Date: Wed, 9 Apr 2025 13:40:02 +0200 Subject: [PATCH 003/121] Remove Surprisal analysis --- src/FSharp.Stats/ML/SurprisalAnalysis.fs | 131 ----------------------- 1 file changed, 131 deletions(-) delete mode 100644 src/FSharp.Stats/ML/SurprisalAnalysis.fs diff --git a/src/FSharp.Stats/ML/SurprisalAnalysis.fs b/src/FSharp.Stats/ML/SurprisalAnalysis.fs deleted file mode 100644 index f125d1a4e..000000000 --- a/src/FSharp.Stats/ML/SurprisalAnalysis.fs +++ /dev/null @@ -1,131 +0,0 @@ -namespace FSharp.Stats.ML - -module SurprisalAnalysis = - open FSharp.Stats - open FSharp.Stats.Algebra.LinearAlgebra - open ProviderService - - ///Summary type for the results of applying Surprisal Analysis to a dataset - type SAResult = - { - ///left singular vectors resulting from the thin SVD of the input matrix - LeftSingularVecors : Matrix - ///right singular vectors resulting from the thin SVD of the input matrix - RightSingularVectors : Matrix - ///diagonal matrix containing the singular values resulting from the thin SVD of the input matrix - SingularValuesDiag: Matrix - ///Vector containing the singular values resulting from the thin SVD of the input matrix in descending order - SingularValues: Vector - /// - MolecularPhenotypes: Matrix - /// - Potentials: Matrix - //Error estimation not implemented yet - //ErrorMatrix: Matrix - } - - let private createSAResult lsv rsv svdiag sv mp pot = {LeftSingularVecors=lsv; RightSingularVectors=rsv; SingularValuesDiag=svdiag; SingularValues=sv; MolecularPhenotypes=mp; Potentials=pot} - - ///performs Surprisal Analysis on the input matrix A. For meaningfull results, A should be - ///of the following form: - ///The rows contain measurements for a single unique entity, - /// corresponding to timepoints represented by the columns - /// - /// - /// - /// - /// - /// - /// - let compute (A:Matrix) : SAResult= - //perform SVD - let sv,lsv,rsv = thinSVD A - //Singular values in diagonal matrix - let svMatrix = Matrix.diag sv - //get time dependant potentials - let lagranges = svMatrix * rsv - createSAResult lsv rsv svMatrix sv lsv lagranges - - //let errorEstimation (A:Matrix) = - // () - - let getEnergyLandscapeData (saRes: SAResult) = - - let g1 = Matrix.getCol saRes.MolecularPhenotypes 1 - let g2 = Matrix.getCol saRes.MolecularPhenotypes 2 - let lambda1 = Matrix.getRow saRes.Potentials 1 - let lambda2 = Matrix.getRow saRes.Potentials 2 - - let XL1L2 = - Array2D.init lambda1.Length lambda1.Length (fun lt1 lt2 -> - Array.init (saRes.MolecularPhenotypes.NumRows) (fun i -> - - (lambda1.[lt1] * g1.[i]) - (lambda2.[lt2] * g2.[i])) - |> Array.sum ) - |> JaggedArray.ofArray2D - - XL1L2 - //Chart.Surface(XL1L2,lab,lab,Opacity=0.85,Contours=Contours.initXyz(Show=true,Color="#8a8a8a"),Colorscale=Colorscale.Custom [(0.,"#0B12B0");((zero/2.),"#5F7BEF");(zero,"#BEBDBD");((zero+1.)/2.,"#E6925D");(1.,"#B4101F")]) - - let getDiagonalEnergyData (saRes:SAResult)= - [|0..saRes.Potentials.NumCols - 1|] - |> Array.map (fun t -> - let l1 = saRes.Potentials.Row 1 - let l2 = saRes.Potentials.Row 2 - let g1 = saRes.MolecularPhenotypes.Column 1 - let g2 = saRes.MolecularPhenotypes.Column 2 - g1 - |> Seq.mapi (fun i x -> - - l1.[t] * g1.[i] - l2.[t] * g2.[i] - ) - |> Seq.sum - ) - - //|> Seq.mapi (fun i x -> labels |> Seq.item i ,labels|> Seq.item i,x) - //|> fun data -> Chart.Scatter3d(data,mode=StyleParam.Lines_Markers_Text,Color = "#474747",Dash=DrawingStyle.DashDot,Width = 5.,Labels = labels)//,Color="#121111") - - //let hikingpath labels lambda (saRes:ML.SurprisalAnalysis.SAResult) = - // [|0..saRes.Potentials.NumCols - 1|] - // |> Array.map (fun t -> - // let l1 = saRes.Potentials.Row lambda - // let g1 = saRes.MolecularPhenotypes.Column lambda - // g1 - // |> Seq.mapi (fun i x -> - // - l1.[t] * g1.[i] - // ) - // |> Seq.sum - // ) - // |> Seq.mapi (fun i x -> - // if lambda = 1 then - // 0,i,x - // else i,0,x) - // |> fun data -> Chart.Scatter3d(data,mode=StyleParam.Lines_Markers_Text,Dash=DrawingStyle.DashDot,Width = 5.,Labels = (labels|> Seq.map (fun l -> sprintf "l%i_%s" lambda l ))) - - - -//let com title labels saRes = -// let xAxis() = LinearAxis.init(Title="lambda 2 at timepoint",Mirror=Mirror.All,Ticks=TickOptions.Inside,Showgrid=true,Showline=true) -// let yAxis() = LinearAxis.init(Title="lambda 1 at timepoint",Mirror=Mirror.All,Ticks=TickOptions.Inside,Showgrid=true,Showline=true) -// let ZAxis() = LinearAxis.init(Title="Free energy / RT",Mirror=Mirror.All,Ticks=TickOptions.Inside,Showgrid=true,Showline=true)//,Range=Range.MinMax(-1000.,1000.)) -// let surfacePlot = -// getSurfacePlotData saRes -// |> fun data -> -// let max = (data) |> Array.concat |> Array.max -// let min = (data) |> Array.concat |> Array.min -// let zero = - min / (max - min) -// Chart.Surface(data,labels,labels,Opacity=0.85,Contours=Contours.initXyz(Show=true,Color="#8a8a8a"),Colorscale=Colorscale.Custom [(0.,"#0B12B0");((zero/2.),"#5F7BEF");(zero,"#BEBDBD");((zero+1.)/2.,"#E6925D");(1.,"#B4101F")]) -// let diagonal = -// getDiagonalData saRes -// |> Seq.mapi (fun i x -> labels |> Seq.item i ,labels|> Seq.item i,x) -// |> fun data -> Chart.Scatter3d(data,mode=StyleParam.Lines_Markers_Text,Color = "#474747",Dash=DrawingStyle.DashDot,Width = 5.,Labels = labels)//,Color="#121111") - -// [ -// surfacePlot -// diagonal -// ] -// |> Chart.Combine -// |> Chart.withSize(1000.,1000.) -// |> Chart.withX_Axis(xAxis()) -// |> Chart.withY_Axis(yAxis()) -// |> Chart.withZ_Axis(ZAxis()) -// |> Chart.withTitle title -// |> Chart.Show \ No newline at end of file From 96f49d73c359b0d69a950834d97f6653a7831e26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20M=C3=BChlhaus?= Date: Wed, 9 Apr 2025 13:40:37 +0200 Subject: [PATCH 004/121] Remove PCA --- .../PrincipalComponentAnalysis.fs | 112 ------------------ 1 file changed, 112 deletions(-) delete mode 100644 src/FSharp.Stats/ML/Unsupervised/PrincipalComponentAnalysis.fs diff --git a/src/FSharp.Stats/ML/Unsupervised/PrincipalComponentAnalysis.fs b/src/FSharp.Stats/ML/Unsupervised/PrincipalComponentAnalysis.fs deleted file mode 100644 index 79651c207..000000000 --- a/src/FSharp.Stats/ML/Unsupervised/PrincipalComponentAnalysis.fs +++ /dev/null @@ -1,112 +0,0 @@ -namespace FSharp.Stats.ML.Unsupervised - -open FSharp.Stats - - -/// Principle component analysis -module PCA = - //The Implementation was compared to the R function prcomp(). The implementation is based on remarks found in https://stats.stackexchange.com/a/134283 - //Signs of loadings and principal components (scores) can differ from the R implementation due to different svd implementations being used internally. - //Colab workbook for direct comparison to prcomps output is accessible at: https://colab.research.google.com/drive/1DJ4ky5F5kBM87JprmAbx_gTHqSdz3vqU?usp=sharing - - type PCA = { - VarianceOfComponent: vector - ///Variance explained by principal components - VarExplainedByComponentIndividual : vector - ///Cumulative Variance explained by principal components - VarExplainedByComponentCumulative : vector - ///Matrix with columns representing individual principal components ("raw" principal components, projections on principal directions) and rows representing samples. - ///Also reffered to as "scores". Corresponds to the attribute "x" of the result object of Rs prcomp() function. - PrincipalComponents : Matrix - ///Matrix with columns representing component loadings and rows individual features. - ///Corresponds to the attribute "rotation" of the result object of Rs prcomp() function. - Loadings : Matrix - } - - - /// Normalizes each feature by substracting the corresponing mean followed by a division by its standard deviation.
The centered features of the matrix are centered around 0 and possess a standard deviation of 1.
Expects a data matrix with rows representing observations and columns representing features.
- /// - /// - /// - /// - /// - /// - /// - let center m = - if m |> Matrix.exists (fun x -> Ops.isNan x || Ops.isInf x) then - failwith "Computation not possible. Matrix contains invalid entries. Check for the existence of values equal to nan, infinity or -infinity." - else - let columnMeans = - m - |> Matrix.mapiCols (fun i x -> Seq.mean x) - |> vector - - let columnStabw = - m - |> Matrix.mapiCols (fun i x -> Seq.stDevPopulation x) - |> vector - - let substractionMatrix = - let colV = Vector.init m.NumRows (fun i -> 1.) - colV*columnMeans.Transpose - - let stabwMatrix = - let colV = Vector.init m.NumRows (fun i -> 1.) - colV*columnStabw.Transpose - - let centeredM = - m - substractionMatrix - |> Matrix.mapi (fun i j x -> x / stabwMatrix.[i,j] ) - centeredM - - /// Computes the PCA of a column centered data matrix m.
Expects a column centered data matrix m, with rows representing observations (a.k.a. samples) and columns representing features.
- /// - /// - /// - /// - /// - /// - /// - let compute m = - if m |> Matrix.exists (fun x -> Ops.isNan x || Ops.isInf x) then - failwith "Computation not possible. Matrix contains invalid entries. Check for the existence of values equal to nan, infinity or -infinity." - else - let s,u,v = FSharp.Stats.Algebra.LinearAlgebra.SVD (m) - let n = m.NumRows |> float - let varOfComp = - let e = Vector.map (fun x -> x**2.) s - e - |> Vector.map (fun x -> x / (n-1.)) - |> Vector.map sqrt - let varExplained = - let e = Vector.map (fun x -> x**2.) s - let sum = Seq.sum e - Vector.map (fun l -> abs l / sum) e - let varExplainedCum = - varExplained - |> Vector.foldi (fun i (sum,(v:vector)) x -> - let c = x+sum - v.[i] <- c - c,v - ) (0.,Vector.zeroCreate varExplained.Length) - |> snd - let pc = u * (Matrix.diag (Vector.init u.NumCols (fun i -> if i <= s.Length-1 then s.[i] else 0.))); - let loadings = Matrix.getCols v.Transpose 0 varExplained.Length - //Update: - // There seems to be a lot of ambuiguity when it comes to the use of the term loading. Here we use the term loading to - // refer to the eigenvectors, also termed "unit scaled loading". see: https://stats.stackexchange.com/questions/143905/loadings-vs-eigenvectors-in-pca-when-to-use-one-or-another - // proper loadings when https://stats.stackexchange.com/a/141531 is right, however the described scaling does - // not result in vectors of norm 1 (the columns of principal axes do) and differ from rs prcomp() "rotation" propertie which is - // described here: https://stats.stackexchange.com/a/510465 and here https://www.rdocumentation.org/packages/stats/versions/3.6.2/topics/prcomp as loadings - //let principalAxes = Matrix.getCols v.Transpose 0 varExplained.Length - //let loadings = - // principalAxes*(Matrix.diag (Vector.init principalAxes.NumCols (fun i -> if i <= s.Length-1 then s.[i] else 0.))) - // |> Matrix.map (fun x -> x / sqrt(n-1.)) - // Note: Rs biplot function with param scale=0 applies this scaling to loadings: //principalAxes*(Matrix.diag (Vector.init principalAxes.NumCols (fun i -> if i <= s.Length-1 then s.[i] else 0.))) - { - VarianceOfComponent=varOfComp - VarExplainedByComponentIndividual = varExplained - VarExplainedByComponentCumulative = varExplainedCum - PrincipalComponents = pc - Loadings = loadings - } From 9987be08c844b4f57dd46b399466e4f81af6308d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20M=C3=BChlhaus?= Date: Wed, 9 Apr 2025 13:42:05 +0200 Subject: [PATCH 005/121] Add new Vector and Matrix types using Numerics.INumber<'T> --- src/FSharp.Stats/AlgTypes/GenericMath.fs | 68 ++ src/FSharp.Stats/AlgTypes/Matrix.fs | 792 +++++++++++++++++++++++ src/FSharp.Stats/AlgTypes/MatrixExt.fs | 108 ++++ src/FSharp.Stats/AlgTypes/SIMDUtils.fs | 404 ++++++++++++ src/FSharp.Stats/AlgTypes/Vector.fs | 253 ++++++++ src/FSharp.Stats/AlgTypes/VectorExt.fs | 182 ++++++ src/FSharp.Stats/AlgTypes/VectorOps.fs | 38 ++ 7 files changed, 1845 insertions(+) create mode 100644 src/FSharp.Stats/AlgTypes/GenericMath.fs create mode 100644 src/FSharp.Stats/AlgTypes/Matrix.fs create mode 100644 src/FSharp.Stats/AlgTypes/MatrixExt.fs create mode 100644 src/FSharp.Stats/AlgTypes/SIMDUtils.fs create mode 100644 src/FSharp.Stats/AlgTypes/Vector.fs create mode 100644 src/FSharp.Stats/AlgTypes/VectorExt.fs create mode 100644 src/FSharp.Stats/AlgTypes/VectorOps.fs diff --git a/src/FSharp.Stats/AlgTypes/GenericMath.fs b/src/FSharp.Stats/AlgTypes/GenericMath.fs new file mode 100644 index 000000000..8bb1e0543 --- /dev/null +++ b/src/FSharp.Stats/AlgTypes/GenericMath.fs @@ -0,0 +1,68 @@ +namespace FSharp.Stats + +open System +open System.Runtime.InteropServices + +module GenericMath = + + /// Generic Zero + let inline zero<'T when 'T :> Numerics.INumber<'T>> = + 'T.Zero + + /// Generic One + let inline one<'T when 'T :> Numerics.INumber<'T>> = + 'T.One + + /// Generic float conversion + let inline T<'T when 'T :> Numerics.INumber<'T>> (x: float) : 'T = + 'T.CreateChecked x + + /// Generic square root + let inline sqrt<'T when 'T :> Numerics.IRootFunctions<'T>> (x: 'T) : 'T = + 'T.Sqrt(x) + + /// Generic exponentiation (e^x) + let inline exp<'T when 'T :> Numerics.IExponentialFunctions<'T>> (x: 'T) : 'T = + 'T.Exp(x) + + /// Generic power function (x^y) + let inline pow<'T when 'T :> Numerics.IPowerFunctions<'T>> (x: 'T) (y: 'T) : 'T = + 'T.Pow(x, y) + + /// Generic natural logarithm + let inline log<'T when 'T :> Numerics.ILogarithmicFunctions<'T>> (x: 'T) : 'T = + 'T.Log(x) + + /// Generic absolute value + let inline abs<'T when 'T :> Numerics.INumber<'T>> (x: 'T) : 'T = + 'T.Abs(x) + + /// Generic sine + let inline sin<'T when 'T :> Numerics.ITrigonometricFunctions<'T>> (x: 'T) : 'T = + 'T.Sin(x) + + /// Generic cosine + let inline cos<'T when 'T :> Numerics.ITrigonometricFunctions<'T>> (x: 'T) : 'T = + 'T.Cos(x) + + // /// Generic pi constant + // let inline pi<'T when 'T :> Numerics.IFloatingPointConstants<'T> and 'T :> Numerics.INumber<'T>> () : 'T = + // pi<'T>() + + /// Generic e constant (Euler's number) + let inline e<'T when 'T :> Numerics.IFloatingPointConstants<'T>> () : 'T = + 'T.E + + // /// Generic tau constant (2 * pi) + // let inline tau<'T when 'T :> Numerics.IFloatingPointConstants<'T> and 'T :> Numerics.INumber<'T>> () : 'T = + // T<'T> 2.0 * pi<'T>() + + + + + // let inline min x y = if x < y then x else y + // let inline max x y = if x > y then x else y + + // let inline clamp minVal maxVal x = + // if x < minVal then minVal elif x > maxVal then maxVal else x + diff --git a/src/FSharp.Stats/AlgTypes/Matrix.fs b/src/FSharp.Stats/AlgTypes/Matrix.fs new file mode 100644 index 000000000..a960e5b11 --- /dev/null +++ b/src/FSharp.Stats/AlgTypes/Matrix.fs @@ -0,0 +1,792 @@ +namespace FSharp.Stats + +open System +open System.Runtime.InteropServices + +// let blockSize = +// match sizeof<'T> with +// | 4 -> 32 // float32 or int +// | 8 -> 16 // float64 +// | _ -> 16 // fallback + + +/// Matrix type to hold values of a matrix in a 1D Arrays (Flattened Representation) +type Matrix<'T when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T :> ValueType> + (rows: int, cols: int, data: Vector<'T>) = + + /// Exposes the raw underlying data array (row-major flattened). + member _.Data = data + + /// Number of rows in the matrix. + member _.NumRows = rows + + /// Number of columns in the matrix. + member _.NumCols = cols + + /// Matrix indexer for getting and setting elements at (i, j). + member this.Item + with get (i, j) = + if i < 0 || i >= rows || j < 0 || j >= cols then + invalidArg "index" $"Index out of range: ({i}, {j})" + data.[i * cols + j] + and set (i, j) value = + if i < 0 || i >= rows || j < 0 || j >= cols then + invalidArg "index" $"Index out of range: ({i}, {j})" + data.[i * cols + j] <- value + + + /// + /// Returns a new Matrix<'T> that is the slice of rows [rowStart..rowEnd] + /// and columns [colStart..colEnd]. If any of these bounds is omitted, + /// it defaults to the full range in that dimension. + /// + /// Optional start row (inclusive) + /// Optional end row (inclusive) + /// Optional start column (inclusive) + /// Optional end column (inclusive) + /// A new submatrix copy. + member this.GetSlice + (rowStart: int option, rowEnd: int option, + colStart: int option, colEnd: int option) : Matrix<'T> = + + // 1) Determine actual start/end indices + let r1 = defaultArg rowStart 0 + let r2 = defaultArg rowEnd (rows - 1) + let c1 = defaultArg colStart 0 + let c2 = defaultArg colEnd (cols - 1) + + // 2) Validate them + if r1 < 0 || r2 < r1 || r2 >= rows then + invalidArg "row range" $"Invalid row slice range: {r1}..{r2}" + if c1 < 0 || c2 < c1 || c2 >= cols then + invalidArg "col range" $"Invalid column slice range: {c1}..{c2}" + + let subRows = r2 - r1 + 1 + let subCols = c2 - c1 + 1 + + // 3) Allocate new array for the submatrix + let subData = Array.zeroCreate<'T> (subRows * subCols) + + // 4) Copy row by row + for rr in 0 .. subRows - 1 do + let srcIndex = (r1 + rr) * cols + c1 + let dstIndex = rr * subCols + // Copy from data[srcIndex..(srcIndex+subCols-1)] + // to subData[dstIndex..(dstIndex+subCols-1)] + Array.blit data srcIndex subData dstIndex subCols + + // 5) Return a new Matrix with the submatrix data + Matrix<'T>(subRows, subCols, subData) + + /// + /// Convenience "slice indexer" for F# syntax: mat.[r1..r2, c1..c2]. + /// Internally calls GetSlice(...). + /// + member this.GetSlice + (rowRange: Range, colRange: Range) : Matrix<'T> = + + // Convert the F# Range type into int option pairs + let rowStart, rowEnd = + (if rowRange.Start = System.Index.Start then None else Some rowRange.Start.Value), + (if rowRange.End = System.Index.End then None else Some rowRange.End.Value) + + let colStart, colEnd = + (if colRange.Start = System.Index.Start then None else Some colRange.Start.Value), + (if colRange.End = System.Index.End then None else Some colRange.End.Value) + + // Use the primary GetSlice overload + this.GetSlice(rowStart, rowEnd, colStart, colEnd) + + + static member inline map2Unchecked<'T when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T :> ValueType> + (fVec: Numerics.Vector<'T> -> Numerics.Vector<'T> -> Numerics.Vector<'T>) + (fScalar: 'T -> 'T -> 'T) + (a: Matrix<'T>) + (b: Matrix<'T>) + : Matrix<'T> = + + // if a.Rows <> b.Rows || a.Cols <> b.Cols then + // invalidArg "b" "Matrix dimensions must match" + + let len = a.Data.Length + let result = Array.zeroCreate<'T> len + + let simdSize = Numerics.Vector<'T>.Count + let simdCount = len / simdSize + let tailStart = simdCount * simdSize + + // Cast arrays to Vector<'T> spans + let aVec = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(a.Data.AsSpan()) + let bVec = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(b.Data.AsSpan()) + let rVec = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(result.AsSpan()) + + for i = 0 to simdCount - 1 do + rVec.[i] <- fVec aVec.[i] bVec.[i] + + for i = tailStart to len - 1 do + result.[i] <- fScalar a.Data.[i] b.Data.[i] + + Matrix(a.NumRows, a.NumCols, result) + + + static member inline mapScalar<'T when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T :> ValueType> + (fv: Numerics.Vector<'T> -> Numerics.Vector<'T> -> Numerics.Vector<'T>) + (f: 'T -> 'T -> 'T) + (matrix: Matrix<'T>) + (scalar: 'T) + : Matrix<'T> = + + let length = matrix.Data.Length + let result = Array.zeroCreate<'T> length + + let slotSize = Numerics.Vector<'T>.Count + let slotCount = length / slotSize + let ceiling = slotCount * slotSize + + let scalarVec = Numerics.Vector<'T>(scalar) + + let mSpan = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(matrix.Data.AsSpan()) + let rSpan = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(result.AsSpan()) + + // SIMD chunk-wise operation + for i = 0 to slotCount - 1 do + rSpan.[i] <- fv mSpan.[i] scalarVec + + // Scalar fallback for remainder + for i = ceiling to length - 1 do + result.[i] <- f matrix.Data.[i] scalar + + Matrix(matrix.NumRows, matrix.NumCols, result) + + + + /// Creates a new matrix by initializing each element with a function `f(row, col)`. + static member inline transpose<'T when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T :> ValueType> + (rows : int) + (cols : int) + (data: 'T[]) + (blockSize: int) = + + //let blockSize = defaultArg blockSize 16 + + let src = data + let dst = Array.zeroCreate<'T> (rows * cols) + + let vectorSize = Numerics.Vector<'T>.Count + + // Process the matrix in blocks + for i0 in 0 .. blockSize .. rows - 1 do + for j0 in 0 .. blockSize .. cols - 1 do + + let iMax = min (i0 + blockSize) rows + let jMax = min (j0 + blockSize) cols + + for i in i0 .. iMax - 1 do + let srcOffset = i * cols + for j in j0 .. jMax - 1 do + let v = src.[srcOffset + j] + dst.[j * rows + i] <- v + + dst + + member this.Transpose() = + let blocksize = 16 + Matrix(this.NumCols, this.NumRows, Matrix.transpose this.NumRows this.NumCols this.Data blocksize) + + static member init<'T when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T :> ValueType> + (rows: int) + (cols: int) + (f: int -> int -> 'T) = + let data = Array.init (rows * cols) (fun idx -> f (idx / cols) (idx % cols)) + Matrix(rows, cols, data) + + static member create<'T when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T :> ValueType> + (rows: int) + (cols: int) + (data: 'T[]) : Matrix<'T> = + + Matrix(rows, cols, data) + + + /// Constructs a matrix from a 2D array. + static member ofArray2D<'T when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T :> ValueType> + (arr2D: 'T[,]) = + let rows = arr2D.GetLength(0) + let cols = arr2D.GetLength(1) + let length = rows * cols + + let flat = Array.zeroCreate<'T> length + let sourceSpan = MemoryMarshal.CreateSpan(&arr2D.[0, 0], length) + sourceSpan.CopyTo(flat.AsSpan()) + + Matrix(rows, cols, flat) + + /// Converts this matrix into a 2D array. + member this.toArray2D() = + let arr2D = Array2D.zeroCreate<'T> this.NumRows this.NumCols + let targetSpan = MemoryMarshal.CreateSpan(&arr2D.[0, 0], this.NumRows * this.NumCols) + this.Data.AsSpan().CopyTo(targetSpan) + arr2D + + + /// Constructs a matrix from a jagged array (`'T[][]`), assuming a rectangular structure. + static member ofJaggedArray<'T when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T :> ValueType> + (jagged: 'T[][]) = + let rows = jagged.Length + let cols = if rows > 0 then jagged.[0].Length else 0 + + // Optional safety check for rectangular shape + for row in jagged do + if row.Length <> cols then + invalidArg "jagged" "All rows in jagged array must have the same length." + + let flat = Array.zeroCreate<'T> (rows * cols) + + for i = 0 to rows - 1 do + let source = jagged.[i].AsSpan() + let target = flat.AsSpan(i * cols, cols) + source.CopyTo(target) + + Matrix(rows, cols, flat) + + /// Converts this matrix into a jagged array (`'T[][]`). + member this.toJaggedArray() = + let result = Array.zeroCreate<'T[]> this.NumRows + let dataSpan = this.Data.AsSpan() + + for i = 0 to this.NumRows - 1 do + let row = Array.zeroCreate<'T> this.NumCols + dataSpan.Slice(i * this.NumCols, this.NumCols).CopyTo(row.AsSpan()) + result.[i] <- row + + result + + + /// Pretty string representation with formatting and truncation, using StringBuilder. + /// Supports optional scientific notation for floating point types. + member this.toFormattedString(?maxRows: int, ?maxCols: int, ?floatFormat: string, ?useScientific: bool) = + let maxRows = defaultArg maxRows 10 + let maxCols = defaultArg maxCols 10 + let useScientific = defaultArg useScientific false + let floatFormat = + match floatFormat with + | Some f -> f + | None -> if useScientific then "0.##E+0" else "0.##" + + if this.NumRows = 0 || this.NumCols = 0 then + "Matrix (empty)" + else + let rowsToShow = min this.NumRows maxRows + let colsToShow = min this.NumCols maxCols + + // Format a single cell + let formatCell (value: 'T) = + match box value with + | :? float as f -> f.ToString(floatFormat) + | :? float32 as f -> f.ToString(floatFormat) + | _ -> string value + + let formattedCells = + Array.init rowsToShow (fun i -> + Array.init colsToShow (fun j -> + formatCell this.[i, j] + ) + ) + + let colWidths = + Array.init colsToShow (fun j -> + Array.init rowsToShow (fun i -> formattedCells.[i].[j].Length) + |> Array.max + ) + + let divider = + colWidths + |> Array.map (fun w -> String.replicate w "─") + |> String.concat "─┼─" + + let sb = Text.StringBuilder() + sb.AppendLine($"Matrix {this.NumRows}x{this.NumCols}:") |> ignore + sb.AppendLine("┌ " + divider + " ┐") |> ignore + + for i = 0 to rowsToShow - 1 do + sb.Append("│ ") |> ignore + for j = 0 to colsToShow - 1 do + let cell = formattedCells.[i].[j].PadLeft(colWidths.[j]) + sb.Append(cell) |> ignore + if j < colsToShow - 1 then sb.Append(" │ ") |> ignore + sb.AppendLine(" │") |> ignore + + if this.NumRows > rowsToShow || this.NumCols > colsToShow then + sb.AppendLine($"│ ... truncated ({this.NumRows}x{this.NumCols}) │") |> ignore + + sb.AppendLine("└ " + divider + " ┘") |> ignore + sb.ToString() + + + /// Default string representation (truncated, human-readable) + override this.ToString() = this.toFormattedString() + + static member inline checkSameShape<'T when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T :> ValueType> + (a: Matrix<'T>) (b: Matrix<'T>) = + if a.NumRows <> b.NumRows || a.NumCols <> b.NumCols then + invalidArg "b" $"Matrix dimensions must match. A is {a.NumRows}x{a.NumCols}, B is {b.NumRows}x{b.NumCols}" + + /// Element-wise addition + static member inline add<'T when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T :> ValueType> + (a: Matrix<'T>) + (b: Matrix<'T>) : Matrix<'T> = + + Matrix.checkSameShape a b + let data = + Acceleration.SIMDUtils.map2Unchecked (+) (+) a.Data b.Data + Matrix(a.NumRows, a.NumCols, data) + + static member inline subtract<'T when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T :> ValueType> + (a: Matrix<'T>) + (b: Matrix<'T>) : Matrix<'T> = + + Matrix.checkSameShape a b + Matrix.map2Unchecked (-) (-) a b + + + + static member inline multiply<'T + when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T :> ValueType> + (a: Matrix<'T>) + (b: Matrix<'T>) : Matrix<'T> = + + Matrix.checkSameShape a b + Matrix.map2Unchecked (*) (*) a b + + + static member inline divide<'T + when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T :> ValueType> + (a: Matrix<'T>) + (b: Matrix<'T>) : Matrix<'T> = + + Matrix.checkSameShape a b + Matrix.map2Unchecked (/) (/) a b + + + static member inline addScalar<'T when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T :> ValueType> + (m: Matrix<'T>) (scalar: 'T) : Matrix<'T> = + + Matrix.mapScalar (+) (+) m scalar + + + + static member inline subtractScalar<'T + when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T :> ValueType> + (m: Matrix<'T>) + (scalar: 'T) : Matrix<'T> = + + Matrix.mapScalar (-) (-) m scalar + + + static member inline multiplyScalar<'T + when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T :> ValueType> + (m: Matrix<'T>) + (scalar: 'T) : Matrix<'T> = + + Matrix.mapScalar (*) (*) m scalar + + + static member inline divideScalar<'T + when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T :> ValueType> + (m: Matrix<'T>) + (scalar: 'T) : Matrix<'T> = + + Matrix.mapScalar (/) (/) m scalar + + + /// Standard matrix-vector product + static member inline muliplyVector<'T + when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T :> ValueType> + (m: Matrix<'T>) + (v: Vector<'T>) : Vector<'T> = + + if m.NumCols <> v.Length then + invalidArg "v" $"Vector length {v.Length} must match matrix column count {m.NumCols}" + + let result: Vector<'T> = Array.zeroCreate m.NumRows + let zero = LanguagePrimitives.GenericZero<'T> + + let simdSize = Numerics.Vector<'T>.Count + let vSpan = v.AsSpan() + let vSimd = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(vSpan) + + let tailStart = (v.Length / simdSize) * simdSize + + for row = 0 to m.NumRows - 1 do + let rowOffset = row * m.NumCols + let rowSpan = m.Data.AsSpan(rowOffset, m.NumCols) + let rowSimd = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(rowSpan) + + let mutable acc = Numerics.Vector<'T>(zero) + + for i = 0 to vSimd.Length - 1 do + acc <- acc + rowSimd.[i] * vSimd.[i] + + let mutable tail = zero + for i = tailStart to m.NumCols - 1 do + tail <- tail + m.Data.[rowOffset + i] * v.[i] + + result.[row] <- Numerics.Vector.Sum(acc) + tail + + result + + static member inline addRowVector<'T + when 'T :> Numerics.INumber<'T> + and 'T : struct + and 'T : (new : unit -> 'T) + and 'T :> ValueType> + (m: Matrix<'T>) + (v: Vector<'T>) : Matrix<'T> = + + if v.Length <> m.NumCols then + invalidArg "v" $"Row vector length {v.Length} must match matrix column count {m.NumCols}" + + let resultData = Array.zeroCreate<'T> (m.NumRows * m.NumCols) + let simdSize = Numerics.Vector<'T>.Count + let simdCount = m.NumCols / simdSize + let scalarStart = simdCount * simdSize + + let vSimd = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(v.AsSpan()) + + for row = 0 to m.NumRows - 1 do + let offset = row * m.NumCols + let srcSpan = m.Data.AsSpan(offset, m.NumCols) + let dstSpan = resultData.AsSpan(offset, m.NumCols) + + let srcSimd = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(srcSpan) + let dstSimd = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(dstSpan) + + // SIMD part + for i = 0 to simdCount - 1 do + dstSimd.[i] <- srcSimd.[i] + vSimd.[i] + + // Tail (scalar) + for i = scalarStart to m.NumCols - 1 do + dstSpan.[i] <- srcSpan.[i] + v.[i] + + Matrix(m.NumRows, m.NumCols, resultData) + + + static member inline addColVector<'T + when 'T :> Numerics.INumber<'T> + and 'T : struct + and 'T : (new : unit -> 'T) + and 'T :> ValueType> + (m: Matrix<'T>) + (v: Vector<'T>) : Matrix<'T> = + + if v.Length <> m.NumRows then + invalidArg "v" $"Column vector length {v.Length} must match matrix row count {m.NumRows}" + + let cols = m.NumCols + let resultData = Array.zeroCreate<'T> (m.NumRows * cols) + let simdSize = Numerics.Vector<'T>.Count + + for row = 0 to m.NumRows - 1 do + let rowOffset = row * cols + let srcRow = m.Data.AsSpan(rowOffset, cols) + let dstRow = resultData.AsSpan(rowOffset, cols) + + let simdRow = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(srcRow) + let simdDst = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(dstRow) + + let broadcast = Numerics.Vector<'T>(v.[row]) + let simdCount = cols / simdSize + let scalarStart = simdCount * simdSize + + // SIMD-add: row + broadcast vector + for i = 0 to simdCount - 1 do + simdDst.[i] <- simdRow.[i] + broadcast + + // Scalar tail + for i = scalarStart to cols - 1 do + dstRow.[i] <- srcRow.[i] + v.[row] + + Matrix(m.NumRows, cols, resultData) + + // Matrix - matrix operations + static member inline ( + ) (a: Matrix<'T>, b: Matrix<'T>) = Matrix.add a b + static member inline ( - ) (a: Matrix<'T>, b: Matrix<'T>) = Matrix.subtract a b + static member inline ( * ) (a: Matrix<'T>, b: Matrix<'T>) = Matrix.multiply a b + static member inline ( / ) (a: Matrix<'T>, b: Matrix<'T>) = Matrix.divide a b + + // Matrix - vector operations + static member inline ( * ) (m: Matrix<'T>, v: Vector<'T>) = Matrix.muliplyVector m v + // static member inline ( + ) (m: Matrix<'T>, colVector: Vector<'T>) = Matrix.addColVector m colVector + // static member inline ( +| ) (m: Matrix<'T>, rowVector: Vector<'T>) = Matrix.addRowVector m rowVector + + // Matrix - scalar operations + static member inline (+) (m: Matrix<'T>, s: 'T) = Matrix.addScalar m s + static member inline (+) (s: 'T, m: Matrix<'T>) = Matrix.addScalar m s + + static member inline (-) (m: Matrix<'T>, s: 'T) = Matrix.subtractScalar m s + static member inline (-) (s: 'T, m: Matrix<'T>) = Matrix.subtractScalar m s + + static member inline (*) (m: Matrix<'T>, s: 'T) = Matrix.multiplyScalar m s + static member inline (*) (s: 'T, m: Matrix<'T>) = Matrix.multiplyScalar m s + + static member inline (/) (m: Matrix<'T>, s: 'T) = Matrix.divideScalar m s + static member inline (/) (s: 'T, m: Matrix<'T>) = Matrix.divideScalar m s + + + + static member inline diagonal<'T + when 'T :> Numerics.INumber<'T> + and 'T : struct + and 'T : (new : unit -> 'T) + and 'T :> ValueType> + (diag: Vector<'T>) : Matrix<'T> = + + let n = diag.Length + let data = Array.zeroCreate<'T> (n * n) + for i = 0 to n - 1 do + data.[i * n + i] <- diag.[i] + Matrix(n, n, data) + + /// + /// Returns the diagonal elements of this matrix as an array of length = min(NumRows, NumCols). + /// + static member inline getDiagonal + (m:Matrix<'T>) : Vector<'T> = + let n = min m.NumRows m.NumCols + let diag = Array.zeroCreate<'T> n + for i = 0 to n - 1 do + // The diagonal element at row i, col i is stored at offset i * cols + i + diag.[i] <- m.Data.[i * m.NumCols + i] + diag + + + static member inline identity<'T + when 'T :> Numerics.INumber<'T> + and 'T : struct + and 'T : (new : unit -> 'T) + and 'T :> ValueType> + (n: int) : Matrix<'T> = + + let data = Array.zeroCreate<'T> (n * n) + for i = 0 to n - 1 do + data.[i * n + i] <- 'T.One + Matrix(n, n, data) + + static member inline zeroCreate<'T + when 'T :> Numerics.INumber<'T> + and 'T : struct + and 'T : (new : unit -> 'T) + and 'T :> ValueType> + (rows: int) + (cols: int) : Matrix<'T> = + + let data = Array.zeroCreate<'T> (rows * cols) + Matrix(rows, cols, data) + + static member inline ones<'T + when 'T :> Numerics.INumber<'T> + and 'T : struct + and 'T : (new : unit -> 'T) + and 'T :> ValueType> + (rows: int) + (cols: int) : Matrix<'T> = + + let size = rows * cols + let data = Array.zeroCreate<'T> size + let simdSize = Numerics.Vector<'T>.Count + let simdCount = size / simdSize + + let vOne = Numerics.Vector<'T>('T.One) + let span = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(data.AsSpan()) + + for i = 0 to simdCount - 1 do + span.[i] <- vOne + + for i = simdCount * simdSize to size - 1 do + data.[i] <- 'T.One + + Matrix(rows, cols, data) + + static member inline getRow<'T + when 'T :> Numerics.INumber<'T> + and 'T : struct + and 'T : (new : unit -> 'T) + and 'T :> ValueType> + (i: int) + (m: Matrix<'T>) : Vector<'T> = + + if i < 0 || i >= m.NumRows then + invalidArg "i" $"Row index out of bounds: {i}" + + let rowSpan = m.Data.AsSpan(i * m.NumCols, m.NumCols) + let result = Array.zeroCreate<'T> m.NumCols + rowSpan.CopyTo(result.AsSpan()) + result + + static member inline getRows (m: Matrix<'T>) : Vector<'T>[] = + Array.init m.NumRows (fun i -> Matrix.getRow i m) + + + static member inline getCol<'T + when 'T :> Numerics.INumber<'T> + and 'T : struct + and 'T : (new : unit -> 'T) + and 'T :> ValueType> + (j: int) + (m: Matrix<'T>) : Vector<'T> = + + if j < 0 || j >= m.NumCols then + invalidArg "j" $"Column index out of bounds: {j}" + + let result = Array.zeroCreate<'T> m.NumRows + let mutable offset = j + for i = 0 to m.NumRows - 1 do + result.[i] <- m.Data.[offset] + offset <- offset + m.NumCols + + result + + static member inline getCols<'T + when 'T :> Numerics.INumber<'T> + and 'T : struct + and 'T : (new : unit -> 'T) + and 'T :> ValueType> + (m: Matrix<'T>) : Vector<'T>[] = + + Array.init m.NumCols (fun j -> + let col = Array.zeroCreate<'T> m.NumRows + let mutable offset = j + for i = 0 to m.NumRows - 1 do + col.[i] <- m.Data.[offset] + offset <- offset + m.NumCols + col + ) + + + /// + /// Sets row of this matrix to the contents of . + /// The length of must match the number of columns in this matrix. + /// + /// The zero-based row index to set. + /// An array of new values for the row, of length equal to . + /// Thrown if is out of range. + /// Thrown if has incorrect length. + member this.SetRow(i: int, rowData: 'T[]) = + if i < 0 || i >= rows then + invalidArg (nameof i) "Row index out of range." + if rowData.Length <> cols then + invalidArg (nameof rowData) $"rowData must have length = {cols}." + + let offset = i * cols + Array.blit rowData 0 data offset cols + + + + + + // static member MatrixMultiply + + // (a: Matrix<'T>, b: Matrix<'T>, ?blockSize: int) : Matrix<'T> + // when 'T : struct + // and 'T : (new : unit -> 'T) + // and 'T :> INumber<'T> + // and 'T :> ValueType = + + // if a.Cols <> b.Rows then + // invalidArg "b" "Matrix dimensions must agree: a.Cols must equal b.Rows." + + // let blockSize = defaultArg blockSize 32 + + // let m = a.Rows + // let n = b.Cols + // let k = a.Cols + + // let result = Array.zeroCreate<'T> (m * n) + // let aData = a.Data + // let bData = b.Data + // let rData = result + + // let vSize = Vector<'T>.Count + + // // Blocked GEMM + // for i0 in 0 .. blockSize .. m - 1 do + // let iMax = min (i0 + blockSize) m + // for j0 in 0 .. blockSize .. n - 1 do + // let jMax = min (j0 + blockSize) n + // for k0 in 0 .. blockSize .. k - 1 do + // let kMax = min (k0 + blockSize) k + + // // Iterate over block + // for i in i0 .. iMax - 1 do + // for j in j0 .. jMax - 1 do + // let mutable sum = 'T.Zero + // let mutable kk = k0 + + // // SIMD accumulation + // while kk <= kMax - vSize do + // let aVec = Vector<'T>(aData, i * k + kk) + // let bVec = Vector<'T>([| for offset in 0 .. vSize - 1 -> bData.[(kk + offset) * n + j] |]) + // sum <- sum + Vector.Dot(aVec, bVec) + // kk <- kk + vSize + + // // Scalar tail + // while kk < kMax do + // sum <- sum + aData.[i * k + kk] * bData.[kk * n + j] + // kk <- kk + 1 + + // rData.[i * n + j] <- rData.[i * n + j] + sum diff --git a/src/FSharp.Stats/AlgTypes/MatrixExt.fs b/src/FSharp.Stats/AlgTypes/MatrixExt.fs new file mode 100644 index 000000000..bf0acce03 --- /dev/null +++ b/src/FSharp.Stats/AlgTypes/MatrixExt.fs @@ -0,0 +1,108 @@ +namespace FSharp.Stats + +open System +open System.Runtime.InteropServices + + +[] +module Matrix = + +// /// Indexed fold over a matrix +// let inline foldi<'T when 'T :> Numerics.INumber<'T>> f (state: 'T) (m: Matrix<'T>) : 'T = +// let mutable acc = state +// for i = 0 to m.NumRows - 1 do +// for j = 0 to m.NumCols - 1 do +// acc <- f i j acc m.[i, j] +// acc + + + /// + /// Creates and returns a new with the same dimensions + /// as this matrix and a copy of the underlying data. + /// + let inline copy (m:Matrix<'T>) : Matrix<'T> = + // Make a copy of the data array + let newData = Array.copy m.Data + Matrix<'T>(m.NumRows, m.NumCols, newData) + + + /// Splits a matrix along row direction according to given indices. Returns (matrix including rows according to indices, rest) + /// + /// + /// + /// + /// + /// + /// + /// + let splitRows (indices:int[]) (m:Matrix<'T>) = + + let nRows,nCols = m.NumRows,m.NumCols + //let nm = Matrix.Generic.zero (nRows-indices.Length) nCols + //let nmi = Matrix.Generic.zero indices.Length nCols + let nm = Matrix.zeroCreate (nRows-indices.Length) nCols + let nmi = Matrix.zeroCreate indices.Length nCols + indices |> Array.sortInPlace + let rec loop nRowI nRowIi rowI = + match rowI with + | i as rowI when rowI < 0 -> nmi,nm + | i as rowI when nRowIi >= 0 && rowI = indices.[nRowIi] -> + for colI=0 to nCols-1 do + nmi.[nRowIi,colI] <- m.[rowI,colI] + loop (nRowI) (nRowIi-1) (rowI-1) + | _ -> //i as rowI when rowI <> indices.[ii] -> + for colI=0 to nCols-1 do + nm.[nRowI,colI] <- m.[rowI,colI] + loop (nRowI-1) (nRowIi) (rowI-1) + + loop (nRows-1-indices.Length) (indices.Length-1) (nRows-1) + + /// Splits a matrix along column direction according to given indices. Returns (matrix including cols according to indices, rest) + /// + /// + /// + /// + /// + /// + /// + /// + let splitCols (indices:int[]) (m:Matrix<_>) = + let nRows,nCols = m.NumRows,m.NumCols + //let nm = Matrix.Generic.zero nRows (nCols-indices.Length) + //let nmi = Matrix.Generic.zero nRows indices.Length + let nm = Matrix.zeroCreate nRows (nCols-indices.Length) + let nmi = Matrix.zeroCreate nRows indices.Length + indices |> Array.sortInPlace + let rec loop nColI nColIi colI = + match colI with + | i as colI when colI < 0 -> nmi,nm + | i as colI when nColIi >= 0 && colI = indices.[nColIi] -> + for rowI=0 to nRows-1 do + nmi.[rowI,nColIi] <- m.[rowI,colI] + loop (nColI) (nColIi-1) (colI-1) + | _ -> //i as rowI when rowI <> indices.[ii] -> + for rowI=0 to nRows-1 do + nm.[rowI,nColI] <- m.[rowI,colI] + loop (nColI-1) (nColIi) (colI-1) + + loop (nCols-1-indices.Length) (indices.Length-1) (nCols-1) + + /// + /// Creates a new matrix by permuting the rows of matrix according + /// to the permutation . That is, row i of the result is row + /// P(i) of . + /// + /// A permutation function that maps row indices. Should be valid + /// An r x c matrix whose rows will be reordered. + /// for all i in [0..r-1]. + /// + /// A new matrix of the same dimensions r x c, with rows permuted by . + /// + let permuteRowsBy (P: Permutation) (M: Matrix<'T>) : Matrix<'T> = + let r, c = M.NumRows, M.NumCols + let newData = Array.zeroCreate<'T> (r * c) + for i = 0 to r - 1 do + let srcRow = P i + // Copy row srcRow from M into row i of the new matrix + Array.blit M.Data (srcRow * c) newData (i * c) c + Matrix<'T>(r, c, newData) \ No newline at end of file diff --git a/src/FSharp.Stats/AlgTypes/SIMDUtils.fs b/src/FSharp.Stats/AlgTypes/SIMDUtils.fs new file mode 100644 index 000000000..54aabfeec --- /dev/null +++ b/src/FSharp.Stats/AlgTypes/SIMDUtils.fs @@ -0,0 +1,404 @@ +namespace FSharp.Stats.Acceleration + +open System +open System.Runtime.InteropServices +open System.Runtime.CompilerServices + + +/// +/// A utility class for performing SIMD (Single Instruction, Multiple Data) operations on arrays. +/// +type SIMDUtils() = + + /// + /// Applies a safe element-wise unary operation on an array using SIMD for performance. + /// + /// The numeric type of the array elements. + /// A function that performs the SIMD operation on a vector. + /// A fallback function for scalar operations. + /// The input array. + /// An array with the operation applied to each element. + static member inline map<'T when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T :> ValueType> + (fv:Numerics.Vector<'T> -> Numerics.Vector<'T>) + (f: 'T -> 'T) + (v: 'T[]) : 'T[] = + + let length = v.Length + let slotSize = Numerics.Vector<'T>.Count + let slotCount = length / slotSize + let ceiling = slotSize * slotCount + + let results = Array.zeroCreate<'T> length + let rsSpan = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(results.AsSpan()) + let vSpan = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(v.AsSpan()) + + for i = 0 to slotCount - 1 do + rsSpan.[i] <- fv vSpan[i] + + for i = ceiling to length - 1 do + results.[i] <- f v.[i] + + results + + /// + /// Applies an element-wise binary operation on two arrays using SIMD for performance. + /// + /// The numeric type of the array elements. + /// A function that performs the SIMD operation on two vectors. + /// A fallback function for scalar operations. + /// The first input array. + /// The second input array. + /// An array with the operation applied to each pair of elements. + static member inline map2Unchecked<'T when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T :> ValueType> + (fv:Numerics.Vector<'T> -> Numerics.Vector<'T> -> Numerics.Vector<'T>) + (f:'T -> 'T -> 'T) + (v1: 'T[]) + (v2: 'T[]) = + + let length = v1.Length + let slotSize= Numerics.Vector<'T>.Count + let slotCount = length / slotSize + let ceiling = slotSize * slotCount + + let results = Array.zeroCreate<'T> length + let rsSpan = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(results.AsSpan()) + let v1Span = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(v1.AsSpan()) + let v2Span = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(v2.AsSpan()) + + for i=0 to slotCount - 1 do + rsSpan.[i] <- fv v1Span[i] v2Span[i] + + for i=ceiling to v1.Length - 1 do + results.[i] <- f v1.[i] v2[i] + + results + + /// + /// Reduces an array to a single value using a binary operation, with SIMD optimization. + /// + /// The numeric type of the array elements. + /// A function that performs the SIMD reduction on two vectors. + /// A fallback function for scalar reduction. + /// The initial value for the reduction. + /// The input array. + /// The result of the reduction. + static member inline fold<'T when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T :> ValueType> + (fv:Numerics.Vector<'T> -> Numerics.Vector<'T> -> Numerics.Vector<'T>) + (f: 'T -> 'T -> 'T) + (zero: 'T) + (v: 'T[]) : 'T = + + let length = v.Length + let slotSize = Numerics.Vector<'T>.Count + let slotCount = length / slotSize + let ceiling = slotSize * slotCount + + let vSpan: Span> = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(v.AsSpan()) + + let mutable accVec = Numerics.Vector<'T>(zero) + + for i = 0 to slotCount - 1 do + accVec <- fv accVec vSpan[i] + + let mutable acc = accVec.[0] + for i = 1 to slotSize - 1 do + acc <- f acc accVec.[i] + + for i = ceiling to length - 1 do + acc <- f acc v[i] + + acc + + /// + /// Applies an element-wise binary operation between an array and a scalar using SIMD for performance. + /// + /// The numeric type of the array elements. + /// A function that performs the SIMD operation on a vector and a scalar vector. + /// A fallback function for scalar operations. + /// The input array. + /// The scalar value. + /// An array with the operation applied to each element and the scalar. + static member inline mapScalar<'T when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T :> ValueType> + (fv:Numerics.Vector<'T> -> Numerics.Vector<'T> -> Numerics.Vector<'T> ) + (f:'T -> 'T -> 'T) + (v1:'T[]) + (scalar:'T) : 'T[] = + + let length = v1.Length + let slotSize= Numerics.Vector<'T>.Count + let slotCount = length / slotSize + let ceiling = slotSize * slotCount + + let results = Array.zeroCreate<'T> length + let rsSpan = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(results.AsSpan()) + let v1Span = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(v1.AsSpan()) + let scalarVec = Numerics.Vector(scalar) + + for i=0 to slotCount - 1 do + rsSpan.[i] <- fv v1Span[i] scalarVec + + for i=ceiling to v1.Length - 1 do + results.[i] <- f v1.[i] scalar + + results + + + +type SIMDRangeUtils = + + /// In-place transformation of v[startIndex..(startIndex + count - 1)] + /// using a SIMD operation (fv) for chunked parts and a scalar function (f) for leftovers. + static member inline mapRangeInPlace<'T when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T :> ValueType> + (fv : Numerics.Vector<'T> -> Numerics.Vector<'T>) + (f : 'T -> 'T) + (startIndex : int) + (count : int) + (v : 'T[]) : unit = + + // 1) Validate parameters + if startIndex < 0 || count < 0 || (startIndex + count) > v.Length then + invalidArg (nameof count) "Invalid start index or count." + + // 2) Early exit if there's nothing to do + if count = 0 then + // nothing to do + () + + else + // 3) Compute how many full Vector<'T>.Count chunks we can process + let simdSize = Numerics.Vector<'T>.Count + let simdCount = count / simdSize + let tailStart = simdCount * simdSize + + // 4) Slice the relevant portion of v + let span = v.AsSpan(startIndex, count) + // 5) Interpret that span as a span of Vector<'T> + let vecSpan = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(span) + + // 6) Apply fv to each SIMD chunk + for i in 0 .. simdCount - 1 do + vecSpan.[i] <- fv vecSpan.[i] + + // 7) Handle leftover elements with f + for i in tailStart .. count - 1 do + let idx = startIndex + i + v.[idx] <- f v.[idx] + + + + /// In-place combination of two arrays (dst, src) over 'count' elements, + /// starting from 'dstStartIndex' and 'srcStartIndex' respectively. + /// Uses 'fv' for chunked SIMD processing and 'f' for leftover scalar elements. + static member inline map2RangeInPlace<'T when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T :> ValueType> + (fv : Numerics.Vector<'T> -> Numerics.Vector<'T> -> Numerics.Vector<'T>) + (f : 'T -> 'T -> 'T) + (dstStartIndex : int) + (srcStartIndex : int) + (count : int) + (dst : 'T[]) + (src : 'T[]) : unit = + + // 1) Validate parameters + if dstStartIndex < 0 || srcStartIndex < 0 || count < 0 then + invalidArg (nameof count) "Start indices and count must be non-negative." + if dstStartIndex + count > dst.Length then + invalidArg (nameof dstStartIndex) "Destination range out of bounds." + if srcStartIndex + count > src.Length then + invalidArg (nameof srcStartIndex) "Source range out of bounds." + + // 2) Early exit if there's nothing to do + if count = 0 then + () + else + // 3) How many full 'Vector<'T>' chunks fit into 'count'? + let simdSize = Numerics.Vector<'T>.Count + let simdCount = count / simdSize + let tailStart = simdCount * simdSize + + // 4) Create Spans for the subranges + let dstSpan = dst.AsSpan(dstStartIndex, count) + let srcSpan = src.AsSpan(srcStartIndex, count) + + // 5) Cast to Span> for chunked SIMD ops + let dstVecSpan = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(dstSpan) + let srcVecSpan = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(srcSpan) + + // 6) Apply 'fv' to each pair of SIMD chunks + for i = 0 to simdCount - 1 do + dstVecSpan.[i] <- fv dstVecSpan.[i] srcVecSpan.[i] + + // 7) Handle leftover scalar elements + for i = tailStart to count - 1 do + let dstIdx = dstStartIndex + i + let srcIdx = srcStartIndex + i + dst.[dstIdx] <- f dst.[dstIdx] src.[srcIdx] + + + /// Dot product of arr1[off1..off1+count-1] and arr2[off2..off2+count-1]. + /// Uses SIMD if available; otherwise a naive loop. + static member inline dotRange<'T when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T :> ValueType> + (arr1: 'T[]) (off1: int) + (arr2: 'T[]) (off2: int) + (count: int) = + + if Numerics.Vector.IsHardwareAccelerated && count >= Numerics.Vector<'T>.Count then + let simdSize = Numerics.Vector<'T>.Count + let simdCount = count / simdSize + let tailStart = simdCount * simdSize + + let mutable sumVec = Numerics.Vector<'T>.Zero + + let span1 = arr1.AsSpan(off1, count) + let span2 = arr2.AsSpan(off2, count) + + let vec1 = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(span1) + let vec2 = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(span2) + + for i = 0 to simdCount - 1 do + sumVec <- sumVec + (vec1.[i] * vec2.[i]) + + // Reduce the SIMD lanes + let mutable simdSum = LanguagePrimitives.GenericZero<'T> + for lane = 0 to simdSize - 1 do + simdSum <- simdSum + sumVec.[lane] + + // Handle leftover tail + let mutable tailSum = LanguagePrimitives.GenericZero<'T> + for i = tailStart to count - 1 do + tailSum <- tailSum + arr1.[off1 + i] * arr2.[off2 + i] + + simdSum + tailSum + else + // Fallback naive loop + let mutable acc = LanguagePrimitives.GenericZero<'T> + for i = 0 to count - 1 do + acc <- acc + arr1.[off1 + i] * arr2.[off2 + i] + acc + + +// + +// // +// static member map2Unchecked<'T when 'T :> Numerics.INumber<'T> +// and 'T : (new: unit -> 'T) +// and 'T : struct +// and 'T :> ValueType> +// (fv:Numerics.Vector<'T> -> Numerics.Vector<'T> -> Numerics.Vector<'T>) +// (f:'T -> 'T -> 'T) +// (v1: 'T[]) +// (v2: 'T[]) : 'T[] = + + +// // Gets the total number of elements of this vector +// let length = v1.Length +// // +// let slotSize= Numerics.Vector<'T>.Count +// // Number of slots (rasterized vectors) +// let slotCount = length / slotSize +// // Index at which the non rasterd remain starts +// let ceiling = slotSize * slotCount + +// // Allocate the result array +// let results = Array.zeroCreate<'T> length +// let rsSpan = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(results.AsSpan()) +// let v1Span = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(v1.AsSpan()) +// let v2Span = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(v2.AsSpan()) + +// // Perform SIMD addition for chunks +// for i=0 to slotCount - 1 do +// rsSpan.[i] <- fv v1Span[i] v2Span[i] + +// // Handle the remaining elements +// for i=ceiling to v1.Length - 1 do +// results.[i] <- f v1.[i] v2[i] + +// results + +// type SIMDMatrixUtils() = + +// static member map2<'T when 'T :> Numerics.INumber<'T> +// and 'T : (new: unit -> 'T) +// and 'T : struct +// and 'T :> ValueType> +// (fVec: Numerics.Vector<'T> -> Numerics.Vector<'T> -> Numerics.Vector<'T>) +// (fScalar: 'T -> 'T -> 'T) +// (a: Matrix<'T>) +// (b: Matrix<'T>) +// : Matrix<'T> = + +// if a.Rows <> b.Rows || a.Cols <> b.Cols then +// invalidArg "b" "Matrix dimensions must match" + +// let len = a.Data.Length +// let result = Array.zeroCreate<'T> len + +// let simdSize = Numerics.Vector<'T>.Count +// let simdCount = len / simdSize +// let tailStart = simdCount * simdSize + +// // Cast arrays to Vector<'T> spans +// let aVec = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(a.Data.AsSpan()) +// let bVec = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(b.Data.AsSpan()) +// let rVec = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(result.AsSpan()) + +// for i = 0 to simdCount - 1 do +// rVec.[i] <- fVec aVec.[i] bVec.[i] + +// for i = tailStart to len - 1 do +// result.[i] <- fScalar a.Data.[i] b.Data.[i] + +// Matrix(a.Rows, a.Cols, result) + + +// static member mapScalar<'T when 'T :> Numerics.INumber<'T> +// and 'T : (new: unit -> 'T) +// and 'T : struct +// and 'T :> ValueType> +// (fv: Numerics.Vector<'T> -> Numerics.Vector<'T> -> Numerics.Vector<'T>) +// (f: 'T -> 'T -> 'T) +// (matrix: Matrix<'T>) +// (scalar: 'T) +// : Matrix<'T> = + +// let length = matrix.Data.Length +// let result = Array.zeroCreate<'T> length + +// let slotSize = Numerics.Vector<'T>.Count +// let slotCount = length / slotSize +// let ceiling = slotCount * slotSize + +// let scalarVec = Numerics.Vector<'T>(scalar) + +// let mSpan = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(matrix.Data.AsSpan()) +// let rSpan = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(result.AsSpan()) + +// // SIMD chunk-wise operation +// for i = 0 to slotCount - 1 do +// rSpan.[i] <- fv mSpan.[i] scalarVec + +// // Scalar fallback for remainder +// for i = ceiling to length - 1 do +// result.[i] <- f matrix.Data.[i] scalar + +// Matrix(matrix.Rows, matrix.Cols, result) diff --git a/src/FSharp.Stats/AlgTypes/Vector.fs b/src/FSharp.Stats/AlgTypes/Vector.fs new file mode 100644 index 000000000..eba35ac1d --- /dev/null +++ b/src/FSharp.Stats/AlgTypes/Vector.fs @@ -0,0 +1,253 @@ +namespace FSharp.Stats + +open System +open System.Runtime.InteropServices + +/// Vector as a Array type alias +type Vector<'T when 'T :> Numerics.INumber<'T>> = 'T [] + +type Vector = + + /// Adds two vectors element-wise. + /// The first vector. + /// The second vector. + /// A new vector containing the element-wise sum of the two input vectors. + /// Thrown when the vectors have different lengths. + static member inline add<'T when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T :> ValueType> (v1 : Vector<'T>) (v2 : Vector<'T>) : Vector<'T> = + + if v1.Length <> v2.Length then + invalidArg "" "Cannot add two vectors of different dimensions." + + if Numerics.Vector.IsHardwareAccelerated then + Acceleration.SIMDUtils.map2Unchecked (+) (+) v1 v2 + else + Array.map2 (+) v1 v2 + + + /// Subtracts the second vector from the first vector element-wise. + /// The first vector. + /// The second vector. + /// A new vector containing the element-wise difference of the two input vectors. + /// Thrown when the vectors have different lengths. + static member inline subtract<'T when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T :> ValueType> (v1 : Vector<'T>) (v2 : Vector<'T>) : Vector<'T> = + + if v1.Length <> v2.Length then + invalidArg "" "Cannot subtract two vectors of different dimensions." + + if Numerics.Vector.IsHardwareAccelerated then + Acceleration.SIMDUtils.map2Unchecked (-) (-) v1 v2 + else + Array.map2 (-) v1 v2 + + + /// Multiplies two vectors element-wise. + /// The first vector. + /// The second vector. + /// A new vector containing the element-wise product of the two input vectors. + /// Thrown when the vectors have different lengths. + static member inline multiply<'T when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T :> ValueType> (v1 : Vector<'T>) (v2 : Vector<'T>) : Vector<'T> = + + if v1.Length <> v2.Length then + invalidArg "" "Cannot multiply two vectors of different dimensions." + + if Numerics.Vector.IsHardwareAccelerated then + Acceleration.SIMDUtils.map2Unchecked ( * ) ( * ) v1 v2 + else + Array.map2 ( * ) v1 v2 + + + /// Divides the first vector by the second vector element-wise. + /// The first vector. + /// The second vector. + /// A new vector containing the element-wise division of the two input vectors. + /// Thrown when the vectors have different lengths. + static member inline divide<'T when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T :> ValueType> (v1 : Vector<'T>) (v2 : Vector<'T>) : Vector<'T> = + if v1.Length <> v2.Length then + invalidArg "" "Cannot divide two vectors of different dimensions." + + if Numerics.Vector.IsHardwareAccelerated then + Acceleration.SIMDUtils.map2Unchecked ( / ) ( / ) v1 v2 + else + Array.map2 ( / ) v1 v2 + + + /// Adds a scalar to each element of the vector. + /// The vector. + /// The scalar value to add. + /// A new vector with the scalar added to each element. + static member inline addScalar<'T when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T :> ValueType> (v:Vector<'T>) (scalar:'T) : Vector<'T> = + + if Numerics.Vector.IsHardwareAccelerated then + Acceleration.SIMDUtils.mapScalar (+) (+) v scalar + else + Array.map (fun x -> x + scalar) v + + + /// Subtracts a scalar from each element of the vector. + /// The vector. + /// The scalar value to subtract. + /// A new vector with the scalar subtracted from each element. + static member inline subtractScalar<'T when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T :> ValueType> (v:Vector<'T>) (scalar:'T) : Vector<'T> = + if Numerics.Vector.IsHardwareAccelerated then + Acceleration.SIMDUtils.mapScalar (-) (-) v scalar + else + Array.map (fun x -> x - scalar) v + + + /// Multiplies each element of the vector by a scalar. + /// The vector. + /// The scalar value to multiply by. + /// A new vector with each element multiplied by the scalar. + static member inline multiplyScalar<'T when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T :> ValueType> (v:Vector<'T>) (scalar:'T) : Vector<'T> = + + if Numerics.Vector.IsHardwareAccelerated then + Acceleration.SIMDUtils.mapScalar ( * ) ( * ) v scalar + else + Array.map (fun x -> x * scalar) v + + + /// Divides each element of the vector by a scalar. + /// The vector. + /// The scalar value to divide by. + /// A new vector with each element divided by the scalar. + static member inline divideScalar<'T when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T :> ValueType> (v:Vector<'T>) (scalar:'T) : Vector<'T> = + + if Numerics.Vector.IsHardwareAccelerated then + Acceleration.SIMDUtils.mapScalar ( / ) ( / ) v scalar + else + Array.map (fun x -> x / scalar) v + + /// Computes the sum of all elements in the vector. + /// The vector. + /// The sum of all elements in the vector. + static member inline sum<'T when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T :> ValueType> + (v:Vector<'T>) : 'T = + let zero = LanguagePrimitives.GenericZero<'T> + if Numerics.Vector.IsHardwareAccelerated then + Acceleration.SIMDUtils.fold (+) (+) zero v + else + Array.sum v + + /// Computes the product of all elements in the vector. + /// The vector. + /// The product of all elements in the vector. + static member inline product<'T when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T :> ValueType> + (v:Vector<'T>) : 'T = + let one = LanguagePrimitives.GenericOne<'T> + if Numerics.Vector.IsHardwareAccelerated then + Acceleration.SIMDUtils.fold (*) (*) one v + else + Array.fold ( * ) one v + + + /// Computes the mean of the elements in the vector. + /// The vector. + /// The mean of the elements in the vector. + /// Thrown when the vector is empty. + static member inline mean<'T when 'T :> Numerics.INumber<'T> + and 'T : (static member DivideByInt : 'T * int -> 'T) + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T :> ValueType> + (v: Vector<'T>) : 'T = + if v.Length = 0 then invalidArg "v" "Cannot compute mean of empty vector." + let sum = Vector.sum v + LanguagePrimitives.DivideByInt<'T> sum v.Length + + /// Computes the dot product of two vectors. + /// The first vector. + /// The second vector. + /// The dot product of the two vectors. + /// Thrown when the vectors have different lengths. + static member inline dotProduct<'T when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T :> ValueType> (v1 : Vector<'T>) (v2 : Vector<'T>) : 'T = + + if v1.Length <> v2.Length then + invalidArg "v2" "Arrays must have the same length." + if Numerics.Vector.IsHardwareAccelerated then + let length = v1.Length + let slotSize = Numerics.Vector<'T>.Count + let slotCount = length / slotSize + let ceiling = slotSize * slotCount + + let mutable result = Numerics.Vector<'T>.Zero + let v1Span = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(v1.AsSpan()) + let v2Span = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(v2.AsSpan()) + let mutable scalarResult = LanguagePrimitives.GenericZero<'T> + + for i = 0 to slotCount - 1 do + result <- Numerics.Vector.Add(result, Numerics.Vector.Multiply(v1Span.[i], v2Span.[i])) + scalarResult <- Numerics.Vector.Sum result + + for i = ceiling to v1.Length - 1 do + scalarResult <- scalarResult + (v1.[i] * v2.[i]) + + scalarResult + else + Array.fold2 (fun acc x y -> acc + (x * y)) LanguagePrimitives.GenericZero v1 v2 + + + /// Computes the Euclidean norm (magnitude) of the vector. + /// The vector. + /// The Euclidean norm of the vector. + static member inline norm<'T when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T :> ValueType + and 'T :> Numerics.IRootFunctions<'T>> + (v:Vector<'T>) : 'T = + + let sumSquares = Vector.dotProduct v v + 'T.Sqrt sumSquares + + static member inline min<'T when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T : comparison + and 'T :> ValueType> + (v:Vector<'T>) : 'T = + if v.Length = 0 then invalidArg "v" "Cannot compute min of empty vector." + Acceleration.SIMDUtils.fold (fun a b -> Numerics.Vector.Min(a, b)) min v.[0] v + + static member inline max<'T when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T : comparison + and 'T :> ValueType> + (v:Vector<'T>) : 'T = + if v.Length = 0 then invalidArg "v" "Cannot compute min of empty vector." + Acceleration.SIMDUtils.fold (fun a b -> Numerics.Vector.Max(a, b)) min v.[0] v + + diff --git a/src/FSharp.Stats/AlgTypes/VectorExt.fs b/src/FSharp.Stats/AlgTypes/VectorExt.fs new file mode 100644 index 000000000..3badfca7d --- /dev/null +++ b/src/FSharp.Stats/AlgTypes/VectorExt.fs @@ -0,0 +1,182 @@ +namespace FSharp.Stats + +open System +open System.Runtime.InteropServices + +[] +module Vector = + + let inline zeroCreate<'T when 'T :> Numerics.INumber<'T>> count : Vector<'T> = + Array.zeroCreate<'T> count + + /// Indexed fold over a vector + let inline foldi<'T when 'T :> Numerics.INumber<'T>> f (state: 'T) (v: Vector<'T>) : 'T = + let mutable acc = state + for i = 0 to v.Length - 1 do + acc <- f i acc v.[i] + acc + + /// Indexed map over a vector + let inline mapi<'T when 'T :> Numerics.INumber<'T>> (f: int -> 'T -> 'T) (v: Vector<'T>) : Vector<'T> = + Array.mapi f v + + /// Filter vector elements by predicate + let inline filter<'T when 'T :> Numerics.INumber<'T>> (predicate: 'T -> bool) (v: Vector<'T>) : Vector<'T> = + Array.filter predicate v + + /// Initialize vector by index-based generator + let inline init<'T when 'T :> Numerics.INumber<'T>> (n: int) (f: int -> 'T) : Vector<'T> = + Array.init n f + + /// Extract a slice from a vector + let inline slice<'T when 'T :> Numerics.INumber<'T>> (start: int) (length: int) (v: Vector<'T>) : Vector<'T> = + Array.sub v start length + + /// Find index of maximum value + let inline argmax<'T when 'T :> Numerics.INumber<'T> and 'T : comparison> (v: Vector<'T>) : int = + let mutable maxIdx = 0 + let mutable maxVal = v.[0] + for i = 1 to v.Length - 1 do + if v.[i] > maxVal then + maxVal <- v.[i] + maxIdx <- i + maxIdx + + /// Find index of minimum value + let inline argmin<'T when 'T :> Numerics.INumber<'T> and 'T : comparison> (v: Vector<'T>) : int = + let mutable minIdx = 0 + let mutable minVal = v.[0] + for i = 1 to v.Length - 1 do + if v.[i] < minVal then + minVal <- v.[i] + minIdx <- i + minIdx + + /// Pad vector to a given length with a constant value + let inline padRight<'T when 'T :> Numerics.INumber<'T>> (length: int) (value: 'T) (v: Vector<'T>) : Vector<'T> = + if v.Length >= length then v + else + Array.init length (fun i -> if i < v.Length then v.[i] else value) + + /// Zip two vectors into (index, left, right) + let inline zip<'T when 'T :> Numerics.INumber<'T>> (v1: Vector<'T>) (v2: Vector<'T>) : (int * 'T * 'T)[] = + Array.init (min v1.Length v2.Length) (fun i -> i, v1.[i], v2.[i]) + + + + /// Find index of minimum value using projection + let inline argminBy<'T, 'U + when 'T :> Numerics.INumber<'T> and 'U : comparison> + (f: 'T -> 'U) (v: Vector<'T>) : int = + let mutable minIdx = 0 + let mutable minVal = f v.[0] + for i = 1 to v.Length - 1 do + let candidate = f v.[i] + if candidate < minVal then + minVal <- candidate + minIdx <- i + minIdx + + /// Find index of maximum value using projection + let inline argmaxBy<'T, 'U + when 'T :> Numerics.INumber<'T> and 'U : comparison> + (f: 'T -> 'U) (v: Vector<'T>) : int = + let mutable maxIdx = 0 + let mutable maxVal = f v.[0] + for i = 1 to v.Length - 1 do + let candidate = f v.[i] + if candidate > maxVal then + maxVal <- candidate + maxIdx <- i + maxIdx + + /// Try to find index of first matching element + let inline tryFindIndex<'T when 'T :> Numerics.INumber<'T>> (predicate: 'T -> bool) (v: Vector<'T>) : int option = + let mutable i = 0 + let mutable found = false + while i < v.Length && not found do + if predicate v.[i] then found <- true + else i <- i + 1 + if found then Some i else None + + /// Find index of first matching element or throw + let inline findIndex<'T when 'T :> Numerics.INumber<'T>> (predicate: 'T -> bool) (v: Vector<'T>) : int = + match tryFindIndex predicate v with + | Some i -> i + | None -> failwith "Element not found." + + /// Enumerate non-zero elements with index + let inline enumerateNonZero<'T when 'T :> Numerics.INumber<'T> and 'T : equality> (v: Vector<'T>) : (int * 'T)[] = + v + |> Array.mapi (fun i x -> i, x) + |> Array.filter (fun (_, x) -> x <> 'T.Zero) + + /// Split a vector into prefix and suffix at a given index + let inline split<'T when 'T :> Numerics.INumber<'T>> (index: int) (v: Vector<'T>) : Vector<'T> * Vector<'T> = + Array.sub v 0 index, Array.sub v index (v.Length - index) + + /// Chunk a vector into equally sized pieces (last may be shorter) + let inline chunk<'T when 'T :> Numerics.INumber<'T>> (chunkSize: int) (v: Vector<'T>) : Vector<'T>[] = + let len = v.Length + [| for i in 0 .. chunkSize .. len - 1 -> + let size = min chunkSize (len - i) + Array.sub v i size |] + + /// Sliding window over the vector + let inline windowed<'T when 'T :> Numerics.INumber<'T>> (windowSize: int) (v: Vector<'T>) : Vector<'T>[] = + if windowSize > v.Length then [||] + else + [| for i in 0 .. v.Length - windowSize -> + Array.sub v i windowSize |] + + + /// + /// Splits the vector `v` into two parts based on `indices`. + /// The elements at positions in `indices` end up in `nvi`, + /// all others go into `nv`. + /// + /// Zero-based positions to extract from `v`. + /// The full vector to split. + /// (nvi, nv): nvi contains the elements at `indices`, nv contains the rest. + let splitVector (indices: int[]) (v: Vector<'T>) = + + Array.sortInPlace indices + + let n = v.Length + let k = indices.Length + + let nvi = zeroCreate<'T> k + let nv = zeroCreate<'T> (n - k) + + let mutable iInd = 0 + let mutable iNvi = 0 + let mutable iNv = 0 + + for i = 0 to n - 1 do + // If we've not exhausted the `indices` array AND the current i matches indices.[iInd] + if iInd < k && i = indices.[iInd] then + nvi.[iNvi] <- v.[i] + iNvi <- iNvi + 1 + iInd <- iInd + 1 + else + nv.[iNv] <- v.[i] + iNv <- iNv + 1 + + nvi, nv + + /// + /// Creates a new vector that is the result of applying the permutation + /// to the vector . The element result.[i] becomes b.[P(i)]. + /// + /// A permutation function of type int -> int, + /// The original vector to be permuted. Must have length n. + /// typically created by Permutation.ofArray or Permutation.ofFreshArray. + /// + /// A new vector of the same length n, reordered according to . + /// + let permuteBy (P: Permutation) (b: Vector<'T>) : Vector<'T> = + let n = b.Length + let result = Array.zeroCreate<'T> n + for i = 0 to n - 1 do + result.[i] <- b.[P i] + result diff --git a/src/FSharp.Stats/AlgTypes/VectorOps.fs b/src/FSharp.Stats/AlgTypes/VectorOps.fs new file mode 100644 index 000000000..127395a1f --- /dev/null +++ b/src/FSharp.Stats/AlgTypes/VectorOps.fs @@ -0,0 +1,38 @@ +namespace FSharp.Stats + +open System + +// Fallback implementation container (Type class) +type VectorOps = + + + static member inline Plus (a: Vector<'T>, b: Vector<'T>) = Vector.add a b + static member inline Plus (a: Vector<'T>, b: 'T) = Vector.addScalar a b + static member inline Plus (a: 'T, b: Vector<'T>) = Vector.addScalar b a + + static member inline Minus (a: Vector<'T>, b: Vector<'T>) = Vector.subtract a b + static member inline Minus (a: Vector<'T>, b: 'T) = Vector.subtractScalar a b + + + static member inline Multiply (a: Vector<'T>, b: Vector<'T>) = Vector.multiply a b + static member inline Multiply (a: Vector<'T>, b: 'T) = Vector.multiplyScalar a b + static member inline Multiply (a: 'T, b: Vector<'T>) = Vector.multiplyScalar b a + + static member inline Divide (a: Vector<'T>, b: Vector<'T>) = Vector.divide a b + static member inline Divide (a: Vector<'T>, b: 'T) = Vector.divideScalar a b + + + +// Dispatcher types (Instance resolution) +type Plus = static member inline Invoke (a: ^A, b: ^B) = ((^A or ^B or VectorOps) : (static member Plus : ^A * ^B -> _)(a, b)) +type Minus = static member inline Invoke (a: ^A, b: ^B) = ((^A or ^B or VectorOps) : (static member Minus : ^A * ^B -> _)(a, b)) +type Multiply = static member inline Invoke (a: ^A, b: ^B) = ((^A or ^B or VectorOps) : (static member Multiply : ^A * ^B -> _)(a, b)) +type Divide = static member inline Invoke (a: ^A, b: ^B) = ((^A or ^B or VectorOps) : (static member Divide : ^A * ^B -> _)(a, b)) + +// Operators +[] +module VectorOpsSymbols = + let inline (.+) a b = Plus.Invoke(a, b) + let inline (.-) a b = Minus.Invoke(a, b) + let inline (.*) a b = Multiply.Invoke(a, b) + let inline (./) a b = Divide.Invoke(a, b) \ No newline at end of file From 01907941fa58fdbe0ca8dea4b1f821edcafcbf61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20M=C3=BChlhaus?= Date: Wed, 9 Apr 2025 13:43:55 +0200 Subject: [PATCH 006/121] Add basic Linerar Algebra (necessary for advanced statistics) --- src/FSharp.Stats/Algebra/LinearAlgebra.fs | 1060 ++++++++++++--------- 1 file changed, 602 insertions(+), 458 deletions(-) diff --git a/src/FSharp.Stats/Algebra/LinearAlgebra.fs b/src/FSharp.Stats/Algebra/LinearAlgebra.fs index 28e25f071..9dde6a896 100644 --- a/src/FSharp.Stats/Algebra/LinearAlgebra.fs +++ b/src/FSharp.Stats/Algebra/LinearAlgebra.fs @@ -1,487 +1,631 @@ -namespace FSharp.Stats.Algebra +namespace FSharp.Stats.Algebra + -open FSharp.Stats open System +open FSharp.Stats +type LinearAlgebra = + + /// Subtract `scaleVal * src[srcOffset..srcOffset+count-1]` from + /// `dst[dstOffset..dstOffset+count-1]` in place. + static member inline private subScaledRowInPlace + (scaleVal : 'T) + (dstOffset : int) + (srcOffset : int) + (count : int) + (dst : 'T[]) + (src : 'T[]) = + + let scaleVec = Numerics.Vector<'T>(scaleVal) -module LinearAlgebra = + // Vector-level callback: dstVec - (scaleVal * srcVec) + let fv (dstVec: Numerics.Vector<'T>) (srcVec: Numerics.Vector<'T>) = + dstVec - (scaleVec * srcVec) + + // Scalar fallback: d - (scaleVal * s) + let f (d: 'T) (s: 'T) = + d - (scaleVal * s) + Acceleration.SIMDRangeUtils.map2RangeInPlace fv f dstOffset srcOffset count dst src + + static member inline private householderTransform + (A: Matrix<'T>) (i: int) : Vector<'T> = + let n = A.NumRows + let v = Vector.zeroCreate<'T> n + let aCol = Matrix.getCol i A + let norm = Vector.norm aCol + v.[i] <- aCol.[i] + if aCol.[i] >= 'T.Zero then -norm else norm + for j = 0 to n - 1 do + if j <> i then + v.[j] <- aCol.[j] + v + /// QR decomposition using modified Gram-Schmidt + /// Returns Q and R such that A = QR + static member inline qrModifiedGramSchmidt<'T when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T :> ValueType + and 'T :> Numerics.IRootFunctions<'T>> + (A: Matrix<'T>) : Matrix<'T> * Matrix<'T> = + + let m, n = A.NumRows, A.NumCols + + let r = Matrix.zeroCreate n n + let qCols: Vector<'T>[] = Array.zeroCreate n + let aCols = Matrix.getCols A + + for j = 0 to n - 1 do + let v = Array.copy aCols.[j] + + for i = 0 to j - 1 do + let qi = qCols.[i] + let rij = Vector.dotProduct qi v + r.[i, j] <- rij + for k = 0 to m - 1 do + v.[k] <- v.[k] - rij * qi.[k] + + let norm = Vector.norm v + r.[j, j] <- norm + let qj = Vector.divideScalar v norm + qCols.[j] <- qj + + let qData = Array.zeroCreate (m * n) + for j = 0 to n - 1 do + for i = 0 to m - 1 do + qData.[i * n + j] <- qCols.[j].[i] + + Matrix(m, n, qData), r + + /// Back substitute to solve R * x = y + /// R is upper triangular + static member inline backSubstitute<'T when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T :> ValueType> + (r: Matrix<'T>) + (y: Vector<'T>) : Vector<'T> = + + let n = r.NumRows + + if r.NumCols <> n || y.Length <> n then + invalidArg "dimensions" "R must be square and match the length of y" + + let x = Array.zeroCreate<'T> n + + for i = n - 1 downto 0 do + let mutable sum = y.[i] + for j = i + 1 to n - 1 do + sum <- sum - r.[i, j] * x.[j] + x.[i] <- sum / r.[i, i] + + x + + + + + /// Solve A * x = b for x, where A is a square matrix (n×n) and b is a vector (length n). + static member inline solveLinearQR<'T when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T :> ValueType + and 'T :> Numerics.IRootFunctions<'T>> + (A: Matrix<'T>) + (b: Vector<'T>) : Vector<'T> = + + if A.NumRows <> b.Length then + invalidArg "b" "Vector length must match number of rows in matrix A" + + let Q, R = LinearAlgebra.qrModifiedGramSchmidt A + let Qt = Q.Transpose() + let y = Matrix.muliplyVector Qt b + LinearAlgebra.backSubstitute R y + + + + /// Solve K * X = B for X, where K is a triangular matrix (lower or upper). + /// K is square of size n×n; B is n×m. Returns an n×m result X. + static member inline solveTriangularLinearSystems + (K : Matrix<'T>) + (B : Matrix<'T>) + (isLower : bool) + : Matrix<'T> = + + /// Multiply `arr[offset..offset+count-1]` by `scaleVal` in place + let inline scaleRowInPlace + (scaleVal : 'T) + (offset : int) + (count : int) + (arr : 'T[]) = + + let scaleVec = Numerics.Vector<'T>(scaleVal) + + // Vector-level callback: chunk * scaleVal + let fv (chunk: Numerics.Vector<'T>) = + chunk * scaleVec + + // Scalar fallback: x * scaleVal + let f (x: 'T) = x * scaleVal + + // mapRangeInPlace fv f offset count arr + Acceleration.SIMDRangeUtils.mapRangeInPlace fv f offset count arr + + // Check shape consistency + let nK, mK = K.NumRows, K.NumCols + let nB, mB = B.NumRows, B.NumCols + if nK <> mK || nB <> nK then + invalidArg "Matrix" "K must be square and B must have matching row count for K" + + // Copy B into a new matrix X (the solution) + let X = Matrix<'T>(B.NumRows, B.NumCols, Array.copy B.Data) + + let n = nK // size of the NxN triangular matrix K + let m = mB // # of columns in B (and thus X) + + let Kdata = K.Data + let Xdata = X.Data + + // For row i, the contiguous slice in Xdata is [i*m .. i*m + m - 1] + // => offset = i*m, length = m + + if isLower then + // ------ Forward Substitution ------ + // for i in [0..n-1]: + // X[i,*] <- X[i,*] - Σ_{j=0..i-1} [K[i,j] * X[j,*]] + // then scale row i by 1/K[i,i] + for i = 0 to n - 1 do + let baseI = i * m + // Subtract scaled rows for j in [0..i-1] + for j = 0 to i - 1 do + let kij = Kdata.[i * n + j] // K[i,j] + if kij <> 'T.Zero then + let baseJ = j * m + // subScaledRowInPlace scaleVal dstOffset srcOffset count dst src + LinearAlgebra.subScaledRowInPlace + kij + baseI // row i offset in X + baseJ // row j offset in X + m // number of columns + Xdata + Xdata + //LinearAlgebra.subScaledRowInPlace + // Xdata + // baseI // row i offset in X + // Xdata + // baseJ // row j offset in X + // m // number of columns + // kij + + - type Factorization = matrix -> (matrix*matrix*matrix) + // Divide row i by the diagonal K[i,i] + let diag = Kdata.[i * n + i] + let invDiag = 'T.One / diag + // scaleRowInPlace scaleVal offset count arr + scaleRowInPlace + invDiag + baseI + m + Xdata + else + // ------ Backward Substitution ------ + // for i in [n-1..0]: + // X[i,*] <- X[i,*] - Σ_{j=i+1..n-1} [K[i,j] * X[j,*]] + // then scale row i by 1/K[i,i] + for i = n - 1 downto 0 do + let baseI = i * m + for j = i + 1 to n - 1 do + let kij = Kdata.[i * n + j] // K[i,j] + if kij <> 'T.Zero then + let baseJ = j * m + LinearAlgebra.subScaledRowInPlace + kij + baseI + baseJ + m + Xdata + Xdata + let diag = Kdata.[i * n + i] + let invDiag = 'T.One / diag + scaleRowInPlace + invDiag + baseI + m + Xdata + + X + + + + /// Solve K * x = v (triangular system) in-place, returning a copy of x. + /// K must be n×n, v must be length n. + /// isLower = true => forward substitution + /// isLower = false => backward substitution + static member inline solveTriangularLinearSystem + (K : Matrix<'T>) + (v : Vector<'T>) + (isLower : bool) + : Vector<'T> = + + let nK, mK = K.NumRows, K.NumCols + let nV = v.Length + if nK <> mK || nV <> nK then + invalidArg (nameof K) "K must be square, and v must match its dimension." + + let x = Array.copy v + let Kdata = K.Data // row-major flattened + + // Forward or backward substitution + if isLower then + // For i in [0..n-1]: + // x[i] <- ( x[i] - sum_{j=0..i-1}(K[i,j] * x[j]) ) / K[i,i] + for i = 0 to nK - 1 do + let mutable s = x.[i] + let rowOffset = i * nK + for j = 0 to i - 1 do + s <- s - (Kdata.[rowOffset + j] * x.[j]) + let diag = Kdata.[rowOffset + i] + x.[i] <- s / diag + else + // For i in [n-1..downto..0]: + // x[i] <- ( x[i] - sum_{j=i+1..n-1}(K[i,j] * x[j]) ) / K[i,i] + for i = nK - 1 downto 0 do + let mutable s = x.[i] + let rowOffset = i * nK + for j = i + 1 to nK - 1 do + s <- s - (Kdata.[rowOffset + j] * x.[j]) + let diag = Kdata.[rowOffset + i] + x.[i] <- s / diag + + x + + + + /// QR decomposition using Householder reflections + static member inline qrDecompose (A : Matrix<'T>) : (Matrix<'T> * Matrix<'T>) = + // former QR + let UpdateQ (Q : Matrix<'T>) (v : Vector<'T>) = + let nQ, mQ = Q.NumRows, Q.NumCols + let n = v.Length + let Qv = Vector.zeroCreate<'T> nQ + for i = 0 to nQ - 1 do + // offset in Q.Data for row i is i*mQ + let rowOffset = i * mQ + (mQ - n) + // Dot the subrange Q[i, mQ-n..mQ-1] with v[0..n-1] + Qv.[i] <- Acceleration.SIMDRangeUtils.dotRange Q.Data rowOffset v 0 n + + // Update each row i in the subrange of columns [mQ-n..mQ-1] + // Q[i, j] -= 2 * Qv[i] * v[j - (mQ - n)] + for i = 0 to nQ - 1 do + let alpha = Qv.[i] + Qv.[i] + // We want to do a row operation: Q[i, (mQ-n)..(mQ-1)] + // = Q[i, (mQ-n)..(mQ-1)] - alpha * v[0..n-1]. + let rowOffset = i * mQ + (mQ - n) + //LinearAlgebra.subScaledRowInPlace Q.Data rowOffset v 0 n alpha + LinearAlgebra.subScaledRowInPlace alpha rowOffset 0 n Q.Data v + + + + let (n, m) = (A.NumRows, A.NumCols) + + // Q starts as identity(n) + let Q = Matrix.identity n + let R = Matrix.copy A + + for i = 0 to (min n m) - 1 do + // 1) Compute Householder transform v for column i + let v = LinearAlgebra.householderTransform R i + // 2) Update Q + UpdateQ Q v + + Q, R + + /// Given A[m,n] and B[m] solves AX = B for X[n].
+ /// When m => n, have over constrained system, finds least squares solution for X.
+ /// When m < n, have under constrained system, finds least norm solution for X.
+ static member inline leastSquares + (A : Matrix<'T>) + (b: Vector<'T>) = + + let (m,n) = A.NumRows, A.NumCols + let Qm, R = LinearAlgebra.qrDecompose A + let Qtb = Qm.Transpose() * b + + // Is this an overdetermined or underdetermined system? + if m > n then + LinearAlgebra.solveTriangularLinearSystem R.[0..n-1,0..n-1] Qtb.[0..n-1] false + else + let s = LinearAlgebra.solveTriangularLinearSystem R.[0..m-1,0..m-1] Qtb false + Vector.init n (fun i -> if i < m then s.[i] else 'T.Zero) - //let private LinearAlgebraService = - // let tmp = new ServiceLocator.ServiceProvider([ProviderService.MKLProvider]) - // tmp.Start() - // tmp - let private MKLService = new ServiceLocator.ServiceProvider([ProviderService.LAPACKProvider;(*ProviderService.MKLProvider*)]) + /// + /// Computes the Cholesky factor L of a symmetric positive-definite matrix A, + /// returning L as a lower-triangular such that A = L * L^T. + /// Throws if A is not positive-definite (i.e., if any diagonal element ≤ 0). + /// + static member inline cholesky + (A : Matrix<'T>) + : Matrix<'T> = - let Service() = - match MKLService.Service() with - | Some svc -> svc - | None -> failwith "MKL service either not available, or not started" - - let private HaveService() = - MKLService.Available() - - let SolveTriangularLinearSystem (A:matrix) (b:vector) (isLower:bool) = - //if HaveService() then LinearAlgebraService.solveTriangularForVector A b isLower - // else LinearAlgebraManaged.SolveTriangularLinearSystem A b isLower - LinearAlgebraManaged.SolveTriangularLinearSystem A b isLower - - let SolveTriangularLinearSystems (A:matrix) (B:matrix) (isLower:bool) = - //if HaveService() then LinearAlgebraService.solveTriangularForMatrix A B isLower - // else LinearAlgebraManaged.SolveTriangularLinearSystems A B isLower - LinearAlgebraManaged.SolveTriangularLinearSystems A B isLower - - let SolveLinearSystem (A:matrix) (b:vector) = - //if HaveService() then LinearAlgebraService.preDivideByVector A b - // else LinearAlgebraManaged.SolveLinearSystem A b - LinearAlgebraManaged.SolveLinearSystem A b - - let SolveLinearSystems (A:matrix) (B:matrix) = - //if HaveService() then LinearAlgebraService.preDivideByMatrix A B - // else LinearAlgebraManaged.SolveLinearSystems A B - LinearAlgebraManaged.SolveLinearSystems A B - - /// Given A[n,m] and B[n] solve for x[m] such that Ax = B
This call may fail.
- /// - /// - /// - /// - /// - /// - /// - /// - let preDivideByVector A b = - //if HaveService() then LinearAlgebraService.preDivideByVector A b - // else LinearAlgebraManaged.SolveLinearSystem A b - LinearAlgebraManaged.SolveLinearSystem A b - + let n = A.NumRows + let m = A.NumCols + if n <> m then + invalidArg (nameof A) "Cholesky: matrix must be square." - /// Given A[n,m] and B[n,k] solve for X[m,k] such that AX = B
This call may fail.
- /// - /// - /// - /// - /// - /// - /// - /// - let preDivideByMatrix a b = - //if HaveService() then LinearAlgebraService.preDivideByMatrix a b - // else LinearAlgebraManaged.SolveLinearSystems a b - LinearAlgebraManaged.SolveLinearSystems a b - - ///Compoutes for an N-by-N real nonsymmetric matrix A, the - ///eigenvalue decomposition eigenvalues and right eigenvectors. - ///The right eigenvector v(j) of A satisfies - /// - /// A * v(j) = lambda(j) * v(j) - /// - ///where lambda(j) is its eigenvalue. - ///The computed eigenvectors are normalized to have Euclidean norm - ///equal to 1 and largest component real. Uses the LAPACK subroutine dgeev with arguments JOBVR = 'V' and JOBVL = 'N' - /// - /// Returns the real (first array) and imaginary (second array) parts of the eigenvalues and a matrix containing the corresponding eigenvectors - /// - /// - /// - /// - /// - /// - /// - let EVD m = - //if HaveService() then - //Service().dgeev_(m) - LinearAlgebraManaged.eigenvectors m - - /// Compute eigenvalues of a square real matrix.
Returns arrays containing the eigenvalues which may be complex.
This call may fail.
- /// - /// - /// - /// - /// - /// - /// - let EigenValues m = - //if HaveService() then let evals = LinearAlgebraService.eigenvalues m - // let n = evals.Length - // Vector.Generic.init n (fun i -> evals.[i]) - // else LinearAlgebraManaged.eigenvalues m - LinearAlgebraManaged.eigenvalues m - - /// Compute eigenvalues for a real symmetric matrix.
Returns array of real eigenvalues.
This call may fail.
- /// - /// - /// - /// - /// - /// - /// - let EigenValuesWhenSymmetric a = - //if HaveService() then let evals = LinearAlgebraService.symmetricEigenvalues a - // let n = evals.Length - // Vector.init n (fun i -> evals.[i]) - // else LinearAlgebraManaged.symmetricEigenvalues a - LinearAlgebraManaged.symmetricEigenvalues a - - /// Compute eigenvalues and eigenvectors for a real symmetric matrix.
Returns arrays of the values and vectors (both based on reals).
This call may fail.
- /// - /// - /// - /// - /// - /// - /// - let EigenSpectrumWhenSymmetric a = - if HaveService() then - Service().dsyevd_(a) - else - LinearAlgebraManaged.symmetricEigenvectors a + let dataA = A.Data + // We'll create an n×n zeroed matrix for L + let Ldata = Array.zeroCreate<'T> (n * n) + + // Helper function for indexing row-major arrays: + let inline idx r c = r * n + c + + for j = 0 to n - 1 do + // 1) Diagonal element L[j,j] + // L[j,j] = sqrt(A[j,j] - ∑(k=0..j-1) L[j,k]^2) + let mutable sumjj = dataA.[idx j j] + for k = 0 to j - 1 do + let ljk = Ldata.[idx j k] + sumjj <- sumjj - (ljk * ljk) + + // Check positivity + if sumjj <= 'T.Zero then + invalidArg "A" "Cholesky: matrix not positive-definite (diagonal <= 0)." + + let ljj = GenericMath.sqrt sumjj + Ldata.[idx j j] <- ljj + + // 2) Off-diagonal: L[i,j] for i=j+1..n-1 + // L[i,j] = (A[i,j] - ∑(k=0..j-1) L[i,k]*L[j,k]) / L[j,j] + for i = j + 1 to n - 1 do + let mutable sumij = dataA.[idx i j] + for k = 0 to j - 1 do + sumij <- sumij - (Ldata.[idx i k] * Ldata.[idx j k]) + Ldata.[idx i j] <- sumij / ljj + + Matrix<'T>(n, n, Ldata) + + + /// Given A[m,n] and b[m] solves AX = b for X[n].
+ /// When the system is under constrained,
+ /// for example when the columns of A are not linearly independent,
+ /// then it will not give sensible results.
+ static member inline leastSquaresCholesky + (A : Matrix<'T>) + (b: Vector<'T>) = + + let AT = A.Transpose() + + let upper = (AT * A) |> LinearAlgebra.cholesky + let gamma = + LinearAlgebra.solveTriangularLinearSystem(upper.Transpose()) (AT * b) true + let beta = + LinearAlgebra.solveTriangularLinearSystem upper gamma false + beta + + + /// computes the hat matrix by the QR decomposition of the designmatrix used in ordinary least squares approaches + static member inline hatMatrix + (designMatrix: Matrix<'T>) = + let qm,R = LinearAlgebra.qrDecompose designMatrix + let q1 = qm.GetSlice ((Some 0),(Some (qm.NumRows-1)),(Some 0),(Some (R.NumCols-1))) + // computes the hatmatrix + q1 * q1.Transpose() - /// Given A[n,n] find it's inverse.
This call may fail.
- /// - /// - /// - /// - /// - /// - /// - let Inverse a = - //if HaveService() then LinearAlgebraService.inverse a - // else LinearAlgebraManaged.Inverse a - LinearAlgebraManaged.Inverse a - - /// Given A[m,n] and B[m] solves AX = B for X[n].
When m => n, have over constrained system, finds least squares solution for X.
When m < n, have under constrained system, finds least norm solution for X.
- /// - /// - /// - /// - /// - /// - /// - /// - let LeastSquares a b = - //if HaveService() then LinearAlgebraService.leastSquares a b - // else LinearAlgebraManaged.leastSquares a b - LinearAlgebraManaged.leastSquares a b - - /// Given A[m,n] and b[m] solves AX = b for X[n].
When the system is under constrained,
for example when the columns of A are not linearly independent,
then it will not give sensible results.
- /// - /// - /// - /// - /// - /// - /// - /// - let LeastSquaresCholesky (a : Matrix) (b : Vector) = - LinearAlgebraManaged.leastSquaresCholesky a b - - /// Given A[n,n] real symmetric positive definite.
Finds the cholesky decomposition L such that L' * L = A.
May fail if not positive definite.
- /// - /// - /// - /// - /// - /// - /// - let Cholesky a = - //if HaveService() then LinearAlgebraService.Cholesky a - // else LinearAlgebraManaged.Cholesky a - LinearAlgebraManaged.Cholesky a - - /// Given A[n,n] real matrix.
Finds P,L,U such that L*U = P*A with L,U lower/upper triangular.
- /// - /// - /// - /// - /// - /// - /// - let LU a = - //if HaveService() then LinearAlgebraService.LU a - // else LinearAlgebraManaged.LU a - LinearAlgebraManaged.LU a - - - /// Given A[m,n] finds Q[m,m] and R[k,n] where k = min m n.
Have A = Q.R when m < =n.
Have A = Q.RX when m > n and RX[m,n] is R[n,n] row extended with (m-n) zero rows.
- /// - /// - /// - /// - /// - /// - /// - let QR a = - //if HaveService() then LinearAlgebraService.QR a - // else LinearAlgebraManaged.QR a - LinearAlgebraManaged.QR a + /// computes the leverages of every dataPoint of a dataSet given by the diagonal of the hat matrix. + static member inline leverageBy + (hatMatrix: Matrix<'T>) = + + Matrix.getDiagonal hatMatrix + + + /// computes the leverage directly by QR decomposition of the designmatrix used in ordinary least squares approaches
+ /// and computing of the diagnonal entries of the Hat matrix, known as the leverages of the regressors
+ static member inline leverage + (designMatrix: Matrix<'T>) = + + let qm,R = LinearAlgebra.qrDecompose designMatrix + let q1 = qm.GetSlice ((Some 0),(Some (qm.NumRows-1)),(Some 0),(Some (R.NumCols-1))) + + Vector.init q1.NumRows (fun i -> + let mutable sumOfSquares = 'T.Zero + for j = 0 to q1.NumCols - 1 do + let x = q1.[i, j] + sumOfSquares <- sumOfSquares + x * x + sumOfSquares + ) + /// - /// Performs QR decomposition using an alternative algorithm. - /// QR decomposition is a method to decompose a matrix A into two components: - /// Q (an orthogonal matrix) and R (an upper triangular matrix), - /// such that A = Q * R. It is commonly used in solving linear systems, - /// least squares fitting, and eigenvalue problems. + /// Computes the LU factorization of a square matrix A with partial pivoting. + /// That is, P * A = L * U, where P is a permutation, and L, U are lower/upper triangular. + /// Returns (Permutation P, L, U). /// - /// - /// A tuple containing: - /// - /// Q: The orthogonal matrix obtained from the decomposition. - /// R: The upper triangular matrix obtained from the decomposition. - /// - /// - let qrAlternative (A: Matrix) = - let m: int = A.NumRows - let n: int = A.NumCols - - let q: Matrix = Matrix.zero m n - let r: Matrix = Matrix.zero n n - let qLengths: Vector = Vector.zeroCreate n - - let getVectorLength (v: Vector) = Vector.fold (fun folder i -> folder+(i*i)) 0. v - - let setqOfA (n: int) = - let aN: Vector = Matrix.getCol A n - let qN = - if n = 0 then - aN - else - Array.init (n) (fun i -> - let denominator = qLengths[i] - let forNominator: Vector = Matrix.getCol q i - let nominator: float = Vector.dot aN forNominator - r.[i, n] <- nominator - (nominator/denominator) * forNominator - ) - |> Array.fold (fun folder e -> folder-e ) aN - Matrix.setCol q n qN - qN - - for i=0 to n-1 do - let qN = setqOfA i - let qLength = getVectorLength qN - let rValue = sqrt(qLength) - r[i,i] <- rValue - qLengths[i] <- qLength - - for i=0 to n-1 do - let qN: Vector = Matrix.getCol q i - let updateQ = (1./sqrt( qLengths[i] )) * qN - Matrix.setCol q i updateQ - for j=i+1 to n-1 do - let denominator = r[i, i] - let nominator = r[i, j] - r[i, j] <- (nominator/denominator) - - q, r + static member inline luDecompose (A : Matrix<'T>) = + let n, m = A.NumRows, A.NumCols + if n <> m then + invalidArg (nameof A) "LU: A must be square." + + let U = Matrix.copy A // We'll transform U in place. + let L = Matrix.zeroCreate n n // We'll fill L below the diagonal. + let P = [| 0 .. n-1 |] // Pivot array + + // Row-swap function for U: swap entire row i, row j + let swapRows (M: Matrix<'T>) i j = + let rowI = i + let rowJ = j + for col = 0 to m - 1 do + let tmp = M.[rowI, col] + M.[rowI, col] <- M.[rowJ, col] + M.[rowJ, col] <- tmp + + // Row-swap function for L: only swap the columns up to i-1 (since the rest is not yet set). + // Because in Doolittle's method, columns [0..i-1] of L are already determined at pivot step i. + let swapRowsPartial (M: Matrix<'T>) i j pivotCol = + for col = 0 to pivotCol - 1 do + let tmp = M.[i, col] + M.[i, col] <- M.[j, col] + M.[j, col] <- tmp + + // Perform the decomposition + for i = 0 to n - 2 do + // 1) Find pivot row by max absolute value in U column i + let mutable pivotRow = i + let mutable pivotVal = abs(U.[pivotRow, i]) + for r = i + 1 to n - 1 do + let candidate = abs(U.[r, i]) + if candidate > pivotVal then + pivotVal <- candidate + pivotRow <- r + + // 2) If pivotRow != i, swap rows in U, swap partial in L, and update pivot array + if pivotRow <> i then + swapRows U i pivotRow + swapRowsPartial L i pivotRow i + let tmp = P.[i] + P.[i] <- P.[pivotRow] + P.[pivotRow] <- tmp + + // 3) Eliminate below pivot + for j = i + 1 to n - 1 do + // L[j,i] = U[j,i] / U[i,i] + L.[j,i] <- U.[j,i] / U.[i,i] + // Update row j of U + for k = i + 1 to n - 1 do + U.[j,k] <- U.[j,k] - L.[j,i] * U.[i,k] + U.[j,i] <- 'T.Zero + + // Add identity to L (so diagonal = 1.0) + // i.e., L[i,i] <- 1.0 + for i = 0 to n - 1 do + L.[i,i] <- 'T.One + + // Return the permutation (as an array or your custom Permutation type), + // plus the final L and U + (Permutation.ofArray P, L, U) /// - /// Solves a linear system of equations using QR decomposition. + /// Solves the system of linear equations A * X = B using LU factorization. + /// A must be square; B must have the same number of rows as A. + /// Returns a matrix X s.t. A*X = B. /// - /// The coefficient matrix of the linear system. - /// The target vector of the linear system. - /// - /// A tuple containing: - /// - /// mX: The solution vector of the linear system. - /// r: The upper triangular matrix obtained from QR decomposition. - /// - /// - let solveLinearQR (A: Matrix) (t: Vector) = - let m = A.NumRows - let n = A.NumCols - - System.Diagnostics.Debug.Assert(m >= n) - - let q,r = qrAlternative A - - let QT = q.Transpose - - let mX = Vector.zeroCreate n - - let c: Vector = QT * t - - let rec build_mX_inner cross_prod i j = - if j=n then - cross_prod - else - let newCrossprod = cross_prod + (r[i, j] * mX[j]) - build_mX_inner newCrossprod i (j+1) - - let rec build_mX_outer i = - if i<0 then - () - else - let crossProd = build_mX_inner 0. i (i+1) - mX[i] <- (c[i] - crossProd) / r[i, i] - build_mX_outer (i-1) - - build_mX_outer (n-1) - - mX,r - + static member inline solveLinearSystems (A: Matrix<'T>) (B: Matrix<'T>) = + let nA, mA = A.NumRows, A.NumCols + let nB, mB = B.NumRows, B.NumCols - ///Returns the full Singular Value Decomposition of the input MxN matrix - /// - ///A : A = U * SIGMA * V**T in the tuple (S, U, V**T), - /// - ///where S is an array containing the diagonal elements of SIGMA. - /// uses the LAPACK routine dgesdd with the argument JOBZ = 'A' - /// - /// - /// - /// - /// - /// - /// - let SVD (a:Matrix) = - if HaveService() then - let S,U,Vt = Service().dgesdd_ a - Vector.ofArray S,U,Vt - else - LinearAlgebraManaged.SVD a - - /// spectral norm of a matrix (for Frobenius norm use Matrix.norm) - /// - /// - /// - /// - /// - /// - /// - let spectralNorm (a:Matrix) = - //let maxEigenVal = LinearAlgebra.EigenValues mat |> Seq.max - let maxEigenVal = - SVD (a * a.Transpose) - |> fun (S,U,V') -> S - |> Seq.max - maxEigenVal |> sqrt - - ///Returns the thin Singular Value Decomposition of the input MxN matrix A - /// - ///A = U * SIGMA * V**T in the tuple (S, U, V), - /// - ///where S is an array containing the diagonal elements of SIGMA. - ///The first min(M,N) columns of U and the first min(M,N) rows of V**T are returned in the arrays U and VT; - /// uses the LAPACK routine dgesdd with the argument JOBZ = 'S' - /// - /// - /// - /// - /// - /// - /// - let thinSVD a = - if HaveService() then - let S,U,Vt = Service().dgesdd_thin_ a - Vector.ofArray S, U, Vt - else - failwith "managed version not implemented" + // 1) Check shape: A must be square, B's rows must match A's rows + if nA <> mA then + invalidArg (nameof A) "Matrix A must be square." + if nB <> nA then + invalidArg (nameof B) "Matrix B must have same number of rows as A." - let Hessenberg A = - //if HaveService() then failwith "Not implemented yet."// REVIEW LinearAlgebraService.Hessenberg A - // else LinearAlgebraManaged.Hessenberg A - LinearAlgebraManaged.Hessenberg A - - /// computes the hat matrix by the QR decomposition of the designmatrix used in ordinary least squares approaches - /// - /// - /// - /// - /// - /// - /// - let hatmatrix A = - LinearAlgebraManaged.hatMatrix A - - /// computes the hat matrix by the QR decomposition of the designmatrix used in ordinary least squares approaches - /// - /// - /// - /// - /// - /// - /// - let leverageBy A = - LinearAlgebraManaged.leverageBy A - - /// computes the leverage directly by QR decomposition of the designmatrix used in ordinary least squares approaches
and computing of the diagnonal entries of the Hat matrix, known as the leverages of the regressors
- /// - /// - /// - /// - /// - /// - /// - let leverage A = - LinearAlgebraManaged.leverage A - ///// This method computes the condition number by just dividing the largest singular value - ///// by the smallest. - //let Condition (A:matrix) = - // let _,D,_ = SVD A - // D.[0] / D.[D.Length-1] - - /// Compute the determinant of a matrix by performing an LU decomposition since if A = P'LU,
then det(A) = det(P') * det(L) * det(U).
- /// - /// - /// - /// - /// - /// - /// - let Determinant A = - let P,_,U = LU A - // Compute the sign of a permutation REVIEW maybe this should go into permutation? - let PermutationSign (len,p) = - let a = Array.init len (fun i -> p i) // Get an array representation of the permutation - let v = Array.init len // Find the positions of all the positions in the permutation - (fun i -> Array.findIndex (fun x -> x = i) a) - let mutable sign = 1.0 // Remember the sign - for i=0 to len-2 do // Start transposing elements keeping track of how many - if a.[i] <> i then // transpositions we have taken. - a.[v.[i]] <- a.[i] - a.[i] <- i - v.[a.[v.[i]]] <- v.[i] - v.[i] <- i - sign <- -sign - assert(a = [|0 .. len-1|]) - assert(v = [|0 .. len-1|]) - sign - let n = A.NumRows - let P = (fun i -> P i) - (PermutationSign (n,P)) * (Vector.prod U.Diagonal) - - //// matrix multiplication - //let MM A B = - // if HaveService() then - // LinearAlgebraService.MM A B - // else - // A * B + // 2) Factor A -> (P, L, U) + let (P, L, U) = LinearAlgebra.luDecompose A + + // 3) Permute B according to P (i.e., reorder rows) + let Bpermuted = B |> Matrix.permuteRowsBy P + + // 4) Forward substitution: solve L * Y = Bpermuted + let Y = LinearAlgebra.solveTriangularLinearSystems L Bpermuted true // isLower = true -type LinearAlgebra() = + // 5) Back substitution: solve U * X = Y + let X = LinearAlgebra.solveTriangularLinearSystems U Y false // isLower = false - /// Synonym: kernel / right null space. Returns an orthonormal basis for the null space of matrix A (Ax = 0).
The accuracy defines a threshold whether a singular value is considered as zero (default: 1e-08). - static member nullspace(?Accuracy :float ) = + X - let accuracy = defaultArg Accuracy 1e-08 + /// + /// Solves the system A * x = b for x, using LU factorization with partial pivoting. + /// A must be square, and b must have length = A.NumRows. + /// + static member inline solveLinearSystem (A : Matrix<'T>) (b : Vector<'T>) = + let n, m = A.NumRows, A.NumCols + if n <> m then + invalidArg (nameof A) "Matrix A must be square." + if b.Length <> n then + invalidArg (nameof b) "Vector b must have length = A.NumRows." - fun (a: Matrix) -> - - // Either MKL or fallback implementation of the full SVD - let (sigma,U,Vt) = LinearAlgebra.SVD a + // 1) Factor A => (P, L, U) + let (P, L, U) = LinearAlgebra.luDecompose A - // The rank is the number of nonzero singular values - let rank = - sigma - |> Seq.sumBy (fun x -> if x >= accuracy then 1 else 0) + // 2) Permute b according to P + let bPermuted = b |> Vector.permuteBy P - let count = Vt.NumRows - rank + // 3) Forward solve: L * y = bPermuted + let y = LinearAlgebra.solveTriangularLinearSystem L bPermuted true // isLower = true - Matrix.getRows Vt rank count - |> Matrix.transpose + // 4) Back solve: U * x = y + let x = LinearAlgebra.solveTriangularLinearSystem U y false // isLower = false + + x + + /// + /// Computes the inverse of a square matrix A using its LU factorization. + /// If A is n×n, we factor A = P * L * U, then solve A * X = I for X, returning X = A^-1. + /// + /// A square matrix of size n×n. + /// The inverse of A, an n×n matrix. + /// + /// Thrown if A is not square, or if factorization fails (e.g., if A is singular). + /// + static member inline inverse (A: Matrix<'T>) : Matrix<'T> = + let n, m = A.NumRows, A.NumCols + if n <> m then + invalidArg (nameof A) "Matrix must be square when computing its inverse." + // 1) Factor A => P, L, U + let (P, L, U) = LinearAlgebra.luDecompose A + // 2) Build the identity matrix I, size n + let I = Matrix.identity n + // 3) Permute I's rows by P (so effectively P*I) + let IPerm = I |> Matrix.permuteRowsBy P + + // 4) Forward substitution: solve L * Y = IPerm + let Y = LinearAlgebra.solveTriangularLinearSystems L IPerm true + + // 5) Back substitution: solve U * X = Y + let X = LinearAlgebra.solveTriangularLinearSystems U Y false + + // X is A^-1 + X + + + /// + /// Computes the Moore-Penrose pseudoinverse of a matrix using a QR-based approach. + /// If the matrix is overdetermined (m > n), returns (R⁻¹ Qᵀ) for A = Q R with A[m×n]. + /// If underdetermined (m < n), uses the transpose trick, then returns the transpose of the partial solution. + /// + /// An m×n matrix. + /// The (n×m) pseudoinverse of . + static member inline pseudoInvers (matrix: Matrix<'T>) = + let m, n = matrix.NumRows, matrix.NumCols + + // Overdetermined: A is m×n with m > n + if m > n then + // A = Q (m×m) * R (m×n) [or economy size Q (m×n), R (n×n)] + let qm, R = LinearAlgebra.qrDecompose matrix + // Instead of multiplying qm.Transpose by identity(m×m), just use qm.Transpose + // Next, we want sub-blocks: R is m×n, but we only need the top n×n portion, + // and we want the top-left n×m portion of qm.Transpose. + let Qt = qm.Transpose() + // Solve R[0..n-1, 0..n-1] * X = Qt[0..n-1, 0..m-1] (back-substitution) + LinearAlgebra.solveTriangularLinearSystems + R.[0..n-1, 0..n-1] + Qt.[0..n-1, 0..m-1] + false + + // Underdetermined: A is m×n with m < n + else + // We do matrix.Transpose => n×m + // Then QR => qm (n×n?), R (n×m?), etc. + let qm, R = LinearAlgebra.qrDecompose (matrix.Transpose()) + // Again skip identity multiply: just use qm.Transpose + let Qt = qm.Transpose() + // Solve R[0..m-1, 0..m-1] * X = Qt[0..m-1, 0..n-1] + let s = + LinearAlgebra.solveTriangularLinearSystems + R.[0..m-1, 0..m-1] + Qt.[0..m-1, 0..n-1] + false + // Return sᵀ => the actual pseudoinverse shape (n×m) + s.Transpose() From efb3fe7ead48efe827950cf6c4313fbcd44acc7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20M=C3=BChlhaus?= Date: Wed, 9 Apr 2025 13:48:09 +0200 Subject: [PATCH 007/121] Integrate CrossValidation and new AlgTypes --- src/FSharp.Stats/Fitting/CrossValidation.fs | 74 +++++---------------- 1 file changed, 18 insertions(+), 56 deletions(-) diff --git a/src/FSharp.Stats/Fitting/CrossValidation.fs b/src/FSharp.Stats/Fitting/CrossValidation.fs index 34c87fe5a..ebc0a1ad6 100644 --- a/src/FSharp.Stats/Fitting/CrossValidation.fs +++ b/src/FSharp.Stats/Fitting/CrossValidation.fs @@ -23,8 +23,8 @@ module CrossValidation = /// /// let ssr (y:Vector) (p:Vector)= - let residuals = y-p - residuals.Transpose * residuals + let residuals = y .- p + Vector.dotProduct residuals residuals /// Computes root mean square error (RMSE) /// @@ -45,39 +45,6 @@ module CrossValidation = let createCrossValidationResult error errorStDev = {Error=error;ErrorStDev=errorStDev} - /// Computes a k fold cross-validation (in parallel) - [] - let inline kFoldParallel< ^T when ^T : (static member ( + ) : ^T * ^T -> ^T) - and ^T : (static member DivideByInt : ^T*int -> ^T) - and ^T : (static member Zero : ^T)> - - k iterations degreeOfParallelism (xData:Matrix< ^T >) (yData:Vector< ^T >) - (fit: Matrix< ^T > -> Vector< ^T > -> Matrix< ^T > -> Vector< ^T >) - (error: Vector< ^T > -> Vector< ^T >-> ^T) - - = - - let chunkSize = int (ceil (float yData.Length / float k)) - let chunks = - Seq.init iterations (fun _ -> - Array.init chunkSize (fun i -> FSharp.Stats.Random.rndgen.NextInt(i) ) - ) - - chunks - |> PSeq.map (fun chunk -> - let xTest,xTrain = - xData - |> Matrix.splitRows chunk - let yTest,yTrain = - yData - |> Vector.splitVector chunk - - let preds = fit xTrain yTrain xTest - let error = error preds yTest - error - ) - |> PSeq.withDegreeOfParallelism degreeOfParallelism - |> Seq.average /// Computes a repeated k fold cross-validation,
k: training set size (and number of iterations),
iterations: number of random subset creation,
xData: rowwise x-coordinate matrix,
yData: yData vector
fit: x and y data lead to function that maps a xData row vector to a y-coordinate,
error: defines the error of the fitted y-coordinate and the actual y-coordinate,
getStDev: function that calculates the standard deviation from a seq<^T>. (Seq.stDev)
/// @@ -87,12 +54,9 @@ module CrossValidation = /// /// /// - let inline repeatedKFold< ^T when ^T : (static member ( + ) : ^T * ^T -> ^T) - and ^T : (static member DivideByInt : ^T*int -> ^T) - and ^T : (static member Zero : ^T)> - + let inline repeatedKFold k (iterations: int) (xData:Matrix< ^T >) (yData:Vector< ^T >) - (fit: Matrix< ^T > -> Vector< ^T > -> RowVector< ^T > -> ^T) + (fit: Matrix< ^T > -> Vector< ^T > -> Vector< ^T > -> ^T) (error: ^T -> ^T -> ^T) (getStDev: seq< ^T > -> ^T) = let chunkSize = int (ceil (float yData.Length / float k)) @@ -113,12 +77,13 @@ module CrossValidation = yData |> Vector.splitVector indices xTest - |> Matrix.Generic.mapiRows (fun i xSingle -> + |> Matrix.getRows + |> Array.mapi (fun i xSingle -> let preds = fit xTrain yTrain xSingle - let error = error preds yTest.[i] + let error = error preds yTest[i] error ) - |> Seq.average + |> Vector.mean ) |> Seq.average ) @@ -139,7 +104,7 @@ module CrossValidation = /// /// let inline kFold k (xData:Matrix< ^T >) (yData:Vector< ^T >) - (fit: Matrix< ^T > -> Vector< ^T > -> RowVector< ^T > -> ^T) + (fit: Matrix< ^T > -> Vector< ^T > -> Vector< ^T > -> ^T) (error: ^T -> ^T -> ^T) = repeatedKFold k 1 xData yData fit error (fun s -> Seq.head s) |> fun r -> r.Error @@ -152,10 +117,8 @@ module CrossValidation = /// /// /// - let inline loocv< ^T when ^T : (static member ( + ) : ^T * ^T -> ^T) - and ^T : (static member DivideByInt : ^T*int -> ^T) - and ^T : (static member Zero : ^T)> - (xData:Matrix< ^T >) (yData:Vector< ^T >) (fitFunc:Matrix< ^T > -> Vector< ^T > -> (RowVector< ^T > -> ^T)) + let inline loocv + (xData:Matrix< ^T >) (yData:Vector< ^T >) (fitFunc:Matrix< ^T > -> Vector< ^T > -> (Vector< ^T > -> ^T)) (error: ^T -> ^T -> ^T) = let n = xData.NumRows @@ -164,10 +127,10 @@ module CrossValidation = |> List.map (fun i -> let (xTest,xTrain) = Matrix.splitRows [|i|] xData - |> fun (y,x) -> Matrix.Generic.toRowVector y,x + |> fun (y,x) -> Matrix.getRow 0 y,x let (yTest,yTrain) = Vector.splitVector [|i|] yData - |> fun (y,x) -> y.[0],x + |> fun (y,x) -> y[0],x let fit = fitFunc xTrain yTrain let yFit = fit xTest error yFit yTest @@ -182,11 +145,9 @@ module CrossValidation = /// /// /// - let inline shuffelAndSplit< ^T when ^T : (static member ( + ) : ^T * ^T -> ^T) - and ^T : (static member DivideByInt : ^T*int -> ^T) - and ^T : (static member Zero : ^T)> + let inline shuffelAndSplit p (iterations: int) (xData:Matrix< ^T >) (yData:Vector< ^T >) - (fit: Matrix< ^T > -> Vector< ^T > -> RowVector< ^T > -> ^T) + (fit: Matrix< ^T > -> Vector< ^T > -> Vector< ^T > -> ^T) (error: ^T -> ^T -> ^T) (getStDev: seq< ^T > -> ^T) = let n = xData.NumRows @@ -205,9 +166,10 @@ module CrossValidation = yData |> Vector.splitVector chunkIndices xTest - |> Matrix.Generic.mapiRows (fun i xSingle -> + |> Matrix.getRows + |> Array.mapi(fun i xSingle -> let preds = fit xTrain yTrain xSingle - let error = error preds yTest.[i] + let error = error preds yTest[i] error ) |> Seq.average From 4d0e56456fc076db5a922cd8b4e01586fe888910 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20M=C3=BChlhaus?= Date: Wed, 9 Apr 2025 13:48:59 +0200 Subject: [PATCH 008/121] Integrate LinearRegression new AlgTypes --- src/FSharp.Stats/Fitting/LinearRegression.fs | 97 +++++++++++--------- 1 file changed, 52 insertions(+), 45 deletions(-) diff --git a/src/FSharp.Stats/Fitting/LinearRegression.fs b/src/FSharp.Stats/Fitting/LinearRegression.fs index bf1aef5ec..a43f7a1e6 100644 --- a/src/FSharp.Stats/Fitting/LinearRegression.fs +++ b/src/FSharp.Stats/Fitting/LinearRegression.fs @@ -3,6 +3,7 @@ namespace FSharp.Stats.Fitting open System open FSharp.Stats +open FSharp.Stats.Algebra /// /// Linear regression is used to estimate the relationship of one variable (y) with another (x) by expressing y in terms of a linear function of x. @@ -21,7 +22,7 @@ module LinearRegression = /// /// Polynomial coefficients with various properties are stored within this type. /// - type Coefficients(coefficients: vector) = + type Coefficients(coefficients: Vector<'T>) = let n = coefficients.Length /// Contains polynomial coefficients as vector in the form of [constant; linear; quadratic; cubic]. @@ -55,13 +56,13 @@ module LinearRegression = member this.Item degree = coefficients.[degree] /// Gets a x value and predicts the corresponding y value for the given polynomial coefficients. - member this.Predict (x: float) = - Vector.dot coefficients (vandermondeRow this.Degree x) + member this.Predict (x: 'T) = + Vector.dotProduct coefficients (vandermondeRow this.Degree x) /// Gets a x value vector and predicts the corresponding y value for the given polynomial coefficients. - member this.Predict (x: vector) = - let tmp = Vector.init (x.Length + 1) (fun i -> if i = 0 then 1. else x.[i-1]) - Vector.dot tmp coefficients + member this.Predict (x: Vector<'T>) = + let tmp = Vector.init (x.Length + 1) (fun i -> if i = 0 then 'T.One else x.[i-1]) + Vector.dotProduct tmp coefficients /// Prints the polynomial function in a human readable form. override this.ToString() = @@ -78,7 +79,7 @@ module LinearRegression = static member Init(coefficients) = Coefficients(coefficients) /// Initializes Coefficients type with an empty vector. - static member Empty() = Coefficients(vector []) + static member Empty() = Coefficients(Array.empty) /// /// Ordinary Least Squares (OLS) regression aims to minimise the sum of squared y intercepts between the original and predicted points at each x value. @@ -119,7 +120,7 @@ module LinearRegression = let numerator = Seq.zip xData yData |> Seq.sumBy (fun (x,y) -> x * y) let denominator = xData |> Seq.sumBy (fun x -> x * x) let slope = numerator / denominator - Coefficients(vector [0.;slope]) + Coefficients([|0.;slope|]) [] let coefficientOfVector (xData : Vector) (yData : Vector) = @@ -143,8 +144,8 @@ module LinearRegression = /// LinearRegression.OLS.Linear.RTO.fit xData yData /// /// - let fit (xData : seq) (yData : seq) = - fitOfVector (vector xData) (vector yData) + let fit (xData : Vector) (yData : Vector) = + fitOfVector xData yData [] let coefficient (xData : Vector) (yData : Vector) = @@ -215,7 +216,7 @@ module LinearRegression = raise (System.ArgumentException("vector x and y have to be the same size!")) let N = xData.Length let X = Matrix.init N 2 (fun m x -> if x = 0 then 1. else xData.[m] ) - let coef = Algebra.LinearAlgebra.LeastSquares X yData + let coef = LinearAlgebra.leastSquares X yData Coefficients(coef) [] @@ -241,13 +242,13 @@ module LinearRegression = /// /// let fitCholesky (xData: Vector) (yData: Vector) = - if xData.NumRows <> yData.Length then + if xData.Length <> yData.Length then raise (System.ArgumentException("vector x and y have to be the same size!")) let X = Matrix.init (xData.Length) 2 (fun i j -> if j = 0 then 1.0 else xData.[i]) - let coef = Algebra.LinearAlgebra.LeastSquaresCholesky X yData + let coef = LinearAlgebra.leastSquaresCholesky X yData Coefficients(coef) @@ -274,11 +275,11 @@ module LinearRegression = /// /// let fitConstrained (xData : Vector) (yData : Vector) ((xC,yC): float*float) = - let xTransformed = xData |> Vector.map (fun x -> x - xC) - let yTransformed = yData |> Vector.map (fun y -> y - yC) + let xTransformed = xData .- xC + let yTransformed = yData .- yC let slope = (RTO.fitOfVector xTransformed yTransformed).Linear let intercept = yC - xC * slope - Coefficients(vector [|intercept;slope|]) + Coefficients([|intercept;slope|]) [] @@ -334,10 +335,13 @@ module LinearRegression = raise (System.ArgumentException("vector x and y have to be the same size!")) let N = xData.Length let X = Matrix.init N 2 (fun m x -> if x = 0 then 1. else xData.[m] ) - let coeffs = Coefficients(Algebra.LinearAlgebra.LeastSquares X yData) + let coeffs = Coefficients(LinearAlgebra.leastSquares X yData) let leverages = Algebra.LinearAlgebra.leverage X - let yPred = Vector.map (predict coeffs) xData - let squaredDeviations = Vector.map2 (fun y yPr -> (y - yPr) ** 2.) yPred yData + // TODO: Better performance by using a vector operation + let yPred = Array.map (predict coeffs) xData + let squaredDeviations = + let tmp = yData .- yPred // maybe switch to yData - yPred + tmp .* tmp let MSE = squaredDeviations |> Vector.sum |> fun sumOfSquares -> sumOfSquares / (float xData.Length) // compute cooksDistance for every Point in the dataSet squaredDeviations @@ -390,7 +394,7 @@ module LinearRegression = let m = xData.NumRows let n = xData.NumCols let X = Matrix.init m (n+1) (fun m n -> if n = 0 then 1. else xData.[m,n-1] ) - Coefficients(Algebra.LinearAlgebra.LeastSquares X yData) + Coefficients(LinearAlgebra.leastSquares X yData) [] let coefficients (xData : Matrix) (yData : Vector) = @@ -436,7 +440,7 @@ module LinearRegression = Matrix.init (xData.NumRows) (xData.NumCols + 1) (fun i j -> if j = 0 then 1.0 else xData.[i, j - 1]) - Coefficients(Algebra.LinearAlgebra.LeastSquaresCholesky X yData) + Coefficients(LinearAlgebra.leastSquaresCholesky X yData) [] let coefficientsCholesky (xData : Matrix) (yData : Vector) = @@ -479,7 +483,7 @@ module LinearRegression = /// let predict (coef: Coefficients) (x: Vector) = let tmp: Vector = Vector.init (x.Length+1) (fun i -> if i = 0 then 1. else x.[i-1]) - Vector.dot tmp coef.Coefficients + Vector.dotProduct tmp coef.Coefficients module RidgeRegression = @@ -491,10 +495,10 @@ module LinearRegression = let n = xData.NumCols let X = Matrix.init m (n+1) (fun m n -> if n = 0 then 1. else xData.[m,n-1] ) - let lambdaIdentity = lambda .* Matrix.identity n - let sumDot = X.Transpose * X + lambdaIdentity - let theInverse = Algebra.LinearAlgebra.Inverse sumDot - let inverseXt = theInverse * X.Transpose + let lambdaIdentity = lambda * Matrix.identity n + let sumDot = X.Transpose() * X + lambdaIdentity + let theInverse = LinearAlgebra.inverse sumDot + let inverseXt = theInverse * X.Transpose() let w = inverseXt * yData Coefficients(w) @@ -514,7 +518,7 @@ module LinearRegression = /// let predict (coef : Coefficients) (x:Vector) = let tmp :Vector = Vector.init (x.Length+1) (fun i -> if i = 0 then 1. else x.[i-1]) - Vector.dot tmp coef.Coefficients + Vector.dotProduct tmp coef.Coefficients /// /// Linear regression using polynomials as regression function: f(x) = a + bx + cx^2 + .... @@ -548,9 +552,9 @@ module LinearRegression = // Least Squares of |y=A(x)*c| // tr(A)*y = tr(A)*A*c // inv(tr(A)*A)*tr(A)*y = c - let AtA = A.Transpose * A - let Aty = A.Transpose * yData - Coefficients(Algebra.LinearAlgebra.LeastSquares AtA Aty ) + let AtA = A.Transpose() * A + let Aty = A.Transpose() * yData + Coefficients(LinearAlgebra.leastSquares AtA Aty ) [] let coefficient order (xData : Vector) (yData : Vector) = @@ -579,22 +583,23 @@ module LinearRegression = let fitWithWeighting order (weighting : Vector) (xData : Vector) (yData : Vector) = if xData.Length <> yData.Length || xData.Length <> weighting.Length then raise (System.ArgumentException("vector x,y and weighting have to be the same size!")) + // TODO: Accelaration by using a matrix operation let A = Matrix.init (order + 1) (order + 1) (fun i j -> - Vector.map2 (fun x w -> w * (pown x (i + j))) xData weighting + Array.map2 (fun x w -> w * (pown x (i + j))) xData weighting |> Vector.sum ) let b = Vector.init (order + 1) (fun i -> - Vector.map3 (fun x y w -> w * (pown x i) * y) xData yData weighting + Array.map3 (fun x y w -> w * (pown x i) * y) xData yData weighting |> Vector.sum ) - Coefficients(Algebra.LinearAlgebra.SolveLinearSystem A b) + Coefficients(LinearAlgebra.solveLinearSystem A b) [] let coefficientsWithWeighting order (weighting : Vector) (xData : Vector) (yData : Vector) = @@ -635,7 +640,7 @@ module LinearRegression = /// /// If all coefficients are nonzero, the order is equal to the length of the coefficient vector! let predict (coef: Coefficients) (x: float) = - Vector.dot coef.Coefficients (vandermondeRow coef.Degree x) + Vector.dotProduct coef.Coefficients (vandermondeRow coef.Degree x) /// /// calculates derivative values at X=x with given polynomial coefficients. Level 1 = fst derivative; Level2 = snd derivative ... @@ -697,10 +702,12 @@ module LinearRegression = raise (System.ArgumentException("vector x and y have to be the same size!")) let N = xData.Length let A = vandermondeMatrix order xData - let coeffs = Coefficients(Algebra.LinearAlgebra.LeastSquares A yData) + let coeffs = Coefficients(LinearAlgebra.leastSquares A yData) let leverages = Algebra.LinearAlgebra.leverage A - let yPred = Vector.map (predict coeffs) xData - let squaredDeviations = Vector.map2 (fun y yPr -> (y - yPr) ** 2.) yPred yData + let yPred = Array.map (predict coeffs) xData + let squaredDeviations = + let tmp = yData .- yPred // maybe switch to yData - yPred + tmp .* tmp let MSE = squaredDeviations |> Vector.sum |> fun sumOfSquares -> sumOfSquares / (float xData.Length) // compute cooksDistance for every Point in the dataSet squaredDeviations @@ -742,7 +749,7 @@ module LinearRegression = let theilEstimator (xData: Vector) (yData: Vector)= //sort data in ascending order (xData) let data = - Array.zip (Vector.toArray xData) (Vector.toArray yData) + Array.zip xData yData |> Array.sortBy fst //low/high group. (If n is odd, the middle value is ignored) @@ -770,7 +777,7 @@ module LinearRegression = |> Array.map (fun (xV,yV) -> yV - (slope * xV)) |> FSharp.Stats.Array.median - Coefficients(vector [|intercept;slope|]) + Coefficients([|intercept;slope|]) /// /// Calculates simple linear regression coefficients using the Theil-Sen estimator in the form of [|intercept; slope;|]. Performs well if outlier corrupt the regression line. @@ -810,7 +817,7 @@ module LinearRegression = let isolateUnique (data: Vector) = indicesOfUniqueOccurences |> List.map (fun i -> data.[i]) - |> vector + |> Array.ofList let filteredXData = isolateUnique xData let filteredYData = isolateUnique yData @@ -931,7 +938,7 @@ type LinearRegression() = /// /// /// Default is simple linear regression fitting without constraints. - static member fit(xData: vector, yData, ?FittingMethod: Method, ?Constraint: Constraint, ?Weighting: vector) = + static member fit(xData: Vector<'T>, yData, ?FittingMethod: Method, ?Constraint: Constraint, ?Weighting: Vector) = let _constraint = defaultArg Constraint Unconstrained @@ -945,9 +952,9 @@ type LinearRegression() = | Constraint.Unconstrained -> LinearRegression.OLS.Linear.Univariable.fit xData yData | Constraint.RegressionThroughOrigin -> - LinearRegression.OLS.Linear.RTO.fit (vector xData) (vector yData) + LinearRegression.OLS.Linear.RTO.fit xData yData | Constraint.RegressionThroughXY coordinate -> - LinearRegression.OLS.Linear.Univariable.fitConstrained (vector xData) (vector yData) coordinate + LinearRegression.OLS.Linear.Univariable.fitConstrained xData yData coordinate | _ -> failwithf "Weighted simple linear regression is not yet implemented! Use polynomial weighted regression with degree 1 instead." | Method.Polynomial o -> @@ -997,7 +1004,7 @@ type LinearRegression() = /// /// /// Default is simple linear regression fitting without constraints. - static member fit(xData: matrix, yData, ?FittingMethod: Method) = + static member fit(xData: Matrix<'T>, yData, ?FittingMethod: Method) = let _fittingMethod = defaultArg FittingMethod Method.SimpleLinear @@ -1070,6 +1077,6 @@ type LinearRegression() = /// LinearRegression.predictMultivariate(coefficientsSimpleLinear) (vector [1.;2.;3.;]) /// /// - static member predictMultivariate(coeff: LinearRegression.Coefficients) (xVector: vector) = + static member predictMultivariate(coeff: LinearRegression.Coefficients) (xVector: Vector) = coeff.Predict xVector \ No newline at end of file From 444dab57211d2a6c169217468406e6ad4cfe1192 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20M=C3=BChlhaus?= Date: Wed, 9 Apr 2025 13:49:24 +0200 Subject: [PATCH 009/121] Integrate LogisticRegression and new AlgTypes --- .../Fitting/LogisticRegression.fs | 54 ++++++++++++++----- 1 file changed, 40 insertions(+), 14 deletions(-) diff --git a/src/FSharp.Stats/Fitting/LogisticRegression.fs b/src/FSharp.Stats/Fitting/LogisticRegression.fs index 92637b974..6fa01b3f7 100644 --- a/src/FSharp.Stats/Fitting/LogisticRegression.fs +++ b/src/FSharp.Stats/Fitting/LogisticRegression.fs @@ -10,22 +10,48 @@ module LogisticRegression = open System - // Weights have 1 element more than observations, for constant - let internal predict (weights: vector) (obs: vector) = - Vector.init (obs.Length+1) (fun i -> if i = 0 then 1. else obs.[i-1]) - |> Vector.dot weights + /// Creates a new vector (length = obs.Length + 1) whose + /// first element is 1.0 (for the intercept), followed by obs's elements. + /// If obs = [x0; x1; ...; xN-1], then withIntercept obs = [1.0; x0; x1; ...; xN-1]. + let internal withIntercept (obs: Vector) : Vector = + let n = obs.Length + let result = Vector.zeroCreate (n + 1) + result.[0] <- 1.0 + // copy obs into result[1..], leveraging the library's copy or a loop + Array.blit obs 0 result 1 n + result + + /// Logistic regression prediction: + /// weights : Vector of length obs.Length+1 + /// obs : Vector (the features, excluding intercept) + /// Returns logistic(dot(weights, [1.0; obs])) + let internal predict (weights: Vector) (obs: Vector) = + // Build intercept-augmented obs + let iobs = withIntercept obs + // Dot product => logistic function + Vector.dotProduct weights iobs |> FSharp.Stats.SpecialFunctions.Logistic.standard - let internal error (weights: vector) (obs: vector) label = + /// Error = (label - prediction) + let internal error (weights: Vector) (obs: Vector) label = label - predict weights obs - let internal update alpha (weights: vector) (obs: vector) label = - Vector.add weights (Vector.scale (alpha * (error weights obs label)) (Vector.init (obs.Length+1) (fun i -> if i = 0 then 1. else obs.[i-1]))) + /// Update rule: weights <- weights + alpha * error * [1.0; obs] + let internal update alpha (weights: Vector) (obs: Vector) label = + // 1) compute scalar = alpha * error + let e = alpha * error weights obs label + // 2) build intercept obs + let iobs = withIntercept obs + // 3) scaled = e * iobs + let scaled = e .* iobs + // 4) add => new weights + Vector.add weights scaled + // simple training: returns vector of weights // after fixed number of passes / iterations over dataset, // with constant alpha - let internal simpleTrain (dataset: (float * vector) seq) passes alpha = + let internal simpleTrain (dataset: (float * Vector) seq) passes alpha = let rec descent iter curWeights = match iter with | 0 -> curWeights @@ -35,7 +61,7 @@ module LogisticRegression = update alpha w observ label) curWeights |> descent (iter - 1) - let vars = dataset |> Seq.item 1 |> snd |> Vector.length + let vars = dataset |> Seq.item 1 |> snd |> Array.length let weights = Vector.zeroCreate (vars+1) // 1 more weight for constant descent passes weights @@ -46,9 +72,9 @@ module LogisticRegression = // rate of change in the weights vector, // computed as the % change in norm - let private changeRate (before:vector) (after:vector) = + let private changeRate (before:Vector) (after:Vector) = let numerator = - Vector.sub before after + Vector.subtract before after |> Vector.norm let denominator = Vector.norm before numerator / denominator @@ -81,7 +107,7 @@ module LogisticRegression = indices |> Seq.take len |> Seq.fold (fun w i -> - let (label, observ) = yData.[i], Vector.singleton xData.[i] + let (label, observ) = yData.[i], [|xData.[i]|] update alpha w observ label) curWeights if changeRate curWeights updatedWeights <= epsilon then updatedWeights @@ -106,7 +132,7 @@ module LogisticRegression = /// /// let predict (coef: Vector) x= - predict coef (Vector.singleton x) + predict coef ([|x|]) let estimateAlpha epsilon (xData : Vector) (yData : Vector) = let fR2 alpha = @@ -143,7 +169,7 @@ module LogisticRegression = indices |> Seq.take len |> Seq.fold (fun w i -> - let (label, observ) = yData.[i], vector (Matrix.getRow xData i) + let (label, observ) = yData.[i], (Matrix.getRow i xData) update alpha w observ label) curWeights if changeRate curWeights updatedWeights <= epsilon then updatedWeights From edd3318ce2e68073d201cae168f614ef2302714a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20M=C3=BChlhaus?= Date: Wed, 9 Apr 2025 13:49:51 +0200 Subject: [PATCH 010/121] Integrate NomLinearRegression and new AlgTypes --- .../Fitting/NonLinearRegression.fs | 60 +++++++++---------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/src/FSharp.Stats/Fitting/NonLinearRegression.fs b/src/FSharp.Stats/Fitting/NonLinearRegression.fs index d741528d6..0daaea611 100644 --- a/src/FSharp.Stats/Fitting/NonLinearRegression.fs +++ b/src/FSharp.Stats/Fitting/NonLinearRegression.fs @@ -71,7 +71,7 @@ module NonLinearRegression = for i = 0 to xData.Length-1 do let gradient = Vector.zeroCreate paramCount model.GetGradientValue paramVector gradient xData.[i] |> ignore - Matrix.setRow jacobian i gradient + jacobian.SetRow( i, gradient ) jacobian /// Returns the residual vector, each row i contains the difference between the yEst_i and the yData_i. @@ -108,13 +108,13 @@ module NonLinearRegression = let shouldTerminate (currentValueRSS: float) (newValueRSS: float) (iterationCount:int) (currentParamGuess:Vector) (newParamGuess:Vector) (solverOptions: SolverOptions) = //abs (newValueRSS-currentValueRSS) <= solverOptions.MinimumDeltaValue || - Vector.sub newParamGuess currentParamGuess |> Vector.norm <= solverOptions.MinimumDeltaParameters || + Vector.subtract newParamGuess currentParamGuess |> Vector.norm <= solverOptions.MinimumDeltaParameters || iterationCount >= solverOptions.MaximumIterations /// - let solverConverged (solverOptions: SolverOptions) (estParams:ResizeArray) = + let solverConverged (solverOptions: SolverOptions) (estParams:ResizeArray>) = solverOptions.MaximumIterations = estParams.Count |> not @@ -131,17 +131,17 @@ module NonLinearRegression = /// /// let estimatedParamsVerbose (model: Model) (solverOptions: SolverOptions) (xData: float[]) (yData: float []) = - let paramsAtIteration = new ResizeArray() - let initialParamGuess = Vector.ofArray solverOptions.InitialParamGuess + let paramsAtIteration = new ResizeArray>() + let initialParamGuess = solverOptions.InitialParamGuess let residualVector = Vector.zeroCreate xData.Length - let jacobian = Matrix.zero xData.Length solverOptions.InitialParamGuess.Length + let jacobian = Matrix.zeroCreate xData.Length solverOptions.InitialParamGuess.Length let initialValueRSS = getRSS model xData yData initialParamGuess - let rec loop jacobian residualVector currentParamGuess currentValueRSS (paramsAtIteration:ResizeArray) = + let rec loop jacobian residualVector currentParamGuess currentValueRSS (paramsAtIteration:ResizeArray>) = let jacobian' = updateJacobianInplace model xData currentParamGuess jacobian let residualVector' = updateResidualVectorInPlace model xData yData currentParamGuess residualVector - let hessian = jacobian'.Transpose * jacobian' - let step = LinearAlgebra.LeastSquares hessian (Matrix.mulV (jacobian'.Transpose) residualVector') - let newParamGuess = currentParamGuess - step + let hessian = jacobian'.Transpose() * jacobian' + let step = LinearAlgebra.leastSquares hessian (Matrix.muliplyVector (jacobian'.Transpose()) residualVector') + let newParamGuess = currentParamGuess .- step let newValueRSS = getRSS model xData yData newParamGuess paramsAtIteration.Add(newParamGuess) if shouldTerminate currentValueRSS newValueRSS paramsAtIteration.Count currentParamGuess newParamGuess solverOptions then @@ -183,18 +183,18 @@ module NonLinearRegression = /// /// let estimatedParamsVerbose (model: Model) (solverOptions: SolverOptions) lambdaInitial lambdaFactor (xData: float[]) (yData: float []) = - let paramsAtIteration = new ResizeArray() - let initialParamGuess = Vector.ofArray solverOptions.InitialParamGuess + let paramsAtIteration = new ResizeArray>() + let initialParamGuess = solverOptions.InitialParamGuess let residualVector = Vector.zeroCreate xData.Length - let jacobian = Matrix.zero xData.Length solverOptions.InitialParamGuess.Length + let jacobian = Matrix.zeroCreate xData.Length solverOptions.InitialParamGuess.Length let initialValueRSS = getRSS model xData yData initialParamGuess - let rec loop lambda jacobian residualVector currentParamGuess currentValueRSS (paramsAtIteration:ResizeArray) = + let rec loop lambda jacobian residualVector currentParamGuess currentValueRSS (paramsAtIteration:ResizeArray>) = let jacobian' = updateJacobianInplace model xData currentParamGuess jacobian let residualVector' = updateResidualVectorInPlace model xData yData currentParamGuess residualVector - let hessian = jacobian'.Transpose * jacobian' + let hessian = jacobian'.Transpose() * jacobian' let diagonal = Matrix.initDiagonal (Vector.map (fun x -> ((lambda)*x)) hessian.Diagonal) let modHessian = (hessian + diagonal) - let step = FSharp.Stats.Algebra.LinearAlgebra.SolveLinearSystem modHessian (Matrix.mulV (jacobian'.Transpose) residualVector') + let step = LinearAlgebra.solveLinearSystem modHessian (Matrix.mulV (jacobian'.Transpose) residualVector') let newParamGuess = currentParamGuess - step let newValueRSS = getRSS model xData yData newParamGuess paramsAtIteration.Add(newParamGuess) @@ -234,7 +234,7 @@ module NonLinearRegression = module LevenbergMarquardtConstrained = /// - let private validateBounds (lowerBound: vector) (upperBound: vector) (parameters: vector) = + let private validateBounds (lowerBound: Vector) (upperBound: Vector) (parameters: Vector) = try if Vector.map3 (fun l u x -> if l <= x && u >= x then x else nan) lowerBound upperBound parameters |> Vector.exists Ops.isNan then failwith "initial parameters are not within Bounds" @@ -244,31 +244,31 @@ module NonLinearRegression = | _ -> failwith "vector lengths differ" /// - let private toInternalParameters (lowerBound: vector) (upperBound: vector) (extParameters: vector) = + let private toInternalParameters (lowerBound: Vector) (upperBound: Vector) (extParameters: Vector) = Vector.map3 (fun l u x -> Math.Asin((2.0 * (x - l) / (u - l)) - 1.0) ) lowerBound upperBound extParameters /// - let private toExternalParameters (lowerBound: vector) (upperBound: vector) (intParameters: vector) = + let private toExternalParameters (lowerBound: Vector) (upperBound: Vector) (intParameters: Vector) = Vector.map3 (fun l u x -> l + (u / 2.0 - l / 2.0) * (Math.Sin(x) + 1.0) ) lowerBound upperBound intParameters /// - let private calculateJacScaleFactors (lowerBound: vector) (upperBound: vector) (intParameters: vector) = + let private calculateJacScaleFactors (lowerBound: Vector) (upperBound: Vector) (intParameters: Vector) = Vector.map3 (fun l u x -> (u - l) / 2.0 * Math.Cos(x) ) lowerBound upperBound intParameters /// - let private scaleJacobian (scaleFactors: vector) (jacobian:matrix) = + let private scaleJacobian (scaleFactors: Vector) (jacobian:Matrix) = jacobian |> Matrix.mapi (fun m n x -> x * scaleFactors.[m] * scaleFactors.[n]) /// - let private scaleGradient (scaleFactors: vector) (gradient:vector) = - Vector.cptMul scaleFactors gradient + let private scaleGradient (scaleFactors: Vector) (gradient:Vector) = + Vector.multiply scaleFactors gradient /// Returns an collection of parameter vectors as a possible solution for least square based nonlinear fitting of a given dataset (xData, yData) with a given
model function.
/// @@ -286,12 +286,12 @@ module NonLinearRegression = /// /// let estimatedParamsVerbose (model: Model) (solverOptions: SolverOptions) lambdaInitial lambdaFactor (lowerBound: vector) (upperBound: vector) (xData: float[]) (yData: float []) = - let paramsAtIteration = new ResizeArray() - let initialParamGuess = Vector.ofArray solverOptions.InitialParamGuess + let paramsAtIteration = new ResizeArray>() + let initialParamGuess = solverOptions.InitialParamGuess validateBounds lowerBound upperBound initialParamGuess let internalParamsGuess = toInternalParameters lowerBound upperBound initialParamGuess let residualVector = Vector.zeroCreate xData.Length - let jacobian = Matrix.zero xData.Length solverOptions.InitialParamGuess.Length + let jacobian = Matrix.zeroCreate xData.Length solverOptions.InitialParamGuess.Length let initialValueRSS = getRSS model xData yData initialParamGuess let rec loop lambda jacobian residualVector currentParamGuessExt currentParamGuessInt currentValueRSS (paramsAtIteration:ResizeArray) = let scaleFactors = calculateJacScaleFactors lowerBound upperBound currentParamGuessInt @@ -331,8 +331,8 @@ module NonLinearRegression = /// /// /// - let estimatedParams (model: Model) (solverOptions: SolverOptions) lambdaInitial lambdaFactor (lowerBound: vector) (upperBound: vector) (xData: float[]) (yData: float []) = - let estParams = estimatedParamsVerbose model solverOptions lambdaInitial lambdaFactor (lowerBound: vector) (upperBound: vector) xData yData + let estimatedParams (model: Model) (solverOptions: SolverOptions) lambdaInitial lambdaFactor (lowerBound: Vector) (upperBound: Vector) (xData: float[]) (yData: float []) = + let estParams = estimatedParamsVerbose model solverOptions lambdaInitial lambdaFactor (lowerBound: Vector) (upperBound: Vector) xData yData estParams.[estParams.Count-1] /// Returns a parameter vector tupled with its residual sum of squares (RSS) as a possible solution for linear least square based nonlinear fitting of a given dataset (xData, yData) with a given
model function.
@@ -350,7 +350,7 @@ module NonLinearRegression = /// /// /// - let estimatedParamsWithRSS (model: Model) (solverOptions: SolverOptions) lambdaInitial lambdaFactor (lowerBound: vector) (upperBound: vector) (xData: float[]) (yData: float []) = + let estimatedParamsWithRSS (model: Model) (solverOptions: SolverOptions) lambdaInitial lambdaFactor (lowerBound: Vector) (upperBound: Vector) (xData: float[]) (yData: float []) = let estParams = estimatedParamsVerbose model solverOptions lambdaInitial lambdaFactor lowerBound upperBound xData yData estParams |> fun estParams -> @@ -542,7 +542,7 @@ module NonLinearRegression = let expSolverOptions (xData:float []) (yData:float [])= //gets the linear representation of the problem and solves it by simple linear regression let initialParamGuess = - let yLn = yData |> Array.map (fun x -> Math.Log(x)) |> vector + let yLn : Vector = yData |> Array.map (fun x -> Math.Log(x)) let linearReg = LinearRegression.OLS.Linear.Univariable.fit (vector xData) yLn let a = exp linearReg.Constant let b = linearReg.Linear From 32d0183805adf89832be8c60892431826e4074e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20M=C3=BChlhaus?= Date: Wed, 9 Apr 2025 13:50:05 +0200 Subject: [PATCH 011/121] Integrate Spline and new AlgTypes --- src/FSharp.Stats/Fitting/Spline.fs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/FSharp.Stats/Fitting/Spline.fs b/src/FSharp.Stats/Fitting/Spline.fs index 58f95cf98..656793a10 100644 --- a/src/FSharp.Stats/Fitting/Spline.fs +++ b/src/FSharp.Stats/Fitting/Spline.fs @@ -41,7 +41,6 @@ module Spline = // Some preprocessing let basistmp = preprocessBasis basispts let xdata,ydata = data |> preprocess |> Array.unzip - let ydata = vector ydata let n = Array.length xdata let n' = Array.length basistmp let xm = basistmp.[n'-2] @@ -60,7 +59,7 @@ module Spline = // Construct the matrices we need let Bt = Matrix.init n' n (fun c r -> basis.[c] xdata.[r]) - let BtB = Bt * Bt.Transpose + let BtB = Bt * Bt.Transpose() let penaltyFunc r c = let xi = xdata.[-2+min r c] let xj = xdata.[-2+max r c] @@ -74,8 +73,8 @@ module Spline = let n' = float n' fun (lambda: float) -> do checkSmoothingParameter lambda - let beta = FSharp.Stats.Algebra.LinearAlgebra.LeastSquares (BtB + n'*lambda*Omega) (Bt * ydata) - let helper = Array.zip basis (beta.ToArray()) + let beta = LinearAlgebra.leastSquares (BtB + n'*lambda*Omega) (Bt * ydata) + let helper = Array.zip basis beta /// Our actualy smoothing spline fun x -> helper |> Array.sumBy (fun (f,w) -> w * f x) \ No newline at end of file From 85acabeb9a56f90f094d6cf242c01332c2fb54b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20M=C3=BChlhaus?= Date: Wed, 9 Apr 2025 13:50:28 +0200 Subject: [PATCH 012/121] Integrate GoodnessOfFit and new AlgTypes --- src/FSharp.Stats/Fitting/GoodnessOfFit.fs | 85 ++++++++++++++--------- 1 file changed, 51 insertions(+), 34 deletions(-) diff --git a/src/FSharp.Stats/Fitting/GoodnessOfFit.fs b/src/FSharp.Stats/Fitting/GoodnessOfFit.fs index 45829778f..fdcf21bfe 100644 --- a/src/FSharp.Stats/Fitting/GoodnessOfFit.fs +++ b/src/FSharp.Stats/Fitting/GoodnessOfFit.fs @@ -354,43 +354,60 @@ module GoodnessOfFit = Vector.init (order+1) (fun i -> pown x i) let calculateANOVA (order) (coef : Vector) (xData) (yData) = - let fitFunction x = Vector.dot coef (vandermondeRow order x) + let fitFunction x = Vector.dotProduct coef (vandermondeRow order x) calculateANOVA order fitFunction xData yData [] module CrossValidation = - - /// calculates LeaveOneOutCrossValidation - /// - /// - /// - /// - /// - /// - /// - /// - /// - let loocv (xData:Vector) (yData:Vector) order = - [0..xData.Length-1] - |> List.map (fun x -> - let xTmp = - xData - |> Seq.toList - |> fun xDat -> xDat.[..x-1]@xDat.[x+1..] - |> vector - let yTmp = - yData - |> Seq.toList - |> fun yDat -> yDat.[..x-1]@yDat.[x+1..] - |> vector - let coefTmp = LinearRegression.OLS.Polynomial.fit order xTmp yTmp - let error = - let yFit = LinearRegression.OLS.Polynomial.predict coefTmp (float xData.[x]) - pown (yFit - yData.[x]) 2 - error - ) - |> List.sum - |> fun x -> x/(float xData.Length) + + /// + /// Computes the leave-one-out cross-validation (LOOCV) error for a polynomial + /// fit of given on the dataset (xData, yData). + /// + /// The vector of x-values (length n). + /// The vector of y-values (length n), corresponding to xData. + /// Polynomial order. For example, order=2 => quadratic. + /// The mean squared error of leave-one-out predictions. + let loocv (xData: Vector) (yData: Vector) (order: int) : float = + let n = xData.Length + if n <> yData.Length then + invalidArg (nameof yData) "xData and yData must have the same length." + + let xArr = xData + let yArr = yData + + // Sum of squared errors across leave-one-out folds + let sse = + [0..n-1] + |> List.sumBy (fun i -> + // Create new arrays xLOO, yLOO that skip index i + let xLOO = Array.zeroCreate (n - 1) + let yLOO = Array.zeroCreate (n - 1) + + // Copy all elements up to i + Array.blit xArr 0 xLOO 0 i + Array.blit yArr 0 yLOO 0 i + + // Copy elements after i + if i < n - 1 then + Array.blit xArr (i + 1) xLOO i (n - 1 - i) + Array.blit yArr (i + 1) yLOO i (n - 1 - i) + + // Fit polynomial of the given 'order' to the (n-1) data + let coef = + LinearRegression.OLS.Polynomial.fit + order + (xLOO) + (yLOO) + + // Predict for the left-out xArr.[i], compare to actual yArr.[i] + let yPred = LinearRegression.OLS.Polynomial.predict coef xArr.[i] + let residual = yPred - yArr.[i] + residual * residual // squared error + ) + + // Return mean (average) of all squared errors + sse / float n ///k-fold cross validation ///Calculates the average SSE of given data, the order used to fit the polynomial and the subset you want to leave out (k). @@ -445,7 +462,7 @@ module GoodnessOfFit = |> Array.unzip let dataLeftOut = x let fit = - Fitting.LinearRegression.OLS.Polynomial.fit order (vector subX) (vector subY) + Fitting.LinearRegression.OLS.Polynomial.fit order (subX) (subY) |> fun coeffs -> Fitting.LinearRegression.OLS.Polynomial.predict coeffs dataLeftOut |> Array.map (fun (xLO,yLO) -> pown (fit xLO - yLO) 2) From 54df125b7dd53148bc6a088fb1d33f6e74370cb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20M=C3=BChlhaus?= Date: Wed, 9 Apr 2025 13:50:59 +0200 Subject: [PATCH 013/121] Integrate Clustering and new AlgTypes --- .../ML/Unsupervised/ClusterNumber.fs | 38 ++++++++++++------- .../ML/Unsupervised/IterativeClustering.fs | 2 +- 2 files changed, 26 insertions(+), 14 deletions(-) diff --git a/src/FSharp.Stats/ML/Unsupervised/ClusterNumber.fs b/src/FSharp.Stats/ML/Unsupervised/ClusterNumber.fs index 927af7367..1150da672 100644 --- a/src/FSharp.Stats/ML/Unsupervised/ClusterNumber.fs +++ b/src/FSharp.Stats/ML/Unsupervised/ClusterNumber.fs @@ -176,21 +176,22 @@ module ClusterNumber = ) ) - let contingencyMatrix: Matrix = compareall correctLabels clusteredLabels |> matrix + let contingencyMatrix: Matrix = + compareall correctLabels clusteredLabels + |> Matrix.ofJaggedArray let rowSum = contingencyMatrix - |> Matrix.Generic.mapRows Seq.sum - |> Vector.toArray + |> Matrix.getRows + |> Array.map Vector.sum let colSum = contingencyMatrix - |> Matrix.Generic.mapCols Seq.sum - |> RowVector.toArray + |> Matrix.getCols + |> Array.map Vector.sum let totalSum = - contingencyMatrix - |> Matrix.Generic.sum + contingencyMatrix.Data |> Vector.sum let pi = Array.map (fun i -> i / totalSum) rowSum @@ -303,8 +304,16 @@ https://www.datanovia.com/en/lessons/determining-the-optimal-number-of-clusters- /// let generateUniformPoints (rnd:System.Random) = fun (data:array) -> - let min = matrix data |> Matrix.mapiCols (fun i x -> Seq.min x) |> Array.ofSeq - let max = matrix data |> Matrix.mapiCols (fun i x -> Seq.max x) |> Array.ofSeq + let cols = + data + |> Matrix.ofJaggedArray + |> Matrix.getCols + let min = + cols + |> Array.map (fun v -> Vector.min v) + let max = + cols + |> Array.map (fun v -> Vector.max v) let range = Array.map2 (fun ma mi -> ma - mi) max min let generateUniform () = @@ -337,9 +346,12 @@ https://www.datanovia.com/en/lessons/determining-the-optimal-number-of-clusters- // |> Array.map (fun _ -> generateUniform s)) let dataMat = (JaggedArray.toArray2D data) let (u,s,vt) = Algebra.SVD.compute dataMat - let X' = (Matrix.ofJaggedArray data) * (Matrix.ofArray2D vt).Transpose - let min = X' |> Matrix.mapiCols (fun i x -> Seq.min x) |> Array.ofSeq - let max = X' |> Matrix.mapiCols (fun i x -> Seq.max x) |> Array.ofSeq + let X' = (Matrix.ofJaggedArray data) * (Matrix.ofArray2D vt).Transpose() + let colsX' = + X' + |> Matrix.getCols + let min = colsX' |> Array.map (fun v -> Vector.min v) + let max = colsX' |> Array.map (fun v -> Vector.max v) let range = Seq.map2 (fun ma mi -> ma - mi) max min |> Array.ofSeq let generateUniform () = min @@ -349,7 +361,7 @@ https://www.datanovia.com/en/lessons/determining-the-optimal-number-of-clusters- let generateUniformSVD = Array.init data.Length (fun x -> generateUniform()) //backtransform points to get reference data (Matrix.ofJaggedArray generateUniformSVD) * (Matrix.ofArray2D vt) - |> Matrix.toJaggedArray + |> fun m -> m.toJaggedArray() [] let generate_uniform_points_PCA (rnd:System.Random) = generateUniformPointsPCA rnd diff --git a/src/FSharp.Stats/ML/Unsupervised/IterativeClustering.fs b/src/FSharp.Stats/ML/Unsupervised/IterativeClustering.fs index ef4d04d64..695db9aea 100644 --- a/src/FSharp.Stats/ML/Unsupervised/IterativeClustering.fs +++ b/src/FSharp.Stats/ML/Unsupervised/IterativeClustering.fs @@ -62,7 +62,7 @@ module IterativeClustering = // cvmax - Algorithm by Moth’d Belal. Al-Daoud (Ref.: A New Algorithm for Cluster Initialization) let initCVMAX (sampleRows: float[] []) k = - let dmatrix = matrix sampleRows + let dmatrix = Matrix.ofJaggedArray sampleRows let cvmax = sampleRows |> JaggedArray.transpose From de7b7e8c7a09a6b7b93fc7e313c5b0afad417d86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20M=C3=BChlhaus?= Date: Wed, 9 Apr 2025 13:51:45 +0200 Subject: [PATCH 014/121] Refactor GLM into an external project with FSharp.Stats dependencies --- .../Fitting/GeneralisedLinearModel.fs | 697 ------------------ 1 file changed, 697 deletions(-) delete mode 100644 src/FSharp.Stats/Fitting/GeneralisedLinearModel.fs diff --git a/src/FSharp.Stats/Fitting/GeneralisedLinearModel.fs b/src/FSharp.Stats/Fitting/GeneralisedLinearModel.fs deleted file mode 100644 index 1653c5b4f..000000000 --- a/src/FSharp.Stats/Fitting/GeneralisedLinearModel.fs +++ /dev/null @@ -1,697 +0,0 @@ -namespace FSharp.Stats.Fitting.GLM - - -open System -open FSharp.Stats -open Algebra.LinearAlgebra - -/// -/// Represents the distribution families for Generalized Linear Models (GLMs). -/// -type GlmDistributionFamily = - /// Normal distribution family. - | Normal - /// Exponential distribution family. - | Exponential - /// Gamma distribution family. - | Gamma - /// Inverse Gaussian distribution family. - | InverseGaussian - /// Poisson distribution family. - | Poisson - /// Bernoulli distribution family. - | Bernouli - /// Binomial distribution family. - | Binomial - /// Categorical distribution family. - | Categorical - /// Multinomial distribution family. - | Multinomial - -/// -/// Represents a collection of link functions used in a generalized linear model. -/// -type LinkFunctions = - | GetLink of (float -> float) - | GetInvLink of (float -> float) - | GetInvLinkDerivative of (float -> float) - -/// -/// Represents a link function used in a generalized linear model. -/// -type LinkFunction = - { - /// Gets the link function. - getLink: float -> float - /// Gets the inverse link function. - getInvLink: float -> float - /// Gets the derivative of the link function. - getDeriv: float -> float - /// Gets the derivative of the inverse link function. - getInvLinkDerivative: float -> float - } - -/// -/// Represents the return type of a Generalised Linear Model (GLM). -/// -/// -/// This type contains the following elements: -/// -/// -/// -/// mX: The coefficients used in the GLM. -/// -/// -/// -/// -/// mu: The predicted mean values of the GLM. -/// -/// -/// -/// -type GLMReturn = - { - /// The coefficients used in the GLM. - mX: Vector - /// The predicted mean values of the GLM. - mu: Vector - } - -/// -/// Represents the statistics of a Generalised Linear Model (GLM). -/// -/// -/// This type contains the following elements: -/// -/// -/// -/// LogLikelihood: The log-likelihood of the GLM. -/// -/// -/// -/// -/// Deviance: The deviance of the GLM. -/// -/// -/// -/// -/// PearsonChi2: The Pearson chi-squared statistic of the GLM. -/// -/// -/// -/// -type GLMStatisticsModel = - { - /// The log-likelihood of the GLM. - LogLikelihood: float - /// The deviance of the GLM. - Deviance: float - /// The Pearson chi-squared statistic of the GLM. - PearsonChi2: float - //PseudoR2:float - } - -/// -/// Represents the parameters of a Generalised Linear Model (GLM). -/// -/// -/// This type contains the following elements: -/// -/// -/// -/// Coefficient: The coefficient of the parameter. -/// -/// -/// -/// -/// StandardError: The standard error of the parameter. -/// -/// -/// -/// -/// ZScore: The Z-score of the parameter. -/// -/// -/// -/// -/// PearsonOfZScore: The Pearson of the Z-score. -/// -/// -/// -/// -type GLMStatisticsPrameter = - { - //Name:string - /// The coefficient of the parameter. - Coefficient: float - /// The standard error of the parameter. - StandardError: float - /// The Z-score of the parameter. - ZScore: float - /// The Pearson of the Z-score. - PearsonOfZScore: float - } - -/// This module contains various link functions used in generalized linear models. -module LinkFunctions = - /// Clips the logistic values to avoid numerical instability. - let internal clipLogisticValues (p : float) = - let floatEps = 2.220446049250313e-16 - - max floatEps (min (1.0-floatEps) p) - - /// Clips the logistic values to avoid numerical instability. - let internal clipLogisticValues2 (p : float) = - let floatEps = 2.220446049250313e-16 - - max floatEps p - - /// The logit link function used in logistic regression. - let LogitLinkFunction : LinkFunction = - { - // Computes the link function value for a given parameter. - getLink = fun b -> - let p = clipLogisticValues b - System.Math.Log(p / (1.0 - p)) - // Computes the inverse link function value for a given parameter. - getInvLink = fun a -> - 1.0 / (1.0 + System.Math.Exp(-a)) - // Computes the derivative of the link function for a given parameter. - getDeriv = fun a -> - let p = clipLogisticValues a - 1./(p*(1.-p)) - // Computes the derivative of the inverse link function for a given parameter. - getInvLinkDerivative = fun a -> - let t = System.Math.Exp(a) - t / ((1.0 + t) * (1.0 + t)) - } - - /// The log link function used in Poisson regression. - let LogLinkFunction : LinkFunction = - { - // Computes the link function value for a given parameter. - getLink = fun b -> System.Math.Log((clipLogisticValues2 b)) - // Computes the inverse link function value for a given parameter. - getInvLink = fun a -> System.Math.Exp(a) - // Computes the derivative of the link function for a given parameter. - getDeriv = fun a -> 1./(clipLogisticValues2 a) - // Computes the derivative of the inverse link function for a given parameter. - getInvLinkDerivative = fun a -> System.Math.Exp(a) - } - - /// The inverse squared link function used in gamma regression. - let InverseSquaredLinkFunction: LinkFunction = - { - // Computes the link function value for a given parameter. - getLink = fun b -> Math.Pow(b,-2.)//1.0 / b - // Computes the inverse link function value for a given parameter. - getInvLink = fun a -> Math.Pow(a,(1./ -2.))//1.0 / a - // Computes the derivative of the link function for a given parameter. - getDeriv = fun a -> -2. * (Math.Pow(a,(-2.-1.))) - // Computes the derivative of the inverse link function for a given parameter. - getInvLinkDerivative = fun a -> - let inv1 = 1. - -2. - let inv2 = inv1 / -2. - let inv3 = Math.Pow(a,inv2) - inv3 / -2. - } - - /// The inverse link function used in inverse Gaussian regression. - let InverseLinkFunction: LinkFunction = - { - // Computes the link function value for a given parameter. - getLink = fun b -> Math.Pow(b,-1.)//1.0 / b - // Computes the inverse link function value for a given parameter. - getInvLink = fun a -> Math.Pow(a,-1.)//1.0 / a - // Computes the derivative of the link function for a given parameter. - getDeriv = fun a -> -1. * (Math.Pow(a,(-1.-1.))) - // Computes the derivative of the inverse link function for a given parameter. - getInvLinkDerivative = fun a -> - let inv1 = 1. - -1. - let inv2 = inv1 / -1. - let inv3 = Math.Pow(a,inv2) - inv3 / -1. - } - - /// The identity link function used in linear regression. - let IdentityLinkFunction: LinkFunction = - { - // Computes the link function value for a given parameter. - getLink = fun b -> b - // Computes the inverse link function value for a given parameter. - getInvLink = fun a -> a - // Computes the derivative of the link function for a given parameter. - getDeriv = fun a -> 1. - // Computes the derivative of the inverse link function for a given parameter. - getInvLinkDerivative = fun a -> 1. - } - - -module GlmDistributionFamily = - /// Cleans a floating-point value by replacing it with a minimum threshold value. - /// Returns the original value if it is greater than the threshold. - /// Otherwise, returns the threshold value. - let internal clean (p: float) = - let floatEps = 2.220446049250313e-16 - - max floatEps p - - /// Returns the sign of a floating-point value. - /// Returns 1.0 if the value is positive, 0.0 if it is zero, and -1.0 if it is negative. - let internal signFunction x = - if x > 0. then 1. - elif x = 0. then 0. - else -1. - - /// - /// Calculates the variance for a given distribution family and value. - /// - /// The distribution family. - /// The value for which to calculate the variance. - /// The variance for the given distribution family and value. - let getVariance (mDistributionFamily: GlmDistributionFamily) (g: float) = - - match mDistributionFamily with - | GlmDistributionFamily.Multinomial -> - g * (1.0 - g) - | GlmDistributionFamily.Gamma -> - (abs(g)) ** 2. - | GlmDistributionFamily.InverseGaussian -> - g * g * g - | GlmDistributionFamily.Normal -> - 1.0 - | GlmDistributionFamily.Poisson -> - (g) - | GlmDistributionFamily.Bernouli -> - g * (1.0 - g) - | GlmDistributionFamily.Binomial -> - let cleanG = max 1e-8 (min (1.0-1e-8) g) - cleanG * (1.0 - cleanG) - | GlmDistributionFamily.Categorical -> - g * (1.0 - g) - | GlmDistributionFamily.Exponential -> - g * (1.0 - g) - | _ -> - raise (System.NotImplementedException()) - - /// - /// Returns the link function associated with a distribution family. - /// - /// The distribution family. - /// The link function for the distribution family. - let getLinkFunction (mDistributionFamily: GlmDistributionFamily) = - match mDistributionFamily with - | GlmDistributionFamily.Multinomial -> - LinkFunctions.LogitLinkFunction - | GlmDistributionFamily.Gamma -> - LinkFunctions.InverseLinkFunction - | GlmDistributionFamily.InverseGaussian -> - LinkFunctions.InverseSquaredLinkFunction - | GlmDistributionFamily.Normal -> - LinkFunctions.IdentityLinkFunction - | GlmDistributionFamily.Poisson -> - LinkFunctions.LogLinkFunction - | GlmDistributionFamily.Exponential -> - LinkFunctions.LogitLinkFunction - | GlmDistributionFamily.Bernouli -> - LinkFunctions.LogitLinkFunction - | GlmDistributionFamily.Binomial -> - LinkFunctions.LogitLinkFunction - | GlmDistributionFamily.Categorical -> - LinkFunctions.LogitLinkFunction - | _ -> - raise (System.NotImplementedException()) - - /// - /// Returns the weights associated with a distribution family given the mean. - /// - /// The distribution family. - /// The mean vector. - /// The weights for the distribution family. - let getFamilyWeights (family: GlmDistributionFamily) (mu: Vector) = - let link = getLinkFunction family - let deriv = link.getDeriv - let variance = getVariance family - - mu - |> Vector.map(fun m -> - 1. / (((deriv m) ** 2) * (variance m)) - ) - - /// - /// Returns the residual deviance associated with a distribution family given the endogenous variable and the mean. - /// - /// The distribution family. - /// The endogenous variable. - /// The mean vector. - /// The residual deviance for the distribution family. - let getFamilyResidualDeviance (family: GlmDistributionFamily) (endog: Vector) (mu: Vector) = - match family with - | GlmDistributionFamily.Poisson -> - Vector.map2(fun endV muV -> - let a = clean(endV / muV) - let b = System.Math.Log(a) - let c = endV - muV - let d = endV * b - c - 2. * d - ) endog mu - |> Vector.sum - | GlmDistributionFamily.Normal -> - Vector.map2(fun endV muV -> - let a = endV - muV - a ** 2. - ) endog mu - |> Vector.sum - | GlmDistributionFamily.Gamma -> - Vector.map2(fun endV muV -> - let a = clean(endV / muV) - let b = System.Math.Log(a) - let c = endV - muV - let d = c / muV - let e = -b + d - 2. * d - ) endog mu - |> Vector.sum - // | GlmDistributionFamily.Binomial -> - // Vector.map2(fun endV muV -> - // let endogmu = clean(endV / (muV + 1e-20)) - // let nendogmu = clean((1. - endV) / (1. - muV + 1e-20)) - // endV * System.Math.Log(endogmu) + (1. - endV) * System.Math.Log(nendogmu) - // |> fun x -> 2. * x * tries - // ) endog mu - // |> Vector.sum - | GlmDistributionFamily.InverseGaussian -> - Vector.map2(fun endV muV -> - 1. / (endV * muV ** 2.) * (endV - muV) ** 2. - ) endog mu - |> Vector.sum - | _ -> - raise (System.NotImplementedException()) - - -module GLMStatistics = - - /// - /// Calculates the log-likelihood of a generalised linear model. - /// - /// The coefficient vector. - /// The mean vector. - /// The log-likelihood value. - let getLogLikelihood (b: Vector) (mu: Vector) = - Vector.mapi(fun i v -> - let y = b.[i] - let meanDist = v - y * System.Math.Log(meanDist) - meanDist - (SpecialFunctions.Gamma.gammaLn(y+1.0)) - ) mu - |> Vector.sum - - /// - /// Calculates the chi-square statistic for a generalised linear model. - /// - /// The coefficient vector. - /// The mean vector. - /// The distribution family. - /// The chi-square statistic value. - let getChi2 (b: Vector) (mu: Vector) (family: GlmDistributionFamily) = - Vector.map2(fun y yi -> - let a = y - yi - let nominator = a**2. - nominator / (GlmDistributionFamily.getVariance family yi) - ) b mu - |> Vector.sum - - /// - /// Calculates GLM statistics model. - /// - /// The coefficient vector. - /// The GLM return type. - /// The distribution family. - /// The GLM statistics model. - let getGLMStatisticsModel (b:Vector) (glmResult:GLMReturn) (family: GlmDistributionFamily) = - let logLikelihood = getLogLikelihood b glmResult.mu - let deviance = GlmDistributionFamily.getFamilyResidualDeviance family b glmResult.mu - let chi2 = getChi2 b glmResult.mu family - //let r2 = testR2 b (glmResult.mX * A) - - { - LogLikelihood=logLikelihood - Deviance=deviance - PearsonChi2=chi2 - //PseudoR2=0. - } - - /// - /// Calculates the standard errors for the coefficients in a generalized linear model. - /// The standard errors are calculated using the formula: sqrt(diagonal elements of (A^T * W * A)^-1) - /// where A is the design matrix, b is the response vector, and W is the weight vector. - /// - /// The design matrix. - /// The response vector. - /// The weight vector. - /// The standard errors. - let getStandardError (A: Matrix) (b: Vector) (W: Vector) = - let At :Matrix = Matrix.transpose A - let WMatrix = Matrix.diag W - let AtW = At * WMatrix - let AtWA :Matrix = AtW*A - let AtWAInv = Algebra.LinearAlgebra.Inverse AtWA - - let n = AtWAInv.NumRows - let m = Vector.length b - let stndErrors: Vector = - Vector.init n (fun v -> - Matrix.get AtWAInv v v - |> fun x -> System.Math.Sqrt(x) - ) - stndErrors - - /// - /// Calculates the Z-statistic for the coefficients in a generalized linear model. - /// The Z-statistic is calculated as the ratio of the coefficient estimate to its standard error. - /// - /// The coefficient vector. - /// The standard error vector. - /// The Z-statistic vector. - let getZStatistic (mx: Vector) (stndError: Vector) = - Vector.map2 (fun x y -> - x/y - ) mx stndError - - /// - /// Calculates the p-value using the z-statistic. - /// The p-value is calculated as 2 * (1 - phi), where phi is the cumulative distribution function (CDF) of the standard normal distribution. - /// The z-statistic is a vector of values for which the p-value is calculated. - /// - /// The Z-statistic vector. - /// The p-value vector. - let getPearsonOfZ (zStatistic: Vector) = - Vector.map(fun x -> - let phi = Distributions.Continuous.Normal.CDF 0. 1. (abs(x)) - let PearsonOfZScore = 2. * (1. - phi) - PearsonOfZScore - )zStatistic - - /// - /// Calculates the GLM parameter statistics. - /// - /// The design matrix. - /// The response vector. - /// The GLM return type. - /// The sequence of parameter names. - /// The sequence of parameter statistics for each element of the given coefficients - let getGLMParameterStatistics (A:Matrix) (b:Vector ) (solved:GLMReturn) (names:string seq) = - - let stndErrors = getStandardError A b solved.mu - let zStatistic = getZStatistic solved.mX stndErrors - let PearsonOfZScore = getPearsonOfZ zStatistic - Seq.init (Vector.length solved.mX) (fun i -> - Seq.item i names, - { - Coefficient=solved.mX.[i] - StandardError=stndErrors.[i] - ZScore=zStatistic.[i] - PearsonOfZScore=PearsonOfZScore.[i] - } - ) - -module internal QRSolver = - - /// - /// Performs a stepwise gain QR calculation for a generalised linear model. - /// This function calculates the cost, updated mean values, updated linear predictions, - /// weighted least squares results, and weighted least squares endogenous values for a given - /// matrix A, vector b, distribution family, vector t, vector mu, vector linPred, and old result. - /// - /// The design matrix. - /// The response vector. - /// The distribution family. - /// The vector t. - /// The mean vector. - /// The linear prediction vector. - /// The old result vector. - /// A tuple containing the cost, updated mean values, updated linear predictions, weighted least squares results, and weighted least squares endogenous values. - let stepwiseGainQR - (A: Matrix) - (b: Vector) - (mDistributionFamily: GlmDistributionFamily) - (t:Vector) - (mu:Vector) - (linPred:Vector) - (oldResult:Vector) - = - - let m = A.NumRows - let n = A.NumCols - - // Get the link function in accordance to the distribution type - let linkFunction= GlmDistributionFamily.getLinkFunction mDistributionFamily - - // Calculate the family weights for each observation - let famWeight = GlmDistributionFamily.getFamilyWeights mDistributionFamily mu - - // Calculate the self-weights for each observation - let selfWeights = - Vector.init m (fun i -> t[i] * (float 1.) * famWeight[i]) - - // Calculate the derivatives of the link function at each observation - let derivs = Vector.map(fun x -> linkFunction.getDeriv x) mu - - // Calculate the endogenous values for the weighted least squares - let wlsendog: Vector = Vector.init m (fun i -> linPred[i] + derivs[i] * (b[i]-mu[i])) - - // Calculate the weighted endogenous values and the weighted exogenous matrix - let wlsendog2,wlsexdog: Vector*Matrix = - let whalf = Vector.map(fun x -> System.Math.Sqrt(x)) selfWeights - let en = Vector.init m (fun i -> whalf[i] * wlsendog[i]) - let ex = - A - |> Matrix.toJaggedArray - |> Array.mapi(fun i x -> - x - |> Array.map(fun v -> v*whalf[i]) - ) - |> Matrix.ofJaggedArray - en,ex - - // Solve the linear system using QR decomposition - let (wlsResults: Vector),R = solveLinearQR wlsexdog wlsendog2 - - // Calculate the new linear predictions - let linPred_new: Vector = A * wlsResults - - // Calculate the new mean values - let mu_new = Vector.init m (fun i -> linkFunction.getInvLink(linPred_new[i])) - - // Calculate the cost of this step - let cost:float = - oldResult - wlsResults - |> Vector.norm - - cost,mu_new,linPred_new,wlsResults,wlsendog - - /// - /// This function performs a loop until the maximum number of iterations or until the cost for the gain is smaller than a given tolerance. - /// It uses a cost function to calculate the cost, update the parameters, and check the termination condition. - /// The loop stops when the maximum number of iterations is reached or when the cost is smaller than the tolerance. - /// Returns the final values of the parameters and intermediate results. - /// - /// The design matrix. - /// The response vector. - /// The distribution family. - /// The maximum number of iterations. - /// The tolerance for convergence. - /// The cost function. - /// A tuple containing the final values of the parameters and intermediate results. - let internal loopTilIterQR - (A: Matrix) - (b: Vector) - (mDistributionFamily: GlmDistributionFamily) - (maxIter: int) - (mTol: float) - (costFunction: - Matrix -> - Vector -> - GlmDistributionFamily -> - Vector -> - Vector -> - Vector -> - Vector -> - float * Vector * Vector * Vector * Vector - ) = - - let m = A.NumRows - let n = A.NumCols - - // Initialize an empty vector x - let t_original: Vector = Vector.init m (fun i -> 1.) - let bMean: float = Vector.mean b - let muStart:Vector = Vector.map(fun x -> ((x+bMean)/2.)) b - let linPredStart: Vector = Vector.init m (fun k -> GlmDistributionFamily.getLinkFunction(mDistributionFamily).getLink(muStart[k])) - - // Run the costFunction until maxIter has been reached or the cost for the gain is smaller than mTol - let rec loopTilMaxIter (t: Vector) (loopCount: int) (mu:Vector) (linPred:Vector) (wlsResult: Vector) (wlsendog: Vector) = - if loopCount = maxIter then - t_original,mu,linPred,wlsResult,wlsendog - else - let cost,mu_new,linPred_new,wlsResult_new,wlsendogNew = - costFunction - A - b - mDistributionFamily - t_original - mu - linPred - wlsResult - - if loopCount%10 = 0 then - printfn $"Iteration {loopCount}, Cost {cost}" - - if cost < mTol then - t_original,mu,linPred,wlsResult,wlsendog - else - loopTilMaxIter t_original (loopCount+1) mu_new linPred_new wlsResult_new wlsendogNew - - - loopTilMaxIter t_original 0 muStart linPredStart (Vector.zeroCreate n) (Vector.zeroCreate m) - - /// - /// Solves a generalized linear model using the QR decomposition and Newton's method. - /// - /// The design matrix. - /// The response vector. - /// The maximum number of iterations. - /// The distribution family of the model. - /// The tolerance for convergence. - /// The solved generalized linear model. - let solveQrNewton - (A: Matrix) - (b: Vector) - (maxIter: int) - (mDistributionFamily: GlmDistributionFamily) - (mTol: float) = - let m = A.NumRows - let n = A.NumCols - - System.Diagnostics.Debug.Assert(m >= n) - - let t,mu,linPred,wlsResult,wlsendog = - loopTilIterQR A b mDistributionFamily maxIter mTol stepwiseGainQR - - let mX,R = wlsResult,wlsendog - - {mX=mX;mu=mu} - -module SolveGLM = - - /// - /// Solves a generalized linear model using the QR decomposition and Newton's method. - /// - /// The design matrix. - /// The response vector. - /// The maximum number of iterations. - /// The distribution family of the model. - /// The tolerance for convergence. - /// The solved generalized linear model. - let solveQR (A: Matrix) (b: Vector) (maxIter: int) (mDistributionFamily: GlmDistributionFamily) (mTol: float) = - QRSolver.solveQrNewton (A: Matrix) (b: Vector) (maxIter: int) (mDistributionFamily: GlmDistributionFamily) (mTol: float) - From f9c37707763a27e2ee447b391e630bc4f9f7fb1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20M=C3=BChlhaus?= Date: Wed, 9 Apr 2025 13:52:58 +0200 Subject: [PATCH 015/121] Integrate new AlgTypes --- src/FSharp.Stats/FSIPrinters.fs | 2 +- src/FSharp.Stats/Permutation.fs | 75 ++++++++++++++++++++++++--------- 2 files changed, 56 insertions(+), 21 deletions(-) diff --git a/src/FSharp.Stats/FSIPrinters.fs b/src/FSharp.Stats/FSIPrinters.fs index 16fbc0788..dc37f480f 100644 --- a/src/FSharp.Stats/FSIPrinters.fs +++ b/src/FSharp.Stats/FSIPrinters.fs @@ -34,7 +34,7 @@ module FSIPrinters = //print row with row index and vertical separator let printRow index = - let currentRow = mat.Row index + let currentRow = Matrix.getRow index mat let toString (rv) = rv |> Seq.map (fun x -> diff --git a/src/FSharp.Stats/Permutation.fs b/src/FSharp.Stats/Permutation.fs index 3e726d09d..9be2edc52 100644 --- a/src/FSharp.Stats/Permutation.fs +++ b/src/FSharp.Stats/Permutation.fs @@ -1,41 +1,76 @@ -// (c) Microsoft Corporation 2005-2009. - -//namespace Microsoft.FSharp.Math // old namespace namespace FSharp.Stats -open System + +/// +/// A permutation represented as a function from indices to indices. +/// If P is a Permutation, then P(i) gives the +/// new row index for row i (or vice versa). +/// type Permutation = int -> int -type permutation = int -> int +/// +/// The Permutation module defines a type and helper functions +/// for representing and constructing permutations from integer arrays. +/// [] [] module Permutation = - let invalidArg arg msg = raise (new System.ArgumentException((msg:string),(arg:string))) + /// + /// Validates that the given integer array is a valid + /// permutation of length n (i.e., it contains every integer from + /// 0 to n-1 exactly once), then returns a function + /// P(i) = arr[i].
+ /// Throws an exception if is invalid. + ///
+ /// + /// The array containing the permutation. Each element arr[i] must + /// be a unique integer in [0..n-1]. + /// + /// + /// A permutation function Permutation where P(i) = arr[i]. + /// + let ofFreshArray (arr: int[]) : Permutation = + let n = arr.Length + let visited = Array.create n false + + // Validate that arr[i] is unique and in [0..n-1]. + for i = 0 to n - 1 do + let x = arr.[i] + if x < 0 || x >= n then + invalidArg (nameof arr) "Permutation array contains out-of-range index." + if visited.[x] then + invalidArg (nameof arr) "Permutation array contains duplicate indices." + visited.[x] <- true - let ofFreshArray (arr:_[]) = - let arr2 = Array.zeroCreate arr.Length - for i = 0 to arr.Length - 1 do - let x = arr.[i] - if x < 0 || x >= arr.Length then invalidArg "arr" "invalid permutation" - arr2.[x] <- 1 - for i = 0 to arr.Length - 1 do - if arr2.[i] <> 1 then invalidArg "arr" "invalid permutation" - (fun k -> arr.[k]) + // Return a function P(i) = arr[i]. + fun i -> + if i < 0 || i >= n then + invalidArg "i" "Permutation function called with out-of-range index." + arr.[i] - let ofArray (arr:_[]) = arr |> Array.copy |> ofFreshArray + /// + /// Makes a copy of , then calls . + /// Useful for preserving the original array. + /// + /// An array of length n that should represent + /// a valid permutation of 0..n-1. + /// + /// A Permutation function representing the same reordering as + /// . + /// + let ofArray (arr: int[]) : Permutation = + // Defensive copy + let copy = Array.copy arr + ofFreshArray copy - [] - let of_array (arr:_[]) = ofArray arr let ofPairs (mappings: seq) = let p = dict mappings (fun k -> if p.ContainsKey k then p.[k] else k) - [] - let of_pairs (mappings: seq) = ofPairs mappings let swap (n:int) (m:int) = (fun k -> if k = n then m elif k = m then n else k) From a5b0a602ef7d39c41247bcd27a80dc03ef8c3b14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20M=C3=BChlhaus?= Date: Wed, 9 Apr 2025 14:08:43 +0200 Subject: [PATCH 016/121] Refactoring Interpolation --- src/FSharp.Stats/Interpolation.fs | 146 +++++++++++++++--------------- 1 file changed, 73 insertions(+), 73 deletions(-) diff --git a/src/FSharp.Stats/Interpolation.fs b/src/FSharp.Stats/Interpolation.fs index 536e89612..bc0555726 100644 --- a/src/FSharp.Stats/Interpolation.fs +++ b/src/FSharp.Stats/Interpolation.fs @@ -186,7 +186,7 @@ module Interpolation = pown xData.[i] j ) let b = yData - PolynomialCoef.Create (LinearAlgebra.SolveLinearSystem A b) + PolynomialCoef.Create (LinearAlgebra.solveLinearSystem A b) /// /// takes polynomial coefficients and x value to predict the corresponding interpolating y value @@ -1050,11 +1050,11 @@ module Interpolation = /// Contains x data, y data (c0), slopes (c1), curvatures (c2), and the third derivative at each knot /// type CubicSplineCoef = { - XData : vector + XData : Vector /// /// vector of [a0;b0;c0;d0;a1;b1;...;d(n-2)] where f_n(x) = (an)x^3 + (bn)x^2 + (cn)x + (dn) /// - C0_3 : vector} with + C0_3 : Vector} with static member Create x c = {XData=x;C0_3=c} /// @@ -1160,11 +1160,11 @@ module Interpolation = let (xVal,yVal) = let indices = xValues - |> Seq.indexed - |> Seq.sortBy snd - |> Seq.map fst - let sortedXValues = indices |> Seq.map (fun i -> xValues.[i]) |> vector - let sortedYValues = indices |> Seq.map (fun i -> yValues.[i]) |> vector + |> Array.indexed + |> Array.sortBy snd + |> Array.map fst + let sortedXValues = indices |> Array.map (fun i -> xValues.[i]) + let sortedYValues = indices |> Array.map (fun i -> yValues.[i]) sortedXValues,sortedYValues let intervalNumber = xVal.Length - 1 @@ -1194,12 +1194,12 @@ module Interpolation = let (xVal,yVal,c1) = let indices = xValues - |> Seq.indexed - |> Seq.sortBy snd - |> Seq.map fst - let sortedXValues = indices |> Seq.map (fun i -> xValues.[i]) |> vector - let sortedYValues = indices |> Seq.map (fun i -> yValues.[i]) |> vector - let sortedslopes = indices |> Seq.map (fun i -> slopes.[i]) |> vector + |> Array.indexed + |> Array.sortBy snd + |> Array.map fst + let sortedXValues = indices |> Array.map (fun i -> xValues.[i]) + let sortedYValues = indices |> Array.map (fun i -> yValues.[i]) + let sortedslopes = indices |> Array.map (fun i -> slopes.[i]) sortedXValues,sortedYValues,sortedslopes let intervalNumber = xVal.Length - 1 @@ -1232,11 +1232,11 @@ module Interpolation = let (xVal,yVal) = let indices = xValues - |> Seq.indexed - |> Seq.sortBy snd - |> Seq.map fst - let sortedXValues = indices |> Seq.map (fun i -> xValues.[i]) |> vector - let sortedYValues = indices |> Seq.map (fun i -> yValues.[i]) |> vector + |> Array.indexed + |> Array.sortBy snd + |> Array.map fst + let sortedXValues = indices |> Array.map (fun i -> xValues.[i]) + let sortedYValues = indices |> Array.map (fun i -> yValues.[i]) sortedXValues,sortedYValues let intervalNumber = xVal.Length - 1 @@ -1267,12 +1267,12 @@ module Interpolation = let (xVal,yVal,c2) = let indices = xValues - |> Seq.indexed - |> Seq.sortBy snd - |> Seq.map fst - let sortedXValues = indices |> Seq.map (fun i -> xValues.[i]) |> vector - let sortedYValues = indices |> Seq.map (fun i -> yValues.[i]) |> vector - let sortedslopes = indices |> Seq.map (fun i -> curvature.[i]) |> vector + |> Array.indexed + |> Array.sortBy snd + |> Array.map fst + let sortedXValues = indices |> Array.map (fun i -> xValues.[i]) + let sortedYValues = indices |> Array.map (fun i -> yValues.[i]) + let sortedslopes = indices |> Array.map (fun i -> curvature.[i]) sortedXValues,sortedYValues,sortedslopes let intervalNumber = xVal.Length - 1 @@ -1303,11 +1303,11 @@ module Interpolation = let (xVal,yVal) = let indices = xValues - |> Seq.indexed - |> Seq.sortBy snd - |> Seq.map fst - let sortedXValues = indices |> Seq.map (fun i -> xValues.[i]) |> vector - let sortedYValues = indices |> Seq.map (fun i -> yValues.[i]) |> vector + |> Array.indexed + |> Array.sortBy snd + |> Array.map fst + let sortedXValues = indices |> Array.map (fun i -> xValues.[i]) + let sortedYValues = indices |> Array.map (fun i -> yValues.[i]) sortedXValues,sortedYValues let intervalNumber = xVal.Length - 1 @@ -1331,43 +1331,43 @@ module Interpolation = /// /// Interpolates x and y coordinates with given slopes at the knots. Curvature cannot be set anymore /// - let interpolateWithSlopes (x: vector) (y: vector) (slopes: vector) = + let interpolateWithSlopes (x: Vector) (y: Vector) (slopes: Vector) = let x',y',s' = - let order = x |> Seq.indexed |> Seq.sortBy snd |> Seq.map fst + let order = x |> Array.indexed |> Array.sortBy snd |> Array.map fst let l = Seq.length order - Vector.init l (fun i -> x.[order |> Seq.item i]), - Vector.init l (fun i -> y.[order |> Seq.item i]), - Vector.init l (fun i -> slopes.[order |> Seq.item i]) + Vector.init l (fun i -> x.[order[i]]), + Vector.init l (fun i -> y.[order[i]]), + Vector.init l (fun i -> slopes.[order[i]]) let interpol,i = getInterpolatingConstraints x' y' let slopes,s = getFstDerivativeConstraints x' y' s' let (equations,solutions) = [|interpol;slopes|] |> Array.concat, [|i;s|] |> Array.concat let A = Matrix.ofJaggedArray equations - let b = Vector.ofArray solutions + let b = solutions - let coeffs = Algebra.LinearAlgebra.SolveLinearSystem A b + let coeffs = Algebra.LinearAlgebra.solveLinearSystem A b CubicSplineCoef.Create x coeffs /// /// Interpolates x and y coordinates with given slopes at the knots. Probably makes no sense because slope isnt continuous anymore /// - let interpolateWithCurvature (x: vector) (y: vector) (curvatures: vector) = + let interpolateWithCurvature (x: Vector) (y: Vector) (curvatures: Vector) = let x',y',c' = - let order = x |> Seq.indexed |> Seq.sortBy snd |> Seq.map fst - let l = Seq.length order - Vector.init l (fun i -> x.[order |> Seq.item i]), - Vector.init l (fun i -> y.[order |> Seq.item i]), - Vector.init l (fun i -> curvatures.[order |> Seq.item i]) + let order = x |> Array.indexed |> Array.sortBy snd |> Array.map fst + let l = Array.length order + Vector.init l (fun i -> x.[order[i]]), + Vector.init l (fun i -> y.[order[i]]), + Vector.init l (fun i -> curvatures.[order[i]]) let interpol,i = getInterpolatingConstraints x' y' let curv,c = getSndDerivativeConstraints x' y' c' let (equations,solutions) = [|interpol;curv|] |> Array.concat, [|i;c|] |> Array.concat let A = Matrix.ofJaggedArray equations - let b = Vector.ofArray solutions + let b = solutions - let coeffs = Algebra.LinearAlgebra.SolveLinearSystem A b + let coeffs = Algebra.LinearAlgebra.solveLinearSystem A b CubicSplineCoef.Create x coeffs /// @@ -1566,9 +1566,9 @@ module Interpolation = |> Array.unzip let A = Matrix.ofJaggedArray equations - let b = Vector.ofArray solutions + let b = solutions - let coeffs = Algebra.LinearAlgebra.SolveLinearSystem A b + let coeffs = Algebra.LinearAlgebra.solveLinearSystem A b CubicSplineCoef.Create xVal coeffs @@ -1753,11 +1753,11 @@ module Interpolation = type HermiteCoef = { /// sample points, sorted ascending - XValues : vector + XValues : Vector /// Zero order spline coefficients, intersects, y values - YValues : vector + YValues : Vector /// First order spline coefficients, slopes at knots - Slopes : vector + Slopes : Vector } with static member Create xValues yValues slopes = { XValues=xValues;YValues=yValues;Slopes=slopes @@ -1822,7 +1822,7 @@ module Interpolation = | t when x <= first -> calculate 0 x | _ -> let i = - match Array.tryFindIndexBack (fun xs -> xs <= x) (this.XValues |> Vector.toArray) with + match Array.tryFindIndexBack (fun xs -> xs <= x) (this.XValues) with | Some x -> x | None -> failwith "The given xValue is out of the range defined in xData" calculate i x @@ -1965,11 +1965,11 @@ module Interpolation = let (xVal,yVal) = let order = xData - |> Seq.indexed - |> Seq.sortBy snd - |> Seq.map fst - Vector.init xData.Length (fun i -> xData.[Seq.item i order]), - Vector.init xData.Length (fun i -> yData.[Seq.item i order]) + |> Array.indexed + |> Array.sortBy snd + |> Array.map fst + Vector.init xData.Length (fun i -> xData.[Array.item i order]), + Vector.init xData.Length (fun i -> yData.[Array.item i order]) let calcSlope i = let s1 = (xVal.[i+1] - xVal.[i]) / (yVal.[i+1] - yVal.[i]) @@ -1995,8 +1995,8 @@ module Interpolation = let slope = s1 - s2 slope - let slopes = loop 1 [slopeAtFstKnot] - HermiteCoef.Create xVal yVal (slopes |> vector) + let slopes = (loop 1 [slopeAtFstKnot]) |> Array.ofList + HermiteCoef.Create xVal yVal slopes /// @@ -2069,7 +2069,7 @@ module Interpolation = slope let slopes = loop 1 [slopeAtFstKnot] - slopes |> vector + slopes |> Array.ofList [] module Simple = @@ -2138,15 +2138,15 @@ module Interpolation = /// Bezier interpolates data between 2 points using a number of control points, which determine the degree of the interpolated curve. /// module Bezier = - let inline lerp (p1: vector) (p2: vector) (t: float) = - p1 + t * (p2 - p1) + let inline lerp (p1: Vector) (p2: Vector) (t: float) = + p1 .+ t .* (p2 .- p1) /// /// This implements Bezier interpolation using De Casteljau's algorithm. /// /// an array containg the starting point, the control points, and the end point to use for interpolation /// The generated interpolation function - let interpolate (values: vector []): (float -> vector) = + let interpolate (values: Vector []): (float -> Vector) = if values.Length < 2 then invalidArg (nameof values) "There must be at least 2 points" fun t -> let results = Array.copy values @@ -2219,7 +2219,7 @@ module Interpolation = center + halfrange * cos(Math.PI * (2. * (float i + 1.) - 1.)/(2. * float n)) ) |> Array.sort - |> vector + /// /// Creates a collection of ordered x values within a given interval. The spacing of the values is always the same. @@ -2247,11 +2247,11 @@ module Interpolation = match spacing with | Approximation.Equally -> let xVal = Approximation.equalNodes i n - let yVal = Vector.map f xVal + let yVal = Array.map f xVal Polynomial.interpolate xVal yVal | Approximation.Chebyshev -> let xVal = Approximation.chebyshevNodes i n - let yVal = Vector.map f xVal + let yVal = Array.map f xVal Polynomial.interpolate xVal yVal /// @@ -2270,14 +2270,14 @@ module Interpolation = let linearSplineCoeff = LinearSpline.interpolate (Array.ofSeq xData) (Array.ofSeq yData) let f = LinearSpline.predict linearSplineCoeff let xVal = Approximation.equalNodes i n - let yVal = Vector.map f xVal + let yVal = Array.map f xVal Polynomial.interpolate xVal yVal | Approximation.Chebyshev -> let i = Interval.ofSeq xData let linearSplineCoeff = LinearSpline.interpolate (Array.ofSeq xData) (Array.ofSeq yData) let f = LinearSpline.predict linearSplineCoeff let xVal = Approximation.chebyshevNodes i n - let yVal = Vector.map f xVal + let yVal = Array.map f xVal Polynomial.interpolate xVal yVal //open FSharp.Stats @@ -2337,7 +2337,7 @@ type HermiteMethod = /// Creates a spline from x,y coordinates. x,y coordinates are interpolated by cubic polynomialsbetween two knots. /// The slope at each knot is defined by a input slope vector. /// - | WithSlopes of vector + | WithSlopes of Vector /// /// Creates a spline from x,y coordinates. x,y coordinates are interpolated by cubic polynomials between two knots. /// If a region in the raw data is monotone, the resulting interpolator is monotone as well. @@ -2452,14 +2452,14 @@ type Interpolation() = match method with | InterpolationMethod.Step -> Step.interpolate xData yData |> InterpolationCoefficients.StepCoef | InterpolationMethod.LinearSpline -> LinearSpline.interpolate xData yData |> InterpolationCoefficients.LinearSplineCoef - | InterpolationMethod.Polynomial -> Polynomial.interpolate (vector xData) (vector yData) |> InterpolationCoefficients.PolynomialCoef - | InterpolationMethod.CubicSpline bc -> CubicSpline.interpolate bc (vector xData) (vector yData) |> InterpolationCoefficients.CubicSplineCoef + | InterpolationMethod.Polynomial -> Polynomial.interpolate xData yData |> InterpolationCoefficients.PolynomialCoef + | InterpolationMethod.CubicSpline bc -> CubicSpline.interpolate bc xData yData |> InterpolationCoefficients.CubicSplineCoef | InterpolationMethod.AkimaSubSpline -> Akima.interpolate xData yData |> InterpolationCoefficients.AkimaSubSplineCoef | InterpolationMethod.HermiteSpline s -> match s with - | HermiteMethod.CSpline -> CubicSpline.Hermite.interpolate (vector xData) (vector yData) |> InterpolationCoefficients.HermiteSplineCoef - | HermiteMethod.WithSlopes s -> CubicSpline.Hermite.interpolateWithSlopes (vector xData) (vector yData) s |> InterpolationCoefficients.HermiteSplineCoef - | HermiteMethod.PreserveMonotonicity -> CubicSpline.Hermite.interpolatePreserveMonotonicity (vector xData) (vector yData) |> InterpolationCoefficients.HermiteSplineCoef + | HermiteMethod.CSpline -> CubicSpline.Hermite.interpolate xData yData |> InterpolationCoefficients.HermiteSplineCoef + | HermiteMethod.WithSlopes s -> CubicSpline.Hermite.interpolateWithSlopes xData yData s |> InterpolationCoefficients.HermiteSplineCoef + | HermiteMethod.PreserveMonotonicity -> CubicSpline.Hermite.interpolatePreserveMonotonicity xData yData |> InterpolationCoefficients.HermiteSplineCoef interpolate method xValues yValues /// From a417172a1181a2a64528db7d409575b2c80b13da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20M=C3=BChlhaus?= Date: Wed, 9 Apr 2025 14:46:36 +0200 Subject: [PATCH 017/121] Updated savitzkyGolay --- src/FSharp.Stats/Signal/Filtering.fs | 158 +++++++++++++++++---------- 1 file changed, 98 insertions(+), 60 deletions(-) diff --git a/src/FSharp.Stats/Signal/Filtering.fs b/src/FSharp.Stats/Signal/Filtering.fs index ca337e139..353f4587b 100644 --- a/src/FSharp.Stats/Signal/Filtering.fs +++ b/src/FSharp.Stats/Signal/Filtering.fs @@ -2,7 +2,7 @@ open System open FSharp.Stats - +open FSharp.Stats.Algebra module Filtering = @@ -38,67 +38,105 @@ module Filtering = // let chebeshevFilter = // 0 - - - - /// Smooth (and optionally differentiate) data with a Savitzky-Golay filter.
The Savitzky-Golay filter is a type of low-pass filter and removes high frequency noise from data. - // Parameters - // ---------- - // data : array_like, shape (N,) - // the values of the time history of the signal. - // windowSize : int - // the length of the window. Must be an odd integer number. - // order : int - // the order of the polynomial used in the filtering. - // Must be less then `windowSize` - 1. - // deriv: int - // the order of the derivative to compute (default = 0 means only smoothing) - // - // The Savitzky-Golay is a type of low-pass filter, particularly suited for smoothing noisy data. - // The main idea behind this approach is to make for each point a least-square fit with a - // polynomial of high order over a odd-sized window centered at the point. - let savitzkyGolay (windowSize:int) (order:int) deriv rate (data:float[]) = - /// - let correlateValid (x:Vector) (y:Vector) = - if x.Length >= y.Length then - [|Vector.dot x y|] - else - let n = x.Length - [|for i=1 to y.Length-n do - yield Vector.dot x y.[i..i+n-1] |] - - + /// + /// "Valid" cross-correlation of a kernel with a signal . + /// Returns an array of length (signal.Length - kernel.Length + 1) if signal.Length >= kernel.Length, + /// otherwise a single dot product if kernel.Length > signal.Length. + /// + /// Vector of length K (FIR filter, etc.). + /// Vector of length N. + /// + /// An array of length max(1, N-K+1) with the "valid" correlation result. Typically used for FIR filtering. + /// + let correlateValid (kernel: Vector) (signal: Vector) : float[] = + let kLen = kernel.Length + let sLen = signal.Length + + if sLen < kLen then + // The original code returned a single dot if kernel longer than signal + [| Vector.dotProduct kernel signal |] + else + // We produce sLen - kLen + 1 outputs + let outLen = sLen - kLen + 1 + Array.init outLen (fun i -> + // dot kernel with signal[i.. i+kLen-1] + Vector.dotProduct kernel signal.[i .. i + kLen - 1] + ) + + + /// + /// Smooth (or differentiate) data with a Savitzky–Golay filter of given + /// and polynomial . The parameter specifies the + /// derivative order to compute (0 = smoothing only). The helps scale the + /// derivative if deriv > 0. + /// + /// Must be odd and at least (order+2) if deriving. + /// Polynomial order (must be >= deriv). A higher order can better fit curvature. + /// Order of derivative to compute (0 => smoothing). + /// Scaling factor for derivative, typically sampling rate = 1.0 if no special scale needed. + /// The data vector to filter (length N). + /// + /// A float[] array with the filtered (or derived) signal, of length = data.Length. + /// + let savitzkyGolay (windowSize:int) (order:int) (deriv:int) (rate:float) (data: Vector) : float[] = + // 0) Validate parameters if windowSize % 2 <> 1 || windowSize < 1 then - failwith "windowSize size must be a positive odd number" + failwith "windowSize must be a positive odd integer." if order < deriv then - failwith "order must be greater or equal to the used derivative" + failwith "Polynomial order must be >= derivative order." if windowSize < order + 2 then - failwith "windowSize is too small for the polynomials order" - //let orderRange = [0..order] + failwithf "windowSize (%d) is too small for polynomial order (%d)." windowSize order + + let n = data.Length + if n < windowSize then + failwithf "Data length (%d) smaller than windowSize (%d)." n windowSize + + // 1) Precompute "b" matrix of shape (windowSize × (order+1)). + // b[k, col] = (float(k - halfWindow))^(col) let halfWindow = (windowSize - 1) / 2 - // precompute coefficients - let b = Matrix.init (halfWindow*2 + 1) (order+1) (fun k coli -> float(k-halfWindow)**float(coli)) - - let m = (Algebra.LinearAlgebraManaged.pseudoInvers b).Row(deriv) * ((float(rate)**float(deriv)) * SpecialFunctions.Factorial.factorial(deriv)) - //pad the signal at the extremes with values taken from the signal itself - - let firstvals = - let length = halfWindow + 1 - Array.init length (fun i -> - data.[0] - (abs data.[length-i] - data.[0])) - - let lastvals = - Array.init halfWindow (fun i -> - data.[data.Length-1] - (abs data.[data.Length-(2+i)] - data.[data.Length-1]) ) - - let y = - Array.concat [firstvals; data; lastvals;] |> vector - - correlateValid m.Transpose y + let b = + Matrix.init windowSize (order + 1) (fun k col -> + // k goes 0..(windowSize-1), so "center" is k - halfWindow + let x = float (k - halfWindow) + x ** float col + ) + + // 2) Pseudoinverse of b => shape = ((order+1) × windowSize). + // Then we select row(deriv), which is shape (1 × windowSize). + // We'll scale it by (rate^deriv * factorial(deriv)) if derivative is requested. + let bInv = LinearAlgebra.pseudoInvers b + // The row we want is bInv.Row(deriv), which is a 1×windowSize slice -> treat as Vector + let rowDeriv = Matrix.getRow deriv bInv // shape (1, windowSize), but we can interpret as Vector + + // Scale row by factor = rate^deriv * factorial(deriv) + let factor = (rate ** float(deriv)) * float (FSharp.Stats.SpecialFunctions.Factorial.factorial deriv) + let m = factor .* rowDeriv // final FIR coefficients (length = windowSize) + + // 3) Build the padded signal array "y" at both ends to handle "valid" portion + // Pad with a reflection scheme: for the left side, reflect the first part of data; + // for the right side, reflect the last part. + let firstvals = + // halfWindow+1 elements for the left pad + Array.init (halfWindow) (fun i -> + let diff = data.[(halfWindow - i)] - data.[0] + data.[0] - diff + ) + |> Array.rev // ensure the left-most index is for i=0 + + let lastvals = + // halfWindow elements for the right pad + Array.init halfWindow (fun i -> + let diff = data.[n-1] - data.[(n-2 - i)] + data.[n-1] + diff + ) + + let yVec = Array.concat [ firstvals; data; lastvals ] + + // 4) Correlate "m" with padded "y" in "valid" mode, i.e. output length = data.Length + let result = correlateValid m yVec + + result - [] - let savitzky_golay (windowSize:int) (order:int) deriv rate (data:float[]) = - savitzkyGolay windowSize order deriv rate data /// Estimates the autocorrelation at lag 1 of a blank signal (containing only noise). Subsequently, the signal of interest is smoothed
several times by a savitzky golay filter using constant polynomial order and variing windowWidth. For each iteration, the deviation
of the smoothed to the original signal is computed and the autocorrelation at lag 1 of this residual noise is computed. The function returns the optimized
window width yielding a autocorrelation at lag 1 closest to the value computed for the blank signal.
/// Method is based on: https://doi.org/10.1021/ac0600196 @@ -112,15 +150,15 @@ module Filtering = /// /// let optimizeWindowWidth polOrder (windowWidthToTest:int[]) (blankSignal:float[]) (signalOfInterest:float[]) = - let signalOfInterest' = signalOfInterest |> vector - let noiseAutoCorr = Correlation.Vector.autoCorrelation 1 (blankSignal |> vector) + let signalOfInterest' = signalOfInterest + let noiseAutoCorr = Correlation.Vector.autoCorrelation 1 (blankSignal) let filterF w yData = savitzkyGolay w polOrder 0 0 yData let windowWidthToTest' = windowWidthToTest |> Array.filter (fun x -> x%2 <> 0) let optimizedWindowWidth = windowWidthToTest' |> Array.map (fun w -> let smoothedY = filterF w signalOfInterest - let noise = (vector smoothedY) - (signalOfInterest') + let noise = (smoothedY) .- (signalOfInterest') w, Correlation.Vector.autoCorrelation 1 noise ) |> Array.minBy (fun (w,ac) -> (ac - noiseAutoCorr) |> abs ) From e421198b76ae4f64e830fa6cdcaaa0275ba73bed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20M=C3=BChlhaus?= Date: Wed, 9 Apr 2025 17:45:52 +0200 Subject: [PATCH 018/121] Normalization needs a revision --- src/FSharp.Stats/Signal/Normalization.fs | 239 +++++++++++------------ 1 file changed, 119 insertions(+), 120 deletions(-) diff --git a/src/FSharp.Stats/Signal/Normalization.fs b/src/FSharp.Stats/Signal/Normalization.fs index 5712150ba..6678980fe 100644 --- a/src/FSharp.Stats/Signal/Normalization.fs +++ b/src/FSharp.Stats/Signal/Normalization.fs @@ -16,10 +16,10 @@ module Normalization = /// /// /// Bortz J., Schuster C., Statistik für Human- und Sozialwissenschaftler, 7 (2010), p. 35 - let zScoreTransformPopulation (yVal:Vector) = + let zScoreTransformPopulation (yVal:Vector) : Vector = let yMean = Seq.mean yVal let std = Seq.stDevPopulation yVal - yVal |> Vector.map (fun x -> (x - yMean) / std) + yVal |> Array.map (fun x -> (x - yMean) / std) /// /// z score normalization/transformation using the sample standard deviation. Rarely used since variance is not equal to 1. @@ -33,135 +33,134 @@ module Normalization = /// /// /// Bortz J., Schuster C., Statistik für Human- und Sozialwissenschaftler, 7 (2010), p. 35 - let zScoreTransform (yVal:Vector) = + let zScoreTransform (yVal:Vector) : Vector = let yMean = Seq.mean yVal let std = Seq.stDev yVal - yVal |> Vector.map (fun x -> (x - yMean) / std) + yVal |> Array.map (fun x -> (x - yMean) / std) /// Summary of the median of ratios (mor) normalization with normed data, determined correctionfactors, and transformation function. type MorResult = { CorrFactors : seq NormedData : Matrix - NormFunction : matrix -> matrix + NormFunction : Matrix -> Matrix } with static member Create cf nd f = {CorrFactors=cf;NormedData=nd;NormFunction=f} - /// - /// Median of ratios normalization As used by Deseq2, see: https://github.com/hbctraining/DGE_workshop/blob/master/lessons/02_DGE_count_normalization.md . - /// Rows are genes, columns are samples - /// - /// The transformation function is applied on all values of the matrix before calculating the normalization factors. - /// data matrix with columns as features (samples,time points) and rows as measured entities (genes,proteins). - /// Normalized data matrix with correction factors and normalization function. - /// - /// - /// // raw data with proteins as rows and samples as columns - /// let myData = Matrix.init 500 5 (fun _ _ -> rnd.NextDouble()) - /// let normedData = Normalization.medianOfRatiosBy (fun x -> ln (x+1)) myData - /// - /// - let medianOfRatiosBy (f: float -> float) (data: Matrix) = - let sampleWiseCorrectionFactors = - data - |> Matrix.mapiRows (fun _ v -> - let v = RowVector.map f v - let geometricMean = Seq.meanGeometric v - RowVector.map (fun s -> s / geometricMean) v - ) - |> Matrix.ofRows - |> Matrix.mapiCols (fun _ v -> Vector.median v) - let normData m = - m - |> Matrix.mapi (fun r c v -> - v / sampleWiseCorrectionFactors.[c] - ) - MorResult.Create sampleWiseCorrectionFactors (normData data) normData + ///// + ///// Median of ratios normalization As used by Deseq2, see: https://github.com/hbctraining/DGE_workshop/blob/master/lessons/02_DGE_count_normalization.md . + ///// Rows are genes, columns are samples + ///// + ///// The transformation function is applied on all values of the matrix before calculating the normalization factors. + ///// data matrix with columns as features (samples,time points) and rows as measured entities (genes,proteins). + ///// Normalized data matrix with correction factors and normalization function. + ///// + ///// + ///// // raw data with proteins as rows and samples as columns + ///// let myData = Matrix.init 500 5 (fun _ _ -> rnd.NextDouble()) + ///// let normedData = Normalization.medianOfRatiosBy (fun x -> ln (x+1)) myData + ///// + ///// + //let medianOfRatiosBy (f: float -> float) (data: Matrix) = + // let sampleWiseCorrectionFactors = + // data + // |> Matrix.mapiRows (fun _ v -> + // let v = Array.map f v + // let geometricMean = Seq.meanGeometric v + // Array.map (fun s -> s / geometricMean) v + // ) + // |> Matrix.mapiCols (fun _ (v:Vector) -> Seq.median v) + // let normData m = + // m + // |> Matrix.mapi (fun r c v -> + // v / sampleWiseCorrectionFactors.[c] + // ) + // MorResult.Create sampleWiseCorrectionFactors (normData data) normData - /// - /// Median of ratios normalization As used by Deseq2, see: https://github.com/hbctraining/DGE_workshop/blob/master/lessons/02_DGE_count_normalization.md . - /// Rows are genes, columns are samples - /// - /// data matrix with columns as features (samples,time points) and rows as measured entities (genes,proteins). - /// Normalized data matrix with correction factors and normalization function. - /// - /// - /// // raw data with proteins as rows and samples as columns - /// let myData = Matrix.init 500 5 (fun _ _ -> rnd.NextDouble()) - /// let normedData = Normalization.medianOfRatios myData - /// - /// - let medianOfRatios (data:Matrix) = - medianOfRatiosBy id data + ///// + ///// Median of ratios normalization As used by Deseq2, see: https://github.com/hbctraining/DGE_workshop/blob/master/lessons/02_DGE_count_normalization.md . + ///// Rows are genes, columns are samples + ///// + ///// data matrix with columns as features (samples,time points) and rows as measured entities (genes,proteins). + ///// Normalized data matrix with correction factors and normalization function. + ///// + ///// + ///// // raw data with proteins as rows and samples as columns + ///// let myData = Matrix.init 500 5 (fun _ _ -> rnd.NextDouble()) + ///// let normedData = Normalization.medianOfRatios myData + ///// + ///// + //let medianOfRatios (data:Matrix) = + // medianOfRatiosBy id data - /// - /// Median of ratios normalization As used by Deseq2, see: https://github.com/hbctraining/DGE_workshop/blob/master/lessons/02_DGE_count_normalization.md . - /// Columns are genes, rows are samples - /// - /// The transformation function is applied on all values of the matrix before calculating the normalization factors. - /// data matrix with columns as measured entities and rows as features (samples,time points) (genes,proteins). - /// Normalized data matrix with correction factors and normalization function. - /// - /// - /// // raw data with proteins as columns and samples as rows - /// let myData = Matrix.init 5 500 (fun _ _ -> rnd.NextDouble()) - /// let normedData = Normalization.medianOfRatiosWideBy (fun x -> ln (x+1)) myData - /// - /// - let medianOfRatiosWideBy (f: float -> float) (data:Matrix) = - let sampleWiseCorrectionFactors = - data - |> Matrix.mapiCols (fun _ v -> - let v = Vector.map f v - let geometricMean = Seq.meanGeometric v - Vector.map (fun s -> s / geometricMean) v - ) - |> Matrix.ofCols - |> Matrix.mapiRows (fun _ v -> Seq.median v) - let normData m = - m - |> Matrix.mapi (fun r c v -> - v / sampleWiseCorrectionFactors.[r] - ) - MorResult.Create sampleWiseCorrectionFactors (normData data) normData + ///// + ///// Median of ratios normalization As used by Deseq2, see: https://github.com/hbctraining/DGE_workshop/blob/master/lessons/02_DGE_count_normalization.md . + ///// Columns are genes, rows are samples + ///// + ///// The transformation function is applied on all values of the matrix before calculating the normalization factors. + ///// data matrix with columns as measured entities and rows as features (samples,time points) (genes,proteins). + ///// Normalized data matrix with correction factors and normalization function. + ///// + ///// + ///// // raw data with proteins as columns and samples as rows + ///// let myData = Matrix.init 5 500 (fun _ _ -> rnd.NextDouble()) + ///// let normedData = Normalization.medianOfRatiosWideBy (fun x -> ln (x+1)) myData + ///// + ///// + //let medianOfRatiosWideBy (f: float -> float) (data:Matrix) = + // let sampleWiseCorrectionFactors = + // data + // |> Matrix.mapiCols (fun _ v -> + // let v = Vector.map f v + // let geometricMean = Seq.meanGeometric v + // Vector.map (fun s -> s / geometricMean) v + // ) + // |> Matrix.ofCols + // |> Matrix.mapiRows (fun _ v -> Seq.median v) + // let normData m = + // m + // |> Matrix.mapi (fun r c v -> + // v / sampleWiseCorrectionFactors.[r] + // ) + // MorResult.Create sampleWiseCorrectionFactors (normData data) normData - /// - /// Median of ratios normalization As used by Deseq2, see: https://github.com/hbctraining/DGE_workshop/blob/master/lessons/02_DGE_count_normalization.md . - /// Columns are genes, rows are samples - /// - /// data matrix with columns as measured entities and rows as features (samples,time points) (genes,proteins). - /// Normalized data matrix with correction factors and normalization function. - /// - /// - /// // raw data with proteins as columns and samples as rows - /// let myData = Matrix.init 5 500 (fun _ _ -> rnd.NextDouble()) - /// let normedData = Normalization.medianOfRatiosWide myData - /// - /// - let medianOfRatiosWide (data:Matrix) = - medianOfRatiosWideBy id data + ///// + ///// Median of ratios normalization As used by Deseq2, see: https://github.com/hbctraining/DGE_workshop/blob/master/lessons/02_DGE_count_normalization.md . + ///// Columns are genes, rows are samples + ///// + ///// data matrix with columns as measured entities and rows as features (samples,time points) (genes,proteins). + ///// Normalized data matrix with correction factors and normalization function. + ///// + ///// + ///// // raw data with proteins as columns and samples as rows + ///// let myData = Matrix.init 5 500 (fun _ _ -> rnd.NextDouble()) + ///// let normedData = Normalization.medianOfRatiosWide myData + ///// + ///// + //let medianOfRatiosWide (data:Matrix) = + // medianOfRatiosWideBy id data - /// - /// Quantile normalization with equal number of elements (rows) for each sample (column). - /// Column mean and column standard deviation are qual after normalization. - /// Rows are genes, columns are samples. - /// - /// data matrix with columns as measured entities and rows as features (samples,time points) (genes,proteins). - /// Normalized data matrix. - /// - /// - /// // raw data with proteins as rows and samples as columns - /// let myData = Matrix.init 500 5 (fun _ _ -> rnd.NextDouble()) - /// let normedData = Normalization.quantile myData - /// - /// - let quantile (data:Matrix) = - data - |> Matrix.mapCols (Seq.indexed >> Seq.sortBy snd) - |> Matrix.Generic.ofColSeq - |> Matrix.Generic.mapRows (fun row -> - let avg = Seq.meanBy snd row - row |> RowVector.Generic.map (fun (i,_) -> i,avg) - ) - |> Matrix.Generic.ofSeq - |> Matrix.Generic.mapCols (Seq.sortBy fst >> Seq.map snd >> vector) - |> Matrix.ofCols + ///// + ///// Quantile normalization with equal number of elements (rows) for each sample (column). + ///// Column mean and column standard deviation are qual after normalization. + ///// Rows are genes, columns are samples. + ///// + ///// data matrix with columns as measured entities and rows as features (samples,time points) (genes,proteins). + ///// Normalized data matrix. + ///// + ///// + ///// // raw data with proteins as rows and samples as columns + ///// let myData = Matrix.init 500 5 (fun _ _ -> rnd.NextDouble()) + ///// let normedData = Normalization.quantile myData + ///// + ///// + //let quantile (data:Matrix) = + // data + // |> Matrix.mapCols (Seq.indexed >> Seq.sortBy snd) + // |> Matrix.Generic.ofColSeq + // |> Matrix.Generic.mapRows (fun row -> + // let avg = Seq.meanBy snd row + // row |> RowVector.Generic.map (fun (i,_) -> i,avg) + // ) + // |> Matrix.Generic.ofSeq + // |> Matrix.Generic.mapCols (Seq.sortBy fst >> Seq.map snd >> vector) + // |> Matrix.ofCols From b714e2059a512746bae2f744435ed026ccfd99b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20M=C3=BChlhaus?= Date: Wed, 9 Apr 2025 17:49:19 +0200 Subject: [PATCH 019/121] Integrate in Signal --- src/FSharp.Stats/AlgTypes/MatrixExt.fs | 26 +++++++- src/FSharp.Stats/FSharp.Stats.fsproj | 29 +++------ src/FSharp.Stats/Signal/Baseline.fs | 62 +++++++++---------- src/FSharp.Stats/Signal/Convolution.fs | 2 +- src/FSharp.Stats/Signal/Outliers.fs | 84 +++++++++++++------------- src/FSharp.Stats/Signal/QQPlot.fs | 19 +++--- 6 files changed, 117 insertions(+), 105 deletions(-) diff --git a/src/FSharp.Stats/AlgTypes/MatrixExt.fs b/src/FSharp.Stats/AlgTypes/MatrixExt.fs index bf0acce03..aa3f95959 100644 --- a/src/FSharp.Stats/AlgTypes/MatrixExt.fs +++ b/src/FSharp.Stats/AlgTypes/MatrixExt.fs @@ -105,4 +105,28 @@ module Matrix = let srcRow = P i // Copy row srcRow from M into row i of the new matrix Array.blit M.Data (srcRow * c) newData (i * c) c - Matrix<'T>(r, c, newData) \ No newline at end of file + Matrix<'T>(r, c, newData) + + let ofRows (rows : 'T[][]) : Matrix<'T> = + Matrix.ofJaggedArray rows + + let mapiRows (f: int -> Vector<'T> -> Vector<'U>) (m:Matrix<'T>) : Matrix<'U> = + Matrix.getRows m + |> Array.mapi (fun i v -> f i v) + |> ofRows + + let ofCols (cols : 'T[][]) : Matrix<'T> = + Matrix.ofJaggedArray cols + |> fun m -> m.Transpose() + + let mapiCols (f: int -> Vector<'T> -> Vector<'U>) (m:Matrix<'T>) : Matrix<'U> = + let cols = + Array.init m.NumCols (fun j -> + let col = Array.zeroCreate<'T> m.NumRows + let mutable offset = j + for i = 0 to m.NumRows - 1 do + col.[i] <- m.Data.[offset] + offset <- offset + m.NumCols + f j col + ) + ofCols cols \ No newline at end of file diff --git a/src/FSharp.Stats/FSharp.Stats.fsproj b/src/FSharp.Stats/FSharp.Stats.fsproj index c0ee4e4f2..7565d7d93 100644 --- a/src/FSharp.Stats/FSharp.Stats.fsproj +++ b/src/FSharp.Stats/FSharp.Stats.fsproj @@ -28,29 +28,27 @@ + + + + + + + + - - - - - - - - - - @@ -64,16 +62,10 @@ + - - - - - - - @@ -152,15 +144,12 @@ - - - diff --git a/src/FSharp.Stats/Signal/Baseline.fs b/src/FSharp.Stats/Signal/Baseline.fs index 627cb8e49..cbdef104b 100644 --- a/src/FSharp.Stats/Signal/Baseline.fs +++ b/src/FSharp.Stats/Signal/Baseline.fs @@ -53,60 +53,60 @@ module Baseline = let baselineAls (maxiter:int) (lambda:int) (p:float) (data:float[]) = let dMatrix' = let dMatrix = Matrix.ofArray2D (diff 2 (diag data.Length 1.)) - (pown 10. lambda) * (dMatrix * dMatrix.Transpose) + (pown 10. lambda) * (dMatrix * dMatrix.Transpose()) - let wInitial = Vector.create (data.Length) 1. - let y = Vector.ofArray data + let wInitial = Array.create (data.Length) 1. + let y = data let rec loop niter (w:Vector) = if niter < 1 then - let wMatrix = Matrix.diag w + let wMatrix = Matrix.diagonal w let zMatrix = wMatrix + dMatrix' - Algebra.LinearAlgebra.SolveLinearSystem zMatrix (w .* y) + Algebra.LinearAlgebra.solveLinearSystem zMatrix (w .* y) //zMatrix.Solve(w .* y) else - let wMatrix = Matrix.diag w + let wMatrix = Matrix.diagonal w let zMatrix = wMatrix + dMatrix' //let z = zMatrix.Solve(w .* y) - let z = Algebra.LinearAlgebra.SolveLinearSystem zMatrix (w .* y) + let z = Algebra.LinearAlgebra.solveLinearSystem zMatrix (w .* y) // w = p * (y > z) + (1-p) * (y < z) - let w' = Vector.map2 (fun yi zi -> if yi > zi then p else (1.-p)) y z + let w' = Array.map2 (fun yi zi -> if yi > zi then p else (1.-p)) y z loop (niter-1) w' loop maxiter wInitial - /// Asymmetric Least Squares Smoothing using sparse Matrix - // by P. Eilers and H. Boelens in 2005 - let baselineAls' (maxiter:int) (lambda:int) (p:float) (data:float[]) = - let dMatrix' = - let dMatrix = - (diff 2 (diag data.Length 1.)) - |> Matrix.sparseOfArray2D - (10.**float lambda) * (dMatrix * dMatrix.Transpose) + ///// Asymmetric Least Squares Smoothing using sparse Matrix + //// by P. Eilers and H. Boelens in 2005 + //let baselineAls' (maxiter:int) (lambda:int) (p:float) (data:float[]) = + // let dMatrix' = + // let dMatrix = + // (diff 2 (diag data.Length 1.)) + // |> Matrix.sparseOfArray2D + // (10.**float lambda) * (dMatrix * dMatrix.Transpose) - let wInitial = Vector.create (data.Length) 1. - let y = Vector.ofArray data + // let wInitial = Vector.create (data.Length) 1. + // let y = Vector.ofArray data - let rec loop niter (w:Vector) = - if niter < 1 then - let wMatrix = Matrix.toSparse (Matrix.diag w) - let zMatrix = wMatrix + dMatrix' + // let rec loop niter (w:Vector) = + // if niter < 1 then + // let wMatrix = Matrix.toSparse (Matrix.diag w) + // let zMatrix = wMatrix + dMatrix' - FSharp.Stats.Algebra.LinearAlgebraManaged.leastSquares zMatrix (w .* y) - else - let wMatrix = Matrix.toSparse (Matrix.diag w) - let zMatrix = wMatrix + dMatrix' - let z = FSharp.Stats.Algebra.LinearAlgebraManaged.leastSquares zMatrix (w .* y) - // w = p * (y > z) + (1-p) * (y < z) - let w' = Vector.map2 (fun yi zi -> if yi > zi then p else (1.-p)) y z + // FSharp.Stats.Algebra.LinearAlgebraManaged.leastSquares zMatrix (w .* y) + // else + // let wMatrix = Matrix.toSparse (Matrix.diag w) + // let zMatrix = wMatrix + dMatrix' + // let z = FSharp.Stats.Algebra.LinearAlgebraManaged.leastSquares zMatrix (w .* y) + // // w = p * (y > z) + (1-p) * (y < z) + // let w' = Vector.map2 (fun yi zi -> if yi > zi then p else (1.-p)) y z - loop (niter-1) w' + // loop (niter-1) w' - loop maxiter wInitial + // loop maxiter wInitial diff --git a/src/FSharp.Stats/Signal/Convolution.fs b/src/FSharp.Stats/Signal/Convolution.fs index f8aa23e5d..fc1b56fff 100644 --- a/src/FSharp.Stats/Signal/Convolution.fs +++ b/src/FSharp.Stats/Signal/Convolution.fs @@ -15,7 +15,7 @@ module Convolution = /// /// /// - let convolve (v1:vector) (v2:vector) = + let convolve (v1:Vector<'T>) (v2:Vector<'T>) = let k = (v1.Length+v2.Length-1) let tmp = Vector.zeroCreate k for i = 0 to v1.Length-1 do diff --git a/src/FSharp.Stats/Signal/Outliers.fs b/src/FSharp.Stats/Signal/Outliers.fs index a209ceed5..5dda0ff2f 100644 --- a/src/FSharp.Stats/Signal/Outliers.fs +++ b/src/FSharp.Stats/Signal/Outliers.fs @@ -91,46 +91,46 @@ module Outliers = let s = Seq.stDev(ls) Interval.CreateClosed ((minZ * s + m),(maxZ * s + m)) - ///Returns Mahalanobi's distance for an individual observation in a matrix. - ///dataSource - Sample or Population. - /// orientation - RowWise or ColWise. - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - let mahalanobisDistanceOfEntry (dataMatrix:matrix) (dataSource:DataSource) (orientation:Orientation) (observation:seq) :float = - let sub (a:seq) b = Seq.map2 (fun xa xb -> xb - xa) a b - let invertedCovarianceMatrix = Algebra.LinearAlgebra.Inverse (covarianceMatrixOf dataSource orientation.Inverse dataMatrix) - let meanVector = Matrix.meanAsSeq orientation.Inverse dataMatrix - let subObsMean = Matrix.ofJaggedColSeq([sub observation meanVector]) - let multObsCov = Matrix.mul (subObsMean.Transpose) invertedCovarianceMatrix - let distance = Matrix.toScalar(Matrix.mul multObsCov subObsMean) - sqrt distance + /////Returns Mahalanobi's distance for an individual observation in a matrix. + /////dataSource - Sample or Population. + ///// orientation - RowWise or ColWise. + ///// + ///// + ///// + ///// + ///// + ///// + ///// + ///// + ///// + ///// + //let mahalanobisDistanceOfEntry (dataMatrix:Matrix) (dataSource:DataSource) (orientation:Orientation) (observation:seq) :float = + // let sub (a:seq) b = Seq.map2 (fun xa xb -> xb - xa) a b + // let invertedCovarianceMatrix = Algebra.LinearAlgebra.Inverse (covarianceMatrixOf dataSource orientation.Inverse dataMatrix) + // let meanVector = Matrix.meanAsSeq orientation.Inverse dataMatrix + // let subObsMean = Matrix.ofJaggedColSeq([sub observation meanVector]) + // let multObsCov = Matrix.mul (subObsMean.Transpose) invertedCovarianceMatrix + // let distance = Matrix.toScalar(Matrix.mul multObsCov subObsMean) + // sqrt distance - ///Returns Mahalanobi's distance for for every observation in a matrix. - ///dataSource - Sample or Population. - /// orientation - RowWise or ColWise. (RowWise orientation means that each row is a Vector) - /// - /// - /// - /// - /// - /// - /// - /// - /// - let mahalanobisDistances (dataSource:DataSource) (orientation:Orientation) (dataMatrix:matrix) = - let getObsList = - match orientation with - |ColWise -> - dataMatrix.Transpose - |> Matrix.toJaggedArray - |RowWise -> - dataMatrix |> Matrix.toJaggedArray - getObsList |> Array.map (mahalanobisDistanceOfEntry dataMatrix dataSource orientation) \ No newline at end of file + /////Returns Mahalanobi's distance for for every observation in a matrix. + /////dataSource - Sample or Population. + ///// orientation - RowWise or ColWise. (RowWise orientation means that each row is a Vector) + ///// + ///// + ///// + ///// + ///// + ///// + ///// + ///// + ///// + //let mahalanobisDistances (dataSource:DataSource) (orientation:Orientation) (dataMatrix:Matrix) = + // let getObsList = + // match orientation with + // |ColWise -> + // dataMatrix.Transpose + // |> Matrix.toJaggedArray + // |RowWise -> + // dataMatrix |> Matrix.toJaggedArray + // getObsList |> Array.map (mahalanobisDistanceOfEntry dataMatrix dataSource orientation) \ No newline at end of file diff --git a/src/FSharp.Stats/Signal/QQPlot.fs b/src/FSharp.Stats/Signal/QQPlot.fs index 679f59809..0014e2c85 100644 --- a/src/FSharp.Stats/Signal/QQPlot.fs +++ b/src/FSharp.Stats/Signal/QQPlot.fs @@ -70,16 +70,15 @@ module QQPlot = /// Computes the quantile quantile coordinates of a sample distributions against a normal distribution. /// The sample can be z transformed. StandardMethod = Rankit // tested against R qqnorm - let internal fromSampleToGauss method zTransformSample (sample:seq) = + let internal fromSampleToGauss method zTransformSample (sample:Vector) = let sampleLength = Seq.length sample |> float let standardizedData = if zTransformSample then - Signal.Normalization.zScoreTransformPopulation (vector sample) - |> Vector.toArray + Signal.Normalization.zScoreTransformPopulation sample else - sample |> Seq.toArray + sample let getQuantile rank = match method with @@ -109,15 +108,15 @@ module QQPlot = /// /// /// - let internal fromSampleToUniform method standardizeSample (sample:seq) = + let internal fromSampleToUniform method standardizeSample (sample:Vector) = let sampleLength = Seq.length sample |> float let standardizedSample = if standardizeSample then - let min = Seq.min sample - let max = Seq.max sample - sample |> Seq.map (fun x -> (x-min) / (max-min)) + let min = Vector.min sample + let max = Vector.max sample + sample |> Array.map (fun x -> (x-min) / (max-min)) else sample @@ -175,7 +174,7 @@ type QQPlot() = let standardize = defaultArg ZTransform false let method = defaultArg Method QQPlot.QuantileMethod.Rankit - fun (sample: seq) -> + fun (sample: Vector) -> QQPlot.fromSampleToGauss method standardize sample /// Computes the quantile quantile coordinates of a sample distributions against a normal distribution. @@ -185,7 +184,7 @@ type QQPlot() = let standardize = defaultArg Standardize false let method = defaultArg Method QQPlot.QuantileMethod.Rankit - fun (sample: seq) -> + fun (sample: Vector) -> QQPlot.fromSampleToUniform method standardize sample /// Computes the quantile quantile coordinates of a sample distributions against a specified inverseCDF function. You can derive an inverse CDF of any statistical distribution. From d3d9aea61dee633d84c7bac9237f5642cfd0d095 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20M=C3=BChlhaus?= Date: Fri, 11 Apr 2025 08:25:16 +0200 Subject: [PATCH 020/121] Change to Numeric. Compiles but without test! --- src/FSharp.Stats/AlgTypes/Matrix.fs | 59 +++++++++++ src/FSharp.Stats/AlgTypes/MatrixExt.fs | 64 +++++++++++- src/FSharp.Stats/AlgTypes/Vector.fs | 15 ++- src/FSharp.Stats/AlgTypes/VectorExt.fs | 19 +++- src/FSharp.Stats/AlgTypes/VectorOps.fs | 14 ++- src/FSharp.Stats/Algebra/LinearAlgebra.fs | 40 +++++++- src/FSharp.Stats/Correlation.fs | 38 ++++---- .../Continuous/MultivariateNormal.fs | 35 ++++--- .../Distributions/Discrete/Multinomial.fs | 20 ++-- .../Distributions/Distribution.fs | 4 +- src/FSharp.Stats/FSharp.Stats.fsproj | 4 +- src/FSharp.Stats/Fitting/CrossValidation.fs | 2 +- src/FSharp.Stats/Fitting/GoodnessOfFit.fs | 2 +- src/FSharp.Stats/Fitting/LinearRegression.fs | 10 +- .../Fitting/LogisticRegression.fs | 2 +- .../Fitting/NonLinearRegression.fs | 30 +++--- src/FSharp.Stats/Optimization/NelderMead.fs | 37 ++++--- src/FSharp.Stats/Permutation.fs | 16 +++ src/FSharp.Stats/Seq.fs | 10 +- src/FSharp.Stats/Signal/Filtering.fs | 4 +- src/FSharp.Stats/Testing/ConfusionMatrix.fs | 4 +- src/FSharp.Stats/Testing/RMT.fs | 2 +- src/FSharp.Stats/Testing/TTest.fs | 6 +- src/FSharp.Stats/Testing/Tables.fs | 97 +++++++++---------- 24 files changed, 363 insertions(+), 171 deletions(-) diff --git a/src/FSharp.Stats/AlgTypes/Matrix.fs b/src/FSharp.Stats/AlgTypes/Matrix.fs index a960e5b11..ccfd95f57 100644 --- a/src/FSharp.Stats/AlgTypes/Matrix.fs +++ b/src/FSharp.Stats/AlgTypes/Matrix.fs @@ -563,6 +563,64 @@ type Matrix<'T when 'T :> Numerics.INumber<'T> Matrix(m.NumRows, cols, resultData) + + /// + /// Computes row-vector v (length = mat.NumRows) times matrix mat (size = [NumRows × NumCols]), + /// returning a new vector of length mat.NumCols. Uses chunk-based SIMD with manual gather. + /// + static member inline multiplyRowVector<'T + when 'T :> Numerics.INumber<'T> + and 'T : struct + and 'T : (new : unit -> 'T) + and 'T :> ValueType> + (v: Vector<'T>) + (mat: Matrix<'T>) : Vector<'T> = + + let n = mat.NumRows + let m = mat.NumCols + if v.Length <> n then + invalidArg (nameof v) "Vector length must match mat.NumRows." + + let result = Vector.zeroCreate<'T> m + + // We'll chunk over v in blocks of 'simdSize'. For each column j, + // we gather that column's slice [ (i*m + j) for i in 0..n-1 ] in blocks. + let simdSize = Numerics.Vector<'T>.Count + + for j in 0 .. m - 1 do + // sumVec accumulates partial sums in vector-lanes + let mutable sumVec = Numerics.Vector<'T>.Zero + + // 1) Process as many full 'simdSize' blocks as possible + let blockCount = n / simdSize + let tailStart = blockCount * simdSize + + for blockIndex in 0 .. blockCount - 1 do + let baseIdx = blockIndex * simdSize + + // Gather the column’s elements for this block into 'gatherArr' + // These are mat.Data.[(baseIdx + s)*m + j] for s in [0..simdSize-1] + let gatherArr = Vector.zeroCreate<'T> simdSize + for s in 0 .. simdSize - 1 do + gatherArr.[s] <- mat.Data.[(baseIdx + s) * m + j] + + let colVec = Numerics.Vector<'T>(gatherArr) // column-block chunk + let rowVec = Numerics.Vector<'T>(v, baseIdx) // row vector chunk + sumVec <- sumVec + (rowVec * colVec) + + // 2) Reduce sumVec’s lanes into a scalar + let mutable colSum = 'T.Zero + for lane in 0 .. simdSize - 1 do + colSum <- colSum + sumVec.[lane] + + // 3) Handle any leftover elements (remainder) + for i in tailStart .. n - 1 do + colSum <- colSum + v.[i] * mat.Data.[i*m + j] + + result.[j] <- colSum + + result + // Matrix - matrix operations static member inline ( + ) (a: Matrix<'T>, b: Matrix<'T>) = Matrix.add a b static member inline ( - ) (a: Matrix<'T>, b: Matrix<'T>) = Matrix.subtract a b @@ -571,6 +629,7 @@ type Matrix<'T when 'T :> Numerics.INumber<'T> // Matrix - vector operations static member inline ( * ) (m: Matrix<'T>, v: Vector<'T>) = Matrix.muliplyVector m v + static member inline ( * ) (v: Vector<'T>, m: Matrix<'T>) = Matrix.multiplyRowVector v m // static member inline ( + ) (m: Matrix<'T>, colVector: Vector<'T>) = Matrix.addColVector m colVector // static member inline ( +| ) (m: Matrix<'T>, rowVector: Vector<'T>) = Matrix.addRowVector m rowVector diff --git a/src/FSharp.Stats/AlgTypes/MatrixExt.fs b/src/FSharp.Stats/AlgTypes/MatrixExt.fs index aa3f95959..d9cf579a3 100644 --- a/src/FSharp.Stats/AlgTypes/MatrixExt.fs +++ b/src/FSharp.Stats/AlgTypes/MatrixExt.fs @@ -98,13 +98,13 @@ module Matrix = /// /// A new matrix of the same dimensions r x c, with rows permuted by . /// - let permuteRowsBy (P: Permutation) (M: Matrix<'T>) : Matrix<'T> = - let r, c = M.NumRows, M.NumCols + let permuteRowsBy (P: Permutation) (m: Matrix<'T>) : Matrix<'T> = + let r, c = m.NumRows, m.NumCols let newData = Array.zeroCreate<'T> (r * c) for i = 0 to r - 1 do let srcRow = P i // Copy row srcRow from M into row i of the new matrix - Array.blit M.Data (srcRow * c) newData (i * c) c + Array.blit m.Data (srcRow * c) newData (i * c) c Matrix<'T>(r, c, newData) let ofRows (rows : 'T[][]) : Matrix<'T> = @@ -129,4 +129,60 @@ module Matrix = offset <- offset + m.NumCols f j col ) - ofCols cols \ No newline at end of file + ofCols cols + + /// + /// Applies a function to each element of the matrix, + /// returning a new matrix with updated values. The iteration occurs in + /// row-major order for performance. + /// + /// + /// A function taking (rowIndex, colIndex, oldValue) + /// and returning the new value for that position. + /// + /// A new Matrix with updated elements. + let mapi (f: int -> int -> 'T -> 'U) (A: Matrix<'T>) : Matrix<'U> = + let newData = Array.zeroCreate<'U> A.Data.Length + let rows, cols = A.NumRows, A.NumCols + for i in 0 .. rows - 1 do + let rowOffset = i * cols + for j in 0 .. cols - 1 do + let idx = rowOffset + j + newData.[idx] <- f i j A.Data.[idx] + Matrix<'U>(rows, cols, newData) + + + let map (f: 'T -> 'U) (m:Matrix<'T>) : Matrix<'U> = + let r, c = m.NumRows, m.NumCols + let newData = + m.Data |> Array.map f + Matrix<'U>(r, c, newData) + + + /// + /// Folds over each element in row-major order, accumulating a result of type 'State. + /// The callback receives (currentState, rowIndex, colIndex, elementValue), + /// and returns the new state. + /// + /// A function taking (state, i, j, value) -> newState. + /// The initial accumulation state. + /// The matrix to fold over. + /// The final accumulated state. + let foldi + (f : int -> int -> 'State -> 'T -> 'State ) + (initialState : 'State) + (A : Matrix<'T>) + : 'State = + + let mutable acc = initialState + let rows, cols = A.NumRows, A.NumCols + for i in 0 .. rows - 1 do + let rowOffset = i * cols + for j in 0 .. cols - 1 do + let idx = rowOffset + j + acc <- f i j acc A.Data.[idx] + acc + + /// Sums all elements in the matrix. + let sum (m:Matrix<'T>) : 'T = + m.Data |> Vector.sum \ No newline at end of file diff --git a/src/FSharp.Stats/AlgTypes/Vector.fs b/src/FSharp.Stats/AlgTypes/Vector.fs index eba35ac1d..29523787d 100644 --- a/src/FSharp.Stats/AlgTypes/Vector.fs +++ b/src/FSharp.Stats/AlgTypes/Vector.fs @@ -3,10 +3,15 @@ open System open System.Runtime.InteropServices -/// Vector as a Array type alias +/// Vector as an array type alias type Vector<'T when 'T :> Numerics.INumber<'T>> = 'T [] type Vector = + + + static member inline zeroCreate<'T when 'T :> Numerics.INumber<'T>> count : Vector<'T> = + Array.zeroCreate<'T> count + /// Adds two vectors element-wise. /// The first vector. @@ -184,18 +189,18 @@ type Vector = let sum = Vector.sum v LanguagePrimitives.DivideByInt<'T> sum v.Length - /// Computes the dot product of two vectors. + /// Computes the dot product ab^T of two vectors. /// The first vector. /// The second vector. /// The dot product of the two vectors. /// Thrown when the vectors have different lengths. - static member inline dotProduct<'T when 'T :> Numerics.INumber<'T> + static member inline dot<'T when 'T :> Numerics.INumber<'T> and 'T : (new: unit -> 'T) and 'T : struct and 'T :> ValueType> (v1 : Vector<'T>) (v2 : Vector<'T>) : 'T = if v1.Length <> v2.Length then - invalidArg "v2" "Arrays must have the same length." + invalidArg "v2" "Vector must have the same length to compute the dot product." if Numerics.Vector.IsHardwareAccelerated then let length = v1.Length let slotSize = Numerics.Vector<'T>.Count @@ -229,7 +234,7 @@ type Vector = and 'T :> Numerics.IRootFunctions<'T>> (v:Vector<'T>) : 'T = - let sumSquares = Vector.dotProduct v v + let sumSquares = Vector.dot v v 'T.Sqrt sumSquares static member inline min<'T when 'T :> Numerics.INumber<'T> diff --git a/src/FSharp.Stats/AlgTypes/VectorExt.fs b/src/FSharp.Stats/AlgTypes/VectorExt.fs index 3badfca7d..ed6ba70b2 100644 --- a/src/FSharp.Stats/AlgTypes/VectorExt.fs +++ b/src/FSharp.Stats/AlgTypes/VectorExt.fs @@ -6,8 +6,19 @@ open System.Runtime.InteropServices [] module Vector = - let inline zeroCreate<'T when 'T :> Numerics.INumber<'T>> count : Vector<'T> = - Array.zeroCreate<'T> count + /// Computes the vector cross product a^Tb + /// The first vector is column vector. + /// The second vector is the row vector. + /// The cross product of the two vectors. + let inline cross<'T when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T :> ValueType> (colvec: Vector<'T>) (rowvec:Vector<'T>) : Matrix<'T> = + if colvec.Length <> rowvec.Length then + invalidArg "" "Vector must have the same length to compute the dot product." + let data = Acceleration.SIMDUtils.map2Unchecked ( * ) ( * ) colvec rowvec + Matrix(colvec.Length,rowvec.Length,data) + /// Indexed fold over a vector let inline foldi<'T when 'T :> Numerics.INumber<'T>> f (state: 'T) (v: Vector<'T>) : 'T = @@ -145,8 +156,8 @@ module Vector = let n = v.Length let k = indices.Length - let nvi = zeroCreate<'T> k - let nv = zeroCreate<'T> (n - k) + let nvi = Vector.zeroCreate<'T> k + let nv = Vector.zeroCreate<'T> (n - k) let mutable iInd = 0 let mutable iNvi = 0 diff --git a/src/FSharp.Stats/AlgTypes/VectorOps.fs b/src/FSharp.Stats/AlgTypes/VectorOps.fs index 127395a1f..5d338291c 100644 --- a/src/FSharp.Stats/AlgTypes/VectorOps.fs +++ b/src/FSharp.Stats/AlgTypes/VectorOps.fs @@ -35,4 +35,16 @@ module VectorOpsSymbols = let inline (.+) a b = Plus.Invoke(a, b) let inline (.-) a b = Minus.Invoke(a, b) let inline (.*) a b = Multiply.Invoke(a, b) - let inline (./) a b = Divide.Invoke(a, b) \ No newline at end of file + let inline (./) a b = Divide.Invoke(a, b) + + +//// A type extension on `'T[]` so you can do `myArray.Transposed`. +//module ArrayExtensions = + +// type Array with + +// member this.Transpose + +// with get () = +// RowVector<'T>(this) + diff --git a/src/FSharp.Stats/Algebra/LinearAlgebra.fs b/src/FSharp.Stats/Algebra/LinearAlgebra.fs index 9dde6a896..e3cc65a1f 100644 --- a/src/FSharp.Stats/Algebra/LinearAlgebra.fs +++ b/src/FSharp.Stats/Algebra/LinearAlgebra.fs @@ -58,7 +58,7 @@ type LinearAlgebra = for i = 0 to j - 1 do let qi = qCols.[i] - let rij = Vector.dotProduct qi v + let rij = Vector.dot qi v r.[i, j] <- rij for k = 0 to m - 1 do v.[k] <- v.[k] - rij * qi.[k] @@ -629,3 +629,41 @@ type LinearAlgebra = false // Return sᵀ => the actual pseudoinverse shape (n×m) s.Transpose() + + + /// + /// Computes the determinant of a square matrix A by factoring A = P * L * U, + /// then det(A) = sign(P) * ∏ diag(U). + /// (Assumes L has diag=1, as in Doolittle.) + /// + static member inline determinant (A: Matrix) : float = + let n = A.NumRows + if n <> A.NumCols then + invalidArg (nameof A) "Matrix must be square." + + // 1) Factor A => (P, L, U) + let (P, L, U) = LinearAlgebra.luDecompose A + + // 2) Compute sign from the permutation P with domain size n + let permSign = Permutation.sign n P + + // 3) Product of diag(U) + let diagProd = + let mutable product = 1.0 + for i = 0 to n - 1 do + product <- product * U.Data.[i*n + i] + product + + // 4) Return sign(P) * product + permSign * diagProd + + + static member inline SVD (a:Matrix) = + let (umatrix,s,vmatrix) = SVD.computeInPlace (a.toArray2D()) + //Matrix.diag + s,Matrix.ofArray2D umatrix,Matrix.ofArray2D vmatrix + //(Matrix.ofArray2D umatrix,s,Matrix.ofArray2D vmatrix) + + static member inline symmetricEigenspectrum (a:Matrix) = + let (e,v,d) = EVD.symmetricEvd (a.toArray2D()) + (Matrix.ofArray2D v, d) diff --git a/src/FSharp.Stats/Correlation.fs b/src/FSharp.Stats/Correlation.fs index 40c122c5a..7651f1677 100644 --- a/src/FSharp.Stats/Correlation.fs +++ b/src/FSharp.Stats/Correlation.fs @@ -665,7 +665,7 @@ module Correlation = /// /// /// - let correlationOf (corrF: vector -> vector -> float) lag (v1:vector) (v2:vector) = + let correlationOf (corrF: Vector -> Vector -> float) lag (v1:Vector) (v2:Vector) = if v1.Length <> v2.Length then failwithf "Vectors need to have the same length." if lag >= v1.Length then failwithf "lag must be smaller than input length" let v1' = v1.[0..(v1.Length-1 - lag)] @@ -694,7 +694,7 @@ module Correlation = /// /// let autoCovariance lag seq = - correlationOf Vector.cov lag seq seq + correlationOf Array.cov lag seq seq /// computes the normalized (using pearson correlation) cross-correlation of signals v1 and v2 at a given lag. /// @@ -731,9 +731,9 @@ module Correlation = /// /// /// - let bicor (vec1:vector) (vec2:vector) = + let bicor (vec1:Vector) (vec2:Vector) = - let xs,ys = vec1.Values, vec2.Values + let xs,ys = vec1, vec2 let xMed = xs |> Array.median let xMad = xs |> Array.medianAbsoluteDev @@ -764,12 +764,10 @@ module Correlation = /// /// /// - let rv2 (x: matrix) (y: matrix) = - let xxt = x*x.Transpose - let yyt = y*y.Transpose - xxt |> Matrix.inplace_mapi (fun r c x -> if r = c then 0. else x) - yyt |> Matrix.inplace_mapi (fun r c x -> if r = c then 0. else x) - let num = (xxt*yyt).Diagonal |> Vector.sum + let rv2 (x: Matrix) (y: Matrix) = + let xxt = x*x.Transpose() |> Matrix.mapi (fun r c x -> if r = c then 0. else x) // change back to inplace + let yyt = y*y.Transpose() |> Matrix.mapi (fun r c x -> if r = c then 0. else x) + let num = (xxt*yyt) |> Matrix.getDiagonal |> Vector.sum let deno1 = xxt |> Matrix.map (fun x -> x**2.) |> Matrix.sum |> sqrt let deno2 = yyt |> Matrix.map (fun x -> x**2.) |> Matrix.sum |> sqrt num / (deno1 * deno2) @@ -783,15 +781,15 @@ module Correlation = /// /// /// - let rowWiseCorrelationMatrix (corrFunction : seq -> seq -> float) (m : matrix) = - let vectors = Matrix.toJaggedArray m + let rowWiseCorrelationMatrix (corrFunction : seq -> seq -> float) (m : Matrix) = + let vectors = m.toJaggedArray() let result : float [] [] = [|for i=0 to vectors.Length-1 do yield (Array.init vectors.Length (fun innerIndex -> if i=innerIndex then 1. else 0.))|] for i=0 to vectors.Length-1 do for j=i+1 to vectors.Length-1 do let corr = corrFunction vectors.[i] vectors.[j] result.[i].[j] <- corr result.[j].[i] <- corr - result |> matrix + result |> Matrix.ofRows /// computes a matrix that contains the metric given by the corrFunction parameter applied columnwise for every column against every other column of the input matrix /// @@ -803,8 +801,7 @@ module Correlation = /// /// let columnWiseCorrelationMatrix (corrFunction : seq -> seq -> float) (m : Matrix) = - m - |> Matrix.transpose + m.Transpose() |> (rowWiseCorrelationMatrix corrFunction) /// computes the rowwise pearson correlation matrix for the input matrix @@ -839,9 +836,9 @@ module Correlation = /// /// /// - let rowWiseBicor (m : matrix) = + let rowWiseBicor (m : Matrix) = - let vectors = Matrix.toJaggedArray m + let vectors = m.toJaggedArray() let result : float [] [] = [|for i=0 to vectors.Length-1 do yield (Array.init vectors.Length (fun innerIndex -> if i=innerIndex then 1. else 0.))|] let meds : float [] = Array.zeroCreate vectors.Length @@ -869,7 +866,7 @@ module Correlation = xs xWeights vectors.[j] weightss.[j] result.[i].[j] <- corr result.[j].[i] <- corr - result |> matrix + result |> Matrix.ofRows /// Computes the columnwise biweighted midcorrelation matrix for the input matrix /// @@ -879,9 +876,8 @@ module Correlation = /// /// /// - let columnWiseBicor (m : matrix) = - m - |> Matrix.transpose + let columnWiseBicor (m : Matrix) = + m.Transpose() |> rowWiseBicor ///// Computes rowise pearson correlation diff --git a/src/FSharp.Stats/Distributions/Continuous/MultivariateNormal.fs b/src/FSharp.Stats/Distributions/Continuous/MultivariateNormal.fs index 2076d1d03..eba88d822 100644 --- a/src/FSharp.Stats/Distributions/Continuous/MultivariateNormal.fs +++ b/src/FSharp.Stats/Distributions/Continuous/MultivariateNormal.fs @@ -14,50 +14,53 @@ open FSharp.Stats.Ops type MultivariateNormal = // multivariate normal distribution helper functions. - static member CheckParam (mu:vector) (sigma:matrix) = + static member CheckParam (mu:Vector) (sigma:Matrix) = // TODO Implement checkParam for MultivariateNormal if false then failwith "Multivariate normal distribution should be parametrized by " /// Computes the mean. - static member Mean (mu:vector) (sigma:matrix) = + static member Mean (mu:Vector) (sigma:Matrix) = MultivariateNormal.CheckParam mu sigma mu /// Computes the variance. - static member Variance (mu:vector) (sigma:matrix) = + static member Variance (mu:Vector) (sigma:Matrix) = MultivariateNormal.CheckParam mu sigma //sigma*sigma failwith "Not implemented yet." /// Computes the standard deviation. - static member StandardDeviation (mu:vector) (sigma:matrix) = + static member StandardDeviation (mu:Vector) (sigma:Matrix) = MultivariateNormal.CheckParam mu sigma //sigma failwith "Not implemented yet." /// Produces a random sample using the current random number generator (from GetSampleGenerator()). - static member Sample (mu:vector) (sigma:matrix) = - if Vector.length mu = 2 then - let a = Algebra.LinearAlgebra.Cholesky sigma - let z = Random.boxMullerTransform() |> fun (a,b) -> vector [a;b] - mu + a*z + static member Sample (mu:Vector) (sigma:Matrix) = + if Array.length mu = 2 then + let a = Algebra.LinearAlgebra.cholesky sigma + let z = Random.boxMullerTransform() |> fun (a,b) -> [|a;b|] + mu .+ a * z else failwith "Not implemented yet." /// Computes the probability density function. - static member PDF (mu:vector) (sigma:matrix) (x:vector) = + static member PDF (mu:Vector) (sigma:Matrix) (x:Vector) = MultivariateNormal.CheckParam mu sigma let k = Seq.length mu |> float - let ex = Math.Exp(-0.5 * (x - mu).Transpose * (Algebra.LinearAlgebra.Inverse sigma) * (x-mu)) - (2.*Math.PI)**(-k/2.) * (Algebra.LinearAlgebra.Determinant sigma ** (-0.5)) * ex + let tmp = x .- mu + let tmp' = -0.5 .* tmp * (Algebra.LinearAlgebra.inverse sigma) + let ex = Math.Exp(Vector.dot tmp' tmp) + (2.*Math.PI)**(-k/2.) * (Algebra.LinearAlgebra.determinant sigma ** (-0.5)) * ex + /// Computes the cumulative distribution function. - static member CDF (mu:vector) (sigma:matrix) (x:vector) = + static member CDF (mu:Vector) (sigma:Matrix) (x:Vector) = failwith "Not implemented yet." /// Computes the inverse cumulative distribution function (quantile function). - static member InvCDF (mu:vector) (sigma:matrix) (x:vector) = + static member InvCDF (mu:Vector) (sigma:Matrix) (x:Vector) = failwith "InvCDF not implemented yet." /// Initializes a multivariate normal distribution with mean mu and covariance matrix sigma - static member Init (mu:vector) (sigma:matrix) = - { new ContinuousDistribution with + static member Init (mu:Vector) (sigma:Matrix) = + { new ContinuousDistribution,Vector> with member d.Mode = MultivariateNormal.Mean mu sigma member d.Mean = MultivariateNormal.Mean mu sigma member d.StandardDeviation = MultivariateNormal.StandardDeviation mu sigma diff --git a/src/FSharp.Stats/Distributions/Discrete/Multinomial.fs b/src/FSharp.Stats/Distributions/Discrete/Multinomial.fs index 6dbf92cdc..8cc737607 100644 --- a/src/FSharp.Stats/Distributions/Discrete/Multinomial.fs +++ b/src/FSharp.Stats/Distributions/Discrete/Multinomial.fs @@ -12,7 +12,7 @@ open FSharp.Stats.SpecialFunctions type Multinomial = // Multinomial distribution helper functions. - static member CheckParam (p: vector) n = + static member CheckParam (p: Vector) n = if n < 0 then failwith "Multinomial distribution should be parametrized by n >= 0." let checkBetween p = @@ -28,9 +28,9 @@ type Multinomial = /// /// vector of event probabilities in each trial /// number of trails - static member Mean (p: vector) (n: int) = + static member Mean (p: Vector) (n: int) = Multinomial.CheckParam p n - p * float n + p .* float n /// Computes the variance vector /// @@ -44,9 +44,9 @@ type Multinomial = /// /// vector of event probabilities in each trial /// number of trails - static member StandardDeviation p n = + static member StandardDeviation p n : Vector = Multinomial.CheckParam p n - Vector.map sqrt (Multinomial.Variance p n) + Array.map sqrt (Multinomial.Variance p n) /// Produces a random sample using the current random number generator (from GetSampleGenerator()). No parameter checking! /// @@ -88,7 +88,7 @@ type Multinomial = /// // result: 0.118125 /// /// - static member PMF_Unchecked (p: vector) (x: Vector) = + static member PMF_Unchecked (p: Vector) (x: Vector) = //corresponds to function with gamma notation let n = x |> Seq.sum |> int let a = Factorial.factorialLn n @@ -96,7 +96,7 @@ type Multinomial = let c = p |> Seq.indexed |> Seq.fold (fun acc (i,pi) -> pi**x.[i] * acc) 1. floor (0.5 + Math.Exp(a - b)) * c // must be an integer, to compensate for floating point errors: floor +0.5 - static member PMF (p: vector) (x: Vector) = + static member PMF (p: Vector) (x: Vector) = let n = x |> Seq.sum |> int //checks Multinomial.CheckParam p n @@ -118,15 +118,15 @@ type Multinomial = /// /// /// - static member Support (p: vector) n = + static member Support (p: Vector) n = Multinomial.CheckParam p n - Vector.Generic.init p.Length (fun xi -> Interval.createClosedOfSize 0 n) + Array.init p.Length (fun xi -> Interval.createClosedOfSize 0 n) /// A string representation of the distribution. /// /// vector of event probabilities in each trial /// number of trails - static member ToString (p: vector) (n: int) = + static member ToString (p: Vector) (n: int) = sprintf "Multinomial(p = %A, n = %i,)" p n /// Initializes a Multinomial distribution diff --git a/src/FSharp.Stats/Distributions/Distribution.fs b/src/FSharp.Stats/Distributions/Distribution.fs index 71b55aa49..17ee2d05d 100644 --- a/src/FSharp.Stats/Distributions/Distribution.fs +++ b/src/FSharp.Stats/Distributions/Distribution.fs @@ -37,8 +37,8 @@ module Parameters = StandardDeviation : float} type MultivariateNormal = { - Mean : vector - StandardDeviation : matrix} + Mean : Vector + StandardDeviation : Matrix} type Exponential = { Lambda : float} diff --git a/src/FSharp.Stats/FSharp.Stats.fsproj b/src/FSharp.Stats/FSharp.Stats.fsproj index 7565d7d93..b5c4c4605 100644 --- a/src/FSharp.Stats/FSharp.Stats.fsproj +++ b/src/FSharp.Stats/FSharp.Stats.fsproj @@ -32,9 +32,9 @@ + - @@ -62,10 +62,10 @@ - + diff --git a/src/FSharp.Stats/Fitting/CrossValidation.fs b/src/FSharp.Stats/Fitting/CrossValidation.fs index ebc0a1ad6..8dab5a641 100644 --- a/src/FSharp.Stats/Fitting/CrossValidation.fs +++ b/src/FSharp.Stats/Fitting/CrossValidation.fs @@ -24,7 +24,7 @@ module CrossValidation = /// let ssr (y:Vector) (p:Vector)= let residuals = y .- p - Vector.dotProduct residuals residuals + Vector.dot residuals residuals /// Computes root mean square error (RMSE) /// diff --git a/src/FSharp.Stats/Fitting/GoodnessOfFit.fs b/src/FSharp.Stats/Fitting/GoodnessOfFit.fs index fdcf21bfe..8efdb100d 100644 --- a/src/FSharp.Stats/Fitting/GoodnessOfFit.fs +++ b/src/FSharp.Stats/Fitting/GoodnessOfFit.fs @@ -354,7 +354,7 @@ module GoodnessOfFit = Vector.init (order+1) (fun i -> pown x i) let calculateANOVA (order) (coef : Vector) (xData) (yData) = - let fitFunction x = Vector.dotProduct coef (vandermondeRow order x) + let fitFunction x = Vector.dot coef (vandermondeRow order x) calculateANOVA order fitFunction xData yData [] diff --git a/src/FSharp.Stats/Fitting/LinearRegression.fs b/src/FSharp.Stats/Fitting/LinearRegression.fs index a43f7a1e6..b02ab463b 100644 --- a/src/FSharp.Stats/Fitting/LinearRegression.fs +++ b/src/FSharp.Stats/Fitting/LinearRegression.fs @@ -57,12 +57,12 @@ module LinearRegression = /// Gets a x value and predicts the corresponding y value for the given polynomial coefficients. member this.Predict (x: 'T) = - Vector.dotProduct coefficients (vandermondeRow this.Degree x) + Vector.dot coefficients (vandermondeRow this.Degree x) /// Gets a x value vector and predicts the corresponding y value for the given polynomial coefficients. member this.Predict (x: Vector<'T>) = let tmp = Vector.init (x.Length + 1) (fun i -> if i = 0 then 'T.One else x.[i-1]) - Vector.dotProduct tmp coefficients + Vector.dot tmp coefficients /// Prints the polynomial function in a human readable form. override this.ToString() = @@ -483,7 +483,7 @@ module LinearRegression = /// let predict (coef: Coefficients) (x: Vector) = let tmp: Vector = Vector.init (x.Length+1) (fun i -> if i = 0 then 1. else x.[i-1]) - Vector.dotProduct tmp coef.Coefficients + Vector.dot tmp coef.Coefficients module RidgeRegression = @@ -518,7 +518,7 @@ module LinearRegression = /// let predict (coef : Coefficients) (x:Vector) = let tmp :Vector = Vector.init (x.Length+1) (fun i -> if i = 0 then 1. else x.[i-1]) - Vector.dotProduct tmp coef.Coefficients + Vector.dot tmp coef.Coefficients /// /// Linear regression using polynomials as regression function: f(x) = a + bx + cx^2 + .... @@ -640,7 +640,7 @@ module LinearRegression = /// /// If all coefficients are nonzero, the order is equal to the length of the coefficient vector! let predict (coef: Coefficients) (x: float) = - Vector.dotProduct coef.Coefficients (vandermondeRow coef.Degree x) + Vector.dot coef.Coefficients (vandermondeRow coef.Degree x) /// /// calculates derivative values at X=x with given polynomial coefficients. Level 1 = fst derivative; Level2 = snd derivative ... diff --git a/src/FSharp.Stats/Fitting/LogisticRegression.fs b/src/FSharp.Stats/Fitting/LogisticRegression.fs index 6fa01b3f7..ae03c4008 100644 --- a/src/FSharp.Stats/Fitting/LogisticRegression.fs +++ b/src/FSharp.Stats/Fitting/LogisticRegression.fs @@ -29,7 +29,7 @@ module LogisticRegression = // Build intercept-augmented obs let iobs = withIntercept obs // Dot product => logistic function - Vector.dotProduct weights iobs + Vector.dot weights iobs |> FSharp.Stats.SpecialFunctions.Logistic.standard /// Error = (label - prediction) diff --git a/src/FSharp.Stats/Fitting/NonLinearRegression.fs b/src/FSharp.Stats/Fitting/NonLinearRegression.fs index 0daaea611..daec51af3 100644 --- a/src/FSharp.Stats/Fitting/NonLinearRegression.fs +++ b/src/FSharp.Stats/Fitting/NonLinearRegression.fs @@ -192,10 +192,10 @@ module NonLinearRegression = let jacobian' = updateJacobianInplace model xData currentParamGuess jacobian let residualVector' = updateResidualVectorInPlace model xData yData currentParamGuess residualVector let hessian = jacobian'.Transpose() * jacobian' - let diagonal = Matrix.initDiagonal (Vector.map (fun x -> ((lambda)*x)) hessian.Diagonal) + let diagonal = Matrix.diagonal (Array.map (fun x -> ((lambda)*x)) (Matrix.getDiagonal hessian)) let modHessian = (hessian + diagonal) - let step = LinearAlgebra.solveLinearSystem modHessian (Matrix.mulV (jacobian'.Transpose) residualVector') - let newParamGuess = currentParamGuess - step + let step = LinearAlgebra.solveLinearSystem modHessian (Matrix.muliplyVector (jacobian'.Transpose()) residualVector') + let newParamGuess = currentParamGuess .- step let newValueRSS = getRSS model xData yData newParamGuess paramsAtIteration.Add(newParamGuess) if shouldTerminate currentValueRSS newValueRSS paramsAtIteration.Count currentParamGuess newParamGuess solverOptions then @@ -236,7 +236,7 @@ module NonLinearRegression = /// let private validateBounds (lowerBound: Vector) (upperBound: Vector) (parameters: Vector) = try - if Vector.map3 (fun l u x -> if l <= x && u >= x then x else nan) lowerBound upperBound parameters |> Vector.exists Ops.isNan then + if Array.map3 (fun l u x -> if l <= x && u >= x then x else nan) lowerBound upperBound parameters |> Array.exists Ops.isNan then failwith "initial parameters are not within Bounds" else () @@ -245,19 +245,19 @@ module NonLinearRegression = /// let private toInternalParameters (lowerBound: Vector) (upperBound: Vector) (extParameters: Vector) = - Vector.map3 (fun l u x -> + Array.map3 (fun l u x -> Math.Asin((2.0 * (x - l) / (u - l)) - 1.0) ) lowerBound upperBound extParameters /// let private toExternalParameters (lowerBound: Vector) (upperBound: Vector) (intParameters: Vector) = - Vector.map3 (fun l u x -> + Array.map3 (fun l u x -> l + (u / 2.0 - l / 2.0) * (Math.Sin(x) + 1.0) ) lowerBound upperBound intParameters /// let private calculateJacScaleFactors (lowerBound: Vector) (upperBound: Vector) (intParameters: Vector) = - Vector.map3 (fun l u x -> + Array.map3 (fun l u x -> (u - l) / 2.0 * Math.Cos(x) ) lowerBound upperBound intParameters @@ -285,7 +285,7 @@ module NonLinearRegression = /// /// /// - let estimatedParamsVerbose (model: Model) (solverOptions: SolverOptions) lambdaInitial lambdaFactor (lowerBound: vector) (upperBound: vector) (xData: float[]) (yData: float []) = + let estimatedParamsVerbose (model: Model) (solverOptions: SolverOptions) lambdaInitial lambdaFactor (lowerBound: Vector) (upperBound: Vector) (xData: float[]) (yData: float []) = let paramsAtIteration = new ResizeArray>() let initialParamGuess = solverOptions.InitialParamGuess validateBounds lowerBound upperBound initialParamGuess @@ -293,16 +293,16 @@ module NonLinearRegression = let residualVector = Vector.zeroCreate xData.Length let jacobian = Matrix.zeroCreate xData.Length solverOptions.InitialParamGuess.Length let initialValueRSS = getRSS model xData yData initialParamGuess - let rec loop lambda jacobian residualVector currentParamGuessExt currentParamGuessInt currentValueRSS (paramsAtIteration:ResizeArray) = + let rec loop lambda jacobian residualVector currentParamGuessExt currentParamGuessInt currentValueRSS (paramsAtIteration:ResizeArray>) = let scaleFactors = calculateJacScaleFactors lowerBound upperBound currentParamGuessInt let jacobian' = updateJacobianInplace model xData currentParamGuessExt jacobian let residualVector' = updateResidualVectorInPlace model xData yData currentParamGuessExt residualVector - let gradient = Matrix.mulV (jacobian'.Transpose) residualVector' |> scaleGradient scaleFactors - let hessian = jacobian'.Transpose * jacobian' |> scaleJacobian scaleFactors - let diagonal = Matrix.initDiagonal (Vector.map (fun x -> ((lambda)*x)) hessian.Diagonal) + let gradient = Matrix.muliplyVector (jacobian'.Transpose()) residualVector' |> scaleGradient scaleFactors + let hessian = jacobian'.Transpose() * jacobian' |> scaleJacobian scaleFactors + let diagonal = Matrix.diagonal (Array.map (fun x -> ((lambda)*x)) (hessian |> Matrix.getDiagonal)) let modHessian = (hessian + diagonal) - let step = FSharp.Stats.Algebra.LinearAlgebra.SolveLinearSystem modHessian gradient - let newParamGuessInt = currentParamGuessInt - step + let step = FSharp.Stats.Algebra.LinearAlgebra.solveLinearSystem modHessian gradient + let newParamGuessInt = currentParamGuessInt .- step let newParamGuessExt = toExternalParameters lowerBound upperBound newParamGuessInt let newValueRSS = getRSS model xData yData newParamGuessExt paramsAtIteration.Add(newParamGuessExt) @@ -543,7 +543,7 @@ module NonLinearRegression = //gets the linear representation of the problem and solves it by simple linear regression let initialParamGuess = let yLn : Vector = yData |> Array.map (fun x -> Math.Log(x)) - let linearReg = LinearRegression.OLS.Linear.Univariable.fit (vector xData) yLn + let linearReg = LinearRegression.OLS.Linear.Univariable.fit xData yLn let a = exp linearReg.Constant let b = linearReg.Linear [|a;b|] diff --git a/src/FSharp.Stats/Optimization/NelderMead.fs b/src/FSharp.Stats/Optimization/NelderMead.fs index 98848e2de..34235174e 100644 --- a/src/FSharp.Stats/Optimization/NelderMead.fs +++ b/src/FSharp.Stats/Optimization/NelderMead.fs @@ -4,7 +4,6 @@ module NelderMead = open FSharp.Stats open FSharp.Stats.Algebra - open FSharp.Stats.Algebra.LinearAlgebra type NmConfig = { /// Delta used to generate initial simplex for non-zero value elements @@ -51,12 +50,12 @@ module NelderMead = type NmInterationResult = { - Simplexes : vector [] + Simplexes : Vector [] Fx : float array - Vectors : vector [] + Vectors : Vector [] Values : float array GradientNorms : float array - SolutionVector : vector + SolutionVector : Vector Solution : float LastStep : StepType } @@ -64,11 +63,11 @@ module NelderMead = /// Create an initial simplex - let createSimplex (nmc : NmConfig) (x : vector) = + let createSimplex (nmc : NmConfig) (x : Vector) = let n = x.Length let simplex = Array.init (n+1) - (fun _ -> Vector.copy x ) + (fun _ -> Array.copy x ) for i = 1 to n do if (x[i - 1] <> 0) then simplex[i][i - 1] <- (1. + nmc.Delta) * x[i - 1] @@ -79,7 +78,7 @@ module NelderMead = // determine the values of each vertice in the initial simplex - let rankVertices (simplexes : vector[]) (fn : vector -> float) = + let rankVertices (simplexes : Vector[]) (fn : Vector -> float) = let x = Array.copy simplexes let fx = simplexes |> Array.map fn System.Array.Sort(fx,x) @@ -87,7 +86,7 @@ module NelderMead = - let update (nmc : NmConfig) (stopCounter:OptimizationStop.StopCounter) (fn : vector -> float) (nmInterResult : NmInterationResult) = + let update (nmc : NmConfig) (stopCounter:OptimizationStop.StopCounter) (fn : Vector -> float) (nmInterResult : NmInterationResult) = let simplexes = Array.copy nmInterResult.Simplexes // Copy necessary ??? let fx = nmInterResult.Fx let mutable laststep_ = nmInterResult.LastStep @@ -96,13 +95,13 @@ module NelderMead = let xbar = let mutable tmp = Vector.zeroCreate simplexes[0].Length for i = 0 to (simplexes.Length - 2) do - tmp <- tmp + simplexes[i] + tmp <- tmp .+ simplexes[i] let d = float (simplexes.Length - 1) - tmp |> Vector.map (fun v -> v / d) + tmp |> Array.map (fun v -> v / d) // Calculate reflection point - let xr = (1. + nmc.Rho) * xbar - nmc.Rho * simplexes[simplexes.Length - 1] + let xr = (1. + nmc.Rho) .* xbar .- nmc.Rho .* simplexes[simplexes.Length - 1] let fxr = fn xr stopCounter.IncFunctionEvaluationCounter() @@ -110,7 +109,7 @@ module NelderMead = // reflection point is better than worst point if (fxr < fx[0]) then //reflection point is better than best point - > expand - let xe = (1. + nmc.Rho * nmc.Chi) * xbar - nmc.Rho * nmc.Chi * simplexes[simplexes.Length - 1] + let xe = (1. + nmc.Rho * nmc.Chi) .* xbar .- nmc.Rho * nmc.Chi .* simplexes[simplexes.Length - 1] let fxe = fn xe stopCounter.IncFunctionEvaluationCounter() if (fxe < fxr) then @@ -136,7 +135,7 @@ module NelderMead = if ((fx[simplexes.Length - 2] <= fxr) && (fxr < fx[simplexes.Length - 1])) then // perform an outside contraction - let xc = (1. + nmc.Psi * nmc.Rho) * xbar - nmc.Psi * nmc.Rho * simplexes[simplexes.Length - 1] + let xc = (1. + nmc.Psi * nmc.Rho) .* xbar .- nmc.Psi * nmc.Rho .* simplexes[simplexes.Length - 1] let fxc = fn xc stopCounter.IncFunctionEvaluationCounter() if (fxc < fxr) then @@ -147,7 +146,7 @@ module NelderMead = else // perform a shrink step for i = 1 to (simplexes.Length - 1) do - simplexes[i] <- simplexes[0] + nmc.Sigma * (simplexes[i] - simplexes[0]) + simplexes[i] <- simplexes[0] .+ nmc.Sigma .* (simplexes[i] .- simplexes[0]) fx[i] <- fn simplexes[i] stopCounter.IncFunctionEvaluationCounter() @@ -155,7 +154,7 @@ module NelderMead = else // perform an inside contraction - let xcc = (1. - nmc.Psi) * xbar + nmc.Psi * simplexes[simplexes.Length - 1]; + let xcc = (1. - nmc.Psi) .* xbar .+ nmc.Psi .* simplexes[simplexes.Length - 1]; let fxcc = fn xcc stopCounter.IncFunctionEvaluationCounter() @@ -169,7 +168,7 @@ module NelderMead = // perform a shrink step for i = 1 to (simplexes.Length - 1) do - simplexes[i] <- simplexes[0] + nmc.Sigma * (simplexes[i] - simplexes[0]) + simplexes[i] <- simplexes[0] .+ nmc.Sigma .* (simplexes[i] .- simplexes[0]) fx[i] <- fn simplexes[i] stopCounter.IncFunctionEvaluationCounter() @@ -205,7 +204,7 @@ module NelderMead = /// Initialize the optimization method /// The use of this function is intended for testing/debugging purposes only - let initInteration (maxIteration:int) (initialsimplex :vector[]) (fn : vector -> float) = + let initInteration (maxIteration:int) (initialsimplex :Vector[]) (fn : Vector -> float) = let x,fx = rankVertices initialsimplex fn let evalFn = fn initialsimplex[0] @@ -235,7 +234,7 @@ module NelderMead = /// Minimize the given cost function and stop criteria - let minimizeWithStopCriteria (nmc : NmConfig) (x :vector) (fn : vector -> float) (stopCriteria:OptimizationStop.StopCriteria) = + let minimizeWithStopCriteria (nmc : NmConfig) (x :Vector) (fn : Vector -> float) (stopCriteria:OptimizationStop.StopCriteria) = // Action newMinimalValueFound) let initialsimplex = createSimplex nmc x @@ -266,5 +265,5 @@ module NelderMead = /// Minimize the given cost function and stop criteria - let minimize (nmc : NmConfig) (x :vector) (fn : vector -> float) = + let minimize (nmc : NmConfig) (x :Vector) (fn : Vector -> float) = minimizeWithStopCriteria nmc x fn OptimizationStop.defaultStopCriteria diff --git a/src/FSharp.Stats/Permutation.fs b/src/FSharp.Stats/Permutation.fs index 9be2edc52..5067b2992 100644 --- a/src/FSharp.Stats/Permutation.fs +++ b/src/FSharp.Stats/Permutation.fs @@ -66,6 +66,22 @@ module Permutation = let copy = Array.copy arr ofFreshArray copy + /// Computes the sign (+1.0 or -1.0) of a permutation P, + /// given its domain size n. sign(P) = (-1)^(n - numCycles). + let sign (n: int) (P: Permutation) : float = + let visited = Array.create n false + let mutable numCycles = 0 + for i in 0 .. n - 1 do + if not visited.[i] then + numCycles <- numCycles + 1 + let mutable current = i + while not visited.[current] do + visited.[current] <- true + current <- P current + let numTranspositions = n - numCycles + if numTranspositions % 2 = 0 then 1.0 else -1.0 + + let ofPairs (mappings: seq) = let p = dict mappings diff --git a/src/FSharp.Stats/Seq.fs b/src/FSharp.Stats/Seq.fs index 1853cfe1d..c0f93baa6 100644 --- a/src/FSharp.Stats/Seq.fs +++ b/src/FSharp.Stats/Seq.fs @@ -7,8 +7,6 @@ namespace FSharp.Stats [] module Seq = - module OpsS = SpecializedGenericImpl - /// /// Computes the range of the input sequence. /// @@ -814,8 +812,8 @@ module Seq = /// /// let inline covPopulation (seq1:seq<'T>) (seq2:seq<'T>) : 'U = - let v1 = seq1 |> OpsS.seqV - let v2 = seq2 |> OpsS.seqV + let v1 = seq1 |>Array.ofSeq + let v2 = seq2 |>Array.ofSeq if v1.Length <> v2.Length then failwith "Inputs need to have the same length." let zero = LanguagePrimitives.GenericZero<'U> let div = LanguagePrimitives.DivideByInt<'U> @@ -880,8 +878,8 @@ module Seq = /// /// let inline cov (seq1:seq<'T>) (seq2:seq<'T>) : 'U = - let v1 = seq1 |> OpsS.seqV - let v2 = seq2 |> OpsS.seqV + let v1 = seq1 |>Array.ofSeq + let v2 = seq2 |>Array.ofSeq if v1.Length <> v2.Length then failwith "Inputs need to have the same length." let zero = LanguagePrimitives.GenericZero<'U> let div = LanguagePrimitives.DivideByInt<'U> diff --git a/src/FSharp.Stats/Signal/Filtering.fs b/src/FSharp.Stats/Signal/Filtering.fs index 353f4587b..d70f09cad 100644 --- a/src/FSharp.Stats/Signal/Filtering.fs +++ b/src/FSharp.Stats/Signal/Filtering.fs @@ -54,13 +54,13 @@ module Filtering = if sLen < kLen then // The original code returned a single dot if kernel longer than signal - [| Vector.dotProduct kernel signal |] + [| Vector.dot kernel signal |] else // We produce sLen - kLen + 1 outputs let outLen = sLen - kLen + 1 Array.init outLen (fun i -> // dot kernel with signal[i.. i+kLen-1] - Vector.dotProduct kernel signal.[i .. i + kLen - 1] + Vector.dot kernel signal.[i .. i + kLen - 1] ) diff --git a/src/FSharp.Stats/Testing/ConfusionMatrix.fs b/src/FSharp.Stats/Testing/ConfusionMatrix.fs index bf25b4bc8..8290da7d1 100644 --- a/src/FSharp.Stats/Testing/ConfusionMatrix.fs +++ b/src/FSharp.Stats/Testing/ConfusionMatrix.fs @@ -114,7 +114,7 @@ type MultiLabelConfusionMatrix = { let zipped = Array.zip actual predictions let confusion = - Matrix.Generic.init labels.Length labels.Length (fun m n -> + Matrix.init labels.Length labels.Length (fun m n -> let labelM = labels[m] let labelN = labels[n] zipped @@ -131,7 +131,7 @@ type MultiLabelConfusionMatrix = { let labelIndex = Array.findIndex (fun x -> x = label) mlcm.Labels mlcm.Confusion - |> Matrix.Generic.foldi ( + |> Matrix.foldi ( fun rI cI cm elem -> match (rI, cI) with | (rI, cI) when rI = labelIndex && cI = labelIndex -> {cm with TP = cm.TP + elem} diff --git a/src/FSharp.Stats/Testing/RMT.fs b/src/FSharp.Stats/Testing/RMT.fs index 19ee135a5..405ab8535 100644 --- a/src/FSharp.Stats/Testing/RMT.fs +++ b/src/FSharp.Stats/Testing/RMT.fs @@ -34,7 +34,7 @@ module RMT = let computeChiSquared (bwQuantile : float) (m:Matrix) = let unfoldedEgv = - FSharp.Stats.Algebra.LinearAlgebra.EigenSpectrumWhenSymmetric m + Algebra.LinearAlgebra.symmetricEigenspectrum m |> fun (eigenvectors,eigenvalues) -> let spUnfold = eigenvalues diff --git a/src/FSharp.Stats/Testing/TTest.fs b/src/FSharp.Stats/Testing/TTest.fs index 37466956f..98017a682 100644 --- a/src/FSharp.Stats/Testing/TTest.fs +++ b/src/FSharp.Stats/Testing/TTest.fs @@ -40,8 +40,8 @@ module TTest = /// Computes a t-test or a Welch test (unequal variances) let twoSample (assumeEqualVariances:bool) sample1 sample2 = - let s1Stats = Vector.stats sample1 - let s2Stats = Vector.stats sample2 + let s1Stats = Seq.stats sample1 + let s2Stats = Seq.stats sample2 let v1 = SummaryStats.var s1Stats let v2 = SummaryStats.var s2Stats @@ -64,7 +64,7 @@ module TTest = //// Computes a paired t-test used to compare two population means where you have two samples in /// which observations in one sample can be paired with observations in the other sample. let twoSamplePaired (sample1:Vector) (sample2:Vector) = - let deltas = Vector.map2 (fun a b -> b - a) sample1 sample2 + let deltas = Array.map2 (fun a b -> b - a) sample1 sample2 oneSample deltas 0. /// Union type indicating whether One Tail or Two Tail Student's T critical value is desired. diff --git a/src/FSharp.Stats/Testing/Tables.fs b/src/FSharp.Stats/Testing/Tables.fs index f8f007a67..c7b071c27 100644 --- a/src/FSharp.Stats/Testing/Tables.fs +++ b/src/FSharp.Stats/Testing/Tables.fs @@ -10,53 +10,52 @@ module Tables = // and C. W. Dunnett, New Tables for Multiple Comparisons with a Control,Biometrics , Sep., 1964, Vol. 20, No. 3 (Sep., 1964), pp. 482-491 // df = totalcount - groupcount, k = number of means (including control) let dunnettsTwoSided095 = - matrix [ + Matrix.ofJaggedArray [| //d k 2; 3; 4; 5; 6; 7; 8; 9; 10 11 12 13 14 15 - (*1 *) [12.706; 17.369;20.034; 21.85; 23.209;24.285; 25.171;25.922; 26.57; nan; nan; nan; nan; 28.901;] - (*2 *) [4.303; 5.418; 6.065; 6.513; 6.852; 7.124; 7.349; 7.540; 7.707; nan; nan; nan; nan; 8.31 ;] - (*3 *) [3.182; 3.867; 4.263; 4.538; 4.748; 4.916; 5.056; 5.176; 5.280; nan; nan; nan; nan; 5.66 ;] - (*4 *) [2.776; 3.310; 3.618; 3.832; 3.994; 4.125; 4.235; 4.328; 4.410; nan; nan; nan; nan; 4.707 ;] - (*5 *) [2.571; 3.03 ; 3.293; 3.476; 3.615; 3.727; 3.821; 3.900; 3.970; nan; nan; nan; nan; 4.225 ;] - (*6 *) [2.447; 2.863; 3.099; 3.263; 3.388; 3.489; 3.573; 3.644; 3.707; nan; nan; nan; nan; 3.936 ;] - (*7 *) [2.365; 2.752; 2.971; 3.123; 3.238; 3.331; 3.408; 3.475; 3.533; nan; nan; nan; nan; 3.744 ;] - (*8 *) [2.306; 2.673; 2.880; 3.023; 3.131; 3.219; 3.292; 3.354; 3.408; nan; nan; nan; nan; 3.608 ;] - (*9 *) [2.262; 2.614; 2.812; 2.948; 3.052; 3.135; 3.205; 3.264; 3.316; nan; nan; nan; nan; 3.506 ;] - (*10 *) [2.228; 2.568; 2.759; 2.890; 2.990; 3.075; 3.137; 3.194; 3.244; nan; nan; nan; nan; 3.427 ;] - (*11 *) [2.201; 2.532; 2.717; 2.845; 2.941; 3.019; 3.084; 3.139; 3.187; nan; nan; nan; nan; 3.363 ;] - (*12 *) [2.179; 2.502; 2.683; 2.807; 2.901; 2.977; 3.040; 3.094; 3.140; nan; nan; nan; nan; 3.312 ;] - (*13 *) [2.160; 2.478; 2.654; 2.776; 2.868; 2.942; 3.003; 3.056; 3.102; nan; nan; nan; nan; 3.269 ;] - (*14 *) [2.145; 2.457; 2.631; 2.750; 2.840; 2.912; 2.973; 3.024; 3.069; nan; nan; nan; nan; 3.233 ;] - (*15 *) [2.131; 2.439; 2.610; 2.727; 2.816; 2.887; 2.946; 2.997; 3.041; nan; nan; nan; nan; 3.202 ;] - (*16 *) [2.120; 2.424; 2.592; 2.708; 2.798; 2.865; 2.924; 2.974; 3.017; nan; nan; nan; nan; 3.176 ;] - (*17 *) [2.110; 2.410; 2.577; 2.691; 2.777; 2.846; 2.904; 2.953; 2.996; nan; nan; nan; nan; 3.152 ;] - (*18 *) [2.101; 2.399; 2.563; 2.676; 2.761; 2.830; 2.887; 2.935; 2.977; nan; nan; nan; nan; 3.132 ;] - (*19 *) [2.093; 2.388; 2.551; 2.663; 2.747; 2.815; 2.871; 2.919; 2.961; nan; nan; nan; nan; 3.114 ;] - (*20 *) [2.086; 2.379; 2.540; 2.651; 2.735; 2.802; 2.857; 2.905; 2.946; nan; nan; nan; nan; 3.098 ;] - (*21 *) [2.080; 2.370; 2.531; 2.640; 2.723; 2.790; 2.845; 2.892; 2.933; nan; nan; nan; nan; 3.083 ;] - (*22 *) [2.074; 2.363; 2.522; 2.631; 2.713; 2.779; 2.832; 2.880; 2.921; nan; nan; nan; nan; 3.070 ;] - (*23 *) [2.069; 2.356; 2.514; 2.622; 2.704; 2.769; 2.824; 2.870; 2.910; nan; nan; nan; nan; 3.058 ;] - (*24 *) [2.064; 2.349; 2.507; 2.614; 2.695; 2.760; 2.814; 2.860; 2.900; nan; nan; nan; nan; 3.047 ;] - (*25 *) [2.060; 2.344; 2.500; 2.607; 2.688; 2.752; 2.806; 2.851; 2.891; nan; nan; nan; nan; 3.037 ;] - (*26 *) [2.056; 2.338; 2.494; 2.600; 2.680; 2.745; 2.798; 2.843; 2.883; nan; nan; nan; nan; 3.028 ;] - (*27 *) [2.052; 2.333; 2.488; 2.594; 2.674; 2.738; 2.791; 2.836; 2.875; nan; nan; nan; nan; 3.019 ;] - (*28 *) [2.048; 2.329; 2.483; 2.588; 2.668; 2.731; 2.784; 2.829; 2.868; nan; nan; nan; nan; 3.011 ;] - (*29 *) [2.045; 2.325; 2.478; 2.583; 2.662; 2.725; 2.778; 2.823; 2.862; nan; nan; nan; nan; 3.004 ;] - (*30 *) [2.042; 2.321; 2.474; 2.578; 2.657; 2.720; 2.772; 2.817; 2.856; nan; nan; nan; nan; 2.997 ;] - (*31 *) [2.040; 2.317; 2.469; 2.574; 2.652; 2.715; 2.767; 2.811; 2.850; nan; nan; nan; nan; 2.991 ;] - (*32 *) [2.037; 2.314; 2.466; 2.569; 2.647; 2.710; 2.762; 2.806; 2.845; nan; nan; nan; nan; 2.985 ;] - (*33 *) [2.035; 2.310; 2.462; 2.565; 2.643; 2.705; 2.757; 2.801; 2.840; nan; nan; nan; nan; 2.979 ;] - (*34 *) [2.032; 2.307; 2.458; 2.561; 2.639; 2.701; 2.753; 2.797; 2.835; nan; nan; nan; nan; 2.974 ;] - (*35 *) [2.030; 2.305; 2.455; 2.558; 2.635; 2.697; 2.748; 2.792; 2.830; nan; nan; nan; nan; 2.969 ;] - (*36 *) [2.028; 2.302; 2.452; 2.555; 2.632; 2.693; 2.745; 2.788; 2.826; nan; nan; nan; nan; 2.965 ;] - (*37 *) [2.026; 2.299; 2.449; 2.551; 2.628; 2.690; 2.741; 2.784; 2.822; nan; nan; nan; nan; 2.960 ;] - (*38 *) [2.024; 2.297; 2.447; 2.548; 2.625; 2.686; 2.737; 2.781; 2.819; nan; nan; nan; nan; 2.956 ;] - (*39 *) [2.023; 2.295; 2.444; 2.546; 2.622; 2.683; 2.734; 2.777; 2.815; nan; nan; nan; nan; 2.952 ;] - (*40 *) [2.021; 2.293; 2.441; 2.543; 2.619; 2.680; 2.731; 2.774; 2.812; nan; nan; nan; nan; 2.949 ;] - (*48 *) [2.011; 2.279; 2.426; 2.526; 2.601; 2.661; 2.711; 2.753; 2.790; nan; nan; nan; nan; 2.925 ;] - (*60 *) [2.000; 2.265; 2.410; 2.508; 2.582; 2.642; 2.691; 2.733; 2.769; nan; nan; nan; nan; 2.901 ;] - (*80 *) [1.990; 2.252; 2.394; 2.491; 2.564; 2.623; 2.671; 2.712; 2.748; nan; nan; nan; nan; 2.878 ;] - (*120*) [1.980; 2.238; 2.379; 2.475; 2.547; 2.604; 2.651; 2.692; 2.727; nan; nan; nan; nan; 2.855 ;] - (*240*) [1.970; 2.225; 2.364; 2.458; 2.529; 2.585; 2.632; 2.672; 2.707; nan; nan; nan; nan; 2.832 ;] - (*inf*) [1.960; 2.212; 2.349; 2.442; 2.511; 2.567; 2.613; 2.652; 2.686; nan; nan; nan; nan; 2.810 ;] - ] - + (*1 *) [|12.706; 17.369;20.034; 21.85; 23.209;24.285; 25.171;25.922; 26.57; nan; nan; nan; nan; 28.901;|] + (*2 *) [|4.303; 5.418; 6.065; 6.513; 6.852; 7.124; 7.349; 7.540; 7.707; nan; nan; nan; nan; 8.31 ;|] + (*3 *) [|3.182; 3.867; 4.263; 4.538; 4.748; 4.916; 5.056; 5.176; 5.280; nan; nan; nan; nan; 5.66 ;|] + (*4 *) [|2.776; 3.310; 3.618; 3.832; 3.994; 4.125; 4.235; 4.328; 4.410; nan; nan; nan; nan; 4.707 ;|] + (*5 *) [|2.571; 3.03 ; 3.293; 3.476; 3.615; 3.727; 3.821; 3.900; 3.970; nan; nan; nan; nan; 4.225 ;|] + (*6 *) [|2.447; 2.863; 3.099; 3.263; 3.388; 3.489; 3.573; 3.644; 3.707; nan; nan; nan; nan; 3.936 ;|] + (*7 *) [|2.365; 2.752; 2.971; 3.123; 3.238; 3.331; 3.408; 3.475; 3.533; nan; nan; nan; nan; 3.744 ;|] + (*8 *) [|2.306; 2.673; 2.880; 3.023; 3.131; 3.219; 3.292; 3.354; 3.408; nan; nan; nan; nan; 3.608 ;|] + (*9 *) [|2.262; 2.614; 2.812; 2.948; 3.052; 3.135; 3.205; 3.264; 3.316; nan; nan; nan; nan; 3.506 ;|] + (*10 *) [|2.228; 2.568; 2.759; 2.890; 2.990; 3.075; 3.137; 3.194; 3.244; nan; nan; nan; nan; 3.427 ;|] + (*11 *) [|2.201; 2.532; 2.717; 2.845; 2.941; 3.019; 3.084; 3.139; 3.187; nan; nan; nan; nan; 3.363 ;|] + (*12 *) [|2.179; 2.502; 2.683; 2.807; 2.901; 2.977; 3.040; 3.094; 3.140; nan; nan; nan; nan; 3.312 ;|] + (*13 *) [|2.160; 2.478; 2.654; 2.776; 2.868; 2.942; 3.003; 3.056; 3.102; nan; nan; nan; nan; 3.269 ;|] + (*14 *) [|2.145; 2.457; 2.631; 2.750; 2.840; 2.912; 2.973; 3.024; 3.069; nan; nan; nan; nan; 3.233 ;|] + (*15 *) [|2.131; 2.439; 2.610; 2.727; 2.816; 2.887; 2.946; 2.997; 3.041; nan; nan; nan; nan; 3.202 ;|] + (*16 *) [|2.120; 2.424; 2.592; 2.708; 2.798; 2.865; 2.924; 2.974; 3.017; nan; nan; nan; nan; 3.176 ;|] + (*17 *) [|2.110; 2.410; 2.577; 2.691; 2.777; 2.846; 2.904; 2.953; 2.996; nan; nan; nan; nan; 3.152 ;|] + (*18 *) [|2.101; 2.399; 2.563; 2.676; 2.761; 2.830; 2.887; 2.935; 2.977; nan; nan; nan; nan; 3.132 ;|] + (*19 *) [|2.093; 2.388; 2.551; 2.663; 2.747; 2.815; 2.871; 2.919; 2.961; nan; nan; nan; nan; 3.114 ;|] + (*20 *) [|2.086; 2.379; 2.540; 2.651; 2.735; 2.802; 2.857; 2.905; 2.946; nan; nan; nan; nan; 3.098 ;|] + (*21 *) [|2.080; 2.370; 2.531; 2.640; 2.723; 2.790; 2.845; 2.892; 2.933; nan; nan; nan; nan; 3.083 ;|] + (*22 *) [|2.074; 2.363; 2.522; 2.631; 2.713; 2.779; 2.832; 2.880; 2.921; nan; nan; nan; nan; 3.070 ;|] + (*23 *) [|2.069; 2.356; 2.514; 2.622; 2.704; 2.769; 2.824; 2.870; 2.910; nan; nan; nan; nan; 3.058 ;|] + (*24 *) [|2.064; 2.349; 2.507; 2.614; 2.695; 2.760; 2.814; 2.860; 2.900; nan; nan; nan; nan; 3.047 ;|] + (*25 *) [|2.060; 2.344; 2.500; 2.607; 2.688; 2.752; 2.806; 2.851; 2.891; nan; nan; nan; nan; 3.037 ;|] + (*26 *) [|2.056; 2.338; 2.494; 2.600; 2.680; 2.745; 2.798; 2.843; 2.883; nan; nan; nan; nan; 3.028 ;|] + (*27 *) [|2.052; 2.333; 2.488; 2.594; 2.674; 2.738; 2.791; 2.836; 2.875; nan; nan; nan; nan; 3.019 ;|] + (*28 *) [|2.048; 2.329; 2.483; 2.588; 2.668; 2.731; 2.784; 2.829; 2.868; nan; nan; nan; nan; 3.011 ;|] + (*29 *) [|2.045; 2.325; 2.478; 2.583; 2.662; 2.725; 2.778; 2.823; 2.862; nan; nan; nan; nan; 3.004 ;|] + (*30 *) [|2.042; 2.321; 2.474; 2.578; 2.657; 2.720; 2.772; 2.817; 2.856; nan; nan; nan; nan; 2.997 ;|] + (*31 *) [|2.040; 2.317; 2.469; 2.574; 2.652; 2.715; 2.767; 2.811; 2.850; nan; nan; nan; nan; 2.991 ;|] + (*32 *) [|2.037; 2.314; 2.466; 2.569; 2.647; 2.710; 2.762; 2.806; 2.845; nan; nan; nan; nan; 2.985 ;|] + (*33 *) [|2.035; 2.310; 2.462; 2.565; 2.643; 2.705; 2.757; 2.801; 2.840; nan; nan; nan; nan; 2.979 ;|] + (*34 *) [|2.032; 2.307; 2.458; 2.561; 2.639; 2.701; 2.753; 2.797; 2.835; nan; nan; nan; nan; 2.974 ;|] + (*35 *) [|2.030; 2.305; 2.455; 2.558; 2.635; 2.697; 2.748; 2.792; 2.830; nan; nan; nan; nan; 2.969 ;|] + (*36 *) [|2.028; 2.302; 2.452; 2.555; 2.632; 2.693; 2.745; 2.788; 2.826; nan; nan; nan; nan; 2.965 ;|] + (*37 *) [|2.026; 2.299; 2.449; 2.551; 2.628; 2.690; 2.741; 2.784; 2.822; nan; nan; nan; nan; 2.960 ;|] + (*38 *) [|2.024; 2.297; 2.447; 2.548; 2.625; 2.686; 2.737; 2.781; 2.819; nan; nan; nan; nan; 2.956 ;|] + (*39 *) [|2.023; 2.295; 2.444; 2.546; 2.622; 2.683; 2.734; 2.777; 2.815; nan; nan; nan; nan; 2.952 ;|] + (*40 *) [|2.021; 2.293; 2.441; 2.543; 2.619; 2.680; 2.731; 2.774; 2.812; nan; nan; nan; nan; 2.949 ;|] + (*48 *) [|2.011; 2.279; 2.426; 2.526; 2.601; 2.661; 2.711; 2.753; 2.790; nan; nan; nan; nan; 2.925 ;|] + (*60 *) [|2.000; 2.265; 2.410; 2.508; 2.582; 2.642; 2.691; 2.733; 2.769; nan; nan; nan; nan; 2.901 ;|] + (*80 *) [|1.990; 2.252; 2.394; 2.491; 2.564; 2.623; 2.671; 2.712; 2.748; nan; nan; nan; nan; 2.878 ;|] + (*120*) [|1.980; 2.238; 2.379; 2.475; 2.547; 2.604; 2.651; 2.692; 2.727; nan; nan; nan; nan; 2.855 ;|] + (*240*) [|1.970; 2.225; 2.364; 2.458; 2.529; 2.585; 2.632; 2.672; 2.707; nan; nan; nan; nan; 2.832 ;|] + (*inf*) [|1.960; 2.212; 2.349; 2.442; 2.511; 2.567; 2.613; 2.652; 2.686; nan; nan; nan; nan; 2.810 ;|] + |] From 94830de4b9ce79c78ab7de4d28b50ca209baad4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20M=C3=BChlhaus?= Date: Fri, 11 Apr 2025 08:45:15 +0200 Subject: [PATCH 021/121] Exclude all Unit tests to successively update it --- .../FSharp.Stats.Tests.fsproj | 31 ------------------- 1 file changed, 31 deletions(-) diff --git a/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj b/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj index f4295d1f5..0c6ac7aba 100644 --- a/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj +++ b/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj @@ -5,37 +5,6 @@ false - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - From 2df732cec286baddbbd8f29f22904e7e1a7c003a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20M=C3=BChlhaus?= Date: Fri, 11 Apr 2025 08:45:39 +0200 Subject: [PATCH 022/121] Update Test: Hypothesis Testing --- tests/FSharp.Stats.Tests/Testing.fs | 42 ++++++++++++++--------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/tests/FSharp.Stats.Tests/Testing.fs b/tests/FSharp.Stats.Tests/Testing.fs index 41edb81d3..18ab34a44 100644 --- a/tests/FSharp.Stats.Tests/Testing.fs +++ b/tests/FSharp.Stats.Tests/Testing.fs @@ -182,10 +182,10 @@ let wilcoxonTestTests = [] let tTestTests = // tested in SPSS version 27 - let groupA = vector [-5.;-3.;-3.;-4.;-5.;] - let groupB = vector [-2.;-4.;-4.;-6.;-6.;-6.;-5.;] - let groupC = vector [-3.;-7.;-8.;-4.;-2.; 1.;-1.;] - let groupD = vector [1.;-1.;0.;2.;2.;] + let groupA = [|-5.;-3.;-3.;-4.;-5.;|] + let groupB = [|-2.;-4.;-4.;-6.;-6.;-6.;-5.;|] + let groupC = [|-3.;-7.;-8.;-4.;-2.; 1.;-1.;|] + let groupD = [|1.;-1.;0.;2.;2.;|] let meanA = Seq.mean groupA let meanB = Seq.mean groupB @@ -271,8 +271,8 @@ let tTestTests = testCase "twoSamplePaired" <| fun () -> // tested with R function t.test(x, y, paired = TRUE, alternative = "two.sided") - let vectorX = vector [1.;2.;4.;8.] - let vectorY = vector [10.;23.;11;9.] + let vectorX = [|1.;2.;4.;8.|] + let vectorY = [|10.;23.;11;9.|] let expectedPval = 0.10836944173355316 let expectedStatistic = 2.26554660552391818 let twoSamplePaired = Testing.TTest.twoSamplePaired vectorX vectorY @@ -280,36 +280,36 @@ let tTestTests = Expect.floatClose Accuracy.high twoSamplePaired.Statistic expectedStatistic "t statistic should be equal." Expect.equal twoSamplePaired.DegreesOfFreedom 3. "df should be equal." - let vectorZ = vector [-5.;-9.;0.;-8.] + let vectorZ = [|-5.;-9.;0.;-8.|] let twoSamplePaired2 = Testing.TTest.twoSamplePaired vectorX vectorZ let expectedPval1 = 0.041226646225439562 let expectedStatistic1 = -3.44031028692427698 Expect.floatClose Accuracy.high twoSamplePaired2.PValue expectedPval1 "pValue should be equal." Expect.floatClose Accuracy.high twoSamplePaired2.Statistic expectedStatistic1 "t statistic should be equal." - let vectorNan = vector [nan;10.;23.;11.] + let vectorNan = [|nan;10.;23.;11.|] let twoSamplePaired3 = Testing.TTest.twoSamplePaired vectorX vectorNan Expect.isTrue (nan.Equals(twoSamplePaired3.PValue)) "pValue should be nan." Expect.isTrue (nan.Equals(twoSamplePaired3.Statistic)) "t statistic should be nan." - let vectorBefore = vector [10.;4.;15.;12.;6.] + let vectorBefore = [|10.;4.;15.;12.;6.|] let twoSamplePaired4() = Testing.TTest.twoSamplePaired vectorBefore vectorX |>ignore Expect.throws twoSamplePaired4 "Vectors of different length" // test if exception Test works // Expect.throws (fun _ -> Testing.TTest.twoSamplePaired vectorX vectorY|>ignore) "Vetors should have equal length" - let vectorWithInfinity = vector [infinity;4.;15.;12.] + let vectorWithInfinity = [|infinity;4.;15.;12.|] let twoSamplePairedInfinity = Testing.TTest.twoSamplePaired vectorWithInfinity vectorX Expect.isTrue (nan.Equals(twoSamplePairedInfinity.PValue)) "pValue should be nan." Expect.isTrue (nan.Equals(twoSamplePairedInfinity.Statistic)) "t statistic should be nan." - let vectorWithNegativeInfinity = vector [infinity;4.;15.;12.] + let vectorWithNegativeInfinity = [|infinity;4.;15.;12.|] let twoSampleNegativeInfinity = Testing.TTest.twoSamplePaired vectorWithNegativeInfinity vectorX Expect.isTrue (nan.Equals(twoSampleNegativeInfinity.PValue)) "pValue should be nan." Expect.isTrue (nan.Equals(twoSampleNegativeInfinity.Statistic)) "t statistic should be nan." - let vectorNull = vector [0;0;0;0] + let vectorNull = [|0.;0.;0.;0.|] let twoSamplePairedWithNullVector = Testing.TTest.twoSamplePaired vectorNull vectorY let expectedPval2 = 0.0272 let expectedStatistic2 = 4.0451 @@ -322,12 +322,12 @@ let tTestTests = let fTestTests = // F-Test validated against res.ftest <- var.test(samplea, sampleb, alternative = "two.sided") RStudio 2022.02.3+492 "Prairie Trillium" Release (1db809b8323ba0a87c148d16eb84efe39a8e7785, 2022-05-20) for Windows - let sampleFA = vector [|5.0; 6.0; 5.8; 5.7|] - let sampleFB = vector [|3.5; 3.7; 4.0; 3.3; 3.6|] - let sampleNaN = vector [|5.0; 6.0; 5.8; nan|] - let sampleInf = vector [|5.0; 6.0; 5.8; infinity|] - let sampleNegInf = vector [|5.0; 6.0; 5.8; -infinity|] - let sampleties = vector [|5.0; 5.0; 5.8; 5.3|] + let sampleFA = [|5.0; 6.0; 5.8; 5.7|] + let sampleFB = [|3.5; 3.7; 4.0; 3.3; 3.6|] + let sampleNaN = [|5.0; 6.0; 5.8; nan|] + let sampleInf = [|5.0; 6.0; 5.8; infinity|] + let sampleNegInf = [|5.0; 6.0; 5.8; -infinity|] + let sampleties = [|5.0; 5.0; 5.8; 5.3|] // calculation of the F test let fResult = FTest.testVariances sampleFA sampleFB @@ -672,7 +672,7 @@ let multiLabelConfusionMatrixTests = [2; 0; 4] ] |> array2D - |> Matrix.Generic.ofArray2D + |> Matrix.ofArray2D let expectedMLCM = { @@ -684,7 +684,7 @@ let multiLabelConfusionMatrixTests = [2; 0; 4] ] |> array2D - |> Matrix.Generic.ofArray2D + |> Matrix.ofArray2D } let multiLabelCM = MultiLabelConfusionMatrix.create([|"A";"B";"C"|], c) @@ -816,7 +816,7 @@ let comparisonMetricsTests = [2; 0; 4] ] |> array2D - |> Matrix.Generic.ofArray2D + |> Matrix.ofArray2D let multiLabelCM = MultiLabelConfusionMatrix.create([|"A";"B";"C"|], c) From f4cf68fb8a120c390a55a181254c2383e783f7b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20M=C3=BChlhaus?= Date: Fri, 11 Apr 2025 09:53:30 +0200 Subject: [PATCH 023/121] Add Matrix compare by value --- .github/workflows/build-and-test.yml | 8 ++-- build/build.fsproj | 4 ++ global.json | 4 +- src/FSharp.Stats/AlgTypes/Matrix.fs | 43 ++++++++++++++++++- src/FSharp.Stats/AlgTypes/VectorExt.fs | 1 + src/FSharp.Stats/Algebra/LinearAlgebra.fs | 3 ++ .../FSharp.Stats.Tests.fsproj | 4 ++ 7 files changed, 59 insertions(+), 8 deletions(-) diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml index 1e03eb3f9..ce45285cf 100644 --- a/.github/workflows/build-and-test.yml +++ b/.github/workflows/build-and-test.yml @@ -13,10 +13,10 @@ jobs: steps: - uses: actions/checkout@v2 - - name: Setup .NET 6 + - name: Setup .NET uses: actions/setup-dotnet@v1 with: - dotnet-version: '6.x.x' + dotnet-version: '9.x.x' - name: Restore local tools run: dotnet tool restore - name: make script executable @@ -31,10 +31,10 @@ jobs: steps: - uses: actions/checkout@v2 - - name: Setup .NET 6 + - name: Setup .NET uses: actions/setup-dotnet@v1 with: - dotnet-version: '6.x.x' + dotnet-version: '9.x.x' - name: Restore local tools run: dotnet tool restore - name: Build and test diff --git a/build/build.fsproj b/build/build.fsproj index b3f0ebf49..f978756ba 100644 --- a/build/build.fsproj +++ b/build/build.fsproj @@ -31,4 +31,8 @@ + + + + diff --git a/global.json b/global.json index 501e79a87..f15a95928 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "sdk": { - "version": "8.0.100", - "rollForward": "latestFeature" + "version": "9.0.100", + "rollForward": "latestMinor" } } \ No newline at end of file diff --git a/src/FSharp.Stats/AlgTypes/Matrix.fs b/src/FSharp.Stats/AlgTypes/Matrix.fs index ccfd95f57..13f95e15a 100644 --- a/src/FSharp.Stats/AlgTypes/Matrix.fs +++ b/src/FSharp.Stats/AlgTypes/Matrix.fs @@ -14,7 +14,8 @@ open System.Runtime.InteropServices type Matrix<'T when 'T :> Numerics.INumber<'T> and 'T : (new: unit -> 'T) and 'T : struct - and 'T :> ValueType> + and 'T :> ValueType + and 'T : equality> (rows: int, cols: int, data: Vector<'T>) = /// Exposes the raw underlying data array (row-major flattened). @@ -36,7 +37,45 @@ type Matrix<'T when 'T :> Numerics.INumber<'T> if i < 0 || i >= rows || j < 0 || j >= cols then invalidArg "index" $"Index out of range: ({i}, {j})" data.[i * cols + j] <- value - + + // Implement IEquatable so that F# structural equality can use it + interface IEquatable> with + member this.Equals(other: Matrix<'T>) = + + // 1) Check dimension + if rows <> other.NumRows || cols <> other.NumCols then + false + else + // 2) Compare all elements + let otherData = other.Data + let mutable i = 0 + let mutable eq = true + while eq && i < data.Length do + if data[i] <> otherData[i] then + eq <- false + i <- i + 1 + eq + + // Override Object.Equals + override this.Equals(obj: obj) = + match obj with + | :? Matrix<'T> as other -> + (this :> IEquatable>).Equals(other) + | _ -> false + + // Override Object.GetHashCode + override this.GetHashCode() = + // We'll combine the row/col count plus some portion of the data to avoid huge cost. + // There's no perfect hashing for big arrays, but here's a simple example: + + let mutable hash = HashCode() + hash.Add(rows) + hash.Add(cols) + // Optionally: incorporate some or all elements + // For big arrays, consider sampling or a rolling hash approach. + for i in 0 .. data.Length - 1 do + hash.Add(data[i]) + hash.ToHashCode() /// /// Returns a new Matrix<'T> that is the slice of rows [rowStart..rowEnd] diff --git a/src/FSharp.Stats/AlgTypes/VectorExt.fs b/src/FSharp.Stats/AlgTypes/VectorExt.fs index ed6ba70b2..46ce0dfa5 100644 --- a/src/FSharp.Stats/AlgTypes/VectorExt.fs +++ b/src/FSharp.Stats/AlgTypes/VectorExt.fs @@ -13,6 +13,7 @@ module Vector = let inline cross<'T when 'T :> Numerics.INumber<'T> and 'T : (new: unit -> 'T) and 'T : struct + and 'T : equality and 'T :> ValueType> (colvec: Vector<'T>) (rowvec:Vector<'T>) : Matrix<'T> = if colvec.Length <> rowvec.Length then invalidArg "" "Vector must have the same length to compute the dot product." diff --git a/src/FSharp.Stats/Algebra/LinearAlgebra.fs b/src/FSharp.Stats/Algebra/LinearAlgebra.fs index e3cc65a1f..a291897b0 100644 --- a/src/FSharp.Stats/Algebra/LinearAlgebra.fs +++ b/src/FSharp.Stats/Algebra/LinearAlgebra.fs @@ -43,6 +43,7 @@ type LinearAlgebra = static member inline qrModifiedGramSchmidt<'T when 'T :> Numerics.INumber<'T> and 'T : (new: unit -> 'T) and 'T : struct + and 'T : equality and 'T :> ValueType and 'T :> Numerics.IRootFunctions<'T>> (A: Matrix<'T>) : Matrix<'T> * Matrix<'T> = @@ -80,6 +81,7 @@ type LinearAlgebra = static member inline backSubstitute<'T when 'T :> Numerics.INumber<'T> and 'T : (new: unit -> 'T) and 'T : struct + and 'T : equality and 'T :> ValueType> (r: Matrix<'T>) (y: Vector<'T>) : Vector<'T> = @@ -106,6 +108,7 @@ type LinearAlgebra = static member inline solveLinearQR<'T when 'T :> Numerics.INumber<'T> and 'T : (new: unit -> 'T) and 'T : struct + and 'T : equality and 'T :> ValueType and 'T :> Numerics.IRootFunctions<'T>> (A: Matrix<'T>) diff --git a/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj b/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj index 0c6ac7aba..6c420bdbe 100644 --- a/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj +++ b/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj @@ -5,6 +5,10 @@ false + + + + From 36f4139dad6a3115be698bcc7eef00eb336e790f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20M=C3=BChlhaus?= Date: Fri, 11 Apr 2025 14:43:15 +0200 Subject: [PATCH 024/121] Add some updated test cases --- .../AlgTypes/AlgTypesTopLevelOps.fs | 9 ++++ src/FSharp.Stats/AlgTypes/MatrixExt.fs | 24 +++++++++ src/FSharp.Stats/AlgTypes/VectorExt.fs | 4 ++ src/FSharp.Stats/FSharp.Stats.fsproj | 1 + tests/FSharp.Stats.Tests/Covariance.fs | 50 +++++++++---------- .../DistributionsContinuous.fs | 16 +++--- .../DistributionsDiscrete.fs | 36 ++++++------- .../FSharp.Stats.Tests.fsproj | 12 ++++- tests/FSharp.Stats.Tests/LinearAlgebra.fs | 13 +++-- 9 files changed, 106 insertions(+), 59 deletions(-) create mode 100644 src/FSharp.Stats/AlgTypes/AlgTypesTopLevelOps.fs diff --git a/src/FSharp.Stats/AlgTypes/AlgTypesTopLevelOps.fs b/src/FSharp.Stats/AlgTypes/AlgTypesTopLevelOps.fs new file mode 100644 index 000000000..9e2f89788 --- /dev/null +++ b/src/FSharp.Stats/AlgTypes/AlgTypesTopLevelOps.fs @@ -0,0 +1,9 @@ +namespace FSharp.Stats + + +[] +module AlgTypesTopLevelOps = + + let matrix ll = Matrix.ofRowSeq ll + let vector l = Vector.ofSeq l + //let rowvec l = RowVector.ofSeq l diff --git a/src/FSharp.Stats/AlgTypes/MatrixExt.fs b/src/FSharp.Stats/AlgTypes/MatrixExt.fs index d9cf579a3..5d4386ab6 100644 --- a/src/FSharp.Stats/AlgTypes/MatrixExt.fs +++ b/src/FSharp.Stats/AlgTypes/MatrixExt.fs @@ -110,6 +110,30 @@ module Matrix = let ofRows (rows : 'T[][]) : Matrix<'T> = Matrix.ofJaggedArray rows + /// Creates a matrix from a sequence of row sequences + let inline ofRowSeq (rows: seq<#seq<'T>>) : Matrix<'T> = + // Convert the outer seq to an array of row-seqs + let rowArr = rows |> Seq.toArray + if rowArr.Length = 0 then + invalidArg "rows" "Cannot create a matrix from an empty sequence of rows." + + // Determine the number of columns by checking the first row’s length + let colCount = rowArr.[0] |> Seq.length + + // Verify all rows have the same length + for i in 1 .. rowArr.Length - 1 do + let currentLen = rowArr.[i] |> Seq.length + if currentLen <> colCount then + invalidArg "rows" (sprintf "Row %d has length %d, expected %d." i currentLen colCount) + + // Flatten all row-seqs into a single array (row-major order) + let data = + rowArr + |> Array.collect (fun rowSeq -> rowSeq |> Seq.toArray) + + // Construct the matrix + Matrix<'T>(rowArr.Length, colCount, data) + let mapiRows (f: int -> Vector<'T> -> Vector<'U>) (m:Matrix<'T>) : Matrix<'U> = Matrix.getRows m |> Array.mapi (fun i v -> f i v) diff --git a/src/FSharp.Stats/AlgTypes/VectorExt.fs b/src/FSharp.Stats/AlgTypes/VectorExt.fs index 46ce0dfa5..cc9393c25 100644 --- a/src/FSharp.Stats/AlgTypes/VectorExt.fs +++ b/src/FSharp.Stats/AlgTypes/VectorExt.fs @@ -192,3 +192,7 @@ module Vector = for i = 0 to n - 1 do result.[i] <- b.[P i] result + + /// + let inline ofSeq (s:seq<'T>) : Vector<'T> = + s |> Array.ofSeq diff --git a/src/FSharp.Stats/FSharp.Stats.fsproj b/src/FSharp.Stats/FSharp.Stats.fsproj index b5c4c4605..542b345c4 100644 --- a/src/FSharp.Stats/FSharp.Stats.fsproj +++ b/src/FSharp.Stats/FSharp.Stats.fsproj @@ -36,6 +36,7 @@ + diff --git a/tests/FSharp.Stats.Tests/Covariance.fs b/tests/FSharp.Stats.Tests/Covariance.fs index 43f9c3a4e..93c0c93ec 100644 --- a/tests/FSharp.Stats.Tests/Covariance.fs +++ b/tests/FSharp.Stats.Tests/Covariance.fs @@ -107,31 +107,31 @@ let arrayTests = //tested in comparison with //https://www.itl.nist.gov/div898/handbook/pmc/section5/pmc541.htm -[] -let matrixTests = - let m = - [| - [|4.0;4.2;3.9;4.3;4.1|] - [|2.0;2.1;2.0;2.1;2.2|] - [|0.60;0.59;0.58;0.62;0.63|] - |] - |> matrix +//[] +//let matrixTests = +// let m = +// [| +// [|4.0;4.2;3.9;4.3;4.1|] +// [|2.0;2.1;2.0;2.1;2.2|] +// [|0.60;0.59;0.58;0.62;0.63|] +// |] +// |> matrix - testList "Matrix" [ - testCase "rowSampleCovarianceMatrixOf" <| fun () -> - let actual = Matrix.rowSampleCovarianceMatrixOf m - let expected = - [| - [|0.025; 0.0075; 0.00175|] - [|0.0075; 0.0070; 0.00135|] - [|0.00175;0.00135;0.00043|] - |] - |> matrix - let difference = - actual - expected - |> Matrix.mapiCols (fun i x -> Seq.max x) - |> Seq.max +// testList "Matrix" [ +// testCase "rowSampleCovarianceMatrixOf" <| fun () -> +// let actual = Matrix.rowSampleCovarianceMatrixOf m +// let expected = +// [| +// [|0.025; 0.0075; 0.00175|] +// [|0.0075; 0.0070; 0.00135|] +// [|0.00175;0.00135;0.00043|] +// |] +// |> matrix +// let difference = +// actual - expected +// |> Matrix.mapiCols (fun i x -> Seq.max x) +// |> Seq.max - Expect.floatClose Accuracy.high difference 0. "Should be equal (double precision)" - ] +// Expect.floatClose Accuracy.high difference 0. "Should be equal (double precision)" +// ] diff --git a/tests/FSharp.Stats.Tests/DistributionsContinuous.fs b/tests/FSharp.Stats.Tests/DistributionsContinuous.fs index 2a6b19c63..56f963b75 100644 --- a/tests/FSharp.Stats.Tests/DistributionsContinuous.fs +++ b/tests/FSharp.Stats.Tests/DistributionsContinuous.fs @@ -644,15 +644,15 @@ let chiTests = ] let multivariateNormalTests = - let mvn = Continuous.MultivariateNormal.Init (vector [0.;0.;0.;0.;0.]) (Matrix.identity 5) + let mvn = Continuous.MultivariateNormal.Init ([|0.;0.;0.;0.;0.|]) (Matrix.identity 5) let pdfs= [| - [0.537667139546100;3.578396939725760;-0.124144348216312;0.488893770311789;-1.068870458168032] - [0.318765239858981;0.725404224946106;0.671497133608080;0.293871467096658;0.325190539456195] - [-0.433592022305684;0.714742903826096;0.717238651328838;0.888395631757642;1.370298540095228] + [| 0.537667139546100;3.578396939725760;-0.124144348216312;0.488893770311789;-1.068870458168032 |] + [| 0.318765239858981;0.725404224946106;0.671497133608080;0.293871467096658;0.325190539456195 |] + [| -0.433592022305684;0.714742903826096;0.717238651328838;0.888395631757642;1.370298540095228 |] |] |> Array.map (fun v -> - mvn.PDF (vector v) + mvn.PDF v ) // TestCases from Matlab: (* @@ -665,10 +665,10 @@ let multivariateNormalTests = testList "Distributions.multivariateNormal" [ testCase "Parameters" <| fun () -> let param = - match (Continuous.MultivariateNormal.Init (vector [1.;0.4]) (matrix [[0.3;2.3];[1.2;4.3]])).Parameters with + match (Continuous.MultivariateNormal.Init ([|1.;0.4|]) (matrix [[0.3;2.3];[1.2;4.3]])).Parameters with | MultivariateNormal x -> x.Mean,x.StandardDeviation - | _ -> (vector [],matrix[]) - Expect.equal param ((vector [1.;0.4]),(matrix [[0.3;2.3];[1.2;4.3]])) "Distribution parameters are incorrect." + | _ -> ([||],matrix[]) + Expect.equal param (( [|1.;0.4|]),(matrix [[0.3;2.3];[1.2;4.3]])) "Distribution parameters are incorrect." testCase "PDF.testCase_1" <| fun () -> Expect.floatClose Accuracy.veryHigh 0.000007209186311 pdfs.[0] "Should be equal" testCase "PDF.testCase_2" <| fun () -> diff --git a/tests/FSharp.Stats.Tests/DistributionsDiscrete.fs b/tests/FSharp.Stats.Tests/DistributionsDiscrete.fs index a4f9ff8e9..029354c87 100644 --- a/tests/FSharp.Stats.Tests/DistributionsDiscrete.fs +++ b/tests/FSharp.Stats.Tests/DistributionsDiscrete.fs @@ -383,15 +383,15 @@ let binomialTests = [] let multinomialTests = // TestCases from R stats: dmultinom(prob, x) - let prob1 = vector [0.2;0.4;0.4;0.] - let x1 = Vector.Generic.ofList [2;4;2;0] + let prob1 = [|0.2;0.4;0.4;0.|] + let x1 = [|2;4;2;0|] - let prob2 = vector [0.02;0.04;0.02;0.;0.01;0.1;0.81] - let x2 = Vector.Generic.ofList [2;4;2;0;1;10;100] + let prob2 = [|0.02;0.04;0.02;0.;0.01;0.1;0.81|] + let x2 = [|2;4;2;0;1;10;100|] testList "Distributions.Discrete.Multinominal" [ testCase "Mean" <| fun () -> let testCase = Discrete.Multinomial.Mean prob1 100 - let means = vector [20.;40.;40.;0.] + let means = [|20.;40.;40.;0.|] TestExtensions.TestExtensions.sequenceEqual Accuracy.veryHigh testCase means @@ -399,7 +399,7 @@ let multinomialTests = testCase "Variance" <| fun () -> let testCase = Discrete.Multinomial.Variance prob2 119 - let variances = vector [2.3324;4.5696;2.3324;0;1.1781;10.71;18.3141] + let variances = [|2.3324;4.5696;2.3324;0;1.1781;10.71;18.3141|] TestExtensions.TestExtensions.sequenceEqual Accuracy.veryHigh testCase variances @@ -420,8 +420,8 @@ let multinomialTests = testCase pmf "Multinominal.PMF is incorrect" - let prob1 = vector [0.1;0.4;0.5] - let x = Vector.Generic.ofList [0;0;0] + let prob1 = [|0.1;0.4;0.5|] + let x = [|0;0;0|] let testCase3 = Discrete.Multinomial.PMF prob1 x Expect.floatClose Accuracy.veryHigh @@ -429,7 +429,7 @@ let multinomialTests = 1. "Multinominal.PMF is incorrect" - let testCase4 = Discrete.Multinomial.PMF (vector [|0.5; 0.5|]) (Vector.Generic.ofArray [|5; 5|]) + let testCase4 = Discrete.Multinomial.PMF [|0.5; 0.5|] [|5; 5|] let r_value4 = 0.2460937500001213 Expect.floatClose Accuracy.high @@ -438,7 +438,7 @@ let multinomialTests = "Multinomial.PMF (vector [|0.5; 0.5|]) (Vector.Generic.ofArray [|5; 5|]) should result in Binomial.PMF 0.5 10 5" - let testCase5 = Discrete.Multinomial.PMF (vector [|0.123; 0.877|]) (Vector.Generic.ofArray [|20; 180|]) + let testCase5 = Discrete.Multinomial.PMF [|0.123; 0.877|] [|20; 180|] Expect.floatClose Accuracy.high testCase5 @@ -448,26 +448,26 @@ let multinomialTests = testCase "Checks.pSum1" <| fun () -> - let prob2 = vector [0.1;0.3;0.5] - let x = Vector.Generic.ofList [1;2;3] + let prob2 = [|0.1;0.3;0.5|] + let x = [|1;2;3|] let testCase() = Discrete.Multinomial.PMF prob2 x Expect.throws (fun _ -> testCase() |> ignore) "p does not sum up to 1 but no error is thrown" testCase "Checks.UnequalInputLength" <| fun () -> - let prob3 = vector [0.1;0.4;0.5;0] - let x = Vector.Generic.ofList [1;2;3] + let prob3 = [|0.1;0.4;0.5;0|] + let x = [|1;2;3|] let testCase() = Discrete.Multinomial.PMF prob3 x Expect.throws (fun _ -> testCase() |> ignore) "input vectors are of unequal length" testCase "Checks.WrongProb" <| fun () -> - let prob4 = vector [1.;-0.5;0.5] - let x = Vector.Generic.ofList [1;2;3] + let prob4 = [|1.;-0.5;0.5|] + let x =[|1;2;3|] let testCase() = Discrete.Multinomial.PMF prob4 x Expect.throws (fun _ -> testCase() |> ignore) "probabilities are negative" testCase "Checks.SuccessAtProb0" <| fun () -> - let prob5 = vector [0.5;0;0.5] - let x = Vector.Generic.ofList [1;2;3] + let prob5 = [|0.5;0;0.5|] + let x = [|1;2;3|] let testCase() = Discrete.Multinomial.PMF prob5 x Expect.throws (fun _ -> testCase() |> ignore) "probabilities of 0 is associated to success event" ] diff --git a/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj b/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj index 6c420bdbe..1415e95d3 100644 --- a/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj +++ b/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj @@ -6,9 +6,19 @@ + + + + + + + + + + - + diff --git a/tests/FSharp.Stats.Tests/LinearAlgebra.fs b/tests/FSharp.Stats.Tests/LinearAlgebra.fs index 989ea81f0..f0a96db43 100644 --- a/tests/FSharp.Stats.Tests/LinearAlgebra.fs +++ b/tests/FSharp.Stats.Tests/LinearAlgebra.fs @@ -4,16 +4,15 @@ open Expecto open FSharp.Stats open FSharp.Stats.Algebra -open FSharp.Stats.Algebra.LinearAlgebraManaged open TestExtensions [] let managedSVDTests = let svdManaged A = - let s,u,vt = LinearAlgebraManaged.SVD A + let s,u,vt = LinearAlgebra.SVD A let sM = - let tmp= Matrix.create A.NumRows A.NumCols 0. + let tmp= Matrix.zeroCreate A.NumRows A.NumCols for i = 0 to s.Length-1 do tmp.[i,i] <- s.[i] tmp @@ -26,15 +25,15 @@ let managedSVDTests = testCase "m=n Matrix: Recover from decomposition" <| fun () -> let u,s,vt = svdManaged mEqualN let mEqualNRecov = (u * s * vt) - let m = mEqualN |> Matrix.toJaggedArray |> Array.concat - let m' = mEqualNRecov |> Matrix.toJaggedArray |> Array.concat + let m = mEqualN.toJaggedArray() |> Array.concat + let m' = mEqualNRecov.toJaggedArray() |> Array.concat TestExtensions.sequenceEqual Accuracy.high m m' "Matrices computed by SVD did not yield the initial matrix when multiplied." testCase "m=n Matrix: u and vt consist of unit vectors, row- and column- wise." <| fun () -> let u,s,vt = svdManaged mEqualN let vecNorms = [ - u |> Matrix.mapCols Vector.norm |> RowVector.toArray + u |> Matrix.mapiCols (fun _ v -> Vector.norm v) vt|> Matrix.mapCols Vector.norm |> RowVector.toArray u |> Matrix.mapRows (fun x -> x.Transpose |> Vector.norm) |> Vector.toArray vt|> Matrix.mapRows (fun x -> x.Transpose |> Vector.norm) |> Vector.toArray @@ -43,7 +42,7 @@ let managedSVDTests = TestExtensions.sequenceEqual Accuracy.high (Array.create vecNorms.Length 1.) vecNorms "Matrices computed by SVD did not consist of unit vectors, row- and column- wise." testCase "m=n Matrix: s contains correct singular values." <| fun () -> - let s,u,vt = LinearAlgebraManaged.SVD mEqualN + let s,u,vt = LinearAlgebra.SVD mEqualN TestExtensions.sequenceEqual Accuracy.high ([|15.81461344;2.213142934|]) s "Matrices computed by SVD did not yield correct singular values." testCase "m From ef409e01099e6bacb5e5670dd1ec28cae5d799ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20M=C3=BChlhaus?= Date: Fri, 11 Apr 2025 16:01:17 +0200 Subject: [PATCH 025/121] Add Vector tests --- src/FSharp.Stats/AlgTypes/Vector.fs | 2 +- src/FSharp.Stats/AlgTypes/VectorExt.fs | 19 +- src/FSharp.Stats/Playground.fsx | 16 +- .../FSharp.Stats.Tests.fsproj | 1 + tests/FSharp.Stats.Tests/Vector.fs | 616 +++++++++++++++++- 5 files changed, 632 insertions(+), 22 deletions(-) diff --git a/src/FSharp.Stats/AlgTypes/Vector.fs b/src/FSharp.Stats/AlgTypes/Vector.fs index 29523787d..d32954d85 100644 --- a/src/FSharp.Stats/AlgTypes/Vector.fs +++ b/src/FSharp.Stats/AlgTypes/Vector.fs @@ -253,6 +253,6 @@ type Vector = and 'T :> ValueType> (v:Vector<'T>) : 'T = if v.Length = 0 then invalidArg "v" "Cannot compute min of empty vector." - Acceleration.SIMDUtils.fold (fun a b -> Numerics.Vector.Max(a, b)) min v.[0] v + Acceleration.SIMDUtils.fold (fun a b -> Numerics.Vector.Max(a, b)) max v.[0] v diff --git a/src/FSharp.Stats/AlgTypes/VectorExt.fs b/src/FSharp.Stats/AlgTypes/VectorExt.fs index cc9393c25..22be07622 100644 --- a/src/FSharp.Stats/AlgTypes/VectorExt.fs +++ b/src/FSharp.Stats/AlgTypes/VectorExt.fs @@ -9,16 +9,29 @@ module Vector = /// Computes the vector cross product a^Tb /// The first vector is column vector. /// The second vector is the row vector. - /// The cross product of the two vectors. + /// The cross product (or outer product) of the two vectors. let inline cross<'T when 'T :> Numerics.INumber<'T> and 'T : (new: unit -> 'T) and 'T : struct and 'T : equality and 'T :> ValueType> (colvec: Vector<'T>) (rowvec:Vector<'T>) : Matrix<'T> = + //TODO: SIMD Acceleration! + if colvec.Length <> rowvec.Length then invalidArg "" "Vector must have the same length to compute the dot product." - let data = Acceleration.SIMDUtils.map2Unchecked ( * ) ( * ) colvec rowvec - Matrix(colvec.Length,rowvec.Length,data) + let n = colvec.Length + let m = rowvec.Length + + // Allocate the n*m storage + let data = Array.zeroCreate<'T> (n * m) + + // Fill with colvec[i] * rowvec[j], typical row-major arrangement + for i in 0 .. n - 1 do + for j in 0 .. m - 1 do + data.[i * m + j] <- colvec.[i] * rowvec.[j] + + // Build the matrix (n x m) + Matrix<'T>(n, m, data) /// Indexed fold over a vector diff --git a/src/FSharp.Stats/Playground.fsx b/src/FSharp.Stats/Playground.fsx index a6b066450..31b063053 100644 --- a/src/FSharp.Stats/Playground.fsx +++ b/src/FSharp.Stats/Playground.fsx @@ -1,4 +1,4 @@ -#I "bin/Debug/netstandard2.0" +#I "bin/Release/.net8.0" #r "FSharp.Stats.dll" #r "nuget: Plotly.NET" @@ -7,6 +7,20 @@ open FSharp.Stats open FSharp.Stats.Distributions open Plotly.NET +let a = 1 % 3 // 1 +let b = 2 % 3 // 2 +let c = 3 % 3 // 0 + + +let colvec = [| 1.0; 2.0; 3.0 |] +let rowvec = [| 4.0; 5.0; 6.0 |] + +// The expected 3x3 matrix is computed by: +// [ [1.0*4.0, 1.0*5.0, 1.0*6.0] +// [2.0*4.0, 2.0*5.0, 2.0*6.0] +// [3.0*4.0, 3.0*5.0, 3.0*6.0] ] +let result = Vector.cross colvec rowvec + let alpha = 9.9 //0.4 let beta = 31 //4.2 diff --git a/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj b/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj index 1415e95d3..8c720070e 100644 --- a/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj +++ b/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj @@ -18,6 +18,7 @@ + diff --git a/tests/FSharp.Stats.Tests/Vector.fs b/tests/FSharp.Stats.Tests/Vector.fs index 42009b896..70cfa5713 100644 --- a/tests/FSharp.Stats.Tests/Vector.fs +++ b/tests/FSharp.Stats.Tests/Vector.fs @@ -1,23 +1,605 @@ module VectorTests -open Expecto +open System +open Expecto open FSharp.Stats -open FSharp.Stats.Vector - -let private testVectorA = - let values = [|0.;3.;6.|] - Vector(Some (Instances.FloatNumerics :> INumeric),values) [] -let covarianceTests = - let x = vector [5.;12.;18.;-23.;45.] - let y = vector [2.;8.;18.;-20.;28.] - - testList "Vector" [ - testCase "cov" <| fun () -> - let cov = Vector.cov x y - Expect.floatClose Accuracy.high cov 434.90 "Should be equal (double precision)" - testCase "covPopulation" <| fun () -> - let covPop = Vector.covPopulation x y - Expect.floatClose Accuracy.high covPop 347.92 "Should be equal (double precision)" +let vectorTests = + testList "Vector Tests" [ + + // ====================================================================== + // INT TESTS + // ====================================================================== + testList "Integer Vector Tests" [ + + // ------------------------------------------------------------------ + // Add + // ------------------------------------------------------------------ + testCase "add: integer vectors of same length" <| fun _ -> + let v1 = [| 1; 2; 3 |] + let v2 = [| 4; 5; 6 |] + let result = Vector.add v1 v2 + let expected = [| 5; 7; 9 |] + Expect.equal result expected "Should add each element pairwise" + + testCase "add: throws on dimension mismatch" <| fun _ -> + let v1 = [| 1; 2 |] + let v2 = [| 1; 2; 3 |] + Expect.throwsT (fun () -> Vector.add v1 v2 |> ignore) + "Should throw ArgumentException when vectors differ in length" + + // ------------------------------------------------------------------ + // Subtract + // ------------------------------------------------------------------ + testCase "subtract: integer vectors of same length" <| fun _ -> + let v1 = [| 5; 5; 5 |] + let v2 = [| 1; 2; 3 |] + let result = Vector.subtract v1 v2 + let expected = [| 4; 3; 2 |] + Expect.equal result expected "Should subtract each element pairwise" + + testCase "subtract: throws on dimension mismatch" <| fun _ -> + let v1 = [| 1; 2; 3 |] + let v2 = [| 1; 2 |] + Expect.throwsT (fun () -> Vector.subtract v1 v2 |> ignore) + "Should throw ArgumentException when vectors differ in length" + + // ------------------------------------------------------------------ + // Multiply + // ------------------------------------------------------------------ + testCase "multiply: integer vectors of same length" <| fun _ -> + let v1 = [| 2; 2; 2 |] + let v2 = [| 3; 4; 5 |] + let result = Vector.multiply v1 v2 + let expected = [| 6; 8; 10 |] + Expect.equal result expected "Should multiply each element pairwise" + + testCase "multiply: throws on dimension mismatch" <| fun _ -> + let v1 = [| 2; 2 |] + let v2 = [| 3; 4; 5 |] + Expect.throwsT (fun () -> Vector.multiply v1 v2 |> ignore) + "Should throw ArgumentException when vectors differ in length" + + // ------------------------------------------------------------------ + // Divide + // ------------------------------------------------------------------ + testCase "divide: integer vectors of same length" <| fun _ -> + let v1 = [| 10; 20; 30 |] + let v2 = [| 2; 5; 5 |] + let result = Vector.divide v1 v2 + let expected = [| 5; 4; 6 |] + Expect.equal result expected "Should divide each element pairwise" + + testCase "divide: throws on dimension mismatch" <| fun _ -> + let v1 = [| 10; 20 |] + let v2 = [| 2; 5; 5 |] + Expect.throwsT (fun () -> Vector.divide v1 v2 |> ignore) + "Should throw ArgumentException when vectors differ in length" + + // ------------------------------------------------------------------ + // Scalar Operations + // ------------------------------------------------------------------ + testCase "addScalar: adds scalar to every element" <| fun _ -> + let v = [| 1; 2; 3 |] + let scalar = 5 + let result = Vector.addScalar v scalar + let expected = [| 6; 7; 8 |] + Expect.equal result expected "Should add the scalar to each element" + + testCase "subtractScalar: subtracts scalar from every element" <| fun _ -> + let v = [| 1; 2; 3 |] + let scalar = 1 + let result = Vector.subtractScalar v scalar + let expected = [| 0; 1; 2 |] + Expect.equal result expected "Should subtract the scalar from each element" + + testCase "multiplyScalar: multiplies scalar to every element" <| fun _ -> + let v = [| 2; 4; 6 |] + let scalar = 3 + let result = Vector.multiplyScalar v scalar + let expected = [| 6; 12; 18 |] + Expect.equal result expected "Should multiply the scalar with each element" + + testCase "divideScalar: divides every element by scalar" <| fun _ -> + let v = [| 10; 20; 30 |] + let scalar = 10 + let result = Vector.divideScalar v scalar + let expected = [| 1; 2; 3 |] + Expect.equal result expected "Should divide each element by the scalar" + + // ------------------------------------------------------------------ + // sum + // ------------------------------------------------------------------ + testCase "sum: sums all elements of an integer vector" <| fun _ -> + let v = [| 1; 2; 3; 4 |] + let result = Vector.sum v + Expect.equal result 10 "Should be the sum of all elements" + + testCase "sum: sums an empty integer vector (should be 0)" <| fun _ -> + let v : int[] = [||] + let result = Vector.sum v + Expect.equal result 0 "Sum of empty array should be 0" + + // ------------------------------------------------------------------ + // product + // ------------------------------------------------------------------ + testCase "product: multiplies all elements of an integer vector" <| fun _ -> + let v = [| 1; 2; 3; 4 |] + let result = Vector.product v + Expect.equal result 24 "Should be the product of all elements" + + testCase "product: empty integer vector (should be 1 for identity)" <| fun _ -> + let v : int[] = [||] + let result = Vector.product v + Expect.equal result 1 "Product of empty array should be 1" + + + // ------------------------------------------------------------------ + // dot + // ------------------------------------------------------------------ + testCase "dot: computes dot product of two integer vectors" <| fun _ -> + let v1 = [| 1; 2; 3 |] + let v2 = [| 4; 5; 6 |] + let result = Vector.dot v1 v2 + // Dot = 1*4 + 2*5 + 3*6 = 4 + 10 + 18 = 32 + Expect.equal result 32 "Dot product should match expected" + + testCase "dot: throws on dimension mismatch" <| fun _ -> + let v1 = [| 1; 2 |] + let v2 = [| 3; 4; 5 |] + Expect.throwsT (fun () -> Vector.dot v1 v2 |> ignore) + "Should throw ArgumentException when vectors differ in length" + + + // ------------------------------------------------------------------ + // min + // ------------------------------------------------------------------ + testCase "min: finds minimum in a non-empty integer vector" <| fun _ -> + let v = [| 10; 2; 30; 4 |] + let result = Vector.min v + Expect.equal result 2 "Should find the smallest integer in the array" + + testCase "min: throws on empty integer vector" <| fun _ -> + let v : int[] = [||] + Expect.throwsT (fun () -> Vector.min v |> ignore) + "Should throw ArgumentException for empty vector" + + // ------------------------------------------------------------------ + // max + // ------------------------------------------------------------------ + testCase "max: finds maximum in a non-empty integer vector" <| fun _ -> + let v = [| 10; 2; 30; 4 |] + let result = Vector.max v + Expect.equal result 30 "Should find the largest integer in the array" + + testCase "max: throws on empty integer vector" <| fun _ -> + let v : int[] = [||] + Expect.throwsT (fun () -> Vector.max v |> ignore) + "Should throw ArgumentException for empty vector" + + // ------------------------------------------------------------------ + // OPERATOR TESTS (Int) + // ------------------------------------------------------------------ + testCase "vector-vector operators (int): .+ .- .* ./" <| fun _ -> + let v1 = [| 1; 2; 3 |] + let v2 = [| 4; 5; 6 |] + + // .+ + let addResult = v1 .+ v2 + Expect.equal addResult [|5; 7; 9|] "v1 .+ v2 should match element-wise add" + + // .- + let subResult = v1 .- v2 + Expect.equal subResult [|-3; -3; -3|] "v1 .- v2 should match element-wise subtract" + + // .* + let mulResult = v1 .* v2 + Expect.equal mulResult [|4; 10; 18|] "v1 .* v2 should match element-wise multiply" + + // ./ + let divResult = [| 10; 20; 30 |] ./ [| 2; 5; 5 |] + Expect.equal divResult [|5; 4; 6|] "Should match element-wise division" + + testCase "vector-scalar operators (int): .+ .- .* ./" <| fun _ -> + let v = [| 2; 4; 6 |] + + // v .+ scalar + let addScalarResult = v .+ 2 + Expect.equal addScalarResult [|4; 6; 8|] "v .+ 2 should add 2 to all elements" + + // v .- scalar + let subScalarResult = v .- 2 + Expect.equal subScalarResult [|0; 2; 4|] "v .- 2 should subtract 2 from all elements" + + // v .* scalar + let mulScalarResult = v .* 3 + Expect.equal mulScalarResult [|6; 12; 18|] "v .* 3 should multiply all elements by 3" + + // v ./ scalar + let divScalarResult = [| 10; 20; 30 |] ./ 10 + Expect.equal divScalarResult [|1; 2; 3|] "Should divide all elements by 10" + ] + + + // ====================================================================== + // FLOAT TESTS + // ====================================================================== + testList "Float Vector Tests" [ + + // ------------------------------------------------------------------ + // Add + // ------------------------------------------------------------------ + testCase "add: float vectors of same length" <| fun _ -> + let v1 = [| 1.0; 2.0; 3.0 |] + let v2 = [| 4.0; 5.0; 6.0 |] + let result = Vector.add v1 v2 + let expected = [| 5.0; 7.0; 9.0 |] + Expect.equal result expected "Should add each element pairwise" + + testCase "add: throws on dimension mismatch" <| fun _ -> + let v1 = [| 1.0; 2.0 |] + let v2 = [| 1.0; 2.0; 3.0 |] + Expect.throwsT (fun () -> Vector.add v1 v2 |> ignore) + "Should throw ArgumentException when vectors differ in length" + + // ------------------------------------------------------------------ + // Subtract + // ------------------------------------------------------------------ + testCase "subtract: float vectors of same length" <| fun _ -> + let v1 = [| 5.5; 5.0; 5.75 |] + let v2 = [| 1.5; 2.0; 3.25 |] + let result = Vector.subtract v1 v2 + let expected = [| 4.0; 3.0; 2.5 |] + Expect.equal result expected "Should subtract each element pairwise" + + // ------------------------------------------------------------------ + // Multiply + // ------------------------------------------------------------------ + testCase "multiply: float vectors of same length" <| fun _ -> + let v1 = [| 2.0; 2.5; 3.0 |] + let v2 = [| 3.0; 4.0; 5.0 |] + let result = Vector.multiply v1 v2 + let expected = [| 6.0; 10.0; 15.0 |] + Expect.equal result expected "Should multiply each element pairwise" + + // ------------------------------------------------------------------ + // Divide + // ------------------------------------------------------------------ + testCase "divide: float vectors of same length" <| fun _ -> + let v1 = [| 10.0; 20.0; 30.0 |] + let v2 = [| 2.0; 5.0; 5.0 |] + let result = Vector.divide v1 v2 + let expected = [| 5.0; 4.0; 6.0 |] + Expect.equal result expected "Should divide each element pairwise" + + // ------------------------------------------------------------------ + // Scalar Operations + // ------------------------------------------------------------------ + testCase "addScalar: adds scalar to every float element" <| fun _ -> + let v = [| 1.0; 2.0; 3.0 |] + let scalar = 5.5 + let result = Vector.addScalar v scalar + let expected = [| 6.5; 7.5; 8.5 |] + Expect.equal result expected "Should add 5.5 to each element" + + testCase "subtractScalar: subtract scalar from every float element" <| fun _ -> + let v = [| 1.0; 2.5; 3.75 |] + let scalar = 1.25 + let result = Vector.subtractScalar v scalar + let expected = [| -0.25; 1.25; 2.5 |] + Expect.equal result expected "Should subtract 1.25 from each element" + + testCase "multiplyScalar: multiplies scalar with every float element" <| fun _ -> + let v = [| 2.5; 4.0; 6.0 |] + let scalar = 2.0 + let result = Vector.multiplyScalar v scalar + let expected = [| 5.0; 8.0; 12.0 |] + Expect.equal result expected "Should multiply each element by 2.0" + + testCase "divideScalar: divides every float element by scalar" <| fun _ -> + let v = [| 10.0; 20.0; 30.0 |] + let scalar = 2.0 + let result = Vector.divideScalar v scalar + let expected = [| 5.0; 10.0; 15.0 |] + Expect.equal result expected "Should divide each element by 2.0" + + // ------------------------------------------------------------------ + // sum + // ------------------------------------------------------------------ + testCase "sum: sums all elements of a float vector" <| fun _ -> + let v = [| 1.1; 2.2; 3.3; 4.4 |] + let result = Vector.sum v + // Expect exact or near: 1.1 + 2.2 + 3.3 + 4.4 = 11.0 + Expect.floatClose Accuracy.veryHigh 11.0 result "Sum of [1.1;2.2;3.3;4.4] = 11.0" + + testCase "sum: sums empty float vector (should be 0.0)" <| fun _ -> + let v : float[] = [||] + let result = Vector.sum v + Expect.equal result 0.0 "Sum of empty array should be 0.0" + + // ------------------------------------------------------------------ + // product + // ------------------------------------------------------------------ + testCase "product: multiplies all elements of a float vector" <| fun _ -> + let v = [| 1.0; 2.0; 3.0 |] + let result = Vector.product v + Expect.equal result 6.0 "1.0 * 2.0 * 3.0 = 6.0" + + testCase "product: empty float vector" <| fun _ -> + // By definition in your code, fold starts with 1. + let v : float[] = [||] + let result = Vector.product v + Expect.equal result 1.0 "Product of empty array should be 1.0" + + // ------------------------------------------------------------------ + // mean + // ------------------------------------------------------------------ + testCase "mean: computes mean of a float vector" <| fun _ -> + let v = [| 2.0; 4.0; 6.0; 8.0 |] + let result = Vector.mean v + // (2.0 + 4.0 + 6.0 + 8.0) / 4 = 5.0 + Expect.floatClose Accuracy.veryHigh 5.0 result "Mean should be 5.0" + + testCase "mean: throws on empty float vector" <| fun _ -> + let v : float[] = [||] + Expect.throwsT (fun () -> Vector.mean v |> ignore) + "Should throw ArgumentException when float vector is empty" + + // ------------------------------------------------------------------ + // dot + // ------------------------------------------------------------------ + testCase "dot: computes dot product of two float vectors" <| fun _ -> + let v1 = [| 1.0; 2.0; 3.0 |] + let v2 = [| 4.0; 5.0; 6.0 |] + let result = Vector.dot v1 v2 + // Dot = 1*4 + 2*5 + 3*6 = 4 + 10 + 18 = 32 + Expect.floatClose Accuracy.veryHigh 32.0 result "Dot product should be 32.0" + + // ------------------------------------------------------------------ + // norm + // ------------------------------------------------------------------ + testCase "norm: computes Euclidean norm of a 3-4-5 triangle (float)" <| fun _ -> + let v = [| 3.0; 4.0 |] + let result = Vector.norm v + Expect.floatClose Accuracy.veryHigh 5.0 result "Norm of [3.0;4.0] should be 5.0" + + // ------------------------------------------------------------------ + // min + // ------------------------------------------------------------------ + testCase "min: finds minimum in a non-empty float vector" <| fun _ -> + let v = [| 10.0; 2.0; 30.5; 4.1 |] + let result = Vector.min v + Expect.equal result 2.0 "Should find the smallest float in the array" + + testCase "min: throws on empty float vector" <| fun _ -> + let v : float[] = [||] + Expect.throwsT (fun () -> Vector.min v |> ignore) + "Should throw ArgumentException for empty vector" + + // ------------------------------------------------------------------ + // max + // ------------------------------------------------------------------ + testCase "max: finds maximum in a non-empty float vector" <| fun _ -> + let v = [| 10.0; 2.0; 30.5; 4.1 |] + let result = Vector.max v + Expect.equal result 30.5 "Should find the largest float in the array" + + testCase "max: throws on empty float vector" <| fun _ -> + let v : float[] = [||] + Expect.throwsT (fun () -> Vector.max v |> ignore) + "Should throw ArgumentException for empty vector" + + // ------------------------------------------------------------------ + // OPERATOR TESTS (Float) + // ------------------------------------------------------------------ + testCase "vector-vector operators (float): .+ .- .* ./" <| fun _ -> + let v1 = [| 1.0; 2.0; 3.0 |] + let v2 = [| 4.0; 5.0; 6.0 |] + + // .+ + let addResult = v1 .+ v2 + Expect.equal addResult [|5.0; 7.0; 9.0|] "v1 .+ v2 should match element-wise add" + + // .- + let subResult = v1 .- v2 + Expect.equal subResult [|-3.0; -3.0; -3.0|] "v1 .- v2 should match element-wise subtract" + + // .* + let mulResult = v1 .* v2 + Expect.equal mulResult [|4.0; 10.0; 18.0|] "v1 .* v2 should match element-wise multiply" + + // ./ + let divResult = [| 10.0; 20.0; 30.0 |] ./ [| 2.0; 5.0; 5.0 |] + Expect.equal divResult [|5.0; 4.0; 6.0|] "Should match element-wise division" + + testCase "vector-scalar operators (float): .+ .- .* ./" <| fun _ -> + let v = [| 2.5; 4.0; 6.0 |] + + // v .+ scalar + let addScalarResult = v .+ 2.0 + Expect.equal addScalarResult [|4.5; 6.0; 8.0|] "v .+ 2.0 should add 2.0 to all elements" + + // v .- scalar + let subScalarResult = v .- 0.5 + Expect.equal subScalarResult [|2.0; 3.5; 5.5|] "v .- 0.5 should subtract 0.5 from all elements" + + // v .* scalar + let mulScalarResult = v .* 1.5 + Expect.equal mulScalarResult [|3.75; 6.0; 9.0|] "v .* 1.5 should multiply all elements by 1.5" + + // v ./ scalar + let divScalarResult = [| 10.0; 20.0; 30.0 |] ./ 10.0 + Expect.equal divScalarResult [|1.0; 2.0; 3.0|] "Should divide all elements by 10.0" + + // ------------------------------------------------------------------ + // cross (outer) product + // ------------------------------------------------------------------ + testCase "cross: computes the outer product of two float vectors" <| fun _ -> + // 'Vector.cross' is assumed to produce a 2D array (matrix) + let colvec = [| 1.0; 2.0; 3.0 |] + let rowvec = [| 4.0; 5.0; 6.0 |] + + // The expected 3x3 matrix is computed by: + // [ [1.0*4.0, 1.0*5.0, 1.0*6.0] + // [2.0*4.0, 2.0*5.0, 2.0*6.0] + // [3.0*4.0, 3.0*5.0, 3.0*6.0] ] + let result = Vector.cross colvec rowvec + let expected = + [| [|4.0; 5.0; 6.0|] + [|8.0; 10.0; 12.0|] + [|12.0;15.0; 18.0|] |] |> matrix + + Expect.equal result expected "Expected outer product of colvec and rowvec" + ] + // ====================================================================== + // Vector manipulation tests + // ====================================================================== + testList "Vector manipulation Tests" [ + + test "foldi applies a function with index to a vector" { + let v = [|1; 2; 3|] + let result = Vector.foldi (fun i acc x -> acc + i * x) 0 v + Expect.equal result 8 "Expected indexed fold result" + } + + test "mapi applies a function with index to each element" { + let v = [|1; 2; 3|] + let result = Vector.mapi (fun i x -> x + i) v + Expect.equal result [|1; 3; 5|] "Expected indexed map result" + } + + test "filter filters elements by predicate" { + let v = [|1; 2; 3; 4|] + let result = Vector.filter (fun x -> x % 2 = 0) v + Expect.equal result [|2; 4|] "Expected filtered vector" + } + + test "init creates a vector using a generator function" { + let result = Vector.init 5 (fun i -> i * 2) + Expect.equal result [|0; 2; 4; 6; 8|] "Expected initialized vector" + } + + test "slice extracts a slice from a vector" { + let v = [|1; 2; 3; 4; 5|] + let result = Vector.slice 1 3 v + Expect.equal result [|2; 3; 4|] "Expected sliced vector" + } + + test "argmax finds the index of the maximum value" { + let v = [|1; 3; 2|] + let result = Vector.argmax v + Expect.equal result 1 "Expected index of maximum value" + } + + test "argmin finds the index of the minimum value" { + let v = [|3; 1; 2|] + let result = Vector.argmin v + Expect.equal result 1 "Expected index of minimum value" + } + + test "padRight pads a vector to a given length" { + let v = [|1; 2|] + let result = Vector.padRight 5 0 v + Expect.equal result [|1; 2; 0; 0; 0|] "Expected padded vector" + } + + test "zip combines two vectors with indices" { + let v1 = [|1; 2; 3|] + let v2 = [|4; 5; 6|] + let result = Vector.zip v1 v2 + Expect.equal result [|(0, 1, 4); (1, 2, 5); (2, 3, 6)|] "Expected zipped vector" + } + + test "argminBy finds the index of the minimum value using a projection" { + let v = [|1; 2; 3|] + let result = Vector.argminBy (fun x -> -x) v + Expect.equal result 2 "Expected index of minimum value by projection" + } + + test "argmaxBy finds the index of the maximum value using a projection" { + let v = [|1; 2; 3|] + let result = Vector.argmaxBy (fun x -> -x) v + Expect.equal result 0 "Expected index of maximum value by projection" + } + + test "tryFindIndex finds the index of the first matching element" { + let v = [|1; 2; 3|] + let result = Vector.tryFindIndex (fun x -> x = 2) v + Expect.equal result (Some 1) "Expected index of first matching element" + } + + test "findIndex finds the index of the first matching element or throws" { + let v = [|1; 2; 3|] + let result = Vector.findIndex (fun x -> x = 2) v + Expect.equal result 1 "Expected index of first matching element" + } + + test "enumerateNonZero enumerates non-zero elements with indices" { + let v = [|0; 1; 0; 2|] + let result = Vector.enumerateNonZero v + Expect.equal result [|(1, 1); (3, 2)|] "Expected non-zero elements with indices" + } + + test "split splits a vector into prefix and suffix" { + let v = [|1; 2; 3; 4|] + let prefix, suffix = Vector.split 2 v + Expect.equal prefix [|1; 2|] "Expected prefix" + Expect.equal suffix [|3; 4|] "Expected suffix" + } + + test "chunk chunks a vector into equally sized pieces" { + let v = [|1; 2; 3; 4; 5|] + let result = Vector.chunk 2 v + Expect.equal result [|[|1; 2|]; [|3; 4|]; [|5|]|] "Expected chunked vector" + } + + test "windowed creates a sliding window over the vector" { + let v = [|1; 2; 3; 4|] + let result = Vector.windowed 2 v + Expect.equal result [|[|1; 2|]; [|2; 3|]; [|3; 4|]|] "Expected sliding windows" + } + + test "splitVector splits a vector based on indices" { + let v = [|1; 2; 3; 4|] + let nvi, nv = Vector.splitVector [|1; 3|] v + Expect.equal nvi [|2; 4|] "Expected extracted elements" + Expect.equal nv [|1; 3|] "Expected remaining elements" + } + + test "permuteBy permutes a vector using a permutation function" { + let v = [|1; 2; 3|] + let result = Vector.permuteBy (fun i -> (i + 1) % 3) v // 1 2 0 + Expect.equal result [|2; 3; 1|] "Expected permuted vector" + } + + test "ofSeq converts a sequence to a vector" { + let seq = seq { 1; 2; 3 } + let result = Vector.ofSeq seq + Expect.equal result [|1; 2; 3|] "Expected vector from sequence" + } + ] + ] + + + + + +//let private testVectorA = +// let values = [|0.;3.;6.|] +// Vector(Some (Instances.FloatNumerics :> INumeric),values) + +//[] +//let covarianceTests = +// let x = vector [5.;12.;18.;-23.;45.] +// let y = vector [2.;8.;18.;-20.;28.] + +// testList "Vector" [ +// testCase "cov" <| fun () -> +// let cov = Vector.cov x y +// Expect.floatClose Accuracy.high cov 434.90 "Should be equal (double precision)" +// testCase "covPopulation" <| fun () -> +// let covPop = Vector.covPopulation x y +// Expect.floatClose Accuracy.high covPop 347.92 "Should be equal (double precision)" +// ] From 85c1a60c8b1ebab08c111c076bc0d07e3f89c912 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20M=C3=BChlhaus?= Date: Fri, 11 Apr 2025 19:37:17 +0200 Subject: [PATCH 026/121] Add Matrix test cases --- src/FSharp.Stats/AlgTypes/Matrix.fs | 80 +- src/FSharp.Stats/AlgTypes/VectorOps.fs | 1 + src/FSharp.Stats/Playground.fsx | 16 +- .../FSharp.Stats.Tests.fsproj | 1 + tests/FSharp.Stats.Tests/Matrix.fs | 1595 +++-------------- 5 files changed, 371 insertions(+), 1322 deletions(-) diff --git a/src/FSharp.Stats/AlgTypes/Matrix.fs b/src/FSharp.Stats/AlgTypes/Matrix.fs index 13f95e15a..1512f91ae 100644 --- a/src/FSharp.Stats/AlgTypes/Matrix.fs +++ b/src/FSharp.Stats/AlgTypes/Matrix.fs @@ -14,8 +14,8 @@ open System.Runtime.InteropServices type Matrix<'T when 'T :> Numerics.INumber<'T> and 'T : (new: unit -> 'T) and 'T : struct - and 'T :> ValueType - and 'T : equality> + and 'T : equality + and 'T :> ValueType> (rows: int, cols: int, data: Vector<'T>) = /// Exposes the raw underlying data array (row-major flattened). @@ -421,7 +421,7 @@ type Matrix<'T when 'T :> Numerics.INumber<'T> Matrix.map2Unchecked (-) (-) a b - + /// Hadamard product static member inline multiply<'T when 'T :> Numerics.INumber<'T> and 'T : (new: unit -> 'T) @@ -660,11 +660,71 @@ type Matrix<'T when 'T :> Numerics.INumber<'T> result + /// + /// Standard matrix multiplication (A x B). + /// A is (M x K), B is (K x N) => result is (M x N). + /// Then each (row of A) .dot. (row of B^T) is done with Vector<'T> chunks. + /// + static member matmul + (A: Matrix<'T>) (B: Matrix<'T>) : Matrix<'T> = + + // 1) Dimension checks + if A.NumCols <> B.NumRows then + invalidArg (nameof B) + $"Inner dimensions mismatch. A is {A.NumRows}x{A.NumCols}, B is {B.NumRows}x{B.NumCols}" + + let M = A.NumRows + let K = A.NumCols + let N = B.NumCols + + // 2) Transpose B to get B^T => shape [N x K], row j of B^T is col j of B + let Btrans = B.Transpose() + let bTData = Btrans.Data // Now each "row" in bTData is length=K, contiguous + + // 3) We'll allocate result + let resultData = Array.zeroCreate<'T> (M * N) + let aData = A.Data + + // 4) For each row i in A, row j in B^T => element in [i*N + j] + // The row i in A is contiguous of length K => offset i*K in aData + // The row j in B^T is contiguous of length K => offset j*K in bTData + for i in 0 .. M - 1 do + let aRowOffset = i * K + let aRowSpan = aData.AsSpan(aRowOffset, K) + // Convert A's row to a "Vector<'T>" span + let aVecSpan = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(aRowSpan) + + for j in 0 .. N - 1 do + let bTRowOffset = j * K + let bTRowSpan = bTData.AsSpan(bTRowOffset, K) + // Convert B^T's row j to a "Vector<'T>" span + let bTVecSpan = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(bTRowSpan) + + // 4.a) Do the chunkwise vector multiply-add + let mutable accum = Numerics.Vector<'T>.Zero + for chunk in 0 .. aVecSpan.Length - 1 do + accum <- accum + (aVecSpan.[chunk] * bTVecSpan.[chunk]) + + // 4.b) Sum up the vector lanes to a single scalar + let mutable sum = Numerics.Vector.Sum(accum) + + // 4.c) Handle remainder elements if K not multiple of Vector<'T>.Count + let remainderStart = aVecSpan.Length * Numerics.Vector<'T>.Count + for r in remainderStart .. K - 1 do + sum <- sum + aRowSpan.[r] * bTRowSpan.[r] + + // 4.d) Place result into the final matrix + resultData.[i*N + j] <- sum + + Matrix(M, N, resultData) + + // Matrix - matrix operations - static member inline ( + ) (a: Matrix<'T>, b: Matrix<'T>) = Matrix.add a b - static member inline ( - ) (a: Matrix<'T>, b: Matrix<'T>) = Matrix.subtract a b - static member inline ( * ) (a: Matrix<'T>, b: Matrix<'T>) = Matrix.multiply a b - static member inline ( / ) (a: Matrix<'T>, b: Matrix<'T>) = Matrix.divide a b + static member inline ( + ) (a: Matrix<'T>, b: Matrix<'T>) = Matrix.add a b + static member inline ( - ) (a: Matrix<'T>, b: Matrix<'T>) = Matrix.subtract a b + static member inline ( .* ) (a: Matrix<'T>, b: Matrix<'T>) = Matrix.multiply a b + static member inline ( * ) (a: Matrix<'T>, b: Matrix<'T>) = Matrix.matmul a b + static member inline ( / ) (a: Matrix<'T>, b: Matrix<'T>) = Matrix.divide a b // Matrix - vector operations static member inline ( * ) (m: Matrix<'T>, v: Vector<'T>) = Matrix.muliplyVector m v @@ -687,11 +747,7 @@ type Matrix<'T when 'T :> Numerics.INumber<'T> - static member inline diagonal<'T - when 'T :> Numerics.INumber<'T> - and 'T : struct - and 'T : (new : unit -> 'T) - and 'T :> ValueType> + static member inline diagonal (diag: Vector<'T>) : Matrix<'T> = let n = diag.Length diff --git a/src/FSharp.Stats/AlgTypes/VectorOps.fs b/src/FSharp.Stats/AlgTypes/VectorOps.fs index 5d338291c..ab93bcd00 100644 --- a/src/FSharp.Stats/AlgTypes/VectorOps.fs +++ b/src/FSharp.Stats/AlgTypes/VectorOps.fs @@ -36,6 +36,7 @@ module VectorOpsSymbols = let inline (.-) a b = Minus.Invoke(a, b) let inline (.*) a b = Multiply.Invoke(a, b) let inline (./) a b = Divide.Invoke(a, b) + // Dot product ( @ ) //// A type extension on `'T[]` so you can do `myArray.Transposed`. diff --git a/src/FSharp.Stats/Playground.fsx b/src/FSharp.Stats/Playground.fsx index 31b063053..1087204b6 100644 --- a/src/FSharp.Stats/Playground.fsx +++ b/src/FSharp.Stats/Playground.fsx @@ -1,26 +1,14 @@ #I "bin/Release/.net8.0" #r "FSharp.Stats.dll" -#r "nuget: Plotly.NET" +//#r "nuget: Plotly.NET" open System open FSharp.Stats open FSharp.Stats.Distributions -open Plotly.NET +//open Plotly.NET -let a = 1 % 3 // 1 -let b = 2 % 3 // 2 -let c = 3 % 3 // 0 -let colvec = [| 1.0; 2.0; 3.0 |] -let rowvec = [| 4.0; 5.0; 6.0 |] - -// The expected 3x3 matrix is computed by: -// [ [1.0*4.0, 1.0*5.0, 1.0*6.0] -// [2.0*4.0, 2.0*5.0, 2.0*6.0] -// [3.0*4.0, 3.0*5.0, 3.0*6.0] ] -let result = Vector.cross colvec rowvec - let alpha = 9.9 //0.4 let beta = 31 //4.2 diff --git a/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj b/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj index 8c720070e..d469885ab 100644 --- a/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj +++ b/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj @@ -19,6 +19,7 @@ + diff --git a/tests/FSharp.Stats.Tests/Matrix.fs b/tests/FSharp.Stats.Tests/Matrix.fs index 519ebf234..a528aec77 100644 --- a/tests/FSharp.Stats.Tests/Matrix.fs +++ b/tests/FSharp.Stats.Tests/Matrix.fs @@ -1,1306 +1,309 @@ module MatrixTests -open Expecto +open System open FSharp.Stats -open FSharp.Stats.Matrix - -let private testRowVecA = - let values = [|1.;4.|] - RowVector(Some (Instances.FloatNumerics :> INumeric),values) - -let private testRowVecB = - let values = [|0.;3.;6.|] - RowVector(Some (Instances.FloatNumerics :> INumeric),values) - -let private testRowVecC = - let values = [|0.;3.;4.|] - RowVector(Some (Instances.FloatNumerics :> INumeric),values) - -let private testRowVecD = - let values = [|0.;0.;0.|] - RowVector(Some (Instances.FloatNumerics :> INumeric),values) - -let private testVectorA = - let values = [|0.;3.;6.|] - Vector(Some (Instances.FloatNumerics :> INumeric),values) - -let private testVectorB = - let values = [|0.;0.;0.|] - Vector(Some (Instances.FloatNumerics :> INumeric),values) - -let private testVector1LowerDiag = - let values = [|0.;5.|] - Vector(Some (Instances.FloatNumerics :> INumeric),values) - -let private testVector1UpperDiag = - let values = [|1.;4.|] - Vector(Some (Instances.FloatNumerics :> INumeric),values) - -let private testDiagonalMatrixA : Matrix = - let values = - Array2D.init - 3 - 3 - (fun i j -> - if i = j then - testVectorA.[i] - else 0. - ) - Matrix.DenseRepr - (DenseMatrix(Some (Instances.FloatNumerics :> INumeric),values)) - - -let private identity3Int : Matrix = - let values = - Array2D.init - 3 - 3 - (fun i j -> - if i = j then 1 else 0 - ) - Matrix.DenseRepr - (DenseMatrix(Some (Instances.Int32Numerics :> INumeric),values)) - - -let private identityFloat3 = - let values = - Array2D.init - 3 - 3 - (fun i j -> - if i = j then 1. else 0. - ) - Matrix.DenseRepr - (DenseMatrix(Some (Instances.FloatNumerics :> INumeric),values)) - - -let private testValuesArrRows = - [| - [|0.;1.;2.|] - [|0.;3.;4.|] - [|0.;5.;6.|] - |] - -let private testValuesArrCols = - [| - [|0.;0.;0.|] - [|1.;3.;5.|] - [|2.;4.;6.|] - |] - -let private testValues2x3 = - [| - [|0.;0.;0.|] - [|1.;3.;5.|] - |] - -let private testValues2x3Transposed = - [| - [|0.;1.|] - [|0.;3.|] - [|0.;5.|] - |] - -let private testValues3x2 = - [| - [|0.;0.|] - [|1.;3.|] - [|2.;4.|] - |] - -let private testSquareMatrixA : Matrix = - let values = - Array2D.init - 3 - 3 - (fun i j -> - testValuesArrRows.[i].[j] - ) - Matrix.DenseRepr - (DenseMatrix(Some (Instances.FloatNumerics :> INumeric),values)) - -let private testSquareMatrixB : Matrix = - let values = - Array2D.init - 3 - 3 - (fun i j -> - testValuesArrCols.[i].[j] - ) - Matrix.DenseRepr - (DenseMatrix(Some (Instances.FloatNumerics :> INumeric),values)) - - -let private test2x3Matrix : Matrix = - let values = - Array2D.init - 2 - 3 - (fun i j -> - testValues2x3.[i].[j] - ) - Matrix.DenseRepr - (DenseMatrix(Some (Instances.FloatNumerics :> INumeric),values)) - - - -let private test2x3MatrixTransposed : Matrix = - let values = - Array2D.init - 3 - 2 - (fun i j -> - testValues2x3Transposed.[i].[j] - ) - Matrix.DenseRepr - (DenseMatrix(Some (Instances.FloatNumerics :> INumeric),values)) - - -let private test3x2MatrixB : Matrix = - let values = - Array2D.init - 3 - 2 - (fun i j -> - testValues3x2.[i].[j] - ) - Matrix.DenseRepr - (DenseMatrix(Some (Instances.FloatNumerics :> INumeric),values)) - -let private testConstDiagMatrix : Matrix = - let values = - Array2D.init - 3 - 3 - (fun i j -> - if i = j then 3. else 0. - ) - Matrix.DenseRepr - (DenseMatrix(Some (Instances.FloatNumerics :> INumeric),values)) - -let private testConstMatrix : Matrix = - let values = - Array2D.init - 3 - 3 - (fun i j -> - 3. - ) - Matrix.DenseRepr - (DenseMatrix(Some (Instances.FloatNumerics :> INumeric),values)) +open Expecto -let private testScalarMatrix : Matrix = - let values = - Array2D.init - 1 - 1 - (fun i j -> - 3. - ) - Matrix.DenseRepr - (DenseMatrix(Some (Instances.FloatNumerics :> INumeric),values)) [] -let genericImplementationTests = - testList "Matrix.GenericImplementation" [ - //TO-DO: cover generic implementation here, using another numeric then float - testCase "" <| fun () -> - () - ] - -[] -let floatImplementationSparseTests = - testList "Matrix.FloatImplementation.Sparse" [ - //TO-DO: adapt all dense tests for sparse matrices - testCase "" <| fun () -> - () +let matrixTests = + testList "Matrix Tests" [ + + // ---------------------------------------------------------------------- + // Basic construction + // ---------------------------------------------------------------------- + testCase "ofJaggedArray creates matrix from jagged array" <| fun _ -> + let jagged = + [| [|0.0; 0.0|] + [|1.0; 3.0|] + [|2.0; 4.0|] |] + let mat = Matrix.ofJaggedArray jagged // We specifically test 'ofJaggedArray' here + Expect.equal mat.NumRows 3 "Matrix should have 3 rows" + Expect.equal mat.NumCols 2 "Matrix should have 2 columns" + Expect.equal mat.Data [|0.0; 0.0; 1.0; 3.0; 2.0; 4.0|] + "Flattened data should match row-major flattening" + + testCase "ofArray2D creates matrix from 2D array" <| fun _ -> + let arr2d = + array2D [ [ 1; 2 ] + [ 3; 4 ] + [ 5; 6 ] ] + let mat = Matrix.ofArray2D arr2d + Expect.equal mat.NumRows 3 "Matrix should have 3 rows" + Expect.equal mat.NumCols 2 "Matrix should have 2 columns" + Expect.equal mat.Data [|1; 2; 3; 4; 5; 6|] "Flattened data should match row-major order" + + testCase "init creates a matrix using a function of row,col" <| fun _ -> + let mat = Matrix.init 2 3 (fun r c -> float (r + c)) + // For r=0, c=0..2 => [0;1;2] + // For r=1, c=0..2 => [1;2;3] + // Flatten => [0;1;2; 1;2;3] + let expected = [|0.0; 1.0; 2.0; 1.0; 2.0; 3.0|] + Expect.equal mat.NumRows 2 "Rows = 2" + Expect.equal mat.NumCols 3 "Cols = 3" + Expect.equal mat.Data expected "Data should match the function r+c" + + testCase "ofJaggedArray throws on non-rectangular jagged input" <| fun _ -> + let jagged = + [| [|1.0; 2.0|] + [|3.0|] |] // 2nd row has length=1, first row has length=2 + Expect.throws (fun () -> Matrix.ofJaggedArray jagged |> ignore) + "Should throw due to inconsistent row lengths" + + // ---------------------------------------------------------------------- + // Access & Slicing + // ---------------------------------------------------------------------- + testCase "indexer get/set within bounds" <| fun _ -> + let mat = matrix [| [|1.0; 2.0|] + [|3.0; 4.0|] |] + Expect.equal mat.[0,0] 1.0 "Element (0,0) is 1.0" + mat.[1,1] <- 99.0 + Expect.equal mat.[1,1] 99.0 "Element (1,1) updated to 99.0" + + testCase "indexer throws on out-of-range access" <| fun _ -> + let mat = matrix [| [|1.0; 2.0|] + [|3.0; 4.0|] |] + Expect.throwsT (fun () -> let _ = mat.[999, 999] in ()) + "Indexer out of range should throw" + + testCase "GetSlice works with row and col start..end" <| fun _ -> + // 3x3 matrix + let mat = matrix [| + [|1.0; 2.0; 3.0|] + [|4.0; 5.0; 6.0|] + [|7.0; 8.0; 9.0|] + |] + // slice submatrix: rows [0..1], cols [1..2] + let subMat = mat.[0..1, 1..2] + // This submatrix should be: + // [ [2.0; 3.0] + // [5.0; 6.0] ] + Expect.equal subMat.NumRows 2 "2 rows" + Expect.equal subMat.NumCols 2 "2 cols" + Expect.equal subMat.Data [|2.0; 3.0; 5.0; 6.0|] "Flattened submatrix data" + + testCase "GetSlice throws on invalid slice range" <| fun _ -> + let mat = matrix [| [|1.;2.|] + [|3.;4.|] |] + Expect.throwsT (fun () -> mat.[0..99, *] |> ignore) + "Should throw due to invalid row end" + + // ---------------------------------------------------------------------- + // Arithmetic (element-wise) + // ---------------------------------------------------------------------- + testCase "add: element-wise addition of same-dimension matrices" <| fun _ -> + let m1 = matrix [| [|1.; 2.|] + [|3.; 4.|] |] + let m2 = matrix [| [|10.;20.|] + [|30.;40.|] |] + let result = Matrix.add m1 m2 + let expected = [| (1.+10.); (2.+20.); (3.+30.); (4.+40.) |] // => [11;22;33;44] + Expect.equal result.Data expected "Element-wise addition result" + + testCase "subtract: dimension mismatch throws" <| fun _ -> + let m1 = matrix [| [|1.;2.|] |] // 1x2 + let m2 = matrix [| [|1.;2.;3.|] |] // 1x3 + Expect.throwsT (fun () -> Matrix.subtract m1 m2 |> ignore) + "Subtract must throw if shapes differ" + + testCase "multiply & divide: element-wise" <| fun _ -> + let m1 = matrix [| [|2.;4.|] + [|6.;8.|] |] + let m2 = matrix [| [|1.;2.|] + [|3.;4.|] |] + + // multiply => [ [2.*1. , 4.*2.] ; [6.*3., 8.*4.] ] => [ [2.,8.]; [18.,32.] ] + let mulResult = Matrix.multiply m1 m2 + Expect.equal mulResult.Data [|2.; 8.; 18.; 32.|] "Element-wise multiply" + + // divide => [ [2./1., 4./2.]; [6./3., 8./4.] ] => [ [2.,2.]; [2.,2.] ] + let divResult = Matrix.divide m1 m2 + Expect.equal divResult.Data [|2.;2.;2.;2.|] "Element-wise divide" + + + // ---------------------------------------------------------------------- + // Standard matrix multiplication + // ---------------------------------------------------------------------- + testCase "matmul: 2x3 times 3x2 => 2x2 result" <| fun _ -> + // A=2x3, B=3x2 + let A = matrix [| [|1.0; 2.0; 3.0|] + [|4.0; 5.0; 6.0|] |] + let B = matrix [| [|7.0; 10.0|] + [|8.0; 11.0|] + [|9.0; 12.0|] |] + + // Expected: + // C[0,0] = 1*7 + 2*8 + 3*9 = 50 + // C[0,1] = 1*10+2*11+3*12 = 68 + // C[1,0] = 4*7 + 5*8 + 6*9 = 122 + // C[1,1] = 4*10+5*11+6*12 = 167 + let C = Matrix.matmul A B + Expect.equal C.NumRows 2 "Should have 2 rows" + Expect.equal C.NumCols 2 "Should have 2 cols" + Expect.equal C.Data [|50.0; 68.0; 122.0; 167.0|] "Check standard matmul result" + + + // ---------------------------------------------------------------------- + // Scalar Operations + // ---------------------------------------------------------------------- + testCase "addScalar, subtractScalar, multiplyScalar, divideScalar" <| fun _ -> + let m = matrix [| [|1.;2.|] + [|3.;4.|] |] + let addRes = Matrix.addScalar m 10.0 + Expect.equal addRes.Data [|11.;12.;13.;14.|] "Add 10.0 to all" + + let subRes = Matrix.subtractScalar m 1.0 + Expect.equal subRes.Data [|0.;1.;2.;3.|] "Subtract 1.0 from all" + + let mulRes = Matrix.multiplyScalar m 2.0 + Expect.equal mulRes.Data [|2.;4.;6.;8.|] "Multiply all by 2.0" + + let divRes = Matrix.divideScalar m 2.0 + Expect.equal divRes.Data [|0.5;1.;1.5;2.|] "Divide all by 2.0" + + // ---------------------------------------------------------------------- + // Matrix-Vector Multiply + // ---------------------------------------------------------------------- + testCase "m * v => standard matrix-vector product" <| fun _ -> + // 2x3 times vector of length 3 => vector of length 2 + // mat = [ [1.,2.,3.] + // [4.,5.,6.] ] + let mat = matrix [| [|1.;2.;3.|] + [|4.;5.;6.|] |] + let v = [| 10.; 20.; 30. |] + // result = [ + // row0 dot v => (1.*10. + 2.*20. + 3.*30.) = 140. + // row1 dot v => (4.*10. + 5.*20. + 6.*30.) = 320. + // ] + let result = mat * v + Expect.equal result [|140.; 320.|] "Matrix-vector product" + + testCase "v * m => row-vector times matrix => vector" <| fun _ -> + // 1x2 row vector times a 2x2 matrix => 1x2 vector + let v = [|2.; 3.|] // length=2 + let mat = matrix [| [|10.; 100.|] + [|20.; 200.|] |] + // v*m => [ (2.*10. + 3.*20.), (2.*100. + 3.*200.) ] + // => [ 2.*10. + 3.*20. , 2.*100. + 3.*200. ] + // => [ 20.+60., 200.+600. ] => [80., 800.] + let result = v * mat + Expect.equal result [|80.; 800.|] "Row-vector times matrix" + + testCase "m * v => dimension mismatch throws" <| fun _ -> + let mat = matrix [| [|1.;2.|] + [|3.;4.|] |] // 2x2 + let v = [|1.;2.;3.|] // length=3 + Expect.throwsT (fun () -> let _ = mat * v in ()) + "Matrix(2x2)*Vector(3) => dimension mismatch should throw" + + // ---------------------------------------------------------------------- + // Transpose + // ---------------------------------------------------------------------- + testCase "Transpose: changes shape and flips row<->col" <| fun _ -> + let mat = matrix [| [|1.;2.;3.|] + [|4.;5.;6.|] |] // 2x3 + let t = mat.Transpose() + Expect.equal t.NumRows 3 "Should have 3 rows" + Expect.equal t.NumCols 2 "Should have 2 cols" + Expect.equal t.Data [|1.;4.;2.;5.;3.;6.|] "Flattened transpose" + + // ---------------------------------------------------------------------- + // Identity, Diagonal, and Zero/Ones + // ---------------------------------------------------------------------- + testCase "identity n => NxN identity matrix" <| fun _ -> + let eye = Matrix.identity 3 + // => [1,0,0; 0,1,0; 0,0,1] + let expected = [|1.;0.;0.; 0.;1.;0.; 0.;0.;1.|] + Expect.equal eye.Data expected "3x3 identity" + + testCase "diagonal => builds NxN from diag vector" <| fun _ -> + let diagVec = [|10.; 20.; 30.|] + let mat = Matrix.diagonal diagVec + // => [ [10, 0, 0], + // [ 0,20, 0], + // [ 0, 0,30] ] + Expect.equal mat.NumRows 3 "3x3" + Expect.equal mat.NumCols 3 "3x3" + let expected = [|10.;0.;0.; 0.;20.;0.; 0.;0.;30.|] + Expect.equal mat.Data expected "Diagonal in main diagonal positions" + + testCase "ones => NxM matrix of all 1's" <| fun _ -> + let mat = Matrix.ones 2 3 + Expect.equal mat.Data [|1.;1.;1.;1.;1.;1.|] "2x3 of all 1." + + testCase "zeroCreate => NxM matrix of all 0's" <| fun _ -> + let mat = Matrix.zeroCreate 2 3 + Expect.equal mat.Data [|0.;0.;0.;0.;0.;0.|] "2x3 of all zero." + + // ---------------------------------------------------------------------- + // getRow / getCol + // ---------------------------------------------------------------------- + testCase "getRow gets row i as a vector" <| fun _ -> + let mat = matrix [| [|1.;2.|] + [|3.;4.|] |] + let row0 = Matrix.getRow 0 mat + let row1 = Matrix.getRow 1 mat + Expect.equal row0 [|1.;2.|] "Row 0" + Expect.equal row1 [|3.;4.|] "Row 1" + + testCase "getCol gets column j as a vector" <| fun _ -> + let mat = matrix [| [|1.;2.;3.|] + [|4.;5.;6.|] |] + let col0 = Matrix.getCol 0 mat + let col2 = Matrix.getCol 2 mat + Expect.equal col0 [|1.;4.|] "Column 0" + Expect.equal col2 [|3.;6.|] "Column 2" + + // ---------------------------------------------------------------------- + // Equality (IEquatable) + // ---------------------------------------------------------------------- + testCase "Equals returns true for same shape+elements" <| fun _ -> + let m1 = matrix [| [|1.;2.|] + [|3.;4.|] |] + // 'Matrix.create' constructs from a flattened array + let m2 = Matrix.create 2 2 [|1.;2.;3.;4.|] + Expect.isTrue (m1.Equals m2) "Matrices should be equal" + + testCase "Equals returns false for dimension mismatch" <| fun _ -> + let m1 = matrix [| [|1.;2.|] |] // 1x2 + let m2 = matrix [| [|1.;2.;3.|] |] // 1x3 + Expect.isFalse (m1.Equals m2) "Should be different shapes => not equal" + + testCase "Equals returns false for data difference" <| fun _ -> + let m1 = matrix [| [|1.;2.|] |] + let m2 = matrix [| [|1.;9.|] |] + Expect.isFalse (m1.Equals m2) "Same shape, different data => not equal" + + // ---------------------------------------------------------------------- + // Misc: toArray2D, toJaggedArray + // ---------------------------------------------------------------------- + testCase "toArray2D transforms a matrix into 2D array" <| fun _ -> + let mat = matrix [| [|1.;2.|] + [|3.;4.|] + [|5.;6.|] |] + let arr2d = mat.toArray2D() + Expect.equal (arr2d.GetLength(0)) 3 "3 rows in arr2d" + Expect.equal (arr2d.GetLength(1)) 2 "2 cols in arr2d" + Expect.equal arr2d.[2,1] 6.0 "Check element" + + testCase "toJaggedArray transforms a matrix into jagged array" <| fun _ -> + let mat = matrix [| [|7.;8.|] + [|9.;10.|] |] + let jagged = mat.toJaggedArray() + Expect.equal jagged.Length 2 "2 rows in jagged" + Expect.equal jagged.[1] [|9.;10.|] "Second row matches" + + // ---------------------------------------------------------------------- + // Slicing & Setting Row + // ---------------------------------------------------------------------- + testCase "SetRow updates row i" <| fun _ -> + let mat = matrix [| [|1.;2.|] + [|3.;4.|] |] + mat.SetRow(0, [|10.;20.|]) + Expect.equal mat.Data [|10.;20.;3.;4.|] "Row 0 replaced" + + // (Optional) More tests can be added for addRowVector, addColVector, etc. ] -[] -let floatImplementationDenseTests = - testList "Matrix.FloatImplementation.Dense" [ - //Tests for acessing and setting values in the underlying array2D - testList "Acessors" [ - - testCase "Get value" <| fun () -> - let actual = Matrix.get testSquareMatrixA 0 1 - Expect.equal actual 1. "Matrix.get returned wrong value" - - testCase "Getting value out of range should fail" <| fun () -> - Expect.throws (fun () -> Matrix.get testSquareMatrixA 0 7 |> ignore) "Getting value out of range should fail" - - testCase "Set value" <| fun () -> - - let actual = - Matrix.copy testSquareMatrixA - Matrix.set actual 0 0 1337. - - let expected = - [ - [1337.;1.;2.] - [0.;3.;4.] - [0.;5.;6.] - ] - |> matrix - - Expect.equal actual expected "Matrix.set mutated the wrong value" - - testCase "Setting value out of range should fail" <| fun () -> - Expect.throws (fun () -> Matrix.set (Matrix.copy testSquareMatrixA) 0 7 3. |> ignore) "Getting value out of range should fail" - ] - - testList "Creation" [ - - testCase "init" <| fun () -> - let actual = - Matrix.init 3 3 (fun i j -> testValuesArrRows.[i].[j]) - Expect.equal actual testSquareMatrixA "Matrix was not initialized correctly using Matrix.init" - - testCase "ofRows" <| fun () -> - let actual = - testValues2x3 - |> Array.map rowvec - |> Vector.Generic.ofSeq - |> Matrix.ofRows - - Expect.equal actual test2x3Matrix "Matrix was not initialized correctly using Matrix.ofRows" - - testCase "ofCols" <| fun () -> - let actual = - testValues2x3Transposed - |> Array.map vector - |> RowVector.Generic.ofSeq - |> Matrix.ofCols - - Expect.equal actual test2x3Matrix "Matrix was not initialized correctly using Matrix.ofCols" - - testCase "ofJaggedList" <| fun () -> - - let actual = - testValues2x3 - |> List.ofArray - |> List.map List.ofArray - |> Matrix.ofJaggedList - - Expect.equal actual test2x3Matrix "Matrix was not initialized correctly using Matrix.ofJaggedList" - - testCase "ofJaggedColList" <| fun () -> - let actual = - testValues2x3Transposed - |> List.ofArray - |> List.map List.ofArray - |> Matrix.ofJaggedColList - - Expect.equal actual test2x3Matrix "Matrix was not initialized correctly using Matrix.ofJaggedColList" - - - testCase "ofJaggedSeq" <| fun () -> - let actual = - testValues2x3 - |> Seq.ofArray - |> Seq.map Seq.ofArray - |> Matrix.ofJaggedSeq - - Expect.equal actual test2x3Matrix "Matrix was not initialized correctly using Matrix.ofJaggedSeq" - - - testCase "ofJaggedColSeq" <| fun () -> - let actual = - testValues2x3Transposed - |> Seq.ofArray - |> Seq.map Seq.ofArray - |> Matrix.ofJaggedColSeq - - Expect.equal actual test2x3Matrix "Matrix was not initialized correctly using Matrix.ofJaggedColSeq" - - - testCase "ofJaggedArray" <| fun () -> - let actual = - testValues2x3 - |> Matrix.ofJaggedArray - - Expect.equal actual test2x3Matrix "Matrix was not initialized correctly using Matrix.ofJaggedArray" - - - testCase "ofJaggedColArray" <| fun () -> - let actual = - testValues2x3Transposed - |> Matrix.ofJaggedColArray - - Expect.equal actual test2x3Matrix "Matrix was not initialized correctly using Matrix.ofJaggedColArray" - - - testCase "diag" <| fun () -> - let actual = Matrix.diag testVectorA - - Expect.equal actual testDiagonalMatrixA "Diagonal Matrix was not correctly initialized using Matrix.diag" - - testCase "initDiagonal" <| fun () -> - - let actual = Matrix.initDiagonal testVectorA - - Expect.equal actual testDiagonalMatrixA "Diagonal Matrix was not correctly initialized using Matrix.initDiag" - - testCase "constDiag" <| fun () -> - - let actual = Matrix.constDiag 3 3. - - Expect.equal actual testConstDiagMatrix "Constant diagonal matrix was not correctly initialized using Matrix.constDiag" - - - testCase "create" <| fun () -> - - let actual = Matrix.create 3 3 3. - - Expect.equal actual testConstMatrix "Constant matrix was not initialized correctly using Matrix.create" - - testCase "ofScalar" <| fun () -> - - let actual = Matrix.ofScalar 3. - - Expect.equal actual testScalarMatrix "1x1 Matrix was not correctly initialized using Matrix.ofScalar" - - testCase "ofArray2D" <| fun () -> - - let values = - Array2D.init - 3 - 3 - (fun i j -> - testValuesArrRows.[i].[j] - ) - - let actual = Matrix.ofArray2D values - - Expect.equal actual testSquareMatrixA "Matrix was not initialized correctly using Matrix.ofArray2D" - - testCase "toArray2D" <| fun () -> - - let expected = - Array2D.init - 3 - 3 - (fun i j -> - testValuesArrRows.[i].[j] - ) - - let actual = Matrix.toArray2D testSquareMatrixA - - Expect.equal actual expected "Matrix.toArray2D did not return the correct Array2D" - - testCase "toJaggedArray" <| fun () -> - let actual = Matrix.toJaggedArray testSquareMatrixA - Expect.equal actual testValuesArrRows "Matrix.toJaggedArray did not return the correct JaggedArray" - - testCase "toJaggedSeq" <| fun () -> - let actual = Matrix.toJaggedSeq testSquareMatrixA |> JaggedArray.ofJaggedSeq - Expect.equal actual testValuesArrRows "Matrix.toJaggedSeq did not return the correct JaggedSeq" - - testCase "toJaggedColArray" <| fun () -> - let actual = Matrix.toJaggedColArray testSquareMatrixA - Expect.equal actual testValuesArrCols "Matrix.toJaggedColArray did not return the correct JaggedArray" - - testCase "toJaggedColSeq" <| fun () -> - let actual = Matrix.toJaggedColSeq testSquareMatrixA |> JaggedArray.ofJaggedSeq - Expect.equal actual testValuesArrCols "Matrix.toJaggedColSeq did not return the correct JaggedSeq" - - - testCase "getDiagN 1 above diagonal" <| fun () -> - - let actual = Matrix.getDiagN testSquareMatrixA 1 - - Expect.equal actual testVector1UpperDiag "Matrix.getDiagN did not return the correct offset +1 diagonal" - - testCase "getDiag 1 below diagonal" <| fun () -> - - let actual = Matrix.getDiagN testSquareMatrixA -1 - - Expect.equal actual testVector1LowerDiag "Matrix.getDiagN did not return the correct offset -1 diagonal" - - ] - - testList "Operators" [ - - testList "add" [ - - testCase "Addition of 2 Matrices with the same dimensions" <| fun () -> - - let actual = Matrix.add testSquareMatrixA testSquareMatrixB - - let expected = - let values = - Array2D.init - 3 - 3 - (fun i j -> - testValuesArrRows.[i].[j] + testValuesArrCols.[i].[j] - ) - Matrix.DenseRepr - (DenseMatrix(Some (Instances.FloatNumerics :> INumeric),values)) - - Expect.equal actual expected "Matrix.add did not add the values of two matrices with the same dimensions correctly" - - testCase "Addition of matrices with different sizes should fail" <| fun () -> - - Expect.throws (fun () -> Matrix.add test2x3Matrix testSquareMatrixA |> ignore) "Addition of Matrices with different dimesnions did not fail although it should" - - ] - testList "sub" [ - - testCase "Substraction of 2 Matrices with the same dimensions" <| fun () -> - - let actual = Matrix.sub testSquareMatrixA testSquareMatrixB - - let expected = - let values = - Array2D.init - 3 - 3 - (fun i j -> - testValuesArrRows.[i].[j] - testValuesArrCols.[i].[j] - ) - Matrix.DenseRepr - (DenseMatrix(Some (Instances.FloatNumerics :> INumeric),values)) - - Expect.equal actual expected "Matrix.add did not add the values of two matrices with the same dimensions correctly" - - - testCase "Subtraction of matrices with different sizes should fail" <| fun () -> - - Expect.throws (fun () -> Matrix.sub test2x3Matrix testSquareMatrixA |> ignore) "Subtraction of Matrices with different dimesnions did not fail although it should" - ] - testList "mul" [ - - testCase "Matrix Multiplication with fitting dimensions" <| fun () -> - - let actual = Matrix.mul test2x3Matrix test3x2MatrixB - let expected = - let values = - [ - [0.;0.;] - [13.;29.] - ] - let valArr = - Array2D.init - 2 - 2 - (fun i j -> - values.[i].[j] - ) - Matrix.DenseRepr - (DenseMatrix(Some (Instances.FloatNumerics :> INumeric),valArr)) - - Expect.equal actual expected "Matrix multiplication of the 2x3 and 3x2 testmatrices did not return the correct result." - - testCase "Matrix Multiplication with non-fitting dimensions should fail" <| fun () -> - Expect.throws (fun () -> Matrix.mul testScalarMatrix testSquareMatrixA |> ignore) "Matrix multiplication with non-fitting dimensions did not fail although it should" - - ] - testList "mulV" [ - - testCase "Matrix (m*1)Vector multiplication with correct dimensions" <| fun () -> - let actual = Matrix.mulV testSquareMatrixA testVectorA - - let expected = - let values = [|15.;33.;51.|] - Vector(Some (Instances.FloatNumerics :> INumeric),values) - - Expect.equal actual expected "Matrix (m*1)Vector multiplication with correct dimensions did not return the correct result vector" - - testCase "Matrix (m*1)Vector multiplication with incorrect dimensions should fail" <| fun () -> - Expect.throws (fun () -> Matrix.mulV testSquareMatrixA testVector1UpperDiag |> ignore) "Matrix (m*1)Vector multiplication with incorrect dimensions should fail although it should" - ] - testList "mulRV" [ - - testCase "Matrix (1*n) RowVector multiplication with correct dimensions" <| fun () -> - let actual = Matrix.mulRV testRowVecB testSquareMatrixA - let expected = - let values = [|0.;39.;48.|] - RowVector(Some (Instances.FloatNumerics :> INumeric),values) - - Expect.equal actual expected "Matrix (1*n) RowVector multiplication with correct dimensions did not return the correct result rowVector" - - testCase "Matrix (1*n) RowVector multiplication with incorrect dimensions should fail" <| fun () -> - Expect.throws (fun () -> Matrix.mulRV testRowVecA testSquareMatrixA |> ignore) "Matrix (1*n) RowVector multiplication with incorrect dimensions didnt fail although it should" - - ] - testList "cptMul" [ - - testCase "Point wise multiplication of two matrices with the same dimensions" <| fun () -> - let actual = - Matrix.cptMul testSquareMatrixA testSquareMatrixB - - let expected = - let values = - Array2D.init - 3 - 3 - (fun i j -> - testValuesArrRows.[i].[j] * testValuesArrCols.[i].[j] - ) - Matrix.DenseRepr - (DenseMatrix(Some (Instances.FloatNumerics :> INumeric),values)) - Expect.equal actual expected "Point wise multiplication of two matrices with the same dimensions did not return the correct result matrix" - - testCase "Point wise multiplication of two matrices with different dimensions should fail" <| fun () -> - Expect.throws (fun () -> Matrix.cptMul testSquareMatrixA testScalarMatrix |> ignore) "Point wise multiplication of two matrices with different dimensions did not fail although it should" - ] - testList "cptMax" [ - testCase "Point wise maximization of two matrices with the same dimensions" <| fun () -> - let actual = - Matrix.cptMax testSquareMatrixA testSquareMatrixB - - let expected = - let values = - Array2D.init - 3 - 3 - (fun i j -> - max testValuesArrRows.[i].[j] testValuesArrCols.[i].[j] - ) - Matrix.DenseRepr - (DenseMatrix(Some (Instances.FloatNumerics :> INumeric),values)) - - Expect.equal actual expected "Point wise maximization of two matrices with the same dimensions did not return the correct result matrix" - - testCase "Point wise maximization of two matrices with different dimensions should fail" <| fun () -> - Expect.throws (fun () -> Matrix.cptMax testSquareMatrixA testScalarMatrix |> ignore) "Point wise maximization of two matrices with different dimensions did not fail although it should" - - - ] - testList "cptMin" [ - - testCase "Point wise minimization of two matrices with the same dimensions" <| fun () -> - let actual = - Matrix.cptMin testSquareMatrixA testSquareMatrixB - - let expected = - let values = - Array2D.init - 3 - 3 - (fun i j -> - min testValuesArrRows.[i].[j] testValuesArrCols.[i].[j] - ) - Matrix.DenseRepr - (DenseMatrix(Some (Instances.FloatNumerics :> INumeric),values)) - - Expect.equal actual expected "Point wise minimization of two matrices with the same dimensions did not return the correct result matrix" - - testCase "Point wise minimization of two matrices with different dimensions should fail" <| fun () -> - Expect.throws (fun () -> Matrix.cptMin testSquareMatrixA testScalarMatrix |> ignore) "Point wise minimization of two matrices with different dimensions did not fail although it should" - - - ] - testList "scale" [ - - testCase "scale" <| fun () -> - let actual = Matrix.scale 2. testSquareMatrixA - - let expected : Matrix = - let values = - Array2D.init - 3 - 3 - (fun i j -> - testValuesArrRows.[i].[j] * 2. - ) - Matrix.DenseRepr - (DenseMatrix(Some (Instances.FloatNumerics :> INumeric),values)) - - Expect.equal actual expected "Scaling a matrix by a scalar did not return the correctly scaled matrix" - ] - testList "neg" [ - - let actual = Matrix.neg testSquareMatrixA - - let expected : Matrix = - let values = - Array2D.init - 3 - 3 - (fun i j -> - testValuesArrRows.[i].[j] * -1. - ) - Matrix.DenseRepr - (DenseMatrix(Some (Instances.FloatNumerics :> INumeric),values)) - - Expect.equal actual expected "Negating a matrix did not return the correctly negated matrix" - - ] - testList "trace" [ - - testCase "Trace of a square matrix" <| fun () -> - let actual = Matrix.trace testSquareMatrixA - Expect.equal actual 9. "Trace of a square matrix was not calculated correctly" - - testCase "Trace of a non-square matrix should fail" <| fun () -> - Expect.throws (fun () -> Matrix.trace test2x3Matrix |> ignore) "Trace of a non-square matrix did not fail although it should" - - ] - testList "transpose" [ - - testCase "transpose of a square matrix" <| fun () -> - let actual = Matrix.transpose testSquareMatrixA - Expect.equal actual testSquareMatrixB "Transposing a test square matrix did not return the correct result" - - testCase "transpose of a non-square matrix" <| fun () -> - let actual = Matrix.transpose test2x3Matrix - Expect.equal actual test2x3MatrixTransposed "Transposing a test non-square matrix did not return the correct result" - ] - testList "forall" [ - - testCase "Check if all values in a matrix are >= 0. (expected to be true)" <| fun () -> - Expect.isTrue (Matrix.forall (fun elem -> elem >= 0.) testSquareMatrixA) "test matrix had all values => 0. but the Matrix.forall function failed to recognize" - - testCase "Check if all values in a matrix are >= 1. (expected to be false)" <| fun () -> - Expect.isFalse (Matrix.forall (fun elem -> elem >= 1.) testSquareMatrixA) "test matrix did not have all values => 1. but the Matrix.forall function failed to recognize" - - ] - testList "exists" [ - - testCase "Check if a testMatrix contains 0. (expected to be true)" <| fun () -> - Expect.isTrue (Matrix.exists (fun elem -> elem = 0.) testSquareMatrixA) "Test matrix was expected to contain a value 0., but Matrix.exists returned false" - - testCase "Check if a testMatrix contains 1337. (expected to be false)" <| fun () -> - Expect.isFalse (Matrix.exists (fun elem -> elem = 1337.) testSquareMatrixA) "Test matrix was not expected to contain a value 1337., but Matrix.exists returned true" - ] - testList "foralli" [ - - testCase "Check if all values in a matrix are >= 0. (expected to be true)" <| fun () -> - Expect.isTrue (Matrix.foralli (fun outerI innerI elem -> elem >= 0.) testSquareMatrixA) "test matrix had all values => 0. but the Matrix.forall function failed to recognize" - - testCase "Check if all values in a matrix are >= 1. (expected to be false)" <| fun () -> - Expect.isFalse (Matrix.foralli (fun outerI innerI elem -> elem >= 1.) testSquareMatrixA) "test matrix did not have all values => 1. but the Matrix.forall function failed to recognize" - - testCase "Check if values on the diagonal in a matrix are >= 0. (expected to be true)" <| fun () -> - Expect.isTrue (Matrix.foralli (fun outerI innerI elem -> if outerI = innerI then elem >= 0. else true) testSquareMatrixA) "test matrix had all diagonal values => 0. but the Matrix.forall function failed to recognize" - - testCase "Check if all non-diagonal values in a matrix are >= 1337. (expected to be false)" <| fun () -> - Expect.isFalse (Matrix.foralli (fun outerI innerI elem -> if outerI <> innerI then elem >= 1337. else true) testSquareMatrixA) "test matrix did not have all non-diagonal values => 1337. but the Matrix.foralli function failed to recognize" - - ] - testList "existsi" [ - - testCase "Check if a testMatrix contains 0. (expected to be true)" <| fun () -> - Expect.isTrue (Matrix.existsi (fun outerI innerI elem -> elem = 0.) testSquareMatrixA) "Test matrix was expected to contain a value 0., but Matrix.existsi returned false" - - testCase "Check if a testMatrix contains 1337. (expected to be false)" <| fun () -> - Expect.isFalse (Matrix.existsi (fun outerI innerI elem -> elem = 1337.) testSquareMatrixA) "Test matrix was not expected to contain a value 1337., but Matrix.existsi returned true" - - testCase "Check if a testMatrix contains 0. on the diagonal (expected to be true)" <| fun () -> - Expect.isTrue (Matrix.existsi (fun outerI innerI elem -> if outerI = innerI then elem = 0. else false) testSquareMatrixA) "Test matrix was expected to contain a diagonal value 0., but Matrix.existsi returned false" - - testCase "Check if a testMatrix contains a non diagonal value 1337. (expected to be false)" <| fun () -> - Expect.isFalse (Matrix.existsi (fun outerI innerI elem -> if outerI <> innerI then elem = 1337. else false) testSquareMatrixA) "Test matrix was not expected to contain a non-diagonal value 1337., but Matrix.existsi returned true" - ] - testList "map" [ - - testCase "map with (fun elem -> elem * 2)" <| fun () -> - let actual = - testSquareMatrixA - |> Matrix.map (fun elem -> elem * 2.) - - let expected = - let values = - Array2D.init - 3 - 3 - (fun i j -> - testValuesArrRows.[i].[j] * 2. - ) - Matrix.DenseRepr - (DenseMatrix(Some (Instances.FloatNumerics :> INumeric),values)) - - Expect.equal actual expected "Mapping the values of a test matrix with * 2. did not return the correct result" - - testCase "map with multiplication by constant should return the same result as matrix.scale" <| fun () -> - let actual = - testSquareMatrixA - |> Matrix.map (fun elem -> elem * 2.) - - let expected = - testSquareMatrixA - |> Matrix.scale 2. - - Expect.equal actual expected "map with multiplication by constant did not return the same result as Matrix.scale" - - testCase "map with multiplication by constant -1. should return the same result as matrix.neg" <| fun () -> - let actual = - testSquareMatrixA - |> Matrix.map (fun elem -> elem * -1.) - - let expected = - testSquareMatrixA - |> Matrix.neg - - Expect.equal actual expected "map with multiplication by constant did not return the same result as Matrix.neg" - - ] - testList "copy" [ - - testCase "Matrix copy created by Matrix.copy should equal original matrix" <| fun () -> - Expect.equal (Matrix.copy testSquareMatrixA) testSquareMatrixA "Matrix copy created by Matrix.copy was not equal to original matrix" - - testCase "Matrix copy created by Matrix.copy should stay the same when original matrix is mutated" <| fun () -> - let testCopyA = Matrix.copy testSquareMatrixA - let testCopyB = Matrix.copy testCopyA - Matrix.set testCopyA 0 0 1337. - Expect.notEqual testCopyA testCopyB "Matrix copy created by Matrix.copy did not stay the same when original matrix is mutated" - ] - testList "mapi" [ - - testCase "mapi with (fun elem -> elem * 2)" <| fun () -> - let actual = - testSquareMatrixA - |> Matrix.mapi (fun i j elem -> elem * 2.) - - let expected = - let values = - Array2D.init - 3 - 3 - (fun i j -> - testValuesArrRows.[i].[j] * 2. - ) - Matrix.DenseRepr - (DenseMatrix(Some (Instances.FloatNumerics :> INumeric),values)) - - Expect.equal actual expected "Mapping the values of a test matrix with * 2. did not return the correct result" - - testCase "map with multiplication by constant should return the same result as matrix.scale" <| fun () -> - let actual = - testSquareMatrixA - |> Matrix.mapi (fun i j elem -> elem * 2.) - - let expected = - testSquareMatrixA - |> Matrix.scale 2. - - Expect.equal actual expected "map with multiplication by constant did not return the same result as Matrix.scale" - - testCase "map with multiplication by constant -1. should return the same result as matrix.neg" <| fun () -> - let actual = - testSquareMatrixA - |> Matrix.mapi (fun i j elem -> elem * -1.) - - let expected = - testSquareMatrixA - |> Matrix.neg - - Expect.equal actual expected "map with multiplication by constant did not return the same result as Matrix.neg" - - testCase "create identity matrix using mapi" <| fun () -> - let actual = - testSquareMatrixA - |> Matrix.mapi - (fun i j elem -> - if i = j then - 1. - else - 0. - ) - Expect.equal actual identityFloat3 "creating identity matrix using Matrix.mapi failed" - - ] - testList "mapRows" [ - - testCase "map with Seq.mean" <| fun () -> - let actual = - testSquareMatrixA - |> Matrix.mapRows Seq.mean - - let expected = - Vector.init - 3 - (fun i -> Seq.mean testValuesArrRows.[i]) - - Expect.equal actual expected "Mapping the rows of a test matrix with Seq.mean did not return the correct result" - ] - testList "mapCols" [ - - testCase "map with Seq.mean" <| fun () -> - let actual = - testSquareMatrixA - |> Matrix.mapCols Seq.mean - - let expected = - RowVector.init 3 (fun i -> Seq.mean testValuesArrCols.[i]) - - Expect.equal actual expected "Mapping the cols of a test matrix with Seq.mean did not return the correct result" - ] - testList "mapiRows" [ - - testCase "mapi with Seq.mean" <| fun () -> - let actual = - testSquareMatrixA - |> Matrix.mapiRows (fun i x -> float i * Seq.mean x) - - let expected = - Vector.init 3 (fun i -> float i * Seq.average testValuesArrRows.[i]) - - Expect.equal actual expected "Mapping the rows of a test matrix with Seq.mean did not return the correct result" - ] - testList "mapiCols" [ - - testCase "mapi with Seq.mean" <| fun () -> - let actual = - testSquareMatrixA - |> Matrix.mapiCols (fun i x -> float i * Seq.mean x) - - let expected = - RowVector.init 3 (fun i -> float i * Seq.average testValuesArrCols.[i]) - - Expect.equal actual expected "Mapping the columns of a test matrix with Seq.mean did not return the correct result" - ] - testList "fold" [ - - testCase "Sum of all matrix entries using Matrix.fold" <| fun () -> - let actual = - testSquareMatrixA - |> Matrix.fold (fun acc elem -> acc + elem) 0. - - Expect.equal actual 21. "Sum of matrix elements was not correctly computed using Matrix.fold" - - testCase "count matrix entries using Matrix.fold" <| fun () -> - let actual = - testSquareMatrixA - |> Matrix.fold (fun acc _ -> acc + 1) 0 - - Expect.equal actual 9 "Matrix entries where not correctly counted using Matrix.fold" - ] - testList "foldi" [ - - testCase "Sum of all matrix entries using Matrix.foldi" <| fun () -> - let actual = - testSquareMatrixA - |> Matrix.foldi (fun i j acc elem -> acc + elem) 0. - - Expect.equal actual 21. "Sum of matrix elements was not correctly computed using Matrix.foldi" - - testCase "count matrix entries using Matrix.foldi" <| fun () -> - let actual = - testSquareMatrixA - |> Matrix.foldi (fun i j acc _ -> acc + 1) 0 - - Expect.equal actual 9 "Matrix entries where not correctly counted using Matrix.foldi" - - testCase "Calculation of Matrix trace using Matrix.foldi should be equal to the result of the Matrix.trace function" <| fun () -> - let actual = - testSquareMatrixA - |> Matrix.foldi - (fun i j acc elem -> - if i = j then - acc + elem - else - acc - ) - 0. - Expect.equal actual (Matrix.trace testSquareMatrixA) "Results of Matrix.trace and calculating matrix trace with Matrix.foldi where not equal" - ] - testList "filterRows" [ - testCase "simple filter by sum" <| fun () -> - let expected = - matrix [ - [1.;2.] - [2.;1.] - ] - let actual = - matrix [ - [5.;5.] - [1.;2.] - [5.;5.] - [2.;1.] - [5.;5.] - [5.;5.] - ] - |> Matrix.filterRows (fun r -> r |> Seq.sum = 3.) - Expect.equal actual expected "Matrix.filterRows did not return correct result" - - testCase "simple filter by contains" <| fun () -> - let expected = - matrix [ - [1.;100.] - [2.;100.] - ] - let actual = - matrix [ - [5.;5.] - [1.;2.] - [5.;5.] - [1.;100.] - [2.;100.] - [2.;1.] - [5.;5.] - [5.;5.] - ] - |> Matrix.filterRows (fun r -> r |> Seq.contains 100.) - Expect.equal actual expected "Matrix.filterRows did not return correct result" - ] - testList "filterCols" [ - testCase "simple filter by sum" <| fun () -> - let expected = - matrix [ - [1.;2.] - [2.;1.] - ] - let actual = - matrix [ - [5.;1.;6.;2.;0.] - [5.;2.;6.;1.;0.] - ] - |> Matrix.filterCols (fun c -> c |> Seq.sum = 3.) - Expect.equal actual expected "Matrix.filterCols did not return correct result" - - testCase "simple filter by contains" <| fun () -> - let expected = - matrix [ - [100.;2.] - [2.;100.] - ] - let actual = - matrix [ - [5.;100.;6.;2.;0.] - [5.;2.;6.;100.;0.] - ] - |> Matrix.filterCols (fun c -> c |> Seq.contains 100.) - Expect.equal actual expected "Matrix.filterCols did not return correct result" - ] - testList "filterCols" [ - - ] - testList "toDense" [ - - testCase "toDense" <| fun () -> - () - ] - testList "initDense" [ - - testCase "initDense" <| fun () -> - () - ] - testList "initSparse" [ - - testCase "initSparse" <| fun () -> - () - ] - testList "nonzero_entries" [ - - testCase "nonzero_entries" <| fun () -> - let actual = - Matrix.nonzero_entries testSquareMatrixA - |> Array.ofSeq - - let expected = - testValuesArrRows - |> Array.mapi - (fun outerI row -> - row - |> Array.mapi - (fun innerI elem -> - (outerI,innerI,elem) - ) - ) - |> Array.concat - |> Array.filter (fun (_,_,elem) -> elem > 0.) - - Expect.equal actual expected "Matrix.nonzero_entries returned the wron elements/indices" - - - ] - testList "zero" [ - - let actual = - Matrix.zero 3 3 - - let expected = - let values = - Array2D.init - 3 - 3 - (fun i j -> - 0. - ) - Matrix.DenseRepr - (DenseMatrix(Some (Instances.FloatNumerics :> INumeric),values)) - - Expect.equal actual expected "Matrix with zero entries was not initialized corrtectly" - - ] - testList "identity" [ - testCase "Create 3x3 identity matrix" <| fun () -> - let actual = Matrix.identity 3 - - Expect.equal actual identityFloat3 "Identity Matrix was not correctly initialized" - - ] - testList "ones" [ - - testCase "Create 3x3 Matrix with only 1. as entries" <| fun () -> - let actual = - Matrix.ones 3 3 - - let expected = - let values = - Array2D.init - 3 - 3 - (fun i j -> - 1. - ) - Matrix.DenseRepr - (DenseMatrix(Some (Instances.FloatNumerics :> INumeric),values)) - Expect.equal actual expected "Matrix with only 1. as entries was not initialized correctly" - ] - testList "getRow" [ - - testCase "getRow" <| fun () -> - let actual = Matrix.getRow testSquareMatrixA 1 - Expect.equal actual testRowVecC "Matrix.getRow did not return the correct rowvector" - - testCase "Getting row out of row range using Matrix.getRow should fail" <| fun () -> - Expect.throws (fun () -> Matrix.getRow testSquareMatrixA 1337 |> ignore) "Getting row out of row range using Matrix.getRow did not fail although it should" - - ] - testList "setRow" [ - - testCase "Set Row" <| fun () -> - - let actual = Matrix.copy testSquareMatrixA - Matrix.setRow actual 1 testVectorA - - let expected = - let rows = - [| - [|0.;1.;2.|] - [|0.;3.;6.|] - [|0.;5.;6.|] - |] - let values = - Array2D.init - 3 - 3 - (fun i j -> - rows.[i].[j] - ) - Matrix.DenseRepr - (DenseMatrix(Some (Instances.FloatNumerics :> INumeric),values)) - - Expect.equal actual expected "Matrix.getRow did not return the correct rowvector" - - testCase "Setting row out of row range using Matrix.setRow should fail" <| fun () -> - Expect.throws (fun () -> Matrix.setRow testSquareMatrixA 1337 testVectorA |> ignore) "Settingetting row out of row range using Matrix.getRow did not fail although it should" - - testCase "Setting row with vector of wrong length using Matrix.setRow should fail" <| fun () -> - Expect.throws (fun () -> Matrix.setRow testSquareMatrixA 1 testVector1LowerDiag |> ignore) "Setting row with vector of wrong length using Matrix.setRow did not fail although it should" - - ] - testList "getCol" [ - - testCase "getCol" <| fun () -> - let actual = Matrix.getCol testSquareMatrixA 0 - Expect.equal actual testVectorB "Matrix.getCol did nbot return the correct vector" - - testCase "Getting column out of col range using Matrix.getCol should fail" <| fun () -> - Expect.throws (fun () -> Matrix.getCol testSquareMatrixA 1337 |> ignore) "Getting Column out of col range using Matrix.getCol did not fail although it should" - - ] - testList "setCol" [ - - testCase "Set Column" <| fun () -> - - let actual = Matrix.copy testSquareMatrixA - Matrix.setCol actual 0 testVectorA - - let expected = - let rows = - [| - [|0.;1.;2.|] - [|3.;3.;4.|] - [|6.;5.;6.|] - |] - let values = - Array2D.init - 3 - 3 - (fun i j -> - rows.[i].[j] - ) - Matrix.DenseRepr - (DenseMatrix(Some (Instances.FloatNumerics :> INumeric),values)) - - Expect.equal actual expected "Matrix.setCol did not return the correct vector" - - testCase "Setting column out of col range using Matrix.setCol should fail" <| fun () -> - Expect.throws (fun () -> Matrix.setCol testSquareMatrixA 1337 testVectorA |> ignore) "Setting column out of col range using Matrix.setCol did not fail although it should" - - testCase "Setting column with vector of wrong length using Matrix.setCol should fail" <| fun () -> - Expect.throws (fun () -> Matrix.setCol testSquareMatrixA 1 testVector1LowerDiag |> ignore) "Setting row with vector of wrong length using Matrix.setRow did not fail although it should" - - testCase "Set Column non square" <| fun () -> - - let test2x3MatrixNonSquare : Matrix = - let values = - Array2D.init - 2 - 3 - (fun i j -> - 0. - ) - Matrix.DenseRepr - (DenseMatrix(Some (Instances.FloatNumerics :> INumeric),values)) - - Matrix.setCol test2x3MatrixNonSquare 0 ([1.;1.]|>Vector.ofList) - - let expected = - let rows = - [| - [|1.;0.;0.|] - [|1.;0.;0.|] - |] - let values = - Array2D.init - 2 - 3 - (fun i j -> - rows.[i].[j] - ) - Matrix.DenseRepr - (DenseMatrix(Some (Instances.FloatNumerics :> INumeric),values)) - - Expect.equal test2x3MatrixNonSquare expected "Matrix.setCol did not return the correct vector for non square Matrix" - - - ] - testList "getCols" [ - - testCase "getCols" <| fun () -> - () - ] - testList "getRows" [ - - testCase "getRows" <| fun () -> - () - ] - testList "getRegion" [ - - testCase "get Region" <| fun () -> - - let actual = Matrix.getRegion testSquareMatrixA 0 0 3 2 - - Expect.equal actual test2x3MatrixTransposed "Matrix. getRegion did not return the correct matrix window" - ] - testList "rowRange" [ - - testCase "rowRange" <| fun () -> - Expect.equal (Matrix.rowRange testSquareMatrixA) (0,2) "Matrix.rowRange did not return the correct dimension" - ] - testList "colRange" [ - - testCase "colRange" <| fun () -> - Expect.equal (Matrix.colRange testSquareMatrixA) (0,2) "Matrix.colRange did not return the correct dimension" - ] - testList "wholeRegion" [ - - testCase "wholeRegion" <| fun () -> - Expect.equal (Matrix.wholeRegion testSquareMatrixA) ((0,2),(0,2)) "Matrix.wholeRange did not return the correct dimensions" - ] - testList "foldByRow" [ - - testCase "compute row sum vector" <| fun () -> - let actual = - testSquareMatrixA - |> Matrix.foldByRow (fun acc elem -> acc + elem) testVectorB - - let expected = - let values = [|3.;7.;11.|] - Vector(Some (Instances.FloatNumerics :> INumeric),values) - - Expect.equal actual expected "Matrix.foldByCol did not compute the correct row sum vector" - ] - testList "foldByCol" [ - - testCase "compute column sum vector" <| fun () -> - let actual = - testSquareMatrixA - |> Matrix.foldByCol (fun acc elem -> acc + elem) testRowVecD - - let expected = - let values = [|0.;9.;12.|] - RowVector(Some (Instances.FloatNumerics :> INumeric),values) - - Expect.equal actual expected "Matrix.foldByCol did not compute the correct column sum vector" - ] - testList "foldRow" [ - - testCase "compute sum of a row" <| fun () -> - let actual = Matrix.foldRow (fun acc elem -> acc + elem) 0. testSquareMatrixA 0 - Expect.equal actual 3. "Matrix.foldRow did not return the correct sum for a row" - ] - testList "foldCol" [ - - testCase "compute sum of a column" <| fun () -> - let actual = Matrix.foldCol (fun acc elem -> acc + elem) 0. testSquareMatrixA 0 - Expect.equal actual 0. "Matrix.foldRow did not return the correct sum for a column" - ] - testList "sum" [ - - testCase "Sum of all matrix entries using Matrix.sum" <| fun () -> - let actual = - testSquareMatrixA - |> Matrix.sum - - Expect.equal actual 21. "Sum of matrix elements was not correctly computed using Matrix.sum" - ] - testList "prod" [ - - testCase "Product of all matrix entries using Matrix.prod" <| fun () -> - let actual = - testSquareMatrixA - |> Matrix.prod - - Expect.equal actual 0. "Product of matrix elements was not correctly computed using Matrix.sum" - - ] - testList "mean" [ - testCase "meanRowWise" <| fun() -> - let testMat = matrix [ - [20.; 11.]; - [6.; 29.]; - [12.; 8.]; - ] - let correctList = [15.5; 17.5; 10.] - - let testlist = List.ofArray( Vector.toArray (Matrix.meanRowWise testMat)) - List.iter2 (fun a b -> Expect.floatClose Accuracy.high a b "means of matrix RowWise was calculated incorrectly") testlist correctList - - testCase "meanColumnWise"<| fun() -> - let testMat = matrix[ - [20.;6.;12.]; - [11.;29.;8.] - ] - let correctList = [15.5; 17.5; 10.] - let testlist = List.ofArray( RowVector.toArray (Matrix.meanColumnWise testMat)) - List.iter2 (fun a b -> Expect.floatClose Accuracy.high a b "means of matrix ColumnWise was calculated incorrectly") testlist correctList - - ] - testList "norm" [ - - testCase "norm" <| fun () -> - () - ] - testList "dot" [ - - testCase "dot" <| fun () -> - () - ] - testList "cptPow" [ - - testCase "cptPow" <| fun () -> - () - ] - - ] - ] From 9c0a9f3d56779e54d3a2122f6a65c29760286024 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20M=C3=BChlhaus?= Date: Sat, 12 Apr 2025 12:20:37 +0200 Subject: [PATCH 027/121] Add Unit test for SummaryStats (former RunningStats) --- src/FSharp.Stats/AlgTypes/Matrix.fs | 7 +- src/FSharp.Stats/Algebra/LinearAlgebra.fs | 4 +- src/FSharp.Stats/FSharp.Stats.fsproj | 2 +- src/FSharp.Stats/Playground.fsx | 111 +- src/FSharp.Stats/RunningStats.fs | 132 --- src/FSharp.Stats/Seq.fs | 28 +- src/FSharp.Stats/SummaryStats.fs | 303 +++++ .../FSharp.Stats.Tests.fsproj | 8 + tests/FSharp.Stats.Tests/Interpolation.fs | 24 +- tests/FSharp.Stats.Tests/LinAlgebra.fs | 529 +++++++++ tests/FSharp.Stats.Tests/LinearAlgebra.fs | 1003 ++++++----------- tests/FSharp.Stats.Tests/Seq.fs | 54 +- tests/FSharp.Stats.Tests/Signal.fs | 2 +- tests/FSharp.Stats.Tests/SummaryStats.fs | 174 +++ 14 files changed, 1488 insertions(+), 893 deletions(-) delete mode 100644 src/FSharp.Stats/RunningStats.fs create mode 100644 src/FSharp.Stats/SummaryStats.fs create mode 100644 tests/FSharp.Stats.Tests/LinAlgebra.fs create mode 100644 tests/FSharp.Stats.Tests/SummaryStats.fs diff --git a/src/FSharp.Stats/AlgTypes/Matrix.fs b/src/FSharp.Stats/AlgTypes/Matrix.fs index 1512f91ae..0888bcaf9 100644 --- a/src/FSharp.Stats/AlgTypes/Matrix.fs +++ b/src/FSharp.Stats/AlgTypes/Matrix.fs @@ -209,7 +209,7 @@ type Matrix<'T when 'T :> Numerics.INumber<'T> /// Creates a new matrix by initializing each element with a function `f(row, col)`. - static member inline transpose<'T when 'T :> Numerics.INumber<'T> + static member inline private transposeByBlock<'T when 'T :> Numerics.INumber<'T> and 'T : (new: unit -> 'T) and 'T : struct and 'T :> ValueType> @@ -240,9 +240,12 @@ type Matrix<'T when 'T :> Numerics.INumber<'T> dst + static member inline transpose (m:Matrix<'T>) : Matrix<'T> = + m.Transpose() + member this.Transpose() = let blocksize = 16 - Matrix(this.NumCols, this.NumRows, Matrix.transpose this.NumRows this.NumCols this.Data blocksize) + Matrix(this.NumCols, this.NumRows, Matrix.transposeByBlock this.NumRows this.NumCols this.Data blocksize) static member init<'T when 'T :> Numerics.INumber<'T> and 'T : (new: unit -> 'T) diff --git a/src/FSharp.Stats/Algebra/LinearAlgebra.fs b/src/FSharp.Stats/Algebra/LinearAlgebra.fs index a291897b0..b5f0eac95 100644 --- a/src/FSharp.Stats/Algebra/LinearAlgebra.fs +++ b/src/FSharp.Stats/Algebra/LinearAlgebra.fs @@ -8,7 +8,7 @@ type LinearAlgebra = /// Subtract `scaleVal * src[srcOffset..srcOffset+count-1]` from /// `dst[dstOffset..dstOffset+count-1]` in place. - static member inline private subScaledRowInPlace + static member inline subScaledRowInPlace (scaleVal : 'T) (dstOffset : int) (srcOffset : int) @@ -27,7 +27,7 @@ type LinearAlgebra = d - (scaleVal * s) Acceleration.SIMDRangeUtils.map2RangeInPlace fv f dstOffset srcOffset count dst src - static member inline private householderTransform + static member inline householderTransform (A: Matrix<'T>) (i: int) : Vector<'T> = let n = A.NumRows let v = Vector.zeroCreate<'T> n diff --git a/src/FSharp.Stats/FSharp.Stats.fsproj b/src/FSharp.Stats/FSharp.Stats.fsproj index 542b345c4..31d570668 100644 --- a/src/FSharp.Stats/FSharp.Stats.fsproj +++ b/src/FSharp.Stats/FSharp.Stats.fsproj @@ -44,7 +44,7 @@ - + diff --git a/src/FSharp.Stats/Playground.fsx b/src/FSharp.Stats/Playground.fsx index 1087204b6..ed66d5edb 100644 --- a/src/FSharp.Stats/Playground.fsx +++ b/src/FSharp.Stats/Playground.fsx @@ -9,6 +9,72 @@ open FSharp.Stats.Distributions +let data = [|1.0; 2.0; 3.0; 4.0; 5.0|] + +SummaryStats.ofSeq data +SummaryStats.ofArray data + +let statsC = SummaryStats.ofSeq data +let calcMean = Seq.mean data +let calcSumOfSquares = Seq.sumBy (fun x -> x * x) data +let calcMin = Seq.min data +let calcMax = Seq.max data +let calcN = Seq.length data + + +open FSharp.Stats.Testing + +let groupA = [|-5.;-3.;-3.;-4.;-5.;|] +let groupB = [|-2.;-4.;-4.;-6.;-6.;-6.;-5.;|] + +let statsA = Seq.stats groupA +let statsB = Seq.stats groupB + + +let meanA = Seq.mean groupA +let meanB = Seq.mean groupB +let varA = Seq.var groupA +let varB = Seq.var groupB +let nA = float (Seq.length groupA) +let nB = float (Seq.length groupB) + +// calculation of the H test +let tTest1 = TTest.twoSample true groupA groupB +let tTest2 = TTest.twoSampleFromMeanAndVar true (meanA,varA,nA) (meanB,varB,nB) +let tTest3 = TTest.twoSample false groupA groupB + + + + + +let KDiagonal1 = + [| + [|1.;0.;0.|] + [|0.;1.;0.|] + [|0.;0.;1.|] + |] + |> Matrix.ofJaggedArray + +let BNegInf = + [| + [|-infinity;-infinity;-infinity|] + [|-infinity;-infinity;-infinity|] + [|-infinity;-infinity;-infinity|] + |] + |> Matrix.ofJaggedArray + + +Algebra.LinearAlgebra .solveTriangularLinearSystems KDiagonal1 BNegInf false + +//|> fun res -> +// let expected = +// matrix [| +// [|nan;nan;nan|]; +// [|nan;nan;nan|]; +// [|-infinity;-infinity;-infinity|] +// |] + + let alpha = 9.9 //0.4 let beta = 31 //4.2 @@ -40,12 +106,12 @@ let samplesHisto = Array.init 999999 (fun _ -> Continuous.Gamma.Sample alpha bet let bw = 1.//FSharp.Stats.Distributions.Bandwidth.forHistogram samplesHisto let histo = FSharp.Stats.Distributions.KernelDensity.estimate KernelDensity.Kernel.gaussian bw samplesHisto let histoPdf = histo |> Seq.map (fun (x,y) -> x,Continuous.Gamma.PDF alpha beta x) -[ - Chart.Column(histo) - Chart.Point(histoPdf) -] -|> Chart.combine -|> Chart.show +//[ +// Chart.Column(histo) +// Chart.Point(histoPdf) +//] +//|> Chart.combine +//|> Chart.show let alpha', beta' = Continuous.Gamma.Fit samplesHisto @@ -64,36 +130,3 @@ d.Mean -open FSharp.Stats -let rnd = new System.Random(69) - -let mDenseInt1 = Matrix.Generic.init 10 10 (fun r c -> $"{r}{c}" ) -let mDenseInt2 = Matrix.Generic.init 10 100 (fun r c -> $"{r}{c}" ) -let mDenseInt3 = Matrix.Generic.init 100 10 (fun r c -> $"{r}{c}" ) -let mDenseInt4 = Matrix.Generic.init 100 100 (fun r c -> $"{r}{c}" ) - -mDenseInt1.Format(false) -mDenseInt1.Format(true) -mDenseInt2.Format(false) -mDenseInt2.Format(true) -mDenseInt3.Format(false) -mDenseInt3.Format(true) -mDenseInt4.Format(false) -mDenseInt4.Format(true) - -let mDense1 = Matrix.init 10 10 (fun i j -> float i * float j * rnd.NextDouble()) -let mDense2 = Matrix.init 10 100 (fun i j -> float i * float j * rnd.NextDouble()) -let mDense3 = Matrix.init 100 10 (fun i j -> float i * float j * rnd.NextDouble()) -let mDense4 = Matrix.init 100 100 (fun i j -> float i * float j * rnd.NextDouble()) -let mDenseSpecial = matrix[[nan;100000000.;infinity;1.4];[1.337;-nan;4269420.42;-infinity]] - -mDense1.Format(false) -mDense1.Format(true) -mDense2.Format(false) -mDense2.Format(true) -mDense3.Format(false) -mDense3.Format(true) -mDense4.Format(false) -mDense4.Format(true) -mDenseSpecial.Format(false) -mDenseSpecial.Format(true) diff --git a/src/FSharp.Stats/RunningStats.fs b/src/FSharp.Stats/RunningStats.fs deleted file mode 100644 index b9f8d23fd..000000000 --- a/src/FSharp.Stats/RunningStats.fs +++ /dev/null @@ -1,132 +0,0 @@ -namespace FSharp.Stats - - -/// Module to compute common statistical measure on -module SummaryStats = - - type SummaryStats<'T> = { - N : 'T - Mean : 'T - SumOfSquares : 'T - Min : 'T - Max : 'T - } - - let createSummaryStats n mean sos min max = - {N=n;Mean=mean;SumOfSquares=sos;Min=min;Max=max} - - - /// - let inline mean sStats = sStats.Mean - /// - let inline varPopulation sStats = sStats.SumOfSquares / sStats.N - /// - let inline var (sStats:SummaryStats<'T>) = - let one = LanguagePrimitives.GenericOne<'T> - sStats.SumOfSquares / (sStats.N - one) - /// - let inline stDev (rStats:SummaryStats<'T>) = - sqrt (var rStats) - /// - let inline stDevPopulation (rStats:SummaryStats<'T>) = - sqrt (varPopulation rStats) - - - - -module RunningStats = - - type RunningStats<'T> = { - N : int - M1 : 'T - M2 : 'T - M3 : 'T - M4 : 'T - } - - let createRunningStats n m1 m2 m3 m4 = - {N=n;M1=m1;M2=m2;M3=m3;M4=m4} - - //let inline combine (a:RunningStats<'T>) (b:RunningStats<'T>) = - - // let (..*) n a = Ops.multByInt32 a n - - // let cn = a.N + b.N - // let delta = b.M1 - a.M1 - // let delta2 = delta * delta - // let delta3 = delta * delta2 - // let delta4 = delta2 * delta2 - - // let cM1 = LanguagePrimitives.DivideByInt<'T> ( (Ops.multByInt32 a.M1 a.N ) + (Ops.multByInt32 b.M1 b.N)) cn - // let cM2 = LanguagePrimitives.DivideByInt<'T> (Ops.multByInt32 (a.M2 + b.M2 + delta2) (a.N * b.N)) cn - // let cM3 = - // let tmp = LanguagePrimitives.DivideByInt<'T> (Ops.multByInt32 (a.M3 + b.M3 + delta3) (a.N * b.N * (a.N - b.N))) (cn * cn) - // tmp + LanguagePrimitives.DivideByInt<'T> ((Ops.multByInt32 delta 3) * (Ops.multByInt32 b.M2 a.N) - (Ops.multByInt32 a.M2 b.N)) cn - // let cM4 = - // let tmp = LanguagePrimitives.DivideByInt<'T> (Ops.multByInt32 (Ops.multByInt32 (a.M4 + b.M4 + delta4) (a.N*b.N)) (a.N*a.N - a.N*b.N + b.N*b.N)) (cn * cn * cn) - // //let tmp2 = LanguagePrimitives.DivideByInt<'T> ((Ops.multByInt32 delta2 6) * ((Ops.multByInt32 b.M2 (a.N * a.N)) + (Ops.multByInt32 a.M2 (b.N * b.N)))) (cn*cn) - // tmp + (LanguagePrimitives.DivideByInt<'T> (6 ..* delta2 * ( (a.N * a.N) ..* b.M2 + (b.N * b.N) ..* a.M2)) (cn*cn)) + LanguagePrimitives.DivideByInt<'T> (4 ..* delta * (a.N ..* b.M3 - b.N ..* a.M3)) cn - - // createRunningStats cn cM1 cM2 cM3 cM4 - - - - - let inline mean rStats = - rStats.M1 - /// - let inline varPopulation rStats = - LanguagePrimitives.DivideByInt rStats.M2 rStats.N - /// - let inline var (rStats:RunningStats<'T>) = - LanguagePrimitives.DivideByInt rStats.M2 (rStats.N-1) - /// - let inline stDev (rStats:RunningStats<'T>) = - sqrt (var rStats) - /// - let inline stDevPopulation (rStats:RunningStats<'T>) = - sqrt (varPopulation rStats) - -// ///Skewness -// let inline skewness (rStats:RunningStats<'T>) = -// sqrt(double(n)) * M3/ pown(M2, 1.5) -// sqrt (varPopulation rStats) - - /// Kurtosis -// let inline kurtosis (rStats:RunningStats<'T>) = -// let one = LanguagePrimitives.GenericOne< 'T > -// let tmp = Ops.multByInt32 rStats.M4 rStats.N -// tmp / (rStats.M2 * rStats.M2) - (one + one + one) - - - -// let inline ofSeq (items:seq<'T>) : RunningStats< 'U > = -// use e = items.GetEnumerator() -// let zero = LanguagePrimitives.GenericZero< 'U > -// //let one = LanguagePrimitives.GenericOne< 'U > - -// let rec loop n (m1:'U) (m2:'U) (m3:'U) (m4:'U) = -// match e.MoveNext() with -// | true -> -// let n' = n + 1 -// let delta = e.Current - m1 -// let delta_n = LanguagePrimitives.DivideByInt< 'U > delta n -// let delta_n2 = delta_n * delta_n -// let term1 = Ops.multByInt32 (delta * delta_n) n' -// let m1' = m1 + delta_n -// let m4' = m4 + (Ops.multByInt32 (term1 * delta_n2) (n'*n' - 3*n' + 3)) + (Ops.multByInt32 (delta_n2 * m2) 6) - (Ops.multByInt32 (delta_n * m3) 4) -// let m3' = m3 + (Ops.multByInt32 (term1 * m2) (n' - 2)) - (Ops.multByInt32 (delta_n * m2) 3 ) -//// let m4' = m4 + (term1 * delta_n2 * (n'*n' - 3*n' + 3) + 6 * delta_n2 * m2 - 4 * delta_n * m3) -//// let m3' = m3 + (term1 * delta_n * (n' - 2) - 3 * delta_n * m2) -// let m2' = term1 - -// loop (n + 1) m1' m2' m3' m4' -// | false -> -// if (n > 1) then -// createRunningStats n m1 m2 m3 m4 -// else -// let nanU = zero / zero -// createRunningStats n nanU nanU nanU nanU -// loop 0 zero zero zero zero - - diff --git a/src/FSharp.Stats/Seq.fs b/src/FSharp.Stats/Seq.fs index c0f93baa6..3cf9dc50f 100644 --- a/src/FSharp.Stats/Seq.fs +++ b/src/FSharp.Stats/Seq.fs @@ -1172,7 +1172,8 @@ module Seq = // /// /// Returns SummaryStats of the input sequence with N, mean, sum-of-squares, minimum and maximum. - /// + /// + /// Welfords online algorithm /// The input sequence. /// The SummaryStats of the input sequence. /// @@ -1181,35 +1182,14 @@ module Seq = /// let stats = Seq.stats values /// // returns SummaryStats with: /// // N = 5 - /// // Mean = 3.5 + /// // Mean = 3.0 /// // SumOfSquares = 5.0 /// // Minimum = 1.0 /// // Maximum = 5.0 /// /// let inline stats (items:seq<'T>) = - use e = items.GetEnumerator() - let zero = LanguagePrimitives.GenericZero< 'T > - let one = LanguagePrimitives.GenericOne< 'T > - - let rec loop n (minimum) (maximum) m1 m2 = - match e.MoveNext() with - | true -> - let current = e.Current - let delta = current - m1 - let deltaN = (delta / n) - //let delta_n2 = deltaN * deltaN - let m1' = m1 + deltaN - let m2' = m2 + delta * deltaN * (n-one) - loop (n + one) (min current minimum) (max current maximum) m1' m2' - | false -> SummaryStats.createSummaryStats n m1 m2 minimum maximum - - //Init by first value - match e.MoveNext() with - | true -> loop one e.Current e.Current zero zero - | false -> - let uNan = zero / zero - SummaryStats.createSummaryStats zero uNan uNan uNan uNan + SummaryStats.ofSeq items /// /// Calculates the sample means with a given number of replicates present in the sequence. diff --git a/src/FSharp.Stats/SummaryStats.fs b/src/FSharp.Stats/SummaryStats.fs new file mode 100644 index 000000000..315eb5389 --- /dev/null +++ b/src/FSharp.Stats/SummaryStats.fs @@ -0,0 +1,303 @@ +namespace FSharp.Stats + + +/// +/// Module to compute summary statistics for a collection of numeric values, +/// including the count, mean, M2 (sum of squared deviations), +/// minimum, and maximum. +/// +module SummaryStats = + + + /// + /// Represents summary statistics for a collection of numeric values, + /// including the count, mean, M2 (sum of squared deviations), + /// minimum, and maximum. + /// + type SummaryStats<'T> = + { + /// The number of data points observed. + N : 'T + /// The mean (average) of all observed data points. + Mean : 'T + /// The sum of squared deviations fom the mean + SumSqrdDevations : 'T + /// The minimum observed value. + Min : 'T + /// The maximum observed value. + Max : 'T + } + + /// + /// Creates a SummaryStats record from the given fields. + /// + /// The number of observed data points. + /// The running mean of the data points. + /// The sum of squared deviations fom the mean + /// The minimum observed value. + /// The maximum observed value. + /// A new SummaryStats record. + let createSummaryStats n mean sos min max = + {N=n;Mean=mean;SumSqrdDevations=sos;Min=min;Max=max} + + /// + /// Returns the mean (average) value from the specified summary statistics. + /// + /// A summary statistics record. + /// The mean of the observed data. + let inline mean sStats = + sStats.Mean + + /// + /// Returns the population variance from the specified summary statistics. + /// + /// + /// The population variance is defined as SumOfSquares / N, + /// where SumOfSquares is the sum of squared deviations (M2), + /// and N is the total count. + /// + /// A summary statistics record. + /// The population variance of the observed data. + let inline varPopulation sStats = + sStats.SumSqrdDevations / sStats.N + + /// + /// Returns the sample variance from the specified summary statistics, + /// using N - 1 in the denominator. + /// + /// + /// The sample variance is computed as SumOfSquares / (N - 1), + /// which is the unbiased estimator when N > 1. + /// + /// A summary statistics record. + /// The sample variance of the observed data. + let inline var (sStats: SummaryStats<'T>) = + let one = LanguagePrimitives.GenericOne<'T> + sStats.SumSqrdDevations / (sStats.N - one) + + /// + /// Returns the sample standard deviation from the specified summary statistics. + /// + /// + /// This is the square root of the sample variance. + /// + /// A summary statistics record. + /// The sample standard deviation of the observed data. + let inline stDev (sStats: SummaryStats<'T>) = + sqrt (var sStats) + + /// + /// Returns the population standard deviation from the specified summary statistics. + /// + /// + /// This is the square root of the population variance. + /// + /// A summary statistics record. + /// The population standard deviation of the observed data. + let inline stDevPopulation (sStats: SummaryStats<'T>) = + sqrt (varPopulation sStats) + + + /// + /// Computes Welford-based summary statistics (count, mean, sum of squares, min, max) + /// in a single pass for a given sequence of numeric data. + /// + /// + /// This function reads the sequence one item at a time (via its enumerator), + /// applying Welford's online update formula. It is generic over any numeric + /// type 'T that supports F# inlined arithmetic. + /// + /// A sequence of numeric data. + /// + /// A SummaryStats record containing the final count, mean, sum of squares, min, and max. + let inline ofSeq (items: seq<'T>) = + use e = items.GetEnumerator() + let zero = LanguagePrimitives.GenericZero<'T> + let one = LanguagePrimitives.GenericOne<'T> + + // Recursive loop for Welford’s algorithm + let rec loop n currentMin currentMax mean m2 = + match e.MoveNext() with + | true -> + let x = e.Current + // "delta" is how far the new value is from the old mean + let delta = x - mean + // n+1 is the new total number of data points + let n' = n + one + let mean' = mean + delta / n' + // Welford’s M2 update -> (M2) is the sum of squares of the differences from the mean + let m2' = m2 + delta * (x - mean') + loop n' (min x currentMin) (max x currentMax) mean' m2' + | false -> + // At the end, n is the total count of items, + // mean is the final mean, M2 is the sum of squared deviations, etc. + createSummaryStats n mean m2 currentMin currentMax + + // Pull the first item out before starting the loop. + match e.MoveNext() with + | true -> + let firstVal = e.Current + // n = 1, mean = firstVal, M2 = 0, min = max = firstVal + loop one firstVal firstVal firstVal zero + | false -> + // No data --> return "empty" stats + let nan = zero / zero + createSummaryStats zero nan nan nan nan + + + /// + /// Computes Welford-based summary statistics (count, mean, sum of squares, min, max) + /// in a single pass for a given array of numeric data. + /// + /// + /// This function iterates over the array exactly once. It is generic over any + /// numeric type 'T that supports F# inlined arithmetic. + /// + /// An array of numeric data. + /// + /// A SummaryStats record containing the final count, mean, sum of squares, min, and max. + /// + let inline ofArray (arr: 'T[]) = + // We'll need zero, one, etc. from generic operators: + let zero = LanguagePrimitives.GenericZero<'T> + let one = LanguagePrimitives.GenericOne<'T> + + // Define a "generic NaN" to handle empty arrays: + let uNan = zero / zero + + match arr.Length with + | 0 -> + // No elements, produce an all-NaN stats + createSummaryStats zero uNan uNan uNan uNan + + | _ -> + // Initialize with the first value + let mutable count = one + let mutable m1 = arr.[0] // mean + let mutable m2 = zero // sum of squared deviations + let mutable minVal = arr.[0] + let mutable maxVal = arr.[0] + + // Process the rest of the array + for i in 1 .. arr.Length - 1 do + + let x = arr.[i] + // "delta" is how far the new value is from the old mean + let delta = x - m1 + // n+1 is the new total number of data points + let n' = count + one + let mean' = m1 + delta / n' + // Welford’s M2 update -> (M2) is the sum of squares of the differences from the mean + let m2' = m2 + delta * (x - mean') + + // Update rolling state + count <- n' + m1 <- mean' + m2 <- m2' + + // Track min/max + if x < minVal then minVal <- x + if x > maxVal then maxVal <- x + + createSummaryStats count m1 m2 minVal maxVal + + + + + +//module RunningStats = + +// type RunningStats<'T> = { +// N : int +// M1 : 'T +// M2 : 'T +// M3 : 'T +// M4 : 'T +// } + +// let createRunningStats n m1 m2 m3 m4 = +// {N=n;M1=m1;M2=m2;M3=m3;M4=m4} + +// //let inline combine (a:RunningStats<'T>) (b:RunningStats<'T>) = + +// // let (..*) n a = Ops.multByInt32 a n + +// // let cn = a.N + b.N +// // let delta = b.M1 - a.M1 +// // let delta2 = delta * delta +// // let delta3 = delta * delta2 +// // let delta4 = delta2 * delta2 + +// // let cM1 = LanguagePrimitives.DivideByInt<'T> ( (Ops.multByInt32 a.M1 a.N ) + (Ops.multByInt32 b.M1 b.N)) cn +// // let cM2 = LanguagePrimitives.DivideByInt<'T> (Ops.multByInt32 (a.M2 + b.M2 + delta2) (a.N * b.N)) cn +// // let cM3 = +// // let tmp = LanguagePrimitives.DivideByInt<'T> (Ops.multByInt32 (a.M3 + b.M3 + delta3) (a.N * b.N * (a.N - b.N))) (cn * cn) +// // tmp + LanguagePrimitives.DivideByInt<'T> ((Ops.multByInt32 delta 3) * (Ops.multByInt32 b.M2 a.N) - (Ops.multByInt32 a.M2 b.N)) cn +// // let cM4 = +// // let tmp = LanguagePrimitives.DivideByInt<'T> (Ops.multByInt32 (Ops.multByInt32 (a.M4 + b.M4 + delta4) (a.N*b.N)) (a.N*a.N - a.N*b.N + b.N*b.N)) (cn * cn * cn) +// // //let tmp2 = LanguagePrimitives.DivideByInt<'T> ((Ops.multByInt32 delta2 6) * ((Ops.multByInt32 b.M2 (a.N * a.N)) + (Ops.multByInt32 a.M2 (b.N * b.N)))) (cn*cn) +// // tmp + (LanguagePrimitives.DivideByInt<'T> (6 ..* delta2 * ( (a.N * a.N) ..* b.M2 + (b.N * b.N) ..* a.M2)) (cn*cn)) + LanguagePrimitives.DivideByInt<'T> (4 ..* delta * (a.N ..* b.M3 - b.N ..* a.M3)) cn + +// // createRunningStats cn cM1 cM2 cM3 cM4 + + + + +// let inline mean rStats = +// rStats.M1 +// /// +// let inline varPopulation rStats = +// LanguagePrimitives.DivideByInt rStats.M2 rStats.N +// /// +// let inline var (rStats:RunningStats<'T>) = +// LanguagePrimitives.DivideByInt rStats.M2 (rStats.N-1) +// /// +// let inline stDev (rStats:RunningStats<'T>) = +// sqrt (var rStats) +// /// +// let inline stDevPopulation (rStats:RunningStats<'T>) = +// sqrt (varPopulation rStats) + +//// ///Skewness +//// let inline skewness (rStats:RunningStats<'T>) = +//// sqrt(double(n)) * M3/ pown(M2, 1.5) +//// sqrt (varPopulation rStats) + +// /// Kurtosis +//// let inline kurtosis (rStats:RunningStats<'T>) = +//// let one = LanguagePrimitives.GenericOne< 'T > +//// let tmp = Ops.multByInt32 rStats.M4 rStats.N +//// tmp / (rStats.M2 * rStats.M2) - (one + one + one) + + + +//// let inline ofSeq (items:seq<'T>) : RunningStats< 'U > = +//// use e = items.GetEnumerator() +//// let zero = LanguagePrimitives.GenericZero< 'U > +//// //let one = LanguagePrimitives.GenericOne< 'U > + +//// let rec loop n (m1:'U) (m2:'U) (m3:'U) (m4:'U) = +//// match e.MoveNext() with +//// | true -> +//// let n' = n + 1 +//// let delta = e.Current - m1 +//// let delta_n = LanguagePrimitives.DivideByInt< 'U > delta n +//// let delta_n2 = delta_n * delta_n +//// let term1 = Ops.multByInt32 (delta * delta_n) n' +//// let m1' = m1 + delta_n +//// let m4' = m4 + (Ops.multByInt32 (term1 * delta_n2) (n'*n' - 3*n' + 3)) + (Ops.multByInt32 (delta_n2 * m2) 6) - (Ops.multByInt32 (delta_n * m3) 4) +//// let m3' = m3 + (Ops.multByInt32 (term1 * m2) (n' - 2)) - (Ops.multByInt32 (delta_n * m2) 3 ) +////// let m4' = m4 + (term1 * delta_n2 * (n'*n' - 3*n' + 3) + 6 * delta_n2 * m2 - 4 * delta_n * m3) +////// let m3' = m3 + (term1 * delta_n * (n' - 2) - 3 * delta_n * m2) +//// let m2' = term1 + +//// loop (n + 1) m1' m2' m3' m4' +//// | false -> +//// if (n > 1) then +//// createRunningStats n m1 m2 m3 m4 +//// else +//// let nanU = zero / zero +//// createRunningStats n nanU nanU nanU nanU +//// loop 0 zero zero zero zero + + diff --git a/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj b/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj index d469885ab..f25262a84 100644 --- a/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj +++ b/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj @@ -21,6 +21,14 @@ + + + + + + + + diff --git a/tests/FSharp.Stats.Tests/Interpolation.fs b/tests/FSharp.Stats.Tests/Interpolation.fs index 486acb157..e97496a99 100644 --- a/tests/FSharp.Stats.Tests/Interpolation.fs +++ b/tests/FSharp.Stats.Tests/Interpolation.fs @@ -21,7 +21,7 @@ let cubicInterpolationTests = //https://columbiaeconomics.com/2010/01/20/how-economists-convert-quarterly-data-into-monthly-cubic-spline-interpolation/comment-page-1/ let coefficientsSpline = CubicSpline.interpolate CubicSpline.Natural t y - let fitOutPut = tt |> Vector.map (CubicSpline.predict coefficientsSpline) + let fitOutPut = tt |> Array.map (CubicSpline.predict coefficientsSpline) let expectedValues = vector [187.6; 186.4328125; 185.5425; 185.2059375; 185.7; 187.179375;189.31; 191.635625; 193.7; 195.1528125; 196.0675; 196.6234375;197.0] TestExtensions.sequenceEqual Accuracy.low expectedValues fitOutPut "Fitted Values and Expected Output should be equal (double precision)" @@ -43,7 +43,7 @@ let cubicInterpolationTests = CubicSpline.predict coeffParabolic x let genrateX = vector [20.0..25.0] - let interpParabolic = genrateX |> Vector.map fittingFuncParabolic + let interpParabolic = genrateX |> Array.map fittingFuncParabolic let parabolicSndDeriv x = CubicSpline.getSecondDerivative coeffParabolic x Expect.floatClose Accuracy.high (parabolicSndDeriv interpParabolic.[0]) (parabolicSndDeriv interpParabolic.[1]) "the second derivative at the first and second points should be equal (double precision)" @@ -101,7 +101,7 @@ let BezierInterpolationTests = let p1 = vector [|3.;2.;0.|] //point 1 that should be traversed let data = [|p0;p1|] let interpolate = Bezier.interpolate data - let expectedMiddle = p0 + 0.5 * (p1 - p0) + let expectedMiddle = p0 .+ 0.5 .* (p1 .- p0) TestExtensions.sequenceEqual(Accuracy.high) (interpolate 0.) p0 "Initial point should be equal (double precision)" TestExtensions.sequenceEqual(Accuracy.high) (interpolate 0.5) expectedMiddle "Middle point should be equal (double precision)" TestExtensions.sequenceEqual(Accuracy.high) (interpolate 1.) p1 "Final point should be equal (double precision)" @@ -112,9 +112,9 @@ let BezierInterpolationTests = let p1 = vector [|3.;2.;0.|] //point 1 that should be traversed let data = [|p0;c0;p1|] let interpolate = Bezier.interpolate data - let a = p0 + 0.5 * (c0 - p0) - let b = c0 + 0.5 * (p1 - c0) - let expectedMiddle = a + 0.5 * (b - a) + let a = p0 .+ 0.5 .* (c0 .- p0) + let b = c0 .+ 0.5 .* (p1 .- c0) + let expectedMiddle = a .+ 0.5 .* (b .- a) TestExtensions.sequenceEqual(Accuracy.high) (interpolate 0.) p0 "Initial point should be equal (double precision)" TestExtensions.sequenceEqual(Accuracy.high) (interpolate 0.5) expectedMiddle "Middle point should be equal (double precision)" TestExtensions.sequenceEqual(Accuracy.high) (interpolate 1.) p1 "Final point should be equal (double precision)" @@ -126,12 +126,12 @@ let BezierInterpolationTests = let p1 = vector [|3.;2.;0.|] //point 1 that should be traversed let data = [|p0;c0;c1;p1|] let interpolate = Bezier.interpolate data - let a = p0 + 0.5 * (c0 - p0) - let b = c0 + 0.5 * (c1 - c0) - let c = c1 + 0.5 * (p1 - c1) - let d = a + 0.5 * (b - a) - let e = b + 0.5 * (c - b) - let expectedMiddle = d + 0.5 * (e - d) + let a = p0 .+ 0.5 .* (c0 .- p0) + let b = c0 .+ 0.5 .* (c1 .- c0) + let c = c1 .+ 0.5 .* (p1 .- c1) + let d = a .+ 0.5 .* (b .- a) + let e = b .+ 0.5 .* (c .- b) + let expectedMiddle = d .+ 0.5 .* (e .- d) TestExtensions.sequenceEqual(Accuracy.high) (interpolate 0.) p0 "Initial point should be equal (double precision)" TestExtensions.sequenceEqual(Accuracy.high) (interpolate 0.5) expectedMiddle "Middle point should be equal (double precision)" TestExtensions.sequenceEqual(Accuracy.high) (interpolate 1.) p1 "Final point should be equal (double precision)" diff --git a/tests/FSharp.Stats.Tests/LinAlgebra.fs b/tests/FSharp.Stats.Tests/LinAlgebra.fs new file mode 100644 index 000000000..dc3dc3024 --- /dev/null +++ b/tests/FSharp.Stats.Tests/LinAlgebra.fs @@ -0,0 +1,529 @@ +module LinAlgebraTests + +open Expecto +open System +open FSharp.Stats +open FSharp.Stats.Algebra + +[] +let linearAlgebraTests = + testList "LinearAlgebra Tests" [ + + // ---------------------------------------------------------------------- + // Basic tests + // ---------------------------------------------------------------------- + + testCase "subScaledRowInPlace: subtract scaled portion of source row from destination row" <| fun _ -> + let dst = [|10.0; 20.0; 30.0|] + let src = [|1.0 ; 2.0 ; 3.0 |] + LinearAlgebra.subScaledRowInPlace 2.0 0 0 3 dst src + let expected = [|8.0; 16.0; 24.0|] + Expect.equal dst expected "dst should be updated correctly" + + testCase "householderTransform: returns a Householder vector for column i" <| fun _ -> + let matData = [| 1.0; 2.0; 3.0 + 4.0; 5.0; 6.0 + 7.0; 8.0; 9.0 |] + let A = Matrix(3, 3, matData) + let v = LinearAlgebra.householderTransform A 1 + Expect.equal v.Length 3 "Householder vector should have 3 elements" + Expect.isFalse (Double.IsNaN v.[1]) "v.[1] should not be NaN" + + testCase "qrModifiedGramSchmidt: Q*R reconstructs A (2x2 example)" <| fun _ -> + let A = Matrix(2, 2, [|1.0; 2.0; 3.0; 4.0|]) + let Q, R = LinearAlgebra.qrModifiedGramSchmidt A + // Multiply Q*R => 2x2 => compare with A + let APrime = Array.zeroCreate 4 + for i in 0..1 do + for j in 0..1 do + let mutable sum = 0.0 + for k in 0..1 do + sum <- sum + Q.[i,k] * R.[k,j] + APrime.[i*2 + j] <- sum + for idx in 0..3 do + Expect.floatClose Accuracy.high A.Data.[idx] APrime.[idx] + $"A' and A differ at idx={idx}" + + testCase "backSubstitute: solves R*x=y for x, R upper-triangular" <| fun _ -> + // R = [2,3; 0,4], y = [8,12] => x= [-0.5,3] + let R = Matrix(2, 2, [|2.0;3.0; 0.0;4.0|]) + let y = [|8.0;12.0|] + let x = LinearAlgebra.backSubstitute R y + let expected = [|-0.5;3.0|] + Expect.floatClose Accuracy.high expected.[0] x.[0] "x0 mismatch" + Expect.floatClose Accuracy.high expected.[1] x.[1] "x1 mismatch" + + testCase "solveLinearQR: solves A*x=b (2x2 system)" <| fun _ -> + // A= [1,2; 3,4], b= [5,11] => x= [1,2] + let A = Matrix(2,2,[|1.;2.;3.;4.|]) + let b = [|5.; 11.|] + let x = LinearAlgebra.solveLinearQR A b + let expected = [|1.;2.|] + Expect.floatClose Accuracy.high expected.[0] x.[0] "x[0] mismatch" + Expect.floatClose Accuracy.high expected.[1] x.[1] "x[1] mismatch" + + + // ====================================================================== + // EDGE CASES: Infinity, -Infinity, NaN + // ====================================================================== + testList "Edge Cases with Infinity, -Infinity, NaN" [ + + testCase "subScaledRowInPlace with scaleVal = +∞" <| fun _ -> + // Let dst[0] = +∞, and scaleVal= +∞. Then dst[0] = ∞ - ∞*something => usually NaN + // Also check second entry for leftover infinite results. + let dst = [| Double.PositiveInfinity; 10.0 |] + let src = [| 2.0; 1.0 |] + LinearAlgebra.subScaledRowInPlace Double.PositiveInfinity 0 0 2 dst src + // The math: + // dst[0] <- ∞ - (∞ * 2) => ∞ - ∞ => NaN + // dst[1] <- 10 - (∞ * 1) => 10 - ∞ => -∞ + Expect.isTrue (Double.IsNaN dst.[0]) "Expected NaN in dst.[0]" + Expect.isTrue (Double.IsNegativeInfinity dst.[1]) "Expected -∞ in dst.[1]" + + testCase "householderTransform with NaN in matrix" <| fun _ -> + // Insert a NaN into the matrix + let matData = [| 1.0; Double.NaN; 3.0 + 4.0; 5.0; 6.0 |] + // 2x3 matrix + let A = Matrix(2, 3, matData) + let v = LinearAlgebra.householderTransform A 1 + // It's likely that the result will incorporate NaN somewhere (since row #1 has NaN). + // We'll confirm that it yields at least one NaN. + let hasNaN = v |> Array.exists Double.IsNaN + Expect.isTrue hasNaN "Expected Householder vector to contain NaN" + + testCase "backSubstitute with 0.0 on R-diagonal => Infinity result" <| fun _ -> + // R = [ [2., 1.], + // [0., 0.] ] => zero on diagonal => x.[1] => y.[1] / 0 => ∞ or NaN + let rData = [|2.;1.; 0.;0.|] + let R = Matrix(2,2,rData) + let y = [|5.0; 3.0|] + // This might yield x.[1] = 3.0 / 0 => +∞ (or possibly throw). + // If your code doesn't throw, let's see if it yields Infinity: + let x = LinearAlgebra.backSubstitute R y + // We'll check x.[1] + Expect.isTrue (Double.IsInfinity x.[1] || Double.IsNaN x.[1]) + "Expected Infinity or NaN for x.[1]" + + testCase "solveLinearQR with b containing ∞" <| fun _ -> + // 2x2 matrix A => [1,2; 3,4], b => [∞, 1] + // The solution might be ∞ or NaN, or the factorization might produce weird results. + let A = Matrix(2,2,[|1.;2.;3.;4.|]) + let b = [|Double.PositiveInfinity; 1.0|] + // We'll see if it returns a vector with ∞ or NaN, or possibly throws. + // We'll not test for a "correct" solution in the usual sense, only that it yields a result. + let x = LinearAlgebra.solveLinearQR A b + // We expect at least one ∞ or NaN in the solution: + let hasSpecial = x |> Array.exists (fun v -> Double.IsNaN(v) || Double.IsInfinity(v)) + Expect.isTrue hasSpecial "Expected ∞ or NaN in the solution" + ] + + testList "Extended LinearAlgebra Tests" [ + + // ===================================================================== + // solveLinearQR + // ===================================================================== + testCase "solveLinearQR: throws if b's length doesn't match A's row count" <| fun _ -> + // A is 2x2, but b has length=3 => mismatch + let A = Matrix(2, 2, [|1.0;2.0; 3.0;4.0|]) + let b = [|1.0; 2.0; 3.0|] // length=3 + Expect.throwsT (fun () -> + let _ = LinearAlgebra.solveLinearQR A b + () + ) "Should throw if A.NumRows != b.Length" + + testCase "solveLinearQR: solves small 3x3 system" <| fun _ -> + // We'll define a 3x3 with an easy integer solution. + // + // A*x = b + // A = [ [1.,2.,0.] + // [2.,1.,1.] + // [0.,1.,2.] ] + // + // We'll pick x => [1., 2., 3.] => let's compute b => A*x by hand: + // row0 => 1*1 +2*2 +0*3 = 5 + // row1 => 2*1 +1*2 +1*3 = 2 +2 +3=7 + // row2 => 0*1 +1*2 +2*3 = 2 +6=8 + // => b= [5,7,8] + let Adata = [| + 1.0; 2.0; 0.0 + 2.0; 1.0; 1.0 + 0.0; 1.0; 2.0 |] // row-major flatten + let A = Matrix(3, 3, Adata) + let b = [|5.0; 7.0; 8.0|] + + let x = LinearAlgebra.solveLinearQR A b + // Expect x= [1,2,3] + let expected = [|1.0; 2.0; 3.0|] + for i in 0..2 do + Expect.floatClose Accuracy.high expected.[i] x.[i] $"x[{i}] mismatch" + + // ===================================================================== + // solveTriangularLinearSystems + // ===================================================================== + testCase "solveTriangularLinearSystems: throws if shape mismatch" <| fun _ -> + // K must be square NxN, B must have Nx? shape + // We'll define a 2x2 K, and B as 3x2 => mismatch + let K = Matrix(2, 2, [|2.0;0.0; 1.0;2.0|]) // just a 2x2 + let B = Matrix(3, 2, [|1.0;2.0; 3.0;4.0; 5.0;6.0|]) // 3x2 + Expect.throwsT (fun () -> + let _ = LinearAlgebra.solveTriangularLinearSystems K B true + () + ) "Should throw on dimension mismatch" + + testCase "solveTriangularLinearSystems: lower-triangular forward substitution (2x2, 2 columns)" <| fun _ -> + // K= L= [ [2,0], + // [1,2] ] + // K is 2x2, B is 2x2 + // We'll pick B so that K*X = B has a known solution X. + // + // Suppose X => [ [1., 10.], + // [2., 4.] ] + // Then K*X => B + // B row0 => row0*K => [2*1 +0*2, 2*10 +0*4] => [2,20] + // B row1 => row1*K => [1*1 +2*2, 1*10 +2*4] => [1+4=5, 10+8=18] + // Wait, careful with row-major. Actually, let's do it systematically: + // If K is NxN, X is NxM => B is NxM + // B[i,*] = sum_{j} (K[i,j] * X[j,*]) (like matrix multiply) + // + // For K= [ [2,0], [1,2] ], X= [ [1,10],[2,4] ] + // Flatten X => row0= (1,10), row1= (2,4) + // B[0,*] => K[0,0]*X[0,*] + K[0,1]*X[1,*] + // => 2*(1,10) + 0*(2,4) => (2,20) + // B[1,*] => K[1,0]*X[0,*] + K[1,1]*X[1,*] + // => 1*(1,10)+2*(2,4) => (1+4, 10+8)= (5,18) + // => B= [ (2,20),(5,18) ] + let Kdata = [| 2.0; 0.0 + 1.0; 2.0 |] + let X_expected_data = [| 1.0; 10.0 + 2.0; 4.0 |] + let B_data = [| 2.0; 20.0 + 5.0; 18.0 |] + let Kmat = Matrix(2,2,Kdata) + let Bmat = Matrix(2,2,B_data) + // We want to solve K*X = B for X. isLower=true => forward substitution + let Xsol = LinearAlgebra.solveTriangularLinearSystems Kmat Bmat true + // Check that Xsol matches X_expected + for i in 0..3 do + Expect.floatClose Accuracy.high X_expected_data.[i] Xsol.Data.[i] $"X mismatch at idx={i}" + + testCase "solveTriangularLinearSystems: upper-triangular backward substitution (2x2, 2 columns)" <| fun _ -> + // Let K= U= [ [2,3], [0,4] ] + // We'll define X => [ [1,10],[2,4] ] + // Then B= K*X => 2x2 + // Let's compute B carefully: + // B row0 => K[0,0]*X[0,*] + K[0,1]*X[1,*] => 2*(1,10)+3*(2,4) => (2+6,20+12)= (8,32) + // B row1 => K[1,0]*X[0,*] + K[1,1]*X[1,*] => 0*(1,10)+4*(2,4) => (8,16) + // => B= [ (8,32),(8,16) ] + let Kdata = [|2.0;3.0; 0.0;4.0|] // 2x2 upper + let X_expected_data = [| 1.0; 10.0 + 2.0; 4.0 |] // shape=2x2 + let B_data = [| 8.0; 32.0 + 8.0; 16.0 |] + let Kmat = Matrix(2,2,Kdata) + let Bmat = Matrix(2,2,B_data) + let Xsol = LinearAlgebra.solveTriangularLinearSystems Kmat Bmat false // isLower=false => backward sub + for i in 0..3 do + Expect.floatClose Accuracy.high X_expected_data.[i] Xsol.Data.[i] $"X mismatch at idx={i}" + + // ===================================================================== + // solveTriangularLinearSystem + // ===================================================================== + testCase "solveTriangularLinearSystem: dimension mismatch => throws" <| fun _ -> + // K=2x2, v= length=3 => mismatch + let K = Matrix(2,2,[|2.0;0.0; 1.0;2.0|]) + let v = [|1.0;2.0;3.0|] + Expect.throwsT (fun () -> + let _ = LinearAlgebra.solveTriangularLinearSystem K v true + () + ) "Should throw dimension mismatch" + + testCase "solveTriangularLinearSystem: lower triangular forward substitution (2x2 single system)" <| fun _ -> + // K= L= [ [2,0],[1,2] ] + // We'll define a single x => [1,2], compute b => K*x, then see if we get x back. + // + // For x => [1.,2.], + // B row0 => 2*1 +0*2=2 + // B row1 => 1*1 +2*2=1+4=5 + // => b= [2,5] + let Kdata = [|2.0;0.0; 1.0;2.0|] + let Kmat = Matrix(2,2,Kdata) + let xExpected = [|1.0;2.0|] + let b = [|2.0;5.0|] + // Solve K*x=b + let xSol = LinearAlgebra.solveTriangularLinearSystem Kmat b true + Expect.floatClose Accuracy.high xExpected.[0] xSol.[0] "x[0] mismatch" + Expect.floatClose Accuracy.high xExpected.[1] xSol.[1] "x[1] mismatch" + + testCase "solveTriangularLinearSystem: upper triangular backward substitution (2x2 single system)" <| fun _ -> + // K= U= [ [2,3],[0,4] ] + // Let x => [1,2]. Then b => K*x => + // row0 => 2*1 +3*2=2+6=8 + // row1 => 0*1 +4*2=8 + // => b= [8,8] + let Kdata = [|2.0;3.0; 0.0;4.0|] + let Kmat = Matrix(2,2,Kdata) + let xExpected = [|1.0;2.0|] + let b = [|8.0;8.0|] + let xSol = LinearAlgebra.solveTriangularLinearSystem Kmat b false + Expect.floatClose Accuracy.high xExpected.[0] xSol.[0] "x[0] mismatch" + Expect.floatClose Accuracy.high xExpected.[1] xSol.[1] "x[1] mismatch" + + ] + + testList "Additional Linear Algebra Tests" [ + + // ===================================================================== + // 1) qrDecompose + // ===================================================================== + testCase "qrDecompose: Q*R ~ A for a small 3x2" <| fun _ -> + // A=3x2 => [ [1.,2.],[3.,4.],[5.,6.] ] + let Adata = [|1.;2.; 3.;4.; 5.;6.|] + let A = Matrix(3, 2, Adata) + + let Q, R = LinearAlgebra.qrDecompose A + // Q is 3x3 in the code above since we use the identity(3) initially, + // but only the first 2 columns or some partial region might be relevant. + // We'll do a truncated multiply to compare or do a naive Q*R if R is 3x2. + + // Let's do a direct approach: A' = Q * R (both are 3x2 effectively, if R is 3x2). + // If R is the same shape as A, it's 3x2 => multiply 3x3 * 3x2 isn't well-defined. + // But the code as posted doesn't necessarily do the typical Householder approach + // that modifies R to upper triangular shape. It's more of a placeholder. + // We'll do a "Compare shape" approach, then do a partial multiply in any case. + + let APrimeData = Array.zeroCreate (3*2) + // We'll assume R is 3x2. Then Q is 3x3 => Q(3x3)*R(3x2)= A'(3x2). + for i in 0..2 do + for j in 0..1 do + let mutable sum = 0.0 + for k in 0..2 do + sum <- sum + Q.[i,k] * R.[k,j] + APrimeData.[i*2 + j] <- sum + + // Compare A' with A + for idx in 0..5 do + Expect.floatClose Accuracy.high Adata.[idx] APrimeData.[idx] + $"A' vs A mismatch at idx={idx}" + + // ===================================================================== + // 2) leastSquares + // ===================================================================== + testCase "leastSquares: overdetermined system 3x2" <| fun _ -> + // We'll create a design matrix A=3x2, b=3 + // A= [ [1.,2.], + // [2.,1.], + // [3.,4.] ] + // b= [ [8.],[10.],[19.] ] + // We want to solve min ||A x - b||^2 for x in R^2. + // We'll pick a small example and do a naive check or compare with a known solution if possible. + + let Adata = [|1.;2.; 2.;1.; 3.;4.|] + let A = Matrix(3, 2, Adata) + let b = [|8.; 10.; 19.|] + + let x = LinearAlgebra.leastSquares A b + // We only do a round-trip check: A*x ~ b in least-squares sense. + // We'll compute A*x (3x2 * 2 => 3) and see if that is close to b. + let Ax = + let result = Array.zeroCreate 3 + for i in 0..2 do + // row i => i*2, dot with x + let rowOffset = i*2 + result.[i] <- Adata.[rowOffset]*x.[0] + Adata.[rowOffset+1]*x.[1] + result + + // Compare Ax to b + for i in 0..2 do + // Because it's least squares, we might not get an exact match if system is not exactly consistent. + // But let's see if it's close. + Expect.floatClose Accuracy.high b.[i] Ax.[i] $"A*x mismatch at row {i}" + + // ===================================================================== + // 3) cholesky + // ===================================================================== + testCase "cholesky: factor a positive-definite 3x3" <| fun _ -> + // We'll define A => 3x3 symmetric positive definite. + // E.g. A= [ [4, 12, -16], + // [12,37, -43], + // [-16, -43, 98] ] + // Classic example => L => [ [2,0,0], [6,1,0], [-8,5,3] ] + let Adata = [| + 4.0; 12.0; -16.0; + 12.0; 37.0; -43.0; + -16.0; -43.0; 98.0; |] + let A = Matrix(3,3,Adata) + let L = LinearAlgebra.cholesky A + // Compare with known L + let Lexpected = [| 2.0; 0.0; 0.0; + 6.0; 1.0; 0.0; + -8.0; 5.0; 3.0; |] + for i in 0..8 do + Expect.floatClose Accuracy.high Lexpected.[i] L.Data.[i] $"L mismatch at idx {i}" + + testCase "cholesky: throws if matrix is not square" <| fun _ -> + let nonsquare = Matrix(2,3, [|1.0;2.0;3.0;4.0;5.0;6.0|]) + Expect.throwsT (fun () -> + let _ = LinearAlgebra.cholesky nonsquare + () + ) "Should throw if not square" + + // ===================================================================== + // 4) leastSquaresCholesky + // ===================================================================== + testCase "leastSquaresCholesky: small example" <| fun _ -> + // We'll do the same design matrix from earlier, which is 3x2, and b= length=3. + let Adata = [|1.;2.; 2.;1.; 3.;4.|] + let A = Matrix(3, 2, Adata) + let b = [|8.; 10.; 19.|] + + let x = LinearAlgebra.leastSquaresCholesky A b + // We'll do the same "A*x ~ b" check as above + let Ax = + let result = Array.zeroCreate 3 + for i in 0..2 do + let rowOffset = i*2 + result.[i] <- Adata.[rowOffset]*x.[0] + Adata.[rowOffset+1]*x.[1] + result + for i in 0..2 do + Expect.floatClose Accuracy.high b.[i] Ax.[i] $"A*x mismatch at row {i}" + + // ===================================================================== + // 5a) hatMatrix + // ===================================================================== + testCase "hatMatrix: check if H = Q1 Q1^T for a small design matrix" <| fun _ -> + // We'll do design=3x2 => same as above + let Adata = [|1.;2.; 2.;1.; 3.;4.|] + let A = Matrix(3, 2, Adata) + let H = LinearAlgebra.hatMatrix A + // We expect H to be 3x3. We can do a partial check: + // H ~ Q1 Q1^T, where Q1 is from the Householder-based QR in the code. + // We'll check shape => should be 3x3, plus we can check if H^2=H (idempotent property). + Expect.equal (H.NumRows, H.NumCols) (3,3) "Hat matrix is 3x3" + + // Quick idempotence test: H^2 ~ H + let H2data = Array.zeroCreate (3*3) + for i in 0..2 do + for j in 0..2 do + let mutable sum = 0.0 + for k in 0..2 do + sum <- sum + H.[i,k] * H.[k,j] + H2data.[i*3 + j] <- sum + + for idx in 0..8 do + Expect.floatClose Accuracy.high H.Data.[idx] H2data.[idx] $"Hat matrix not idempotent at idx={idx}" + + // ===================================================================== + // 5b) leverageBy and leverage + // ===================================================================== + testCase "leverageBy: diagonal of H" <| fun _ -> + // We'll reuse the hat matrix from above, check if leverageBy returns the diagonal + let Adata = [|1.;2.; 2.;1.; 3.;4.|] + let A = Matrix(3, 2, Adata) + let H = LinearAlgebra.hatMatrix A + let diag = LinearAlgebra.leverageBy H + // Compare with Matrix.getDiagonal + let diag2 = Matrix.getDiagonal H + Expect.equal diag diag2 "Expected same diagonal from leverageBy" + + testCase "leverage: direct Q approach" <| fun _ -> + // We'll see if leverage designMatrix ~ diagonal of H + let Adata = [|1.;2.; 2.;1.; 3.;4.|] + let A = Matrix(3, 2, Adata) + // direct approach => Q1 from qrDecompose + let directLever = LinearAlgebra.leverage A + // The same as leverageBy (hatMatrix's diagonal) + let H = LinearAlgebra.hatMatrix A + let diagH = Matrix.getDiagonal H + Expect.equal directLever diagH "Leverage mismatch" + + // ===================================================================== + // 6) luDecompose + // ===================================================================== + testCase "luDecompose: pivot array, L and U multiply back to P*A" <| fun _ -> + // A= 3x3 => we'll pick something that requires row swaps + // A= [ [0,2,1],[3,4,5],[1,2,3] ] + let Adata = [|0.;2.;1.; 3.;4.;5.; 1.;2.;3.|] + let A = Matrix(3,3,Adata) + let (P, L, U) = LinearAlgebra.luDecompose A + // Check dimension => L, U => 3x3, P => perm array + Expect.equal (L.NumRows, L.NumCols) (3,3) "L shape" + Expect.equal (U.NumRows, U.NumCols) (3,3) "U shape" + + // We'll see if P*A= L*U + // 1) build PA => permute rows of A by P => do a naive approach or if you have a function + let PA = Matrix.permuteRowsBy P A + // 2) multiply L,U => LU + let LUdata = Array.zeroCreate (3*3) + for i in 0..2 do + for j in 0..2 do + let mutable sum = 0.0 + for k in 0..2 do + sum <- sum + L.[i,k]*U.[k,j] + LUdata.[i*3 + j] <- sum + + // Compare LU vs PA + for idx in 0..8 do + Expect.floatClose Accuracy.high PA.Data.[idx] LUdata.[idx] $"LU mismatch at idx={idx}" + + // ===================================================================== + // 7) solveLinearSystems + // ===================================================================== + testCase "solveLinearSystems: A is 2x2, B=2x2" <| fun _ -> + // We'll define A => [ [2,3],[1,2] ], + // B => 2x2 => pick X => 2x2 => solve => see if we get X + // X => [ [1,10],[2,4] ] => B= A*X => let's do the multiply: + // row0 => (2,3)*X => 2*(1,10)+3*(2,4)= (2+6,20+12)= (8,32) + // row1 => (1,2)*X => 1*(1,10)+2*(2,4)= (1+4,10+8)= (5,18) + // => B => [ (8,32),(5,18) ] + let Adata = [|2.;3.; 1.;2.|] + let Bdata = [|8.;32.; 5.;18.|] + let A = Matrix(2,2,Adata) + let B = Matrix(2,2,Bdata) + let Xsol = LinearAlgebra.solveLinearSystems A B + let Xexpected = [|1.;10.; 2.;4.|] + for i in 0..3 do + Expect.floatClose Accuracy.high Xexpected.[i] Xsol.Data.[i] $"X mismatch at idx={i}" + + // ===================================================================== + // 8) solveLinearSystem + // ===================================================================== + testCase "solveLinearSystem: 3x3 single system" <| fun _ -> + // A => [ [0,2,1],[3,4,5],[1,2,3] ] from above, b => let's pick x => [1,2,3], compute b => A*x + // row0 => 0*1 +2*2 +1*3= 4+3=7 + // row1 => 3*1 +4*2 +5*3= 3+8+15=26 + // row2 => 1*1 +2*2 +3*3= 1+4+9=14 + let Adata = [|0.;2.;1.; 3.;4.;5.; 1.;2.;3.|] + let A = Matrix(3,3,Adata) + let b = [|7.;26.;14.|] + let xSol = LinearAlgebra.solveLinearSystem A b + let expected = [|1.;2.;3.|] + for i in 0..2 do + Expect.floatClose Accuracy.high expected.[i] xSol.[i] $"x mismatch at {i}" + + // ===================================================================== + // 9) inverse + // ===================================================================== + testCase "inverse: 2x2 inverse" <| fun _ -> + // A => [ [1,2],[3,4] ], inverse => [ [-2,1],[1.5, -0.5] ] + // because 1*4 -2*3= (4-6)= -2 => A^-1 => 1/det * [ [4,-2],[-3,1] ] => 1/-2 => [ [-2,1],[1.5,-0.5] ] + let Adata = [|1.;2.; 3.;4.|] + let A = Matrix(2,2,Adata) + let Ainverse = LinearAlgebra.inverse A + // Compare with known + let expected = [| -2.0; 1.0; 1.5; -0.5 |] + for i in 0..3 do + Expect.floatClose Accuracy.high expected.[i] Ainverse.Data.[i] $"Inverse mismatch at idx={i}" + + testCase "inverse: dimension mismatch => throws" <| fun _ -> + let nonsquare = Matrix(2,3,[|1.;2.;3.;4.;5.;6.|]) + Expect.throwsT (fun () -> + let _ = LinearAlgebra.inverse nonsquare + () + ) "Should throw if not square" + ] + + + + + ] diff --git a/tests/FSharp.Stats.Tests/LinearAlgebra.fs b/tests/FSharp.Stats.Tests/LinearAlgebra.fs index f0a96db43..e52f3cf6e 100644 --- a/tests/FSharp.Stats.Tests/LinearAlgebra.fs +++ b/tests/FSharp.Stats.Tests/LinearAlgebra.fs @@ -29,85 +29,85 @@ let managedSVDTests = let m' = mEqualNRecov.toJaggedArray() |> Array.concat TestExtensions.sequenceEqual Accuracy.high m m' "Matrices computed by SVD did not yield the initial matrix when multiplied." - testCase "m=n Matrix: u and vt consist of unit vectors, row- and column- wise." <| fun () -> - let u,s,vt = svdManaged mEqualN - let vecNorms = - [ - u |> Matrix.mapiCols (fun _ v -> Vector.norm v) - vt|> Matrix.mapCols Vector.norm |> RowVector.toArray - u |> Matrix.mapRows (fun x -> x.Transpose |> Vector.norm) |> Vector.toArray - vt|> Matrix.mapRows (fun x -> x.Transpose |> Vector.norm) |> Vector.toArray - ] - |> Array.concat - TestExtensions.sequenceEqual Accuracy.high (Array.create vecNorms.Length 1.) vecNorms "Matrices computed by SVD did not consist of unit vectors, row- and column- wise." + //testCase "m=n Matrix: u and vt consist of unit vectors, row- and column- wise." <| fun () -> + // let u,s,vt = svdManaged mEqualN + // let vecNorms = + // [ + // u |> Matrix.mapiCols (fun _ v -> FSharp.Stats.Vector.norm v) + // vt|> Matrix.mapiCols (fun _ v -> Vector.norm v) + // u |> Matrix.mapiRows (fun _ x -> x |> Vector.norm) + // vt|> Matrix.mapiRows (fun _ x -> x |> Vector.norm) + // ] + // |> Array.concat + // TestExtensions.sequenceEqual Accuracy.high (Array.create vecNorms.Length 1.) vecNorms "Matrices computed by SVD did not consist of unit vectors, row- and column- wise." - testCase "m=n Matrix: s contains correct singular values." <| fun () -> - let s,u,vt = LinearAlgebra.SVD mEqualN - TestExtensions.sequenceEqual Accuracy.high ([|15.81461344;2.213142934|]) s "Matrices computed by SVD did not yield correct singular values." + //testCase "m=n Matrix: s contains correct singular values." <| fun () -> + // let s,u,vt = LinearAlgebra.SVD mEqualN + // TestExtensions.sequenceEqual Accuracy.high ([|15.81461344;2.213142934|]) s "Matrices computed by SVD did not yield correct singular values." - testCase "m - let u,s,vt = svdManaged mSmallerN - let mSmallernRecov = (u * s * vt) - let m = mSmallerN |> Matrix.toJaggedArray |> Array.concat - let m' = mSmallernRecov |> Matrix.toJaggedArray |> Array.concat - TestExtensions.sequenceEqual Accuracy.high m m' "Matrices computed by SVD did not yield the initial matrix when multiplied." + //testCase "m + // let u,s,vt = svdManaged mSmallerN + // let mSmallernRecov = (u * s * vt) + // let m = mSmallerN |> Matrix.toJaggedArray |> Array.concat + // let m' = mSmallernRecov |> Matrix.toJaggedArray |> Array.concat + // TestExtensions.sequenceEqual Accuracy.high m m' "Matrices computed by SVD did not yield the initial matrix when multiplied." - testCase "m - let u,s,vt = svdManaged mSmallerN - let vecNorms = - [ - u |> Matrix.mapCols Vector.norm |> RowVector.toArray - vt|> Matrix.mapCols Vector.norm |> RowVector.toArray - u |> Matrix.mapRows (fun x -> x.Transpose |> Vector.norm) |> Vector.toArray - vt|> Matrix.mapRows (fun x -> x.Transpose |> Vector.norm) |> Vector.toArray - ] - |> Array.concat - TestExtensions.sequenceEqual Accuracy.high (Array.create vecNorms.Length 1.) vecNorms "Matrices computed by SVD did not consist of unit vectors, row- and column- wise." + //testCase "m + // let u,s,vt = svdManaged mSmallerN + // let vecNorms = + // [ + // u |> Matrix.mapCols Vector.norm |> RowVector.toArray + // vt|> Matrix.mapCols Vector.norm |> RowVector.toArray + // u |> Matrix.mapRows (fun x -> x.Transpose |> Vector.norm) |> Vector.toArray + // vt|> Matrix.mapRows (fun x -> x.Transpose |> Vector.norm) |> Vector.toArray + // ] + // |> Array.concat + // TestExtensions.sequenceEqual Accuracy.high (Array.create vecNorms.Length 1.) vecNorms "Matrices computed by SVD did not consist of unit vectors, row- and column- wise." - testCase "m - let s,u,vt = LinearAlgebraManaged.SVD mSmallerN - TestExtensions.sequenceEqual Accuracy.high ([|22.51999394;6.986424855;2.00991059|]) s "Matrices computed by SVD did not yield correct singular values." + //testCase "m + // let s,u,vt = LinearAlgebra.SVD mSmallerN + // TestExtensions.sequenceEqual Accuracy.high ([|22.51999394;6.986424855;2.00991059|]) s "Matrices computed by SVD did not yield correct singular values." - testCase "m>n Matrix: Recover from decomposition" <| fun () -> - let u,s,vt = svdManaged mSmallerN.Transpose - let mSmallernRecov = (u * s * vt) - let m = mSmallerN.Transpose |> Matrix.toJaggedArray |> Array.concat - let m' = mSmallernRecov |> Matrix.toJaggedArray |> Array.concat - TestExtensions.sequenceEqual Accuracy.high m m' "Matrices computed by SVD did not yield the initial matrix when multiplied." + //testCase "m>n Matrix: Recover from decomposition" <| fun () -> + // let u,s,vt = svdManaged (mSmallerN.Transpose()) + // let mSmallernRecov = (u * s * vt) + // let m = mSmallerN.Transpose().toJaggedArray() |> Array.concat + // let m' = mSmallernRecov.toJaggedArray() |> Array.concat + // TestExtensions.sequenceEqual Accuracy.high m m' "Matrices computed by SVD did not yield the initial matrix when multiplied." - testCase "m>n Matrix: u and vt consist of unit vectors, row- and column- wise." <| fun () -> - let u,s,vt = svdManaged mSmallerN.Transpose - let vecNorms = - [ - u |> Matrix.mapCols Vector.norm |> RowVector.toArray - vt|> Matrix.mapCols Vector.norm |> RowVector.toArray - u |> Matrix.mapRows (fun x -> x.Transpose |> Vector.norm) |> Vector.toArray - vt|> Matrix.mapRows (fun x -> x.Transpose |> Vector.norm) |> Vector.toArray - ] - |> Array.concat - TestExtensions.sequenceEqual Accuracy.high (Array.create vecNorms.Length 1.) vecNorms "Matrices computed by SVD did not consist of unit vectors, row- and column- wise." + //testCase "m>n Matrix: u and vt consist of unit vectors, row- and column- wise." <| fun () -> + // let u,s,vt = svdManaged (mSmallerN.Transpose()) + // let vecNorms = + // [ + // u |> Matrix.mapCols Vector.norm |> RowVector.toArray + // vt|> Matrix.mapCols Vector.norm |> RowVector.toArray + // u |> Matrix.mapRows (fun x -> x.Transpose |> Vector.norm) |> Vector.toArray + // vt|> Matrix.mapRows (fun x -> x.Transpose |> Vector.norm) |> Vector.toArray + // ] + // |> Array.concat + // TestExtensions.sequenceEqual Accuracy.high (Array.create vecNorms.Length 1.) vecNorms "Matrices computed by SVD did not consist of unit vectors, row- and column- wise." - testCase "m>n Matrix: s contains correct singular values." <| fun () -> - let s,u,vt = LinearAlgebraManaged.SVD mSmallerN.Transpose - TestExtensions.sequenceEqual Accuracy.high ([|22.51999394;6.986424855;2.00991059|]) s "Matrices computed by SVD did not yield correct singular values." + //testCase "m>n Matrix: s contains correct singular values." <| fun () -> + // let s,u,vt = LinearAlgebra.SVD (mSmallerN.Transpose()) + // TestExtensions.sequenceEqual Accuracy.high ([|22.51999394;6.986424855;2.00991059|]) s "Matrices computed by SVD did not yield correct singular values." ] -[] -let nullspace = +//[] +//let nullspace = - let mSmallerN = Matrix.ofJaggedArray [| [|2.;-1.;2.;-1.|]; [|4.;3.;4.;3.|]; [|9.;13.;-13.;9.|]; |] +// let mSmallerN = Matrix.ofJaggedArray [| [|2.;-1.;2.;-1.|]; [|4.;3.;4.;3.|]; [|9.;13.;-13.;9.|]; |] - testList "LinearAlgebra.nullspace" [ - testCase "accuracy 1e-5" <| fun () -> - let ns = LinearAlgebra.nullspace (Accuracy=1e-5) mSmallerN - let prod = - mSmallerN * ns - |> Matrix.toJaggedSeq - |> Seq.concat - let expected = seq {0.;0.;0.;} - TestExtensions.sequenceEqual Accuracy.veryHigh expected prod "A * (nullspace A) should be matrix of zeros" - ] +// testList "LinearAlgebra.nullspace" [ +// testCase "accuracy 1e-5" <| fun () -> +// let ns = LinearAlgebra.nullspace (Accuracy=1e-5) mSmallerN +// let prod = +// mSmallerN * ns +// |> Matrix.toJaggedSeq +// |> Seq.concat +// let expected = seq {0.;0.;0.;} +// TestExtensions.sequenceEqual Accuracy.veryHigh expected prod "A * (nullspace A) should be matrix of zeros" +// ] [] let linearSystems = @@ -251,7 +251,7 @@ let linearSystems = // Tested vs R package "bdsmatrix: Routines for Block Diagonal Symmetric Matrices" Version 1.3-6 testList "SolveTriangularLinearSystems (Upper)" [ testCase "3x3 Upper Triangular Matrix with 3x3 Matrix (realistic example)" <| fun () -> - SolveTriangularLinearSystems + LinearAlgebra.solveTriangularLinearSystems ( [| [|1.;2.;3.|]; @@ -270,443 +270,298 @@ let linearSystems = ) false |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|-1.;-0.5;0.|]; [|3.;1.5;1.|]; [|1.;0.5;0.|] |] - |> Array.concat - TestExtensions.sequenceEqual Accuracy.high concatRes concatExpected "Should be 3x3 Matrix: \n-1.;-0.5;0.\n3.;1.5;1.\n1.;0.5;0." + TestExtensions.sequenceEqual Accuracy.high res.Data expected.Data "Should be 3x3 Matrix: \n-1.;-0.5;0.\n3.;1.5;1.\n1.;0.5;0." testCase "3x3 diagonal Matrix (Values = 1) with 3x3 Matrix (Values = 1)" <| fun () -> - SolveTriangularLinearSystems KDiagonal1 B1 false + LinearAlgebra.solveTriangularLinearSystems KDiagonal1 B1 false |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|1.;1.;1.|]; [|1.;1.;1.|]; [|1.;1.;1.|] |] - |> Array.concat - TestExtensions.sequenceEqual Accuracy.high concatRes concatExpected "Should be 3x3 Matrix of 1" + TestExtensions.sequenceEqual Accuracy.high res.Data expected.Data "Should be 3x3 Matrix of 1" testCase "3x3 Upper Triangular Matrix (Values = 1) with 3x3 Matrix (Values = 1)" <| fun () -> - SolveTriangularLinearSystems KUpper1 B1 false + LinearAlgebra.solveTriangularLinearSystems KUpper1 B1 false |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|0.;0.;0.|]; [|0.;0.;0.|]; [|1.;1.;1.|] |] - |> Array.concat - TestExtensions.sequenceEqual Accuracy.high concatRes concatExpected "Should be 3x3 Matrix with 1 in last row" + TestExtensions.sequenceEqual Accuracy.high res.Data expected.Data "Should be 3x3 Matrix with 1 in last row" testCase "3x3 Upper Triangular Matrix (Values = -1) with 3x3 Matrix (Values = 1)" <| fun () -> - SolveTriangularLinearSystems KUpperNeg1 B1 false + LinearAlgebra.solveTriangularLinearSystems KUpperNeg1 B1 false |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|0.;0.;0.|]; [|0.;0.;0.|]; [|-1.;-1.;-1.|] |] - |> Array.concat - TestExtensions.sequenceEqual Accuracy.high concatRes concatExpected "Should be 3x3 Matrix with 1 in last row" + TestExtensions.sequenceEqual Accuracy.high res.Data expected.Data "Should be 3x3 Matrix with 1 in last row" testCase "3x3 Upper Triangular Matrix (Values = Inf) with 3x3 Matrix (Values = 1)" <| fun () -> - SolveTriangularLinearSystems KUpperInf B1 false + LinearAlgebra.solveTriangularLinearSystems KUpperInf B1 false |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|nan;nan;nan|]; [|nan;nan;nan|]; [|0.;0.;0.|] |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix with 0 in last row and NaN in other rows" + TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix with 0 in last row and NaN in other rows" testCase "3x3 Upper Triangular Matrix (Values = -Inf) with 3x3 Matrix (Values = 1)" <| fun () -> - SolveTriangularLinearSystems KUpperNegInf B1 false + LinearAlgebra.solveTriangularLinearSystems KUpperNegInf B1 false |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|nan;nan;nan|]; [|nan;nan;nan|]; [|0.;0.;0.|] |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix with 0 in last row and NaN in other rows" + TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix with 0 in last row and NaN in other rows" testCase "3x3 Upper Triangular Matrix (Values = NaN) with 3x3 Matrix (Values = 1)" <| fun () -> - SolveTriangularLinearSystems KUpperNaN B1 false + LinearAlgebra.solveTriangularLinearSystems KUpperNaN B1 false |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|nan;nan;nan|]; [|nan;nan;nan|]; [|nan;nan;nan|] |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix of NaN" + TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix of NaN" testCase "3x3 diagonal Matrix (Values = 1) with 3x3 Matrix (Values = Inf)" <| fun () -> - SolveTriangularLinearSystems KDiagonal1 BInf false + LinearAlgebra.solveTriangularLinearSystems KDiagonal1 BInf false |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|nan;nan;nan|]; [|nan;nan;nan|]; [|infinity;infinity;infinity|] |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix with Inf in last row and NaN in other rows" + TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix with Inf in last row and NaN in other rows" testCase "3x3 Upper Triangular Matrix (Values = 1) with 3x3 Matrix (Values = Inf)" <| fun () -> - SolveTriangularLinearSystems KUpper1 BInf false + LinearAlgebra.solveTriangularLinearSystems KUpper1 BInf false |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|nan;nan;nan|]; [|nan;nan;nan|]; [|infinity;infinity;infinity|] |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix with Inf in last row and NaN in other rows" + TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix with Inf in last row and NaN in other rows" testCase "3x3 Upper Triangular Matrix (Values = -1) with 3x3 Matrix (Values = Inf)" <| fun () -> - SolveTriangularLinearSystems KUpperNeg1 BInf false + LinearAlgebra.solveTriangularLinearSystems KUpperNeg1 BInf false |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|nan;nan;nan|]; [|nan;nan;nan|]; [|-infinity;-infinity;-infinity|] |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix with Inf in last row and NaN in other rows" + TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix with Inf in last row and NaN in other rows" testCase "3x3 Upper Triangular Matrix (Values = Inf) with 3x3 Matrix (Values = Inf)" <| fun () -> - SolveTriangularLinearSystems KUpperInf BInf false + LinearAlgebra.solveTriangularLinearSystems KUpperInf BInf false |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|nan;nan;nan|]; [|nan;nan;nan|]; [|nan;nan;nan|] |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix of NaN" + TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix of NaN" testCase "3x3 Upper Triangular Matrix (Values = -Inf) with 3x3 Matrix (Values = Inf)" <| fun () -> - SolveTriangularLinearSystems KUpperNegInf BInf false + LinearAlgebra.solveTriangularLinearSystems KUpperNegInf BInf false |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|nan;nan;nan|]; [|nan;nan;nan|]; [|nan;nan;nan|] |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix of NaN" + TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix of NaN" testCase "3x3 Upper Triangular Matrix (Values = NaN) with 3x3 Matrix (Values = Inf)" <| fun () -> - SolveTriangularLinearSystems KUpperNaN BInf false + LinearAlgebra.solveTriangularLinearSystems KUpperNaN BInf false |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|nan;nan;nan|]; [|nan;nan;nan|]; [|nan;nan;nan|] |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix of NaN" + TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix of NaN" testCase "3x3 diagonal Matrix (Values = 1) with 3x3 Matrix (Values = -Inf)" <| fun () -> - SolveTriangularLinearSystems KDiagonal1 BNegInf false + LinearAlgebra.solveTriangularLinearSystems KDiagonal1 BNegInf false |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|nan;nan;nan|]; [|nan;nan;nan|]; [|-infinity;-infinity;-infinity|] |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix with -Inf in last row and NaN in other rows" + TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix with -Inf in last row and NaN in other rows" testCase "3x3 Upper Triangular Matrix (Values = 1) with 3x3 Matrix (Values = -Inf)" <| fun () -> - SolveTriangularLinearSystems KUpper1 BNegInf false + LinearAlgebra.solveTriangularLinearSystems KUpper1 BNegInf false |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|nan;nan;nan|]; [|nan;nan;nan|]; [|-infinity;-infinity;-infinity|] |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix with -Inf in last row and NaN in other rows" + TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix with -Inf in last row and NaN in other rows" testCase "3x3 Upper Triangular Matrix (Values = Inf) with 3x3 Matrix (Values = -Inf)" <| fun () -> - SolveTriangularLinearSystems KUpperInf BNegInf false + LinearAlgebra.solveTriangularLinearSystems KUpperInf BNegInf false |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|nan;nan;nan|]; [|nan;nan;nan|]; [|nan;nan;nan|] |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix of NaN" + TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix of NaN" testCase "3x3 Upper Triangular Matrix (Values = -Inf) with 3x3 Matrix (Values = -Inf)" <| fun () -> - SolveTriangularLinearSystems KUpperNegInf BNegInf false + LinearAlgebra.solveTriangularLinearSystems KUpperNegInf BNegInf false |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|nan;nan;nan|]; [|nan;nan;nan|]; [|nan;nan;nan|] |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix of NaN" + TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix of NaN" testCase "3x3 Upper Triangular Matrix (Values = NaN) with 3x3 Matrix (Values = -Inf)" <| fun () -> - SolveTriangularLinearSystems KUpperNaN BNegInf false + LinearAlgebra.solveTriangularLinearSystems KUpperNaN BNegInf false |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|nan;nan;nan|]; [|nan;nan;nan|]; [|nan;nan;nan|] |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix of NaN" + TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix of NaN" testCase "3x3 diagonal Matrix (Values = 1) with 3x3 Matrix (Values = NaN)" <| fun () -> - SolveTriangularLinearSystems KDiagonal1 BNaN false + LinearAlgebra.solveTriangularLinearSystems KDiagonal1 BNaN false |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|nan;nan;nan|]; [|nan;nan;nan|]; [|nan;nan;nan|] |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix with Inf in last row and NaN in other rows" + TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix with Inf in last row and NaN in other rows" testCase "3x3 Upper Triangular Matrix (Values = 1) with 3x3 Matrix (Values = NaN)" <| fun () -> - SolveTriangularLinearSystems KUpper1 BNaN false + LinearAlgebra.solveTriangularLinearSystems KUpper1 BNaN false |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|nan;nan;nan|]; [|nan;nan;nan|]; [|nan;nan;nan|] |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix with Inf in last row and NaN in other rows" + TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix with Inf in last row and NaN in other rows" testCase "3x3 Upper Triangular Matrix (Values = Inf) with 3x3 Matrix (Values = NaN)" <| fun () -> - SolveTriangularLinearSystems KUpperInf BNaN false + LinearAlgebra.solveTriangularLinearSystems KUpperInf BNaN false |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|nan;nan;nan|]; [|nan;nan;nan|]; [|nan;nan;nan|] |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix of NaN" + TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix of NaN" testCase "3x3 Upper Triangular Matrix (Values = -Inf) with 3x3 Matrix (Values = NaN)" <| fun () -> - SolveTriangularLinearSystems KUpperNegInf BNaN false + LinearAlgebra.solveTriangularLinearSystems KUpperNegInf BNaN false |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|nan;nan;nan|]; [|nan;nan;nan|]; [|nan;nan;nan|] |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix of NaN" + TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix of NaN" testCase "3x3 Upper Triangular Matrix (Values = NaN) with 3x3 Matrix (Values = NaN)" <| fun () -> - SolveTriangularLinearSystems KUpperNaN BNaN false + LinearAlgebra.solveTriangularLinearSystems KUpperNaN BNaN false |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|nan;nan;nan|]; [|nan;nan;nan|]; [|nan;nan;nan|] |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix of NaN" + TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix of NaN" testCase "3x3 diagonal Matrix (Values = 1) with 3x3 Matrix (Values = -1)" <| fun () -> - SolveTriangularLinearSystems KDiagonal1 BNeg1 false + LinearAlgebra.solveTriangularLinearSystems KDiagonal1 BNeg1 false |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|-1.;-1.;-1.|]; [|-1.;-1.;-1.|]; [|-1.;-1.;-1.|] |] - |> Array.concat - TestExtensions.sequenceEqual Accuracy.high concatRes concatExpected "Should be 3x3 Matrix of -1" + TestExtensions.sequenceEqual Accuracy.high res.Data expected.Data "Should be 3x3 Matrix of -1" testCase "3x3 Upper Triangular Matrix (Values = 1) with 3x3 Matrix (Values = -1)" <| fun () -> - SolveTriangularLinearSystems KUpper1 BNeg1 false + LinearAlgebra.solveTriangularLinearSystems KUpper1 BNeg1 false |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|0.;0.;0.|]; [|0.;0.;0.|]; [|-1.;-1.;-1.|] |] - |> Array.concat - TestExtensions.sequenceEqual Accuracy.high concatRes concatExpected "Should be 3x3 Matrix with -1 in last row" + TestExtensions.sequenceEqual Accuracy.high res.Data expected.Data "Should be 3x3 Matrix with -1 in last row" testCase "3x3 Upper Triangular Matrix (Values = -1) with 3x3 Matrix (Values = -1)" <| fun () -> - SolveTriangularLinearSystems KUpperNeg1 BNeg1 false + LinearAlgebra.solveTriangularLinearSystems KUpperNeg1 BNeg1 false |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|0.;0.;0.|]; [|0.;0.;0.|]; [|1.;1.;1.|] |] - |> Array.concat - TestExtensions.sequenceEqual Accuracy.high concatRes concatExpected "Should be 3x3 Matrix with -1 in last row" + TestExtensions.sequenceEqual Accuracy.high res.Data expected.Data "Should be 3x3 Matrix with -1 in last row" testCase "3x3 Upper Triangular Matrix (Values = Inf) with 3x3 Matrix (Values = -1)" <| fun () -> - SolveTriangularLinearSystems KUpperInf BNeg1 false + LinearAlgebra.solveTriangularLinearSystems KUpperInf BNeg1 false |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|nan;nan;nan|]; [|nan;nan;nan|]; [|0.;0.;0.|] |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix with 0 in last row and NaN in other rows" + TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix with 0 in last row and NaN in other rows" testCase "3x3 Upper Triangular Matrix (Values = -Inf) with 3x3 Matrix (Values = -1)" <| fun () -> - SolveTriangularLinearSystems KUpperNegInf BNeg1 false + LinearAlgebra.solveTriangularLinearSystems KUpperNegInf BNeg1 false |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|nan;nan;nan|]; [|nan;nan;nan|]; [|0.;0.;0.|] |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix with 0 in last row and NaN in other rows" + TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix with 0 in last row and NaN in other rows" testCase "3x3 Upper Triangular Matrix (Values = NaN) with 3x3 Matrix (Values = -1)" <| fun () -> - SolveTriangularLinearSystems KUpperNaN BNeg1 false + LinearAlgebra.solveTriangularLinearSystems KUpperNaN BNeg1 false |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|nan;nan;nan|]; [|nan;nan;nan|]; [|nan;nan;nan|] |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix of NaN" + TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix of NaN" ] // Tested vs R package "bdsmatrix: Routines for Block Diagonal Symmetric Matrices" Version 1.3-6 testList "SolveTriangularLinearSystems (Lower)" [ testCase "3x3 Lower Triangular Matrix with 3x3 Matrix (realistic example)" <| fun () -> - SolveTriangularLinearSystems + LinearAlgebra.solveTriangularLinearSystems ( [| [|1.;0.;0.|]; @@ -725,442 +580,310 @@ let linearSystems = ) true |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|8.;4.;2.|]; [|-12.;-6.;-3.|]; [|-5.;-2.5;-1.5|] |] - |> Array.concat - TestExtensions.sequenceEqual Accuracy.high concatRes concatExpected "Should be 3x3 Matrix: \n8.;4.;2.\n-12.;-6.;-3.\n-5.;-2.5;-1.5" + TestExtensions.sequenceEqual Accuracy.high res.Data expected.Data "Should be 3x3 Matrix: \n8.;4.;2.\n-12.;-6.;-3.\n-5.;-2.5;-1.5" testCase "3x3 diagonal Matrix (Values = 1) with 3x3 Matrix (Values = 1) (lower)" <| fun () -> - SolveTriangularLinearSystems KDiagonal1 B1 true + LinearAlgebra.solveTriangularLinearSystems KDiagonal1 B1 true |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|1.;1.;1.|]; [|1.;1.;1.|]; [|1.;1.;1.|] |] - |> Array.concat - TestExtensions.sequenceEqual Accuracy.high concatRes concatExpected "Should be 3x3 Matrix of 1" + TestExtensions.sequenceEqual Accuracy.high res.Data expected.Data "Should be 3x3 Matrix of 1" testCase "3x3 Lower Triangular Matrix (Values = 1) with 3x3 Matrix (Values = 1)" <| fun () -> - SolveTriangularLinearSystems KLower1 B1 true + LinearAlgebra.solveTriangularLinearSystems KLower1 B1 true |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|1.;1.;1.|]; [|0.;0.;0.|]; [|0.;0.;0.|] |] - |> Array.concat - TestExtensions.sequenceEqual Accuracy.high concatRes concatExpected "Should be 3x3 Matrix with 1 in first row" + TestExtensions.sequenceEqual Accuracy.high res.Data expected.Data "Should be 3x3 Matrix with 1 in first row" testCase "3x3 Lower Triangular Matrix (Values = -1) with 3x3 Matrix (Values = 1)" <| fun () -> - SolveTriangularLinearSystems KLowerNeg1 B1 true + LinearAlgebra.solveTriangularLinearSystems KLowerNeg1 B1 true |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|-1.;-1.;-1.|]; [|0.;0.;0.|]; [|0.;0.;0.|] |] - |> Array.concat - TestExtensions.sequenceEqual Accuracy.high concatRes concatExpected "Should be 3x3 Matrix with -1 in first row" + TestExtensions.sequenceEqual Accuracy.high res.Data expected.Data "Should be 3x3 Matrix with -1 in first row" testCase "3x3 Lower Triangular Matrix (Values = Inf) with 3x3 Matrix (Values = 1)" <| fun () -> - SolveTriangularLinearSystems KLowerInf B1 true + LinearAlgebra.solveTriangularLinearSystems KLowerInf B1 true |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|0.;0.;0.|]; [|nan;nan;nan|]; [|nan;nan;nan|] |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix with 0 in first row and NaN in other rows" + TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix with 0 in first row and NaN in other rows" testCase "3x3 Lower Triangular Matrix (Values = -Inf) with 3x3 Matrix (Values = 1)" <| fun () -> - SolveTriangularLinearSystems KLowerNegInf B1 true + LinearAlgebra.solveTriangularLinearSystems KLowerNegInf B1 true |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|0.;0.;0.|]; [|nan;nan;nan|]; [|nan;nan;nan|] |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix with 0 in first row and NaN in other rows" + TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix with 0 in first row and NaN in other rows" testCase "3x3 Lower Triangular Matrix (Values = NaN) with 3x3 Matrix (Values = 1)" <| fun () -> - SolveTriangularLinearSystems KLowerNaN B1 true + LinearAlgebra.solveTriangularLinearSystems KLowerNaN B1 true |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|nan;nan;nan|]; [|nan;nan;nan|]; [|nan;nan;nan|] |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix of NaN" + TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix of NaN" testCase "3x3 diagonal Matrix (Values = 1) with 3x3 Matrix (Values = Inf) (lower)" <| fun () -> - SolveTriangularLinearSystems KDiagonal1 BInf true + LinearAlgebra.solveTriangularLinearSystems KDiagonal1 BInf true |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|infinity;infinity;infinity|]; [|nan;nan;nan|]; [|nan;nan;nan|] |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix with Inf in first row and NaN in other rows" + TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix with Inf in first row and NaN in other rows" testCase "3x3 Upper Triangular Matrix (Values = 1) with 3x3 Matrix (Values = Inf)" <| fun () -> - SolveTriangularLinearSystems KLower1 BInf true + LinearAlgebra.solveTriangularLinearSystems KLower1 BInf true |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|infinity;infinity;infinity|]; [|nan;nan;nan|]; [|nan;nan;nan|] |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix with Inf in first row and NaN in other rows" + TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix with Inf in first row and NaN in other rows" testCase "3x3 Lower Triangular Matrix (Values = -1) with 3x3 Matrix (Values = Inf)" <| fun () -> - SolveTriangularLinearSystems KLowerNeg1 BInf true + LinearAlgebra.solveTriangularLinearSystems KLowerNeg1 BInf true |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|-infinity;-infinity;-infinity|]; [|nan;nan;nan|]; [|nan;nan;nan|] |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix with Inf in first row and NaN in other rows" + TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix with Inf in first row and NaN in other rows" testCase "3x3 Lower Triangular Matrix (Values = Inf) with 3x3 Matrix (Values = Inf)" <| fun () -> - SolveTriangularLinearSystems KLowerInf BInf true + LinearAlgebra.solveTriangularLinearSystems KLowerInf BInf true |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|nan;nan;nan|]; [|nan;nan;nan|]; [|nan;nan;nan|] |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix of NaN" + TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix of NaN" testCase "3x3 Lower Triangular Matrix (Values = -Inf) with 3x3 Matrix (Values = Inf)" <| fun () -> - SolveTriangularLinearSystems KLowerNegInf BInf true + LinearAlgebra.solveTriangularLinearSystems KLowerNegInf BInf true |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|nan;nan;nan|]; [|nan;nan;nan|]; [|nan;nan;nan|] |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix of NaN" + TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix of NaN" testCase "3x3 Lower Triangular Matrix (Values = NaN) with 3x3 Matrix (Values = Inf)" <| fun () -> - SolveTriangularLinearSystems KLowerNaN BInf true + LinearAlgebra.solveTriangularLinearSystems KLowerNaN BInf true |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|nan;nan;nan|]; [|nan;nan;nan|]; [|nan;nan;nan|] |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix of NaN" + + TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix of NaN" testCase "3x3 diagonal Matrix (Values = 1) with 3x3 Matrix (Values = -Inf)" <| fun () -> - SolveTriangularLinearSystems KDiagonal1 BNegInf true + LinearAlgebra.solveTriangularLinearSystems KDiagonal1 BNegInf true |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|-infinity;-infinity;-infinity|]; [|nan;nan;nan|]; [|nan;nan;nan|] |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix with -Inf in first row and NaN in other rows" + + TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix with -Inf in first row and NaN in other rows" testCase "3x3 Lower Triangular Matrix (Values = 1) with 3x3 Matrix (Values = -Inf)" <| fun () -> - SolveTriangularLinearSystems KLower1 BNegInf true + LinearAlgebra.solveTriangularLinearSystems KLower1 BNegInf true |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|-infinity;-infinity;-infinity|]; [|nan;nan;nan|]; [|nan;nan;nan|] |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix with -Inf in first row and NaN in other rows" + + TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix with -Inf in first row and NaN in other rows" testCase "3x3 Lower Triangular Matrix (Values = Inf) with 3x3 Matrix (Values = -Inf)" <| fun () -> - SolveTriangularLinearSystems KLowerInf BNegInf true + LinearAlgebra.solveTriangularLinearSystems KLowerInf BNegInf true |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|nan;nan;nan|]; [|nan;nan;nan|]; [|nan;nan;nan|] |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix of NaN" + TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix of NaN" testCase "3x3 Lower Triangular Matrix (Values = -Inf) with 3x3 Matrix (Values = -Inf)" <| fun () -> - SolveTriangularLinearSystems KLowerNegInf BNegInf true + LinearAlgebra.solveTriangularLinearSystems KLowerNegInf BNegInf true |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|nan;nan;nan|]; [|nan;nan;nan|]; [|nan;nan;nan|] |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix of NaN" + + TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix of NaN" testCase "3x3 Lower Triangular Matrix (Values = NaN) with 3x3 Matrix (Values = -Inf)" <| fun () -> - SolveTriangularLinearSystems KLowerNaN BNegInf true + LinearAlgebra.solveTriangularLinearSystems KLowerNaN BNegInf true |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|nan;nan;nan|]; [|nan;nan;nan|]; [|nan;nan;nan|] |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix of NaN" + + TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix of NaN" testCase "3x3 diagonal Matrix (Values = 1) with 3x3 Matrix (Values = NaN) (lower)" <| fun () -> - SolveTriangularLinearSystems KDiagonal1 BNaN true + LinearAlgebra.solveTriangularLinearSystems KDiagonal1 BNaN true |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|nan;nan;nan|]; [|nan;nan;nan|]; [|nan;nan;nan|] |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix with Inf in last row and NaN in other rows" + TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix with Inf in last row and NaN in other rows" testCase "3x3 Lower Triangular Matrix (Values = 1) with 3x3 Matrix (Values = NaN)" <| fun () -> - SolveTriangularLinearSystems KLower1 BNaN true + LinearAlgebra.solveTriangularLinearSystems KLower1 BNaN true |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|nan;nan;nan|]; [|nan;nan;nan|]; [|nan;nan;nan|] |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix with Inf in last row and NaN in other rows" + TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix with Inf in last row and NaN in other rows" testCase "3x3 Lower Triangular Matrix (Values = Inf) with 3x3 Matrix (Values = NaN)" <| fun () -> - SolveTriangularLinearSystems KLowerInf BNaN true + LinearAlgebra.solveTriangularLinearSystems KLowerInf BNaN true |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|nan;nan;nan|]; [|nan;nan;nan|]; [|nan;nan;nan|] |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix of NaN" + TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix of NaN" testCase "3x3 Lower Triangular Matrix (Values = -Inf) with 3x3 Matrix (Values = NaN)" <| fun () -> - SolveTriangularLinearSystems KLowerNegInf BNaN true + LinearAlgebra.solveTriangularLinearSystems KLowerNegInf BNaN true |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|nan;nan;nan|]; [|nan;nan;nan|]; [|nan;nan;nan|] |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix of NaN" + + TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix of NaN" testCase "3x3 Lower Triangular Matrix (Values = NaN) with 3x3 Matrix (Values = NaN)" <| fun () -> - SolveTriangularLinearSystems KLowerNaN BNaN true + LinearAlgebra.solveTriangularLinearSystems KLowerNaN BNaN true |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|nan;nan;nan|]; [|nan;nan;nan|]; [|nan;nan;nan|] |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix of NaN" + + TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix of NaN" testCase "3x3 diagonal Matrix (Values = 1) with 3x3 Matrix (Values = -1) (lower)" <| fun () -> - SolveTriangularLinearSystems KDiagonal1 BNeg1 true + LinearAlgebra.solveTriangularLinearSystems KDiagonal1 BNeg1 true |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|-1.;-1.;-1.|]; [|-1.;-1.;-1.|]; [|-1.;-1.;-1.|] |] - |> Array.concat - TestExtensions.sequenceEqual Accuracy.high concatRes concatExpected "Should be 3x3 Matrix of -1" + + TestExtensions.sequenceEqual Accuracy.high res.Data expected.Data "Should be 3x3 Matrix of -1" testCase "3x3 Lower Triangular Matrix (Values = 1) with 3x3 Matrix (Values = -1)" <| fun () -> - SolveTriangularLinearSystems KLower1 BNeg1 true + LinearAlgebra.solveTriangularLinearSystems KLower1 BNeg1 true |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|-1.;-1.;-1.|]; [|0.;0.;0.|]; [|0.;0.;0.|] |] - |> Array.concat - TestExtensions.sequenceEqual Accuracy.high concatRes concatExpected "Should be 3x3 Matrix with -1 in first row" + + TestExtensions.sequenceEqual Accuracy.high res.Data expected.Data "Should be 3x3 Matrix with -1 in first row" testCase "3x3 Lower Triangular Matrix (Values = -1) with 3x3 Matrix (Values = -1)" <| fun () -> - SolveTriangularLinearSystems KLowerNeg1 BNeg1 true + LinearAlgebra.solveTriangularLinearSystems KLowerNeg1 BNeg1 true |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|1.;1.;1.|]; [|0.;0.;0.|]; [|0.;0.;0.|] |] - |> Array.concat - TestExtensions.sequenceEqual Accuracy.high concatRes concatExpected "Should be 3x3 Matrix with -1 in first row" + + TestExtensions.sequenceEqual Accuracy.high res.Data expected.Data "Should be 3x3 Matrix with -1 in first row" testCase "3x3 Lower Triangular Matrix (Values = Inf) with 3x3 Matrix (Values = -1)" <| fun () -> - SolveTriangularLinearSystems KLowerInf BNeg1 true + LinearAlgebra.solveTriangularLinearSystems KLowerInf BNeg1 true |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|0.;0.;0.|]; [|nan;nan;nan|]; [|nan;nan;nan|] |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix with 0 in first row and NaN in other rows" + + TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix with 0 in first row and NaN in other rows" testCase "3x3 Lower Triangular Matrix (Values = -Inf) with 3x3 Matrix (Values = -1)" <| fun () -> - SolveTriangularLinearSystems KLowerNegInf BNeg1 true + LinearAlgebra.solveTriangularLinearSystems KLowerNegInf BNeg1 true |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|0.;0.;0.|]; [|nan;nan;nan|]; [|nan;nan;nan|] |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix with 0 in first row and NaN in other rows" + + TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix with 0 in first row and NaN in other rows" testCase "3x3 Lower Triangular Matrix (Values = NaN) with 3x3 Matrix (Values = -1)" <| fun () -> - SolveTriangularLinearSystems KLowerNaN BNeg1 true + LinearAlgebra.solveTriangularLinearSystems KLowerNaN BNeg1 true |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|nan;nan;nan|]; [|nan;nan;nan|]; [|nan;nan;nan|] |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix of NaN" + + TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix of NaN" ] testList "SolveTriangularLinearSystem (Upper)" [ testCase "3x3 Upper Triangular Matrix with Vector (realistic example)" <| fun () -> - SolveTriangularLinearSystem + LinearAlgebra.solveTriangularLinearSystem ( [| [|1.;2.;3.|]; @@ -1175,64 +898,43 @@ let linearSystems = ) false |> fun res -> - let concatRes = - res - |> Vector.toArray - let concatExpected = + let expected = [|-1.;3.;1.|] - TestExtensions.sequenceEqual Accuracy.high concatRes concatExpected "Should be Vector of -1.;3.;1." + TestExtensions.sequenceEqual Accuracy.high res expected "Should be Vector of -1.;3.;1." testCase "3x3 diagonal Matrix (Values = 1) with Vector (Values = 1)" <| fun () -> - SolveTriangularLinearSystem KDiagonal1 b1 false + LinearAlgebra.solveTriangularLinearSystem KDiagonal1 b1 false |> fun res -> - let concatRes = - res - |> Vector.toArray let expected = [|1.;1.;1.|] - TestExtensions.sequenceEqualRoundedNaN 9 concatRes expected "Should be Vector of 1" + TestExtensions.sequenceEqualRoundedNaN 9 res expected "Should be Vector of 1" testCase "3x3 Upper Triangular Matrix (Values = 1) with Vector (Values = 1)" <| fun () -> - SolveTriangularLinearSystem KUpper1 b1 false + LinearAlgebra.solveTriangularLinearSystem KUpper1 b1 false |> fun res -> - let concatRes = - res - |> Vector.toArray let expected = [|0.;0.;1.|] - TestExtensions.sequenceEqualRoundedNaN 9 concatRes expected "Should be Vector of 0 0 1" + TestExtensions.sequenceEqualRoundedNaN 9 res expected "Should be Vector of 0 0 1" testCase "3x3 Upper Triangular Matrix (Values = -1) with Vector (Values = 1)" <| fun () -> - SolveTriangularLinearSystem KUpperNeg1 b1 false + LinearAlgebra.solveTriangularLinearSystem KUpperNeg1 b1 false |> fun res -> - let concatRes = - res - |> Vector.toArray let expected = [|0.;0.;-1.|] - TestExtensions.sequenceEqualRoundedNaN 9 concatRes expected "Should be Vector of 0 0 -1" + TestExtensions.sequenceEqualRoundedNaN 9 res expected "Should be Vector of 0 0 -1" testCase "3x3 Upper Triangular Matrix (Values = Inf) with Vector (Values = 1)" <| fun () -> - SolveTriangularLinearSystem KUpperInf b1 false + LinearAlgebra.solveTriangularLinearSystem KUpperInf b1 false |> fun res -> - let concatRes = - res - |> Vector.toArray let expected = [|nan;nan;0|] - TestExtensions.sequenceEqualRoundedNaN 9 concatRes expected "Should be Vector of NaN NaN 0" + TestExtensions.sequenceEqualRoundedNaN 9 res expected "Should be Vector of NaN NaN 0" testCase "3x3 Upper Triangular Matrix (Values = -Inf) with Vector (Values = 1)" <| fun () -> - SolveTriangularLinearSystem KUpperNegInf b1 false + LinearAlgebra.solveTriangularLinearSystem KUpperNegInf b1 false |> fun res -> - let concatRes = - res - |> Vector.toArray let expected = [|nan;nan;0|] - TestExtensions.sequenceEqualRoundedNaN 9 concatRes expected "Should be Vector of NaN NaN 0" + TestExtensions.sequenceEqualRoundedNaN 9 res expected "Should be Vector of NaN NaN 0" testCase "3x3 Upper Triangular Matrix (Values = NaN) with Vector (Values = 1)" <| fun () -> - SolveTriangularLinearSystem KUpperNaN b1 false + LinearAlgebra.solveTriangularLinearSystem KUpperNaN b1 false |> fun res -> - let concatRes = - res - |> Vector.toArray let expected = [|nan;nan;nan|] - TestExtensions.sequenceEqualRoundedNaN 9 concatRes expected "Should be Vector of NaN" + TestExtensions.sequenceEqualRoundedNaN 9 res expected "Should be Vector of NaN" ] testList "SolveTriangularLinearSystem (Lower)" [ testCase "3x3 Upper Triangular Matrix with Vector (realistic example)" <| fun () -> - SolveTriangularLinearSystem + LinearAlgebra.solveTriangularLinearSystem ( [| [|1.;0.;0.|]; @@ -1247,60 +949,39 @@ let linearSystems = ) true |> fun res -> - let concatRes = - res - |> Vector.toArray - let concatExpected = + let expected = [|8.;-12.;-5.|] - TestExtensions.sequenceEqual Accuracy.high concatRes concatExpected "Should be Vector of 8.;-12.;-5." + TestExtensions.sequenceEqual Accuracy.high res expected "Should be Vector of 8.;-12.;-5." testCase "3x3 diagonal Matrix (Values = 1) with Vector (Values = 1)" <| fun () -> - SolveTriangularLinearSystem KDiagonal1 b1 true + LinearAlgebra.solveTriangularLinearSystem KDiagonal1 b1 true |> fun res -> - let concatRes = - res - |> Vector.toArray let expected = [|1.;1.;1.|] - TestExtensions.sequenceEqualRoundedNaN 9 concatRes expected "Should be Vector of 1" + TestExtensions.sequenceEqualRoundedNaN 9 res expected "Should be Vector of 1" testCase "3x3 Lower Triangular Matrix (Values = 1) with Vector (Values = 1)" <| fun () -> - SolveTriangularLinearSystem KLower1 b1 true + LinearAlgebra.solveTriangularLinearSystem KLower1 b1 true |> fun res -> - let concatRes = - res - |> Vector.toArray let expected = [|1.;0.;0.|] - TestExtensions.sequenceEqualRoundedNaN 9 concatRes expected "Should be Vector of 1 0 0" + TestExtensions.sequenceEqualRoundedNaN 9 res expected "Should be Vector of 1 0 0" testCase "3x3 Lower Triangular Matrix (Values = -1) with Vector (Values = 1)" <| fun () -> - SolveTriangularLinearSystem KLowerNeg1 b1 true + LinearAlgebra.solveTriangularLinearSystem KLowerNeg1 b1 true |> fun res -> - let concatRes = - res - |> Vector.toArray let expected = [|-1.;0.;0.|] - TestExtensions.sequenceEqualRoundedNaN 9 concatRes expected "Should be Vector of -1 0 0" + TestExtensions.sequenceEqualRoundedNaN 9 res expected "Should be Vector of -1 0 0" testCase "3x3 Lower Triangular Matrix (Values = Inf) with Vector (Values = 1)" <| fun () -> - SolveTriangularLinearSystem KLowerInf b1 true + LinearAlgebra.solveTriangularLinearSystem KLowerInf b1 true |> fun res -> - let concatRes = - res - |> Vector.toArray let expected = [|0.;nan;nan|] - TestExtensions.sequenceEqualRoundedNaN 9 concatRes expected "Should be Vector of 0 NaN NaN" + TestExtensions.sequenceEqualRoundedNaN 9 res expected "Should be Vector of 0 NaN NaN" testCase "3x3 Lower Triangular Matrix (Values = -Inf) with Vector (Values = 1)" <| fun () -> - SolveTriangularLinearSystem KLowerNegInf b1 true + LinearAlgebra.solveTriangularLinearSystem KLowerNegInf b1 true |> fun res -> - let concatRes = - res - |> Vector.toArray let expected = [|0.;nan;nan|] - TestExtensions.sequenceEqualRoundedNaN 9 concatRes expected "Should be Vector of 0 NaN NaN" + TestExtensions.sequenceEqualRoundedNaN 9 res expected "Should be Vector of 0 NaN NaN" testCase "3x3 Lower Triangular Matrix (Values = NaN) with Vector (Values = 1)" <| fun () -> - SolveTriangularLinearSystem KLowerNaN b1 true + LinearAlgebra.solveTriangularLinearSystem KLowerNaN b1 true |> fun res -> - let concatRes = - res - |> Vector.toArray let expected = [|nan;nan;nan|] - TestExtensions.sequenceEqualRoundedNaN 9 concatRes expected "Should be Vector of NaN" + TestExtensions.sequenceEqualRoundedNaN 9 res expected "Should be Vector of NaN" ] ] diff --git a/tests/FSharp.Stats.Tests/Seq.fs b/tests/FSharp.Stats.Tests/Seq.fs index 8cdb188a3..c91e0ad08 100644 --- a/tests/FSharp.Stats.Tests/Seq.fs +++ b/tests/FSharp.Stats.Tests/Seq.fs @@ -829,31 +829,32 @@ let statsTests = let stats = Seq.stats (Seq.empty) Expect.equal stats.N 0 "N should be 0" Expect.isTrue (Double.IsNaN stats.Mean) "Mean should be NaN" - Expect.isTrue (Double.IsNaN stats.SumOfSquares) "SumOfSquares should be NaN" + Expect.isTrue (Double.IsNaN stats.SumSqrdDevations) "SumSqrdDevations should be NaN" Expect.isTrue (Double.IsNaN stats.Min) "Min should be NaN" Expect.isTrue (Double.IsNaN stats.Max) "Max should be NaN" - testCase "statsSeqGen10" <| fun () -> - let stats = seqGen 10 |> Seq.stats - Expect.equal stats.N 10 "N should be 9" - Expect.floatClose Accuracy.high stats.Mean -13.979665708718687 "Mean should be -13.979665708718687" - Expect.floatClose Accuracy.high stats.SumOfSquares 362450.2113702808 "SumOfSquares should be 362450.2113702808" - Expect.floatClose Accuracy.high stats.Min -499.92173630740575163 "Min should be -499.92173630740575163" - Expect.floatClose Accuracy.high stats.Max 292.9640583661216624 "Max should be 10.644420177367894" - - testCase "statsSeqGen1000" <| fun () -> - let stats = seqGen 1000 |> Seq.stats - Expect.equal stats.N 1000 "N should be 999" - Expect.floatClose Accuracy.medium stats.Mean -5.133606105015737 "Mean should be -5.133606105015737" - Expect.floatClose Accuracy.medium stats.SumOfSquares 81701824.38921407 "SumOfSquares should be 81701824.38921407" - Expect.floatClose Accuracy.medium stats.Min -498.70270583718212265 "Min should be -498.70270583718212265" - Expect.floatClose Accuracy.medium stats.Max 499.80056798076293489 "Max should be 10.644420177367894" + // Seems to be wrong ?!? + //testCase "statsSeqGen10" <| fun () -> + // let stats = seqGen 10 |> Seq.stats + // Expect.equal stats.N 10 "N should be 9" + // Expect.floatClose Accuracy.high stats.Mean -13.979665708718687 "Mean should be -13.979665708718687" + // Expect.floatClose Accuracy.high stats.SumSqrdDevations 362450.2113702808 "SumSqrdDevations should be 362450.2113702808" + // Expect.floatClose Accuracy.high stats.Min -499.92173630740575163 "Min should be -499.92173630740575163" + // Expect.floatClose Accuracy.high stats.Max 292.9640583661216624 "Max should be 10.644420177367894" + + //testCase "statsSeqGen1000" <| fun () -> + // let stats = seqGen 1000 |> Seq.stats + // Expect.equal stats.N 1000 "N should be 999" + // Expect.floatClose Accuracy.medium stats.Mean -5.133606105015737 "Mean should be -5.133606105015737" + // Expect.floatClose Accuracy.medium stats.SumSqrdDevations 81701824.38921407 "SumSqrdDevations should be 81701824.38921407" + // Expect.floatClose Accuracy.medium stats.Min -498.70270583718212265 "Min should be -498.70270583718212265" + // Expect.floatClose Accuracy.medium stats.Max 499.80056798076293489 "Max should be 10.644420177367894" testCase "statsAllSame" <| fun () -> let stats = Seq.init 100 (fun _ -> 42.0) |> Seq.stats Expect.equal stats.N 100 "N should be 100" Expect.equal stats.Mean 42.0 "Mean should be 42.0" - Expect.equal stats.SumOfSquares 0.0 "SumOfSquares should be 0.0" + Expect.equal stats.SumSqrdDevations 0.0 "SumSqrdDevations should be 0.0" Expect.equal stats.Min 42.0 "Min should be 42.0" Expect.equal stats.Max 42.0 "Max should be 42.0" @@ -861,15 +862,30 @@ let statsTests = let stats = Seq.stats [1.0; 2.0; Double.NaN; 3.0] Expect.equal stats.N 4 "N should be 4" Expect.isTrue (Double.IsNaN stats.Mean) "Mean should be NaN" - Expect.isTrue (Double.IsNaN stats.SumOfSquares) "SumOfSquares should be NaN" + Expect.isTrue (Double.IsNaN stats.SumSqrdDevations) "SumSqrdDevations should be NaN" testCase "statsInfinity" <| fun () -> let stats = Seq.stats [1.0; Double.PositiveInfinity; 2.0; Double.NegativeInfinity] Expect.equal stats.N 4 "N should be 4" Expect.isTrue (Double.IsNaN stats.Mean) "Mean should be NaN" - Expect.isTrue (Double.IsNaN stats.SumOfSquares) "SumOfSquares should be NaN" + Expect.isTrue (Double.IsNaN stats.SumSqrdDevations) "SumSqrdDevations should be NaN" Expect.equal stats.Min Double.NegativeInfinity "Min should be negative infinity" Expect.equal stats.Max Double.PositiveInfinity "Max should be positive infinity" + + testCase "statsAgainstImplementation" <| fun () -> + let data = seqGen 1000 + let stats = data |> Seq.stats + let calcMean = Seq.mean data + let calcSumOfSquares = data |> Seq.sumBy (fun x -> (x - calcMean) * (x - calcMean)) + let calcMin = Seq.min data + let calcMax = Seq.max data + let calcN = Seq.length data + Expect.floatClose Accuracy.high stats.Mean calcMean $"Mean should be {calcMean}" + Expect.floatClose Accuracy.high stats.SumSqrdDevations calcSumOfSquares $"SumSqrdDevations should {calcSumOfSquares}" + Expect.floatClose Accuracy.high stats.Min calcMin $"Min should be {calcMin}" + Expect.floatClose Accuracy.high stats.Max calcMax $"Max should {calcMax}" + Expect.equal stats.N calcN $"N should be {calcN}" + ] diff --git a/tests/FSharp.Stats.Tests/Signal.fs b/tests/FSharp.Stats.Tests/Signal.fs index 11e722ca6..7206abbd0 100644 --- a/tests/FSharp.Stats.Tests/Signal.fs +++ b/tests/FSharp.Stats.Tests/Signal.fs @@ -70,7 +70,7 @@ let outlierTests = testList "Mahalanobi's Distance" [ testCase "Mahalanobi's Distance for an observation in a matrix"<| fun() -> - let obs = Vector.ofList [20.; 11.] + let obs = [|20.; 11.|] Expect.floatClose Accuracy.high (mahalanobisDistanceOfEntry dataRow Matrix.Sample Matrix.RowWise obs) 1.843936618 "Mahalanobi's Distance for an observation(Sample, RowWise) calculated incorrectly" Expect.floatClose Accuracy.high (mahalanobisDistanceOfEntry dataColumn Matrix.Sample Matrix.ColWise obs) 1.843936618 "Mahalanobi's Distance for an observation calculated(Sample, ColWise) incorrectly" Expect.floatClose Accuracy.high (mahalanobisDistanceOfEntry dataRow Matrix.Population Matrix.RowWise obs) 1.943679857 "Mahalanobi's Distance for an observation calculated(Population, RowWise) incorrectly" diff --git a/tests/FSharp.Stats.Tests/SummaryStats.fs b/tests/FSharp.Stats.Tests/SummaryStats.fs new file mode 100644 index 000000000..5bedc8b44 --- /dev/null +++ b/tests/FSharp.Stats.Tests/SummaryStats.fs @@ -0,0 +1,174 @@ +module SummaryStatsTests + +open Expecto +open FSharp.Stats + + +[] +let summaryStatsTests = + testList "SummaryStats Tests" [ + + testCase "ofSeq with empty sequence" <| fun _ -> + let emptySeq: float seq = Seq.empty + let stats = SummaryStats.ofSeq emptySeq + // N = 0, Mean/Min/Max/SumSqrdDevations should be NaN (by definition here) + Expect.equal stats.N 0.0 "Count should be zero for empty sequence." + Expect.isTrue (System.Double.IsNaN stats.Mean) "Mean should be NaN for empty sequence." + Expect.isTrue (System.Double.IsNaN stats.SumSqrdDevations) "SumSqrdDevations should be NaN for empty sequence." + Expect.isTrue (System.Double.IsNaN stats.Min) "Min should be NaN for empty sequence." + Expect.isTrue (System.Double.IsNaN stats.Max) "Max should be NaN for empty sequence." + + testCase "ofSeq with [1.0; 2.0; 3.0]" <| fun _ -> + let stats = SummaryStats.ofSeq [1.0; 2.0; 3.0] + Expect.equal stats.N 3.0 "N should be 3.0" + Expect.equal stats.Mean 2.0 "Mean should be 2.0" + Expect.equal stats.Min 1.0 "Min should be 1.0" + Expect.equal stats.Max 3.0 "Max should be 3.0" + Expect.equal stats.SumSqrdDevations 2.0 "SumSqrdDevations should be (1-2)^2 + (2-2)^2 + (3-2)^2 = 2" + + // population variance = 2/3 + let popVar = SummaryStats.varPopulation stats + // sample variance = 2/ (3-1) = 1 + let sampVar = SummaryStats.var stats + // stDev = sqrt(sample variance) = 1 + let sd = SummaryStats.stDev stats + // stDevPopulation = sqrt( popVar ) = sqrt(2/3) + let sdPop = SummaryStats.stDevPopulation stats + + Expect.floatClose Accuracy.high popVar (2.0/3.0) "Population variance should be 2/3." + Expect.equal sampVar 1.0 "Sample variance should be 1.0" + Expect.equal sd 1.0 "Sample standard deviation should be 1.0" + Expect.floatClose Accuracy.high sdPop (sqrt(2.0/3.0)) "Population std. dev. should be sqrt(2/3)." + + testCase "ofArray with [|1.0; 2.0; 3.0|]" <| fun _ -> + let statsArr = SummaryStats.ofArray [|1.0; 2.0; 3.0|] + Expect.equal statsArr.N 3.0 "N should be 3.0" + Expect.equal statsArr.Mean 2.0 "Mean should be 2.0" + Expect.equal statsArr.Min 1.0 "Min should be 1.0" + Expect.equal statsArr.Max 3.0 "Max should be 3.0" + Expect.equal statsArr.SumSqrdDevations 2.0 "SumSqrdDevations should be 2.0" + + // Double-check a couple stats + Expect.floatClose Accuracy.high (SummaryStats.varPopulation statsArr) (2.0/3.0) "Pop var should be 2/3." + Expect.equal (SummaryStats.var statsArr) 1.0 "Sample variance should be 1.0" + + testList "SummaryStats vs. FSharp.Stats (Random Data)" [ + + testCase "Random data (Seq) comparison" <| fun _ -> + // 1) Generate some random data + let rng = System.Random(42) + let dataCount = 100 + let dataSeq = + Seq.init dataCount (fun _ -> rng.NextDouble() * 100.0) + |> Seq.cache // ensure we can iterate multiple times if needed + + // 2) Compute stats with your SummaryStats.ofSeq + let sStats = SummaryStats.ofSeq dataSeq + + // 3) Compute stats with FSharp.Stats library + let lengthFS = Seq.length dataSeq + let meanFS = Seq.mean dataSeq + let minFS = Seq.min dataSeq + let maxFS = Seq.max dataSeq + let varPopFS = Seq.varPopulation dataSeq + let varFS = Seq.var dataSeq + let sdPopFS = Seq.stDevPopulation dataSeq + let sdFS = Seq.stDev dataSeq + + // 4) Compare + + // N vs. length + // Your sStats.N is a 'T. Here, we assume 'T = float in your usage. + // If 'T = float, you can compare directly to float lengthFS. + Expect.equal sStats.N (float lengthFS) "N (count) mismatch" + + // mean + Expect.floatClose Accuracy.high sStats.Mean meanFS "Mean mismatch" + // min + Expect.floatClose Accuracy.high sStats.Min minFS "Min mismatch" + // max + Expect.floatClose Accuracy.high sStats.Max maxFS "Max mismatch" + + // population variance + let varPop = SummaryStats.varPopulation sStats + Expect.floatClose Accuracy.high varPop varPopFS "Population variance mismatch" + + // sample variance + let varSample = SummaryStats.var sStats + Expect.floatClose Accuracy.high varSample varFS "Sample variance mismatch" + + // population std dev + let sdPop = SummaryStats.stDevPopulation sStats + Expect.floatClose Accuracy.high sdPop sdPopFS "Population std. dev mismatch" + + // sample std dev + let sdSample = SummaryStats.stDev sStats + Expect.floatClose Accuracy.high sdSample sdFS "Sample std. dev mismatch" + + testCase "Random data (Array) comparison" <| fun _ -> + // 1) Generate some random data for an array + let rng = System.Random(42) + let dataCount = 100 + let dataArr = + Array.init dataCount (fun _ -> rng.NextDouble() * 100.0) + + // 2) SummaryStats.ofsArray + let sStatsArray = SummaryStats.ofArray dataArr + + // 3) FSharp.Stats.* for arrays + let lengthFS = Array.length dataArr + let meanFS = Array.average dataArr + let minFS = Array.min dataArr + let maxFS = Array.max dataArr + let varPopFS = Seq.varPopulation dataArr + let varFS = Seq.var dataArr + let sdPopFS = Seq.stDevPopulation dataArr + let sdFS = Seq.stDev dataArr + + // 4) Compare results + Expect.equal sStatsArray.N (float lengthFS) "N (count) mismatch" + Expect.floatClose Accuracy.high sStatsArray.Mean meanFS "Mean mismatch" + Expect.floatClose Accuracy.high sStatsArray.Min minFS "Min mismatch" + Expect.floatClose Accuracy.high sStatsArray.Max maxFS "Max mismatch" + + // population variance + let varPopArr = SummaryStats.varPopulation sStatsArray + Expect.floatClose Accuracy.high varPopArr varPopFS "Population variance mismatch" + + // sample variance + let varSampleArr = SummaryStats.var sStatsArray + Expect.floatClose Accuracy.high varSampleArr varFS "Sample variance mismatch" + + // population std dev + let sdPopArr = SummaryStats.stDevPopulation sStatsArray + Expect.floatClose Accuracy.high sdPopArr sdPopFS "Population std. dev mismatch" + + // sample std dev + let sdSampleArr = SummaryStats.stDev sStatsArray + Expect.floatClose Accuracy.high sdSampleArr sdFS "Sample std. dev mismatch" + + testCase "Random data (ofSeq + ofArray) comparison" <| fun _ -> + // 1) Generate some random data for an array + let rng = System.Random(42) + let dataCount = 100 + let dataArr = + Array.init dataCount (fun _ -> rng.NextDouble() * 100.0) + + // 2) SummaryStats.ofsArray + let sStatsArray = SummaryStats.ofArray dataArr + let sStatsSeq = SummaryStats.ofArray dataArr + Expect.equal sStatsArray sStatsSeq "SummaryStats.ofArray and SummaryStats.ofSeq should yield the same results." + + ] + + + ] + +// Seq.length +// Seq.mean +// Seq.min +// Seq.max +// Seq.stDev +// Seq.stDevPopulation +// Seq.var +// Seq.varPopulation \ No newline at end of file From 83c5c11cbe36bc18ca8a0e2eebae132df3f28192 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20M=C3=BChlhaus?= Date: Sat, 12 Apr 2025 12:29:54 +0200 Subject: [PATCH 028/121] Update unit testing for Optimization --- tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj | 1 + tests/FSharp.Stats.Tests/Optimization.fs | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj b/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj index f25262a84..4985f80a9 100644 --- a/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj +++ b/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj @@ -28,6 +28,7 @@ + diff --git a/tests/FSharp.Stats.Tests/Optimization.fs b/tests/FSharp.Stats.Tests/Optimization.fs index 2c4f2feae..f91b77906 100644 --- a/tests/FSharp.Stats.Tests/Optimization.fs +++ b/tests/FSharp.Stats.Tests/Optimization.fs @@ -13,21 +13,21 @@ open FSharp.Stats.Optimization let NelderMeadTests = testList "Optimization.NelderMead" [ - let poly (xs: vector) = + let poly (xs: Vector) = System.Math.Pow(xs[0], 2) // Rosenbrock's valley or Rosenbrock's banana function - let rosenbrock (xs: vector) = + let rosenbrock (xs: Vector) = let x, y = xs.[0], xs.[1] pown (1.0 - x) 2 + 100.0 * pown (y - pown x 2) 2 // Fletcher and Powell's helic valley - let fphv (x : vector) = + let fphv (x : Vector) = 100. * (x[2] - 10. * (atan2 x[1] x[0]) / (2. * Ops.pi))**2. + (sqrt(x[0]**2. + x[1]**2.) - 1.)**2. + x[2]**2. // Powell's Singular Function (PSF) - let psf (x : vector) = + let psf (x : Vector) = (x[0] + 10. * x[1])**2. + 5. * (x[2] - x[3])**2. + (x[1] - 2. * x[2])**4. + 10.*(x[0] - x[3])**4. From 1596e41904af03cf6d8373d196236690127aeadd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20M=C3=BChlhaus?= Date: Sat, 12 Apr 2025 17:47:46 +0200 Subject: [PATCH 029/121] Add benchmarks --- FSharp.Stats.sln | 22 +++++++-- ...nchmarks.MatrixBenchmarks-report-github.md | 24 ++++++++++ ...ats.Benchmarks.MatrixBenchmarks-report.csv | 13 +++++ ...ts.Benchmarks.MatrixBenchmarks-report.html | 41 ++++++++++++++++ ...nchmarks.VectorBenchmarks-report-github.md | 24 ++++++++++ ...ats.Benchmarks.VectorBenchmarks-report.csv | 13 +++++ ...ts.Benchmarks.VectorBenchmarks-report.html | 41 ++++++++++++++++ .../FSharp.Stats.Benchmarks.fsproj | 22 +++++++++ benchmarks/FSharp.Stats.Benchmarks/Matrix.fs | 44 +++++++++++++++++ benchmarks/FSharp.Stats.Benchmarks/Program.fs | 13 +++++ benchmarks/FSharp.Stats.Benchmarks/Vector.fs | 48 +++++++++++++++++++ ...nchmarks.MatrixBenchmarks-report-github.md | 24 ++++++++++ ...gacyBenchmarks.MatrixBenchmarks-report.csv | 13 +++++ ...acyBenchmarks.MatrixBenchmarks-report.html | 41 ++++++++++++++++ ...nchmarks.VectorBenchmarks-report-github.md | 24 ++++++++++ ...gacyBenchmarks.VectorBenchmarks-report.csv | 13 +++++ ...acyBenchmarks.VectorBenchmarks-report.html | 41 ++++++++++++++++ .../FSharp.Stats.LegacyBenchmarks.fsproj | 19 ++++++++ .../FSharp.Stats.LegacyBenchmarks/Matrix.fs | 44 +++++++++++++++++ .../FSharp.Stats.LegacyBenchmarks/Program.fs | 15 ++++++ .../FSharp.Stats.LegacyBenchmarks/Vector.fs | 48 +++++++++++++++++++ .../FSharp.Stats.Tests.fsproj | 5 +- 22 files changed, 587 insertions(+), 5 deletions(-) create mode 100644 benchmarks/FSharp.Stats.Benchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.Benchmarks.MatrixBenchmarks-report-github.md create mode 100644 benchmarks/FSharp.Stats.Benchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.Benchmarks.MatrixBenchmarks-report.csv create mode 100644 benchmarks/FSharp.Stats.Benchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.Benchmarks.MatrixBenchmarks-report.html create mode 100644 benchmarks/FSharp.Stats.Benchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.Benchmarks.VectorBenchmarks-report-github.md create mode 100644 benchmarks/FSharp.Stats.Benchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.Benchmarks.VectorBenchmarks-report.csv create mode 100644 benchmarks/FSharp.Stats.Benchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.Benchmarks.VectorBenchmarks-report.html create mode 100644 benchmarks/FSharp.Stats.Benchmarks/FSharp.Stats.Benchmarks.fsproj create mode 100644 benchmarks/FSharp.Stats.Benchmarks/Matrix.fs create mode 100644 benchmarks/FSharp.Stats.Benchmarks/Program.fs create mode 100644 benchmarks/FSharp.Stats.Benchmarks/Vector.fs create mode 100644 benchmarks/FSharp.Stats.LegacyBenchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.LegacyBenchmarks.MatrixBenchmarks-report-github.md create mode 100644 benchmarks/FSharp.Stats.LegacyBenchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.LegacyBenchmarks.MatrixBenchmarks-report.csv create mode 100644 benchmarks/FSharp.Stats.LegacyBenchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.LegacyBenchmarks.MatrixBenchmarks-report.html create mode 100644 benchmarks/FSharp.Stats.LegacyBenchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.LegacyBenchmarks.VectorBenchmarks-report-github.md create mode 100644 benchmarks/FSharp.Stats.LegacyBenchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.LegacyBenchmarks.VectorBenchmarks-report.csv create mode 100644 benchmarks/FSharp.Stats.LegacyBenchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.LegacyBenchmarks.VectorBenchmarks-report.html create mode 100644 benchmarks/FSharp.Stats.LegacyBenchmarks/FSharp.Stats.LegacyBenchmarks.fsproj create mode 100644 benchmarks/FSharp.Stats.LegacyBenchmarks/Matrix.fs create mode 100644 benchmarks/FSharp.Stats.LegacyBenchmarks/Program.fs create mode 100644 benchmarks/FSharp.Stats.LegacyBenchmarks/Vector.fs diff --git a/FSharp.Stats.sln b/FSharp.Stats.sln index bc6834aac..f70606d2f 100644 --- a/FSharp.Stats.sln +++ b/FSharp.Stats.sln @@ -57,13 +57,13 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "docs", "docs", "{23F9FB2E-6 docs\Intervals.fsx = docs\Intervals.fsx docs\LinearAlgebra.fsx = docs\LinearAlgebra.fsx docs\Matrix_Vector.fsx = docs\Matrix_Vector.fsx + docs\ML.fsx = docs\ML.fsx + docs\Normalization.fsx = docs\Normalization.fsx + docs\NuGet.config = docs\NuGet.config docs\Optimization.fsx = docs\Optimization.fsx docs\Quantiles.fsx = docs\Quantiles.fsx - docs\NuGet.config = docs\NuGet.config docs\Rank.fsx = docs\Rank.fsx docs\Signal.fsx = docs\Signal.fsx - docs\Normalization.fsx = docs\Normalization.fsx - docs\ML.fsx = docs\ML.fsx docs\Testing.fsx = docs\Testing.fsx docs\_template.html = docs\_template.html docs\_template.ipynb = docs\_template.ipynb @@ -76,6 +76,12 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "content", "content", "{50E3 EndProject Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FSharp.Stats.Interactive", "src\FSharp.Stats.Interactive\FSharp.Stats.Interactive.fsproj", "{D7BCF5C0-9E2B-4170-9390-607B0B65A8CD}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "benchmarks", "benchmarks", "{02EA681E-C7D8-13C7-8484-4AC65E1B71E8}" +EndProject +Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FSharp.Stats.Benchmarks", "benchmarks\FSharp.Stats.Benchmarks\FSharp.Stats.Benchmarks.fsproj", "{E3942700-8589-770A-6224-F6D2DDF977E8}" +EndProject +Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FSharp.Stats.LegacyBenchmarks", "benchmarks\FSharp.Stats.LegacyBenchmarks\FSharp.Stats.LegacyBenchmarks.fsproj", "{D84267B7-0C5A-4679-A63C-D94315A458CB}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -98,6 +104,14 @@ Global {D7BCF5C0-9E2B-4170-9390-607B0B65A8CD}.Debug|Any CPU.Build.0 = Debug|Any CPU {D7BCF5C0-9E2B-4170-9390-607B0B65A8CD}.Release|Any CPU.ActiveCfg = Release|Any CPU {D7BCF5C0-9E2B-4170-9390-607B0B65A8CD}.Release|Any CPU.Build.0 = Release|Any CPU + {E3942700-8589-770A-6224-F6D2DDF977E8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E3942700-8589-770A-6224-F6D2DDF977E8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E3942700-8589-770A-6224-F6D2DDF977E8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E3942700-8589-770A-6224-F6D2DDF977E8}.Release|Any CPU.Build.0 = Release|Any CPU + {D84267B7-0C5A-4679-A63C-D94315A458CB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D84267B7-0C5A-4679-A63C-D94315A458CB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D84267B7-0C5A-4679-A63C-D94315A458CB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D84267B7-0C5A-4679-A63C-D94315A458CB}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -106,6 +120,8 @@ Global {DA7E2263-283A-497F-B122-B2E1A5AC2C8C} = {ED8079DD-2B06-4030-9F0F-DC548F98E1C4} {8830D84C-C999-4816-9742-AC54A3CC1E13} = {7C6D08E7-3EAC-4335-8F4B-252C193C27C9} {50E3E339-AA4D-4FD2-8791-DEBD2EBF0504} = {23F9FB2E-6804-4AF9-B6D5-5CBD00E14A02} + {E3942700-8589-770A-6224-F6D2DDF977E8} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8} + {D84267B7-0C5A-4679-A63C-D94315A458CB} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {97270415-1E71-487B-BDF5-FBE2D8EFFD09} diff --git a/benchmarks/FSharp.Stats.Benchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.Benchmarks.MatrixBenchmarks-report-github.md b/benchmarks/FSharp.Stats.Benchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.Benchmarks.MatrixBenchmarks-report-github.md new file mode 100644 index 000000000..8d9d79de7 --- /dev/null +++ b/benchmarks/FSharp.Stats.Benchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.Benchmarks.MatrixBenchmarks-report-github.md @@ -0,0 +1,24 @@ +``` + +BenchmarkDotNet v0.14.0, Windows 11 (10.0.26100.3775) +13th Gen Intel Core i7-13800H, 1 CPU, 20 logical and 14 physical cores +.NET SDK 9.0.201 + [Host] : .NET 8.0.14 (8.0.1425.11118), X64 RyuJIT AVX2 DEBUG + DefaultJob : .NET 8.0.14 (8.0.1425.11118), X64 RyuJIT AVX2 + + +``` +| Method | Size | Mean | Error | StdDev | Gen0 | Gen1 | Gen2 | Allocated | +|------------------ |----- |------------------:|-----------------:|-----------------:|----------:|---------:|---------:|-----------:| +| **Add** | **10** | **38.33 ns** | **0.686 ns** | **0.642 ns** | **0.0682** | **0.0002** | **-** | **856 B** | +| MatMultiply | 10 | 436.79 ns | 2.776 ns | 2.461 ns | 0.1364 | - | - | 1712 B | +| MultiplyVector | 10 | 32.20 ns | 0.439 ns | 0.411 ns | 0.0083 | - | - | 104 B | +| MultiplyRowVector | 10 | 228.95 ns | 1.473 ns | 1.378 ns | 0.0975 | - | - | 1224 B | +| **Add** | **500** | **282,714.76 ns** | **5,416.776 ns** | **5,066.855 ns** | **206.5430** | **206.5430** | **206.5430** | **2000168 B** | +| MatMultiply | 500 | 17,514,488.54 ns | 216,980.386 ns | 202,963.588 ns | 375.0000 | 375.0000 | 375.0000 | 4000242 B | +| MultiplyVector | 500 | 33,458.92 ns | 334.582 ns | 312.968 ns | 0.3052 | - | - | 4024 B | +| MultiplyRowVector | 500 | 613,450.40 ns | 7,962.085 ns | 7,447.740 ns | 278.3203 | 3.9063 | - | 3504024 B | +| **Add** | **1000** | **1,360,217.58 ns** | **24,506.528 ns** | **21,724.399 ns** | **398.4375** | **398.4375** | **398.4375** | **8000206 B** | +| MatMultiply | 1000 | 143,946,340.15 ns | 2,872,749.805 ns | 4,556,485.985 ns | 250.0000 | 250.0000 | 250.0000 | 16000296 B | +| MultiplyVector | 1000 | 137,378.76 ns | 942.798 ns | 881.894 ns | 0.4883 | - | - | 8024 B | +| MultiplyRowVector | 1000 | 2,999,358.20 ns | 48,713.356 ns | 45,566.504 ns | 1113.2813 | 27.3438 | - | 14008026 B | diff --git a/benchmarks/FSharp.Stats.Benchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.Benchmarks.MatrixBenchmarks-report.csv b/benchmarks/FSharp.Stats.Benchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.Benchmarks.MatrixBenchmarks-report.csv new file mode 100644 index 000000000..7d087c45d --- /dev/null +++ b/benchmarks/FSharp.Stats.Benchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.Benchmarks.MatrixBenchmarks-report.csv @@ -0,0 +1,13 @@ +Method,Job,AnalyzeLaunchVariance,EvaluateOverhead,MaxAbsoluteError,MaxRelativeError,MinInvokeCount,MinIterationTime,OutlierMode,Affinity,EnvironmentVariables,Jit,LargeAddressAware,Platform,PowerPlanMode,Runtime,AllowVeryLargeObjects,Concurrent,CpuGroups,Force,HeapAffinitizeMask,HeapCount,NoAffinitize,RetainVm,Server,Arguments,BuildConfiguration,Clock,EngineFactory,NuGetReferences,Toolchain,IsMutator,InvocationCount,IterationCount,IterationTime,LaunchCount,MaxIterationCount,MaxWarmupIterationCount,MemoryRandomization,MinIterationCount,MinWarmupIterationCount,RunStrategy,UnrollFactor,WarmupCount,Size,Mean,Error,StdDev,Gen0,Gen1,Gen2,Allocated +Add,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,10,38.33 ns,0.686 ns,0.642 ns,0.0682,0.0002,0.0000,856 B +MatMultiply,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,10,436.79 ns,2.776 ns,2.461 ns,0.1364,0.0000,0.0000,1712 B +MultiplyVector,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,10,32.20 ns,0.439 ns,0.411 ns,0.0083,0.0000,0.0000,104 B +MultiplyRowVector,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,10,228.95 ns,1.473 ns,1.378 ns,0.0975,0.0000,0.0000,1224 B +Add,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,500,"282,714.76 ns","5,416.776 ns","5,066.855 ns",206.5430,206.5430,206.5430,2000168 B +MatMultiply,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,500,"17,514,488.54 ns","216,980.386 ns","202,963.588 ns",375.0000,375.0000,375.0000,4000242 B +MultiplyVector,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,500,"33,458.92 ns",334.582 ns,312.968 ns,0.3052,0.0000,0.0000,4024 B +MultiplyRowVector,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,500,"613,450.40 ns","7,962.085 ns","7,447.740 ns",278.3203,3.9063,0.0000,3504024 B +Add,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,1000,"1,360,217.58 ns","24,506.528 ns","21,724.399 ns",398.4375,398.4375,398.4375,8000206 B +MatMultiply,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,1000,"143,946,340.15 ns","2,872,749.805 ns","4,556,485.985 ns",250.0000,250.0000,250.0000,16000296 B +MultiplyVector,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,1000,"137,378.76 ns",942.798 ns,881.894 ns,0.4883,0.0000,0.0000,8024 B +MultiplyRowVector,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,1000,"2,999,358.20 ns","48,713.356 ns","45,566.504 ns",1113.2813,27.3438,0.0000,14008026 B diff --git a/benchmarks/FSharp.Stats.Benchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.Benchmarks.MatrixBenchmarks-report.html b/benchmarks/FSharp.Stats.Benchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.Benchmarks.MatrixBenchmarks-report.html new file mode 100644 index 000000000..cc4406755 --- /dev/null +++ b/benchmarks/FSharp.Stats.Benchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.Benchmarks.MatrixBenchmarks-report.html @@ -0,0 +1,41 @@ + + + + +FSharp.Stats.Benchmarks.MatrixBenchmarks-20250412-173020 + + + + +

+BenchmarkDotNet v0.14.0, Windows 11 (10.0.26100.3775)
+13th Gen Intel Core i7-13800H, 1 CPU, 20 logical and 14 physical cores
+.NET SDK 9.0.201
+  [Host]     : .NET 8.0.14 (8.0.1425.11118), X64 RyuJIT AVX2 DEBUG
+  DefaultJob : .NET 8.0.14 (8.0.1425.11118), X64 RyuJIT AVX2
+
+
+ + + + + + + + + + + + + + + + +
Method SizeMean Error StdDev Gen0Gen1Gen2Allocated
Add1038.33 ns0.686 ns0.642 ns0.06820.0002-856 B
MatMultiply10436.79 ns2.776 ns2.461 ns0.1364--1712 B
MultiplyVector1032.20 ns0.439 ns0.411 ns0.0083--104 B
MultiplyRowVector10228.95 ns1.473 ns1.378 ns0.0975--1224 B
Add500282,714.76 ns5,416.776 ns5,066.855 ns206.5430206.5430206.54302000168 B
MatMultiply50017,514,488.54 ns216,980.386 ns202,963.588 ns375.0000375.0000375.00004000242 B
MultiplyVector50033,458.92 ns334.582 ns312.968 ns0.3052--4024 B
MultiplyRowVector500613,450.40 ns7,962.085 ns7,447.740 ns278.32033.9063-3504024 B
Add10001,360,217.58 ns24,506.528 ns21,724.399 ns398.4375398.4375398.43758000206 B
MatMultiply1000143,946,340.15 ns2,872,749.805 ns4,556,485.985 ns250.0000250.0000250.000016000296 B
MultiplyVector1000137,378.76 ns942.798 ns881.894 ns0.4883--8024 B
MultiplyRowVector10002,999,358.20 ns48,713.356 ns45,566.504 ns1113.281327.3438-14008026 B
+ + diff --git a/benchmarks/FSharp.Stats.Benchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.Benchmarks.VectorBenchmarks-report-github.md b/benchmarks/FSharp.Stats.Benchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.Benchmarks.VectorBenchmarks-report-github.md new file mode 100644 index 000000000..dd345e8fe --- /dev/null +++ b/benchmarks/FSharp.Stats.Benchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.Benchmarks.VectorBenchmarks-report-github.md @@ -0,0 +1,24 @@ +``` + +BenchmarkDotNet v0.14.0, Windows 11 (10.0.26100.3775) +13th Gen Intel Core i7-13800H, 1 CPU, 20 logical and 14 physical cores +.NET SDK 9.0.201 + [Host] : .NET 8.0.14 (8.0.1425.11118), X64 RyuJIT AVX2 DEBUG + DefaultJob : .NET 8.0.14 (8.0.1425.11118), X64 RyuJIT AVX2 + + +``` +| Method | Size | Mean | Error | StdDev | Gen0 | Allocated | +|----------- |------ |------------:|----------:|----------:|-------:|----------:| +| **Add** | **100** | **34.90 ns** | **0.620 ns** | **0.580 ns** | **0.0656** | **824 B** | +| Subtract | 100 | 34.40 ns | 0.533 ns | 0.445 ns | 0.0656 | 824 B | +| DotProduct | 100 | 17.35 ns | 0.160 ns | 0.150 ns | - | - | +| Norm | 100 | 17.25 ns | 0.085 ns | 0.076 ns | - | - | +| **Add** | **1000** | **336.82 ns** | **3.095 ns** | **2.585 ns** | **0.6390** | **8024 B** | +| Subtract | 1000 | 342.57 ns | 6.743 ns | 11.631 ns | 0.6390 | 8024 B | +| DotProduct | 1000 | 166.93 ns | 2.838 ns | 3.154 ns | - | - | +| Norm | 1000 | 166.51 ns | 0.808 ns | 0.756 ns | - | - | +| **Add** | **10000** | **3,557.53 ns** | **8.350 ns** | **7.402 ns** | **6.3286** | **80024 B** | +| Subtract | 10000 | 3,563.04 ns | 11.255 ns | 9.977 ns | 6.3286 | 80024 B | +| DotProduct | 10000 | 1,824.85 ns | 27.335 ns | 24.232 ns | - | - | +| Norm | 10000 | 1,639.84 ns | 15.430 ns | 14.433 ns | - | - | diff --git a/benchmarks/FSharp.Stats.Benchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.Benchmarks.VectorBenchmarks-report.csv b/benchmarks/FSharp.Stats.Benchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.Benchmarks.VectorBenchmarks-report.csv new file mode 100644 index 000000000..129047732 --- /dev/null +++ b/benchmarks/FSharp.Stats.Benchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.Benchmarks.VectorBenchmarks-report.csv @@ -0,0 +1,13 @@ +Method,Job,AnalyzeLaunchVariance,EvaluateOverhead,MaxAbsoluteError,MaxRelativeError,MinInvokeCount,MinIterationTime,OutlierMode,Affinity,EnvironmentVariables,Jit,LargeAddressAware,Platform,PowerPlanMode,Runtime,AllowVeryLargeObjects,Concurrent,CpuGroups,Force,HeapAffinitizeMask,HeapCount,NoAffinitize,RetainVm,Server,Arguments,BuildConfiguration,Clock,EngineFactory,NuGetReferences,Toolchain,IsMutator,InvocationCount,IterationCount,IterationTime,LaunchCount,MaxIterationCount,MaxWarmupIterationCount,MemoryRandomization,MinIterationCount,MinWarmupIterationCount,RunStrategy,UnrollFactor,WarmupCount,Size,Mean,Error,StdDev,Gen0,Allocated +Add,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,100,34.90 ns,0.620 ns,0.580 ns,0.0656,824 B +Subtract,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,100,34.40 ns,0.533 ns,0.445 ns,0.0656,824 B +DotProduct,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,100,17.35 ns,0.160 ns,0.150 ns,0.0000,0 B +Norm,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,100,17.25 ns,0.085 ns,0.076 ns,0.0000,0 B +Add,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,1000,336.82 ns,3.095 ns,2.585 ns,0.6390,8024 B +Subtract,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,1000,342.57 ns,6.743 ns,11.631 ns,0.6390,8024 B +DotProduct,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,1000,166.93 ns,2.838 ns,3.154 ns,0.0000,0 B +Norm,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,1000,166.51 ns,0.808 ns,0.756 ns,0.0000,0 B +Add,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,10000,"3,557.53 ns",8.350 ns,7.402 ns,6.3286,80024 B +Subtract,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,10000,"3,563.04 ns",11.255 ns,9.977 ns,6.3286,80024 B +DotProduct,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,10000,"1,824.85 ns",27.335 ns,24.232 ns,0.0000,0 B +Norm,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,10000,"1,639.84 ns",15.430 ns,14.433 ns,0.0000,0 B diff --git a/benchmarks/FSharp.Stats.Benchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.Benchmarks.VectorBenchmarks-report.html b/benchmarks/FSharp.Stats.Benchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.Benchmarks.VectorBenchmarks-report.html new file mode 100644 index 000000000..886ab7fca --- /dev/null +++ b/benchmarks/FSharp.Stats.Benchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.Benchmarks.VectorBenchmarks-report.html @@ -0,0 +1,41 @@ + + + + +FSharp.Stats.Benchmarks.VectorBenchmarks-20250412-160341 + + + + +

+BenchmarkDotNet v0.14.0, Windows 11 (10.0.26100.3775)
+13th Gen Intel Core i7-13800H, 1 CPU, 20 logical and 14 physical cores
+.NET SDK 9.0.201
+  [Host]     : .NET 8.0.14 (8.0.1425.11118), X64 RyuJIT AVX2 DEBUG
+  DefaultJob : .NET 8.0.14 (8.0.1425.11118), X64 RyuJIT AVX2
+
+
+ + + + + + + + + + + + + + + + +
MethodSizeMean ErrorStdDevGen0Allocated
Add10034.90 ns0.620 ns0.580 ns0.0656824 B
Subtract10034.40 ns0.533 ns0.445 ns0.0656824 B
DotProduct10017.35 ns0.160 ns0.150 ns--
Norm10017.25 ns0.085 ns0.076 ns--
Add1000336.82 ns3.095 ns2.585 ns0.63908024 B
Subtract1000342.57 ns6.743 ns11.631 ns0.63908024 B
DotProduct1000166.93 ns2.838 ns3.154 ns--
Norm1000166.51 ns0.808 ns0.756 ns--
Add100003,557.53 ns8.350 ns7.402 ns6.328680024 B
Subtract100003,563.04 ns11.255 ns9.977 ns6.328680024 B
DotProduct100001,824.85 ns27.335 ns24.232 ns--
Norm100001,639.84 ns15.430 ns14.433 ns--
+ + diff --git a/benchmarks/FSharp.Stats.Benchmarks/FSharp.Stats.Benchmarks.fsproj b/benchmarks/FSharp.Stats.Benchmarks/FSharp.Stats.Benchmarks.fsproj new file mode 100644 index 000000000..647da67b2 --- /dev/null +++ b/benchmarks/FSharp.Stats.Benchmarks/FSharp.Stats.Benchmarks.fsproj @@ -0,0 +1,22 @@ + + + + Exe + net8.0 + + + + + + + + + + + + + + + + + diff --git a/benchmarks/FSharp.Stats.Benchmarks/Matrix.fs b/benchmarks/FSharp.Stats.Benchmarks/Matrix.fs new file mode 100644 index 000000000..516becad8 --- /dev/null +++ b/benchmarks/FSharp.Stats.Benchmarks/Matrix.fs @@ -0,0 +1,44 @@ +namespace FSharp.Stats.Benchmarks + +open System +open BenchmarkDotNet.Attributes +open BenchmarkDotNet.Running +open FSharp.Stats + +[] +type MatrixBenchmarks() = + + let mutable matrixA = Unchecked.defaultof> + let mutable matrixB = Unchecked.defaultof> + let mutable vector = [||] + + // Parameterize matrix sizes + [] + member val Size = 0 with get, set + + [] + member this.Setup() = + // Initialize matrices and vector + matrixA <- Matrix.init this.Size this.Size (fun i j -> float (i + j)) + matrixB <- Matrix.init this.Size this.Size (fun i j -> float (i * j)) + vector <- Array.init this.Size (fun i -> float i) + + [] + member _.Add() = + let result = Matrix.add matrixA matrixB + GC.KeepAlive(result) // Prevent dead code elimination + + [] + member _.MatMultiply() = + let result = Matrix.matmul matrixA matrixB + GC.KeepAlive(result) // Prevent dead code elimination + + [] + member _.MultiplyVector() = + let result = Matrix.muliplyVector matrixA vector + GC.KeepAlive(result) // Prevent dead code elimination + + [] + member _.MultiplyRowVector() = + let result = Matrix.multiplyRowVector vector matrixA + GC.KeepAlive(result) // Prevent dead code elimination diff --git a/benchmarks/FSharp.Stats.Benchmarks/Program.fs b/benchmarks/FSharp.Stats.Benchmarks/Program.fs new file mode 100644 index 000000000..d15db5097 --- /dev/null +++ b/benchmarks/FSharp.Stats.Benchmarks/Program.fs @@ -0,0 +1,13 @@ +open System +open BenchmarkDotNet.Running +open FSharp.Stats.Benchmarks + +[] +let Main args = + // Register multiple benchmark classes + let switcher = BenchmarkSwitcher [| + typeof + typeof + |] + switcher.Run args |> ignore + 0 diff --git a/benchmarks/FSharp.Stats.Benchmarks/Vector.fs b/benchmarks/FSharp.Stats.Benchmarks/Vector.fs new file mode 100644 index 000000000..b72d29d5f --- /dev/null +++ b/benchmarks/FSharp.Stats.Benchmarks/Vector.fs @@ -0,0 +1,48 @@ +namespace FSharp.Stats.Benchmarks + + +open System +open BenchmarkDotNet.Attributes +open BenchmarkDotNet.Running +open FSharp.Stats + +[] +type VectorBenchmarks() = + + let mutable vector1 = [||] + let mutable vector2 = [||] + + // Parameterize vector sizes + [] + member val Size = 0 with get, set + + [] + member this.Setup() = + vector1 <- Array.init this.Size (fun i -> float i) + vector2 <- Array.init this.Size (fun i -> float (i * 2)) + + [] + member _.Add() = + let result = Vector.add vector1 vector2 + GC.KeepAlive(result) // Prevents the result from being optimized away + + [] + member _.multiply() = + let result = Vector.multiply vector1 vector2 + GC.KeepAlive(result) // Prevents the result from being optimized away + + [] + member _.DotProduct() = + let result = Vector.dot vector1 vector2 + GC.KeepAlive(result) // Prevents the result from being optimized away + + [] + member _.CrossProduct() = + let result = Vector.cross vector1 vector2 + GC.KeepAlive(result) // Prevents the result from being optimized away + + [] + member _.Norm() = + let result = Vector.norm vector1 + GC.KeepAlive(result) // Prevents the result from being optimized away + diff --git a/benchmarks/FSharp.Stats.LegacyBenchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.LegacyBenchmarks.MatrixBenchmarks-report-github.md b/benchmarks/FSharp.Stats.LegacyBenchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.LegacyBenchmarks.MatrixBenchmarks-report-github.md new file mode 100644 index 000000000..1a1f73202 --- /dev/null +++ b/benchmarks/FSharp.Stats.LegacyBenchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.LegacyBenchmarks.MatrixBenchmarks-report-github.md @@ -0,0 +1,24 @@ +``` + +BenchmarkDotNet v0.14.0, Windows 11 (10.0.26100.3775) +13th Gen Intel Core i7-13800H, 1 CPU, 20 logical and 14 physical cores +.NET SDK 9.0.201 + [Host] : .NET 8.0.14 (8.0.1425.11118), X64 RyuJIT AVX2 DEBUG + DefaultJob : .NET 8.0.14 (8.0.1425.11118), X64 RyuJIT AVX2 + + +``` +| Method | Size | Mean | Error | StdDev | Gen0 | Gen1 | Gen2 | Allocated | +|------------------ |----- |--------------------:|------------------:|------------------:|---------:|---------:|---------:|----------:| +| **Add** | **10** | **169.55 ns** | **2.046 ns** | **1.914 ns** | **0.0713** | **-** | **-** | **896 B** | +| MatMultiply | 10 | 1,084.51 ns | 8.513 ns | 7.963 ns | 0.0706 | - | - | 896 B | +| MultiplyVector | 10 | 73.57 ns | 0.786 ns | 0.736 ns | 0.0107 | - | - | 136 B | +| MultiplyRowVector | 10 | 88.03 ns | 0.853 ns | 0.756 ns | 0.0235 | - | - | 296 B | +| **Add** | **500** | **456,439.67 ns** | **3,024.351 ns** | **2,681.009 ns** | **201.1719** | **201.1719** | **201.1719** | **2000166 B** | +| MatMultiply | 500 | 119,541,061.36 ns | 547,145.379 ns | 671,943.721 ns | - | - | - | 2000196 B | +| MultiplyVector | 500 | 156,250.79 ns | 1,292.534 ns | 1,145.798 ns | 0.2441 | - | - | 4056 B | +| MultiplyRowVector | 500 | 183,556.08 ns | 1,804.318 ns | 1,687.760 ns | 0.4883 | - | - | 8136 B | +| **Add** | **1000** | **2,104,678.07 ns** | **35,051.052 ns** | **32,786.776 ns** | **148.4375** | **148.4375** | **148.4375** | **8000146 B** | +| MatMultiply | 1000 | 1,164,345,128.57 ns | 15,512,547.293 ns | 13,751,469.125 ns | - | - | - | 8000496 B | +| MultiplyVector | 1000 | 620,032.55 ns | 3,989.956 ns | 3,732.207 ns | - | - | - | 8056 B | +| MultiplyRowVector | 1000 | 880,712.25 ns | 8,715.623 ns | 8,152.599 ns | 0.9766 | - | - | 16136 B | diff --git a/benchmarks/FSharp.Stats.LegacyBenchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.LegacyBenchmarks.MatrixBenchmarks-report.csv b/benchmarks/FSharp.Stats.LegacyBenchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.LegacyBenchmarks.MatrixBenchmarks-report.csv new file mode 100644 index 000000000..b0ed15a08 --- /dev/null +++ b/benchmarks/FSharp.Stats.LegacyBenchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.LegacyBenchmarks.MatrixBenchmarks-report.csv @@ -0,0 +1,13 @@ +Method,Job,AnalyzeLaunchVariance,EvaluateOverhead,MaxAbsoluteError,MaxRelativeError,MinInvokeCount,MinIterationTime,OutlierMode,Affinity,EnvironmentVariables,Jit,LargeAddressAware,Platform,PowerPlanMode,Runtime,AllowVeryLargeObjects,Concurrent,CpuGroups,Force,HeapAffinitizeMask,HeapCount,NoAffinitize,RetainVm,Server,Arguments,BuildConfiguration,Clock,EngineFactory,NuGetReferences,Toolchain,IsMutator,InvocationCount,IterationCount,IterationTime,LaunchCount,MaxIterationCount,MaxWarmupIterationCount,MemoryRandomization,MinIterationCount,MinWarmupIterationCount,RunStrategy,UnrollFactor,WarmupCount,Size,Mean,Error,StdDev,Gen0,Gen1,Gen2,Allocated +Add,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,10,169.55 ns,2.046 ns,1.914 ns,0.0713,0.0000,0.0000,896 B +MatMultiply,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,10,"1,084.51 ns",8.513 ns,7.963 ns,0.0706,0.0000,0.0000,896 B +MultiplyVector,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,10,73.57 ns,0.786 ns,0.736 ns,0.0107,0.0000,0.0000,136 B +MultiplyRowVector,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,10,88.03 ns,0.853 ns,0.756 ns,0.0235,0.0000,0.0000,296 B +Add,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,500,"456,439.67 ns","3,024.351 ns","2,681.009 ns",201.1719,201.1719,201.1719,2000166 B +MatMultiply,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,500,"119,541,061.36 ns","547,145.379 ns","671,943.721 ns",0.0000,0.0000,0.0000,2000196 B +MultiplyVector,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,500,"156,250.79 ns","1,292.534 ns","1,145.798 ns",0.2441,0.0000,0.0000,4056 B +MultiplyRowVector,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,500,"183,556.08 ns","1,804.318 ns","1,687.760 ns",0.4883,0.0000,0.0000,8136 B +Add,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,1000,"2,104,678.07 ns","35,051.052 ns","32,786.776 ns",148.4375,148.4375,148.4375,8000146 B +MatMultiply,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,1000,"1,164,345,128.57 ns","15,512,547.293 ns","13,751,469.125 ns",0.0000,0.0000,0.0000,8000496 B +MultiplyVector,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,1000,"620,032.55 ns","3,989.956 ns","3,732.207 ns",0.0000,0.0000,0.0000,8056 B +MultiplyRowVector,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,1000,"880,712.25 ns","8,715.623 ns","8,152.599 ns",0.9766,0.0000,0.0000,16136 B diff --git a/benchmarks/FSharp.Stats.LegacyBenchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.LegacyBenchmarks.MatrixBenchmarks-report.html b/benchmarks/FSharp.Stats.LegacyBenchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.LegacyBenchmarks.MatrixBenchmarks-report.html new file mode 100644 index 000000000..045741468 --- /dev/null +++ b/benchmarks/FSharp.Stats.LegacyBenchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.LegacyBenchmarks.MatrixBenchmarks-report.html @@ -0,0 +1,41 @@ + + + + +FSharp.Stats.LegacyBenchmarks.MatrixBenchmarks-20250412-172149 + + + + +

+BenchmarkDotNet v0.14.0, Windows 11 (10.0.26100.3775)
+13th Gen Intel Core i7-13800H, 1 CPU, 20 logical and 14 physical cores
+.NET SDK 9.0.201
+  [Host]     : .NET 8.0.14 (8.0.1425.11118), X64 RyuJIT AVX2 DEBUG
+  DefaultJob : .NET 8.0.14 (8.0.1425.11118), X64 RyuJIT AVX2
+
+
+ + + + + + + + + + + + + + + + +
Method SizeMean Error StdDev Gen0Gen1Gen2Allocated
Add10169.55 ns2.046 ns1.914 ns0.0713--896 B
MatMultiply101,084.51 ns8.513 ns7.963 ns0.0706--896 B
MultiplyVector1073.57 ns0.786 ns0.736 ns0.0107--136 B
MultiplyRowVector1088.03 ns0.853 ns0.756 ns0.0235--296 B
Add500456,439.67 ns3,024.351 ns2,681.009 ns201.1719201.1719201.17192000166 B
MatMultiply500119,541,061.36 ns547,145.379 ns671,943.721 ns---2000196 B
MultiplyVector500156,250.79 ns1,292.534 ns1,145.798 ns0.2441--4056 B
MultiplyRowVector500183,556.08 ns1,804.318 ns1,687.760 ns0.4883--8136 B
Add10002,104,678.07 ns35,051.052 ns32,786.776 ns148.4375148.4375148.43758000146 B
MatMultiply10001,164,345,128.57 ns15,512,547.293 ns13,751,469.125 ns---8000496 B
MultiplyVector1000620,032.55 ns3,989.956 ns3,732.207 ns---8056 B
MultiplyRowVector1000880,712.25 ns8,715.623 ns8,152.599 ns0.9766--16136 B
+ + diff --git a/benchmarks/FSharp.Stats.LegacyBenchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.LegacyBenchmarks.VectorBenchmarks-report-github.md b/benchmarks/FSharp.Stats.LegacyBenchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.LegacyBenchmarks.VectorBenchmarks-report-github.md new file mode 100644 index 000000000..4805e1c21 --- /dev/null +++ b/benchmarks/FSharp.Stats.LegacyBenchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.LegacyBenchmarks.VectorBenchmarks-report-github.md @@ -0,0 +1,24 @@ +``` + +BenchmarkDotNet v0.14.0, Windows 11 (10.0.26100.3775) +13th Gen Intel Core i7-13800H, 1 CPU, 20 logical and 14 physical cores +.NET SDK 9.0.201 + [Host] : .NET 8.0.14 (8.0.1425.11118), X64 RyuJIT AVX2 DEBUG + DefaultJob : .NET 8.0.14 (8.0.1425.11118), X64 RyuJIT AVX2 + + +``` +| Method | Size | Mean | Error | StdDev | Gen0 | Gen1 | Allocated | +|----------- |------ |-------------:|-----------:|-----------:|-------:|-------:|----------:| +| **Add** | **100** | **73.21 ns** | **0.966 ns** | **0.903 ns** | **0.0682** | **0.0001** | **856 B** | +| Subtract | 100 | 72.11 ns | 0.991 ns | 0.927 ns | 0.0682 | 0.0001 | 856 B | +| DotProduct | 100 | 47.26 ns | 0.188 ns | 0.176 ns | - | - | - | +| Norm | 100 | 206.61 ns | 0.945 ns | 0.789 ns | - | - | - | +| **Add** | **1000** | **599.70 ns** | **6.201 ns** | **5.497 ns** | **0.6418** | **0.0191** | **8056 B** | +| Subtract | 1000 | 596.90 ns | 7.515 ns | 7.030 ns | 0.6418 | 0.0191 | 8056 B | +| DotProduct | 1000 | 407.63 ns | 1.324 ns | 1.239 ns | - | - | - | +| Norm | 1000 | 2,007.79 ns | 18.324 ns | 17.140 ns | - | - | - | +| **Add** | **10000** | **6,141.20 ns** | **118.523 ns** | **110.867 ns** | **6.3629** | **1.5869** | **80056 B** | +| Subtract | 10000 | 6,006.92 ns | 76.595 ns | 71.647 ns | 6.3629 | 1.5869 | 80056 B | +| DotProduct | 10000 | 3,980.27 ns | 28.423 ns | 26.587 ns | - | - | - | +| Norm | 10000 | 20,024.93 ns | 137.963 ns | 129.050 ns | - | - | - | diff --git a/benchmarks/FSharp.Stats.LegacyBenchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.LegacyBenchmarks.VectorBenchmarks-report.csv b/benchmarks/FSharp.Stats.LegacyBenchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.LegacyBenchmarks.VectorBenchmarks-report.csv new file mode 100644 index 000000000..b3dcc06f3 --- /dev/null +++ b/benchmarks/FSharp.Stats.LegacyBenchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.LegacyBenchmarks.VectorBenchmarks-report.csv @@ -0,0 +1,13 @@ +Method,Job,AnalyzeLaunchVariance,EvaluateOverhead,MaxAbsoluteError,MaxRelativeError,MinInvokeCount,MinIterationTime,OutlierMode,Affinity,EnvironmentVariables,Jit,LargeAddressAware,Platform,PowerPlanMode,Runtime,AllowVeryLargeObjects,Concurrent,CpuGroups,Force,HeapAffinitizeMask,HeapCount,NoAffinitize,RetainVm,Server,Arguments,BuildConfiguration,Clock,EngineFactory,NuGetReferences,Toolchain,IsMutator,InvocationCount,IterationCount,IterationTime,LaunchCount,MaxIterationCount,MaxWarmupIterationCount,MemoryRandomization,MinIterationCount,MinWarmupIterationCount,RunStrategy,UnrollFactor,WarmupCount,Size,Mean,Error,StdDev,Gen0,Gen1,Allocated +Add,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,100,73.21 ns,0.966 ns,0.903 ns,0.0682,0.0001,856 B +Subtract,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,100,72.11 ns,0.991 ns,0.927 ns,0.0682,0.0001,856 B +DotProduct,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,100,47.26 ns,0.188 ns,0.176 ns,0.0000,0.0000,0 B +Norm,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,100,206.61 ns,0.945 ns,0.789 ns,0.0000,0.0000,0 B +Add,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,1000,599.70 ns,6.201 ns,5.497 ns,0.6418,0.0191,8056 B +Subtract,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,1000,596.90 ns,7.515 ns,7.030 ns,0.6418,0.0191,8056 B +DotProduct,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,1000,407.63 ns,1.324 ns,1.239 ns,0.0000,0.0000,0 B +Norm,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,1000,"2,007.79 ns",18.324 ns,17.140 ns,0.0000,0.0000,0 B +Add,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,10000,"6,141.20 ns",118.523 ns,110.867 ns,6.3629,1.5869,80056 B +Subtract,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,10000,"6,006.92 ns",76.595 ns,71.647 ns,6.3629,1.5869,80056 B +DotProduct,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,10000,"3,980.27 ns",28.423 ns,26.587 ns,0.0000,0.0000,0 B +Norm,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,10000,"20,024.93 ns",137.963 ns,129.050 ns,0.0000,0.0000,0 B diff --git a/benchmarks/FSharp.Stats.LegacyBenchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.LegacyBenchmarks.VectorBenchmarks-report.html b/benchmarks/FSharp.Stats.LegacyBenchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.LegacyBenchmarks.VectorBenchmarks-report.html new file mode 100644 index 000000000..72a750e35 --- /dev/null +++ b/benchmarks/FSharp.Stats.LegacyBenchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.LegacyBenchmarks.VectorBenchmarks-report.html @@ -0,0 +1,41 @@ + + + + +FSharp.Stats.LegacyBenchmarks.VectorBenchmarks-20250412-165006 + + + + +

+BenchmarkDotNet v0.14.0, Windows 11 (10.0.26100.3775)
+13th Gen Intel Core i7-13800H, 1 CPU, 20 logical and 14 physical cores
+.NET SDK 9.0.201
+  [Host]     : .NET 8.0.14 (8.0.1425.11118), X64 RyuJIT AVX2 DEBUG
+  DefaultJob : .NET 8.0.14 (8.0.1425.11118), X64 RyuJIT AVX2
+
+
+ + + + + + + + + + + + + + + + +
MethodSizeMean ErrorStdDevGen0Gen1Allocated
Add10073.21 ns0.966 ns0.903 ns0.06820.0001856 B
Subtract10072.11 ns0.991 ns0.927 ns0.06820.0001856 B
DotProduct10047.26 ns0.188 ns0.176 ns---
Norm100206.61 ns0.945 ns0.789 ns---
Add1000599.70 ns6.201 ns5.497 ns0.64180.01918056 B
Subtract1000596.90 ns7.515 ns7.030 ns0.64180.01918056 B
DotProduct1000407.63 ns1.324 ns1.239 ns---
Norm10002,007.79 ns18.324 ns17.140 ns---
Add100006,141.20 ns118.523 ns110.867 ns6.36291.586980056 B
Subtract100006,006.92 ns76.595 ns71.647 ns6.36291.586980056 B
DotProduct100003,980.27 ns28.423 ns26.587 ns---
Norm1000020,024.93 ns137.963 ns129.050 ns---
+ + diff --git a/benchmarks/FSharp.Stats.LegacyBenchmarks/FSharp.Stats.LegacyBenchmarks.fsproj b/benchmarks/FSharp.Stats.LegacyBenchmarks/FSharp.Stats.LegacyBenchmarks.fsproj new file mode 100644 index 000000000..98bde68c0 --- /dev/null +++ b/benchmarks/FSharp.Stats.LegacyBenchmarks/FSharp.Stats.LegacyBenchmarks.fsproj @@ -0,0 +1,19 @@ + + + + Exe + net8.0 + + + + + + + + + + + + + + diff --git a/benchmarks/FSharp.Stats.LegacyBenchmarks/Matrix.fs b/benchmarks/FSharp.Stats.LegacyBenchmarks/Matrix.fs new file mode 100644 index 000000000..8a566b79d --- /dev/null +++ b/benchmarks/FSharp.Stats.LegacyBenchmarks/Matrix.fs @@ -0,0 +1,44 @@ +namespace FSharp.Stats.LegacyBenchmarks + +open System +open BenchmarkDotNet.Attributes +open BenchmarkDotNet.Running +open FSharp.Stats + +[] +type MatrixBenchmarks() = + + let mutable matrixA = Unchecked.defaultof> + let mutable matrixB = Unchecked.defaultof> + let mutable vector = vector [||] + + // Parameterize matrix sizes + [] + member val Size = 0 with get, set + + [] + member this.Setup() = + // Initialize matrices and vector + matrixA <- Matrix.init this.Size this.Size (fun i j -> float (i + j)) + matrixB <- Matrix.init this.Size this.Size (fun i j -> float (i * j)) + vector <- Vector.init this.Size (fun i -> float i) + + [] + member _.Add() = + let result = Matrix.add matrixA matrixB + GC.KeepAlive(result) // Prevent dead code elimination + + [] + member _.MatMultiply() = + let result = Matrix.mul matrixA matrixB + GC.KeepAlive(result) // Prevent dead code elimination + + [] + member _.MultiplyVector() = + let result = Matrix.mulV matrixA vector + GC.KeepAlive(result) // Prevent dead code elimination + + [] + member _.MultiplyRowVector() = + let result = Matrix.mulRV vector.Transpose matrixA + GC.KeepAlive(result) // Prevent dead code elimination diff --git a/benchmarks/FSharp.Stats.LegacyBenchmarks/Program.fs b/benchmarks/FSharp.Stats.LegacyBenchmarks/Program.fs new file mode 100644 index 000000000..5a6658fd3 --- /dev/null +++ b/benchmarks/FSharp.Stats.LegacyBenchmarks/Program.fs @@ -0,0 +1,15 @@ + +open System +open BenchmarkDotNet.Attributes +open BenchmarkDotNet.Running +open FSharp.Stats.LegacyBenchmarks + +[] +let Main args = + // Register multiple benchmark classes + let switcher = BenchmarkSwitcher [| + typeof + typeof + |] + switcher.Run args |> ignore + 0 diff --git a/benchmarks/FSharp.Stats.LegacyBenchmarks/Vector.fs b/benchmarks/FSharp.Stats.LegacyBenchmarks/Vector.fs new file mode 100644 index 000000000..ebc866093 --- /dev/null +++ b/benchmarks/FSharp.Stats.LegacyBenchmarks/Vector.fs @@ -0,0 +1,48 @@ +namespace FSharp.Stats.LegacyBenchmarks + + +open System +open BenchmarkDotNet.Attributes +open BenchmarkDotNet.Running +open FSharp.Stats + +[] +type VectorBenchmarks() = + + let mutable vector1 = vector [||] + let mutable vector2 = vector [||] + + // Parameterize vector sizes + [] + member val Size = 0 with get, set + + [] + member this.Setup() = + vector1 <- Vector.init this.Size (fun i -> float i) + vector2 <- Vector.init this.Size (fun i -> float (i * 2)) + + [] + member _.Add() = + let result = Vector.add vector1 vector2 + GC.KeepAlive(result) // Prevents the result from being optimized away + + [] + member _.multiply() = + let result = Vector.cptMul vector1 vector2 + GC.KeepAlive(result) // Prevents the result from being optimized away + + [] + member _.DotProduct() = + let result = Vector.dot vector1 vector2 + GC.KeepAlive(result) // Prevents the result from being optimized away + + [] + member _.CrossProduct() = + let result = Vector.mulRVV vector1.Transpose vector2 + GC.KeepAlive(result) // Prevents the result from being optimized away + + [] + member _.Norm() = + let result = Vector.norm vector1 + GC.KeepAlive(result) // Prevents the result from being optimized away + diff --git a/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj b/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj index 4985f80a9..16eb6aae5 100644 --- a/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj +++ b/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj @@ -6,20 +6,21 @@ + + - - + From 24bc9b39c7497f152502d122c4fc09698ce258d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20M=C3=BChlhaus?= Date: Sat, 12 Apr 2025 18:58:53 +0200 Subject: [PATCH 030/121] Improved Vector^T * Matrix with new benchmark --- ...nchmarks.MatrixBenchmarks-report-github.md | 28 ++++++------ ...ats.Benchmarks.MatrixBenchmarks-report.csv | 24 +++++----- ...ts.Benchmarks.MatrixBenchmarks-report.html | 26 +++++------ src/FSharp.Stats/AlgTypes/Matrix.fs | 44 ++++--------------- 4 files changed, 48 insertions(+), 74 deletions(-) diff --git a/benchmarks/FSharp.Stats.Benchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.Benchmarks.MatrixBenchmarks-report-github.md b/benchmarks/FSharp.Stats.Benchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.Benchmarks.MatrixBenchmarks-report-github.md index 8d9d79de7..6760521d6 100644 --- a/benchmarks/FSharp.Stats.Benchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.Benchmarks.MatrixBenchmarks-report-github.md +++ b/benchmarks/FSharp.Stats.Benchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.Benchmarks.MatrixBenchmarks-report-github.md @@ -8,17 +8,17 @@ BenchmarkDotNet v0.14.0, Windows 11 (10.0.26100.3775) ``` -| Method | Size | Mean | Error | StdDev | Gen0 | Gen1 | Gen2 | Allocated | -|------------------ |----- |------------------:|-----------------:|-----------------:|----------:|---------:|---------:|-----------:| -| **Add** | **10** | **38.33 ns** | **0.686 ns** | **0.642 ns** | **0.0682** | **0.0002** | **-** | **856 B** | -| MatMultiply | 10 | 436.79 ns | 2.776 ns | 2.461 ns | 0.1364 | - | - | 1712 B | -| MultiplyVector | 10 | 32.20 ns | 0.439 ns | 0.411 ns | 0.0083 | - | - | 104 B | -| MultiplyRowVector | 10 | 228.95 ns | 1.473 ns | 1.378 ns | 0.0975 | - | - | 1224 B | -| **Add** | **500** | **282,714.76 ns** | **5,416.776 ns** | **5,066.855 ns** | **206.5430** | **206.5430** | **206.5430** | **2000168 B** | -| MatMultiply | 500 | 17,514,488.54 ns | 216,980.386 ns | 202,963.588 ns | 375.0000 | 375.0000 | 375.0000 | 4000242 B | -| MultiplyVector | 500 | 33,458.92 ns | 334.582 ns | 312.968 ns | 0.3052 | - | - | 4024 B | -| MultiplyRowVector | 500 | 613,450.40 ns | 7,962.085 ns | 7,447.740 ns | 278.3203 | 3.9063 | - | 3504024 B | -| **Add** | **1000** | **1,360,217.58 ns** | **24,506.528 ns** | **21,724.399 ns** | **398.4375** | **398.4375** | **398.4375** | **8000206 B** | -| MatMultiply | 1000 | 143,946,340.15 ns | 2,872,749.805 ns | 4,556,485.985 ns | 250.0000 | 250.0000 | 250.0000 | 16000296 B | -| MultiplyVector | 1000 | 137,378.76 ns | 942.798 ns | 881.894 ns | 0.4883 | - | - | 8024 B | -| MultiplyRowVector | 1000 | 2,999,358.20 ns | 48,713.356 ns | 45,566.504 ns | 1113.2813 | 27.3438 | - | 14008026 B | +| Method | Size | Mean | Error | StdDev | Gen0 | Gen1 | Gen2 | Allocated | +|------------------ |----- |------------------:|-----------------:|-----------------:|---------:|---------:|---------:|-----------:| +| **Add** | **10** | **40.06 ns** | **0.550 ns** | **0.488 ns** | **0.0682** | **0.0002** | **-** | **856 B** | +| MatMultiply | 10 | 442.83 ns | 2.841 ns | 2.373 ns | 0.1364 | - | - | 1712 B | +| MultiplyVector | 10 | 33.28 ns | 0.425 ns | 0.397 ns | 0.0083 | - | - | 104 B | +| MultiplyRowVector | 10 | 50.55 ns | 0.500 ns | 0.468 ns | 0.0083 | - | - | 104 B | +| **Add** | **500** | **280,736.93 ns** | **5,376.045 ns** | **5,279.995 ns** | **212.4023** | **212.4023** | **212.4023** | **2000164 B** | +| MatMultiply | 500 | 17,572,322.92 ns | 318,470.458 ns | 297,897.464 ns | 375.0000 | 375.0000 | 375.0000 | 4000242 B | +| MultiplyVector | 500 | 31,726.43 ns | 202.403 ns | 189.328 ns | 0.3052 | - | - | 4024 B | +| MultiplyRowVector | 500 | 127,918.10 ns | 996.783 ns | 832.359 ns | 0.2441 | - | - | 4024 B | +| **Add** | **1000** | **1,377,902.79 ns** | **20,816.673 ns** | **18,453.438 ns** | **148.4375** | **148.4375** | **148.4375** | **8000105 B** | +| MatMultiply | 1000 | 143,300,325.00 ns | 1,445,291.857 ns | 1,606,438.070 ns | 250.0000 | 250.0000 | 250.0000 | 16000296 B | +| MultiplyVector | 1000 | 135,247.34 ns | 1,334.685 ns | 1,248.465 ns | 0.4883 | - | - | 8024 B | +| MultiplyRowVector | 1000 | 677,195.35 ns | 6,896.007 ns | 6,450.529 ns | - | - | - | 8024 B | diff --git a/benchmarks/FSharp.Stats.Benchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.Benchmarks.MatrixBenchmarks-report.csv b/benchmarks/FSharp.Stats.Benchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.Benchmarks.MatrixBenchmarks-report.csv index 7d087c45d..27e1571ed 100644 --- a/benchmarks/FSharp.Stats.Benchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.Benchmarks.MatrixBenchmarks-report.csv +++ b/benchmarks/FSharp.Stats.Benchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.Benchmarks.MatrixBenchmarks-report.csv @@ -1,13 +1,13 @@ Method,Job,AnalyzeLaunchVariance,EvaluateOverhead,MaxAbsoluteError,MaxRelativeError,MinInvokeCount,MinIterationTime,OutlierMode,Affinity,EnvironmentVariables,Jit,LargeAddressAware,Platform,PowerPlanMode,Runtime,AllowVeryLargeObjects,Concurrent,CpuGroups,Force,HeapAffinitizeMask,HeapCount,NoAffinitize,RetainVm,Server,Arguments,BuildConfiguration,Clock,EngineFactory,NuGetReferences,Toolchain,IsMutator,InvocationCount,IterationCount,IterationTime,LaunchCount,MaxIterationCount,MaxWarmupIterationCount,MemoryRandomization,MinIterationCount,MinWarmupIterationCount,RunStrategy,UnrollFactor,WarmupCount,Size,Mean,Error,StdDev,Gen0,Gen1,Gen2,Allocated -Add,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,10,38.33 ns,0.686 ns,0.642 ns,0.0682,0.0002,0.0000,856 B -MatMultiply,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,10,436.79 ns,2.776 ns,2.461 ns,0.1364,0.0000,0.0000,1712 B -MultiplyVector,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,10,32.20 ns,0.439 ns,0.411 ns,0.0083,0.0000,0.0000,104 B -MultiplyRowVector,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,10,228.95 ns,1.473 ns,1.378 ns,0.0975,0.0000,0.0000,1224 B -Add,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,500,"282,714.76 ns","5,416.776 ns","5,066.855 ns",206.5430,206.5430,206.5430,2000168 B -MatMultiply,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,500,"17,514,488.54 ns","216,980.386 ns","202,963.588 ns",375.0000,375.0000,375.0000,4000242 B -MultiplyVector,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,500,"33,458.92 ns",334.582 ns,312.968 ns,0.3052,0.0000,0.0000,4024 B -MultiplyRowVector,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,500,"613,450.40 ns","7,962.085 ns","7,447.740 ns",278.3203,3.9063,0.0000,3504024 B -Add,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,1000,"1,360,217.58 ns","24,506.528 ns","21,724.399 ns",398.4375,398.4375,398.4375,8000206 B -MatMultiply,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,1000,"143,946,340.15 ns","2,872,749.805 ns","4,556,485.985 ns",250.0000,250.0000,250.0000,16000296 B -MultiplyVector,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,1000,"137,378.76 ns",942.798 ns,881.894 ns,0.4883,0.0000,0.0000,8024 B -MultiplyRowVector,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,1000,"2,999,358.20 ns","48,713.356 ns","45,566.504 ns",1113.2813,27.3438,0.0000,14008026 B +Add,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,10,40.06 ns,0.550 ns,0.488 ns,0.0682,0.0002,0.0000,856 B +MatMultiply,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,10,442.83 ns,2.841 ns,2.373 ns,0.1364,0.0000,0.0000,1712 B +MultiplyVector,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,10,33.28 ns,0.425 ns,0.397 ns,0.0083,0.0000,0.0000,104 B +MultiplyRowVector,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,10,50.55 ns,0.500 ns,0.468 ns,0.0083,0.0000,0.0000,104 B +Add,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,500,"280,736.93 ns","5,376.045 ns","5,279.995 ns",212.4023,212.4023,212.4023,2000164 B +MatMultiply,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,500,"17,572,322.92 ns","318,470.458 ns","297,897.464 ns",375.0000,375.0000,375.0000,4000242 B +MultiplyVector,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,500,"31,726.43 ns",202.403 ns,189.328 ns,0.3052,0.0000,0.0000,4024 B +MultiplyRowVector,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,500,"127,918.10 ns",996.783 ns,832.359 ns,0.2441,0.0000,0.0000,4024 B +Add,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,1000,"1,377,902.79 ns","20,816.673 ns","18,453.438 ns",148.4375,148.4375,148.4375,8000105 B +MatMultiply,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,1000,"143,300,325.00 ns","1,445,291.857 ns","1,606,438.070 ns",250.0000,250.0000,250.0000,16000296 B +MultiplyVector,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,1000,"135,247.34 ns","1,334.685 ns","1,248.465 ns",0.4883,0.0000,0.0000,8024 B +MultiplyRowVector,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,1000,"677,195.35 ns","6,896.007 ns","6,450.529 ns",0.0000,0.0000,0.0000,8024 B diff --git a/benchmarks/FSharp.Stats.Benchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.Benchmarks.MatrixBenchmarks-report.html b/benchmarks/FSharp.Stats.Benchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.Benchmarks.MatrixBenchmarks-report.html index cc4406755..bcfdb6957 100644 --- a/benchmarks/FSharp.Stats.Benchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.Benchmarks.MatrixBenchmarks-report.html +++ b/benchmarks/FSharp.Stats.Benchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.Benchmarks.MatrixBenchmarks-report.html @@ -2,7 +2,7 @@ -FSharp.Stats.Benchmarks.MatrixBenchmarks-20250412-173020 +FSharp.Stats.Benchmarks.MatrixBenchmarks-20250412-175902 + + +

+BenchmarkDotNet v0.14.0, Windows 11 (10.0.26100.3775)
+13th Gen Intel Core i7-13800H, 1 CPU, 20 logical and 14 physical cores
+.NET SDK 9.0.201
+  [Host]     : .NET 8.0.14 (8.0.1425.11118), X64 RyuJIT AVX2 DEBUG
+  DefaultJob : .NET 8.0.14 (8.0.1425.11118), X64 RyuJIT AVX2
+
+
+ + + + + + + + + + + + +
Method NMean Error StdDevGen0Allocated
SolveTriangularSystemLower10186.3 ns1.23 ns1.09 ns0.0172216 B
SolveTriangularSystemUpper10185.9 ns1.33 ns1.18 ns0.0172216 B
SolveTriangularSystemLower500372,737.0 ns2,926.50 ns2,737.45 ns0.48838056 B
SolveTriangularSystemUpper500357,818.8 ns1,729.90 ns1,618.15 ns0.48838056 B
SolveTriangularSystemLower10001,510,031.5 ns7,131.73 ns6,671.03 ns-16057 B
SolveTriangularSystemUpper10001,422,197.8 ns8,642.37 ns8,084.08 ns-16057 B
SolveTriangularSystemLower20006,119,478.8 ns40,341.69 ns37,735.64 ns-32059 B
SolveTriangularSystemUpper20005,776,260.6 ns30,122.54 ns28,176.64 ns-32059 B
+ + diff --git a/benchmarks/FSharp.Stats.Benchmarks/FSharp.Stats.Benchmarks.fsproj b/benchmarks/FSharp.Stats.Benchmarks/FSharp.Stats.Benchmarks.fsproj index 647da67b2..28d22c175 100644 --- a/benchmarks/FSharp.Stats.Benchmarks/FSharp.Stats.Benchmarks.fsproj +++ b/benchmarks/FSharp.Stats.Benchmarks/FSharp.Stats.Benchmarks.fsproj @@ -8,6 +8,7 @@ + diff --git a/benchmarks/FSharp.Stats.Benchmarks/Program.fs b/benchmarks/FSharp.Stats.Benchmarks/Program.fs index d15db5097..ee69be2d0 100644 --- a/benchmarks/FSharp.Stats.Benchmarks/Program.fs +++ b/benchmarks/FSharp.Stats.Benchmarks/Program.fs @@ -8,6 +8,7 @@ let Main args = let switcher = BenchmarkSwitcher [| typeof typeof + typeof |] switcher.Run args |> ignore 0 diff --git a/benchmarks/FSharp.Stats.Benchmarks/TriangularSolver.fs b/benchmarks/FSharp.Stats.Benchmarks/TriangularSolver.fs new file mode 100644 index 000000000..6513e7d97 --- /dev/null +++ b/benchmarks/FSharp.Stats.Benchmarks/TriangularSolver.fs @@ -0,0 +1,48 @@ +namespace FSharp.Stats.Benchmarks + +open System +open BenchmarkDotNet.Attributes +open BenchmarkDotNet.Running +open FSharp.Stats +open FSharp.Stats.Algebra + +[] +type TriangularBenchmark() = + + + // We'll hold the test data here + let mutable K : Matrix = Unchecked.defaultof> + let mutable B : Matrix = Unchecked.defaultof> + + /// + /// We'll vary 'N' in [500, 1000, 2000] for the matrix dimension. + /// BenchmarkDotNet will run separate benchmarks for each N. + /// + [] + member val N = 0 with get, set + + [] + member this.Setup() = + // Use the parameter N to build NxN matrix K and NxM matrix B + let n = this.N + let m = 2 // or some other number of columns for B + let rnd = Random(1234) + + // Build K + let dataK = Array.init (n*n) (fun _ -> float(rnd.Next(1,10))) + K <- Matrix(n, n, dataK) + + // Build B + let dataB = Array.init (n*m) (fun _ -> float(rnd.Next(1,5))) + B <- Matrix(n, m, dataB) + + + [] + member this.SolveTriangularSystemLower() = + // The method we want to benchmark + LinearAlgebra.solveTriangularLinearSystems K B true + + [] + member this.SolveTriangularSystemUpper() = + // The method we want to benchmark + LinearAlgebra.solveTriangularLinearSystems K B false \ No newline at end of file diff --git a/benchmarks/FSharp.Stats.LegacyBenchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.LegacyBenchmarks.TriangularBenchmark-report-github.md b/benchmarks/FSharp.Stats.LegacyBenchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.LegacyBenchmarks.TriangularBenchmark-report-github.md new file mode 100644 index 000000000..ed728cb36 --- /dev/null +++ b/benchmarks/FSharp.Stats.LegacyBenchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.LegacyBenchmarks.TriangularBenchmark-report-github.md @@ -0,0 +1,20 @@ +``` + +BenchmarkDotNet v0.14.0, Windows 11 (10.0.26100.3775) +13th Gen Intel Core i7-13800H, 1 CPU, 20 logical and 14 physical cores +.NET SDK 9.0.201 + [Host] : .NET 8.0.14 (8.0.1425.11118), X64 RyuJIT AVX2 DEBUG + DefaultJob : .NET 8.0.14 (8.0.1425.11118), X64 RyuJIT AVX2 + + +``` +| Method | N | Mean | Error | StdDev | Gen0 | Gen1 | Gen2 | Allocated | +|--------------------------- |----- |----------------:|-------------:|--------------:|---------:|---------:|---------:|------------:| +| **SolveTriangularSystemLower** | **10** | **731.0 ns** | **5.15 ns** | **4.82 ns** | **0.1097** | **-** | **-** | **1.34 KB** | +| SolveTriangularSystemUpper | 10 | 665.6 ns | 5.93 ns | 5.54 ns | 0.1097 | - | - | 1.34 KB | +| **SolveTriangularSystemLower** | **500** | **1,474,179.5 ns** | **29,026.42 ns** | **32,262.78 ns** | **332.0313** | **330.0781** | **330.0781** | **1977.87 KB** | +| SolveTriangularSystemUpper | 500 | 1,508,533.3 ns | 25,877.28 ns | 24,205.62 ns | 333.9844 | 332.0313 | 332.0313 | 1977.72 KB | +| **SolveTriangularSystemLower** | **1000** | **6,405,608.8 ns** | **83,698.88 ns** | **78,291.99 ns** | **390.6250** | **390.6250** | **390.6250** | **7860.04 KB** | +| SolveTriangularSystemUpper | 1000 | 6,555,258.3 ns | 81,557.32 ns | 76,288.76 ns | 390.6250 | 390.6250 | 390.6250 | 7859.79 KB | +| **SolveTriangularSystemLower** | **2000** | **26,497,907.6 ns** | **81,721.04 ns** | **189,400.94 ns** | **875.0000** | **875.0000** | **875.0000** | **31344.14 KB** | +| SolveTriangularSystemUpper | 2000 | 27,361,796.9 ns | 98,627.77 ns | 196,970.33 ns | 875.0000 | 875.0000 | 875.0000 | 31344.14 KB | diff --git a/benchmarks/FSharp.Stats.LegacyBenchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.LegacyBenchmarks.TriangularBenchmark-report.csv b/benchmarks/FSharp.Stats.LegacyBenchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.LegacyBenchmarks.TriangularBenchmark-report.csv new file mode 100644 index 000000000..56d252a8c --- /dev/null +++ b/benchmarks/FSharp.Stats.LegacyBenchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.LegacyBenchmarks.TriangularBenchmark-report.csv @@ -0,0 +1,9 @@ +Method,Job,AnalyzeLaunchVariance,EvaluateOverhead,MaxAbsoluteError,MaxRelativeError,MinInvokeCount,MinIterationTime,OutlierMode,Affinity,EnvironmentVariables,Jit,LargeAddressAware,Platform,PowerPlanMode,Runtime,AllowVeryLargeObjects,Concurrent,CpuGroups,Force,HeapAffinitizeMask,HeapCount,NoAffinitize,RetainVm,Server,Arguments,BuildConfiguration,Clock,EngineFactory,NuGetReferences,Toolchain,IsMutator,InvocationCount,IterationCount,IterationTime,LaunchCount,MaxIterationCount,MaxWarmupIterationCount,MemoryRandomization,MinIterationCount,MinWarmupIterationCount,RunStrategy,UnrollFactor,WarmupCount,N,Mean,Error,StdDev,Gen0,Gen1,Gen2,Allocated +SolveTriangularSystemLower,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,10,731.0 ns,5.15 ns,4.82 ns,0.1097,0.0000,0.0000,1.34 KB +SolveTriangularSystemUpper,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,10,665.6 ns,5.93 ns,5.54 ns,0.1097,0.0000,0.0000,1.34 KB +SolveTriangularSystemLower,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,500,"1,474,179.5 ns","29,026.42 ns","32,262.78 ns",332.0313,330.0781,330.0781,1977.87 KB +SolveTriangularSystemUpper,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,500,"1,508,533.3 ns","25,877.28 ns","24,205.62 ns",333.9844,332.0313,332.0313,1977.72 KB +SolveTriangularSystemLower,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,1000,"6,405,608.8 ns","83,698.88 ns","78,291.99 ns",390.6250,390.6250,390.6250,7860.04 KB +SolveTriangularSystemUpper,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,1000,"6,555,258.3 ns","81,557.32 ns","76,288.76 ns",390.6250,390.6250,390.6250,7859.79 KB +SolveTriangularSystemLower,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,2000,"26,497,907.6 ns","81,721.04 ns","189,400.94 ns",875.0000,875.0000,875.0000,31344.14 KB +SolveTriangularSystemUpper,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,2000,"27,361,796.9 ns","98,627.77 ns","196,970.33 ns",875.0000,875.0000,875.0000,31344.14 KB diff --git a/benchmarks/FSharp.Stats.LegacyBenchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.LegacyBenchmarks.TriangularBenchmark-report.html b/benchmarks/FSharp.Stats.LegacyBenchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.LegacyBenchmarks.TriangularBenchmark-report.html new file mode 100644 index 000000000..faab41b07 --- /dev/null +++ b/benchmarks/FSharp.Stats.LegacyBenchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.LegacyBenchmarks.TriangularBenchmark-report.html @@ -0,0 +1,37 @@ + + + + +FSharp.Stats.LegacyBenchmarks.TriangularBenchmark-20250412-194859 + + + + +

+BenchmarkDotNet v0.14.0, Windows 11 (10.0.26100.3775)
+13th Gen Intel Core i7-13800H, 1 CPU, 20 logical and 14 physical cores
+.NET SDK 9.0.201
+  [Host]     : .NET 8.0.14 (8.0.1425.11118), X64 RyuJIT AVX2 DEBUG
+  DefaultJob : .NET 8.0.14 (8.0.1425.11118), X64 RyuJIT AVX2
+
+
+ + + + + + + + + + + + +
Method NMean Error StdDev Gen0Gen1Gen2Allocated
SolveTriangularSystemLower10731.0 ns5.15 ns4.82 ns0.1097--1.34 KB
SolveTriangularSystemUpper10665.6 ns5.93 ns5.54 ns0.1097--1.34 KB
SolveTriangularSystemLower5001,474,179.5 ns29,026.42 ns32,262.78 ns332.0313330.0781330.07811977.87 KB
SolveTriangularSystemUpper5001,508,533.3 ns25,877.28 ns24,205.62 ns333.9844332.0313332.03131977.72 KB
SolveTriangularSystemLower10006,405,608.8 ns83,698.88 ns78,291.99 ns390.6250390.6250390.62507860.04 KB
SolveTriangularSystemUpper10006,555,258.3 ns81,557.32 ns76,288.76 ns390.6250390.6250390.62507859.79 KB
SolveTriangularSystemLower200026,497,907.6 ns81,721.04 ns189,400.94 ns875.0000875.0000875.000031344.14 KB
SolveTriangularSystemUpper200027,361,796.9 ns98,627.77 ns196,970.33 ns875.0000875.0000875.000031344.14 KB
+ + diff --git a/benchmarks/FSharp.Stats.LegacyBenchmarks/FSharp.Stats.LegacyBenchmarks.fsproj b/benchmarks/FSharp.Stats.LegacyBenchmarks/FSharp.Stats.LegacyBenchmarks.fsproj index 98bde68c0..78b884d9d 100644 --- a/benchmarks/FSharp.Stats.LegacyBenchmarks/FSharp.Stats.LegacyBenchmarks.fsproj +++ b/benchmarks/FSharp.Stats.LegacyBenchmarks/FSharp.Stats.LegacyBenchmarks.fsproj @@ -6,8 +6,9 @@ - + + diff --git a/benchmarks/FSharp.Stats.LegacyBenchmarks/Program.fs b/benchmarks/FSharp.Stats.LegacyBenchmarks/Program.fs index 5a6658fd3..829e670f5 100644 --- a/benchmarks/FSharp.Stats.LegacyBenchmarks/Program.fs +++ b/benchmarks/FSharp.Stats.LegacyBenchmarks/Program.fs @@ -10,6 +10,7 @@ let Main args = let switcher = BenchmarkSwitcher [| typeof typeof + typeof |] switcher.Run args |> ignore 0 diff --git a/benchmarks/FSharp.Stats.LegacyBenchmarks/TriangularSolver.fs b/benchmarks/FSharp.Stats.LegacyBenchmarks/TriangularSolver.fs new file mode 100644 index 000000000..2a85e3f12 --- /dev/null +++ b/benchmarks/FSharp.Stats.LegacyBenchmarks/TriangularSolver.fs @@ -0,0 +1,46 @@ +namespace FSharp.Stats.LegacyBenchmarks + +open System +open BenchmarkDotNet.Attributes +open BenchmarkDotNet.Running +open FSharp.Stats +open FSharp.Stats.Algebra + +[] +type TriangularBenchmark() = + + + // We'll hold the test data here + let mutable K : Matrix = Unchecked.defaultof> + let mutable B : Matrix = Unchecked.defaultof> + + /// + /// We'll vary 'N' in [500, 1000, 2000] for the matrix dimension. + /// BenchmarkDotNet will run separate benchmarks for each N. + /// + [] + member val N = 0 with get, set + + [] + member this.Setup() = + // Use the parameter N to build NxN matrix K and NxM matrix B + let n = this.N + let m = 2 // or some other number of columns for B + let rnd = Random(1234) + + // Build K + K <- Matrix.init n n (fun _ _ -> float(rnd.Next(1,10))) + + // Build B + B <- Matrix.init n m (fun _ _ -> float(rnd.Next(1,5))) + + + [] + member this.SolveTriangularSystemLower() = + // The method we want to benchmark + LinearAlgebra.SolveTriangularLinearSystems K B true + + [] + member this.SolveTriangularSystemUpper() = + // The method we want to benchmark + LinearAlgebra.SolveTriangularLinearSystems K B false \ No newline at end of file From 7795deb9114dbd98aba3ece38d6c9575ed75bad7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20M=C3=BChlhaus?= Date: Sat, 12 Apr 2025 21:59:39 +0200 Subject: [PATCH 032/121] Add LinearAlgebra unit test cases --- src/FSharp.Stats/Algebra/LinearAlgebra.fs | 60 ++++++++---- src/FSharp.Stats/Playground.fsx | 57 ++++------- tests/FSharp.Stats.Tests/LinearAlgebra.fs | 111 +++++++++++----------- 3 files changed, 113 insertions(+), 115 deletions(-) diff --git a/src/FSharp.Stats/Algebra/LinearAlgebra.fs b/src/FSharp.Stats/Algebra/LinearAlgebra.fs index b5f0eac95..5a6e8b7a5 100644 --- a/src/FSharp.Stats/Algebra/LinearAlgebra.fs +++ b/src/FSharp.Stats/Algebra/LinearAlgebra.fs @@ -179,17 +179,17 @@ type LinearAlgebra = // Subtract scaled rows for j in [0..i-1] for j = 0 to i - 1 do let kij = Kdata.[i * n + j] // K[i,j] - if kij <> 'T.Zero then - let baseJ = j * m - // subScaledRowInPlace scaleVal dstOffset srcOffset count dst src - LinearAlgebra.subScaledRowInPlace - kij - baseI // row i offset in X - baseJ // row j offset in X - m // number of columns - Xdata - Xdata - //LinearAlgebra.subScaledRowInPlace + //if kij <> 'T.Zero then // normaly speed things up, but -inf * 0 = nan + let baseJ = j * m + // subScaledRowInPlace scaleVal dstOffset srcOffset count dst src + LinearAlgebra.subScaledRowInPlace + kij + baseI // row i offset in X + baseJ // row j offset in X + m // number of columns + Xdata + Xdata + //LinearAlgebra.subScaledRowInPlace // Xdata // baseI // row i offset in X // Xdata @@ -217,15 +217,15 @@ type LinearAlgebra = let baseI = i * m for j = i + 1 to n - 1 do let kij = Kdata.[i * n + j] // K[i,j] - if kij <> 'T.Zero then - let baseJ = j * m - LinearAlgebra.subScaledRowInPlace - kij - baseI - baseJ - m - Xdata - Xdata + //if kij <> 'T.Zero then // normaly speed things up, but -inf * 0 = nan + let baseJ = j * m + LinearAlgebra.subScaledRowInPlace + kij + baseI + baseJ + m + Xdata + Xdata let diag = Kdata.[i * n + i] let invDiag = 'T.One / diag scaleRowInPlace @@ -670,3 +670,23 @@ type LinearAlgebra = static member inline symmetricEigenspectrum (a:Matrix) = let (e,v,d) = EVD.symmetricEvd (a.toArray2D()) (Matrix.ofArray2D v, d) + + ///// Synonym: kernel / right null space. Returns an orthonormal basis for the null space of matrix A (Ax = 0).
The accuracy defines a threshold whether a singular value is considered as zero (default: 1e-08). + //static member nullspace(?Accuracy :float ) = + + // let accuracy = defaultArg Accuracy 1e-08 + + // fun (a: Matrix) -> + + // // Either MKL or fallback implementation of the full SVD + // let (sigma,U,Vt) = LinearAlgebra.SVD a + + // // The rank is the number of nonzero singular values + // let rank = + // sigma + // |> Seq.sumBy (fun x -> if x >= accuracy then 1 else 0) + + // let count = Vt.NumRows - rank + + // Matrix.getRows Vt rank count + // |> Matrix.transpose \ No newline at end of file diff --git a/src/FSharp.Stats/Playground.fsx b/src/FSharp.Stats/Playground.fsx index ed66d5edb..ac76cc2c3 100644 --- a/src/FSharp.Stats/Playground.fsx +++ b/src/FSharp.Stats/Playground.fsx @@ -6,46 +6,7 @@ open System open FSharp.Stats open FSharp.Stats.Distributions //open Plotly.NET - - - -let data = [|1.0; 2.0; 3.0; 4.0; 5.0|] - -SummaryStats.ofSeq data -SummaryStats.ofArray data - -let statsC = SummaryStats.ofSeq data -let calcMean = Seq.mean data -let calcSumOfSquares = Seq.sumBy (fun x -> x * x) data -let calcMin = Seq.min data -let calcMax = Seq.max data -let calcN = Seq.length data - - -open FSharp.Stats.Testing - -let groupA = [|-5.;-3.;-3.;-4.;-5.;|] -let groupB = [|-2.;-4.;-4.;-6.;-6.;-6.;-5.;|] - -let statsA = Seq.stats groupA -let statsB = Seq.stats groupB - - -let meanA = Seq.mean groupA -let meanB = Seq.mean groupB -let varA = Seq.var groupA -let varB = Seq.var groupB -let nA = float (Seq.length groupA) -let nB = float (Seq.length groupB) - -// calculation of the H test -let tTest1 = TTest.twoSample true groupA groupB -let tTest2 = TTest.twoSampleFromMeanAndVar true (meanA,varA,nA) (meanB,varB,nB) -let tTest3 = TTest.twoSample false groupA groupB - - - - +open FSharp.Stats.Algebra let KDiagonal1 = [| @@ -64,7 +25,21 @@ let BNegInf = |> Matrix.ofJaggedArray -Algebra.LinearAlgebra .solveTriangularLinearSystems KDiagonal1 BNegInf false +Algebra.LinearAlgebra.solveTriangularLinearSystems KDiagonal1 BNegInf false + + +KDiagonal1 +|> Matrix.mapiCols (fun i v -> + let m = Vector.norm v + [|m|]) + +let expected = + matrix [| + [|nan;nan;nan|]; + [|nan;nan;nan|]; + [|-infinity;-infinity;-infinity|] + |] + //|> fun res -> // let expected = diff --git a/tests/FSharp.Stats.Tests/LinearAlgebra.fs b/tests/FSharp.Stats.Tests/LinearAlgebra.fs index e52f3cf6e..3225fe876 100644 --- a/tests/FSharp.Stats.Tests/LinearAlgebra.fs +++ b/tests/FSharp.Stats.Tests/LinearAlgebra.fs @@ -29,67 +29,70 @@ let managedSVDTests = let m' = mEqualNRecov.toJaggedArray() |> Array.concat TestExtensions.sequenceEqual Accuracy.high m m' "Matrices computed by SVD did not yield the initial matrix when multiplied." - //testCase "m=n Matrix: u and vt consist of unit vectors, row- and column- wise." <| fun () -> - // let u,s,vt = svdManaged mEqualN - // let vecNorms = - // [ - // u |> Matrix.mapiCols (fun _ v -> FSharp.Stats.Vector.norm v) - // vt|> Matrix.mapiCols (fun _ v -> Vector.norm v) - // u |> Matrix.mapiRows (fun _ x -> x |> Vector.norm) - // vt|> Matrix.mapiRows (fun _ x -> x |> Vector.norm) - // ] - // |> Array.concat - // TestExtensions.sequenceEqual Accuracy.high (Array.create vecNorms.Length 1.) vecNorms "Matrices computed by SVD did not consist of unit vectors, row- and column- wise." + testCase "m=n Matrix: u and vt consist of unit vectors, row- and column- wise." <| fun () -> + let u,s,vt = svdManaged mEqualN + let vecNorms = + [| + u |> Matrix.mapiCols (fun _ v -> [|FSharp.Stats.Vector.norm v|]) + vt|> Matrix.mapiCols (fun _ v -> [|FSharp.Stats.Vector.norm v|]) + u |> Matrix.mapiRows (fun _ x -> [|FSharp.Stats.Vector.norm x|]) + vt|> Matrix.mapiRows (fun _ x -> [|FSharp.Stats.Vector.norm x|]) + |] + |> Array.map (fun m -> m.Data) + |> Array.concat + TestExtensions.sequenceEqual Accuracy.high (Array.create vecNorms.Length 1.) vecNorms "Matrices computed by SVD did not consist of unit vectors, row- and column- wise." - //testCase "m=n Matrix: s contains correct singular values." <| fun () -> - // let s,u,vt = LinearAlgebra.SVD mEqualN - // TestExtensions.sequenceEqual Accuracy.high ([|15.81461344;2.213142934|]) s "Matrices computed by SVD did not yield correct singular values." + testCase "m=n Matrix: s contains correct singular values." <| fun () -> + let s,u,vt = LinearAlgebra.SVD mEqualN + TestExtensions.sequenceEqual Accuracy.high ([|15.81461344;2.213142934|]) s "Matrices computed by SVD did not yield correct singular values." - //testCase "m - // let u,s,vt = svdManaged mSmallerN - // let mSmallernRecov = (u * s * vt) - // let m = mSmallerN |> Matrix.toJaggedArray |> Array.concat - // let m' = mSmallernRecov |> Matrix.toJaggedArray |> Array.concat - // TestExtensions.sequenceEqual Accuracy.high m m' "Matrices computed by SVD did not yield the initial matrix when multiplied." + testCase "m + let u,s,vt = svdManaged mSmallerN + let mSmallernRecov = (u * s * vt) + let m = mSmallerN.Data + let m' = mSmallernRecov.Data + TestExtensions.sequenceEqual Accuracy.high m m' "Matrices computed by SVD did not yield the initial matrix when multiplied." - //testCase "m - // let u,s,vt = svdManaged mSmallerN - // let vecNorms = - // [ - // u |> Matrix.mapCols Vector.norm |> RowVector.toArray - // vt|> Matrix.mapCols Vector.norm |> RowVector.toArray - // u |> Matrix.mapRows (fun x -> x.Transpose |> Vector.norm) |> Vector.toArray - // vt|> Matrix.mapRows (fun x -> x.Transpose |> Vector.norm) |> Vector.toArray - // ] - // |> Array.concat - // TestExtensions.sequenceEqual Accuracy.high (Array.create vecNorms.Length 1.) vecNorms "Matrices computed by SVD did not consist of unit vectors, row- and column- wise." + testCase "m + let u,s,vt = svdManaged mSmallerN + let vecNorms = + [| + u |> Matrix.mapiCols (fun _ v -> [|FSharp.Stats.Vector.norm v|]) + vt|> Matrix.mapiCols (fun _ v -> [|FSharp.Stats.Vector.norm v|]) + u |> Matrix.mapiRows (fun _ x -> [|FSharp.Stats.Vector.norm x|]) + vt|> Matrix.mapiRows (fun _ x -> [|FSharp.Stats.Vector.norm x|]) + |] + |> Array.map (fun m -> m.Data) + |> Array.concat + TestExtensions.sequenceEqual Accuracy.high (Array.create vecNorms.Length 1.) vecNorms "Matrices computed by SVD did not consist of unit vectors, row- and column- wise." - //testCase "m - // let s,u,vt = LinearAlgebra.SVD mSmallerN - // TestExtensions.sequenceEqual Accuracy.high ([|22.51999394;6.986424855;2.00991059|]) s "Matrices computed by SVD did not yield correct singular values." + testCase "m + let s,u,vt = LinearAlgebra.SVD mSmallerN + TestExtensions.sequenceEqual Accuracy.high ([|22.51999394;6.986424855;2.00991059|]) s "Matrices computed by SVD did not yield correct singular values." - //testCase "m>n Matrix: Recover from decomposition" <| fun () -> - // let u,s,vt = svdManaged (mSmallerN.Transpose()) - // let mSmallernRecov = (u * s * vt) - // let m = mSmallerN.Transpose().toJaggedArray() |> Array.concat - // let m' = mSmallernRecov.toJaggedArray() |> Array.concat - // TestExtensions.sequenceEqual Accuracy.high m m' "Matrices computed by SVD did not yield the initial matrix when multiplied." + testCase "m>n Matrix: Recover from decomposition" <| fun () -> + let u,s,vt = svdManaged (mSmallerN.Transpose()) + let mSmallernRecov = (u * s * vt) + let m = mSmallerN.Transpose().Data + let m' = mSmallernRecov.Data + TestExtensions.sequenceEqual Accuracy.high m m' "Matrices computed by SVD did not yield the initial matrix when multiplied." - //testCase "m>n Matrix: u and vt consist of unit vectors, row- and column- wise." <| fun () -> - // let u,s,vt = svdManaged (mSmallerN.Transpose()) - // let vecNorms = - // [ - // u |> Matrix.mapCols Vector.norm |> RowVector.toArray - // vt|> Matrix.mapCols Vector.norm |> RowVector.toArray - // u |> Matrix.mapRows (fun x -> x.Transpose |> Vector.norm) |> Vector.toArray - // vt|> Matrix.mapRows (fun x -> x.Transpose |> Vector.norm) |> Vector.toArray - // ] - // |> Array.concat - // TestExtensions.sequenceEqual Accuracy.high (Array.create vecNorms.Length 1.) vecNorms "Matrices computed by SVD did not consist of unit vectors, row- and column- wise." + testCase "m>n Matrix: u and vt consist of unit vectors, row- and column- wise." <| fun () -> + let u,s,vt = svdManaged (mSmallerN.Transpose()) + let vecNorms = + [| + u |> Matrix.mapiCols (fun _ v -> [|FSharp.Stats.Vector.norm v|]) + vt|> Matrix.mapiCols (fun _ v -> [|FSharp.Stats.Vector.norm v|]) + u |> Matrix.mapiRows (fun _ x -> [|FSharp.Stats.Vector.norm x|]) + vt|> Matrix.mapiRows (fun _ x -> [|FSharp.Stats.Vector.norm x|]) + |] + |> Array.map (fun m -> m.Data) + |> Array.concat + TestExtensions.sequenceEqual Accuracy.high (Array.create vecNorms.Length 1.) vecNorms "Matrices computed by SVD did not consist of unit vectors, row- and column- wise." - //testCase "m>n Matrix: s contains correct singular values." <| fun () -> - // let s,u,vt = LinearAlgebra.SVD (mSmallerN.Transpose()) - // TestExtensions.sequenceEqual Accuracy.high ([|22.51999394;6.986424855;2.00991059|]) s "Matrices computed by SVD did not yield correct singular values." + testCase "m>n Matrix: s contains correct singular values." <| fun () -> + let s,u,vt = LinearAlgebra.SVD (mSmallerN.Transpose()) + TestExtensions.sequenceEqual Accuracy.high ([|22.51999394;6.986424855;2.00991059|]) s "Matrices computed by SVD did not yield correct singular values." ] From 280857da8a8d201989953cb4cb3b200035f96749 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20M=C3=BChlhaus?= Date: Sun, 13 Apr 2025 14:50:14 +0200 Subject: [PATCH 033/121] Add distribution Categorical --- src/FSharp.Stats/Algebra/LinearAlgebra.fs | 7 +- .../Distributions/Discrete/Categorical.fs | 160 ++++++++++++++++++ .../Discrete/LabelledCategorical.fs | 125 ++++++++++++++ src/FSharp.Stats/FSharp.Stats.fsproj | 2 + 4 files changed, 292 insertions(+), 2 deletions(-) create mode 100644 src/FSharp.Stats/Distributions/Discrete/Categorical.fs create mode 100644 src/FSharp.Stats/Distributions/Discrete/LabelledCategorical.fs diff --git a/src/FSharp.Stats/Algebra/LinearAlgebra.fs b/src/FSharp.Stats/Algebra/LinearAlgebra.fs index 5a6e8b7a5..7fe1807a6 100644 --- a/src/FSharp.Stats/Algebra/LinearAlgebra.fs +++ b/src/FSharp.Stats/Algebra/LinearAlgebra.fs @@ -6,8 +6,8 @@ open FSharp.Stats type LinearAlgebra = - /// Subtract `scaleVal * src[srcOffset..srcOffset+count-1]` from - /// `dst[dstOffset..dstOffset+count-1]` in place. + /// Subtract `scaleVal * src[srcOffset..srcOffset+count-1]` from + /// `dst[dstOffset..dstOffset+count-1]` in place. static member inline subScaledRowInPlace (scaleVal : 'T) (dstOffset : int) @@ -27,6 +27,7 @@ type LinearAlgebra = d - (scaleVal * s) Acceleration.SIMDRangeUtils.map2RangeInPlace fv f dstOffset srcOffset count dst src + static member inline householderTransform (A: Matrix<'T>) (i: int) : Vector<'T> = let n = A.NumRows @@ -38,6 +39,8 @@ type LinearAlgebra = if j <> i then v.[j] <- aCol.[j] v + + /// QR decomposition using modified Gram-Schmidt /// Returns Q and R such that A = QR static member inline qrModifiedGramSchmidt<'T when 'T :> Numerics.INumber<'T> diff --git a/src/FSharp.Stats/Distributions/Discrete/Categorical.fs b/src/FSharp.Stats/Distributions/Discrete/Categorical.fs new file mode 100644 index 000000000..08fb89c7e --- /dev/null +++ b/src/FSharp.Stats/Distributions/Discrete/Categorical.fs @@ -0,0 +1,160 @@ +namespace FSharp.Stats.Distributions.Discrete + +open FSharp.Stats +open FSharp.Stats.Distributions + +/// +/// Categorical distribution (finite discrete distribution over k categories with probabilities). +/// +type Categorical = + + /// Checks if the given probability vector is valid (all values ∈ [0,1] and sum to 1). + /// An array of probabilities over k categories. + static member CheckParam (probabilities: float[]) = + if probabilities.Length = 0 then failwith "Categorical distribution must have at least one category." + if probabilities |> Array.exists (fun p -> p < 0. || p > 1. || Ops.isNan(p)) then + failwith "All probabilities must be in [0, 1]." + let total = probabilities |> Array.sum + if abs (total - 1.0) > 1e-8 then + failwithf "Probabilities must sum to 1.0 (got %f)." total + + /// Computes the mean (expected index) of the categorical distribution. + /// An array of probabilities over k categories. + /// The weighted average of indices based on probabilities. + static member Mean (probabilities: float[]) = + Categorical.CheckParam probabilities + probabilities + |> Array.mapi (fun i p -> float i * p) + |> Array.sum + + /// Computes the variance of the categorical distribution. + /// An array of probabilities over k categories. + /// The variance: E[X²] - (E[X])². + static member Variance (probabilities: float[]) = + Categorical.CheckParam probabilities + let mean = Categorical.Mean probabilities + probabilities + |> Array.mapi (fun i p -> p * float i ** 2.0) + |> Array.sum + |> fun ex2 -> ex2 - mean ** 2.0 + + /// Generates a random sample from the categorical distribution. No parameter checking. + /// An array of probabilities over k categories. + /// An integer representing the sampled category index. + static member SampleUnchecked (probabilities: float[]) = + let rnd = Random.rndgen.NextFloat() + let rec search i acc = + if i >= probabilities.Length then probabilities.Length - 1 + elif acc + probabilities[i] >= rnd then i + else search (i + 1) (acc + probabilities[i]) + search 0 0.0 + + /// Generates a random sample from the categorical distribution. + /// An array of probabilities over k categories. + /// An integer representing the sampled category index. + static member Sample (probabilities: float[]) = + Categorical.CheckParam probabilities + Categorical.SampleUnchecked probabilities + + /// Computes the probability mass function at index k: P(X = k). + /// An array of probabilities over k categories. + /// The index to evaluate. + /// The probability of observing category k. + static member PMF (probabilities: float[]) (k:int) = + Categorical.CheckParam probabilities + if k < 0 || k >= probabilities.Length then 0.0 + else probabilities[k] + + /// Computes the cumulative distribution function at x: P(X ≤ x). + /// An array of probabilities over k categories. + /// A float value where CDF is evaluated (interpreted as an index). + /// The cumulative probability up to and including ⌊x⌋. + static member CDF (probabilities: float[]) (x: float) = + Categorical.CheckParam probabilities + if x < 0. then 0.0 + elif x >= float (probabilities.Length) then 1.0 + else + let k = floor x |> int + probabilities + |> Array.take (k + 1) + |> Array.sum + + /// Returns the support (valid outcome range) of the distribution: [0, k-1]. + /// An array of probabilities over k categories. + /// A closed interval [0, k-1]. + static member Support (probabilities: float[]) = + Categorical.CheckParam probabilities + Interval.CreateClosed(0, probabilities.Length - 1) + + /// Returns a string representation of the categorical distribution. + /// An array of probabilities over k categories. + /// A string describing the distribution. + static member ToString (probabilities: float[]) = + sprintf "Categorical(p = [%s])" (String.concat "; " (probabilities |> Array.map string)) + + /// Fits the categorical distribution to a set of integer observations (category indices). + /// Total number of categories. + /// Array of category indices (0-based). + /// Estimated probability vector. + static member Fit (numCategories:int) (observations:int[]) = + let counts = Array.zeroCreate numCategories + for i in observations do + if i < 0 || i >= numCategories then + failwithf "Observation index %d out of bounds [0, %d]" i (numCategories - 1) + counts[i] <- counts[i] + 1 + let total = float (Array.sum counts) + counts |> Array.map (fun c -> float c / total) + + /// Estimates a categorical distribution from observed category indices. + /// Total number of categories. + /// Array of category indices (0-based). + /// A categorical distribution fitted to the observations. + static member Estimate numCategories observations = + Categorical.Fit numCategories observations + |> fun probs -> Categorical.Init probs + + /// Initializes a categorical distribution instance from a given probability vector. + /// An array of probabilities over k categories. + /// A distribution implementing DiscreteDistribution<float, int>. + static member Init (probabilities: float[]) = + Categorical.CheckParam probabilities + { new DiscreteDistribution with + member d.Mean = Categorical.Mean probabilities + member d.Variance = Categorical.Variance probabilities + member d.StandardDeviation = sqrt (Categorical.Variance probabilities) + member d.Sample () = Categorical.Sample probabilities + member d.CDF x = Categorical.CDF probabilities x + member d.InvCDF x = failwith "InvCDF not implemented for Categorical" + member d.Mode = probabilities |> Array.mapi (fun i p -> i, p) |> Array.maxBy snd |> fst + member d.PMF k = Categorical.PMF probabilities k + member d.Parameters = DistributionParameters.Categorical probabilities + override d.ToString() = Categorical.ToString probabilities + } + + + /// + /// Converts a cumulative unnormalized weight array into a normalized PMF. + /// + /// An array of cumulative weights. + /// A normalized probability mass function. + static member CdfToPmf (cdf: float[]) = + if cdf.Length = 0 then failwith "CDF must not be empty." + if cdf |> Array.exists (fun x -> x < 0. || Ops.isNan x) then + failwith "CDF values must be non-negative." + let pmf = + Array.init cdf.Length (fun i -> + if i = 0 then cdf.[0] + else cdf.[i] - cdf.[i - 1]) + let total = Array.sum pmf + if total = 0.0 then failwith "CDF must contain non-zero mass." + pmf |> Array.map (fun x -> x / total) + + /// + /// Initializes a Categorical distribution from an unnormalized CDF. + /// + /// An array of cumulative unnormalized weights. + /// A normalized Categorical distribution. + static member FromCdfUnnormalized (cdf: float[]) = + let probs = Categorical.CdfToPmf cdf + Categorical.Init probs + diff --git a/src/FSharp.Stats/Distributions/Discrete/LabelledCategorical.fs b/src/FSharp.Stats/Distributions/Discrete/LabelledCategorical.fs new file mode 100644 index 000000000..ef8d194bf --- /dev/null +++ b/src/FSharp.Stats/Distributions/Discrete/LabelledCategorical.fs @@ -0,0 +1,125 @@ +namespace FSharp.Stats.Distributions.Discrete + +open FSharp.Stats +open FSharp.Stats.Distributions + +/// +/// A wrapper around the Categorical distribution that associates each probability with a custom label of type 'Label. +/// +/// The type used to label the categories (e.g., string, union, enum). +type LabelledCategorical<'Label when 'Label: comparison> private + ( + labelToIndex: Map<'Label, int>, + indexToLabel: 'Label[], + probs: float[] + ) = + + let dist = Categorical.Init probs + + /// + /// Initializes a new instance of the LabelledCategorical distribution using label-probability pairs. + /// + /// An array of labels for each category (must be unique). + /// An array of probabilities for each label (must sum to 1). + new (labels: 'Label[], probs: float[]) = + if labels.Length <> probs.Length then + failwith "Label and probability array must be the same length." + let labelToIndex = labels |> Array.mapi (fun i l -> l, i) |> Map.ofArray + LabelledCategorical(labelToIndex, labels, probs) + + /// + /// Gets the array of category labels. + /// + member _.Labels : 'Label[] = indexToLabel + + /// + /// Gets the array of probabilities associated with the labels. + /// + member _.Probabilities : float[] = probs + + /// + /// Returns the probability of a given label. + /// + /// The label to query. + /// The probability associated with the label, or 0.0 if the label is not found. + member _.PMF(label: 'Label) = + match Map.tryFind label labelToIndex with + | Some i -> dist.PMF i + | None -> 0.0 + + /// + /// Returns the cumulative probability up to and including the given label. + /// + /// The label to evaluate the cumulative probability up to. + /// The cumulative probability. + member _.CDF(label: 'Label) = + match Map.tryFind label labelToIndex with + | Some i -> probs |> Array.take (i + 1) |> Array.sum + | None -> 0.0 + + /// + /// Returns the array of labels (support of the distribution). + /// + member _.Support = indexToLabel + + /// + /// Draws a random sample from the distribution and returns the sampled label. + /// + /// A label corresponding to a sampled category. + member _.Sample() = + let i = dist.Sample() + indexToLabel[i] + + /// + /// Returns the label closest to the expected (mean) index of the distribution. + /// + /// The label whose index is closest to the mean. + member _.MeanLabel() = + let mi = dist.Mean |> round |> int + indexToLabel[mi] + + /// + /// Fits a LabelledCategorical distribution from a set of labeled observations. + /// + /// An array of observed labels. + /// A new LabelledCategorical distribution with probabilities estimated from observed frequencies. + static member Fit (observations: 'Label[]) = + observations + |> Array.countBy id + |> Array.sortBy fst + |> fun counts -> + let total = float observations.Length + let labelArray = counts |> Array.map fst + let probs = counts |> Array.map (fun (_, c) -> float c / total) + LabelledCategorical(labelArray, probs) + + /// + /// Estimates a distribution from labels and counts (frequencies). + /// + /// An array of labels. + /// An array of counts corresponding to each label. + /// A new LabelledCategorical distribution. + static member Estimate (labels: 'Label[]) (counts: int[]) = + if labels.Length <> counts.Length then + failwith "Labels and counts must be the same length." + let total = float (Array.sum counts) + let probs = counts |> Array.map (fun c -> float c / total) + LabelledCategorical(labels, probs) + + + /// + /// Initializes a LabelledCategorical distribution from labels and a cumulative unnormalized weight vector. + /// + /// Labels corresponding to cumulative weights. + /// Unnormalized cumulative weights (must be increasing). + /// A normalized LabelledCategorical distribution. + static member FromCdfUnnormalized(labels: 'Label[], cdf: float[]) = + if labels.Length <> cdf.Length then + failwith "Labels and cumulative weights must be the same length." + let deltas = + Array.init cdf.Length (fun i -> + if i = 0 then cdf.[0] + else cdf.[i] - cdf.[i - 1]) + let total = Array.sum deltas + let probs = deltas |> Array.map (fun x -> x / total) + LabelledCategorical(labels, probs) diff --git a/src/FSharp.Stats/FSharp.Stats.fsproj b/src/FSharp.Stats/FSharp.Stats.fsproj index 31d570668..00a4c4621 100644 --- a/src/FSharp.Stats/FSharp.Stats.fsproj +++ b/src/FSharp.Stats/FSharp.Stats.fsproj @@ -108,6 +108,8 @@ + + From cf1aa55d8ba183a234db787f8fa85b601d6fe489 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20M=C3=BChlhaus?= Date: Sun, 13 Apr 2025 16:44:35 +0200 Subject: [PATCH 034/121] Add sampling from multinomial distribution --- .../Distributions/Discrete/Multinomial.fs | 30 ++++++++++++++----- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/src/FSharp.Stats/Distributions/Discrete/Multinomial.fs b/src/FSharp.Stats/Distributions/Discrete/Multinomial.fs index 8cc737607..7660c19b9 100644 --- a/src/FSharp.Stats/Distributions/Discrete/Multinomial.fs +++ b/src/FSharp.Stats/Distributions/Discrete/Multinomial.fs @@ -48,17 +48,31 @@ type Multinomial = Multinomial.CheckParam p n Array.map sqrt (Multinomial.Variance p n) + /// + /// Converts a probability mass function into an unnormalized cumulative distribution function (CDF). + /// + /// An array of probabilities (not validated). + /// An array of cumulative probabilities. + static member ProbabilityMassToCumulativeDistribution (p : float[]) = + let cdfUnnormalized = Array.zeroCreate p.Length + cdfUnnormalized[0] <- p[0] + for i = 1 to p.Length - 1 do + cdfUnnormalized[i] <- cdfUnnormalized[i - 1] + p[i] + cdfUnnormalized + /// Produces a random sample using the current random number generator (from GetSampleGenerator()). No parameter checking! /// /// vector of event probabilities in each trial - /// number of trails - /// - /// - /// - /// - /// - static member internal SampleUnchecked p n = - failwithf "Not implemented yet" + /// number of trails(must be ≥ 0). + /// An array of counts per category. + static member SampleUnchecked (p : float[]) n = + let cp = Multinomial.ProbabilityMassToCumulativeDistribution p + let ret = Array.zeroCreate p.Length + for _ = 1 to n do + let idx = Categorical.SampleUnchecked cp + ret[idx] <- ret[idx] + 1 + ret + /// Produces a random sample using the current random number generator (from GetSampleGenerator()). /// From a854ed50f45c11dffba5fda6841653e5da7b0091 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20M=C3=BChlhaus?= Date: Sun, 13 Apr 2025 17:11:27 +0200 Subject: [PATCH 035/121] Add Unit testing categorical distribution --- .../Distributions/Distribution.fs | 1 + .../DistributionsDiscrete.fs | 120 ++++++++++++++++++ 2 files changed, 121 insertions(+) diff --git a/src/FSharp.Stats/Distributions/Distribution.fs b/src/FSharp.Stats/Distributions/Distribution.fs index 17ee2d05d..0952617de 100644 --- a/src/FSharp.Stats/Distributions/Distribution.fs +++ b/src/FSharp.Stats/Distributions/Distribution.fs @@ -92,6 +92,7 @@ type DistributionParameters = // Discrete distributions | Bernoulli of Parameters.Bernoulli | Binomial of Parameters.Binomial + | Categorical of float[] | NegativeBinomial of Parameters.NegativeBinomial | Hypergeometric of Parameters.Hypergeometric | Poisson of Parameters.Poisson diff --git a/tests/FSharp.Stats.Tests/DistributionsDiscrete.fs b/tests/FSharp.Stats.Tests/DistributionsDiscrete.fs index 029354c87..24a5feed8 100644 --- a/tests/FSharp.Stats.Tests/DistributionsDiscrete.fs +++ b/tests/FSharp.Stats.Tests/DistributionsDiscrete.fs @@ -379,6 +379,126 @@ let binomialTests = ] +[] +let categoricalTests = + testList "Categorical distribution tests" [ + + test "CheckParam should fail on invalid probabilities" { + let invalid1 = [| -0.1; 0.6; 0.5 |] + let invalid2 = [| 0.2; 0.3; 0.4 |] // sum ≠ 1.0 + Expect.throws (fun () -> Discrete.Categorical.CheckParam invalid1) "Negative probability should throw" + Expect.throws (fun () -> Discrete.Categorical.CheckParam invalid2) "Probabilities that do not sum to 1.0 should throw" + } + + test "PMF returns correct probability" { + let p = [| 0.2; 0.3; 0.5 |] + let d = Discrete.Categorical.Init p + Expect.floatClose Accuracy.high (d.PMF 0) 0.2 "PMF for category 0" + Expect.floatClose Accuracy.high (d.PMF 1) 0.3 "PMF for category 1" + Expect.floatClose Accuracy.high (d.PMF 2) 0.5 "PMF for category 2" + Expect.equal (d.PMF 3) 0.0 "PMF for out-of-range index" + } + + test "CDF returns correct cumulative probability" { + let p = [| 0.1; 0.2; 0.3; 0.4 |] + let d = Discrete.Categorical.Init p + Expect.floatClose Accuracy.high (d.CDF -1.0) 0.0 "CDF below 0" + Expect.floatClose Accuracy.high (d.CDF 0.0) 0.1 "CDF at 0" + Expect.floatClose Accuracy.high (d.CDF 1.0) 0.3 "CDF at 1" + Expect.floatClose Accuracy.high (d.CDF 2.0) 0.6 "CDF at 2" + Expect.floatClose Accuracy.high (d.CDF 3.0) 1.0 "CDF at 3" + Expect.floatClose Accuracy.high (d.CDF 4.0) 1.0 "CDF above max index" + } + + test "Sampling produces plausible frequencies" { + let p = [| 0.1; 0.3; 0.6 |] + let d = Discrete.Categorical.Init p + let samples = Array.init 10000 (fun _ -> d.Sample()) + let freqs = samples |> Array.countBy id |> Map.ofArray + let getFreq k = Map.tryFind k freqs |> Option.defaultValue 0 |> float + let total = float samples.Length + Expect.floatClose fittingAccuracy (getFreq 0 / total) 0.1 "Sample frequency for 0" + Expect.floatClose fittingAccuracy (getFreq 1 / total) 0.3 "Sample frequency for 1" + Expect.floatClose fittingAccuracy (getFreq 2 / total) 0.6 "Sample frequency for 2" + } + + test "Mean and variance are correctly computed" { + let p = [| 0.0; 0.5; 0.5 |] + let d =Discrete.Categorical.Init p + Expect.floatClose Accuracy.high d.Mean 1.5 "Mean should be 1.5" + Expect.floatClose Accuracy.high d.Variance 0.25 "Variance should be 0.25" + } + + test "Fit returns estimated probabilities from observations" { + let observations = [| 0; 1; 1; 2; 2; 2 |] + let est = Discrete.Categorical.Fit 3 observations + Expect.floatClose Accuracy.high est[0] (1.0/6.0) "P(0)" + Expect.floatClose Accuracy.high est[1] (2.0/6.0) "P(1)" + Expect.floatClose Accuracy.high est[2] (3.0/6.0) "P(2)" + } + + test "Estimate returns a distribution with valid PMFs" { + let observations = [| 0; 0; 1; 2; 2; 2 |] + let d = Discrete.Categorical.Estimate 3 observations + Expect.floatClose Accuracy.high (d.PMF 0) (2.0/6.0) "PMF for category 0" + Expect.floatClose Accuracy.high (d.PMF 1) (1.0/6.0) "PMF for category 1" + Expect.floatClose Accuracy.high (d.PMF 2) (3.0/6.0) "PMF for category 2" + } + + ] + + +[] +let labelledCategoricalTests = + testList "LabelledCategorical tests" [ + + test "PMF returns correct probability for labels" { + let labels = [| "A"; "B"; "C" |] + let probs = [| 0.2; 0.3; 0.5 |] + let d = Discrete.LabelledCategorical(labels, probs) + Expect.floatClose Accuracy.high (d.PMF "A") 0.2 "PMF A" + Expect.floatClose Accuracy.high (d.PMF "B") 0.3 "PMF B" + Expect.floatClose Accuracy.high (d.PMF "C") 0.5 "PMF C" + } + + test "CDF computes cumulative probabilities" { + let labels = [| "A"; "B"; "C" |] + let probs = [| 0.1; 0.2; 0.7 |] + let d = Discrete.LabelledCategorical(labels, probs) + Expect.floatClose Accuracy.high (d.CDF "A") 0.1 "CDF A" + Expect.floatClose Accuracy.high (d.CDF "B") 0.3 "CDF B" + Expect.floatClose Accuracy.high (d.CDF "C") 1.0 "CDF C" + } + + test "Sampling returns expected label frequencies" { + let labels = [| "Yes"; "No" |] + let probs = [| 0.7; 0.3 |] + let d = Discrete.LabelledCategorical(labels, probs) + let samples = Array.init 10000 (fun _ -> d.Sample()) + let freq = samples |> Array.countBy id |> Map.ofArray + let yesFreq = Map.tryFind "Yes" freq |> Option.defaultValue 0 |> float + Expect.floatClose fittingAccuracy (yesFreq / 10000.0) 0.7 "Sampling approx 70%" + } + + test "Fit estimates correct probabilities from observations" { + let observations = [| "X"; "X"; "Y"; "Z"; "Z"; "Z" |] + let d = Discrete.LabelledCategorical.Fit observations + Expect.floatClose Accuracy.high (d.PMF "X") (2.0/6.0) "P(X)" + Expect.floatClose Accuracy.high (d.PMF "Y") (1.0/6.0) "P(Y)" + Expect.floatClose Accuracy.high (d.PMF "Z") (3.0/6.0) "P(Z)" + } + + test "Estimate constructs distribution from labels and counts" { + let labels = [| "Red"; "Green"; "Blue" |] + let counts = [| 3; 1; 6 |] + let d = Discrete.LabelledCategorical.Estimate labels counts + Expect.floatClose Accuracy.high (d.PMF "Red") 0.3 "P(Red)" + Expect.floatClose Accuracy.high (d.PMF "Green") 0.1 "P(Green)" + Expect.floatClose Accuracy.high (d.PMF "Blue") 0.6 "P(Blue)" + } + + ] + [] let multinomialTests = From 6b231f300096e273b759eb74efcb6ff9de20fc85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20M=C3=BChlhaus?= Date: Sun, 13 Apr 2025 22:59:32 +0200 Subject: [PATCH 036/121] Add unit testing for Multinomial.sample --- .../Distributions/Discrete/Multinomial.fs | 4 +- src/FSharp.Stats/Playground.fsx | 78 +++++++++++++++++++ .../DistributionsDiscrete.fs | 15 ++++ 3 files changed, 95 insertions(+), 2 deletions(-) diff --git a/src/FSharp.Stats/Distributions/Discrete/Multinomial.fs b/src/FSharp.Stats/Distributions/Discrete/Multinomial.fs index 7660c19b9..c1b6bbda6 100644 --- a/src/FSharp.Stats/Distributions/Discrete/Multinomial.fs +++ b/src/FSharp.Stats/Distributions/Discrete/Multinomial.fs @@ -66,10 +66,10 @@ type Multinomial = /// number of trails(must be ≥ 0). /// An array of counts per category. static member SampleUnchecked (p : float[]) n = - let cp = Multinomial.ProbabilityMassToCumulativeDistribution p + //let cp = Multinomial.ProbabilityMassToCumulativeDistribution p let ret = Array.zeroCreate p.Length for _ = 1 to n do - let idx = Categorical.SampleUnchecked cp + let idx = Categorical.SampleUnchecked p ret[idx] <- ret[idx] + 1 ret diff --git a/src/FSharp.Stats/Playground.fsx b/src/FSharp.Stats/Playground.fsx index ac76cc2c3..89a1bf27f 100644 --- a/src/FSharp.Stats/Playground.fsx +++ b/src/FSharp.Stats/Playground.fsx @@ -8,6 +8,84 @@ open FSharp.Stats.Distributions //open Plotly.NET open FSharp.Stats.Algebra + + +let Categorical_SampleUnchecked (probabilities: float[]) = + let rnd = Random.rndgen.NextFloat() + let rec search i acc = + if i >= probabilities.Length then probabilities.Length - 1 + elif acc + probabilities[i] >= rnd then i + else search (i + 1) (acc + probabilities[i]) + search 0 0.0 + + + + +/// Helper function to sample many times and collect counts. +let sampleMany (times: int) (probabilities: float[]) = + let counts = Array.zeroCreate probabilities.Length + for _ in 1 .. times do + let idx = Categorical_SampleUnchecked probabilities + counts.[idx] <- counts.[idx] + 1 + counts + + + +let p = [| 0.2; 0.3; 0.5 |] +let iterations = 10000000 + +Array.init iterations (fun _ -> Categorical_SampleUnchecked p) +|> Array.countBy id + + + +// Act +let counts = sampleMany iterations p +float counts.[2] / float iterations + + +// Assert +// All indices should be between 0 and p.Length - 1 +// If out of range, an exception would occur while incrementing counts. +// So, if we got this far without an exception, the function is generating valid indices. +// We can add an extra check that the sum of counts equals 'iterations'. +let total = Array.sum counts + + +let SampleUnchecked (p : float[]) n = + //let cp = Discrete.Multinomial.ProbabilityMassToCumulativeDistribution p + let ret = Array.zeroCreate p.Length + for _ = 1 to n do + let idx = Discrete.Categorical.SampleUnchecked p + ret[idx] <- ret[idx] + 1 + ret + +let n = 100000 // Large n to reduce variance +let probabilities = [| 0.2; 0.3; 0.5 |] +//// Act +//let sampleCounts = Categorical_SampleUnchecked probabilities + +//probabilities +//|> Array.iteri (fun i p -> +// let observedProportion = float sampleCounts.[i] / float n +// printfn $"Probability of {i}: {p}, Observed proportion: {observedProportion}") + + + +//let n = 100000 // Larger n to reduce sampling variance +let sample = SampleUnchecked probabilities n + +let () = + probabilities + |> Array.iteri (fun i p -> + let observedProportion = float sample.[i] / float n + printfn $"Probability of {i}: {p}, Observed proportion: {observedProportion}") + + + +Discrete.Multinomial.ProbabilityMassToCumulativeDistribution probabilities + + let KDiagonal1 = [| [|1.;0.;0.|] diff --git a/tests/FSharp.Stats.Tests/DistributionsDiscrete.fs b/tests/FSharp.Stats.Tests/DistributionsDiscrete.fs index 24a5feed8..47280168a 100644 --- a/tests/FSharp.Stats.Tests/DistributionsDiscrete.fs +++ b/tests/FSharp.Stats.Tests/DistributionsDiscrete.fs @@ -590,6 +590,21 @@ let multinomialTests = let x = [|1;2;3|] let testCase() = Discrete.Multinomial.PMF prob5 x Expect.throws (fun _ -> testCase() |> ignore) "probabilities of 0 is associated to success event" + + test "Sample proportions should be close to the expected probabilities" { + let probabilities = [| 0.2; 0.3; 0.5 |] + let n = 100000 // Larger n to reduce sampling variance + let sample = Discrete.Multinomial.Sample probabilities n + probabilities + |> Array.iteri (fun i p -> + let observedProportion = float sample.[i] / float n + Expect.floatClose + Accuracy.low // or a custom `floatClose` config + observedProportion + p + $"Observed proportion ({observedProportion}) should be close to expected probability ({p})" + ) + } ] [] From ddf5e26957886463506f098fb0557f30ca872471 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20M=C3=BChlhaus?= Date: Sun, 13 Apr 2025 23:42:22 +0200 Subject: [PATCH 037/121] Add testing accuracy veryLow for random sampling tests --- tests/FSharp.Stats.Tests/DistributionsDiscrete.fs | 6 +++--- tests/FSharp.Stats.Tests/TestExtensions.fs | 5 +++++ 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/tests/FSharp.Stats.Tests/DistributionsDiscrete.fs b/tests/FSharp.Stats.Tests/DistributionsDiscrete.fs index 47280168a..d20692289 100644 --- a/tests/FSharp.Stats.Tests/DistributionsDiscrete.fs +++ b/tests/FSharp.Stats.Tests/DistributionsDiscrete.fs @@ -4,7 +4,7 @@ open Expecto open System open FSharp.Stats open FSharp.Stats.Distributions - +open TestExtensions // Defining an accuracy appropriate for testing random sampling and inference let fittingAccuracy : Accuracy = {absolute= 0.1 ;relative= 0.1} @@ -593,13 +593,13 @@ let multinomialTests = test "Sample proportions should be close to the expected probabilities" { let probabilities = [| 0.2; 0.3; 0.5 |] - let n = 100000 // Larger n to reduce sampling variance + let n = 1000000 // Larger n to reduce sampling variance let sample = Discrete.Multinomial.Sample probabilities n probabilities |> Array.iteri (fun i p -> let observedProportion = float sample.[i] / float n Expect.floatClose - Accuracy.low // or a custom `floatClose` config + Accuracy.veryLow // or a custom `floatClose` config observedProportion p $"Observed proportion ({observedProportion}) should be close to expected probability ({p})" diff --git a/tests/FSharp.Stats.Tests/TestExtensions.fs b/tests/FSharp.Stats.Tests/TestExtensions.fs index 09c1b8a0c..f427bc5f8 100644 --- a/tests/FSharp.Stats.Tests/TestExtensions.fs +++ b/tests/FSharp.Stats.Tests/TestExtensions.fs @@ -8,6 +8,11 @@ open System.Text open System.Reflection + module Accuracy = + /// veryLow accuracy: absolute = 1e-4, relative = 1e-1 + let veryLow = { absolute = 1e-4; relative = 1e-1 } + + type TestExtensions() = static member sequenceEqual(digits: int) = let round (v:float) = System.Math.Round(v,digits) From 616d3c6e2cf608c69bfa7c7ccdf8bcb5ac1086ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20M=C3=BChlhaus?= Date: Thu, 17 Apr 2025 18:13:23 +0200 Subject: [PATCH 038/121] Add Geometric distribution --- .../Distributions/Discrete/Geometric.fs | 154 ++++++++++++++++++ 1 file changed, 154 insertions(+) create mode 100644 src/FSharp.Stats/Distributions/Discrete/Geometric.fs diff --git a/src/FSharp.Stats/Distributions/Discrete/Geometric.fs b/src/FSharp.Stats/Distributions/Discrete/Geometric.fs new file mode 100644 index 000000000..c5504b69b --- /dev/null +++ b/src/FSharp.Stats/Distributions/Discrete/Geometric.fs @@ -0,0 +1,154 @@ +namespace FSharp.Stats.Distributions.Discrete + +open System +open System.Numerics +open FSharp.Stats +open FSharp.Stats.Distributions +open FSharp.Stats.GenericMath + +//IFloatingPoint + +/// +/// Geometric distribution (number of failures before the first success). +/// +type Geometric = + + /// Checks whether the parameter is valid (0.0 < p <= 1.0). + static member inline CheckParam<'T when 'T :> Numerics.INumber<'T> + and 'T : comparison + and 'T : (new : unit -> 'T)> + (p: 'T) = + if p <= 'T.Zero || p > 'T.One then + failwith "Geometric distribution requires 0.0 < p <= 1.0" + + /// Computes the mean: (1 - p) / p + static member inline Mean<'T when 'T :> Numerics.INumber<'T> + and 'T : comparison + and 'T : (new : unit -> 'T)> + (p: 'T) = + Geometric.CheckParam p + ('T.One - p) / p + + /// Computes the variance: (1 - p) / p^2 + static member inline Variance<'T when 'T :> Numerics.INumber<'T> + and 'T : comparison + and 'T : (new : unit -> 'T)> + (p: 'T) = + Geometric.CheckParam p + ('T.One - p) / (p * p) + + /// Computes the standard deviation. + static member inline StandardDeviation<'T when 'T :> Numerics.INumber<'T> + and Numerics.IRootFunctions<'T> + and 'T : comparison + and 'T : (new : unit -> 'T)> + (p: 'T) = + Geometric.CheckParam p + (( 'T.One - p ) / (p * p)) |> GenericMath.sqrt + + /// Computes the mode (always 0). + static member inline Mode<'T when 'T :> Numerics.INumber<'T> + and 'T : comparison + and 'T : (new : unit -> 'T)> + (p: 'T) = + Geometric.CheckParam p + LanguagePrimitives.GenericZero<'T> + + /// Computes the PMF: P(X = k) = (1 - p)^k * p + static member inline PMF<'T when 'T :> Numerics.INumber<'T> + and Numerics.IPowerFunctions<'T> + and 'T : comparison + and 'T : (new : unit -> 'T)> + (p: 'T) (k: int) : 'T = + Geometric.CheckParam p + if k < 0 then 'T.Zero + else + let q = 'T.One - p + p * q ** (T k) + + /// Computes the CDF: P(X ≤ k) = 1 - (1 - p)^(k + 1) + static member inline CDF<'T when 'T :> Numerics.INumber<'T> + and Numerics.IPowerFunctions<'T> + and 'T : comparison + and 'T : (new : unit -> 'T)> + (p: 'T) (k: int) : 'T = + Geometric.CheckParam p + if k < 0 then 'T.Zero + else + let q = 'T.One - p + let tmp = k + 1 + 'T.One - (GenericMath.pow q (T tmp)) + + /// Computes the inverse CDF (quantile function). + static member inline InvCDF<'T when 'T :> Numerics.IFloatingPoint<'T> + and Numerics.ILogarithmicFunctions<'T> + and 'T : comparison + and 'T : (new : unit -> 'T)> + (p: 'T) (x: 'T) = // : int = + Geometric.CheckParam p + if x < 'T.Zero || x > 'T.One then failwith "x must be in [0.0, 1.0]" + let oneMinusX = GenericMath.log ('T.One - x) + let oneMinusP = GenericMath.log ('T.One - p) + let raw = oneMinusX / oneMinusP + GenericMath.floor raw + |> Convert.ToInt32 + + /// samples a value using the built-in random number generator. + static member inline sample<'T when 'T :> Numerics.IFloatingPoint<'T> + and Numerics.ILogarithmicFunctions<'T> + and 'T : comparison + and 'T : (new : unit -> 'T)> + (p: 'T) : int = + Geometric.CheckParam p + let u = 'T.CreateTruncating(Random.rndgen.NextFloat()) + let oneMinusX = GenericMath.log ('T.One - u) + let oneMinusP = GenericMath.log ('T.One - p) + let raw = oneMinusX / oneMinusP + GenericMath.floor raw + |> Convert.ToInt32 + + /// Fits the distribution by estimating p = 1 / (mean + 1). + static member inline Fit<'T when 'T :> Numerics.IFloatingPoint<'T> + and 'T : (static member DivideByInt : 'T * int -> 'T) + and Numerics.ILogarithmicFunctions<'T> + and 'T : comparison + and 'T : (new : unit -> 'T) + and 'T : struct + and 'T :> ValueType> + (observations: 'T[], ?weights: 'T[]) : 'T = + let mean = + match weights with + | None -> Vector.mean observations + | Some w -> Array.weightedMean w observations + 'T.One / (mean + 'T.One) + + ///// Estimates and returns a new initialized distribution instance. + //static member inline Estimate(observations: 'T[], ?weights: 'T[]) = + // let p = Geometric.Fit(observations, ?weights = weights) + // Geometric.Init p + + ///// Returns the support of the geometric distribution: {0, 1, 2, ...}. + //static member inline Support(p: 'T) = + // Geometric.CheckParam p + // Interval.CreateLowerBounded(0) + + /// Returns a formatted string representation. + static member inline ToString(p: 'T) = + $"Geometric(p = {p})" + + ///// Initializes the generic geometric distribution. + //static member inline Init(p: 'T) = + // { new DiscreteDistribution<'T, int> with + // member _.Mean = Geometric.Mean p + // member _.Variance = Geometric.Variance p + // member _.StandardDeviation = Geometric.StandardDeviation p + // member _.CDF x = Geometric.CDF(p, x) + // member _.InvCDF x = Geometric.InvCDF(p, x) + // member _.Mode = Geometric.Mode p + // member _.Sample() = Geometric.Sample p + // member _.PMF x = Geometric.PMF(p, x) + // member _.Parameters = DistributionParameters.Geometric {P = float p} // Assumes parameter storage as float + // override _.ToString() = Geometric.ToString p + // } + + From 837a8df254cce0c0c8f418b3289ca3ed4e926510 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20M=C3=BChlhaus?= Date: Thu, 17 Apr 2025 18:33:10 +0200 Subject: [PATCH 039/121] Add Vector.pow --- src/FSharp.Stats/AlgTypes/GenericMath.fs | 16 +++++++++------- src/FSharp.Stats/AlgTypes/VectorExt.fs | 5 +++++ src/FSharp.Stats/FSharp.Stats.fsproj | 1 + 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/FSharp.Stats/AlgTypes/GenericMath.fs b/src/FSharp.Stats/AlgTypes/GenericMath.fs index 8bb1e0543..8ed65f3ef 100644 --- a/src/FSharp.Stats/AlgTypes/GenericMath.fs +++ b/src/FSharp.Stats/AlgTypes/GenericMath.fs @@ -45,19 +45,21 @@ module GenericMath = let inline cos<'T when 'T :> Numerics.ITrigonometricFunctions<'T>> (x: 'T) : 'T = 'T.Cos(x) - // /// Generic pi constant - // let inline pi<'T when 'T :> Numerics.IFloatingPointConstants<'T> and 'T :> Numerics.INumber<'T>> () : 'T = - // pi<'T>() + /// Generic pi constant + let inline pi<'T when 'T :> Numerics.IFloatingPointConstants<'T> and 'T :> Numerics.INumber<'T>> () : 'T = + 'T.Pi /// Generic e constant (Euler's number) let inline e<'T when 'T :> Numerics.IFloatingPointConstants<'T>> () : 'T = 'T.E - // /// Generic tau constant (2 * pi) - // let inline tau<'T when 'T :> Numerics.IFloatingPointConstants<'T> and 'T :> Numerics.INumber<'T>> () : 'T = - // T<'T> 2.0 * pi<'T>() - + /// Generic tau constant (2 * pi) + let inline tau<'T when 'T :> Numerics.IFloatingPointConstants<'T> and 'T :> Numerics.INumber<'T>> () : 'T = + 'T.Tau + /// Generic floor function + let inline floor<'T when 'T :> Numerics.IFloatingPoint<'T>> (x: 'T) : 'T = + 'T. Floor(x) // let inline min x y = if x < y then x else y diff --git a/src/FSharp.Stats/AlgTypes/VectorExt.fs b/src/FSharp.Stats/AlgTypes/VectorExt.fs index 22be07622..e9a721997 100644 --- a/src/FSharp.Stats/AlgTypes/VectorExt.fs +++ b/src/FSharp.Stats/AlgTypes/VectorExt.fs @@ -209,3 +209,8 @@ module Vector = /// let inline ofSeq (s:seq<'T>) : Vector<'T> = s |> Array.ofSeq + + + /// + let inline pow (power: 'T) (v:Vector<'T>) : Vector<'T> = + v |> Array.map (fun x -> GenericMath.pow x power) diff --git a/src/FSharp.Stats/FSharp.Stats.fsproj b/src/FSharp.Stats/FSharp.Stats.fsproj index 00a4c4621..8ba72819e 100644 --- a/src/FSharp.Stats/FSharp.Stats.fsproj +++ b/src/FSharp.Stats/FSharp.Stats.fsproj @@ -109,6 +109,7 @@ + From 210a40398f7b7da9c6a6d77872ae03b1d4a724ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20M=C3=BChlhaus?= Date: Thu, 17 Apr 2025 18:33:35 +0200 Subject: [PATCH 040/121] Change Vector scalar parameter order --- src/FSharp.Stats/AlgTypes/Vector.fs | 12 ++++++++---- src/FSharp.Stats/AlgTypes/VectorOps.fs | 15 +++++++++------ src/FSharp.Stats/Algebra/LinearAlgebra.fs | 2 +- tests/FSharp.Stats.Tests/Vector.fs | 16 ++++++++-------- 4 files changed, 26 insertions(+), 19 deletions(-) diff --git a/src/FSharp.Stats/AlgTypes/Vector.fs b/src/FSharp.Stats/AlgTypes/Vector.fs index d32954d85..4d99f727e 100644 --- a/src/FSharp.Stats/AlgTypes/Vector.fs +++ b/src/FSharp.Stats/AlgTypes/Vector.fs @@ -95,7 +95,8 @@ type Vector = static member inline addScalar<'T when 'T :> Numerics.INumber<'T> and 'T : (new: unit -> 'T) and 'T : struct - and 'T :> ValueType> (v:Vector<'T>) (scalar:'T) : Vector<'T> = + and 'T :> ValueType> + (scalar:'T) (v:Vector<'T>) : Vector<'T> = if Numerics.Vector.IsHardwareAccelerated then Acceleration.SIMDUtils.mapScalar (+) (+) v scalar @@ -110,7 +111,8 @@ type Vector = static member inline subtractScalar<'T when 'T :> Numerics.INumber<'T> and 'T : (new: unit -> 'T) and 'T : struct - and 'T :> ValueType> (v:Vector<'T>) (scalar:'T) : Vector<'T> = + and 'T :> ValueType> + (scalar:'T) (v:Vector<'T>) : Vector<'T> = if Numerics.Vector.IsHardwareAccelerated then Acceleration.SIMDUtils.mapScalar (-) (-) v scalar else @@ -124,7 +126,8 @@ type Vector = static member inline multiplyScalar<'T when 'T :> Numerics.INumber<'T> and 'T : (new: unit -> 'T) and 'T : struct - and 'T :> ValueType> (v:Vector<'T>) (scalar:'T) : Vector<'T> = + and 'T :> ValueType> + (scalar:'T) (v:Vector<'T>) : Vector<'T> = if Numerics.Vector.IsHardwareAccelerated then Acceleration.SIMDUtils.mapScalar ( * ) ( * ) v scalar @@ -139,7 +142,8 @@ type Vector = static member inline divideScalar<'T when 'T :> Numerics.INumber<'T> and 'T : (new: unit -> 'T) and 'T : struct - and 'T :> ValueType> (v:Vector<'T>) (scalar:'T) : Vector<'T> = + and 'T :> ValueType> + (scalar:'T) (v:Vector<'T>) : Vector<'T> = if Numerics.Vector.IsHardwareAccelerated then Acceleration.SIMDUtils.mapScalar ( / ) ( / ) v scalar diff --git a/src/FSharp.Stats/AlgTypes/VectorOps.fs b/src/FSharp.Stats/AlgTypes/VectorOps.fs index ab93bcd00..6ca4e458b 100644 --- a/src/FSharp.Stats/AlgTypes/VectorOps.fs +++ b/src/FSharp.Stats/AlgTypes/VectorOps.fs @@ -7,20 +7,21 @@ type VectorOps = static member inline Plus (a: Vector<'T>, b: Vector<'T>) = Vector.add a b - static member inline Plus (a: Vector<'T>, b: 'T) = Vector.addScalar a b - static member inline Plus (a: 'T, b: Vector<'T>) = Vector.addScalar b a + static member inline Plus (a: Vector<'T>, b: 'T) = Vector.addScalar b a + static member inline Plus (a: 'T, b: Vector<'T>) = Vector.addScalar a b static member inline Minus (a: Vector<'T>, b: Vector<'T>) = Vector.subtract a b - static member inline Minus (a: Vector<'T>, b: 'T) = Vector.subtractScalar a b + static member inline Minus (a: Vector<'T>, b: 'T) = Vector.subtractScalar b a static member inline Multiply (a: Vector<'T>, b: Vector<'T>) = Vector.multiply a b - static member inline Multiply (a: Vector<'T>, b: 'T) = Vector.multiplyScalar a b - static member inline Multiply (a: 'T, b: Vector<'T>) = Vector.multiplyScalar b a + static member inline Multiply (a: Vector<'T>, b: 'T) = Vector.multiplyScalar b a + static member inline Multiply (a: 'T, b: Vector<'T>) = Vector.multiplyScalar a b static member inline Divide (a: Vector<'T>, b: Vector<'T>) = Vector.divide a b - static member inline Divide (a: Vector<'T>, b: 'T) = Vector.divideScalar a b + static member inline Divide (a: Vector<'T>, b: 'T) = Vector.divideScalar b a + static member inline Power (a: Vector<'T>, power: 'T) = Vector.pow power a // Dispatcher types (Instance resolution) @@ -28,6 +29,7 @@ type Plus = static member inline Invoke (a: ^A, b: ^B) = ((^A or ^B or VectorOps type Minus = static member inline Invoke (a: ^A, b: ^B) = ((^A or ^B or VectorOps) : (static member Minus : ^A * ^B -> _)(a, b)) type Multiply = static member inline Invoke (a: ^A, b: ^B) = ((^A or ^B or VectorOps) : (static member Multiply : ^A * ^B -> _)(a, b)) type Divide = static member inline Invoke (a: ^A, b: ^B) = ((^A or ^B or VectorOps) : (static member Divide : ^A * ^B -> _)(a, b)) +type Power = static member inline Invoke (a: ^A, b: ^B) = ((^A or ^B or VectorOps) : (static member Power : ^A * ^B -> _)(a, b)) // Operators [] @@ -36,6 +38,7 @@ module VectorOpsSymbols = let inline (.-) a b = Minus.Invoke(a, b) let inline (.*) a b = Multiply.Invoke(a, b) let inline (./) a b = Divide.Invoke(a, b) + let inline (.^) a b = Power.Invoke(a, b) // Dot product ( @ ) diff --git a/src/FSharp.Stats/Algebra/LinearAlgebra.fs b/src/FSharp.Stats/Algebra/LinearAlgebra.fs index 7fe1807a6..9bf636a4b 100644 --- a/src/FSharp.Stats/Algebra/LinearAlgebra.fs +++ b/src/FSharp.Stats/Algebra/LinearAlgebra.fs @@ -69,7 +69,7 @@ type LinearAlgebra = let norm = Vector.norm v r.[j, j] <- norm - let qj = Vector.divideScalar v norm + let qj = Vector.divideScalar norm v qCols.[j] <- qj let qData = Array.zeroCreate (m * n) diff --git a/tests/FSharp.Stats.Tests/Vector.fs b/tests/FSharp.Stats.Tests/Vector.fs index 70cfa5713..5d6e313be 100644 --- a/tests/FSharp.Stats.Tests/Vector.fs +++ b/tests/FSharp.Stats.Tests/Vector.fs @@ -83,28 +83,28 @@ let vectorTests = testCase "addScalar: adds scalar to every element" <| fun _ -> let v = [| 1; 2; 3 |] let scalar = 5 - let result = Vector.addScalar v scalar + let result = Vector.addScalar scalar v let expected = [| 6; 7; 8 |] Expect.equal result expected "Should add the scalar to each element" testCase "subtractScalar: subtracts scalar from every element" <| fun _ -> let v = [| 1; 2; 3 |] let scalar = 1 - let result = Vector.subtractScalar v scalar + let result = Vector.subtractScalar scalar v let expected = [| 0; 1; 2 |] Expect.equal result expected "Should subtract the scalar from each element" testCase "multiplyScalar: multiplies scalar to every element" <| fun _ -> let v = [| 2; 4; 6 |] let scalar = 3 - let result = Vector.multiplyScalar v scalar + let result = Vector.multiplyScalar scalar v let expected = [| 6; 12; 18 |] Expect.equal result expected "Should multiply the scalar with each element" testCase "divideScalar: divides every element by scalar" <| fun _ -> let v = [| 10; 20; 30 |] let scalar = 10 - let result = Vector.divideScalar v scalar + let result = Vector.divideScalar scalar v let expected = [| 1; 2; 3 |] Expect.equal result expected "Should divide each element by the scalar" @@ -279,28 +279,28 @@ let vectorTests = testCase "addScalar: adds scalar to every float element" <| fun _ -> let v = [| 1.0; 2.0; 3.0 |] let scalar = 5.5 - let result = Vector.addScalar v scalar + let result = Vector.addScalar scalar v let expected = [| 6.5; 7.5; 8.5 |] Expect.equal result expected "Should add 5.5 to each element" testCase "subtractScalar: subtract scalar from every float element" <| fun _ -> let v = [| 1.0; 2.5; 3.75 |] let scalar = 1.25 - let result = Vector.subtractScalar v scalar + let result = Vector.subtractScalar scalar v let expected = [| -0.25; 1.25; 2.5 |] Expect.equal result expected "Should subtract 1.25 from each element" testCase "multiplyScalar: multiplies scalar with every float element" <| fun _ -> let v = [| 2.5; 4.0; 6.0 |] let scalar = 2.0 - let result = Vector.multiplyScalar v scalar + let result = Vector.multiplyScalar scalar v let expected = [| 5.0; 8.0; 12.0 |] Expect.equal result expected "Should multiply each element by 2.0" testCase "divideScalar: divides every float element by scalar" <| fun _ -> let v = [| 10.0; 20.0; 30.0 |] let scalar = 2.0 - let result = Vector.divideScalar v scalar + let result = Vector.divideScalar scalar v let expected = [| 5.0; 10.0; 15.0 |] Expect.equal result expected "Should divide each element by 2.0" From edc17ec7af78a13f9fd4956dd768991db5745087 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20M=C3=BChlhaus?= Date: Thu, 24 Apr 2025 11:43:10 +0200 Subject: [PATCH 041/121] Add Gamma inverse CDF --- .../Distributions/Continuous/Gamma.fs | 62 +++++++++++++++---- .../DistributionsContinuous.fs | 47 ++++++++++++++ 2 files changed, 97 insertions(+), 12 deletions(-) diff --git a/src/FSharp.Stats/Distributions/Continuous/Gamma.fs b/src/FSharp.Stats/Distributions/Continuous/Gamma.fs index 852f8d8ce..b654725e2 100644 --- a/src/FSharp.Stats/Distributions/Continuous/Gamma.fs +++ b/src/FSharp.Stats/Distributions/Continuous/Gamma.fs @@ -189,19 +189,57 @@ type Gamma = else SpecialFunctions.Gamma.lowerIncompleteRegularized alpha (x / beta) - /// Computes the inverse cumulative distribution function (quantile function). - /// - /// - /// - /// - /// - /// - /// - /// - /// - static member InvCDF alpha beta x = + /// Inverse CDF (quantile function) for the Gamma(α, β) distribution. + /// + /// Uses numerical root-finding (bisection) to solve CDF(x) = p. + /// Requires Gamma.CDF(alpha, beta, x) to be defined. + /// + /// Shape parameter α (must be > 0). + /// Rate parameter β (must be > 0). + /// Cumulative probability in [0, 1]. + /// The quantile value x such that P(X ≤ x) = p. + static member InvCDF + (alpha: float) (beta: float) (p: float) : float = + Gamma.CheckParam alpha beta - failwithf "not implemented yet" + + // Trivial cases + if p = 0. then 0. + elif p = 1. then + inf + //'T.CreateTruncating(1e10) // simulate ∞ + + else + let tolerance = 1e-10//'T.CreateTruncating(1e-10) + let maxIter = 100 + let mutable low = 0. // 'T.Zero + let mutable high = 1. //'T.One + + // Increase high bound until CDF(high) > p + while SpecialFunctions.Gamma.lowerIncompleteRegularized alpha (high / beta) < p do + high <- high * 2. //'T.CreateTruncating(2.0) + + // Bisection loop + let mutable iter = 0 + let mutable result = 0. //'T.Zero + + while iter < maxIter do + let mid = (low + high) / 2. //'T.CreateTruncating(2.0) + let cdfMid = + SpecialFunctions.Gamma.lowerIncompleteRegularized alpha (mid / beta) + + if abs (cdfMid - p) < tolerance then + result <- mid + iter <- maxIter + elif cdfMid < p then + low <- mid + else + high <- mid + + iter <- iter + 1 + + result + /// Fits the underlying distribution to a given set of observations. static member Fit(observations:float[],?maxIter,?tolerance) = diff --git a/tests/FSharp.Stats.Tests/DistributionsContinuous.fs b/tests/FSharp.Stats.Tests/DistributionsContinuous.fs index 56f963b75..6dafe0baf 100644 --- a/tests/FSharp.Stats.Tests/DistributionsContinuous.fs +++ b/tests/FSharp.Stats.Tests/DistributionsContinuous.fs @@ -118,6 +118,53 @@ let GammaDistributionTests = "Gamma Distribution Fit" Expect.floatClose fittingAccuracy beta beta' "Gamma Distribution Fit" + + testList "Gamma.InvCDF tests" [ + + test "Gamma.InvCDF returns 0.0 for p=0.0" { + let alpha = 2.0 + let beta = 1.0 + let p = 0.0 + let x = Gamma.InvCDF alpha beta p + Expect.equal x 0.0 "Quantile at p=0 should be 0" + } + + test "Gamma.InvCDF returns ~∞ for p=1.0" { + let alpha = 2.0 + let beta = 1.0 + let p = 1.0 + let x = Gamma.InvCDF alpha beta p + Expect.isGreaterThan x 1e6 "Quantile at p=1 should be very large" + } + + test "Gamma.InvCDF round-trip at p=0.5" { + let alpha = 3.0 + let beta = 2.0 + let p = 0.5 + let x = Gamma.InvCDF alpha beta p + let p2 = Gamma.CDF alpha beta x + Expect.floatClose Accuracy.high p p2 "CDF(InvCDF(p)) ≈ p" + } + + test "Gamma.InvCDF round-trip at p=0.95" { + let alpha = 5.0 + let beta = 1.0 + let p = 0.95 + let x = Gamma.InvCDF alpha beta p + let p2 = Gamma.CDF alpha beta x + Expect.floatClose Accuracy.high p p2 "CDF(InvCDF(p)) ≈ p" + } + + test "Gamma.InvCDF round-trip at p=0.01" { + let alpha = 2.0 + let beta = 0.5 + let p = 0.01 + let x = Gamma.InvCDF alpha beta p + let p2 = Gamma.CDF alpha beta x + Expect.floatClose Accuracy.high p p2 "CDF(InvCDF(p)) ≈ p" + } + ] + ] From 43d1b450d764c17d22bc467f1c249904a17adab3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20M=C3=BChlhaus?= Date: Thu, 24 Apr 2025 11:43:35 +0200 Subject: [PATCH 042/121] Add sample from ChiSquared --- .../Distributions/Continuous/ChiSquared.fs | 53 ++++++++++++++----- src/FSharp.Stats/Playground.fsx | 6 +++ 2 files changed, 45 insertions(+), 14 deletions(-) diff --git a/src/FSharp.Stats/Distributions/Continuous/ChiSquared.fs b/src/FSharp.Stats/Distributions/Continuous/ChiSquared.fs index da9f09ef3..393c70c5d 100644 --- a/src/FSharp.Stats/Distributions/Continuous/ChiSquared.fs +++ b/src/FSharp.Stats/Distributions/Continuous/ChiSquared.fs @@ -66,6 +66,15 @@ type ChiSquared = static member StandardDeviation dof = ChiSquared.CheckParam dof sqrt (dof * 2.) + + /// Degrees of freedom (must be positive). + /// A sample from χ²(dof), interpreted as Gamma(dof/2, 2). + static member SampleUnchecked (dof: float) : float = + let alpha = dof / 2.0 + let beta = 1. / 2.0 + Gamma.SampleUnchecked alpha beta + + /// Produces a random sample using the current random number generator (from GetSampleGenerator()). /// /// @@ -76,8 +85,7 @@ type ChiSquared = /// static member Sample dof = ChiSquared.CheckParam dof - //rndgen.NextFloat() * (max - min) + min - raise (NotImplementedException()) + ChiSquared.SampleUnchecked dof /// Computes the probability density function. /// @@ -127,18 +135,14 @@ type ChiSquared = elif isNan x then nan else Gamma.lowerIncompleteRegularized (dof/2.) (x/2.) - /// Computes the inverse cumulative distribution function (quantile function). - /// - /// - /// - /// - /// - /// - /// - /// - static member InvCDF dof x = - ChiSquared.CheckParam dof - failwithf "InvCDF not implemented yet" + /// Computes the inverse CDF (quantile function). + /// Degrees of freedom. + /// The probability value in [0.0, 1.0]. + /// The quantile corresponding to the cumulative probability p. + static member InvCDF (dof: float) (p: float) : float = + let alpha = dof / 2.0 + let beta = 1. / 2.0 + Gamma.InvCDF alpha beta p /// Returns the support of the exponential distribution: [0, Positive Infinity). /// @@ -164,6 +168,27 @@ type ChiSquared = static member ToString dof = sprintf "ChiSquared(dof = %f)" dof + + /// Fits a Chi-squared distribution by method-of-moments from raw observations. + /// An array of observed values. + /// Optional weights. + /// Estimated degrees of freedom k. + static member inline Fit(observations: 'T[], ?weights: 'T[]) : 'T = + let mean = + match weights with + | None -> Array.average observations + | Some w -> Array.weightedMean w observations + // Mean = k ⇒ k = mean + mean + + /// Estimates the Chi-squared distribution from data. + /// An array of observed values. + /// Optional weights. + /// An initialized Chi-squared distribution with estimated k. + static member inline Estimate(observations: 'T[], ?weights: 'T[]) = + let k = ChiSquared.Fit(observations, ?weights = weights) + ChiSquared.Init k + /// Initializes a ChiSquared distribution /// /// diff --git a/src/FSharp.Stats/Playground.fsx b/src/FSharp.Stats/Playground.fsx index 89a1bf27f..c38b6e8d6 100644 --- a/src/FSharp.Stats/Playground.fsx +++ b/src/FSharp.Stats/Playground.fsx @@ -7,6 +7,12 @@ open FSharp.Stats open FSharp.Stats.Distributions //open Plotly.NET open FSharp.Stats.Algebra +open FSharp.Stats.Distributions.Continuous + +let alpha = 5.0 +let beta = 1.0 +let p = 0.95 +let x = Gamma.InvCDF alpha beta p From 43d4ecb3c29edcf93e3552d7ad5bfc5a100be1cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20M=C3=BChlhaus?= Date: Thu, 24 Apr 2025 12:15:07 +0200 Subject: [PATCH 043/121] Change Gamma.InvCDF using Newton-Raphson refinement --- .../Distributions/Continuous/Gamma.fs | 112 ++++++++++++------ src/FSharp.Stats/SpecialFunctions/Gamma.fs | 1 + 2 files changed, 77 insertions(+), 36 deletions(-) diff --git a/src/FSharp.Stats/Distributions/Continuous/Gamma.fs b/src/FSharp.Stats/Distributions/Continuous/Gamma.fs index b654725e2..b7770795f 100644 --- a/src/FSharp.Stats/Distributions/Continuous/Gamma.fs +++ b/src/FSharp.Stats/Distributions/Continuous/Gamma.fs @@ -191,54 +191,94 @@ type Gamma = /// Inverse CDF (quantile function) for the Gamma(α, β) distribution. /// - /// Uses numerical root-finding (bisection) to solve CDF(x) = p. - /// Requires Gamma.CDF(alpha, beta, x) to be defined. + /// Uses tail-recursive Newton-Raphson refinement /// /// Shape parameter α (must be > 0). /// Rate parameter β (must be > 0). /// Cumulative probability in [0, 1]. /// The quantile value x such that P(X ≤ x) = p. - static member InvCDF - (alpha: float) (beta: float) (p: float) : float = - + static member InvCDF(alpha: float) (beta: float) (p: float) : float = Gamma.CheckParam alpha beta - // Trivial cases + if p < 0.0 || p > 1.0 then failwith "p must be in [0, 1]" if p = 0. then 0. - elif p = 1. then - inf - //'T.CreateTruncating(1e10) // simulate ∞ - + elif p = 1. then Double.PositiveInfinity else - let tolerance = 1e-10//'T.CreateTruncating(1e-10) - let maxIter = 100 - let mutable low = 0. // 'T.Zero - let mutable high = 1. //'T.One - - // Increase high bound until CDF(high) > p - while SpecialFunctions.Gamma.lowerIncompleteRegularized alpha (high / beta) < p do - high <- high * 2. //'T.CreateTruncating(2.0) - - // Bisection loop - let mutable iter = 0 - let mutable result = 0. //'T.Zero - - while iter < maxIter do - let mid = (low + high) / 2. //'T.CreateTruncating(2.0) - let cdfMid = - SpecialFunctions.Gamma.lowerIncompleteRegularized alpha (mid / beta) - - if abs (cdfMid - p) < tolerance then - result <- mid - iter <- maxIter - elif cdfMid < p then - low <- mid + // Initial approximation using Wilson–Hilferty for alpha > 1 + let initialGuess = + if alpha > 1.0 then + let z = Normal.InvCDF 0. 1. p + let a = 1.0 / (9.0 * alpha) + let t = 1.0 - a + z * sqrt a + beta * alpha * t * t * t + else + let g = SpecialFunctions.Gamma.gamma alpha + beta * (g * p) ** (1.0 / alpha) + + // Recursive Newton-Raphson refinement + let rec refine x iter = + if iter >= 20 then x else - high <- mid + let fx = SpecialFunctions.Gamma.lowerIncompleteRegularized alpha (x / beta) - p + let dfx = Gamma.PDF alpha beta x + + if dfx = 0.0 then x + else + let dx = fx / dfx + let x' = x - dx + if abs dx < 1e-10 then x' + else refine x' (iter + 1) + + refine initialGuess 0 + + + //static member InvCDF + // (alpha: float) (beta: float) (p: float) : float = + + // Gamma.CheckParam alpha beta + + // // Trivial cases + // if p = 0. then 0. + // elif p = 1. then + // inf + // //'T.CreateTruncating(1e10) // simulate ∞ + + // else + // let tolerance = 1e-10//'T.CreateTruncating(1e-10) + // let maxIter = 100 + // let mutable low = 0. // 'T.Zero + // let mutable high = 1. //'T.One + + // // Increase high bound until CDF(high) > p + // while SpecialFunctions.Gamma.lowerIncompleteRegularized alpha (high / beta) < p do + // high <- high * 2. //'T.CreateTruncating(2.0) + + // // Bisection loop + // let mutable iter = 0 + // let mutable result = 0. //'T.Zero + + // while iter < maxIter do + // let mid = (low + high) / 2. //'T.CreateTruncating(2.0) + // let cdfMid = + // SpecialFunctions.Gamma.lowerIncompleteRegularized alpha (mid / beta) + + // if abs (cdfMid - p) < tolerance then + // result <- mid + // iter <- maxIter + // elif cdfMid < p then + // low <- mid + // else + // high <- mid + + // iter <- iter + 1 + + // result + + + + - iter <- iter + 1 - result /// Fits the underlying distribution to a given set of observations. diff --git a/src/FSharp.Stats/SpecialFunctions/Gamma.fs b/src/FSharp.Stats/SpecialFunctions/Gamma.fs index 91a7dd8ce..189af2aa9 100644 --- a/src/FSharp.Stats/SpecialFunctions/Gamma.fs +++ b/src/FSharp.Stats/SpecialFunctions/Gamma.fs @@ -60,6 +60,7 @@ module Gamma = /// /// The function input for approximating Γ(z) let gamma z = + //TODO: maybe rename in "complete" for consisteny match z with | z when (infinity.Equals(z)) -> infinity | z when ((-infinity).Equals(z)) -> nan From 27094a541e9dcec9c12432be94ff9c95a781d0eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20M=C3=BChlhaus?= Date: Sun, 27 Jul 2025 16:22:16 +0200 Subject: [PATCH 044/121] ADd ChiSquare contingency table --- src/FSharp.Stats/AlgTypes/GenericMath.fs | 5 +- src/FSharp.Stats/AlgTypes/SIMDUtils.fs | 41 +++ src/FSharp.Stats/AlgTypes/Vector.fs | 10 +- src/FSharp.Stats/Algebra/SVD.fs | 259 ++++++++++++++++++ src/FSharp.Stats/FSharp.Stats.fsproj | 2 + src/FSharp.Stats/Playground.fsx | 48 +++- src/FSharp.Stats/Table.fs | 158 +++++++++++ src/FSharp.Stats/Testing/ChiSquareTest.fs | 65 ++++- src/FSharp.Stats/Testing/ContingencyTable.fs | 247 +++++++++++++++++ .../FSharp.Stats.Tests.fsproj | 1 + tests/FSharp.Stats.Tests/SVD.fs | 205 ++++++++++++++ 11 files changed, 1030 insertions(+), 11 deletions(-) create mode 100644 src/FSharp.Stats/Table.fs create mode 100644 src/FSharp.Stats/Testing/ContingencyTable.fs create mode 100644 tests/FSharp.Stats.Tests/SVD.fs diff --git a/src/FSharp.Stats/AlgTypes/GenericMath.fs b/src/FSharp.Stats/AlgTypes/GenericMath.fs index 8ed65f3ef..0dea3c597 100644 --- a/src/FSharp.Stats/AlgTypes/GenericMath.fs +++ b/src/FSharp.Stats/AlgTypes/GenericMath.fs @@ -61,7 +61,10 @@ module GenericMath = let inline floor<'T when 'T :> Numerics.IFloatingPoint<'T>> (x: 'T) : 'T = 'T. Floor(x) - + /// Generic floor function + let inline epsilon<'T when 'T :> Numerics.IFloatingPoint<'T>> () : 'T = + 'T.CreateTruncating System.Double.Epsilon + // let inline min x y = if x < y then x else y // let inline max x y = if x > y then x else y diff --git a/src/FSharp.Stats/AlgTypes/SIMDUtils.fs b/src/FSharp.Stats/AlgTypes/SIMDUtils.fs index 54aabfeec..2d12c9d19 100644 --- a/src/FSharp.Stats/AlgTypes/SIMDUtils.fs +++ b/src/FSharp.Stats/AlgTypes/SIMDUtils.fs @@ -5,6 +5,9 @@ open System.Runtime.InteropServices open System.Runtime.CompilerServices + + + /// /// A utility class for performing SIMD (Single Instruction, Multiple Data) operations on arrays. /// @@ -155,6 +158,44 @@ type SIMDUtils() = results + static member inline mapFoldUnchecked<'T + when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T :> ValueType> + (fMapSimd: Numerics.Vector<'T> -> Numerics.Vector<'T>, + fMap: 'T -> 'T, + fReduceSimd: Numerics.Vector<'T> -> Numerics.Vector<'T> -> Numerics.Vector<'T>, + fReduceScalar: 'T -> 'T -> 'T, + zero: 'T, + input: ReadOnlySpan<'T>) + : 'T = + + let len = input.Length + let simdSize = Numerics.Vector<'T>.Count + let simdBlocks = len / simdSize + let tailStart = simdBlocks * simdSize + + // SIMD map + accumulation + let mutable accVec = Numerics.Vector<'T>(zero) + let inputVec = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(input) + + for i = 0 to simdBlocks - 1 do + let mapped = fMapSimd inputVec[i] + accVec <- fReduceSimd accVec mapped + + // Reduce SIMD accumulator to scalar + let mutable acc = accVec.[0] + for i = 1 to simdSize - 1 do + acc <- fReduceScalar acc accVec.[i] + + // Scalar tail + for i = tailStart to len - 1 do + acc <- fReduceScalar acc (fMap input[i]) + + acc + + type SIMDRangeUtils = diff --git a/src/FSharp.Stats/AlgTypes/Vector.fs b/src/FSharp.Stats/AlgTypes/Vector.fs index 4d99f727e..7107c5387 100644 --- a/src/FSharp.Stats/AlgTypes/Vector.fs +++ b/src/FSharp.Stats/AlgTypes/Vector.fs @@ -211,15 +211,17 @@ type Vector = let slotCount = length / slotSize let ceiling = slotSize * slotCount - let mutable result = Numerics.Vector<'T>.Zero let v1Span = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(v1.AsSpan()) let v2Span = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(v2.AsSpan()) - let mutable scalarResult = LanguagePrimitives.GenericZero<'T> + let mutable result = Numerics.Vector<'T>.Zero + //let mutable scalarResult = LanguagePrimitives.GenericZero<'T> for i = 0 to slotCount - 1 do result <- Numerics.Vector.Add(result, Numerics.Vector.Multiply(v1Span.[i], v2Span.[i])) - scalarResult <- Numerics.Vector.Sum result - + //scalarResult <- Numerics.Vector.Sum result + + let mutable scalarResult = Numerics.Vector.Sum result + for i = ceiling to v1.Length - 1 do scalarResult <- scalarResult + (v1.[i] * v2.[i]) diff --git a/src/FSharp.Stats/Algebra/SVD.fs b/src/FSharp.Stats/Algebra/SVD.fs index cbe44bcbd..820d025d1 100644 --- a/src/FSharp.Stats/Algebra/SVD.fs +++ b/src/FSharp.Stats/Algebra/SVD.fs @@ -1,6 +1,265 @@ namespace FSharp.Stats.Algebra + +open System open FSharp.Stats +open FSharp.Stats.Acceleration + +[] +type Householder<'T when 'T :> Numerics.INumber<'T>> = + { + V: Vector<'T> + Tau: 'T + Beta: 'T + } + + +type Householder() = + + static member inline create<'T when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T : comparison + and 'T :> ValueType + and 'T :> Numerics.IRootFunctions<'T>> + (x: Vector<'T>) : Householder<'T> = + + let xSpan = x.AsSpan() + let alpha = xSpan[0] + let tail = xSpan.Slice(1) + + let zero = GenericMath.zero<'T> + let one = GenericMath.one<'T> + + let sigma = + SIMDUtils.mapFoldUnchecked( + (fun v -> v * v), + (fun x -> x * x), + (+), + (+), + zero, + tail + ) + + if sigma.Equals(zero) then + let v = Vector.zeroCreate x.Length + v.[0] <- one + { + V = v + Tau = zero + Beta = alpha + } + else + let sum = alpha * alpha + sigma + let beta = GenericMath.sqrt sum + + let v0 = + if alpha <= zero then alpha - beta + else -sigma / (alpha + beta) + + let tau = + let v0Sq = v0 * v0 + (v0Sq + v0Sq) / (sigma + v0Sq) + + let v = Vector.divideScalar v0 x // SIMD-aware scalar division + v.[0] <- one + + { + V = v + Tau = tau + Beta = beta + } + + static member inline applyLeft<'T when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T : equality + and 'T :> ValueType> + (h: Householder<'T>, A: Matrix<'T>, rowOffset: int) = + + let v = h.V + let tau = h.Tau + let m = A.NumRows + let n = A.NumCols + let vLen = v.Length + + for j = 0 to n - 1 do + let mutable dot = GenericMath.zero<'T> + for i = 0 to vLen - 1 do + dot <- dot + v.[i] * A.[rowOffset + i, j] + let scale = tau * dot + for i = 0 to vLen - 1 do + A.[rowOffset + i, j] <- A.[rowOffset + i, j] - scale * v.[i] + + + static member inline applyRight<'T when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T : equality + and 'T :> ValueType> + (h: Householder<'T>, A: Matrix<'T>, colOffset: int) = + + let v = h.V + let tau = h.Tau + let m = A.NumRows + let vLen = v.Length + + for i = 0 to m - 1 do + let mutable dot = GenericMath.zero<'T> + for j = 0 to vLen - 1 do + dot <- dot + A.[i, colOffset + j] * v.[j] + let scale = tau * dot + for j = 0 to vLen - 1 do + A.[i, colOffset + j] <- A.[i, colOffset + j] - scale * v.[j] + +type Bidiagonalization() = + + static member inline bidiagonalizeInPlace<'T + when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T : comparison + and 'T :> ValueType + and 'T :> Numerics.IRootFunctions<'T>> + (A: Matrix<'T>) : unit = + + let m = A.NumCols + let n = A.NumRows + let minMN = min m n + + for k = 0 to minMN - 1 do + // --- LEFT REFLECTION: Column k (zero below diagonal) --- + let colLen = m - k + let colVector = Array.init colLen (fun i -> A.[k + i, k]) + let hLeft = Householder.create colVector + + Householder.applyLeft(hLeft, A, k) + + // Overwrite A[k..,k] with Householder beta at top and zeros below + A.[k, k] <- hLeft.Beta + for i = k + 1 to m - 1 do + A.[i, k] <- GenericMath.zero<'T> + + + + // --- RIGHT REFLECTION: Row k (zero right of superdiagonal) --- + if k < n - 1 then + let rowLen = n - (k + 1) + let rowVector = Array.init rowLen (fun j -> A.[k, k + 1 + j]) + let hRight = Householder.create rowVector + + Householder.applyRight(hRight, A, k + 1) + + // Overwrite A[k,k+1..] with Householder beta at front, zeros right + A.[k, k + 1] <- hRight.Beta + for j = k + 2 to n - 1 do + A.[k, j] <- GenericMath.zero<'T> + + +[] +type Bidiagonal<'T when 'T :> Numerics.INumber<'T>> = { + D : Vector<'T> // main diagonal + E : Vector<'T> // superdiagonal (length n-1) +} + + +/// Givens Rotation (Generic) +module Givens = + + let inline compute<'T + when 'T :> Numerics.INumber<'T> + and 'T : comparison + and 'T :> Numerics.IRootFunctions<'T> + and 'T :> Numerics.IFloatingPointIeee754<'T>> + (a: 'T) (b: 'T) : 'T * 'T = + + if b = GenericMath.zero then GenericMath.one, GenericMath.zero + elif GenericMath.abs b > GenericMath.abs a then + let t = a / b + let s = GenericMath.one / GenericMath.sqrt(GenericMath.one + t * t) + s * t, s + else + let t = b / a + let c = GenericMath.one / GenericMath.sqrt(GenericMath.one + t * t) + c, c * t + +module GolubKahan = + + let inline diagonalize<'T + when 'T :> Numerics.INumber<'T> + and 'T :> Numerics.IRootFunctions<'T> + and 'T :> Numerics.IFloatingPointIeee754<'T> + and 'T : comparison + and 'T : struct + and 'T : (new: unit -> 'T) + and 'T :> ValueType> + (b: Bidiagonal<'T>) : Vector<'T> = + + let d = Array.copy b.D + let e = Array.copy b.E + let n = d.Length + let eps = GenericMath.epsilon() + let two = GenericMath.one + GenericMath.one + + let mutable iter = 0 + let maxIter = 1000 + let mutable doneIterating = false + + + + while iter < maxIter && not doneIterating do + let mutable converged = true + + for i = 0 to n - 2 do + let tolerance = eps * (GenericMath.abs d.[i] + GenericMath.abs d.[i + 1]) + if abs e.[i] > tolerance then + converged <- false + + if converged then + doneIterating <- true + else + // Wilkinson shift + let m = n - 1 + let dm1 = d.[m - 1] + let dm = d.[m] + let em1 = e.[m - 1] + + let delta = (dm1 - dm) / two + let sign = + if delta >= GenericMath.zero then GenericMath.one + else -GenericMath.one + + let denom = abs delta + sqrt (delta * delta + em1 * em1) + let mu = dm - sign * (em1 * em1) / denom + + // Initial bulge + let mutable x = d.[0] * d.[0] - mu * mu + let mutable z = d.[0] * e.[0] + + for k = 0 to n - 2 do + let c, s = Givens.compute x z + + let dk = d.[k] + let ek = e.[k] + let dk1 = d.[k + 1] + + let tau1 = c * dk + s * ek + let tau2 = -s * dk1 + + d.[k] <- c * tau1 + s * tau2 + e.[k] <- c * ek - s * dk1 + d.[k + 1] <- s * tau1 - c * tau2 + + if k < n - 2 then + x <- e.[k] + z <- -s * e.[k + 1] + e.[k + 1] <- c * e.[k + 1] + + iter <- iter + 1 + + d + + module SVD = diff --git a/src/FSharp.Stats/FSharp.Stats.fsproj b/src/FSharp.Stats/FSharp.Stats.fsproj index 8ba72819e..580bef79e 100644 --- a/src/FSharp.Stats/FSharp.Stats.fsproj +++ b/src/FSharp.Stats/FSharp.Stats.fsproj @@ -56,6 +56,7 @@ + @@ -123,6 +124,7 @@ + diff --git a/src/FSharp.Stats/Playground.fsx b/src/FSharp.Stats/Playground.fsx index c38b6e8d6..884d62f9b 100644 --- a/src/FSharp.Stats/Playground.fsx +++ b/src/FSharp.Stats/Playground.fsx @@ -9,13 +9,59 @@ open FSharp.Stats.Distributions open FSharp.Stats.Algebra open FSharp.Stats.Distributions.Continuous +let d = [| 4.0; 3.0 |] +let e = [| 2.0 |] + +let bidiag = { + D = d + E = e +} + +let sigma = GolubKahan.diagonalize bidiag + + +let A = + matrix [| + [| 4.0; 1.0; 2.0 |] + [| 3.0; 1.0; 0.0 |] + [| 5.0; 1.0; 3.0 |] + |] + +// Extract column 0 +let colVector = [| A.[0, 0]; A.[1, 0]; A.[2, 0] |] +let h = Householder.create colVector + +// Overwrite A[0..,0] with [β; 0; 0] +A.[0, 0] <- h.Beta +for i = 1 to 2 do + A.[i, 0] <- 0.0 + +Householder.applyLeft(h, A, 0) + +A.[1, 0] + +//let input = +// matrix [| +// [| 1.0; 2.0; 3.0 |] +// [| 4.0; 5.0; 6.0 |] +// [| 7.0; 8.0; 9.0 |] +// |] + +//let A = input |> Matrix.copy + +//Bidiagonalization.bidiagonalizeInPlace A +//A + + + +// Apply reflector from the left to matrix A starting at row 0 + let alpha = 5.0 let beta = 1.0 let p = 0.95 let x = Gamma.InvCDF alpha beta p - let Categorical_SampleUnchecked (probabilities: float[]) = let rnd = Random.rndgen.NextFloat() let rec search i acc = diff --git a/src/FSharp.Stats/Table.fs b/src/FSharp.Stats/Table.fs new file mode 100644 index 000000000..793ac42e5 --- /dev/null +++ b/src/FSharp.Stats/Table.fs @@ -0,0 +1,158 @@ +namespace FSharp.Stats + + +open System +open FSharp.Stats + + +open System +open System.Collections.Generic +open System.Runtime.InteropServices +open System.Numerics +open System.Text + + +/// A general read-only 2D table abstraction. +type ITable<'R,'C,'T> = + /// All row labels (in order). + abstract RowKeys : 'R[] + /// All column labels (in order). + abstract ColKeys : 'C[] + /// Number of rows + abstract NumRows : int + /// Number of columns + abstract NumCols : int + /// Get the value at (rowLabel, colLabel) + abstract Get : rowLabel:'R * colLabel:'C -> 'T + /// Enumerate a single row as (colLabel * value) seq + abstract GetRow : rowLabel:'R -> seq<'C * 'T> + /// Enumerate a single column as (rowLabel * value) seq + abstract GetColumn : colLabel:'C -> seq<'R * 'T> + +/// A read/write extension (if you need mutability) +type ITableMutable<'R,'C,'T> = + inherit ITable<'R,'C,'T> + /// Set the value at (rowLabel, colLabel) + abstract Set : rowLabel:'R * colLabel:'C * value:'T -> unit + + + + + + + + +/// A 2D table with generic row‐labels and column‐labels, +/// backed by a flattened Matrix<'T> +type Table<'R,'C,'T + when 'R : comparison + and 'C : comparison + and 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T : equality + and 'T :> ValueType> + ( rowKeys : 'R[], + colKeys : 'C[], + dataMatrix : Matrix<'T> ) = + + // validate shapes + do + if rowKeys.Length <> dataMatrix.NumRows then + invalidArg "rowKeys" $"Length of rowKeys ({rowKeys.Length}) <> data.NumRows ({dataMatrix.NumRows})" + if colKeys.Length <> dataMatrix.NumCols then + invalidArg "colKeys" $"Length of colKeys ({colKeys.Length}) <> data.NumCols ({dataMatrix.NumCols})" + + // build fast lookup maps + let rowIndexMap = + rowKeys |> Array.mapi (fun i k -> k,i) |> dict<'R,int> + let colIndexMap = + colKeys |> Array.mapi (fun j k -> k,j) |> dict<'C,int> + + /// All row labels in order. + member _.RowKeys = rowKeys + + /// All column labels in order. + member _.ColKeys = colKeys + + /// Underlying matrix storage. + member _.DataMatrix = dataMatrix + + /// Underlying data storage. + member _.Data = dataMatrix.Data + + /// Number of rows. + member _.NumRows = rowKeys.Length + + /// Number of columns. + member _.NumCols = colKeys.Length + + /// Indexer by integer coordinates (0-based). + member this.Item + with get (i:int, j:int) = + dataMatrix.[i, j] + and set (i:int, j:int) (v:'T) = + dataMatrix.[i, j] <- v + + /// Indexer by label keys. + member this.Item + with get (r:'R, c:'C) = + let i = + match rowIndexMap.TryGetValue r with + | true, idx -> idx + | _ -> invalidArg "r" $"Invalid row label: {r}" + let j = + match colIndexMap.TryGetValue c with + | true, idx -> idx + | _ -> invalidArg "c" $"Invalid column label: {c}" + dataMatrix.[i, j] + and set (r:'R, c:'C) (v:'T) = + let i = + match rowIndexMap.TryGetValue r with + | true, idx -> idx + | _ -> invalidArg "r" $"Invalid row label: {r}" + let j = + match colIndexMap.TryGetValue c with + | true, idx -> idx + | _ -> invalidArg "c" $"Invalid column label: {c}" + dataMatrix.[i, j] <- v + + /// Slice out a row (as array of label * value). + member this.GetRow (r:'R) : ('C * 'T)[] = + // ToDo: leaverage the Matrix based Matrix.getRows for accelaration + let i = + match rowIndexMap.TryGetValue r with + | true, idx -> idx + | _ -> invalidArg "r" $"Invalid row label: {r}" + colKeys + |> Array.mapi (fun j c -> c, dataMatrix.[i,j]) + + /// Slice out a column (as array of label * value). + member this.GetColumn (c:'C) : ('R * 'T)[] = + let j = + match colIndexMap.TryGetValue c with + | true, idx -> idx + | _ -> invalidArg "c" $"Invalid column label: {c}" + rowKeys + |> Array.mapi (fun i r -> r, dataMatrix.[i,j]) + + /// Pretty‐print with headers and labels. + override this.ToString() = + let sb = StringBuilder() + + // Header row: blank corner + column keys + sb.Append("\t") |> ignore + for c in colKeys do + sb.Append(c.ToString()).Append("\t") |> ignore + sb.AppendLine() |> ignore + + // Each data row: row key + its values + for i in 0 .. this.NumRows - 1 do + let r = rowKeys.[i] + sb.Append(r.ToString()).Append("\t") |> ignore + for j in 0 .. this.NumCols - 1 do + sb.Append(dataMatrix.[i, j].ToString()).Append("\t") |> ignore + sb.AppendLine() |> ignore + + sb.ToString() + diff --git a/src/FSharp.Stats/Testing/ChiSquareTest.fs b/src/FSharp.Stats/Testing/ChiSquareTest.fs index 7d1db8c04..a701711df 100644 --- a/src/FSharp.Stats/Testing/ChiSquareTest.fs +++ b/src/FSharp.Stats/Testing/ChiSquareTest.fs @@ -1,5 +1,8 @@ namespace FSharp.Stats.Testing +open System +open FSharp.Stats + /// /// Two-Sample (Goodness-of-fit) Chi-Square Test (Upper Tail) @@ -31,14 +34,12 @@ /// /// /// -module ChiSquareTest = - - open System - open FSharp.Stats +type ChiSquareTest = + /// Computes the Chi-Square test /// n data points -> degrees of freedom = n - 1 - let compute (degreesOfFreedom:int) (expected:seq) (observed:seq) = + static member compute (degreesOfFreedom:int) (expected:seq) (observed:seq) = //let chechParams = // if expected |> Seq.exists (fun x -> abs x < 5.) then printfn "Warning: A value less than 5 is present in expected values. Results may not be correct!" // let sumEx = Seq.sum expected @@ -52,5 +53,59 @@ module ChiSquareTest = TestStatistics.createChiSquare chi2 (float degreesOfFreedom) + static member pearsonChiSquared (table:ContingencyTable<_,_>) = + 42. + + static member pearsonChiSquared (table:Contingency2x2<_,_>) = + let apply o e = + let diff = abs (o - e) + diff * diff / e + let a = table.A + let b = table.B + let c = table.C + let d = table.D + + let N = float (a + b + c + d) + let rowSums = [| float (a + b); float (c + d) |] + let colSums = [| float (a + c); float (b + d) |] + + // compute Σ (O – E)²/E (with Yates) + let chi2 = + [| for i in 0..1 do + for j in 0..1 do + let O = float table.[i,j] + let E = rowSums.[i] * colSums.[j] / N + yield apply O E |] + |> Array.sum + + let df = 1 // (2–1)*(2–1) + TestStatistics.createChiSquare chi2 (float df) + + + /// Pearson χ² test with **Yates’s continuity correction** (only for 2×2). + static member pearsonChiSquaredWithYates (table:Contingency2x2<_,_>) = + let applyYates o e = + let diff = abs (o - e) - 0.5 + diff * diff / e + + let a = table.A + let b = table.B + let c = table.C + let d = table.D + + let N = float (a + b + c + d) + let rowSums = [| float (a + b); float (c + d) |] + let colSums = [| float (a + c); float (b + d) |] + + // compute Σ (O – E)²/E (with Yates) + let chi2 = + [| for i in 0..1 do + for j in 0..1 do + let O = float table.[i,j] + let E = rowSums.[i] * colSums.[j] / N + yield applyYates O E |] + |> Array.sum + let df = 1 // (2–1)*(2–1) + TestStatistics.createChiSquare chi2 (float df) diff --git a/src/FSharp.Stats/Testing/ContingencyTable.fs b/src/FSharp.Stats/Testing/ContingencyTable.fs new file mode 100644 index 000000000..71a93608d --- /dev/null +++ b/src/FSharp.Stats/Testing/ContingencyTable.fs @@ -0,0 +1,247 @@ +namespace FSharp.Stats.Testing + +open System +open System.Collections.Generic +open FSharp.Stats + + +/// An estimate with its standard‐error uncertainty. +type UncertainValue = { + Estimate : float + Uncertainty : float +} + + +///// A contingency-specific interface on top of ITable<_,_,int> +//type IContingencyTable<'R,'C> = +// inherit ITable<'R,'C,int> +// /// Sum of counts in one row +// abstract RowTotal : 'R -> int +// /// Sum of counts in one column +// abstract ColumnTotal : 'C -> int +// /// Grand total +// abstract Total : unit -> int +// ///// Probability of a single cell (with uncertainty) +// //abstract ProbabilityOf : 'R * 'C -> UncertainValue + + +/// Alias: a contingency table is just a Table<'R,'C,int> +type ContingencyTable<'R,'C when 'R : comparison and 'C : comparison> = Table<'R,'C,int> + + +/// A strictly 2×2 contingency table with generic row and column labels. +type Contingency2x2<'R,'C when 'R : comparison and 'C : comparison> + ( rowKeys : 'R * 'R, + colKeys : 'C * 'C, + counts : int * int * int * int ) = + + let (r1, r2) = rowKeys + let (c1, c2) = colKeys + let (a, b, c, d) = counts + + do if a<0 || b<0 || c<0 || d<0 then + invalidArg "counts" "All cell counts must be non‐negative" + + /// First row label + member _.Row1 = r1 + /// Second row label + member _.Row2 = r2 + /// First column label + member _.Col1 = c1 + /// Second column label + member _.Col2 = c2 + + /// Cell a = (r1,c1) + member _.A = a + /// Cell b = (r1,c2) + member _.B = b + /// Cell c = (r2,c1) + member _.C = c + /// Cell d = (r2,c2) + member _.D = d + + /// Index by zero‐based coordinates 0..1 × 0..1 + member _.Item + with get(i,j) = + match i,j with + | 0,0 -> a | 0,1 -> b + | 1,0 -> c | 1,1 -> d + | _ -> invalidArg "i,j" "Indices must be 0 or 1" + + /// Index by labels + member this.Item + with get(row: 'R, col: 'C) = + match (row,col) with + | (x,y) when x = r1 && y = c1 -> a + | (x,y) when x = r1 && y = c2 -> b + | (x,y) when x = r2 && y = c1 -> c + | (x,y) when x = r2 && y = c2 -> d + | _ -> invalidArg "r,c" "Invalid row or column label" + + //interface IContingencyTable<'R,'C> with + // member _.RowKeys = [| r1; r2 |] + // member _.ColKeys = [| c1; c2 |] + // member _.NumRows = 2 + // member _.NumCols = 2 + // member this.Get(row,col) = this.[row,col] + // member this.GetRow(row) = [| c1, this.[row,c1]; c2, this.[row,c2] |] + // member this.GetColumn(col)= [| r1, this.[r1,col]; r2, this.[r2,col] |] + // member _.RowTotal(row) = if row = r1 then a+b else c+d + // member _.ColumnTotal(col)= if col = c1 then a+c else b+d + // member _.Total() = a + b + c + d + + /// Odds ratio = (a·d)/(b·c) + member _.OddsRatio() = + if b = 0 || c = 0 then + invalidOp "Cannot compute odds‐ratio with a zero cell in denominator." + float a * float d / (float b * float c) + + + +module Contingency = + + let create (rows: 'R []) (cols: 'C []) (data: int[]) : ContingencyTable<'R,'C> = + // validate shapes + if rows.Length * cols.Length <> data.Length then + invalidArg "data" $"Length of data ({data.Length}) does not match rows × cols ({rows.Length}×{cols.Length})" + // build the table + Table( rows, cols, Matrix(rows.Length, cols.Length, data) ) + + /// Create a zero‐filled table for the given row & column labels. + let zeroCreate (rows: 'R []) (cols: 'C []) : ContingencyTable<'R,'C> = + // zero‐filled flat data + let data = Matrix.zeroCreate rows.Length cols.Length + Table( rows, cols, data ) + + + /// Build a ContingencyTable<'R,'C> of counts from a sequence of category‐pairs. + let ofDataSeq + (rows: seq<'R>) + (cols: seq<'C>) + (data: seq<'R * 'C>) + : ContingencyTable<'R,'C> = + + // 1) Materialize the label sets + let rowKeys = rows |> Seq.distinct |> Seq.toArray + let colKeys = cols |> Seq.distinct |> Seq.toArray + + // 2) Start with all zeros + let table = zeroCreate rowKeys colKeys + + // 3) Tally each occurrence + for (r,c) in data do + let curr = table.[r,c] + table.[r, c] <- curr + 1 + + table + + /// Build from a 2D integer array (rows × columns), zero‐based. + /// Throws if any entry is negative. + let ofArray (data2d: int[,]) : ContingencyTable = + let numRows = data2d.GetLength 0 + let numCols = data2d.GetLength 1 + // flatten row-major + let flat = Array.zeroCreate (numRows * numCols) + for i in 0..numRows-1 do + for j in 0..numCols-1 do + let v = data2d.[i,j] + if v < 0 then + invalidArg "data2d" $"Negative entry at (%d{i},%d{j})" + flat.[i * numCols + j] <- v + let matrix = Matrix(numRows,numCols,flat) + Table( Array.init numRows id, Array.init numCols id, matrix ) + + /// Get the count in cell (r,c). Throws if (r,c) not a valid key. + let getCount (r:'R) (c:'C) (t:ContingencyTable<'R,'C>) = + t.[r, c] + + /// Set the count in (r,c) to a non‐negative value, returning a new table. + let setCount (r:'R) (c:'C) (value:int) (t:ContingencyTable<'R,'C>) = + if value < 0 then invalidArg "value" "Count must be ≥0" + // clone the flat array, update the one entry + let data' = Array.copy t.Data + // find the zero-based indices + let i = Array.findIndex ((=) r) t.RowKeys + let j = Array.findIndex ((=) c) t.ColKeys + data'.[i * t.NumCols + j] <- value + Table( t.RowKeys, t.ColKeys, Matrix(t.RowKeys.Length,t.ColKeys.Length, data') ) + + /// Increment cell (r,c) by 1. + let increment (r:'R) (c:'C) (t:ContingencyTable<'R,'C>) = + let old = getCount r c t + setCount r c (old + 1) t + + /// Decrement cell (r,c) by 1 (throws if it would go below zero). + let decrement (r:'R) (c:'C) (t:ContingencyTable<'R,'C>) = + let old = getCount r c t + if old < 1 then invalidOp "Cell count is already zero." + setCount r c (old - 1) t + + /// Sum of counts in a given row. + let rowTotal (r:'R) (t:ContingencyTable<'R,'C>) = + t.ColKeys |> Array.sumBy (fun c -> getCount r c t) + + /// Sum of counts in a given column. + let columnTotal (c:'C) (t:ContingencyTable<'R,'C>) = + t.RowKeys |> Array.sumBy (fun r -> getCount r c t) + + /// Total count in the whole table. + let total (t:ContingencyTable<'R,'C>) = + t.RowKeys |> Array.sumBy (fun r -> rowTotal r t) + + + /// Uncertainty = sqrt(p*(1-p)/N), binomial approximation. + let private uncertainty (p:float) (N:float) = + sqrt (p * (1.0 - p) / N) + + /// Probability of a single cell. + let probabilityOf (r:'R) (c:'C) (t:ContingencyTable<'R,'C>) : UncertainValue = + let n = float (getCount r c t) + let N = float (total t) + let p = n / N + { Estimate = p; Uncertainty = uncertainty p N } + + /// Probability of a row. + let probabilityOfRow (r:'R) (t:ContingencyTable<'R,'C>) : UncertainValue = + let n = float (rowTotal r t) + let N = float (total t) + let p = n / N + { Estimate = p; Uncertainty = uncertainty p N } + + /// Probability of a column. + let probabilityOfColumn (c:'C) (t:ContingencyTable<'R,'C>) : UncertainValue = + let n = float (columnTotal c t) + let N = float (total t) + let p = n / N + { Estimate = p; Uncertainty = uncertainty p N } + + /// Probability of row given column. + let probabilityRowGivenColumn (r:'R) (c:'C) (t:ContingencyTable<'R,'C>) : UncertainValue = + let nrc = float (getCount r c t) + let Nc = float (columnTotal c t) + let p = nrc / Nc + { Estimate = p; Uncertainty = uncertainty p Nc } + + /// Probability of column given row. + let probabilityColumnGivenRow (c:'C) (r:'R) (t:ContingencyTable<'R,'C>) : UncertainValue = + let nrc = float (getCount r c t) + let Nr = float (rowTotal r t) + let p = nrc / Nr + { Estimate = p; Uncertainty = uncertainty p Nr } + + /// Ensure it's 2×2; throws otherwise. + let ensure2x2 (t:ContingencyTable<'R,'C>) = + if t.NumRows <> 2 || t.NumCols <> 2 then + invalidArg "t" "ContingencyTable must be 2×2." + t + + let as2x2 (t: Table<'R,'C,int>) : Contingency2x2<'R,'C> = + if t.NumRows <> 2 || t.NumCols <> 2 then + invalidArg "t" "Must be 2×2" + let rkeys = t.RowKeys.[0], t.RowKeys.[1] + let ckeys = t.ColKeys.[0], t.ColKeys.[1] + let a = t.DataMatrix.[0,0] + let b = t.DataMatrix.[0,1] + let c = t.DataMatrix.[1,0] + let d = t.DataMatrix.[1,1] + Contingency2x2( rowKeys = rkeys, colKeys = ckeys, counts = (a,b,c,d)) \ No newline at end of file diff --git a/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj b/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj index 16eb6aae5..8435d6b1f 100644 --- a/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj +++ b/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj @@ -31,6 +31,7 @@ + diff --git a/tests/FSharp.Stats.Tests/SVD.fs b/tests/FSharp.Stats.Tests/SVD.fs new file mode 100644 index 000000000..c2b886af2 --- /dev/null +++ b/tests/FSharp.Stats.Tests/SVD.fs @@ -0,0 +1,205 @@ +module SVDTests + +open Expecto +open System +open FSharp.Stats +open FSharp.Stats.Algebra + +module MatrixUtils = + + let inline isApproxZero<'T when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T : comparison + and 'T :> ValueType> + (epsilon: 'T) (x: 'T) = + (GenericMath.abs x) < epsilon + + let inline isUpperBidiagonalWithTolerance<'T when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T : comparison + and 'T :> ValueType> + (epsilon: 'T) + (A: Matrix<'T>) : bool = + let m = A.NumCols + let n = A.NumRows + + let mutable ok = true + for i = 0 to m - 1 do + for j = 0 to n - 1 do + let onDiagonal = j = i + let onSuperDiagonal = j = i + 1 + let aij = A.[i, j] + if not (onDiagonal || onSuperDiagonal) && not (isApproxZero epsilon aij) then + ok <- false + ok + + +[] +let householderCreateTest = + test "Householder.create" { + let x = [| 4.0; 3.0; 0.0 |] + let h = Householder.create x + + let v = h.V + let tau = h.Tau + let n = v.Length + + // Compute Hx = (I - τ v vᵗ) x + // First: dot(v, x) + let dot = Vector.dot v x + + // Then: Hx = x - τ * dot * v + let hx = Array.init n (fun i -> x.[i] - tau * dot * v.[i]) + + // We expect: hx = [±||x||; 0; 0] + let norm = sqrt (Array.sumBy (fun xi -> xi * xi) x) + Expect.floatClose Accuracy.high hx.[0] norm "Should be equal (double precision)" + Expect.floatClose Accuracy.high hx.[1] 0.0 "Should be equal (double precision)" + Expect.floatClose Accuracy.high hx.[2] 0.0 "Should be equal (double precision)" + } + //test " zeroes out tail of vector" { + // Expect.floatClose Accuracy.high hx.[0] norm "Should be equal (double precision)" + //} + //test " zeroes out tail of vector" { + // Expect.floatClose Accuracy.high hx.[1] 0.0 "Should be equal (double precision)" + //} + //test " zeroes out tail of vector" { + // Expect.floatClose Accuracy.high hx.[2] 0.0 "Should be equal (double precision)" + //} + //] + +[] +let applyLeftTest = + test "Householder.applyLeft zeroes out subdiagonal column elements" { + // Define 3x3 test matrix + let A = + matrix [| + [| 4.0; 2.0; 1.0 |] + [| 3.0; 0.0; 0.0 |] + [| 0.0; 0.0; 0.0 |] + |] + + // Create Householder vector from column 0 (x = [4; 3; 0]) + let x = [| A.[0, 0]; A.[1, 0]; A.[2, 0] |] + let h = Householder.create x + + // Apply reflector from the left to matrix A starting at row 0 + Householder.applyLeft(h, A, 0) + + // Check: entries below A[0][0] should be zero + //let eps = 1e-10 + Expect.floatClose Accuracy.high A.[1, 0] 0.0 "Should be equal (double precision)" + Expect.floatClose Accuracy.high A.[2, 0] 0.0 "Should be equal (double precision)" + + // Optionally check the first value matches h.Beta + Expect.floatClose Accuracy.high A.[0, 0] h.Beta "Should be equal (double precision)" + } + +let applyRightTest = + test "Householder.applyRight zeroes out row tail elements" { + // Define 3x3 test matrix + let A = + matrix [| + [| 1.0; 4.0; 3.0 |] + [| 0.0; 0.0; 0.0 |] + [| 0.0; 0.0; 0.0 |] + |] + + // Take the row vector to the right of the diagonal: [4.0; 3.0] + let x = [| A.[0, 1]; A.[0, 2] |] + let h = Householder.create x + + // Apply the Householder from the right starting at column 1 + Householder.applyRight(h, A, 1) + + // Check that A[0].[2] is now approximately 0 + //let eps = 1e-10 + Expect.floatClose Accuracy.high A.[0, 2] 0.0 "Should be equal (double precision)" + + // Check that A[0].[1] is updated to h.Beta + Expect.floatClose Accuracy.high A.[0, 1] h.Beta "Should be equal (double precision)" + } + + +[] +let bidiagonalizationTest = + testList "bidiagonalization" [ + test "First step of bidiagonalization (applyLeft to column 0) works" { + // Full-rank 3x3 matrix + let A = + matrix [| + [| 4.0; 1.0; 2.0 |] + [| 3.0; 1.0; 0.0 |] + [| 5.0; 1.0; 3.0 |] + |] + + // Extract column 0 + let colVector = [| A.[0, 0]; A.[1, 0]; A.[2, 0] |] + let h = Householder.create colVector + + Householder.applyLeft(h, A, 0) + + // Overwrite A[0..,0] with [β; 0; 0] + A.[0, 0] <- h.Beta + for i = 1 to 2 do + A.[i, 0] <- 0.0 + + // Check column 0 + Expect.floatClose Accuracy.high A.[1, 0] 0.0 "Should be equal (double precision)" + Expect.floatClose Accuracy.high A.[2, 0] 0.0 "Should be equal (double precision)" + Expect.floatClose Accuracy.high A.[0, 0] h.Beta "Should be equal (double precision)" + } + + + + test "bidiagonalizeInPlace produces upper bidiagonal matrix" { + let input = + matrix [| + [| 1.0; 2.0; 3.0 |] + [| 4.0; 5.0; 6.0 |] + [| 7.0; 8.0; 9.0 |] + |] + + let A = input |> Matrix.copy + + Bidiagonalization.bidiagonalizeInPlace A + + let isBidiagonal = MatrixUtils.isUpperBidiagonalWithTolerance 1e-10 A + + Expect.isTrue isBidiagonal "Matrix should be upper bidiagonal after bidiagonalization" + } + ] + + +//[] +//let golubKahanTests = +// testList "Golub-Kahan Diagonalization" [ + +// test "Diagonalize 2x2 upper bidiagonal matrix" { +// // Construct bidiagonal: [ [4, 2]; [0, 3] ] +// let d = [| 4.0; 3.0 |] +// let e = [| 2.0 |] + +// let bidiag = { +// D = d +// E = e +// } + +// let sigma = GolubKahan.diagonalize bidiag + +// // Expected from NumPy SVD +// let expected = [| 4.74341649; 2.5355339 |] +// let eps = 1e-6 + +// // Compare sorted values (SVD is unordered) +// let actualSorted = Array.sortDescending sigma +// let expectedSorted = Array.sortDescending expected + +// for i in 0 .. expected.Length - 1 do +// Expect.floatClose Accuracy.high actualSorted.[i] expectedSorted.[i] $"Singular value {i} mismatch" +// } + +// // You can add more tests here for larger bidiagonal matrices or edge cases +// ] \ No newline at end of file From 2e6f9c68684cb04c364bfdcbbdee95596b84c019 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20M=C3=BChlhaus?= Date: Mon, 28 Jul 2025 21:57:42 +0200 Subject: [PATCH 045/121] fix qrDecompose --- src/FSharp.Stats/AlgTypes/Householder.fs | 126 +++ src/FSharp.Stats/AlgTypes/Vector.fs | 2 + src/FSharp.Stats/AlgTypes/VectorExt.fs | 10 + src/FSharp.Stats/Algebra/LinearAlgebra.fs | 217 +++-- src/FSharp.Stats/Algebra/SVD.fs | 107 --- src/FSharp.Stats/FSharp.Stats.fsproj | 1 + src/FSharp.Stats/Fitting/Spline.fs | 2 +- src/FSharp.Stats/Playground.fsx | 743 +++++++++++++----- tests/FSharp.Stats.Tests/Acceleration.fs | 49 ++ .../FSharp.Stats.Tests.fsproj | 2 + tests/FSharp.Stats.Tests/LinearAlgebra.fs | 528 +++++++++++++ tests/FSharp.Stats.Tests/TestExtensions.fs | 7 + 12 files changed, 1457 insertions(+), 337 deletions(-) create mode 100644 src/FSharp.Stats/AlgTypes/Householder.fs create mode 100644 tests/FSharp.Stats.Tests/Acceleration.fs diff --git a/src/FSharp.Stats/AlgTypes/Householder.fs b/src/FSharp.Stats/AlgTypes/Householder.fs new file mode 100644 index 000000000..a68931fe6 --- /dev/null +++ b/src/FSharp.Stats/AlgTypes/Householder.fs @@ -0,0 +1,126 @@ +namespace FSharp.Stats.Algebra + + +open System +open FSharp.Stats +open FSharp.Stats.Acceleration + +[] +type Householder<'T when 'T :> Numerics.INumber<'T>> = + { + V: Vector<'T> + Tau: 'T + Beta: 'T + } + + +type Householder() = + + static member inline create<'T when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T : comparison + and 'T :> ValueType + and 'T :> Numerics.IRootFunctions<'T>> + (x: Vector<'T>) : Householder<'T> = + + let xSpan = x.AsSpan() + let alpha = xSpan[0] + let tail = xSpan.Slice(1) + + let zero = GenericMath.zero<'T> + let one = GenericMath.one<'T> + + let sigma = + SIMDUtils.mapFoldUnchecked( + (fun v -> v * v), + (fun x -> x * x), + (+), + (+), + zero, + tail + ) + + if sigma.Equals(zero) then + let v = Vector.zeroCreate x.Length + v.[0] <- one + { + V = v + Tau = zero + Beta = alpha + } + else + let sum = alpha * alpha + sigma + let beta = GenericMath.sqrt sum + + let v0 = + if alpha <= zero then alpha - beta + else -sigma / (alpha + beta) + + let tau = + let v0Sq = v0 * v0 + (v0Sq + v0Sq) / (sigma + v0Sq) + + let v = Vector.divideScalar v0 x // SIMD-aware scalar division + v.[0] <- one + + { + V = v + Tau = tau + Beta = beta + } + + static member inline applyLeft<'T when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T : equality + and 'T :> ValueType> + (h: Householder<'T>, A: Matrix<'T>, rowOffset: int) = + + let v = h.V + let tau = h.Tau + let m = A.NumRows + let n = A.NumCols + let vLen = v.Length + + //for j = 0 to n - 1 do + // let mutable dot = GenericMath.zero<'T> + // for i = 0 to vLen - 1 do + // dot <- dot + v.[i] * A.[rowOffset + i, j] + // let scale = tau * dot + // for i = 0 to vLen - 1 do + // A.[rowOffset + i, j] <- A.[rowOffset + i, j] - scale * v.[i] + + for j = 0 to n - 1 do + let mutable dot = GenericMath.zero<'T> + for i = 0 to vLen - 1 do + let row = rowOffset + i + if row < m then + dot <- dot + v.[i] * A.[row, j] + let scale = tau * dot + for i = 0 to vLen - 1 do + let row = rowOffset + i + if row < m then + A.[row, j] <- A.[row, j] - scale * v.[i] + + + static member inline applyRight<'T when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T : equality + and 'T :> ValueType> + (h: Householder<'T>, A: Matrix<'T>, colOffset: int) = + + let v = h.V + let tau = h.Tau + let m = A.NumRows + let vLen = v.Length + + for i = 0 to m - 1 do + let mutable dot = GenericMath.zero<'T> + for j = 0 to vLen - 1 do + dot <- dot + A.[i, colOffset + j] * v.[j] + let scale = tau * dot + for j = 0 to vLen - 1 do + A.[i, colOffset + j] <- A.[i, colOffset + j] - scale * v.[j] + diff --git a/src/FSharp.Stats/AlgTypes/Vector.fs b/src/FSharp.Stats/AlgTypes/Vector.fs index 7107c5387..5171c0a8b 100644 --- a/src/FSharp.Stats/AlgTypes/Vector.fs +++ b/src/FSharp.Stats/AlgTypes/Vector.fs @@ -6,6 +6,7 @@ open System.Runtime.InteropServices /// Vector as an array type alias type Vector<'T when 'T :> Numerics.INumber<'T>> = 'T [] + type Vector = @@ -23,6 +24,7 @@ type Vector = and 'T : struct and 'T :> ValueType> (v1 : Vector<'T>) (v2 : Vector<'T>) : Vector<'T> = + if v1.Length <> v2.Length then invalidArg "" "Cannot add two vectors of different dimensions." diff --git a/src/FSharp.Stats/AlgTypes/VectorExt.fs b/src/FSharp.Stats/AlgTypes/VectorExt.fs index e9a721997..3c72a6f84 100644 --- a/src/FSharp.Stats/AlgTypes/VectorExt.fs +++ b/src/FSharp.Stats/AlgTypes/VectorExt.fs @@ -214,3 +214,13 @@ module Vector = /// let inline pow (power: 'T) (v:Vector<'T>) : Vector<'T> = v |> Array.map (fun x -> GenericMath.pow x power) + + + /// Returns a subvector from offset i to the end of the vector. + let inline sub (i: int) (v: Vector<'T>) : Vector<'T> = + if i < 0 || i > v.Length then + invalidArg (nameof i) "Index out of bounds." + let len = v.Length - i + let res = Array.zeroCreate<'T> len + Array.blit v i res 0 len + res \ No newline at end of file diff --git a/src/FSharp.Stats/Algebra/LinearAlgebra.fs b/src/FSharp.Stats/Algebra/LinearAlgebra.fs index 9bf636a4b..9585ee434 100644 --- a/src/FSharp.Stats/Algebra/LinearAlgebra.fs +++ b/src/FSharp.Stats/Algebra/LinearAlgebra.fs @@ -28,18 +28,19 @@ type LinearAlgebra = Acceleration.SIMDRangeUtils.map2RangeInPlace fv f dstOffset srcOffset count dst src - static member inline householderTransform - (A: Matrix<'T>) (i: int) : Vector<'T> = - let n = A.NumRows - let v = Vector.zeroCreate<'T> n - let aCol = Matrix.getCol i A - let norm = Vector.norm aCol - v.[i] <- aCol.[i] + if aCol.[i] >= 'T.Zero then -norm else norm - for j = 0 to n - 1 do - if j <> i then - v.[j] <- aCol.[j] - v - + //static member inline householderTransform + // (A: Matrix<'T>) (i: int) : Vector<'T> = + // let n = A.NumRows + + // let v = Vector.zeroCreate<'T> n + // let aCol = Matrix.getCol i A + // let norm = Vector.norm aCol.[i..] // ToDO: use a more efficient norm calculation + // v.[i] <- aCol.[i] + if aCol.[i] >= 'T.Zero then norm else -norm + // for j = i + 1 to n - 1 do + // v.[j] <- aCol.[j] + // v + + /// QR decomposition using modified Gram-Schmidt /// Returns Q and R such that A = QR @@ -52,6 +53,10 @@ type LinearAlgebra = (A: Matrix<'T>) : Matrix<'T> * Matrix<'T> = let m, n = A.NumRows, A.NumCols + + if m < n then + invalidArg "A" $"QR decomposition via Modified Gram-Schmidt requires m ≥ n, but got {m}×{n} matrix." + let r = Matrix.zeroCreate n n let qCols: Vector<'T>[] = Array.zeroCreate n @@ -100,7 +105,10 @@ type LinearAlgebra = let mutable sum = y.[i] for j = i + 1 to n - 1 do sum <- sum - r.[i, j] * x.[j] - x.[i] <- sum / r.[i, i] + let diag = r.[i, i] + if diag = 'T.Zero then + invalidArg $"r[{i},{i}]" "Diagonal element is zero. Cannot divide." + x.[i] <- sum / diag x @@ -269,6 +277,8 @@ type LinearAlgebra = for j = 0 to i - 1 do s <- s - (Kdata.[rowOffset + j] * x.[j]) let diag = Kdata.[rowOffset + i] + if diag = 'T.Zero then + invalidArg $"K[{i},{i}]" "Diagonal element is zero. Cannot divide." x.[i] <- s / diag else // For i in [n-1..downto..0]: @@ -279,50 +289,119 @@ type LinearAlgebra = for j = i + 1 to nK - 1 do s <- s - (Kdata.[rowOffset + j] * x.[j]) let diag = Kdata.[rowOffset + i] + if diag = 'T.Zero then + invalidArg $"K[{i},{i}]" "Diagonal element is zero. Cannot divide." x.[i] <- s / diag x - /// QR decomposition using Householder reflections - static member inline qrDecompose (A : Matrix<'T>) : (Matrix<'T> * Matrix<'T>) = - // former QR - let UpdateQ (Q : Matrix<'T>) (v : Vector<'T>) = - let nQ, mQ = Q.NumRows, Q.NumCols - let n = v.Length - let Qv = Vector.zeroCreate<'T> nQ - for i = 0 to nQ - 1 do - // offset in Q.Data for row i is i*mQ - let rowOffset = i * mQ + (mQ - n) - // Dot the subrange Q[i, mQ-n..mQ-1] with v[0..n-1] - Qv.[i] <- Acceleration.SIMDRangeUtils.dotRange Q.Data rowOffset v 0 n + ///// QR decomposition using Householder reflections + //static member inline qrDecompose (A : Matrix<'T>) : (Matrix<'T> * Matrix<'T>) = + //// former QR + // let updateQ (Q : Matrix<'T>) (v : Vector<'T>) = + // let nQ, mQ = Q.NumRows, Q.NumCols + // let n = v.Length + // let Qv = Vector.zeroCreate<'T> nQ + // for i = 0 to nQ - 1 do + // // offset in Q.Data for row i is i*mQ + // let rowOffset = i * mQ + (mQ - n) + // // Dot the subrange Q[i, mQ-n..mQ-1] with v[0..n-1] + // Qv.[i] <- Acceleration.SIMDRangeUtils.dotRange Q.Data rowOffset v 0 n + + // // Update each row i in the subrange of columns [mQ-n..mQ-1] + // // Q[i, j] -= 2 * Qv[i] * v[j - (mQ - n)] + // for i = 0 to nQ - 1 do + // let alpha = Qv.[i] + Qv.[i] + // // We want to do a row operation: Q[i, (mQ-n)..(mQ-1)] + // // = Q[i, (mQ-n)..(mQ-1)] - alpha * v[0..n-1]. + // let rowOffset = i * mQ + (mQ - n) + // //LinearAlgebra.subScaledRowInPlace Q.Data rowOffset v 0 n alpha + // LinearAlgebra.subScaledRowInPlace alpha rowOffset 0 n Q.Data v + + // // TODO: Refector in Householder module + // let normalize (v: Vector<'T>) : Vector<'T> = + // let norm = Vector.norm v + // if norm = 'T.Zero then v + // else + // Array.map (fun x -> x / norm) v + + // let m, n = A.NumRows, A.NumCols + + // // Q starts as identity(n) + // let Q = Matrix.identity m + // let R = Matrix.copy A + + // for i = 0 to (min n m) - 1 do + // let x = [| for k in i .. m - 1 -> R.[k, i] |] + // //let a = Matrix.getCol i R + // let hh = Householder.create x //a.[i..] Create Householder reflector for column i + // let v = hh.V |> normalize + // updateQ Q v + // Householder.applyLeft(hh, R, i) - // Update each row i in the subrange of columns [mQ-n..mQ-1] - // Q[i, j] -= 2 * Qv[i] * v[j - (mQ - n)] - for i = 0 to nQ - 1 do - let alpha = Qv.[i] + Qv.[i] - // We want to do a row operation: Q[i, (mQ-n)..(mQ-1)] - // = Q[i, (mQ-n)..(mQ-1)] - alpha * v[0..n-1]. - let rowOffset = i * mQ + (mQ - n) - //LinearAlgebra.subScaledRowInPlace Q.Data rowOffset v 0 n alpha - LinearAlgebra.subScaledRowInPlace alpha rowOffset 0 n Q.Data v + // Q, R - let (n, m) = (A.NumRows, A.NumCols) + /// QR decomposition using Householder reflections + static member inline qrDecompose (A : Matrix<'T>) : (Matrix<'T> * Matrix<'T>) = + // former QR + + /// Compute normalized Householder vector from a subcolumn x + let householderVector (x: 'T[]) : 'T[] = + let norm = sqrt (Array.sumBy (fun xi -> xi * xi) x) + let v = Array.copy x + v.[0] <- v.[0] + (if x.[0] >= 'T.Zero then norm else -norm) + let norm_v = sqrt (Array.sumBy (fun vi -> vi * vi) v) + if norm_v = 'T.Zero then v + else Array.map (fun vi -> vi / norm_v) v + + /// Update Q: Q ← Q * Hᵢ using Householder vector v (from column i) + let updateQ (Q: Matrix<'T>) (v: 'T[]) (i: int) = + let nQ, mQ = Q.NumRows, Q.NumCols + for row = 0 to nQ - 1 do + let mutable dot = 'T.Zero + for k = 0 to v.Length - 1 do + dot <- dot + Q.[row, i + k] * v.[k] + let alpha = dot + dot + for k = 0 to v.Length - 1 do + Q.[row, i + k] <- Q.[row, i + k] - alpha * v.[k] + + /// Apply Hᵢ to R from the left: R ← H * R + let applyHouseholderLeft (R: Matrix<'T>) (v: 'T[]) (i: int) = + let m, n = R.NumRows, R.NumCols + for col = i to n - 1 do + let mutable dot = 'T.Zero + for k = 0 to v.Length - 1 do + let row = i + k + if row < m then + dot <- dot + v.[k] * R.[row, col] + let alpha = dot + dot + for k = 0 to v.Length - 1 do + let row = i + k + if row < m then + R.[row, col] <- R.[row, col] - alpha * v.[k] + + /// Main QR decomposition function + let qrDecompose (A: Matrix<'T>) : Matrix<'T> * Matrix<'T> = + let m, n = A.NumRows, A.NumCols + let Q = Matrix.identity m + let R = Matrix.copy A + + for i = 0 to min m n - 1 do + let x = [| for k in i .. m - 1 -> R.[k, i] |] + let v = householderVector x + updateQ Q v i + applyHouseholderLeft R v i + + Q, R + + qrDecompose A - // Q starts as identity(n) - let Q = Matrix.identity n - let R = Matrix.copy A - for i = 0 to (min n m) - 1 do - // 1) Compute Householder transform v for column i - let v = LinearAlgebra.householderTransform R i - // 2) Update Q - UpdateQ Q v - Q, R /// Given A[m,n] and B[m] solves AX = B for X[n].
/// When m => n, have over constrained system, finds least squares solution for X.
@@ -330,17 +409,46 @@ type LinearAlgebra = static member inline leastSquares (A : Matrix<'T>) (b: Vector<'T>) = - + // Maybe rename to leastSquaresQR? let (m,n) = A.NumRows, A.NumCols - let Qm, R = LinearAlgebra.qrDecompose A - let Qtb = Qm.Transpose() * b - + // Is this an overdetermined or underdetermined system? - if m > n then + if m >= n then + //printfn "Least squares: solving %dx%d system with %d equations." m n n + let Qm, R = LinearAlgebra.qrDecompose A + let Qtb = Qm.Transpose() * b LinearAlgebra.solveTriangularLinearSystem R.[0..n-1,0..n-1] Qtb.[0..n-1] false else - let s = LinearAlgebra.solveTriangularLinearSystem R.[0..m-1,0..m-1] Qtb false - Vector.init n (fun i -> if i < m then s.[i] else 'T.Zero) + // underdetermined: solve A^T * x = 0 with min ||x|| + //printfn "underdetermined- Least squares: solving %dx%d system with %d equations." m n n + let AT = A.Transpose() + let Q, R = LinearAlgebra.qrDecompose AT + let RT = R.Transpose() + let s = LinearAlgebra.solveTriangularLinearSystem RT.[0..m-1, 0..m-1] b true + Q.[0.., 0..m-1] * s + + //let AT = A.Transpose() + //let Q, R = LinearAlgebra.qrDecompose AT + //let y = Q.Transpose() * b + //let s = LinearAlgebra.solveTriangularLinearSystem R.[0..m-1, 0..m-1] y.[0..m-1] false + + //Q.[0..n,0..m] * s + + + + + //let AT = A.Transpose() + //let QT, RT = LinearAlgebra.qrDecompose AT + //let y = QT.Transpose() * b + //let s = LinearAlgebra.solveTriangularLinearSystem RT.[0..m-1, 0..m-1] y.[0..m-1] false + //let s = LinearAlgebra.solveTriangularLinearSystem R.[0..m-1,0..m-1] Qtb false + //Vector.init n (fun i -> if i < m then s.[i] else 'T.Zero) + + //// underdetermined: solve min ||x|| such that Ax = b + //let AT = A.Transpose() + //let QT, RT = LinearAlgebra.qrDecompose AT + //let y = LinearAlgebra.solveTriangularLinearSystem (RT.Transpose().[0..m-1, 0..m-1]) b false + //QT.[*, 0..m-1] * y /// @@ -398,13 +506,16 @@ type LinearAlgebra = (A : Matrix<'T>) (b: Vector<'T>) = + if b.Length <> A.NumRows then + invalidArg "b" "Length of b must match the number of rows of A." + let AT = A.Transpose() let upper = (AT * A) |> LinearAlgebra.cholesky let gamma = - LinearAlgebra.solveTriangularLinearSystem(upper.Transpose()) (AT * b) true + LinearAlgebra.solveTriangularLinearSystem(upper) (AT * b) true let beta = - LinearAlgebra.solveTriangularLinearSystem upper gamma false + LinearAlgebra.solveTriangularLinearSystem (upper.Transpose()) gamma false beta diff --git a/src/FSharp.Stats/Algebra/SVD.fs b/src/FSharp.Stats/Algebra/SVD.fs index 820d025d1..35a9408ea 100644 --- a/src/FSharp.Stats/Algebra/SVD.fs +++ b/src/FSharp.Stats/Algebra/SVD.fs @@ -5,113 +5,6 @@ open System open FSharp.Stats open FSharp.Stats.Acceleration -[] -type Householder<'T when 'T :> Numerics.INumber<'T>> = - { - V: Vector<'T> - Tau: 'T - Beta: 'T - } - - -type Householder() = - - static member inline create<'T when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T : comparison - and 'T :> ValueType - and 'T :> Numerics.IRootFunctions<'T>> - (x: Vector<'T>) : Householder<'T> = - - let xSpan = x.AsSpan() - let alpha = xSpan[0] - let tail = xSpan.Slice(1) - - let zero = GenericMath.zero<'T> - let one = GenericMath.one<'T> - - let sigma = - SIMDUtils.mapFoldUnchecked( - (fun v -> v * v), - (fun x -> x * x), - (+), - (+), - zero, - tail - ) - - if sigma.Equals(zero) then - let v = Vector.zeroCreate x.Length - v.[0] <- one - { - V = v - Tau = zero - Beta = alpha - } - else - let sum = alpha * alpha + sigma - let beta = GenericMath.sqrt sum - - let v0 = - if alpha <= zero then alpha - beta - else -sigma / (alpha + beta) - - let tau = - let v0Sq = v0 * v0 - (v0Sq + v0Sq) / (sigma + v0Sq) - - let v = Vector.divideScalar v0 x // SIMD-aware scalar division - v.[0] <- one - - { - V = v - Tau = tau - Beta = beta - } - - static member inline applyLeft<'T when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T : equality - and 'T :> ValueType> - (h: Householder<'T>, A: Matrix<'T>, rowOffset: int) = - - let v = h.V - let tau = h.Tau - let m = A.NumRows - let n = A.NumCols - let vLen = v.Length - - for j = 0 to n - 1 do - let mutable dot = GenericMath.zero<'T> - for i = 0 to vLen - 1 do - dot <- dot + v.[i] * A.[rowOffset + i, j] - let scale = tau * dot - for i = 0 to vLen - 1 do - A.[rowOffset + i, j] <- A.[rowOffset + i, j] - scale * v.[i] - - - static member inline applyRight<'T when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T : equality - and 'T :> ValueType> - (h: Householder<'T>, A: Matrix<'T>, colOffset: int) = - - let v = h.V - let tau = h.Tau - let m = A.NumRows - let vLen = v.Length - - for i = 0 to m - 1 do - let mutable dot = GenericMath.zero<'T> - for j = 0 to vLen - 1 do - dot <- dot + A.[i, colOffset + j] * v.[j] - let scale = tau * dot - for j = 0 to vLen - 1 do - A.[i, colOffset + j] <- A.[i, colOffset + j] - scale * v.[j] - type Bidiagonalization() = static member inline bidiagonalizeInPlace<'T diff --git a/src/FSharp.Stats/FSharp.Stats.fsproj b/src/FSharp.Stats/FSharp.Stats.fsproj index 580bef79e..db80f410f 100644 --- a/src/FSharp.Stats/FSharp.Stats.fsproj +++ b/src/FSharp.Stats/FSharp.Stats.fsproj @@ -37,6 +37,7 @@ + diff --git a/src/FSharp.Stats/Fitting/Spline.fs b/src/FSharp.Stats/Fitting/Spline.fs index 656793a10..7dbef668d 100644 --- a/src/FSharp.Stats/Fitting/Spline.fs +++ b/src/FSharp.Stats/Fitting/Spline.fs @@ -59,7 +59,7 @@ module Spline = // Construct the matrices we need let Bt = Matrix.init n' n (fun c r -> basis.[c] xdata.[r]) - let BtB = Bt * Bt.Transpose() + let BtB = Bt * (Bt.Transpose()) let penaltyFunc r c = let xi = xdata.[-2+min r c] let xj = xdata.[-2+max r c] diff --git a/src/FSharp.Stats/Playground.fsx b/src/FSharp.Stats/Playground.fsx index 884d62f9b..7eb5fbae0 100644 --- a/src/FSharp.Stats/Playground.fsx +++ b/src/FSharp.Stats/Playground.fsx @@ -9,220 +9,611 @@ open FSharp.Stats.Distributions open FSharp.Stats.Algebra open FSharp.Stats.Distributions.Continuous -let d = [| 4.0; 3.0 |] -let e = [| 2.0 |] +let canonicalizeQR (Q: Matrix, R: Matrix) = + let m, n = R.NumRows, R.NumCols + for j = 0 to min m n - 1 do + if R.[j, j] < 0.0 then + // Flip column j of Q + for i = 0 to Q.NumRows - 1 do + Q.[i, j] <- -Q.[i, j] + // Flip row j of R + for k = 0 to R.NumCols - 1 do + R.[j, k] <- -R.[j, k] + Q, R + +// TODO: Refector in Householder module +let normalize (v: Vector) : Vector = + let norm = Vector.norm v + if norm = 0. then v + else + Array.map (fun x -> x / norm) v + + +let leastSquares (A : Matrix) (b: Vector) = +// Maybe rename to leastSquaresQR? + let (m,n) = A.NumRows, A.NumCols + + // Is this an overdetermined or underdetermined system? + if m >= n then + //printfn "Least squares: solving %dx%d system with %d equations." m n n + let Qm, R = LinearAlgebra.qrDecompose A + let Qtb = Qm.Transpose() * b + LinearAlgebra.solveTriangularLinearSystem R.[0..n-1,0..n-1] Qtb.[0..n-1] false + + + else + // underdetermined: solve A^T * x = 0 with min ||x|| + let AT = A.Transpose() + let Q, R = LinearAlgebra.qrDecompose AT + let RT = R.Transpose() + let s = LinearAlgebra.solveTriangularLinearSystem RT.[0..m-1, 0..m-1] b true + Q.[0.., 0..m-1] * s + + + +let A = Matrix(2, 3, [| 1.0; 2.0; 0.0; + 0.0; 1.0; 1.0 |]) +let b = [| 3.0; 2.0 |] +let x = leastSquares A b + + + +let Q, R = LinearAlgebra.qrDecompose A +Q * R + +//let A = Matrix(2, 2, [| 2.0; 1.0; +// 1.0; 3.0 |]) +//let b = [| 5.0; 10.0 |] +//let x = LinearAlgebra.leastSquares A b +//let expected = [| 1.0; 3.0 |] + +//let Q, R = LinearAlgebra.qrDecompose A + + +//let A = Matrix(2, 2, [| 2.0; 1.0; +// 1.0; 3.0 |]) +//let Q, R = LinearAlgebra.qrDecompose A |> canonicalizeQR +//let QR = Q * R + + + + + + + +////let UpdateQ_Debug (Q : Matrix) (v : float[]) = +//// let nQ, mQ = Q.NumRows, Q.NumCols +//// let n = v.Length +//// let Qv = Array.zeroCreate nQ + +//// printfn "=== UpdateQ_Debug ===" +//// printfn "Input matrix Q:" +//// printfn "%A" Q +//// printfn "Householder vector v: [%s]" (String.Join("; ", v |> Array.map (fun x -> x.ToString("F3")))) + +//// // Step 1: Compute Qv = Q * v over trailing n columns +//// for i = 0 to nQ - 1 do +//// let rowOffset = i * mQ + (mQ - n) +//// let dot = Acceleration.SIMDRangeUtils.dotRange Q.Data rowOffset v 0 n +//// //let rowOffset = i * mQ + i +//// //let dot = Acceleration.SIMDRangeUtils.dotRange Q.Data rowOffset v 0 n +//// Qv.[i] <- dot +//// printfn $"Row {i}: dot(Q[{i}, {mQ-n}..], v) = {dot:F3}" + +//// // Step 2: Apply in-place update to Q +//// for i = 0 to nQ - 1 do +//// let alpha = 2.0 * Qv.[i] +//// let rowOffset = i * mQ + (mQ - n) +//// let tmp1 = (Q.Data.[rowOffset .. rowOffset + n - 1] |> Array.map (fun x -> x.ToString()) |> String.concat("; ")) +//// printfn $"Row {i}: alpha = 2 * {Qv.[i]:F3} = {alpha:F3}" +//// printfn $"Before update Q[{i}, {mQ-n}..]: [{tmp1}]" + + +//// LinearAlgebra.subScaledRowInPlace alpha rowOffset 0 (n - i) Q.Data v//alpha rowOffset 0 n Q.Data v +//// let tmp2 = (Q.Data.[rowOffset .. rowOffset + n - 1] |> Array.map (fun x -> x.ToString()) |> String.concat("; ")) +//// printfn $"After update Q[{i}, {mQ-n}..]: [{tmp2}]" + + +//// printfn "Updated Q matrix:" +//// printfn "%A" (Q) +//// printfn "=== End UpdateQ_Debug ===" + + + +////let applyHouseholderLeft (R: Matrix<'T>) (v: Vector<'T>) (i: int) = +//// let m, n = R.NumRows, R.NumCols +//// let nV = v.Length + +//// for col = i to n - 1 do +//// // Compute projection of column onto v +//// let mutable dot = LanguagePrimitives.GenericZero<'T> +//// for k = 0 to nV - 1 do +//// let row = i + k +//// if row < m then +//// dot <- dot + v.[k] * R.[row, col] + +//// let alpha = dot + dot + +//// // Update R[i.., col] +//// for k = 0 to nV - 1 do +//// let row = i + k +//// if row < m then +//// R.[row, col] <- R.[row, col] - alpha * v.[k] + +///// Apply Householder reflector from the left: R ← H * R +///// Only modifies the submatrix R[i.., i..] +//let applyHouseholderLeft (R: Matrix) (v: Vector) (i: int) = +// let m, n = R.NumRows, R.NumCols +// let nV = v.Length + +// for col = i to n - 1 do +// // Compute dot product: vᵗ * R[i.., col] +// let mutable dot = 0.0 +// for k = 0 to nV - 1 do +// let row = i + k +// if row < m then +// dot <- dot + v.[k] * R.[row, col] + +// let alpha = 2.0 * dot -let bidiag = { - D = d - E = e -} +// // Apply reflection to R[i.., col] +// for k = 0 to nV - 1 do +// let row = i + k +// if row < m then +// R.[row, col] <- R.[row, col] - alpha * v.[k] + + + +//let UpdateQ_Debug (Q : Matrix<'T>) (v : Vector<'T>) = +// let nQ, mQ = Q.NumRows, Q.NumCols +// let n = v.Length // Length of Householder vector +// let i = mQ - n // Starting column (pivot position) +// let Qv = Vector.zeroCreate<'T> nQ // Holds dot products for each row + +// // Compute Qv[i] = Q[i, i..] ⋅ v +// for row = 0 to nQ - 1 do +// let rowOffset = row * mQ + i +// Qv.[row] <- Acceleration.SIMDRangeUtils.dotRange Q.Data rowOffset v 0 n + +// // Apply the Householder update to the trailing part of each row +// for row = 0 to nQ - 1 do +// let alpha = Qv.[row] + Qv.[row] // 2 * dot product +// let rowOffset = row * mQ + i +// LinearAlgebra.subScaledRowInPlace alpha rowOffset 0 n Q.Data v + + + + +//type Testing() = +// /// QR decomposition using Householder reflections +// static member inline qrDecompose (A : Matrix<'T>) : (Matrix<'T> * Matrix<'T>) = +// // former QR +// let UpdateQ (Q : Matrix<'T>) (v : Vector<'T>) = +// let nQ, mQ = Q.NumRows, Q.NumCols +// let n = v.Length +// let Qv = Vector.zeroCreate<'T> nQ +// for i = 0 to nQ - 1 do +// // offset in Q.Data for row i is i*mQ +// let rowOffset = i * mQ + (mQ - n) +// // Dot the subrange Q[i, mQ-n..mQ-1] with v[0..n-1] +// Qv.[i] <- Acceleration.SIMDRangeUtils.dotRange Q.Data rowOffset v 0 n + +// // Update each row i in the subrange of columns [mQ-n..mQ-1] +// // Q[i, j] -= 2 * Qv[i] * v[j - (mQ - n)] +// for i = 0 to nQ - 1 do +// let alpha = Qv.[i] + Qv.[i] +// // We want to do a row operation: Q[i, (mQ-n)..(mQ-1)] +// // = Q[i, (mQ-n)..(mQ-1)] - alpha * v[0..n-1]. +// let rowOffset = i * mQ + (mQ - n) +// //LinearAlgebra.subScaledRowInPlace Q.Data rowOffset v 0 n alpha +// LinearAlgebra.subScaledRowInPlace alpha rowOffset 0 n Q.Data v + +// let normalize (v: Vector<'T>) : Vector<'T> = +// let norm = Vector.norm v +// if norm = 'T.Zero then +// invalidArg "v" "Cannot normalize a zero vector." +// Array.map (fun x -> x / norm) v + +// let (n, m) = (A.NumRows, A.NumCols) + +// // Q starts as identity(n) +// let Q = Matrix.identity n +// let R = Matrix.copy A + +// for i = 0 to (min n m) - 1 do +// // 1) Compute Householder transform v for column i +// let v = LinearAlgebra.householderTransform R i |> normalize +// // 2) Update Q +// UpdateQ Q v +// applyHouseholderLeft R v i + +// Q, R + + +// //static member inline householderTransform +// // (A: Matrix<'T>) (i: int) : Vector<'T> = +// // let n = A.NumRows + +// // let v = Vector.zeroCreate<'T> n +// // let aCol = Matrix.getCol i A +// // let norm = Vector.norm aCol // ToDO: use a more efficient norm calculation +// // v.[i] <- aCol.[i] + if aCol.[i] >= 'T.Zero then norm else -norm +// // for j = i + 1 to n - 1 do +// // v.[j] <- aCol.[j] +// // v + + +////let Q :Matrix = Matrix.identity 3 +////let v = [| 1.0; 2.0; 3.0 |] +////UpdateQ Q v + +////Q = +////[[ 1.073 -2.0 -2.0 ] +//// [ 1.464 -1.0 -2.0 ] +//// [ 1.464 -2.0 -1.0 ]] + +//module Testing = + +// open System + +// /// Compute normalized Householder vector from a subcolumn x +// let householderVector (x: float[]) : float[] = +// let norm = sqrt (Array.sumBy (fun xi -> xi * xi) x) +// let v = Array.copy x +// v.[0] <- v.[0] + (if x.[0] >= 0.0 then norm else -norm) +// let norm_v = sqrt (Array.sumBy (fun vi -> vi * vi) v) +// if norm_v = 0.0 then v +// else Array.map (fun vi -> vi / norm_v) v + +// let householderTransform +// (A: Matrix) (i: int) : Vector = +// let n = A.NumRows + +// let aCol = Matrix.getCol i A +// let v = aCol[i..] +// let norm = Vector.norm v // ToDO: use a more efficient norm calculation +// v.[0] <- v.[0] + (if v.[0] >= 0. then norm else -norm) +// v + +// let normalize (v: Vector) : Vector = +// let norm = Vector.norm v +// if norm = 0. then v +// else +// Array.map (fun x -> x / norm) v + +// /// Update Q: Q ← Q * Hᵢ using Householder vector v (from column i) +// let updateQ (Q: Matrix) (v: float[]) (i: int) = +// let nQ, mQ = Q.NumRows, Q.NumCols +// for row = 0 to nQ - 1 do +// let mutable dot = 0.0 +// for k = 0 to v.Length - 1 do +// dot <- dot + Q.[row, i + k] * v.[k] +// let alpha = 2.0 * dot +// for k = 0 to v.Length - 1 do +// Q.[row, i + k] <- Q.[row, i + k] - alpha * v.[k] + + +// let update_Q (Q : Matrix<'T>) (v : Vector<'T>) = +// let nQ, mQ = Q.NumRows, Q.NumCols +// let n = v.Length +// let Qv = Vector.zeroCreate<'T> nQ +// for i = 0 to nQ - 1 do +// // offset in Q.Data for row i is i*mQ +// let rowOffset = i * mQ + (mQ - n) +// // Dot the subrange Q[i, mQ-n..mQ-1] with v[0..n-1] +// Qv.[i] <- Acceleration.SIMDRangeUtils.dotRange Q.Data rowOffset v 0 n + +// // Update each row i in the subrange of columns [mQ-n..mQ-1] +// // Q[i, j] -= 2 * Qv[i] * v[j - (mQ - n)] +// for i = 0 to nQ - 1 do +// let alpha = Qv.[i] + Qv.[i] +// // We want to do a row operation: Q[i, (mQ-n)..(mQ-1)] +// // = Q[i, (mQ-n)..(mQ-1)] - alpha * v[0..n-1]. +// let rowOffset = i * mQ + (mQ - n) +// //LinearAlgebra.subScaledRowInPlace Q.Data rowOffset v 0 n alpha +// LinearAlgebra.subScaledRowInPlace alpha rowOffset 0 n Q.Data v + +// /// Apply Hᵢ to R from the left: R ← H * R +// let applyHouseholderLeft (R: Matrix) (v: float[]) (i: int) = +// let m, n = R.NumRows, R.NumCols +// for col = i to n - 1 do +// let mutable dot = 0.0 +// for k = 0 to v.Length - 1 do +// let row = i + k +// if row < m then +// dot <- dot + v.[k] * R.[row, col] +// let alpha = 2.0 * dot +// for k = 0 to v.Length - 1 do +// let row = i + k +// if row < m then +// R.[row, col] <- R.[row, col] - alpha * v.[k] + + + + +// /// Main QR decomposition function +// let qrDecompose (A: Matrix) : Matrix * Matrix = +// let m, n = A.NumRows, A.NumCols +// let Q = Matrix.identity m +// let R = Matrix.copy A + +// for i = 0 to n - 1 do +// //let x = [| for k in i .. m - 1 -> R.[k, i] |] +// let x = Matrix.getCol i R +// let hh = Householder.create x.[i..] // Create Householder reflector for column i +// let v = hh.V |> normalize +// //let v = householderTransform R i |> normalize // householderVector x +// update_Q Q v +// //applyHouseholderLeft R v i +// Householder.applyLeft(hh, R, i) + +// Q, R + + + +//let A = Matrix(3, 2, [| 1.0; 1.0; +// 1.0; 2.0; +// 1.0; 3.0 |]) +//let Q, R = Testing.qrDecompose A + +//let QR = Matrix.matmul Q R + +//let t:Vector = Matrix.getCol 1 A +//t.[0] <- nan + +//let i = 1 +//let m, n = A.NumRows, A.NumCols +//[| for k in i .. m - 1 -> A.[k, i] |] + +//let v = Testing.householderTransform A 0 |> normalize + +//Vector.norm v + +//let H = +// let n = v.Length +// let I : Matrix = Matrix.identity n +// let outer = Matrix.init n n (fun i j -> v.[i] * v.[j]) +// I - (outer * 2.0) +// (outer * 2.0) -let sigma = GolubKahan.diagonalize bidiag +//let R1 = Matrix.matmul H A +//let (n, m) = (A.NumRows, A.NumCols) -let A = - matrix [| - [| 4.0; 1.0; 2.0 |] - [| 3.0; 1.0; 0.0 |] - [| 5.0; 1.0; 3.0 |] - |] +//let Q : Matrix = Matrix.identity n +//let R = Matrix.copy A +//UpdateQ_Debug Q v +//applyHouseholderLeft R v 0 -// Extract column 0 -let colVector = [| A.[0, 0]; A.[1, 0]; A.[2, 0] |] -let h = Householder.create colVector -// Overwrite A[0..,0] with [β; 0; 0] -A.[0, 0] <- h.Beta -for i = 1 to 2 do - A.[i, 0] <- 0.0 -Householder.applyLeft(h, A, 0) -A.[1, 0] -//let input = + +//let Q : Matrix = Matrix.identity 3 +//let v = [| 1.0; 2.0; 3.0 |] +//UpdateQ_Debug Q v + +//let A = Matrix(3, 2, [| 1.0; 1.0; +// 1.0; 2.0; +// 1.0; 3.0 |]) + +//let v = LinearAlgebra.householderTransform A 1 + +//let d = [| 4.0; 3.0 |] +//let e = [| 2.0 |] + +//let bidiag = { +// D = d +// E = e +//} + +//let sigma = GolubKahan.diagonalize bidiag + + +//let A = // matrix [| -// [| 1.0; 2.0; 3.0 |] -// [| 4.0; 5.0; 6.0 |] -// [| 7.0; 8.0; 9.0 |] +// [| 4.0; 1.0; 2.0 |] +// [| 3.0; 1.0; 0.0 |] +// [| 5.0; 1.0; 3.0 |] // |] -//let A = input |> Matrix.copy +//// Extract column 0 +//let colVector = [| A.[0, 0]; A.[1, 0]; A.[2, 0] |] +//let h = Householder.create colVector -//Bidiagonalization.bidiagonalizeInPlace A -//A +//// Overwrite A[0..,0] with [β; 0; 0] +//A.[0, 0] <- h.Beta +//for i = 1 to 2 do +// A.[i, 0] <- 0.0 +//Householder.applyLeft(h, A, 0) +//A.[1, 0] -// Apply reflector from the left to matrix A starting at row 0 +////let input = +//// matrix [| +//// [| 1.0; 2.0; 3.0 |] +//// [| 4.0; 5.0; 6.0 |] +//// [| 7.0; 8.0; 9.0 |] +//// |] -let alpha = 5.0 -let beta = 1.0 -let p = 0.95 -let x = Gamma.InvCDF alpha beta p +////let A = input |> Matrix.copy +////Bidiagonalization.bidiagonalizeInPlace A +////A -let Categorical_SampleUnchecked (probabilities: float[]) = - let rnd = Random.rndgen.NextFloat() - let rec search i acc = - if i >= probabilities.Length then probabilities.Length - 1 - elif acc + probabilities[i] >= rnd then i - else search (i + 1) (acc + probabilities[i]) - search 0 0.0 +//// Apply reflector from the left to matrix A starting at row 0 +//let alpha = 5.0 +//let beta = 1.0 +//let p = 0.95 +//let x = Gamma.InvCDF alpha beta p -/// Helper function to sample many times and collect counts. -let sampleMany (times: int) (probabilities: float[]) = - let counts = Array.zeroCreate probabilities.Length - for _ in 1 .. times do - let idx = Categorical_SampleUnchecked probabilities - counts.[idx] <- counts.[idx] + 1 - counts +//let Categorical_SampleUnchecked (probabilities: float[]) = +// let rnd = Random.rndgen.NextFloat() +// let rec search i acc = +// if i >= probabilities.Length then probabilities.Length - 1 +// elif acc + probabilities[i] >= rnd then i +// else search (i + 1) (acc + probabilities[i]) +// search 0 0.0 -let p = [| 0.2; 0.3; 0.5 |] -let iterations = 10000000 -Array.init iterations (fun _ -> Categorical_SampleUnchecked p) -|> Array.countBy id +///// Helper function to sample many times and collect counts. +//let sampleMany (times: int) (probabilities: float[]) = +// let counts = Array.zeroCreate probabilities.Length +// for _ in 1 .. times do +// let idx = Categorical_SampleUnchecked probabilities +// counts.[idx] <- counts.[idx] + 1 +// counts -// Act -let counts = sampleMany iterations p -float counts.[2] / float iterations +//let p = [| 0.2; 0.3; 0.5 |] +//let iterations = 10000000 -// Assert -// All indices should be between 0 and p.Length - 1 -// If out of range, an exception would occur while incrementing counts. -// So, if we got this far without an exception, the function is generating valid indices. -// We can add an extra check that the sum of counts equals 'iterations'. -let total = Array.sum counts +//Array.init iterations (fun _ -> Categorical_SampleUnchecked p) +//|> Array.countBy id -let SampleUnchecked (p : float[]) n = - //let cp = Discrete.Multinomial.ProbabilityMassToCumulativeDistribution p - let ret = Array.zeroCreate p.Length - for _ = 1 to n do - let idx = Discrete.Categorical.SampleUnchecked p - ret[idx] <- ret[idx] + 1 - ret -let n = 100000 // Large n to reduce variance -let probabilities = [| 0.2; 0.3; 0.5 |] //// Act -//let sampleCounts = Categorical_SampleUnchecked probabilities - -//probabilities -//|> Array.iteri (fun i p -> -// let observedProportion = float sampleCounts.[i] / float n -// printfn $"Probability of {i}: {p}, Observed proportion: {observedProportion}") +//let counts = sampleMany iterations p +//float counts.[2] / float iterations + + +//// Assert +//// All indices should be between 0 and p.Length - 1 +//// If out of range, an exception would occur while incrementing counts. +//// So, if we got this far without an exception, the function is generating valid indices. +//// We can add an extra check that the sum of counts equals 'iterations'. +//let total = Array.sum counts + + +//let SampleUnchecked (p : float[]) n = +// //let cp = Discrete.Multinomial.ProbabilityMassToCumulativeDistribution p +// let ret = Array.zeroCreate p.Length +// for _ = 1 to n do +// let idx = Discrete.Categorical.SampleUnchecked p +// ret[idx] <- ret[idx] + 1 +// ret + +//let n = 100000 // Large n to reduce variance +//let probabilities = [| 0.2; 0.3; 0.5 |] +////// Act +////let sampleCounts = Categorical_SampleUnchecked probabilities + +////probabilities +////|> Array.iteri (fun i p -> +//// let observedProportion = float sampleCounts.[i] / float n +//// printfn $"Probability of {i}: {p}, Observed proportion: {observedProportion}") + + + +////let n = 100000 // Larger n to reduce sampling variance +//let sample = SampleUnchecked probabilities n + +//let () = +// probabilities +// |> Array.iteri (fun i p -> +// let observedProportion = float sample.[i] / float n +// printfn $"Probability of {i}: {p}, Observed proportion: {observedProportion}") + + + +//Discrete.Multinomial.ProbabilityMassToCumulativeDistribution probabilities + + +//let KDiagonal1 = +// [| +// [|1.;0.;0.|] +// [|0.;1.;0.|] +// [|0.;0.;1.|] +// |] +// |> Matrix.ofJaggedArray + +//let BNegInf = +// [| +// [|-infinity;-infinity;-infinity|] +// [|-infinity;-infinity;-infinity|] +// [|-infinity;-infinity;-infinity|] +// |] +// |> Matrix.ofJaggedArray + + +//Algebra.LinearAlgebra.solveTriangularLinearSystems KDiagonal1 BNegInf false + + +//KDiagonal1 +//|> Matrix.mapiCols (fun i v -> +// let m = Vector.norm v +// [|m|]) + +//let expected = +// matrix [| +// [|nan;nan;nan|]; +// [|nan;nan;nan|]; +// [|-infinity;-infinity;-infinity|] +// |] - -//let n = 100000 // Larger n to reduce sampling variance -let sample = SampleUnchecked probabilities n - -let () = - probabilities - |> Array.iteri (fun i p -> - let observedProportion = float sample.[i] / float n - printfn $"Probability of {i}: {p}, Observed proportion: {observedProportion}") - - - -Discrete.Multinomial.ProbabilityMassToCumulativeDistribution probabilities - - -let KDiagonal1 = - [| - [|1.;0.;0.|] - [|0.;1.;0.|] - [|0.;0.;1.|] - |] - |> Matrix.ofJaggedArray - -let BNegInf = - [| - [|-infinity;-infinity;-infinity|] - [|-infinity;-infinity;-infinity|] - [|-infinity;-infinity;-infinity|] - |] - |> Matrix.ofJaggedArray - - -Algebra.LinearAlgebra.solveTriangularLinearSystems KDiagonal1 BNegInf false - - -KDiagonal1 -|> Matrix.mapiCols (fun i v -> - let m = Vector.norm v - [|m|]) - -let expected = - matrix [| - [|nan;nan;nan|]; - [|nan;nan;nan|]; - [|-infinity;-infinity;-infinity|] - |] - - -//|> fun res -> -// let expected = -// matrix [| -// [|nan;nan;nan|]; -// [|nan;nan;nan|]; -// [|-infinity;-infinity;-infinity|] -// |] - - - -let alpha = 9.9 //0.4 -let beta = 31 //4.2 -// https://keisan.casio.com/exec/system/1180573216 -let pdfs = [| 0.987113653; 0.635929273; 0.486870787; 0.400046182; 0.341683319; - 0.299071263; 0.266235685; 0.239955525; 0.218322701; 0.200126249; - 0.184555971; 0.171046668; 0.159190450; 0.148684554; 0.139298865; - 0.130854902; 0.123211796; 0.116256647; 0.109897748; 0.104059710; - 0.098679897; 0.093705765; 0.089092854; 0.084803247; 0.080804376; - 0.077068078; 0.073569861; 0.070288299; 0.067204554; 0.064301989; - 0.061565838; 0.058982949; 0.056541557; 0.054231102; 0.052042076; - 0.049965886; 0.047994748; 0.046121587; 0.044339960; 0.042643979; - 0.041028256; 0.039487846; 0.038018205; 0.036615142; 0.035274793; - 0.033993583; 0.032768200; 0.031595571; 0.030472842; 0.029397355; - 0.028366635; 0.027378369; 0.026430398; 0.025520703; 0.024647389; - 0.023808683; 0.023002918; 0.022228528; 0.021484040; 0.020768066; - 0.020079300; 0.019416507; 0.018778524; 0.018164249; 0.017572643; - 0.017002719; 0.016453546; 0.015924240; 0.015413961; 0.014921914; - 0.014447344; 0.013989532; 0.013547795; 0.013121484; 0.012709981; - 0.012312696; 0.011929068; 0.011558563; 0.011200670; 0.010854903; - 0.010520795; 0.010197904; 0.009885805; 0.009584092; 0.009292377; - 0.009010290; 0.008737475; 0.008473592; 0.008218316; 0.007971333; - 0.007732346; 0.007501068; 0.007277223; 0.007060548; 0.006850789; - 0.006647704; 0.006451059; 0.006260630; 0.006076203; 0.005897569; |] - -//let xy_pdf = pdfs |> Array.mapi (fun i v -> (float (i + 1) / 10.), Continuous.Gamma.PDF alpha beta (float (i + 1) / 10.)) -let samplesHisto = Array.init 999999 (fun _ -> Continuous.Gamma.Sample alpha beta) - -let bw = 1.//FSharp.Stats.Distributions.Bandwidth.forHistogram samplesHisto -let histo = FSharp.Stats.Distributions.KernelDensity.estimate KernelDensity.Kernel.gaussian bw samplesHisto -let histoPdf = histo |> Seq.map (fun (x,y) -> x,Continuous.Gamma.PDF alpha beta x) -//[ -// Chart.Column(histo) -// Chart.Point(histoPdf) -//] -//|> Chart.combine -//|> Chart.show - - -let alpha', beta' = Continuous.Gamma.Fit samplesHisto - -let d = Continuous.Gamma.Estimate pdfs -d.Mean +////|> fun res -> +//// let expected = +//// matrix [| +//// [|nan;nan;nan|]; +//// [|nan;nan;nan|]; +//// [|-infinity;-infinity;-infinity|] +//// |] + + + +//let alpha = 9.9 //0.4 +//let beta = 31 //4.2 +//// https://keisan.casio.com/exec/system/1180573216 +//let pdfs = [| 0.987113653; 0.635929273; 0.486870787; 0.400046182; 0.341683319; +// 0.299071263; 0.266235685; 0.239955525; 0.218322701; 0.200126249; +// 0.184555971; 0.171046668; 0.159190450; 0.148684554; 0.139298865; +// 0.130854902; 0.123211796; 0.116256647; 0.109897748; 0.104059710; +// 0.098679897; 0.093705765; 0.089092854; 0.084803247; 0.080804376; +// 0.077068078; 0.073569861; 0.070288299; 0.067204554; 0.064301989; +// 0.061565838; 0.058982949; 0.056541557; 0.054231102; 0.052042076; +// 0.049965886; 0.047994748; 0.046121587; 0.044339960; 0.042643979; +// 0.041028256; 0.039487846; 0.038018205; 0.036615142; 0.035274793; +// 0.033993583; 0.032768200; 0.031595571; 0.030472842; 0.029397355; +// 0.028366635; 0.027378369; 0.026430398; 0.025520703; 0.024647389; +// 0.023808683; 0.023002918; 0.022228528; 0.021484040; 0.020768066; +// 0.020079300; 0.019416507; 0.018778524; 0.018164249; 0.017572643; +// 0.017002719; 0.016453546; 0.015924240; 0.015413961; 0.014921914; +// 0.014447344; 0.013989532; 0.013547795; 0.013121484; 0.012709981; +// 0.012312696; 0.011929068; 0.011558563; 0.011200670; 0.010854903; +// 0.010520795; 0.010197904; 0.009885805; 0.009584092; 0.009292377; +// 0.009010290; 0.008737475; 0.008473592; 0.008218316; 0.007971333; +// 0.007732346; 0.007501068; 0.007277223; 0.007060548; 0.006850789; +// 0.006647704; 0.006451059; 0.006260630; 0.006076203; 0.005897569; |] + +////let xy_pdf = pdfs |> Array.mapi (fun i v -> (float (i + 1) / 10.), Continuous.Gamma.PDF alpha beta (float (i + 1) / 10.)) +//let samplesHisto = Array.init 999999 (fun _ -> Continuous.Gamma.Sample alpha beta) + +//let bw = 1.//FSharp.Stats.Distributions.Bandwidth.forHistogram samplesHisto +//let histo = FSharp.Stats.Distributions.KernelDensity.estimate KernelDensity.Kernel.gaussian bw samplesHisto +//let histoPdf = histo |> Seq.map (fun (x,y) -> x,Continuous.Gamma.PDF alpha beta x) +////[ +//// Chart.Column(histo) +//// Chart.Point(histoPdf) +////] +////|> Chart.combine +////|> Chart.show + + +//let alpha', beta' = Continuous.Gamma.Fit samplesHisto + +//let d = Continuous.Gamma.Estimate pdfs +//d.Mean diff --git a/tests/FSharp.Stats.Tests/Acceleration.fs b/tests/FSharp.Stats.Tests/Acceleration.fs new file mode 100644 index 000000000..4c7b45014 --- /dev/null +++ b/tests/FSharp.Stats.Tests/Acceleration.fs @@ -0,0 +1,49 @@ +module AccelerationTests + +open Expecto +open System +open FSharp.Stats +open TestExtensions + +open Expecto + +[] +let dotRangeTests = + testList "dotRange tests" [ + + test "Basic dot product with zero offset" { + let a = [| 1.0; 2.0; 3.0 |] + let b = [| 4.0; 5.0; 6.0 |] + let result = Acceleration.SIMDRangeUtils.dotRange a 0 b 0 3 + Expect.floatClose Accuracy.high result 32.0 "Dot product mismatch" + } + + test "Dot product with offset in first array" { + let a = [| 0.0; 1.0; 2.0; 3.0 |] // use 1.0, 2.0, 3.0 + let b = [| 4.0; 5.0; 6.0 |] + let result = Acceleration.SIMDRangeUtils.dotRange a 1 b 0 3 + Expect.floatClose Accuracy.high result 32.0 "Offset dot mismatch" + } + + test "Dot product with both arrays offset" { + let a = [| 0.0; 1.0; 2.0; 3.0 |] + let b = [| 0.0; 4.0; 5.0; 6.0 |] + let result = Acceleration.SIMDRangeUtils.dotRange a 1 b 1 3 + Expect.floatClose Accuracy.high result 32.0 "Offset-dot mismatch" + } + + test "Dot with zero-length" { + let a = [| 1.0; 2.0; 3.0 |] + let b = [| 4.0; 5.0; 6.0 |] + let result = Acceleration.SIMDRangeUtils.dotRange a 0 b 0 0 + Expect.equal result 0.0 "Zero-length dot should be 0" + } + + test "Out of bounds throws" { + let a = [| 1.0; 2.0 |] + let b = [| 1.0; 2.0 |] + Expect.throws (fun () -> + Acceleration.SIMDRangeUtils.dotRange a 1 b 1 2 |> ignore) + "Should throw on out-of-bounds" + } + ] diff --git a/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj b/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj index 8435d6b1f..94d433f8b 100644 --- a/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj +++ b/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj @@ -6,6 +6,7 @@ + @@ -17,6 +18,7 @@ + diff --git a/tests/FSharp.Stats.Tests/LinearAlgebra.fs b/tests/FSharp.Stats.Tests/LinearAlgebra.fs index 3225fe876..48d7d5aa2 100644 --- a/tests/FSharp.Stats.Tests/LinearAlgebra.fs +++ b/tests/FSharp.Stats.Tests/LinearAlgebra.fs @@ -6,6 +6,534 @@ open FSharp.Stats open FSharp.Stats.Algebra open TestExtensions + +[] +let householderTests = + testList "Householder tests" [ + + test "Householder reflection zeros subcolumn (3x2 matrix)" { + let A = Matrix(3, 2, [| 4.0; 1.0; + 2.0; 3.0; + 6.0; 5.0 |]) + let R = Matrix.copy A + let x = Matrix.getCol 0 R |> Vector.sub 0 + + let h = Householder.create x + Householder.applyLeft(h, R, 0) + + // After application, first column should be [beta, 0, 0] + Expect.floatClose Accuracy.high R.[1,0] 0.0 "R[1,0] should be zero" + Expect.floatClose Accuracy.high R.[2,0] 0.0 "R[2,0] should be zero" + + // Check tau and beta match known values (approximate) + let expectedBeta = sqrt (4.0**2 + 2.0**2 + 6.0**2) // ||x|| + Expect.floatClose Accuracy.high (float h.Beta) expectedBeta "Beta should match norm" + Expect.isTrue (float h.Tau > 0.0 && float h.Tau < 2.0) "Tau should be in (0, 2)" + } + + test "Householder reflection zeros subcolumn (2x2 matrix)" { + let A = Matrix(2, 2, [| 3.0; 1.0; + 4.0; 5.0 |]) + let R = Matrix.copy A + let x = Matrix.getCol 0 R |> Vector.sub 0 + + let h = Householder.create x + Householder.applyLeft(h, R, 0) + + Expect.floatClose Accuracy.high R.[1,0] 0.0 "R[1,0] should be zero" + let expectedBeta = sqrt (3.0**2 + 4.0**2) + Expect.floatClose Accuracy.high (float h.Beta) expectedBeta "Beta should match norm" + } + + test "Tau and v correctness on a known input" { + let x = [| 3.0; 4.0 |] + let h = Householder.create x + + // We expect: + // - v[0] = 1 + // - v[1] = (4 / v0), since we normalize the vector to have v[0] = 1 + // - tau e (0, 2), beta = ||x|| + Expect.equal h.V.[0] 1.0 "v[0] should be 1.0" + Expect.isTrue (float h.Tau > 0.0 && float h.Tau < 2.0) "Tau should be reasonable" + Expect.floatClose Accuracy.high (float h.Beta) 5.0 "Beta should be ||x|| = 5.0" + } + + test "Degenerate vector returns trivial Householder" { + let x = [| 0.0; 0.0; 0.0 |] + let h = Householder.create x + Expect.equal h.Tau 0.0 "Tau should be 0.0" + Expect.equal h.Beta 0.0 "Beta should be 0.0" + Expect.sequenceEqual h.V [| 1.0; 0.0; 0.0 |] "v should be unit vector" + } + + ] + + + + +[] +let subScaledRowInPlaceTests = + testList "subScaledRowInPlace" [ + + test "Basic subtraction (no offset)" { + let dst = [| 10.0; 20.0; 30.0 |] + let src = [| 1.0; 2.0; 3.0 |] + LinearAlgebra.subScaledRowInPlace 2.0 0 0 3 dst src + let expected = [| 8.0; 16.0; 24.0 |] + Expect.sequenceEqual dst expected "Subtraction incorrect" + } + + test "With dst and src offset" { + let dst = [| 0.0; 10.0; 20.0; 30.0; 0.0 |] + let src = [| 0.0; 1.0; 2.0; 3.0; 0.0 |] + // Subtract 2src[1..3] from dst[1..3] + LinearAlgebra.subScaledRowInPlace 2.0 1 1 3 dst src + let expected = [| 0.0; 8.0; 16.0; 24.0; 0.0 |] + Expect.sequenceEqual dst expected "Offset subtraction incorrect" + } + + test "Single element (scalar fallback)" { + let dst = [| 42.0 |] + let src = [| 2.0 |] + LinearAlgebra.subScaledRowInPlace 3.0 0 0 1 dst src + let expected = [| 36.0 |] + Expect.sequenceEqual dst expected "Scalar fallback incorrect" + } + + test "No modification outside range" { + let dst = [| 1.0; 2.0; 3.0; 4.0 |] + let src = [| 0.0; 1.0; 1.0; 0.0 |] + LinearAlgebra.subScaledRowInPlace 2.0 1 1 2 dst src + let expected = [| 1.0; 0.0; 1.0; 4.0 |] + Expect.sequenceEqual dst expected "Boundary elements modified" + } + + test "basic 3-element row subtraction" { + let dst = [| 1.0; 2.0; 3.0 |] + let src = [| 4.0; 5.0; 6.0 |] + let alpha = 2.0 + let expected = [| -7.0; -8.0; -9.0 |] + + LinearAlgebra.subScaledRowInPlace alpha 0 0 3 dst src + + Expect.sequenceEqual dst expected "Result should be elementwise dst - alpha * src" + } + + test "offsets respected correctly" { + let dst = [| 0.0; 1.0; 2.0; 3.0; 4.0 |] + let src = [| 0.0; 0.0; 1.0; 2.0; 3.0 |] + let alpha = 2.0 + let expected = [| 0.0; 1.0; 0.0; -1.0; -2.0 |] + + // Only update dst[2..4] = [2.0; 3.0; 4.0] with src[2..4] = [1.0; 2.0; 3.0] + LinearAlgebra.subScaledRowInPlace alpha 2 2 3 dst src + + Expect.sequenceEqual dst expected "Offsets should target the correct subarrays" + } + + ] + +[] +let qrDecompositionTests = + testList "QR Decomposition (Modified Gram-Schmidt)" [ + + test "Decompose identity matrix" { + let A = Matrix.identity 3 + let Q, R = LinearAlgebra.qrModifiedGramSchmidt A + let I = Matrix.identity 3 + TestExtensions.floatMatrixClose Accuracy.high Q I "Q should be identity" + TestExtensions.floatMatrixClose Accuracy.high R I "R should be identity" + } + + test "Reconstruct original matrix from Q * R" { + let A = Matrix(3, 2, [| 1.0; 0.0; + 1.0; 1.0; + 0.0; 1.0 |]) + let Q, R = LinearAlgebra.qrModifiedGramSchmidt A + let QR = Matrix.matmul Q R + TestExtensions.floatMatrixClose Accuracy.high QR A "Q * R should reconstruct A" + } + + test "Q has orthonormal columns" { + let A = Matrix(3, 2, [| 1.0; 0.0; + 1.0; 1.0; + 0.0; 1.0 |]) + let Q, _ = LinearAlgebra.qrModifiedGramSchmidt A + let QTQ = Matrix.matmul (Matrix.transpose Q) Q + let I = Matrix.identity 2 + TestExtensions.floatMatrixClose Accuracy.high QTQ I "Q^TQ should be identity" + } + + test "R is upper triangular" { + let A = Matrix(3, 2, [| 1.0; 0.0; + 1.0; 1.0; + 0.0; 1.0 |]) + let _, R = LinearAlgebra.qrModifiedGramSchmidt A + for i in 0 .. R.NumRows - 1 do + for j in 0 .. i - 1 do + Expect.floatClose Accuracy.high R.[i, j] 0.0 $"R[{i},{j}] should be zero" + } + + test "Tall matrix 4x2 decomposition" { + let A = Matrix(4, 2, [| 1.0; 2.0; + 3.0; 4.0; + 5.0; 6.0; + 7.0; 8.0 |]) + let Q, R = LinearAlgebra.qrModifiedGramSchmidt A + let QR = Matrix.matmul Q R + TestExtensions.floatMatrixClose Accuracy.medium QR A "QR ~ A for tall matrix" + } + + test "Wide matrix throws or truncates" { + let A = Matrix(2, 3, [| 1.0; 2.0; 3.0; + 4.0; 5.0; 6.0 |]) + Expect.throws (fun () -> LinearAlgebra.qrModifiedGramSchmidt A |> ignore) + "Wide matrices are not supported (m < n)" + } + ] + +[] +let backSubstituteTests = + testList "Back substitution tests" [ + + test "Solve simple upper triangular system" { + // R = [2 1] + // [0 3] + let r = Matrix(2, 2, [| 2.0; 1.0; + 0.0; 3.0 |]) + let y = [| 5.0; 6.0 |] + let x = LinearAlgebra. backSubstitute r y + // Solve: 3x1 = 6 -> x1 = 2 + // Then: 2x0 + x1 = 5 -> x0 = (5 - 1*2)/2 = 1.5 + let expected = [| 1.5; 2.0 |] + for i in 0..1 do + Expect.floatClose Accuracy.high x.[i] expected.[i] $"x[{i}] incorrect" + } + + test "Identity matrix returns y as solution" { + let r = Matrix.identity 3 + let y = [| 4.0; -2.0; 0.5 |] + let x = LinearAlgebra.backSubstitute r y + Expect.sequenceEqual x y "Identity matrix should return y = x" + } + + test "Upper triangular with zeros below diagonal" { + // R = [1 2 3] + // [0 4 5] + // [0 0 6] + let r = Matrix(3, 3, [| 1.0; 2.0; 3.0; + 0.0; 4.0; 5.0; + 0.0; 0.0; 6.0 |]) + let y = [| 14.0; 23.0; 18.0 |] + let x = LinearAlgebra.backSubstitute r y + let expected = [| 1.0; 2.0; 3.0 |] + for i in 0..2 do + Expect.floatClose Accuracy.high x.[i] expected.[i] $"x[{i}] incorrect" + } + + test "Throws on non-square R" { + let r = Matrix(2, 3, [| 1.0; 2.0; 3.0; + 0.0; 4.0; 5.0 |]) + let y = [| 1.0; 2.0 |] + Expect.throws (fun () -> LinearAlgebra.backSubstitute r y |> ignore) + "Should throw on non-square R" + } + + test "Throws on mismatched dimensions with y" { + let r = Matrix.identity 3 + let y = [| 1.0; 2.0 |] + Expect.throws (fun () -> LinearAlgebra.backSubstitute r y |> ignore) + "Should throw on mismatched y length" + } + + test "Throws on zero diagonal entry (division by zero)" { + let r = Matrix(2, 2, [| 0.0; 1.0; + 0.0; 2.0 |]) + let y = [| 3.0; 4.0 |] + Expect.throws (fun () -> LinearAlgebra.backSubstitute r y |> ignore) + "Should throw on division by zero" + } + ] + +// solveLinearQR +// solveTriangularLinearSystems + + +[] +let solveTriangularLinearSystemTests = + testList "solveTriangularLinearSystem tests" [ + + test "Solve L x = b (lower triangular)" { + // L = [1 0 0; 2 1 0; 3 4 1] + let L = Matrix(3, 3, [| 1.0; 0.0; 0.0; + 2.0; 1.0; 0.0; + 3.0; 4.0; 1.0 |]) + let b = [| 2.0; 5.0; 20.0 |] + let x = LinearAlgebra.solveTriangularLinearSystem L b true + // Solve: Lx = b -> x = [2; 1; 5] + let expected = [| 2.0; 1.0; 10.0 |] + for i in 0..2 do + Expect.floatClose Accuracy.high x.[i] expected.[i] $"x[{i}] incorrect" + } + + test "Solve L^T x = b (upper triangular)" { + // L = [1 0 0; 2 1 0; 3 4 1] + // L^T = [1 2 3; 0 1 4; 0 0 1] + let L = Matrix(3, 3, [| 1.0; 0.0; 0.0; + 2.0; 1.0; 0.0; + 3.0; 4.0; 1.0 |]) + + let b = [| 23.0; 9.0; 1.0 |] + let LT = Matrix.transpose L + let x = LinearAlgebra.solveTriangularLinearSystem LT b false + // Solve L^T x = b -> x = [1; 2; 1] + let expected = [| 10.0; 5.0; 1.0 |] + for i in 0..2 do + Expect.floatClose Accuracy.high x.[i] expected.[i] $"x[{i}] incorrect" + } + + test "Throws on mismatched dimensions" { + let L = Matrix.identity 3 + let b = [| 1.0; 2.0 |] + Expect.throws (fun () -> LinearAlgebra.solveTriangularLinearSystem L b true |> ignore) + "Should throw if dimensions don't match" + } + + test "Throws on zero diagonal (division by zero)" { + let L = Matrix(2, 2, [| 0.0; 0.0; + 1.0; 1.0 |]) + let b = [| 1.0; 2.0 |] + Expect.throws (fun () -> LinearAlgebra.solveTriangularLinearSystem L b true |> ignore) + "Should throw on division by zero" + } + ] + +[] +let qrTests = + testList "QR decomposition via Householder" [ + + test "Q * R reconstructs A" { + let A = Matrix(3, 2, [| 1.0; 1.0; + 1.0; 2.0; + 1.0; 3.0 |]) + let Q, R = LinearAlgebra.qrDecompose A + let QR = Matrix.matmul Q R + TestExtensions.floatMatrixClose Accuracy.high QR A "QR ~ A" + } + + test "Q is orthogonal: Q^TQ = I" { + let A = Matrix(3, 2, [| 1.0; 0.0; + 1.0; 1.0; + 1.0; 2.0 |]) + let Q, _ = LinearAlgebra.qrDecompose A + let QtQ = Matrix.matmul (Matrix.transpose Q) Q + let I = Matrix.identity Q.NumCols + TestExtensions.floatMatrixClose Accuracy.high QtQ I "Q^TQ ~ I" + } + + test "R is upper triangular" { + let A = Matrix(3, 2, [| 1.0; 0.0; + 2.0; 1.0; + 3.0; 2.0 |]) + let _, R = LinearAlgebra.qrDecompose A + for i = 0 to R.NumRows - 1 do + for j = 0 to i - 1 do + Expect.floatClose Accuracy.veryHigh R.[i,j] 0.0 $"R[{i},{j}] should be zero" + } + + test "QR of square matrix" { + let A = Matrix(3, 3, [| 1.0; 2.0; 3.0; + 4.0; 5.0; 6.0; + 7.0; 8.0; 9.0 |]) + let Q, R = LinearAlgebra.qrDecompose A + let QR = Q * R + TestExtensions.floatMatrixClose Accuracy.medium QR A "QR ~ A" + } + + test "QR of small square matrix" { + let A = Matrix(2, 2, [| 2.0; 1.0; + 1.0; 3.0 |]) + let Q, R = LinearAlgebra.qrDecompose A + let QR = Q * R + TestExtensions.floatMatrixClose Accuracy.medium QR A "QR ~ A" + } + + ] + +[] +let leastSquaresQRTests = + testList "Least squares (QR-based)" [ + + test "Overdetermined 3x2 system" { + let A = Matrix(3, 2, [| 1.0; 1.0; + 1.0; 2.0; + 1.0; 3.0 |]) + let b = [| 6.0; 0.0; 0.0 |] + let x = LinearAlgebra.leastSquares A b + let expected = [| 8.0; -3.0 |] + for i in 0..1 do + Expect.floatClose Accuracy.medium x.[i] expected.[i] $"x[{i}] incorrect" + } + + test "Underdetermined 2x3 system (minimum norm)" { + let A = Matrix(2, 3, [| 1.0; 2.0; 0.0; + 0.0; 1.0; 1.0 |]) + let b = [| 3.0; 2.0 |] + let x = LinearAlgebra.leastSquares A b + + // There are infinite solutions, but least norm solution is: + // min ||x|| such that Ax = b + // numpy gives: [0.33333333, 1.33333333, 0.66666667] + let expected = [| 0.33333333; 1.33333333; 0.66666667 |] + for i in 0..2 do + Expect.floatClose Accuracy.medium x.[i] expected.[i] $"x[{i}] incorrect" + } + + test "Square system returns exact solution" { + let A = Matrix(2, 2, [| 2.0; 1.0; + 1.0; 3.0 |]) + let b = [| 5.0; 10.0 |] + let x = LinearAlgebra.leastSquares A b + let expected = [| 1.0; 3.0 |] + for i in 0..1 do + Expect.floatClose Accuracy.high x.[i] expected.[i] $"x[{i}] incorrect" + } + + test "Residual Ax ~ projection of b" { + let A = Matrix(3, 2, [| 1.0; 1.0; + 1.0; 2.0; + 1.0; 3.0 |]) + let b = [| 6.0; 0.0; 0.0 |] + let x = LinearAlgebra.leastSquares A b + let Ax = Matrix.muliplyVector A x + let expected = [| 5.0; 2.0; -1.0 |] + for i in 0..2 do + Expect.floatClose Accuracy.medium Ax.[i] expected.[i] $"Ax[{i}] incorrect" + } + ] + + +[] +let choleskyTests = + testList "Cholesky decomposition tests" [ + + test "Decompose identity matrix" { + let I = Matrix.identity 3 + let L = LinearAlgebra.cholesky I + TestExtensions.floatMatrixClose Accuracy.high L I "L should be identity for identity input" + } + + test "Decompose known positive-definite matrix" { + // A = [4 2; 2 3] -> L = [2 0; 1 1.4142] + let A = Matrix(2, 2, [| 4.0; 2.0; + 2.0; 3.0 |]) + let L = LinearAlgebra.cholesky A + let expected = Matrix(2, 2, [| 2.0; 0.0; + 1.0; sqrt 2.0 |]) + for i in 0..1 do + for j in 0..1 do + Expect.floatClose Accuracy.medium L.[i,j] expected.[i,j] $"L[{i},{j}] incorrect" + } + + test "Reconstruct A from L * L^T" { + let A = Matrix(3, 3, [| 25.0; 15.0; -5.0; + 15.0; 18.0; 0.0; + -5.0; 0.0; 11.0 |]) + let L = LinearAlgebra.cholesky A + let LT = Matrix.transpose L + let reconstructed = Matrix.matmul L LT + TestExtensions.floatMatrixClose Accuracy.high reconstructed A "Reconstructed A <> original" + } + test "Throws on non-positive-definite matrix" { + // Not positive-definite: eigenvalues are [1, -1] + let A = Matrix(2, 2, [| 0.0; 1.0; + 1.0; 0.0 |]) + Expect.throws (fun () -> LinearAlgebra.cholesky A |> ignore) + "Should throw on non-positive-definite matrix" + } + + test "Throws on non-square matrix" { + let A = Matrix(2, 3, [| 1.0; 2.0; 3.0; + 2.0; 5.0; 6.0 |]) + Expect.throws (fun () -> LinearAlgebra.cholesky A |> ignore) + "Should throw on non-square matrix" + } + + test "Zero matrix throws (not positive-definite)" { + let A : Matrix = Matrix.zeroCreate 3 3 + Expect.throws (fun () -> LinearAlgebra.cholesky A |> ignore) + "Should throw on zero matrix" + } + + ] + +[] +let leastSquaresTests = + testList "Least Squares via Cholesky" [ + + test "Solve overdetermined 3x2 system" { + // A = [1 1; 1 2; 1 3], b = [6; 0; 0] + // Should find least-squares fit: beta = [8.0; -3.0] + let A = Matrix(3, 2, [| 1.0; 1.0; + 1.0; 2.0; + 1.0; 3.0 |]) + let b = [| 6.0; 0.0; 0.0 |] + let beta = LinearAlgebra.leastSquaresCholesky A b + let expected = [| 8.0; -3.0 |] + for i in 0..1 do + Expect.floatClose Accuracy.medium beta.[i] expected.[i] $"beta[{i}] incorrect" + } + + test "Reconstruction A * beta ~ projection of b" { + // Same setup as above + let A = Matrix(3, 2, [| 1.0; 1.0; + 1.0; 2.0; + 1.0; 3.0 |]) + let b = [| 6.0; 0.0; 0.0 |] + let beta = LinearAlgebra.leastSquaresCholesky A b + let predicted = Matrix.muliplyVector A beta + // Expected projection of b onto Col(A): A * (A' b) + let expected = [| 5.0; 2.0; -1.0 |] + for i in 0..2 do + Expect.floatClose Accuracy.medium predicted.[i] expected.[i] $"predicted[{i}] incorrect" + } + + test "Throws on dimension mismatch A and b" { + let A = Matrix.identity 3 + let b = [| 1.0; 2.0 |] + Expect.throws (fun () -> LinearAlgebra.leastSquaresCholesky A b |> ignore) + "Should throw if A.NumRows <> b.Length" + } + + test "Exact solution when A is square and full-rank" { + let A = Matrix(2, 2, [| 2.0; 1.0; + 1.0; 3.0 |]) + let b = [| 5.0; 10.0 |] + let beta = LinearAlgebra.leastSquaresCholesky A b + let expected = [| 1.0; 3.0 |] + for i in 0..1 do + Expect.floatClose Accuracy.high beta.[i] expected.[i] $"beta[{i}] incorrect" + } + + ] + + + +// hatMatrix +// leverageBy +// leverage +// luDecompose +// solveLinearSystems (LU) +// solveLinearSystem (LU) + + + + + + + + + [] let managedSVDTests = diff --git a/tests/FSharp.Stats.Tests/TestExtensions.fs b/tests/FSharp.Stats.Tests/TestExtensions.fs index f427bc5f8..4d917f9e6 100644 --- a/tests/FSharp.Stats.Tests/TestExtensions.fs +++ b/tests/FSharp.Stats.Tests/TestExtensions.fs @@ -37,6 +37,13 @@ actual expected + static member floatMatrixClose accuracy (A: Matrix) (B: Matrix) message = + Expect.equal A.NumCols B.NumCols "Column count mismatch" + Expect.equal A.NumRows B.NumRows "Row count mismatch" + for i = 0 to A.NumRows - 1 do + for j = 0 to A.NumCols - 1 do + Expect.floatClose accuracy A.[i, j] B.[i, j] $"{message} at ({i},{j})" + let assembly = Assembly.GetExecutingAssembly() let resnames = assembly.GetManifestResourceNames(); let readEmbeddedRessource (name:string) = From 4a71736e58094c371b4bb97ad323cab75e91900b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20M=C3=BChlhaus?= Date: Fri, 8 Aug 2025 13:11:00 +0200 Subject: [PATCH 046/121] Refactoring towards FsMath dependency --- FSharp.Stats.sln | 3 - benchmarks/FSharp.Stats.Benchmarks/Matrix.fs | 2 + .../TriangularSolver.fs | 3 +- benchmarks/FSharp.Stats.Benchmarks/Vector.fs | 7 +- docs/BasicStats.fsx | 3 +- docs/Clustering.fsx | 3 +- docs/ComparisonMetrics.fsx | 2 + docs/Correlation.fsx | 2 + docs/Covariance.fsx | 2 + docs/CrossValidation.fsx | 2 + docs/Differentiation.fsx | 2 + docs/Distributions.fsx | 2 + docs/Fitting.fsx | 2 + docs/GoodnessOfFit.fsx | 2 + docs/GrowthCurve.fsx | 2 + docs/Imputation.fsx | 4 + docs/Integration.fsx | 2 + docs/Interpolation.fsx | 2 + docs/Intervals.fsx | 2 + docs/LinearAlgebra.fsx | 74 - docs/ML.fsx | 122 -- docs/Matrix_Vector.fsx | 290 ---- docs/Normalization.fsx | 2 + docs/Optimization.fsx | 2 + docs/Quantiles.fsx | 2 + docs/Rank.fsx | 2 + docs/Signal.fsx | 2 + docs/Testing.fsx | 2 + docs/index.fsx | 2 + .../AlgTypes/AlgTypesTopLevelOps.fs | 9 - src/FSharp.Stats/AlgTypes/GenericMath.fs | 73 - src/FSharp.Stats/AlgTypes/Householder.fs | 126 -- src/FSharp.Stats/AlgTypes/Matrix.fs | 923 ---------- src/FSharp.Stats/AlgTypes/MatrixExt.fs | 212 --- src/FSharp.Stats/AlgTypes/SIMDUtils.fs | 445 ----- src/FSharp.Stats/AlgTypes/Vector.fs | 266 --- src/FSharp.Stats/AlgTypes/VectorExt.fs | 226 --- src/FSharp.Stats/AlgTypes/VectorOps.fs | 54 - src/FSharp.Stats/Algebra/EVD.fs | 257 --- src/FSharp.Stats/Algebra/LinearAlgebra.fs | 806 --------- src/FSharp.Stats/Algebra/SVD.fs | 567 ------ src/FSharp.Stats/Correlation.fs | 3 + src/FSharp.Stats/DistanceMetrics.fs | 2 + .../Continuous/MultivariateNormal.fs | 6 +- .../Distributions/Discrete/Geometric.fs | 3 +- .../Distributions/Discrete/Multinomial.fs | 2 + .../Distributions/Distribution.fs | 2 + src/FSharp.Stats/FSIPrinters.fs | 1 + src/FSharp.Stats/FSharp.Stats.fsproj | 21 +- src/FSharp.Stats/Fitting/CrossValidation.fs | 2 + src/FSharp.Stats/Fitting/GoodnessOfFit.fs | 3 + src/FSharp.Stats/Fitting/LinearRegression.fs | 3 +- .../Fitting/LogisticRegression.fs | 1 + .../Fitting/NonLinearRegression.fs | 5 +- src/FSharp.Stats/Fitting/Spline.fs | 3 +- src/FSharp.Stats/Interpolation.fs | 3 +- src/FSharp.Stats/ML/DistanceMetrics.fs | 2 + .../ML/Unsupervised/ClusterNumber.fs | 2 + .../ML/Unsupervised/IterativeClustering.fs | 1 + src/FSharp.Stats/Optimization/NelderMead.fs | 3 +- src/FSharp.Stats/Signal/Baseline.fs | 2 +- src/FSharp.Stats/Signal/Convolution.fs | 2 +- src/FSharp.Stats/Signal/Filtering.fs | 3 +- src/FSharp.Stats/Signal/Normalization.fs | 1 + src/FSharp.Stats/Signal/Outliers.fs | 2 +- src/FSharp.Stats/Signal/PeakDetection.fs | 3 +- src/FSharp.Stats/Signal/QQPlot.fs | 2 + src/FSharp.Stats/Table.fs | 5 +- src/FSharp.Stats/Testing/ConfusionMatrix.fs | 2 + src/FSharp.Stats/Testing/ContingencyTable.fs | 2 +- src/FSharp.Stats/Testing/FTest.fs | 2 + src/FSharp.Stats/Testing/PostHoc.fs | 1 + src/FSharp.Stats/Testing/RMT.fs | 2 + src/FSharp.Stats/Testing/TTest.fs | 1 + src/FSharp.Stats/Testing/Tables.fs | 2 + tests/FSharp.Stats.Tests/Acceleration.fs | 49 - tests/FSharp.Stats.Tests/DistanceMetrics.fs | 1 + .../DistributionsContinuous.fs | 1 + .../FSharp.Stats.Tests.fsproj | 5 - tests/FSharp.Stats.Tests/Fitting.fs | 2 +- tests/FSharp.Stats.Tests/Interpolation.fs | 1 + tests/FSharp.Stats.Tests/LinAlgebra.fs | 529 ------ tests/FSharp.Stats.Tests/LinearAlgebra.fs | 1518 ----------------- tests/FSharp.Stats.Tests/Matrix.fs | 309 ---- tests/FSharp.Stats.Tests/Optimization.fs | 1 + tests/FSharp.Stats.Tests/RowVector.fs | 28 - tests/FSharp.Stats.Tests/SVD.fs | 205 --- tests/FSharp.Stats.Tests/TestExtensions.fs | 1 + tests/FSharp.Stats.Tests/Testing.fs | 5 +- tests/FSharp.Stats.Tests/Vector.fs | 605 ------- 90 files changed, 134 insertions(+), 7739 deletions(-) delete mode 100644 docs/LinearAlgebra.fsx delete mode 100644 docs/ML.fsx delete mode 100644 docs/Matrix_Vector.fsx delete mode 100644 src/FSharp.Stats/AlgTypes/AlgTypesTopLevelOps.fs delete mode 100644 src/FSharp.Stats/AlgTypes/GenericMath.fs delete mode 100644 src/FSharp.Stats/AlgTypes/Householder.fs delete mode 100644 src/FSharp.Stats/AlgTypes/Matrix.fs delete mode 100644 src/FSharp.Stats/AlgTypes/MatrixExt.fs delete mode 100644 src/FSharp.Stats/AlgTypes/SIMDUtils.fs delete mode 100644 src/FSharp.Stats/AlgTypes/Vector.fs delete mode 100644 src/FSharp.Stats/AlgTypes/VectorExt.fs delete mode 100644 src/FSharp.Stats/AlgTypes/VectorOps.fs delete mode 100644 src/FSharp.Stats/Algebra/EVD.fs delete mode 100644 src/FSharp.Stats/Algebra/LinearAlgebra.fs delete mode 100644 src/FSharp.Stats/Algebra/SVD.fs delete mode 100644 tests/FSharp.Stats.Tests/Acceleration.fs delete mode 100644 tests/FSharp.Stats.Tests/LinAlgebra.fs delete mode 100644 tests/FSharp.Stats.Tests/LinearAlgebra.fs delete mode 100644 tests/FSharp.Stats.Tests/Matrix.fs delete mode 100644 tests/FSharp.Stats.Tests/RowVector.fs delete mode 100644 tests/FSharp.Stats.Tests/SVD.fs delete mode 100644 tests/FSharp.Stats.Tests/Vector.fs diff --git a/FSharp.Stats.sln b/FSharp.Stats.sln index f70606d2f..2c18d0e23 100644 --- a/FSharp.Stats.sln +++ b/FSharp.Stats.sln @@ -55,9 +55,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "docs", "docs", "{23F9FB2E-6 docs\Integration.fsx = docs\Integration.fsx docs\Interpolation.fsx = docs\Interpolation.fsx docs\Intervals.fsx = docs\Intervals.fsx - docs\LinearAlgebra.fsx = docs\LinearAlgebra.fsx - docs\Matrix_Vector.fsx = docs\Matrix_Vector.fsx - docs\ML.fsx = docs\ML.fsx docs\Normalization.fsx = docs\Normalization.fsx docs\NuGet.config = docs\NuGet.config docs\Optimization.fsx = docs\Optimization.fsx diff --git a/benchmarks/FSharp.Stats.Benchmarks/Matrix.fs b/benchmarks/FSharp.Stats.Benchmarks/Matrix.fs index 516becad8..cab6c1a95 100644 --- a/benchmarks/FSharp.Stats.Benchmarks/Matrix.fs +++ b/benchmarks/FSharp.Stats.Benchmarks/Matrix.fs @@ -4,6 +4,8 @@ open System open BenchmarkDotNet.Attributes open BenchmarkDotNet.Running open FSharp.Stats +open FsMath +open FsMath.Algebra [] type MatrixBenchmarks() = diff --git a/benchmarks/FSharp.Stats.Benchmarks/TriangularSolver.fs b/benchmarks/FSharp.Stats.Benchmarks/TriangularSolver.fs index 6513e7d97..e71072935 100644 --- a/benchmarks/FSharp.Stats.Benchmarks/TriangularSolver.fs +++ b/benchmarks/FSharp.Stats.Benchmarks/TriangularSolver.fs @@ -4,7 +4,8 @@ open System open BenchmarkDotNet.Attributes open BenchmarkDotNet.Running open FSharp.Stats -open FSharp.Stats.Algebra +open FsMath +open FsMath.Algebra [] type TriangularBenchmark() = diff --git a/benchmarks/FSharp.Stats.Benchmarks/Vector.fs b/benchmarks/FSharp.Stats.Benchmarks/Vector.fs index b72d29d5f..6276b5dd5 100644 --- a/benchmarks/FSharp.Stats.Benchmarks/Vector.fs +++ b/benchmarks/FSharp.Stats.Benchmarks/Vector.fs @@ -5,6 +5,8 @@ open System open BenchmarkDotNet.Attributes open BenchmarkDotNet.Running open FSharp.Stats +open FsMath + [] type VectorBenchmarks() = @@ -36,11 +38,6 @@ type VectorBenchmarks() = let result = Vector.dot vector1 vector2 GC.KeepAlive(result) // Prevents the result from being optimized away - [] - member _.CrossProduct() = - let result = Vector.cross vector1 vector2 - GC.KeepAlive(result) // Prevents the result from being optimized away - [] member _.Norm() = let result = Vector.norm vector1 diff --git a/docs/BasicStats.fsx b/docs/BasicStats.fsx index 34cacd0c2..e03c4106f 100644 --- a/docs/BasicStats.fsx +++ b/docs/BasicStats.fsx @@ -11,7 +11,8 @@ categoryindex: 0 (*** condition: prepare ***) #r "../src/FSharp.Stats/bin/Release/netstandard2.0/FSharp.Stats.dll" - +#r "nuget: FsMath, 0.0.1" +open FsMath (*** condition: ipynb ***) #if IPYNB #r "nuget: FSharp.Stats" diff --git a/docs/Clustering.fsx b/docs/Clustering.fsx index d20ebea16..4491a7d73 100644 --- a/docs/Clustering.fsx +++ b/docs/Clustering.fsx @@ -16,7 +16,8 @@ categoryindex: 0 #r "nuget: FSharpAux, 1.0.0" #r "nuget: Cyjs.NET" #r "nuget: OptimizedPriorityQueue, 5.1.0" - +#r "nuget: FsMath, 0.0.1" +open FsMath Plotly.NET.Defaults.DefaultDisplayOptions <- Plotly.NET.DisplayOptions.init (PlotlyJSReference = Plotly.NET.PlotlyJSReference.NoReference) diff --git a/docs/ComparisonMetrics.fsx b/docs/ComparisonMetrics.fsx index a95d0b8b9..9920c443f 100644 --- a/docs/ComparisonMetrics.fsx +++ b/docs/ComparisonMetrics.fsx @@ -13,6 +13,8 @@ categoryindex: 0 #I "../src/FSharp.Stats/bin/Release/netstandard2.0/" #r "FSharp.Stats.dll" #r "nuget: Plotly.NET, 4.0.0" +#r "nuget: FsMath, 0.0.1" +open FsMath Plotly.NET.Defaults.DefaultDisplayOptions <- Plotly.NET.DisplayOptions.init (PlotlyJSReference = Plotly.NET.PlotlyJSReference.NoReference) diff --git a/docs/Correlation.fsx b/docs/Correlation.fsx index 3b22549dd..cbaddadd8 100644 --- a/docs/Correlation.fsx +++ b/docs/Correlation.fsx @@ -13,6 +13,8 @@ categoryindex: 0 #I "../src/FSharp.Stats/bin/Release/netstandard2.0/" #r "FSharp.Stats.dll" #r "nuget: Plotly.NET, 4.0.0" +#r "nuget: FsMath, 0.0.1" +open FsMath Plotly.NET.Defaults.DefaultDisplayOptions <- Plotly.NET.DisplayOptions.init (PlotlyJSReference = Plotly.NET.PlotlyJSReference.NoReference) diff --git a/docs/Covariance.fsx b/docs/Covariance.fsx index 18007f55f..41b35d0d6 100644 --- a/docs/Covariance.fsx +++ b/docs/Covariance.fsx @@ -13,6 +13,8 @@ categoryindex: 0 #I "../src/FSharp.Stats/bin/Release/netstandard2.0/" #r "FSharp.Stats.dll" #r "nuget: Plotly.NET, 4.0.0" +#r "nuget: FsMath, 0.0.1" +open FsMath Plotly.NET.Defaults.DefaultDisplayOptions <- Plotly.NET.DisplayOptions.init (PlotlyJSReference = Plotly.NET.PlotlyJSReference.NoReference) diff --git a/docs/CrossValidation.fsx b/docs/CrossValidation.fsx index 566b7dd8c..f78da9e08 100644 --- a/docs/CrossValidation.fsx +++ b/docs/CrossValidation.fsx @@ -14,6 +14,8 @@ categoryindex: 0 #I "../src/FSharp.Stats/bin/Release/netstandard2.0/" #r "FSharp.Stats.dll" #r "nuget: Plotly.NET, 4.0.0" +#r "nuget: FsMath, 0.0.1" +open FsMath Plotly.NET.Defaults.DefaultDisplayOptions <- Plotly.NET.DisplayOptions.init (PlotlyJSReference = Plotly.NET.PlotlyJSReference.NoReference) diff --git a/docs/Differentiation.fsx b/docs/Differentiation.fsx index e393ee430..25eda0fb4 100644 --- a/docs/Differentiation.fsx +++ b/docs/Differentiation.fsx @@ -13,6 +13,8 @@ categoryindex: 0 #I "../src/FSharp.Stats/bin/Release/netstandard2.0/" #r "FSharp.Stats.dll" #r "nuget: Plotly.NET, 4.0.0" +#r "nuget: FsMath, 0.0.1" +open FsMath Plotly.NET.Defaults.DefaultDisplayOptions <- Plotly.NET.DisplayOptions.init (PlotlyJSReference = Plotly.NET.PlotlyJSReference.NoReference) diff --git a/docs/Distributions.fsx b/docs/Distributions.fsx index 4eb559af4..5a631acd1 100644 --- a/docs/Distributions.fsx +++ b/docs/Distributions.fsx @@ -14,6 +14,8 @@ categoryindex: 0 #I "../src/FSharp.Stats/bin/Release/netstandard2.0/" #r "FSharp.Stats.dll" #r "nuget: Plotly.NET, 4.0.0" +#r "nuget: FsMath, 0.0.1" +open FsMath Plotly.NET.Defaults.DefaultDisplayOptions <- Plotly.NET.DisplayOptions.init (PlotlyJSReference = Plotly.NET.PlotlyJSReference.NoReference) diff --git a/docs/Fitting.fsx b/docs/Fitting.fsx index 7e79432d5..666aaf7e2 100644 --- a/docs/Fitting.fsx +++ b/docs/Fitting.fsx @@ -15,6 +15,8 @@ categoryindex: 0 #r "nuget: DynamicObj, 2.0.0" #r "nuget: Giraffe.ViewEngine, 1.4.0" #r "nuget: Plotly.NET, 4.0.0" +#r "nuget: FsMath, 0.0.1" +open FsMath Plotly.NET.Defaults.DefaultDisplayOptions <- Plotly.NET.DisplayOptions.init (PlotlyJSReference = Plotly.NET.PlotlyJSReference.NoReference) diff --git a/docs/GoodnessOfFit.fsx b/docs/GoodnessOfFit.fsx index 6331c49d0..307e2e733 100644 --- a/docs/GoodnessOfFit.fsx +++ b/docs/GoodnessOfFit.fsx @@ -13,6 +13,8 @@ categoryindex: 0 #I "../src/FSharp.Stats/bin/Release/netstandard2.0/" #r "FSharp.Stats.dll" #r "nuget: Plotly.NET, 4.0.0" +#r "nuget: FsMath, 0.0.1" +open FsMath Plotly.NET.Defaults.DefaultDisplayOptions <- Plotly.NET.DisplayOptions.init (PlotlyJSReference = Plotly.NET.PlotlyJSReference.NoReference) diff --git a/docs/GrowthCurve.fsx b/docs/GrowthCurve.fsx index fe22176ca..520fa5dfe 100644 --- a/docs/GrowthCurve.fsx +++ b/docs/GrowthCurve.fsx @@ -13,6 +13,8 @@ categoryindex: 0 #I "../src/FSharp.Stats/bin/Release/netstandard2.0/" #r "FSharp.Stats.dll" #r "nuget: Plotly.NET, 4.0.0" +#r "nuget: FsMath, 0.0.1" +open FsMath Plotly.NET.Defaults.DefaultDisplayOptions <- Plotly.NET.DisplayOptions.init (PlotlyJSReference = Plotly.NET.PlotlyJSReference.NoReference) diff --git a/docs/Imputation.fsx b/docs/Imputation.fsx index a33c29386..92b646902 100644 --- a/docs/Imputation.fsx +++ b/docs/Imputation.fsx @@ -13,6 +13,8 @@ categoryindex: 0 #I "../src/FSharp.Stats/bin/Release/netstandard2.0/" #r "FSharp.Stats.dll" #r "nuget: Plotly.NET, 4.0.0" +#r "nuget: FsMath, 0.0.1" +open FsMath Plotly.NET.Defaults.DefaultDisplayOptions <- Plotly.NET.DisplayOptions.init (PlotlyJSReference = Plotly.NET.PlotlyJSReference.NoReference) @@ -22,6 +24,8 @@ Plotly.NET.Defaults.DefaultDisplayOptions <- #r "nuget: Plotly.NET, 4.0.0" #r "nuget: Plotly.NET.Interactive, 4.0.0" #r "nuget: FSharp.Stats" +#r "nuget: FsMath, 0.0.1" +open FsMath open Plotly.NET #endif // IPYNB diff --git a/docs/Integration.fsx b/docs/Integration.fsx index 4615e5b53..2e201f0f0 100644 --- a/docs/Integration.fsx +++ b/docs/Integration.fsx @@ -13,6 +13,8 @@ categoryindex: 0 #I "../src/FSharp.Stats/bin/Release/netstandard2.0/" #r "FSharp.Stats.dll" #r "nuget: Plotly.NET, 4.0.0" +#r "nuget: FsMath, 0.0.1" +open FsMath Plotly.NET.Defaults.DefaultDisplayOptions <- Plotly.NET.DisplayOptions.init (PlotlyJSReference = Plotly.NET.PlotlyJSReference.NoReference) diff --git a/docs/Interpolation.fsx b/docs/Interpolation.fsx index 657cdf9f0..ddc4eb368 100644 --- a/docs/Interpolation.fsx +++ b/docs/Interpolation.fsx @@ -13,6 +13,8 @@ categoryindex: 0 #I "../src/FSharp.Stats/bin/Release/netstandard2.0/" #r "FSharp.Stats.dll" #r "nuget: Plotly.NET, 4.0.0" +#r "nuget: FsMath, 0.0.1" +open FsMath Plotly.NET.Defaults.DefaultDisplayOptions <- Plotly.NET.DisplayOptions.init (PlotlyJSReference = Plotly.NET.PlotlyJSReference.NoReference) diff --git a/docs/Intervals.fsx b/docs/Intervals.fsx index ec50b1e16..13e90c87f 100644 --- a/docs/Intervals.fsx +++ b/docs/Intervals.fsx @@ -13,6 +13,8 @@ categoryindex: 0 #I "../src/FSharp.Stats/bin/Release/netstandard2.0/" #r "FSharp.Stats.dll" #r "nuget: Plotly.NET, 4.0.0" +#r "nuget: FsMath, 0.0.1" +open FsMath Plotly.NET.Defaults.DefaultDisplayOptions <- Plotly.NET.DisplayOptions.init (PlotlyJSReference = Plotly.NET.PlotlyJSReference.NoReference) diff --git a/docs/LinearAlgebra.fsx b/docs/LinearAlgebra.fsx deleted file mode 100644 index b666e271a..000000000 --- a/docs/LinearAlgebra.fsx +++ /dev/null @@ -1,74 +0,0 @@ -(** ---- -title: Linear Algebra -index: 4 -category: Documentation -categoryindex: 0 ---- -*) - -(*** hide ***) - -(*** condition: prepare ***) -#I "../src/FSharp.Stats/bin/Release/netstandard2.0/" -#r "FSharp.Stats.dll" -#r "nuget: Plotly.NET, 4.0.0" - -Plotly.NET.Defaults.DefaultDisplayOptions <- - Plotly.NET.DisplayOptions.init (PlotlyJSReference = Plotly.NET.PlotlyJSReference.NoReference) - - -(*** condition: ipynb ***) -#if IPYNB -#r "nuget: Plotly.NET, 4.0.0" -#r "nuget: Plotly.NET.Interactive, 4.0.0" -#r "nuget: FSharp.Stats" - -open Plotly.NET -#endif // IPYNB - - -(** -# Linear Algebra - -Some algorithms such as SVD, EVD, or QR are implemented as a managed version in F# for a full list check the [API reference](https://fslab.org/FSharp.Stats/reference/fsharp-stats-algebra.html) -[![Notebook]({{root}}img/badge-notebook.svg)]({{root}}{{fsdocs-source-basename}}.ipynb) -*) - -open FSharp.Stats -open FSharp.Stats.Algebra - -let A = - matrix [ [ 1.0; 1.0; -1.0 ] - [ 1.0; -2.0; -3.0 ] - [ 2.0; 3.0; 1.0 ] ] - -let B = - matrix [ [ 4.0; ] - [ -6.0; ] - [ 7.0; ] ] - -let svdRes = LinearAlgebra.SVD A - -(***include-value:svdRes***) - -(** - -## Using unmanaged optimized linear algebra functions - -Additionally, we provide some bindings for [LAPACK]() routines. This is currently only tested on windows. - -**Attention**: These bindings are highly incomplete and will most likely be dropped for something like MKL.NET. [See issue#](https://github.com/fslaborg/FSharp.Stats/issues/91) - -the native libraries are contained in the nuget package at the `netlib_LAPACK` path. Include that one instead of the `/../../lib` pth used here. - -*) - -ServiceLocator.setEnvironmentPathVariable (__SOURCE_DIRECTORY__ + "/../../lib") //"D:/Source/FSharp.Stats/lib" - -// initialize the native service provider. This will search on many system paths for the needed binaries. -LinearAlgebra.Service() - -let svdResLapack = LinearAlgebra.SVD A - - diff --git a/docs/ML.fsx b/docs/ML.fsx deleted file mode 100644 index b98296be4..000000000 --- a/docs/ML.fsx +++ /dev/null @@ -1,122 +0,0 @@ -(** ---- -title: Machine Learning -index: 22 -category: Documentation -categoryindex: 0 ---- -*) - -(*** hide ***) - -(*** condition: prepare ***) -#I "../src/FSharp.Stats/bin/Release/netstandard2.0/" -#r "FSharp.Stats.dll" -#r "nuget: Plotly.NET, 4.0.0" - -Plotly.NET.Defaults.DefaultDisplayOptions <- - Plotly.NET.DisplayOptions.init (PlotlyJSReference = Plotly.NET.PlotlyJSReference.NoReference) - - -(*** condition: ipynb ***) -#if IPYNB -#r "nuget: Plotly.NET, 4.0.0" -#r "nuget: Plotly.NET.Interactive, 4.0.0" -#r "nuget: FSharp.Stats" - -open Plotly.NET -#endif // IPYNB - - -(** - -# Machine Learning - -[![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/fslaborg/FSharp.Stats/gh-pages?urlpath=/tree/home/jovyan/Signal.ipynb) -[![Notebook]({{root}}img/badge-notebook.svg)]({{root}}{{fsdocs-source-basename}}.ipynb) - -_Summary:_ this tutorial demonstrates functionality relevant in the context of machine learning. - -### Table of contents - - - [Dimensionality Reduction](#Dimensionality-Reduction) - - [PCA](#PCA) - -## Dimensionality Reduction - -### PCA - -A common approach for to reduce the dimensionality of large data sets is the use of Principal component analyis. - -*) -open Plotly.NET -open FSharp.Stats -open FSharp.Stats.ML.Unsupervised - -let data = - [ - [1.0; 2.0;1.0; 2.0;]; - [1.1; 2.1;1.1; 2.1;]; - [-1.0; -2.0;1.0; 2.0;]; - [-1.1; -2.1;1.1; 2.1;]; - [-1.15; -2.15;1.15; 2.15;]; - ] - |> FSharp.Stats.Matrix.ofJaggedList - -// The PCA implementation expects column wise centered data, which can be generated by calling: -let dc = PCA.center data - -// Calling compute will compute the PCA of the centered data matrix. Relevant information is stored in the result object. -let pca = PCA.compute dc - -// The result of the PCA allows to visualize the analyzed data set projected onto the principal axis: - -// extract components 1 and 2 -let pcs = pca.PrincipalComponents |> Matrix.mapiRows (fun i v -> v.[0],v.[1]) - -// typical PCA "score" plot of components 1 and 2 with the explained variance indicated -let scorePlot = - Chart.Point(pcs) - |> Chart.withTemplate ChartTemplates.lightMirrored - |> Chart.withXAxisStyle (sprintf "PC1, Var explained %f" pca.VarExplainedByComponentIndividual.[0]) - |> Chart.withYAxisStyle (sprintf "PC2, Var explained %f" pca.VarExplainedByComponentIndividual.[1]) - |> Chart.withTitle "Score Plot" - -(*** condition: ipynb ***) -#if IPYNB -scorePlot -#endif // IPYNB - -(***hide***) -scorePlot |> GenericChart.toChartHTML -(***include-it-raw***) - -// Additionally the variable loadings can be visualized: -// Disclaimer: there is a certain ambiguity when it comes to the use of the term loading. -// To stay consistent with other implementations the term loading is used. - -/// Extract loadings of the variables onto the first and second principal component -let loadings = - pca.Loadings - |> Matrix.mapRows (fun v -> v.[0],v.[1]) - - -// typical PCA "loading" plot -let loadingPlot = - loadings - |> Seq.map (fun l -> [0.,0.;l]) - |> Seq.map Chart.Line - |> Chart.combine - |> Chart.withTemplate ChartTemplates.lightMirrored - |> Chart.withXAxisStyle "PC1" - |> Chart.withYAxisStyle "PC2" - |> Chart.withTitle "Loading Plot" - -(*** condition: ipynb ***) -#if IPYNB -loadingPlot -#endif // IPYNB - -(***hide***) -loadingPlot |> GenericChart.toChartHTML -(***include-it-raw***) \ No newline at end of file diff --git a/docs/Matrix_Vector.fsx b/docs/Matrix_Vector.fsx deleted file mode 100644 index 6801bf291..000000000 --- a/docs/Matrix_Vector.fsx +++ /dev/null @@ -1,290 +0,0 @@ -(** ---- -title: Matrix and Vector -index: 3 -category: Documentation -categoryindex: 0 ---- -*) - - -(*** hide ***) - -(*** condition: prepare ***) -#I "../src/FSharp.Stats/bin/Release/netstandard2.0/" -#r "FSharp.Stats.dll" - -(*** condition: ipynb ***) -#if IPYNB -#r "nuget: FSharp.Stats" -#endif // IPYNB - -(** -# Matrix and Vector - -[![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/fslaborg/FSharp.Stats/gh-pages?urlpath=/tree/home/jovyan/Matrix_Vector.ipynb) -[![Notebook]({{root}}img/badge-notebook.svg)]({{root}}{{fsdocs-source-basename}}.ipynb) - -_Summary:_ this tutorial demonstrates some of the functionality for matrices and vectors provided by FSharp.Stats. - -## Vector -*) -open FSharp.Stats - -let v = - vector [|2.0; 20.0; 1.|] - -(*** include-value:v ***) - -let rv = - rowvec [|2.0; 20.0; 1.|] - -(*** include-value:rv ***) - -(***hide***) -let exmp13 = v + 1. -let exmp14 = rv + 1. - -(**Addition to every element of vector.*) -v + 1. - -(*** include-value:exmp13 ***) - -(**Addition to every element of row vector.*) -rv + 1. - -(*** include-value:exmp14 ***) - - -(** - -## Matrix - -### Creating Matrices with FSharp.Stats. -Matrices will also be printed with the FSharp.Stats.FSIPrinters.matrix function to get a nice console output. -*) -open FSharp.Stats - -// http://fdatamining.blogspot.de/2010/03/matrix-and-linear-algebra-in-f-part-i-f.html -// http://fdatamining.blogspot.de/search/label/linear%20algebra - -let A = - matrix [ [ 1.0; 7.0; 2.0 ] - [ 1.0; 3.0; 1.0 ] - [ 2.0; 9.0; 1.0 ] ] - -(***hide***) -let APrint = - FSharp.Stats.FSIPrinters.matrix A - -(*** include-value:APrint ***) - -let B = - matrix [ [ 10.0; 70.0; 20.0 ] - [ 10.0; 30.0; 10.0 ] - [ 20.0; 90.0; 10.0 ] ] - -(***hide***) -let BPrint = - FSharp.Stats.FSIPrinters.matrix B - -(*** include-value:BPrint ***) - - -(** -### Calculation Examples for Matrices -*) - -(***hide***) -let exmp1 = - A - |> Matrix.Generic.mapRows (Seq.sum) - -(**Get sum of each row.*) -A -|> Matrix.Generic.mapRows (Seq.sum) - -(*** include-value:exmp1 ***) - -(***hide***) -let exmp2 = - A - |> Matrix.mapiCols (fun i r -> r) - -(**Create seq of vectors of matrix columns.*) -A -|> Matrix.mapiCols (fun i r -> r) - -(*** include-value:exmp2 ***) - -(***hide***) -let exmp3 = A + B |> FSharp.Stats.FSIPrinters.matrix -let exmp4 = A - B|> FSharp.Stats.FSIPrinters.matrix -let exmp5 = A * B|> FSharp.Stats.FSIPrinters.matrix -let exmp6 = A.*B|> FSharp.Stats.FSIPrinters.matrix -let exmp7 = A * 2.0|> FSharp.Stats.FSIPrinters.matrix -let exmp9 = -A|> FSharp.Stats.FSIPrinters.matrix -let exmp10 = A * v -let exmp11 = Matrix.dot A B -let exmp12 = A + 1.|> FSharp.Stats.FSIPrinters.matrix - - -(**Sum of two matrices.*) -A + B - -(*** include-value:exmp3 ***) - -(**Difference between two matrices.*) -A - B - -(*** include-value:exmp4 ***) - -(**Product of two matrices.*) -A * B - -(*** include-value:exmp5 ***) - -(**Element-wise product of two matrices*) -A .* B - -(*** include-value:exmp6 ***) - -(**Scalar product of a matrix.*) -A * 2.0 -2.0 * A // also ok, gives same result - -(*** include-value:exmp7 ***) - -(**Negation of a matrix*) --A - -(*** include-value:exmp9 ***) - -(**Product of a matrix-vector.*) -A * v - -(*** include-value:exmp10 ***) - -(**Dot product of two matrices.*) -Matrix.dot A B - -(*** include-value:exmp11 ***) - -(**Addition to every element of matrix.*) -A + 1. - -(*** include-value:exmp12 ***) - - -(***hide***) -//let () = -// let assemblyProbeDirectory = "D:/Source/FSharp.Stats/lib" -// System.IO.Directory.SetCurrentDirectory(assemblyProbeDirectory) - -(***hide***) -//// Linear regression -//let cost theta X (y:vector) = -// let tmp = Matrix.dot X theta -// y -// |> Vector.fold (fun sum v -> -// let error = v - tmp -// sum + (error * error) ) 0. -// |> (/) (float y.Length * 2.0) - -(***hide***) -//let inline (.-) a b = -// a |> Matrix.map (fun x -> x - b) - -(***hide***) -//let estimateCoefficientsBySGD (X:matrix) y theta alpha = // rate nEpoch (data:array>) -// //let delta = Vector.create (X.NumCols) 1. -// let cost' = cost theta X y -// let rec loop delta = -// match (delta.Values|> Array.maxBy abs > 1e-6) with -// | false -> theta -// | true -> -// let error = -// let tmp = Matrix.dot X theta -// y |> Vector.map (fun v -> v - y) -// let delta' = -// Matrix.dot X.Transpose error -// |> (/) (float y.Length) -// let trial_theta = theta - alpha * delta -// let trial_cost = cost trial_theta X y -// loop delta' -// let rec wloop (theta:vector) (ttheta:vector) (tcost:vector) (pcost:vector) = -// let ttheta' = (theta + ttheta) / 2. -// let tcost' = cost ttheta X y -// //while (np.max(np.abs(delta)) > 1e-6) do -// // 1. - - - -(***hide***) -//// F# Numerics Interface -//// http://fdatamining.blogspot.de/2010/03/f-inumerics-interface-and-matrix-class.html - -(***hide***) -//// Service Provider model pattern -//// -//// http://blog.ploeh.dk/2011/04/27/Providerisnotapattern/ -//// http://blog.ploeh.dk/2011/04/27/Providerisnotapattern/ - -(***hide***) -//open System.Runtime.InteropServices - -(***hide***) -//// [] -//[] -//extern void dgemm_ -// ( char *transa, char *transb, -// int *m, int *n, int *k, -// double *alpha, double *a, int *lda, -// double *b, int *ldb, double *beta, -// double *c, int *ldc ); - - - -(***hide***) -//#nowarn "51" -//open Microsoft.FSharp.NativeInterop - -(***hide***) -//let matmul_blas (a:float[,]) (b:float[,]) = -// // Get dimensions of the input matrices -// let m = Array2D.length1 a -// let k = Array2D.length2 a -// let n = Array2D.length2 b -// // Allocate array for the result -// let c = Array2D.create n m 0.0 -// // Declare arguments for the call -// let mutable arg_transa = 't' -// let mutable arg_transb = 't' -// let mutable arg_m = m -// let mutable arg_n = n -// let mutable arg_k = k -// let mutable arg_alpha = 1.0 -// let mutable arg_ldk = k -// let mutable arg_ldn = n -// let mutable arg_beta = 1.0 -// let mutable arg_ldm = m - -(***hide***) -// // Temporarily pin the arrays -// use arg_a = PinnedArray2.of_array2D(a) -// use arg_b = PinnedArray2.of_array2D(b) -// use arg_c = PinnedArray2.of_array2D(c) -// // Invoke the native routine -// dgemm_( &&arg_transa, &&arg_transb, -// &&arg_m, &&arg_n, &&arg_k, -// &&arg_alpha, arg_a.Ptr, &&arg_ldk, -// arg_b.Ptr, &&arg_ldn, &&arg_beta, -// arg_c.Ptr, &&arg_ldm ) -// // Transpose the result to get m*n matrix -// Array2D.init m n (fun i j -> c.[j,i]) - - - -(***hide***) -//matmul_blas (A.ToArray2D()) (B.ToArray2D()) - diff --git a/docs/Normalization.fsx b/docs/Normalization.fsx index 61692ec23..3bd51bfd4 100644 --- a/docs/Normalization.fsx +++ b/docs/Normalization.fsx @@ -13,6 +13,8 @@ categoryindex: 0 #I "../src/FSharp.Stats/bin/Release/netstandard2.0/" #r "FSharp.Stats.dll" #r "nuget: Plotly.NET, 4.0.0" +#r "nuget: FsMath, 0.0.1" +open FsMath Plotly.NET.Defaults.DefaultDisplayOptions <- Plotly.NET.DisplayOptions.init (PlotlyJSReference = Plotly.NET.PlotlyJSReference.NoReference) diff --git a/docs/Optimization.fsx b/docs/Optimization.fsx index 0509eb3bf..c175a8f07 100644 --- a/docs/Optimization.fsx +++ b/docs/Optimization.fsx @@ -13,6 +13,8 @@ categoryindex: 0 #I "../src/FSharp.Stats/bin/Release/netstandard2.0/" #r "FSharp.Stats.dll" #r "nuget: Plotly.NET, 4.0.0" +#r "nuget: FsMath, 0.0.1" +open FsMath Plotly.NET.Defaults.DefaultDisplayOptions <- Plotly.NET.DisplayOptions.init (PlotlyJSReference = Plotly.NET.PlotlyJSReference.NoReference) diff --git a/docs/Quantiles.fsx b/docs/Quantiles.fsx index 605313385..9e2102e77 100644 --- a/docs/Quantiles.fsx +++ b/docs/Quantiles.fsx @@ -13,6 +13,8 @@ categoryindex: 0 #I "../src/FSharp.Stats/bin/Release/netstandard2.0/" #r "FSharp.Stats.dll" #r "nuget: Plotly.NET, 4.0.0" +#r "nuget: FsMath, 0.0.1" +open FsMath Plotly.NET.Defaults.DefaultDisplayOptions <- Plotly.NET.DisplayOptions.init (PlotlyJSReference = Plotly.NET.PlotlyJSReference.NoReference) diff --git a/docs/Rank.fsx b/docs/Rank.fsx index cbeefbc94..7b7af6534 100644 --- a/docs/Rank.fsx +++ b/docs/Rank.fsx @@ -13,6 +13,8 @@ categoryindex: 0 #I "../src/FSharp.Stats/bin/Release/netstandard2.0/" #r "FSharp.Stats.dll" #r "nuget: Plotly.NET, 4.0.0" +#r "nuget: FsMath, 0.0.1" +open FsMath Plotly.NET.Defaults.DefaultDisplayOptions <- Plotly.NET.DisplayOptions.init (PlotlyJSReference = Plotly.NET.PlotlyJSReference.NoReference) diff --git a/docs/Signal.fsx b/docs/Signal.fsx index c97228c16..cdf566238 100644 --- a/docs/Signal.fsx +++ b/docs/Signal.fsx @@ -13,6 +13,8 @@ categoryindex: 0 #I "../src/FSharp.Stats/bin/Release/netstandard2.0/" #r "FSharp.Stats.dll" #r "nuget: Plotly.NET, 4.0.0" +#r "nuget: FsMath, 0.0.1" +open FsMath Plotly.NET.Defaults.DefaultDisplayOptions <- Plotly.NET.DisplayOptions.init (PlotlyJSReference = Plotly.NET.PlotlyJSReference.NoReference) diff --git a/docs/Testing.fsx b/docs/Testing.fsx index ed9a456c2..ba709a690 100644 --- a/docs/Testing.fsx +++ b/docs/Testing.fsx @@ -15,6 +15,8 @@ categoryindex: 0 #r "nuget: Plotly.NET, 4.0.0" #r "nuget: FSharpAux, 1.1.0" #r "nuget: Deedle, 3.0.0" +#r "nuget: FsMath, 0.0.1" +open FsMath Plotly.NET.Defaults.DefaultDisplayOptions <- Plotly.NET.DisplayOptions.init (PlotlyJSReference = Plotly.NET.PlotlyJSReference.NoReference) diff --git a/docs/index.fsx b/docs/index.fsx index 770a8887d..f53b10a9e 100644 --- a/docs/index.fsx +++ b/docs/index.fsx @@ -4,6 +4,8 @@ #I "../src/FSharp.Stats/bin/Release/netstandard2.0/" #r "FSharp.Stats.dll" #r "nuget: Plotly.NET, 4.0.0" +#r "nuget: FsMath, 0.0.1" +open FsMath Plotly.NET.Defaults.DefaultDisplayOptions <- Plotly.NET.DisplayOptions.init (PlotlyJSReference = Plotly.NET.PlotlyJSReference.NoReference) diff --git a/src/FSharp.Stats/AlgTypes/AlgTypesTopLevelOps.fs b/src/FSharp.Stats/AlgTypes/AlgTypesTopLevelOps.fs deleted file mode 100644 index 9e2f89788..000000000 --- a/src/FSharp.Stats/AlgTypes/AlgTypesTopLevelOps.fs +++ /dev/null @@ -1,9 +0,0 @@ -namespace FSharp.Stats - - -[] -module AlgTypesTopLevelOps = - - let matrix ll = Matrix.ofRowSeq ll - let vector l = Vector.ofSeq l - //let rowvec l = RowVector.ofSeq l diff --git a/src/FSharp.Stats/AlgTypes/GenericMath.fs b/src/FSharp.Stats/AlgTypes/GenericMath.fs deleted file mode 100644 index 0dea3c597..000000000 --- a/src/FSharp.Stats/AlgTypes/GenericMath.fs +++ /dev/null @@ -1,73 +0,0 @@ -namespace FSharp.Stats - -open System -open System.Runtime.InteropServices - -module GenericMath = - - /// Generic Zero - let inline zero<'T when 'T :> Numerics.INumber<'T>> = - 'T.Zero - - /// Generic One - let inline one<'T when 'T :> Numerics.INumber<'T>> = - 'T.One - - /// Generic float conversion - let inline T<'T when 'T :> Numerics.INumber<'T>> (x: float) : 'T = - 'T.CreateChecked x - - /// Generic square root - let inline sqrt<'T when 'T :> Numerics.IRootFunctions<'T>> (x: 'T) : 'T = - 'T.Sqrt(x) - - /// Generic exponentiation (e^x) - let inline exp<'T when 'T :> Numerics.IExponentialFunctions<'T>> (x: 'T) : 'T = - 'T.Exp(x) - - /// Generic power function (x^y) - let inline pow<'T when 'T :> Numerics.IPowerFunctions<'T>> (x: 'T) (y: 'T) : 'T = - 'T.Pow(x, y) - - /// Generic natural logarithm - let inline log<'T when 'T :> Numerics.ILogarithmicFunctions<'T>> (x: 'T) : 'T = - 'T.Log(x) - - /// Generic absolute value - let inline abs<'T when 'T :> Numerics.INumber<'T>> (x: 'T) : 'T = - 'T.Abs(x) - - /// Generic sine - let inline sin<'T when 'T :> Numerics.ITrigonometricFunctions<'T>> (x: 'T) : 'T = - 'T.Sin(x) - - /// Generic cosine - let inline cos<'T when 'T :> Numerics.ITrigonometricFunctions<'T>> (x: 'T) : 'T = - 'T.Cos(x) - - /// Generic pi constant - let inline pi<'T when 'T :> Numerics.IFloatingPointConstants<'T> and 'T :> Numerics.INumber<'T>> () : 'T = - 'T.Pi - - /// Generic e constant (Euler's number) - let inline e<'T when 'T :> Numerics.IFloatingPointConstants<'T>> () : 'T = - 'T.E - - /// Generic tau constant (2 * pi) - let inline tau<'T when 'T :> Numerics.IFloatingPointConstants<'T> and 'T :> Numerics.INumber<'T>> () : 'T = - 'T.Tau - - /// Generic floor function - let inline floor<'T when 'T :> Numerics.IFloatingPoint<'T>> (x: 'T) : 'T = - 'T. Floor(x) - - /// Generic floor function - let inline epsilon<'T when 'T :> Numerics.IFloatingPoint<'T>> () : 'T = - 'T.CreateTruncating System.Double.Epsilon - - // let inline min x y = if x < y then x else y - // let inline max x y = if x > y then x else y - - // let inline clamp minVal maxVal x = - // if x < minVal then minVal elif x > maxVal then maxVal else x - diff --git a/src/FSharp.Stats/AlgTypes/Householder.fs b/src/FSharp.Stats/AlgTypes/Householder.fs deleted file mode 100644 index a68931fe6..000000000 --- a/src/FSharp.Stats/AlgTypes/Householder.fs +++ /dev/null @@ -1,126 +0,0 @@ -namespace FSharp.Stats.Algebra - - -open System -open FSharp.Stats -open FSharp.Stats.Acceleration - -[] -type Householder<'T when 'T :> Numerics.INumber<'T>> = - { - V: Vector<'T> - Tau: 'T - Beta: 'T - } - - -type Householder() = - - static member inline create<'T when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T : comparison - and 'T :> ValueType - and 'T :> Numerics.IRootFunctions<'T>> - (x: Vector<'T>) : Householder<'T> = - - let xSpan = x.AsSpan() - let alpha = xSpan[0] - let tail = xSpan.Slice(1) - - let zero = GenericMath.zero<'T> - let one = GenericMath.one<'T> - - let sigma = - SIMDUtils.mapFoldUnchecked( - (fun v -> v * v), - (fun x -> x * x), - (+), - (+), - zero, - tail - ) - - if sigma.Equals(zero) then - let v = Vector.zeroCreate x.Length - v.[0] <- one - { - V = v - Tau = zero - Beta = alpha - } - else - let sum = alpha * alpha + sigma - let beta = GenericMath.sqrt sum - - let v0 = - if alpha <= zero then alpha - beta - else -sigma / (alpha + beta) - - let tau = - let v0Sq = v0 * v0 - (v0Sq + v0Sq) / (sigma + v0Sq) - - let v = Vector.divideScalar v0 x // SIMD-aware scalar division - v.[0] <- one - - { - V = v - Tau = tau - Beta = beta - } - - static member inline applyLeft<'T when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T : equality - and 'T :> ValueType> - (h: Householder<'T>, A: Matrix<'T>, rowOffset: int) = - - let v = h.V - let tau = h.Tau - let m = A.NumRows - let n = A.NumCols - let vLen = v.Length - - //for j = 0 to n - 1 do - // let mutable dot = GenericMath.zero<'T> - // for i = 0 to vLen - 1 do - // dot <- dot + v.[i] * A.[rowOffset + i, j] - // let scale = tau * dot - // for i = 0 to vLen - 1 do - // A.[rowOffset + i, j] <- A.[rowOffset + i, j] - scale * v.[i] - - for j = 0 to n - 1 do - let mutable dot = GenericMath.zero<'T> - for i = 0 to vLen - 1 do - let row = rowOffset + i - if row < m then - dot <- dot + v.[i] * A.[row, j] - let scale = tau * dot - for i = 0 to vLen - 1 do - let row = rowOffset + i - if row < m then - A.[row, j] <- A.[row, j] - scale * v.[i] - - - static member inline applyRight<'T when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T : equality - and 'T :> ValueType> - (h: Householder<'T>, A: Matrix<'T>, colOffset: int) = - - let v = h.V - let tau = h.Tau - let m = A.NumRows - let vLen = v.Length - - for i = 0 to m - 1 do - let mutable dot = GenericMath.zero<'T> - for j = 0 to vLen - 1 do - dot <- dot + A.[i, colOffset + j] * v.[j] - let scale = tau * dot - for j = 0 to vLen - 1 do - A.[i, colOffset + j] <- A.[i, colOffset + j] - scale * v.[j] - diff --git a/src/FSharp.Stats/AlgTypes/Matrix.fs b/src/FSharp.Stats/AlgTypes/Matrix.fs deleted file mode 100644 index f9c878579..000000000 --- a/src/FSharp.Stats/AlgTypes/Matrix.fs +++ /dev/null @@ -1,923 +0,0 @@ -namespace FSharp.Stats - -open System -open System.Runtime.InteropServices - -// let blockSize = -// match sizeof<'T> with -// | 4 -> 32 // float32 or int -// | 8 -> 16 // float64 -// | _ -> 16 // fallback - - -/// Matrix type to hold values of a matrix in a 1D Arrays (Flattened Representation) -type Matrix<'T when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T : equality - and 'T :> ValueType> - (rows: int, cols: int, data: Vector<'T>) = - - /// Exposes the raw underlying data array (row-major flattened). - member _.Data = data - - /// Number of rows in the matrix. - member _.NumRows = rows - - /// Number of columns in the matrix. - member _.NumCols = cols - - /// Matrix indexer for getting and setting elements at (i, j). - member this.Item - with get (i, j) = - if i < 0 || i >= rows || j < 0 || j >= cols then - invalidArg "index" $"Index out of range: ({i}, {j})" - data.[i * cols + j] - and set (i, j) value = - if i < 0 || i >= rows || j < 0 || j >= cols then - invalidArg "index" $"Index out of range: ({i}, {j})" - data.[i * cols + j] <- value - - // Implement IEquatable so that F# structural equality can use it - interface IEquatable> with - member this.Equals(other: Matrix<'T>) = - - // 1) Check dimension - if rows <> other.NumRows || cols <> other.NumCols then - false - else - // 2) Compare all elements - let otherData = other.Data - let mutable i = 0 - let mutable eq = true - while eq && i < data.Length do - if data[i] <> otherData[i] then - eq <- false - i <- i + 1 - eq - - // Override Object.Equals - override this.Equals(obj: obj) = - match obj with - | :? Matrix<'T> as other -> - (this :> IEquatable>).Equals(other) - | _ -> false - - // Override Object.GetHashCode - override this.GetHashCode() = - // We'll combine the row/col count plus some portion of the data to avoid huge cost. - // There's no perfect hashing for big arrays, but here's a simple example: - - let mutable hash = HashCode() - hash.Add(rows) - hash.Add(cols) - // Optionally: incorporate some or all elements - // For big arrays, consider sampling or a rolling hash approach. - for i in 0 .. data.Length - 1 do - hash.Add(data[i]) - hash.ToHashCode() - - /// - /// Returns a new Matrix<'T> that is the slice of rows [rowStart..rowEnd] - /// and columns [colStart..colEnd]. If any of these bounds is omitted, - /// it defaults to the full range in that dimension. - /// - /// Optional start row (inclusive) - /// Optional end row (inclusive) - /// Optional start column (inclusive) - /// Optional end column (inclusive) - /// A new submatrix copy. - member this.GetSlice - (rowStart: int option, rowEnd: int option, - colStart: int option, colEnd: int option) : Matrix<'T> = - - // 1) Determine actual start/end indices - let r1 = defaultArg rowStart 0 - let r2 = defaultArg rowEnd (rows - 1) - let c1 = defaultArg colStart 0 - let c2 = defaultArg colEnd (cols - 1) - - // 2) Validate them - if r1 < 0 || r2 < r1 || r2 >= rows then - invalidArg "row range" $"Invalid row slice range: {r1}..{r2}" - if c1 < 0 || c2 < c1 || c2 >= cols then - invalidArg "col range" $"Invalid column slice range: {c1}..{c2}" - - let subRows = r2 - r1 + 1 - let subCols = c2 - c1 + 1 - - // 3) Allocate new array for the submatrix - let subData = Array.zeroCreate<'T> (subRows * subCols) - - // 4) Copy row by row - for rr in 0 .. subRows - 1 do - let srcIndex = (r1 + rr) * cols + c1 - let dstIndex = rr * subCols - // Copy from data[srcIndex..(srcIndex+subCols-1)] - // to subData[dstIndex..(dstIndex+subCols-1)] - Array.blit data srcIndex subData dstIndex subCols - - // 5) Return a new Matrix with the submatrix data - Matrix<'T>(subRows, subCols, subData) - - /// - /// Convenience "slice indexer" for F# syntax: mat.[r1..r2, c1..c2]. - /// Internally calls GetSlice(...). - /// - member this.GetSlice - (rowRange: Range, colRange: Range) : Matrix<'T> = - - // Convert the F# Range type into int option pairs - let rowStart, rowEnd = - (if rowRange.Start = System.Index.Start then None else Some rowRange.Start.Value), - (if rowRange.End = System.Index.End then None else Some rowRange.End.Value) - - let colStart, colEnd = - (if colRange.Start = System.Index.Start then None else Some colRange.Start.Value), - (if colRange.End = System.Index.End then None else Some colRange.End.Value) - - // Use the primary GetSlice overload - this.GetSlice(rowStart, rowEnd, colStart, colEnd) - - - static member inline map2Unchecked<'T when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T :> ValueType> - (fVec: Numerics.Vector<'T> -> Numerics.Vector<'T> -> Numerics.Vector<'T>) - (fScalar: 'T -> 'T -> 'T) - (a: Matrix<'T>) - (b: Matrix<'T>) - : Matrix<'T> = - - // if a.Rows <> b.Rows || a.Cols <> b.Cols then - // invalidArg "b" "Matrix dimensions must match" - - let len = a.Data.Length - let result = Array.zeroCreate<'T> len - - let simdSize = Numerics.Vector<'T>.Count - let simdCount = len / simdSize - let tailStart = simdCount * simdSize - - // Cast arrays to Vector<'T> spans - let aVec = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(a.Data.AsSpan()) - let bVec = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(b.Data.AsSpan()) - let rVec = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(result.AsSpan()) - - for i = 0 to simdCount - 1 do - rVec.[i] <- fVec aVec.[i] bVec.[i] - - for i = tailStart to len - 1 do - result.[i] <- fScalar a.Data.[i] b.Data.[i] - - Matrix(a.NumRows, a.NumCols, result) - - - static member inline mapScalar<'T when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T :> ValueType> - (fv: Numerics.Vector<'T> -> Numerics.Vector<'T> -> Numerics.Vector<'T>) - (f: 'T -> 'T -> 'T) - (matrix: Matrix<'T>) - (scalar: 'T) - : Matrix<'T> = - - let length = matrix.Data.Length - let result = Array.zeroCreate<'T> length - - let slotSize = Numerics.Vector<'T>.Count - let slotCount = length / slotSize - let ceiling = slotCount * slotSize - - let scalarVec = Numerics.Vector<'T>(scalar) - - let mSpan = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(matrix.Data.AsSpan()) - let rSpan = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(result.AsSpan()) - - // SIMD chunk-wise operation - for i = 0 to slotCount - 1 do - rSpan.[i] <- fv mSpan.[i] scalarVec - - // Scalar fallback for remainder - for i = ceiling to length - 1 do - result.[i] <- f matrix.Data.[i] scalar - - Matrix(matrix.NumRows, matrix.NumCols, result) - - - - /// Creates a new matrix by initializing each element with a function `f(row, col)`. - static member inline private transposeByBlock<'T when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T :> ValueType> - (rows : int) - (cols : int) - (data: 'T[]) - (blockSize: int) = - - //let blockSize = defaultArg blockSize 16 - - let src = data - let dst = Array.zeroCreate<'T> (rows * cols) - - let vectorSize = Numerics.Vector<'T>.Count - - // Process the matrix in blocks - for i0 in 0 .. blockSize .. rows - 1 do - for j0 in 0 .. blockSize .. cols - 1 do - - let iMax = min (i0 + blockSize) rows - let jMax = min (j0 + blockSize) cols - - for i in i0 .. iMax - 1 do - let srcOffset = i * cols - for j in j0 .. jMax - 1 do - let v = src.[srcOffset + j] - dst.[j * rows + i] <- v - - dst - - static member inline transpose (m:Matrix<'T>) : Matrix<'T> = - m.Transpose() - - member this.Transpose() = - let blocksize = 16 - Matrix(this.NumCols, this.NumRows, Matrix.transposeByBlock this.NumRows this.NumCols this.Data blocksize) - - static member init<'T when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T :> ValueType> - (rows: int) - (cols: int) - (f: int -> int -> 'T) = - let data = Array.init (rows * cols) (fun idx -> f (idx / cols) (idx % cols)) - Matrix(rows, cols, data) - - static member create<'T when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T :> ValueType> - (rows: int) - (cols: int) - (data: 'T[]) : Matrix<'T> = - - Matrix(rows, cols, data) - - - /// Constructs a matrix from a 2D array. - static member ofArray2D<'T when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T :> ValueType> - (arr2D: 'T[,]) = - let rows = arr2D.GetLength(0) - let cols = arr2D.GetLength(1) - let length = rows * cols - - let flat = Array.zeroCreate<'T> length - let sourceSpan = MemoryMarshal.CreateSpan(&arr2D.[0, 0], length) - sourceSpan.CopyTo(flat.AsSpan()) - - Matrix(rows, cols, flat) - - /// Converts this matrix into a 2D array. - member this.toArray2D() = - let arr2D = Array2D.zeroCreate<'T> this.NumRows this.NumCols - let targetSpan = MemoryMarshal.CreateSpan(&arr2D.[0, 0], this.NumRows * this.NumCols) - this.Data.AsSpan().CopyTo(targetSpan) - arr2D - - - /// Constructs a matrix from a jagged array (`'T[][]`), assuming a rectangular structure. - static member ofJaggedArray<'T when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T :> ValueType> - (jagged: 'T[][]) = - let rows = jagged.Length - let cols = if rows > 0 then jagged.[0].Length else 0 - - // Optional safety check for rectangular shape - for row in jagged do - if row.Length <> cols then - invalidArg "jagged" "All rows in jagged array must have the same length." - - let flat = Array.zeroCreate<'T> (rows * cols) - - for i = 0 to rows - 1 do - let source = jagged.[i].AsSpan() - let target = flat.AsSpan(i * cols, cols) - source.CopyTo(target) - - Matrix(rows, cols, flat) - - /// Converts this matrix into a jagged array (`'T[][]`). - member this.toJaggedArray() = - let result = Array.zeroCreate<'T[]> this.NumRows - let dataSpan = this.Data.AsSpan() - - for i = 0 to this.NumRows - 1 do - let row = Array.zeroCreate<'T> this.NumCols - dataSpan.Slice(i * this.NumCols, this.NumCols).CopyTo(row.AsSpan()) - result.[i] <- row - - result - - - /// Pretty string representation with formatting and truncation, using StringBuilder. - /// Supports optional scientific notation for floating point types. - member this.toFormattedString(?maxRows: int, ?maxCols: int, ?floatFormat: string, ?useScientific: bool) = - let maxRows = defaultArg maxRows 10 - let maxCols = defaultArg maxCols 10 - let useScientific = defaultArg useScientific false - let floatFormat = - match floatFormat with - | Some f -> f - | None -> if useScientific then "0.##E+0" else "0.##" - - if this.NumRows = 0 || this.NumCols = 0 then - "Matrix (empty)" - else - let rowsToShow = min this.NumRows maxRows - let colsToShow = min this.NumCols maxCols - - // Format a single cell - let formatCell (value: 'T) = - match box value with - | :? float as f -> f.ToString(floatFormat) - | :? float32 as f -> f.ToString(floatFormat) - | _ -> string value - - let formattedCells = - Array.init rowsToShow (fun i -> - Array.init colsToShow (fun j -> - formatCell this.[i, j] - ) - ) - - let colWidths = - Array.init colsToShow (fun j -> - Array.init rowsToShow (fun i -> formattedCells.[i].[j].Length) - |> Array.max - ) - - let divider = - colWidths - |> Array.map (fun w -> String.replicate w "─") - |> String.concat "─┼─" - - let sb = Text.StringBuilder() - sb.AppendLine($"Matrix {this.NumRows}x{this.NumCols}:") |> ignore - sb.AppendLine("┌ " + divider + " ┐") |> ignore - - for i = 0 to rowsToShow - 1 do - sb.Append("│ ") |> ignore - for j = 0 to colsToShow - 1 do - let cell = formattedCells.[i].[j].PadLeft(colWidths.[j]) - sb.Append(cell) |> ignore - if j < colsToShow - 1 then sb.Append(" │ ") |> ignore - sb.AppendLine(" │") |> ignore - - if this.NumRows > rowsToShow || this.NumCols > colsToShow then - sb.AppendLine($"│ ... truncated ({this.NumRows}x{this.NumCols}) │") |> ignore - - sb.AppendLine("└ " + divider + " ┘") |> ignore - sb.ToString() - - - /// Default string representation (truncated, human-readable) - override this.ToString() = this.toFormattedString() - - static member inline checkSameShape<'T when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T :> ValueType> - (a: Matrix<'T>) (b: Matrix<'T>) = - if a.NumRows <> b.NumRows || a.NumCols <> b.NumCols then - invalidArg "b" $"Matrix dimensions must match. A is {a.NumRows}x{a.NumCols}, B is {b.NumRows}x{b.NumCols}" - - /// Element-wise addition - static member inline add<'T when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T :> ValueType> - (a: Matrix<'T>) - (b: Matrix<'T>) : Matrix<'T> = - - Matrix.checkSameShape a b - let data = - Acceleration.SIMDUtils.map2Unchecked (+) (+) a.Data b.Data - Matrix(a.NumRows, a.NumCols, data) - - static member inline subtract<'T when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T :> ValueType> - (a: Matrix<'T>) - (b: Matrix<'T>) : Matrix<'T> = - - Matrix.checkSameShape a b - Matrix.map2Unchecked (-) (-) a b - - - /// Hadamard product - static member inline multiply<'T - when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T :> ValueType> - (a: Matrix<'T>) - (b: Matrix<'T>) : Matrix<'T> = - - Matrix.checkSameShape a b - Matrix.map2Unchecked (*) (*) a b - - - static member inline divide<'T - when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T :> ValueType> - (a: Matrix<'T>) - (b: Matrix<'T>) : Matrix<'T> = - - Matrix.checkSameShape a b - Matrix.map2Unchecked (/) (/) a b - - - static member inline addScalar<'T when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T :> ValueType> - (m: Matrix<'T>) (scalar: 'T) : Matrix<'T> = - - Matrix.mapScalar (+) (+) m scalar - - - - static member inline subtractScalar<'T - when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T :> ValueType> - (m: Matrix<'T>) - (scalar: 'T) : Matrix<'T> = - - Matrix.mapScalar (-) (-) m scalar - - - static member inline multiplyScalar<'T - when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T :> ValueType> - (m: Matrix<'T>) - (scalar: 'T) : Matrix<'T> = - - Matrix.mapScalar (*) (*) m scalar - - - static member inline divideScalar<'T - when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T :> ValueType> - (m: Matrix<'T>) - (scalar: 'T) : Matrix<'T> = - - Matrix.mapScalar (/) (/) m scalar - - - /// Standard matrix-vector product - static member inline muliplyVector<'T - when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T :> ValueType> - (m: Matrix<'T>) - (v: Vector<'T>) : Vector<'T> = - - if m.NumCols <> v.Length then - invalidArg "v" $"Vector length {v.Length} must match matrix column count {m.NumCols}" - - let result: Vector<'T> = Array.zeroCreate m.NumRows - let zero = LanguagePrimitives.GenericZero<'T> - - let simdSize = Numerics.Vector<'T>.Count - let vSpan = v.AsSpan() - let vSimd = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(vSpan) - - let tailStart = (v.Length / simdSize) * simdSize - - for row = 0 to m.NumRows - 1 do - let rowOffset = row * m.NumCols - let rowSpan = m.Data.AsSpan(rowOffset, m.NumCols) - let rowSimd = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(rowSpan) - - let mutable acc = Numerics.Vector<'T>(zero) - - for i = 0 to vSimd.Length - 1 do - acc <- acc + rowSimd.[i] * vSimd.[i] - - let mutable tail = zero - for i = tailStart to m.NumCols - 1 do - tail <- tail + m.Data.[rowOffset + i] * v.[i] - - result.[row] <- Numerics.Vector.Sum(acc) + tail - - result - - static member inline addRowVector<'T - when 'T :> Numerics.INumber<'T> - and 'T : struct - and 'T : (new : unit -> 'T) - and 'T :> ValueType> - (m: Matrix<'T>) - (v: Vector<'T>) : Matrix<'T> = - - if v.Length <> m.NumCols then - invalidArg "v" $"Row vector length {v.Length} must match matrix column count {m.NumCols}" - - let resultData = Array.zeroCreate<'T> (m.NumRows * m.NumCols) - let simdSize = Numerics.Vector<'T>.Count - let simdCount = m.NumCols / simdSize - let scalarStart = simdCount * simdSize - - let vSimd = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(v.AsSpan()) - - for row = 0 to m.NumRows - 1 do - let offset = row * m.NumCols - let srcSpan = m.Data.AsSpan(offset, m.NumCols) - let dstSpan = resultData.AsSpan(offset, m.NumCols) - - let srcSimd = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(srcSpan) - let dstSimd = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(dstSpan) - - // SIMD part - for i = 0 to simdCount - 1 do - dstSimd.[i] <- srcSimd.[i] + vSimd.[i] - - // Tail (scalar) - for i = scalarStart to m.NumCols - 1 do - dstSpan.[i] <- srcSpan.[i] + v.[i] - - Matrix(m.NumRows, m.NumCols, resultData) - - - static member inline addColVector<'T - when 'T :> Numerics.INumber<'T> - and 'T : struct - and 'T : (new : unit -> 'T) - and 'T :> ValueType> - (m: Matrix<'T>) - (v: Vector<'T>) : Matrix<'T> = - - if v.Length <> m.NumRows then - invalidArg "v" $"Column vector length {v.Length} must match matrix row count {m.NumRows}" - - let cols = m.NumCols - let resultData = Array.zeroCreate<'T> (m.NumRows * cols) - let simdSize = Numerics.Vector<'T>.Count - - for row = 0 to m.NumRows - 1 do - let rowOffset = row * cols - let srcRow = m.Data.AsSpan(rowOffset, cols) - let dstRow = resultData.AsSpan(rowOffset, cols) - - let simdRow = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(srcRow) - let simdDst = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(dstRow) - - let broadcast = Numerics.Vector<'T>(v.[row]) - let simdCount = cols / simdSize - let scalarStart = simdCount * simdSize - - // SIMD-add: row + broadcast vector - for i = 0 to simdCount - 1 do - simdDst.[i] <- simdRow.[i] + broadcast - - // Scalar tail - for i = scalarStart to cols - 1 do - dstRow.[i] <- srcRow.[i] + v.[row] - - Matrix(m.NumRows, cols, resultData) - - - /// - /// Computes row-vector v (length = mat.NumRows) times matrix mat (size = [NumRows × NumCols]), - /// returning a new vector of length mat.NumCols. Uses chunk-based SIMD with manual gather. - /// - static member inline multiplyRowVector<'T - when 'T :> Numerics.INumber<'T> - and 'T : struct - and 'T : (new : unit -> 'T) - and 'T :> ValueType> - (v: Vector<'T>) - (mat: Matrix<'T>) : Vector<'T> = - - // 1) Dimension checks - let n = mat.NumRows - let m = mat.NumCols - if v.Length <> n then - invalidArg (nameof v) "Vector length must match mat.NumRows." - - let result = Vector.zeroCreate<'T> m - let data = mat.Data // row-major: element (i,j) is data.[i*m + j] - - // O(n*m) nested loops (not SIMD seems to be faster in the row-layout matrix) - for j = 0 to m - 1 do - let mutable sum = 'T.Zero - for i = 0 to n - 1 do - sum <- sum + (v.[i] * data.[i*m + j]) - result.[j] <- sum - - result - - - /// - /// Standard matrix multiplication (A x B). - /// A is (M x K), B is (K x N) => result is (M x N). - /// Then each (row of A) .dot. (row of B^T) is done with Vector<'T> chunks. - /// - static member matmul - (A: Matrix<'T>) (B: Matrix<'T>) : Matrix<'T> = - - // 1) Dimension checks - if A.NumCols <> B.NumRows then - invalidArg (nameof B) - $"Inner dimensions mismatch. A is {A.NumRows}x{A.NumCols}, B is {B.NumRows}x{B.NumCols}" - - let M = A.NumRows - let K = A.NumCols - let N = B.NumCols - - // 2) Transpose B to get B^T => shape [N x K], row j of B^T is col j of B - let Btrans = B.Transpose() - let bTData = Btrans.Data // Now each "row" in bTData is length=K, contiguous - - // 3) We'll allocate result - let resultData = Array.zeroCreate<'T> (M * N) - let aData = A.Data - - // 4) For each row i in A, row j in B^T => element in [i*N + j] - // The row i in A is contiguous of length K => offset i*K in aData - // The row j in B^T is contiguous of length K => offset j*K in bTData - for i in 0 .. M - 1 do - let aRowOffset = i * K - let aRowSpan = aData.AsSpan(aRowOffset, K) - // Convert A's row to a "Vector<'T>" span - let aVecSpan = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(aRowSpan) - - for j in 0 .. N - 1 do - let bTRowOffset = j * K - let bTRowSpan = bTData.AsSpan(bTRowOffset, K) - // Convert B^T's row j to a "Vector<'T>" span - let bTVecSpan = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(bTRowSpan) - - // 4.a) Do the chunkwise vector multiply-add - let mutable accum = Numerics.Vector<'T>.Zero - for chunk in 0 .. aVecSpan.Length - 1 do - accum <- accum + (aVecSpan.[chunk] * bTVecSpan.[chunk]) - - // 4.b) Sum up the vector lanes to a single scalar - let mutable sum = Numerics.Vector.Sum(accum) - - // 4.c) Handle remainder elements if K not multiple of Vector<'T>.Count - let remainderStart = aVecSpan.Length * Numerics.Vector<'T>.Count - for r in remainderStart .. K - 1 do - sum <- sum + aRowSpan.[r] * bTRowSpan.[r] - - // 4.d) Place result into the final matrix - resultData.[i*N + j] <- sum - - Matrix(M, N, resultData) - - - // Matrix - matrix operations - static member inline ( + ) (a: Matrix<'T>, b: Matrix<'T>) = Matrix.add a b - static member inline ( - ) (a: Matrix<'T>, b: Matrix<'T>) = Matrix.subtract a b - static member inline ( .* ) (a: Matrix<'T>, b: Matrix<'T>) = Matrix.multiply a b - static member inline ( * ) (a: Matrix<'T>, b: Matrix<'T>) = Matrix.matmul a b - static member inline ( / ) (a: Matrix<'T>, b: Matrix<'T>) = Matrix.divide a b - - // Matrix - vector operations - static member inline ( * ) (m: Matrix<'T>, v: Vector<'T>) = Matrix.muliplyVector m v - static member inline ( * ) (v: Vector<'T>, m: Matrix<'T>) = Matrix.multiplyRowVector v m - // static member inline ( + ) (m: Matrix<'T>, colVector: Vector<'T>) = Matrix.addColVector m colVector - // static member inline ( +| ) (m: Matrix<'T>, rowVector: Vector<'T>) = Matrix.addRowVector m rowVector - - // Matrix - scalar operations - static member inline (+) (m: Matrix<'T>, s: 'T) = Matrix.addScalar m s - static member inline (+) (s: 'T, m: Matrix<'T>) = Matrix.addScalar m s - - static member inline (-) (m: Matrix<'T>, s: 'T) = Matrix.subtractScalar m s - static member inline (-) (s: 'T, m: Matrix<'T>) = Matrix.subtractScalar m s - - static member inline (*) (m: Matrix<'T>, s: 'T) = Matrix.multiplyScalar m s - static member inline (*) (s: 'T, m: Matrix<'T>) = Matrix.multiplyScalar m s - - static member inline (/) (m: Matrix<'T>, s: 'T) = Matrix.divideScalar m s - static member inline (/) (s: 'T, m: Matrix<'T>) = Matrix.divideScalar m s - - - - static member inline diagonal - (diag: Vector<'T>) : Matrix<'T> = - - let n = diag.Length - let data = Array.zeroCreate<'T> (n * n) - for i = 0 to n - 1 do - data.[i * n + i] <- diag.[i] - Matrix(n, n, data) - - /// - /// Returns the diagonal elements of this matrix as an array of length = min(NumRows, NumCols). - /// - static member inline getDiagonal - (m:Matrix<'T>) : Vector<'T> = - let n = min m.NumRows m.NumCols - let diag = Array.zeroCreate<'T> n - for i = 0 to n - 1 do - // The diagonal element at row i, col i is stored at offset i * cols + i - diag.[i] <- m.Data.[i * m.NumCols + i] - diag - - - static member inline identity<'T - when 'T :> Numerics.INumber<'T> - and 'T : struct - and 'T : (new : unit -> 'T) - and 'T :> ValueType> - (n: int) : Matrix<'T> = - - let data = Array.zeroCreate<'T> (n * n) - for i = 0 to n - 1 do - data.[i * n + i] <- 'T.One - Matrix(n, n, data) - - static member inline zeroCreate<'T - when 'T :> Numerics.INumber<'T> - and 'T : struct - and 'T : (new : unit -> 'T) - and 'T :> ValueType> - (rows: int) - (cols: int) : Matrix<'T> = - - let data = Array.zeroCreate<'T> (rows * cols) - Matrix(rows, cols, data) - - static member inline ones<'T - when 'T :> Numerics.INumber<'T> - and 'T : struct - and 'T : (new : unit -> 'T) - and 'T :> ValueType> - (rows: int) - (cols: int) : Matrix<'T> = - - let size = rows * cols - let data = Array.zeroCreate<'T> size - let simdSize = Numerics.Vector<'T>.Count - let simdCount = size / simdSize - - let vOne = Numerics.Vector<'T>('T.One) - let span = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(data.AsSpan()) - - for i = 0 to simdCount - 1 do - span.[i] <- vOne - - for i = simdCount * simdSize to size - 1 do - data.[i] <- 'T.One - - Matrix(rows, cols, data) - - static member inline getRow<'T - when 'T :> Numerics.INumber<'T> - and 'T : struct - and 'T : (new : unit -> 'T) - and 'T :> ValueType> - (i: int) - (m: Matrix<'T>) : Vector<'T> = - - if i < 0 || i >= m.NumRows then - invalidArg "i" $"Row index out of bounds: {i}" - - let rowSpan = m.Data.AsSpan(i * m.NumCols, m.NumCols) - let result = Array.zeroCreate<'T> m.NumCols - rowSpan.CopyTo(result.AsSpan()) - result - - static member inline getRows (m: Matrix<'T>) : Vector<'T>[] = - Array.init m.NumRows (fun i -> Matrix.getRow i m) - - - static member inline getCol<'T - when 'T :> Numerics.INumber<'T> - and 'T : struct - and 'T : (new : unit -> 'T) - and 'T :> ValueType> - (j: int) - (m: Matrix<'T>) : Vector<'T> = - - if j < 0 || j >= m.NumCols then - invalidArg "j" $"Column index out of bounds: {j}" - - let result = Array.zeroCreate<'T> m.NumRows - let mutable offset = j - for i = 0 to m.NumRows - 1 do - result.[i] <- m.Data.[offset] - offset <- offset + m.NumCols - - result - - static member inline getCols<'T - when 'T :> Numerics.INumber<'T> - and 'T : struct - and 'T : (new : unit -> 'T) - and 'T :> ValueType> - (m: Matrix<'T>) : Vector<'T>[] = - - Array.init m.NumCols (fun j -> - let col = Array.zeroCreate<'T> m.NumRows - let mutable offset = j - for i = 0 to m.NumRows - 1 do - col.[i] <- m.Data.[offset] - offset <- offset + m.NumCols - col - ) - - - /// - /// Sets row of this matrix to the contents of . - /// The length of must match the number of columns in this matrix. - /// - /// The zero-based row index to set. - /// An array of new values for the row, of length equal to . - /// Thrown if is out of range. - /// Thrown if has incorrect length. - member this.SetRow(i: int, rowData: 'T[]) = - if i < 0 || i >= rows then - invalidArg (nameof i) "Row index out of range." - if rowData.Length <> cols then - invalidArg (nameof rowData) $"rowData must have length = {cols}." - - let offset = i * cols - Array.blit rowData 0 data offset cols - - - - - - // static member MatrixMultiply - - // (a: Matrix<'T>, b: Matrix<'T>, ?blockSize: int) : Matrix<'T> - // when 'T : struct - // and 'T : (new : unit -> 'T) - // and 'T :> INumber<'T> - // and 'T :> ValueType = - - // if a.Cols <> b.Rows then - // invalidArg "b" "Matrix dimensions must agree: a.Cols must equal b.Rows." - - // let blockSize = defaultArg blockSize 32 - - // let m = a.Rows - // let n = b.Cols - // let k = a.Cols - - // let result = Array.zeroCreate<'T> (m * n) - // let aData = a.Data - // let bData = b.Data - // let rData = result - - // let vSize = Vector<'T>.Count - - // // Blocked GEMM - // for i0 in 0 .. blockSize .. m - 1 do - // let iMax = min (i0 + blockSize) m - // for j0 in 0 .. blockSize .. n - 1 do - // let jMax = min (j0 + blockSize) n - // for k0 in 0 .. blockSize .. k - 1 do - // let kMax = min (k0 + blockSize) k - - // // Iterate over block - // for i in i0 .. iMax - 1 do - // for j in j0 .. jMax - 1 do - // let mutable sum = 'T.Zero - // let mutable kk = k0 - - // // SIMD accumulation - // while kk <= kMax - vSize do - // let aVec = Vector<'T>(aData, i * k + kk) - // let bVec = Vector<'T>([| for offset in 0 .. vSize - 1 -> bData.[(kk + offset) * n + j] |]) - // sum <- sum + Vector.Dot(aVec, bVec) - // kk <- kk + vSize - - // // Scalar tail - // while kk < kMax do - // sum <- sum + aData.[i * k + kk] * bData.[kk * n + j] - // kk <- kk + 1 - - // rData.[i * n + j] <- rData.[i * n + j] + sum diff --git a/src/FSharp.Stats/AlgTypes/MatrixExt.fs b/src/FSharp.Stats/AlgTypes/MatrixExt.fs deleted file mode 100644 index 5d4386ab6..000000000 --- a/src/FSharp.Stats/AlgTypes/MatrixExt.fs +++ /dev/null @@ -1,212 +0,0 @@ -namespace FSharp.Stats - -open System -open System.Runtime.InteropServices - - -[] -module Matrix = - -// /// Indexed fold over a matrix -// let inline foldi<'T when 'T :> Numerics.INumber<'T>> f (state: 'T) (m: Matrix<'T>) : 'T = -// let mutable acc = state -// for i = 0 to m.NumRows - 1 do -// for j = 0 to m.NumCols - 1 do -// acc <- f i j acc m.[i, j] -// acc - - - /// - /// Creates and returns a new with the same dimensions - /// as this matrix and a copy of the underlying data. - /// - let inline copy (m:Matrix<'T>) : Matrix<'T> = - // Make a copy of the data array - let newData = Array.copy m.Data - Matrix<'T>(m.NumRows, m.NumCols, newData) - - - /// Splits a matrix along row direction according to given indices. Returns (matrix including rows according to indices, rest) - /// - /// - /// - /// - /// - /// - /// - /// - let splitRows (indices:int[]) (m:Matrix<'T>) = - - let nRows,nCols = m.NumRows,m.NumCols - //let nm = Matrix.Generic.zero (nRows-indices.Length) nCols - //let nmi = Matrix.Generic.zero indices.Length nCols - let nm = Matrix.zeroCreate (nRows-indices.Length) nCols - let nmi = Matrix.zeroCreate indices.Length nCols - indices |> Array.sortInPlace - let rec loop nRowI nRowIi rowI = - match rowI with - | i as rowI when rowI < 0 -> nmi,nm - | i as rowI when nRowIi >= 0 && rowI = indices.[nRowIi] -> - for colI=0 to nCols-1 do - nmi.[nRowIi,colI] <- m.[rowI,colI] - loop (nRowI) (nRowIi-1) (rowI-1) - | _ -> //i as rowI when rowI <> indices.[ii] -> - for colI=0 to nCols-1 do - nm.[nRowI,colI] <- m.[rowI,colI] - loop (nRowI-1) (nRowIi) (rowI-1) - - loop (nRows-1-indices.Length) (indices.Length-1) (nRows-1) - - /// Splits a matrix along column direction according to given indices. Returns (matrix including cols according to indices, rest) - /// - /// - /// - /// - /// - /// - /// - /// - let splitCols (indices:int[]) (m:Matrix<_>) = - let nRows,nCols = m.NumRows,m.NumCols - //let nm = Matrix.Generic.zero nRows (nCols-indices.Length) - //let nmi = Matrix.Generic.zero nRows indices.Length - let nm = Matrix.zeroCreate nRows (nCols-indices.Length) - let nmi = Matrix.zeroCreate nRows indices.Length - indices |> Array.sortInPlace - let rec loop nColI nColIi colI = - match colI with - | i as colI when colI < 0 -> nmi,nm - | i as colI when nColIi >= 0 && colI = indices.[nColIi] -> - for rowI=0 to nRows-1 do - nmi.[rowI,nColIi] <- m.[rowI,colI] - loop (nColI) (nColIi-1) (colI-1) - | _ -> //i as rowI when rowI <> indices.[ii] -> - for rowI=0 to nRows-1 do - nm.[rowI,nColI] <- m.[rowI,colI] - loop (nColI-1) (nColIi) (colI-1) - - loop (nCols-1-indices.Length) (indices.Length-1) (nCols-1) - - /// - /// Creates a new matrix by permuting the rows of matrix according - /// to the permutation . That is, row i of the result is row - /// P(i) of . - /// - /// A permutation function that maps row indices. Should be valid - /// An r x c matrix whose rows will be reordered. - /// for all i in [0..r-1]. - /// - /// A new matrix of the same dimensions r x c, with rows permuted by . - /// - let permuteRowsBy (P: Permutation) (m: Matrix<'T>) : Matrix<'T> = - let r, c = m.NumRows, m.NumCols - let newData = Array.zeroCreate<'T> (r * c) - for i = 0 to r - 1 do - let srcRow = P i - // Copy row srcRow from M into row i of the new matrix - Array.blit m.Data (srcRow * c) newData (i * c) c - Matrix<'T>(r, c, newData) - - let ofRows (rows : 'T[][]) : Matrix<'T> = - Matrix.ofJaggedArray rows - - /// Creates a matrix from a sequence of row sequences - let inline ofRowSeq (rows: seq<#seq<'T>>) : Matrix<'T> = - // Convert the outer seq to an array of row-seqs - let rowArr = rows |> Seq.toArray - if rowArr.Length = 0 then - invalidArg "rows" "Cannot create a matrix from an empty sequence of rows." - - // Determine the number of columns by checking the first row’s length - let colCount = rowArr.[0] |> Seq.length - - // Verify all rows have the same length - for i in 1 .. rowArr.Length - 1 do - let currentLen = rowArr.[i] |> Seq.length - if currentLen <> colCount then - invalidArg "rows" (sprintf "Row %d has length %d, expected %d." i currentLen colCount) - - // Flatten all row-seqs into a single array (row-major order) - let data = - rowArr - |> Array.collect (fun rowSeq -> rowSeq |> Seq.toArray) - - // Construct the matrix - Matrix<'T>(rowArr.Length, colCount, data) - - let mapiRows (f: int -> Vector<'T> -> Vector<'U>) (m:Matrix<'T>) : Matrix<'U> = - Matrix.getRows m - |> Array.mapi (fun i v -> f i v) - |> ofRows - - let ofCols (cols : 'T[][]) : Matrix<'T> = - Matrix.ofJaggedArray cols - |> fun m -> m.Transpose() - - let mapiCols (f: int -> Vector<'T> -> Vector<'U>) (m:Matrix<'T>) : Matrix<'U> = - let cols = - Array.init m.NumCols (fun j -> - let col = Array.zeroCreate<'T> m.NumRows - let mutable offset = j - for i = 0 to m.NumRows - 1 do - col.[i] <- m.Data.[offset] - offset <- offset + m.NumCols - f j col - ) - ofCols cols - - /// - /// Applies a function to each element of the matrix, - /// returning a new matrix with updated values. The iteration occurs in - /// row-major order for performance. - /// - /// - /// A function taking (rowIndex, colIndex, oldValue) - /// and returning the new value for that position. - /// - /// A new Matrix with updated elements. - let mapi (f: int -> int -> 'T -> 'U) (A: Matrix<'T>) : Matrix<'U> = - let newData = Array.zeroCreate<'U> A.Data.Length - let rows, cols = A.NumRows, A.NumCols - for i in 0 .. rows - 1 do - let rowOffset = i * cols - for j in 0 .. cols - 1 do - let idx = rowOffset + j - newData.[idx] <- f i j A.Data.[idx] - Matrix<'U>(rows, cols, newData) - - - let map (f: 'T -> 'U) (m:Matrix<'T>) : Matrix<'U> = - let r, c = m.NumRows, m.NumCols - let newData = - m.Data |> Array.map f - Matrix<'U>(r, c, newData) - - - /// - /// Folds over each element in row-major order, accumulating a result of type 'State. - /// The callback receives (currentState, rowIndex, colIndex, elementValue), - /// and returns the new state. - /// - /// A function taking (state, i, j, value) -> newState. - /// The initial accumulation state. - /// The matrix to fold over. - /// The final accumulated state. - let foldi - (f : int -> int -> 'State -> 'T -> 'State ) - (initialState : 'State) - (A : Matrix<'T>) - : 'State = - - let mutable acc = initialState - let rows, cols = A.NumRows, A.NumCols - for i in 0 .. rows - 1 do - let rowOffset = i * cols - for j in 0 .. cols - 1 do - let idx = rowOffset + j - acc <- f i j acc A.Data.[idx] - acc - - /// Sums all elements in the matrix. - let sum (m:Matrix<'T>) : 'T = - m.Data |> Vector.sum \ No newline at end of file diff --git a/src/FSharp.Stats/AlgTypes/SIMDUtils.fs b/src/FSharp.Stats/AlgTypes/SIMDUtils.fs deleted file mode 100644 index 2d12c9d19..000000000 --- a/src/FSharp.Stats/AlgTypes/SIMDUtils.fs +++ /dev/null @@ -1,445 +0,0 @@ -namespace FSharp.Stats.Acceleration - -open System -open System.Runtime.InteropServices -open System.Runtime.CompilerServices - - - - - -/// -/// A utility class for performing SIMD (Single Instruction, Multiple Data) operations on arrays. -/// -type SIMDUtils() = - - /// - /// Applies a safe element-wise unary operation on an array using SIMD for performance. - /// - /// The numeric type of the array elements. - /// A function that performs the SIMD operation on a vector. - /// A fallback function for scalar operations. - /// The input array. - /// An array with the operation applied to each element. - static member inline map<'T when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T :> ValueType> - (fv:Numerics.Vector<'T> -> Numerics.Vector<'T>) - (f: 'T -> 'T) - (v: 'T[]) : 'T[] = - - let length = v.Length - let slotSize = Numerics.Vector<'T>.Count - let slotCount = length / slotSize - let ceiling = slotSize * slotCount - - let results = Array.zeroCreate<'T> length - let rsSpan = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(results.AsSpan()) - let vSpan = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(v.AsSpan()) - - for i = 0 to slotCount - 1 do - rsSpan.[i] <- fv vSpan[i] - - for i = ceiling to length - 1 do - results.[i] <- f v.[i] - - results - - /// - /// Applies an element-wise binary operation on two arrays using SIMD for performance. - /// - /// The numeric type of the array elements. - /// A function that performs the SIMD operation on two vectors. - /// A fallback function for scalar operations. - /// The first input array. - /// The second input array. - /// An array with the operation applied to each pair of elements. - static member inline map2Unchecked<'T when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T :> ValueType> - (fv:Numerics.Vector<'T> -> Numerics.Vector<'T> -> Numerics.Vector<'T>) - (f:'T -> 'T -> 'T) - (v1: 'T[]) - (v2: 'T[]) = - - let length = v1.Length - let slotSize= Numerics.Vector<'T>.Count - let slotCount = length / slotSize - let ceiling = slotSize * slotCount - - let results = Array.zeroCreate<'T> length - let rsSpan = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(results.AsSpan()) - let v1Span = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(v1.AsSpan()) - let v2Span = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(v2.AsSpan()) - - for i=0 to slotCount - 1 do - rsSpan.[i] <- fv v1Span[i] v2Span[i] - - for i=ceiling to v1.Length - 1 do - results.[i] <- f v1.[i] v2[i] - - results - - /// - /// Reduces an array to a single value using a binary operation, with SIMD optimization. - /// - /// The numeric type of the array elements. - /// A function that performs the SIMD reduction on two vectors. - /// A fallback function for scalar reduction. - /// The initial value for the reduction. - /// The input array. - /// The result of the reduction. - static member inline fold<'T when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T :> ValueType> - (fv:Numerics.Vector<'T> -> Numerics.Vector<'T> -> Numerics.Vector<'T>) - (f: 'T -> 'T -> 'T) - (zero: 'T) - (v: 'T[]) : 'T = - - let length = v.Length - let slotSize = Numerics.Vector<'T>.Count - let slotCount = length / slotSize - let ceiling = slotSize * slotCount - - let vSpan: Span> = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(v.AsSpan()) - - let mutable accVec = Numerics.Vector<'T>(zero) - - for i = 0 to slotCount - 1 do - accVec <- fv accVec vSpan[i] - - let mutable acc = accVec.[0] - for i = 1 to slotSize - 1 do - acc <- f acc accVec.[i] - - for i = ceiling to length - 1 do - acc <- f acc v[i] - - acc - - /// - /// Applies an element-wise binary operation between an array and a scalar using SIMD for performance. - /// - /// The numeric type of the array elements. - /// A function that performs the SIMD operation on a vector and a scalar vector. - /// A fallback function for scalar operations. - /// The input array. - /// The scalar value. - /// An array with the operation applied to each element and the scalar. - static member inline mapScalar<'T when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T :> ValueType> - (fv:Numerics.Vector<'T> -> Numerics.Vector<'T> -> Numerics.Vector<'T> ) - (f:'T -> 'T -> 'T) - (v1:'T[]) - (scalar:'T) : 'T[] = - - let length = v1.Length - let slotSize= Numerics.Vector<'T>.Count - let slotCount = length / slotSize - let ceiling = slotSize * slotCount - - let results = Array.zeroCreate<'T> length - let rsSpan = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(results.AsSpan()) - let v1Span = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(v1.AsSpan()) - let scalarVec = Numerics.Vector(scalar) - - for i=0 to slotCount - 1 do - rsSpan.[i] <- fv v1Span[i] scalarVec - - for i=ceiling to v1.Length - 1 do - results.[i] <- f v1.[i] scalar - - results - - - static member inline mapFoldUnchecked<'T - when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T :> ValueType> - (fMapSimd: Numerics.Vector<'T> -> Numerics.Vector<'T>, - fMap: 'T -> 'T, - fReduceSimd: Numerics.Vector<'T> -> Numerics.Vector<'T> -> Numerics.Vector<'T>, - fReduceScalar: 'T -> 'T -> 'T, - zero: 'T, - input: ReadOnlySpan<'T>) - : 'T = - - let len = input.Length - let simdSize = Numerics.Vector<'T>.Count - let simdBlocks = len / simdSize - let tailStart = simdBlocks * simdSize - - // SIMD map + accumulation - let mutable accVec = Numerics.Vector<'T>(zero) - let inputVec = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(input) - - for i = 0 to simdBlocks - 1 do - let mapped = fMapSimd inputVec[i] - accVec <- fReduceSimd accVec mapped - - // Reduce SIMD accumulator to scalar - let mutable acc = accVec.[0] - for i = 1 to simdSize - 1 do - acc <- fReduceScalar acc accVec.[i] - - // Scalar tail - for i = tailStart to len - 1 do - acc <- fReduceScalar acc (fMap input[i]) - - acc - - - -type SIMDRangeUtils = - - /// In-place transformation of v[startIndex..(startIndex + count - 1)] - /// using a SIMD operation (fv) for chunked parts and a scalar function (f) for leftovers. - static member inline mapRangeInPlace<'T when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T :> ValueType> - (fv : Numerics.Vector<'T> -> Numerics.Vector<'T>) - (f : 'T -> 'T) - (startIndex : int) - (count : int) - (v : 'T[]) : unit = - - // 1) Validate parameters - if startIndex < 0 || count < 0 || (startIndex + count) > v.Length then - invalidArg (nameof count) "Invalid start index or count." - - // 2) Early exit if there's nothing to do - if count = 0 then - // nothing to do - () - - else - // 3) Compute how many full Vector<'T>.Count chunks we can process - let simdSize = Numerics.Vector<'T>.Count - let simdCount = count / simdSize - let tailStart = simdCount * simdSize - - // 4) Slice the relevant portion of v - let span = v.AsSpan(startIndex, count) - // 5) Interpret that span as a span of Vector<'T> - let vecSpan = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(span) - - // 6) Apply fv to each SIMD chunk - for i in 0 .. simdCount - 1 do - vecSpan.[i] <- fv vecSpan.[i] - - // 7) Handle leftover elements with f - for i in tailStart .. count - 1 do - let idx = startIndex + i - v.[idx] <- f v.[idx] - - - - /// In-place combination of two arrays (dst, src) over 'count' elements, - /// starting from 'dstStartIndex' and 'srcStartIndex' respectively. - /// Uses 'fv' for chunked SIMD processing and 'f' for leftover scalar elements. - static member inline map2RangeInPlace<'T when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T :> ValueType> - (fv : Numerics.Vector<'T> -> Numerics.Vector<'T> -> Numerics.Vector<'T>) - (f : 'T -> 'T -> 'T) - (dstStartIndex : int) - (srcStartIndex : int) - (count : int) - (dst : 'T[]) - (src : 'T[]) : unit = - - // 1) Validate parameters - if dstStartIndex < 0 || srcStartIndex < 0 || count < 0 then - invalidArg (nameof count) "Start indices and count must be non-negative." - if dstStartIndex + count > dst.Length then - invalidArg (nameof dstStartIndex) "Destination range out of bounds." - if srcStartIndex + count > src.Length then - invalidArg (nameof srcStartIndex) "Source range out of bounds." - - // 2) Early exit if there's nothing to do - if count = 0 then - () - else - // 3) How many full 'Vector<'T>' chunks fit into 'count'? - let simdSize = Numerics.Vector<'T>.Count - let simdCount = count / simdSize - let tailStart = simdCount * simdSize - - // 4) Create Spans for the subranges - let dstSpan = dst.AsSpan(dstStartIndex, count) - let srcSpan = src.AsSpan(srcStartIndex, count) - - // 5) Cast to Span> for chunked SIMD ops - let dstVecSpan = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(dstSpan) - let srcVecSpan = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(srcSpan) - - // 6) Apply 'fv' to each pair of SIMD chunks - for i = 0 to simdCount - 1 do - dstVecSpan.[i] <- fv dstVecSpan.[i] srcVecSpan.[i] - - // 7) Handle leftover scalar elements - for i = tailStart to count - 1 do - let dstIdx = dstStartIndex + i - let srcIdx = srcStartIndex + i - dst.[dstIdx] <- f dst.[dstIdx] src.[srcIdx] - - - /// Dot product of arr1[off1..off1+count-1] and arr2[off2..off2+count-1]. - /// Uses SIMD if available; otherwise a naive loop. - static member inline dotRange<'T when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T :> ValueType> - (arr1: 'T[]) (off1: int) - (arr2: 'T[]) (off2: int) - (count: int) = - - if Numerics.Vector.IsHardwareAccelerated && count >= Numerics.Vector<'T>.Count then - let simdSize = Numerics.Vector<'T>.Count - let simdCount = count / simdSize - let tailStart = simdCount * simdSize - - let mutable sumVec = Numerics.Vector<'T>.Zero - - let span1 = arr1.AsSpan(off1, count) - let span2 = arr2.AsSpan(off2, count) - - let vec1 = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(span1) - let vec2 = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(span2) - - for i = 0 to simdCount - 1 do - sumVec <- sumVec + (vec1.[i] * vec2.[i]) - - // Reduce the SIMD lanes - let mutable simdSum = LanguagePrimitives.GenericZero<'T> - for lane = 0 to simdSize - 1 do - simdSum <- simdSum + sumVec.[lane] - - // Handle leftover tail - let mutable tailSum = LanguagePrimitives.GenericZero<'T> - for i = tailStart to count - 1 do - tailSum <- tailSum + arr1.[off1 + i] * arr2.[off2 + i] - - simdSum + tailSum - else - // Fallback naive loop - let mutable acc = LanguagePrimitives.GenericZero<'T> - for i = 0 to count - 1 do - acc <- acc + arr1.[off1 + i] * arr2.[off2 + i] - acc - - -// - -// // -// static member map2Unchecked<'T when 'T :> Numerics.INumber<'T> -// and 'T : (new: unit -> 'T) -// and 'T : struct -// and 'T :> ValueType> -// (fv:Numerics.Vector<'T> -> Numerics.Vector<'T> -> Numerics.Vector<'T>) -// (f:'T -> 'T -> 'T) -// (v1: 'T[]) -// (v2: 'T[]) : 'T[] = - - -// // Gets the total number of elements of this vector -// let length = v1.Length -// // -// let slotSize= Numerics.Vector<'T>.Count -// // Number of slots (rasterized vectors) -// let slotCount = length / slotSize -// // Index at which the non rasterd remain starts -// let ceiling = slotSize * slotCount - -// // Allocate the result array -// let results = Array.zeroCreate<'T> length -// let rsSpan = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(results.AsSpan()) -// let v1Span = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(v1.AsSpan()) -// let v2Span = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(v2.AsSpan()) - -// // Perform SIMD addition for chunks -// for i=0 to slotCount - 1 do -// rsSpan.[i] <- fv v1Span[i] v2Span[i] - -// // Handle the remaining elements -// for i=ceiling to v1.Length - 1 do -// results.[i] <- f v1.[i] v2[i] - -// results - -// type SIMDMatrixUtils() = - -// static member map2<'T when 'T :> Numerics.INumber<'T> -// and 'T : (new: unit -> 'T) -// and 'T : struct -// and 'T :> ValueType> -// (fVec: Numerics.Vector<'T> -> Numerics.Vector<'T> -> Numerics.Vector<'T>) -// (fScalar: 'T -> 'T -> 'T) -// (a: Matrix<'T>) -// (b: Matrix<'T>) -// : Matrix<'T> = - -// if a.Rows <> b.Rows || a.Cols <> b.Cols then -// invalidArg "b" "Matrix dimensions must match" - -// let len = a.Data.Length -// let result = Array.zeroCreate<'T> len - -// let simdSize = Numerics.Vector<'T>.Count -// let simdCount = len / simdSize -// let tailStart = simdCount * simdSize - -// // Cast arrays to Vector<'T> spans -// let aVec = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(a.Data.AsSpan()) -// let bVec = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(b.Data.AsSpan()) -// let rVec = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(result.AsSpan()) - -// for i = 0 to simdCount - 1 do -// rVec.[i] <- fVec aVec.[i] bVec.[i] - -// for i = tailStart to len - 1 do -// result.[i] <- fScalar a.Data.[i] b.Data.[i] - -// Matrix(a.Rows, a.Cols, result) - - -// static member mapScalar<'T when 'T :> Numerics.INumber<'T> -// and 'T : (new: unit -> 'T) -// and 'T : struct -// and 'T :> ValueType> -// (fv: Numerics.Vector<'T> -> Numerics.Vector<'T> -> Numerics.Vector<'T>) -// (f: 'T -> 'T -> 'T) -// (matrix: Matrix<'T>) -// (scalar: 'T) -// : Matrix<'T> = - -// let length = matrix.Data.Length -// let result = Array.zeroCreate<'T> length - -// let slotSize = Numerics.Vector<'T>.Count -// let slotCount = length / slotSize -// let ceiling = slotCount * slotSize - -// let scalarVec = Numerics.Vector<'T>(scalar) - -// let mSpan = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(matrix.Data.AsSpan()) -// let rSpan = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(result.AsSpan()) - -// // SIMD chunk-wise operation -// for i = 0 to slotCount - 1 do -// rSpan.[i] <- fv mSpan.[i] scalarVec - -// // Scalar fallback for remainder -// for i = ceiling to length - 1 do -// result.[i] <- f matrix.Data.[i] scalar - -// Matrix(matrix.Rows, matrix.Cols, result) diff --git a/src/FSharp.Stats/AlgTypes/Vector.fs b/src/FSharp.Stats/AlgTypes/Vector.fs deleted file mode 100644 index 5171c0a8b..000000000 --- a/src/FSharp.Stats/AlgTypes/Vector.fs +++ /dev/null @@ -1,266 +0,0 @@ -namespace FSharp.Stats - -open System -open System.Runtime.InteropServices - -/// Vector as an array type alias -type Vector<'T when 'T :> Numerics.INumber<'T>> = 'T [] - - -type Vector = - - - static member inline zeroCreate<'T when 'T :> Numerics.INumber<'T>> count : Vector<'T> = - Array.zeroCreate<'T> count - - - /// Adds two vectors element-wise. - /// The first vector. - /// The second vector. - /// A new vector containing the element-wise sum of the two input vectors. - /// Thrown when the vectors have different lengths. - static member inline add<'T when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T :> ValueType> (v1 : Vector<'T>) (v2 : Vector<'T>) : Vector<'T> = - - - if v1.Length <> v2.Length then - invalidArg "" "Cannot add two vectors of different dimensions." - - if Numerics.Vector.IsHardwareAccelerated then - Acceleration.SIMDUtils.map2Unchecked (+) (+) v1 v2 - else - Array.map2 (+) v1 v2 - - - /// Subtracts the second vector from the first vector element-wise. - /// The first vector. - /// The second vector. - /// A new vector containing the element-wise difference of the two input vectors. - /// Thrown when the vectors have different lengths. - static member inline subtract<'T when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T :> ValueType> (v1 : Vector<'T>) (v2 : Vector<'T>) : Vector<'T> = - - if v1.Length <> v2.Length then - invalidArg "" "Cannot subtract two vectors of different dimensions." - - if Numerics.Vector.IsHardwareAccelerated then - Acceleration.SIMDUtils.map2Unchecked (-) (-) v1 v2 - else - Array.map2 (-) v1 v2 - - - /// Multiplies two vectors element-wise. - /// The first vector. - /// The second vector. - /// A new vector containing the element-wise product of the two input vectors. - /// Thrown when the vectors have different lengths. - static member inline multiply<'T when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T :> ValueType> (v1 : Vector<'T>) (v2 : Vector<'T>) : Vector<'T> = - - if v1.Length <> v2.Length then - invalidArg "" "Cannot multiply two vectors of different dimensions." - - if Numerics.Vector.IsHardwareAccelerated then - Acceleration.SIMDUtils.map2Unchecked ( * ) ( * ) v1 v2 - else - Array.map2 ( * ) v1 v2 - - - /// Divides the first vector by the second vector element-wise. - /// The first vector. - /// The second vector. - /// A new vector containing the element-wise division of the two input vectors. - /// Thrown when the vectors have different lengths. - static member inline divide<'T when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T :> ValueType> (v1 : Vector<'T>) (v2 : Vector<'T>) : Vector<'T> = - if v1.Length <> v2.Length then - invalidArg "" "Cannot divide two vectors of different dimensions." - - if Numerics.Vector.IsHardwareAccelerated then - Acceleration.SIMDUtils.map2Unchecked ( / ) ( / ) v1 v2 - else - Array.map2 ( / ) v1 v2 - - - /// Adds a scalar to each element of the vector. - /// The vector. - /// The scalar value to add. - /// A new vector with the scalar added to each element. - static member inline addScalar<'T when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T :> ValueType> - (scalar:'T) (v:Vector<'T>) : Vector<'T> = - - if Numerics.Vector.IsHardwareAccelerated then - Acceleration.SIMDUtils.mapScalar (+) (+) v scalar - else - Array.map (fun x -> x + scalar) v - - - /// Subtracts a scalar from each element of the vector. - /// The vector. - /// The scalar value to subtract. - /// A new vector with the scalar subtracted from each element. - static member inline subtractScalar<'T when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T :> ValueType> - (scalar:'T) (v:Vector<'T>) : Vector<'T> = - if Numerics.Vector.IsHardwareAccelerated then - Acceleration.SIMDUtils.mapScalar (-) (-) v scalar - else - Array.map (fun x -> x - scalar) v - - - /// Multiplies each element of the vector by a scalar. - /// The vector. - /// The scalar value to multiply by. - /// A new vector with each element multiplied by the scalar. - static member inline multiplyScalar<'T when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T :> ValueType> - (scalar:'T) (v:Vector<'T>) : Vector<'T> = - - if Numerics.Vector.IsHardwareAccelerated then - Acceleration.SIMDUtils.mapScalar ( * ) ( * ) v scalar - else - Array.map (fun x -> x * scalar) v - - - /// Divides each element of the vector by a scalar. - /// The vector. - /// The scalar value to divide by. - /// A new vector with each element divided by the scalar. - static member inline divideScalar<'T when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T :> ValueType> - (scalar:'T) (v:Vector<'T>) : Vector<'T> = - - if Numerics.Vector.IsHardwareAccelerated then - Acceleration.SIMDUtils.mapScalar ( / ) ( / ) v scalar - else - Array.map (fun x -> x / scalar) v - - /// Computes the sum of all elements in the vector. - /// The vector. - /// The sum of all elements in the vector. - static member inline sum<'T when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T :> ValueType> - (v:Vector<'T>) : 'T = - let zero = LanguagePrimitives.GenericZero<'T> - if Numerics.Vector.IsHardwareAccelerated then - Acceleration.SIMDUtils.fold (+) (+) zero v - else - Array.sum v - - /// Computes the product of all elements in the vector. - /// The vector. - /// The product of all elements in the vector. - static member inline product<'T when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T :> ValueType> - (v:Vector<'T>) : 'T = - let one = LanguagePrimitives.GenericOne<'T> - if Numerics.Vector.IsHardwareAccelerated then - Acceleration.SIMDUtils.fold (*) (*) one v - else - Array.fold ( * ) one v - - - /// Computes the mean of the elements in the vector. - /// The vector. - /// The mean of the elements in the vector. - /// Thrown when the vector is empty. - static member inline mean<'T when 'T :> Numerics.INumber<'T> - and 'T : (static member DivideByInt : 'T * int -> 'T) - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T :> ValueType> - (v: Vector<'T>) : 'T = - if v.Length = 0 then invalidArg "v" "Cannot compute mean of empty vector." - let sum = Vector.sum v - LanguagePrimitives.DivideByInt<'T> sum v.Length - - /// Computes the dot product ab^T of two vectors. - /// The first vector. - /// The second vector. - /// The dot product of the two vectors. - /// Thrown when the vectors have different lengths. - static member inline dot<'T when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T :> ValueType> (v1 : Vector<'T>) (v2 : Vector<'T>) : 'T = - - if v1.Length <> v2.Length then - invalidArg "v2" "Vector must have the same length to compute the dot product." - if Numerics.Vector.IsHardwareAccelerated then - let length = v1.Length - let slotSize = Numerics.Vector<'T>.Count - let slotCount = length / slotSize - let ceiling = slotSize * slotCount - - let v1Span = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(v1.AsSpan()) - let v2Span = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(v2.AsSpan()) - let mutable result = Numerics.Vector<'T>.Zero - //let mutable scalarResult = LanguagePrimitives.GenericZero<'T> - - for i = 0 to slotCount - 1 do - result <- Numerics.Vector.Add(result, Numerics.Vector.Multiply(v1Span.[i], v2Span.[i])) - //scalarResult <- Numerics.Vector.Sum result - - let mutable scalarResult = Numerics.Vector.Sum result - - for i = ceiling to v1.Length - 1 do - scalarResult <- scalarResult + (v1.[i] * v2.[i]) - - scalarResult - else - Array.fold2 (fun acc x y -> acc + (x * y)) LanguagePrimitives.GenericZero v1 v2 - - - /// Computes the Euclidean norm (magnitude) of the vector. - /// The vector. - /// The Euclidean norm of the vector. - static member inline norm<'T when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T :> ValueType - and 'T :> Numerics.IRootFunctions<'T>> - (v:Vector<'T>) : 'T = - - let sumSquares = Vector.dot v v - 'T.Sqrt sumSquares - - static member inline min<'T when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T : comparison - and 'T :> ValueType> - (v:Vector<'T>) : 'T = - if v.Length = 0 then invalidArg "v" "Cannot compute min of empty vector." - Acceleration.SIMDUtils.fold (fun a b -> Numerics.Vector.Min(a, b)) min v.[0] v - - static member inline max<'T when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T : comparison - and 'T :> ValueType> - (v:Vector<'T>) : 'T = - if v.Length = 0 then invalidArg "v" "Cannot compute min of empty vector." - Acceleration.SIMDUtils.fold (fun a b -> Numerics.Vector.Max(a, b)) max v.[0] v - - diff --git a/src/FSharp.Stats/AlgTypes/VectorExt.fs b/src/FSharp.Stats/AlgTypes/VectorExt.fs deleted file mode 100644 index 3c72a6f84..000000000 --- a/src/FSharp.Stats/AlgTypes/VectorExt.fs +++ /dev/null @@ -1,226 +0,0 @@ -namespace FSharp.Stats - -open System -open System.Runtime.InteropServices - -[] -module Vector = - - /// Computes the vector cross product a^Tb - /// The first vector is column vector. - /// The second vector is the row vector. - /// The cross product (or outer product) of the two vectors. - let inline cross<'T when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T : equality - and 'T :> ValueType> (colvec: Vector<'T>) (rowvec:Vector<'T>) : Matrix<'T> = - //TODO: SIMD Acceleration! - - if colvec.Length <> rowvec.Length then - invalidArg "" "Vector must have the same length to compute the dot product." - let n = colvec.Length - let m = rowvec.Length - - // Allocate the n*m storage - let data = Array.zeroCreate<'T> (n * m) - - // Fill with colvec[i] * rowvec[j], typical row-major arrangement - for i in 0 .. n - 1 do - for j in 0 .. m - 1 do - data.[i * m + j] <- colvec.[i] * rowvec.[j] - - // Build the matrix (n x m) - Matrix<'T>(n, m, data) - - - /// Indexed fold over a vector - let inline foldi<'T when 'T :> Numerics.INumber<'T>> f (state: 'T) (v: Vector<'T>) : 'T = - let mutable acc = state - for i = 0 to v.Length - 1 do - acc <- f i acc v.[i] - acc - - /// Indexed map over a vector - let inline mapi<'T when 'T :> Numerics.INumber<'T>> (f: int -> 'T -> 'T) (v: Vector<'T>) : Vector<'T> = - Array.mapi f v - - /// Filter vector elements by predicate - let inline filter<'T when 'T :> Numerics.INumber<'T>> (predicate: 'T -> bool) (v: Vector<'T>) : Vector<'T> = - Array.filter predicate v - - /// Initialize vector by index-based generator - let inline init<'T when 'T :> Numerics.INumber<'T>> (n: int) (f: int -> 'T) : Vector<'T> = - Array.init n f - - /// Extract a slice from a vector - let inline slice<'T when 'T :> Numerics.INumber<'T>> (start: int) (length: int) (v: Vector<'T>) : Vector<'T> = - Array.sub v start length - - /// Find index of maximum value - let inline argmax<'T when 'T :> Numerics.INumber<'T> and 'T : comparison> (v: Vector<'T>) : int = - let mutable maxIdx = 0 - let mutable maxVal = v.[0] - for i = 1 to v.Length - 1 do - if v.[i] > maxVal then - maxVal <- v.[i] - maxIdx <- i - maxIdx - - /// Find index of minimum value - let inline argmin<'T when 'T :> Numerics.INumber<'T> and 'T : comparison> (v: Vector<'T>) : int = - let mutable minIdx = 0 - let mutable minVal = v.[0] - for i = 1 to v.Length - 1 do - if v.[i] < minVal then - minVal <- v.[i] - minIdx <- i - minIdx - - /// Pad vector to a given length with a constant value - let inline padRight<'T when 'T :> Numerics.INumber<'T>> (length: int) (value: 'T) (v: Vector<'T>) : Vector<'T> = - if v.Length >= length then v - else - Array.init length (fun i -> if i < v.Length then v.[i] else value) - - /// Zip two vectors into (index, left, right) - let inline zip<'T when 'T :> Numerics.INumber<'T>> (v1: Vector<'T>) (v2: Vector<'T>) : (int * 'T * 'T)[] = - Array.init (min v1.Length v2.Length) (fun i -> i, v1.[i], v2.[i]) - - - - /// Find index of minimum value using projection - let inline argminBy<'T, 'U - when 'T :> Numerics.INumber<'T> and 'U : comparison> - (f: 'T -> 'U) (v: Vector<'T>) : int = - let mutable minIdx = 0 - let mutable minVal = f v.[0] - for i = 1 to v.Length - 1 do - let candidate = f v.[i] - if candidate < minVal then - minVal <- candidate - minIdx <- i - minIdx - - /// Find index of maximum value using projection - let inline argmaxBy<'T, 'U - when 'T :> Numerics.INumber<'T> and 'U : comparison> - (f: 'T -> 'U) (v: Vector<'T>) : int = - let mutable maxIdx = 0 - let mutable maxVal = f v.[0] - for i = 1 to v.Length - 1 do - let candidate = f v.[i] - if candidate > maxVal then - maxVal <- candidate - maxIdx <- i - maxIdx - - /// Try to find index of first matching element - let inline tryFindIndex<'T when 'T :> Numerics.INumber<'T>> (predicate: 'T -> bool) (v: Vector<'T>) : int option = - let mutable i = 0 - let mutable found = false - while i < v.Length && not found do - if predicate v.[i] then found <- true - else i <- i + 1 - if found then Some i else None - - /// Find index of first matching element or throw - let inline findIndex<'T when 'T :> Numerics.INumber<'T>> (predicate: 'T -> bool) (v: Vector<'T>) : int = - match tryFindIndex predicate v with - | Some i -> i - | None -> failwith "Element not found." - - /// Enumerate non-zero elements with index - let inline enumerateNonZero<'T when 'T :> Numerics.INumber<'T> and 'T : equality> (v: Vector<'T>) : (int * 'T)[] = - v - |> Array.mapi (fun i x -> i, x) - |> Array.filter (fun (_, x) -> x <> 'T.Zero) - - /// Split a vector into prefix and suffix at a given index - let inline split<'T when 'T :> Numerics.INumber<'T>> (index: int) (v: Vector<'T>) : Vector<'T> * Vector<'T> = - Array.sub v 0 index, Array.sub v index (v.Length - index) - - /// Chunk a vector into equally sized pieces (last may be shorter) - let inline chunk<'T when 'T :> Numerics.INumber<'T>> (chunkSize: int) (v: Vector<'T>) : Vector<'T>[] = - let len = v.Length - [| for i in 0 .. chunkSize .. len - 1 -> - let size = min chunkSize (len - i) - Array.sub v i size |] - - /// Sliding window over the vector - let inline windowed<'T when 'T :> Numerics.INumber<'T>> (windowSize: int) (v: Vector<'T>) : Vector<'T>[] = - if windowSize > v.Length then [||] - else - [| for i in 0 .. v.Length - windowSize -> - Array.sub v i windowSize |] - - - /// - /// Splits the vector `v` into two parts based on `indices`. - /// The elements at positions in `indices` end up in `nvi`, - /// all others go into `nv`. - /// - /// Zero-based positions to extract from `v`. - /// The full vector to split. - /// (nvi, nv): nvi contains the elements at `indices`, nv contains the rest. - let splitVector (indices: int[]) (v: Vector<'T>) = - - Array.sortInPlace indices - - let n = v.Length - let k = indices.Length - - let nvi = Vector.zeroCreate<'T> k - let nv = Vector.zeroCreate<'T> (n - k) - - let mutable iInd = 0 - let mutable iNvi = 0 - let mutable iNv = 0 - - for i = 0 to n - 1 do - // If we've not exhausted the `indices` array AND the current i matches indices.[iInd] - if iInd < k && i = indices.[iInd] then - nvi.[iNvi] <- v.[i] - iNvi <- iNvi + 1 - iInd <- iInd + 1 - else - nv.[iNv] <- v.[i] - iNv <- iNv + 1 - - nvi, nv - - /// - /// Creates a new vector that is the result of applying the permutation - /// to the vector . The element result.[i] becomes b.[P(i)]. - /// - /// A permutation function of type int -> int, - /// The original vector to be permuted. Must have length n. - /// typically created by Permutation.ofArray or Permutation.ofFreshArray. - /// - /// A new vector of the same length n, reordered according to . - /// - let permuteBy (P: Permutation) (b: Vector<'T>) : Vector<'T> = - let n = b.Length - let result = Array.zeroCreate<'T> n - for i = 0 to n - 1 do - result.[i] <- b.[P i] - result - - /// - let inline ofSeq (s:seq<'T>) : Vector<'T> = - s |> Array.ofSeq - - - /// - let inline pow (power: 'T) (v:Vector<'T>) : Vector<'T> = - v |> Array.map (fun x -> GenericMath.pow x power) - - - /// Returns a subvector from offset i to the end of the vector. - let inline sub (i: int) (v: Vector<'T>) : Vector<'T> = - if i < 0 || i > v.Length then - invalidArg (nameof i) "Index out of bounds." - let len = v.Length - i - let res = Array.zeroCreate<'T> len - Array.blit v i res 0 len - res \ No newline at end of file diff --git a/src/FSharp.Stats/AlgTypes/VectorOps.fs b/src/FSharp.Stats/AlgTypes/VectorOps.fs deleted file mode 100644 index 6ca4e458b..000000000 --- a/src/FSharp.Stats/AlgTypes/VectorOps.fs +++ /dev/null @@ -1,54 +0,0 @@ -namespace FSharp.Stats - -open System - -// Fallback implementation container (Type class) -type VectorOps = - - - static member inline Plus (a: Vector<'T>, b: Vector<'T>) = Vector.add a b - static member inline Plus (a: Vector<'T>, b: 'T) = Vector.addScalar b a - static member inline Plus (a: 'T, b: Vector<'T>) = Vector.addScalar a b - - static member inline Minus (a: Vector<'T>, b: Vector<'T>) = Vector.subtract a b - static member inline Minus (a: Vector<'T>, b: 'T) = Vector.subtractScalar b a - - - static member inline Multiply (a: Vector<'T>, b: Vector<'T>) = Vector.multiply a b - static member inline Multiply (a: Vector<'T>, b: 'T) = Vector.multiplyScalar b a - static member inline Multiply (a: 'T, b: Vector<'T>) = Vector.multiplyScalar a b - - static member inline Divide (a: Vector<'T>, b: Vector<'T>) = Vector.divide a b - static member inline Divide (a: Vector<'T>, b: 'T) = Vector.divideScalar b a - - static member inline Power (a: Vector<'T>, power: 'T) = Vector.pow power a - - -// Dispatcher types (Instance resolution) -type Plus = static member inline Invoke (a: ^A, b: ^B) = ((^A or ^B or VectorOps) : (static member Plus : ^A * ^B -> _)(a, b)) -type Minus = static member inline Invoke (a: ^A, b: ^B) = ((^A or ^B or VectorOps) : (static member Minus : ^A * ^B -> _)(a, b)) -type Multiply = static member inline Invoke (a: ^A, b: ^B) = ((^A or ^B or VectorOps) : (static member Multiply : ^A * ^B -> _)(a, b)) -type Divide = static member inline Invoke (a: ^A, b: ^B) = ((^A or ^B or VectorOps) : (static member Divide : ^A * ^B -> _)(a, b)) -type Power = static member inline Invoke (a: ^A, b: ^B) = ((^A or ^B or VectorOps) : (static member Power : ^A * ^B -> _)(a, b)) - -// Operators -[] -module VectorOpsSymbols = - let inline (.+) a b = Plus.Invoke(a, b) - let inline (.-) a b = Minus.Invoke(a, b) - let inline (.*) a b = Multiply.Invoke(a, b) - let inline (./) a b = Divide.Invoke(a, b) - let inline (.^) a b = Power.Invoke(a, b) - // Dot product ( @ ) - - -//// A type extension on `'T[]` so you can do `myArray.Transposed`. -//module ArrayExtensions = - -// type Array with - -// member this.Transpose - -// with get () = -// RowVector<'T>(this) - diff --git a/src/FSharp.Stats/Algebra/EVD.fs b/src/FSharp.Stats/Algebra/EVD.fs deleted file mode 100644 index c641aad12..000000000 --- a/src/FSharp.Stats/Algebra/EVD.fs +++ /dev/null @@ -1,257 +0,0 @@ -namespace FSharp.Stats.Algebra - -open FSharp.Stats - -module EVD = - - /// Symmetric Householder reduction to tridiagonal form. - /// - /// - /// - /// - /// - /// - /// - /// - /// - let private tred2Inplace (d:float[]) (e:float[]) (v:float [,]) = - - // This is derived from the Algol procedures tred2 by - // Bowdler, Martin, Reinsch, and Wilkinson, Handbook for - // Auto. Comp., Vol.ii-Linear Algebra, and the corresponding - // Fortran subroutine in EISPACK. - - let n = v.GetLength(1) // cols count v - - for i = n - 1 downto 1 do - // Scale to avoid under/overflow. - - let mutable scale = 0.0; - let mutable h = 0.0; - for k = 0 to i-1 do - scale <- scale + abs (d.[k]) - - if scale = 0.0 then - e.[i] <- d.[i - 1] - for j = 0 to i-1 do - d.[j] <- v.[i - 1,j] - v.[i,j] <- 0.0 - v.[j,i] <- 0.0 - else - // Generate Householder vector. - - for k = 0 to i-1 do - d.[k] <- d.[k] / scale - h <- h + d.[k] * d.[k] - let mutable f = d.[i - 1] - let mutable g = if (f > 0.) then -sqrt(h) else sqrt(h) - e.[i] <- scale*g - h <- h - f*g - d.[i - 1] <- f - g - for j = 0 to i-1 do - e.[j] <- 0.0 - - // Apply similarity transformation to remaining columns. - - for j = 0 to i-1 do - f <- d.[j] - v.[j,i] <- f - g <- e.[j] + v.[j,j]*f - for k = j + 1 to i - 1 do - g <- g + v.[k,j]*d.[k] - e.[k] <- e.[k] + v.[k,j]*f - - e.[j] <- g - - f <- 0.0 - for j = 0 to i-1 do - e.[j] <- e.[j] / h - f <- f + e.[j] * d.[j] - let hh = f/(h + h) - for j = 0 to i-1 do - e.[j] <- e.[j] - hh*d.[j] - - for j = 0 to i-1 do - f <- d.[j] - g <- e.[j] - for k = j to i - 1 do - v.[k,j] <- v.[k,j] - (f*e.[k] + g*d.[k]) - - d.[j] <- v.[i - 1,j] - v.[i,j] <- 0.0 - d.[i] <- h - - // Accumulate transformations. - for i = 0 to n - 2 do - v.[n - 1,i] <- v.[i,i] - v.[i,i] <- 1.0; - let h = d.[i + 1] - if (h <> 0.0) then - for k = 0 to i do - d.[k] <- v.[k,i + 1]/h - for j = 0 to i do - let mutable g = 0.0 - for k = 0 to i do - g <- g + v.[k,i + 1]*v.[k,j] - for k = 0 to i do - v.[k,j] <- v.[k,j] - g*d.[k] - for k = 0 to i do - v.[k,i + 1] <- 0.0 - - for j = 0 to n-1 do - d.[j] <- v.[n - 1,j] - v.[n - 1,j] <- 0.0 - - v.[n - 1,n - 1] <- 1.0 - e.[0] <- 0.0 - - - /// Symmetric tridiagonal QL algorithm. - /// - /// - /// - /// - /// - /// - /// - /// - /// - let private tql2Inplace (d:float[]) (e:float[]) (v:float [,]) = - - // This is derived from the Algol procedures tql2, by - // Bowdler, Martin, Reinsch, and Wilkinson, Handbook for - // Auto. Comp., Vol.ii-Linear Algebra, and the corresponding - // Fortran subroutine in EISPACK. - - let n = v.GetLength(1) // cols count v - - for i = 1 to n-1 do - e.[i - 1] <- e.[i] - e.[n - 1] <- 0.0 - - let mutable f = 0.0 - let mutable tst1 = 0.0 - let mutable eps = 2.0**(-52.0) - for l = 0 to n-1 do - // Find small subdiagonal element - - tst1 <- max tst1 (abs(d.[l]) + abs(e.[l])) - let m = - let rec loop m = - if m > n-2 || (abs(e.[m]) <= eps*tst1) then - m - else - loop (m+1) - loop l - - // If m == l, d.[l] is an eigenvalue, - // otherwise, iterate. - - if (m > l) then - let rec loop iter = - // (Could check iteration count here.) - - // Compute implicit shift - - let mutable g = d.[l] - let mutable p = (d.[l + 1] - g)/(2.0*e.[l]) - let mutable r = if (p < 0.) then -(Geometry.hypot p 1.0) else Geometry.hypot p 1.0 - d.[l] <- e.[l]/(p + r) - d.[l + 1] <- e.[l]*(p + r) - let dl1 = d.[l + 1]; - let mutable h = g - d.[l] - for i = l + 2 to n-1 do - d.[i] <- d.[i] - h; - - f <- f + h - - // Implicit QL transformation. - - p <- d.[m]; - let mutable c = 1.0 - let mutable c2 = c - let mutable c3 = c - let mutable el1 = e.[l + 1] - let mutable s = 0.0 - let mutable s2 = 0.0 - for i = m-1 downto l do - c3 <- c2 - c2 <- c - s2 <- s - g <- c*e.[i] - h <- c*p - r <- Geometry.hypot p e.[i] - e.[i + 1] <- s*r - s <- e.[i]/r - c <- p/r - p <- c*d.[i] - s*g - d.[i + 1] <- h + s*(c*g + s*d.[i]) - - // Accumulate transformation. - - for k = 0 to n-1 do - h <- v.[k,i + 1] - v.[k,i + 1] <- s*v.[k,i] + c*h - v.[k,i] <- c*v.[k,i] - s*h - - p <- -s*s2*c3*el1*e.[l]/dl1 - e.[l] <- s*p - d.[l] <- c*p - - // Check for convergence. - if (abs(e.[l]) > eps*tst1) then - loop (iter+1) - loop 0 - - d.[l] <- d.[l] + f - e.[l] <- 0.0 - - - // Sort eigenvalues and corresponding vectors. - for i = 0 to n-2 do - let mutable k = i - let mutable p = d.[i] - for j = i+1 to n-1 do - if (d.[j] < p) then - k <- j - p <- d.[j] - - if (k <> i) then - d.[k] <- d.[i]; - d.[i] <- p; - for j = 0 to n-1 do - p <- v.[j,i] - v.[j,i] <- v.[j,k] - v.[j,k] <- p - - /// Computes the - /// - /// - /// - /// - /// - /// - /// - let symmetricEvd (a:float[,]) = - - // number of columns in A - let n = a.GetLength(1) - // Init array for the real parts of the eigenvalues - let d = Array.init n (fun j -> a.[n - 1,j]) - // Init array for the imaginary parts of the eigenvalues - let e = Array.zeroCreate n - - // Eigenvalue matrix - let v = Array2D.copy a - - // Tridiagonalize. - tred2Inplace d e v - // Diagonalize. - tql2Inplace d e v - - (e,v,d) - - let getRealEigenvalues (e,v,d) = d - let getImaginaryEigenvalues (e,v,d) = e - let getEigenvalueMAtrix (e,v,d) = v - diff --git a/src/FSharp.Stats/Algebra/LinearAlgebra.fs b/src/FSharp.Stats/Algebra/LinearAlgebra.fs deleted file mode 100644 index 9585ee434..000000000 --- a/src/FSharp.Stats/Algebra/LinearAlgebra.fs +++ /dev/null @@ -1,806 +0,0 @@ -namespace FSharp.Stats.Algebra - - -open System -open FSharp.Stats - -type LinearAlgebra = - - /// Subtract `scaleVal * src[srcOffset..srcOffset+count-1]` from - /// `dst[dstOffset..dstOffset+count-1]` in place. - static member inline subScaledRowInPlace - (scaleVal : 'T) - (dstOffset : int) - (srcOffset : int) - (count : int) - (dst : 'T[]) - (src : 'T[]) = - - let scaleVec = Numerics.Vector<'T>(scaleVal) - - // Vector-level callback: dstVec - (scaleVal * srcVec) - let fv (dstVec: Numerics.Vector<'T>) (srcVec: Numerics.Vector<'T>) = - dstVec - (scaleVec * srcVec) - - // Scalar fallback: d - (scaleVal * s) - let f (d: 'T) (s: 'T) = - d - (scaleVal * s) - Acceleration.SIMDRangeUtils.map2RangeInPlace fv f dstOffset srcOffset count dst src - - - //static member inline householderTransform - // (A: Matrix<'T>) (i: int) : Vector<'T> = - // let n = A.NumRows - - // let v = Vector.zeroCreate<'T> n - // let aCol = Matrix.getCol i A - // let norm = Vector.norm aCol.[i..] // ToDO: use a more efficient norm calculation - // v.[i] <- aCol.[i] + if aCol.[i] >= 'T.Zero then norm else -norm - // for j = i + 1 to n - 1 do - // v.[j] <- aCol.[j] - // v - - - - /// QR decomposition using modified Gram-Schmidt - /// Returns Q and R such that A = QR - static member inline qrModifiedGramSchmidt<'T when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T : equality - and 'T :> ValueType - and 'T :> Numerics.IRootFunctions<'T>> - (A: Matrix<'T>) : Matrix<'T> * Matrix<'T> = - - let m, n = A.NumRows, A.NumCols - - if m < n then - invalidArg "A" $"QR decomposition via Modified Gram-Schmidt requires m ≥ n, but got {m}×{n} matrix." - - - let r = Matrix.zeroCreate n n - let qCols: Vector<'T>[] = Array.zeroCreate n - let aCols = Matrix.getCols A - - for j = 0 to n - 1 do - let v = Array.copy aCols.[j] - - for i = 0 to j - 1 do - let qi = qCols.[i] - let rij = Vector.dot qi v - r.[i, j] <- rij - for k = 0 to m - 1 do - v.[k] <- v.[k] - rij * qi.[k] - - let norm = Vector.norm v - r.[j, j] <- norm - let qj = Vector.divideScalar norm v - qCols.[j] <- qj - - let qData = Array.zeroCreate (m * n) - for j = 0 to n - 1 do - for i = 0 to m - 1 do - qData.[i * n + j] <- qCols.[j].[i] - - Matrix(m, n, qData), r - - /// Back substitute to solve R * x = y - /// R is upper triangular - static member inline backSubstitute<'T when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T : equality - and 'T :> ValueType> - (r: Matrix<'T>) - (y: Vector<'T>) : Vector<'T> = - - let n = r.NumRows - - if r.NumCols <> n || y.Length <> n then - invalidArg "dimensions" "R must be square and match the length of y" - - let x = Array.zeroCreate<'T> n - - for i = n - 1 downto 0 do - let mutable sum = y.[i] - for j = i + 1 to n - 1 do - sum <- sum - r.[i, j] * x.[j] - let diag = r.[i, i] - if diag = 'T.Zero then - invalidArg $"r[{i},{i}]" "Diagonal element is zero. Cannot divide." - x.[i] <- sum / diag - - x - - - - - /// Solve A * x = b for x, where A is a square matrix (n×n) and b is a vector (length n). - static member inline solveLinearQR<'T when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T : equality - and 'T :> ValueType - and 'T :> Numerics.IRootFunctions<'T>> - (A: Matrix<'T>) - (b: Vector<'T>) : Vector<'T> = - - if A.NumRows <> b.Length then - invalidArg "b" "Vector length must match number of rows in matrix A" - - let Q, R = LinearAlgebra.qrModifiedGramSchmidt A - let Qt = Q.Transpose() - let y = Matrix.muliplyVector Qt b - LinearAlgebra.backSubstitute R y - - - - /// Solve K * X = B for X, where K is a triangular matrix (lower or upper). - /// K is square of size n×n; B is n×m. Returns an n×m result X. - static member inline solveTriangularLinearSystems - (K : Matrix<'T>) - (B : Matrix<'T>) - (isLower : bool) - : Matrix<'T> = - - /// Multiply `arr[offset..offset+count-1]` by `scaleVal` in place - let inline scaleRowInPlace - (scaleVal : 'T) - (offset : int) - (count : int) - (arr : 'T[]) = - - let scaleVec = Numerics.Vector<'T>(scaleVal) - - // Vector-level callback: chunk * scaleVal - let fv (chunk: Numerics.Vector<'T>) = - chunk * scaleVec - - // Scalar fallback: x * scaleVal - let f (x: 'T) = x * scaleVal - - // mapRangeInPlace fv f offset count arr - Acceleration.SIMDRangeUtils.mapRangeInPlace fv f offset count arr - - // Check shape consistency - let nK, mK = K.NumRows, K.NumCols - let nB, mB = B.NumRows, B.NumCols - if nK <> mK || nB <> nK then - invalidArg "Matrix" "K must be square and B must have matching row count for K" - - // Copy B into a new matrix X (the solution) - let X = Matrix<'T>(B.NumRows, B.NumCols, Array.copy B.Data) - - let n = nK // size of the NxN triangular matrix K - let m = mB // # of columns in B (and thus X) - - let Kdata = K.Data - let Xdata = X.Data - - // For row i, the contiguous slice in Xdata is [i*m .. i*m + m - 1] - // => offset = i*m, length = m - - if isLower then - // ------ Forward Substitution ------ - // for i in [0..n-1]: - // X[i,*] <- X[i,*] - Σ_{j=0..i-1} [K[i,j] * X[j,*]] - // then scale row i by 1/K[i,i] - for i = 0 to n - 1 do - let baseI = i * m - // Subtract scaled rows for j in [0..i-1] - for j = 0 to i - 1 do - let kij = Kdata.[i * n + j] // K[i,j] - //if kij <> 'T.Zero then // normaly speed things up, but -inf * 0 = nan - let baseJ = j * m - // subScaledRowInPlace scaleVal dstOffset srcOffset count dst src - LinearAlgebra.subScaledRowInPlace - kij - baseI // row i offset in X - baseJ // row j offset in X - m // number of columns - Xdata - Xdata - //LinearAlgebra.subScaledRowInPlace - // Xdata - // baseI // row i offset in X - // Xdata - // baseJ // row j offset in X - // m // number of columns - // kij - - - - // Divide row i by the diagonal K[i,i] - let diag = Kdata.[i * n + i] - let invDiag = 'T.One / diag - // scaleRowInPlace scaleVal offset count arr - scaleRowInPlace - invDiag - baseI - m - Xdata - else - // ------ Backward Substitution ------ - // for i in [n-1..0]: - // X[i,*] <- X[i,*] - Σ_{j=i+1..n-1} [K[i,j] * X[j,*]] - // then scale row i by 1/K[i,i] - for i = n - 1 downto 0 do - let baseI = i * m - for j = i + 1 to n - 1 do - let kij = Kdata.[i * n + j] // K[i,j] - //if kij <> 'T.Zero then // normaly speed things up, but -inf * 0 = nan - let baseJ = j * m - LinearAlgebra.subScaledRowInPlace - kij - baseI - baseJ - m - Xdata - Xdata - let diag = Kdata.[i * n + i] - let invDiag = 'T.One / diag - scaleRowInPlace - invDiag - baseI - m - Xdata - - X - - - - /// Solve K * x = v (triangular system) in-place, returning a copy of x. - /// K must be n×n, v must be length n. - /// isLower = true => forward substitution - /// isLower = false => backward substitution - static member inline solveTriangularLinearSystem - (K : Matrix<'T>) - (v : Vector<'T>) - (isLower : bool) - : Vector<'T> = - - let nK, mK = K.NumRows, K.NumCols - let nV = v.Length - if nK <> mK || nV <> nK then - invalidArg (nameof K) "K must be square, and v must match its dimension." - - let x = Array.copy v - let Kdata = K.Data // row-major flattened - - // Forward or backward substitution - if isLower then - // For i in [0..n-1]: - // x[i] <- ( x[i] - sum_{j=0..i-1}(K[i,j] * x[j]) ) / K[i,i] - for i = 0 to nK - 1 do - let mutable s = x.[i] - let rowOffset = i * nK - for j = 0 to i - 1 do - s <- s - (Kdata.[rowOffset + j] * x.[j]) - let diag = Kdata.[rowOffset + i] - if diag = 'T.Zero then - invalidArg $"K[{i},{i}]" "Diagonal element is zero. Cannot divide." - x.[i] <- s / diag - else - // For i in [n-1..downto..0]: - // x[i] <- ( x[i] - sum_{j=i+1..n-1}(K[i,j] * x[j]) ) / K[i,i] - for i = nK - 1 downto 0 do - let mutable s = x.[i] - let rowOffset = i * nK - for j = i + 1 to nK - 1 do - s <- s - (Kdata.[rowOffset + j] * x.[j]) - let diag = Kdata.[rowOffset + i] - if diag = 'T.Zero then - invalidArg $"K[{i},{i}]" "Diagonal element is zero. Cannot divide." - x.[i] <- s / diag - - x - - - - ///// QR decomposition using Householder reflections - //static member inline qrDecompose (A : Matrix<'T>) : (Matrix<'T> * Matrix<'T>) = - //// former QR - // let updateQ (Q : Matrix<'T>) (v : Vector<'T>) = - // let nQ, mQ = Q.NumRows, Q.NumCols - // let n = v.Length - // let Qv = Vector.zeroCreate<'T> nQ - // for i = 0 to nQ - 1 do - // // offset in Q.Data for row i is i*mQ - // let rowOffset = i * mQ + (mQ - n) - // // Dot the subrange Q[i, mQ-n..mQ-1] with v[0..n-1] - // Qv.[i] <- Acceleration.SIMDRangeUtils.dotRange Q.Data rowOffset v 0 n - - // // Update each row i in the subrange of columns [mQ-n..mQ-1] - // // Q[i, j] -= 2 * Qv[i] * v[j - (mQ - n)] - // for i = 0 to nQ - 1 do - // let alpha = Qv.[i] + Qv.[i] - // // We want to do a row operation: Q[i, (mQ-n)..(mQ-1)] - // // = Q[i, (mQ-n)..(mQ-1)] - alpha * v[0..n-1]. - // let rowOffset = i * mQ + (mQ - n) - // //LinearAlgebra.subScaledRowInPlace Q.Data rowOffset v 0 n alpha - // LinearAlgebra.subScaledRowInPlace alpha rowOffset 0 n Q.Data v - - // // TODO: Refector in Householder module - // let normalize (v: Vector<'T>) : Vector<'T> = - // let norm = Vector.norm v - // if norm = 'T.Zero then v - // else - // Array.map (fun x -> x / norm) v - - // let m, n = A.NumRows, A.NumCols - - // // Q starts as identity(n) - // let Q = Matrix.identity m - // let R = Matrix.copy A - - // for i = 0 to (min n m) - 1 do - // let x = [| for k in i .. m - 1 -> R.[k, i] |] - // //let a = Matrix.getCol i R - // let hh = Householder.create x //a.[i..] Create Householder reflector for column i - // let v = hh.V |> normalize - // updateQ Q v - // Householder.applyLeft(hh, R, i) - - - // Q, R - - - /// QR decomposition using Householder reflections - static member inline qrDecompose (A : Matrix<'T>) : (Matrix<'T> * Matrix<'T>) = - // former QR - - /// Compute normalized Householder vector from a subcolumn x - let householderVector (x: 'T[]) : 'T[] = - let norm = sqrt (Array.sumBy (fun xi -> xi * xi) x) - let v = Array.copy x - v.[0] <- v.[0] + (if x.[0] >= 'T.Zero then norm else -norm) - let norm_v = sqrt (Array.sumBy (fun vi -> vi * vi) v) - if norm_v = 'T.Zero then v - else Array.map (fun vi -> vi / norm_v) v - - /// Update Q: Q ← Q * Hᵢ using Householder vector v (from column i) - let updateQ (Q: Matrix<'T>) (v: 'T[]) (i: int) = - let nQ, mQ = Q.NumRows, Q.NumCols - for row = 0 to nQ - 1 do - let mutable dot = 'T.Zero - for k = 0 to v.Length - 1 do - dot <- dot + Q.[row, i + k] * v.[k] - let alpha = dot + dot - for k = 0 to v.Length - 1 do - Q.[row, i + k] <- Q.[row, i + k] - alpha * v.[k] - - /// Apply Hᵢ to R from the left: R ← H * R - let applyHouseholderLeft (R: Matrix<'T>) (v: 'T[]) (i: int) = - let m, n = R.NumRows, R.NumCols - for col = i to n - 1 do - let mutable dot = 'T.Zero - for k = 0 to v.Length - 1 do - let row = i + k - if row < m then - dot <- dot + v.[k] * R.[row, col] - let alpha = dot + dot - for k = 0 to v.Length - 1 do - let row = i + k - if row < m then - R.[row, col] <- R.[row, col] - alpha * v.[k] - - /// Main QR decomposition function - let qrDecompose (A: Matrix<'T>) : Matrix<'T> * Matrix<'T> = - let m, n = A.NumRows, A.NumCols - let Q = Matrix.identity m - let R = Matrix.copy A - - for i = 0 to min m n - 1 do - let x = [| for k in i .. m - 1 -> R.[k, i] |] - let v = householderVector x - updateQ Q v i - applyHouseholderLeft R v i - - Q, R - - qrDecompose A - - - - - /// Given A[m,n] and B[m] solves AX = B for X[n].
- /// When m => n, have over constrained system, finds least squares solution for X.
- /// When m < n, have under constrained system, finds least norm solution for X.
- static member inline leastSquares - (A : Matrix<'T>) - (b: Vector<'T>) = - // Maybe rename to leastSquaresQR? - let (m,n) = A.NumRows, A.NumCols - - // Is this an overdetermined or underdetermined system? - if m >= n then - //printfn "Least squares: solving %dx%d system with %d equations." m n n - let Qm, R = LinearAlgebra.qrDecompose A - let Qtb = Qm.Transpose() * b - LinearAlgebra.solveTriangularLinearSystem R.[0..n-1,0..n-1] Qtb.[0..n-1] false - else - // underdetermined: solve A^T * x = 0 with min ||x|| - //printfn "underdetermined- Least squares: solving %dx%d system with %d equations." m n n - let AT = A.Transpose() - let Q, R = LinearAlgebra.qrDecompose AT - let RT = R.Transpose() - let s = LinearAlgebra.solveTriangularLinearSystem RT.[0..m-1, 0..m-1] b true - Q.[0.., 0..m-1] * s - - //let AT = A.Transpose() - //let Q, R = LinearAlgebra.qrDecompose AT - //let y = Q.Transpose() * b - //let s = LinearAlgebra.solveTriangularLinearSystem R.[0..m-1, 0..m-1] y.[0..m-1] false - - //Q.[0..n,0..m] * s - - - - - //let AT = A.Transpose() - //let QT, RT = LinearAlgebra.qrDecompose AT - //let y = QT.Transpose() * b - //let s = LinearAlgebra.solveTriangularLinearSystem RT.[0..m-1, 0..m-1] y.[0..m-1] false - //let s = LinearAlgebra.solveTriangularLinearSystem R.[0..m-1,0..m-1] Qtb false - //Vector.init n (fun i -> if i < m then s.[i] else 'T.Zero) - - //// underdetermined: solve min ||x|| such that Ax = b - //let AT = A.Transpose() - //let QT, RT = LinearAlgebra.qrDecompose AT - //let y = LinearAlgebra.solveTriangularLinearSystem (RT.Transpose().[0..m-1, 0..m-1]) b false - //QT.[*, 0..m-1] * y - - - /// - /// Computes the Cholesky factor L of a symmetric positive-definite matrix A, - /// returning L as a lower-triangular such that A = L * L^T. - /// Throws if A is not positive-definite (i.e., if any diagonal element ≤ 0). - /// - static member inline cholesky - (A : Matrix<'T>) - : Matrix<'T> = - - let n = A.NumRows - let m = A.NumCols - if n <> m then - invalidArg (nameof A) "Cholesky: matrix must be square." - - let dataA = A.Data - // We'll create an n×n zeroed matrix for L - let Ldata = Array.zeroCreate<'T> (n * n) - - // Helper function for indexing row-major arrays: - let inline idx r c = r * n + c - - for j = 0 to n - 1 do - // 1) Diagonal element L[j,j] - // L[j,j] = sqrt(A[j,j] - ∑(k=0..j-1) L[j,k]^2) - let mutable sumjj = dataA.[idx j j] - for k = 0 to j - 1 do - let ljk = Ldata.[idx j k] - sumjj <- sumjj - (ljk * ljk) - - // Check positivity - if sumjj <= 'T.Zero then - invalidArg "A" "Cholesky: matrix not positive-definite (diagonal <= 0)." - - let ljj = GenericMath.sqrt sumjj - Ldata.[idx j j] <- ljj - - // 2) Off-diagonal: L[i,j] for i=j+1..n-1 - // L[i,j] = (A[i,j] - ∑(k=0..j-1) L[i,k]*L[j,k]) / L[j,j] - for i = j + 1 to n - 1 do - let mutable sumij = dataA.[idx i j] - for k = 0 to j - 1 do - sumij <- sumij - (Ldata.[idx i k] * Ldata.[idx j k]) - Ldata.[idx i j] <- sumij / ljj - - Matrix<'T>(n, n, Ldata) - - - /// Given A[m,n] and b[m] solves AX = b for X[n].
- /// When the system is under constrained,
- /// for example when the columns of A are not linearly independent,
- /// then it will not give sensible results.
- static member inline leastSquaresCholesky - (A : Matrix<'T>) - (b: Vector<'T>) = - - if b.Length <> A.NumRows then - invalidArg "b" "Length of b must match the number of rows of A." - - let AT = A.Transpose() - - let upper = (AT * A) |> LinearAlgebra.cholesky - let gamma = - LinearAlgebra.solveTriangularLinearSystem(upper) (AT * b) true - let beta = - LinearAlgebra.solveTriangularLinearSystem (upper.Transpose()) gamma false - beta - - - /// computes the hat matrix by the QR decomposition of the designmatrix used in ordinary least squares approaches - static member inline hatMatrix - (designMatrix: Matrix<'T>) = - let qm,R = LinearAlgebra.qrDecompose designMatrix - let q1 = qm.GetSlice ((Some 0),(Some (qm.NumRows-1)),(Some 0),(Some (R.NumCols-1))) - // computes the hatmatrix - q1 * q1.Transpose() - - - /// computes the leverages of every dataPoint of a dataSet given by the diagonal of the hat matrix. - static member inline leverageBy - (hatMatrix: Matrix<'T>) = - - Matrix.getDiagonal hatMatrix - - - /// computes the leverage directly by QR decomposition of the designmatrix used in ordinary least squares approaches
- /// and computing of the diagnonal entries of the Hat matrix, known as the leverages of the regressors
- static member inline leverage - (designMatrix: Matrix<'T>) = - - let qm,R = LinearAlgebra.qrDecompose designMatrix - let q1 = qm.GetSlice ((Some 0),(Some (qm.NumRows-1)),(Some 0),(Some (R.NumCols-1))) - - Vector.init q1.NumRows (fun i -> - let mutable sumOfSquares = 'T.Zero - for j = 0 to q1.NumCols - 1 do - let x = q1.[i, j] - sumOfSquares <- sumOfSquares + x * x - sumOfSquares - ) - - - /// - /// Computes the LU factorization of a square matrix A with partial pivoting. - /// That is, P * A = L * U, where P is a permutation, and L, U are lower/upper triangular. - /// Returns (Permutation P, L, U). - /// - static member inline luDecompose (A : Matrix<'T>) = - let n, m = A.NumRows, A.NumCols - if n <> m then - invalidArg (nameof A) "LU: A must be square." - - let U = Matrix.copy A // We'll transform U in place. - let L = Matrix.zeroCreate n n // We'll fill L below the diagonal. - let P = [| 0 .. n-1 |] // Pivot array - - // Row-swap function for U: swap entire row i, row j - let swapRows (M: Matrix<'T>) i j = - let rowI = i - let rowJ = j - for col = 0 to m - 1 do - let tmp = M.[rowI, col] - M.[rowI, col] <- M.[rowJ, col] - M.[rowJ, col] <- tmp - - // Row-swap function for L: only swap the columns up to i-1 (since the rest is not yet set). - // Because in Doolittle's method, columns [0..i-1] of L are already determined at pivot step i. - let swapRowsPartial (M: Matrix<'T>) i j pivotCol = - for col = 0 to pivotCol - 1 do - let tmp = M.[i, col] - M.[i, col] <- M.[j, col] - M.[j, col] <- tmp - - // Perform the decomposition - for i = 0 to n - 2 do - // 1) Find pivot row by max absolute value in U column i - let mutable pivotRow = i - let mutable pivotVal = abs(U.[pivotRow, i]) - for r = i + 1 to n - 1 do - let candidate = abs(U.[r, i]) - if candidate > pivotVal then - pivotVal <- candidate - pivotRow <- r - - // 2) If pivotRow != i, swap rows in U, swap partial in L, and update pivot array - if pivotRow <> i then - swapRows U i pivotRow - swapRowsPartial L i pivotRow i - let tmp = P.[i] - P.[i] <- P.[pivotRow] - P.[pivotRow] <- tmp - - // 3) Eliminate below pivot - for j = i + 1 to n - 1 do - // L[j,i] = U[j,i] / U[i,i] - L.[j,i] <- U.[j,i] / U.[i,i] - // Update row j of U - for k = i + 1 to n - 1 do - U.[j,k] <- U.[j,k] - L.[j,i] * U.[i,k] - U.[j,i] <- 'T.Zero - - // Add identity to L (so diagonal = 1.0) - // i.e., L[i,i] <- 1.0 - for i = 0 to n - 1 do - L.[i,i] <- 'T.One - - // Return the permutation (as an array or your custom Permutation type), - // plus the final L and U - (Permutation.ofArray P, L, U) - - /// - /// Solves the system of linear equations A * X = B using LU factorization. - /// A must be square; B must have the same number of rows as A. - /// Returns a matrix X s.t. A*X = B. - /// - static member inline solveLinearSystems (A: Matrix<'T>) (B: Matrix<'T>) = - let nA, mA = A.NumRows, A.NumCols - let nB, mB = B.NumRows, B.NumCols - - // 1) Check shape: A must be square, B's rows must match A's rows - if nA <> mA then - invalidArg (nameof A) "Matrix A must be square." - if nB <> nA then - invalidArg (nameof B) "Matrix B must have same number of rows as A." - - // 2) Factor A -> (P, L, U) - let (P, L, U) = LinearAlgebra.luDecompose A - - // 3) Permute B according to P (i.e., reorder rows) - let Bpermuted = B |> Matrix.permuteRowsBy P - - // 4) Forward substitution: solve L * Y = Bpermuted - let Y = LinearAlgebra.solveTriangularLinearSystems L Bpermuted true // isLower = true - - // 5) Back substitution: solve U * X = Y - let X = LinearAlgebra.solveTriangularLinearSystems U Y false // isLower = false - - X - - /// - /// Solves the system A * x = b for x, using LU factorization with partial pivoting. - /// A must be square, and b must have length = A.NumRows. - /// - static member inline solveLinearSystem (A : Matrix<'T>) (b : Vector<'T>) = - let n, m = A.NumRows, A.NumCols - if n <> m then - invalidArg (nameof A) "Matrix A must be square." - if b.Length <> n then - invalidArg (nameof b) "Vector b must have length = A.NumRows." - - // 1) Factor A => (P, L, U) - let (P, L, U) = LinearAlgebra.luDecompose A - - // 2) Permute b according to P - let bPermuted = b |> Vector.permuteBy P - - // 3) Forward solve: L * y = bPermuted - let y = LinearAlgebra.solveTriangularLinearSystem L bPermuted true // isLower = true - - // 4) Back solve: U * x = y - let x = LinearAlgebra.solveTriangularLinearSystem U y false // isLower = false - - x - - /// - /// Computes the inverse of a square matrix A using its LU factorization. - /// If A is n×n, we factor A = P * L * U, then solve A * X = I for X, returning X = A^-1. - /// - /// A square matrix of size n×n. - /// The inverse of A, an n×n matrix. - /// - /// Thrown if A is not square, or if factorization fails (e.g., if A is singular). - /// - static member inline inverse (A: Matrix<'T>) : Matrix<'T> = - let n, m = A.NumRows, A.NumCols - if n <> m then - invalidArg (nameof A) "Matrix must be square when computing its inverse." - - // 1) Factor A => P, L, U - let (P, L, U) = LinearAlgebra.luDecompose A - - // 2) Build the identity matrix I, size n - let I = Matrix.identity n - - // 3) Permute I's rows by P (so effectively P*I) - let IPerm = I |> Matrix.permuteRowsBy P - - // 4) Forward substitution: solve L * Y = IPerm - let Y = LinearAlgebra.solveTriangularLinearSystems L IPerm true - - // 5) Back substitution: solve U * X = Y - let X = LinearAlgebra.solveTriangularLinearSystems U Y false - - // X is A^-1 - X - - - /// - /// Computes the Moore-Penrose pseudoinverse of a matrix using a QR-based approach. - /// If the matrix is overdetermined (m > n), returns (R⁻¹ Qᵀ) for A = Q R with A[m×n]. - /// If underdetermined (m < n), uses the transpose trick, then returns the transpose of the partial solution. - /// - /// An m×n matrix. - /// The (n×m) pseudoinverse of . - static member inline pseudoInvers (matrix: Matrix<'T>) = - let m, n = matrix.NumRows, matrix.NumCols - - // Overdetermined: A is m×n with m > n - if m > n then - // A = Q (m×m) * R (m×n) [or economy size Q (m×n), R (n×n)] - let qm, R = LinearAlgebra.qrDecompose matrix - // Instead of multiplying qm.Transpose by identity(m×m), just use qm.Transpose - // Next, we want sub-blocks: R is m×n, but we only need the top n×n portion, - // and we want the top-left n×m portion of qm.Transpose. - let Qt = qm.Transpose() - // Solve R[0..n-1, 0..n-1] * X = Qt[0..n-1, 0..m-1] (back-substitution) - LinearAlgebra.solveTriangularLinearSystems - R.[0..n-1, 0..n-1] - Qt.[0..n-1, 0..m-1] - false - - // Underdetermined: A is m×n with m < n - else - // We do matrix.Transpose => n×m - // Then QR => qm (n×n?), R (n×m?), etc. - let qm, R = LinearAlgebra.qrDecompose (matrix.Transpose()) - // Again skip identity multiply: just use qm.Transpose - let Qt = qm.Transpose() - // Solve R[0..m-1, 0..m-1] * X = Qt[0..m-1, 0..n-1] - let s = - LinearAlgebra.solveTriangularLinearSystems - R.[0..m-1, 0..m-1] - Qt.[0..m-1, 0..n-1] - false - // Return sᵀ => the actual pseudoinverse shape (n×m) - s.Transpose() - - - /// - /// Computes the determinant of a square matrix A by factoring A = P * L * U, - /// then det(A) = sign(P) * ∏ diag(U). - /// (Assumes L has diag=1, as in Doolittle.) - /// - static member inline determinant (A: Matrix) : float = - let n = A.NumRows - if n <> A.NumCols then - invalidArg (nameof A) "Matrix must be square." - - // 1) Factor A => (P, L, U) - let (P, L, U) = LinearAlgebra.luDecompose A - - // 2) Compute sign from the permutation P with domain size n - let permSign = Permutation.sign n P - - // 3) Product of diag(U) - let diagProd = - let mutable product = 1.0 - for i = 0 to n - 1 do - product <- product * U.Data.[i*n + i] - product - - // 4) Return sign(P) * product - permSign * diagProd - - - static member inline SVD (a:Matrix) = - let (umatrix,s,vmatrix) = SVD.computeInPlace (a.toArray2D()) - //Matrix.diag - s,Matrix.ofArray2D umatrix,Matrix.ofArray2D vmatrix - //(Matrix.ofArray2D umatrix,s,Matrix.ofArray2D vmatrix) - - static member inline symmetricEigenspectrum (a:Matrix) = - let (e,v,d) = EVD.symmetricEvd (a.toArray2D()) - (Matrix.ofArray2D v, d) - - ///// Synonym: kernel / right null space. Returns an orthonormal basis for the null space of matrix A (Ax = 0).
The accuracy defines a threshold whether a singular value is considered as zero (default: 1e-08). - //static member nullspace(?Accuracy :float ) = - - // let accuracy = defaultArg Accuracy 1e-08 - - // fun (a: Matrix) -> - - // // Either MKL or fallback implementation of the full SVD - // let (sigma,U,Vt) = LinearAlgebra.SVD a - - // // The rank is the number of nonzero singular values - // let rank = - // sigma - // |> Seq.sumBy (fun x -> if x >= accuracy then 1 else 0) - - // let count = Vt.NumRows - rank - - // Matrix.getRows Vt rank count - // |> Matrix.transpose \ No newline at end of file diff --git a/src/FSharp.Stats/Algebra/SVD.fs b/src/FSharp.Stats/Algebra/SVD.fs deleted file mode 100644 index 35a9408ea..000000000 --- a/src/FSharp.Stats/Algebra/SVD.fs +++ /dev/null @@ -1,567 +0,0 @@ -namespace FSharp.Stats.Algebra - - -open System -open FSharp.Stats -open FSharp.Stats.Acceleration - -type Bidiagonalization() = - - static member inline bidiagonalizeInPlace<'T - when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T : comparison - and 'T :> ValueType - and 'T :> Numerics.IRootFunctions<'T>> - (A: Matrix<'T>) : unit = - - let m = A.NumCols - let n = A.NumRows - let minMN = min m n - - for k = 0 to minMN - 1 do - // --- LEFT REFLECTION: Column k (zero below diagonal) --- - let colLen = m - k - let colVector = Array.init colLen (fun i -> A.[k + i, k]) - let hLeft = Householder.create colVector - - Householder.applyLeft(hLeft, A, k) - - // Overwrite A[k..,k] with Householder beta at top and zeros below - A.[k, k] <- hLeft.Beta - for i = k + 1 to m - 1 do - A.[i, k] <- GenericMath.zero<'T> - - - - // --- RIGHT REFLECTION: Row k (zero right of superdiagonal) --- - if k < n - 1 then - let rowLen = n - (k + 1) - let rowVector = Array.init rowLen (fun j -> A.[k, k + 1 + j]) - let hRight = Householder.create rowVector - - Householder.applyRight(hRight, A, k + 1) - - // Overwrite A[k,k+1..] with Householder beta at front, zeros right - A.[k, k + 1] <- hRight.Beta - for j = k + 2 to n - 1 do - A.[k, j] <- GenericMath.zero<'T> - - -[] -type Bidiagonal<'T when 'T :> Numerics.INumber<'T>> = { - D : Vector<'T> // main diagonal - E : Vector<'T> // superdiagonal (length n-1) -} - - -/// Givens Rotation (Generic) -module Givens = - - let inline compute<'T - when 'T :> Numerics.INumber<'T> - and 'T : comparison - and 'T :> Numerics.IRootFunctions<'T> - and 'T :> Numerics.IFloatingPointIeee754<'T>> - (a: 'T) (b: 'T) : 'T * 'T = - - if b = GenericMath.zero then GenericMath.one, GenericMath.zero - elif GenericMath.abs b > GenericMath.abs a then - let t = a / b - let s = GenericMath.one / GenericMath.sqrt(GenericMath.one + t * t) - s * t, s - else - let t = b / a - let c = GenericMath.one / GenericMath.sqrt(GenericMath.one + t * t) - c, c * t - -module GolubKahan = - - let inline diagonalize<'T - when 'T :> Numerics.INumber<'T> - and 'T :> Numerics.IRootFunctions<'T> - and 'T :> Numerics.IFloatingPointIeee754<'T> - and 'T : comparison - and 'T : struct - and 'T : (new: unit -> 'T) - and 'T :> ValueType> - (b: Bidiagonal<'T>) : Vector<'T> = - - let d = Array.copy b.D - let e = Array.copy b.E - let n = d.Length - let eps = GenericMath.epsilon() - let two = GenericMath.one + GenericMath.one - - let mutable iter = 0 - let maxIter = 1000 - let mutable doneIterating = false - - - - while iter < maxIter && not doneIterating do - let mutable converged = true - - for i = 0 to n - 2 do - let tolerance = eps * (GenericMath.abs d.[i] + GenericMath.abs d.[i + 1]) - if abs e.[i] > tolerance then - converged <- false - - if converged then - doneIterating <- true - else - // Wilkinson shift - let m = n - 1 - let dm1 = d.[m - 1] - let dm = d.[m] - let em1 = e.[m - 1] - - let delta = (dm1 - dm) / two - let sign = - if delta >= GenericMath.zero then GenericMath.one - else -GenericMath.one - - let denom = abs delta + sqrt (delta * delta + em1 * em1) - let mu = dm - sign * (em1 * em1) / denom - - // Initial bulge - let mutable x = d.[0] * d.[0] - mu * mu - let mutable z = d.[0] * e.[0] - - for k = 0 to n - 2 do - let c, s = Givens.compute x z - - let dk = d.[k] - let ek = e.[k] - let dk1 = d.[k + 1] - - let tau1 = c * dk + s * ek - let tau2 = -s * dk1 - - d.[k] <- c * tau1 + s * tau2 - e.[k] <- c * ek - s * dk1 - d.[k + 1] <- s * tau1 - c * tau2 - - if k < n - 2 then - x <- e.[k] - z <- -s * e.[k + 1] - e.[k + 1] <- c * e.[k + 1] - - iter <- iter + 1 - - d - - - -module SVD = - - type private SvdCase = - // 1 if s(p) and e[k-1] are negligible and k

a.[j,i]) - - let computeInPlace (a:float[,]) = - let transposeBeforeSVD = - let m = a.GetLength(0) - let n = a.GetLength(1) - m < n - let a = if transposeBeforeSVD then transpose a else a - //let a = Array2D.copy A - // number of rows in A - let m = a.GetLength(0) - // number of columns in A - let n = a.GetLength(1) - // * Apparently the failing cases are only a proper subset of (m= n") } - let nu = min m n - let s = Array.zeroCreate (min (m+1) n) - let umatrix = Array2D.zeroCreate m m - let vmatrix = Array2D.zeroCreate n n - let e = Array.zeroCreate n - let work = Array.zeroCreate m - let mutable wantu = true - let mutable wantv = true - - // Reduce A to bidiagonal form, storing the diagonal elements - // in s and the super-diagonal elements in e. - - let nct = min (m - 1) n - let nrt = max 0 (min (n - 2) m) - for k = 0 to (max nct nrt) do - if (k < nct) then - // Compute the transformation for the k-th column and - // place the k-th diagonal in s.[k]. - // Compute 2-norm of k-th column without under/overflow. - s.[k] <- 0. - for i = k to m-1 do - s.[k] <- Geometry.hypot s.[k] a.[i,k] - - if (s.[k] <> 0.0) then - if (a.[k,k] < 0.0) then - s.[k] <- -s.[k] - - for i = k to m-1 do - a.[i,k] <- a.[i,k] / s.[k] - - a.[k,k] <- a.[k,k] + 1.0 - - s.[k] <- -s.[k] - - for j = k+1 to n-1 do - if ((k < nct) && (s.[k] <> 0.0)) then - // Apply the transformation. - - let mutable t = 0. - for i = k to m-1 do - t <- t + a.[i,k] * a.[i,j] - - t <- -t / a.[k,k] - for i = k to m-1 do - a.[i,j] <- a.[i,j] + t * a.[i,k] - - - // Place the k-th row of A into e for the - // subsequent calculation of the row transformation. - - e.[j] <- a.[k,j] - - if (wantu && (k < nct)) then - - // Place the transformation in U for subsequent back - // multiplication. - - for i = k to m-1 do - umatrix.[i,k] <- a.[i,k] - - if (k < nrt) then - // Compute the k-th row transformation and place the - // k-th super-diagonal in e[k]. - // Compute 2-norm without under/overflow. - e.[k] <- 0. - for i = k+1 to n-1 do - e.[k] <- Geometry.hypot e.[k] e.[i] - - if (e.[k] <> 0.0) then - if (e.[k + 1] < 0.0) then - e.[k] <- -e.[k] - - for i = k+1 to n-1 do - e.[i] <- e.[i] / e.[k] - - e.[k + 1] <- e.[k + 1] + 1.0 - - e.[k] <- -e.[k] - if ((k + 1 < m) && (e.[k] <> 0.0)) then - // Apply the transformation. - for i = k+1 to m-1 do - work.[i] <- 0.0 - - for j = k+1 to n-1 do - for i = k+1 to m-1 do - work.[i] <- work.[i] + e.[j] * a.[i,j] - - for j = k+1 to n-1 do - let t = -e.[j] / e.[k + 1] - for i = k+1 to m-1 do - a.[i,j] <- a.[i,j] + t * work.[i] - - - if (wantv) then - // Place the transformation in V for subsequent - // back multiplication. - for i = k+1 to n-1 do - vmatrix.[i,k] <- e.[i] - - - // Set up the final bidiagonal matrix or order p. - let mutable p = min n (m + 1) - if (nct < n) then - s.[nct] <- a.[nct,nct] - - if (m < p) then - s.[p - 1] <- 0.0 - - if (nrt + 1 < p) then - e.[nrt] <- a.[nrt,p - 1] - - e.[p - 1] <- 0.0 - - // If required, generate U. - if (wantu) then - for j = nct to m-1 do - for i = 0 to m-1 do - umatrix.[i,j] <- 0.0 - umatrix.[j,j] <- 1.0 - - for k = nct-1 downto 0 do - if (s.[k] <> 0.0) then - for j = k+1 to m-1 do - let mutable t = 0. - for i = k to m-1 do - t <- t + umatrix.[i,k] * umatrix.[i,j] - - t <- -t / umatrix.[k,k] - for i = k to m-1 do - umatrix.[i,j] <- umatrix.[i,j] + t * umatrix.[i,k] - - for i = k to m-1 do - umatrix.[i,k] <- -umatrix.[i,k] - - umatrix.[k,k] <- 1.0 + umatrix.[k,k] - for i = 0 to k-2 do - umatrix.[i,k] <- 0.0 - - else - for i = 0 to m-1 do - umatrix.[i,k] <- 0.0 - - umatrix.[k,k] <- 1.0 - - - // If required, generate V. - - if (wantv) then - for k = n-1 downto 0 do - if ((k < nrt) && (e.[k] <> 0.0)) then - for j = k+1 to nu-1 do - let mutable t = 0. - for i = k+1 to n-1 do - t <- t + vmatrix.[i,k] * vmatrix.[i,j] - - t <- -t / vmatrix.[k + 1,k] - for i = k+1 to n-1 do - vmatrix.[i,j] <- vmatrix.[i,j] + t * vmatrix.[i,k] - - for i = 0 to n-1 do - vmatrix.[i,k] <- 0.0 - vmatrix.[k,k] <- 1.0 - - // Main iteration loop for the singular values. - // TODO: rec - let mutable pp = p - 1 - let mutable iter = 0 - let eps = System.Math.Pow(2.0, -52.0) - let tiny = System.Math.Pow(2.0, -966.0) - while (p > 0) do - let mutable k = -1 - let mutable case = -1 - - // Here is where a test for too many iterations would go. - - // This section of the program inspects for - // negligible elements in the s and e arrays. On - // completion the variables case and k are set as follows. - - // case = 1 if s(p) and e[k-1] are negligible and k

() - - if (k = p - 2) then - case <- 4 - else - let mutable ks = p-1 - try - for ks' = p-1 downto k do - ks <- ks' - if (ks = k) then - raise BreakException - let mutable t = (if ks <> p then (abs e.[ks]) else 0.0) + - (if ks <> k+1 then (abs e.[ks-1]) else 0.0) - if ((abs s.[ks]) <= tiny + eps*t) then - s.[ks] <- 0.0 - raise BreakException - - with BreakException -> () - - if (ks = k) then case <- 3 - elif (ks = p-1) then case <- 1 - else - case <- 2 - k <- ks - k <- k + 1 - // Perform the task indicated by case. - - match case with - | 1 -> - // Deflate negligible s(p). - //printfn "case 1" - let mutable f = e.[p - 2] - e.[p - 2] <- 0.0 - for j = p-2 downto k do - let mutable t = Geometry.hypot s.[j] f - printfn "t : %A - f: %A" t f - let cs = s.[j] / t - let sn = f / t - s.[j] <- t - if (j <> k) then - f <- -sn * e.[j - 1] - e.[j - 1] <- cs * e.[j - 1] - - if (wantv) then - for i = 0 to n-1 do - t <- cs * vmatrix.[i,j] + sn*vmatrix.[i,p - 1] - vmatrix.[i,p - 1] <- -sn * vmatrix.[i,j] + cs * vmatrix.[i,p - 1] - vmatrix.[i,j] <- t - - | 2 -> - // Split at negligible s(k). - //printfn "case 2" - let mutable f = e.[k - 1] - e.[k - 1] <- 0.0 - for j = k to p-1 do - let mutable t = Geometry.hypot s.[j] f - let cs = s.[j]/t - let sn = f/t - s.[j] <- t - f <- -sn*e.[j] - e.[j] <- cs*e.[j] - if (wantu) then - for i = 0 to m-1 do - t <- cs*umatrix.[i,j] + sn*umatrix.[i,k - 1] - umatrix.[i,k - 1] <- -sn*umatrix.[i,j] + cs*umatrix.[i,k - 1] - umatrix.[i,j] <- t - // Perform one qr step. - | 3 -> - // Calculate the shift. - //printfn "case 3" - let scale = - max (abs s.[p - 1]) (abs s.[p - 2]) - |> max (abs e.[p - 2]) - |> max (abs s.[k]) - |> max (abs e.[k]) - - let sp = s.[p - 1]/scale - let spm1 = s.[p - 2]/scale - let epm1 = e.[p - 2]/scale - let sk = s.[k]/scale - let ek = e.[k]/scale - let b = ((spm1 + sp)*(spm1 - sp) + epm1*epm1)/2.0 - let c = (sp*epm1)*(sp*epm1) - let mutable shift = 0.0 - if ((b <> 0.0) || (c <> 0.0)) then - shift <- sqrt (b*b + c) - if (b < 0.0) then - shift <- -shift - shift <- c/(b + shift) - - let mutable f = (sk + sp)*(sk - sp) + shift - let mutable g = sk*ek - - // Chase zeros. - for j = k to p-2 do - let mutable t = Geometry.hypot f g - let mutable cs = f/t - let mutable sn = g/t - if (j <> k) then - e.[j - 1] <- t - - f <- cs*s.[j] + sn*e.[j] - e.[j] <- cs*e.[j] - sn*s.[j] - g <- sn*s.[j + 1] - s.[j + 1] <- cs*s.[j + 1] - if (wantv) then - for i = 0 to n-1 do - t <- cs*vmatrix.[i,j] + sn*vmatrix.[i,j + 1] - vmatrix.[i,j + 1] <- -sn*vmatrix.[i,j] + cs*vmatrix.[i,j + 1] - vmatrix.[i,j] <- t - - - t <- Geometry.hypot f g - cs <- f/t - sn <- g/t - s.[j] <- t - f <- cs*e.[j] + sn*s.[j + 1] - s.[j + 1] <- -sn*e.[j] + cs*s.[j + 1] - g <- sn*e.[j + 1] - e.[j + 1] <- cs*e.[j + 1] - if (wantu && (j < m - 1)) then - for i = 0 to m-1 do - t <- cs*umatrix.[i,j] + sn*umatrix.[i,j + 1] - umatrix.[i,j + 1] <- -sn*umatrix.[i,j] + cs*umatrix.[i,j + 1] - umatrix.[i,j] <- t - - - - e.[p - 2] <- f - iter <- iter + 1 - - // Convergence. - | 4 -> - // Make the singular values positive. - //printfn "case 4" - if (s.[k] <= 0.0) then - s.[k] <- (if s.[k] < 0.0 then -s.[k] else 0.0) - if (wantv) then - for i = 0 to pp do - vmatrix.[i,k] <- -vmatrix.[i,k] - - - - // Order the singular values. - try - while (k < pp) do - - if (s.[k] >= s.[k + 1]) then raise BreakException - - let t = s.[k] - s.[k] <- s.[k + 1] - s.[k + 1] <- t - if (wantv && (k < n - 1)) then - for i = 0 to n-1 do - let t = vmatrix.[i,k + 1] // mutable - vmatrix.[i,k + 1] <- vmatrix.[i,k] - vmatrix.[i,k] <- t - - if (wantu && (k < m - 1)) then - for i = 0 to m-1 do - let t = umatrix.[i,k + 1] - umatrix.[i,k + 1] <- umatrix.[i,k] - umatrix.[i,k] <- t - - k <- k+1 - - with BreakException -> () - - iter <- 0 - p <- p - 1 - | _ -> failwithf "case %i does not exist" case - - if transposeBeforeSVD then - (vmatrix,s,transpose umatrix) - else - (umatrix,s,transpose vmatrix) - - - - let compute (a:float[,]) = - Array2D.copy a - |> computeInPlace - - \ No newline at end of file diff --git a/src/FSharp.Stats/Correlation.fs b/src/FSharp.Stats/Correlation.fs index 7651f1677..805000d38 100644 --- a/src/FSharp.Stats/Correlation.fs +++ b/src/FSharp.Stats/Correlation.fs @@ -1,4 +1,7 @@ namespace FSharp.Stats + +open FsMath + /// Contains correlation functions for different data types module Correlation = diff --git a/src/FSharp.Stats/DistanceMetrics.fs b/src/FSharp.Stats/DistanceMetrics.fs index 85c94a613..aa2f0ff20 100644 --- a/src/FSharp.Stats/DistanceMetrics.fs +++ b/src/FSharp.Stats/DistanceMetrics.fs @@ -1,5 +1,7 @@ namespace FSharp.Stats +open FsMath + ///Functions for computing distances of elements or sets module DistanceMetrics = diff --git a/src/FSharp.Stats/Distributions/Continuous/MultivariateNormal.fs b/src/FSharp.Stats/Distributions/Continuous/MultivariateNormal.fs index eba88d822..bef59dddd 100644 --- a/src/FSharp.Stats/Distributions/Continuous/MultivariateNormal.fs +++ b/src/FSharp.Stats/Distributions/Continuous/MultivariateNormal.fs @@ -1,9 +1,13 @@ namespace FSharp.Stats.Distributions.Continuous + open System open FSharp.Stats open FSharp.Stats.Distributions -open FSharp.Stats.Ops + +open FsMath +open FsMath.Algebra + // ###### // Multivariate normal distribution diff --git a/src/FSharp.Stats/Distributions/Discrete/Geometric.fs b/src/FSharp.Stats/Distributions/Discrete/Geometric.fs index c5504b69b..b43b4678c 100644 --- a/src/FSharp.Stats/Distributions/Discrete/Geometric.fs +++ b/src/FSharp.Stats/Distributions/Discrete/Geometric.fs @@ -4,7 +4,8 @@ open System open System.Numerics open FSharp.Stats open FSharp.Stats.Distributions -open FSharp.Stats.GenericMath +open FsMath +open FsMath.GenericMath //IFloatingPoint diff --git a/src/FSharp.Stats/Distributions/Discrete/Multinomial.fs b/src/FSharp.Stats/Distributions/Discrete/Multinomial.fs index c1b6bbda6..0b12baf4a 100644 --- a/src/FSharp.Stats/Distributions/Discrete/Multinomial.fs +++ b/src/FSharp.Stats/Distributions/Discrete/Multinomial.fs @@ -4,6 +4,8 @@ open System open FSharp.Stats open FSharp.Stats.Distributions open FSharp.Stats.SpecialFunctions +open FsMath + // n is the number of trails, // k is the vector of observed successes diff --git a/src/FSharp.Stats/Distributions/Distribution.fs b/src/FSharp.Stats/Distributions/Distribution.fs index 0952617de..901dc15a5 100644 --- a/src/FSharp.Stats/Distributions/Distribution.fs +++ b/src/FSharp.Stats/Distributions/Distribution.fs @@ -1,6 +1,8 @@ namespace FSharp.Stats.Distributions open FSharp.Stats +open FsMath + module Parameters = diff --git a/src/FSharp.Stats/FSIPrinters.fs b/src/FSharp.Stats/FSIPrinters.fs index dc37f480f..2b1babbdf 100644 --- a/src/FSharp.Stats/FSIPrinters.fs +++ b/src/FSharp.Stats/FSIPrinters.fs @@ -3,6 +3,7 @@ module FSIPrinters = open System open System.Linq + open FsMath let matrix (mat: Matrix<_>) = //TODO: Difficult to read because of all exceptions. Simplified version! diff --git a/src/FSharp.Stats/FSharp.Stats.fsproj b/src/FSharp.Stats/FSharp.Stats.fsproj index db80f410f..bc175d2b9 100644 --- a/src/FSharp.Stats/FSharp.Stats.fsproj +++ b/src/FSharp.Stats/FSharp.Stats.fsproj @@ -29,15 +29,6 @@ - - - - - - - - - @@ -66,9 +57,6 @@ - - - @@ -171,10 +159,19 @@ + + + + + + + + + diff --git a/src/FSharp.Stats/Fitting/CrossValidation.fs b/src/FSharp.Stats/Fitting/CrossValidation.fs index 8dab5a641..6e724ac76 100644 --- a/src/FSharp.Stats/Fitting/CrossValidation.fs +++ b/src/FSharp.Stats/Fitting/CrossValidation.fs @@ -1,5 +1,7 @@ namespace FSharp.Stats.Fitting +open FsMath + (* diff --git a/src/FSharp.Stats/Fitting/GoodnessOfFit.fs b/src/FSharp.Stats/Fitting/GoodnessOfFit.fs index 8efdb100d..48783c81d 100644 --- a/src/FSharp.Stats/Fitting/GoodnessOfFit.fs +++ b/src/FSharp.Stats/Fitting/GoodnessOfFit.fs @@ -8,6 +8,9 @@ we estimate the relationship of one variable with another by expressing one in t module GoodnessOfFit = open FSharp.Stats open System + open FsMath + + /// Three sum of squares type SumOfSquares = { /// Regression sum of squares (SSR: explained); Sum((yFit-yMean)**2.) diff --git a/src/FSharp.Stats/Fitting/LinearRegression.fs b/src/FSharp.Stats/Fitting/LinearRegression.fs index b02ab463b..0d89702c5 100644 --- a/src/FSharp.Stats/Fitting/LinearRegression.fs +++ b/src/FSharp.Stats/Fitting/LinearRegression.fs @@ -3,7 +3,8 @@ namespace FSharp.Stats.Fitting open System open FSharp.Stats -open FSharp.Stats.Algebra +open FsMath +open FsMath.Algebra ///

/// Linear regression is used to estimate the relationship of one variable (y) with another (x) by expressing y in terms of a linear function of x. diff --git a/src/FSharp.Stats/Fitting/LogisticRegression.fs b/src/FSharp.Stats/Fitting/LogisticRegression.fs index ae03c4008..873c1a639 100644 --- a/src/FSharp.Stats/Fitting/LogisticRegression.fs +++ b/src/FSharp.Stats/Fitting/LogisticRegression.fs @@ -9,6 +9,7 @@ open FSharp.Stats module LogisticRegression = open System + open FsMath /// Creates a new vector (length = obs.Length + 1) whose /// first element is 1.0 (for the intercept), followed by obs's elements. diff --git a/src/FSharp.Stats/Fitting/NonLinearRegression.fs b/src/FSharp.Stats/Fitting/NonLinearRegression.fs index daec51af3..54c5234ca 100644 --- a/src/FSharp.Stats/Fitting/NonLinearRegression.fs +++ b/src/FSharp.Stats/Fitting/NonLinearRegression.fs @@ -7,7 +7,8 @@ we estimate the relationship of one variable with another by expressing one in t *) module NonLinearRegression = open FSharp.Stats - open FSharp.Stats.Algebra + open FsMath + open FsMath.Algebra /// let standardErrorOfPrediction dOF (predicted:float []) (actual:float []) = @@ -301,7 +302,7 @@ module NonLinearRegression = let hessian = jacobian'.Transpose() * jacobian' |> scaleJacobian scaleFactors let diagonal = Matrix.diagonal (Array.map (fun x -> ((lambda)*x)) (hessian |> Matrix.getDiagonal)) let modHessian = (hessian + diagonal) - let step = FSharp.Stats.Algebra.LinearAlgebra.solveLinearSystem modHessian gradient + let step = LinearAlgebra.solveLinearSystem modHessian gradient let newParamGuessInt = currentParamGuessInt .- step let newParamGuessExt = toExternalParameters lowerBound upperBound newParamGuessInt let newValueRSS = getRSS model xData yData newParamGuessExt diff --git a/src/FSharp.Stats/Fitting/Spline.fs b/src/FSharp.Stats/Fitting/Spline.fs index 7dbef668d..80eaa661c 100644 --- a/src/FSharp.Stats/Fitting/Spline.fs +++ b/src/FSharp.Stats/Fitting/Spline.fs @@ -4,7 +4,8 @@ namespace FSharp.Stats.Fitting module Spline = open FSharp.Stats - open FSharp.Stats.Algebra + open FsMath + open FsMath.Algebra /// Some preprocessing of the input data /// diff --git a/src/FSharp.Stats/Interpolation.fs b/src/FSharp.Stats/Interpolation.fs index bc0555726..dfbe59bbe 100644 --- a/src/FSharp.Stats/Interpolation.fs +++ b/src/FSharp.Stats/Interpolation.fs @@ -2,7 +2,8 @@ open System open FSharp.Stats -open FSharp.Stats.Algebra +open FsMath +open FsMath.Algebra /// /// This module contains functionalities to perform various interpolation methods for two dimensional data. diff --git a/src/FSharp.Stats/ML/DistanceMetrics.fs b/src/FSharp.Stats/ML/DistanceMetrics.fs index e0e1c4be4..a9c034a2a 100644 --- a/src/FSharp.Stats/ML/DistanceMetrics.fs +++ b/src/FSharp.Stats/ML/DistanceMetrics.fs @@ -2,6 +2,8 @@ open System open FSharp.Stats +open FsMath + [] module DistanceMetrics = diff --git a/src/FSharp.Stats/ML/Unsupervised/ClusterNumber.fs b/src/FSharp.Stats/ML/Unsupervised/ClusterNumber.fs index 1150da672..e9fe0579b 100644 --- a/src/FSharp.Stats/ML/Unsupervised/ClusterNumber.fs +++ b/src/FSharp.Stats/ML/Unsupervised/ClusterNumber.fs @@ -3,6 +3,8 @@ namespace FSharp.Stats.ML.Unsupervised open System open FSharp.Stats open FSharpAux +open FsMath + module ClusterNumber = diff --git a/src/FSharp.Stats/ML/Unsupervised/IterativeClustering.fs b/src/FSharp.Stats/ML/Unsupervised/IterativeClustering.fs index 695db9aea..9c4a286ea 100644 --- a/src/FSharp.Stats/ML/Unsupervised/IterativeClustering.fs +++ b/src/FSharp.Stats/ML/Unsupervised/IterativeClustering.fs @@ -6,6 +6,7 @@ module IterativeClustering = open FSharp.Stats open FSharp.Stats.DistanceMetrics + open FsMath diff --git a/src/FSharp.Stats/Optimization/NelderMead.fs b/src/FSharp.Stats/Optimization/NelderMead.fs index 34235174e..e0a39b90e 100644 --- a/src/FSharp.Stats/Optimization/NelderMead.fs +++ b/src/FSharp.Stats/Optimization/NelderMead.fs @@ -3,7 +3,8 @@ module NelderMead = open FSharp.Stats - open FSharp.Stats.Algebra + open FsMath + open FsMath.Algebra type NmConfig = { /// Delta used to generate initial simplex for non-zero value elements diff --git a/src/FSharp.Stats/Signal/Baseline.fs b/src/FSharp.Stats/Signal/Baseline.fs index cbdef104b..c2dea6112 100644 --- a/src/FSharp.Stats/Signal/Baseline.fs +++ b/src/FSharp.Stats/Signal/Baseline.fs @@ -1,7 +1,7 @@ namespace FSharp.Stats.Signal open FSharp.Stats - +open FsMath module Baseline = diff --git a/src/FSharp.Stats/Signal/Convolution.fs b/src/FSharp.Stats/Signal/Convolution.fs index fc1b56fff..fa10b4f83 100644 --- a/src/FSharp.Stats/Signal/Convolution.fs +++ b/src/FSharp.Stats/Signal/Convolution.fs @@ -1,7 +1,7 @@ namespace FSharp.Stats.Signal open FSharp.Stats - +open FsMath module Convolution = diff --git a/src/FSharp.Stats/Signal/Filtering.fs b/src/FSharp.Stats/Signal/Filtering.fs index d70f09cad..41fb4d257 100644 --- a/src/FSharp.Stats/Signal/Filtering.fs +++ b/src/FSharp.Stats/Signal/Filtering.fs @@ -2,7 +2,8 @@ open System open FSharp.Stats -open FSharp.Stats.Algebra +open FsMath +open FsMath.Algebra module Filtering = diff --git a/src/FSharp.Stats/Signal/Normalization.fs b/src/FSharp.Stats/Signal/Normalization.fs index 6678980fe..de46e6568 100644 --- a/src/FSharp.Stats/Signal/Normalization.fs +++ b/src/FSharp.Stats/Signal/Normalization.fs @@ -1,6 +1,7 @@ namespace FSharp.Stats.Signal open FSharp.Stats +open FsMath module Normalization = diff --git a/src/FSharp.Stats/Signal/Outliers.fs b/src/FSharp.Stats/Signal/Outliers.fs index 5dda0ff2f..a2f166a8f 100644 --- a/src/FSharp.Stats/Signal/Outliers.fs +++ b/src/FSharp.Stats/Signal/Outliers.fs @@ -3,7 +3,7 @@ module Outliers = open FSharp.Stats - open Matrix + open FsMath /// Tukey's fences based on interquartile range. c defines the magnitude of interquartile range that is added/subtracted to Q3 and Q1 respectively.
Commonly c is 1.5 for outliers and 3 for points 'far out' (Tukey 1977).
/// diff --git a/src/FSharp.Stats/Signal/PeakDetection.fs b/src/FSharp.Stats/Signal/PeakDetection.fs index d6a42ef76..a011d4865 100644 --- a/src/FSharp.Stats/Signal/PeakDetection.fs +++ b/src/FSharp.Stats/Signal/PeakDetection.fs @@ -2,7 +2,8 @@ namespace FSharp.Stats.Signal open FSharp.Stats open System - +open FsMath +open FsMath.Algebra module PeakDetection = diff --git a/src/FSharp.Stats/Signal/QQPlot.fs b/src/FSharp.Stats/Signal/QQPlot.fs index 0014e2c85..160a231c3 100644 --- a/src/FSharp.Stats/Signal/QQPlot.fs +++ b/src/FSharp.Stats/Signal/QQPlot.fs @@ -6,6 +6,8 @@ open System open FSharp.Stats.SpecialFunctions open FSharp.Stats.Quantile open FSharp.Stats.Interpolation +open FsMath + module QQPlot = diff --git a/src/FSharp.Stats/Table.fs b/src/FSharp.Stats/Table.fs index 793ac42e5..3212a0b55 100644 --- a/src/FSharp.Stats/Table.fs +++ b/src/FSharp.Stats/Table.fs @@ -3,7 +3,8 @@ open System open FSharp.Stats - +open FsMath +open FsMath.Algebra open System open System.Collections.Generic @@ -50,7 +51,7 @@ type Table<'R,'C,'T and 'T :> Numerics.INumber<'T> and 'T : (new: unit -> 'T) and 'T : struct - and 'T : equality + and 'T : comparison and 'T :> ValueType> ( rowKeys : 'R[], colKeys : 'C[], diff --git a/src/FSharp.Stats/Testing/ConfusionMatrix.fs b/src/FSharp.Stats/Testing/ConfusionMatrix.fs index 8290da7d1..dd3f0af50 100644 --- a/src/FSharp.Stats/Testing/ConfusionMatrix.fs +++ b/src/FSharp.Stats/Testing/ConfusionMatrix.fs @@ -1,5 +1,7 @@ namespace FSharp.Stats.Testing open FSharp.Stats +open FsMath + /// Confusion matrix for binary classification type BinaryConfusionMatrix = { diff --git a/src/FSharp.Stats/Testing/ContingencyTable.fs b/src/FSharp.Stats/Testing/ContingencyTable.fs index 71a93608d..c92083d70 100644 --- a/src/FSharp.Stats/Testing/ContingencyTable.fs +++ b/src/FSharp.Stats/Testing/ContingencyTable.fs @@ -3,7 +3,7 @@ open System open System.Collections.Generic open FSharp.Stats - +open FsMath /// An estimate with its standard‐error uncertainty. type UncertainValue = { diff --git a/src/FSharp.Stats/Testing/FTest.fs b/src/FSharp.Stats/Testing/FTest.fs index 83c144258..f9c3e3fa1 100644 --- a/src/FSharp.Stats/Testing/FTest.fs +++ b/src/FSharp.Stats/Testing/FTest.fs @@ -1,5 +1,7 @@ namespace FSharp.Stats.Testing +open FsMath + module FTest = open FSharp.Stats diff --git a/src/FSharp.Stats/Testing/PostHoc.fs b/src/FSharp.Stats/Testing/PostHoc.fs index 072332307..2b4968563 100644 --- a/src/FSharp.Stats/Testing/PostHoc.fs +++ b/src/FSharp.Stats/Testing/PostHoc.fs @@ -1,6 +1,7 @@ namespace FSharp.Stats.Testing open FSharp.Stats +open FsMath module PostHoc = diff --git a/src/FSharp.Stats/Testing/RMT.fs b/src/FSharp.Stats/Testing/RMT.fs index 405ab8535..1e5922a61 100644 --- a/src/FSharp.Stats/Testing/RMT.fs +++ b/src/FSharp.Stats/Testing/RMT.fs @@ -1,5 +1,7 @@ namespace FSharp.Stats.Testing +open FsMath + module RMT = // implementation from: diff --git a/src/FSharp.Stats/Testing/TTest.fs b/src/FSharp.Stats/Testing/TTest.fs index 98017a682..8733d86ae 100644 --- a/src/FSharp.Stats/Testing/TTest.fs +++ b/src/FSharp.Stats/Testing/TTest.fs @@ -4,6 +4,7 @@ namespace FSharp.Stats.Testing module TTest = open System open FSharp.Stats + open FsMath /// Equal or unequal sample sizes, assume nothing about variance. /// input: (mean1,variance1,N1) (mean2,variance2,N3) diff --git a/src/FSharp.Stats/Testing/Tables.fs b/src/FSharp.Stats/Testing/Tables.fs index c7b071c27..42c10a406 100644 --- a/src/FSharp.Stats/Testing/Tables.fs +++ b/src/FSharp.Stats/Testing/Tables.fs @@ -1,6 +1,8 @@ namespace FSharp.Stats.Testing open FSharp.Stats +open FsMath + /// Some statistical tests lack in distributions for exact p value calculation. In order to enable the usage of these tests module Tables = diff --git a/tests/FSharp.Stats.Tests/Acceleration.fs b/tests/FSharp.Stats.Tests/Acceleration.fs deleted file mode 100644 index 4c7b45014..000000000 --- a/tests/FSharp.Stats.Tests/Acceleration.fs +++ /dev/null @@ -1,49 +0,0 @@ -module AccelerationTests - -open Expecto -open System -open FSharp.Stats -open TestExtensions - -open Expecto - -[] -let dotRangeTests = - testList "dotRange tests" [ - - test "Basic dot product with zero offset" { - let a = [| 1.0; 2.0; 3.0 |] - let b = [| 4.0; 5.0; 6.0 |] - let result = Acceleration.SIMDRangeUtils.dotRange a 0 b 0 3 - Expect.floatClose Accuracy.high result 32.0 "Dot product mismatch" - } - - test "Dot product with offset in first array" { - let a = [| 0.0; 1.0; 2.0; 3.0 |] // use 1.0, 2.0, 3.0 - let b = [| 4.0; 5.0; 6.0 |] - let result = Acceleration.SIMDRangeUtils.dotRange a 1 b 0 3 - Expect.floatClose Accuracy.high result 32.0 "Offset dot mismatch" - } - - test "Dot product with both arrays offset" { - let a = [| 0.0; 1.0; 2.0; 3.0 |] - let b = [| 0.0; 4.0; 5.0; 6.0 |] - let result = Acceleration.SIMDRangeUtils.dotRange a 1 b 1 3 - Expect.floatClose Accuracy.high result 32.0 "Offset-dot mismatch" - } - - test "Dot with zero-length" { - let a = [| 1.0; 2.0; 3.0 |] - let b = [| 4.0; 5.0; 6.0 |] - let result = Acceleration.SIMDRangeUtils.dotRange a 0 b 0 0 - Expect.equal result 0.0 "Zero-length dot should be 0" - } - - test "Out of bounds throws" { - let a = [| 1.0; 2.0 |] - let b = [| 1.0; 2.0 |] - Expect.throws (fun () -> - Acceleration.SIMDRangeUtils.dotRange a 1 b 1 2 |> ignore) - "Should throw on out-of-bounds" - } - ] diff --git a/tests/FSharp.Stats.Tests/DistanceMetrics.fs b/tests/FSharp.Stats.Tests/DistanceMetrics.fs index 4d4cafd0b..f3700eac7 100644 --- a/tests/FSharp.Stats.Tests/DistanceMetrics.fs +++ b/tests/FSharp.Stats.Tests/DistanceMetrics.fs @@ -2,6 +2,7 @@ open Expecto open FSharp.Stats open FSharp.Stats.DistanceMetrics.Vector +open FsMath open FSharp.Stats.DistanceMetrics [] let hammingfunctiontests = diff --git a/tests/FSharp.Stats.Tests/DistributionsContinuous.fs b/tests/FSharp.Stats.Tests/DistributionsContinuous.fs index 6dafe0baf..6d13c751c 100644 --- a/tests/FSharp.Stats.Tests/DistributionsContinuous.fs +++ b/tests/FSharp.Stats.Tests/DistributionsContinuous.fs @@ -2,6 +2,7 @@ open Expecto open System +open FsMath open FSharp.Stats open FSharp.Stats.Distributions open FSharp.Stats.Distributions.Continuous diff --git a/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj b/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj index 94d433f8b..f17873db7 100644 --- a/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj +++ b/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj @@ -6,7 +6,6 @@ - @@ -20,9 +19,6 @@ - - - @@ -33,7 +29,6 @@ - diff --git a/tests/FSharp.Stats.Tests/Fitting.fs b/tests/FSharp.Stats.Tests/Fitting.fs index 84fc56dd0..91111c405 100644 --- a/tests/FSharp.Stats.Tests/Fitting.fs +++ b/tests/FSharp.Stats.Tests/Fitting.fs @@ -1,7 +1,7 @@ module FittingTests open Expecto - +open FsMath open FSharp.Stats open FSharp.Stats.Fitting open FSharp.Stats.Fitting.NonLinearRegression diff --git a/tests/FSharp.Stats.Tests/Interpolation.fs b/tests/FSharp.Stats.Tests/Interpolation.fs index e97496a99..6a8054813 100644 --- a/tests/FSharp.Stats.Tests/Interpolation.fs +++ b/tests/FSharp.Stats.Tests/Interpolation.fs @@ -1,6 +1,7 @@ module InterpolationTests open Expecto +open FsMath open FSharp.Stats open FSharp.Stats.Interpolation diff --git a/tests/FSharp.Stats.Tests/LinAlgebra.fs b/tests/FSharp.Stats.Tests/LinAlgebra.fs deleted file mode 100644 index dc3dc3024..000000000 --- a/tests/FSharp.Stats.Tests/LinAlgebra.fs +++ /dev/null @@ -1,529 +0,0 @@ -module LinAlgebraTests - -open Expecto -open System -open FSharp.Stats -open FSharp.Stats.Algebra - -[] -let linearAlgebraTests = - testList "LinearAlgebra Tests" [ - - // ---------------------------------------------------------------------- - // Basic tests - // ---------------------------------------------------------------------- - - testCase "subScaledRowInPlace: subtract scaled portion of source row from destination row" <| fun _ -> - let dst = [|10.0; 20.0; 30.0|] - let src = [|1.0 ; 2.0 ; 3.0 |] - LinearAlgebra.subScaledRowInPlace 2.0 0 0 3 dst src - let expected = [|8.0; 16.0; 24.0|] - Expect.equal dst expected "dst should be updated correctly" - - testCase "householderTransform: returns a Householder vector for column i" <| fun _ -> - let matData = [| 1.0; 2.0; 3.0 - 4.0; 5.0; 6.0 - 7.0; 8.0; 9.0 |] - let A = Matrix(3, 3, matData) - let v = LinearAlgebra.householderTransform A 1 - Expect.equal v.Length 3 "Householder vector should have 3 elements" - Expect.isFalse (Double.IsNaN v.[1]) "v.[1] should not be NaN" - - testCase "qrModifiedGramSchmidt: Q*R reconstructs A (2x2 example)" <| fun _ -> - let A = Matrix(2, 2, [|1.0; 2.0; 3.0; 4.0|]) - let Q, R = LinearAlgebra.qrModifiedGramSchmidt A - // Multiply Q*R => 2x2 => compare with A - let APrime = Array.zeroCreate 4 - for i in 0..1 do - for j in 0..1 do - let mutable sum = 0.0 - for k in 0..1 do - sum <- sum + Q.[i,k] * R.[k,j] - APrime.[i*2 + j] <- sum - for idx in 0..3 do - Expect.floatClose Accuracy.high A.Data.[idx] APrime.[idx] - $"A' and A differ at idx={idx}" - - testCase "backSubstitute: solves R*x=y for x, R upper-triangular" <| fun _ -> - // R = [2,3; 0,4], y = [8,12] => x= [-0.5,3] - let R = Matrix(2, 2, [|2.0;3.0; 0.0;4.0|]) - let y = [|8.0;12.0|] - let x = LinearAlgebra.backSubstitute R y - let expected = [|-0.5;3.0|] - Expect.floatClose Accuracy.high expected.[0] x.[0] "x0 mismatch" - Expect.floatClose Accuracy.high expected.[1] x.[1] "x1 mismatch" - - testCase "solveLinearQR: solves A*x=b (2x2 system)" <| fun _ -> - // A= [1,2; 3,4], b= [5,11] => x= [1,2] - let A = Matrix(2,2,[|1.;2.;3.;4.|]) - let b = [|5.; 11.|] - let x = LinearAlgebra.solveLinearQR A b - let expected = [|1.;2.|] - Expect.floatClose Accuracy.high expected.[0] x.[0] "x[0] mismatch" - Expect.floatClose Accuracy.high expected.[1] x.[1] "x[1] mismatch" - - - // ====================================================================== - // EDGE CASES: Infinity, -Infinity, NaN - // ====================================================================== - testList "Edge Cases with Infinity, -Infinity, NaN" [ - - testCase "subScaledRowInPlace with scaleVal = +∞" <| fun _ -> - // Let dst[0] = +∞, and scaleVal= +∞. Then dst[0] = ∞ - ∞*something => usually NaN - // Also check second entry for leftover infinite results. - let dst = [| Double.PositiveInfinity; 10.0 |] - let src = [| 2.0; 1.0 |] - LinearAlgebra.subScaledRowInPlace Double.PositiveInfinity 0 0 2 dst src - // The math: - // dst[0] <- ∞ - (∞ * 2) => ∞ - ∞ => NaN - // dst[1] <- 10 - (∞ * 1) => 10 - ∞ => -∞ - Expect.isTrue (Double.IsNaN dst.[0]) "Expected NaN in dst.[0]" - Expect.isTrue (Double.IsNegativeInfinity dst.[1]) "Expected -∞ in dst.[1]" - - testCase "householderTransform with NaN in matrix" <| fun _ -> - // Insert a NaN into the matrix - let matData = [| 1.0; Double.NaN; 3.0 - 4.0; 5.0; 6.0 |] - // 2x3 matrix - let A = Matrix(2, 3, matData) - let v = LinearAlgebra.householderTransform A 1 - // It's likely that the result will incorporate NaN somewhere (since row #1 has NaN). - // We'll confirm that it yields at least one NaN. - let hasNaN = v |> Array.exists Double.IsNaN - Expect.isTrue hasNaN "Expected Householder vector to contain NaN" - - testCase "backSubstitute with 0.0 on R-diagonal => Infinity result" <| fun _ -> - // R = [ [2., 1.], - // [0., 0.] ] => zero on diagonal => x.[1] => y.[1] / 0 => ∞ or NaN - let rData = [|2.;1.; 0.;0.|] - let R = Matrix(2,2,rData) - let y = [|5.0; 3.0|] - // This might yield x.[1] = 3.0 / 0 => +∞ (or possibly throw). - // If your code doesn't throw, let's see if it yields Infinity: - let x = LinearAlgebra.backSubstitute R y - // We'll check x.[1] - Expect.isTrue (Double.IsInfinity x.[1] || Double.IsNaN x.[1]) - "Expected Infinity or NaN for x.[1]" - - testCase "solveLinearQR with b containing ∞" <| fun _ -> - // 2x2 matrix A => [1,2; 3,4], b => [∞, 1] - // The solution might be ∞ or NaN, or the factorization might produce weird results. - let A = Matrix(2,2,[|1.;2.;3.;4.|]) - let b = [|Double.PositiveInfinity; 1.0|] - // We'll see if it returns a vector with ∞ or NaN, or possibly throws. - // We'll not test for a "correct" solution in the usual sense, only that it yields a result. - let x = LinearAlgebra.solveLinearQR A b - // We expect at least one ∞ or NaN in the solution: - let hasSpecial = x |> Array.exists (fun v -> Double.IsNaN(v) || Double.IsInfinity(v)) - Expect.isTrue hasSpecial "Expected ∞ or NaN in the solution" - ] - - testList "Extended LinearAlgebra Tests" [ - - // ===================================================================== - // solveLinearQR - // ===================================================================== - testCase "solveLinearQR: throws if b's length doesn't match A's row count" <| fun _ -> - // A is 2x2, but b has length=3 => mismatch - let A = Matrix(2, 2, [|1.0;2.0; 3.0;4.0|]) - let b = [|1.0; 2.0; 3.0|] // length=3 - Expect.throwsT (fun () -> - let _ = LinearAlgebra.solveLinearQR A b - () - ) "Should throw if A.NumRows != b.Length" - - testCase "solveLinearQR: solves small 3x3 system" <| fun _ -> - // We'll define a 3x3 with an easy integer solution. - // - // A*x = b - // A = [ [1.,2.,0.] - // [2.,1.,1.] - // [0.,1.,2.] ] - // - // We'll pick x => [1., 2., 3.] => let's compute b => A*x by hand: - // row0 => 1*1 +2*2 +0*3 = 5 - // row1 => 2*1 +1*2 +1*3 = 2 +2 +3=7 - // row2 => 0*1 +1*2 +2*3 = 2 +6=8 - // => b= [5,7,8] - let Adata = [| - 1.0; 2.0; 0.0 - 2.0; 1.0; 1.0 - 0.0; 1.0; 2.0 |] // row-major flatten - let A = Matrix(3, 3, Adata) - let b = [|5.0; 7.0; 8.0|] - - let x = LinearAlgebra.solveLinearQR A b - // Expect x= [1,2,3] - let expected = [|1.0; 2.0; 3.0|] - for i in 0..2 do - Expect.floatClose Accuracy.high expected.[i] x.[i] $"x[{i}] mismatch" - - // ===================================================================== - // solveTriangularLinearSystems - // ===================================================================== - testCase "solveTriangularLinearSystems: throws if shape mismatch" <| fun _ -> - // K must be square NxN, B must have Nx? shape - // We'll define a 2x2 K, and B as 3x2 => mismatch - let K = Matrix(2, 2, [|2.0;0.0; 1.0;2.0|]) // just a 2x2 - let B = Matrix(3, 2, [|1.0;2.0; 3.0;4.0; 5.0;6.0|]) // 3x2 - Expect.throwsT (fun () -> - let _ = LinearAlgebra.solveTriangularLinearSystems K B true - () - ) "Should throw on dimension mismatch" - - testCase "solveTriangularLinearSystems: lower-triangular forward substitution (2x2, 2 columns)" <| fun _ -> - // K= L= [ [2,0], - // [1,2] ] - // K is 2x2, B is 2x2 - // We'll pick B so that K*X = B has a known solution X. - // - // Suppose X => [ [1., 10.], - // [2., 4.] ] - // Then K*X => B - // B row0 => row0*K => [2*1 +0*2, 2*10 +0*4] => [2,20] - // B row1 => row1*K => [1*1 +2*2, 1*10 +2*4] => [1+4=5, 10+8=18] - // Wait, careful with row-major. Actually, let's do it systematically: - // If K is NxN, X is NxM => B is NxM - // B[i,*] = sum_{j} (K[i,j] * X[j,*]) (like matrix multiply) - // - // For K= [ [2,0], [1,2] ], X= [ [1,10],[2,4] ] - // Flatten X => row0= (1,10), row1= (2,4) - // B[0,*] => K[0,0]*X[0,*] + K[0,1]*X[1,*] - // => 2*(1,10) + 0*(2,4) => (2,20) - // B[1,*] => K[1,0]*X[0,*] + K[1,1]*X[1,*] - // => 1*(1,10)+2*(2,4) => (1+4, 10+8)= (5,18) - // => B= [ (2,20),(5,18) ] - let Kdata = [| 2.0; 0.0 - 1.0; 2.0 |] - let X_expected_data = [| 1.0; 10.0 - 2.0; 4.0 |] - let B_data = [| 2.0; 20.0 - 5.0; 18.0 |] - let Kmat = Matrix(2,2,Kdata) - let Bmat = Matrix(2,2,B_data) - // We want to solve K*X = B for X. isLower=true => forward substitution - let Xsol = LinearAlgebra.solveTriangularLinearSystems Kmat Bmat true - // Check that Xsol matches X_expected - for i in 0..3 do - Expect.floatClose Accuracy.high X_expected_data.[i] Xsol.Data.[i] $"X mismatch at idx={i}" - - testCase "solveTriangularLinearSystems: upper-triangular backward substitution (2x2, 2 columns)" <| fun _ -> - // Let K= U= [ [2,3], [0,4] ] - // We'll define X => [ [1,10],[2,4] ] - // Then B= K*X => 2x2 - // Let's compute B carefully: - // B row0 => K[0,0]*X[0,*] + K[0,1]*X[1,*] => 2*(1,10)+3*(2,4) => (2+6,20+12)= (8,32) - // B row1 => K[1,0]*X[0,*] + K[1,1]*X[1,*] => 0*(1,10)+4*(2,4) => (8,16) - // => B= [ (8,32),(8,16) ] - let Kdata = [|2.0;3.0; 0.0;4.0|] // 2x2 upper - let X_expected_data = [| 1.0; 10.0 - 2.0; 4.0 |] // shape=2x2 - let B_data = [| 8.0; 32.0 - 8.0; 16.0 |] - let Kmat = Matrix(2,2,Kdata) - let Bmat = Matrix(2,2,B_data) - let Xsol = LinearAlgebra.solveTriangularLinearSystems Kmat Bmat false // isLower=false => backward sub - for i in 0..3 do - Expect.floatClose Accuracy.high X_expected_data.[i] Xsol.Data.[i] $"X mismatch at idx={i}" - - // ===================================================================== - // solveTriangularLinearSystem - // ===================================================================== - testCase "solveTriangularLinearSystem: dimension mismatch => throws" <| fun _ -> - // K=2x2, v= length=3 => mismatch - let K = Matrix(2,2,[|2.0;0.0; 1.0;2.0|]) - let v = [|1.0;2.0;3.0|] - Expect.throwsT (fun () -> - let _ = LinearAlgebra.solveTriangularLinearSystem K v true - () - ) "Should throw dimension mismatch" - - testCase "solveTriangularLinearSystem: lower triangular forward substitution (2x2 single system)" <| fun _ -> - // K= L= [ [2,0],[1,2] ] - // We'll define a single x => [1,2], compute b => K*x, then see if we get x back. - // - // For x => [1.,2.], - // B row0 => 2*1 +0*2=2 - // B row1 => 1*1 +2*2=1+4=5 - // => b= [2,5] - let Kdata = [|2.0;0.0; 1.0;2.0|] - let Kmat = Matrix(2,2,Kdata) - let xExpected = [|1.0;2.0|] - let b = [|2.0;5.0|] - // Solve K*x=b - let xSol = LinearAlgebra.solveTriangularLinearSystem Kmat b true - Expect.floatClose Accuracy.high xExpected.[0] xSol.[0] "x[0] mismatch" - Expect.floatClose Accuracy.high xExpected.[1] xSol.[1] "x[1] mismatch" - - testCase "solveTriangularLinearSystem: upper triangular backward substitution (2x2 single system)" <| fun _ -> - // K= U= [ [2,3],[0,4] ] - // Let x => [1,2]. Then b => K*x => - // row0 => 2*1 +3*2=2+6=8 - // row1 => 0*1 +4*2=8 - // => b= [8,8] - let Kdata = [|2.0;3.0; 0.0;4.0|] - let Kmat = Matrix(2,2,Kdata) - let xExpected = [|1.0;2.0|] - let b = [|8.0;8.0|] - let xSol = LinearAlgebra.solveTriangularLinearSystem Kmat b false - Expect.floatClose Accuracy.high xExpected.[0] xSol.[0] "x[0] mismatch" - Expect.floatClose Accuracy.high xExpected.[1] xSol.[1] "x[1] mismatch" - - ] - - testList "Additional Linear Algebra Tests" [ - - // ===================================================================== - // 1) qrDecompose - // ===================================================================== - testCase "qrDecompose: Q*R ~ A for a small 3x2" <| fun _ -> - // A=3x2 => [ [1.,2.],[3.,4.],[5.,6.] ] - let Adata = [|1.;2.; 3.;4.; 5.;6.|] - let A = Matrix(3, 2, Adata) - - let Q, R = LinearAlgebra.qrDecompose A - // Q is 3x3 in the code above since we use the identity(3) initially, - // but only the first 2 columns or some partial region might be relevant. - // We'll do a truncated multiply to compare or do a naive Q*R if R is 3x2. - - // Let's do a direct approach: A' = Q * R (both are 3x2 effectively, if R is 3x2). - // If R is the same shape as A, it's 3x2 => multiply 3x3 * 3x2 isn't well-defined. - // But the code as posted doesn't necessarily do the typical Householder approach - // that modifies R to upper triangular shape. It's more of a placeholder. - // We'll do a "Compare shape" approach, then do a partial multiply in any case. - - let APrimeData = Array.zeroCreate (3*2) - // We'll assume R is 3x2. Then Q is 3x3 => Q(3x3)*R(3x2)= A'(3x2). - for i in 0..2 do - for j in 0..1 do - let mutable sum = 0.0 - for k in 0..2 do - sum <- sum + Q.[i,k] * R.[k,j] - APrimeData.[i*2 + j] <- sum - - // Compare A' with A - for idx in 0..5 do - Expect.floatClose Accuracy.high Adata.[idx] APrimeData.[idx] - $"A' vs A mismatch at idx={idx}" - - // ===================================================================== - // 2) leastSquares - // ===================================================================== - testCase "leastSquares: overdetermined system 3x2" <| fun _ -> - // We'll create a design matrix A=3x2, b=3 - // A= [ [1.,2.], - // [2.,1.], - // [3.,4.] ] - // b= [ [8.],[10.],[19.] ] - // We want to solve min ||A x - b||^2 for x in R^2. - // We'll pick a small example and do a naive check or compare with a known solution if possible. - - let Adata = [|1.;2.; 2.;1.; 3.;4.|] - let A = Matrix(3, 2, Adata) - let b = [|8.; 10.; 19.|] - - let x = LinearAlgebra.leastSquares A b - // We only do a round-trip check: A*x ~ b in least-squares sense. - // We'll compute A*x (3x2 * 2 => 3) and see if that is close to b. - let Ax = - let result = Array.zeroCreate 3 - for i in 0..2 do - // row i => i*2, dot with x - let rowOffset = i*2 - result.[i] <- Adata.[rowOffset]*x.[0] + Adata.[rowOffset+1]*x.[1] - result - - // Compare Ax to b - for i in 0..2 do - // Because it's least squares, we might not get an exact match if system is not exactly consistent. - // But let's see if it's close. - Expect.floatClose Accuracy.high b.[i] Ax.[i] $"A*x mismatch at row {i}" - - // ===================================================================== - // 3) cholesky - // ===================================================================== - testCase "cholesky: factor a positive-definite 3x3" <| fun _ -> - // We'll define A => 3x3 symmetric positive definite. - // E.g. A= [ [4, 12, -16], - // [12,37, -43], - // [-16, -43, 98] ] - // Classic example => L => [ [2,0,0], [6,1,0], [-8,5,3] ] - let Adata = [| - 4.0; 12.0; -16.0; - 12.0; 37.0; -43.0; - -16.0; -43.0; 98.0; |] - let A = Matrix(3,3,Adata) - let L = LinearAlgebra.cholesky A - // Compare with known L - let Lexpected = [| 2.0; 0.0; 0.0; - 6.0; 1.0; 0.0; - -8.0; 5.0; 3.0; |] - for i in 0..8 do - Expect.floatClose Accuracy.high Lexpected.[i] L.Data.[i] $"L mismatch at idx {i}" - - testCase "cholesky: throws if matrix is not square" <| fun _ -> - let nonsquare = Matrix(2,3, [|1.0;2.0;3.0;4.0;5.0;6.0|]) - Expect.throwsT (fun () -> - let _ = LinearAlgebra.cholesky nonsquare - () - ) "Should throw if not square" - - // ===================================================================== - // 4) leastSquaresCholesky - // ===================================================================== - testCase "leastSquaresCholesky: small example" <| fun _ -> - // We'll do the same design matrix from earlier, which is 3x2, and b= length=3. - let Adata = [|1.;2.; 2.;1.; 3.;4.|] - let A = Matrix(3, 2, Adata) - let b = [|8.; 10.; 19.|] - - let x = LinearAlgebra.leastSquaresCholesky A b - // We'll do the same "A*x ~ b" check as above - let Ax = - let result = Array.zeroCreate 3 - for i in 0..2 do - let rowOffset = i*2 - result.[i] <- Adata.[rowOffset]*x.[0] + Adata.[rowOffset+1]*x.[1] - result - for i in 0..2 do - Expect.floatClose Accuracy.high b.[i] Ax.[i] $"A*x mismatch at row {i}" - - // ===================================================================== - // 5a) hatMatrix - // ===================================================================== - testCase "hatMatrix: check if H = Q1 Q1^T for a small design matrix" <| fun _ -> - // We'll do design=3x2 => same as above - let Adata = [|1.;2.; 2.;1.; 3.;4.|] - let A = Matrix(3, 2, Adata) - let H = LinearAlgebra.hatMatrix A - // We expect H to be 3x3. We can do a partial check: - // H ~ Q1 Q1^T, where Q1 is from the Householder-based QR in the code. - // We'll check shape => should be 3x3, plus we can check if H^2=H (idempotent property). - Expect.equal (H.NumRows, H.NumCols) (3,3) "Hat matrix is 3x3" - - // Quick idempotence test: H^2 ~ H - let H2data = Array.zeroCreate (3*3) - for i in 0..2 do - for j in 0..2 do - let mutable sum = 0.0 - for k in 0..2 do - sum <- sum + H.[i,k] * H.[k,j] - H2data.[i*3 + j] <- sum - - for idx in 0..8 do - Expect.floatClose Accuracy.high H.Data.[idx] H2data.[idx] $"Hat matrix not idempotent at idx={idx}" - - // ===================================================================== - // 5b) leverageBy and leverage - // ===================================================================== - testCase "leverageBy: diagonal of H" <| fun _ -> - // We'll reuse the hat matrix from above, check if leverageBy returns the diagonal - let Adata = [|1.;2.; 2.;1.; 3.;4.|] - let A = Matrix(3, 2, Adata) - let H = LinearAlgebra.hatMatrix A - let diag = LinearAlgebra.leverageBy H - // Compare with Matrix.getDiagonal - let diag2 = Matrix.getDiagonal H - Expect.equal diag diag2 "Expected same diagonal from leverageBy" - - testCase "leverage: direct Q approach" <| fun _ -> - // We'll see if leverage designMatrix ~ diagonal of H - let Adata = [|1.;2.; 2.;1.; 3.;4.|] - let A = Matrix(3, 2, Adata) - // direct approach => Q1 from qrDecompose - let directLever = LinearAlgebra.leverage A - // The same as leverageBy (hatMatrix's diagonal) - let H = LinearAlgebra.hatMatrix A - let diagH = Matrix.getDiagonal H - Expect.equal directLever diagH "Leverage mismatch" - - // ===================================================================== - // 6) luDecompose - // ===================================================================== - testCase "luDecompose: pivot array, L and U multiply back to P*A" <| fun _ -> - // A= 3x3 => we'll pick something that requires row swaps - // A= [ [0,2,1],[3,4,5],[1,2,3] ] - let Adata = [|0.;2.;1.; 3.;4.;5.; 1.;2.;3.|] - let A = Matrix(3,3,Adata) - let (P, L, U) = LinearAlgebra.luDecompose A - // Check dimension => L, U => 3x3, P => perm array - Expect.equal (L.NumRows, L.NumCols) (3,3) "L shape" - Expect.equal (U.NumRows, U.NumCols) (3,3) "U shape" - - // We'll see if P*A= L*U - // 1) build PA => permute rows of A by P => do a naive approach or if you have a function - let PA = Matrix.permuteRowsBy P A - // 2) multiply L,U => LU - let LUdata = Array.zeroCreate (3*3) - for i in 0..2 do - for j in 0..2 do - let mutable sum = 0.0 - for k in 0..2 do - sum <- sum + L.[i,k]*U.[k,j] - LUdata.[i*3 + j] <- sum - - // Compare LU vs PA - for idx in 0..8 do - Expect.floatClose Accuracy.high PA.Data.[idx] LUdata.[idx] $"LU mismatch at idx={idx}" - - // ===================================================================== - // 7) solveLinearSystems - // ===================================================================== - testCase "solveLinearSystems: A is 2x2, B=2x2" <| fun _ -> - // We'll define A => [ [2,3],[1,2] ], - // B => 2x2 => pick X => 2x2 => solve => see if we get X - // X => [ [1,10],[2,4] ] => B= A*X => let's do the multiply: - // row0 => (2,3)*X => 2*(1,10)+3*(2,4)= (2+6,20+12)= (8,32) - // row1 => (1,2)*X => 1*(1,10)+2*(2,4)= (1+4,10+8)= (5,18) - // => B => [ (8,32),(5,18) ] - let Adata = [|2.;3.; 1.;2.|] - let Bdata = [|8.;32.; 5.;18.|] - let A = Matrix(2,2,Adata) - let B = Matrix(2,2,Bdata) - let Xsol = LinearAlgebra.solveLinearSystems A B - let Xexpected = [|1.;10.; 2.;4.|] - for i in 0..3 do - Expect.floatClose Accuracy.high Xexpected.[i] Xsol.Data.[i] $"X mismatch at idx={i}" - - // ===================================================================== - // 8) solveLinearSystem - // ===================================================================== - testCase "solveLinearSystem: 3x3 single system" <| fun _ -> - // A => [ [0,2,1],[3,4,5],[1,2,3] ] from above, b => let's pick x => [1,2,3], compute b => A*x - // row0 => 0*1 +2*2 +1*3= 4+3=7 - // row1 => 3*1 +4*2 +5*3= 3+8+15=26 - // row2 => 1*1 +2*2 +3*3= 1+4+9=14 - let Adata = [|0.;2.;1.; 3.;4.;5.; 1.;2.;3.|] - let A = Matrix(3,3,Adata) - let b = [|7.;26.;14.|] - let xSol = LinearAlgebra.solveLinearSystem A b - let expected = [|1.;2.;3.|] - for i in 0..2 do - Expect.floatClose Accuracy.high expected.[i] xSol.[i] $"x mismatch at {i}" - - // ===================================================================== - // 9) inverse - // ===================================================================== - testCase "inverse: 2x2 inverse" <| fun _ -> - // A => [ [1,2],[3,4] ], inverse => [ [-2,1],[1.5, -0.5] ] - // because 1*4 -2*3= (4-6)= -2 => A^-1 => 1/det * [ [4,-2],[-3,1] ] => 1/-2 => [ [-2,1],[1.5,-0.5] ] - let Adata = [|1.;2.; 3.;4.|] - let A = Matrix(2,2,Adata) - let Ainverse = LinearAlgebra.inverse A - // Compare with known - let expected = [| -2.0; 1.0; 1.5; -0.5 |] - for i in 0..3 do - Expect.floatClose Accuracy.high expected.[i] Ainverse.Data.[i] $"Inverse mismatch at idx={i}" - - testCase "inverse: dimension mismatch => throws" <| fun _ -> - let nonsquare = Matrix(2,3,[|1.;2.;3.;4.;5.;6.|]) - Expect.throwsT (fun () -> - let _ = LinearAlgebra.inverse nonsquare - () - ) "Should throw if not square" - ] - - - - - ] diff --git a/tests/FSharp.Stats.Tests/LinearAlgebra.fs b/tests/FSharp.Stats.Tests/LinearAlgebra.fs deleted file mode 100644 index 48d7d5aa2..000000000 --- a/tests/FSharp.Stats.Tests/LinearAlgebra.fs +++ /dev/null @@ -1,1518 +0,0 @@ -module LinearAlgebraTests - -open Expecto - -open FSharp.Stats -open FSharp.Stats.Algebra -open TestExtensions - - -[] -let householderTests = - testList "Householder tests" [ - - test "Householder reflection zeros subcolumn (3x2 matrix)" { - let A = Matrix(3, 2, [| 4.0; 1.0; - 2.0; 3.0; - 6.0; 5.0 |]) - let R = Matrix.copy A - let x = Matrix.getCol 0 R |> Vector.sub 0 - - let h = Householder.create x - Householder.applyLeft(h, R, 0) - - // After application, first column should be [beta, 0, 0] - Expect.floatClose Accuracy.high R.[1,0] 0.0 "R[1,0] should be zero" - Expect.floatClose Accuracy.high R.[2,0] 0.0 "R[2,0] should be zero" - - // Check tau and beta match known values (approximate) - let expectedBeta = sqrt (4.0**2 + 2.0**2 + 6.0**2) // ||x|| - Expect.floatClose Accuracy.high (float h.Beta) expectedBeta "Beta should match norm" - Expect.isTrue (float h.Tau > 0.0 && float h.Tau < 2.0) "Tau should be in (0, 2)" - } - - test "Householder reflection zeros subcolumn (2x2 matrix)" { - let A = Matrix(2, 2, [| 3.0; 1.0; - 4.0; 5.0 |]) - let R = Matrix.copy A - let x = Matrix.getCol 0 R |> Vector.sub 0 - - let h = Householder.create x - Householder.applyLeft(h, R, 0) - - Expect.floatClose Accuracy.high R.[1,0] 0.0 "R[1,0] should be zero" - let expectedBeta = sqrt (3.0**2 + 4.0**2) - Expect.floatClose Accuracy.high (float h.Beta) expectedBeta "Beta should match norm" - } - - test "Tau and v correctness on a known input" { - let x = [| 3.0; 4.0 |] - let h = Householder.create x - - // We expect: - // - v[0] = 1 - // - v[1] = (4 / v0), since we normalize the vector to have v[0] = 1 - // - tau e (0, 2), beta = ||x|| - Expect.equal h.V.[0] 1.0 "v[0] should be 1.0" - Expect.isTrue (float h.Tau > 0.0 && float h.Tau < 2.0) "Tau should be reasonable" - Expect.floatClose Accuracy.high (float h.Beta) 5.0 "Beta should be ||x|| = 5.0" - } - - test "Degenerate vector returns trivial Householder" { - let x = [| 0.0; 0.0; 0.0 |] - let h = Householder.create x - Expect.equal h.Tau 0.0 "Tau should be 0.0" - Expect.equal h.Beta 0.0 "Beta should be 0.0" - Expect.sequenceEqual h.V [| 1.0; 0.0; 0.0 |] "v should be unit vector" - } - - ] - - - - -[] -let subScaledRowInPlaceTests = - testList "subScaledRowInPlace" [ - - test "Basic subtraction (no offset)" { - let dst = [| 10.0; 20.0; 30.0 |] - let src = [| 1.0; 2.0; 3.0 |] - LinearAlgebra.subScaledRowInPlace 2.0 0 0 3 dst src - let expected = [| 8.0; 16.0; 24.0 |] - Expect.sequenceEqual dst expected "Subtraction incorrect" - } - - test "With dst and src offset" { - let dst = [| 0.0; 10.0; 20.0; 30.0; 0.0 |] - let src = [| 0.0; 1.0; 2.0; 3.0; 0.0 |] - // Subtract 2src[1..3] from dst[1..3] - LinearAlgebra.subScaledRowInPlace 2.0 1 1 3 dst src - let expected = [| 0.0; 8.0; 16.0; 24.0; 0.0 |] - Expect.sequenceEqual dst expected "Offset subtraction incorrect" - } - - test "Single element (scalar fallback)" { - let dst = [| 42.0 |] - let src = [| 2.0 |] - LinearAlgebra.subScaledRowInPlace 3.0 0 0 1 dst src - let expected = [| 36.0 |] - Expect.sequenceEqual dst expected "Scalar fallback incorrect" - } - - test "No modification outside range" { - let dst = [| 1.0; 2.0; 3.0; 4.0 |] - let src = [| 0.0; 1.0; 1.0; 0.0 |] - LinearAlgebra.subScaledRowInPlace 2.0 1 1 2 dst src - let expected = [| 1.0; 0.0; 1.0; 4.0 |] - Expect.sequenceEqual dst expected "Boundary elements modified" - } - - test "basic 3-element row subtraction" { - let dst = [| 1.0; 2.0; 3.0 |] - let src = [| 4.0; 5.0; 6.0 |] - let alpha = 2.0 - let expected = [| -7.0; -8.0; -9.0 |] - - LinearAlgebra.subScaledRowInPlace alpha 0 0 3 dst src - - Expect.sequenceEqual dst expected "Result should be elementwise dst - alpha * src" - } - - test "offsets respected correctly" { - let dst = [| 0.0; 1.0; 2.0; 3.0; 4.0 |] - let src = [| 0.0; 0.0; 1.0; 2.0; 3.0 |] - let alpha = 2.0 - let expected = [| 0.0; 1.0; 0.0; -1.0; -2.0 |] - - // Only update dst[2..4] = [2.0; 3.0; 4.0] with src[2..4] = [1.0; 2.0; 3.0] - LinearAlgebra.subScaledRowInPlace alpha 2 2 3 dst src - - Expect.sequenceEqual dst expected "Offsets should target the correct subarrays" - } - - ] - -[] -let qrDecompositionTests = - testList "QR Decomposition (Modified Gram-Schmidt)" [ - - test "Decompose identity matrix" { - let A = Matrix.identity 3 - let Q, R = LinearAlgebra.qrModifiedGramSchmidt A - let I = Matrix.identity 3 - TestExtensions.floatMatrixClose Accuracy.high Q I "Q should be identity" - TestExtensions.floatMatrixClose Accuracy.high R I "R should be identity" - } - - test "Reconstruct original matrix from Q * R" { - let A = Matrix(3, 2, [| 1.0; 0.0; - 1.0; 1.0; - 0.0; 1.0 |]) - let Q, R = LinearAlgebra.qrModifiedGramSchmidt A - let QR = Matrix.matmul Q R - TestExtensions.floatMatrixClose Accuracy.high QR A "Q * R should reconstruct A" - } - - test "Q has orthonormal columns" { - let A = Matrix(3, 2, [| 1.0; 0.0; - 1.0; 1.0; - 0.0; 1.0 |]) - let Q, _ = LinearAlgebra.qrModifiedGramSchmidt A - let QTQ = Matrix.matmul (Matrix.transpose Q) Q - let I = Matrix.identity 2 - TestExtensions.floatMatrixClose Accuracy.high QTQ I "Q^TQ should be identity" - } - - test "R is upper triangular" { - let A = Matrix(3, 2, [| 1.0; 0.0; - 1.0; 1.0; - 0.0; 1.0 |]) - let _, R = LinearAlgebra.qrModifiedGramSchmidt A - for i in 0 .. R.NumRows - 1 do - for j in 0 .. i - 1 do - Expect.floatClose Accuracy.high R.[i, j] 0.0 $"R[{i},{j}] should be zero" - } - - test "Tall matrix 4x2 decomposition" { - let A = Matrix(4, 2, [| 1.0; 2.0; - 3.0; 4.0; - 5.0; 6.0; - 7.0; 8.0 |]) - let Q, R = LinearAlgebra.qrModifiedGramSchmidt A - let QR = Matrix.matmul Q R - TestExtensions.floatMatrixClose Accuracy.medium QR A "QR ~ A for tall matrix" - } - - test "Wide matrix throws or truncates" { - let A = Matrix(2, 3, [| 1.0; 2.0; 3.0; - 4.0; 5.0; 6.0 |]) - Expect.throws (fun () -> LinearAlgebra.qrModifiedGramSchmidt A |> ignore) - "Wide matrices are not supported (m < n)" - } - ] - -[] -let backSubstituteTests = - testList "Back substitution tests" [ - - test "Solve simple upper triangular system" { - // R = [2 1] - // [0 3] - let r = Matrix(2, 2, [| 2.0; 1.0; - 0.0; 3.0 |]) - let y = [| 5.0; 6.0 |] - let x = LinearAlgebra. backSubstitute r y - // Solve: 3x1 = 6 -> x1 = 2 - // Then: 2x0 + x1 = 5 -> x0 = (5 - 1*2)/2 = 1.5 - let expected = [| 1.5; 2.0 |] - for i in 0..1 do - Expect.floatClose Accuracy.high x.[i] expected.[i] $"x[{i}] incorrect" - } - - test "Identity matrix returns y as solution" { - let r = Matrix.identity 3 - let y = [| 4.0; -2.0; 0.5 |] - let x = LinearAlgebra.backSubstitute r y - Expect.sequenceEqual x y "Identity matrix should return y = x" - } - - test "Upper triangular with zeros below diagonal" { - // R = [1 2 3] - // [0 4 5] - // [0 0 6] - let r = Matrix(3, 3, [| 1.0; 2.0; 3.0; - 0.0; 4.0; 5.0; - 0.0; 0.0; 6.0 |]) - let y = [| 14.0; 23.0; 18.0 |] - let x = LinearAlgebra.backSubstitute r y - let expected = [| 1.0; 2.0; 3.0 |] - for i in 0..2 do - Expect.floatClose Accuracy.high x.[i] expected.[i] $"x[{i}] incorrect" - } - - test "Throws on non-square R" { - let r = Matrix(2, 3, [| 1.0; 2.0; 3.0; - 0.0; 4.0; 5.0 |]) - let y = [| 1.0; 2.0 |] - Expect.throws (fun () -> LinearAlgebra.backSubstitute r y |> ignore) - "Should throw on non-square R" - } - - test "Throws on mismatched dimensions with y" { - let r = Matrix.identity 3 - let y = [| 1.0; 2.0 |] - Expect.throws (fun () -> LinearAlgebra.backSubstitute r y |> ignore) - "Should throw on mismatched y length" - } - - test "Throws on zero diagonal entry (division by zero)" { - let r = Matrix(2, 2, [| 0.0; 1.0; - 0.0; 2.0 |]) - let y = [| 3.0; 4.0 |] - Expect.throws (fun () -> LinearAlgebra.backSubstitute r y |> ignore) - "Should throw on division by zero" - } - ] - -// solveLinearQR -// solveTriangularLinearSystems - - -[] -let solveTriangularLinearSystemTests = - testList "solveTriangularLinearSystem tests" [ - - test "Solve L x = b (lower triangular)" { - // L = [1 0 0; 2 1 0; 3 4 1] - let L = Matrix(3, 3, [| 1.0; 0.0; 0.0; - 2.0; 1.0; 0.0; - 3.0; 4.0; 1.0 |]) - let b = [| 2.0; 5.0; 20.0 |] - let x = LinearAlgebra.solveTriangularLinearSystem L b true - // Solve: Lx = b -> x = [2; 1; 5] - let expected = [| 2.0; 1.0; 10.0 |] - for i in 0..2 do - Expect.floatClose Accuracy.high x.[i] expected.[i] $"x[{i}] incorrect" - } - - test "Solve L^T x = b (upper triangular)" { - // L = [1 0 0; 2 1 0; 3 4 1] - // L^T = [1 2 3; 0 1 4; 0 0 1] - let L = Matrix(3, 3, [| 1.0; 0.0; 0.0; - 2.0; 1.0; 0.0; - 3.0; 4.0; 1.0 |]) - - let b = [| 23.0; 9.0; 1.0 |] - let LT = Matrix.transpose L - let x = LinearAlgebra.solveTriangularLinearSystem LT b false - // Solve L^T x = b -> x = [1; 2; 1] - let expected = [| 10.0; 5.0; 1.0 |] - for i in 0..2 do - Expect.floatClose Accuracy.high x.[i] expected.[i] $"x[{i}] incorrect" - } - - test "Throws on mismatched dimensions" { - let L = Matrix.identity 3 - let b = [| 1.0; 2.0 |] - Expect.throws (fun () -> LinearAlgebra.solveTriangularLinearSystem L b true |> ignore) - "Should throw if dimensions don't match" - } - - test "Throws on zero diagonal (division by zero)" { - let L = Matrix(2, 2, [| 0.0; 0.0; - 1.0; 1.0 |]) - let b = [| 1.0; 2.0 |] - Expect.throws (fun () -> LinearAlgebra.solveTriangularLinearSystem L b true |> ignore) - "Should throw on division by zero" - } - ] - -[] -let qrTests = - testList "QR decomposition via Householder" [ - - test "Q * R reconstructs A" { - let A = Matrix(3, 2, [| 1.0; 1.0; - 1.0; 2.0; - 1.0; 3.0 |]) - let Q, R = LinearAlgebra.qrDecompose A - let QR = Matrix.matmul Q R - TestExtensions.floatMatrixClose Accuracy.high QR A "QR ~ A" - } - - test "Q is orthogonal: Q^TQ = I" { - let A = Matrix(3, 2, [| 1.0; 0.0; - 1.0; 1.0; - 1.0; 2.0 |]) - let Q, _ = LinearAlgebra.qrDecompose A - let QtQ = Matrix.matmul (Matrix.transpose Q) Q - let I = Matrix.identity Q.NumCols - TestExtensions.floatMatrixClose Accuracy.high QtQ I "Q^TQ ~ I" - } - - test "R is upper triangular" { - let A = Matrix(3, 2, [| 1.0; 0.0; - 2.0; 1.0; - 3.0; 2.0 |]) - let _, R = LinearAlgebra.qrDecompose A - for i = 0 to R.NumRows - 1 do - for j = 0 to i - 1 do - Expect.floatClose Accuracy.veryHigh R.[i,j] 0.0 $"R[{i},{j}] should be zero" - } - - test "QR of square matrix" { - let A = Matrix(3, 3, [| 1.0; 2.0; 3.0; - 4.0; 5.0; 6.0; - 7.0; 8.0; 9.0 |]) - let Q, R = LinearAlgebra.qrDecompose A - let QR = Q * R - TestExtensions.floatMatrixClose Accuracy.medium QR A "QR ~ A" - } - - test "QR of small square matrix" { - let A = Matrix(2, 2, [| 2.0; 1.0; - 1.0; 3.0 |]) - let Q, R = LinearAlgebra.qrDecompose A - let QR = Q * R - TestExtensions.floatMatrixClose Accuracy.medium QR A "QR ~ A" - } - - ] - -[] -let leastSquaresQRTests = - testList "Least squares (QR-based)" [ - - test "Overdetermined 3x2 system" { - let A = Matrix(3, 2, [| 1.0; 1.0; - 1.0; 2.0; - 1.0; 3.0 |]) - let b = [| 6.0; 0.0; 0.0 |] - let x = LinearAlgebra.leastSquares A b - let expected = [| 8.0; -3.0 |] - for i in 0..1 do - Expect.floatClose Accuracy.medium x.[i] expected.[i] $"x[{i}] incorrect" - } - - test "Underdetermined 2x3 system (minimum norm)" { - let A = Matrix(2, 3, [| 1.0; 2.0; 0.0; - 0.0; 1.0; 1.0 |]) - let b = [| 3.0; 2.0 |] - let x = LinearAlgebra.leastSquares A b - - // There are infinite solutions, but least norm solution is: - // min ||x|| such that Ax = b - // numpy gives: [0.33333333, 1.33333333, 0.66666667] - let expected = [| 0.33333333; 1.33333333; 0.66666667 |] - for i in 0..2 do - Expect.floatClose Accuracy.medium x.[i] expected.[i] $"x[{i}] incorrect" - } - - test "Square system returns exact solution" { - let A = Matrix(2, 2, [| 2.0; 1.0; - 1.0; 3.0 |]) - let b = [| 5.0; 10.0 |] - let x = LinearAlgebra.leastSquares A b - let expected = [| 1.0; 3.0 |] - for i in 0..1 do - Expect.floatClose Accuracy.high x.[i] expected.[i] $"x[{i}] incorrect" - } - - test "Residual Ax ~ projection of b" { - let A = Matrix(3, 2, [| 1.0; 1.0; - 1.0; 2.0; - 1.0; 3.0 |]) - let b = [| 6.0; 0.0; 0.0 |] - let x = LinearAlgebra.leastSquares A b - let Ax = Matrix.muliplyVector A x - let expected = [| 5.0; 2.0; -1.0 |] - for i in 0..2 do - Expect.floatClose Accuracy.medium Ax.[i] expected.[i] $"Ax[{i}] incorrect" - } - ] - - -[] -let choleskyTests = - testList "Cholesky decomposition tests" [ - - test "Decompose identity matrix" { - let I = Matrix.identity 3 - let L = LinearAlgebra.cholesky I - TestExtensions.floatMatrixClose Accuracy.high L I "L should be identity for identity input" - } - - test "Decompose known positive-definite matrix" { - // A = [4 2; 2 3] -> L = [2 0; 1 1.4142] - let A = Matrix(2, 2, [| 4.0; 2.0; - 2.0; 3.0 |]) - let L = LinearAlgebra.cholesky A - let expected = Matrix(2, 2, [| 2.0; 0.0; - 1.0; sqrt 2.0 |]) - for i in 0..1 do - for j in 0..1 do - Expect.floatClose Accuracy.medium L.[i,j] expected.[i,j] $"L[{i},{j}] incorrect" - } - - test "Reconstruct A from L * L^T" { - let A = Matrix(3, 3, [| 25.0; 15.0; -5.0; - 15.0; 18.0; 0.0; - -5.0; 0.0; 11.0 |]) - let L = LinearAlgebra.cholesky A - let LT = Matrix.transpose L - let reconstructed = Matrix.matmul L LT - TestExtensions.floatMatrixClose Accuracy.high reconstructed A "Reconstructed A <> original" - } - test "Throws on non-positive-definite matrix" { - // Not positive-definite: eigenvalues are [1, -1] - let A = Matrix(2, 2, [| 0.0; 1.0; - 1.0; 0.0 |]) - Expect.throws (fun () -> LinearAlgebra.cholesky A |> ignore) - "Should throw on non-positive-definite matrix" - } - - test "Throws on non-square matrix" { - let A = Matrix(2, 3, [| 1.0; 2.0; 3.0; - 2.0; 5.0; 6.0 |]) - Expect.throws (fun () -> LinearAlgebra.cholesky A |> ignore) - "Should throw on non-square matrix" - } - - test "Zero matrix throws (not positive-definite)" { - let A : Matrix = Matrix.zeroCreate 3 3 - Expect.throws (fun () -> LinearAlgebra.cholesky A |> ignore) - "Should throw on zero matrix" - } - - ] - -[] -let leastSquaresTests = - testList "Least Squares via Cholesky" [ - - test "Solve overdetermined 3x2 system" { - // A = [1 1; 1 2; 1 3], b = [6; 0; 0] - // Should find least-squares fit: beta = [8.0; -3.0] - let A = Matrix(3, 2, [| 1.0; 1.0; - 1.0; 2.0; - 1.0; 3.0 |]) - let b = [| 6.0; 0.0; 0.0 |] - let beta = LinearAlgebra.leastSquaresCholesky A b - let expected = [| 8.0; -3.0 |] - for i in 0..1 do - Expect.floatClose Accuracy.medium beta.[i] expected.[i] $"beta[{i}] incorrect" - } - - test "Reconstruction A * beta ~ projection of b" { - // Same setup as above - let A = Matrix(3, 2, [| 1.0; 1.0; - 1.0; 2.0; - 1.0; 3.0 |]) - let b = [| 6.0; 0.0; 0.0 |] - let beta = LinearAlgebra.leastSquaresCholesky A b - let predicted = Matrix.muliplyVector A beta - // Expected projection of b onto Col(A): A * (A' b) - let expected = [| 5.0; 2.0; -1.0 |] - for i in 0..2 do - Expect.floatClose Accuracy.medium predicted.[i] expected.[i] $"predicted[{i}] incorrect" - } - - test "Throws on dimension mismatch A and b" { - let A = Matrix.identity 3 - let b = [| 1.0; 2.0 |] - Expect.throws (fun () -> LinearAlgebra.leastSquaresCholesky A b |> ignore) - "Should throw if A.NumRows <> b.Length" - } - - test "Exact solution when A is square and full-rank" { - let A = Matrix(2, 2, [| 2.0; 1.0; - 1.0; 3.0 |]) - let b = [| 5.0; 10.0 |] - let beta = LinearAlgebra.leastSquaresCholesky A b - let expected = [| 1.0; 3.0 |] - for i in 0..1 do - Expect.floatClose Accuracy.high beta.[i] expected.[i] $"beta[{i}] incorrect" - } - - ] - - - -// hatMatrix -// leverageBy -// leverage -// luDecompose -// solveLinearSystems (LU) -// solveLinearSystem (LU) - - - - - - - - - -[] -let managedSVDTests = - - let svdManaged A = - let s,u,vt = LinearAlgebra.SVD A - let sM = - let tmp= Matrix.zeroCreate A.NumRows A.NumCols - for i = 0 to s.Length-1 do - tmp.[i,i] <- s.[i] - tmp - u,sM,vt - - let mSmallerN = Matrix.ofJaggedArray [| [|2.;-1.;2.;-1.|]; [|4.;3.;4.;3.|]; [|9.;13.;-13.;9.|]; |] - let mEqualN = Matrix.ofJaggedArray [| [|2.;-1.|]; [|9.;13.|]; |] - - testList "LinearAlgebra.LinearAlgebraManaged.SVD" [ - testCase "m=n Matrix: Recover from decomposition" <| fun () -> - let u,s,vt = svdManaged mEqualN - let mEqualNRecov = (u * s * vt) - let m = mEqualN.toJaggedArray() |> Array.concat - let m' = mEqualNRecov.toJaggedArray() |> Array.concat - TestExtensions.sequenceEqual Accuracy.high m m' "Matrices computed by SVD did not yield the initial matrix when multiplied." - - testCase "m=n Matrix: u and vt consist of unit vectors, row- and column- wise." <| fun () -> - let u,s,vt = svdManaged mEqualN - let vecNorms = - [| - u |> Matrix.mapiCols (fun _ v -> [|FSharp.Stats.Vector.norm v|]) - vt|> Matrix.mapiCols (fun _ v -> [|FSharp.Stats.Vector.norm v|]) - u |> Matrix.mapiRows (fun _ x -> [|FSharp.Stats.Vector.norm x|]) - vt|> Matrix.mapiRows (fun _ x -> [|FSharp.Stats.Vector.norm x|]) - |] - |> Array.map (fun m -> m.Data) - |> Array.concat - TestExtensions.sequenceEqual Accuracy.high (Array.create vecNorms.Length 1.) vecNorms "Matrices computed by SVD did not consist of unit vectors, row- and column- wise." - - testCase "m=n Matrix: s contains correct singular values." <| fun () -> - let s,u,vt = LinearAlgebra.SVD mEqualN - TestExtensions.sequenceEqual Accuracy.high ([|15.81461344;2.213142934|]) s "Matrices computed by SVD did not yield correct singular values." - - testCase "m - let u,s,vt = svdManaged mSmallerN - let mSmallernRecov = (u * s * vt) - let m = mSmallerN.Data - let m' = mSmallernRecov.Data - TestExtensions.sequenceEqual Accuracy.high m m' "Matrices computed by SVD did not yield the initial matrix when multiplied." - - testCase "m - let u,s,vt = svdManaged mSmallerN - let vecNorms = - [| - u |> Matrix.mapiCols (fun _ v -> [|FSharp.Stats.Vector.norm v|]) - vt|> Matrix.mapiCols (fun _ v -> [|FSharp.Stats.Vector.norm v|]) - u |> Matrix.mapiRows (fun _ x -> [|FSharp.Stats.Vector.norm x|]) - vt|> Matrix.mapiRows (fun _ x -> [|FSharp.Stats.Vector.norm x|]) - |] - |> Array.map (fun m -> m.Data) - |> Array.concat - TestExtensions.sequenceEqual Accuracy.high (Array.create vecNorms.Length 1.) vecNorms "Matrices computed by SVD did not consist of unit vectors, row- and column- wise." - - testCase "m - let s,u,vt = LinearAlgebra.SVD mSmallerN - TestExtensions.sequenceEqual Accuracy.high ([|22.51999394;6.986424855;2.00991059|]) s "Matrices computed by SVD did not yield correct singular values." - - testCase "m>n Matrix: Recover from decomposition" <| fun () -> - let u,s,vt = svdManaged (mSmallerN.Transpose()) - let mSmallernRecov = (u * s * vt) - let m = mSmallerN.Transpose().Data - let m' = mSmallernRecov.Data - TestExtensions.sequenceEqual Accuracy.high m m' "Matrices computed by SVD did not yield the initial matrix when multiplied." - - testCase "m>n Matrix: u and vt consist of unit vectors, row- and column- wise." <| fun () -> - let u,s,vt = svdManaged (mSmallerN.Transpose()) - let vecNorms = - [| - u |> Matrix.mapiCols (fun _ v -> [|FSharp.Stats.Vector.norm v|]) - vt|> Matrix.mapiCols (fun _ v -> [|FSharp.Stats.Vector.norm v|]) - u |> Matrix.mapiRows (fun _ x -> [|FSharp.Stats.Vector.norm x|]) - vt|> Matrix.mapiRows (fun _ x -> [|FSharp.Stats.Vector.norm x|]) - |] - |> Array.map (fun m -> m.Data) - |> Array.concat - TestExtensions.sequenceEqual Accuracy.high (Array.create vecNorms.Length 1.) vecNorms "Matrices computed by SVD did not consist of unit vectors, row- and column- wise." - - testCase "m>n Matrix: s contains correct singular values." <| fun () -> - let s,u,vt = LinearAlgebra.SVD (mSmallerN.Transpose()) - TestExtensions.sequenceEqual Accuracy.high ([|22.51999394;6.986424855;2.00991059|]) s "Matrices computed by SVD did not yield correct singular values." - ] - - -//[] -//let nullspace = - -// let mSmallerN = Matrix.ofJaggedArray [| [|2.;-1.;2.;-1.|]; [|4.;3.;4.;3.|]; [|9.;13.;-13.;9.|]; |] - -// testList "LinearAlgebra.nullspace" [ -// testCase "accuracy 1e-5" <| fun () -> -// let ns = LinearAlgebra.nullspace (Accuracy=1e-5) mSmallerN -// let prod = -// mSmallerN * ns -// |> Matrix.toJaggedSeq -// |> Seq.concat -// let expected = seq {0.;0.;0.;} -// TestExtensions.sequenceEqual Accuracy.veryHigh expected prod "A * (nullspace A) should be matrix of zeros" -// ] - -[] -let linearSystems = - - let KDiagonal1 = - [| - [|1.;0.;0.|] - [|0.;1.;0.|] - [|0.;0.;1.|] - |] - |> Matrix.ofJaggedArray - - let KUpper1 = - [| - [|1.;1.;1.|] - [|0.;1.;1.|] - [|0.;0.;1.|] - |] - |> Matrix.ofJaggedArray - - let KUpperNeg1 = - [| - [|-1.;-1.;-1.|] - [|0.;-1.;-1.|] - [|0.;0.;-1.|] - |] - |> Matrix.ofJaggedArray - - let KUpperInf = - [| - [|infinity;infinity;infinity|] - [|0.;infinity;infinity|] - [|0.;0.;infinity|] - |] - |> Matrix.ofJaggedArray - - let KUpperNegInf = - [| - [|-infinity;-infinity;-infinity|] - [|0.;-infinity;-infinity|] - [|0.;0.;-infinity|] - |] - |> Matrix.ofJaggedArray - - let KUpperNaN = - [| - [|nan;nan;nan|] - [|0.;nan;nan|] - [|0.;0.;nan|] - |] - |> Matrix.ofJaggedArray - - let KLower1 = - [| - [|1.;1.;1.|] - [|0.;1.;1.|] - [|0.;0.;1.|] - |] - |> Matrix.ofJaggedArray - |> Matrix.transpose - - let KLowerNeg1 = - [| - [|-1.;-1.;-1.|] - [|0.;-1.;-1.|] - [|0.;0.;-1.|] - |] - |> Matrix.ofJaggedArray - |> Matrix.transpose - - let KLowerInf = - [| - [|infinity;infinity;infinity|] - [|0.;infinity;infinity|] - [|0.;0.;infinity|] - |] - |> Matrix.ofJaggedArray - |> Matrix.transpose - - let KLowerNegInf = - [| - [|-infinity;-infinity;-infinity|] - [|0.;-infinity;-infinity|] - [|0.;0.;-infinity|] - |] - |> Matrix.ofJaggedArray - |> Matrix.transpose - - let KLowerNaN = - [| - [|nan;nan;nan|] - [|0.;nan;nan|] - [|0.;0.;nan|] - |] - |> Matrix.ofJaggedArray - |> Matrix.transpose - - let B1 = - [| - [|1.;1.;1.|] - [|1.;1.;1.|] - [|1.;1.;1.|] - |] - |> Matrix.ofJaggedArray - - let BNeg1 = - [| - [|-1.;-1.;-1.|] - [|-1.;-1.;-1.|] - [|-1.;-1.;-1.|] - |] - |> Matrix.ofJaggedArray - - let BInf = - [| - [|infinity;infinity;infinity|] - [|infinity;infinity;infinity|] - [|infinity;infinity;infinity|] - |] - |> Matrix.ofJaggedArray - - let BNegInf = - [| - [|-infinity;-infinity;-infinity|] - [|-infinity;-infinity;-infinity|] - [|-infinity;-infinity;-infinity|] - |] - |> Matrix.ofJaggedArray - - let BNaN = - [| - [|nan;nan;nan|] - [|nan;nan;nan|] - [|nan;nan;nan|] - |] - |> Matrix.ofJaggedArray - - let b1 = vector [|1.;1.;1.|] - - testList "Triangular Linear Systems" [ - // Tested vs R package "bdsmatrix: Routines for Block Diagonal Symmetric Matrices" Version 1.3-6 - testList "SolveTriangularLinearSystems (Upper)" [ - testCase "3x3 Upper Triangular Matrix with 3x3 Matrix (realistic example)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems - ( - [| - [|1.;2.;3.|]; - [|0.;1.;1.|]; - [|0.;0.;2.|] - |] - |> Matrix.ofJaggedArray - ) - ( - [| - [|8.;4.;2.|]; - [|4.;2.;1.|]; - [|2.;1.;0.|] - |] - |> Matrix.ofJaggedArray - ) - false - |> fun res -> - let expected = - matrix [| - [|-1.;-0.5;0.|]; - [|3.;1.5;1.|]; - [|1.;0.5;0.|] - |] - TestExtensions.sequenceEqual Accuracy.high res.Data expected.Data "Should be 3x3 Matrix: \n-1.;-0.5;0.\n3.;1.5;1.\n1.;0.5;0." - testCase "3x3 diagonal Matrix (Values = 1) with 3x3 Matrix (Values = 1)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KDiagonal1 B1 false - |> fun res -> - let expected = - matrix [| - [|1.;1.;1.|]; - [|1.;1.;1.|]; - [|1.;1.;1.|] - |] - TestExtensions.sequenceEqual Accuracy.high res.Data expected.Data "Should be 3x3 Matrix of 1" - testCase "3x3 Upper Triangular Matrix (Values = 1) with 3x3 Matrix (Values = 1)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KUpper1 B1 false - |> fun res -> - let expected = - matrix [| - [|0.;0.;0.|]; - [|0.;0.;0.|]; - [|1.;1.;1.|] - |] - TestExtensions.sequenceEqual Accuracy.high res.Data expected.Data "Should be 3x3 Matrix with 1 in last row" - testCase "3x3 Upper Triangular Matrix (Values = -1) with 3x3 Matrix (Values = 1)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KUpperNeg1 B1 false - |> fun res -> - let expected = - matrix [| - [|0.;0.;0.|]; - [|0.;0.;0.|]; - [|-1.;-1.;-1.|] - |] - TestExtensions.sequenceEqual Accuracy.high res.Data expected.Data "Should be 3x3 Matrix with 1 in last row" - testCase "3x3 Upper Triangular Matrix (Values = Inf) with 3x3 Matrix (Values = 1)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KUpperInf B1 false - |> fun res -> - let expected = - matrix [| - [|nan;nan;nan|]; - [|nan;nan;nan|]; - [|0.;0.;0.|] - |] - TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix with 0 in last row and NaN in other rows" - testCase "3x3 Upper Triangular Matrix (Values = -Inf) with 3x3 Matrix (Values = 1)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KUpperNegInf B1 false - |> fun res -> - let expected = - matrix [| - [|nan;nan;nan|]; - [|nan;nan;nan|]; - [|0.;0.;0.|] - |] - TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix with 0 in last row and NaN in other rows" - testCase "3x3 Upper Triangular Matrix (Values = NaN) with 3x3 Matrix (Values = 1)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KUpperNaN B1 false - |> fun res -> - let expected = - matrix [| - [|nan;nan;nan|]; - [|nan;nan;nan|]; - [|nan;nan;nan|] - |] - TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix of NaN" - testCase "3x3 diagonal Matrix (Values = 1) with 3x3 Matrix (Values = Inf)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KDiagonal1 BInf false - |> fun res -> - let expected = - matrix [| - [|nan;nan;nan|]; - [|nan;nan;nan|]; - [|infinity;infinity;infinity|] - |] - TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix with Inf in last row and NaN in other rows" - testCase "3x3 Upper Triangular Matrix (Values = 1) with 3x3 Matrix (Values = Inf)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KUpper1 BInf false - |> fun res -> - let expected = - matrix [| - [|nan;nan;nan|]; - [|nan;nan;nan|]; - [|infinity;infinity;infinity|] - |] - TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix with Inf in last row and NaN in other rows" - testCase "3x3 Upper Triangular Matrix (Values = -1) with 3x3 Matrix (Values = Inf)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KUpperNeg1 BInf false - |> fun res -> - let expected = - matrix [| - [|nan;nan;nan|]; - [|nan;nan;nan|]; - [|-infinity;-infinity;-infinity|] - |] - TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix with Inf in last row and NaN in other rows" - testCase "3x3 Upper Triangular Matrix (Values = Inf) with 3x3 Matrix (Values = Inf)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KUpperInf BInf false - |> fun res -> - let expected = - matrix [| - [|nan;nan;nan|]; - [|nan;nan;nan|]; - [|nan;nan;nan|] - |] - TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix of NaN" - testCase "3x3 Upper Triangular Matrix (Values = -Inf) with 3x3 Matrix (Values = Inf)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KUpperNegInf BInf false - |> fun res -> - let expected = - matrix [| - [|nan;nan;nan|]; - [|nan;nan;nan|]; - [|nan;nan;nan|] - |] - TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix of NaN" - testCase "3x3 Upper Triangular Matrix (Values = NaN) with 3x3 Matrix (Values = Inf)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KUpperNaN BInf false - |> fun res -> - let expected = - matrix [| - [|nan;nan;nan|]; - [|nan;nan;nan|]; - [|nan;nan;nan|] - |] - TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix of NaN" - testCase "3x3 diagonal Matrix (Values = 1) with 3x3 Matrix (Values = -Inf)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KDiagonal1 BNegInf false - |> fun res -> - let expected = - matrix [| - [|nan;nan;nan|]; - [|nan;nan;nan|]; - [|-infinity;-infinity;-infinity|] - |] - TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix with -Inf in last row and NaN in other rows" - testCase "3x3 Upper Triangular Matrix (Values = 1) with 3x3 Matrix (Values = -Inf)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KUpper1 BNegInf false - |> fun res -> - let expected = - matrix [| - [|nan;nan;nan|]; - [|nan;nan;nan|]; - [|-infinity;-infinity;-infinity|] - |] - TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix with -Inf in last row and NaN in other rows" - testCase "3x3 Upper Triangular Matrix (Values = Inf) with 3x3 Matrix (Values = -Inf)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KUpperInf BNegInf false - |> fun res -> - let expected = - matrix [| - [|nan;nan;nan|]; - [|nan;nan;nan|]; - [|nan;nan;nan|] - |] - TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix of NaN" - testCase "3x3 Upper Triangular Matrix (Values = -Inf) with 3x3 Matrix (Values = -Inf)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KUpperNegInf BNegInf false - |> fun res -> - let expected = - matrix [| - [|nan;nan;nan|]; - [|nan;nan;nan|]; - [|nan;nan;nan|] - |] - TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix of NaN" - testCase "3x3 Upper Triangular Matrix (Values = NaN) with 3x3 Matrix (Values = -Inf)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KUpperNaN BNegInf false - |> fun res -> - let expected = - matrix [| - [|nan;nan;nan|]; - [|nan;nan;nan|]; - [|nan;nan;nan|] - |] - TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix of NaN" - testCase "3x3 diagonal Matrix (Values = 1) with 3x3 Matrix (Values = NaN)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KDiagonal1 BNaN false - |> fun res -> - let expected = - matrix [| - [|nan;nan;nan|]; - [|nan;nan;nan|]; - [|nan;nan;nan|] - |] - TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix with Inf in last row and NaN in other rows" - testCase "3x3 Upper Triangular Matrix (Values = 1) with 3x3 Matrix (Values = NaN)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KUpper1 BNaN false - |> fun res -> - let expected = - matrix [| - [|nan;nan;nan|]; - [|nan;nan;nan|]; - [|nan;nan;nan|] - |] - TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix with Inf in last row and NaN in other rows" - testCase "3x3 Upper Triangular Matrix (Values = Inf) with 3x3 Matrix (Values = NaN)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KUpperInf BNaN false - |> fun res -> - let expected = - matrix [| - [|nan;nan;nan|]; - [|nan;nan;nan|]; - [|nan;nan;nan|] - |] - TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix of NaN" - testCase "3x3 Upper Triangular Matrix (Values = -Inf) with 3x3 Matrix (Values = NaN)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KUpperNegInf BNaN false - |> fun res -> - let expected = - matrix [| - [|nan;nan;nan|]; - [|nan;nan;nan|]; - [|nan;nan;nan|] - |] - TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix of NaN" - testCase "3x3 Upper Triangular Matrix (Values = NaN) with 3x3 Matrix (Values = NaN)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KUpperNaN BNaN false - |> fun res -> - let expected = - matrix [| - [|nan;nan;nan|]; - [|nan;nan;nan|]; - [|nan;nan;nan|] - |] - TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix of NaN" - testCase "3x3 diagonal Matrix (Values = 1) with 3x3 Matrix (Values = -1)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KDiagonal1 BNeg1 false - |> fun res -> - let expected = - matrix [| - [|-1.;-1.;-1.|]; - [|-1.;-1.;-1.|]; - [|-1.;-1.;-1.|] - |] - TestExtensions.sequenceEqual Accuracy.high res.Data expected.Data "Should be 3x3 Matrix of -1" - testCase "3x3 Upper Triangular Matrix (Values = 1) with 3x3 Matrix (Values = -1)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KUpper1 BNeg1 false - |> fun res -> - let expected = - matrix [| - [|0.;0.;0.|]; - [|0.;0.;0.|]; - [|-1.;-1.;-1.|] - |] - TestExtensions.sequenceEqual Accuracy.high res.Data expected.Data "Should be 3x3 Matrix with -1 in last row" - testCase "3x3 Upper Triangular Matrix (Values = -1) with 3x3 Matrix (Values = -1)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KUpperNeg1 BNeg1 false - |> fun res -> - let expected = - matrix [| - [|0.;0.;0.|]; - [|0.;0.;0.|]; - [|1.;1.;1.|] - |] - TestExtensions.sequenceEqual Accuracy.high res.Data expected.Data "Should be 3x3 Matrix with -1 in last row" - testCase "3x3 Upper Triangular Matrix (Values = Inf) with 3x3 Matrix (Values = -1)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KUpperInf BNeg1 false - |> fun res -> - let expected = - matrix [| - [|nan;nan;nan|]; - [|nan;nan;nan|]; - [|0.;0.;0.|] - |] - TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix with 0 in last row and NaN in other rows" - testCase "3x3 Upper Triangular Matrix (Values = -Inf) with 3x3 Matrix (Values = -1)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KUpperNegInf BNeg1 false - |> fun res -> - let expected = - matrix [| - [|nan;nan;nan|]; - [|nan;nan;nan|]; - [|0.;0.;0.|] - |] - TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix with 0 in last row and NaN in other rows" - testCase "3x3 Upper Triangular Matrix (Values = NaN) with 3x3 Matrix (Values = -1)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KUpperNaN BNeg1 false - |> fun res -> - let expected = - matrix [| - [|nan;nan;nan|]; - [|nan;nan;nan|]; - [|nan;nan;nan|] - |] - TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix of NaN" - ] - // Tested vs R package "bdsmatrix: Routines for Block Diagonal Symmetric Matrices" Version 1.3-6 - testList "SolveTriangularLinearSystems (Lower)" [ - testCase "3x3 Lower Triangular Matrix with 3x3 Matrix (realistic example)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems - ( - [| - [|1.;0.;0.|]; - [|2.;1.;0.|]; - [|3.;1.;2.|] - |] - |> Matrix.ofJaggedArray - ) - ( - [| - [|8.;4.;2.|]; - [|4.;2.;1.|]; - [|2.;1.;0.|] - |] - |> Matrix.ofJaggedArray - ) - true - |> fun res -> - let expected = - matrix [| - [|8.;4.;2.|]; - [|-12.;-6.;-3.|]; - [|-5.;-2.5;-1.5|] - |] - TestExtensions.sequenceEqual Accuracy.high res.Data expected.Data "Should be 3x3 Matrix: \n8.;4.;2.\n-12.;-6.;-3.\n-5.;-2.5;-1.5" - testCase "3x3 diagonal Matrix (Values = 1) with 3x3 Matrix (Values = 1) (lower)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KDiagonal1 B1 true - |> fun res -> - let expected = - matrix [| - [|1.;1.;1.|]; - [|1.;1.;1.|]; - [|1.;1.;1.|] - |] - TestExtensions.sequenceEqual Accuracy.high res.Data expected.Data "Should be 3x3 Matrix of 1" - testCase "3x3 Lower Triangular Matrix (Values = 1) with 3x3 Matrix (Values = 1)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KLower1 B1 true - |> fun res -> - let expected = - matrix [| - [|1.;1.;1.|]; - [|0.;0.;0.|]; - [|0.;0.;0.|] - |] - TestExtensions.sequenceEqual Accuracy.high res.Data expected.Data "Should be 3x3 Matrix with 1 in first row" - testCase "3x3 Lower Triangular Matrix (Values = -1) with 3x3 Matrix (Values = 1)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KLowerNeg1 B1 true - |> fun res -> - let expected = - matrix [| - [|-1.;-1.;-1.|]; - [|0.;0.;0.|]; - [|0.;0.;0.|] - |] - TestExtensions.sequenceEqual Accuracy.high res.Data expected.Data "Should be 3x3 Matrix with -1 in first row" - testCase "3x3 Lower Triangular Matrix (Values = Inf) with 3x3 Matrix (Values = 1)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KLowerInf B1 true - |> fun res -> - let expected = - matrix [| - [|0.;0.;0.|]; - [|nan;nan;nan|]; - [|nan;nan;nan|] - |] - TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix with 0 in first row and NaN in other rows" - testCase "3x3 Lower Triangular Matrix (Values = -Inf) with 3x3 Matrix (Values = 1)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KLowerNegInf B1 true - |> fun res -> - let expected = - matrix [| - [|0.;0.;0.|]; - [|nan;nan;nan|]; - [|nan;nan;nan|] - |] - TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix with 0 in first row and NaN in other rows" - testCase "3x3 Lower Triangular Matrix (Values = NaN) with 3x3 Matrix (Values = 1)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KLowerNaN B1 true - |> fun res -> - let expected = - matrix [| - [|nan;nan;nan|]; - [|nan;nan;nan|]; - [|nan;nan;nan|] - |] - TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix of NaN" - testCase "3x3 diagonal Matrix (Values = 1) with 3x3 Matrix (Values = Inf) (lower)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KDiagonal1 BInf true - |> fun res -> - let expected = - matrix [| - [|infinity;infinity;infinity|]; - [|nan;nan;nan|]; - [|nan;nan;nan|] - |] - TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix with Inf in first row and NaN in other rows" - testCase "3x3 Upper Triangular Matrix (Values = 1) with 3x3 Matrix (Values = Inf)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KLower1 BInf true - |> fun res -> - let expected = - matrix [| - [|infinity;infinity;infinity|]; - [|nan;nan;nan|]; - [|nan;nan;nan|] - |] - TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix with Inf in first row and NaN in other rows" - testCase "3x3 Lower Triangular Matrix (Values = -1) with 3x3 Matrix (Values = Inf)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KLowerNeg1 BInf true - |> fun res -> - let expected = - matrix [| - [|-infinity;-infinity;-infinity|]; - [|nan;nan;nan|]; - [|nan;nan;nan|] - |] - TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix with Inf in first row and NaN in other rows" - testCase "3x3 Lower Triangular Matrix (Values = Inf) with 3x3 Matrix (Values = Inf)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KLowerInf BInf true - |> fun res -> - let expected = - matrix [| - [|nan;nan;nan|]; - [|nan;nan;nan|]; - [|nan;nan;nan|] - |] - TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix of NaN" - testCase "3x3 Lower Triangular Matrix (Values = -Inf) with 3x3 Matrix (Values = Inf)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KLowerNegInf BInf true - |> fun res -> - let expected = - matrix [| - [|nan;nan;nan|]; - [|nan;nan;nan|]; - [|nan;nan;nan|] - |] - TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix of NaN" - testCase "3x3 Lower Triangular Matrix (Values = NaN) with 3x3 Matrix (Values = Inf)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KLowerNaN BInf true - |> fun res -> - let expected = - matrix [| - [|nan;nan;nan|]; - [|nan;nan;nan|]; - [|nan;nan;nan|] - |] - - TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix of NaN" - testCase "3x3 diagonal Matrix (Values = 1) with 3x3 Matrix (Values = -Inf)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KDiagonal1 BNegInf true - |> fun res -> - let expected = - matrix [| - [|-infinity;-infinity;-infinity|]; - [|nan;nan;nan|]; - [|nan;nan;nan|] - |] - - TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix with -Inf in first row and NaN in other rows" - testCase "3x3 Lower Triangular Matrix (Values = 1) with 3x3 Matrix (Values = -Inf)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KLower1 BNegInf true - |> fun res -> - let expected = - matrix [| - [|-infinity;-infinity;-infinity|]; - [|nan;nan;nan|]; - [|nan;nan;nan|] - |] - - TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix with -Inf in first row and NaN in other rows" - testCase "3x3 Lower Triangular Matrix (Values = Inf) with 3x3 Matrix (Values = -Inf)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KLowerInf BNegInf true - |> fun res -> - let expected = - matrix [| - [|nan;nan;nan|]; - [|nan;nan;nan|]; - [|nan;nan;nan|] - |] - TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix of NaN" - testCase "3x3 Lower Triangular Matrix (Values = -Inf) with 3x3 Matrix (Values = -Inf)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KLowerNegInf BNegInf true - |> fun res -> - let expected = - matrix [| - [|nan;nan;nan|]; - [|nan;nan;nan|]; - [|nan;nan;nan|] - |] - - TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix of NaN" - testCase "3x3 Lower Triangular Matrix (Values = NaN) with 3x3 Matrix (Values = -Inf)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KLowerNaN BNegInf true - |> fun res -> - let expected = - matrix [| - [|nan;nan;nan|]; - [|nan;nan;nan|]; - [|nan;nan;nan|] - |] - - TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix of NaN" - testCase "3x3 diagonal Matrix (Values = 1) with 3x3 Matrix (Values = NaN) (lower)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KDiagonal1 BNaN true - |> fun res -> - let expected = - matrix [| - [|nan;nan;nan|]; - [|nan;nan;nan|]; - [|nan;nan;nan|] - |] - TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix with Inf in last row and NaN in other rows" - testCase "3x3 Lower Triangular Matrix (Values = 1) with 3x3 Matrix (Values = NaN)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KLower1 BNaN true - |> fun res -> - let expected = - matrix [| - [|nan;nan;nan|]; - [|nan;nan;nan|]; - [|nan;nan;nan|] - |] - TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix with Inf in last row and NaN in other rows" - testCase "3x3 Lower Triangular Matrix (Values = Inf) with 3x3 Matrix (Values = NaN)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KLowerInf BNaN true - |> fun res -> - let expected = - matrix [| - [|nan;nan;nan|]; - [|nan;nan;nan|]; - [|nan;nan;nan|] - |] - TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix of NaN" - testCase "3x3 Lower Triangular Matrix (Values = -Inf) with 3x3 Matrix (Values = NaN)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KLowerNegInf BNaN true - |> fun res -> - let expected = - matrix [| - [|nan;nan;nan|]; - [|nan;nan;nan|]; - [|nan;nan;nan|] - |] - - TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix of NaN" - testCase "3x3 Lower Triangular Matrix (Values = NaN) with 3x3 Matrix (Values = NaN)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KLowerNaN BNaN true - |> fun res -> - let expected = - matrix [| - [|nan;nan;nan|]; - [|nan;nan;nan|]; - [|nan;nan;nan|] - |] - - TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix of NaN" - testCase "3x3 diagonal Matrix (Values = 1) with 3x3 Matrix (Values = -1) (lower)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KDiagonal1 BNeg1 true - |> fun res -> - let expected = - matrix [| - [|-1.;-1.;-1.|]; - [|-1.;-1.;-1.|]; - [|-1.;-1.;-1.|] - |] - - TestExtensions.sequenceEqual Accuracy.high res.Data expected.Data "Should be 3x3 Matrix of -1" - testCase "3x3 Lower Triangular Matrix (Values = 1) with 3x3 Matrix (Values = -1)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KLower1 BNeg1 true - |> fun res -> - let expected = - matrix [| - [|-1.;-1.;-1.|]; - [|0.;0.;0.|]; - [|0.;0.;0.|] - |] - - TestExtensions.sequenceEqual Accuracy.high res.Data expected.Data "Should be 3x3 Matrix with -1 in first row" - testCase "3x3 Lower Triangular Matrix (Values = -1) with 3x3 Matrix (Values = -1)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KLowerNeg1 BNeg1 true - |> fun res -> - let expected = - matrix [| - [|1.;1.;1.|]; - [|0.;0.;0.|]; - [|0.;0.;0.|] - |] - - TestExtensions.sequenceEqual Accuracy.high res.Data expected.Data "Should be 3x3 Matrix with -1 in first row" - testCase "3x3 Lower Triangular Matrix (Values = Inf) with 3x3 Matrix (Values = -1)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KLowerInf BNeg1 true - |> fun res -> - let expected = - matrix [| - [|0.;0.;0.|]; - [|nan;nan;nan|]; - [|nan;nan;nan|] - |] - - TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix with 0 in first row and NaN in other rows" - testCase "3x3 Lower Triangular Matrix (Values = -Inf) with 3x3 Matrix (Values = -1)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KLowerNegInf BNeg1 true - |> fun res -> - let expected = - matrix [| - [|0.;0.;0.|]; - [|nan;nan;nan|]; - [|nan;nan;nan|] - |] - - TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix with 0 in first row and NaN in other rows" - testCase "3x3 Lower Triangular Matrix (Values = NaN) with 3x3 Matrix (Values = -1)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KLowerNaN BNeg1 true - |> fun res -> - let expected = - matrix [| - [|nan;nan;nan|]; - [|nan;nan;nan|]; - [|nan;nan;nan|] - |] - - TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix of NaN" - ] - testList "SolveTriangularLinearSystem (Upper)" [ - testCase "3x3 Upper Triangular Matrix with Vector (realistic example)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystem - ( - [| - [|1.;2.;3.|]; - [|0.;1.;1.|]; - [|0.;0.;2.|] - |] - |> Matrix.ofJaggedArray - ) - ( - [|8.;4.;2.|] - |> vector - ) - false - |> fun res -> - let expected = - [|-1.;3.;1.|] - TestExtensions.sequenceEqual Accuracy.high res expected "Should be Vector of -1.;3.;1." - testCase "3x3 diagonal Matrix (Values = 1) with Vector (Values = 1)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystem KDiagonal1 b1 false - |> fun res -> - let expected = [|1.;1.;1.|] - TestExtensions.sequenceEqualRoundedNaN 9 res expected "Should be Vector of 1" - testCase "3x3 Upper Triangular Matrix (Values = 1) with Vector (Values = 1)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystem KUpper1 b1 false - |> fun res -> - let expected = [|0.;0.;1.|] - TestExtensions.sequenceEqualRoundedNaN 9 res expected "Should be Vector of 0 0 1" - testCase "3x3 Upper Triangular Matrix (Values = -1) with Vector (Values = 1)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystem KUpperNeg1 b1 false - |> fun res -> - let expected = [|0.;0.;-1.|] - TestExtensions.sequenceEqualRoundedNaN 9 res expected "Should be Vector of 0 0 -1" - testCase "3x3 Upper Triangular Matrix (Values = Inf) with Vector (Values = 1)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystem KUpperInf b1 false - |> fun res -> - let expected = [|nan;nan;0|] - TestExtensions.sequenceEqualRoundedNaN 9 res expected "Should be Vector of NaN NaN 0" - testCase "3x3 Upper Triangular Matrix (Values = -Inf) with Vector (Values = 1)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystem KUpperNegInf b1 false - |> fun res -> - let expected = [|nan;nan;0|] - TestExtensions.sequenceEqualRoundedNaN 9 res expected "Should be Vector of NaN NaN 0" - testCase "3x3 Upper Triangular Matrix (Values = NaN) with Vector (Values = 1)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystem KUpperNaN b1 false - |> fun res -> - let expected = [|nan;nan;nan|] - TestExtensions.sequenceEqualRoundedNaN 9 res expected "Should be Vector of NaN" - ] - testList "SolveTriangularLinearSystem (Lower)" [ - testCase "3x3 Upper Triangular Matrix with Vector (realistic example)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystem - ( - [| - [|1.;0.;0.|]; - [|2.;1.;0.|]; - [|3.;1.;2.|] - |] - |> Matrix.ofJaggedArray - ) - ( - [|8.;4.;2.|] - |> vector - ) - true - |> fun res -> - let expected = - [|8.;-12.;-5.|] - TestExtensions.sequenceEqual Accuracy.high res expected "Should be Vector of 8.;-12.;-5." - testCase "3x3 diagonal Matrix (Values = 1) with Vector (Values = 1)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystem KDiagonal1 b1 true - |> fun res -> - let expected = [|1.;1.;1.|] - TestExtensions.sequenceEqualRoundedNaN 9 res expected "Should be Vector of 1" - testCase "3x3 Lower Triangular Matrix (Values = 1) with Vector (Values = 1)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystem KLower1 b1 true - |> fun res -> - let expected = [|1.;0.;0.|] - TestExtensions.sequenceEqualRoundedNaN 9 res expected "Should be Vector of 1 0 0" - testCase "3x3 Lower Triangular Matrix (Values = -1) with Vector (Values = 1)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystem KLowerNeg1 b1 true - |> fun res -> - let expected = [|-1.;0.;0.|] - TestExtensions.sequenceEqualRoundedNaN 9 res expected "Should be Vector of -1 0 0" - testCase "3x3 Lower Triangular Matrix (Values = Inf) with Vector (Values = 1)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystem KLowerInf b1 true - |> fun res -> - let expected = [|0.;nan;nan|] - TestExtensions.sequenceEqualRoundedNaN 9 res expected "Should be Vector of 0 NaN NaN" - testCase "3x3 Lower Triangular Matrix (Values = -Inf) with Vector (Values = 1)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystem KLowerNegInf b1 true - |> fun res -> - let expected = [|0.;nan;nan|] - TestExtensions.sequenceEqualRoundedNaN 9 res expected "Should be Vector of 0 NaN NaN" - testCase "3x3 Lower Triangular Matrix (Values = NaN) with Vector (Values = 1)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystem KLowerNaN b1 true - |> fun res -> - let expected = [|nan;nan;nan|] - TestExtensions.sequenceEqualRoundedNaN 9 res expected "Should be Vector of NaN" - ] - ] - diff --git a/tests/FSharp.Stats.Tests/Matrix.fs b/tests/FSharp.Stats.Tests/Matrix.fs deleted file mode 100644 index a528aec77..000000000 --- a/tests/FSharp.Stats.Tests/Matrix.fs +++ /dev/null @@ -1,309 +0,0 @@ -module MatrixTests - -open System -open FSharp.Stats -open Expecto - - -[] -let matrixTests = - testList "Matrix Tests" [ - - // ---------------------------------------------------------------------- - // Basic construction - // ---------------------------------------------------------------------- - testCase "ofJaggedArray creates matrix from jagged array" <| fun _ -> - let jagged = - [| [|0.0; 0.0|] - [|1.0; 3.0|] - [|2.0; 4.0|] |] - let mat = Matrix.ofJaggedArray jagged // We specifically test 'ofJaggedArray' here - Expect.equal mat.NumRows 3 "Matrix should have 3 rows" - Expect.equal mat.NumCols 2 "Matrix should have 2 columns" - Expect.equal mat.Data [|0.0; 0.0; 1.0; 3.0; 2.0; 4.0|] - "Flattened data should match row-major flattening" - - testCase "ofArray2D creates matrix from 2D array" <| fun _ -> - let arr2d = - array2D [ [ 1; 2 ] - [ 3; 4 ] - [ 5; 6 ] ] - let mat = Matrix.ofArray2D arr2d - Expect.equal mat.NumRows 3 "Matrix should have 3 rows" - Expect.equal mat.NumCols 2 "Matrix should have 2 columns" - Expect.equal mat.Data [|1; 2; 3; 4; 5; 6|] "Flattened data should match row-major order" - - testCase "init creates a matrix using a function of row,col" <| fun _ -> - let mat = Matrix.init 2 3 (fun r c -> float (r + c)) - // For r=0, c=0..2 => [0;1;2] - // For r=1, c=0..2 => [1;2;3] - // Flatten => [0;1;2; 1;2;3] - let expected = [|0.0; 1.0; 2.0; 1.0; 2.0; 3.0|] - Expect.equal mat.NumRows 2 "Rows = 2" - Expect.equal mat.NumCols 3 "Cols = 3" - Expect.equal mat.Data expected "Data should match the function r+c" - - testCase "ofJaggedArray throws on non-rectangular jagged input" <| fun _ -> - let jagged = - [| [|1.0; 2.0|] - [|3.0|] |] // 2nd row has length=1, first row has length=2 - Expect.throws (fun () -> Matrix.ofJaggedArray jagged |> ignore) - "Should throw due to inconsistent row lengths" - - // ---------------------------------------------------------------------- - // Access & Slicing - // ---------------------------------------------------------------------- - testCase "indexer get/set within bounds" <| fun _ -> - let mat = matrix [| [|1.0; 2.0|] - [|3.0; 4.0|] |] - Expect.equal mat.[0,0] 1.0 "Element (0,0) is 1.0" - mat.[1,1] <- 99.0 - Expect.equal mat.[1,1] 99.0 "Element (1,1) updated to 99.0" - - testCase "indexer throws on out-of-range access" <| fun _ -> - let mat = matrix [| [|1.0; 2.0|] - [|3.0; 4.0|] |] - Expect.throwsT (fun () -> let _ = mat.[999, 999] in ()) - "Indexer out of range should throw" - - testCase "GetSlice works with row and col start..end" <| fun _ -> - // 3x3 matrix - let mat = matrix [| - [|1.0; 2.0; 3.0|] - [|4.0; 5.0; 6.0|] - [|7.0; 8.0; 9.0|] - |] - // slice submatrix: rows [0..1], cols [1..2] - let subMat = mat.[0..1, 1..2] - // This submatrix should be: - // [ [2.0; 3.0] - // [5.0; 6.0] ] - Expect.equal subMat.NumRows 2 "2 rows" - Expect.equal subMat.NumCols 2 "2 cols" - Expect.equal subMat.Data [|2.0; 3.0; 5.0; 6.0|] "Flattened submatrix data" - - testCase "GetSlice throws on invalid slice range" <| fun _ -> - let mat = matrix [| [|1.;2.|] - [|3.;4.|] |] - Expect.throwsT (fun () -> mat.[0..99, *] |> ignore) - "Should throw due to invalid row end" - - // ---------------------------------------------------------------------- - // Arithmetic (element-wise) - // ---------------------------------------------------------------------- - testCase "add: element-wise addition of same-dimension matrices" <| fun _ -> - let m1 = matrix [| [|1.; 2.|] - [|3.; 4.|] |] - let m2 = matrix [| [|10.;20.|] - [|30.;40.|] |] - let result = Matrix.add m1 m2 - let expected = [| (1.+10.); (2.+20.); (3.+30.); (4.+40.) |] // => [11;22;33;44] - Expect.equal result.Data expected "Element-wise addition result" - - testCase "subtract: dimension mismatch throws" <| fun _ -> - let m1 = matrix [| [|1.;2.|] |] // 1x2 - let m2 = matrix [| [|1.;2.;3.|] |] // 1x3 - Expect.throwsT (fun () -> Matrix.subtract m1 m2 |> ignore) - "Subtract must throw if shapes differ" - - testCase "multiply & divide: element-wise" <| fun _ -> - let m1 = matrix [| [|2.;4.|] - [|6.;8.|] |] - let m2 = matrix [| [|1.;2.|] - [|3.;4.|] |] - - // multiply => [ [2.*1. , 4.*2.] ; [6.*3., 8.*4.] ] => [ [2.,8.]; [18.,32.] ] - let mulResult = Matrix.multiply m1 m2 - Expect.equal mulResult.Data [|2.; 8.; 18.; 32.|] "Element-wise multiply" - - // divide => [ [2./1., 4./2.]; [6./3., 8./4.] ] => [ [2.,2.]; [2.,2.] ] - let divResult = Matrix.divide m1 m2 - Expect.equal divResult.Data [|2.;2.;2.;2.|] "Element-wise divide" - - - // ---------------------------------------------------------------------- - // Standard matrix multiplication - // ---------------------------------------------------------------------- - testCase "matmul: 2x3 times 3x2 => 2x2 result" <| fun _ -> - // A=2x3, B=3x2 - let A = matrix [| [|1.0; 2.0; 3.0|] - [|4.0; 5.0; 6.0|] |] - let B = matrix [| [|7.0; 10.0|] - [|8.0; 11.0|] - [|9.0; 12.0|] |] - - // Expected: - // C[0,0] = 1*7 + 2*8 + 3*9 = 50 - // C[0,1] = 1*10+2*11+3*12 = 68 - // C[1,0] = 4*7 + 5*8 + 6*9 = 122 - // C[1,1] = 4*10+5*11+6*12 = 167 - let C = Matrix.matmul A B - Expect.equal C.NumRows 2 "Should have 2 rows" - Expect.equal C.NumCols 2 "Should have 2 cols" - Expect.equal C.Data [|50.0; 68.0; 122.0; 167.0|] "Check standard matmul result" - - - // ---------------------------------------------------------------------- - // Scalar Operations - // ---------------------------------------------------------------------- - testCase "addScalar, subtractScalar, multiplyScalar, divideScalar" <| fun _ -> - let m = matrix [| [|1.;2.|] - [|3.;4.|] |] - let addRes = Matrix.addScalar m 10.0 - Expect.equal addRes.Data [|11.;12.;13.;14.|] "Add 10.0 to all" - - let subRes = Matrix.subtractScalar m 1.0 - Expect.equal subRes.Data [|0.;1.;2.;3.|] "Subtract 1.0 from all" - - let mulRes = Matrix.multiplyScalar m 2.0 - Expect.equal mulRes.Data [|2.;4.;6.;8.|] "Multiply all by 2.0" - - let divRes = Matrix.divideScalar m 2.0 - Expect.equal divRes.Data [|0.5;1.;1.5;2.|] "Divide all by 2.0" - - // ---------------------------------------------------------------------- - // Matrix-Vector Multiply - // ---------------------------------------------------------------------- - testCase "m * v => standard matrix-vector product" <| fun _ -> - // 2x3 times vector of length 3 => vector of length 2 - // mat = [ [1.,2.,3.] - // [4.,5.,6.] ] - let mat = matrix [| [|1.;2.;3.|] - [|4.;5.;6.|] |] - let v = [| 10.; 20.; 30. |] - // result = [ - // row0 dot v => (1.*10. + 2.*20. + 3.*30.) = 140. - // row1 dot v => (4.*10. + 5.*20. + 6.*30.) = 320. - // ] - let result = mat * v - Expect.equal result [|140.; 320.|] "Matrix-vector product" - - testCase "v * m => row-vector times matrix => vector" <| fun _ -> - // 1x2 row vector times a 2x2 matrix => 1x2 vector - let v = [|2.; 3.|] // length=2 - let mat = matrix [| [|10.; 100.|] - [|20.; 200.|] |] - // v*m => [ (2.*10. + 3.*20.), (2.*100. + 3.*200.) ] - // => [ 2.*10. + 3.*20. , 2.*100. + 3.*200. ] - // => [ 20.+60., 200.+600. ] => [80., 800.] - let result = v * mat - Expect.equal result [|80.; 800.|] "Row-vector times matrix" - - testCase "m * v => dimension mismatch throws" <| fun _ -> - let mat = matrix [| [|1.;2.|] - [|3.;4.|] |] // 2x2 - let v = [|1.;2.;3.|] // length=3 - Expect.throwsT (fun () -> let _ = mat * v in ()) - "Matrix(2x2)*Vector(3) => dimension mismatch should throw" - - // ---------------------------------------------------------------------- - // Transpose - // ---------------------------------------------------------------------- - testCase "Transpose: changes shape and flips row<->col" <| fun _ -> - let mat = matrix [| [|1.;2.;3.|] - [|4.;5.;6.|] |] // 2x3 - let t = mat.Transpose() - Expect.equal t.NumRows 3 "Should have 3 rows" - Expect.equal t.NumCols 2 "Should have 2 cols" - Expect.equal t.Data [|1.;4.;2.;5.;3.;6.|] "Flattened transpose" - - // ---------------------------------------------------------------------- - // Identity, Diagonal, and Zero/Ones - // ---------------------------------------------------------------------- - testCase "identity n => NxN identity matrix" <| fun _ -> - let eye = Matrix.identity 3 - // => [1,0,0; 0,1,0; 0,0,1] - let expected = [|1.;0.;0.; 0.;1.;0.; 0.;0.;1.|] - Expect.equal eye.Data expected "3x3 identity" - - testCase "diagonal => builds NxN from diag vector" <| fun _ -> - let diagVec = [|10.; 20.; 30.|] - let mat = Matrix.diagonal diagVec - // => [ [10, 0, 0], - // [ 0,20, 0], - // [ 0, 0,30] ] - Expect.equal mat.NumRows 3 "3x3" - Expect.equal mat.NumCols 3 "3x3" - let expected = [|10.;0.;0.; 0.;20.;0.; 0.;0.;30.|] - Expect.equal mat.Data expected "Diagonal in main diagonal positions" - - testCase "ones => NxM matrix of all 1's" <| fun _ -> - let mat = Matrix.ones 2 3 - Expect.equal mat.Data [|1.;1.;1.;1.;1.;1.|] "2x3 of all 1." - - testCase "zeroCreate => NxM matrix of all 0's" <| fun _ -> - let mat = Matrix.zeroCreate 2 3 - Expect.equal mat.Data [|0.;0.;0.;0.;0.;0.|] "2x3 of all zero." - - // ---------------------------------------------------------------------- - // getRow / getCol - // ---------------------------------------------------------------------- - testCase "getRow gets row i as a vector" <| fun _ -> - let mat = matrix [| [|1.;2.|] - [|3.;4.|] |] - let row0 = Matrix.getRow 0 mat - let row1 = Matrix.getRow 1 mat - Expect.equal row0 [|1.;2.|] "Row 0" - Expect.equal row1 [|3.;4.|] "Row 1" - - testCase "getCol gets column j as a vector" <| fun _ -> - let mat = matrix [| [|1.;2.;3.|] - [|4.;5.;6.|] |] - let col0 = Matrix.getCol 0 mat - let col2 = Matrix.getCol 2 mat - Expect.equal col0 [|1.;4.|] "Column 0" - Expect.equal col2 [|3.;6.|] "Column 2" - - // ---------------------------------------------------------------------- - // Equality (IEquatable) - // ---------------------------------------------------------------------- - testCase "Equals returns true for same shape+elements" <| fun _ -> - let m1 = matrix [| [|1.;2.|] - [|3.;4.|] |] - // 'Matrix.create' constructs from a flattened array - let m2 = Matrix.create 2 2 [|1.;2.;3.;4.|] - Expect.isTrue (m1.Equals m2) "Matrices should be equal" - - testCase "Equals returns false for dimension mismatch" <| fun _ -> - let m1 = matrix [| [|1.;2.|] |] // 1x2 - let m2 = matrix [| [|1.;2.;3.|] |] // 1x3 - Expect.isFalse (m1.Equals m2) "Should be different shapes => not equal" - - testCase "Equals returns false for data difference" <| fun _ -> - let m1 = matrix [| [|1.;2.|] |] - let m2 = matrix [| [|1.;9.|] |] - Expect.isFalse (m1.Equals m2) "Same shape, different data => not equal" - - // ---------------------------------------------------------------------- - // Misc: toArray2D, toJaggedArray - // ---------------------------------------------------------------------- - testCase "toArray2D transforms a matrix into 2D array" <| fun _ -> - let mat = matrix [| [|1.;2.|] - [|3.;4.|] - [|5.;6.|] |] - let arr2d = mat.toArray2D() - Expect.equal (arr2d.GetLength(0)) 3 "3 rows in arr2d" - Expect.equal (arr2d.GetLength(1)) 2 "2 cols in arr2d" - Expect.equal arr2d.[2,1] 6.0 "Check element" - - testCase "toJaggedArray transforms a matrix into jagged array" <| fun _ -> - let mat = matrix [| [|7.;8.|] - [|9.;10.|] |] - let jagged = mat.toJaggedArray() - Expect.equal jagged.Length 2 "2 rows in jagged" - Expect.equal jagged.[1] [|9.;10.|] "Second row matches" - - // ---------------------------------------------------------------------- - // Slicing & Setting Row - // ---------------------------------------------------------------------- - testCase "SetRow updates row i" <| fun _ -> - let mat = matrix [| [|1.;2.|] - [|3.;4.|] |] - mat.SetRow(0, [|10.;20.|]) - Expect.equal mat.Data [|10.;20.;3.;4.|] "Row 0 replaced" - - // (Optional) More tests can be added for addRowVector, addColVector, etc. - ] - - - diff --git a/tests/FSharp.Stats.Tests/Optimization.fs b/tests/FSharp.Stats.Tests/Optimization.fs index f91b77906..a4205bccb 100644 --- a/tests/FSharp.Stats.Tests/Optimization.fs +++ b/tests/FSharp.Stats.Tests/Optimization.fs @@ -3,6 +3,7 @@ open Expecto open System +open FsMath open FSharp.Stats open FSharp.Stats.Optimization diff --git a/tests/FSharp.Stats.Tests/RowVector.fs b/tests/FSharp.Stats.Tests/RowVector.fs deleted file mode 100644 index 82a436a81..000000000 --- a/tests/FSharp.Stats.Tests/RowVector.fs +++ /dev/null @@ -1,28 +0,0 @@ -module RowVectorTests -open Expecto - -open FSharp.Stats -open FSharp.Stats.RowVector - -let private testRowVectorA = - let values = [|5.;12.;18.;-23.;45.|] - RowVector(Some (Instances.FloatNumerics :> INumeric),values) - -let private testArrayA = - [|5.;12.;18.;-23.;45.|] - -[] -let floatImplementationTests = - let testRowVectorASquare = rowvec [25.0; 144.0; 324.0; 529.0; 2025.] - - testList "RowVector" [ - testCase "map" <| fun () -> - let actual = testRowVectorA |> RowVector.map (fun x -> x**2.) - Expect.equal actual testRowVectorASquare "RowVectors should be equal" - - testCase "init" <| fun () -> - let actual = RowVector.init testArrayA.Length (fun i -> testArrayA.[i]) - Expect.equal actual testRowVectorA "RowVectors should be equal" - ] - - diff --git a/tests/FSharp.Stats.Tests/SVD.fs b/tests/FSharp.Stats.Tests/SVD.fs deleted file mode 100644 index c2b886af2..000000000 --- a/tests/FSharp.Stats.Tests/SVD.fs +++ /dev/null @@ -1,205 +0,0 @@ -module SVDTests - -open Expecto -open System -open FSharp.Stats -open FSharp.Stats.Algebra - -module MatrixUtils = - - let inline isApproxZero<'T when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T : comparison - and 'T :> ValueType> - (epsilon: 'T) (x: 'T) = - (GenericMath.abs x) < epsilon - - let inline isUpperBidiagonalWithTolerance<'T when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T : comparison - and 'T :> ValueType> - (epsilon: 'T) - (A: Matrix<'T>) : bool = - let m = A.NumCols - let n = A.NumRows - - let mutable ok = true - for i = 0 to m - 1 do - for j = 0 to n - 1 do - let onDiagonal = j = i - let onSuperDiagonal = j = i + 1 - let aij = A.[i, j] - if not (onDiagonal || onSuperDiagonal) && not (isApproxZero epsilon aij) then - ok <- false - ok - - -[] -let householderCreateTest = - test "Householder.create" { - let x = [| 4.0; 3.0; 0.0 |] - let h = Householder.create x - - let v = h.V - let tau = h.Tau - let n = v.Length - - // Compute Hx = (I - τ v vᵗ) x - // First: dot(v, x) - let dot = Vector.dot v x - - // Then: Hx = x - τ * dot * v - let hx = Array.init n (fun i -> x.[i] - tau * dot * v.[i]) - - // We expect: hx = [±||x||; 0; 0] - let norm = sqrt (Array.sumBy (fun xi -> xi * xi) x) - Expect.floatClose Accuracy.high hx.[0] norm "Should be equal (double precision)" - Expect.floatClose Accuracy.high hx.[1] 0.0 "Should be equal (double precision)" - Expect.floatClose Accuracy.high hx.[2] 0.0 "Should be equal (double precision)" - } - //test " zeroes out tail of vector" { - // Expect.floatClose Accuracy.high hx.[0] norm "Should be equal (double precision)" - //} - //test " zeroes out tail of vector" { - // Expect.floatClose Accuracy.high hx.[1] 0.0 "Should be equal (double precision)" - //} - //test " zeroes out tail of vector" { - // Expect.floatClose Accuracy.high hx.[2] 0.0 "Should be equal (double precision)" - //} - //] - -[] -let applyLeftTest = - test "Householder.applyLeft zeroes out subdiagonal column elements" { - // Define 3x3 test matrix - let A = - matrix [| - [| 4.0; 2.0; 1.0 |] - [| 3.0; 0.0; 0.0 |] - [| 0.0; 0.0; 0.0 |] - |] - - // Create Householder vector from column 0 (x = [4; 3; 0]) - let x = [| A.[0, 0]; A.[1, 0]; A.[2, 0] |] - let h = Householder.create x - - // Apply reflector from the left to matrix A starting at row 0 - Householder.applyLeft(h, A, 0) - - // Check: entries below A[0][0] should be zero - //let eps = 1e-10 - Expect.floatClose Accuracy.high A.[1, 0] 0.0 "Should be equal (double precision)" - Expect.floatClose Accuracy.high A.[2, 0] 0.0 "Should be equal (double precision)" - - // Optionally check the first value matches h.Beta - Expect.floatClose Accuracy.high A.[0, 0] h.Beta "Should be equal (double precision)" - } - -let applyRightTest = - test "Householder.applyRight zeroes out row tail elements" { - // Define 3x3 test matrix - let A = - matrix [| - [| 1.0; 4.0; 3.0 |] - [| 0.0; 0.0; 0.0 |] - [| 0.0; 0.0; 0.0 |] - |] - - // Take the row vector to the right of the diagonal: [4.0; 3.0] - let x = [| A.[0, 1]; A.[0, 2] |] - let h = Householder.create x - - // Apply the Householder from the right starting at column 1 - Householder.applyRight(h, A, 1) - - // Check that A[0].[2] is now approximately 0 - //let eps = 1e-10 - Expect.floatClose Accuracy.high A.[0, 2] 0.0 "Should be equal (double precision)" - - // Check that A[0].[1] is updated to h.Beta - Expect.floatClose Accuracy.high A.[0, 1] h.Beta "Should be equal (double precision)" - } - - -[] -let bidiagonalizationTest = - testList "bidiagonalization" [ - test "First step of bidiagonalization (applyLeft to column 0) works" { - // Full-rank 3x3 matrix - let A = - matrix [| - [| 4.0; 1.0; 2.0 |] - [| 3.0; 1.0; 0.0 |] - [| 5.0; 1.0; 3.0 |] - |] - - // Extract column 0 - let colVector = [| A.[0, 0]; A.[1, 0]; A.[2, 0] |] - let h = Householder.create colVector - - Householder.applyLeft(h, A, 0) - - // Overwrite A[0..,0] with [β; 0; 0] - A.[0, 0] <- h.Beta - for i = 1 to 2 do - A.[i, 0] <- 0.0 - - // Check column 0 - Expect.floatClose Accuracy.high A.[1, 0] 0.0 "Should be equal (double precision)" - Expect.floatClose Accuracy.high A.[2, 0] 0.0 "Should be equal (double precision)" - Expect.floatClose Accuracy.high A.[0, 0] h.Beta "Should be equal (double precision)" - } - - - - test "bidiagonalizeInPlace produces upper bidiagonal matrix" { - let input = - matrix [| - [| 1.0; 2.0; 3.0 |] - [| 4.0; 5.0; 6.0 |] - [| 7.0; 8.0; 9.0 |] - |] - - let A = input |> Matrix.copy - - Bidiagonalization.bidiagonalizeInPlace A - - let isBidiagonal = MatrixUtils.isUpperBidiagonalWithTolerance 1e-10 A - - Expect.isTrue isBidiagonal "Matrix should be upper bidiagonal after bidiagonalization" - } - ] - - -//[] -//let golubKahanTests = -// testList "Golub-Kahan Diagonalization" [ - -// test "Diagonalize 2x2 upper bidiagonal matrix" { -// // Construct bidiagonal: [ [4, 2]; [0, 3] ] -// let d = [| 4.0; 3.0 |] -// let e = [| 2.0 |] - -// let bidiag = { -// D = d -// E = e -// } - -// let sigma = GolubKahan.diagonalize bidiag - -// // Expected from NumPy SVD -// let expected = [| 4.74341649; 2.5355339 |] -// let eps = 1e-6 - -// // Compare sorted values (SVD is unordered) -// let actualSorted = Array.sortDescending sigma -// let expectedSorted = Array.sortDescending expected - -// for i in 0 .. expected.Length - 1 do -// Expect.floatClose Accuracy.high actualSorted.[i] expectedSorted.[i] $"Singular value {i} mismatch" -// } - -// // You can add more tests here for larger bidiagonal matrices or edge cases -// ] \ No newline at end of file diff --git a/tests/FSharp.Stats.Tests/TestExtensions.fs b/tests/FSharp.Stats.Tests/TestExtensions.fs index 4d917f9e6..ac7cd49d8 100644 --- a/tests/FSharp.Stats.Tests/TestExtensions.fs +++ b/tests/FSharp.Stats.Tests/TestExtensions.fs @@ -1,6 +1,7 @@ module TestExtensions open Expecto + open FsMath open FSharp.Stats open FSharp.Stats.Testing open System diff --git a/tests/FSharp.Stats.Tests/Testing.fs b/tests/FSharp.Stats.Tests/Testing.fs index 18ab34a44..e0593d73e 100644 --- a/tests/FSharp.Stats.Tests/Testing.fs +++ b/tests/FSharp.Stats.Tests/Testing.fs @@ -1,8 +1,11 @@ module TestingTests open Expecto open System -open FSharp.Stats.Testing + +open FsMath open FSharp.Stats +open FSharp.Stats.Testing + open TestExtensions open FSharp.Stats.Testing.SAM open Deedle diff --git a/tests/FSharp.Stats.Tests/Vector.fs b/tests/FSharp.Stats.Tests/Vector.fs deleted file mode 100644 index 5d6e313be..000000000 --- a/tests/FSharp.Stats.Tests/Vector.fs +++ /dev/null @@ -1,605 +0,0 @@ -module VectorTests - -open System -open Expecto -open FSharp.Stats - -[] -let vectorTests = - testList "Vector Tests" [ - - // ====================================================================== - // INT TESTS - // ====================================================================== - testList "Integer Vector Tests" [ - - // ------------------------------------------------------------------ - // Add - // ------------------------------------------------------------------ - testCase "add: integer vectors of same length" <| fun _ -> - let v1 = [| 1; 2; 3 |] - let v2 = [| 4; 5; 6 |] - let result = Vector.add v1 v2 - let expected = [| 5; 7; 9 |] - Expect.equal result expected "Should add each element pairwise" - - testCase "add: throws on dimension mismatch" <| fun _ -> - let v1 = [| 1; 2 |] - let v2 = [| 1; 2; 3 |] - Expect.throwsT (fun () -> Vector.add v1 v2 |> ignore) - "Should throw ArgumentException when vectors differ in length" - - // ------------------------------------------------------------------ - // Subtract - // ------------------------------------------------------------------ - testCase "subtract: integer vectors of same length" <| fun _ -> - let v1 = [| 5; 5; 5 |] - let v2 = [| 1; 2; 3 |] - let result = Vector.subtract v1 v2 - let expected = [| 4; 3; 2 |] - Expect.equal result expected "Should subtract each element pairwise" - - testCase "subtract: throws on dimension mismatch" <| fun _ -> - let v1 = [| 1; 2; 3 |] - let v2 = [| 1; 2 |] - Expect.throwsT (fun () -> Vector.subtract v1 v2 |> ignore) - "Should throw ArgumentException when vectors differ in length" - - // ------------------------------------------------------------------ - // Multiply - // ------------------------------------------------------------------ - testCase "multiply: integer vectors of same length" <| fun _ -> - let v1 = [| 2; 2; 2 |] - let v2 = [| 3; 4; 5 |] - let result = Vector.multiply v1 v2 - let expected = [| 6; 8; 10 |] - Expect.equal result expected "Should multiply each element pairwise" - - testCase "multiply: throws on dimension mismatch" <| fun _ -> - let v1 = [| 2; 2 |] - let v2 = [| 3; 4; 5 |] - Expect.throwsT (fun () -> Vector.multiply v1 v2 |> ignore) - "Should throw ArgumentException when vectors differ in length" - - // ------------------------------------------------------------------ - // Divide - // ------------------------------------------------------------------ - testCase "divide: integer vectors of same length" <| fun _ -> - let v1 = [| 10; 20; 30 |] - let v2 = [| 2; 5; 5 |] - let result = Vector.divide v1 v2 - let expected = [| 5; 4; 6 |] - Expect.equal result expected "Should divide each element pairwise" - - testCase "divide: throws on dimension mismatch" <| fun _ -> - let v1 = [| 10; 20 |] - let v2 = [| 2; 5; 5 |] - Expect.throwsT (fun () -> Vector.divide v1 v2 |> ignore) - "Should throw ArgumentException when vectors differ in length" - - // ------------------------------------------------------------------ - // Scalar Operations - // ------------------------------------------------------------------ - testCase "addScalar: adds scalar to every element" <| fun _ -> - let v = [| 1; 2; 3 |] - let scalar = 5 - let result = Vector.addScalar scalar v - let expected = [| 6; 7; 8 |] - Expect.equal result expected "Should add the scalar to each element" - - testCase "subtractScalar: subtracts scalar from every element" <| fun _ -> - let v = [| 1; 2; 3 |] - let scalar = 1 - let result = Vector.subtractScalar scalar v - let expected = [| 0; 1; 2 |] - Expect.equal result expected "Should subtract the scalar from each element" - - testCase "multiplyScalar: multiplies scalar to every element" <| fun _ -> - let v = [| 2; 4; 6 |] - let scalar = 3 - let result = Vector.multiplyScalar scalar v - let expected = [| 6; 12; 18 |] - Expect.equal result expected "Should multiply the scalar with each element" - - testCase "divideScalar: divides every element by scalar" <| fun _ -> - let v = [| 10; 20; 30 |] - let scalar = 10 - let result = Vector.divideScalar scalar v - let expected = [| 1; 2; 3 |] - Expect.equal result expected "Should divide each element by the scalar" - - // ------------------------------------------------------------------ - // sum - // ------------------------------------------------------------------ - testCase "sum: sums all elements of an integer vector" <| fun _ -> - let v = [| 1; 2; 3; 4 |] - let result = Vector.sum v - Expect.equal result 10 "Should be the sum of all elements" - - testCase "sum: sums an empty integer vector (should be 0)" <| fun _ -> - let v : int[] = [||] - let result = Vector.sum v - Expect.equal result 0 "Sum of empty array should be 0" - - // ------------------------------------------------------------------ - // product - // ------------------------------------------------------------------ - testCase "product: multiplies all elements of an integer vector" <| fun _ -> - let v = [| 1; 2; 3; 4 |] - let result = Vector.product v - Expect.equal result 24 "Should be the product of all elements" - - testCase "product: empty integer vector (should be 1 for identity)" <| fun _ -> - let v : int[] = [||] - let result = Vector.product v - Expect.equal result 1 "Product of empty array should be 1" - - - // ------------------------------------------------------------------ - // dot - // ------------------------------------------------------------------ - testCase "dot: computes dot product of two integer vectors" <| fun _ -> - let v1 = [| 1; 2; 3 |] - let v2 = [| 4; 5; 6 |] - let result = Vector.dot v1 v2 - // Dot = 1*4 + 2*5 + 3*6 = 4 + 10 + 18 = 32 - Expect.equal result 32 "Dot product should match expected" - - testCase "dot: throws on dimension mismatch" <| fun _ -> - let v1 = [| 1; 2 |] - let v2 = [| 3; 4; 5 |] - Expect.throwsT (fun () -> Vector.dot v1 v2 |> ignore) - "Should throw ArgumentException when vectors differ in length" - - - // ------------------------------------------------------------------ - // min - // ------------------------------------------------------------------ - testCase "min: finds minimum in a non-empty integer vector" <| fun _ -> - let v = [| 10; 2; 30; 4 |] - let result = Vector.min v - Expect.equal result 2 "Should find the smallest integer in the array" - - testCase "min: throws on empty integer vector" <| fun _ -> - let v : int[] = [||] - Expect.throwsT (fun () -> Vector.min v |> ignore) - "Should throw ArgumentException for empty vector" - - // ------------------------------------------------------------------ - // max - // ------------------------------------------------------------------ - testCase "max: finds maximum in a non-empty integer vector" <| fun _ -> - let v = [| 10; 2; 30; 4 |] - let result = Vector.max v - Expect.equal result 30 "Should find the largest integer in the array" - - testCase "max: throws on empty integer vector" <| fun _ -> - let v : int[] = [||] - Expect.throwsT (fun () -> Vector.max v |> ignore) - "Should throw ArgumentException for empty vector" - - // ------------------------------------------------------------------ - // OPERATOR TESTS (Int) - // ------------------------------------------------------------------ - testCase "vector-vector operators (int): .+ .- .* ./" <| fun _ -> - let v1 = [| 1; 2; 3 |] - let v2 = [| 4; 5; 6 |] - - // .+ - let addResult = v1 .+ v2 - Expect.equal addResult [|5; 7; 9|] "v1 .+ v2 should match element-wise add" - - // .- - let subResult = v1 .- v2 - Expect.equal subResult [|-3; -3; -3|] "v1 .- v2 should match element-wise subtract" - - // .* - let mulResult = v1 .* v2 - Expect.equal mulResult [|4; 10; 18|] "v1 .* v2 should match element-wise multiply" - - // ./ - let divResult = [| 10; 20; 30 |] ./ [| 2; 5; 5 |] - Expect.equal divResult [|5; 4; 6|] "Should match element-wise division" - - testCase "vector-scalar operators (int): .+ .- .* ./" <| fun _ -> - let v = [| 2; 4; 6 |] - - // v .+ scalar - let addScalarResult = v .+ 2 - Expect.equal addScalarResult [|4; 6; 8|] "v .+ 2 should add 2 to all elements" - - // v .- scalar - let subScalarResult = v .- 2 - Expect.equal subScalarResult [|0; 2; 4|] "v .- 2 should subtract 2 from all elements" - - // v .* scalar - let mulScalarResult = v .* 3 - Expect.equal mulScalarResult [|6; 12; 18|] "v .* 3 should multiply all elements by 3" - - // v ./ scalar - let divScalarResult = [| 10; 20; 30 |] ./ 10 - Expect.equal divScalarResult [|1; 2; 3|] "Should divide all elements by 10" - ] - - - // ====================================================================== - // FLOAT TESTS - // ====================================================================== - testList "Float Vector Tests" [ - - // ------------------------------------------------------------------ - // Add - // ------------------------------------------------------------------ - testCase "add: float vectors of same length" <| fun _ -> - let v1 = [| 1.0; 2.0; 3.0 |] - let v2 = [| 4.0; 5.0; 6.0 |] - let result = Vector.add v1 v2 - let expected = [| 5.0; 7.0; 9.0 |] - Expect.equal result expected "Should add each element pairwise" - - testCase "add: throws on dimension mismatch" <| fun _ -> - let v1 = [| 1.0; 2.0 |] - let v2 = [| 1.0; 2.0; 3.0 |] - Expect.throwsT (fun () -> Vector.add v1 v2 |> ignore) - "Should throw ArgumentException when vectors differ in length" - - // ------------------------------------------------------------------ - // Subtract - // ------------------------------------------------------------------ - testCase "subtract: float vectors of same length" <| fun _ -> - let v1 = [| 5.5; 5.0; 5.75 |] - let v2 = [| 1.5; 2.0; 3.25 |] - let result = Vector.subtract v1 v2 - let expected = [| 4.0; 3.0; 2.5 |] - Expect.equal result expected "Should subtract each element pairwise" - - // ------------------------------------------------------------------ - // Multiply - // ------------------------------------------------------------------ - testCase "multiply: float vectors of same length" <| fun _ -> - let v1 = [| 2.0; 2.5; 3.0 |] - let v2 = [| 3.0; 4.0; 5.0 |] - let result = Vector.multiply v1 v2 - let expected = [| 6.0; 10.0; 15.0 |] - Expect.equal result expected "Should multiply each element pairwise" - - // ------------------------------------------------------------------ - // Divide - // ------------------------------------------------------------------ - testCase "divide: float vectors of same length" <| fun _ -> - let v1 = [| 10.0; 20.0; 30.0 |] - let v2 = [| 2.0; 5.0; 5.0 |] - let result = Vector.divide v1 v2 - let expected = [| 5.0; 4.0; 6.0 |] - Expect.equal result expected "Should divide each element pairwise" - - // ------------------------------------------------------------------ - // Scalar Operations - // ------------------------------------------------------------------ - testCase "addScalar: adds scalar to every float element" <| fun _ -> - let v = [| 1.0; 2.0; 3.0 |] - let scalar = 5.5 - let result = Vector.addScalar scalar v - let expected = [| 6.5; 7.5; 8.5 |] - Expect.equal result expected "Should add 5.5 to each element" - - testCase "subtractScalar: subtract scalar from every float element" <| fun _ -> - let v = [| 1.0; 2.5; 3.75 |] - let scalar = 1.25 - let result = Vector.subtractScalar scalar v - let expected = [| -0.25; 1.25; 2.5 |] - Expect.equal result expected "Should subtract 1.25 from each element" - - testCase "multiplyScalar: multiplies scalar with every float element" <| fun _ -> - let v = [| 2.5; 4.0; 6.0 |] - let scalar = 2.0 - let result = Vector.multiplyScalar scalar v - let expected = [| 5.0; 8.0; 12.0 |] - Expect.equal result expected "Should multiply each element by 2.0" - - testCase "divideScalar: divides every float element by scalar" <| fun _ -> - let v = [| 10.0; 20.0; 30.0 |] - let scalar = 2.0 - let result = Vector.divideScalar scalar v - let expected = [| 5.0; 10.0; 15.0 |] - Expect.equal result expected "Should divide each element by 2.0" - - // ------------------------------------------------------------------ - // sum - // ------------------------------------------------------------------ - testCase "sum: sums all elements of a float vector" <| fun _ -> - let v = [| 1.1; 2.2; 3.3; 4.4 |] - let result = Vector.sum v - // Expect exact or near: 1.1 + 2.2 + 3.3 + 4.4 = 11.0 - Expect.floatClose Accuracy.veryHigh 11.0 result "Sum of [1.1;2.2;3.3;4.4] = 11.0" - - testCase "sum: sums empty float vector (should be 0.0)" <| fun _ -> - let v : float[] = [||] - let result = Vector.sum v - Expect.equal result 0.0 "Sum of empty array should be 0.0" - - // ------------------------------------------------------------------ - // product - // ------------------------------------------------------------------ - testCase "product: multiplies all elements of a float vector" <| fun _ -> - let v = [| 1.0; 2.0; 3.0 |] - let result = Vector.product v - Expect.equal result 6.0 "1.0 * 2.0 * 3.0 = 6.0" - - testCase "product: empty float vector" <| fun _ -> - // By definition in your code, fold starts with 1. - let v : float[] = [||] - let result = Vector.product v - Expect.equal result 1.0 "Product of empty array should be 1.0" - - // ------------------------------------------------------------------ - // mean - // ------------------------------------------------------------------ - testCase "mean: computes mean of a float vector" <| fun _ -> - let v = [| 2.0; 4.0; 6.0; 8.0 |] - let result = Vector.mean v - // (2.0 + 4.0 + 6.0 + 8.0) / 4 = 5.0 - Expect.floatClose Accuracy.veryHigh 5.0 result "Mean should be 5.0" - - testCase "mean: throws on empty float vector" <| fun _ -> - let v : float[] = [||] - Expect.throwsT (fun () -> Vector.mean v |> ignore) - "Should throw ArgumentException when float vector is empty" - - // ------------------------------------------------------------------ - // dot - // ------------------------------------------------------------------ - testCase "dot: computes dot product of two float vectors" <| fun _ -> - let v1 = [| 1.0; 2.0; 3.0 |] - let v2 = [| 4.0; 5.0; 6.0 |] - let result = Vector.dot v1 v2 - // Dot = 1*4 + 2*5 + 3*6 = 4 + 10 + 18 = 32 - Expect.floatClose Accuracy.veryHigh 32.0 result "Dot product should be 32.0" - - // ------------------------------------------------------------------ - // norm - // ------------------------------------------------------------------ - testCase "norm: computes Euclidean norm of a 3-4-5 triangle (float)" <| fun _ -> - let v = [| 3.0; 4.0 |] - let result = Vector.norm v - Expect.floatClose Accuracy.veryHigh 5.0 result "Norm of [3.0;4.0] should be 5.0" - - // ------------------------------------------------------------------ - // min - // ------------------------------------------------------------------ - testCase "min: finds minimum in a non-empty float vector" <| fun _ -> - let v = [| 10.0; 2.0; 30.5; 4.1 |] - let result = Vector.min v - Expect.equal result 2.0 "Should find the smallest float in the array" - - testCase "min: throws on empty float vector" <| fun _ -> - let v : float[] = [||] - Expect.throwsT (fun () -> Vector.min v |> ignore) - "Should throw ArgumentException for empty vector" - - // ------------------------------------------------------------------ - // max - // ------------------------------------------------------------------ - testCase "max: finds maximum in a non-empty float vector" <| fun _ -> - let v = [| 10.0; 2.0; 30.5; 4.1 |] - let result = Vector.max v - Expect.equal result 30.5 "Should find the largest float in the array" - - testCase "max: throws on empty float vector" <| fun _ -> - let v : float[] = [||] - Expect.throwsT (fun () -> Vector.max v |> ignore) - "Should throw ArgumentException for empty vector" - - // ------------------------------------------------------------------ - // OPERATOR TESTS (Float) - // ------------------------------------------------------------------ - testCase "vector-vector operators (float): .+ .- .* ./" <| fun _ -> - let v1 = [| 1.0; 2.0; 3.0 |] - let v2 = [| 4.0; 5.0; 6.0 |] - - // .+ - let addResult = v1 .+ v2 - Expect.equal addResult [|5.0; 7.0; 9.0|] "v1 .+ v2 should match element-wise add" - - // .- - let subResult = v1 .- v2 - Expect.equal subResult [|-3.0; -3.0; -3.0|] "v1 .- v2 should match element-wise subtract" - - // .* - let mulResult = v1 .* v2 - Expect.equal mulResult [|4.0; 10.0; 18.0|] "v1 .* v2 should match element-wise multiply" - - // ./ - let divResult = [| 10.0; 20.0; 30.0 |] ./ [| 2.0; 5.0; 5.0 |] - Expect.equal divResult [|5.0; 4.0; 6.0|] "Should match element-wise division" - - testCase "vector-scalar operators (float): .+ .- .* ./" <| fun _ -> - let v = [| 2.5; 4.0; 6.0 |] - - // v .+ scalar - let addScalarResult = v .+ 2.0 - Expect.equal addScalarResult [|4.5; 6.0; 8.0|] "v .+ 2.0 should add 2.0 to all elements" - - // v .- scalar - let subScalarResult = v .- 0.5 - Expect.equal subScalarResult [|2.0; 3.5; 5.5|] "v .- 0.5 should subtract 0.5 from all elements" - - // v .* scalar - let mulScalarResult = v .* 1.5 - Expect.equal mulScalarResult [|3.75; 6.0; 9.0|] "v .* 1.5 should multiply all elements by 1.5" - - // v ./ scalar - let divScalarResult = [| 10.0; 20.0; 30.0 |] ./ 10.0 - Expect.equal divScalarResult [|1.0; 2.0; 3.0|] "Should divide all elements by 10.0" - - // ------------------------------------------------------------------ - // cross (outer) product - // ------------------------------------------------------------------ - testCase "cross: computes the outer product of two float vectors" <| fun _ -> - // 'Vector.cross' is assumed to produce a 2D array (matrix) - let colvec = [| 1.0; 2.0; 3.0 |] - let rowvec = [| 4.0; 5.0; 6.0 |] - - // The expected 3x3 matrix is computed by: - // [ [1.0*4.0, 1.0*5.0, 1.0*6.0] - // [2.0*4.0, 2.0*5.0, 2.0*6.0] - // [3.0*4.0, 3.0*5.0, 3.0*6.0] ] - let result = Vector.cross colvec rowvec - let expected = - [| [|4.0; 5.0; 6.0|] - [|8.0; 10.0; 12.0|] - [|12.0;15.0; 18.0|] |] |> matrix - - Expect.equal result expected "Expected outer product of colvec and rowvec" - ] - // ====================================================================== - // Vector manipulation tests - // ====================================================================== - testList "Vector manipulation Tests" [ - - test "foldi applies a function with index to a vector" { - let v = [|1; 2; 3|] - let result = Vector.foldi (fun i acc x -> acc + i * x) 0 v - Expect.equal result 8 "Expected indexed fold result" - } - - test "mapi applies a function with index to each element" { - let v = [|1; 2; 3|] - let result = Vector.mapi (fun i x -> x + i) v - Expect.equal result [|1; 3; 5|] "Expected indexed map result" - } - - test "filter filters elements by predicate" { - let v = [|1; 2; 3; 4|] - let result = Vector.filter (fun x -> x % 2 = 0) v - Expect.equal result [|2; 4|] "Expected filtered vector" - } - - test "init creates a vector using a generator function" { - let result = Vector.init 5 (fun i -> i * 2) - Expect.equal result [|0; 2; 4; 6; 8|] "Expected initialized vector" - } - - test "slice extracts a slice from a vector" { - let v = [|1; 2; 3; 4; 5|] - let result = Vector.slice 1 3 v - Expect.equal result [|2; 3; 4|] "Expected sliced vector" - } - - test "argmax finds the index of the maximum value" { - let v = [|1; 3; 2|] - let result = Vector.argmax v - Expect.equal result 1 "Expected index of maximum value" - } - - test "argmin finds the index of the minimum value" { - let v = [|3; 1; 2|] - let result = Vector.argmin v - Expect.equal result 1 "Expected index of minimum value" - } - - test "padRight pads a vector to a given length" { - let v = [|1; 2|] - let result = Vector.padRight 5 0 v - Expect.equal result [|1; 2; 0; 0; 0|] "Expected padded vector" - } - - test "zip combines two vectors with indices" { - let v1 = [|1; 2; 3|] - let v2 = [|4; 5; 6|] - let result = Vector.zip v1 v2 - Expect.equal result [|(0, 1, 4); (1, 2, 5); (2, 3, 6)|] "Expected zipped vector" - } - - test "argminBy finds the index of the minimum value using a projection" { - let v = [|1; 2; 3|] - let result = Vector.argminBy (fun x -> -x) v - Expect.equal result 2 "Expected index of minimum value by projection" - } - - test "argmaxBy finds the index of the maximum value using a projection" { - let v = [|1; 2; 3|] - let result = Vector.argmaxBy (fun x -> -x) v - Expect.equal result 0 "Expected index of maximum value by projection" - } - - test "tryFindIndex finds the index of the first matching element" { - let v = [|1; 2; 3|] - let result = Vector.tryFindIndex (fun x -> x = 2) v - Expect.equal result (Some 1) "Expected index of first matching element" - } - - test "findIndex finds the index of the first matching element or throws" { - let v = [|1; 2; 3|] - let result = Vector.findIndex (fun x -> x = 2) v - Expect.equal result 1 "Expected index of first matching element" - } - - test "enumerateNonZero enumerates non-zero elements with indices" { - let v = [|0; 1; 0; 2|] - let result = Vector.enumerateNonZero v - Expect.equal result [|(1, 1); (3, 2)|] "Expected non-zero elements with indices" - } - - test "split splits a vector into prefix and suffix" { - let v = [|1; 2; 3; 4|] - let prefix, suffix = Vector.split 2 v - Expect.equal prefix [|1; 2|] "Expected prefix" - Expect.equal suffix [|3; 4|] "Expected suffix" - } - - test "chunk chunks a vector into equally sized pieces" { - let v = [|1; 2; 3; 4; 5|] - let result = Vector.chunk 2 v - Expect.equal result [|[|1; 2|]; [|3; 4|]; [|5|]|] "Expected chunked vector" - } - - test "windowed creates a sliding window over the vector" { - let v = [|1; 2; 3; 4|] - let result = Vector.windowed 2 v - Expect.equal result [|[|1; 2|]; [|2; 3|]; [|3; 4|]|] "Expected sliding windows" - } - - test "splitVector splits a vector based on indices" { - let v = [|1; 2; 3; 4|] - let nvi, nv = Vector.splitVector [|1; 3|] v - Expect.equal nvi [|2; 4|] "Expected extracted elements" - Expect.equal nv [|1; 3|] "Expected remaining elements" - } - - test "permuteBy permutes a vector using a permutation function" { - let v = [|1; 2; 3|] - let result = Vector.permuteBy (fun i -> (i + 1) % 3) v // 1 2 0 - Expect.equal result [|2; 3; 1|] "Expected permuted vector" - } - - test "ofSeq converts a sequence to a vector" { - let seq = seq { 1; 2; 3 } - let result = Vector.ofSeq seq - Expect.equal result [|1; 2; 3|] "Expected vector from sequence" - } - ] - - ] - - - - - -//let private testVectorA = -// let values = [|0.;3.;6.|] -// Vector(Some (Instances.FloatNumerics :> INumeric),values) - -//[] -//let covarianceTests = -// let x = vector [5.;12.;18.;-23.;45.] -// let y = vector [2.;8.;18.;-20.;28.] - -// testList "Vector" [ -// testCase "cov" <| fun () -> -// let cov = Vector.cov x y -// Expect.floatClose Accuracy.high cov 434.90 "Should be equal (double precision)" -// testCase "covPopulation" <| fun () -> -// let covPop = Vector.covPopulation x y -// Expect.floatClose Accuracy.high covPop 347.92 "Should be equal (double precision)" -// ] From c1ba0dd4434f256e285c0d7a7353d469d394901f Mon Sep 17 00:00:00 2001 From: Kevin Schneider Date: Tue, 8 Apr 2025 16:24:13 +0200 Subject: [PATCH 047/121] update to .net 8 in preparation for INumerics core --- build/BasicTasks.fs | 7 +++++-- build/PackageTasks.fs | 4 +++- build/ReleaseNotesTasks.fs | 5 ++--- build/TestTasks.fs | 17 +++++++++------- build/build.fsproj | 20 +++++++++---------- global.json | 2 +- .../FSharp.Stats.Interactive.fsproj | 2 +- src/FSharp.Stats/FSharp.Stats.fsproj | 2 +- .../FSharp.Stats.Tests.fsproj | 2 +- 9 files changed, 34 insertions(+), 27 deletions(-) diff --git a/build/BasicTasks.fs b/build/BasicTasks.fs index 713217b79..65cb69bf2 100644 --- a/build/BasicTasks.fs +++ b/build/BasicTasks.fs @@ -26,6 +26,9 @@ let clean = BuildTask.create "Clean" [] { } let build = BuildTask.create "Build" [clean] { - solutionFile - |> DotNet.build id + solutionFile + |> DotNet.build (fun p -> + { p with MSBuildParams = { p.MSBuildParams with DisableInternalBinLog = true }} + |> DotNet.Options.withCustomParams (Some "-tl") + ) } \ No newline at end of file diff --git a/build/PackageTasks.fs b/build/PackageTasks.fs index d51d99a4c..af6517842 100644 --- a/build/PackageTasks.fs +++ b/build/PackageTasks.fs @@ -17,7 +17,8 @@ let pack = BuildTask.create "Pack" [clean; build; runTests] { -- "src/bin/*" |> Seq.iter (Fake.DotNet.DotNet.pack (fun p -> let msBuildParams = - {p.MSBuildParams with + {p.MSBuildParams with + DisableInternalBinLog = true Properties = ([ "Version",stableVersionTag "PackageReleaseNotes", (release.Notes |> String.concat "\r\n") @@ -40,6 +41,7 @@ let packPrerelease = BuildTask.create "PackPrerelease" [setPrereleaseTag; clean; |> Seq.iter (Fake.DotNet.DotNet.pack (fun p -> let msBuildParams = {p.MSBuildParams with + DisableInternalBinLog = true Properties = ([ "Version", prereleaseTag "PackageReleaseNotes", (release.Notes |> String.toLines ) diff --git a/build/ReleaseNotesTasks.fs b/build/ReleaseNotesTasks.fs index 81e35bbba..ba0a99164 100644 --- a/build/ReleaseNotesTasks.fs +++ b/build/ReleaseNotesTasks.fs @@ -8,9 +8,8 @@ open BlackFox.Fake //} let updateReleaseNotes = BuildTask.createFn "ReleaseNotes" [] (fun config -> - Release.exists() - - Release.update(ProjectInfo.gitOwner, ProjectInfo.project, config) + ReleaseNotes.ensure() + ReleaseNotes.update(ProjectInfo.gitOwner, ProjectInfo.project, config) ) //let githubDraft = BuildTask.createFn "GithubDraft" [] (fun config -> diff --git a/build/TestTasks.fs b/build/TestTasks.fs index 65dc6d6ac..d79c6d935 100644 --- a/build/TestTasks.fs +++ b/build/TestTasks.fs @@ -7,14 +7,16 @@ open ProjectInfo open BasicTasks let runTests = BuildTask.create "RunTests" [clean; build] { - Fake.DotNet.DotNet.test(fun testParams -> - { - testParams with - Logger = Some "console;verbosity=detailed" - Configuration = DotNet.BuildConfiguration.fromString configuration - NoBuild = true + testProject + |> Fake.DotNet.DotNet.test (fun testParams -> + { testParams with + Logger = Some "console;verbosity=detailed" + Configuration = DotNet.BuildConfiguration.fromString configuration + NoBuild = true + MSBuildParams = { testParams.MSBuildParams with DisableInternalBinLog = true } } - ) testProject + |> DotNet.Options.withCustomParams (Some "-tl") + ) } // to do: use this once we have actual tests @@ -25,6 +27,7 @@ let runTestsWithCodeCov = BuildTask.create "RunTestsWithCodeCov" [clean; build] testParams with MSBuildParams = { standardParams with + DisableInternalBinLog = true Properties = [ "AltCover","true" "AltCoverCobertura","../../codeCov.xml" diff --git a/build/build.fsproj b/build/build.fsproj index 82dafd230..b3f0ebf49 100644 --- a/build/build.fsproj +++ b/build/build.fsproj @@ -1,7 +1,7 @@  - net6.0 + net8.0 Exe @@ -20,15 +20,15 @@ - - - - - - - - - + + + + + + + + + diff --git a/global.json b/global.json index d6c2c37f7..501e79a87 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "sdk": { - "version": "6.0.100", + "version": "8.0.100", "rollForward": "latestFeature" } } \ No newline at end of file diff --git a/src/FSharp.Stats.Interactive/FSharp.Stats.Interactive.fsproj b/src/FSharp.Stats.Interactive/FSharp.Stats.Interactive.fsproj index dca322b60..4059d91a0 100644 --- a/src/FSharp.Stats.Interactive/FSharp.Stats.Interactive.fsproj +++ b/src/FSharp.Stats.Interactive/FSharp.Stats.Interactive.fsproj @@ -1,7 +1,7 @@  - netstandard2.1 + net8.0 true true diff --git a/src/FSharp.Stats/FSharp.Stats.fsproj b/src/FSharp.Stats/FSharp.Stats.fsproj index 12bc4e587..c0ee4e4f2 100644 --- a/src/FSharp.Stats/FSharp.Stats.fsproj +++ b/src/FSharp.Stats/FSharp.Stats.fsproj @@ -1,7 +1,7 @@  - netstandard2.0 + .net8.0 true diff --git a/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj b/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj index af6b5eb2d..c8d7e411d 100644 --- a/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj +++ b/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj @@ -1,7 +1,7 @@  Exe - net6.0 + net8.0 false From 81a4c8fff02f6a052b652895d93fd80f2b092a34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20M=C3=BChlhaus?= Date: Wed, 9 Apr 2025 13:39:26 +0200 Subject: [PATCH 048/121] Remove Algebra types and the Linerar Algebra services --- src/FSharp.Stats/AlgTypes.fs | 2590 ----------------- src/FSharp.Stats/Algebra/ILinearAlgebra.fs | 122 - .../Algebra/LinearAlgebraServiceMKL.fs | 641 ---- .../Algebra/LinearAlgebraServiceManaged.fs | 643 ---- src/FSharp.Stats/Algebra/NativeArray.fs | 106 - .../Algebra/NativeArrayExtensions.fs | 53 - src/FSharp.Stats/Algebra/NativeUtilities.fs | 49 - src/FSharp.Stats/BigRational.fs | 311 -- src/FSharp.Stats/GlobalAssociations.fs | 45 - src/FSharp.Stats/INumeric.fs | 240 -- src/FSharp.Stats/Matrix.fs | 1611 ---------- src/FSharp.Stats/MatrixTopLevelOperators.fs | 10 - src/FSharp.Stats/RowVector.fs | 88 - src/FSharp.Stats/ServiceLocator.fs | 191 -- src/FSharp.Stats/Vector.fs | 880 ------ 15 files changed, 7580 deletions(-) delete mode 100644 src/FSharp.Stats/AlgTypes.fs delete mode 100644 src/FSharp.Stats/Algebra/ILinearAlgebra.fs delete mode 100644 src/FSharp.Stats/Algebra/LinearAlgebraServiceMKL.fs delete mode 100644 src/FSharp.Stats/Algebra/LinearAlgebraServiceManaged.fs delete mode 100644 src/FSharp.Stats/Algebra/NativeArray.fs delete mode 100644 src/FSharp.Stats/Algebra/NativeArrayExtensions.fs delete mode 100644 src/FSharp.Stats/Algebra/NativeUtilities.fs delete mode 100644 src/FSharp.Stats/BigRational.fs delete mode 100644 src/FSharp.Stats/GlobalAssociations.fs delete mode 100644 src/FSharp.Stats/INumeric.fs delete mode 100644 src/FSharp.Stats/Matrix.fs delete mode 100644 src/FSharp.Stats/MatrixTopLevelOperators.fs delete mode 100644 src/FSharp.Stats/RowVector.fs delete mode 100644 src/FSharp.Stats/ServiceLocator.fs delete mode 100644 src/FSharp.Stats/Vector.fs diff --git a/src/FSharp.Stats/AlgTypes.fs b/src/FSharp.Stats/AlgTypes.fs deleted file mode 100644 index ee79a0db2..000000000 --- a/src/FSharp.Stats/AlgTypes.fs +++ /dev/null @@ -1,2590 +0,0 @@ -// (c) Microsoft Corporation 2005-2009. - -//---------------------------------------------------------------------------- -// An implementation of generic dense and sparse matrix types. -// -// Overview and suffix documentation -// _GU = generic unspecialized (Matrix, Vector etc.) -// _GUA = generic unspecialized op on (underlying) array -// _DS = Double specialized (Matrix = matrix, Vector = vector etc.) -// -// DM = dense matrix -// SM = sparse matrix -// V = vector (dense) -// RV = row vector (dense) - - -namespace FSharp.Stats - - #nowarn "60" // implementations in augmentations - #nowarn "69" // implementations in augmentations - - open System - open System.Collections - open System.Collections.Generic - open System.Diagnostics - open Formatting - //type permutation = int -> int - - -//========================================================================= -// (c) Microsoft Corporation 2005-2009. -//========================================================================= - - [] - module Helpers = - let sparseNYI() = failwith "this operation is not supported on sparse matrices" - let sparseNotMutable() = failwith "sparse matrices are not mutable" - - [] - let opsdata<'T> = GlobalAssociations.TryGetNumericAssociation<'T>() - - [] - let DenseMaxDisplay = 50 - [] - let VectorMaxDisplay = 100 - - - /// The value stored for the dictionary of numeric operations. If none is present then this indicates - /// no operations are known for this type. - type OpsData<'T> = INumeric<'T> option - - type DenseMatrix<'T>(opsData : OpsData<'T>, values : 'T[,]) = - member m.OpsData = opsData - member m.Values = values - member m.NumRows = values.GetLength(0) - member m.NumCols = values.GetLength(1) - - member m.ElementOps = - match opsData with - | None -> raise (new System.NotSupportedException("The element type carried by this matrix does not support numeric operations")) - | Some a -> a - - member m.Item - with get (i,j) = values.[i,j] - and set (i,j) x = values.[i,j] <- x - - type SparseMatrix<'T>(opsData : OpsData<'T>, sparseValues : 'T array, sparseRowOffsets : int array, ncols:int, columnValues: int array) = - member m.OpsData = opsData; - member m.NumCols = ncols - member m.NumRows = sparseRowOffsets.Length - 1 - member m.SparseColumnValues = columnValues - member m.SparseRowOffsets = sparseRowOffsets (* nrows + 1 elements *) - member m.SparseValues = sparseValues - - member m.ElementOps = - match opsData with - | None -> raise (new System.NotSupportedException("The element type carried by this matrix does not support numeric operations")) - | Some a -> a - - member m.MinIndexForRow i = m.SparseRowOffsets.[i] - member m.MaxIndexForRow i = m.SparseRowOffsets.[i+1] - - - member m.Item - with get (i,j) = - let imax = m.NumRows - let jmax = m.NumCols - if j < 0 || j >= jmax || i < 0 || i >= imax then raise (new System.ArgumentOutOfRangeException()) else - let kmin = m.MinIndexForRow i - let kmax = m.MaxIndexForRow i - let rec loopRow k = - (* note: could do a binary chop here *) - if k >= kmax then m.ElementOps.Zero else - let j2 = columnValues.[k] - if j < j2 then m.ElementOps.Zero else - if j = j2 then sparseValues.[k] else - loopRow (k+1) - loopRow kmin - -#if FX_NO_DEBUG_DISPLAYS -#else - [] -#endif - [] - [] - //[>)>] - type Matrix<'T> = - | DenseRepr of DenseMatrix<'T> - | SparseRepr of SparseMatrix<'T> - interface System.IComparable - interface IStructuralComparable - interface IStructuralEquatable - interface IEnumerable<'T> - interface IEnumerable - interface IFsiFormattable - interface IMatrixFormattable - - member m.ElementOps = match m with DenseRepr mr -> mr.ElementOps | SparseRepr mr -> mr.ElementOps - member m.NumRows = match m with DenseRepr mr -> mr.NumRows | SparseRepr mr -> mr.NumRows - member m.NumCols = match m with DenseRepr mr -> mr.NumCols | SparseRepr mr -> mr.NumCols - - member m.Item - with get (i,j) = - match m with - | DenseRepr dm -> dm.[i,j] - | SparseRepr sm -> sm.[i,j] - and set (i,j) x = - match m with - | DenseRepr dm -> dm.[i,j] <- x - | SparseRepr _ -> sparseNotMutable() - - -#if FX_NO_DEBUG_DISPLAYS -#else - [] -#endif - member m.IsDense = match m with DenseRepr _ -> true | SparseRepr _ -> false - -#if FX_NO_DEBUG_DISPLAYS -#else - [] -#endif - member m.IsSparse = match m with DenseRepr _ -> false | SparseRepr _ -> true - -#if FX_NO_DEBUG_DISPLAYS -#else - [] -#endif - member m.InternalSparseColumnValues = match m with DenseRepr _ -> invalidOp "not a sparse matrix" | SparseRepr mr -> mr.SparseColumnValues - -#if FX_NO_DEBUG_DISPLAYS -#else - [] -#endif - member m.InternalSparseRowOffsets = match m with DenseRepr _ -> invalidOp "not a sparse matrix" | SparseRepr mr -> mr.SparseRowOffsets - -#if FX_NO_DEBUG_DISPLAYS -#else - [] -#endif - member m.InternalSparseValues = match m with DenseRepr _ -> invalidOp "not a sparse matrix" | SparseRepr mr -> mr.SparseValues - -#if FX_NO_DEBUG_DISPLAYS -#else - [] -#endif - member m.InternalDenseValues = match m with DenseRepr mr -> mr.Values | SparseRepr _ -> invalidOp "not a dense matrix" - -#if FX_NO_DEBUG_DISPLAYS -#else - [] -#endif -#if FX_NO_DEBUG_PROXIES -#else - [>)>] -#endif - [] - [] - type RowVector<'T>(opsRV : INumeric<'T> option, arrRV : 'T array ) = - interface System.IComparable - interface IStructuralComparable - interface IStructuralEquatable - - -#if FX_NO_DEBUG_DISPLAYS -#else - [] -#endif - member x.InternalValues = arrRV - member x.Values = arrRV - member x.OpsData = opsRV - - - interface IEnumerable<'T> with - member x.GetEnumerator() = (arrRV :> seq<_>).GetEnumerator() - interface IEnumerable with - member x.GetEnumerator() = (arrRV :> IEnumerable).GetEnumerator() - - member x.Length = arrRV.Length - member x.NumCols = arrRV.Length - member x.ElementOps = - match opsRV with - | None -> raise (new System.NotSupportedException("The element type carried by this row vector does not support numeric operations")) - | Some a -> a - - member v.Item - with get i = arrRV.[i] - and set i x = arrRV.[i] <- x - - and - [] - RowVectorDebugView<'T>(v: RowVector<'T>) = - -#if FX_NO_DEBUG_DISPLAYS -#else - [] -#endif - member x.Items = v |> Seq.truncate 1 |> Seq.toArray - -#if FX_NO_DEBUG_DISPLAYS -#else - [] -#endif -#if FX_NO_DEBUG_PROXIES -#else - [>)>] -#endif - [] - [] - type Vector<'T>(opsV : INumeric<'T> option, arrV : 'T array) = - -#if FX_NO_DEBUG_DISPLAYS -#else - [] -#endif - member x.InternalValues = arrV - member x.Values = arrV - member x.OpsData = opsV - interface System.IComparable - interface IStructuralComparable - interface IStructuralEquatable - - interface IEnumerable<'T> with - member x.GetEnumerator() = (arrV :> seq<_>).GetEnumerator() - interface IEnumerable with - member x.GetEnumerator() = (arrV :> IEnumerable).GetEnumerator() - - ///Length of vector - member m.Length = arrV.Length - member m.NumRows = arrV.Length - member m.ElementOps = - match opsV with - | None -> raise (new System.NotSupportedException("The element type carried by this vector does not support numeric operations")) - | Some a -> a - member v.Item - with get i = arrV.[i] - and set i x = arrV.[i] <- x - -#if FX_NO_DEBUG_PROXIES -#else - and - [] - VectorDebugView<'T>(v: Vector<'T>) = - - [] - member x.Items = v |> Seq.truncate 1 |> Seq.toArray -#endif - - - /// Implementations of operations that will work for any type - module GenericImpl = - - type OpsData<'T> = INumeric<'T> option - - let opsOfOpsData (d : OpsData<'T>) = - match d with - | None -> raise (new System.NotSupportedException("The element type '"+(typeof<'T>).ToString()+"' carried by this vector or matrix does not support numeric operations (i.e. does not have a registered numeric association)")) - | Some a -> a - - let getNormOps (ops:INumeric<'T>) = - match box ops with - | :? INormFloat<'T> as ops -> ops - | _ -> raise (new System.NotSupportedException("The element type '"+(typeof<'T>.ToString())+"' carried by this vector or matrix does not support the INormFloat<_> operation (i.e. does not have a registered numeric association that supports this type)")) - - let mkDenseMatrixGU ops arr = DenseMatrix(ops,arr) - let mkSparseMatrixGU ops (arr: 'a[,]) = - let length1 = arr |> Array2D.length1 - let length2 = arr |> Array2D.length2 - - let mutable nnz = 0 - let a = FSharp.Collections.ResizeArray<'a>() - let ja = FSharp.Collections.ResizeArray() - let ia = FSharp.Collections.ResizeArray() - ia.Add(0) - for i = 0 to (length1 - 1) do - for j = 0 to (length2 - 1) do - if ((Array2D.get arr i j) |> System.Convert.ToDouble) >= 0.000001 || ((Array2D.get arr i j)|> System.Convert.ToDouble) <= -0.000001 then - a.Add((Array2D.get arr i j)) - ja.Add(j) - nnz <- nnz + 1 - ia.Add(nnz) - SparseMatrix(ops, a.ToArray(), ia.ToArray(), length2, ja.ToArray()) - let mkRowVecGU ops arr = RowVector(ops, arr) - let mkVecGU ops arr = Vector(ops,arr) - - let inline getArray2D (arrDM : _[,]) i j = arrDM.[i,j] - let inline setArray2D (arrDM : _[,]) i j x = arrDM.[i,j] <- x - - let inline createArray m = Array.zeroCreate m - - let inline createArray2D m n = Array2D.zeroCreate m n - - let inline assignArray2D m n f arr = - for i = 0 to m - 1 do - for j = 0 to n - 1 do - (arr : _[,]).[i,j] <- f i j - - let inline assignConstArray2D m n x arr = - for i = 0 to m - 1 do - for j = 0 to n - 1 do - (arr : _[,]).[i,j] <- x - - let inline assignDenseMatrixGU f (a:DenseMatrix<_>) = - assignArray2D a.NumRows a.NumCols f a.Values - - let inline assignArray m f (arr : _[]) = - for i = 0 to m - 1 do - arr.[i] <- f i - - let inline assignConstArray m x (arr : _[]) = - for i = 0 to m - 1 do - arr.[i] <- x - - let inline assignVecGU f (a:Vector<_>) = - assignArray a.NumRows f a.Values - - let inline assignRowVecGU f (a:RowVector<_>) = - assignArray a.NumCols f a.Values - - let createConstDenseMatrixGU ops m n x = - let arr = createArray2D m n - assignConstArray2D m n x arr; - DenseMatrix(ops,arr) - - let createConstRowVecGU ops m x = - let arr = createArray m - assignConstArray m x arr; - mkRowVecGU ops arr - - let createConstVecGU ops m x = - let arr = createArray m - assignConstArray m x arr; - mkVecGU ops arr - - - let inline createDenseMatrixGU ops m n f = (* inline eliminates unknown f call *) - let arr = createArray2D m n - assignArray2D m n f arr; - DenseMatrix(ops,arr) - - let createRowVecGU ops m f = - let arr = createArray m - assignArray m f arr; - mkRowVecGU ops arr - - let inline createVecGU ops m f = (* inline eliminates unknown f call *) - let arr = createArray m - assignArray m f arr; - mkVecGU ops arr - - /// Create a matrix from a sparse sequence - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - let initSparseMatrixGU maxi maxj ops s = - - (* nb. could use sorted dictionary but that is in System.dll *) - let tab = Array.create maxi null - let count = ref 0 - for (i,j,v) in s do - if i < 0 || i >= maxi || j <0 || j >= maxj then failwith "initial value out of range"; - count := !count + 1; - let tab2 = - match tab.[i] with - | null -> - let tab2 = new Dictionary<_,_>(3) - tab.[i] <- tab2; - tab2 - | tab2 -> tab2 - tab2.[j] <- v - // optimize this line.... - let offsA = - let rowsAcc = Array.zeroCreate (maxi + 1) - let mutable acc = 0 - for i = 0 to maxi-1 do - rowsAcc.[i] <- acc; - acc <- match tab.[i] with - | null -> acc - | tab2 -> acc+tab2.Count - rowsAcc.[maxi] <- acc; - rowsAcc - - let colsA,valsA = - let colsAcc = new ResizeArray<_>(!count) - let valsAcc = new ResizeArray<_>(!count) - for i = 0 to maxi-1 do - match tab.[i] with - | null -> () - | tab2 -> tab2 |> Seq.toArray |> Array.sortBy (fun kvp -> kvp.Key) |> Array.iter (fun kvp -> colsAcc.Add(kvp.Key); valsAcc.Add(kvp.Value)); - colsAcc.ToArray(), valsAcc.ToArray() - - SparseMatrix(opsData=ops, sparseValues=valsA, sparseRowOffsets=offsA, ncols=maxj, columnValues=colsA) - - let zeroizeDenseMatrixGUA arr m n : DenseMatrix<'T> = - let opsData = opsdata<'T> - let ops = opsOfOpsData opsData - let zero = ops.Zero - assignArray2D m n (fun _ _ -> zero) arr; - DenseMatrix(opsData,arr) - - let zeroizeArray opsData arr m = - let ops = opsOfOpsData opsData - let zero = ops.Zero - assignArray m (fun _ -> zero) arr - - let zeroizeVecGUA arr m : Vector<'T> = - let opsData = opsdata<'T> - zeroizeArray opsData arr m; - mkVecGU opsData arr - - let zeroizeRowVecGUA arr m : RowVector<'T> = - let opsData = opsdata<'T> - zeroizeArray opsData arr m; - mkRowVecGU opsData arr - - let listDenseMatrixGU ops xss = - let m = List.length xss - match xss with - | [] -> invalidArg "xss" "unexpected empty list" - | h :: t -> - let n = List.length h - if not (List.forall (fun xs -> List.length xs=n) t) then invalidArg "xss" "the lists are not all of the same length"; - let values = Array2D.zeroCreate m n - List.iteri (fun i rw -> List.iteri (fun j x -> values.[i,j] <- x) rw) xss; - DenseMatrix(ops,values) - - let colListDenseMatrixGU ops xss = - let m = List.length xss - match xss with - | [] -> invalidArg "xss" "unexpected empty list" - | h :: t -> - let n = List.length h - if not (List.forall (fun xs -> List.length xs=n) t) then invalidArg "xss" "the lists are not all of the same length"; - let values = Array2D.zeroCreate n m - List.iteri (fun i rw -> List.iteri (fun j x -> values.[j,i] <- x) rw) xss; - DenseMatrix(ops,values) - - let listVecGU ops xs = mkVecGU ops (Array.ofList xs) - let listRowVecGU ops xs = mkRowVecGU ops (Array.ofList xs) - - let seqDenseMatrixGU ops xss = // TM - //listDenseMatrixGU ops (xss |> Seq.toList |> List.map Seq.toList) - let m = Seq.length xss - if m < 1 then invalidArg "xss" "unexpected empty seq" - let n = xss |> Seq.head |> Seq.length - if not (Seq.forall (fun xs -> Seq.length xs=n) xss) then invalidArg "xss" "the sequences are not all of the same length"; - let values = Array2D.zeroCreate m n - Seq.iteri (fun i rw -> Seq.iteri (fun j x -> values.[i,j] <- x) rw) xss; - DenseMatrix(ops,values) - - let colSeqDenseMatrixGU ops xss = // TM - //listDenseMatrixGU ops (xss |> Seq.toList |> List.map Seq.toList) - let m = Seq.length xss - if m < 1 then invalidArg "xss" "unexpected empty seq" - let n = xss |> Seq.head |> Seq.length - if not (Seq.forall (fun xs -> Seq.length xs=n) xss) then invalidArg "xss" "the sequences are not all of the same length"; - let values = Array2D.zeroCreate n m - Seq.iteri (fun i rw -> Seq.iteri (fun j x -> values.[j,i] <- x) rw) xss; - DenseMatrix(ops,values) - - let seqVecGU ops xss = mkVecGU ops (Array.ofSeq xss) - let seqRowVecGU ops xss = mkRowVecGU ops (Array.ofSeq xss) - - let arrayDenseMatrixGU ops xss = // TM - let m = Array.length xss - if m < 1 then invalidArg "xss" "unexpected empty array" - let n = xss.[0] |> Array.length - if not (Array.forall (fun xs -> Array.length xs=n) xss) then invalidArg "xss" "the arrays are not all of the same length"; - let values = Array2D.zeroCreate m n - Array.iteri (fun i rw -> Array.iteri (fun j x -> values.[i,j] <- x) rw) xss; - DenseMatrix(ops,values) - - let colArrayDenseMatrixGU ops xss = // TM - let m = Array.length xss - if m < 1 then invalidArg "xss" "unexpected empty array" - let n = xss.[0] |> Array.length - if not (Array.forall (fun xs -> Array.length xs=n) xss) then invalidArg "xss" "the arrays are not all of the same length"; - let values = Array2D.zeroCreate n m - Array.iteri (fun i rw -> Array.iteri (fun j x -> values.[j,i] <- x) rw) xss; - DenseMatrix(ops,values) - - let inline binaryOpDenseMatrixGU f (a:DenseMatrix<_>) (b:DenseMatrix<_>) = (* pointwise binary operator *) - let nA = a.NumCols - let mA = a.NumRows - let nB = b.NumCols - let mB = b.NumRows - if nA<>nB || mA<>mB then invalidArg "a" "the two matrices do not have compatible dimensions"; - let arrA = a.Values - let arrB = b.Values - createDenseMatrixGU a.OpsData mA nA (fun i j -> f (getArray2D arrA i j) (getArray2D arrB i j)) - - - let nonZeroEntriesSparseMatrixGU (a:SparseMatrix<_>) = - // This is heavily used, and this version is much faster than - // the sequence operators. - let entries = new ResizeArray<_>(a.SparseColumnValues.Length) - let imax = a.NumRows - let ops = a.ElementOps - let zero = ops.Zero - for i in 0 .. imax - 1 do - let kmin = a.MinIndexForRow i - let kmax = a.MaxIndexForRow i - for k in kmin .. kmax - 1 do - let j = a.SparseColumnValues.[k] - let v = a.SparseValues.[k] - if not (ops.Equals(v,zero)) then - entries.Add((i,j,v)) - (entries :> seq<_>) - - let nonzeroEntriesDenseMatrixGU (a:DenseMatrix<_>) = - let imax = a.NumRows - let jmax = a.NumCols - let ops = a.ElementOps - let zero = ops.Zero - seq { for i in 0 .. imax - 1 do - for j in 0 .. jmax - 1 do - let v = a.[i,j] - if not (ops.Equals(v, zero)) then - yield (i,j,v) } - - - // pointwise operation on two sparse matrices. f must be zero-zero-preserving, i.e. (f 0 0 = 0) - let binaryOpSparseMatrixGU f (a:SparseMatrix<_>) (b:SparseMatrix<_>) = - let ops = a.ElementOps - let zero = ops.Zero - let imax1 = a.NumRows - let imax2 = b.NumRows - let jmax1 = a.NumCols - let jmax2 = b.NumCols - if imax1 <> imax2 || jmax1 <> jmax2 then invalidArg "b" "the two matrices do not have compatible dimensions"; - let imin = 0 - let imax = imax1 - let jmax = jmax1 - let rowsR = Array.zeroCreate (imax+1) - let colsR = new ResizeArray<_>(max a.SparseColumnValues.Length b.SparseColumnValues.Length) - let valsR = new ResizeArray<_>(max a.SparseValues.Length b.SparseValues.Length) - let rec loopRows i = - rowsR.[i] <- valsR.Count; - if i >= imax1 then () else - let kmin1 = a.MinIndexForRow i - let kmax1 = a.MaxIndexForRow i - let kmin2 = b.MinIndexForRow i - let kmax2 = b.MaxIndexForRow i - let rec loopRow k1 k2 = - if k1 >= kmax1 && k2 >= kmax2 then () else - let j1 = if k1 >= kmax1 then jmax else a.SparseColumnValues.[k1] - let j2 = if k2 >= kmax2 then jmax else b.SparseColumnValues.[k2] - let v1 = if j1 <= j2 then a.SparseValues.[k1] else zero - let v2 = if j2 <= j1 then b.SparseValues.[k2] else zero - let jR = min j1 j2 - let vR = f v1 v2 - (* if vR <> zero then *) - colsR.Add(jR); - valsR.Add(vR); - loopRow (if j1 <= j2 then k1+1 else k1) (if j2 <= j1 then k2+1 else k2) - loopRow kmin1 kmin2; - loopRows (i+1) - loopRows imin; - SparseMatrix(opsData= a.OpsData, - sparseRowOffsets=rowsR, - ncols= a.NumCols, - columnValues=colsR.ToArray(), - sparseValues=valsR.ToArray()) - - let inline binaryOpRowVecGU f (a:RowVector<_>) (b:RowVector<_>) = (* pointwise binary operator *) - let mA = a.NumCols - let mB = b.NumCols - if mA<>mB then invalidArg "b" "the two vectors do not have compatible dimensions" - createRowVecGU a.OpsData mA (fun i -> f a.[i] b.[i]) - - let inline binaryOpVecGU f (a:Vector<_>) (b:Vector<_>) = (* pointwise binary operator *) - let mA = a.NumRows - let mB = b.NumRows - if mA<>mB then invalidArg "b" "the two vectors do not have compatible dimensions" - createVecGU a.OpsData mA (fun i -> f a.[i] b.[i]) - - let inline unaryOpDenseMatrixGU f (a:DenseMatrix<_>) = - let nA = a.NumCols - let mA = a.NumRows - let arrA = a.Values - createDenseMatrixGU a.OpsData mA nA (fun i j -> f (getArray2D arrA i j)) - - let inline unaryOpRowVecGU f (a:RowVector<_>) = - let mA = a.NumCols - let arrA = a.Values - createRowVecGU a.OpsData mA (fun j -> f arrA.[j]) - - let inline unaryOpVectorGU f (a:Vector<_>) = - let mA = a.NumRows - let arrA = a.Values - createVecGU a.OpsData mA (fun i -> f arrA.[i]) - - let unaryOpSparseGU f (a:SparseMatrix<_>) = (* pointwise zero-zero-preserving binary operator (f 0 = 0) *) - SparseMatrix(opsData=a.OpsData, - sparseRowOffsets=Array.copy a.SparseRowOffsets, - columnValues=Array.copy a.SparseColumnValues, - sparseValues=Array.map f a.SparseValues, - ncols=a.NumCols) - - // Strictly speaking, sparse arrays are non mutable so no copy is ever needed. But implementing it *) - // anyway in case we move to mutability *) - let copySparseGU (a:SparseMatrix<_>) = - SparseMatrix(opsData=a.OpsData, - sparseRowOffsets=Array.copy a.SparseRowOffsets, - columnValues=Array.copy a.SparseColumnValues, - sparseValues=Array.copy a.SparseValues, - ncols=a.NumCols) - - let addDenseMatrixGU (a:DenseMatrix<_>) b = let ops = a.ElementOps in binaryOpDenseMatrixGU (fun x y -> ops.Add(x, y)) a b - let addSparseMatrixGU (a:SparseMatrix<_>) b = let ops = a.ElementOps in binaryOpSparseMatrixGU (fun x y -> ops.Add(x, y)) a b - let addRowVecGU (a:RowVector<_>) b = let ops = a.ElementOps in binaryOpRowVecGU (fun x y -> ops.Add(x, y)) a b - let addVecGU (a:Vector<_>) b = let ops = a.ElementOps in binaryOpVecGU (fun x y -> ops.Add(x, y)) a b - - let subDenseMatrixGU (a:DenseMatrix<_>) b = let ops = a.ElementOps in binaryOpDenseMatrixGU (fun x y -> ops.Subtract(x, y)) a b - let subSparseMatrixGU (a:SparseMatrix<_>) b = let ops = a.ElementOps in binaryOpSparseMatrixGU (fun x y -> ops.Subtract(x, y)) a b - let subRowVecGU (a:RowVector<_>) b = let ops = a.ElementOps in binaryOpRowVecGU (fun x y -> ops.Subtract(x, y)) a b - let subVecGU (a:Vector<_>) b = let ops = a.ElementOps in binaryOpVecGU (fun x y -> ops.Subtract(x, y)) a b - - ///Point-wise multiplication - let cptMulDenseMatrixGU (a:DenseMatrix<_>) b = let ops = a.ElementOps in binaryOpDenseMatrixGU (fun x y -> ops.Multiply(x, y)) a b - let cptMulSparseMatrixGU (a:SparseMatrix<_>) b = let ops = a.ElementOps in binaryOpSparseMatrixGU (fun x y -> ops.Multiply(x, y)) a b - let cptMulRowVecGU (a:RowVector<_>) b = let ops = a.ElementOps in binaryOpRowVecGU (fun x y -> ops.Multiply(x, y)) a b - let cptMulVecGU (a:Vector<_>) b = let ops = a.ElementOps in binaryOpVecGU (fun x y -> ops.Multiply(x, y)) a b - - let cptMaxDenseMatrixGU (a:DenseMatrix<_>) b = binaryOpDenseMatrixGU max a b - let cptMinDenseMatrixGU (a:DenseMatrix<_>) b = binaryOpDenseMatrixGU min a b - let cptMaxSparseMatrixGU (a:SparseMatrix<_>) b = binaryOpSparseMatrixGU max a b - let cptMinSparseMatrixGU (a:SparseMatrix<_>) b = binaryOpSparseMatrixGU min a b - - let cptMaxVecGU (a:Vector<_>) b = binaryOpVecGU max a b - let cptMinVecGU (a:Vector<_>) b = binaryOpVecGU min a b - - let add (ops : INumeric<'T>) x y = ops.Add(x,y) - let sub (ops : INumeric<'T>) x y = ops.Subtract(x,y) - let mul (ops : INumeric<'T>) x y = ops.Multiply(x,y) - - let inline foldR f z (a,b) = - let mutable res = z in - for i = a to b do - res <- f res i - res - - let inline sumfR f (a,b) = - let mutable res = 0.0 - for i = a to b do - res <- res + f i - res - - - let inline sumRGU (ops : INumeric<_>) f r = - let zero = ops.Zero - r |> foldR (fun z k -> add ops z (f k)) zero - - let genericMulDenseMatrix (a:DenseMatrix<_>) (b:DenseMatrix<_>) = - let nA = a.NumCols - let mA = a.NumRows - let nB = b.NumCols - let mB = b.NumRows - if nA<>mB then invalidArg "b" "the two matrices do not have compatible dimensions" - let ops = a.ElementOps - let arrA = a.Values - let arrB = b.Values - createDenseMatrixGU a.OpsData mA nB - (fun i j -> (0,nA - 1) |> sumRGU ops (fun k -> mul ops (getArray2D arrA i k) (getArray2D arrB k j))) - - let debug = false - - let NormalizeOrdering (M:SparseMatrix<_>) = - for i = 0 to M.NumRows-1 do - let index = M.SparseRowOffsets.[i] - let count = M.SparseRowOffsets.[i+1] - index - if count > 1 then - System.Array.Sort(M.SparseColumnValues, M.SparseValues, index, count) - - // Performs an inplace map with function x => X, skipping zero values - let NormalizeZeros (M:SparseMatrix<_>) = - let mutable nonZero = 0 - for row = 0 to M.NumRows - 1 do - let startIndex = M.SparseRowOffsets.[row] - let endIndex = M.SparseRowOffsets.[row + 1] - M.SparseRowOffsets.[row] <- nonZero - for j = startIndex to endIndex - 1 do - let item = M.SparseValues.[j] - if not(M.ElementOps.Equals(item, M.ElementOps.Zero)) then - M.SparseValues.[nonZero] <- item - M.SparseColumnValues.[nonZero] <- M.SparseColumnValues.[j] - nonZero <- nonZero + 1 - Array.truncate nonZero M.SparseColumnValues |> ignore - Array.truncate nonZero M.SparseValues |> ignore - M.SparseRowOffsets.[M.NumRows] <- nonZero - - let Normalize (M:SparseMatrix<_>) = - NormalizeOrdering M - NormalizeZeros M - - // Sparse matrix multiplication algorithm. inline to get specialization at the 'double' type - let inline genericMulSparse zero add mul (a:SparseMatrix<_>) (b:SparseMatrix<_>) = - let ax = a.SparseValues - let ap = a.SparseRowOffsets - let ai = a.SparseColumnValues - - let bx = b.SparseValues - let bp = b.SparseRowOffsets - let bi = b.SparseColumnValues - - let rows = a.NumRows - let cols = b.NumCols - - let cp = Array.zeroCreate (rows+1) - - let marker = Array.create cols -1 - - let mutable count = 0 - for i = 0 to rows - 1 do - for j= ap.[i] to ap.[i + 1]-1 do - // Row number to be added - let a = ai.[j] - for k = bp.[a] to bp.[a + 1] - 1 do - let b = bi.[k] - if not (marker.[b] = i) then - marker.[b] <- i - count <- count + 1 - cp.[i + 1] <- count - - let ci = Array.zeroCreate count - let cx = Array.create count zero - - // Reset marker array - for ib= 0 to cols-1 do - marker.[ib] <- -1 - // Reset count - count <- 0 - - for i = 0 to rows - 1 do - let rowStart = cp.[i] - for j = ap.[i] to ap.[i + 1] - 1 do - let a = ai.[j] - let aEntry = ax.[j] - for k = bp.[a] to bp.[a + 1] - 1 do - let b = bi.[k] - let bEntry = bx.[k] - if marker.[b] < rowStart then - marker.[b] <- count - ci.[marker.[b]] <- b - cx.[marker.[b]] <- mul aEntry bEntry; - count <- count + 1 - else - let prod = mul aEntry bEntry - cx.[marker.[b]] <- add cx.[marker.[b]] prod - - let matrix = SparseMatrix(opsData = a.OpsData, - sparseRowOffsets= cp, - ncols = cols, - columnValues=ci, - sparseValues=cx) - Normalize matrix - matrix - - let mulSparseMatrixGU (a: SparseMatrix<_>) b = - let ops = a.ElementOps - let zero = ops.Zero - genericMulSparse zero (add ops) (mul ops) a b - - - let mulRowVecVecGU (a:RowVector<_>) (b:Vector<_>) = - let mA = a.NumCols - let nB = b.NumRows - if mA<>nB then invalidArg "b" "the two vectors do not have compatible dimensions" - let ops = a.ElementOps - (0,mA - 1) |> sumRGU ops (fun k -> mul ops a.[k] b.[k]) - - let rowvecDenseMatrixGU (x:RowVector<_>) = createDenseMatrixGU x.OpsData 1 x.NumCols (fun _ j -> x.[j]) - let vectorDenseMatrixGU (x:Vector<_>) = createDenseMatrixGU x.OpsData x.NumRows 1 (fun i _ -> x.[i]) - - let mulVecRowVecGU a b = genericMulDenseMatrix (vectorDenseMatrixGU a) (rowvecDenseMatrixGU b) - - let mulRowVecDenseMatrixGU (a:RowVector<_>) (b:DenseMatrix<_>) = - let nA = a.NumCols - let nB = b.NumCols - let mB = b.NumRows - if nA<>mB then invalidArg "b" "the two vectors do not have compatible dimensions" - let ops = a.ElementOps - let arrA = a.Values - let arrB = b.Values - createRowVecGU a.OpsData nB - (fun j -> (0,nA - 1) |> sumRGU ops (fun k -> mul ops arrA.[k] (getArray2D arrB k j))) - - let mulDenseMatrixVecGU (a:DenseMatrix<_>) (b:Vector<_>) = - let nA = a.NumCols - let mA = a.NumRows - let mB = b.NumRows - if nA<>mB then invalidArg "b" "the two inputs do not have compatible dimensions" - let ops = b.ElementOps - let arrA = a.Values - let arrB = b.Values - createVecGU b.OpsData mA - (fun i -> (0,nA - 1) |> sumRGU ops (fun k -> mul ops (getArray2D arrA i k) arrB.[k])) - - let mulSparseVecGU (a:SparseMatrix<_>) (b:Vector<_>) = - let nA = a.NumCols - let mA = a.NumRows - let mB = b.NumRows - if nA<>mB then invalidArg "b" "the two inputs do not have compatible dimensions" - let ops = b.ElementOps - let zero = ops.Zero - createVecGU b.OpsData mA (fun i -> - let mutable acc = zero - for k = a.MinIndexForRow i to a.MaxIndexForRow i - 1 do - let j = a.SparseColumnValues.[k] - let v = a.SparseValues.[k] - acc <- add ops acc (mul ops v b.[j]); - acc) - - let mulRVSparseMatrixGU (a:RowVector<_>) (b:SparseMatrix<_>) = - let nA = b.NumCols - let mA = b.NumRows - let mB = a.NumCols - if mA<>mB then invalidArg "b" "the two inputs do not have compatible dimensions" - let ops = b.ElementOps - let arr = createArray nA - zeroizeArray a.OpsData arr nA; - for i = 0 to mA - 1 do - for k = b.MinIndexForRow i to b.MaxIndexForRow i - 1 do - let j = b.SparseColumnValues.[k] - let v = b.SparseValues.[k] - arr.[j] <- add ops arr.[j] (mul ops a.[i] v) - mkRowVecGU a.OpsData arr - - - let scaleDenseMatrixGU k (a:DenseMatrix<_>) = let ops = a.ElementOps in unaryOpDenseMatrixGU (fun x -> ops.Multiply(k,x)) a - let scaleRowVecGU k (a:RowVector<_>) = let ops = a.ElementOps in unaryOpRowVecGU (fun x -> ops.Multiply(k,x)) a - let scaleVecGU k (a:Vector<_>) = let ops = a.ElementOps in unaryOpVectorGU (fun x -> ops.Multiply(k,x)) a - let scaleSparseMatrixGU k (a:SparseMatrix<_>) = let ops = a.ElementOps in unaryOpSparseGU (fun x -> ops.Multiply(k,x)) a - // add + - let addScalarDenseMatrixGU k (a:DenseMatrix<_>) = let ops = a.ElementOps in unaryOpDenseMatrixGU (fun x -> ops.Add(k,x)) a - let addScalarRowVecGU k (a:RowVector<_>) = let ops = a.ElementOps in unaryOpRowVecGU (fun x -> ops.Add(k,x)) a - let addScalarVecGU k (a:Vector<_>) = let ops = a.ElementOps in unaryOpVectorGU (fun x -> ops.Add(k,x)) a - let addScalarSparseMatrixGU k (a:SparseMatrix<_>) = let ops = a.ElementOps in unaryOpSparseGU (fun x -> ops.Add(k,x)) a - // sub - - let subScalarDenseMatrixGU k (a:DenseMatrix<_>) = let ops = a.ElementOps in unaryOpDenseMatrixGU (fun x -> ops.Subtract(k,x)) a - let subScalarRowVecGU k (a:RowVector<_>) = let ops = a.ElementOps in unaryOpRowVecGU (fun x -> ops.Subtract(k,x)) a - let subScalarVecGU k (a:Vector<_>) = let ops = a.ElementOps in unaryOpVectorGU (fun x -> ops.Subtract(k,x)) a - let subScalarSparseMatrixGU k (a:SparseMatrix<_>) = let ops = a.ElementOps in unaryOpSparseGU (fun x -> ops.Subtract(k,x)) a - - let negDenseMatrixGU (a:DenseMatrix<_>) = let ops = a.ElementOps in unaryOpDenseMatrixGU (fun x -> ops.Negate(x)) a - let negRowVecGU (a:RowVector<_>) = let ops = a.ElementOps in unaryOpRowVecGU (fun x -> ops.Negate(x)) a - let negVecGU (a:Vector<_>) = let ops = a.ElementOps in unaryOpVectorGU (fun x -> ops.Negate(x)) a - let negSparseMatrixGU (a:SparseMatrix<_>) = let ops = a.ElementOps in unaryOpSparseGU (fun x -> ops.Negate(x)) a - - let mapDenseMatrixGU f (a : DenseMatrix<'T>) : DenseMatrix<'T> = - let arrA = a.Values - createDenseMatrixGU a.OpsData a.NumRows a.NumCols (fun i j -> f (getArray2D arrA i j)) - - let mapVecGU f (a:Vector<_>) = - let mA= a.NumRows - createVecGU a.OpsData mA (fun i -> f a.[i]) - - let map2VecGU f (a:Vector<'a>) (b:Vector<'a>) : Vector<'a> = - let mA= if a.NumRows = b.NumRows then a.NumRows else raise (ArgumentException("Vectors of different length.")) - createVecGU a.OpsData mA (fun i -> f a.[i] b.[i]) - - let map3VecGU f (a:Vector<'a>) (b:Vector<'a>) (c:Vector<'a>) : Vector<'a> = - let mA= if a.NumRows = b.NumRows && a.NumRows = c.NumRows then a.NumRows else raise (ArgumentException("Vectors of different length.")) - createVecGU a.OpsData mA (fun i -> f a.[i] b.[i] c.[i]) - - let zipVecGU (a:Vector<'a>) (b:Vector<'b>) : Vector<'a*'b> = - let mA= if a.NumRows = b.NumRows then a.NumRows else raise (ArgumentException("Vectors of different length.")) - createVecGU None mA (fun i -> a.[i],b.[i]) - - let unzipVecGU (a : Vector<'a*'b>) : Vector<'a> * Vector<'b> = - let mA = a.NumRows - createVecGU None mA (fun i -> fst a.[i]),createVecGU None mA (fun i -> snd a.[i]) - - let copyDenseMatrixGU (a : DenseMatrix<'T>) : DenseMatrix<'T> = - let arrA = a.Values - createDenseMatrixGU a.OpsData a.NumRows a.NumCols (fun i j -> getArray2D arrA i j) - - let copyVecGU (a:Vector<_>) = - createVecGU a.OpsData a.NumRows (fun i -> a.[i]) - - let copyRowVecGU (a:RowVector<_>) = - createRowVecGU a.OpsData a.NumCols (fun i -> a.[i]) - - let toDenseSparseMatrixGU (a:SparseMatrix<_>) = - createDenseMatrixGU a.OpsData a.NumRows a.NumCols (fun i j -> a.[i,j]) - - let mapiDenseMatrixGU f (a: DenseMatrix<'T>) : DenseMatrix<'T> = - let arrA = a.Values - createDenseMatrixGU a.OpsData a.NumRows a.NumCols (fun i j -> f i j (getArray2D arrA i j)) - - let mapRowVecGU f (a:RowVector<_>) = - createRowVecGU a.OpsData a.NumCols (fun i -> f a.[i]) - - let mapiRowVecGU f (a:RowVector<_>) = - createRowVecGU a.OpsData a.NumCols (fun i -> f i a.[i]) - - let mapiVecGU f (a:Vector<_>) = - createVecGU a.OpsData a.NumRows (fun i -> f i a.[i]) - - let permuteVecGU (p:permutation) (a:Vector<_>) = - createVecGU a.OpsData a.NumRows (fun i -> a.[p i]) - - let permuteRowVecGU (p:permutation) (a:RowVector<_>) = - createRowVecGU a.OpsData a.NumCols (fun i -> a.[p i]) - - let inline inplace_mapDenseMatrixGU f (a:DenseMatrix<_>) = - let arrA = a.Values - assignDenseMatrixGU (fun i j -> f (getArray2D arrA i j)) a - - let inline inplace_mapRowVecGU f (a:RowVector<_>) = - assignRowVecGU (fun i -> f a.[i]) a - - let inline inplace_mapVecGU f (a:Vector<_>) = - assignVecGU (fun i -> f a.[i]) a - - let inline inplace_mapiDenseMatrixGU f (a:DenseMatrix<_>) = - let arrA = a.Values - assignDenseMatrixGU (fun i j -> f i j (getArray2D arrA i j)) a - - let inline inplace_mapiRowVecGU f (a:RowVector<_>) = - assignRowVecGU (fun i -> f i a.[i]) a - - let inline inplace_mapiVecGU f (a:Vector<_>) = - assignVecGU (fun i -> f i a.[i]) a - - let inline foldDenseMatrixGU f z (a:DenseMatrix<_>) = - let nA = a.NumCols - let mA = a.NumRows - let arrA = a.Values - let mutable acc = z - for i = 0 to mA-1 do - for j = 0 to nA-1 do - acc <- f acc (getArray2D arrA i j) - acc - - let inline foldVecGU f z (a:Vector<_>) = - let mutable acc = z - for i = 0 to a.NumRows-1 do acc <- f acc a.[i] - acc - - let inline foldiDenseMatrixGU f z (a:DenseMatrix<_>) = - let nA = a.NumCols - let mA = a.NumRows - let arrA = a.Values - let mutable acc = z - for i = 0 to mA-1 do - for j = 0 to nA-1 do - acc <- f i j acc (getArray2D arrA i j) - acc - - let inline foldiVecGU f z (a:Vector<_>) = - let mA = a.NumRows - let mutable acc = z - for i = 0 to mA-1 do acc <- f i acc a.[i] - acc - - let rec forallR f (n,m) = (n > m) || (f n && forallR f (n+1,m)) - let rec existsR f (n,m) = (n <= m) && (f n || existsR f (n+1,m)) - - let foralliDenseMatrixGU pred (a:DenseMatrix<_>) = - let nA = a.NumCols - let mA = a.NumRows - let arrA = a.Values - (0,mA-1) |> forallR (fun i -> - (0,nA-1) |> forallR (fun j -> - pred i j (getArray2D arrA i j))) - - let foralliVecGU pred (a:Vector<_>) = - let mA = a.NumRows - (0,mA-1) |> forallR (fun i -> - pred i a.[i]) - - let existsiDenseMatrixGU pred (a:DenseMatrix<_>) = - let nA = a.NumCols - let mA = a.NumRows - let arrA = a.Values - (0,mA-1) |> existsR (fun i -> - (0,nA-1) |> existsR (fun j -> - pred i j (getArray2D arrA i j))) - - let existsiVecGU pred (a:Vector<_>) = - let mA = a.NumRows - (0,mA-1) |> existsR (fun i -> - pred i a.[i]) - - let sumDenseMatrixGU (a:DenseMatrix<_>) = - let ops = a.ElementOps - foldDenseMatrixGU (fun acc aij -> add ops acc aij) ops.Zero a - - let sumSparseMatrixGU (a:SparseMatrix<_>) = - let ops = a.ElementOps - a |> nonZeroEntriesSparseMatrixGU |> Seq.fold (fun acc (_,_,aij) -> add ops acc aij) ops.Zero - - let sumVecGU (a:Vector<_>) = - let ops = a.ElementOps - foldVecGU (fun acc ai -> add ops acc ai) ops.Zero a - - let prodDenseMatrixGU (a:DenseMatrix<_>) = - let ops = a.ElementOps - foldDenseMatrixGU (fun acc aij -> mul ops acc aij) ops.One a - - let prodSparseMatrixGU (a:SparseMatrix<_>) = a |> toDenseSparseMatrixGU |> prodDenseMatrixGU - - let inline fold2DenseMatrixGU f z (a:DenseMatrix<_>) (b:DenseMatrix<_>) = - let nA = a.NumCols - let mA = a.NumRows - let nB = b.NumCols - let mB = b.NumRows - if nA <> nB || mA <> mB then invalidArg "b" "the two matrices do not have compatible dimensions" - let arrA = a.Values - let arrB = b.Values - let mutable acc = z - for i = 0 to mA-1 do - for j = 0 to nA-1 do - acc <- f acc (getArray2D arrA i j) (getArray2D arrB i j) - acc - - let inline fold2VecGU f z (a:Vector<_>) (b:Vector<_>) = - let mA = a.NumRows - let mB = b.NumRows - if mA <> mB then invalidArg "b" "the two vectors do not have compatible dimensions" - let mutable acc = z - for i = 0 to mA-1 do acc <- f acc a.[i] b.[i] - acc - - let dotDenseMatrixGU (a:DenseMatrix<_>) b = - let ops = a.ElementOps - fold2DenseMatrixGU (fun z va vb -> add ops z (mul ops va vb)) ops.Zero a b - - let dotVecGU (a:Vector<_>) b = - let ops = a.ElementOps - let zero = ops.Zero - fold2VecGU (fun z va vb -> add ops z (mul ops va vb)) zero a b - - let normDenseMatrixGU (a:DenseMatrix<_>) = - let normOps = getNormOps a.ElementOps - foldDenseMatrixGU (fun z aij -> z + ((normOps.Norm aij)**2.0)) 0.0 a |> sqrt - - let normSparseMatrixGU (a:SparseMatrix<_>) = - let normOps = getNormOps a.ElementOps - a |> nonZeroEntriesSparseMatrixGU |> Seq.fold (fun acc (_,_,aij) -> acc + ((normOps.Norm aij)**2.0)) 0.0 |> sqrt - - let inplaceAddDenseMatrixGU (a:DenseMatrix<_>) (b:DenseMatrix<_>) = - let ops = a.ElementOps - let arrB = b.Values - inplace_mapiDenseMatrixGU (fun i j x -> add ops x (getArray2D arrB i j)) a - - let inplaceAddVecGU (a:Vector<_>) (b:Vector<_>) = - let ops = a.ElementOps - inplace_mapiVecGU (fun i x -> add ops x b.[i]) a - - let inplaceAddRowVecGU (a:RowVector<_>) (b:Vector<_>) = - let ops = a.ElementOps - inplace_mapiRowVecGU (fun i x -> add ops x b.[i]) a - - let inplaceSubDenseMatrixGU (a:DenseMatrix<_>) (b:DenseMatrix<_>) = - let ops = a.ElementOps - let arrB = b.Values - inplace_mapiDenseMatrixGU (fun i j x -> sub ops x (getArray2D arrB i j)) a - - let inplaceSubVecGU (a:Vector<_>) (b:Vector<_>) = - let ops = a.ElementOps - inplace_mapiVecGU (fun i x -> sub ops x b.[i]) a - - let inplaceSubRowVecGU (a:RowVector<_>) (b:Vector<_>) = - let ops = a.ElementOps - inplace_mapiRowVecGU (fun i x -> sub ops x b.[i] ) a - - let inplaceCptMulDenseMatrixGU (a:DenseMatrix<_>) (b:DenseMatrix<_>) = - let ops = a.ElementOps - let arrB = b.Values - inplace_mapiDenseMatrixGU (fun i j x -> mul ops x (getArray2D arrB i j)) a - - let inplaceCptMulVecGU (a:Vector<_>) (b:Vector<_>) = - let ops = a.ElementOps - inplace_mapiVecGU (fun i x -> mul ops x b.[i]) a - - let inplaceCptMulRowVecGU (a:RowVector<_>) (b:Vector<_>) = - let ops = a.ElementOps - inplace_mapiRowVecGU (fun i x -> mul ops x b.[i] ) a - - let inplaceScaleDenseMatrixGU x (a:DenseMatrix<_>) = - let ops = a.ElementOps - inplace_mapiDenseMatrixGU (fun _ _ y -> ops.Multiply(x,y)) a - - let inplaceScaleVecGU x (a:Vector<_>) = - let ops = a.ElementOps - inplace_mapiVecGU (fun _ y -> ops.Multiply(x,y)) a - - let inplaceScaleRowVecGU x (a:RowVector<_>) = - let ops = a.ElementOps - inplace_mapiRowVecGU (fun _ y -> ops.Multiply(x,y)) a - - - let wrapList (pre,mid,post,trim) show l = - let post = if trim then "; ..." + post else post - match l with - | [] -> [pre;post] - | [x] -> [pre;show x;post] - | x::xs -> [pre;show x] @ (List.collect (fun x -> [mid;show x]) xs) @ [post] - - let showItem opsData x = - try - let ops = opsOfOpsData opsData - ops.ToString(x,"g10",System.Globalization.CultureInfo.InvariantCulture) - with :? System.NotSupportedException -> (box x).ToString() - - let mapR f (n,m) = if m < n then [] else List.init (m-n+1) (fun i -> f (n+i)) - - let primShowDenseMatrixGU (sepX,sepR) (a : DenseMatrix<'e>) = - let nA = min a.NumCols DenseMaxDisplay - let mA = min a.NumRows DenseMaxDisplay - let ops = a.OpsData - let showLine i = wrapList ("[",";","]", a.NumCols > nA) (showItem ops) ((0,nA-1) |> mapR (fun j -> a.[i,j])) |> Array.ofList |> System.String.Concat - wrapList (string nA + " " + string mA + "matrix [",";"+sepX,"]"+sepR, a.NumRows > mA) showLine [0..mA-1] |> Array.ofList |> System.String.Concat - - let showDenseMatrixGU m = primShowDenseMatrixGU ("\n","\n") m - let debugShowDenseMatrixGU m = primShowDenseMatrixGU ("" ,"" ) m - - let showVecGU s (a : Vector<_>) = - let mA = min a.NumRows VectorMaxDisplay - let ops = a.OpsData - wrapList (s+" [",";","]",a.NumRows > mA) (showItem ops) ((0,mA-1) |> mapR (fun i -> a.[i])) |> Array.ofList |> System.String.Concat - - let showRowVecGU s (a : RowVector<_>) = - let mA = min a.NumCols VectorMaxDisplay - let ops = a.OpsData - wrapList (s+" [",";","]",a.NumCols > mA) (showItem ops) ((0,mA-1) |> mapR (fun i -> a.[i])) |> Array.ofList |> System.String.Concat - - - /// Implementations of operations specific to floating point types - module DoubleImpl = - - module GU = GenericImpl - open Instances - - // Element type OpsData - //type elem = float - let zero = 0.0 - let one = 1.0 - let inline sub (x:float) (y:float) = x - y - let inline add (x:float) (y:float) = x + y - let inline mul (x:float) (y:float) = x * y - let inline neg (x:float) = -x - - // Specialized: these know the relevant set of - // ops without doing a table lookup based on runtime type - let FloatOps = Some (FloatNumerics :> INumeric) - let inline initDenseMatrixDS m n f = GU.createDenseMatrixGU FloatOps m n f - let inline createRowVecDS m f = GU.createRowVecGU FloatOps m f - let inline createVecDS m f = GU.createVecGU FloatOps m f - let inline mkDenseMatrixDS arr = GU.mkDenseMatrixGU FloatOps arr - let inline mkRowVecDS arr = GU.mkRowVecGU FloatOps arr - let inline mkVecDS arr = GU.mkVecGU FloatOps arr - let inline listDenseMatrixDS ll = GU.listDenseMatrixGU FloatOps ll - let inline colListDenseMatrixDS ll = GU.colListDenseMatrixGU FloatOps ll - let inline listRowVecDS l = GU.listRowVecGU FloatOps l - let inline listVecDS l = GU.listVecGU FloatOps l - let inline seqDenseMatrixDS ll = GU.seqDenseMatrixGU FloatOps ll - let inline colSeqDenseMatrixDS ll = GU.colSeqDenseMatrixGU FloatOps ll - let inline arrayDenseMatrixDS ll = GU.arrayDenseMatrixGU FloatOps ll - let inline colArrayDenseMatrixDS ll = GU.colArrayDenseMatrixGU FloatOps ll - let inline seqRowVecDS l = GU.seqRowVecGU FloatOps l - let inline seqVecDS l = GU.seqVecGU FloatOps l - - let constDenseMatrixDS m n x = GU.createDenseMatrixGU FloatOps m n (fun _ _ -> x) - let constRowVecDS m x = GU.createRowVecGU FloatOps m (fun _ -> x) - let constVecDS m x = GU.createVecGU FloatOps m (fun _ -> x) - let scalarDenseMatrixDS x = constDenseMatrixDS 1 1 x - let scalarRowVecDS x = constRowVecDS 1 x - let scalarVecDS x = constVecDS 1 x - - // Beware - when compiled with non-generic code createArray2D creates an array of null values, - // not zero values. Hence the optimized version can only be used when compiling with generics. - let inline zeroDenseMatrixDS m n = - let arr = GU.createArray2D m n - GU.mkDenseMatrixGU FloatOps arr - // Specialized: these inline down to the efficient loops we need - let addDenseMatrixDS a b = GU.binaryOpDenseMatrixGU add a b - let addSparseDS a b = GU.binaryOpSparseMatrixGU add a b - let addRowVecDS a b = GU.binaryOpRowVecGU add a b - let addVecDS a b = GU.binaryOpVecGU add a b - let subDenseMatrixDS a b = GU.binaryOpDenseMatrixGU sub a b - let subSparseDS a b = GU.binaryOpSparseMatrixGU sub a b - let mulSparseDS a b = GU.genericMulSparse zero add mul a b - let subRowVecDS a b = GU.binaryOpRowVecGU sub a b - let subVecDS a b = GU.binaryOpVecGU sub a b - let cptMulDenseMatrixDS a b = GU.binaryOpDenseMatrixGU mul a b - let cptMulSparseDS a b = GU.binaryOpSparseMatrixGU mul a b - let cptMulRowVecDS a b = GU.binaryOpRowVecGU mul a b - let cptMulVecDS a b = GU.binaryOpVecGU mul a b - type smatrix = SparseMatrix - type dmatrix = DenseMatrix - type vector = Vector - type rowvec = RowVector - let cptMaxDenseMatrixDS (a:dmatrix) (b:dmatrix) = GU.binaryOpDenseMatrixGU max a b - let cptMinDenseMatrixDS (a:dmatrix) (b:dmatrix) = GU.binaryOpDenseMatrixGU min a b - let cptMaxSparseDS (a:smatrix) (b:smatrix) = GU.binaryOpSparseMatrixGU max a b - let cptMinSparseDS (a:smatrix) (b:smatrix) = GU.binaryOpSparseMatrixGU min a b - let cptMaxVecDS (a:vector) (b:vector) = GU.binaryOpVecGU max a b - let cptMinVecDS (a:vector) (b:vector) = GU.binaryOpVecGU min a b - - // Don't make any mistake about these ones re. performance. - let mulDenseMatrixDS (a:dmatrix) (b:dmatrix) = - let nA = a.NumCols - let mA = a.NumRows - let nB = b.NumCols - let mB = b.NumRows - if nA<>mB then invalidArg "b" "the two matrices do not have compatible dimensions" - let arr = GU.createArray2D mA nB - let arrA = a.Values - let arrB = b.Values - for i = 0 to mA - 1 do - for j = 0 to nB - 1 do - let mutable r = 0.0 - for k = 0 to mB - 1 do - r <- r + mul (GU.getArray2D arrA i k) (GU.getArray2D arrB k j) - GU.setArray2D arr i j r - mkDenseMatrixDS arr - - let mulRowVecDenseMatrixDS (a:rowvec) (b:dmatrix) = - let nA = a.NumCols - let nB = b.NumCols - let mB = b.NumRows - if nA<>mB then invalidArg "b" "the two inputs do not have compatible dimensions" - let arr = Array.zeroCreate nB - let arrA = a.Values - let arrB = b.Values - for j = 0 to nB - 1 do - let mutable r = 0.0 - for k = 0 to mB - 1 do - r <- r + mul arrA.[k] (GU.getArray2D arrB k j) - arr.[j] <- r - mkRowVecDS arr - - let mulDenseMatrixVecDS (a:dmatrix) (b:vector) = - let nA = a.NumCols - let mA = a.NumRows - let mB = b.NumRows - if nA<>mB then invalidArg "b" "the two inputs do not have compatible dimensions" - let arr = Array.zeroCreate mA - let arrA = a.Values - let arrB = b.Values - for i = 0 to mA - 1 do - let mutable r = 0.0 - for k = 0 to nA - 1 do - r <- r + mul (GU.getArray2D arrA i k) arrB.[k] - arr.[i] <- r - mkVecDS arr - - let mulRowVecVecDS (a:rowvec) (b:vector) = - let nA = a.NumCols - let mB = b.NumRows - if nA<>mB then invalidArg "b" "the two vectors do not have compatible dimensions" - let arrA = a.Values - let arrB = b.Values - let mutable r = 0.0 - for k = 0 to nA - 1 do - r <- r + mul arrA.[k] arrB.[k] - r - - let rowvecDenseMatrixDS (x:rowvec) = initDenseMatrixDS 1 x.NumCols (fun _ j -> x.[j]) - let vectorDenseMatrixDS (x:vector) = initDenseMatrixDS x.NumRows 1 (fun i _ -> x.[i]) - let mulVecRowVecDS a b = mulDenseMatrixDS (vectorDenseMatrixDS a) (rowvecDenseMatrixDS b) - - let scaleDenseMatrixDS k m = GU.unaryOpDenseMatrixGU (fun x -> mul k x) m - let scaleSparseDS k m = GU.unaryOpSparseGU (fun x -> mul k x) m - let scaleRowVecDS k m = GU.unaryOpRowVecGU (fun x -> mul k x) m - let scaleVecDS k m = GU.unaryOpVectorGU (fun x -> mul k x) m - // add + - let addScalarDenseMatrixDS k m = GU.unaryOpDenseMatrixGU (fun x -> add k x) m - let addScalarSparseDS k m = GU.unaryOpSparseGU (fun x -> add k x) m - let addScalarRowVecDS k m = GU.unaryOpRowVecGU (fun x -> add k x) m - let addScalarVecDS k m = GU.unaryOpVectorGU (fun x -> add k x) m - // sub - - let subScalarDenseMatrixDS k m = GU.unaryOpDenseMatrixGU (fun x -> sub k x) m - let subScalarSparseDS k m = GU.unaryOpSparseGU (fun x -> sub k x) m - let subScalarRowVecDS k m = GU.unaryOpRowVecGU (fun x -> sub k x) m - let subScalarVecDS k m = GU.unaryOpVectorGU (fun x -> sub k x) m - - let negDenseMatrixDS m = GU.unaryOpDenseMatrixGU (fun x -> neg x) m - let negSparseDS m = GU.unaryOpSparseGU (fun x -> neg x) m - let negRowVecDS m = GU.unaryOpRowVecGU (fun x -> neg x) m - let negVecDS m = GU.unaryOpVectorGU (fun x -> neg x) m - - let traceDenseMatrixDS (a:dmatrix) = - let nA = a.NumCols - let mA = a.NumRows - if nA<>mA then invalidArg "a" "expected a square matrix"; - let arrA = a.Values - (0,nA-1) |> GU.sumfR (fun i -> GU.getArray2D arrA i i) - - let sumDenseMatrixDS a = GU.foldDenseMatrixGU add zero a - let sumVecDS a = GU.foldVecGU add zero a - let prodDenseMatrixDS a = GU.foldDenseMatrixGU mul one a - let prodVecDS a = GU.foldVecGU mul one a - - let dotDenseMatrixDS a b = GU.fold2DenseMatrixGU (fun z va vb -> add z (mul va vb)) zero a b - let dotVecDS a b = GU.fold2VecGU (fun z va vb -> add z (mul va vb)) zero a b - let sumfDenseMatrixDS f m = GU.foldDenseMatrixGU (fun acc aij -> add acc (f aij)) zero m - let normDenseMatrixDS m = sqrt (sumfDenseMatrixDS (fun x -> x*x) m) - - let inplaceAddDenseMatrixDS a (b:DenseMatrix<_>) = let arrB = b.Values in GU.inplace_mapiDenseMatrixGU (fun i j x -> x + GU.getArray2D arrB i j) a - let inplaceAddVecDS a (b:Vector<_>) = let arrB = b.Values in GU.inplace_mapiVecGU (fun i x -> x + arrB.[i]) a - let inplace_addRowVecDS a (b:RowVector<_>) = let arrB = b.Values in GU.inplace_mapiRowVecGU (fun i x -> x + arrB.[i]) a - let inplaceSubDenseMatrixDS a (b:DenseMatrix<_>) = let arrB = b.Values in GU.inplace_mapiDenseMatrixGU (fun i j x -> x - GU.getArray2D arrB i j) a - let inplaceSubVecDS a (b:Vector<_>) = let arrB = b.Values in GU.inplace_mapiVecGU (fun i x -> x - arrB.[i]) a - let inplace_subRowVecDS a (b:RowVector<_>) = let arrB = b.Values in GU.inplace_mapiRowVecGU (fun i x -> x - arrB.[i]) a - let inplaceCptMulDenseMatrixDS a (b:DenseMatrix<_>) = let arrB = b.Values in GU.inplace_mapiDenseMatrixGU (fun i j x -> x * GU.getArray2D arrB i j) a - let inplaceCptMulVecDS a (b:Vector<_>) = let arrB = b.Values in GU.inplace_mapiVecGU (fun i x -> x * arrB.[i]) a - let inplace_cptMulRowVecDS a (b:RowVector<_>) = let arrB = b.Values in GU.inplace_mapiRowVecGU (fun i x -> x * arrB.[i]) a - let inplaceScaleDenseMatrixDS (a:float) b = GU.inplace_mapiDenseMatrixGU (fun _ _ x -> a * x) b - let inplaceScaleVecDS (a:float) b = GU.inplace_mapiVecGU (fun _ x -> a * x) b - let inplace_scaleRowVecDS (a:float) b = GU.inplace_mapiRowVecGU (fun _ x -> a * x) b - - - - /// Generic operations that, when used on floating point types, use the specialized versions in DoubleImpl - module SpecializedGenericImpl = - -// open Microsoft.FSharp.Math.Instances -// open Microsoft.FSharp.Math.GlobalAssociations - open FSharp.Stats.Instances - open FSharp.Stats.GlobalAssociations - - module GU = GenericImpl - module DS = DoubleImpl - - - type smatrix = SparseMatrix - type dmatrix = DenseMatrix - type vector = Vector - type rowvec = RowVector - let inline dense x = DenseRepr(x) - let inline sparse x = SparseRepr(x) - let inline createMx ops rows columns f = GU.createDenseMatrixGU ops rows columns f |> dense - let inline createVx ops m f = GU.createVecGU ops m f - let inline createRVx ops m f = GU.createRowVecGU ops m f - - let nonZeroEntriesM a = - match a with - | DenseRepr a -> GU.nonzeroEntriesDenseMatrixGU a - | SparseRepr a -> GU.nonZeroEntriesSparseMatrixGU a - - /// Merge two sorted sequences - /// - /// - /// - /// - /// - /// - /// - /// - /// - let mergeSorted cf (s1: seq<'T>) (s2: seq<'b>) = - seq { use e1 = s1.GetEnumerator() - use e2 = s2.GetEnumerator() - let havee1 = ref (e1.MoveNext()) - let havee2 = ref (e2.MoveNext()) - while !havee1 || !havee2 do - if !havee1 && !havee2 then - let v1 = e1.Current - let v2 = e2.Current - let c = cf v1 v2 - if c < 0 then - do havee1 := e1.MoveNext() - yield Some(v1),None - elif c = 0 then - do havee1 := e1.MoveNext() - do havee2 := e2.MoveNext() - yield Some(v1),Some(v2) - else - do havee2 := e2.MoveNext() - yield (None,Some(v2)) - elif !havee1 then - let v1 = e1.Current - do havee1 := e1.MoveNext() - yield (Some(v1),None) - else - let v2 = e2.Current - do havee2 := e2.MoveNext() - yield (None,Some(v2)) } - - /// Non-zero entries from two sequences - let mergedNonZeroEntriesM (a:Matrix<_>) (b:Matrix<_>) = - let ops = a.ElementOps - let zero = ops.Zero - mergeSorted (fun (i1,j1,_) (i2,j2,_) -> let c = compare i1 i2 in if c <> 0 then c else compare j1 j2) (nonZeroEntriesM a) (nonZeroEntriesM b) - |> Seq.map (function | Some(i,j,v1),Some(_,_,v2) -> (v1,v2) - | Some(i,j,v1),None -> (v1,zero) - | None, Some(i,j,v2) -> (zero,v2) - | None, None -> failwith "unreachable") - - - - // Creation - let listM xss : Matrix<'T> = GU.listDenseMatrixGU opsdata<'T> xss |> dense - let listV xss : Vector<'T> = GU.listVecGU opsdata<'T> xss - let listRV xss : RowVector<'T> = GU.listRowVecGU opsdata<'T> xss - - let arrayM xss : Matrix<'T> = GU.mkDenseMatrixGU opsdata<'T> (Array2D.copy xss) |> dense - let arraySM xss : Matrix<'T> = GU.mkSparseMatrixGU opsdata<'T> (Array2D.copy xss) |> sparse - let arrayV xss : Vector<'T> = GU.mkVecGU opsdata<'T> (Array.copy xss) - let arrayRV xss : RowVector<'T> = GU.mkRowVecGU opsdata<'T> (Array.copy xss) - - let rowVecM xss: Matrix<'T> = GU.rowvecDenseMatrixGU xss |> dense - let vecM xss: Matrix<'T> = GU.vectorDenseMatrixGU xss |> dense - - let seqM xss : Matrix<'T> = GU.seqDenseMatrixGU opsdata<'T> xss |> dense - let seqCM xss : Matrix<'T> = GU.colSeqDenseMatrixGU opsdata<'T> xss |> dense - let seqV xss : Vector<'T> = GU.seqVecGU opsdata<'T> xss - let seqRV xss : RowVector<'T> = GU.seqRowVecGU opsdata<'T> xss - - let initM m n f : Matrix<'T> = GU.createDenseMatrixGU opsdata<'T> m n f |> dense - let initRV m f : RowVector<'T> = GU.createRowVecGU opsdata<'T> m f - let initV m f : Vector<'T> = GU.createVecGU opsdata<'T> m f - - let constM m n x : Matrix<'T> = GU.createConstDenseMatrixGU opsdata<'T> m n x |> dense - let constRV m x : RowVector<'T> = GU.createConstRowVecGU opsdata<'T> m x - let constV m x : Vector<'T> = GU.createConstVecGU opsdata<'T> m x - - let inline inplaceAssignM f a = - match a with - | SparseRepr _ -> sparseNotMutable() - | DenseRepr a -> GU.assignDenseMatrixGU f a - let inline assignV f a = GU.assignVecGU f a - - let coerce2 x = unbox(box(x)) - let loosenDM (x: dmatrix) : DenseMatrix<_> = coerce2 x - let loosenSM (x: smatrix) : SparseMatrix<_> = coerce2 x - let loosenV (x: vector) : Vector<_> = coerce2 x - let loosenRV (x: rowvec) : RowVector<_> = coerce2 x - let loosenF (x: float) : 'T = coerce2 x - - let tightenDM (x: DenseMatrix<_>) : dmatrix = coerce2 x - let tightenSM (x: SparseMatrix<_>) : smatrix = coerce2 x - let tightenV (x: Vector<_>) : vector = coerce2 x - let tightenRV (x: RowVector<_>) : rowvec = coerce2 x - let tightenF (x: 'T) : float = coerce2 x - - let zeroM m n = - let arr = GU.createArray2D m n - // This is quite performance critical - // Avoid assigining zeros into the array - match box arr with - | :? (float[,]) as arr -> GU.mkDenseMatrixGU DS.FloatOps arr |> loosenDM |> dense - | _ -> - GU.zeroizeDenseMatrixGUA arr m n |> dense - - let zeroV m : Vector<'T> = - let arr = GU.createArray m - // Avoid assigining zeros into the array - match box (arr: 'T[]) with - | :? (float[]) as arr -> GU.mkVecGU DS.FloatOps arr |> loosenV - | _ -> - GU.zeroizeVecGUA arr m - - let zeroRV m : RowVector<'T> = - let arr = GU.createArray m - // Avoid assigining zeros into the array - match box (arr: 'T[]) with - | :? (float[]) as arr -> GU.mkRowVecGU DS.FloatOps arr |> loosenRV - | _ -> - GU.zeroizeRowVecGUA arr m - - let initNumericM m n f = - let arr = GU.createArray2D m n - let opsData = opsdata<'T> - let ops = GU.opsOfOpsData opsData - GU.assignArray2D m n (f ops) arr; - GU.mkDenseMatrixGU opsData arr |> dense - - let identityM m = - let arr = GU.createArray2D m m - // This is quite performance critical - // Avoid assigining zeros into the array - match box arr with - | :? (float[,]) as arr -> - for i = 0 to m - 1 do - arr.[i,i] <- 1.0 - GU.mkDenseMatrixGU DS.FloatOps arr |> loosenDM |> dense - | _ -> - let opsData = opsdata<'T> - let ops = GU.opsOfOpsData opsData - let zero = ops.Zero - let one = ops.One - GU.assignArray2D m m (fun i j -> if i = j then one else zero) arr; - GU.mkDenseMatrixGU opsData arr |> dense - - let createNumericV m f : Vector<'T> = - let arr = GU.createArray m - let opsData = opsdata<'T> - let ops = GU.opsOfOpsData opsData - GU.assignArray m (f ops) arr; - GU.mkVecGU opsData arr - - let scalarM x = constM 1 1 x - let scalarRV x = constRV 1 x - let scalarV x = constV 1 x - - let diagnM (v:Vector<_>) n = - let ops = v.ElementOps - let zero = ops.Zero - let nV = v.NumRows + (if n < 0 then -n else n) - createMx v.OpsData nV nV (fun i j -> if i+n=j then v.[i] else zero) - - let diagM v = diagnM v 0 - - let constDiagM n x : Matrix<'T> = - let opsData = opsdata<'T> - let ops = GU.opsOfOpsData opsData - let zero = ops.Zero - createMx opsData n n (fun i j -> if i=j then x else zero) - - // Note: we drop sparseness on pointwise multiplication of sparse and dense. - let inline binaryOpM opDenseDS opDenseGU opSparseDS opSparseMatrixGU a b = - match a,b with - | DenseRepr a,DenseRepr b -> - match box a with - | (:? dmatrix as a) -> opDenseDS a (tightenDM b) |> loosenDM |> dense - | _ -> opDenseGU a b |> dense - | SparseRepr a,SparseRepr b -> - match box a with - | (:? smatrix as a) -> opSparseDS a (tightenSM b) |> loosenSM |> sparse - | _ -> opSparseMatrixGU a b |> sparse - | SparseRepr a, DenseRepr b -> opDenseGU (GU.toDenseSparseMatrixGU a) b |> dense - | DenseRepr a, SparseRepr b -> opDenseGU a (GU.toDenseSparseMatrixGU b) |> dense - - let inline unaryOpM opDenseDS opDenseGU opSparseDS opSparseMatrixGU b = - match b with - | DenseRepr b -> - match box b with - | (:? dmatrix as b) -> opDenseDS b |> loosenDM |> dense - | _ -> opDenseGU b |> dense - | SparseRepr b -> - match box b with - | (:? smatrix as b) -> opSparseDS b |> loosenSM |> sparse - | _ -> opSparseMatrixGU b |> sparse - - let inline floatUnaryOpM opDenseDS opDenseGU opSparseDS opSparseMatrixGU b = - match b with - | DenseRepr b -> - match box b with - | (:? dmatrix as b) -> opDenseDS b |> loosenF - | _ -> opDenseGU b - | SparseRepr b -> - match box b with - | (:? smatrix as b) -> opSparseDS b |> loosenF - | _ -> opSparseMatrixGU b - - let addM a b = binaryOpM DS.addDenseMatrixDS GU.addDenseMatrixGU DS.addSparseDS GU.addSparseMatrixGU a b - let subM a b = binaryOpM DS.subDenseMatrixDS GU.subDenseMatrixGU DS.subSparseDS GU.subSparseMatrixGU a b - let mulM a b = binaryOpM DS.mulDenseMatrixDS GU.genericMulDenseMatrix DS.mulSparseDS GU.mulSparseMatrixGU a b - let cptMulM a b = binaryOpM DS.cptMulDenseMatrixDS GU.cptMulDenseMatrixGU DS.cptMulSparseDS GU.cptMulSparseMatrixGU a b - let cptMaxM a b = binaryOpM DS.cptMaxDenseMatrixDS GU.cptMaxDenseMatrixGU DS.cptMaxSparseDS GU.cptMaxSparseMatrixGU a b - let cptMinM a b = binaryOpM DS.cptMinDenseMatrixDS GU.cptMinDenseMatrixGU DS.cptMinSparseDS GU.cptMinSparseMatrixGU a b - - let addRV a b = - match box a with - | (:? rowvec as a) -> DS.addRowVecDS a (tightenRV b) |> loosenRV - | _ -> GU.addRowVecGU a b - - let addV a b = - match box a with - | (:? vector as a) -> DS.addVecDS a (tightenV b) |> loosenV - | _ -> GU.addVecGU a b - - let subRV a b = - match box a with - | (:? rowvec as a) -> DS.subRowVecDS a (tightenRV b) |> loosenRV - | _ -> GU.subRowVecGU a b - - let subV a b = - match box a with - | (:? vector as a) -> DS.subVecDS a (tightenV b) |> loosenV - | _ -> GU.subVecGU a b - - let mulRVM a b = - match b with - | DenseRepr b -> - match box a with - | (:? rowvec as a) -> DS.mulRowVecDenseMatrixDS a (tightenDM b) |> loosenRV - | _ -> GU.mulRowVecDenseMatrixGU a b - | SparseRepr b -> GU.mulRVSparseMatrixGU a b - - let mulMV a b = - match a with - | DenseRepr a -> - match box a with - | (:? dmatrix as a) -> DS.mulDenseMatrixVecDS a (tightenV b) |> loosenV - | _ -> GU.mulDenseMatrixVecGU a b - | SparseRepr a -> GU.mulSparseVecGU a b - - let mulRVV a b = - match box a with - | (:? rowvec as a) -> DS.mulRowVecVecDS a (tightenV b) |> loosenF - | _ -> GU.mulRowVecVecGU a b - - let mulVRV a b = - match box a with - | (:? vector as a) -> DS.mulVecRowVecDS a (tightenRV b) |> loosenDM |> dense - | _ -> GU.mulVecRowVecGU a b |> dense - - let cptMulRV a b = - match box a with - | (:? rowvec as a) -> DS.cptMulRowVecDS a (tightenRV b) |> loosenRV - | _ -> GU.cptMulRowVecGU a b - - let cptMulV a b = - match box a with - | (:? vector as a) -> DS.cptMulVecDS a (tightenV b) |> loosenV - | _ -> GU.cptMulVecGU a b - - let cptMaxV a b = - match box a with - | (:? vector as a) -> DS.cptMaxVecDS a (tightenV b) |> loosenV - | _ -> GU.cptMaxVecGU a b - - let cptMinV a b = - match box a with - | (:? vector as a) -> DS.cptMinVecDS a (tightenV b) |> loosenV - | _ -> GU.cptMinVecGU a b - - let scaleM a b = unaryOpM (fun b -> DS.scaleDenseMatrixDS (tightenF a) b) (GU.scaleDenseMatrixGU a) - (fun b -> DS.scaleSparseDS (tightenF a) b) (GU.scaleSparseMatrixGU a) b - - let scaleRV a b = - match box b with - | (:? rowvec as b) -> DS.scaleRowVecDS (tightenF a) b |> loosenRV - | _ -> GU.scaleRowVecGU a b - - let scaleV a b = - match box b with - | (:? vector as b) -> DS.scaleVecDS (tightenF a) b |> loosenV - | _ -> GU.scaleVecGU a b - - let addScalarM a b = unaryOpM (fun b -> DS.addScalarDenseMatrixDS (tightenF a) b) (GU.addScalarDenseMatrixGU a) - (fun b -> DS.addScalarSparseDS (tightenF a) b) (GU.addScalarSparseMatrixGU a) b - - let addScalarRV a b = - match box b with - | (:? rowvec as b) -> DS.addScalarRowVecDS (tightenF a) b |> loosenRV - | _ -> GU.addScalarRowVecGU a b - - let addScalarV a b = - match box b with - | (:? vector as b) -> DS.addScalarVecDS (tightenF a) b |> loosenV - | _ -> GU.addScalarVecGU a b - - let subScalarM a b = unaryOpM (fun b -> DS.subScalarDenseMatrixDS (tightenF a) b) (GU.subScalarDenseMatrixGU a) - (fun b -> DS.subScalarSparseDS (tightenF a) b) (GU.subScalarSparseMatrixGU a) b - - let subScalarRV a b = - match box b with - | (:? rowvec as b) -> DS.subScalarRowVecDS (tightenF a) b |> loosenRV - | _ -> GU.subScalarRowVecGU a b - - let subScalarV a b = - match box b with - | (:? vector as b) -> DS.subScalarVecDS (tightenF a) b |> loosenV - | _ -> GU.subScalarVecGU a b - - let dotM a b = - match a,b with - | DenseRepr a,DenseRepr b -> - match box b with - | (:? dmatrix as b) -> DS.dotDenseMatrixDS (tightenDM a) b |> loosenF - | _ -> GU.dotDenseMatrixGU a b - | _ -> - let ops = a.ElementOps - mergedNonZeroEntriesM a b |> Seq.fold (fun z (va,vb) -> GU.add ops z (GU.mul ops va vb)) ops.Zero - - let dotV a b = - match box b with - | (:? vector as b) -> DS.dotVecDS (tightenV a) b |> loosenF - | _ -> GU.dotVecGU a b - - let negM a = unaryOpM DS.negDenseMatrixDS GU.negDenseMatrixGU DS.negSparseDS GU.negSparseMatrixGU a - - let negRV a = - match box a with - | (:? rowvec as a) -> DS.negRowVecDS a |> loosenRV - | _ -> GU.negRowVecGU a - - let negV a = - match box a with - | (:? vector as a) -> DS.negVecDS a |> loosenV - | _ -> GU.negVecGU a - - let traceMGU (a:Matrix<_>) = - let nA = a.NumCols - let mA = a.NumRows - if nA<>mA then invalidArg "a" "expected a square matrix"; - let ops = a.ElementOps - (0,nA-1) |> GU.sumRGU ops (fun i -> a.[i,i]) - - let traceM a = floatUnaryOpM DS.traceDenseMatrixDS (dense >> traceMGU) (sparse >> traceMGU) (sparse >> traceMGU) a - let sumM a = floatUnaryOpM DS.sumDenseMatrixDS GU.sumDenseMatrixGU GU.sumSparseMatrixGU GU.sumSparseMatrixGU a - let prodM a = floatUnaryOpM DS.prodDenseMatrixDS GU.prodDenseMatrixGU GU.prodSparseMatrixGU GU.prodSparseMatrixGU a - let normM a = floatUnaryOpM DS.normDenseMatrixDS GU.normDenseMatrixGU GU.normSparseMatrixGU GU.normSparseMatrixGU a - - let opsM a = - match a with - | DenseRepr a -> a.OpsData - | SparseRepr a -> a.OpsData - - let transM a = - match a with - | DenseRepr a -> - // rows of transposed matrix = columns of original matrix and vice versa - createMx a.OpsData a.NumCols a.NumRows (fun i j -> a.[j,i]) - | SparseRepr a -> - a |> GU.nonZeroEntriesSparseMatrixGU |> Seq.map (fun (i,j,v) -> (j,i,v)) |> GU.initSparseMatrixGU a.NumCols a.NumRows a.OpsData |> sparse - - let permuteRows (p: permutation) a = - match a with - | DenseRepr a -> - createMx a.OpsData a.NumRows a.NumCols (fun i j -> a.[p i,j]) - | SparseRepr a -> - a |> GU.nonZeroEntriesSparseMatrixGU |> Seq.map (fun (i,j,v) -> (p i,j,v)) |> GU.initSparseMatrixGU a.NumCols a.NumRows a.OpsData |> sparse - - let permuteColumns (p: permutation) a = - match a with - | DenseRepr a -> - createMx a.OpsData a.NumRows a.NumCols (fun i j -> a.[i,p j]) - | SparseRepr a -> - a |> GU.nonZeroEntriesSparseMatrixGU |> Seq.map (fun (i,j,v) -> (i,p j,v)) |> GU.initSparseMatrixGU a.NumCols a.NumRows a.OpsData |> sparse - - let transRV (a:RowVector<_>) = - createVx a.OpsData a.NumCols (fun i -> a.[i]) - - let transV (a:Vector<_>) = - createRVx a.OpsData a.NumRows (fun i -> a.[i]) - - let inplaceAddM a b = - match a,b with - | DenseRepr a,DenseRepr b -> - match box a with - | (:? dmatrix as a) -> DS.inplaceAddDenseMatrixDS a (tightenDM b) - | _ -> GU.inplaceAddDenseMatrixGU a b - | _ -> sparseNotMutable() - - let inplaceAddV a b = - match box a with - | (:? vector as a) -> DS.inplaceAddVecDS a (tightenV b) - | _ -> GU.inplaceAddVecGU a b - - let inplaceSubM a b = - match a,b with - | DenseRepr a,DenseRepr b -> - match box a with - | (:? dmatrix as a) -> DS.inplaceSubDenseMatrixDS a (tightenDM b) - | _ -> GU.inplaceSubDenseMatrixGU a b - | _ -> sparseNotMutable() - - let inplaceSubV a b = - match box a with - | (:? vector as a) -> DS.inplaceSubVecDS a (tightenV b) - | _ -> GU.inplaceSubVecGU a b - - - let inplaceCptMulM a b = - match a,b with - | DenseRepr a,DenseRepr b -> - match box a with - | (:? dmatrix as a) -> DS.inplaceCptMulDenseMatrixDS a (tightenDM b) - | _ -> GU.inplaceCptMulDenseMatrixGU a b - | _ -> sparseNotMutable() - - let inplaceCptMulV a b = - match box a with - | (:? vector as a) -> DS.inplaceCptMulVecDS a (tightenV b) - | _ -> GU.inplaceCptMulVecGU a b - - let inplaceScaleM a b = - match b with - | DenseRepr b -> - match box b with - | (:? dmatrix as b) -> DS.inplaceScaleDenseMatrixDS (tightenF a) b - | _ -> GU.inplaceScaleDenseMatrixGU a b - | _ -> sparseNotMutable() - - let inplaceScaleV a b = - match box b with - | (:? vector as b) -> DS.inplaceScaleVecDS (tightenF a) b - | _ -> GU.inplaceScaleVecGU a b - - let existsM f a = - match a with - | SparseRepr _ -> sparseNYI() // note: martin says "run f on a token element if it's not full" - | DenseRepr a -> GU.existsiDenseMatrixGU (fun _ _ -> f) a - - let existsV f a = GU.existsiVecGU (fun _ -> f) a - - let forallM f a = - match a with - | SparseRepr _ -> sparseNYI() - | DenseRepr a -> GU.foralliDenseMatrixGU (fun _ _ -> f) a - - let forallV f a = GU.foralliVecGU (fun _ -> f) a - - let existsiM f a = - match a with - | SparseRepr _ -> sparseNYI() - | DenseRepr a -> GU.existsiDenseMatrixGU f a - - let existsiV f a = GU.existsiVecGU f a - - let foralliM f a = - match a with - | SparseRepr _ -> sparseNYI() - | DenseRepr a -> GU.foralliDenseMatrixGU f a - - let foralliV f a = GU.foralliVecGU f a - - let mapM f a = - match a with - | SparseRepr _ -> sparseNYI() - | DenseRepr a -> DenseRepr(GU.mapDenseMatrixGU f a) - - let mapV f a = GU.mapVecGU f a - - let map2V f a b = GU.map2VecGU f a b - - let map3V f a b c = GU.map3VecGU f a b c - - let zipV a b = GU.zipVecGU a b - - let unzipV a = GU.unzipVecGU a - - let copyM a = - match a with - | SparseRepr a -> SparseRepr (GU.copySparseGU a) - | DenseRepr a -> DenseRepr (GU.copyDenseMatrixGU a) - - let copyV a = GU.copyVecGU a - - let copyRV a = GU.copyRowVecGU a - - let mapiM f a = - match a with - | SparseRepr _ -> sparseNYI() - | DenseRepr a -> DenseRepr (GU.mapiDenseMatrixGU f a) - - let mapiV f a = GU.mapiVecGU f a - let permuteV p a = GU.permuteVecGU p a - let permuteRV p a = GU.permuteRowVecGU p a - - let mapRV f a = GU.mapRowVecGU f a - - let mapiRV f a = GU.mapiRowVecGU f a - - let toDenseM a = - match a with - | SparseRepr a -> GU.toDenseSparseMatrixGU a |> dense - | DenseRepr _ -> a - let toSparseM (a: Matrix<'T>) = - match a with - | SparseRepr _ -> a - | DenseRepr a -> - let length1 = a.NumRows - let length2 = a.NumCols - - let mutable nnz = 0 - let ar = FSharp.Collections.ResizeArray<'T>() - let ja = FSharp.Collections.ResizeArray() - let ia = FSharp.Collections.ResizeArray() - ia.Add(0) - - for i = 0 to (length1 - 1) do - for j = 0 to (length2 - 1) do - if (a.Item(i, j)|> System.Convert.ToDouble) >= 0.000001 || (a.Item(i, j)|> System.Convert.ToDouble) <= -0.000001 then - ar.Add(a.Item(i, j)) - ja.Add(j) - nnz <- nnz + 1 - ia.Add(nnz) - SparseRepr (SparseMatrix(opsdata<'T>, ar.ToArray(), ia.ToArray(), length2, ja.ToArray())) - - let initSparseM i j x : Matrix<'T> = - let opsData = opsdata<'T> - GU.initSparseMatrixGU i j opsData x |> sparse - - let initDenseM i j x : Matrix<'T> = - let r = zeroM i j - x |> Seq.iter (fun (i,j,v) -> r.[i,j] <- v); - r - - let getDiagnM (a:Matrix<_>) n = - let nA = a.NumCols - let mA = a.NumRows - if nA<>mA then invalidArg "a" "expected a square matrix"; - let ni = if n < 0 then -n else 0 - let nj = if n > 0 then n else 0 - GU.createVecGU (opsM a) (max (nA-abs(n)) 0) (fun i -> a.[i+ni,i+nj]) - - let getDiagM a = getDiagnM a 0 - - let inline inplace_mapM f a = - match a with - | SparseRepr _ -> sparseNotMutable() - | DenseRepr a -> GU.inplace_mapDenseMatrixGU f a - - let inline inplace_mapiM f a = - match a with - | SparseRepr _ -> sparseNotMutable() - | DenseRepr a -> GU.inplace_mapiDenseMatrixGU f a - - let inline inplace_mapV f a = GU.inplace_mapVecGU f a - - let inline inplace_mapiV f a = GU.inplace_mapiVecGU f a - - let inline foldM f z a = - match a with - | SparseRepr _ -> sparseNYI() - | DenseRepr a -> GU.foldDenseMatrixGU f z a - - let inline foldV f z a = GU.foldVecGU f z a - - let inline foldiM f z a = - match a with - | SparseRepr _ -> sparseNYI() - | DenseRepr a -> GU.foldiDenseMatrixGU f z a - - let inline foldiV f z a = GU.foldiVecGU f z a - - let compareM (comp: IComparer) (a:Matrix<'T>) (b:Matrix<'T>) = - let nA = a.NumCols - let mA = a.NumRows - let nB = b.NumCols - let mB = b.NumRows - let c = compare mA mB - if c <> 0 then c else - let c = compare nA nB - if c <> 0 then c else - match a,b with - | DenseRepr a, DenseRepr b -> - let rec go2 i j = - if j < nA then - let c = comp.Compare( a.[i,j], b.[i,j]) - if c <> 0 then c else - go2 i (j+1) - else 0 - let rec go1 i = - if i < mA then - let c = go2 i 0 - if c <> 0 then c - else go1 (i+1) - else 0 - go1 0 - | _ -> - match (mergedNonZeroEntriesM a b |> Seq.tryPick (fun (v1,v2) -> let c = comp.Compare(v1,v2) in if c = 0 then None else Some(c))) with - | None -> 0 - | Some(c) -> c - - let equalsM (comp: IEqualityComparer) (a:Matrix<'T>) (b:Matrix<'T>) = - let nA = a.NumCols - let mA = a.NumRows - let nB = b.NumCols - let mB = b.NumRows - (mA = mB ) && (nA = nB) && - match a,b with - | DenseRepr a, DenseRepr b -> - let rec go2 i j = j >= nA || (comp.Equals( a.[i,j], b.[i,j]) && go2 i (j+1) ) - let rec go1 i = i >= mA || (go2 i 0 && go1 (i+1)) - go1 0 - | _ -> - mergedNonZeroEntriesM a b |> Seq.forall (fun (v1,v2) -> comp.Equals(v1,v2)) - - - let compareV (comp: IComparer) (a:Vector<'T>) (b:Vector<'T>) = - let mA = a.NumRows - let mB = b.NumRows - let c = compare mA mB - if c <> 0 then c else - let rec go2 j = - if j < mA then - let c = comp.Compare(a.[j],b.[j]) - if c <> 0 then c else go2 (j+1) - else 0 - go2 0 - - let equalsV (comp: IEqualityComparer) (a:Vector<'T>) (b:Vector<'T>) = - let mA = a.NumRows - let mB = b.NumRows - (mA = mB) && - let rec go2 j = (j >= mA) || (comp.Equals(a.[j],b.[j]) && go2 (j+1)) - go2 0 - - let equalsRV (comp: IEqualityComparer) (a:RowVector<'T>) (b:RowVector<'T>) = - let mA = a.NumCols - let mB = b.NumCols - (mA = mB) && - let rec go2 j = (j >= mA) || (comp.Equals(a.[j],b.[j]) && go2 (j+1)) - go2 0 - - let compareRV (comp: IComparer) (a:RowVector<'T>) (b:RowVector<'T>) = - let mA = a.NumCols - let mB = b.NumCols - let c = compare mA mB - if c <> 0 then c else - let rec go2 j = - if j < mA then - let c = comp.Compare(a.[j],b.[j]) - if c <> 0 then c else go2 (j+1) - else 0 - go2 0 - - let inline combineHash x y = (x <<< 1) + y + 631 - - let hashM (comp:IEqualityComparer) (a:Matrix<_>) = - let nA = a.NumCols - let mA = a.NumRows - let acc = hash mA + hash nA - a |> nonZeroEntriesM |> Seq.truncate 20 |> Seq.fold (fun z v -> combineHash z (comp.GetHashCode v)) acc - - let hashV (comp:IEqualityComparer) (a:Vector<_>) = - let mA = a.NumRows - hash mA + - (let mutable c = 0 - for i = 0 to mA - 1 do - c <- combineHash c (comp.GetHashCode a.[i]) - c) - - let hashRV (comp:IEqualityComparer) (a:RowVector<_>) = - let mA = a.NumCols - hash mA + - (let mutable c = 0 - for i = 0 to mA - 1 do - c <- combineHash c (comp.GetHashCode a.[i]) - c) - - type range = int * int - - let startR ((a,_) : range) = a - let countR ((a,b) : range) = (b-a)+1 - let idxR ((a,_) : range) i = a+i - let inR ((a,b) : range) i = a <= i && i <= b - ///Returns row of index i of matrix a as a vector - let getRowM (a:Matrix<_>) i = createRVx (opsM a) a.NumCols (fun j -> a.[i,j]) - /// Replaces row of index j of matrix a with values of vector v, if vector length matches rowsize - /// - /// - /// - /// - /// - /// - /// - /// - /// - let setRowM (a:Matrix<_>) i (v:Vector<_>) = - if a.NumCols = v.Length then - let l = v.Length-1 - for j = 0 to l do - a.[i,j] <- v.[j] - elif a.NumCols < v.Length then - failwith ("Can't set row, vector is longer than matrix column number") - else - failwith ("Can't set row, vector is shorter than matrix column number") - ///Returns col of index i of matrix a as a vector - let getColM (a:Matrix<_>) j = createVx (opsM a) a.NumRows (fun i -> a.[i,j]) - /// Replaces column of index i of matrix a with values of vector v, if vector length matches columnsize - /// - /// - /// - /// - /// - /// - /// - /// - /// - let setColM (a:Matrix<_>) j (v:Vector<_>) = - if a.NumRows = v.Length then - let l = v.Length-1 - for i = 0 to l do - a.[i,j] <- v.[i] - elif a.NumCols < v.Length then - failwith ("Can't set column, vector is longer than matrix row number") - else - failwith ("Can't set column, vector is shorter than matrix row number") - let getRegionV (a:Vector<_>) r = createVx a.OpsData (countR r) (fun i -> a.[idxR r i]) - let getRegionRV (a:RowVector<_>) r = createRVx a.OpsData (countR r) (fun i -> a.[idxR r i]) - - let getRegionM a ri rj = - match a with - | DenseRepr a -> createMx a.OpsData (countR ri) (countR rj) (fun i j -> a.[idxR ri i, idxR rj j]) - | _ -> nonZeroEntriesM a - |> Seq.filter (fun (i,j,_) -> inR ri i && inR rj j) - |> Seq.map (fun (i,j,v) -> (i-startR ri,j-startR rj,v)) - |> initSparseM (countR ri) (countR rj) - - let getColsM (a:Matrix<_>) rj = getRegionM a (0,a.NumRows - 1) rj - let getRowsM (a:Matrix<_>) ri = getRegionM a ri (0,a.NumCols - 1) - - let rowvecM (x:RowVector<_>) = initM 1 x.NumCols (fun _ j -> x.[j]) - let vectorM (x:Vector<_>) = initM x.NumRows 1 (fun i _ -> x.[i]) - let toVectorM x = getColM x 0 - let toRowVectorM x = getRowM x 0 - let toScalarM (x:Matrix<_>) = x.[0,0] - - - -//---------------------------------------------------------------------------- -// type Matrix<'T> augmentation -//---------------------------------------------------------------------------- -// Interface implementation - - type Matrix<'T> with - static member ( + )(a: Matrix<'T>,b) = SpecializedGenericImpl.addM a b - static member ( - )(a: Matrix<'T>,b) = SpecializedGenericImpl.subM a b - static member ( * )(a: Matrix<'T>,b) = SpecializedGenericImpl.mulM a b - static member ( * )(a: Matrix<'T>,b : Vector<'T>) = SpecializedGenericImpl.mulMV a b - - static member ( * )((m: Matrix<'T>),k : 'T) = SpecializedGenericImpl.scaleM k m - - static member ( .* )(a: Matrix<'T>,b) = SpecializedGenericImpl.cptMulM a b - static member ( * )(k,m: Matrix<'T>) = SpecializedGenericImpl.scaleM k m - static member ( ~- )(m: Matrix<'T>) = SpecializedGenericImpl.negM m - static member ( ~+ )(m: Matrix<'T>) = m - // add + - static member ( + )(a: Matrix<'T>,k: 'T) = SpecializedGenericImpl.addScalarM k a - static member ( + )(k: 'T,a: Matrix<'T>) = SpecializedGenericImpl.addScalarM k a - // sub - - static member ( - )(a: Matrix<'T>,k: 'T) = SpecializedGenericImpl.subScalarM k a - static member ( - )(k: 'T,a: Matrix<'T>) = SpecializedGenericImpl.subScalarM k a - - member m.GetSlice (start1,finish1,start2,finish2) = - let start1 = match start1 with None -> 0 | Some v -> v - let finish1 = match finish1 with None -> m.NumRows - 1 | Some v -> v - let start2 = match start2 with None -> 0 | Some v -> v - let finish2 = match finish2 with None -> m.NumCols - 1 | Some v -> v - SpecializedGenericImpl.getRegionM m (start1,finish1) (start2,finish2) - - member m.SetSlice (start1,finish1,start2,finish2,vs:Matrix<_>) = - let start1 = match start1 with None -> 0 | Some v -> v - let finish1 = match finish1 with None -> m.NumRows - 1 | Some v -> v - let start2 = match start2 with None -> 0 | Some v -> v - let finish2 = match finish2 with None -> m.NumCols - 1 | Some v -> v - for i = start1 to finish1 do - for j = start2 to finish2 do - m.[i,j] <- vs.[i-start1,j-start2] - - /// RowCount * ColumnCount - member m.Dimensions = m.NumRows,m.NumCols - - member m.Transpose = SpecializedGenericImpl.transM m - member m.PermuteRows (p: permutation) : Matrix<'T> = SpecializedGenericImpl.permuteRows p m - member m.PermuteColumns (p: permutation) : Matrix<'T> = SpecializedGenericImpl.permuteColumns p m - - -// Interface implementation - - interface IEnumerable<'T> with - member m.GetEnumerator() = - (seq { for i in 0 .. m.NumRows-1 do - for j in 0 .. m.NumCols - 1 do - yield m.[i,j] }).GetEnumerator() - - interface IEnumerable with - member m.GetEnumerator() = ((m :> IEnumerable<_>).GetEnumerator() :> IEnumerator) - - interface System.IComparable with - member m.CompareTo(yobj:obj) = SpecializedGenericImpl.compareM LanguagePrimitives.GenericComparer m (yobj :?> Matrix<'T>) - - interface IStructuralComparable with - member m.CompareTo(yobj:obj,comp:System.Collections.IComparer) = SpecializedGenericImpl.compareM comp m (yobj :?> Matrix<'T>) - - override m.GetHashCode() = SpecializedGenericImpl.hashM LanguagePrimitives.GenericEqualityComparer m - override m.Equals(yobj:obj) = - match yobj with - | :? Matrix<'T> as m2 -> SpecializedGenericImpl.equalsM LanguagePrimitives.GenericEqualityComparer m m2 - | _ -> false - - interface IStructuralEquatable with - member m.GetHashCode(comp:System.Collections.IEqualityComparer) = SpecializedGenericImpl.hashM comp m - member m.Equals(yobj:obj,comp:System.Collections.IEqualityComparer) = - match yobj with - | :? Matrix<'T> as m2 -> SpecializedGenericImpl.equalsM comp m m2 - | _ -> false - - /// Returns four chunks of the matrix as strings depending on the respective row/column start/end count, separated by a row and column indicating omitted rows and columns. - member m.FormatStrings(rowStartCount, rowEndCount, columnStartCount, columnEndCount) = - let nRows, nCols = m.Dimensions - let displayRows = rowStartCount + rowEndCount - let displayCols = columnStartCount + columnEndCount - - - if displayRows >= nRows && displayCols >= nCols then // this formats the full matrix without omitted rows/cols - Array.init (nRows+2) (fun rowIndex -> - match rowIndex with - | 0 -> [|"";"";yield! [for i = 0 to nCols-1 do yield string i]|] // column index header row - | 1 -> [|for i in 0 .. nCols+1 do yield ""|] // empty row to distinguish column indices from data in FSI/StructuredDisplay - | _ -> // the rest of the rows contain data - Array.init (nCols+2) (fun colIndex -> - match colIndex with - | 0 -> string (rowIndex-2) // the first column index contains the row index - | 1 -> "->" // the second column index contains a separator to distinguish row indices from data in FSI/StructuredDisplay - | _ -> m.[rowIndex-2,colIndex-2] |> formatValue // the rest is data. sswitches below work the same, only ommiting some of the data. - ) - ) - elif displayRows >= nRows && displayCols < nCols then // this formats the matrix with only ommitted cols - Array.init (nRows+2) (fun rowIndex -> - match rowIndex with - | 0 -> // column index header row - [| - "";""; - yield! [for i in [0 .. columnStartCount-1] do yield string i]; - "..."; - yield! [for i in [nCols - columnEndCount .. nCols - 1] do yield string i] - |] - | 1 -> [|for i in 0 .. (displayCols + 2) do yield ""|] // empty row to distinguish column indices from data in FSI/StructuredDisplay - | _ -> // the rest of the rows contain data - Array.init (columnStartCount+columnEndCount+3) (fun colIndex -> - if (colIndex-2) < columnStartCount then // left - match colIndex with - | 0 -> string (rowIndex-2) - | 1 -> "->" - | _ -> m.[rowIndex-2,colIndex-2] |> formatValue - elif (colIndex-2) > columnStartCount then // right - m[rowIndex-2,(nCols - 3 - columnEndCount + colIndex - columnStartCount)] |> formatValue - else - "..." // separator for signalling ommitted cols - ) - ) - elif displayRows < nRows && displayCols >= nCols then // this formats the matrix with only ommitted rows - Array.init (rowStartCount+rowEndCount+3) (fun rowIndex -> - match rowIndex with - | 0 -> [|"";"";yield! [for i = 0 to nCols-1 do yield string i]|] // column index header row - | 1 -> [|for i in 0 .. nCols+1 do yield ""|] // empty row to distinguish column indices from data in FSI/StructuredDisplay - | _ -> - Array.init (nCols+2) (fun colIndex -> - if (rowIndex-2) < rowStartCount then // upper half - match colIndex with - | 0 -> string (rowIndex-2) - | 1 -> "->" - | _ -> m.[rowIndex-2,colIndex-2] |> formatValue - elif (rowIndex-2) > rowStartCount then // lower half - match colIndex with - | 0 -> string (nRows - 3 - rowEndCount + rowIndex - rowStartCount) - | 1 -> "->" - | _ -> m[(nRows - 3 - rowEndCount + rowIndex - rowStartCount),colIndex - 2] |> formatValue - else - match colIndex with // separator for signalling ommitted rows - | 0 -> ":" - | 1 -> "" - | _ -> "..." - ) - ) - else // this formats the matrix with ommitted rows and cols - Array.init (rowStartCount+rowEndCount+3) (fun rowIndex -> - match rowIndex with - | 0 -> // column index header row - [| - "";""; - yield! [for i in [0 .. columnStartCount-1] do yield string i]; - "..."; - yield! [for i in [nCols - columnEndCount .. nCols - 1] do yield string i] - |] - | 1 -> [|for i in 0 .. (displayCols + 2) do yield ""|] // empty row to distinguish column indices from data in FSI/StructuredDisplay - | _ -> - Array.init (columnStartCount+columnEndCount+3) (fun colIndex -> - if (rowIndex-2) < rowStartCount then // upper half - if (colIndex-2) < columnStartCount then // upper left - match colIndex with - | 0 -> string (rowIndex-2) - | 1 -> "->" - | _ -> m.[rowIndex-2,colIndex-2] |> formatValue - elif (colIndex-2) > columnStartCount then // upper right - m[rowIndex-2,(nCols - 3 - columnEndCount + colIndex - columnStartCount)] |> formatValue - else - "..." - elif (rowIndex-2) > rowStartCount then // lower half - if (colIndex-2) < columnStartCount then // lower left - match colIndex with - | 0 -> string (nRows - 3 - rowEndCount + rowIndex - rowStartCount) - | 1 -> "->" - | _ -> m[(nRows - 3 - rowEndCount + rowIndex - rowStartCount),(colIndex-2)] |> formatValue - elif (colIndex-2) > columnStartCount then // lower right - m[(nRows - 3 - rowEndCount + rowIndex - rowStartCount),(nCols - 3 - columnEndCount + colIndex - columnStartCount)] |> formatValue - else - "..." - else - match colIndex with - | 0 -> ":" - | 1 -> "" - | _ -> "..." - ) - ) - - member m.Format(rowStartCount, rowEndCount, columnStartCount, columnEndCount, showInfo) = - try - let formattedtable = - m.FormatStrings(rowStartCount, rowEndCount, columnStartCount, columnEndCount) - |> array2D - |> Formatting.formatTable - if showInfo then - let matrixInfo = sprintf "Matrix of %i rows x %i columns" m.NumRows m.NumCols - sprintf "%s%s%s" formattedtable System.Environment.NewLine matrixInfo - else - formattedtable - with e -> sprintf "Formatting failed: %A" e - - member m.Format(rowCount, columnCount, showInfo:bool) = - let rowHalf = rowCount / 2 - let colHalf = columnCount / 2 - m.Format(rowHalf, rowHalf, colHalf, colHalf, showInfo) - - member m.Format(showInfo:bool) = - m.Format( - Formatting.Matrix.RowStartItemCount, - Formatting.Matrix.RowEndItemCount, - Formatting.Matrix.ColumnStartItemCount, - Formatting.Matrix.ColumnEndItemCount, - showInfo - ) - - interface IFsiFormattable with - member m.Format() = m.Format(false) - member m.FormatWithInfo() = m.Format(true) - - interface IMatrixFormattable with - member m.InteractiveFormat(rowCount,colCount) = - m.FormatStrings( - (rowCount / 2), - (rowCount / 2), - (colCount / 2), - (colCount / 2) - ) - member m.GetNumRows() = m.NumRows - member m.GetNumCols() = m.NumCols - - override m.ToString() = - match m with - | DenseRepr m -> GenericImpl.showDenseMatrixGU m - | SparseRepr _ -> "" - - member m.DebugDisplay = - let txt = - match m with - | DenseRepr m -> GenericImpl.debugShowDenseMatrixGU m - | SparseRepr _ -> "" - new System.Text.StringBuilder(txt) // return an object with a ToString with the right value, rather than a string. (strings get shown using quotes) - - member m.StructuredDisplayAsFormattedMatrix = - sprintf "%s%s" System.Environment.NewLine (m.Format(true)) - - member m.StructuredDisplayAsArray = - let rec layout m = - match m with - | DenseRepr _ -> box (Array2D.init m.NumRows m.NumCols (fun i j -> m.[i,j])) - | SparseRepr _ -> (if m.NumRows < 20 && m.NumCols < 20 then layout (SpecializedGenericImpl.toDenseM m) else box(SpecializedGenericImpl.nonZeroEntriesM m)) - layout m - - - -//---------------------------------------------------------------------------- -// type Vector<'T> augmentation -//---------------------------------------------------------------------------- -// Interface implementation - - type Vector<'T> with - static member ( + )(a: Vector<'T>,b) = SpecializedGenericImpl.addV a b - static member ( - )(a: Vector<'T>,b) = SpecializedGenericImpl.subV a b - static member ( .* )(a: Vector<'T>,b) = SpecializedGenericImpl.cptMulV a b - - static member ( * )(k,m: Vector<'T>) = SpecializedGenericImpl.scaleV k m - - static member ( * )(a: Vector<'T>,b) = SpecializedGenericImpl.mulVRV a b - - static member ( * )(m: Vector<'T>,k) = SpecializedGenericImpl.scaleV k m - - static member ( ~- )(m: Vector<'T>) = SpecializedGenericImpl.negV m - static member ( ~+ )(m: Vector<'T>) = m - - // add + - static member ( + )(k,m: Vector<'T>) = SpecializedGenericImpl.addScalarV k m - static member ( + )(m: Vector<'T>,k) = SpecializedGenericImpl.addScalarV k m - // sub - - static member ( - )(k,m: Vector<'T>) = SpecializedGenericImpl.subScalarV k m - static member ( - )(m: Vector<'T>,k) = SpecializedGenericImpl.subScalarV k m - - member m.GetSlice (start,finish) = - let start = match start with None -> 0 | Some v -> v - let finish = match finish with None -> m.NumRows - 1 | Some v -> v - SpecializedGenericImpl.getRegionV m (start,finish) - - member m.SetSlice (start,finish,vs:Vector<_>) = - let start = match start with None -> 0 | Some v -> v - let finish = match finish with None -> m.NumRows - 1 | Some v -> v - for i = start to finish do - m.[i] <- vs.[i-start] - - - member m.DebugDisplay = - let txt = GenericImpl.showVecGU "vector" m - new System.Text.StringBuilder(txt) // return an object with a ToString with the right value, rather than a string. (strings get shown using quotes) - - member m.StructuredDisplayAsArray = Array.init m.NumRows (fun i -> m.[i]) - - member m.Details = m.Values - - member m.Transpose = SpecializedGenericImpl.transV m - - member m.Permute (p:permutation) = SpecializedGenericImpl.permuteV p m - - - interface System.IComparable with - member m.CompareTo(y:obj) = SpecializedGenericImpl.compareV LanguagePrimitives.GenericComparer m (y :?> Vector<'T>) - - interface IStructuralComparable with - member m.CompareTo(y:obj,comp:System.Collections.IComparer) = SpecializedGenericImpl.compareV comp m (y :?> Vector<'T>) - - interface IStructuralEquatable with - member x.GetHashCode(comp) = SpecializedGenericImpl.hashV comp x - member x.Equals(yobj,comp) = - match yobj with - | :? Vector<'T> as v2 -> SpecializedGenericImpl.equalsV comp x v2 - | _ -> false - - override x.GetHashCode() = - SpecializedGenericImpl.hashV LanguagePrimitives.GenericEqualityComparer x - - override x.Equals(yobj) = - match yobj with - | :? Vector<'T> as v2 -> SpecializedGenericImpl.equalsV LanguagePrimitives.GenericEqualityComparer x v2 - | _ -> false - - override m.ToString() = GenericImpl.showVecGU "vector" m - -//---------------------------------------------------------------------------- -// type RowVector<'T> augmentation -//---------------------------------------------------------------------------- - - type RowVector<'T> with - static member ( + )(a: RowVector<'T>,b) = SpecializedGenericImpl.addRV a b - static member ( - )(a: RowVector<'T>,b) = SpecializedGenericImpl.subRV a b - static member ( .* )(a: RowVector<'T>,b) = SpecializedGenericImpl.cptMulRV a b - static member ( * )(k,v: RowVector<'T>) = SpecializedGenericImpl.scaleRV k v - - static member ( * )(a: RowVector<'T>,b: Matrix<'T>) = SpecializedGenericImpl.mulRVM a b - static member ( * )(a: RowVector<'T>,b:Vector<'T>) = SpecializedGenericImpl.mulRVV a b - static member ( * )(v: RowVector<'T>,k:'T) = SpecializedGenericImpl.scaleRV k v - - static member ( ~- )(v: RowVector<'T>) = SpecializedGenericImpl.negRV v - static member ( ~+ )(v: RowVector<'T>) = v - - // add + - static member ( + )(v: RowVector<'T>,k:'T) = SpecializedGenericImpl.addScalarRV k v - static member ( + )(k:'T,v: RowVector<'T>) = SpecializedGenericImpl.addScalarRV k v - // sub - - static member ( - )(v: RowVector<'T>,k:'T) = SpecializedGenericImpl.subScalarRV k v - static member ( - )(k:'T,v: RowVector<'T>) = SpecializedGenericImpl.subScalarRV k v - - member m.GetSlice (start,finish) = - let start = match start with None -> 0 | Some v -> v - let finish = match finish with None -> m.NumCols - 1 | Some v -> v - SpecializedGenericImpl.getRegionRV m (start,finish) - - member m.SetSlice (start,finish,vs:RowVector<_>) = - let start = match start with None -> 0 | Some v -> v - let finish = match finish with None -> m.NumCols - 1 | Some v -> v - for i = start to finish do - m.[i] <- vs.[i-start] - - - member m.DebugDisplay = - let txt = GenericImpl.showRowVecGU "rowvec" m - new System.Text.StringBuilder(txt) // return an object with a ToString with the right value, rather than a string. (strings get shown using quotes) - - member m.StructuredDisplayAsArray = Array.init m.NumCols (fun i -> m.[i]) - - member m.Details = m.Values - - member m.Transpose = SpecializedGenericImpl.transRV m - - member m.Permute (p:permutation) = SpecializedGenericImpl.permuteRV p m - - override m.ToString() = GenericImpl.showRowVecGU "rowvec" m - - interface System.IComparable with - member m.CompareTo(y) = SpecializedGenericImpl.compareRV LanguagePrimitives.GenericComparer m (y :?> RowVector<'T>) - - interface IStructuralComparable with - member m.CompareTo(y,comp) = SpecializedGenericImpl.compareRV comp m (y :?> RowVector<'T>) - - interface IStructuralEquatable with - member x.GetHashCode(comp) = SpecializedGenericImpl.hashRV comp x - member x.Equals(yobj,comp) = - match yobj with - | :? RowVector<'T> as rv2 -> SpecializedGenericImpl.equalsRV comp x rv2 - | _ -> false - - override x.GetHashCode() = - SpecializedGenericImpl.hashRV LanguagePrimitives.GenericEqualityComparer x - - override x.Equals(yobj) = - match yobj with - | :? RowVector<'T> as rv2 -> SpecializedGenericImpl.equalsRV LanguagePrimitives.GenericEqualityComparer x rv2 - | _ -> false - - - - - - type matrix = Matrix - type vector = Vector - type rowvec = RowVector - - - - -// type Matrix<'T> with -// member x.ToArray2() = Matrix.Generic.toArray2D x -// member x.ToArray2D() = Matrix.Generic.toArray2D x -// -//#if FX_NO_DEBUG_DISPLAYS -//#else -// [] -//#endif -// -// member x.NonZeroEntries = Matrix.Generic.nonzero_entries x -// member x.ToScalar() = Matrix.Generic.toScalar x -// member x.ToRowVector() = Matrix.Generic.toRowVector x -// member x.ToVector() = Matrix.Generic.toVector x -// -//#if FX_NO_DEBUG_DISPLAYS -//#else -// [] -//#endif -// member x.Norm = Matrix.Generic.norm x -// -// member x.Column(n) = Matrix.Generic.getCol x n -// member x.Row(n) = Matrix.Generic.getRow x n -// member x.Columns (i,ni) = Matrix.Generic.getCols x i ni -// member x.Rows (j,nj) = Matrix.Generic.getRows x j nj -// member x.Region(i,j,ni,nj) = Matrix.Generic.getRegion x i j ni nj -// member x.GetDiagonal(i) = Matrix.Generic.getDiagN x i -// -//#if FX_NO_DEBUG_DISPLAYS -//#else -// [] -//#endif -// member x.Diagonal = Matrix.Generic.getDiag x -// -// member x.Copy () = Matrix.Generic.copy x -// -// -// type Vector<'T> with -// member x.ToArray() = Vector.Generic.toArray x -// member x.Norm = Vector.Generic.norm x -// member x.Copy () = Vector.Generic.copy x -// -// -// type RowVector<'T> with -// member x.ToArray() = RowVector.Generic.toArray x -// member x.Copy () = RowVector.Generic.copy x -// -// [] -// module MatrixTopLevelOperators = -// -// let matrix ll = Matrix.ofSeq ll -// let vector l = Vector.ofSeq l -// let rowvec l = RowVector.ofSeq l - diff --git a/src/FSharp.Stats/Algebra/ILinearAlgebra.fs b/src/FSharp.Stats/Algebra/ILinearAlgebra.fs deleted file mode 100644 index bfbe859b6..000000000 --- a/src/FSharp.Stats/Algebra/ILinearAlgebra.fs +++ /dev/null @@ -1,122 +0,0 @@ -namespace FSharp.Stats.Algebra - -//namespace Microsoft.FSharp.Math // old namespace -open FSharp.Stats - - -///This is an internal interface and not for user usage. -///It exposes a specialised subset of BLAS/LAPACK functionality. -///This functionality is used by us to build the exposed APIs. -///It is those exposed APIs that should be used. -type ILinearAlgebra = - //Matrix-Matrix Multiplication - abstract dgemm_ : Matrix * Matrix -> Matrix - - ////Matrix-Vector Multiplication - //abstract dgemv_ : Matrix * Vector -> Vector - - ////Solve (linear equations) - //abstract dgesv_ : Matrix * Matrix -> Matrix * int array * Matrix - - ////Solve symmetric positive definite matrix (linear equations) - //abstract dposv_ : Matrix * Matrix -> Matrix * Matrix - - ////Solve triangular (linear equations) - //abstract dtrsv_ : char * Matrix * Vector -> Vector - - ////Solve triangular (linear equations) - //abstract dtrsm_ : char * Matrix * Matrix -> Matrix - - ////Solve (linear equations) using LU factorization - //abstract dgesvx_ : - // Matrix * Matrix -> - // Matrix * Matrix * int array * char * double array * double array * - // Matrix * Matrix * float * double array * double array - - ////Compoutes for an N-by-N real nonsymmetric matrix A, the - ////eigenvalue decomposition eigenvalues and right eigenvectors. - ////The right eigenvector v(j) of A satisfies - //// - //// A * v(j) = lambda(j) * v(j) - //// - ////where lambda(j) is its eigenvalue. - ////The computed eigenvectors are normalized to have Euclidean norm - ////equal to 1 and largest component real. Uses the LAPACK subroutine dgeev with arguments JOBVR = 'V' and JOBVL = 'N' - //// - ///Returns the real (first array) and imaginary (second array) parts of the eigenvalues and a matrix containing the corresponding eigenvectors - //abstract dgeev_ : Matrix -> double array * double array * Matrix - - ////Eigen Value of Symmetric Matrix - //abstract dsyev_ : char * char * Matrix -> Matrix * double array - - - ///Computes for a N-by-N real symmetric matrix A, the - ///eigenvalue decomposition of eigenvalues and right eigenvectors. - ///The right eigenvector v(j) of A satisfies - /// - /// A * v(j) = lambda(j) * v(j) - /// - ///where lambda(j) is its eigenvalue. - abstract dsyevd_ : Matrix -> Matrix * Vector - - ////Eigen Value for a pair of general matrices - //abstract dggev_ : - // Matrix * Matrix -> - // Matrix * Matrix * double array * double array * double array * - // double [,] - - ////Solve least-squares/min-norm. - ////Note the dimension requirements on second input to match second output. - //abstract dgels_ : Matrix * Matrix -> Matrix * Matrix - - ////Solve least-squares/min-norm (with linear equality constraint) - //abstract dgglse_ : - // Matrix * Matrix * Vector * Vector -> - // Matrix * Vector * double array - - ////Singular Value Decomposition - //abstract dgesvd_ : - // Matrix -> double array * Matrix * Matrix - - - ///Returns the full Singular Value Decomposition of the input MxN matrix - /// - ///A : A = U * SIGMA * V**T in the tuple (S, U, V**T), - /// - ///where S is an array containing the diagonal elements of SIGMA. - ///uses the LAPACK routine dgesdd with the argument JOBZ = 'A' - abstract dgesdd_ : Matrix -> double array * Matrix * Matrix - - ///rrqr - //abstract dgejsv_ : Matrix -> double array * Matrix * Matrix - - ///Returns the thin Singular Value Decomposition of the input MxN matrix A - /// - ///A = U * SIGMA * V**T in the tuple (S, U, V**T), - /// - ///where S is an array containing the diagonal elements of SIGMA. - ///The first min(M,N) columns of U and the first min(M,N) rows of V**T are returned in the arrays U and VT; - ///uses the LAPACK routine dgesdd with the argument JOBZ = 'S' - abstract dgesdd_thin_ : Matrix -> double array * Matrix * Matrix - - ////Single Value Decomposition for Symmetric Matrices - //abstract dsygv_ : - // Matrix * Matrix -> Matrix * Matrix * double array - - ////Single Value Decomposition for Symetric Matrices Divide and Conquer - //abstract dsygvd_ : - // Matrix * Matrix -> Matrix * Matrix * double array - - ////Cholesky Factorisation - //abstract dpotrf_ : char * Matrix -> Matrix - - //abstract dgetrf_ : matrix -> matrix * int[] - - ////Cholesky Factorisation - Expert - //abstract dposvx_ : - // Matrix * Matrix -> - // Matrix * Matrix * char * double array * Matrix * Matrix * - // float * double array * double array - - ////QR Factorisation - //abstract dgeqrf_ : Matrix -> Matrix * double array diff --git a/src/FSharp.Stats/Algebra/LinearAlgebraServiceMKL.fs b/src/FSharp.Stats/Algebra/LinearAlgebraServiceMKL.fs deleted file mode 100644 index 9eed14cba..000000000 --- a/src/FSharp.Stats/Algebra/LinearAlgebraServiceMKL.fs +++ /dev/null @@ -1,641 +0,0 @@ -namespace FSharp.Stats - -#nowarn "51" - -/// Warning: -/// IMPORTANT WARNING NOTICE: -/// INTEL MATH KERNEL LIBRARY 9.1 FOR WINDOWS IS THIRD PARTY TECHNOLOGY. -/// IT IS CLEARED ONLY FOR USE BY A SPECIFIC MSR RESEARCH TEAM. -/// DO NOT USE IT UNTIL YOU HAVE CLEARED ITS USE FOR YOUR PROJECT WITH YOUR LEGAL CONTACT. -/// -/// The following stubs bind directly to Intel MKL functionality. -/// You should not use them without: -/// a) Intel MKL developer licenses. -/// b) Seeking local legal approval. -module LapackMKLStubs = - - // [] - // [] - type CBLASLAYOUT = - | CblasRowMajor = 101 | CblasColMajor = 102 - - //[] - type CBLASTRANSPOSE = - | CblasNoTrans=111 | CblasTrans=112 | CblasConjTrans=113 - - - [] - //extern void dgemm_(char *transa, char *transb, int *m, int *n, int *k, double *alpha, double *a, int *lda, double *b, int *ldb, double *beta, double *c, int *ldc) - extern void dgemm_(CBLASLAYOUT *layout,CBLASTRANSPOSE *transa, CBLASTRANSPOSE *transb, int *m, int *n, int *k, double *alpha, double *a, int *lda, double *b, int *ldb, double *beta, double *c, int *ldc) - - // [] - // extern void dtrsv_(char *uplo,char *trans,char *diag,int *n,double *a,int *lda,double *x,int *incx) - - [] - extern void dtrsm_(char *side,char *uplo,char *trans,char *diag,int *m,int *n,double *alpha,double *a,int *lda,double *b,int *ldb) - - [] - extern void dgesv_(int *n, int *nrhs, double *a, int *lda, int *ipiv, double *b, int *ldb, int *info) - - [] - extern void dgeev_(char *jobvl, char *jobvr, int *n, double *a, int *lda, double *wr, double *wi, double *vl, int *ldvl, double *vr, int *ldvr, double *work, int *lwork, int *info) - // [] - // extern void dposv_(char *uplo, int *n, int *nrhs, double *a, int *lda, double *b, int *ldb, int *info) - - [] - extern void dgels_(char *trans, int *m,int *n, int *nrhs, double *a, int *lda, double *b, int *ldb, double *work, int *lwork, int *info) - - // [] - // extern void dgglse_(int *m, int *n, int *p, double *a, int *lda, double *b, int *ldb, double *c, double *d, double *x, double *work, int *lwork, int *info) - - [] - extern void dsyev_(char *jobz, char *uplo, int *n, double *a,int *lda, double *w, double *work, int *lwork, int *info) - - // [] - // extern void dsyevd_(char *jobz, char *uplo, int *n, double *a, int *lda, double *w, double *work, int *lwork, int *iwork, int *liwork, int *info) - - // Available - [] - extern void dgesvd_(char *jobu, char *jobvt, int *m, int *n, double *a, int *lda, double *s, double *u, int *ldu, double *vt, int *ldvt, double *work, int *lwork, int *info) - - [] - extern void dgesdd_(char *JOBZ, int *m, int *n, double *a, int *lda, double *s, double *u, int *ldu, double *vt, int *ldvt, double *work, int *lwork,int *iwork, int *info) - - [] - extern void dsygv_(int *itype, char *jobz, char *uplo, int *n, double *a, int *lda, double *b, int *ldb, double *w, double *work, int *lwork, int *info) - - [] - extern void dsygvd_(int *itype, char *jobz, char *uplo, int *n, double *a, int *lda, double *b, int *ldb, double *w, double *work, int *lwork,int *iwork, int *liwork, int *info) - - [] - extern void dggev_( char *jobvl, char *jobvr, int *n, double *a, int *lda, double *b, int *ldb, double *alphar, double *alphai,double *beta,double *vl,int *ldvl,double *vr,int *ldvr,double *work, int *lwork,int *info) - - [] - extern void dgesvx_(char *fact, char *trans, int *n, int *nrhs, double *a, int *lda, double *af, int *ldaf, int *ipiv, char *equed, double *r, double *c, double *b, int *ldb, double *x, int *ldx, double *rcond, double *ferr, double *berr, double *work, int *iwork, int *info) - - [] - extern void dposvx_(char *fact, char *uplo, int *n, int *nrhs, double *a, int *lda, double *af, int *ldaf, char *equed, double *s, double *b, int *ldb, double *x, int *ldx, double *rcond, double *ferr, double *berr, double *work, int *iwork, int *info) - - [] - extern void dpotrf_(char *uplo, int *n, double *a, int *lda, int *info) - - [] - extern void dgetrf_(int *m, int *n, double *a, int *lda, int *ipiv, int *info) - - [] - extern void dgeqrf_(int *m, int *n, double *a, int *lda, double *tau, double *work, int *lwork, int *info) - - [] - extern void dgemv_(int32* trans, int* m, int* n,double* alpha, double* A, int* lda,double* x, int* incx, double* beta,double* y, int* incy) - - -module BlasStubs = - - [] - extern void dgemm_(char *TRANSA, char *TRANSB, int *M, int *N, int *K, double *ALPHA, double *A, int *LDA, double *B, int *LDB, double *BETA, double *C, int *LDC) - - -module LapackStubs = - - [] - extern void dgesvd_(char* JOBU, char* JOBVT, int *M, int *N, double *A, int *LDA, double *S, double *U, int *LDU, double *VT, int *LDVT, double *WORK, int *LWORK, int *INFO) - - [] - extern void dgesdd_(char *JOBZ, int *M, int *N, double *A, int *LDA, double *S, double *U, int *LDU, double *VT, int *LDVT, double *WORK, int *LWORK, int *IWORK, int *INFO) - - //[] - //extern void dgejsv_(char *JOBA, char *JOBU, char *JOBV, char *JOBR, char *JOBT, char *JOBP, int *M, int *N, double *A, int *LDA, double *SVA, double *U, int *LDU, double *V, int *LDV, double *WORK, int *LWORK, int *IWORK, int *INFO) - - [] - extern void dgeev_(char *JOBVL, char *JOBVR, int *N, double *A, int *LDA, double *WR, double *WI, double *VL, int *LDVL, double *VR, int *LDVR, double *WORK, int *LWORK, int *INFO); - - [] - extern void dsyevd_(char *jobz, char *uplo, int *n, double *a, int *lda, double *w, double *work, int *lwork, int *iwork, int *liwork, int *info); - -open Microsoft.FSharp.NativeInterop -open LapackMKLStubs -open FSharp.Stats.Algebra - -/// Internal provider of MKL functionality, not for direct user usage. -type LinearAlgebraMKL() = - interface ILinearAlgebra with - - ///Matrix-Matrix Multiplication - member this.dgemm_ (a,b) = //(a:matrix) (b:matrix) = - // input copies - let a = Matrix.copy a - let b = Matrix.copy b - // dimensions - let m = NativeUtilities.matrixDim1 a in - let k = NativeUtilities.matrixDim2 a in - NativeUtilities.assertDimensions "dgemm_" ("k","Dim1(b)") (k,NativeUtilities.matrixDim1 b); - let n = NativeUtilities.matrixDim2 b in - // allocate results - let c = Matrix.zero (m) (n) - // transpose - let c = Matrix.transpose c - // setup actuals - let mutable arg_layout = CBLASLAYOUT.CblasColMajor //'t' - let mutable arg_transa = CBLASTRANSPOSE.CblasTrans//'t' - let mutable arg_transb = CBLASTRANSPOSE.CblasNoTrans//'t' - let mutable arg_m = m - let mutable arg_n = n - let mutable arg_k = k - let mutable arg_alpha = 1.0 - let arg_a = NativeUtilities.pinM a - let mutable arg_ldk = k - let arg_b = NativeUtilities.pinM b - let mutable arg_ldn = n - let mutable arg_beta = 1.0 - let arg_c = NativeUtilities.pinM c - let mutable arg_ldm = m - // call function - try - LapackMKLStubs.dgemm_(&&arg_layout,&&arg_transa,&&arg_transb,&&arg_m,&&arg_n,&&arg_k,&&arg_alpha,arg_a.Ptr,&&arg_ldk,arg_b.Ptr,&&arg_ldn,&&arg_beta,arg_c.Ptr,&&arg_ldm) - finally - NativeUtilities.freeM arg_a - NativeUtilities.freeM arg_b - NativeUtilities.freeM arg_c - // INFO - // fixups - let c = Matrix.transpose c - // result tuple - c - - - - - ///Singular Value Decomposition Divide- Conquer - member this.dgesdd_ (a:matrix) = - // input copies - let a = Matrix.copy a - // dimensions - let m = NativeUtilities.matrixDim1 a in - let n = NativeUtilities.matrixDim2 a in - // allocate results - let s = Array.zeroCreate (min m n) - let u = Matrix.zero (m) (m) - let vt = Matrix.zero (n) (n) - let work = Array.zeroCreate (1) - let iwork = Array.zeroCreate (8*(min m n)) - // transpose - let a = Matrix.transpose a - let u = Matrix.transpose u - let vt = Matrix.transpose vt - // setup actuals - let mutable arg_JOBZ = 'A' - let mutable arg_m = m - let mutable arg_n = n - let arg_a = NativeUtilities.pinM a - let mutable arg_lda = max 1 m - let arg_s = NativeUtilities.pinA s - let arg_u = NativeUtilities.pinM u - let mutable arg_ldu = m - let arg_vt = NativeUtilities.pinM vt - let mutable arg_ldvt = n - let arg_work = NativeUtilities.pinA work - let mutable arg_lwork = -1 - let arg_iwork = NativeUtilities.pinA iwork - let mutable arg_info = 0 - // ask for work array size - try - LapackMKLStubs.dgesdd_(&&arg_JOBZ,&&arg_m,&&arg_n,arg_a.Ptr,&&arg_lda,arg_s.Ptr,arg_u.Ptr,&&arg_ldu,arg_vt.Ptr,&&arg_ldvt,arg_work.Ptr,&&arg_lwork,arg_iwork.Ptr,&&arg_info) - finally - NativeUtilities.freeA arg_work - - if arg_info = 0 || arg_info=(-12) then - arg_lwork <- int32 work.[0] - else assert(false) - - let arg_work = NativeUtilities.pinA (Array.zeroCreate arg_lwork : float[]) - // call function - try - LapackMKLStubs.dgesdd_(&&arg_JOBZ,&&arg_m,&&arg_n,arg_a.Ptr,&&arg_lda,arg_s.Ptr,arg_u.Ptr,&&arg_ldu,arg_vt.Ptr,&&arg_ldvt,arg_work.Ptr,&&arg_lwork,arg_iwork.Ptr,&&arg_info) - finally - NativeUtilities.freeM arg_a - NativeUtilities.freeA arg_s - NativeUtilities.freeM arg_u - NativeUtilities.freeM arg_vt - NativeUtilities.freeA arg_work - NativeUtilities.freeA arg_iwork - // INFO - match arg_info with - | -1 -> failwith "dgesdd_: JOBZ (argument 1)" - | -2 -> failwith "dgesdd_: m (argument 2)" - | -3 -> failwith "dgesdd_: n (argument 3)" - | -4 -> failwith "dgesdd_: a (argument 4)" - | -5 -> failwith "dgesdd_: lda (argument 5)" - | -6 -> failwith "dgesdd_: s (argument 6)" - | -7 -> failwith "dgesdd_: u (argument 7)" - | -8 -> failwith "dgesdd_: ldu (argument 8)" - | -9 -> failwith "dgesdd_: vt (argument 9)" - | -10 -> failwith "dgesdd_: ldvt (argument 10)" - | -11 -> failwith "dgesdd_: work (argument 11)" - | -12 -> failwith "dgesdd_: lwork (argument 12)" - | -13 -> failwith "dgesdd_: iwork (argument 13)" - | -14 -> failwith "dgesdd_: info (argument 14)" - | 0 -> () - | n -> failwith (sprintf "dgesdd_ : returned %d. The computation failed." n) - // fixups - let u = Matrix.transpose u - let vt = Matrix.transpose vt - // result tuple - s,u,vt - - member this.dgesdd_thin_(a:matrix) = - printfn "Function not implemented yet, use the lapack provider" - ([||],matrix[||],matrix[||]) - - member this.dsyevd_(a:matrix) = - printfn "Function not implemented yet, use the lapack provider" - (matrix[||],vector [||]) - - //member this.dgeev_(a:Matrix) = - // Array.zeroCreate 0, Array.zeroCreate 0, matrix [||] - - -/// Internal provider of Lapack functionality, not for direct user usage. -type LinearAlgebraLAPACK() = - interface ILinearAlgebra with - //Matrix-Matrix Multiplication - member this.dgemm_ (a:Matrix,b:Matrix) = - - // input copies - let a = Matrix.copy a - let b = Matrix.copy b - - // dimensions - let m = NativeUtilities.matrixDim1 a in - let k = NativeUtilities.matrixDim2 a in - NativeUtilities.assertDimensions "dgemm_" ("k","Dim1(b)") (k,NativeUtilities.matrixDim1 b); - let n = NativeUtilities.matrixDim2 b in - - // allocate results - let c = Matrix.zero (m) (n) - - // transpose - let c = Matrix.transpose c - //setup actuals ------------------------------------------------------------ - //computation type and scalars - let mutable arg_TRANSA = 'T' - let mutable arg_TRANSB = 'T' - let mutable arg_alpha = 1. - let mutable arg_beta = 0. - - //dimensions of input arrays - let mutable arg_m = m - let mutable arg_n = n - let mutable arg_k = k - - let mutable arg_lda = max 1 k - let mutable arg_ldb = max 1 n - let mutable arg_ldc = max 1 m - - let arg_a = NativeUtilities.pinM a - let arg_b = NativeUtilities.pinM b - let arg_c = NativeUtilities.pinM c - - try - printfn "calling dgemm ..." - BlasStubs.dgemm_(&&arg_TRANSA,&&arg_TRANSB,&&arg_m,&&arg_n,&&arg_k,&&arg_alpha,arg_a.Ptr,&&arg_lda,arg_b.Ptr,&&arg_ldb,&&arg_beta,arg_c.Ptr,&&arg_ldc) - finally - NativeUtilities.freeM arg_a - NativeUtilities.freeM arg_b - NativeUtilities.freeM arg_c - - let c = Matrix.transpose c - // result tuple - c - //Full SVD - member this.dgesdd_(a:Matrix) = - - // input copies - let a = Matrix.copy a - // dimensions - let m = NativeUtilities.matrixDim1 a in - let n = NativeUtilities.matrixDim2 a in - - let s = Array.zeroCreate (min m n) - let u = Matrix.zero (m) (m) - let vt = Matrix.zero (n) (n) - let work = Array.zeroCreate (1) - let iwork = Array.zeroCreate (8*(min m n)) - - // transpose - let a = Matrix.transpose a - let u = Matrix.transpose u - let vt = Matrix.transpose vt - - //setup actuals ------------------------------------------------------------ - //computation type - let mutable arg_JOBZ = 'A' - - //dimensions of input array a - let mutable arg_m = m - let mutable arg_n = n - - //output matrices and their leading dimensions - let mutable arg_lda = max 1 m - let mutable arg_ldu = m - let mutable arg_ldvt = n - - let arg_s = NativeUtilities.pinA s - let arg_a = NativeUtilities.pinM a - let arg_u = NativeUtilities.pinM u - let arg_vt = NativeUtilities.pinM vt - - //workspaces - let arg_work = NativeUtilities.pinA work - let mutable arg_lwork = -1 - let arg_iwork = NativeUtilities.pinA iwork - let mutable arg_info = 0 - - try - LapackStubs.dgesdd_(&&arg_JOBZ,&&arg_m,&&arg_n,arg_a.Ptr,&&arg_lda,arg_s.Ptr,arg_u.Ptr,&&arg_ldu,arg_vt.Ptr,&&arg_ldvt,arg_work.Ptr,&&arg_lwork,arg_iwork.Ptr,&&arg_info ) - finally - NativeUtilities.freeA arg_work - - //get workspace size - if arg_info = 0 || arg_info=(-12) then - arg_lwork <- int32 work.[0] - else assert(false) - - //assign workspace size to the work array - let arg_work = NativeUtilities.pinA (Array.zeroCreate arg_lwork : float[]) - //call dgesdd_ - try - LapackStubs.dgesdd_(&&arg_JOBZ,&&arg_m,&&arg_n,arg_a.Ptr,&&arg_lda,arg_s.Ptr,arg_u.Ptr,&&arg_ldu,arg_vt.Ptr,&&arg_ldvt,arg_work.Ptr,&&arg_lwork,arg_iwork.Ptr,&&arg_info ) - finally - NativeUtilities.freeM arg_a - NativeUtilities.freeA arg_s - NativeUtilities.freeM arg_u - NativeUtilities.freeM arg_vt - NativeUtilities.freeA arg_work - NativeUtilities.freeA arg_iwork - //fail if info contains an error code - match arg_info with - | -1 -> failwith "dgesdd_: JOBZ (argument 1)" - | -2 -> failwith "dgesdd_: m (argument 2)" - | -3 -> failwith "dgesdd_: n (argument 3)" - | -4 -> failwith "dgesdd_: a (argument 4)" - | -5 -> failwith "dgesdd_: lda (argument 5)" - | -6 -> failwith "dgesdd_: s (argument 6)" - | -7 -> failwith "dgesdd_: u (argument 7)" - | -8 -> failwith "dgesdd_: ldu (argument 8)" - | -9 -> failwith "dgesdd_: vt (argument 9)" - | -10 -> failwith "dgesdd_: ldvt (argument 10)" - | -11 -> failwith "dgesdd_: work (argument 11)" - | -12 -> failwith "dgesdd_: lwork (argument 12)" - | -13 -> failwith "dgesdd_: iwork (argument 13)" - | -14 -> failwith "dgesdd_: info (argument 14)" - | 0 -> () - | n -> failwith (sprintf "dgesdd_ : returned %d. The computation failed." n) - - // fixups - let u = Matrix.transpose u - let vt = Matrix.transpose vt - // result tuple - s,u,vt - - //Thin SVD - member this.dgesdd_thin_(a:Matrix) = - // input copies - let a = Matrix.copy a - // dimensions - let m = NativeUtilities.matrixDim1 a in - let n = NativeUtilities.matrixDim2 a in - - let s = Array.zeroCreate (min m n) - let u = Matrix.zero (m) (n) - let vt = Matrix.zero (n) (n) - let work = Array.zeroCreate (1) - let iwork = Array.zeroCreate (8*(min m n)) - - //setup actuals ------------------------------------------------------------ - //computation type - let mutable arg_JOBZ = 'S' - - //dimensions of input array a - let mutable arg_m = m - let mutable arg_n = n - - //output matrices and their leading dimensions - let mutable arg_ldu = m - let mutable arg_ldvt = n - let mutable arg_lda = max 1 m - - // transpose - let a = Matrix.transpose a - let u = Matrix.transpose u - let vt = Matrix.transpose vt - - let arg_s = NativeUtilities.pinA s - let arg_a = NativeUtilities.pinM a - let arg_u = NativeUtilities.pinM u - let arg_vt = NativeUtilities.pinM vt - - //workspaces - let arg_work = NativeUtilities.pinA work - let mutable arg_lwork = -1 - let arg_iwork = NativeUtilities.pinA iwork - let mutable arg_info = 0 - - try - LapackStubs.dgesdd_(&&arg_JOBZ,&&arg_m,&&arg_n,arg_a.Ptr,&&arg_lda,arg_s.Ptr,arg_u.Ptr,&&arg_ldu,arg_vt.Ptr,&&arg_ldvt,arg_work.Ptr,&&arg_lwork,arg_iwork.Ptr,&&arg_info ) - finally - NativeUtilities.freeA arg_work - - //get workspace size - if arg_info = 0 || arg_info=(-12) then - arg_lwork <- int32 work.[0] - else assert(false) - - //assign workspace size to the work array - let arg_work = NativeUtilities.pinA (Array.zeroCreate arg_lwork : float[]) - //call dgesdd_ - try - LapackStubs.dgesdd_(&&arg_JOBZ,&&arg_m,&&arg_n,arg_a.Ptr,&&arg_lda,arg_s.Ptr,arg_u.Ptr,&&arg_ldu,arg_vt.Ptr,&&arg_ldvt,arg_work.Ptr,&&arg_lwork,arg_iwork.Ptr,&&arg_info ) - finally - NativeUtilities.freeM arg_a - NativeUtilities.freeA arg_s - NativeUtilities.freeM arg_u - NativeUtilities.freeM arg_vt - NativeUtilities.freeA arg_work - NativeUtilities.freeA arg_iwork - //fail if info contains an error code - match arg_info with - | -1 -> failwith "dgesdd_: JOBZ (argument 1)" - | -2 -> failwith "dgesdd_: m (argument 2)" - | -3 -> failwith "dgesdd_: n (argument 3)" - | -4 -> failwith "dgesdd_: a (argument 4)" - | -5 -> failwith "dgesdd_: lda (argument 5)" - | -6 -> failwith "dgesdd_: s (argument 6)" - | -7 -> failwith "dgesdd_: u (argument 7)" - | -8 -> failwith "dgesdd_: ldu (argument 8)" - | -9 -> failwith "dgesdd_: vt (argument 9)" - | -10 -> failwith "dgesdd_: ldvt (argument 10)" - | -11 -> failwith "dgesdd_: work (argument 11)" - | -12 -> failwith "dgesdd_: lwork (argument 12)" - | -13 -> failwith "dgesdd_: iwork (argument 13)" - | -14 -> failwith "dgesdd_: info (argument 14)" - | 0 -> () - | n -> failwith (sprintf "dgesdd_ : returned %d. The computation failed." n) - - // fixups - let u = Matrix.transpose u - let vt = Matrix.transpose vt - // result tuple - s,u,vt - - //Eigenvalue decomposition of a real non-symmetric square matrix - //member this.dgeev_(a:Matrix) = - // // input copies - // let a = Matrix.copy a - // // dimensions - // let n = NativeUtilities.matrixDim1 a in - // NativeUtilities.assertDimensions "dgeev_" ("n","Dim2(a)") (n,NativeUtilities.matrixDim2 a); - // // allocate results - // let wr = Array.zeroCreate (n) - // let wi = Array.zeroCreate (n) - // let vl = Matrix.zero (n) (n) - // let vr = Matrix.zero (n) (n) - // let work = Array.zeroCreate (1) - // // transpose - // let a = Matrix.transpose a - // // setup actuals - // let mutable arg_jobvl = 'N' - // let mutable arg_jobvr = 'V' - // let mutable arg_n = n - // let arg_a = NativeUtilities.pinM a - // let mutable arg_lda = n - // let arg_wr = NativeUtilities.pinA wr - // let arg_wi = NativeUtilities.pinA wi - // let arg_vl = NativeUtilities.pinM vl - // let mutable arg_ldvl = n - // let arg_vr = NativeUtilities.pinM vr - // let mutable arg_ldvr = n - // let arg_work = NativeUtilities.pinA work - // let mutable arg_lwork = -1 - // let mutable arg_info = 0 - // //workspace query - // try - // LapackStubs.dgeev_(&&arg_jobvl,&&arg_jobvr,&&arg_n,arg_a.Ptr,&&arg_lda,arg_wr.Ptr,arg_wi.Ptr,arg_vl.Ptr,&&arg_ldvl,arg_vr.Ptr,&&arg_ldvr,arg_work.Ptr,&&arg_lwork,&&arg_info) - // finally - // NativeUtilities.freeA arg_work - // //get workspace size - // if arg_info = 0 || arg_info=(-12) then - // arg_lwork <- int32 work.[0] - // else assert(false) - // //assign workspace size to the work array - // let arg_work = NativeUtilities.pinA (Array.zeroCreate arg_lwork : float[]) - // //call function - // try - // LapackStubs.dgeev_(&&arg_jobvl,&&arg_jobvr,&&arg_n,arg_a.Ptr,&&arg_lda,arg_wr.Ptr,arg_wi.Ptr,arg_vl.Ptr,&&arg_ldvl,arg_vr.Ptr,&&arg_ldvr,arg_work.Ptr,&&arg_lwork,&&arg_info) - // finally - // NativeUtilities.freeM arg_a - // NativeUtilities.freeA arg_wr - // NativeUtilities.freeA arg_wi - // NativeUtilities.freeM arg_vl - // NativeUtilities.freeM arg_vr - // NativeUtilities.freeA arg_work - // // INFO - // match arg_info with - // | -1 -> failwith "dgeev_: jobvl (argument 1)" - // | -2 -> failwith "dgeev_: jobvr (argument 2)" - // | -3 -> failwith "dgeev_: n (argument 3)" - // | -4 -> failwith "dgeev_: a (argument 4)" - // | -5 -> failwith "dgeev_: lda (argument 5)" - // | -6 -> failwith "dgeev_: wr (argument 6)" - // | -7 -> failwith "dgeev_: wi (argument 7)" - // | -8 -> failwith "dgeev_: vl (argument 8)" - // | -9 -> failwith "dgeev_: ldvl (argument 9)" - // | -10 -> failwith "dgeev_: vr (argument 10)" - // | -11 -> failwith "dgeev_: ldvr (argument 11)" - // | -12 -> failwith "dgeev_: work (argument 12)" - // | -13 -> failwith "dgeev_: lwork (argument 13)" - // | -14 -> failwith "dgeev_: info (argument 14)" - // | 0 -> () - // | n -> failwith (sprintf "dgeev_ : returned %d. The computation failed." n) - // // fixups - // let vr = Matrix.transpose vr - // // result tuple - // wr,wi,vr - - ///Eigen Value Decomposition of Symmetric Matrix - member this.dsyevd_(a:matrix) = - - let jobz = 'V' - let uplo = 'L' - // input copies - let a = Matrix.copy a - // dimensions - let n = NativeUtilities.matrixDim1 a in - NativeUtilities.assertDimensions "dsyevd_" ("n","Dim2(a)") (n,NativeUtilities.matrixDim2 a); - // allocate results - let w = Array.zeroCreate (n) - let work = Array.zeroCreate (1) - let iwork = Array.zeroCreate (1) - // transpose - let a = Matrix.transpose a - // setup actuals - let mutable arg_jobz = jobz - let mutable arg_uplo = uplo - let mutable arg_n = n - let arg_a = NativeUtilities.pinM a - let mutable arg_lda = max 1 n - let arg_w = NativeUtilities.pinA w - let arg_work = NativeUtilities.pinA work - let mutable arg_lwork = -1 - let arg_iwork = NativeUtilities.pinA iwork - let mutable arg_liwork = -1 - let mutable arg_info = 0 - // ask for work array size - try - LapackStubs.dsyevd_(&&arg_jobz,&&arg_uplo,&&arg_n,arg_a.Ptr,&&arg_lda,arg_w.Ptr,arg_work.Ptr,&&arg_lwork,arg_iwork.Ptr,&&arg_liwork,&&arg_info) - finally - NativeUtilities.freeA arg_work - NativeUtilities.freeA arg_iwork - if arg_info = 0 || arg_info=(-8) || arg_info=(-10) then - arg_lwork <- int32 work.[0] - arg_liwork <- iwork.[0] - else assert(false) - let arg_work = NativeUtilities.pinA (Array.zeroCreate arg_lwork : float[]) - let arg_iwork = NativeUtilities.pinA (Array.zeroCreate arg_liwork : int[]) - // call function - try - LapackStubs.dsyevd_(&&arg_jobz,&&arg_uplo,&&arg_n,arg_a.Ptr,&&arg_lda,arg_w.Ptr,arg_work.Ptr,&&arg_lwork,arg_iwork.Ptr,&&arg_liwork,&&arg_info) - finally - NativeUtilities.freeM arg_a - NativeUtilities.freeA arg_w - NativeUtilities.freeA arg_work - NativeUtilities.freeA arg_iwork - // INFO - match arg_info with - | -1 -> failwith "dsyevd_: jobz (argument 1)" - | -2 -> failwith "dsyevd_: uplo (argument 2)" - | -3 -> failwith "dsyevd_: n (argument 3)" - | -4 -> failwith "dsyevd_: a (argument 4)" - | -5 -> failwith "dsyevd_: lda (argument 5)" - | -6 -> failwith "dsyevd_: w (argument 6)" - | -7 -> failwith "dsyevd_: work (argument 7)" - | -8 -> failwith "dsyevd_: lwork (argument 8)" - | -9 -> failwith "dsyevd_: iwork (argument 9)" - | -10 -> failwith "dsyevd_: liwork (argument 10)" - | -11 -> failwith "dsyevd_: info (argument 11)" - | 0 -> () - | n -> failwith (sprintf "dsyevd_ : returned %d. The computation failed." n) - // fixups - let a = Matrix.transpose a - // result tuple - a,vector w - - - -module ProviderService = - let MKLProvider = ServiceLocator.createProviderX64 "MKL" [|"mkl.dll"|] ServiceLocator.OS.Windows (fun () -> new LinearAlgebraMKL() :> ILinearAlgebra) - let LAPACKProvider = ServiceLocator.createProviderX64 "LAPACK" [|"libblas.dll";"liblapack.dll";"libgcc_s_seh-1.dll";"libgfortran-4.dll";"libquadmath-0.dll";"libwinpthread-1.dll"|] ServiceLocator.OS.Windows (fun () -> new LinearAlgebraLAPACK() :> ILinearAlgebra) - - - - - diff --git a/src/FSharp.Stats/Algebra/LinearAlgebraServiceManaged.fs b/src/FSharp.Stats/Algebra/LinearAlgebraServiceManaged.fs deleted file mode 100644 index 5a3c43bde..000000000 --- a/src/FSharp.Stats/Algebra/LinearAlgebraServiceManaged.fs +++ /dev/null @@ -1,643 +0,0 @@ -// (c) Microsoft Corporation 2005-2009. - -namespace FSharp.Stats.Algebra - -open FSharp.Stats -/// This module is for internal use only. -module LinearAlgebraManaged = - open System - - //let a = 1. - - let private matrixDims (m:Matrix<_>) = m.NumRows, m.NumCols - - let NYI () = failwith "Not yet implemented, managed fallback linear algebra ops coming soon" - - //type Permutation = Permutation of int * (int -> int) - - let SVD (a:matrix) = - let (umatrix,s,vmatrix) = SVD.computeInPlace (a.ToArray2D()) - //Matrix.diag - Vector.ofArray s,Matrix.ofArray2D umatrix,Matrix.ofArray2D vmatrix - //(Matrix.ofArray2D umatrix,s,Matrix.ofArray2D vmatrix) - - let symmetricEigenspectrum (a:matrix) = - let (e,v,d) = EVD.symmetricEvd (a.ToArray2D()) - (Matrix.ofArray2D v,vector d) - - - let EigenSpectrum A = NYI() - let Condition A = NYI() - - let eigenvectors m = NYI() - let eigenvalues m = NYI() - let symmetricEigenvalues a = NYI() - let symmetricEigenvectors a = NYI() - - let SolveTriangularLinearSystems K B isLower = - if isLower then - let (nK,mK) = matrixDims K - let (nB,mB) = matrixDims B - if nK<>mK || nB<> nK then invalidArg "Matrix" "Cannot do backward substitution on non-square matrices." - let X = Matrix.zero(max nB nK) (max mB mK) // t - for i=0 to nK-1 do - for k=0 to mB-1 do - let s = ref B.[i,k] - for j=0 to i-1 do - s := !s - K.[i,j] * X.[j,k] - done - X.[i,k] <- !s / K.[i,i] - done - done - X - else - let (nK,mK) = matrixDims K - let (nB,mB) = matrixDims B - if nK<>mK || nB<> nK then invalidArg "Matrix" "Cannot do backward substitution on non-square matrices." - let X = Matrix.zero (max nB nK) (max mB mK) //t - for i=0 to nK-1 do - for k=0 to mB-1 do - let s = ref B.[nK-i-1,k] - for j=0 to i-1 do - s := !s - K.[nK-i-1,nK-j-1] * X.[nK-j-1,k] - done - X.[nK-i-1,k] <- !s / K.[nK-i-1,nK-i-1] - done - done - X - - let SolveTriangularLinearSystem K v isLower = Matrix.getCol (SolveTriangularLinearSystems K (Matrix.ofVector v) isLower) 0 - - type range = int * int - - let inline sumfR f ((a,b):range) = - let mutable res = 0.0 in - for i = a to b do - res <- res + f i - res - - - let Cholesky (a: matrix) = - let nA,mA = a.Dimensions - if nA<>mA then invalidArg "Matrix" "choleskyFactor: not square"; - let lres = Matrix.zero nA nA (* nA=mA *) - for j=0 to nA-1 do - for i=j to nA-1 do (* j <= i *) - (* Consider a_ij = sum(k=0...n-1) (lres_ik . lresT_kj) - * = sum(k=0...n-1) (lres_ik . lres_jk) - * = sum(k=0...j-1) (lres_ik . lres_jk) + lres_ij . lres_jj + (0 when k>j) - * = psum + lres_ij . lres_jj - * This determines lres_ij terms of preceeding terms. - * lres_ij depends on lres_ik and lres_jk (and maybe lres_ii) for k lres.[i,k] * lres.[j,k]) (0,j-1) - let aij = a.[i,j] - if i=j then - let t = (aij - psum) - if t >= 0.0 then lres.[i,i] <- (System.Math.Sqrt t) else invalidArg "Matrix" "choleskyFactor: not symmetric postive definite" - else - lres.[i,j] <- ((aij - psum) / lres.[j,j]) - done - done; - // if not (isLowerTriangular lres) then failwith "choleskyFactor: not lower triangular result"; - lres.Transpose // REVIEW optimize this so we don't have to take transpose ... - - - /// For a matrix A, the LU factorization is a pair of lower triangular matrix L and upper triangular matrix U so that A = L*U.
The pivot function encode a permutation operation such for a matrix P P*A = L*U.
- /// - /// - /// - /// - /// - /// - /// - let LU A = - let (nA,mA) = matrixDims A - if nA<>mA then invalidArg "Matrix" "lu: not square" - let L = Matrix.zero nA nA - let U = Matrix.copy A - let P = [| 0 .. nA-1 |] - let abs (x:float) = System.Math.Abs x - let swapR X i j = // REVIEW should we make this a general method? - let (nX,mX) = matrixDims X - let t = X.[i .. i,0 .. ] - for k=0 to mX-1 do - X.[i,k] <- X.[j,k] - X.[j,k] <- t.[0,k] - done - - for i=0 to nA-2 do - let mutable maxi = i // Find the biggest pivot element. - for k=i+1 to nA-1 do - if abs(U.[maxi,i]) < abs(U.[k,i]) then maxi <- k - done - //let maxi = maxIndex (i+1) (nA-1) (fun k -> abs(U.[k,i])) - - if maxi <> i then - swapR U i maxi // Swap rows if needed. - swapR L i maxi // REVIEW can be made more performant. - let t = P.[i] - P.[i] <- P.[maxi] - P.[maxi] <- t - - for j=i+1 to nA-1 do - L.[j,i] <- U.[j,i] / U.[i,i] - for k=i+1 to nA-1 do - U.[j,k] <- U.[j,k] - L.[j,i] * U.[i,k] - done - U.[j,i] <- 0.0 - done - done - (((*P.Length,*)Permutation.ofArray P),L + Matrix.identity nA,U) - //(P, L + (Matrix.identity nA), U) - - /// Solves a system of linear equations, AX = B, with A LU factorized. - /// - /// - /// - /// - /// - /// - /// - /// - let SolveLinearSystem (A:matrix) (b:vector) = - let (n,m) = matrixDims A - if n <> m then invalidArg "Matrix" "Matrix must be square." - let P,L,U = LU A - (SolveTriangularLinearSystem U (SolveTriangularLinearSystem L (b.Permute P) true) false) - - /// Solves a system of linear equations, Ax = b, with A LU factorized. - /// - /// - /// - /// - /// - /// - /// - /// - let SolveLinearSystems (A:matrix) (B:matrix) = - let (n,m) = matrixDims A - if n <> m then invalidArg "Matrix" "Matrix must be square." - let P,L,U = LU A - (SolveTriangularLinearSystems U (SolveTriangularLinearSystems L (B.PermuteRows P) true) false) - - let Inverse A = - let (n,m) = matrixDims A - if n <> m then invalidArg "Matrix" "Matrix must be square when computing its inverse." - let P,L,U = LU A - (SolveTriangularLinearSystems U (SolveTriangularLinearSystems L ((Matrix.identity n).PermuteRows P) true) false) - - /// Generates a unit vector [1 0 .. 0 ]. - /// - /// - /// - /// - /// - /// - /// - let unitV k = let e = Vector.create k 0.0 in e.[0] <- 1.0; e - - /// Computes the sign of a floating point number. - /// - /// - /// - /// - /// - /// - /// - let sign (f: float) = float (System.Math.Sign f) // REVIEW put in float library. - - /// This method computes and performs a Householder reflection. It will change the
input matrix and return the reflection vector.
- /// - /// - /// - /// - /// - /// - /// - /// - let HouseholderTransform (A:matrix) (i:int) = - // REVIEW do this using views and get rid of the i. - let (n,m) = matrixDims A - //Old: let x = A.[i..,i..i].Column 0 // Get part of the i'th column of the matrix. - let x = Matrix.getCol A.[i..,i..i] 0 // Get part of the i'th column of the matrix. - let nx = Vector.norm x - let vu = x + sign(x.[0]) * nx * (unitV (n-i)) // Compute the reflector. - let v = 1.0/(Vector.norm vu) * vu // Normalize reflector. - - // Perform the reflection. - let v'A = RowVector.init (m-i) (fun j -> v.Transpose * (A.[i..,i+j..i+j].Column 0)) - for l=i to n-1 do - for k=i to m-1 do - A.[l,k] <- A.[l,k] - 2.0 * v.[l-i] * v'A.[k-i] - v // Return reflection vector. - - /// QR factorization function for dense matrices - /// - /// - /// - /// - /// - /// - /// - let QRDense (A:matrix) = - let (n,m) = matrixDims A - let mutable Q = Matrix.identity n // Keeps track of the orthogonal matrix. - let R = Matrix.copy A - - // This method will update the orhogonal transformation fast when given a reflection vector. - let UpdateQ (qm:matrix) (v:vector) = - let n = Vector.length v - let (nQ,mQ) = matrixDims qm - - // Cache the computation of Q*v. - let Qv = Vector.init nQ (fun i -> (qm.[i..i,nQ-n..].Row 0) * v) - - // Update the orthogonal transformation. - for i=0 to nQ-1 do - for j=nQ-n to nQ-1 do - qm.[i,j] <- qm.[i,j] - 2.0 * Qv.[i] * v.[j-nQ+n] - () - - // This QR implementation keeps the unreduced part of A in R. It computes reflectors one at a time - // and reduces R column by column. In the process it keeps track of the Q matrix. - for i=0 to (min n m)-1 do - let v = HouseholderTransform R i - UpdateQ Q v - Q,R - - /// QR factorization function for sparse matrices, returns Q as a product of givens rotations and R as upper triangular - /// - /// - /// - /// - /// - /// - /// - let QRSparse (A:SparseMatrix) = - - /// Copies the row of a Sparsematrix into a Sparsevector - /// - /// - /// - /// - /// - /// - /// - /// - /// - let CopyRow (nnz:int) (offset:int) (A:SparseMatrix) = - let sparseVector = ResizeArray<(int*float)>() - for i=nnz-1 downto 0 do - if(not (A.SparseValues.[i+offset] = 0.0)) then - let entry = (A.SparseColumnValues.[i+offset], A.SparseValues.[i+offset]) - sparseVector.Insert(0, entry) - sparseVector - - /// Returns "value" with the sign of "sign" - /// - /// - /// - /// - /// - /// - /// - /// - let Copysign (value:float) (sign:float) = - if (sign >= 0.0) then - abs(value) - else // sign is negative - if(value < 0.0) then - value - else - value * -1.0 - - let Encode(c:float) (s:float) = - if(abs(s) < c) then - s - else - Copysign (1.0/c) s - - /// Apply the givens rotation on 2 Sparsevectors - /// - /// - /// - /// - /// - /// - /// - let ApplyGivens (x : ResizeArray<(int*float)>) (y : ResizeArray<(int*float)>) = - let a = snd x.[0] - let b = snd y.[0] - - let mutable c = -1.0 - let mutable s = -1.0 - - if (b = 0.0) then - c <- 1.0 - s <- 0.0 - else - if (abs(b) > abs(a)) then - let tau = -a / b - s <- 1.0 / sqrt(1.0 + tau * tau) - c <- s * tau - if (c < 0.0) then - c <- -c - s <- -s - else - let tau = -b/a - c <- 1.0 / sqrt(1.0 + tau * tau) - s <- c * tau - - // Rotate the start of each list - x.[0] <- (fst x.[0], c * a - s * b) - //was return first and remove after, is returned value ever needed? - y.RemoveAt 0 - - // Iterators - let mutable p = 0 - let mutable q = 0 - p <- p + 1 // Skip the first entry since we already handled it above - - while (p < x.Count && q < y.Count) do - if (fst x.[p] = fst y.[q]) then - let xNew = c * snd x.[p] - s * snd y.[q] - let yNew = s * snd x.[p] + c * snd y.[q] - if (not (xNew = 0.0)) then - x.[p] <- (fst x.[p], xNew) - p <- p + 1 - else - x.RemoveAt(p) - if ( not (yNew = 0.0)) then - y.[q] <- (fst y.[q], yNew) - q <- q + 1 - else - y.RemoveAt(q) - else if(fst x.[p] < fst y.[q]) then - let k = fst x.[p] - let xNew = c * snd x.[p] - let yNew = s * snd x.[p] - x.[p] <- (fst x.[p] , xNew) - p <-p + 1 - y.Insert(q,(k, yNew)) - q <- q + 1 - else - let k = fst y.[q] - let xNew= -s * snd y.[q] - let yNew= c * snd y.[q] - x.Insert(p,(k, xNew)) - p <- p + 1 - y.[q] <- (fst y.[q], yNew) - q <- q + 1 - if(p < x.Count) then - while(p < x.Count) do - let k = fst x.[p] - let xNew = c * snd x.[p] - let yNew = s * snd x.[p] - x.[p] <- (fst x.[p], xNew) - p <- p + 1 - y.Insert(q,(k, yNew)) - q <- q + 1 - else if(q < y.Count) then - while(q < y.Count) do - let k = fst y.[q] - let xNew = -s * snd y.[q] - let yNew = c * snd y.[q] - x.Insert(p,(k, xNew)) - p <- p + 1 - y.[q] <- (fst y.[q], yNew) - q <- q + 1 - - Encode c s - - // Run Sparse QR - let m = A.NumRows - let n = A.NumCols - let mutable Q = new ResizeArray>() - let mutable R = new ResizeArray>() - - for i = 0 to m - 1 do - Q.Add(ResizeArray<(int*float)>()) - R.Add(ResizeArray<(int*float)>()) - - for a = 0 to m-1 do - let mutable row = CopyRow (A.SparseRowOffsets.[a+1] - A.SparseRowOffsets.[a]) A.SparseRowOffsets.[a] A - let mutable q = 0 - while((not (row.Count <= 0)) && fst row.[0] < a && fst row.[0] < n) do - let j = fst row.[0] - - if((R.[j].Count <= 0) || fst R.[j].[0] > j) then - let temp = new ResizeArray<(int*float)> (row) - row <- new ResizeArray<(int*float)>(R.[a]) - R.[a] <- new ResizeArray<(int*float)>(temp) - Q.[a].Insert(q, (j, 1.0)) - q <- q + 1 - () - else - let ret = ApplyGivens R.[j] row - Q.[a].Insert(q, (j, ret)) - q <- q + 1 - () - if (a < n) then - let temp = new ResizeArray<(int*float)> (row) - row <- new ResizeArray<(int*float)>(R.[a]) - R.[a] <- new ResizeArray<(int*float)>(temp) - () - - let mutable x = 0 - - let RSeq = seq{ for row in R do - for entry in row do - yield(x, fst entry, snd entry) - x <- x+1 - } - - - let ROut = Matrix.initSparse m n RSeq - - x <- 0 - let QSeq = seq{ for row in Q do - for entry in row do - yield(x, fst entry, snd entry) - x <- x+1 - } - - let QOut = Matrix.initSparse m n QSeq - QOut, ROut - - /// Matches the union type of the matrix and invokes the according QR factorization function - /// - /// - /// - /// - /// - /// - /// - let QR (A:matrix) = - match A with - | SparseRepr A -> QRSparse(A) - | DenseRepr _ -> QRDense(A) - - let Hessenberg (A:matrix) = - // REVIEW we can do with less copying here. - let (n,m) = matrixDims A - if n<>m then invalidArg "Matrix A" "Currently only implemented for square matrices." - let mutable Q = Matrix.identity n // Keeps track of the orthogonal matrix. - let R = A.[1..,*] - - // This method will update the orhogonal transformation fast when given a reflection vector. - let UpdateQ (qm:Matrix) (v:vector) = - let n = Vector.length v - let (nQ,mQ) = matrixDims qm - - // Cache the computation of Q*v. - let Qv = Vector.init nQ (fun i -> (qm.[i..i,nQ-n..].Row 0) * v) - - // Update the orthogonal transformation. - for i=0 to nQ-1 do - for j=nQ-n to nQ-1 do - qm.[i,j] <- qm.[i,j] - 2.0 * Qv.[i] * v.[j-nQ+n] - () - - // This QR implementation keeps the unreduced part of A in R. It computes reflectors one at a time - // and reduces R column by column. In the process it keeps track of the Q matrix. - for i=0 to n-2 do - let v = HouseholderTransform R i - UpdateQ Q v - Q,Matrix.init n m (fun i j -> if i = 0 then A.[i,j] else R.[i-1,j]) - - let leastSquares A (b: vector) = - - // Q.transpose * b for sparse Q - let MultiplyVectorWithTransposeGivensMatrix (q:SparseMatrix, b:vector) = - let outVec = vector b - let m = q.NumRows - for i = 0 to m-1 do - for j = q.SparseRowOffsets.[i] to (q.SparseRowOffsets.[i+1] - 1) do - let k = q.SparseColumnValues.[j] - if(q.SparseValues.[j] = 1.0) then - let temp = outVec.[i] - outVec.[i] <- outVec.[k] - outVec.[k] <- temp - else - let tau = q.SparseValues.[j] - let mutable c = -1.0 - let mutable s = -1.0 - if(abs(tau) < 1.0) then - s <- tau - c <- sqrt(1.0-s*s) - else - c <- 1.0/tau - s <- sqrt(1.0-c*c) - if(c < 0.0) then - c <- -c - s <- -s - let newxk = c * outVec.[k] - s * outVec.[i] - outVec.[i] <- s * outVec.[k] + c * outVec.[i] - outVec.[k] <- newxk - outVec - - let (m,n) = matrixDims A - let Qm, R = QR A - let mutable Qtb = vector [||] - - match Qm with - | DenseRepr _ -> - Qtb <- Qm.Transpose * b - | SparseRepr qm -> - Qtb <- MultiplyVectorWithTransposeGivensMatrix(qm, b) - - // Is this an overdetermined or underdetermined system? - if m > n then - SolveTriangularLinearSystem R.[0..n-1,0..n-1] Qtb.[0..n-1] false - else - let s = SolveTriangularLinearSystem R.[0..m-1,0..m-1] Qtb false - Vector.init n (fun i -> if i < m then s.[i] else 0.0) - - - let leastSquaresCholesky (A: Matrix) (b: Vector) = - // We want to solve AT*A beta = AT * b for beta. - // We compute an upper triangular matrix U such that UT * U = AT * A - // We then solve UT * gamma = AT * b for gamma (note that UT is lower triangular) - // Finally we solve U * beta = gamma - - let AT = Matrix.transpose A - - let upper = (AT * A) |> Cholesky - let gamma = - SolveTriangularLinearSystem(Matrix.transpose upper) (AT * b) true - let beta = - SolveTriangularLinearSystem upper gamma false - beta - - /// computes the hat matrix by the QR decomposition of the designmatrix used in ordinary least squares approaches - /// - /// - /// - /// - /// - /// - /// - let hatMatrix (designMatrix: Matrix) = - let qm,R = QR designMatrix - let q1 = qm.GetSlice ((Some 0),(Some (qm.NumRows-1)),(Some 0),(Some (R.NumCols-1))) - // computes the hatmatrix - q1 * q1.Transpose - - - /// computes the leverages of every dataPoint of a dataSet given by the diagonal of the hat matrix. - /// - /// - /// - /// - /// - /// - /// - let leverageBy (hatMatrix: Matrix) = - hatMatrix.Diagonal - - /// computes the leverage directly by QR decomposition of the designmatrix used in ordinary least squares approaches
and computing of the diagnonal entries of the Hat matrix, known as the leverages of the regressors
- /// - /// - /// - /// - /// - /// - /// - let leverage (designMatrix: Matrix) = - let qm,R = QR designMatrix - let q1 = qm.GetSlice ((Some 0),(Some (qm.NumRows-1)),(Some 0),(Some (R.NumCols-1))) - let leverage = - let diagonal = FSharp.Stats.Vector.create q1.NumRows 0. - diagonal - |> FSharp.Stats.Vector.mapi (fun i x -> - FSharp.Stats.Matrix.foldRow (fun acc x -> acc + (x ** 2.)) 0. q1 i - ) - leverage - - - /// Calculates the pseudo inverse of the matrix - /// - /// - /// - /// - /// - /// - /// - let pseudoInvers (matrix:Matrix) = - let (m,n) = matrixDims matrix - // Is this an overdetermined or underdetermined system? - if m > n then - let qm,R = QR matrix - let i = Matrix.identity m - let Qtb = qm.Transpose * i - SolveTriangularLinearSystems R.[0..n-1,0..n-1] Qtb.[0..n-1,0..m-1] false - else - let qm,R = QR matrix.Transpose - let i = Matrix.identity n - let Qtb = qm.Transpose * i - let s = SolveTriangularLinearSystems R.[0..m-1,0..m-1] Qtb.[0..m-1,0..n-1] false - s.Transpose - - - diff --git a/src/FSharp.Stats/Algebra/NativeArray.fs b/src/FSharp.Stats/Algebra/NativeArray.fs deleted file mode 100644 index 231b5a4ef..000000000 --- a/src/FSharp.Stats/Algebra/NativeArray.fs +++ /dev/null @@ -1,106 +0,0 @@ -// (c) Microsoft Corporation 2005-2009. - -namespace Microsoft.FSharp.NativeInterop - -#nowarn "44" -#nowarn "9" // unverifiable constructs -#nowarn "51" // The address-of operator may result in non-verifiable code. Its use is restricted to passing byrefs to functions that require them - -open System -open System.Runtime.InteropServices -open Microsoft.FSharp.NativeInterop - -module NativeOps = - [] - let inline pinObjUnscoped (obj: obj) = GCHandle.Alloc(obj,GCHandleType.Pinned) - [] - let inline pinObj (obj: obj) f = - let gch = pinObjUnscoped obj - try f gch - finally - gch.Free() - -[] -type NativeArray<'T when 'T : unmanaged>(ptr : nativeptr<'T>, len: int) = - member x.Ptr = ptr - [] - member inline x.Item - with get n = NativePtr.get x.Ptr n - and set n v = NativePtr.set x.Ptr n v - member x.Length = len - -[] -type FortranMatrix<'T when 'T : unmanaged>(ptr : nativeptr<'T>, nrows: int, ncols:int) = - member x.NumCols = ncols - member x.NumRows = nrows - member x.Ptr = ptr - [] - member inline x.Item - with get (row,col) = NativePtr.get x.Ptr (row + col*x.NumRows) - and set (row,col) v = NativePtr.set x.Ptr (row + col*x.NumRows) v - member x.NativeTranspose = new CMatrix<_>(ptr,ncols,nrows) - -and - [] - NativeArray2<'T when 'T : unmanaged>(ptr : nativeptr<'T>, nrows:int, ncols: int) = - member x.Ptr = ptr - member x.NumRows = nrows - member x.NumCols = ncols - [] - member inline x.Item - with get (row,col) = NativePtr.get x.Ptr (row*x.NumCols + col) - and set (row,col) v = NativePtr.set x.Ptr (row*x.NumCols + col) v - member x.NativeTranspose = new FortranMatrix<_>(x.Ptr,ncols,nrows) - -and CMatrix<'T when 'T : unmanaged> = NativeArray2<'T> - -[] -module Ref = - [] - let inline pin (ref: 'T ref) (f : nativeptr<'T> -> 'b) = - NativeOps.pinObj (box ref) (fun gch -> - f (gch.AddrOfPinnedObject() |> NativePtr.ofNativeInt)) - -open Microsoft.FSharp.Math - -[] -type PinnedArray<'T when 'T : unmanaged>(narray: NativeArray<'T>, gch: GCHandle) = - [] - static member inline of_array(arr: 'T[]) = - let gch = NativeOps.pinObjUnscoped (box arr) - let ptr = &&arr.[0] - new PinnedArray<'T>(new NativeArray<_>(ptr,Array.length arr),gch) - - member x.Ptr = narray.Ptr - member x.Free() = gch.Free() - member x.Length = narray.Length - member x.NativeArray = narray - interface System.IDisposable with - member x.Dispose() = gch.Free() - - -[] -type PinnedArray2<'T when 'T : unmanaged>(narray: NativeArray2<'T>, gch: GCHandle) = - - [] - static member inline of_array2(arr: 'T[,]) = - let gch = NativeOps.pinObjUnscoped (box arr) - let ptr = &&arr.[0,0] - new PinnedArray2<'T>(new NativeArray2<_>(ptr,Array2D.length1 arr,Array2D.length2 arr),gch) - - [] - static member inline of_array2D(arr: 'T[,]) = - let gch = NativeOps.pinObjUnscoped (box arr) - let ptr = &&arr.[0,0] - new PinnedArray2<'T>(new NativeArray2<_>(ptr,Array2D.length1 arr,Array2D.length2 arr),gch) - - - member x.Ptr = narray.Ptr - member x.Free() = gch.Free() - member x.NumRows = narray.NumRows - member x.NumCols = narray.NumCols - member x.NativeArray = narray - interface System.IDisposable with - member x.Dispose() = gch.Free() - - diff --git a/src/FSharp.Stats/Algebra/NativeArrayExtensions.fs b/src/FSharp.Stats/Algebra/NativeArrayExtensions.fs deleted file mode 100644 index 918d79e09..000000000 --- a/src/FSharp.Stats/Algebra/NativeArrayExtensions.fs +++ /dev/null @@ -1,53 +0,0 @@ -// (c) Microsoft Corporation 2005-2009. - -namespace Microsoft.FSharp.NativeInterop - -#nowarn "44" -#nowarn "9" // unverifiable constructs -#nowarn "51" // unverifiable constructs - - - -open System -open System.Runtime.InteropServices -open Microsoft.FSharp.NativeInterop -open FSharp.Stats - -[] -module NativArrayExtensionsForMatrix = - - [] - let inline pinObjUnscoped (obj: obj) = GCHandle.Alloc(obj,GCHandleType.Pinned) - [] - let inline pinObj (obj: obj) f = - let gch = pinObjUnscoped obj - try f gch - finally - gch.Free() - - type Microsoft.FSharp.NativeInterop.PinnedArray<'T when 'T : unmanaged> with - - [] - static member inline of_vector(m:Vector<'T>) = - let gch = pinObjUnscoped (box m.InternalValues) - let ptr = &&m.InternalValues.[0] - new PinnedArray<'T>(new NativeArray<_>(ptr,m.Length),gch) - - [] - static member inline of_rowvec(m:RowVector<'T>) = - let gch = pinObjUnscoped (box m.InternalValues) - let ptr = &&m.InternalValues.[0] - new PinnedArray<'T>(new NativeArray<_>(ptr,m.Length),gch) - - - type Microsoft.FSharp.NativeInterop.PinnedArray2<'T when 'T : unmanaged> with - - [] - static member inline of_matrix(m:Matrix<'T>) = - if m.IsDense then - let gch = pinObjUnscoped (box m.InternalDenseValues) - let ptr = && m.InternalDenseValues.[0,0] - new PinnedArray2<'T>(new NativeArray2<_>(ptr,m.NumRows,m.NumCols),gch) - else - invalidArg "m" "cannot pin sparse matrices" - diff --git a/src/FSharp.Stats/Algebra/NativeUtilities.fs b/src/FSharp.Stats/Algebra/NativeUtilities.fs deleted file mode 100644 index d9ea77819..000000000 --- a/src/FSharp.Stats/Algebra/NativeUtilities.fs +++ /dev/null @@ -1,49 +0,0 @@ -namespace Microsoft.FSharp.NativeInterop - -open Microsoft.FSharp.NativeInterop -open FSharp.Stats - - -module NativeUtilities = - - - let nativeArray_as_CMatrix_colvec (arr: 'T NativeArray) = new CMatrix<_>(arr.Ptr,arr.Length,1) - let nativeArray_as_FortranMatrix_colvec (arr: 'T NativeArray) = new FortranMatrix<_>(arr.Ptr,arr.Length,1) - let pinM m = PinnedArray2.of_matrix(m) - let pinV v = PinnedArray.of_vector(v) - let pinA arr = PinnedArray.of_array(arr) - - let pinA2 arr = PinnedArray2.of_array2D(arr) - - let pinMV m1 v2 = pinM m1,pinV v2 - let pinVV v1 v2 = pinV v1,pinV v2 - let pinAA v1 v2 = pinA v1,pinA v2 - let pinMVV m1 v2 m3 = pinM m1,pinV v2,pinV m3 - let pinMM m1 m2 = pinM m1,pinM m2 - let pinMMM m1 m2 m3 = pinM m1,pinM m2,pinM m3 - let freeM (pA: PinnedArray2<'T>) = pA.Free() - let freeV (pA: PinnedArray<'T>) = pA.Free() - let freeA (pA: PinnedArray<'T>) = pA.Free() - - let freeA2 a = freeM a - - let freeMV (pA: PinnedArray2<'T>,pB : PinnedArray<'T>) = pA.Free(); pB.Free() - let freeVV (pA: PinnedArray<'T>,pB : PinnedArray<'T>) = pA.Free(); pB.Free() - let freeAA (pA: PinnedArray<'T>,pB : PinnedArray<'T>) = pA.Free(); pB.Free() - let freeMM (pA: PinnedArray2<'T>,(pB: PinnedArray2<'T>)) = pA.Free();pB.Free() - let freeMMM (pA: PinnedArray2<'T>,(pB: PinnedArray2<'T>),(pC: PinnedArray2<'T>)) = pA.Free();pB.Free();pC.Free() - let freeMVV (pA: PinnedArray2<'T>,(pB: PinnedArray<'T>),(pC: PinnedArray<'T>)) = pA.Free();pB.Free();pC.Free() - - let matrixDims (m:Matrix<_>) = m.NumRows, m.NumCols - let matrixDim1 (m:Matrix<_>) = m.NumRows - let matrixDim2 (m:Matrix<_>) = m.NumCols - let vectorDim (v:Vector<_>) = v.Length - - let assertDimensions functionName (aName,bName) (a,b) = - if a=b then () else - failwith (sprintf "Require %s = %s, but %s = %d and %s = %d in %s" aName bName aName a bName b functionName) - - - - - diff --git a/src/FSharp.Stats/BigRational.fs b/src/FSharp.Stats/BigRational.fs deleted file mode 100644 index b43edc544..000000000 --- a/src/FSharp.Stats/BigRational.fs +++ /dev/null @@ -1,311 +0,0 @@ -// (c) Microsoft Corporation. All rights reserved - -#nowarn "44" // OK to use the "compiler only" function RangeGeneric -#nowarn "52" // The value has been copied to ensure the original is not mutated by this operation - -//namespace Microsoft.FSharp.Math // old namespace -namespace FSharp.Stats - - open System - open System.Numerics - open System.Globalization - - module BigRationalLargeImpl = - let ZeroI = new BigInteger(0) - let OneI = new BigInteger(1) - let bigint (x:int) = new BigInteger(x) - let ToDoubleI (x:BigInteger) = double x - let ToInt32I (x:BigInteger) = int32 x - - open BigRationalLargeImpl - - [] - type BigRationalLarge = - | Q of BigInteger * BigInteger // invariants: (p,q) in lowest form, q >= 0 - - override n.ToString() = - let (Q(p,q)) = n - if q.IsOne then p.ToString() - else p.ToString() + "/" + q.ToString() - - - static member Hash (Q(ap,aq)) = - // This hash code must be identical to the hash for BigInteger when the numbers coincide. - if aq.IsOne then ap.GetHashCode() else (ap.GetHashCode() <<< 3) + aq.GetHashCode() - - - override x.GetHashCode() = BigRationalLarge.Hash(x) - - static member Equals(Q(ap,aq), Q(bp,bq)) = - BigInteger.(=) (ap,bp) && BigInteger.(=) (aq,bq) // normal form, so structural equality - - static member LessThan(Q(ap,aq), Q(bp,bq)) = - BigInteger.(<) (ap * bq,bp * aq) - - // note: performance improvement possible here - static member Compare(p,q) = - if BigRationalLarge.LessThan(p,q) then -1 - elif BigRationalLarge.LessThan(q,p)then 1 - else 0 - - interface System.IComparable with - member this.CompareTo(obj:obj) = - match obj with - | :? BigRationalLarge as that -> BigRationalLarge.Compare(this,that) - | _ -> invalidArg "obj" "the object does not have the correct type" - - override this.Equals(that:obj) = - match that with - | :? BigRationalLarge as that -> BigRationalLarge.Equals(this,that) - | _ -> false - - member x.IsNegative = let (Q(ap,_)) = x in sign ap < 0 - member x.IsPositive = let (Q(ap,_)) = x in sign ap > 0 - - member x.Numerator = let (Q(p,_)) = x in p - member x.Denominator = let (Q(_,q)) = x in q - member x.Sign = (let (Q(p,_)) = x in sign p) - - static member ToDouble (Q(p,q)) = - ToDoubleI p / ToDoubleI q - - static member Normalize (p:BigInteger,q:BigInteger) = - if q.IsZero then - raise (System.DivideByZeroException()) (* throw for any x/0 *) - elif q.IsOne then - Q(p,q) - else - let k = BigInteger.GreatestCommonDivisor(p,q) - let p = p / k - let q = q / k - if sign q < 0 then Q(-p,-q) else Q(p,q) - - static member Rational (p:int,q:int) = BigRationalLarge.Normalize (bigint p,bigint q) - static member RationalZ (p,q) = BigRationalLarge.Normalize (p,q) - - static member Parse (str:string) = - let len = str.Length - if len=0 then invalidArg "str" "empty string"; - let j = str.IndexOf '/' - if j >= 0 then - let p = BigInteger.Parse (str.Substring(0,j)) - let q = BigInteger.Parse (str.Substring(j+1,len-j-1)) - BigRationalLarge.RationalZ (p,q) - else - let p = BigInteger.Parse str - BigRationalLarge.RationalZ (p,OneI) - - static member (~-) (Q(bp,bq)) = Q(-bp,bq) // still coprime, bq >= 0 - static member (+) (Q(ap,aq),Q(bp,bq)) = BigRationalLarge.Normalize ((ap * bq) + (bp * aq),aq * bq) - static member (-) (Q(ap,aq),Q(bp,bq)) = BigRationalLarge.Normalize ((ap * bq) - (bp * aq),aq * bq) - static member (*) (Q(ap,aq),Q(bp,bq)) = BigRationalLarge.Normalize (ap * bp,aq * bq) - static member (/) (Q(ap,aq),Q(bp,bq)) = BigRationalLarge.Normalize (ap * bq,aq * bp) - static member ( ~+ )(n1:BigRationalLarge) = n1 - - - [] - module BigRationalLarge = - open System.Numerics - - let inv (Q(ap,aq)) = BigRationalLarge.Normalize(aq,ap) - - let pown (Q(p,q)) (n:int) = Q(BigInteger.Pow(p,n),BigInteger.Pow (q,n)) // p,q powers still coprime - - let equal (Q(ap,aq)) (Q(bp,bq)) = ap=bp && aq=bq // normal form, so structural equality - let lt a b = BigRationalLarge.LessThan(a,b) - let gt a b = BigRationalLarge.LessThan(b,a) - let lte (Q(ap,aq)) (Q(bp,bq)) = BigInteger.(<=) (ap * bq,bp * aq) - let gte (Q(ap,aq)) (Q(bp,bq)) = BigInteger.(>=) (ap * bq,bp * aq) - - let ofBigInt z = BigRationalLarge.RationalZ(z,OneI ) - let ofInt n = BigRationalLarge.Rational(n,1) - - [] - let of_bigint z = ofBigInt z - [] - let of_int n = ofInt n - - // integer part - let integer (Q(p,q)) = - let mutable r = BigInteger(0) - let d = BigInteger.DivRem (p,q,&r) // have p = d.q + r, |r| < |q| - if r < ZeroI - then d - OneI // p = (d-1).q + (r+q) - else d // p = d.q + r - - - //---------------------------------------------------------------------------- - // BigRational - //-------------------------------------------------------------------------- - - [] - [] - type BigRational = - | Z of BigInteger - | Q of BigRationalLarge - - static member ( + )(n1,n2) = - match n1,n2 with - | Z z ,Z zz -> Z (z + zz) - | Q q ,Q qq -> Q (q + qq) - | Z z ,Q qq -> Q (BigRationalLarge.ofBigInt z + qq) - | Q q ,Z zz -> Q (q + BigRationalLarge.ofBigInt zz) - - static member ( * )(n1,n2) = - match n1,n2 with - | Z z ,Z zz -> Z (z * zz) - | Q q ,Q qq -> Q (q * qq) - | Z z ,Q qq -> Q (BigRationalLarge.ofBigInt z * qq) - | Q q ,Z zz -> Q (q * BigRationalLarge.ofBigInt zz) - - static member ( - )(n1,n2) = - match n1,n2 with - | Z z ,Z zz -> Z (z - zz) - | Q q ,Q qq -> Q (q - qq) - | Z z ,Q qq -> Q (BigRationalLarge.ofBigInt z - qq) - | Q q ,Z zz -> Q (q - BigRationalLarge.ofBigInt zz) - - static member ( / )(n1,n2) = - match n1,n2 with - | Z z ,Z zz -> Q (BigRationalLarge.RationalZ(z,zz)) - | Q q ,Q qq -> Q (q / qq) - | Z z ,Q qq -> Q (BigRationalLarge.ofBigInt z / qq) - | Q q ,Z zz -> Q (q / BigRationalLarge.ofBigInt zz) - - static member ( ~- )(n1) = - match n1 with - | Z z -> Z (-z) - | Q q -> Q (-q) - - static member ( ~+ )(n1:BigRational) = n1 - - // nb. Q and Z hash codes must match up - see notes above - override n.GetHashCode() = - match n with - | Z z -> z.GetHashCode() - | Q q -> q.GetHashCode() - - override this.Equals(obj:obj) = - match obj with - | :? BigRational as that -> BigRational.(=)(this, that) - | _ -> false - - interface System.IComparable with - member n1.CompareTo(obj:obj) = - match obj with - | :? BigRational as n2 -> - if BigRational.(<)(n1, n2) then -1 elif BigRational.(=)(n1, n2) then 0 else 1 - | _ -> invalidArg "obj" "the objects are not comparable" - - static member FromInt (x:int) = Z (bigint x) - static member FromBigInt x = Z x - - static member Zero = BigRational.FromInt(0) - static member One = BigRational.FromInt(1) - - - static member PowN (n,i:int) = - match n with - | Z z -> Z (BigInteger.Pow (z,i)) - | Q q -> Q (BigRationalLarge.pown q i) - - static member op_Equality (n,nn) = - match n,nn with - | Z z ,Z zz -> BigInteger.(=) (z,zz) - | Q q ,Q qq -> (BigRationalLarge.equal q qq) - | Z z ,Q qq -> (BigRationalLarge.equal (BigRationalLarge.ofBigInt z) qq) - | Q q ,Z zz -> (BigRationalLarge.equal q (BigRationalLarge.ofBigInt zz)) - static member op_Inequality (n,nn) = not (BigRational.op_Equality(n,nn)) - - static member op_LessThan (n,nn) = - match n,nn with - | Z z ,Z zz -> BigInteger.(<) (z,zz) - | Q q ,Q qq -> (BigRationalLarge.lt q qq) - | Z z ,Q qq -> (BigRationalLarge.lt (BigRationalLarge.ofBigInt z) qq) - | Q q ,Z zz -> (BigRationalLarge.lt q (BigRationalLarge.ofBigInt zz)) - static member op_GreaterThan (n,nn) = - match n,nn with - | Z z ,Z zz -> BigInteger.(>) (z,zz) - | Q q ,Q qq -> (BigRationalLarge.gt q qq) - | Z z ,Q qq -> (BigRationalLarge.gt (BigRationalLarge.ofBigInt z) qq) - | Q q ,Z zz -> (BigRationalLarge.gt q (BigRationalLarge.ofBigInt zz)) - static member op_LessThanOrEqual (n,nn) = - match n,nn with - | Z z ,Z zz -> BigInteger.(<=) (z,zz) - | Q q ,Q qq -> (BigRationalLarge.lte q qq) - | Z z ,Q qq -> (BigRationalLarge.lte (BigRationalLarge.ofBigInt z) qq) - | Q q ,Z zz -> (BigRationalLarge.lte q (BigRationalLarge.ofBigInt zz)) - static member op_GreaterThanOrEqual (n,nn) = - match n,nn with - | Z z ,Z zz -> BigInteger.(>=) (z,zz) - | Q q ,Q qq -> (BigRationalLarge.gte q qq) - | Z z ,Q qq -> (BigRationalLarge.gte (BigRationalLarge.ofBigInt z) qq) - | Q q ,Z zz -> (BigRationalLarge.gte q (BigRationalLarge.ofBigInt zz)) - - - member n.IsNegative = - match n with - | Z z -> sign z < 0 - | Q q -> q.IsNegative - - member n.IsPositive = - match n with - | Z z -> sign z > 0 - | Q q -> q.IsPositive - - member n.Numerator = - match n with - | Z z -> z - | Q q -> q.Numerator - - member n.Denominator = - match n with - | Z _ -> OneI - | Q q -> q.Denominator - - member n.Sign = - if n.IsNegative then -1 - elif n.IsPositive then 1 - else 0 - - static member Abs(n:BigRational) = - if n.IsNegative then -n else n - - static member ToDouble(n:BigRational) = - match n with - | Z z -> ToDoubleI z - | Q q -> BigRationalLarge.ToDouble q - - static member ToBigInt(n:BigRational) = - match n with - | Z z -> z - | Q q -> BigRationalLarge.integer q - - static member ToInt32(n:BigRational) = - match n with - | Z z -> ToInt32I(z) - | Q q -> ToInt32I(BigRationalLarge.integer q ) - - static member op_Explicit (n:BigRational) = BigRational.ToInt32 n - static member op_Explicit (n:BigRational) = BigRational.ToDouble n - static member op_Explicit (n:BigRational) = BigRational.ToBigInt n - - - override n.ToString() = - match n with - | Z z -> z.ToString() - | Q q -> q.ToString() - - member x.StructuredDisplayString = x.ToString() - - static member Parse(s:string) = Q (BigRationalLarge.Parse s) - - type BigNum = BigRational - type bignum = BigNum - - module NumericLiteralN = - let FromZero () = BigRational.Zero - let FromOne () = BigRational.One - let FromInt32 i = BigRational.FromInt i - let FromInt64 (i64:int64) = BigRational.FromBigInt (new BigInteger(i64)) - let FromString s = BigRational.Parse s diff --git a/src/FSharp.Stats/GlobalAssociations.fs b/src/FSharp.Stats/GlobalAssociations.fs deleted file mode 100644 index 17122e89b..000000000 --- a/src/FSharp.Stats/GlobalAssociations.fs +++ /dev/null @@ -1,45 +0,0 @@ -// (c) Microsoft Corporation 2005-2009. - -//namespace Microsoft.FSharp.Math // old namespace -namespace FSharp.Stats - -module GlobalAssociations = - -// open Microsoft.FSharp.Math -// open Microsoft.FSharp.Math.Instances - open FSharp.Stats.Instances - open System - open System.Numerics - - let ht = - let ht = new System.Collections.Generic.Dictionary() - let optab = - [ typeof, (Some(FloatNumerics :> INumeric) :> obj); - typeof, (Some(Int32Numerics :> INumeric) :> obj); - typeof, (Some(Int64Numerics :> INumeric) :> obj); - typeof, (Some(BigIntNumerics :> INumeric) :> obj); - typeof, (Some(Float32Numerics :> INumeric) :> obj); - typeof, (Some(BigRationalNumerics :> INumeric) :> obj); ] - - List.iter (fun (ty,ops) -> ht.Add(ty,ops)) optab; - ht - - let Put (ty: System.Type, d : obj) = - lock ht (fun () -> - if ht.ContainsKey(ty) then invalidArg "ty" ("the type "+ty.Name+" already has a registered numeric association"); - ht.Add(ty, d)) - - let TryGetNumericAssociation<'a>() = - lock ht (fun () -> - let ty = typeof<'a> - if ht.ContainsKey(ty) then - match ht.[ty] with - | :? (INumeric<'a> option) as r -> r - | _ -> invalidArg "ty" ("The type "+ty.Name+" has a numeric association but it was not of the correct type") - else - None) - - let GetNumericAssociation() = (TryGetNumericAssociation()).Value - let RegisterNumericAssociation (d : INumeric<'a>) = Put(typeof<'a>, box(Some d)) - - diff --git a/src/FSharp.Stats/INumeric.fs b/src/FSharp.Stats/INumeric.fs deleted file mode 100644 index 35a19fab2..000000000 --- a/src/FSharp.Stats/INumeric.fs +++ /dev/null @@ -1,240 +0,0 @@ -// (c) Microsoft Corporation 2005-2009. - -namespace FSharp.Stats - -open System -open System.Numerics -open System.Globalization - -type INumeric<'T> = - abstract Zero: 'T - abstract One: 'T - abstract Add: 'T * 'T -> 'T - abstract Subtract: 'T * 'T -> 'T - abstract Multiply : 'T * 'T -> 'T - abstract Compare : 'T * 'T -> int - abstract Equals : 'T * 'T -> bool - abstract Negate : 'T -> 'T - abstract Sign : 'T -> int - abstract Abs : 'T -> 'T - abstract ToString : 'T * string * System.IFormatProvider -> string - abstract Parse : string * System.Globalization.NumberStyles * System.IFormatProvider -> 'T - -type IIntegral<'T> = - inherit INumeric<'T> - abstract Modulus: 'T * 'T -> 'T - abstract Divide : 'T * 'T -> 'T - abstract DivRem : 'T * 'T -> 'T * 'T - abstract ToBigInt : 'T -> BigInteger - abstract OfBigInt : BigInteger -> 'T - -type IFractional<'T> = - inherit INumeric<'T> - abstract Reciprocal : 'T -> 'T - abstract Divide : 'T * 'T -> 'T - -type IFloating<'T> = - inherit IFractional<'T> - abstract Pi : 'T - abstract Exp : 'T -> 'T - abstract Log : 'T -> 'T - abstract Sqrt : 'T -> 'T - abstract LogN : 'T * 'T -> 'T - abstract Sin : 'T -> 'T - abstract Cos : 'T -> 'T - abstract Tan : 'T -> 'T - abstract Asin : 'T -> 'T - abstract Acos : 'T -> 'T - abstract Atan : 'T -> 'T - abstract Atan2 : 'T * 'T -> 'T - abstract Sinh : 'T -> 'T - abstract Cosh : 'T -> 'T - abstract Tanh : 'T -> 'T - -type IIEEE<'T> = - inherit IFloating<'T> - abstract PositiveInfinity : 'T - abstract NegativeInfinity : 'T - abstract NaN : 'T - abstract EpsilonOne : 'T - abstract IsNaN: 'T -> bool - abstract IsInfinite : 'T -> bool - -type INormFloat<'T> = - abstract Norm : 'T -> float - -module Instances = - let Int32Numerics = - { new IIntegral with - member __.Zero = 0 - member __.One = 1 - member __.Add(a,b) = a + b - member __.Subtract(a,b) = a - b - member __.Multiply(a,b) = a * b - member __.Equals(a,b) = (a = b) - member __.Compare(a,b) = compare a b - member __.Negate(a) = - a - member __.Abs(a) = a - member __.ToBigInt(a) = new BigInteger(a) - member __.OfBigInt(a) = int32 a - member __.Sign(a) = Math.Sign(a) - member __.Modulus(a,b) = a % b - member __.Divide(a,b) = a / b - member __.DivRem(a,b) = (a / b, a % b) - member __.ToString((x:int32),fmt,fmtprovider) = - x.ToString(fmt,fmtprovider) - member __.Parse(s,numstyle,fmtprovider) = - System.Int32.Parse(s,numstyle,fmtprovider) - interface INormFloat with - member __.Norm(x) = float (abs x) - } - let Int64Numerics = - { new IIntegral with - member __.Zero =0L - member __.One = 1L - member __.Add(a,b) = a + b - member __.Subtract(a,b) = a - b - member __.Multiply(a,b) = a * b - member __.Negate(a) = - a - member __.Abs(a) = Math.Abs(a) - member __.ToBigInt(a) = new BigInteger(a) - member __.OfBigInt(a) = int64 a - member __.Sign(a) = Math.Sign(a) - member __.Modulus(a,b) = a % b - member __.Equals(a,b) = (a = b) - member __.Compare(a,b) = compare a b - member __.Divide(a,b) = a / b - member __.DivRem(a,b) = (a / b, a % b) - member __.ToString((x:int64),fmt,fmtprovider) = x.ToString(fmt,fmtprovider) - member __.Parse(s,numstyle,fmtprovider) = System.Int64.Parse(s,numstyle,fmtprovider) - interface INormFloat with - member __.Norm(x) = float (Math.Abs x) - } - let FloatNumerics = - { new IIEEE with - member __.Zero = 0.0 - member __.One = 1.0 - member __.Add(a,b) = a + b - member __.Subtract(a,b) = a - b - member __.Multiply(a,b) = a * b - member __.Equals(a,b) = (a = b) - member __.Compare(a,b) = compare a b - member __.PositiveInfinity = Double.PositiveInfinity - member __.NegativeInfinity = Double.NegativeInfinity - member __.NaN = Double.NaN - member __.EpsilonOne = 0x3CB0000000000000LF - member __.IsInfinite(a) = Double.IsInfinity(a) - member __.IsNaN(a) = Double.IsNaN(a) - member __.Pi = Math.PI - member __.Reciprocal(a) = 1.0/a - member __.Abs(a) = Math.Abs(a) - member __.Sign(a) = Math.Sign(a) - member __.Asin(a) = Math.Asin(a) - member __.Acos(a) = Math.Acos(a) - member __.Atan(a) = Math.Atan(a) - member __.Atan2(a,b) = Math.Atan2(a,b) - member __.Tanh(a) = Math.Tanh(a) - member __.Tan(a) = Math.Tan(a) - member __.Sqrt(a) = Math.Sqrt(a) - member __.Sinh(a) = Math.Sinh(a) - member __.Cosh(a) = Math.Cosh(a) - member __.Sin(a) = Math.Sin(a) - member __.Cos(a) = Math.Cos(a) - member __.LogN(a,n) = -#if FX_NO_LOGN - raise (System.NotSupportedException("this operation is not supported on this platform")) -#else - Math.Log(a,n) -#endif - member __.Log(a) = Math.Log(a) - member __.Exp(a) = Math.Exp(a) - member __.Negate(a) = -a - member __.Divide(a,b) = a / b - member __.ToString((x:float),fmt,fmtprovider) = x.ToString(fmt,fmtprovider) - member __.Parse(s,numstyle,fmtprovider) = System.Double.Parse(s,numstyle,fmtprovider) - interface INormFloat with - member __.Norm(x) = float (Math.Abs x) - } - let Float32Numerics = - { new IFractional with - member __.Zero = 0.0f - member __.One = 1.0f - member __.Add(a,b) = a + b - member __.Subtract(a,b) = a - b - member __.Multiply(a,b) = a * b - member __.Equals(a,b) = (a = b) - member __.Compare(a,b) = compare a b - member __.Negate(a) = -a - member __.Reciprocal(a) = 1.0f/a - member __.Sign(a) = Math.Sign(a) - member __.Abs(a) = Math.Abs(a) - member __.Divide(a,b) = a / b - member __.ToString((x:float32),fmt,fmtprovider) = x.ToString(fmt,fmtprovider) - member __.Parse(s,numstyle,fmtprovider) = System.Single.Parse(s,numstyle,fmtprovider) - interface INormFloat with - member __.Norm(x) = float (Math.Abs x) - } - - let BigRationalNumerics = - { new IFractional with - member __.Zero = BigRational.Zero - member __.One = BigRational.One - member __.Add(a,b) = a + b - member __.Subtract(a,b) = a - b - member __.Multiply(a,b) = a * b - member __.Equals(a,b) = (a = b) - member __.Compare(a,b) = compare a b - member __.Divide(a,b) = a / b - member __.Abs(a) = BigRational.Abs a - member __.Sign(a) = a.Sign - member __.Negate(a) = - a - member __.Reciprocal(a) = BigRational.One / a - // Note, this ignores fmt, fmtprovider - member __.ToString((x:bignum),fmt,fmtprovider) = x.ToString() - // Note, this ignroes numstyle, fmtprovider - member __.Parse(s,numstyle,fmtprovider) = BigRational.Parse(s) - - interface INormFloat with - member __.Norm(x) = float (BigRational.Abs x) - } - - let BigIntNumerics = - let ZeroI = new BigInteger(0) - { new IIntegral<_> with - member __.Zero = BigInteger.Zero - member __.One = BigInteger.One - member __.Add(a,b) = a + b - member __.Subtract(a,b) = a - b - member __.Multiply(a,b) = a * b - member __.Equals(a,b) = (a = b) - member __.Compare(a,b) = compare a b - member __.Divide(a,b) = a / b - member __.Negate(a) = -a - member __.Modulus(a,b) = a % b - member __.DivRem(a,b) = - let mutable r = new BigInteger(0) - (BigInteger.DivRem (a,b,&r),r) - member __.Sign(a) = a.Sign - member __.Abs(a) = abs a - member __.ToBigInt(a) = a - member __.OfBigInt(a) = a - - member __.ToString(x,fmt,fmtprovider) = -#if FX_ATLEAST_40 - x.ToString(fmt,fmtprovider) -#else - // Note: this ignores fmt and fmtprovider - x.ToString() -#endif - // Note: this ignores fmt and fmtprovider - member __.Parse(s,numstyle,fmtprovider) = -#if FX_ATLEAST_40 - BigInteger.Parse(s,numstyle,fmtprovider) -#else - BigInteger.Parse(s) -#endif - - interface INormFloat with - member __.Norm(x) = float (abs x) - } - diff --git a/src/FSharp.Stats/Matrix.fs b/src/FSharp.Stats/Matrix.fs deleted file mode 100644 index cbf71fafe..000000000 --- a/src/FSharp.Stats/Matrix.fs +++ /dev/null @@ -1,1611 +0,0 @@ -namespace FSharp.Stats - -#nowarn "60" // implementations in augmentations -#nowarn "69" // implementations in augmentations - -open System -open System.Globalization -open System.Collections -open System.Collections.Generic -open System.Diagnostics - -//type matrix = Matrix -//type vector = Vector -//type rowvec = RowVector - -module MRandom = - let randomGen = new System.Random() - let float f = randomGen.NextDouble() * f - -[] -module Matrix = - - - type Orientation = - | RowWise - | ColWise - member this.Inverse = - match this with - | RowWise -> Orientation.ColWise - | ColWise -> Orientation.RowWise - static member inverse (o:Orientation) = - o.Inverse - - type DataSource = - |Sample - |Population - - module Generic = - - module MS = SpecializedGenericImpl - - // Accessors - let get (matrix:Matrix<_>) indexRow indexCol = matrix.[indexRow,indexCol] - let set (matrix:Matrix<_>) indexRow indexCol value = matrix.[indexRow,indexCol] <- value - // Creation - let ofList lists = MS.listM lists - let ofSeq sources = MS.seqM sources - let ofColSeq sources = MS.seqCM sources - let init lengthRow lengthCol initializer = MS.initM lengthRow lengthCol initializer - let ofArray2D (array: 'T[,]) : Matrix<'T> = MS.arrayM array - /// Creates a sparse matrix based on the CSR format - /// - /// - /// - /// - /// - /// - /// - let sparseOfArray2D (array: 'T[,]) : Matrix<'T> = MS.arraySM array - let toArray2D (matrix:Matrix<_>) = Array2D.init matrix.NumRows matrix.NumCols (fun i j -> get matrix i j) - let toJaggedArray (m:Matrix<_>) = [|for i=0 to m.NumRows-1 do yield (Array.init m.NumCols (fun j -> get m i j))|] - let toJaggedColArray (m:Matrix<_>) = [|for i=0 to m.NumCols-1 do yield (Array.init m.NumRows (fun j -> get m j i))|] - let toJaggedSeq (m: Matrix<'a>) = Seq.init m.NumRows (fun i -> Seq.init m.NumCols (fun j -> get m i j)) - let toJaggedColSeq (m: Matrix<'a>) = Seq.init m.NumCols (fun i -> Seq.init m.NumRows (fun j -> get m j i)) - let initNumeric lengthRow lengthCol initializer = MS.initNumericM lengthRow lengthCol initializer - [] - let zero lengthRow lengthCol = MS.zeroM lengthRow lengthCol - let zeroCreate lengthRow lengthCol = MS.zeroM lengthRow lengthCol - let identity m = MS.identityM m - let create lengthRow lengthCol value = MS.constM lengthRow lengthCol value - let ofScalar scalar = MS.scalarM scalar - let diag v = MS.diagM v - let initDiagonal v = MS.diagM v - let constDiag n x = MS.constDiagM n x - - // Operators - /// Performs a element wise addition of matrices matrix1 and matrix2 (matrix1 + matrix2).
Only usable if both matrices have the same dimensions.
- /// - /// - /// - /// - /// - /// - /// - /// - let add matrix1 matrix2 = MS.addM matrix1 matrix2 - /// Performs a element wise substraction of matrices matrix1 and matrix2 (matrix1 - matrix2).
Only usable if both matrices have the same dimensions.
- /// - /// - /// - /// - /// - /// - /// - /// - let sub matrix1 matrix2 = MS.subM matrix1 matrix2 - /// Performs a left sided matrix multiplication of matrices matrix1 and matrix2 (matrix1 * matrix2).
Only usable if both matrices have the same dimensions.
- /// - /// - /// - /// - /// - /// - /// - /// - let mul matrix1 matrix2 = MS.mulM matrix1 matrix2 - /// Performs a matrix multiplication of the 1*n rowVector and the m*n matrix (rowVector*matrix).
Only usable if column number (n) of the vector equals the row number (m) of the matrix.
- /// - /// - /// - /// - /// - /// - /// - /// - let mulRV rowVector matrix = MS.mulRVM rowVector matrix - /// Performs a matrix multiplication of a m*n matrix and the m*1 vector (matrix*vector).
Only usable if column number (n) of the matrix equals the row number (m) of the vector.
- /// - /// - /// - /// - /// - /// - /// - /// - let mulV matrix vector = MS.mulMV matrix vector - /// Performs a element wise multiplication of matrices matrix1 and matrix2 (matrix1 * matrix2, Hadamard-Product).
Only usable if both matrices have the same dimensions.
- /// - /// - /// - /// - /// - /// - /// - /// - let cptMul matrix1 matrix2 = MS.cptMulM matrix1 matrix2 - /// Performs a element wise comparison of matrices matrix1 and matrix2 always preserving the greater value.
Only usable if both matrices have the same dimensions.
- /// - /// - /// - /// - /// - /// - /// - /// - let cptMax matrix1 matrix2 = MS.cptMaxM matrix1 matrix2 - /// Performs a element wise comparison of matrices matrix1 and matrix2 always preserving the smaller value.
Only usable if both matrices have the same dimensions.
- /// - /// - /// - /// - /// - /// - /// - /// - let cptMin matrix1 matrix2 = MS.cptMinM matrix1 matrix2 - /// Builds a new matrix where the elements are the result of multiplying every element of the given matrix with the given value - /// - /// - /// - /// - /// - /// - /// - /// - let scale value matrix = MS.scaleM value matrix - /// Performs a dot product of matrices matrix1 and matrix2.
Only usable if both matrices have the same dimensions.
- /// - /// - /// - /// - /// - /// - /// - /// - let dot matrix1 matrix2 = MS.dotM matrix1 matrix2 - /// Scales the matrix by element wise mulitplication with minus 1. - /// - /// - /// - /// - /// - /// - /// - let neg matrix = MS.negM matrix - /// Computes the trace of the matrix by summing elements of the diagonal.
Only usable if the matrix is a square matrix (m*m).
- /// - /// - /// - /// - /// - /// - /// - let trace matrix = MS.traceM matrix - /// Computes the sum of all matrix elements. - /// - /// - /// - /// - /// - /// - /// - let sum matrix = MS.sumM matrix - /// Computes the product of all matrix elements. - /// - /// - /// - /// - /// - /// - /// - let prod matrix = MS.prodM matrix - /// Frobenius matrix norm - /// - /// - /// - /// - /// - /// - /// - let norm matrix = MS.normM matrix - /// Returns the transpose of the matrix. - /// - /// - /// - /// - /// - /// - /// - let transpose matrix = MS.transM matrix - /// Performs an element wise addition of matrices matrix1 and matrix2 (matrix1 + matrix2).
Attention: the output overrides matrix1.
Only usable if both matrices have the same dimensions.
- /// - /// - /// - /// - /// - /// - /// - /// - let inplaceAdd matrix1 matrix2 = MS.inplaceAddM matrix1 matrix2 - /// Performs an element wise substraction of matrices matrix1 and matrix2 (matrix1 - matrix2).
Attention: the output overrides matrix1.
Only usable if both matrices have the same dimensions.
- /// - /// - /// - /// - /// - /// - /// - /// - let inplaceSub matrix1 matrix2 = MS.inplaceSubM matrix1 matrix2 - /// Iterates the given Matrix row wise and applies the function predicate element wise.
The iteration stops and returns true if an element satisfies the condition or false when the end of
the matrix is reached.
- /// - /// - /// - /// - /// - /// - /// - /// - let exists predicate matrix = MS.existsM predicate matrix - /// Iterates the given Matrix row wise and applies the function predicate element wise.
The iteration stops and returns false if an element fails the condition or true when the end of
the matrix is reached.
- /// - /// - /// - /// - /// - /// - /// - /// - let forall predicate matrix = MS.forallM predicate matrix - /// Iterates the given Matrix row wise and applies the function predicate element wise.
The iteration stops and returns true if an element satisfies the condition or false when the end of
the matrix is reached.
- /// - /// - /// - /// - /// - /// - /// - /// - let existsi predicate matrix = MS.existsiM predicate matrix - /// Iterates the given Matrix row wise and applies the function predicate element wise.
The iteration stops and returns false if an element fails the condition or true when the end of
the matrix is reached.
- /// - /// - /// - /// - /// - /// - /// - /// - let foralli predicate matrix = MS.foralliM predicate matrix - /// - let map mapping matrix = MS.mapM mapping matrix - /// - let copy matrix = MS.copyM matrix - /// - let mapi mapping matrix = MS.mapiM mapping matrix - /// - //TO_DO: refactor to take an Direction union case and use more descriptive name - let getDiagN a n = MS.getDiagnM a n - /// - let getDiag matrix = MS.getDiagnM matrix 0 - /// - let toDense matrix = MS.toDenseM matrix - /// Creates a sparse matrix based on the CSR format - /// - /// - /// - /// - /// - /// - /// - let toSparse matrix = MS.toSparseM matrix - /// - let initDense lengthRow lengthCol source = MS.initDenseM lengthRow lengthCol source - /// - let initSparse lengthRow lengthCol source = MS.initSparseM lengthRow lengthCol source - /// - let fold folder state matrix = MS.foldM folder state matrix - /// - let foldi folder state matrix = MS.foldiM folder state matrix - /// - let compare matrix1 matrix2 = MS.compareM LanguagePrimitives.GenericComparer matrix1 matrix2 - /// - let hash matrix = MS.hashM LanguagePrimitives.GenericEqualityComparer matrix - /// Returns row of given index of a matrix - /// - /// - /// - /// - /// - /// - /// - /// - let getRow matrix index = MS.getRowM matrix index - /// Replaces row of given index of a matrix with values of a vector, if vector length matches rowsize - /// - /// - /// - /// - /// - /// - /// - /// - /// - let setRow (matrix:Matrix<_>) index (vector:Vector<_>) = MS.setRowM matrix index vector - /// Returns col of given index of a matrix - /// - /// - /// - /// - /// - /// - /// - /// - let getCol matrix index = MS.getColM matrix index - /// Replaces column of given index of a matrix with values of a vector, if vector length matches columnsize - /// - /// - /// - /// - /// - /// - /// - /// - /// - let setCol (matrix:Matrix<_>) index (vector:Vector<_>) = MS.setColM matrix index vector - /// - let getCols matrix column1 column2 = MS.getColsM matrix (column1,column1+column2-1) - /// - let getRows matrix row1 row2 = MS.getRowsM matrix (row1,row1+row2-1) - /// - let getRegion matrix column1 row1 column2 row2 = MS.getRegionM matrix (column1,column1+column2-1) (row1,row1+row2-1) - /// - let ofRowVector rowVector = MS.rowvecM rowVector - /// - let ofVector vector = MS.vectorM vector - /// takes the first column of the matrix as vector - /// - /// - /// - /// - /// - /// - /// - let toVector matrix = MS.toVectorM matrix - /// takes the first row of the matrix as rowvector - /// - /// - /// - /// - /// - /// - /// - let toRowVector matrix = MS.toRowVectorM matrix - /// - let toScalar matrix = MS.toScalarM matrix - /// reads matrix from delimiter separated file - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - let readCSV (path: string) (separator: char) (removeHeaderRow: bool) (removeHeaderCol: bool) (transform: string -> 'a) = - IO.File.ReadAllLines(path) - |> fun x -> - if removeHeaderRow then Array.tail x else x - |> Array.map (fun x -> - let tmp = x.Split separator - if removeHeaderCol then - tmp.[1..] |> Array.map transform - else tmp |> Array.map transform - ) - |> ofSeq - - let inplace_assign f matrix = MS.inplaceAssignM f matrix - let inplace_cptMul matrix1 matrix2 = MS.inplaceCptMulM matrix1 matrix2 - let inplace_scale value matrix = MS.inplaceScaleM value matrix - let inplace_map mapping matrix = MS.inplace_mapM mapping matrix - let inplace_mapi mapping matrix = MS.inplace_mapiM mapping matrix - - [] - let of_rowvec rowVector = ofRowVector rowVector - [] - let of_vector vector = ofVector vector - [] - let to_vector matrix = toVector matrix - [] - let to_rowvec matrix = toRowVector matrix - [] - let to_scalar matrix = toScalar matrix - [] - let inplace_add matrix1 matrix2 = inplaceAdd matrix1 matrix2 - [] - let inplace_sub matrix1 matrix2 = inplaceSub matrix1 matrix2 - [] - let of_scalar scalar = ofScalar scalar - [] - let of_list lists = ofList lists - [] - let of_seq sources = ofSeq sources - [] - let inline of_array2D arrays = ofArray2D arrays - [] - let inline sparse_of_array2D arrays = sparseOfArray2D arrays - [] - let inline to_array2D matrix = toArray2D matrix - [] - let init_diagonal vector = initDiagonal vector - [] - let to_dense matrix = toDense matrix - [] - let to_sparse matrix = toSparse matrix - [] - let init_dense lengthRow lengthCol source = initDense lengthRow lengthCol source - [] - let init_sparse lengthRow lengthCol source = initSparse lengthRow lengthCol source - let nonzeroEntries matrix = MS.nonZeroEntriesM matrix - [] - let nonzero_entries matrix = nonzeroEntries matrix - - - // TM - [] - let enumerateRowWise f (matrix:Matrix<'a>) = - seq [ - for rowi=0 to matrix.NumRows-1 do - yield f (seq [for coli=0 to matrix.NumCols-1 do yield matrix.[rowi,coli]]) - ] - /// Applies mapping function along row axis - /// - /// - /// - /// - /// - /// - /// - /// - let mapRows (mapping: RowVector<'a> -> 'b) (matrix: Matrix<'a>) = - Vector.Generic.init matrix.NumRows (fun rowi -> - mapping (getRow matrix rowi) - ) - - /// Maps every matrix row using the position dependent function - /// - /// - /// - /// - /// - /// - /// - /// - let mapiRows (mapping: int -> RowVector<'a> -> 'b) (matrix: Matrix<'a>) = - Vector.Generic.init matrix.NumRows (fun rowi -> - mapping rowi (getRow matrix rowi) - ) - - // TM - /// Applies function f along column axis - [] - let enumerateColumnWise f (matrix:Matrix<'a>) = - seq [ - for coli=0 to matrix.NumCols-1 do - yield f (seq [for rowi=0 to matrix.NumRows-1 do yield matrix.[rowi,coli]]) - ] - /// Applies mapping function along column axis - /// - /// - /// - /// - /// - /// - /// - /// - let mapCols (mapping: Vector<'a> -> 'b) (matrix: Matrix<'a>) = - RowVector.Generic.init matrix.NumCols (fun coli -> - mapping (getCol matrix coli) - ) - /// Maps every matrix column using the position dependant function - /// - /// - /// - /// - /// - /// - /// - /// - let mapiCols (mapping: int -> Vector<'a> -> 'b) (matrix: Matrix<'a>) = - RowVector.Generic.init matrix.NumCols (fun coli -> - mapping coli (getCol matrix coli) - ) - /// Iterates the given Matrix row wise and places every element in a new vector with length n*m. - /// - /// - /// - /// - /// - /// - /// - let flattenRowWise (matrix: Matrix<'a>) = - let tmp = FSharp.Stats.Vector.Generic.zeroCreate (matrix.NumRows*matrix.NumCols) - for m = 0 to matrix.NumRows-1 do - for n = 0 to matrix.NumCols-1 do - tmp.[m*matrix.NumCols+n] <- matrix.[m,n] - tmp - - /// Iterates the given Matrix column wise and places every element in a new vector with length n*m. - /// - /// - /// - /// - /// - /// - /// - let flattenColWise (matrix: Matrix<'a>) = - matrix.Transpose |> flattenRowWise - - - module MG = Generic - module DS = DoubleImpl - module GU = GenericImpl - module MS = SpecializedGenericImpl - - // Element type OpsData - type elem = float - - // Accessors - let get (a:Matrix<_>) i j = MG.get a i j - let set (a:Matrix<_>) i j x = MG.set a i j x - // Creation - ///returns a dense matrix with m rows and n rows, applying the init function with the two indices as arguments - let init m n f = DS.initDenseMatrixDS m n f |> MS.dense - ///returns a dense matrix with the inner lists of the input jagged list as its rows - let ofJaggedList xss = DS.listDenseMatrixDS xss |> MS.dense - ///returns a dense matrix with the inner lists of the input jagged list as its columns - let ofJaggedColList xss = DS.colListDenseMatrixDS xss |> MS.dense - ///returns a dense matrix with the inner sequences of the input jagged sequences as its rows - let ofJaggedSeq xss = DS.seqDenseMatrixDS xss |> MS.dense - ///returns a dense matrix with the inner sequences of the input jagged sequence as its columns - let ofJaggedColSeq xss = DS.colSeqDenseMatrixDS xss |> MS.dense - ///returns a dense matrix with the inner arrays of the input jagged array as its rows - let ofJaggedArray xss = DS.arrayDenseMatrixDS xss |> MS.dense - /// returns a dense matrix with the inner arrays of the input jagged array as its columns - /// - /// - /// - /// - /// - /// - /// - let ofJaggedColArray xss = DS.colArrayDenseMatrixDS xss |> MS.dense - /// returns a dense matrix with the inner rowvectors of the input vector as its rows - /// - /// - /// - /// - /// - /// - /// - let ofRows (rows: Vector>) = DS.seqDenseMatrixDS rows |> MS.dense - /// returns a dense matrix with the inner vectors of the input rowvector as its columns - /// - /// - /// - /// - /// - /// - /// - let ofCols (cols: RowVector>) = DS.colSeqDenseMatrixDS cols |> MS.dense - /// reads matrix from delimiter separated file - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - let readCSV (path: string) (separator: char) (removeHeaderRow: bool) (removeHeaderCol: bool) = - IO.File.ReadAllLines(path) - |> fun x -> - if removeHeaderRow then Array.tail x else x - |> Array.map (fun x -> - let tmp = x.Split separator - if removeHeaderCol then - tmp.[1..] |> Array.map float - else tmp |> Array.map float - ) - |> DS.arrayDenseMatrixDS - |> MS.dense - - /// - let diag (v:vector) = MG.diag v - /// - //TO-DO: this should do something else as Matrix.diag. E.g. int -> (int -> float) -> Matrix - let initDiagonal (v:vector) = MG.diag v - /// - let constDiag n x : matrix = MG.constDiag n x - /// - //TO-DO: maybe rename to constCreate - let create m n x = DS.constDenseMatrixDS m n x |> MS.dense - /// - let ofScalar x = DS.scalarDenseMatrixDS x |> MS.dense - /// - let ofArray2D arr : matrix = MG.ofArray2D arr - /// Creates a sparse matrix based on the CSR format - /// - /// - /// - /// - /// - /// - /// - let sparseOfArray2D arr : matrix = MG.sparseOfArray2D arr - /// - let toArray2D (m : matrix) = MG.toArray2D m - /// - let toJaggedArray (m: matrix) = MG.toJaggedArray m - /// converts the matrix into an array of column arrays - /// - /// - /// - /// - /// - /// - /// - let toJaggedColArray (m: matrix) = MG.toJaggedColArray m - /// converts the matrix into an seq of row seqs - /// - /// - /// - /// - /// - /// - /// - let toJaggedSeq (m: matrix) = MG.toJaggedSeq m - /// converts the matrix into an seq of column seqs - /// - /// - /// - /// - /// - /// - /// - let toJaggedColSeq (m: matrix) = MG.toJaggedColSeq m - /// - let getDiagN (a:matrix) n = MG.getDiagN a n - /// - let getDiag (a:matrix) = MG.getDiag a - - // Operators - /// Performs a element wise addition of matrices a and b (a+b).
Only usable if both matrices have the same dimensions.
- /// - /// - /// - /// - /// - /// - /// - /// - let add (a:matrix) (b:matrix) = MS.addM a b - /// Performs a element wise substraction of matrices a and b (a-b).
Only usable if both matrices have the same dimensions.
- /// - /// - /// - /// - /// - /// - /// - /// - let sub (a:matrix) (b:matrix) = MS.subM a b - /// Performs a left sided matrix multiplication of a and b (a*b).
Only usable if both matrices have the same dimensions.
- /// - /// - /// - /// - /// - /// - /// - /// - let mul (a:matrix) (b:matrix) = MS.mulM a b - /// Performs a matrix multiplication m*n matrix a and the m*1 vector b (a*b).
Only usable if column number (n) of the matrix equals the row number (m) of the vector.
- /// - /// - /// - /// - /// - /// - /// - /// - let mulV (a:matrix) (b:vector) = MS.mulMV a b - /// Performs a matrix multiplication of the 1*n rowvector a and the m*n matrix b (a*b).
Only usable if column number (n) of the vector equals the row number (m) of the matrix.
- /// - /// - /// - /// - /// - /// - /// - /// - let mulRV (a:rowvec) (b:matrix) = MS.mulRVM a b - /// Performs a element wise multiplication of matrices a and b (a+b, Hadamard-Product).
Only usable if both matrices have the same dimensions.
- /// - /// - /// - /// - /// - /// - /// - /// - let cptMul (a:matrix) (b:matrix) = MS.cptMulM a b - /// Performs a element wise comparison of matrices a and b always preserving the greater value.
Only usable if both matrices have the same dimensions.
- /// - /// - /// - /// - /// - /// - /// - /// - let cptMax (a:matrix) (b:matrix) = MS.cptMaxM a b - /// Performs a element wise comparison of matrices a and b always preserving the smaller value.
Only usable if both matrices have the same dimensions.
- /// - /// - /// - /// - /// - /// - /// - /// - let cptMin (a:matrix) (b:matrix) = MS.cptMinM a b - /// Builds a new matrix where the elements are the result of multiplying every element of the given matrix with the given value - /// - /// - /// - /// - /// - /// - /// - /// - let scale a (b:matrix) = MS.scaleM a b - /// Scales matrix a by element wise mulitplication with minus 1. - /// - /// - /// - /// - /// - /// - /// - let neg (a:matrix) = MS.negM a - /// Computes the trace of matrix a by summing elements of the diagonal.
Only usable if matrices a is a square matrix (m*m).
- /// - /// - /// - /// - /// - /// - /// - let trace (a:matrix) = MS.traceM a - /// Returns the transpose of matrix a - /// - /// - /// - /// - /// - /// - /// - let transpose (a:matrix) = MG.transpose a - /// Iterates the given Matrix row wise and applies function f element wise.
The iteration stops and returns false if an element fails the condition or true when the end of
the matrix is reached.
- /// - /// - /// - /// - /// - /// - /// - /// - let forall f (a:matrix) = MG.forall f a - /// Iterates the given Matrix row wise and applies function f element wise.
The iteration stops and returns true if an element satisfies the condition or false when the end of
the matrix is reached.
- /// - /// - /// - /// - /// - /// - /// - /// - let exists f (a:matrix) = MG.exists f a - /// Iterates the given Matrix row wise and applies function f element wise.
The iteration stops and returns false if an element fails the condition or true when the end of
the matrix is reached.
- /// - /// - /// - /// - /// - /// - /// - /// - let foralli f (a:matrix) = MG.foralli f a - /// Iterates the given Matrix row wise and applies function f element wise.
The iteration stops and returns true if an element satisfies the condition or false when the end of
the matrix is reached.
- /// - /// - /// - /// - /// - /// - /// - /// - let existsi f (a:matrix) = MG.existsi f a - let x = List.fold - /// Builds a new matrix whose elements are the result of row wise applying the given function on each element of a. - /// - /// - /// - /// - /// - /// - /// - /// - let map f (a:matrix) = MG.map f a - /// Builds a new matrix whose elements are identical to the elements of a. - /// - /// - /// - /// - /// - /// - /// - let copy (a:matrix) = MG.copy a - /// Builds a new matrix whose elements are the result of row wise applying the given function on each element of a. The integer index
passed to the function indicates the index (from 0) the of the element being transformed.
- /// - /// - /// - /// - /// - /// - /// - /// - let mapi f (a:matrix) : matrix = MG.mapi f a - /// Applies a function f row wise to each element of the matrix, threading an accumulator argument through the computation.
The fold function takes the second argument, and applies the function f to it and the first element of the matrix.
Then, it feeds this result into the function f along with the second element, and so on. It returns the final result.
If the input function is f and the elements are i0...iN, then this function computes f (... (f s i0) i1 ...) iN.
- /// - /// - /// - /// - /// - /// - /// - /// - /// - let fold f z (a:matrix) = MG.fold f z a - /// Applies a function f row wise to each element of the matrix, threading an accumulator argument through the computation.
The fold function takes the second argument, and applies the function f to it and the first element of the matrix.
Then, it feeds this result into the function f along with the second element, and so on. It returns the final result.
If the input function is f and the elements are i0...iN, then this function computes f (... (f s i0) i1 ...) iN.
The integers indicies passed to the function indicate row and column position (from 0) the of the element being transformed.
- /// - /// - /// - /// - /// - /// - /// - /// - /// - let foldi f z (a:matrix) = MG.foldi f z a - /// Transforms the matrix a to a dense matrix representation - /// - /// - /// - /// - /// - /// - /// - let toDense (a:matrix) = MG.toDense a - /// Transforms the matrix a to a sparse matrix representation - /// - /// - /// - /// - /// - /// - /// - let toSparse (a:matrix) = MG.toSparse a - /// Creates a dense matrix with i rows and j columns. All values are initialized to the value of a. - /// - /// - /// - /// - /// - /// - /// - /// - /// - let initDense i j a : matrix = MG.initDense i j a - /// Creates a sparse matrix with i rows and j columns. All values are initialized to the value of a. - /// - /// - /// - /// - /// - /// - /// - /// - /// - let initSparse i j a : matrix = MG.initSparse i j a - /// Iterates the m*n matrix a row wise and returns a list of tuples (mi,ni,v) containing non zero elements of a
and their row (m) and column (n) indicies.
- /// - /// - /// - /// - /// - /// - /// - let nonzero_entries (a:matrix) = MG.nonzeroEntries a - /// Creates a dense matrix with i rows and j columns. All values are initialized to yero (0.). - /// - /// - /// - /// - /// - /// - /// - /// - let zero m n = DS.zeroDenseMatrixDS m n |> MS.dense - /// Creates a dense identiy m*m matrix. A identity matrix is always squared and the elements are set to zero exept elements
on the diagonal, which are set to 1.
e.g.
[[1.;0.;0.]
[0.;1.;0.]
[0.;0.;1.]]
- /// - /// - /// - /// - /// - /// - /// - let identity m : matrix = MG.identity m - /// Creates a dense matrix with i rows and j columns. All values are initialized to one (1.). - /// - /// - /// - /// - /// - /// - /// - /// - let ones m n = create m n 1.0 - /// Returns row of index i of matrix a - /// - /// - /// - /// - /// - /// - /// - /// - let getRow (a:matrix) i = MG.getRow a i - /// Replaces row of index i of matrix a with values of vector v, if vector length matches rowsize - /// - /// - /// - /// - /// - /// - /// - /// - /// - let setRow (a:Matrix<_>) i (v:Vector<_>) = MG.setRow a i v - /// Returns col of index j of matrix a - /// - /// - /// - /// - /// - /// - /// - /// - let getCol (a:matrix) j = MG.getCol a j - /// Replaces column of index j of matrix a with values of vector v, if vector length matches columnsize - /// - /// - /// - /// - /// - /// - /// - /// - /// - let setCol (a:Matrix<_>) j (v:Vector<_>) = MG.setCol a j v - /// Accesses the m*n matrix a and returns a total of j2 Columns starting from column index j1. The Result is a new
m*j2 matrix.
Only usable if (j1+j2-1) does not exceed n.
- /// - /// - /// - /// - /// - /// - /// - /// - /// - let getCols (a:matrix) j1 j2 = MG.getCols a j1 j2 - /// Accesses the m*n matrix a and returns a total of i2 rows starting from row index i1. The Result is a new
i2*n matrix.
Only usable if (i1+i2-1) does not exceed m.
- /// - /// - /// - /// - /// - /// - /// - /// - /// - let getRows (a:matrix) i1 i2 = MG.getRows a i1 i2 - - let countBy f (a:matrix) = - let n = a.NumCols * a.NumRows - let (r,c) = a.Dimensions - let rec loop ir ic acc = - if ir = r then - if ic = c then - [true,acc;false,n - acc] - else loop ir (ic+1) (if f a.[ir,ic] then acc + 1 else acc) - else - if ic = c then - loop (ir+1) 0 acc - else loop (ir+1) (ic+1) (if f a.[ir,ic] then acc + 1 else acc) - loop 0 0 0 - - /// Accesses the m*n matrix a and returns a total of i2 rows and j2 columns starting from row index i1 and colum index j1. The Result is a new
i2*j2 matrix.
Only usable if (i1+i2-1) does not exceed m and (j1+j2-1) does not exceed n.
- /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - let getRegion (a:matrix) i1 j1 i2 j2 = MG.getRegion a i1 j1 i2 j2 - let rowRange (a:Matrix<_>) = (0,a.NumRows - 1) - let colRange (a:Matrix<_>) = (0,a.NumCols - 1) - let wholeRegion a = (colRange a, rowRange a) - let foldByRow f (z:Vector<'T>) (a:Matrix<_>) = - colRange a |> GU.foldR (fun z j -> MS.mapiV (fun i z -> f z (get a i j)) z) z - let foldByCol f (z:RowVector<'T>) (a:Matrix<_>) = - rowRange a |> GU.foldR (fun z i -> MS.mapiRV (fun j z -> f z (get a i j)) z) z - let foldRow f (z:'T) (a:Matrix<_>) i = - colRange a |> GU.foldR (fun (z:'T) j -> f z (get a i j)) z - let foldCol f (z:'T) (a:Matrix<_>) j = - rowRange a |> GU.foldR (fun (z:'T) i -> f z (get a i j)) z - let sum (a:matrix) = MS.sumM a - let prod (a:matrix) = MS.prodM a - let norm (a:matrix) = MS.normM a - let dot (a:matrix) b = MS.dotM a b - let cptPow a y = map (fun x -> x ** y) a - // Functions that only make sense on this type - let randomize v = map (fun vij -> MRandom.float vij) v (* res_ij = random [0,vij] values *) - let ofRowVector x : matrix = MS.rowvecM x - let ofVector x : matrix = MS.vectorM x - let toVector x : vector = MS.toVectorM x - let toRowVector x : rowvec = MS.toRowVectorM x - let toScalar x : float = MS.toScalarM x - let inplaceAdd (a:matrix) b = MS.inplaceAddM a b - let inplaceSub (a:matrix) b = MS.inplaceSubM a b - // Mutation - let inplace_assign f (a:matrix) = MG.inplace_assign f a - let inplace_mapi f (a:matrix) = MG.inplace_mapi f a - let inplace_cptMul (a:matrix) b = MS.inplaceCptMulM a b - let inplace_scale a (b:matrix) = MS.inplaceScaleM a b - [] - let inplace_add a b = inplaceAdd a b - [] - let inplace_sub a b = inplaceSub a b - [] - let of_rowvec x = ofRowVector x - [] - let of_vector x = ofVector x - [] - let to_vector x = toVector x - [] - let to_rowvec x = toRowVector x - [] - let to_scalar x = toScalar x - [] - let inline of_array2D arr = ofArray2D arr - [] - let inline sparse_of_array2D arr = sparseOfArray2D arr - [] - let inline to_array2D m = toArray2D m - [] - let of_list xss = ofJaggedList xss - [] - let of_seq xss = ofJaggedSeq xss - [] - let init_diagonal v = initDiagonal v - [] - let of_scalar x = ofScalar x - [] - let to_dense x = toDense x - [] - let to_sparse x = toSparse x - [] - let init_dense i j a = initDense i j a - [] - let init_sparse i j a = initSparse i j a - - //---------------------------------------------------------------------------- - // Stats - - /// Returns upper triangular Matrix by setting all values beneath the diagonal to Zero.
Warning: triangular matrices can only be computed for square input matrices.
- /// - /// - /// - /// - /// - /// - /// - let getUpperTriangular (a:Matrix) = - let nA = a.NumCols - let mA = a.NumRows - if nA<>mA then invalidArg "a" "expected a square matrix"; - else - a - |> mapi (fun n m x -> if n > m then 0. else x ) - - /// Returns lower triangular Matrix by setting all values beneath the diagonal to Zero.
Warning: triangular matrices can only be computed for square input matrices.
- /// - /// - /// - /// - /// - /// - /// - let getLowerTriangular (a:Matrix) = - let nA = a.NumCols - let mA = a.NumRows - if nA<>mA then invalidArg "a" "expected a square matrix"; - else - a - |> mapi (fun n m x -> if n < m then 0. else x ) - - /// Returns diagonal matrix by setting all values beneath and above the diagonal to Zero.
Warning: diagonal matrices can only be computed for square input matrices.
- /// - /// - /// - /// - /// - /// - /// - let toDiagonal (a:Matrix) = - getDiag a - |> diag - - /// Computes the row wise sums of a Matrix - /// - /// - /// - /// - /// - /// - /// - let sumRows (a:matrix) = - a - |> foldByRow (fun acc r -> acc + r ) (Vector.zeroCreate a.NumRows) - - /// Computes the column wise sums of a Matrix - /// - /// - /// - /// - /// - /// - /// - let sumColumns (a:matrix) = - a - |> foldByCol (fun acc r -> acc + r ) (RowVector.zero a.NumCols) - - /// Computes the row wise mean of a Matrix - /// - /// - /// - /// - /// - /// - /// - let meanRowWise (a:matrix) = - a - |> sumRows - |> Vector.map (fun sum -> sum / (a.NumCols |> float)) - - /// Computes the Column wise mean of a Matrix - /// - /// - /// - /// - /// - /// - /// - let meanColumnWise (a:matrix) = - a - |> sumColumns - |> RowVector.map (fun sum -> sum / (a.NumRows |> float)) - - ///Computes mean in the specified orientation - /// orientation - "RowWise" or "ColWise" - /// - /// - /// - /// - /// - /// - /// - /// - let meanAsSeq (orientation:Orientation) (a:matrix) = - match orientation with - | RowWise -> meanRowWise a |> seq - | ColWise -> meanColumnWise a |> seq - - /// computes the column specific covariance matrix of a data matrix as described at: - // http://stattrek.com/matrix-algebra/covariance-matrix.aspx - let columnCovarianceMatrixOf df (dataMatrix:Matrix) = - /// Step 1:
contains the deviation scores for the data matrix - let devMatrix = - let ident = ones dataMatrix.NumRows dataMatrix.NumRows - dataMatrix - (ident * dataMatrix |> map (fun elem -> elem / float dataMatrix.NumRows)) - /// Step 2:
Compute devMatrix' * devMatrix, the k x k deviation sums of squares and cross products matrix for x. - let devMTdevM = - devMatrix.Transpose * devMatrix - /// Step 3:
Then, divide each term in the deviation sums of squares and cross product matrix by n to create the variance-covariance matrix. That is: - devMTdevM |> map (fun elem -> elem / (float df)) - - /// computes the column specific population covariance matrix of a data matrix - /// - /// - /// - /// - /// - /// - /// - let columnPopulationCovarianceMatrixOf (dataMatrix:Matrix) = - columnCovarianceMatrixOf dataMatrix.NumRows dataMatrix - - /// computes the column specific sample covariance matrix of a data matrix - /// - /// - /// - /// - /// - /// - /// - let columnSampleCovarianceMatrixOf (dataMatrix:Matrix) = - columnCovarianceMatrixOf (dataMatrix.NumRows-1) dataMatrix - - /// computes the row specific population covariance matrix of a data matrix - /// - /// - /// - /// - /// - /// - /// - let rowPopulationCovarianceMatrixOf (dataMatrix:Matrix) = - columnCovarianceMatrixOf dataMatrix.Transpose.NumRows dataMatrix.Transpose - - /// computes the row specific sample covariance matrix of a data matrix - /// - /// - /// - /// - /// - /// - /// - let rowSampleCovarianceMatrixOf (dataMatrix:Matrix) = - columnCovarianceMatrixOf (dataMatrix.Transpose.NumRows-1) dataMatrix.Transpose - - /// computes the orientation and dataSource specific covariance matrix of a dataMatrix\
dataSource - "Sample" or "Population". \
orientation - "RowWise" or "ColWise"
- /// - /// - /// - /// - /// - /// - /// - /// - /// - let covarianceMatrixOf (dataSource:DataSource) (orientation:Orientation) (dataMatrix:matrix) :matrix = - match dataSource with - |Sample -> - match orientation with - |RowWise ->rowSampleCovarianceMatrixOf dataMatrix - |ColWise ->columnSampleCovarianceMatrixOf dataMatrix - |Population -> - match orientation with - |RowWise ->rowPopulationCovarianceMatrixOf dataMatrix - |ColWise ->columnPopulationCovarianceMatrixOf dataMatrix - //---------------------------------------------------------------------------- - - /// Applies function f along row axis - /// - /// - /// - /// - /// - /// - /// - /// - let mapRows f (m:matrix) = Generic.mapRows f m - /// Applies function f along row axis - [] - let enumerateRowWise f (m:matrix) = Generic.mapRows f m - - /// Maps every matrix row using the position dependant function - /// - /// - /// - /// - /// - /// - /// - /// - let mapiRows (f: int -> rowvec -> 'b) (m:matrix) = Generic.mapiRows f m - - /// Applies function f along column axis - /// - /// - /// - /// - /// - /// - /// - /// - let mapCols f (m:matrix) = Generic.mapCols f m - /// Applies function f along column axis - [] - let enumerateColumnWise f (m:matrix) = Generic.mapCols f m - - /// Maps every matrix column using the position dependant function - /// - /// - /// - /// - /// - /// - /// - /// - let mapiCols (f: int -> vector -> 'b) (m:matrix) = Generic.mapiCols f m - - /// Iterates the given Matrix row wise and places every element in a new vector with length n*m. - /// - /// - /// - /// - /// - /// - /// - let flattenRowWise (a: matrix) = Generic.flattenRowWise a - - /// Iterates the given Matrix column wise and places every element in a new vector with length n*m. - /// - /// - /// - /// - /// - /// - /// - let flattenColWise (a: matrix) = Generic.flattenColWise a - - /// Removes a row at a given index - /// - /// - /// - /// - /// - /// - /// - /// - let removeRowAt (index:int) (m:Matrix<'T>) : Matrix<'T> = - let nRows,nCols = m.Dimensions - //let nm = Matrix.Generic.zero (nRows-1) nCols - let nm = MG.zeroCreate (nRows-1) nCols - let rec loop nRowI rowI = - if rowI < 0 then - nm - else - if rowI <> index then - for colI=0 to nCols-1 do - nm.[nRowI,colI] <- m.[rowI,colI] - loop (nRowI-1) (rowI-1) - else - loop (nRowI) (rowI-1) - - loop (nRows-2) (nRows-1) - - /// - /// Returns a matrix without the rows for which the given predicate returns false

The predicate function based on which the rows should be filtered. The resulting matrix will only contain rows for which this function returns true
The matrix to filter rows from
- /// - /// - /// - /// - /// - /// - /// - let filterRows (rowPredicate: (RowVector<'T> -> bool)) (m:Matrix<'T>) : Matrix<'T> = - let validRows = - [| - for rowIndex in 0..m.NumRows - 1 do - let row = MG.getRow m rowIndex - if rowPredicate row then yield rowIndex - |] - MG.init validRows.Length m.NumCols (fun r c -> - m.[validRows.[r],c] - ) - - /// - /// Returns a matrix without the cols for which the given predicate returns false

The predicate function based on which the cols should be filtered. The resulting matrix will only contain rows for which this function returns true
The matrix to filter cols from
- /// - /// - /// - /// - /// - /// - /// - let filterCols (colPredicate: (Vector<'T> -> bool)) (m:Matrix<'T>) : Matrix<'T> = - let validCols = - [| - for colIndex in 0..m.NumCols - 1 do - let col = MG.getCol m colIndex - if colPredicate col then yield colIndex - |] - MG.init m.NumRows validCols.Length (fun r c -> - m.[r,validCols.[c]] - ) - - /// Removes a column at a given index - /// - /// - /// - /// - /// - /// - /// - /// - let removeColAt index (m:Matrix<_>) = - let nRows,nCols = m.Dimensions - //let nm = Matrix.Generic.zero nRows (nCols-1) - let nm = MG.zeroCreate nRows (nCols-1) - let rec loop nColI colI = - if nColI < 0 then - nm - else - if colI <> index then - for rowI=0 to nRows-1 do - nm.[rowI,nColI] <- m.[rowI,colI] - loop (nColI-1) (colI-1) - else - loop (nColI) (colI-1) - - loop (nCols-2) (nCols-1) - - /// Splits a matrix along row direction according to given indices. Returns (matrix including rows according to indices, rest) - /// - /// - /// - /// - /// - /// - /// - /// - let splitRows (indices:int[]) (m:Matrix<_>) = - - let nRows,nCols = m.Dimensions - //let nm = Matrix.Generic.zero (nRows-indices.Length) nCols - //let nmi = Matrix.Generic.zero indices.Length nCols - let nm = MG.zeroCreate (nRows-indices.Length) nCols - let nmi = MG.zeroCreate indices.Length nCols - indices |> Array.sortInPlace - let rec loop nRowI nRowIi rowI = - match rowI with - | i as rowI when rowI < 0 -> nmi,nm - | i as rowI when nRowIi >= 0 && rowI = indices.[nRowIi] -> - for colI=0 to nCols-1 do - nmi.[nRowIi,colI] <- m.[rowI,colI] - loop (nRowI) (nRowIi-1) (rowI-1) - | _ -> //i as rowI when rowI <> indices.[ii] -> - for colI=0 to nCols-1 do - nm.[nRowI,colI] <- m.[rowI,colI] - loop (nRowI-1) (nRowIi) (rowI-1) - - loop (nRows-1-indices.Length) (indices.Length-1) (nRows-1) - - /// Splits a matrix along column direction according to given indices. Returns (matrix including cols according to indices, rest) - /// - /// - /// - /// - /// - /// - /// - /// - let splitCols (indices:int[]) (m:Matrix<_>) = - let nRows,nCols = m.Dimensions - //let nm = Matrix.Generic.zero nRows (nCols-indices.Length) - //let nmi = Matrix.Generic.zero nRows indices.Length - let nm = MG.zeroCreate nRows (nCols-indices.Length) - let nmi = MG.zeroCreate nRows indices.Length - indices |> Array.sortInPlace - let rec loop nColI nColIi colI = - match colI with - | i as colI when colI < 0 -> nmi,nm - | i as colI when nColIi >= 0 && colI = indices.[nColIi] -> - for rowI=0 to nRows-1 do - nmi.[rowI,nColIi] <- m.[rowI,colI] - loop (nColI) (nColIi-1) (colI-1) - | _ -> //i as rowI when rowI <> indices.[ii] -> - for rowI=0 to nRows-1 do - nm.[rowI,nColI] <- m.[rowI,colI] - loop (nColI-1) (nColIi) (colI-1) - - loop (nCols-1-indices.Length) (indices.Length-1) (nCols-1) - - -[] -module MatrixExtension = - - type Matrix<'T> with - member x.ToArray2() = Matrix.Generic.toArray2D x - member x.ToArray2D() = Matrix.Generic.toArray2D x - - /// Reads generic matrix from file. Requires a function to transform the input strings to the desired type - static member ReadCSV(path,transformValues,?Separator,?RemoveHeaderRow,?RemoveHeaderCol): Matrix<'T> = - - let sep = defaultArg Separator '\t' - let rmr = defaultArg RemoveHeaderRow false - let rmc = defaultArg RemoveHeaderCol false - - Matrix.Generic.readCSV path sep rmr rmc transformValues - -#if FX_NO_DEBUG_DISPLAYS -#else - [] -#endif - - member x.NonZeroEntries = Matrix.Generic.nonzeroEntries x - member x.ToScalar() = Matrix.Generic.toScalar x - member x.ToRowVector() = Matrix.Generic.toRowVector x - member x.ToVector() = Matrix.Generic.toVector x - -#if FX_NO_DEBUG_DISPLAYS -#else - [] -#endif - member x.Norm = Matrix.Generic.norm x - member x.Column(n) = Matrix.Generic.getCol x n - member x.Row(n) = Matrix.Generic.getRow x n - member x.Columns (i,ni) = Matrix.Generic.getCols x i ni - member x.Rows (j,nj) = Matrix.Generic.getRows x j nj - member x.Region(i,j,ni,nj) = Matrix.Generic.getRegion x i j ni nj - member x.GetDiagonal(i) = Matrix.Generic.getDiagN x i - -#if FX_NO_DEBUG_DISPLAYS -#else - [] -#endif - member x.Diagonal = Matrix.Generic.getDiag x - - member x.Copy () = Matrix.Generic.copy x - -// [] -// module MatrixTopLevelOperators = -// -// let matrix ll = Matrix.ofSeq ll -// let vector l = Vector.ofSeq l -// let rowvec l = RowVector.ofSeq l diff --git a/src/FSharp.Stats/MatrixTopLevelOperators.fs b/src/FSharp.Stats/MatrixTopLevelOperators.fs deleted file mode 100644 index b54077d12..000000000 --- a/src/FSharp.Stats/MatrixTopLevelOperators.fs +++ /dev/null @@ -1,10 +0,0 @@ -//namespace Microsoft.FSharp.Math // old namespace -namespace FSharp.Stats - -[] -module MatrixTopLevelOperators = - - let matrix ll = Matrix.ofJaggedSeq ll - let vector l = Vector.ofSeq l - let rowvec l = RowVector.ofSeq l - diff --git a/src/FSharp.Stats/RowVector.fs b/src/FSharp.Stats/RowVector.fs deleted file mode 100644 index 586d45c28..000000000 --- a/src/FSharp.Stats/RowVector.fs +++ /dev/null @@ -1,88 +0,0 @@ -namespace FSharp.Stats - -#nowarn "60" // implementations in augmentations -#nowarn "69" // implementations in augmentations - -open System -open System.Globalization -open System.Collections -open System.Collections.Generic -open System.Diagnostics - -[] -module RowVector = - - module Generic = - - module OpsS = SpecializedGenericImpl - - let get (a:RowVector<_>) i = a.[i] - let set (a:RowVector<_>) i x = a.[i] <- x - let zero n = OpsS.zeroRV n - let length (v:RowVector<_>) = v.Length - let init m f = OpsS.initRV m f - let create m x = OpsS.constRV m x - let transpose a = OpsS.transRV a - let copy a = OpsS.copyRV a - let ofList a = OpsS.listRV a - let ofArray a = OpsS.arrayRV a - let ofSeq a = OpsS.seqRV a - let toArray m = Array.init (length m) (get m) - [] - let of_list a = ofList a - [] - let of_array a = ofArray a - [] - let of_seq a = ofSeq a - [] - let to_array m = toArray m - let map mapping (a:RowVector<_>) = OpsS.mapRV mapping a - - module RVG = Generic - - let get (a:rowvec) i = RVG.get a i - let set (a:rowvec) i x = RVG.set a i x - let length (a:rowvec) = RVG.length a - let ncols (a:rowvec) = RVG.length a - let ofArray arr : rowvec = RVG.ofArray arr - let toArray (m : rowvec) = RVG.toArray m - - let init m f : rowvec = RVG.init m f - let create m f : rowvec = RVG.create m f - let zero n = create n 0.0 - let ofList x : rowvec = RVG.ofList x - let ofSeq x : rowvec = RVG.ofSeq x - let transpose x : vector = RVG.transpose x - let copy x : rowvec = RVG.copy x - - [] - let of_list x = ofList x - [] - let of_seq x = ofSeq x - [] - let of_array arr = ofArray arr - [] - let to_array m = toArray m - /// Builds a new rowvector whose elements are the results of applying the given function to each of the elements of the rowvector. - /// - /// - /// - /// - /// - /// - /// - /// - let map mapping (rowvec:rowvec) = RVG.map mapping rowvec - - - - -[] -module RowVectorExtension = - - type RowVector<'T> with - member x.ToArray() = RowVector.Generic.toArray x - member x.Copy () = RowVector.Generic.copy x - - - diff --git a/src/FSharp.Stats/ServiceLocator.fs b/src/FSharp.Stats/ServiceLocator.fs deleted file mode 100644 index b54bc8eb9..000000000 --- a/src/FSharp.Stats/ServiceLocator.fs +++ /dev/null @@ -1,191 +0,0 @@ -namespace FSharp.Stats - -open System.IO -open System.Collections.Generic - -module ServiceLocator = - - type Architecture = - | X64 - | X86 - - type OS = - | Windows - | Linux - | Mac - - /// Generic provider with unmanaged DLL dependencies. - type Provider<'a> = { - Name : string - RequiredDLLs : string seq - Architecture : Architecture - OS : OS - InitService : unit -> 'a - } - - let createProviderX64<'a> name requiredDLLs os initService : Provider<'a> = - {Name=name;RequiredDLLs=requiredDLLs;Architecture=Architecture.X64;OS=os;InitService=initService} - - let createProviderX86<'a> name requiredDLLs os initService : Provider<'a> = - {Name=name;RequiredDLLs=requiredDLLs;Architecture=Architecture.X86;OS=os;InitService=initService} - - let setEnvironmentPathVariable dllDirectory = - System.Environment.SetEnvironmentVariable("PATH", System.Environment.GetEnvironmentVariable("PATH") + ";" + dllDirectory) - - /// The DLLs search procedure for those DLLs - // - // The default behavior now is to look in all the system locations first, then the current directory, and finally any user-defined paths. - // This will have an impact on your code if you install a DLL in the application's directory because Windows Server 2003 no longer loads - // the 'local' DLL if a DLL of the same name is in the system directory. A common example is if an application won't run with a specific - // version of a DLL, an older version is installed that does work in the application directory. This scenario will fail in Windows Server 2003. - // - // Search order: - // The Windows system directory. The GetSystemDirectory function retrieves the path of this directory. - // The Windows directory. The GetWindowsDirectory function retrieves the path of this directory. - // The directory where the executable module for the current process is located. - // The current directory. - // The directories listed in the PATH environment variable. - let initSearchPaths () = - let noLaterRepeats xs = - let collect (soFar,revXs) x = - if Set.contains x soFar then (soFar,revXs) else (Set.add x soFar,x::revXs) - let (_,revXs) = List.fold collect (Set.empty,[]) xs - revXs - //List.rev revXs - - let windowsSystemDir = System.Environment.SystemDirectory - let windowsDir = - windowsSystemDir - |> System.IO.Path.GetDirectoryName - let currentExeDirs = - // This includes EXE directory, and loaded DLL directories. - // It may be an over-estimate of the search path. - let proc = System.Diagnostics.Process.GetCurrentProcess() - [ for m in proc.Modules do - yield Path.GetDirectoryName m.FileName ] - |> List.distinct - let currentDir = System.Environment.CurrentDirectory - let executingAssembly = System.Reflection.Assembly.GetExecutingAssembly().Location - let pathDirs = - match System.Environment.GetEnvironmentVariable("PATH") with - | null -> [] - | paths -> paths.Split([|';'|]) |> List.ofArray - - windowsSystemDir :: windowsDir :: (currentExeDirs @ [currentDir;executingAssembly] @ pathDirs) - //noLaterRepeats orderedSearchPaths - - // normalizes filename - let normDllFilename (dll:string) = - (Path.GetFileName dll).ToLower() - - let initDllPathTable () : Map = - initSearchPaths () - |> Seq.collect (fun path -> - if not (Directory.Exists path) then - seq [] - else - Directory.GetFiles(path,"*.DLL") - |> Seq.map (fun file -> normDllFilename file,path) - ) - |> Seq.fold (fun state (file,path) -> - if state.ContainsKey file then - let tmp = state.[file] - // rev path order ! - state |> Map.add file (path::tmp) - else - state |> Map.add file ([path]) - ) Map.empty - - - let isLoadableProvider (dllPaths:Map) (provider:Provider<'a>) = - let isAvailable (dll:string) = dllPaths.ContainsKey(normDllFilename dll) - provider.RequiredDLLs |> Seq.forall isAvailable - - - let tryCheckProvider (dllPaths:Map) (provider:Provider<'a>) = - //let isAvailable (dll:string) = dllPaths.ContainsKey(normDllFilename dll) - let availableReason (dll:string) = - dllPaths.[normDllFilename dll] - |> Seq.map (fun path -> sprintf "Required %s seen in %s" dll path ) - |> String.concat "\n" - if isLoadableProvider dllPaths provider then - let justification = - provider.RequiredDLLs - |> Seq.map availableReason - |> String.concat "\n" - Some (provider,("Provider: " + provider.Name + "\n" + justification)) - else - None // "Provider is not loadable" - - - - - type 'a ServiceState = - | ServiceDisabled // service disabled, do not look for it. - | ServiceEnabledUninitialised // service enabled, but no search made yet. - | ServiceEnabledOK of 'a * string // service enabled, and justification string for diagnostics. - | ServiceEnabledFailed // service enabled, but DLLs not found, or load failed. - - - type ServiceProvider<'a>(providers:Provider<'a> seq) = - let mutable providers = Seq.toArray providers // possible providers configuration state - let mutable state = ServiceEnabledUninitialised // service state - let dllPaths = initDllPathTable () - - /// Service Providers - member this.Providers with get() = providers - and set(x) = providers <- x - - /// Disable the service. - member this.Stop() = state <- ServiceDisabled - - /// Use the LAPACK service from the given provider. - /// If the supporting DLLs are not available, this may fail (now or later). - member this.StartWith(p:Provider<'a>) = - let justification = - match tryCheckProvider dllPaths p with - | None -> "The provider DLLs did not appear to be present, the service may fail" - | Some (p,justification) -> justification - state <- ServiceEnabledOK (p.InitService(),justification) - - /// Start the service with the first provider that looks loadable. - member this.Start() = - let candidates = Array.choose (tryCheckProvider dllPaths) providers - if candidates.Length=0 then // guard - state <- ServiceEnabledFailed - false - else - let provider,justification = candidates.[0] - state <- ServiceEnabledOK (provider.InitService(),justification) // index covered by guard above - true - - member this.GetPathMap() = dllPaths - - member this.Service() = - match state with - | ServiceEnabledUninitialised -> this.Start() |> ignore - | _ -> () - match state with - | ServiceDisabled - | ServiceEnabledUninitialised // (The above initialisation call must have failed) - | ServiceEnabledFailed -> None - | ServiceEnabledOK (service,_) -> Some service - - member this.Available() = - match state with - | ServiceDisabled - | ServiceEnabledFailed - | ServiceEnabledUninitialised -> false - | ServiceEnabledOK (_,_) -> true - - member this.Status() = - match state with - | ServiceDisabled -> "Disabled" - | ServiceEnabledFailed -> "Failed to start" - | ServiceEnabledUninitialised -> "Will auto enable on demand" - | ServiceEnabledOK (service,justification) -> "Enabled\n" + justification - - - - - diff --git a/src/FSharp.Stats/Vector.fs b/src/FSharp.Stats/Vector.fs deleted file mode 100644 index b2a2cfbce..000000000 --- a/src/FSharp.Stats/Vector.fs +++ /dev/null @@ -1,880 +0,0 @@ -namespace FSharp.Stats - -#nowarn "60" // implementations in augmentations -#nowarn "69" // implementations in augmentations - -open System -open System.Collections - -//---------------------------------------------------------------------------- -// module Vector -//---------------------------------------------------------------------------- - -[] -//Basic vector operations -module Vector = - - module Generic = - - module OpsS = SpecializedGenericImpl - /// Returns the value of the vector a at the given index i - /// vector to get value for - /// index in the vector to get value for - /// the value at index - let get (vector:Vector<'T>) index = vector.[index] - /// Sets the value to the vector a at the given index - /// vector to set value for - /// index in the vector to set value for - /// value to set in the vector - let set (vector:Vector<'T>) index value = vector.[index] <- value - /// Returns length of vector v - /// - /// - /// - /// - /// - /// - /// - let length (vector:Vector<'T>) = vector.Length - /// Creates vector from list xss - /// - /// - /// - /// - /// - /// - /// - let ofList list = OpsS.listV list - /// Creates vector from seq xss - /// - /// - /// - /// - /// - /// - /// - let ofSeq source = OpsS.seqV source - /// Initializes vector with count members, based on function f - /// - /// - /// - /// - /// - /// - /// - /// - let init count initializer = OpsS.initV count initializer - let initNumeric count f = OpsS.createNumericV count f - let ofArray array = OpsS.arrayV array - let toArray (vector:Vector<'T>) = Array.init vector.Length (get vector) - /// Creates vector of length count and fills it with value - /// - /// - /// - /// - /// - /// - /// - /// - let create count value = OpsS.constV count value - /// Creates a vector of length count and fills it with zeros - /// - /// - /// - /// - /// - /// - /// - let zeroCreate count = OpsS.zeroV count - /// Creates a vector of length count and fills it with ones - /// - /// - /// - /// - /// - /// - /// - let oneCreate count = OpsS.createNumericV count (fun ops _ -> ops.One) - [] - let zero count = OpsS.zeroV count - [] - let ones count = OpsS.createNumericV count (fun ops _ -> ops.One) - let ofScalar x = OpsS.scalarV x - let add vector1 vector2 = OpsS.addV vector1 vector2 - let sub vector1 vector2 = OpsS.subV vector1 vector2 - let mulRVV vector1 vector2 = OpsS.mulRVV vector1 vector2 - let mulVRV vector1 vector2 = OpsS.mulVRV vector1 vector2 - let cptMul vector1 vector2 = OpsS.cptMulV vector1 vector2 - let cptMax vector1 vector2 = OpsS.cptMaxV vector1 vector2 - let cptMin vector1 vector2 = OpsS.cptMinV vector1 vector2 - let scale a b = OpsS.scaleV a b - /// Dot product of the two vectors - /// - /// - /// - /// - /// - /// - /// - /// - let dot vector1 vector2 = OpsS.dotV vector1 vector2 - let neg vector = OpsS.negV vector - let transpose vector = OpsS.transV vector - let inplaceAdd vector1 vector2 = OpsS.inplaceAddV vector1 vector2 - let inplaceSub vector1 vector2 = OpsS.inplaceSubV vector1 vector2 - let inplaceCptMul vector1 vector2 = OpsS.inplaceCptMulV vector1 vector2 - let inplaceScale vector1 vector2 = OpsS.inplaceScaleV vector1 vector2 - [] - let inplace_cptMul v1 v2 = OpsS.inplaceCptMulV v1 v2 - [] - let inplace_scale v1 v2 = OpsS.inplaceScaleV v1 v2 - - - let exists predicate (vector:Vector<'T>) = OpsS.existsV predicate vector - let forall predicate (vector:Vector<'T>) = OpsS.forallV predicate vector - let existsi predicate (vector:Vector<'T>) = OpsS.existsiV predicate vector - let foralli predicate (vector:Vector<'T>) = OpsS.foralliV predicate vector - let map mapping vector = OpsS.mapV mapping vector - let map2 mapping vector1 vector2 = OpsS.map2V mapping vector1 vector2 - let map3 mapping vector1 vector2 vector3 = OpsS.map3V mapping vector1 vector2 vector3 - let zip vector1 vector2 = OpsS.zipV vector1 vector2 - let unzip vector = OpsS.unzipV vector - let mapi mapping vector = OpsS.mapiV mapping vector - let copy vector = OpsS.copyV vector - let inplaceMap f v = OpsS.inplace_mapV f v - let inplaceMapi f v = OpsS.inplace_mapiV f v - [] - let inplace_map f a = OpsS.inplace_mapV f a - [] - let inplace_mapi f a = OpsS.inplace_mapiV f a - let fold (folder:'State -> 'T -> 'State) (state:'State) vector = OpsS.foldV folder state vector - let foldi (folder:int -> 'State -> 'T -> 'State) (state:'State) vector = OpsS.foldiV folder state vector - let compare comparer vector = OpsS.compareV comparer vector - let hash a = OpsS.hashV a - let inplaceAssign f vector = OpsS.assignV f vector - [] - let inplace_assign f a = OpsS.assignV f a - /// Sum of all elements of the vector a - /// - /// - /// - /// - /// - /// - /// - let sum (a:Vector<_>) = let ops = a.ElementOps in fold (fun x y -> ops.Add(x,y)) ops.Zero a - let prod (a:Vector<_>) = let ops = a.ElementOps in fold (fun x y -> ops.Multiply(x,y)) ops.One a - - let norm (a:Vector<_>) = - let normOps = GenericImpl.getNormOps a.ElementOps - sqrt (fold (fun x y -> x + normOps.Norm(y)**2.0) 0.0 a) - - [] - let of_list xss = ofList xss - [] - let of_seq xss = ofSeq xss - [] - let of_array arr = ofArray arr - [] - let to_array v = toArray v - [] - let of_scalar x = ofScalar x - [] - let inplace_add a b = inplaceAdd a b - [] - let inplace_sub a b = inplaceSub a b - - module VG = Generic - module VecDS = DoubleImpl - module VecGU = GenericImpl - /// Returns the value of the vector at the given index - /// - /// - /// - /// - /// - /// - /// - /// - let get (vector:vector) index = VG.get vector index - /// Sets the value to the vector at the given index - /// - /// - /// - /// - /// - /// - /// - /// - /// - let set (vector:vector) index value = VG.set vector index value - /// Returns length of vector - /// - /// - /// - /// - /// - /// - /// - let length (vector:vector) = VG.length vector - /// Returns length of vector - /// - /// - /// - /// - /// - /// - /// - let nRows (vector:vector) = VG.length vector - ///Returns length of vector - [] - let nrows (vector:vector) = VG.length vector - /// Initiates vector of length count and fills it by applying initializer function on indices - /// - /// - /// - /// - /// - /// - /// - /// - let init count initializer = VecDS.createVecDS count initializer - /// Creates vector with values of array - /// - /// - /// - /// - /// - /// - /// - let ofArray array : vector = VG.ofArray array - /// Creates array with values of vector - /// - /// - /// - /// - /// - /// - /// - let toArray (vector : vector) = VG.toArray vector - - type range = int * int - let countR ((a,b) : range) = (b-a)+1 - let idxR ((a,_) : range) i = a+i - type rangef = float * float * float // start, skip, end - let countRF ((a,d,b) : rangef) = System.Convert.ToInt32((b-a)/d) + 1 - let countBy projection (vector:Vector<_>) = - let n = vector.Length - let rec loop i acc = - if i = n then - [true,acc;false,n - acc] - else - if projection vector.[i] then - loop (i+1) (acc+1) - else loop (i+1) acc - loop 0 0 - //let countRF ((a,d,b) : rangef) = Float.to_int((b-a)/d) + 1 - let idxRF ((a,d,b) : rangef) i = System.Math.Min (a + d * float(i),b) - - let range n1 n2 = let r = (n1,n2) in init (countR r) (fun i -> float(idxR r i)) - - let rangef a b c = let r = (a,b,c) in init (countRF r) (fun i -> idxRF r i) - /// Creates vector with values of list - /// - /// - /// - /// - /// - /// - /// - let ofList list = VecDS.listVecDS list - /// Creates vector with values of sequence - /// - /// - /// - /// - /// - /// - /// - let ofSeq source = VecDS.seqVecDS source - ///Creates vector of length count and fills it with value - let create count value = VecDS.constVecDS count value - /// Creates one dimensional vector of value - /// - /// - /// - /// - /// - /// - /// - let ofScalar value = VecDS.scalarVecDS value - /// Builds a new vector whose elements are the results of adding the corresponding elements of the two vectors pairwise. The two input vectors must have the same lengths, otherwise ArgumentException is raised. - /// - /// - /// - /// - /// - /// - /// - /// - let add vector1 vector2 = VecDS.addVecDS vector1 vector2 - /// Builds a new vector whose elements are the results of substracting the corresponding elements of vector2 from vector1. The two input vectors must have the same lengths, otherwise ArgumentException is raised. - /// - /// - /// - /// - /// - /// - /// - /// - let sub vector1 vector2 = VecDS.subVecDS vector1 vector2 - let mulRVV vector1 vector2 = VecDS.mulRowVecVecDS vector1 vector2 - let mulVRV vector1 vector2 = VecDS.mulVecRowVecDS vector1 vector2 - /// Builds a new vector whose elements are the results of multiplying the corresponding elements of the given vectors. The two input vectors must have the same lengths, otherwise ArgumentException is raised. - /// - /// - /// - /// - /// - /// - /// - /// - let cptMul vector1 vector2 = VecDS.cptMulVecDS vector1 vector2 - let cptMax vector1 vector2 = VecDS.cptMaxVecDS vector1 vector2 - let cptMin vector1 vector2 = VecDS.cptMinVecDS vector1 vector2 - /// Builds a new vector whose elements are the results of multiplying the given scalar with each of the elements of the vector. - /// - /// - /// - /// - /// - /// - /// - /// - let scale scalar vector = VecDS.scaleVecDS scalar vector - /// Builds a new vector whose elements are the results of multiplying -1 with each of the elements of the vector. - /// - /// - /// - /// - /// - /// - /// - let neg vector = VecDS.negVecDS vector - /// Dot product of the two vectors - /// - /// - /// - /// - /// - /// - /// - /// - let dot vector1 vector2 = VecDS.dotVecDS vector1 vector2 - let transpose (vector:vector) = VG.transpose vector - let exists predicate (vector:vector) = VG.exists predicate vector - let forall predicate (vector:vector) = VG.forall predicate vector - let existsi predicate (vector:vector) = VG.existsi predicate vector - let foralli predicate (vector:vector) = VG.foralli predicate vector - /// Builds a new vector whose elements are the results of applying the given function to each of the elements of the vector. - /// - /// - /// - /// - /// - /// - /// - /// - let map mapping (vector:vector) = VG.map mapping vector - /// Builds a new vector whose elements are the results of applying the given function to the corresponding elements of the two vectors pairwise. The two input vectors must have the same lengths, otherwise ArgumentException is raised. - /// - /// - /// - /// - /// - /// - /// - /// - /// - let map2 mapping (vector1:vector) (vector2:vector) = VG.map2 mapping vector1 vector2 - /// Builds a new vector whose elements are the results of applying the given function to the corresponding elements of the two vectors pairwise. The two input vectors must have the same lengths, otherwise ArgumentException is raised. - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - let map3 mapping (vector1:vector) (vector2:vector) (vector3:vector) = VG.map3 mapping vector1 vector2 vector3 - /// Builds a new vector that contains the elements of the given vector. - /// - /// - /// - /// - /// - /// - /// - let copy (vector:vector) = VG.copy vector - /// Builds a new vector whose elements are the results of applying the given function to each of the elements of the vector and their corresponding index. - /// - /// - /// - /// - /// - /// - /// - /// - let mapi mapping (vector:vector) : vector = VG.mapi mapping vector - /// Applies a function to each element of the vector, threading an accumulator argument through the computation. - /// - /// - /// - /// - /// - /// - /// - /// - /// - let fold folder (state:'State) (vector:vector) = VG.fold folder state vector - /// Applies a function to each element of the vector and their corresponding index, threading an accumulator argument through the computation. - /// - /// - /// - /// - /// - /// - /// - /// - /// - let foldi folder (state:'State) (vector:vector) = VG.foldi folder state vector - /// Creates a vector of length count and fills it with zeros - /// - /// - /// - /// - /// - /// - /// - let zeroCreate count = create count 0.0 - /// Creates a vector of length count and fills it with ones - /// - /// - /// - /// - /// - /// - /// - let oneCreate count = create count 1.0 - [] - let zero count = create count 0.0 - [] - let ones count = create count 1.0 - /// Sum of all elements of the vector - /// - /// - /// - /// - /// - /// - /// - let sum vector = VecDS.sumVecDS vector - /// Product of all elements of the vector - /// - /// - /// - /// - /// - /// - /// - let prod vector = fold (fun x y -> x * y) 1.0 vector - /// Euklidian norm of the vector - /// - /// - /// - /// - /// - /// - /// - let norm (vector:vector) = sqrt (fold (fun x y -> x + y * y) 0.0 vector) (* fixed *) - /// Builds a new vector whose elements are the results of exponentiating each of the elements of the vector with n. - /// - /// - /// - /// - /// - /// - /// - /// - let toThePower n vector = map (fun x -> x ** n) vector - [] - let cptPow vector y = map (fun x -> x ** y) vector - /// Applies the given function to each of the indexes of the vector. No new vector is created. - /// - /// - /// - /// - /// - /// - /// - /// - let inplaceAssign f (vector:vector) = VG.inplaceAssign f vector - /// Applies the given function to each of the elements of the vector. No new vector is created. - /// - /// - /// - /// - /// - /// - /// - /// - let inplaceMap f (vector:vector) = VG.inplaceMap f vector - /// Applies the given function to each of the elements of the vector and their corresponding index. No new vector is created. - /// - /// - /// - /// - /// - /// - /// - /// - let inplaceMapi f (vector:vector) = VG.inplaceMapi f vector - /// Add values of vector2 to values of vector1. Vector2 stays unchanged. - /// - /// - /// - /// - /// - /// - /// - /// - let inplaceAdd vector1 vector2 = VecDS.inplaceAddVecDS vector1 vector2 - /// Substract values of vector2 from values of vector1. Vector2 stays unchanged. - /// - /// - /// - /// - /// - /// - /// - /// - let inplaceSub vector1 vector2 = VecDS.inplaceSubVecDS vector1 vector2 - /// Multiply values of vector1 with values of vector2. Vector2 stays unchanged. - /// - /// - /// - /// - /// - /// - /// - /// - let inplaceCptMul vector1 vector2 = VecDS.inplaceCptMulVecDS vector1 vector2 - /// Multiply values of vector with scalar. - /// - /// - /// - /// - /// - /// - /// - /// - let inplaceScale scalar vector = VecDS.inplaceScaleVecDS scalar vector - ///Applies the given function to each of the indexes of the vector. - /// Builds vector of Length 1 from value x - /// - /// - /// - /// - /// - /// - /// - let singleton x = ofScalar x - [] - let inplace_assign f (v:vector) = VG.inplaceAssign f v - ///Applies the given function to each of the elements of the vector. - [] - let inplace_map f (v:vector) = VG.inplaceMap f v - ///Applies the given function to each of the elements of the vector and their corresponding index. - [] - let inplace_mapi f (v:vector) = VG.inplaceMapi f v - ///Add values of vector v2 to values of vector v1. Vector v2 stays unchanged - [] - let inplace_add v1 v2 = VecDS.inplaceAddVecDS v1 v2 - ///Substract values of vector v2 from values of vector v1. Vector v2 stays unchanged - [] - let inplace_sub v1 v2 = VecDS.inplaceSubVecDS v1 v2 - ///Multiply values of vector v1 with values of vector v2. Vector v2 stays unchanged. - [] - let inplace_cptMul v1 v2 = VecDS.inplaceCptMulVecDS v1 v2 - ///Multiply values of vector v1 with scalar. - [] - let inplace_scale x v = VecDS.inplaceScaleVecDS x v - ///Builds vector from array - [] - let of_array arr = ofArray arr - ///Builds array from vector - [] - let to_array v = toArray v - ///Builds vector from list - [] - let of_list xs = ofList xs - ///Builds vector from sequence - [] - let of_seq xs = ofSeq xs - ///Builds one dimensional vector from scalar - [] - let of_scalar x = ofScalar x - - - - //---------------------------------------------------------------------------- - // Stats - //---------------------------------------------------------------------------- - - /// Returns the raw data array without copy - /// - /// - /// - /// - /// - /// - /// - let raw (vector:Vector<'T>) = vector.Values - - // - let interval (items:Vector<'T>) = - let rec loop index (minimum) (maximum) = - if index < items.Length then - let current = items.[index] - loop (index+1) (min current minimum) (max current maximum) - else - Interval.CreateClosed<_> (minimum,maximum) - //Init by fist value - if items.Length > 1 then - loop 1 items.[0] items.[0] - else - Interval.Empty - - /// Computes the population mean (Normalized by N) - /// - /// - /// - /// - /// - /// - /// - let inline mean (items:Vector<'T>) = - let ops = items.ElementOps - let zero = ops.Zero - let one = ops.One - let rec loop i c acc = - if i < items.Length then - loop (i+1) (ops.Add(c,one)) (ops.Add(acc,items.[i])) - else - acc / c - loop 0 zero zero - - - /// Computes the sample median - /// - /// - /// - /// - /// - /// - /// - let inline median (items:Vector<'T>) = - items.Values |> Array.median - - /// Median absolute deviation (MAD) - /// - /// - /// - /// - /// - /// - /// - let medianAbsoluteDev (items : vector) = - items.Values |> Array.medianAbsoluteDev - - - /// Returns SummaryStats of vector with N, mean, sum-of-squares, minimum and maximum - /// - /// - /// - /// - /// - /// - /// - let inline stats (items:Vector<'T>) = - let zero = LanguagePrimitives.GenericZero< 'T > - let one = LanguagePrimitives.GenericOne< 'T > - - let rec loop index n (minimum) (maximum) m1 m2 = - if index < items.Length then - let current = items.[index] - let delta = current - m1 - let deltaN = (delta / n) - //let delta_n2 = deltaN * deltaN - let m1' = m1 + deltaN - let m2' = m2 + delta * deltaN * (n-one) - loop (index+1) (n + one) (min current minimum) (max current maximum) m1' m2' - else - SummaryStats.createSummaryStats (n-one) m1 m2 minimum maximum - //Init by fist value - if items.Length > 1 then - loop 0 one items.[0] items.[0] zero zero - else - let uNan = zero / zero - SummaryStats.createSummaryStats zero uNan uNan uNan uNan - - - /// Returns an estimator of the population covariance of two random variables v1 and v2 - /// - /// - /// - /// - /// - /// - /// - /// - let covPopulation (v1:vector) (v2:vector) = - Seq.covPopulation v1 v2 - - /// Returns the sample covariance of two random variables v1 and v2. (Bessel's correction by N-1) - /// - /// - /// - /// - /// - /// - /// - /// - let cov (v1:vector) (v2:vector) = - Seq.cov v1 v2 - - /// calculates the sample means with a given number of replicates present in the sequence - /// - /// - /// - /// - /// - /// - /// - /// - let getMeanOfReplicates rep (data:vector) = - Seq.getMeanOfReplicates rep data - |> ofSeq - - /// calculates the sample standard deviations with a given number of replicates present in the sequence - /// - /// - /// - /// - /// - /// - /// - /// - let getStDevOfReplicates rep (data:vector) = - Seq.getStDevOfReplicates rep data - |> ofSeq - - /// calculates the coefficient of variation based on the sample standard deviations with a given number of replicates present in the sequence - /// - /// - /// - /// - /// - /// - /// - /// - let getCvOfReplicates rep (data:vector) = - Seq.getCvOfReplicates rep data - |> ofSeq - - /// Splits a vector according to given indices. Returns (vector including values according to indices, rest) - /// - /// - /// - /// - /// - /// - /// - /// - let splitVector (indices:int[]) (v:Vector<_>) = - let len = v.Length - //let nv = Vector.Generic.zero (len-indices.Length) - //let nvi = Vector.Generic.zero indices.Length - let nv = VG.zeroCreate (len-indices.Length) - let nvi = VG.zeroCreate indices.Length - indices |> Array.sortInPlace - let rec loop ni nii i = - match i with - | i when i < 0 -> nvi,nv - | i when nii >= 0 && i = indices.[nii] -> - nvi.[nii] <- v.[i] - loop (ni) (nii-1) (i-1) - | _ -> - nv.[ni] <- v.[i] - loop (ni-1) (nii) (i-1) - - loop (len-1-indices.Length) (indices.Length-1) (len-1) - - - /// Module to compute common statistical measure on - module SummaryStats = - - /// Returns SummaryStats of vector with N, mean, sum-of-squares, minimum and maximum - /// - /// - /// - /// - /// - /// - /// - let ofVector (a:Vector<'a>) = stats a - - - - - - - - - -[] -module VectorExtension = - - type Vector<'T> with - member x.ToArray() = Vector.Generic.toArray x - member x.Norm = Vector.Generic.norm x - member x.Copy () = Vector.Generic.copy x - - /// - /// Creates an vector with values between a given interval - /// - /// start value (is included) - /// end value (by default is included) - /// sets the number of elements in the vector. If not set, stepsize = 1. - /// If false, the vector does not contain the stop value - static member linspace(start:float,stop:float,num:int,?IncludeEndpoint:bool) : vector = - - let includeEndpoint = defaultArg IncludeEndpoint true - - Seq.linspace(start,stop,num,includeEndpoint) |> Vector.ofSeq - - /// - /// Creates a geometric vector of floats with values between a given interval. - /// - /// start value (is included) - /// end value (by default is included) - /// sets the number of elements in the vector. Defaults to 50. - /// If false, the vector does not contain the stop value. Defaults to true. - static member geomspace(start:float,stop:float,num:int,?IncludeEndpoint:bool) : vector = - let includeEndpoint = defaultArg IncludeEndpoint true - - Seq.geomspace (start, stop ,num, includeEndpoint) - |> Vector.ofSeq - \ No newline at end of file From 4fb4c36bca644136fe9e44f3e5f6771c6eab5e8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20M=C3=BChlhaus?= Date: Wed, 9 Apr 2025 13:40:02 +0200 Subject: [PATCH 049/121] Remove Surprisal analysis --- src/FSharp.Stats/ML/SurprisalAnalysis.fs | 131 ----------------------- 1 file changed, 131 deletions(-) delete mode 100644 src/FSharp.Stats/ML/SurprisalAnalysis.fs diff --git a/src/FSharp.Stats/ML/SurprisalAnalysis.fs b/src/FSharp.Stats/ML/SurprisalAnalysis.fs deleted file mode 100644 index f125d1a4e..000000000 --- a/src/FSharp.Stats/ML/SurprisalAnalysis.fs +++ /dev/null @@ -1,131 +0,0 @@ -namespace FSharp.Stats.ML - -module SurprisalAnalysis = - open FSharp.Stats - open FSharp.Stats.Algebra.LinearAlgebra - open ProviderService - - ///Summary type for the results of applying Surprisal Analysis to a dataset - type SAResult = - { - ///left singular vectors resulting from the thin SVD of the input matrix - LeftSingularVecors : Matrix - ///right singular vectors resulting from the thin SVD of the input matrix - RightSingularVectors : Matrix - ///diagonal matrix containing the singular values resulting from the thin SVD of the input matrix - SingularValuesDiag: Matrix - ///Vector containing the singular values resulting from the thin SVD of the input matrix in descending order - SingularValues: Vector - /// - MolecularPhenotypes: Matrix - /// - Potentials: Matrix - //Error estimation not implemented yet - //ErrorMatrix: Matrix - } - - let private createSAResult lsv rsv svdiag sv mp pot = {LeftSingularVecors=lsv; RightSingularVectors=rsv; SingularValuesDiag=svdiag; SingularValues=sv; MolecularPhenotypes=mp; Potentials=pot} - - ///performs Surprisal Analysis on the input matrix A. For meaningfull results, A should be - ///of the following form: - ///The rows contain measurements for a single unique entity, - /// corresponding to timepoints represented by the columns - /// - /// - /// - /// - /// - /// - /// - let compute (A:Matrix) : SAResult= - //perform SVD - let sv,lsv,rsv = thinSVD A - //Singular values in diagonal matrix - let svMatrix = Matrix.diag sv - //get time dependant potentials - let lagranges = svMatrix * rsv - createSAResult lsv rsv svMatrix sv lsv lagranges - - //let errorEstimation (A:Matrix) = - // () - - let getEnergyLandscapeData (saRes: SAResult) = - - let g1 = Matrix.getCol saRes.MolecularPhenotypes 1 - let g2 = Matrix.getCol saRes.MolecularPhenotypes 2 - let lambda1 = Matrix.getRow saRes.Potentials 1 - let lambda2 = Matrix.getRow saRes.Potentials 2 - - let XL1L2 = - Array2D.init lambda1.Length lambda1.Length (fun lt1 lt2 -> - Array.init (saRes.MolecularPhenotypes.NumRows) (fun i -> - - (lambda1.[lt1] * g1.[i]) - (lambda2.[lt2] * g2.[i])) - |> Array.sum ) - |> JaggedArray.ofArray2D - - XL1L2 - //Chart.Surface(XL1L2,lab,lab,Opacity=0.85,Contours=Contours.initXyz(Show=true,Color="#8a8a8a"),Colorscale=Colorscale.Custom [(0.,"#0B12B0");((zero/2.),"#5F7BEF");(zero,"#BEBDBD");((zero+1.)/2.,"#E6925D");(1.,"#B4101F")]) - - let getDiagonalEnergyData (saRes:SAResult)= - [|0..saRes.Potentials.NumCols - 1|] - |> Array.map (fun t -> - let l1 = saRes.Potentials.Row 1 - let l2 = saRes.Potentials.Row 2 - let g1 = saRes.MolecularPhenotypes.Column 1 - let g2 = saRes.MolecularPhenotypes.Column 2 - g1 - |> Seq.mapi (fun i x -> - - l1.[t] * g1.[i] - l2.[t] * g2.[i] - ) - |> Seq.sum - ) - - //|> Seq.mapi (fun i x -> labels |> Seq.item i ,labels|> Seq.item i,x) - //|> fun data -> Chart.Scatter3d(data,mode=StyleParam.Lines_Markers_Text,Color = "#474747",Dash=DrawingStyle.DashDot,Width = 5.,Labels = labels)//,Color="#121111") - - //let hikingpath labels lambda (saRes:ML.SurprisalAnalysis.SAResult) = - // [|0..saRes.Potentials.NumCols - 1|] - // |> Array.map (fun t -> - // let l1 = saRes.Potentials.Row lambda - // let g1 = saRes.MolecularPhenotypes.Column lambda - // g1 - // |> Seq.mapi (fun i x -> - // - l1.[t] * g1.[i] - // ) - // |> Seq.sum - // ) - // |> Seq.mapi (fun i x -> - // if lambda = 1 then - // 0,i,x - // else i,0,x) - // |> fun data -> Chart.Scatter3d(data,mode=StyleParam.Lines_Markers_Text,Dash=DrawingStyle.DashDot,Width = 5.,Labels = (labels|> Seq.map (fun l -> sprintf "l%i_%s" lambda l ))) - - - -//let com title labels saRes = -// let xAxis() = LinearAxis.init(Title="lambda 2 at timepoint",Mirror=Mirror.All,Ticks=TickOptions.Inside,Showgrid=true,Showline=true) -// let yAxis() = LinearAxis.init(Title="lambda 1 at timepoint",Mirror=Mirror.All,Ticks=TickOptions.Inside,Showgrid=true,Showline=true) -// let ZAxis() = LinearAxis.init(Title="Free energy / RT",Mirror=Mirror.All,Ticks=TickOptions.Inside,Showgrid=true,Showline=true)//,Range=Range.MinMax(-1000.,1000.)) -// let surfacePlot = -// getSurfacePlotData saRes -// |> fun data -> -// let max = (data) |> Array.concat |> Array.max -// let min = (data) |> Array.concat |> Array.min -// let zero = - min / (max - min) -// Chart.Surface(data,labels,labels,Opacity=0.85,Contours=Contours.initXyz(Show=true,Color="#8a8a8a"),Colorscale=Colorscale.Custom [(0.,"#0B12B0");((zero/2.),"#5F7BEF");(zero,"#BEBDBD");((zero+1.)/2.,"#E6925D");(1.,"#B4101F")]) -// let diagonal = -// getDiagonalData saRes -// |> Seq.mapi (fun i x -> labels |> Seq.item i ,labels|> Seq.item i,x) -// |> fun data -> Chart.Scatter3d(data,mode=StyleParam.Lines_Markers_Text,Color = "#474747",Dash=DrawingStyle.DashDot,Width = 5.,Labels = labels)//,Color="#121111") - -// [ -// surfacePlot -// diagonal -// ] -// |> Chart.Combine -// |> Chart.withSize(1000.,1000.) -// |> Chart.withX_Axis(xAxis()) -// |> Chart.withY_Axis(yAxis()) -// |> Chart.withZ_Axis(ZAxis()) -// |> Chart.withTitle title -// |> Chart.Show \ No newline at end of file From 8ab9da990dd623cfac2a515fa78c3b6b14dcc495 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20M=C3=BChlhaus?= Date: Wed, 9 Apr 2025 13:40:37 +0200 Subject: [PATCH 050/121] Remove PCA --- .../PrincipalComponentAnalysis.fs | 112 ------------------ 1 file changed, 112 deletions(-) delete mode 100644 src/FSharp.Stats/ML/Unsupervised/PrincipalComponentAnalysis.fs diff --git a/src/FSharp.Stats/ML/Unsupervised/PrincipalComponentAnalysis.fs b/src/FSharp.Stats/ML/Unsupervised/PrincipalComponentAnalysis.fs deleted file mode 100644 index 79651c207..000000000 --- a/src/FSharp.Stats/ML/Unsupervised/PrincipalComponentAnalysis.fs +++ /dev/null @@ -1,112 +0,0 @@ -namespace FSharp.Stats.ML.Unsupervised - -open FSharp.Stats - - -/// Principle component analysis -module PCA = - //The Implementation was compared to the R function prcomp(). The implementation is based on remarks found in https://stats.stackexchange.com/a/134283 - //Signs of loadings and principal components (scores) can differ from the R implementation due to different svd implementations being used internally. - //Colab workbook for direct comparison to prcomps output is accessible at: https://colab.research.google.com/drive/1DJ4ky5F5kBM87JprmAbx_gTHqSdz3vqU?usp=sharing - - type PCA = { - VarianceOfComponent: vector - ///Variance explained by principal components - VarExplainedByComponentIndividual : vector - ///Cumulative Variance explained by principal components - VarExplainedByComponentCumulative : vector - ///Matrix with columns representing individual principal components ("raw" principal components, projections on principal directions) and rows representing samples. - ///Also reffered to as "scores". Corresponds to the attribute "x" of the result object of Rs prcomp() function. - PrincipalComponents : Matrix - ///Matrix with columns representing component loadings and rows individual features. - ///Corresponds to the attribute "rotation" of the result object of Rs prcomp() function. - Loadings : Matrix - } - - - /// Normalizes each feature by substracting the corresponing mean followed by a division by its standard deviation.
The centered features of the matrix are centered around 0 and possess a standard deviation of 1.
Expects a data matrix with rows representing observations and columns representing features.
- /// - /// - /// - /// - /// - /// - /// - let center m = - if m |> Matrix.exists (fun x -> Ops.isNan x || Ops.isInf x) then - failwith "Computation not possible. Matrix contains invalid entries. Check for the existence of values equal to nan, infinity or -infinity." - else - let columnMeans = - m - |> Matrix.mapiCols (fun i x -> Seq.mean x) - |> vector - - let columnStabw = - m - |> Matrix.mapiCols (fun i x -> Seq.stDevPopulation x) - |> vector - - let substractionMatrix = - let colV = Vector.init m.NumRows (fun i -> 1.) - colV*columnMeans.Transpose - - let stabwMatrix = - let colV = Vector.init m.NumRows (fun i -> 1.) - colV*columnStabw.Transpose - - let centeredM = - m - substractionMatrix - |> Matrix.mapi (fun i j x -> x / stabwMatrix.[i,j] ) - centeredM - - /// Computes the PCA of a column centered data matrix m.
Expects a column centered data matrix m, with rows representing observations (a.k.a. samples) and columns representing features.
- /// - /// - /// - /// - /// - /// - /// - let compute m = - if m |> Matrix.exists (fun x -> Ops.isNan x || Ops.isInf x) then - failwith "Computation not possible. Matrix contains invalid entries. Check for the existence of values equal to nan, infinity or -infinity." - else - let s,u,v = FSharp.Stats.Algebra.LinearAlgebra.SVD (m) - let n = m.NumRows |> float - let varOfComp = - let e = Vector.map (fun x -> x**2.) s - e - |> Vector.map (fun x -> x / (n-1.)) - |> Vector.map sqrt - let varExplained = - let e = Vector.map (fun x -> x**2.) s - let sum = Seq.sum e - Vector.map (fun l -> abs l / sum) e - let varExplainedCum = - varExplained - |> Vector.foldi (fun i (sum,(v:vector)) x -> - let c = x+sum - v.[i] <- c - c,v - ) (0.,Vector.zeroCreate varExplained.Length) - |> snd - let pc = u * (Matrix.diag (Vector.init u.NumCols (fun i -> if i <= s.Length-1 then s.[i] else 0.))); - let loadings = Matrix.getCols v.Transpose 0 varExplained.Length - //Update: - // There seems to be a lot of ambuiguity when it comes to the use of the term loading. Here we use the term loading to - // refer to the eigenvectors, also termed "unit scaled loading". see: https://stats.stackexchange.com/questions/143905/loadings-vs-eigenvectors-in-pca-when-to-use-one-or-another - // proper loadings when https://stats.stackexchange.com/a/141531 is right, however the described scaling does - // not result in vectors of norm 1 (the columns of principal axes do) and differ from rs prcomp() "rotation" propertie which is - // described here: https://stats.stackexchange.com/a/510465 and here https://www.rdocumentation.org/packages/stats/versions/3.6.2/topics/prcomp as loadings - //let principalAxes = Matrix.getCols v.Transpose 0 varExplained.Length - //let loadings = - // principalAxes*(Matrix.diag (Vector.init principalAxes.NumCols (fun i -> if i <= s.Length-1 then s.[i] else 0.))) - // |> Matrix.map (fun x -> x / sqrt(n-1.)) - // Note: Rs biplot function with param scale=0 applies this scaling to loadings: //principalAxes*(Matrix.diag (Vector.init principalAxes.NumCols (fun i -> if i <= s.Length-1 then s.[i] else 0.))) - { - VarianceOfComponent=varOfComp - VarExplainedByComponentIndividual = varExplained - VarExplainedByComponentCumulative = varExplainedCum - PrincipalComponents = pc - Loadings = loadings - } From c0ee20792401a5688b0da09f63d45679f41ab9e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20M=C3=BChlhaus?= Date: Wed, 9 Apr 2025 13:42:05 +0200 Subject: [PATCH 051/121] Add new Vector and Matrix types using Numerics.INumber<'T> --- src/FSharp.Stats/AlgTypes/GenericMath.fs | 68 ++ src/FSharp.Stats/AlgTypes/Matrix.fs | 792 +++++++++++++++++++++++ src/FSharp.Stats/AlgTypes/MatrixExt.fs | 108 ++++ src/FSharp.Stats/AlgTypes/SIMDUtils.fs | 404 ++++++++++++ src/FSharp.Stats/AlgTypes/Vector.fs | 253 ++++++++ src/FSharp.Stats/AlgTypes/VectorExt.fs | 182 ++++++ src/FSharp.Stats/AlgTypes/VectorOps.fs | 38 ++ 7 files changed, 1845 insertions(+) create mode 100644 src/FSharp.Stats/AlgTypes/GenericMath.fs create mode 100644 src/FSharp.Stats/AlgTypes/Matrix.fs create mode 100644 src/FSharp.Stats/AlgTypes/MatrixExt.fs create mode 100644 src/FSharp.Stats/AlgTypes/SIMDUtils.fs create mode 100644 src/FSharp.Stats/AlgTypes/Vector.fs create mode 100644 src/FSharp.Stats/AlgTypes/VectorExt.fs create mode 100644 src/FSharp.Stats/AlgTypes/VectorOps.fs diff --git a/src/FSharp.Stats/AlgTypes/GenericMath.fs b/src/FSharp.Stats/AlgTypes/GenericMath.fs new file mode 100644 index 000000000..8bb1e0543 --- /dev/null +++ b/src/FSharp.Stats/AlgTypes/GenericMath.fs @@ -0,0 +1,68 @@ +namespace FSharp.Stats + +open System +open System.Runtime.InteropServices + +module GenericMath = + + /// Generic Zero + let inline zero<'T when 'T :> Numerics.INumber<'T>> = + 'T.Zero + + /// Generic One + let inline one<'T when 'T :> Numerics.INumber<'T>> = + 'T.One + + /// Generic float conversion + let inline T<'T when 'T :> Numerics.INumber<'T>> (x: float) : 'T = + 'T.CreateChecked x + + /// Generic square root + let inline sqrt<'T when 'T :> Numerics.IRootFunctions<'T>> (x: 'T) : 'T = + 'T.Sqrt(x) + + /// Generic exponentiation (e^x) + let inline exp<'T when 'T :> Numerics.IExponentialFunctions<'T>> (x: 'T) : 'T = + 'T.Exp(x) + + /// Generic power function (x^y) + let inline pow<'T when 'T :> Numerics.IPowerFunctions<'T>> (x: 'T) (y: 'T) : 'T = + 'T.Pow(x, y) + + /// Generic natural logarithm + let inline log<'T when 'T :> Numerics.ILogarithmicFunctions<'T>> (x: 'T) : 'T = + 'T.Log(x) + + /// Generic absolute value + let inline abs<'T when 'T :> Numerics.INumber<'T>> (x: 'T) : 'T = + 'T.Abs(x) + + /// Generic sine + let inline sin<'T when 'T :> Numerics.ITrigonometricFunctions<'T>> (x: 'T) : 'T = + 'T.Sin(x) + + /// Generic cosine + let inline cos<'T when 'T :> Numerics.ITrigonometricFunctions<'T>> (x: 'T) : 'T = + 'T.Cos(x) + + // /// Generic pi constant + // let inline pi<'T when 'T :> Numerics.IFloatingPointConstants<'T> and 'T :> Numerics.INumber<'T>> () : 'T = + // pi<'T>() + + /// Generic e constant (Euler's number) + let inline e<'T when 'T :> Numerics.IFloatingPointConstants<'T>> () : 'T = + 'T.E + + // /// Generic tau constant (2 * pi) + // let inline tau<'T when 'T :> Numerics.IFloatingPointConstants<'T> and 'T :> Numerics.INumber<'T>> () : 'T = + // T<'T> 2.0 * pi<'T>() + + + + + // let inline min x y = if x < y then x else y + // let inline max x y = if x > y then x else y + + // let inline clamp minVal maxVal x = + // if x < minVal then minVal elif x > maxVal then maxVal else x + diff --git a/src/FSharp.Stats/AlgTypes/Matrix.fs b/src/FSharp.Stats/AlgTypes/Matrix.fs new file mode 100644 index 000000000..a960e5b11 --- /dev/null +++ b/src/FSharp.Stats/AlgTypes/Matrix.fs @@ -0,0 +1,792 @@ +namespace FSharp.Stats + +open System +open System.Runtime.InteropServices + +// let blockSize = +// match sizeof<'T> with +// | 4 -> 32 // float32 or int +// | 8 -> 16 // float64 +// | _ -> 16 // fallback + + +/// Matrix type to hold values of a matrix in a 1D Arrays (Flattened Representation) +type Matrix<'T when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T :> ValueType> + (rows: int, cols: int, data: Vector<'T>) = + + /// Exposes the raw underlying data array (row-major flattened). + member _.Data = data + + /// Number of rows in the matrix. + member _.NumRows = rows + + /// Number of columns in the matrix. + member _.NumCols = cols + + /// Matrix indexer for getting and setting elements at (i, j). + member this.Item + with get (i, j) = + if i < 0 || i >= rows || j < 0 || j >= cols then + invalidArg "index" $"Index out of range: ({i}, {j})" + data.[i * cols + j] + and set (i, j) value = + if i < 0 || i >= rows || j < 0 || j >= cols then + invalidArg "index" $"Index out of range: ({i}, {j})" + data.[i * cols + j] <- value + + + /// + /// Returns a new Matrix<'T> that is the slice of rows [rowStart..rowEnd] + /// and columns [colStart..colEnd]. If any of these bounds is omitted, + /// it defaults to the full range in that dimension. + /// + /// Optional start row (inclusive) + /// Optional end row (inclusive) + /// Optional start column (inclusive) + /// Optional end column (inclusive) + /// A new submatrix copy. + member this.GetSlice + (rowStart: int option, rowEnd: int option, + colStart: int option, colEnd: int option) : Matrix<'T> = + + // 1) Determine actual start/end indices + let r1 = defaultArg rowStart 0 + let r2 = defaultArg rowEnd (rows - 1) + let c1 = defaultArg colStart 0 + let c2 = defaultArg colEnd (cols - 1) + + // 2) Validate them + if r1 < 0 || r2 < r1 || r2 >= rows then + invalidArg "row range" $"Invalid row slice range: {r1}..{r2}" + if c1 < 0 || c2 < c1 || c2 >= cols then + invalidArg "col range" $"Invalid column slice range: {c1}..{c2}" + + let subRows = r2 - r1 + 1 + let subCols = c2 - c1 + 1 + + // 3) Allocate new array for the submatrix + let subData = Array.zeroCreate<'T> (subRows * subCols) + + // 4) Copy row by row + for rr in 0 .. subRows - 1 do + let srcIndex = (r1 + rr) * cols + c1 + let dstIndex = rr * subCols + // Copy from data[srcIndex..(srcIndex+subCols-1)] + // to subData[dstIndex..(dstIndex+subCols-1)] + Array.blit data srcIndex subData dstIndex subCols + + // 5) Return a new Matrix with the submatrix data + Matrix<'T>(subRows, subCols, subData) + + /// + /// Convenience "slice indexer" for F# syntax: mat.[r1..r2, c1..c2]. + /// Internally calls GetSlice(...). + /// + member this.GetSlice + (rowRange: Range, colRange: Range) : Matrix<'T> = + + // Convert the F# Range type into int option pairs + let rowStart, rowEnd = + (if rowRange.Start = System.Index.Start then None else Some rowRange.Start.Value), + (if rowRange.End = System.Index.End then None else Some rowRange.End.Value) + + let colStart, colEnd = + (if colRange.Start = System.Index.Start then None else Some colRange.Start.Value), + (if colRange.End = System.Index.End then None else Some colRange.End.Value) + + // Use the primary GetSlice overload + this.GetSlice(rowStart, rowEnd, colStart, colEnd) + + + static member inline map2Unchecked<'T when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T :> ValueType> + (fVec: Numerics.Vector<'T> -> Numerics.Vector<'T> -> Numerics.Vector<'T>) + (fScalar: 'T -> 'T -> 'T) + (a: Matrix<'T>) + (b: Matrix<'T>) + : Matrix<'T> = + + // if a.Rows <> b.Rows || a.Cols <> b.Cols then + // invalidArg "b" "Matrix dimensions must match" + + let len = a.Data.Length + let result = Array.zeroCreate<'T> len + + let simdSize = Numerics.Vector<'T>.Count + let simdCount = len / simdSize + let tailStart = simdCount * simdSize + + // Cast arrays to Vector<'T> spans + let aVec = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(a.Data.AsSpan()) + let bVec = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(b.Data.AsSpan()) + let rVec = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(result.AsSpan()) + + for i = 0 to simdCount - 1 do + rVec.[i] <- fVec aVec.[i] bVec.[i] + + for i = tailStart to len - 1 do + result.[i] <- fScalar a.Data.[i] b.Data.[i] + + Matrix(a.NumRows, a.NumCols, result) + + + static member inline mapScalar<'T when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T :> ValueType> + (fv: Numerics.Vector<'T> -> Numerics.Vector<'T> -> Numerics.Vector<'T>) + (f: 'T -> 'T -> 'T) + (matrix: Matrix<'T>) + (scalar: 'T) + : Matrix<'T> = + + let length = matrix.Data.Length + let result = Array.zeroCreate<'T> length + + let slotSize = Numerics.Vector<'T>.Count + let slotCount = length / slotSize + let ceiling = slotCount * slotSize + + let scalarVec = Numerics.Vector<'T>(scalar) + + let mSpan = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(matrix.Data.AsSpan()) + let rSpan = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(result.AsSpan()) + + // SIMD chunk-wise operation + for i = 0 to slotCount - 1 do + rSpan.[i] <- fv mSpan.[i] scalarVec + + // Scalar fallback for remainder + for i = ceiling to length - 1 do + result.[i] <- f matrix.Data.[i] scalar + + Matrix(matrix.NumRows, matrix.NumCols, result) + + + + /// Creates a new matrix by initializing each element with a function `f(row, col)`. + static member inline transpose<'T when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T :> ValueType> + (rows : int) + (cols : int) + (data: 'T[]) + (blockSize: int) = + + //let blockSize = defaultArg blockSize 16 + + let src = data + let dst = Array.zeroCreate<'T> (rows * cols) + + let vectorSize = Numerics.Vector<'T>.Count + + // Process the matrix in blocks + for i0 in 0 .. blockSize .. rows - 1 do + for j0 in 0 .. blockSize .. cols - 1 do + + let iMax = min (i0 + blockSize) rows + let jMax = min (j0 + blockSize) cols + + for i in i0 .. iMax - 1 do + let srcOffset = i * cols + for j in j0 .. jMax - 1 do + let v = src.[srcOffset + j] + dst.[j * rows + i] <- v + + dst + + member this.Transpose() = + let blocksize = 16 + Matrix(this.NumCols, this.NumRows, Matrix.transpose this.NumRows this.NumCols this.Data blocksize) + + static member init<'T when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T :> ValueType> + (rows: int) + (cols: int) + (f: int -> int -> 'T) = + let data = Array.init (rows * cols) (fun idx -> f (idx / cols) (idx % cols)) + Matrix(rows, cols, data) + + static member create<'T when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T :> ValueType> + (rows: int) + (cols: int) + (data: 'T[]) : Matrix<'T> = + + Matrix(rows, cols, data) + + + /// Constructs a matrix from a 2D array. + static member ofArray2D<'T when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T :> ValueType> + (arr2D: 'T[,]) = + let rows = arr2D.GetLength(0) + let cols = arr2D.GetLength(1) + let length = rows * cols + + let flat = Array.zeroCreate<'T> length + let sourceSpan = MemoryMarshal.CreateSpan(&arr2D.[0, 0], length) + sourceSpan.CopyTo(flat.AsSpan()) + + Matrix(rows, cols, flat) + + /// Converts this matrix into a 2D array. + member this.toArray2D() = + let arr2D = Array2D.zeroCreate<'T> this.NumRows this.NumCols + let targetSpan = MemoryMarshal.CreateSpan(&arr2D.[0, 0], this.NumRows * this.NumCols) + this.Data.AsSpan().CopyTo(targetSpan) + arr2D + + + /// Constructs a matrix from a jagged array (`'T[][]`), assuming a rectangular structure. + static member ofJaggedArray<'T when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T :> ValueType> + (jagged: 'T[][]) = + let rows = jagged.Length + let cols = if rows > 0 then jagged.[0].Length else 0 + + // Optional safety check for rectangular shape + for row in jagged do + if row.Length <> cols then + invalidArg "jagged" "All rows in jagged array must have the same length." + + let flat = Array.zeroCreate<'T> (rows * cols) + + for i = 0 to rows - 1 do + let source = jagged.[i].AsSpan() + let target = flat.AsSpan(i * cols, cols) + source.CopyTo(target) + + Matrix(rows, cols, flat) + + /// Converts this matrix into a jagged array (`'T[][]`). + member this.toJaggedArray() = + let result = Array.zeroCreate<'T[]> this.NumRows + let dataSpan = this.Data.AsSpan() + + for i = 0 to this.NumRows - 1 do + let row = Array.zeroCreate<'T> this.NumCols + dataSpan.Slice(i * this.NumCols, this.NumCols).CopyTo(row.AsSpan()) + result.[i] <- row + + result + + + /// Pretty string representation with formatting and truncation, using StringBuilder. + /// Supports optional scientific notation for floating point types. + member this.toFormattedString(?maxRows: int, ?maxCols: int, ?floatFormat: string, ?useScientific: bool) = + let maxRows = defaultArg maxRows 10 + let maxCols = defaultArg maxCols 10 + let useScientific = defaultArg useScientific false + let floatFormat = + match floatFormat with + | Some f -> f + | None -> if useScientific then "0.##E+0" else "0.##" + + if this.NumRows = 0 || this.NumCols = 0 then + "Matrix (empty)" + else + let rowsToShow = min this.NumRows maxRows + let colsToShow = min this.NumCols maxCols + + // Format a single cell + let formatCell (value: 'T) = + match box value with + | :? float as f -> f.ToString(floatFormat) + | :? float32 as f -> f.ToString(floatFormat) + | _ -> string value + + let formattedCells = + Array.init rowsToShow (fun i -> + Array.init colsToShow (fun j -> + formatCell this.[i, j] + ) + ) + + let colWidths = + Array.init colsToShow (fun j -> + Array.init rowsToShow (fun i -> formattedCells.[i].[j].Length) + |> Array.max + ) + + let divider = + colWidths + |> Array.map (fun w -> String.replicate w "─") + |> String.concat "─┼─" + + let sb = Text.StringBuilder() + sb.AppendLine($"Matrix {this.NumRows}x{this.NumCols}:") |> ignore + sb.AppendLine("┌ " + divider + " ┐") |> ignore + + for i = 0 to rowsToShow - 1 do + sb.Append("│ ") |> ignore + for j = 0 to colsToShow - 1 do + let cell = formattedCells.[i].[j].PadLeft(colWidths.[j]) + sb.Append(cell) |> ignore + if j < colsToShow - 1 then sb.Append(" │ ") |> ignore + sb.AppendLine(" │") |> ignore + + if this.NumRows > rowsToShow || this.NumCols > colsToShow then + sb.AppendLine($"│ ... truncated ({this.NumRows}x{this.NumCols}) │") |> ignore + + sb.AppendLine("└ " + divider + " ┘") |> ignore + sb.ToString() + + + /// Default string representation (truncated, human-readable) + override this.ToString() = this.toFormattedString() + + static member inline checkSameShape<'T when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T :> ValueType> + (a: Matrix<'T>) (b: Matrix<'T>) = + if a.NumRows <> b.NumRows || a.NumCols <> b.NumCols then + invalidArg "b" $"Matrix dimensions must match. A is {a.NumRows}x{a.NumCols}, B is {b.NumRows}x{b.NumCols}" + + /// Element-wise addition + static member inline add<'T when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T :> ValueType> + (a: Matrix<'T>) + (b: Matrix<'T>) : Matrix<'T> = + + Matrix.checkSameShape a b + let data = + Acceleration.SIMDUtils.map2Unchecked (+) (+) a.Data b.Data + Matrix(a.NumRows, a.NumCols, data) + + static member inline subtract<'T when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T :> ValueType> + (a: Matrix<'T>) + (b: Matrix<'T>) : Matrix<'T> = + + Matrix.checkSameShape a b + Matrix.map2Unchecked (-) (-) a b + + + + static member inline multiply<'T + when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T :> ValueType> + (a: Matrix<'T>) + (b: Matrix<'T>) : Matrix<'T> = + + Matrix.checkSameShape a b + Matrix.map2Unchecked (*) (*) a b + + + static member inline divide<'T + when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T :> ValueType> + (a: Matrix<'T>) + (b: Matrix<'T>) : Matrix<'T> = + + Matrix.checkSameShape a b + Matrix.map2Unchecked (/) (/) a b + + + static member inline addScalar<'T when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T :> ValueType> + (m: Matrix<'T>) (scalar: 'T) : Matrix<'T> = + + Matrix.mapScalar (+) (+) m scalar + + + + static member inline subtractScalar<'T + when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T :> ValueType> + (m: Matrix<'T>) + (scalar: 'T) : Matrix<'T> = + + Matrix.mapScalar (-) (-) m scalar + + + static member inline multiplyScalar<'T + when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T :> ValueType> + (m: Matrix<'T>) + (scalar: 'T) : Matrix<'T> = + + Matrix.mapScalar (*) (*) m scalar + + + static member inline divideScalar<'T + when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T :> ValueType> + (m: Matrix<'T>) + (scalar: 'T) : Matrix<'T> = + + Matrix.mapScalar (/) (/) m scalar + + + /// Standard matrix-vector product + static member inline muliplyVector<'T + when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T :> ValueType> + (m: Matrix<'T>) + (v: Vector<'T>) : Vector<'T> = + + if m.NumCols <> v.Length then + invalidArg "v" $"Vector length {v.Length} must match matrix column count {m.NumCols}" + + let result: Vector<'T> = Array.zeroCreate m.NumRows + let zero = LanguagePrimitives.GenericZero<'T> + + let simdSize = Numerics.Vector<'T>.Count + let vSpan = v.AsSpan() + let vSimd = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(vSpan) + + let tailStart = (v.Length / simdSize) * simdSize + + for row = 0 to m.NumRows - 1 do + let rowOffset = row * m.NumCols + let rowSpan = m.Data.AsSpan(rowOffset, m.NumCols) + let rowSimd = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(rowSpan) + + let mutable acc = Numerics.Vector<'T>(zero) + + for i = 0 to vSimd.Length - 1 do + acc <- acc + rowSimd.[i] * vSimd.[i] + + let mutable tail = zero + for i = tailStart to m.NumCols - 1 do + tail <- tail + m.Data.[rowOffset + i] * v.[i] + + result.[row] <- Numerics.Vector.Sum(acc) + tail + + result + + static member inline addRowVector<'T + when 'T :> Numerics.INumber<'T> + and 'T : struct + and 'T : (new : unit -> 'T) + and 'T :> ValueType> + (m: Matrix<'T>) + (v: Vector<'T>) : Matrix<'T> = + + if v.Length <> m.NumCols then + invalidArg "v" $"Row vector length {v.Length} must match matrix column count {m.NumCols}" + + let resultData = Array.zeroCreate<'T> (m.NumRows * m.NumCols) + let simdSize = Numerics.Vector<'T>.Count + let simdCount = m.NumCols / simdSize + let scalarStart = simdCount * simdSize + + let vSimd = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(v.AsSpan()) + + for row = 0 to m.NumRows - 1 do + let offset = row * m.NumCols + let srcSpan = m.Data.AsSpan(offset, m.NumCols) + let dstSpan = resultData.AsSpan(offset, m.NumCols) + + let srcSimd = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(srcSpan) + let dstSimd = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(dstSpan) + + // SIMD part + for i = 0 to simdCount - 1 do + dstSimd.[i] <- srcSimd.[i] + vSimd.[i] + + // Tail (scalar) + for i = scalarStart to m.NumCols - 1 do + dstSpan.[i] <- srcSpan.[i] + v.[i] + + Matrix(m.NumRows, m.NumCols, resultData) + + + static member inline addColVector<'T + when 'T :> Numerics.INumber<'T> + and 'T : struct + and 'T : (new : unit -> 'T) + and 'T :> ValueType> + (m: Matrix<'T>) + (v: Vector<'T>) : Matrix<'T> = + + if v.Length <> m.NumRows then + invalidArg "v" $"Column vector length {v.Length} must match matrix row count {m.NumRows}" + + let cols = m.NumCols + let resultData = Array.zeroCreate<'T> (m.NumRows * cols) + let simdSize = Numerics.Vector<'T>.Count + + for row = 0 to m.NumRows - 1 do + let rowOffset = row * cols + let srcRow = m.Data.AsSpan(rowOffset, cols) + let dstRow = resultData.AsSpan(rowOffset, cols) + + let simdRow = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(srcRow) + let simdDst = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(dstRow) + + let broadcast = Numerics.Vector<'T>(v.[row]) + let simdCount = cols / simdSize + let scalarStart = simdCount * simdSize + + // SIMD-add: row + broadcast vector + for i = 0 to simdCount - 1 do + simdDst.[i] <- simdRow.[i] + broadcast + + // Scalar tail + for i = scalarStart to cols - 1 do + dstRow.[i] <- srcRow.[i] + v.[row] + + Matrix(m.NumRows, cols, resultData) + + // Matrix - matrix operations + static member inline ( + ) (a: Matrix<'T>, b: Matrix<'T>) = Matrix.add a b + static member inline ( - ) (a: Matrix<'T>, b: Matrix<'T>) = Matrix.subtract a b + static member inline ( * ) (a: Matrix<'T>, b: Matrix<'T>) = Matrix.multiply a b + static member inline ( / ) (a: Matrix<'T>, b: Matrix<'T>) = Matrix.divide a b + + // Matrix - vector operations + static member inline ( * ) (m: Matrix<'T>, v: Vector<'T>) = Matrix.muliplyVector m v + // static member inline ( + ) (m: Matrix<'T>, colVector: Vector<'T>) = Matrix.addColVector m colVector + // static member inline ( +| ) (m: Matrix<'T>, rowVector: Vector<'T>) = Matrix.addRowVector m rowVector + + // Matrix - scalar operations + static member inline (+) (m: Matrix<'T>, s: 'T) = Matrix.addScalar m s + static member inline (+) (s: 'T, m: Matrix<'T>) = Matrix.addScalar m s + + static member inline (-) (m: Matrix<'T>, s: 'T) = Matrix.subtractScalar m s + static member inline (-) (s: 'T, m: Matrix<'T>) = Matrix.subtractScalar m s + + static member inline (*) (m: Matrix<'T>, s: 'T) = Matrix.multiplyScalar m s + static member inline (*) (s: 'T, m: Matrix<'T>) = Matrix.multiplyScalar m s + + static member inline (/) (m: Matrix<'T>, s: 'T) = Matrix.divideScalar m s + static member inline (/) (s: 'T, m: Matrix<'T>) = Matrix.divideScalar m s + + + + static member inline diagonal<'T + when 'T :> Numerics.INumber<'T> + and 'T : struct + and 'T : (new : unit -> 'T) + and 'T :> ValueType> + (diag: Vector<'T>) : Matrix<'T> = + + let n = diag.Length + let data = Array.zeroCreate<'T> (n * n) + for i = 0 to n - 1 do + data.[i * n + i] <- diag.[i] + Matrix(n, n, data) + + /// + /// Returns the diagonal elements of this matrix as an array of length = min(NumRows, NumCols). + /// + static member inline getDiagonal + (m:Matrix<'T>) : Vector<'T> = + let n = min m.NumRows m.NumCols + let diag = Array.zeroCreate<'T> n + for i = 0 to n - 1 do + // The diagonal element at row i, col i is stored at offset i * cols + i + diag.[i] <- m.Data.[i * m.NumCols + i] + diag + + + static member inline identity<'T + when 'T :> Numerics.INumber<'T> + and 'T : struct + and 'T : (new : unit -> 'T) + and 'T :> ValueType> + (n: int) : Matrix<'T> = + + let data = Array.zeroCreate<'T> (n * n) + for i = 0 to n - 1 do + data.[i * n + i] <- 'T.One + Matrix(n, n, data) + + static member inline zeroCreate<'T + when 'T :> Numerics.INumber<'T> + and 'T : struct + and 'T : (new : unit -> 'T) + and 'T :> ValueType> + (rows: int) + (cols: int) : Matrix<'T> = + + let data = Array.zeroCreate<'T> (rows * cols) + Matrix(rows, cols, data) + + static member inline ones<'T + when 'T :> Numerics.INumber<'T> + and 'T : struct + and 'T : (new : unit -> 'T) + and 'T :> ValueType> + (rows: int) + (cols: int) : Matrix<'T> = + + let size = rows * cols + let data = Array.zeroCreate<'T> size + let simdSize = Numerics.Vector<'T>.Count + let simdCount = size / simdSize + + let vOne = Numerics.Vector<'T>('T.One) + let span = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(data.AsSpan()) + + for i = 0 to simdCount - 1 do + span.[i] <- vOne + + for i = simdCount * simdSize to size - 1 do + data.[i] <- 'T.One + + Matrix(rows, cols, data) + + static member inline getRow<'T + when 'T :> Numerics.INumber<'T> + and 'T : struct + and 'T : (new : unit -> 'T) + and 'T :> ValueType> + (i: int) + (m: Matrix<'T>) : Vector<'T> = + + if i < 0 || i >= m.NumRows then + invalidArg "i" $"Row index out of bounds: {i}" + + let rowSpan = m.Data.AsSpan(i * m.NumCols, m.NumCols) + let result = Array.zeroCreate<'T> m.NumCols + rowSpan.CopyTo(result.AsSpan()) + result + + static member inline getRows (m: Matrix<'T>) : Vector<'T>[] = + Array.init m.NumRows (fun i -> Matrix.getRow i m) + + + static member inline getCol<'T + when 'T :> Numerics.INumber<'T> + and 'T : struct + and 'T : (new : unit -> 'T) + and 'T :> ValueType> + (j: int) + (m: Matrix<'T>) : Vector<'T> = + + if j < 0 || j >= m.NumCols then + invalidArg "j" $"Column index out of bounds: {j}" + + let result = Array.zeroCreate<'T> m.NumRows + let mutable offset = j + for i = 0 to m.NumRows - 1 do + result.[i] <- m.Data.[offset] + offset <- offset + m.NumCols + + result + + static member inline getCols<'T + when 'T :> Numerics.INumber<'T> + and 'T : struct + and 'T : (new : unit -> 'T) + and 'T :> ValueType> + (m: Matrix<'T>) : Vector<'T>[] = + + Array.init m.NumCols (fun j -> + let col = Array.zeroCreate<'T> m.NumRows + let mutable offset = j + for i = 0 to m.NumRows - 1 do + col.[i] <- m.Data.[offset] + offset <- offset + m.NumCols + col + ) + + + /// + /// Sets row of this matrix to the contents of . + /// The length of must match the number of columns in this matrix. + /// + /// The zero-based row index to set. + /// An array of new values for the row, of length equal to . + /// Thrown if is out of range. + /// Thrown if has incorrect length. + member this.SetRow(i: int, rowData: 'T[]) = + if i < 0 || i >= rows then + invalidArg (nameof i) "Row index out of range." + if rowData.Length <> cols then + invalidArg (nameof rowData) $"rowData must have length = {cols}." + + let offset = i * cols + Array.blit rowData 0 data offset cols + + + + + + // static member MatrixMultiply + + // (a: Matrix<'T>, b: Matrix<'T>, ?blockSize: int) : Matrix<'T> + // when 'T : struct + // and 'T : (new : unit -> 'T) + // and 'T :> INumber<'T> + // and 'T :> ValueType = + + // if a.Cols <> b.Rows then + // invalidArg "b" "Matrix dimensions must agree: a.Cols must equal b.Rows." + + // let blockSize = defaultArg blockSize 32 + + // let m = a.Rows + // let n = b.Cols + // let k = a.Cols + + // let result = Array.zeroCreate<'T> (m * n) + // let aData = a.Data + // let bData = b.Data + // let rData = result + + // let vSize = Vector<'T>.Count + + // // Blocked GEMM + // for i0 in 0 .. blockSize .. m - 1 do + // let iMax = min (i0 + blockSize) m + // for j0 in 0 .. blockSize .. n - 1 do + // let jMax = min (j0 + blockSize) n + // for k0 in 0 .. blockSize .. k - 1 do + // let kMax = min (k0 + blockSize) k + + // // Iterate over block + // for i in i0 .. iMax - 1 do + // for j in j0 .. jMax - 1 do + // let mutable sum = 'T.Zero + // let mutable kk = k0 + + // // SIMD accumulation + // while kk <= kMax - vSize do + // let aVec = Vector<'T>(aData, i * k + kk) + // let bVec = Vector<'T>([| for offset in 0 .. vSize - 1 -> bData.[(kk + offset) * n + j] |]) + // sum <- sum + Vector.Dot(aVec, bVec) + // kk <- kk + vSize + + // // Scalar tail + // while kk < kMax do + // sum <- sum + aData.[i * k + kk] * bData.[kk * n + j] + // kk <- kk + 1 + + // rData.[i * n + j] <- rData.[i * n + j] + sum diff --git a/src/FSharp.Stats/AlgTypes/MatrixExt.fs b/src/FSharp.Stats/AlgTypes/MatrixExt.fs new file mode 100644 index 000000000..bf0acce03 --- /dev/null +++ b/src/FSharp.Stats/AlgTypes/MatrixExt.fs @@ -0,0 +1,108 @@ +namespace FSharp.Stats + +open System +open System.Runtime.InteropServices + + +[] +module Matrix = + +// /// Indexed fold over a matrix +// let inline foldi<'T when 'T :> Numerics.INumber<'T>> f (state: 'T) (m: Matrix<'T>) : 'T = +// let mutable acc = state +// for i = 0 to m.NumRows - 1 do +// for j = 0 to m.NumCols - 1 do +// acc <- f i j acc m.[i, j] +// acc + + + /// + /// Creates and returns a new with the same dimensions + /// as this matrix and a copy of the underlying data. + /// + let inline copy (m:Matrix<'T>) : Matrix<'T> = + // Make a copy of the data array + let newData = Array.copy m.Data + Matrix<'T>(m.NumRows, m.NumCols, newData) + + + /// Splits a matrix along row direction according to given indices. Returns (matrix including rows according to indices, rest) + /// + /// + /// + /// + /// + /// + /// + /// + let splitRows (indices:int[]) (m:Matrix<'T>) = + + let nRows,nCols = m.NumRows,m.NumCols + //let nm = Matrix.Generic.zero (nRows-indices.Length) nCols + //let nmi = Matrix.Generic.zero indices.Length nCols + let nm = Matrix.zeroCreate (nRows-indices.Length) nCols + let nmi = Matrix.zeroCreate indices.Length nCols + indices |> Array.sortInPlace + let rec loop nRowI nRowIi rowI = + match rowI with + | i as rowI when rowI < 0 -> nmi,nm + | i as rowI when nRowIi >= 0 && rowI = indices.[nRowIi] -> + for colI=0 to nCols-1 do + nmi.[nRowIi,colI] <- m.[rowI,colI] + loop (nRowI) (nRowIi-1) (rowI-1) + | _ -> //i as rowI when rowI <> indices.[ii] -> + for colI=0 to nCols-1 do + nm.[nRowI,colI] <- m.[rowI,colI] + loop (nRowI-1) (nRowIi) (rowI-1) + + loop (nRows-1-indices.Length) (indices.Length-1) (nRows-1) + + /// Splits a matrix along column direction according to given indices. Returns (matrix including cols according to indices, rest) + /// + /// + /// + /// + /// + /// + /// + /// + let splitCols (indices:int[]) (m:Matrix<_>) = + let nRows,nCols = m.NumRows,m.NumCols + //let nm = Matrix.Generic.zero nRows (nCols-indices.Length) + //let nmi = Matrix.Generic.zero nRows indices.Length + let nm = Matrix.zeroCreate nRows (nCols-indices.Length) + let nmi = Matrix.zeroCreate nRows indices.Length + indices |> Array.sortInPlace + let rec loop nColI nColIi colI = + match colI with + | i as colI when colI < 0 -> nmi,nm + | i as colI when nColIi >= 0 && colI = indices.[nColIi] -> + for rowI=0 to nRows-1 do + nmi.[rowI,nColIi] <- m.[rowI,colI] + loop (nColI) (nColIi-1) (colI-1) + | _ -> //i as rowI when rowI <> indices.[ii] -> + for rowI=0 to nRows-1 do + nm.[rowI,nColI] <- m.[rowI,colI] + loop (nColI-1) (nColIi) (colI-1) + + loop (nCols-1-indices.Length) (indices.Length-1) (nCols-1) + + /// + /// Creates a new matrix by permuting the rows of matrix according + /// to the permutation . That is, row i of the result is row + /// P(i) of . + /// + /// A permutation function that maps row indices. Should be valid + /// An r x c matrix whose rows will be reordered. + /// for all i in [0..r-1]. + /// + /// A new matrix of the same dimensions r x c, with rows permuted by . + /// + let permuteRowsBy (P: Permutation) (M: Matrix<'T>) : Matrix<'T> = + let r, c = M.NumRows, M.NumCols + let newData = Array.zeroCreate<'T> (r * c) + for i = 0 to r - 1 do + let srcRow = P i + // Copy row srcRow from M into row i of the new matrix + Array.blit M.Data (srcRow * c) newData (i * c) c + Matrix<'T>(r, c, newData) \ No newline at end of file diff --git a/src/FSharp.Stats/AlgTypes/SIMDUtils.fs b/src/FSharp.Stats/AlgTypes/SIMDUtils.fs new file mode 100644 index 000000000..54aabfeec --- /dev/null +++ b/src/FSharp.Stats/AlgTypes/SIMDUtils.fs @@ -0,0 +1,404 @@ +namespace FSharp.Stats.Acceleration + +open System +open System.Runtime.InteropServices +open System.Runtime.CompilerServices + + +/// +/// A utility class for performing SIMD (Single Instruction, Multiple Data) operations on arrays. +/// +type SIMDUtils() = + + /// + /// Applies a safe element-wise unary operation on an array using SIMD for performance. + /// + /// The numeric type of the array elements. + /// A function that performs the SIMD operation on a vector. + /// A fallback function for scalar operations. + /// The input array. + /// An array with the operation applied to each element. + static member inline map<'T when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T :> ValueType> + (fv:Numerics.Vector<'T> -> Numerics.Vector<'T>) + (f: 'T -> 'T) + (v: 'T[]) : 'T[] = + + let length = v.Length + let slotSize = Numerics.Vector<'T>.Count + let slotCount = length / slotSize + let ceiling = slotSize * slotCount + + let results = Array.zeroCreate<'T> length + let rsSpan = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(results.AsSpan()) + let vSpan = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(v.AsSpan()) + + for i = 0 to slotCount - 1 do + rsSpan.[i] <- fv vSpan[i] + + for i = ceiling to length - 1 do + results.[i] <- f v.[i] + + results + + /// + /// Applies an element-wise binary operation on two arrays using SIMD for performance. + /// + /// The numeric type of the array elements. + /// A function that performs the SIMD operation on two vectors. + /// A fallback function for scalar operations. + /// The first input array. + /// The second input array. + /// An array with the operation applied to each pair of elements. + static member inline map2Unchecked<'T when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T :> ValueType> + (fv:Numerics.Vector<'T> -> Numerics.Vector<'T> -> Numerics.Vector<'T>) + (f:'T -> 'T -> 'T) + (v1: 'T[]) + (v2: 'T[]) = + + let length = v1.Length + let slotSize= Numerics.Vector<'T>.Count + let slotCount = length / slotSize + let ceiling = slotSize * slotCount + + let results = Array.zeroCreate<'T> length + let rsSpan = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(results.AsSpan()) + let v1Span = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(v1.AsSpan()) + let v2Span = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(v2.AsSpan()) + + for i=0 to slotCount - 1 do + rsSpan.[i] <- fv v1Span[i] v2Span[i] + + for i=ceiling to v1.Length - 1 do + results.[i] <- f v1.[i] v2[i] + + results + + /// + /// Reduces an array to a single value using a binary operation, with SIMD optimization. + /// + /// The numeric type of the array elements. + /// A function that performs the SIMD reduction on two vectors. + /// A fallback function for scalar reduction. + /// The initial value for the reduction. + /// The input array. + /// The result of the reduction. + static member inline fold<'T when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T :> ValueType> + (fv:Numerics.Vector<'T> -> Numerics.Vector<'T> -> Numerics.Vector<'T>) + (f: 'T -> 'T -> 'T) + (zero: 'T) + (v: 'T[]) : 'T = + + let length = v.Length + let slotSize = Numerics.Vector<'T>.Count + let slotCount = length / slotSize + let ceiling = slotSize * slotCount + + let vSpan: Span> = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(v.AsSpan()) + + let mutable accVec = Numerics.Vector<'T>(zero) + + for i = 0 to slotCount - 1 do + accVec <- fv accVec vSpan[i] + + let mutable acc = accVec.[0] + for i = 1 to slotSize - 1 do + acc <- f acc accVec.[i] + + for i = ceiling to length - 1 do + acc <- f acc v[i] + + acc + + /// + /// Applies an element-wise binary operation between an array and a scalar using SIMD for performance. + /// + /// The numeric type of the array elements. + /// A function that performs the SIMD operation on a vector and a scalar vector. + /// A fallback function for scalar operations. + /// The input array. + /// The scalar value. + /// An array with the operation applied to each element and the scalar. + static member inline mapScalar<'T when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T :> ValueType> + (fv:Numerics.Vector<'T> -> Numerics.Vector<'T> -> Numerics.Vector<'T> ) + (f:'T -> 'T -> 'T) + (v1:'T[]) + (scalar:'T) : 'T[] = + + let length = v1.Length + let slotSize= Numerics.Vector<'T>.Count + let slotCount = length / slotSize + let ceiling = slotSize * slotCount + + let results = Array.zeroCreate<'T> length + let rsSpan = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(results.AsSpan()) + let v1Span = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(v1.AsSpan()) + let scalarVec = Numerics.Vector(scalar) + + for i=0 to slotCount - 1 do + rsSpan.[i] <- fv v1Span[i] scalarVec + + for i=ceiling to v1.Length - 1 do + results.[i] <- f v1.[i] scalar + + results + + + +type SIMDRangeUtils = + + /// In-place transformation of v[startIndex..(startIndex + count - 1)] + /// using a SIMD operation (fv) for chunked parts and a scalar function (f) for leftovers. + static member inline mapRangeInPlace<'T when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T :> ValueType> + (fv : Numerics.Vector<'T> -> Numerics.Vector<'T>) + (f : 'T -> 'T) + (startIndex : int) + (count : int) + (v : 'T[]) : unit = + + // 1) Validate parameters + if startIndex < 0 || count < 0 || (startIndex + count) > v.Length then + invalidArg (nameof count) "Invalid start index or count." + + // 2) Early exit if there's nothing to do + if count = 0 then + // nothing to do + () + + else + // 3) Compute how many full Vector<'T>.Count chunks we can process + let simdSize = Numerics.Vector<'T>.Count + let simdCount = count / simdSize + let tailStart = simdCount * simdSize + + // 4) Slice the relevant portion of v + let span = v.AsSpan(startIndex, count) + // 5) Interpret that span as a span of Vector<'T> + let vecSpan = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(span) + + // 6) Apply fv to each SIMD chunk + for i in 0 .. simdCount - 1 do + vecSpan.[i] <- fv vecSpan.[i] + + // 7) Handle leftover elements with f + for i in tailStart .. count - 1 do + let idx = startIndex + i + v.[idx] <- f v.[idx] + + + + /// In-place combination of two arrays (dst, src) over 'count' elements, + /// starting from 'dstStartIndex' and 'srcStartIndex' respectively. + /// Uses 'fv' for chunked SIMD processing and 'f' for leftover scalar elements. + static member inline map2RangeInPlace<'T when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T :> ValueType> + (fv : Numerics.Vector<'T> -> Numerics.Vector<'T> -> Numerics.Vector<'T>) + (f : 'T -> 'T -> 'T) + (dstStartIndex : int) + (srcStartIndex : int) + (count : int) + (dst : 'T[]) + (src : 'T[]) : unit = + + // 1) Validate parameters + if dstStartIndex < 0 || srcStartIndex < 0 || count < 0 then + invalidArg (nameof count) "Start indices and count must be non-negative." + if dstStartIndex + count > dst.Length then + invalidArg (nameof dstStartIndex) "Destination range out of bounds." + if srcStartIndex + count > src.Length then + invalidArg (nameof srcStartIndex) "Source range out of bounds." + + // 2) Early exit if there's nothing to do + if count = 0 then + () + else + // 3) How many full 'Vector<'T>' chunks fit into 'count'? + let simdSize = Numerics.Vector<'T>.Count + let simdCount = count / simdSize + let tailStart = simdCount * simdSize + + // 4) Create Spans for the subranges + let dstSpan = dst.AsSpan(dstStartIndex, count) + let srcSpan = src.AsSpan(srcStartIndex, count) + + // 5) Cast to Span> for chunked SIMD ops + let dstVecSpan = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(dstSpan) + let srcVecSpan = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(srcSpan) + + // 6) Apply 'fv' to each pair of SIMD chunks + for i = 0 to simdCount - 1 do + dstVecSpan.[i] <- fv dstVecSpan.[i] srcVecSpan.[i] + + // 7) Handle leftover scalar elements + for i = tailStart to count - 1 do + let dstIdx = dstStartIndex + i + let srcIdx = srcStartIndex + i + dst.[dstIdx] <- f dst.[dstIdx] src.[srcIdx] + + + /// Dot product of arr1[off1..off1+count-1] and arr2[off2..off2+count-1]. + /// Uses SIMD if available; otherwise a naive loop. + static member inline dotRange<'T when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T :> ValueType> + (arr1: 'T[]) (off1: int) + (arr2: 'T[]) (off2: int) + (count: int) = + + if Numerics.Vector.IsHardwareAccelerated && count >= Numerics.Vector<'T>.Count then + let simdSize = Numerics.Vector<'T>.Count + let simdCount = count / simdSize + let tailStart = simdCount * simdSize + + let mutable sumVec = Numerics.Vector<'T>.Zero + + let span1 = arr1.AsSpan(off1, count) + let span2 = arr2.AsSpan(off2, count) + + let vec1 = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(span1) + let vec2 = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(span2) + + for i = 0 to simdCount - 1 do + sumVec <- sumVec + (vec1.[i] * vec2.[i]) + + // Reduce the SIMD lanes + let mutable simdSum = LanguagePrimitives.GenericZero<'T> + for lane = 0 to simdSize - 1 do + simdSum <- simdSum + sumVec.[lane] + + // Handle leftover tail + let mutable tailSum = LanguagePrimitives.GenericZero<'T> + for i = tailStart to count - 1 do + tailSum <- tailSum + arr1.[off1 + i] * arr2.[off2 + i] + + simdSum + tailSum + else + // Fallback naive loop + let mutable acc = LanguagePrimitives.GenericZero<'T> + for i = 0 to count - 1 do + acc <- acc + arr1.[off1 + i] * arr2.[off2 + i] + acc + + +// + +// // +// static member map2Unchecked<'T when 'T :> Numerics.INumber<'T> +// and 'T : (new: unit -> 'T) +// and 'T : struct +// and 'T :> ValueType> +// (fv:Numerics.Vector<'T> -> Numerics.Vector<'T> -> Numerics.Vector<'T>) +// (f:'T -> 'T -> 'T) +// (v1: 'T[]) +// (v2: 'T[]) : 'T[] = + + +// // Gets the total number of elements of this vector +// let length = v1.Length +// // +// let slotSize= Numerics.Vector<'T>.Count +// // Number of slots (rasterized vectors) +// let slotCount = length / slotSize +// // Index at which the non rasterd remain starts +// let ceiling = slotSize * slotCount + +// // Allocate the result array +// let results = Array.zeroCreate<'T> length +// let rsSpan = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(results.AsSpan()) +// let v1Span = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(v1.AsSpan()) +// let v2Span = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(v2.AsSpan()) + +// // Perform SIMD addition for chunks +// for i=0 to slotCount - 1 do +// rsSpan.[i] <- fv v1Span[i] v2Span[i] + +// // Handle the remaining elements +// for i=ceiling to v1.Length - 1 do +// results.[i] <- f v1.[i] v2[i] + +// results + +// type SIMDMatrixUtils() = + +// static member map2<'T when 'T :> Numerics.INumber<'T> +// and 'T : (new: unit -> 'T) +// and 'T : struct +// and 'T :> ValueType> +// (fVec: Numerics.Vector<'T> -> Numerics.Vector<'T> -> Numerics.Vector<'T>) +// (fScalar: 'T -> 'T -> 'T) +// (a: Matrix<'T>) +// (b: Matrix<'T>) +// : Matrix<'T> = + +// if a.Rows <> b.Rows || a.Cols <> b.Cols then +// invalidArg "b" "Matrix dimensions must match" + +// let len = a.Data.Length +// let result = Array.zeroCreate<'T> len + +// let simdSize = Numerics.Vector<'T>.Count +// let simdCount = len / simdSize +// let tailStart = simdCount * simdSize + +// // Cast arrays to Vector<'T> spans +// let aVec = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(a.Data.AsSpan()) +// let bVec = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(b.Data.AsSpan()) +// let rVec = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(result.AsSpan()) + +// for i = 0 to simdCount - 1 do +// rVec.[i] <- fVec aVec.[i] bVec.[i] + +// for i = tailStart to len - 1 do +// result.[i] <- fScalar a.Data.[i] b.Data.[i] + +// Matrix(a.Rows, a.Cols, result) + + +// static member mapScalar<'T when 'T :> Numerics.INumber<'T> +// and 'T : (new: unit -> 'T) +// and 'T : struct +// and 'T :> ValueType> +// (fv: Numerics.Vector<'T> -> Numerics.Vector<'T> -> Numerics.Vector<'T>) +// (f: 'T -> 'T -> 'T) +// (matrix: Matrix<'T>) +// (scalar: 'T) +// : Matrix<'T> = + +// let length = matrix.Data.Length +// let result = Array.zeroCreate<'T> length + +// let slotSize = Numerics.Vector<'T>.Count +// let slotCount = length / slotSize +// let ceiling = slotCount * slotSize + +// let scalarVec = Numerics.Vector<'T>(scalar) + +// let mSpan = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(matrix.Data.AsSpan()) +// let rSpan = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(result.AsSpan()) + +// // SIMD chunk-wise operation +// for i = 0 to slotCount - 1 do +// rSpan.[i] <- fv mSpan.[i] scalarVec + +// // Scalar fallback for remainder +// for i = ceiling to length - 1 do +// result.[i] <- f matrix.Data.[i] scalar + +// Matrix(matrix.Rows, matrix.Cols, result) diff --git a/src/FSharp.Stats/AlgTypes/Vector.fs b/src/FSharp.Stats/AlgTypes/Vector.fs new file mode 100644 index 000000000..eba35ac1d --- /dev/null +++ b/src/FSharp.Stats/AlgTypes/Vector.fs @@ -0,0 +1,253 @@ +namespace FSharp.Stats + +open System +open System.Runtime.InteropServices + +/// Vector as a Array type alias +type Vector<'T when 'T :> Numerics.INumber<'T>> = 'T [] + +type Vector = + + /// Adds two vectors element-wise. + /// The first vector. + /// The second vector. + /// A new vector containing the element-wise sum of the two input vectors. + /// Thrown when the vectors have different lengths. + static member inline add<'T when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T :> ValueType> (v1 : Vector<'T>) (v2 : Vector<'T>) : Vector<'T> = + + if v1.Length <> v2.Length then + invalidArg "" "Cannot add two vectors of different dimensions." + + if Numerics.Vector.IsHardwareAccelerated then + Acceleration.SIMDUtils.map2Unchecked (+) (+) v1 v2 + else + Array.map2 (+) v1 v2 + + + /// Subtracts the second vector from the first vector element-wise. + /// The first vector. + /// The second vector. + /// A new vector containing the element-wise difference of the two input vectors. + /// Thrown when the vectors have different lengths. + static member inline subtract<'T when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T :> ValueType> (v1 : Vector<'T>) (v2 : Vector<'T>) : Vector<'T> = + + if v1.Length <> v2.Length then + invalidArg "" "Cannot subtract two vectors of different dimensions." + + if Numerics.Vector.IsHardwareAccelerated then + Acceleration.SIMDUtils.map2Unchecked (-) (-) v1 v2 + else + Array.map2 (-) v1 v2 + + + /// Multiplies two vectors element-wise. + /// The first vector. + /// The second vector. + /// A new vector containing the element-wise product of the two input vectors. + /// Thrown when the vectors have different lengths. + static member inline multiply<'T when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T :> ValueType> (v1 : Vector<'T>) (v2 : Vector<'T>) : Vector<'T> = + + if v1.Length <> v2.Length then + invalidArg "" "Cannot multiply two vectors of different dimensions." + + if Numerics.Vector.IsHardwareAccelerated then + Acceleration.SIMDUtils.map2Unchecked ( * ) ( * ) v1 v2 + else + Array.map2 ( * ) v1 v2 + + + /// Divides the first vector by the second vector element-wise. + /// The first vector. + /// The second vector. + /// A new vector containing the element-wise division of the two input vectors. + /// Thrown when the vectors have different lengths. + static member inline divide<'T when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T :> ValueType> (v1 : Vector<'T>) (v2 : Vector<'T>) : Vector<'T> = + if v1.Length <> v2.Length then + invalidArg "" "Cannot divide two vectors of different dimensions." + + if Numerics.Vector.IsHardwareAccelerated then + Acceleration.SIMDUtils.map2Unchecked ( / ) ( / ) v1 v2 + else + Array.map2 ( / ) v1 v2 + + + /// Adds a scalar to each element of the vector. + /// The vector. + /// The scalar value to add. + /// A new vector with the scalar added to each element. + static member inline addScalar<'T when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T :> ValueType> (v:Vector<'T>) (scalar:'T) : Vector<'T> = + + if Numerics.Vector.IsHardwareAccelerated then + Acceleration.SIMDUtils.mapScalar (+) (+) v scalar + else + Array.map (fun x -> x + scalar) v + + + /// Subtracts a scalar from each element of the vector. + /// The vector. + /// The scalar value to subtract. + /// A new vector with the scalar subtracted from each element. + static member inline subtractScalar<'T when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T :> ValueType> (v:Vector<'T>) (scalar:'T) : Vector<'T> = + if Numerics.Vector.IsHardwareAccelerated then + Acceleration.SIMDUtils.mapScalar (-) (-) v scalar + else + Array.map (fun x -> x - scalar) v + + + /// Multiplies each element of the vector by a scalar. + /// The vector. + /// The scalar value to multiply by. + /// A new vector with each element multiplied by the scalar. + static member inline multiplyScalar<'T when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T :> ValueType> (v:Vector<'T>) (scalar:'T) : Vector<'T> = + + if Numerics.Vector.IsHardwareAccelerated then + Acceleration.SIMDUtils.mapScalar ( * ) ( * ) v scalar + else + Array.map (fun x -> x * scalar) v + + + /// Divides each element of the vector by a scalar. + /// The vector. + /// The scalar value to divide by. + /// A new vector with each element divided by the scalar. + static member inline divideScalar<'T when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T :> ValueType> (v:Vector<'T>) (scalar:'T) : Vector<'T> = + + if Numerics.Vector.IsHardwareAccelerated then + Acceleration.SIMDUtils.mapScalar ( / ) ( / ) v scalar + else + Array.map (fun x -> x / scalar) v + + /// Computes the sum of all elements in the vector. + /// The vector. + /// The sum of all elements in the vector. + static member inline sum<'T when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T :> ValueType> + (v:Vector<'T>) : 'T = + let zero = LanguagePrimitives.GenericZero<'T> + if Numerics.Vector.IsHardwareAccelerated then + Acceleration.SIMDUtils.fold (+) (+) zero v + else + Array.sum v + + /// Computes the product of all elements in the vector. + /// The vector. + /// The product of all elements in the vector. + static member inline product<'T when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T :> ValueType> + (v:Vector<'T>) : 'T = + let one = LanguagePrimitives.GenericOne<'T> + if Numerics.Vector.IsHardwareAccelerated then + Acceleration.SIMDUtils.fold (*) (*) one v + else + Array.fold ( * ) one v + + + /// Computes the mean of the elements in the vector. + /// The vector. + /// The mean of the elements in the vector. + /// Thrown when the vector is empty. + static member inline mean<'T when 'T :> Numerics.INumber<'T> + and 'T : (static member DivideByInt : 'T * int -> 'T) + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T :> ValueType> + (v: Vector<'T>) : 'T = + if v.Length = 0 then invalidArg "v" "Cannot compute mean of empty vector." + let sum = Vector.sum v + LanguagePrimitives.DivideByInt<'T> sum v.Length + + /// Computes the dot product of two vectors. + /// The first vector. + /// The second vector. + /// The dot product of the two vectors. + /// Thrown when the vectors have different lengths. + static member inline dotProduct<'T when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T :> ValueType> (v1 : Vector<'T>) (v2 : Vector<'T>) : 'T = + + if v1.Length <> v2.Length then + invalidArg "v2" "Arrays must have the same length." + if Numerics.Vector.IsHardwareAccelerated then + let length = v1.Length + let slotSize = Numerics.Vector<'T>.Count + let slotCount = length / slotSize + let ceiling = slotSize * slotCount + + let mutable result = Numerics.Vector<'T>.Zero + let v1Span = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(v1.AsSpan()) + let v2Span = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(v2.AsSpan()) + let mutable scalarResult = LanguagePrimitives.GenericZero<'T> + + for i = 0 to slotCount - 1 do + result <- Numerics.Vector.Add(result, Numerics.Vector.Multiply(v1Span.[i], v2Span.[i])) + scalarResult <- Numerics.Vector.Sum result + + for i = ceiling to v1.Length - 1 do + scalarResult <- scalarResult + (v1.[i] * v2.[i]) + + scalarResult + else + Array.fold2 (fun acc x y -> acc + (x * y)) LanguagePrimitives.GenericZero v1 v2 + + + /// Computes the Euclidean norm (magnitude) of the vector. + /// The vector. + /// The Euclidean norm of the vector. + static member inline norm<'T when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T :> ValueType + and 'T :> Numerics.IRootFunctions<'T>> + (v:Vector<'T>) : 'T = + + let sumSquares = Vector.dotProduct v v + 'T.Sqrt sumSquares + + static member inline min<'T when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T : comparison + and 'T :> ValueType> + (v:Vector<'T>) : 'T = + if v.Length = 0 then invalidArg "v" "Cannot compute min of empty vector." + Acceleration.SIMDUtils.fold (fun a b -> Numerics.Vector.Min(a, b)) min v.[0] v + + static member inline max<'T when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T : comparison + and 'T :> ValueType> + (v:Vector<'T>) : 'T = + if v.Length = 0 then invalidArg "v" "Cannot compute min of empty vector." + Acceleration.SIMDUtils.fold (fun a b -> Numerics.Vector.Max(a, b)) min v.[0] v + + diff --git a/src/FSharp.Stats/AlgTypes/VectorExt.fs b/src/FSharp.Stats/AlgTypes/VectorExt.fs new file mode 100644 index 000000000..3badfca7d --- /dev/null +++ b/src/FSharp.Stats/AlgTypes/VectorExt.fs @@ -0,0 +1,182 @@ +namespace FSharp.Stats + +open System +open System.Runtime.InteropServices + +[] +module Vector = + + let inline zeroCreate<'T when 'T :> Numerics.INumber<'T>> count : Vector<'T> = + Array.zeroCreate<'T> count + + /// Indexed fold over a vector + let inline foldi<'T when 'T :> Numerics.INumber<'T>> f (state: 'T) (v: Vector<'T>) : 'T = + let mutable acc = state + for i = 0 to v.Length - 1 do + acc <- f i acc v.[i] + acc + + /// Indexed map over a vector + let inline mapi<'T when 'T :> Numerics.INumber<'T>> (f: int -> 'T -> 'T) (v: Vector<'T>) : Vector<'T> = + Array.mapi f v + + /// Filter vector elements by predicate + let inline filter<'T when 'T :> Numerics.INumber<'T>> (predicate: 'T -> bool) (v: Vector<'T>) : Vector<'T> = + Array.filter predicate v + + /// Initialize vector by index-based generator + let inline init<'T when 'T :> Numerics.INumber<'T>> (n: int) (f: int -> 'T) : Vector<'T> = + Array.init n f + + /// Extract a slice from a vector + let inline slice<'T when 'T :> Numerics.INumber<'T>> (start: int) (length: int) (v: Vector<'T>) : Vector<'T> = + Array.sub v start length + + /// Find index of maximum value + let inline argmax<'T when 'T :> Numerics.INumber<'T> and 'T : comparison> (v: Vector<'T>) : int = + let mutable maxIdx = 0 + let mutable maxVal = v.[0] + for i = 1 to v.Length - 1 do + if v.[i] > maxVal then + maxVal <- v.[i] + maxIdx <- i + maxIdx + + /// Find index of minimum value + let inline argmin<'T when 'T :> Numerics.INumber<'T> and 'T : comparison> (v: Vector<'T>) : int = + let mutable minIdx = 0 + let mutable minVal = v.[0] + for i = 1 to v.Length - 1 do + if v.[i] < minVal then + minVal <- v.[i] + minIdx <- i + minIdx + + /// Pad vector to a given length with a constant value + let inline padRight<'T when 'T :> Numerics.INumber<'T>> (length: int) (value: 'T) (v: Vector<'T>) : Vector<'T> = + if v.Length >= length then v + else + Array.init length (fun i -> if i < v.Length then v.[i] else value) + + /// Zip two vectors into (index, left, right) + let inline zip<'T when 'T :> Numerics.INumber<'T>> (v1: Vector<'T>) (v2: Vector<'T>) : (int * 'T * 'T)[] = + Array.init (min v1.Length v2.Length) (fun i -> i, v1.[i], v2.[i]) + + + + /// Find index of minimum value using projection + let inline argminBy<'T, 'U + when 'T :> Numerics.INumber<'T> and 'U : comparison> + (f: 'T -> 'U) (v: Vector<'T>) : int = + let mutable minIdx = 0 + let mutable minVal = f v.[0] + for i = 1 to v.Length - 1 do + let candidate = f v.[i] + if candidate < minVal then + minVal <- candidate + minIdx <- i + minIdx + + /// Find index of maximum value using projection + let inline argmaxBy<'T, 'U + when 'T :> Numerics.INumber<'T> and 'U : comparison> + (f: 'T -> 'U) (v: Vector<'T>) : int = + let mutable maxIdx = 0 + let mutable maxVal = f v.[0] + for i = 1 to v.Length - 1 do + let candidate = f v.[i] + if candidate > maxVal then + maxVal <- candidate + maxIdx <- i + maxIdx + + /// Try to find index of first matching element + let inline tryFindIndex<'T when 'T :> Numerics.INumber<'T>> (predicate: 'T -> bool) (v: Vector<'T>) : int option = + let mutable i = 0 + let mutable found = false + while i < v.Length && not found do + if predicate v.[i] then found <- true + else i <- i + 1 + if found then Some i else None + + /// Find index of first matching element or throw + let inline findIndex<'T when 'T :> Numerics.INumber<'T>> (predicate: 'T -> bool) (v: Vector<'T>) : int = + match tryFindIndex predicate v with + | Some i -> i + | None -> failwith "Element not found." + + /// Enumerate non-zero elements with index + let inline enumerateNonZero<'T when 'T :> Numerics.INumber<'T> and 'T : equality> (v: Vector<'T>) : (int * 'T)[] = + v + |> Array.mapi (fun i x -> i, x) + |> Array.filter (fun (_, x) -> x <> 'T.Zero) + + /// Split a vector into prefix and suffix at a given index + let inline split<'T when 'T :> Numerics.INumber<'T>> (index: int) (v: Vector<'T>) : Vector<'T> * Vector<'T> = + Array.sub v 0 index, Array.sub v index (v.Length - index) + + /// Chunk a vector into equally sized pieces (last may be shorter) + let inline chunk<'T when 'T :> Numerics.INumber<'T>> (chunkSize: int) (v: Vector<'T>) : Vector<'T>[] = + let len = v.Length + [| for i in 0 .. chunkSize .. len - 1 -> + let size = min chunkSize (len - i) + Array.sub v i size |] + + /// Sliding window over the vector + let inline windowed<'T when 'T :> Numerics.INumber<'T>> (windowSize: int) (v: Vector<'T>) : Vector<'T>[] = + if windowSize > v.Length then [||] + else + [| for i in 0 .. v.Length - windowSize -> + Array.sub v i windowSize |] + + + /// + /// Splits the vector `v` into two parts based on `indices`. + /// The elements at positions in `indices` end up in `nvi`, + /// all others go into `nv`. + /// + /// Zero-based positions to extract from `v`. + /// The full vector to split. + /// (nvi, nv): nvi contains the elements at `indices`, nv contains the rest. + let splitVector (indices: int[]) (v: Vector<'T>) = + + Array.sortInPlace indices + + let n = v.Length + let k = indices.Length + + let nvi = zeroCreate<'T> k + let nv = zeroCreate<'T> (n - k) + + let mutable iInd = 0 + let mutable iNvi = 0 + let mutable iNv = 0 + + for i = 0 to n - 1 do + // If we've not exhausted the `indices` array AND the current i matches indices.[iInd] + if iInd < k && i = indices.[iInd] then + nvi.[iNvi] <- v.[i] + iNvi <- iNvi + 1 + iInd <- iInd + 1 + else + nv.[iNv] <- v.[i] + iNv <- iNv + 1 + + nvi, nv + + /// + /// Creates a new vector that is the result of applying the permutation + /// to the vector . The element result.[i] becomes b.[P(i)]. + /// + /// A permutation function of type int -> int, + /// The original vector to be permuted. Must have length n. + /// typically created by Permutation.ofArray or Permutation.ofFreshArray. + /// + /// A new vector of the same length n, reordered according to . + /// + let permuteBy (P: Permutation) (b: Vector<'T>) : Vector<'T> = + let n = b.Length + let result = Array.zeroCreate<'T> n + for i = 0 to n - 1 do + result.[i] <- b.[P i] + result diff --git a/src/FSharp.Stats/AlgTypes/VectorOps.fs b/src/FSharp.Stats/AlgTypes/VectorOps.fs new file mode 100644 index 000000000..127395a1f --- /dev/null +++ b/src/FSharp.Stats/AlgTypes/VectorOps.fs @@ -0,0 +1,38 @@ +namespace FSharp.Stats + +open System + +// Fallback implementation container (Type class) +type VectorOps = + + + static member inline Plus (a: Vector<'T>, b: Vector<'T>) = Vector.add a b + static member inline Plus (a: Vector<'T>, b: 'T) = Vector.addScalar a b + static member inline Plus (a: 'T, b: Vector<'T>) = Vector.addScalar b a + + static member inline Minus (a: Vector<'T>, b: Vector<'T>) = Vector.subtract a b + static member inline Minus (a: Vector<'T>, b: 'T) = Vector.subtractScalar a b + + + static member inline Multiply (a: Vector<'T>, b: Vector<'T>) = Vector.multiply a b + static member inline Multiply (a: Vector<'T>, b: 'T) = Vector.multiplyScalar a b + static member inline Multiply (a: 'T, b: Vector<'T>) = Vector.multiplyScalar b a + + static member inline Divide (a: Vector<'T>, b: Vector<'T>) = Vector.divide a b + static member inline Divide (a: Vector<'T>, b: 'T) = Vector.divideScalar a b + + + +// Dispatcher types (Instance resolution) +type Plus = static member inline Invoke (a: ^A, b: ^B) = ((^A or ^B or VectorOps) : (static member Plus : ^A * ^B -> _)(a, b)) +type Minus = static member inline Invoke (a: ^A, b: ^B) = ((^A or ^B or VectorOps) : (static member Minus : ^A * ^B -> _)(a, b)) +type Multiply = static member inline Invoke (a: ^A, b: ^B) = ((^A or ^B or VectorOps) : (static member Multiply : ^A * ^B -> _)(a, b)) +type Divide = static member inline Invoke (a: ^A, b: ^B) = ((^A or ^B or VectorOps) : (static member Divide : ^A * ^B -> _)(a, b)) + +// Operators +[] +module VectorOpsSymbols = + let inline (.+) a b = Plus.Invoke(a, b) + let inline (.-) a b = Minus.Invoke(a, b) + let inline (.*) a b = Multiply.Invoke(a, b) + let inline (./) a b = Divide.Invoke(a, b) \ No newline at end of file From c63c741a3e2523f6a2b6d92839a69f5d64efcd1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20M=C3=BChlhaus?= Date: Wed, 9 Apr 2025 13:43:55 +0200 Subject: [PATCH 052/121] Add basic Linerar Algebra (necessary for advanced statistics) --- src/FSharp.Stats/Algebra/LinearAlgebra.fs | 1060 ++++++++++++--------- 1 file changed, 602 insertions(+), 458 deletions(-) diff --git a/src/FSharp.Stats/Algebra/LinearAlgebra.fs b/src/FSharp.Stats/Algebra/LinearAlgebra.fs index 28e25f071..9dde6a896 100644 --- a/src/FSharp.Stats/Algebra/LinearAlgebra.fs +++ b/src/FSharp.Stats/Algebra/LinearAlgebra.fs @@ -1,487 +1,631 @@ -namespace FSharp.Stats.Algebra +namespace FSharp.Stats.Algebra + -open FSharp.Stats open System +open FSharp.Stats +type LinearAlgebra = + + /// Subtract `scaleVal * src[srcOffset..srcOffset+count-1]` from + /// `dst[dstOffset..dstOffset+count-1]` in place. + static member inline private subScaledRowInPlace + (scaleVal : 'T) + (dstOffset : int) + (srcOffset : int) + (count : int) + (dst : 'T[]) + (src : 'T[]) = + + let scaleVec = Numerics.Vector<'T>(scaleVal) -module LinearAlgebra = + // Vector-level callback: dstVec - (scaleVal * srcVec) + let fv (dstVec: Numerics.Vector<'T>) (srcVec: Numerics.Vector<'T>) = + dstVec - (scaleVec * srcVec) + + // Scalar fallback: d - (scaleVal * s) + let f (d: 'T) (s: 'T) = + d - (scaleVal * s) + Acceleration.SIMDRangeUtils.map2RangeInPlace fv f dstOffset srcOffset count dst src + + static member inline private householderTransform + (A: Matrix<'T>) (i: int) : Vector<'T> = + let n = A.NumRows + let v = Vector.zeroCreate<'T> n + let aCol = Matrix.getCol i A + let norm = Vector.norm aCol + v.[i] <- aCol.[i] + if aCol.[i] >= 'T.Zero then -norm else norm + for j = 0 to n - 1 do + if j <> i then + v.[j] <- aCol.[j] + v + /// QR decomposition using modified Gram-Schmidt + /// Returns Q and R such that A = QR + static member inline qrModifiedGramSchmidt<'T when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T :> ValueType + and 'T :> Numerics.IRootFunctions<'T>> + (A: Matrix<'T>) : Matrix<'T> * Matrix<'T> = + + let m, n = A.NumRows, A.NumCols + + let r = Matrix.zeroCreate n n + let qCols: Vector<'T>[] = Array.zeroCreate n + let aCols = Matrix.getCols A + + for j = 0 to n - 1 do + let v = Array.copy aCols.[j] + + for i = 0 to j - 1 do + let qi = qCols.[i] + let rij = Vector.dotProduct qi v + r.[i, j] <- rij + for k = 0 to m - 1 do + v.[k] <- v.[k] - rij * qi.[k] + + let norm = Vector.norm v + r.[j, j] <- norm + let qj = Vector.divideScalar v norm + qCols.[j] <- qj + + let qData = Array.zeroCreate (m * n) + for j = 0 to n - 1 do + for i = 0 to m - 1 do + qData.[i * n + j] <- qCols.[j].[i] + + Matrix(m, n, qData), r + + /// Back substitute to solve R * x = y + /// R is upper triangular + static member inline backSubstitute<'T when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T :> ValueType> + (r: Matrix<'T>) + (y: Vector<'T>) : Vector<'T> = + + let n = r.NumRows + + if r.NumCols <> n || y.Length <> n then + invalidArg "dimensions" "R must be square and match the length of y" + + let x = Array.zeroCreate<'T> n + + for i = n - 1 downto 0 do + let mutable sum = y.[i] + for j = i + 1 to n - 1 do + sum <- sum - r.[i, j] * x.[j] + x.[i] <- sum / r.[i, i] + + x + + + + + /// Solve A * x = b for x, where A is a square matrix (n×n) and b is a vector (length n). + static member inline solveLinearQR<'T when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T :> ValueType + and 'T :> Numerics.IRootFunctions<'T>> + (A: Matrix<'T>) + (b: Vector<'T>) : Vector<'T> = + + if A.NumRows <> b.Length then + invalidArg "b" "Vector length must match number of rows in matrix A" + + let Q, R = LinearAlgebra.qrModifiedGramSchmidt A + let Qt = Q.Transpose() + let y = Matrix.muliplyVector Qt b + LinearAlgebra.backSubstitute R y + + + + /// Solve K * X = B for X, where K is a triangular matrix (lower or upper). + /// K is square of size n×n; B is n×m. Returns an n×m result X. + static member inline solveTriangularLinearSystems + (K : Matrix<'T>) + (B : Matrix<'T>) + (isLower : bool) + : Matrix<'T> = + + /// Multiply `arr[offset..offset+count-1]` by `scaleVal` in place + let inline scaleRowInPlace + (scaleVal : 'T) + (offset : int) + (count : int) + (arr : 'T[]) = + + let scaleVec = Numerics.Vector<'T>(scaleVal) + + // Vector-level callback: chunk * scaleVal + let fv (chunk: Numerics.Vector<'T>) = + chunk * scaleVec + + // Scalar fallback: x * scaleVal + let f (x: 'T) = x * scaleVal + + // mapRangeInPlace fv f offset count arr + Acceleration.SIMDRangeUtils.mapRangeInPlace fv f offset count arr + + // Check shape consistency + let nK, mK = K.NumRows, K.NumCols + let nB, mB = B.NumRows, B.NumCols + if nK <> mK || nB <> nK then + invalidArg "Matrix" "K must be square and B must have matching row count for K" + + // Copy B into a new matrix X (the solution) + let X = Matrix<'T>(B.NumRows, B.NumCols, Array.copy B.Data) + + let n = nK // size of the NxN triangular matrix K + let m = mB // # of columns in B (and thus X) + + let Kdata = K.Data + let Xdata = X.Data + + // For row i, the contiguous slice in Xdata is [i*m .. i*m + m - 1] + // => offset = i*m, length = m + + if isLower then + // ------ Forward Substitution ------ + // for i in [0..n-1]: + // X[i,*] <- X[i,*] - Σ_{j=0..i-1} [K[i,j] * X[j,*]] + // then scale row i by 1/K[i,i] + for i = 0 to n - 1 do + let baseI = i * m + // Subtract scaled rows for j in [0..i-1] + for j = 0 to i - 1 do + let kij = Kdata.[i * n + j] // K[i,j] + if kij <> 'T.Zero then + let baseJ = j * m + // subScaledRowInPlace scaleVal dstOffset srcOffset count dst src + LinearAlgebra.subScaledRowInPlace + kij + baseI // row i offset in X + baseJ // row j offset in X + m // number of columns + Xdata + Xdata + //LinearAlgebra.subScaledRowInPlace + // Xdata + // baseI // row i offset in X + // Xdata + // baseJ // row j offset in X + // m // number of columns + // kij + + - type Factorization = matrix -> (matrix*matrix*matrix) + // Divide row i by the diagonal K[i,i] + let diag = Kdata.[i * n + i] + let invDiag = 'T.One / diag + // scaleRowInPlace scaleVal offset count arr + scaleRowInPlace + invDiag + baseI + m + Xdata + else + // ------ Backward Substitution ------ + // for i in [n-1..0]: + // X[i,*] <- X[i,*] - Σ_{j=i+1..n-1} [K[i,j] * X[j,*]] + // then scale row i by 1/K[i,i] + for i = n - 1 downto 0 do + let baseI = i * m + for j = i + 1 to n - 1 do + let kij = Kdata.[i * n + j] // K[i,j] + if kij <> 'T.Zero then + let baseJ = j * m + LinearAlgebra.subScaledRowInPlace + kij + baseI + baseJ + m + Xdata + Xdata + let diag = Kdata.[i * n + i] + let invDiag = 'T.One / diag + scaleRowInPlace + invDiag + baseI + m + Xdata + + X + + + + /// Solve K * x = v (triangular system) in-place, returning a copy of x. + /// K must be n×n, v must be length n. + /// isLower = true => forward substitution + /// isLower = false => backward substitution + static member inline solveTriangularLinearSystem + (K : Matrix<'T>) + (v : Vector<'T>) + (isLower : bool) + : Vector<'T> = + + let nK, mK = K.NumRows, K.NumCols + let nV = v.Length + if nK <> mK || nV <> nK then + invalidArg (nameof K) "K must be square, and v must match its dimension." + + let x = Array.copy v + let Kdata = K.Data // row-major flattened + + // Forward or backward substitution + if isLower then + // For i in [0..n-1]: + // x[i] <- ( x[i] - sum_{j=0..i-1}(K[i,j] * x[j]) ) / K[i,i] + for i = 0 to nK - 1 do + let mutable s = x.[i] + let rowOffset = i * nK + for j = 0 to i - 1 do + s <- s - (Kdata.[rowOffset + j] * x.[j]) + let diag = Kdata.[rowOffset + i] + x.[i] <- s / diag + else + // For i in [n-1..downto..0]: + // x[i] <- ( x[i] - sum_{j=i+1..n-1}(K[i,j] * x[j]) ) / K[i,i] + for i = nK - 1 downto 0 do + let mutable s = x.[i] + let rowOffset = i * nK + for j = i + 1 to nK - 1 do + s <- s - (Kdata.[rowOffset + j] * x.[j]) + let diag = Kdata.[rowOffset + i] + x.[i] <- s / diag + + x + + + + /// QR decomposition using Householder reflections + static member inline qrDecompose (A : Matrix<'T>) : (Matrix<'T> * Matrix<'T>) = + // former QR + let UpdateQ (Q : Matrix<'T>) (v : Vector<'T>) = + let nQ, mQ = Q.NumRows, Q.NumCols + let n = v.Length + let Qv = Vector.zeroCreate<'T> nQ + for i = 0 to nQ - 1 do + // offset in Q.Data for row i is i*mQ + let rowOffset = i * mQ + (mQ - n) + // Dot the subrange Q[i, mQ-n..mQ-1] with v[0..n-1] + Qv.[i] <- Acceleration.SIMDRangeUtils.dotRange Q.Data rowOffset v 0 n + + // Update each row i in the subrange of columns [mQ-n..mQ-1] + // Q[i, j] -= 2 * Qv[i] * v[j - (mQ - n)] + for i = 0 to nQ - 1 do + let alpha = Qv.[i] + Qv.[i] + // We want to do a row operation: Q[i, (mQ-n)..(mQ-1)] + // = Q[i, (mQ-n)..(mQ-1)] - alpha * v[0..n-1]. + let rowOffset = i * mQ + (mQ - n) + //LinearAlgebra.subScaledRowInPlace Q.Data rowOffset v 0 n alpha + LinearAlgebra.subScaledRowInPlace alpha rowOffset 0 n Q.Data v + + + + let (n, m) = (A.NumRows, A.NumCols) + + // Q starts as identity(n) + let Q = Matrix.identity n + let R = Matrix.copy A + + for i = 0 to (min n m) - 1 do + // 1) Compute Householder transform v for column i + let v = LinearAlgebra.householderTransform R i + // 2) Update Q + UpdateQ Q v + + Q, R + + /// Given A[m,n] and B[m] solves AX = B for X[n].
+ /// When m => n, have over constrained system, finds least squares solution for X.
+ /// When m < n, have under constrained system, finds least norm solution for X.
+ static member inline leastSquares + (A : Matrix<'T>) + (b: Vector<'T>) = + + let (m,n) = A.NumRows, A.NumCols + let Qm, R = LinearAlgebra.qrDecompose A + let Qtb = Qm.Transpose() * b + + // Is this an overdetermined or underdetermined system? + if m > n then + LinearAlgebra.solveTriangularLinearSystem R.[0..n-1,0..n-1] Qtb.[0..n-1] false + else + let s = LinearAlgebra.solveTriangularLinearSystem R.[0..m-1,0..m-1] Qtb false + Vector.init n (fun i -> if i < m then s.[i] else 'T.Zero) - //let private LinearAlgebraService = - // let tmp = new ServiceLocator.ServiceProvider([ProviderService.MKLProvider]) - // tmp.Start() - // tmp - let private MKLService = new ServiceLocator.ServiceProvider([ProviderService.LAPACKProvider;(*ProviderService.MKLProvider*)]) + /// + /// Computes the Cholesky factor L of a symmetric positive-definite matrix A, + /// returning L as a lower-triangular such that A = L * L^T. + /// Throws if A is not positive-definite (i.e., if any diagonal element ≤ 0). + /// + static member inline cholesky + (A : Matrix<'T>) + : Matrix<'T> = - let Service() = - match MKLService.Service() with - | Some svc -> svc - | None -> failwith "MKL service either not available, or not started" - - let private HaveService() = - MKLService.Available() - - let SolveTriangularLinearSystem (A:matrix) (b:vector) (isLower:bool) = - //if HaveService() then LinearAlgebraService.solveTriangularForVector A b isLower - // else LinearAlgebraManaged.SolveTriangularLinearSystem A b isLower - LinearAlgebraManaged.SolveTriangularLinearSystem A b isLower - - let SolveTriangularLinearSystems (A:matrix) (B:matrix) (isLower:bool) = - //if HaveService() then LinearAlgebraService.solveTriangularForMatrix A B isLower - // else LinearAlgebraManaged.SolveTriangularLinearSystems A B isLower - LinearAlgebraManaged.SolveTriangularLinearSystems A B isLower - - let SolveLinearSystem (A:matrix) (b:vector) = - //if HaveService() then LinearAlgebraService.preDivideByVector A b - // else LinearAlgebraManaged.SolveLinearSystem A b - LinearAlgebraManaged.SolveLinearSystem A b - - let SolveLinearSystems (A:matrix) (B:matrix) = - //if HaveService() then LinearAlgebraService.preDivideByMatrix A B - // else LinearAlgebraManaged.SolveLinearSystems A B - LinearAlgebraManaged.SolveLinearSystems A B - - /// Given A[n,m] and B[n] solve for x[m] such that Ax = B
This call may fail.
- /// - /// - /// - /// - /// - /// - /// - /// - let preDivideByVector A b = - //if HaveService() then LinearAlgebraService.preDivideByVector A b - // else LinearAlgebraManaged.SolveLinearSystem A b - LinearAlgebraManaged.SolveLinearSystem A b - + let n = A.NumRows + let m = A.NumCols + if n <> m then + invalidArg (nameof A) "Cholesky: matrix must be square." - /// Given A[n,m] and B[n,k] solve for X[m,k] such that AX = B
This call may fail.
- /// - /// - /// - /// - /// - /// - /// - /// - let preDivideByMatrix a b = - //if HaveService() then LinearAlgebraService.preDivideByMatrix a b - // else LinearAlgebraManaged.SolveLinearSystems a b - LinearAlgebraManaged.SolveLinearSystems a b - - ///Compoutes for an N-by-N real nonsymmetric matrix A, the - ///eigenvalue decomposition eigenvalues and right eigenvectors. - ///The right eigenvector v(j) of A satisfies - /// - /// A * v(j) = lambda(j) * v(j) - /// - ///where lambda(j) is its eigenvalue. - ///The computed eigenvectors are normalized to have Euclidean norm - ///equal to 1 and largest component real. Uses the LAPACK subroutine dgeev with arguments JOBVR = 'V' and JOBVL = 'N' - /// - /// Returns the real (first array) and imaginary (second array) parts of the eigenvalues and a matrix containing the corresponding eigenvectors - /// - /// - /// - /// - /// - /// - /// - let EVD m = - //if HaveService() then - //Service().dgeev_(m) - LinearAlgebraManaged.eigenvectors m - - /// Compute eigenvalues of a square real matrix.
Returns arrays containing the eigenvalues which may be complex.
This call may fail.
- /// - /// - /// - /// - /// - /// - /// - let EigenValues m = - //if HaveService() then let evals = LinearAlgebraService.eigenvalues m - // let n = evals.Length - // Vector.Generic.init n (fun i -> evals.[i]) - // else LinearAlgebraManaged.eigenvalues m - LinearAlgebraManaged.eigenvalues m - - /// Compute eigenvalues for a real symmetric matrix.
Returns array of real eigenvalues.
This call may fail.
- /// - /// - /// - /// - /// - /// - /// - let EigenValuesWhenSymmetric a = - //if HaveService() then let evals = LinearAlgebraService.symmetricEigenvalues a - // let n = evals.Length - // Vector.init n (fun i -> evals.[i]) - // else LinearAlgebraManaged.symmetricEigenvalues a - LinearAlgebraManaged.symmetricEigenvalues a - - /// Compute eigenvalues and eigenvectors for a real symmetric matrix.
Returns arrays of the values and vectors (both based on reals).
This call may fail.
- /// - /// - /// - /// - /// - /// - /// - let EigenSpectrumWhenSymmetric a = - if HaveService() then - Service().dsyevd_(a) - else - LinearAlgebraManaged.symmetricEigenvectors a + let dataA = A.Data + // We'll create an n×n zeroed matrix for L + let Ldata = Array.zeroCreate<'T> (n * n) + + // Helper function for indexing row-major arrays: + let inline idx r c = r * n + c + + for j = 0 to n - 1 do + // 1) Diagonal element L[j,j] + // L[j,j] = sqrt(A[j,j] - ∑(k=0..j-1) L[j,k]^2) + let mutable sumjj = dataA.[idx j j] + for k = 0 to j - 1 do + let ljk = Ldata.[idx j k] + sumjj <- sumjj - (ljk * ljk) + + // Check positivity + if sumjj <= 'T.Zero then + invalidArg "A" "Cholesky: matrix not positive-definite (diagonal <= 0)." + + let ljj = GenericMath.sqrt sumjj + Ldata.[idx j j] <- ljj + + // 2) Off-diagonal: L[i,j] for i=j+1..n-1 + // L[i,j] = (A[i,j] - ∑(k=0..j-1) L[i,k]*L[j,k]) / L[j,j] + for i = j + 1 to n - 1 do + let mutable sumij = dataA.[idx i j] + for k = 0 to j - 1 do + sumij <- sumij - (Ldata.[idx i k] * Ldata.[idx j k]) + Ldata.[idx i j] <- sumij / ljj + + Matrix<'T>(n, n, Ldata) + + + /// Given A[m,n] and b[m] solves AX = b for X[n].
+ /// When the system is under constrained,
+ /// for example when the columns of A are not linearly independent,
+ /// then it will not give sensible results.
+ static member inline leastSquaresCholesky + (A : Matrix<'T>) + (b: Vector<'T>) = + + let AT = A.Transpose() + + let upper = (AT * A) |> LinearAlgebra.cholesky + let gamma = + LinearAlgebra.solveTriangularLinearSystem(upper.Transpose()) (AT * b) true + let beta = + LinearAlgebra.solveTriangularLinearSystem upper gamma false + beta + + + /// computes the hat matrix by the QR decomposition of the designmatrix used in ordinary least squares approaches + static member inline hatMatrix + (designMatrix: Matrix<'T>) = + let qm,R = LinearAlgebra.qrDecompose designMatrix + let q1 = qm.GetSlice ((Some 0),(Some (qm.NumRows-1)),(Some 0),(Some (R.NumCols-1))) + // computes the hatmatrix + q1 * q1.Transpose() - /// Given A[n,n] find it's inverse.
This call may fail.
- /// - /// - /// - /// - /// - /// - /// - let Inverse a = - //if HaveService() then LinearAlgebraService.inverse a - // else LinearAlgebraManaged.Inverse a - LinearAlgebraManaged.Inverse a - - /// Given A[m,n] and B[m] solves AX = B for X[n].
When m => n, have over constrained system, finds least squares solution for X.
When m < n, have under constrained system, finds least norm solution for X.
- /// - /// - /// - /// - /// - /// - /// - /// - let LeastSquares a b = - //if HaveService() then LinearAlgebraService.leastSquares a b - // else LinearAlgebraManaged.leastSquares a b - LinearAlgebraManaged.leastSquares a b - - /// Given A[m,n] and b[m] solves AX = b for X[n].
When the system is under constrained,
for example when the columns of A are not linearly independent,
then it will not give sensible results.
- /// - /// - /// - /// - /// - /// - /// - /// - let LeastSquaresCholesky (a : Matrix) (b : Vector) = - LinearAlgebraManaged.leastSquaresCholesky a b - - /// Given A[n,n] real symmetric positive definite.
Finds the cholesky decomposition L such that L' * L = A.
May fail if not positive definite.
- /// - /// - /// - /// - /// - /// - /// - let Cholesky a = - //if HaveService() then LinearAlgebraService.Cholesky a - // else LinearAlgebraManaged.Cholesky a - LinearAlgebraManaged.Cholesky a - - /// Given A[n,n] real matrix.
Finds P,L,U such that L*U = P*A with L,U lower/upper triangular.
- /// - /// - /// - /// - /// - /// - /// - let LU a = - //if HaveService() then LinearAlgebraService.LU a - // else LinearAlgebraManaged.LU a - LinearAlgebraManaged.LU a - - - /// Given A[m,n] finds Q[m,m] and R[k,n] where k = min m n.
Have A = Q.R when m < =n.
Have A = Q.RX when m > n and RX[m,n] is R[n,n] row extended with (m-n) zero rows.
- /// - /// - /// - /// - /// - /// - /// - let QR a = - //if HaveService() then LinearAlgebraService.QR a - // else LinearAlgebraManaged.QR a - LinearAlgebraManaged.QR a + /// computes the leverages of every dataPoint of a dataSet given by the diagonal of the hat matrix. + static member inline leverageBy + (hatMatrix: Matrix<'T>) = + + Matrix.getDiagonal hatMatrix + + + /// computes the leverage directly by QR decomposition of the designmatrix used in ordinary least squares approaches
+ /// and computing of the diagnonal entries of the Hat matrix, known as the leverages of the regressors
+ static member inline leverage + (designMatrix: Matrix<'T>) = + + let qm,R = LinearAlgebra.qrDecompose designMatrix + let q1 = qm.GetSlice ((Some 0),(Some (qm.NumRows-1)),(Some 0),(Some (R.NumCols-1))) + + Vector.init q1.NumRows (fun i -> + let mutable sumOfSquares = 'T.Zero + for j = 0 to q1.NumCols - 1 do + let x = q1.[i, j] + sumOfSquares <- sumOfSquares + x * x + sumOfSquares + ) + /// - /// Performs QR decomposition using an alternative algorithm. - /// QR decomposition is a method to decompose a matrix A into two components: - /// Q (an orthogonal matrix) and R (an upper triangular matrix), - /// such that A = Q * R. It is commonly used in solving linear systems, - /// least squares fitting, and eigenvalue problems. + /// Computes the LU factorization of a square matrix A with partial pivoting. + /// That is, P * A = L * U, where P is a permutation, and L, U are lower/upper triangular. + /// Returns (Permutation P, L, U). /// - /// - /// A tuple containing: - /// - /// Q: The orthogonal matrix obtained from the decomposition. - /// R: The upper triangular matrix obtained from the decomposition. - /// - /// - let qrAlternative (A: Matrix) = - let m: int = A.NumRows - let n: int = A.NumCols - - let q: Matrix = Matrix.zero m n - let r: Matrix = Matrix.zero n n - let qLengths: Vector = Vector.zeroCreate n - - let getVectorLength (v: Vector) = Vector.fold (fun folder i -> folder+(i*i)) 0. v - - let setqOfA (n: int) = - let aN: Vector = Matrix.getCol A n - let qN = - if n = 0 then - aN - else - Array.init (n) (fun i -> - let denominator = qLengths[i] - let forNominator: Vector = Matrix.getCol q i - let nominator: float = Vector.dot aN forNominator - r.[i, n] <- nominator - (nominator/denominator) * forNominator - ) - |> Array.fold (fun folder e -> folder-e ) aN - Matrix.setCol q n qN - qN - - for i=0 to n-1 do - let qN = setqOfA i - let qLength = getVectorLength qN - let rValue = sqrt(qLength) - r[i,i] <- rValue - qLengths[i] <- qLength - - for i=0 to n-1 do - let qN: Vector = Matrix.getCol q i - let updateQ = (1./sqrt( qLengths[i] )) * qN - Matrix.setCol q i updateQ - for j=i+1 to n-1 do - let denominator = r[i, i] - let nominator = r[i, j] - r[i, j] <- (nominator/denominator) - - q, r + static member inline luDecompose (A : Matrix<'T>) = + let n, m = A.NumRows, A.NumCols + if n <> m then + invalidArg (nameof A) "LU: A must be square." + + let U = Matrix.copy A // We'll transform U in place. + let L = Matrix.zeroCreate n n // We'll fill L below the diagonal. + let P = [| 0 .. n-1 |] // Pivot array + + // Row-swap function for U: swap entire row i, row j + let swapRows (M: Matrix<'T>) i j = + let rowI = i + let rowJ = j + for col = 0 to m - 1 do + let tmp = M.[rowI, col] + M.[rowI, col] <- M.[rowJ, col] + M.[rowJ, col] <- tmp + + // Row-swap function for L: only swap the columns up to i-1 (since the rest is not yet set). + // Because in Doolittle's method, columns [0..i-1] of L are already determined at pivot step i. + let swapRowsPartial (M: Matrix<'T>) i j pivotCol = + for col = 0 to pivotCol - 1 do + let tmp = M.[i, col] + M.[i, col] <- M.[j, col] + M.[j, col] <- tmp + + // Perform the decomposition + for i = 0 to n - 2 do + // 1) Find pivot row by max absolute value in U column i + let mutable pivotRow = i + let mutable pivotVal = abs(U.[pivotRow, i]) + for r = i + 1 to n - 1 do + let candidate = abs(U.[r, i]) + if candidate > pivotVal then + pivotVal <- candidate + pivotRow <- r + + // 2) If pivotRow != i, swap rows in U, swap partial in L, and update pivot array + if pivotRow <> i then + swapRows U i pivotRow + swapRowsPartial L i pivotRow i + let tmp = P.[i] + P.[i] <- P.[pivotRow] + P.[pivotRow] <- tmp + + // 3) Eliminate below pivot + for j = i + 1 to n - 1 do + // L[j,i] = U[j,i] / U[i,i] + L.[j,i] <- U.[j,i] / U.[i,i] + // Update row j of U + for k = i + 1 to n - 1 do + U.[j,k] <- U.[j,k] - L.[j,i] * U.[i,k] + U.[j,i] <- 'T.Zero + + // Add identity to L (so diagonal = 1.0) + // i.e., L[i,i] <- 1.0 + for i = 0 to n - 1 do + L.[i,i] <- 'T.One + + // Return the permutation (as an array or your custom Permutation type), + // plus the final L and U + (Permutation.ofArray P, L, U) /// - /// Solves a linear system of equations using QR decomposition. + /// Solves the system of linear equations A * X = B using LU factorization. + /// A must be square; B must have the same number of rows as A. + /// Returns a matrix X s.t. A*X = B. /// - /// The coefficient matrix of the linear system. - /// The target vector of the linear system. - /// - /// A tuple containing: - /// - /// mX: The solution vector of the linear system. - /// r: The upper triangular matrix obtained from QR decomposition. - /// - /// - let solveLinearQR (A: Matrix) (t: Vector) = - let m = A.NumRows - let n = A.NumCols - - System.Diagnostics.Debug.Assert(m >= n) - - let q,r = qrAlternative A - - let QT = q.Transpose - - let mX = Vector.zeroCreate n - - let c: Vector = QT * t - - let rec build_mX_inner cross_prod i j = - if j=n then - cross_prod - else - let newCrossprod = cross_prod + (r[i, j] * mX[j]) - build_mX_inner newCrossprod i (j+1) - - let rec build_mX_outer i = - if i<0 then - () - else - let crossProd = build_mX_inner 0. i (i+1) - mX[i] <- (c[i] - crossProd) / r[i, i] - build_mX_outer (i-1) - - build_mX_outer (n-1) - - mX,r - + static member inline solveLinearSystems (A: Matrix<'T>) (B: Matrix<'T>) = + let nA, mA = A.NumRows, A.NumCols + let nB, mB = B.NumRows, B.NumCols - ///Returns the full Singular Value Decomposition of the input MxN matrix - /// - ///A : A = U * SIGMA * V**T in the tuple (S, U, V**T), - /// - ///where S is an array containing the diagonal elements of SIGMA. - /// uses the LAPACK routine dgesdd with the argument JOBZ = 'A' - /// - /// - /// - /// - /// - /// - /// - let SVD (a:Matrix) = - if HaveService() then - let S,U,Vt = Service().dgesdd_ a - Vector.ofArray S,U,Vt - else - LinearAlgebraManaged.SVD a - - /// spectral norm of a matrix (for Frobenius norm use Matrix.norm) - /// - /// - /// - /// - /// - /// - /// - let spectralNorm (a:Matrix) = - //let maxEigenVal = LinearAlgebra.EigenValues mat |> Seq.max - let maxEigenVal = - SVD (a * a.Transpose) - |> fun (S,U,V') -> S - |> Seq.max - maxEigenVal |> sqrt - - ///Returns the thin Singular Value Decomposition of the input MxN matrix A - /// - ///A = U * SIGMA * V**T in the tuple (S, U, V), - /// - ///where S is an array containing the diagonal elements of SIGMA. - ///The first min(M,N) columns of U and the first min(M,N) rows of V**T are returned in the arrays U and VT; - /// uses the LAPACK routine dgesdd with the argument JOBZ = 'S' - /// - /// - /// - /// - /// - /// - /// - let thinSVD a = - if HaveService() then - let S,U,Vt = Service().dgesdd_thin_ a - Vector.ofArray S, U, Vt - else - failwith "managed version not implemented" + // 1) Check shape: A must be square, B's rows must match A's rows + if nA <> mA then + invalidArg (nameof A) "Matrix A must be square." + if nB <> nA then + invalidArg (nameof B) "Matrix B must have same number of rows as A." - let Hessenberg A = - //if HaveService() then failwith "Not implemented yet."// REVIEW LinearAlgebraService.Hessenberg A - // else LinearAlgebraManaged.Hessenberg A - LinearAlgebraManaged.Hessenberg A - - /// computes the hat matrix by the QR decomposition of the designmatrix used in ordinary least squares approaches - /// - /// - /// - /// - /// - /// - /// - let hatmatrix A = - LinearAlgebraManaged.hatMatrix A - - /// computes the hat matrix by the QR decomposition of the designmatrix used in ordinary least squares approaches - /// - /// - /// - /// - /// - /// - /// - let leverageBy A = - LinearAlgebraManaged.leverageBy A - - /// computes the leverage directly by QR decomposition of the designmatrix used in ordinary least squares approaches
and computing of the diagnonal entries of the Hat matrix, known as the leverages of the regressors
- /// - /// - /// - /// - /// - /// - /// - let leverage A = - LinearAlgebraManaged.leverage A - ///// This method computes the condition number by just dividing the largest singular value - ///// by the smallest. - //let Condition (A:matrix) = - // let _,D,_ = SVD A - // D.[0] / D.[D.Length-1] - - /// Compute the determinant of a matrix by performing an LU decomposition since if A = P'LU,
then det(A) = det(P') * det(L) * det(U).
- /// - /// - /// - /// - /// - /// - /// - let Determinant A = - let P,_,U = LU A - // Compute the sign of a permutation REVIEW maybe this should go into permutation? - let PermutationSign (len,p) = - let a = Array.init len (fun i -> p i) // Get an array representation of the permutation - let v = Array.init len // Find the positions of all the positions in the permutation - (fun i -> Array.findIndex (fun x -> x = i) a) - let mutable sign = 1.0 // Remember the sign - for i=0 to len-2 do // Start transposing elements keeping track of how many - if a.[i] <> i then // transpositions we have taken. - a.[v.[i]] <- a.[i] - a.[i] <- i - v.[a.[v.[i]]] <- v.[i] - v.[i] <- i - sign <- -sign - assert(a = [|0 .. len-1|]) - assert(v = [|0 .. len-1|]) - sign - let n = A.NumRows - let P = (fun i -> P i) - (PermutationSign (n,P)) * (Vector.prod U.Diagonal) - - //// matrix multiplication - //let MM A B = - // if HaveService() then - // LinearAlgebraService.MM A B - // else - // A * B + // 2) Factor A -> (P, L, U) + let (P, L, U) = LinearAlgebra.luDecompose A + + // 3) Permute B according to P (i.e., reorder rows) + let Bpermuted = B |> Matrix.permuteRowsBy P + + // 4) Forward substitution: solve L * Y = Bpermuted + let Y = LinearAlgebra.solveTriangularLinearSystems L Bpermuted true // isLower = true -type LinearAlgebra() = + // 5) Back substitution: solve U * X = Y + let X = LinearAlgebra.solveTriangularLinearSystems U Y false // isLower = false - /// Synonym: kernel / right null space. Returns an orthonormal basis for the null space of matrix A (Ax = 0).
The accuracy defines a threshold whether a singular value is considered as zero (default: 1e-08). - static member nullspace(?Accuracy :float ) = + X - let accuracy = defaultArg Accuracy 1e-08 + /// + /// Solves the system A * x = b for x, using LU factorization with partial pivoting. + /// A must be square, and b must have length = A.NumRows. + /// + static member inline solveLinearSystem (A : Matrix<'T>) (b : Vector<'T>) = + let n, m = A.NumRows, A.NumCols + if n <> m then + invalidArg (nameof A) "Matrix A must be square." + if b.Length <> n then + invalidArg (nameof b) "Vector b must have length = A.NumRows." - fun (a: Matrix) -> - - // Either MKL or fallback implementation of the full SVD - let (sigma,U,Vt) = LinearAlgebra.SVD a + // 1) Factor A => (P, L, U) + let (P, L, U) = LinearAlgebra.luDecompose A - // The rank is the number of nonzero singular values - let rank = - sigma - |> Seq.sumBy (fun x -> if x >= accuracy then 1 else 0) + // 2) Permute b according to P + let bPermuted = b |> Vector.permuteBy P - let count = Vt.NumRows - rank + // 3) Forward solve: L * y = bPermuted + let y = LinearAlgebra.solveTriangularLinearSystem L bPermuted true // isLower = true - Matrix.getRows Vt rank count - |> Matrix.transpose + // 4) Back solve: U * x = y + let x = LinearAlgebra.solveTriangularLinearSystem U y false // isLower = false + + x + + /// + /// Computes the inverse of a square matrix A using its LU factorization. + /// If A is n×n, we factor A = P * L * U, then solve A * X = I for X, returning X = A^-1. + /// + /// A square matrix of size n×n. + /// The inverse of A, an n×n matrix. + /// + /// Thrown if A is not square, or if factorization fails (e.g., if A is singular). + /// + static member inline inverse (A: Matrix<'T>) : Matrix<'T> = + let n, m = A.NumRows, A.NumCols + if n <> m then + invalidArg (nameof A) "Matrix must be square when computing its inverse." + // 1) Factor A => P, L, U + let (P, L, U) = LinearAlgebra.luDecompose A + // 2) Build the identity matrix I, size n + let I = Matrix.identity n + // 3) Permute I's rows by P (so effectively P*I) + let IPerm = I |> Matrix.permuteRowsBy P + + // 4) Forward substitution: solve L * Y = IPerm + let Y = LinearAlgebra.solveTriangularLinearSystems L IPerm true + + // 5) Back substitution: solve U * X = Y + let X = LinearAlgebra.solveTriangularLinearSystems U Y false + + // X is A^-1 + X + + + /// + /// Computes the Moore-Penrose pseudoinverse of a matrix using a QR-based approach. + /// If the matrix is overdetermined (m > n), returns (R⁻¹ Qᵀ) for A = Q R with A[m×n]. + /// If underdetermined (m < n), uses the transpose trick, then returns the transpose of the partial solution. + /// + /// An m×n matrix. + /// The (n×m) pseudoinverse of . + static member inline pseudoInvers (matrix: Matrix<'T>) = + let m, n = matrix.NumRows, matrix.NumCols + + // Overdetermined: A is m×n with m > n + if m > n then + // A = Q (m×m) * R (m×n) [or economy size Q (m×n), R (n×n)] + let qm, R = LinearAlgebra.qrDecompose matrix + // Instead of multiplying qm.Transpose by identity(m×m), just use qm.Transpose + // Next, we want sub-blocks: R is m×n, but we only need the top n×n portion, + // and we want the top-left n×m portion of qm.Transpose. + let Qt = qm.Transpose() + // Solve R[0..n-1, 0..n-1] * X = Qt[0..n-1, 0..m-1] (back-substitution) + LinearAlgebra.solveTriangularLinearSystems + R.[0..n-1, 0..n-1] + Qt.[0..n-1, 0..m-1] + false + + // Underdetermined: A is m×n with m < n + else + // We do matrix.Transpose => n×m + // Then QR => qm (n×n?), R (n×m?), etc. + let qm, R = LinearAlgebra.qrDecompose (matrix.Transpose()) + // Again skip identity multiply: just use qm.Transpose + let Qt = qm.Transpose() + // Solve R[0..m-1, 0..m-1] * X = Qt[0..m-1, 0..n-1] + let s = + LinearAlgebra.solveTriangularLinearSystems + R.[0..m-1, 0..m-1] + Qt.[0..m-1, 0..n-1] + false + // Return sᵀ => the actual pseudoinverse shape (n×m) + s.Transpose() From 1f2d819fc374c632666cecae748ac8c70cc47a91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20M=C3=BChlhaus?= Date: Wed, 9 Apr 2025 13:48:09 +0200 Subject: [PATCH 053/121] Integrate CrossValidation and new AlgTypes --- src/FSharp.Stats/Fitting/CrossValidation.fs | 74 +++++---------------- 1 file changed, 18 insertions(+), 56 deletions(-) diff --git a/src/FSharp.Stats/Fitting/CrossValidation.fs b/src/FSharp.Stats/Fitting/CrossValidation.fs index 34c87fe5a..ebc0a1ad6 100644 --- a/src/FSharp.Stats/Fitting/CrossValidation.fs +++ b/src/FSharp.Stats/Fitting/CrossValidation.fs @@ -23,8 +23,8 @@ module CrossValidation = /// /// let ssr (y:Vector) (p:Vector)= - let residuals = y-p - residuals.Transpose * residuals + let residuals = y .- p + Vector.dotProduct residuals residuals /// Computes root mean square error (RMSE) /// @@ -45,39 +45,6 @@ module CrossValidation = let createCrossValidationResult error errorStDev = {Error=error;ErrorStDev=errorStDev} - /// Computes a k fold cross-validation (in parallel) - [] - let inline kFoldParallel< ^T when ^T : (static member ( + ) : ^T * ^T -> ^T) - and ^T : (static member DivideByInt : ^T*int -> ^T) - and ^T : (static member Zero : ^T)> - - k iterations degreeOfParallelism (xData:Matrix< ^T >) (yData:Vector< ^T >) - (fit: Matrix< ^T > -> Vector< ^T > -> Matrix< ^T > -> Vector< ^T >) - (error: Vector< ^T > -> Vector< ^T >-> ^T) - - = - - let chunkSize = int (ceil (float yData.Length / float k)) - let chunks = - Seq.init iterations (fun _ -> - Array.init chunkSize (fun i -> FSharp.Stats.Random.rndgen.NextInt(i) ) - ) - - chunks - |> PSeq.map (fun chunk -> - let xTest,xTrain = - xData - |> Matrix.splitRows chunk - let yTest,yTrain = - yData - |> Vector.splitVector chunk - - let preds = fit xTrain yTrain xTest - let error = error preds yTest - error - ) - |> PSeq.withDegreeOfParallelism degreeOfParallelism - |> Seq.average /// Computes a repeated k fold cross-validation,
k: training set size (and number of iterations),
iterations: number of random subset creation,
xData: rowwise x-coordinate matrix,
yData: yData vector
fit: x and y data lead to function that maps a xData row vector to a y-coordinate,
error: defines the error of the fitted y-coordinate and the actual y-coordinate,
getStDev: function that calculates the standard deviation from a seq<^T>. (Seq.stDev)
/// @@ -87,12 +54,9 @@ module CrossValidation = /// /// /// - let inline repeatedKFold< ^T when ^T : (static member ( + ) : ^T * ^T -> ^T) - and ^T : (static member DivideByInt : ^T*int -> ^T) - and ^T : (static member Zero : ^T)> - + let inline repeatedKFold k (iterations: int) (xData:Matrix< ^T >) (yData:Vector< ^T >) - (fit: Matrix< ^T > -> Vector< ^T > -> RowVector< ^T > -> ^T) + (fit: Matrix< ^T > -> Vector< ^T > -> Vector< ^T > -> ^T) (error: ^T -> ^T -> ^T) (getStDev: seq< ^T > -> ^T) = let chunkSize = int (ceil (float yData.Length / float k)) @@ -113,12 +77,13 @@ module CrossValidation = yData |> Vector.splitVector indices xTest - |> Matrix.Generic.mapiRows (fun i xSingle -> + |> Matrix.getRows + |> Array.mapi (fun i xSingle -> let preds = fit xTrain yTrain xSingle - let error = error preds yTest.[i] + let error = error preds yTest[i] error ) - |> Seq.average + |> Vector.mean ) |> Seq.average ) @@ -139,7 +104,7 @@ module CrossValidation = /// /// let inline kFold k (xData:Matrix< ^T >) (yData:Vector< ^T >) - (fit: Matrix< ^T > -> Vector< ^T > -> RowVector< ^T > -> ^T) + (fit: Matrix< ^T > -> Vector< ^T > -> Vector< ^T > -> ^T) (error: ^T -> ^T -> ^T) = repeatedKFold k 1 xData yData fit error (fun s -> Seq.head s) |> fun r -> r.Error @@ -152,10 +117,8 @@ module CrossValidation = /// /// /// - let inline loocv< ^T when ^T : (static member ( + ) : ^T * ^T -> ^T) - and ^T : (static member DivideByInt : ^T*int -> ^T) - and ^T : (static member Zero : ^T)> - (xData:Matrix< ^T >) (yData:Vector< ^T >) (fitFunc:Matrix< ^T > -> Vector< ^T > -> (RowVector< ^T > -> ^T)) + let inline loocv + (xData:Matrix< ^T >) (yData:Vector< ^T >) (fitFunc:Matrix< ^T > -> Vector< ^T > -> (Vector< ^T > -> ^T)) (error: ^T -> ^T -> ^T) = let n = xData.NumRows @@ -164,10 +127,10 @@ module CrossValidation = |> List.map (fun i -> let (xTest,xTrain) = Matrix.splitRows [|i|] xData - |> fun (y,x) -> Matrix.Generic.toRowVector y,x + |> fun (y,x) -> Matrix.getRow 0 y,x let (yTest,yTrain) = Vector.splitVector [|i|] yData - |> fun (y,x) -> y.[0],x + |> fun (y,x) -> y[0],x let fit = fitFunc xTrain yTrain let yFit = fit xTest error yFit yTest @@ -182,11 +145,9 @@ module CrossValidation = /// /// /// - let inline shuffelAndSplit< ^T when ^T : (static member ( + ) : ^T * ^T -> ^T) - and ^T : (static member DivideByInt : ^T*int -> ^T) - and ^T : (static member Zero : ^T)> + let inline shuffelAndSplit p (iterations: int) (xData:Matrix< ^T >) (yData:Vector< ^T >) - (fit: Matrix< ^T > -> Vector< ^T > -> RowVector< ^T > -> ^T) + (fit: Matrix< ^T > -> Vector< ^T > -> Vector< ^T > -> ^T) (error: ^T -> ^T -> ^T) (getStDev: seq< ^T > -> ^T) = let n = xData.NumRows @@ -205,9 +166,10 @@ module CrossValidation = yData |> Vector.splitVector chunkIndices xTest - |> Matrix.Generic.mapiRows (fun i xSingle -> + |> Matrix.getRows + |> Array.mapi(fun i xSingle -> let preds = fit xTrain yTrain xSingle - let error = error preds yTest.[i] + let error = error preds yTest[i] error ) |> Seq.average From 524390f355230af0bf2a09dbc7635a3bf619415b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20M=C3=BChlhaus?= Date: Wed, 9 Apr 2025 13:48:59 +0200 Subject: [PATCH 054/121] Integrate LinearRegression new AlgTypes --- src/FSharp.Stats/Fitting/LinearRegression.fs | 97 +++++++++++--------- 1 file changed, 52 insertions(+), 45 deletions(-) diff --git a/src/FSharp.Stats/Fitting/LinearRegression.fs b/src/FSharp.Stats/Fitting/LinearRegression.fs index bf1aef5ec..a43f7a1e6 100644 --- a/src/FSharp.Stats/Fitting/LinearRegression.fs +++ b/src/FSharp.Stats/Fitting/LinearRegression.fs @@ -3,6 +3,7 @@ namespace FSharp.Stats.Fitting open System open FSharp.Stats +open FSharp.Stats.Algebra /// /// Linear regression is used to estimate the relationship of one variable (y) with another (x) by expressing y in terms of a linear function of x. @@ -21,7 +22,7 @@ module LinearRegression = /// /// Polynomial coefficients with various properties are stored within this type. /// - type Coefficients(coefficients: vector) = + type Coefficients(coefficients: Vector<'T>) = let n = coefficients.Length /// Contains polynomial coefficients as vector in the form of [constant; linear; quadratic; cubic]. @@ -55,13 +56,13 @@ module LinearRegression = member this.Item degree = coefficients.[degree] /// Gets a x value and predicts the corresponding y value for the given polynomial coefficients. - member this.Predict (x: float) = - Vector.dot coefficients (vandermondeRow this.Degree x) + member this.Predict (x: 'T) = + Vector.dotProduct coefficients (vandermondeRow this.Degree x) /// Gets a x value vector and predicts the corresponding y value for the given polynomial coefficients. - member this.Predict (x: vector) = - let tmp = Vector.init (x.Length + 1) (fun i -> if i = 0 then 1. else x.[i-1]) - Vector.dot tmp coefficients + member this.Predict (x: Vector<'T>) = + let tmp = Vector.init (x.Length + 1) (fun i -> if i = 0 then 'T.One else x.[i-1]) + Vector.dotProduct tmp coefficients /// Prints the polynomial function in a human readable form. override this.ToString() = @@ -78,7 +79,7 @@ module LinearRegression = static member Init(coefficients) = Coefficients(coefficients) /// Initializes Coefficients type with an empty vector. - static member Empty() = Coefficients(vector []) + static member Empty() = Coefficients(Array.empty) /// /// Ordinary Least Squares (OLS) regression aims to minimise the sum of squared y intercepts between the original and predicted points at each x value. @@ -119,7 +120,7 @@ module LinearRegression = let numerator = Seq.zip xData yData |> Seq.sumBy (fun (x,y) -> x * y) let denominator = xData |> Seq.sumBy (fun x -> x * x) let slope = numerator / denominator - Coefficients(vector [0.;slope]) + Coefficients([|0.;slope|]) [] let coefficientOfVector (xData : Vector) (yData : Vector) = @@ -143,8 +144,8 @@ module LinearRegression = /// LinearRegression.OLS.Linear.RTO.fit xData yData /// /// - let fit (xData : seq) (yData : seq) = - fitOfVector (vector xData) (vector yData) + let fit (xData : Vector) (yData : Vector) = + fitOfVector xData yData [] let coefficient (xData : Vector) (yData : Vector) = @@ -215,7 +216,7 @@ module LinearRegression = raise (System.ArgumentException("vector x and y have to be the same size!")) let N = xData.Length let X = Matrix.init N 2 (fun m x -> if x = 0 then 1. else xData.[m] ) - let coef = Algebra.LinearAlgebra.LeastSquares X yData + let coef = LinearAlgebra.leastSquares X yData Coefficients(coef) [] @@ -241,13 +242,13 @@ module LinearRegression = /// /// let fitCholesky (xData: Vector) (yData: Vector) = - if xData.NumRows <> yData.Length then + if xData.Length <> yData.Length then raise (System.ArgumentException("vector x and y have to be the same size!")) let X = Matrix.init (xData.Length) 2 (fun i j -> if j = 0 then 1.0 else xData.[i]) - let coef = Algebra.LinearAlgebra.LeastSquaresCholesky X yData + let coef = LinearAlgebra.leastSquaresCholesky X yData Coefficients(coef) @@ -274,11 +275,11 @@ module LinearRegression = /// /// let fitConstrained (xData : Vector) (yData : Vector) ((xC,yC): float*float) = - let xTransformed = xData |> Vector.map (fun x -> x - xC) - let yTransformed = yData |> Vector.map (fun y -> y - yC) + let xTransformed = xData .- xC + let yTransformed = yData .- yC let slope = (RTO.fitOfVector xTransformed yTransformed).Linear let intercept = yC - xC * slope - Coefficients(vector [|intercept;slope|]) + Coefficients([|intercept;slope|]) [] @@ -334,10 +335,13 @@ module LinearRegression = raise (System.ArgumentException("vector x and y have to be the same size!")) let N = xData.Length let X = Matrix.init N 2 (fun m x -> if x = 0 then 1. else xData.[m] ) - let coeffs = Coefficients(Algebra.LinearAlgebra.LeastSquares X yData) + let coeffs = Coefficients(LinearAlgebra.leastSquares X yData) let leverages = Algebra.LinearAlgebra.leverage X - let yPred = Vector.map (predict coeffs) xData - let squaredDeviations = Vector.map2 (fun y yPr -> (y - yPr) ** 2.) yPred yData + // TODO: Better performance by using a vector operation + let yPred = Array.map (predict coeffs) xData + let squaredDeviations = + let tmp = yData .- yPred // maybe switch to yData - yPred + tmp .* tmp let MSE = squaredDeviations |> Vector.sum |> fun sumOfSquares -> sumOfSquares / (float xData.Length) // compute cooksDistance for every Point in the dataSet squaredDeviations @@ -390,7 +394,7 @@ module LinearRegression = let m = xData.NumRows let n = xData.NumCols let X = Matrix.init m (n+1) (fun m n -> if n = 0 then 1. else xData.[m,n-1] ) - Coefficients(Algebra.LinearAlgebra.LeastSquares X yData) + Coefficients(LinearAlgebra.leastSquares X yData) [] let coefficients (xData : Matrix) (yData : Vector) = @@ -436,7 +440,7 @@ module LinearRegression = Matrix.init (xData.NumRows) (xData.NumCols + 1) (fun i j -> if j = 0 then 1.0 else xData.[i, j - 1]) - Coefficients(Algebra.LinearAlgebra.LeastSquaresCholesky X yData) + Coefficients(LinearAlgebra.leastSquaresCholesky X yData) [] let coefficientsCholesky (xData : Matrix) (yData : Vector) = @@ -479,7 +483,7 @@ module LinearRegression = /// let predict (coef: Coefficients) (x: Vector) = let tmp: Vector = Vector.init (x.Length+1) (fun i -> if i = 0 then 1. else x.[i-1]) - Vector.dot tmp coef.Coefficients + Vector.dotProduct tmp coef.Coefficients module RidgeRegression = @@ -491,10 +495,10 @@ module LinearRegression = let n = xData.NumCols let X = Matrix.init m (n+1) (fun m n -> if n = 0 then 1. else xData.[m,n-1] ) - let lambdaIdentity = lambda .* Matrix.identity n - let sumDot = X.Transpose * X + lambdaIdentity - let theInverse = Algebra.LinearAlgebra.Inverse sumDot - let inverseXt = theInverse * X.Transpose + let lambdaIdentity = lambda * Matrix.identity n + let sumDot = X.Transpose() * X + lambdaIdentity + let theInverse = LinearAlgebra.inverse sumDot + let inverseXt = theInverse * X.Transpose() let w = inverseXt * yData Coefficients(w) @@ -514,7 +518,7 @@ module LinearRegression = /// let predict (coef : Coefficients) (x:Vector) = let tmp :Vector = Vector.init (x.Length+1) (fun i -> if i = 0 then 1. else x.[i-1]) - Vector.dot tmp coef.Coefficients + Vector.dotProduct tmp coef.Coefficients /// /// Linear regression using polynomials as regression function: f(x) = a + bx + cx^2 + .... @@ -548,9 +552,9 @@ module LinearRegression = // Least Squares of |y=A(x)*c| // tr(A)*y = tr(A)*A*c // inv(tr(A)*A)*tr(A)*y = c - let AtA = A.Transpose * A - let Aty = A.Transpose * yData - Coefficients(Algebra.LinearAlgebra.LeastSquares AtA Aty ) + let AtA = A.Transpose() * A + let Aty = A.Transpose() * yData + Coefficients(LinearAlgebra.leastSquares AtA Aty ) [] let coefficient order (xData : Vector) (yData : Vector) = @@ -579,22 +583,23 @@ module LinearRegression = let fitWithWeighting order (weighting : Vector) (xData : Vector) (yData : Vector) = if xData.Length <> yData.Length || xData.Length <> weighting.Length then raise (System.ArgumentException("vector x,y and weighting have to be the same size!")) + // TODO: Accelaration by using a matrix operation let A = Matrix.init (order + 1) (order + 1) (fun i j -> - Vector.map2 (fun x w -> w * (pown x (i + j))) xData weighting + Array.map2 (fun x w -> w * (pown x (i + j))) xData weighting |> Vector.sum ) let b = Vector.init (order + 1) (fun i -> - Vector.map3 (fun x y w -> w * (pown x i) * y) xData yData weighting + Array.map3 (fun x y w -> w * (pown x i) * y) xData yData weighting |> Vector.sum ) - Coefficients(Algebra.LinearAlgebra.SolveLinearSystem A b) + Coefficients(LinearAlgebra.solveLinearSystem A b) [] let coefficientsWithWeighting order (weighting : Vector) (xData : Vector) (yData : Vector) = @@ -635,7 +640,7 @@ module LinearRegression = /// /// If all coefficients are nonzero, the order is equal to the length of the coefficient vector! let predict (coef: Coefficients) (x: float) = - Vector.dot coef.Coefficients (vandermondeRow coef.Degree x) + Vector.dotProduct coef.Coefficients (vandermondeRow coef.Degree x) /// /// calculates derivative values at X=x with given polynomial coefficients. Level 1 = fst derivative; Level2 = snd derivative ... @@ -697,10 +702,12 @@ module LinearRegression = raise (System.ArgumentException("vector x and y have to be the same size!")) let N = xData.Length let A = vandermondeMatrix order xData - let coeffs = Coefficients(Algebra.LinearAlgebra.LeastSquares A yData) + let coeffs = Coefficients(LinearAlgebra.leastSquares A yData) let leverages = Algebra.LinearAlgebra.leverage A - let yPred = Vector.map (predict coeffs) xData - let squaredDeviations = Vector.map2 (fun y yPr -> (y - yPr) ** 2.) yPred yData + let yPred = Array.map (predict coeffs) xData + let squaredDeviations = + let tmp = yData .- yPred // maybe switch to yData - yPred + tmp .* tmp let MSE = squaredDeviations |> Vector.sum |> fun sumOfSquares -> sumOfSquares / (float xData.Length) // compute cooksDistance for every Point in the dataSet squaredDeviations @@ -742,7 +749,7 @@ module LinearRegression = let theilEstimator (xData: Vector) (yData: Vector)= //sort data in ascending order (xData) let data = - Array.zip (Vector.toArray xData) (Vector.toArray yData) + Array.zip xData yData |> Array.sortBy fst //low/high group. (If n is odd, the middle value is ignored) @@ -770,7 +777,7 @@ module LinearRegression = |> Array.map (fun (xV,yV) -> yV - (slope * xV)) |> FSharp.Stats.Array.median - Coefficients(vector [|intercept;slope|]) + Coefficients([|intercept;slope|]) /// /// Calculates simple linear regression coefficients using the Theil-Sen estimator in the form of [|intercept; slope;|]. Performs well if outlier corrupt the regression line. @@ -810,7 +817,7 @@ module LinearRegression = let isolateUnique (data: Vector) = indicesOfUniqueOccurences |> List.map (fun i -> data.[i]) - |> vector + |> Array.ofList let filteredXData = isolateUnique xData let filteredYData = isolateUnique yData @@ -931,7 +938,7 @@ type LinearRegression() = /// /// /// Default is simple linear regression fitting without constraints. - static member fit(xData: vector, yData, ?FittingMethod: Method, ?Constraint: Constraint, ?Weighting: vector) = + static member fit(xData: Vector<'T>, yData, ?FittingMethod: Method, ?Constraint: Constraint, ?Weighting: Vector) = let _constraint = defaultArg Constraint Unconstrained @@ -945,9 +952,9 @@ type LinearRegression() = | Constraint.Unconstrained -> LinearRegression.OLS.Linear.Univariable.fit xData yData | Constraint.RegressionThroughOrigin -> - LinearRegression.OLS.Linear.RTO.fit (vector xData) (vector yData) + LinearRegression.OLS.Linear.RTO.fit xData yData | Constraint.RegressionThroughXY coordinate -> - LinearRegression.OLS.Linear.Univariable.fitConstrained (vector xData) (vector yData) coordinate + LinearRegression.OLS.Linear.Univariable.fitConstrained xData yData coordinate | _ -> failwithf "Weighted simple linear regression is not yet implemented! Use polynomial weighted regression with degree 1 instead." | Method.Polynomial o -> @@ -997,7 +1004,7 @@ type LinearRegression() = /// /// /// Default is simple linear regression fitting without constraints. - static member fit(xData: matrix, yData, ?FittingMethod: Method) = + static member fit(xData: Matrix<'T>, yData, ?FittingMethod: Method) = let _fittingMethod = defaultArg FittingMethod Method.SimpleLinear @@ -1070,6 +1077,6 @@ type LinearRegression() = /// LinearRegression.predictMultivariate(coefficientsSimpleLinear) (vector [1.;2.;3.;]) /// /// - static member predictMultivariate(coeff: LinearRegression.Coefficients) (xVector: vector) = + static member predictMultivariate(coeff: LinearRegression.Coefficients) (xVector: Vector) = coeff.Predict xVector \ No newline at end of file From 5cfc2a8001d1efcc0fc311736fe3d9bf013f16a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20M=C3=BChlhaus?= Date: Wed, 9 Apr 2025 13:49:24 +0200 Subject: [PATCH 055/121] Integrate LogisticRegression and new AlgTypes --- .../Fitting/LogisticRegression.fs | 54 ++++++++++++++----- 1 file changed, 40 insertions(+), 14 deletions(-) diff --git a/src/FSharp.Stats/Fitting/LogisticRegression.fs b/src/FSharp.Stats/Fitting/LogisticRegression.fs index 92637b974..6fa01b3f7 100644 --- a/src/FSharp.Stats/Fitting/LogisticRegression.fs +++ b/src/FSharp.Stats/Fitting/LogisticRegression.fs @@ -10,22 +10,48 @@ module LogisticRegression = open System - // Weights have 1 element more than observations, for constant - let internal predict (weights: vector) (obs: vector) = - Vector.init (obs.Length+1) (fun i -> if i = 0 then 1. else obs.[i-1]) - |> Vector.dot weights + /// Creates a new vector (length = obs.Length + 1) whose + /// first element is 1.0 (for the intercept), followed by obs's elements. + /// If obs = [x0; x1; ...; xN-1], then withIntercept obs = [1.0; x0; x1; ...; xN-1]. + let internal withIntercept (obs: Vector) : Vector = + let n = obs.Length + let result = Vector.zeroCreate (n + 1) + result.[0] <- 1.0 + // copy obs into result[1..], leveraging the library's copy or a loop + Array.blit obs 0 result 1 n + result + + /// Logistic regression prediction: + /// weights : Vector of length obs.Length+1 + /// obs : Vector (the features, excluding intercept) + /// Returns logistic(dot(weights, [1.0; obs])) + let internal predict (weights: Vector) (obs: Vector) = + // Build intercept-augmented obs + let iobs = withIntercept obs + // Dot product => logistic function + Vector.dotProduct weights iobs |> FSharp.Stats.SpecialFunctions.Logistic.standard - let internal error (weights: vector) (obs: vector) label = + /// Error = (label - prediction) + let internal error (weights: Vector) (obs: Vector) label = label - predict weights obs - let internal update alpha (weights: vector) (obs: vector) label = - Vector.add weights (Vector.scale (alpha * (error weights obs label)) (Vector.init (obs.Length+1) (fun i -> if i = 0 then 1. else obs.[i-1]))) + /// Update rule: weights <- weights + alpha * error * [1.0; obs] + let internal update alpha (weights: Vector) (obs: Vector) label = + // 1) compute scalar = alpha * error + let e = alpha * error weights obs label + // 2) build intercept obs + let iobs = withIntercept obs + // 3) scaled = e * iobs + let scaled = e .* iobs + // 4) add => new weights + Vector.add weights scaled + // simple training: returns vector of weights // after fixed number of passes / iterations over dataset, // with constant alpha - let internal simpleTrain (dataset: (float * vector) seq) passes alpha = + let internal simpleTrain (dataset: (float * Vector) seq) passes alpha = let rec descent iter curWeights = match iter with | 0 -> curWeights @@ -35,7 +61,7 @@ module LogisticRegression = update alpha w observ label) curWeights |> descent (iter - 1) - let vars = dataset |> Seq.item 1 |> snd |> Vector.length + let vars = dataset |> Seq.item 1 |> snd |> Array.length let weights = Vector.zeroCreate (vars+1) // 1 more weight for constant descent passes weights @@ -46,9 +72,9 @@ module LogisticRegression = // rate of change in the weights vector, // computed as the % change in norm - let private changeRate (before:vector) (after:vector) = + let private changeRate (before:Vector) (after:Vector) = let numerator = - Vector.sub before after + Vector.subtract before after |> Vector.norm let denominator = Vector.norm before numerator / denominator @@ -81,7 +107,7 @@ module LogisticRegression = indices |> Seq.take len |> Seq.fold (fun w i -> - let (label, observ) = yData.[i], Vector.singleton xData.[i] + let (label, observ) = yData.[i], [|xData.[i]|] update alpha w observ label) curWeights if changeRate curWeights updatedWeights <= epsilon then updatedWeights @@ -106,7 +132,7 @@ module LogisticRegression = /// /// let predict (coef: Vector) x= - predict coef (Vector.singleton x) + predict coef ([|x|]) let estimateAlpha epsilon (xData : Vector) (yData : Vector) = let fR2 alpha = @@ -143,7 +169,7 @@ module LogisticRegression = indices |> Seq.take len |> Seq.fold (fun w i -> - let (label, observ) = yData.[i], vector (Matrix.getRow xData i) + let (label, observ) = yData.[i], (Matrix.getRow i xData) update alpha w observ label) curWeights if changeRate curWeights updatedWeights <= epsilon then updatedWeights From 55487918e0cd5a9ea83afa9857d344e9461e5bbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20M=C3=BChlhaus?= Date: Wed, 9 Apr 2025 13:49:51 +0200 Subject: [PATCH 056/121] Integrate NomLinearRegression and new AlgTypes --- .../Fitting/NonLinearRegression.fs | 60 +++++++++---------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/src/FSharp.Stats/Fitting/NonLinearRegression.fs b/src/FSharp.Stats/Fitting/NonLinearRegression.fs index d741528d6..0daaea611 100644 --- a/src/FSharp.Stats/Fitting/NonLinearRegression.fs +++ b/src/FSharp.Stats/Fitting/NonLinearRegression.fs @@ -71,7 +71,7 @@ module NonLinearRegression = for i = 0 to xData.Length-1 do let gradient = Vector.zeroCreate paramCount model.GetGradientValue paramVector gradient xData.[i] |> ignore - Matrix.setRow jacobian i gradient + jacobian.SetRow( i, gradient ) jacobian /// Returns the residual vector, each row i contains the difference between the yEst_i and the yData_i. @@ -108,13 +108,13 @@ module NonLinearRegression = let shouldTerminate (currentValueRSS: float) (newValueRSS: float) (iterationCount:int) (currentParamGuess:Vector) (newParamGuess:Vector) (solverOptions: SolverOptions) = //abs (newValueRSS-currentValueRSS) <= solverOptions.MinimumDeltaValue || - Vector.sub newParamGuess currentParamGuess |> Vector.norm <= solverOptions.MinimumDeltaParameters || + Vector.subtract newParamGuess currentParamGuess |> Vector.norm <= solverOptions.MinimumDeltaParameters || iterationCount >= solverOptions.MaximumIterations /// - let solverConverged (solverOptions: SolverOptions) (estParams:ResizeArray) = + let solverConverged (solverOptions: SolverOptions) (estParams:ResizeArray>) = solverOptions.MaximumIterations = estParams.Count |> not @@ -131,17 +131,17 @@ module NonLinearRegression = /// /// let estimatedParamsVerbose (model: Model) (solverOptions: SolverOptions) (xData: float[]) (yData: float []) = - let paramsAtIteration = new ResizeArray() - let initialParamGuess = Vector.ofArray solverOptions.InitialParamGuess + let paramsAtIteration = new ResizeArray>() + let initialParamGuess = solverOptions.InitialParamGuess let residualVector = Vector.zeroCreate xData.Length - let jacobian = Matrix.zero xData.Length solverOptions.InitialParamGuess.Length + let jacobian = Matrix.zeroCreate xData.Length solverOptions.InitialParamGuess.Length let initialValueRSS = getRSS model xData yData initialParamGuess - let rec loop jacobian residualVector currentParamGuess currentValueRSS (paramsAtIteration:ResizeArray) = + let rec loop jacobian residualVector currentParamGuess currentValueRSS (paramsAtIteration:ResizeArray>) = let jacobian' = updateJacobianInplace model xData currentParamGuess jacobian let residualVector' = updateResidualVectorInPlace model xData yData currentParamGuess residualVector - let hessian = jacobian'.Transpose * jacobian' - let step = LinearAlgebra.LeastSquares hessian (Matrix.mulV (jacobian'.Transpose) residualVector') - let newParamGuess = currentParamGuess - step + let hessian = jacobian'.Transpose() * jacobian' + let step = LinearAlgebra.leastSquares hessian (Matrix.muliplyVector (jacobian'.Transpose()) residualVector') + let newParamGuess = currentParamGuess .- step let newValueRSS = getRSS model xData yData newParamGuess paramsAtIteration.Add(newParamGuess) if shouldTerminate currentValueRSS newValueRSS paramsAtIteration.Count currentParamGuess newParamGuess solverOptions then @@ -183,18 +183,18 @@ module NonLinearRegression = /// /// let estimatedParamsVerbose (model: Model) (solverOptions: SolverOptions) lambdaInitial lambdaFactor (xData: float[]) (yData: float []) = - let paramsAtIteration = new ResizeArray() - let initialParamGuess = Vector.ofArray solverOptions.InitialParamGuess + let paramsAtIteration = new ResizeArray>() + let initialParamGuess = solverOptions.InitialParamGuess let residualVector = Vector.zeroCreate xData.Length - let jacobian = Matrix.zero xData.Length solverOptions.InitialParamGuess.Length + let jacobian = Matrix.zeroCreate xData.Length solverOptions.InitialParamGuess.Length let initialValueRSS = getRSS model xData yData initialParamGuess - let rec loop lambda jacobian residualVector currentParamGuess currentValueRSS (paramsAtIteration:ResizeArray) = + let rec loop lambda jacobian residualVector currentParamGuess currentValueRSS (paramsAtIteration:ResizeArray>) = let jacobian' = updateJacobianInplace model xData currentParamGuess jacobian let residualVector' = updateResidualVectorInPlace model xData yData currentParamGuess residualVector - let hessian = jacobian'.Transpose * jacobian' + let hessian = jacobian'.Transpose() * jacobian' let diagonal = Matrix.initDiagonal (Vector.map (fun x -> ((lambda)*x)) hessian.Diagonal) let modHessian = (hessian + diagonal) - let step = FSharp.Stats.Algebra.LinearAlgebra.SolveLinearSystem modHessian (Matrix.mulV (jacobian'.Transpose) residualVector') + let step = LinearAlgebra.solveLinearSystem modHessian (Matrix.mulV (jacobian'.Transpose) residualVector') let newParamGuess = currentParamGuess - step let newValueRSS = getRSS model xData yData newParamGuess paramsAtIteration.Add(newParamGuess) @@ -234,7 +234,7 @@ module NonLinearRegression = module LevenbergMarquardtConstrained = /// - let private validateBounds (lowerBound: vector) (upperBound: vector) (parameters: vector) = + let private validateBounds (lowerBound: Vector) (upperBound: Vector) (parameters: Vector) = try if Vector.map3 (fun l u x -> if l <= x && u >= x then x else nan) lowerBound upperBound parameters |> Vector.exists Ops.isNan then failwith "initial parameters are not within Bounds" @@ -244,31 +244,31 @@ module NonLinearRegression = | _ -> failwith "vector lengths differ" /// - let private toInternalParameters (lowerBound: vector) (upperBound: vector) (extParameters: vector) = + let private toInternalParameters (lowerBound: Vector) (upperBound: Vector) (extParameters: Vector) = Vector.map3 (fun l u x -> Math.Asin((2.0 * (x - l) / (u - l)) - 1.0) ) lowerBound upperBound extParameters /// - let private toExternalParameters (lowerBound: vector) (upperBound: vector) (intParameters: vector) = + let private toExternalParameters (lowerBound: Vector) (upperBound: Vector) (intParameters: Vector) = Vector.map3 (fun l u x -> l + (u / 2.0 - l / 2.0) * (Math.Sin(x) + 1.0) ) lowerBound upperBound intParameters /// - let private calculateJacScaleFactors (lowerBound: vector) (upperBound: vector) (intParameters: vector) = + let private calculateJacScaleFactors (lowerBound: Vector) (upperBound: Vector) (intParameters: Vector) = Vector.map3 (fun l u x -> (u - l) / 2.0 * Math.Cos(x) ) lowerBound upperBound intParameters /// - let private scaleJacobian (scaleFactors: vector) (jacobian:matrix) = + let private scaleJacobian (scaleFactors: Vector) (jacobian:Matrix) = jacobian |> Matrix.mapi (fun m n x -> x * scaleFactors.[m] * scaleFactors.[n]) /// - let private scaleGradient (scaleFactors: vector) (gradient:vector) = - Vector.cptMul scaleFactors gradient + let private scaleGradient (scaleFactors: Vector) (gradient:Vector) = + Vector.multiply scaleFactors gradient /// Returns an collection of parameter vectors as a possible solution for least square based nonlinear fitting of a given dataset (xData, yData) with a given
model function.
/// @@ -286,12 +286,12 @@ module NonLinearRegression = /// /// let estimatedParamsVerbose (model: Model) (solverOptions: SolverOptions) lambdaInitial lambdaFactor (lowerBound: vector) (upperBound: vector) (xData: float[]) (yData: float []) = - let paramsAtIteration = new ResizeArray() - let initialParamGuess = Vector.ofArray solverOptions.InitialParamGuess + let paramsAtIteration = new ResizeArray>() + let initialParamGuess = solverOptions.InitialParamGuess validateBounds lowerBound upperBound initialParamGuess let internalParamsGuess = toInternalParameters lowerBound upperBound initialParamGuess let residualVector = Vector.zeroCreate xData.Length - let jacobian = Matrix.zero xData.Length solverOptions.InitialParamGuess.Length + let jacobian = Matrix.zeroCreate xData.Length solverOptions.InitialParamGuess.Length let initialValueRSS = getRSS model xData yData initialParamGuess let rec loop lambda jacobian residualVector currentParamGuessExt currentParamGuessInt currentValueRSS (paramsAtIteration:ResizeArray) = let scaleFactors = calculateJacScaleFactors lowerBound upperBound currentParamGuessInt @@ -331,8 +331,8 @@ module NonLinearRegression = /// /// /// - let estimatedParams (model: Model) (solverOptions: SolverOptions) lambdaInitial lambdaFactor (lowerBound: vector) (upperBound: vector) (xData: float[]) (yData: float []) = - let estParams = estimatedParamsVerbose model solverOptions lambdaInitial lambdaFactor (lowerBound: vector) (upperBound: vector) xData yData + let estimatedParams (model: Model) (solverOptions: SolverOptions) lambdaInitial lambdaFactor (lowerBound: Vector) (upperBound: Vector) (xData: float[]) (yData: float []) = + let estParams = estimatedParamsVerbose model solverOptions lambdaInitial lambdaFactor (lowerBound: Vector) (upperBound: Vector) xData yData estParams.[estParams.Count-1] /// Returns a parameter vector tupled with its residual sum of squares (RSS) as a possible solution for linear least square based nonlinear fitting of a given dataset (xData, yData) with a given
model function.
@@ -350,7 +350,7 @@ module NonLinearRegression = /// /// /// - let estimatedParamsWithRSS (model: Model) (solverOptions: SolverOptions) lambdaInitial lambdaFactor (lowerBound: vector) (upperBound: vector) (xData: float[]) (yData: float []) = + let estimatedParamsWithRSS (model: Model) (solverOptions: SolverOptions) lambdaInitial lambdaFactor (lowerBound: Vector) (upperBound: Vector) (xData: float[]) (yData: float []) = let estParams = estimatedParamsVerbose model solverOptions lambdaInitial lambdaFactor lowerBound upperBound xData yData estParams |> fun estParams -> @@ -542,7 +542,7 @@ module NonLinearRegression = let expSolverOptions (xData:float []) (yData:float [])= //gets the linear representation of the problem and solves it by simple linear regression let initialParamGuess = - let yLn = yData |> Array.map (fun x -> Math.Log(x)) |> vector + let yLn : Vector = yData |> Array.map (fun x -> Math.Log(x)) let linearReg = LinearRegression.OLS.Linear.Univariable.fit (vector xData) yLn let a = exp linearReg.Constant let b = linearReg.Linear From 5a2a5b524c6be89a15e4f18e9b74d8f9a6e8e4dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20M=C3=BChlhaus?= Date: Wed, 9 Apr 2025 13:50:05 +0200 Subject: [PATCH 057/121] Integrate Spline and new AlgTypes --- src/FSharp.Stats/Fitting/Spline.fs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/FSharp.Stats/Fitting/Spline.fs b/src/FSharp.Stats/Fitting/Spline.fs index 58f95cf98..656793a10 100644 --- a/src/FSharp.Stats/Fitting/Spline.fs +++ b/src/FSharp.Stats/Fitting/Spline.fs @@ -41,7 +41,6 @@ module Spline = // Some preprocessing let basistmp = preprocessBasis basispts let xdata,ydata = data |> preprocess |> Array.unzip - let ydata = vector ydata let n = Array.length xdata let n' = Array.length basistmp let xm = basistmp.[n'-2] @@ -60,7 +59,7 @@ module Spline = // Construct the matrices we need let Bt = Matrix.init n' n (fun c r -> basis.[c] xdata.[r]) - let BtB = Bt * Bt.Transpose + let BtB = Bt * Bt.Transpose() let penaltyFunc r c = let xi = xdata.[-2+min r c] let xj = xdata.[-2+max r c] @@ -74,8 +73,8 @@ module Spline = let n' = float n' fun (lambda: float) -> do checkSmoothingParameter lambda - let beta = FSharp.Stats.Algebra.LinearAlgebra.LeastSquares (BtB + n'*lambda*Omega) (Bt * ydata) - let helper = Array.zip basis (beta.ToArray()) + let beta = LinearAlgebra.leastSquares (BtB + n'*lambda*Omega) (Bt * ydata) + let helper = Array.zip basis beta /// Our actualy smoothing spline fun x -> helper |> Array.sumBy (fun (f,w) -> w * f x) \ No newline at end of file From ad402dfb7d192049ea566674e8ce57bb33e04faf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20M=C3=BChlhaus?= Date: Wed, 9 Apr 2025 13:50:28 +0200 Subject: [PATCH 058/121] Integrate GoodnessOfFit and new AlgTypes --- src/FSharp.Stats/Fitting/GoodnessOfFit.fs | 85 ++++++++++++++--------- 1 file changed, 51 insertions(+), 34 deletions(-) diff --git a/src/FSharp.Stats/Fitting/GoodnessOfFit.fs b/src/FSharp.Stats/Fitting/GoodnessOfFit.fs index 45829778f..fdcf21bfe 100644 --- a/src/FSharp.Stats/Fitting/GoodnessOfFit.fs +++ b/src/FSharp.Stats/Fitting/GoodnessOfFit.fs @@ -354,43 +354,60 @@ module GoodnessOfFit = Vector.init (order+1) (fun i -> pown x i) let calculateANOVA (order) (coef : Vector) (xData) (yData) = - let fitFunction x = Vector.dot coef (vandermondeRow order x) + let fitFunction x = Vector.dotProduct coef (vandermondeRow order x) calculateANOVA order fitFunction xData yData [] module CrossValidation = - - /// calculates LeaveOneOutCrossValidation - /// - /// - /// - /// - /// - /// - /// - /// - /// - let loocv (xData:Vector) (yData:Vector) order = - [0..xData.Length-1] - |> List.map (fun x -> - let xTmp = - xData - |> Seq.toList - |> fun xDat -> xDat.[..x-1]@xDat.[x+1..] - |> vector - let yTmp = - yData - |> Seq.toList - |> fun yDat -> yDat.[..x-1]@yDat.[x+1..] - |> vector - let coefTmp = LinearRegression.OLS.Polynomial.fit order xTmp yTmp - let error = - let yFit = LinearRegression.OLS.Polynomial.predict coefTmp (float xData.[x]) - pown (yFit - yData.[x]) 2 - error - ) - |> List.sum - |> fun x -> x/(float xData.Length) + + /// + /// Computes the leave-one-out cross-validation (LOOCV) error for a polynomial + /// fit of given on the dataset (xData, yData). + /// + /// The vector of x-values (length n). + /// The vector of y-values (length n), corresponding to xData. + /// Polynomial order. For example, order=2 => quadratic. + /// The mean squared error of leave-one-out predictions. + let loocv (xData: Vector) (yData: Vector) (order: int) : float = + let n = xData.Length + if n <> yData.Length then + invalidArg (nameof yData) "xData and yData must have the same length." + + let xArr = xData + let yArr = yData + + // Sum of squared errors across leave-one-out folds + let sse = + [0..n-1] + |> List.sumBy (fun i -> + // Create new arrays xLOO, yLOO that skip index i + let xLOO = Array.zeroCreate (n - 1) + let yLOO = Array.zeroCreate (n - 1) + + // Copy all elements up to i + Array.blit xArr 0 xLOO 0 i + Array.blit yArr 0 yLOO 0 i + + // Copy elements after i + if i < n - 1 then + Array.blit xArr (i + 1) xLOO i (n - 1 - i) + Array.blit yArr (i + 1) yLOO i (n - 1 - i) + + // Fit polynomial of the given 'order' to the (n-1) data + let coef = + LinearRegression.OLS.Polynomial.fit + order + (xLOO) + (yLOO) + + // Predict for the left-out xArr.[i], compare to actual yArr.[i] + let yPred = LinearRegression.OLS.Polynomial.predict coef xArr.[i] + let residual = yPred - yArr.[i] + residual * residual // squared error + ) + + // Return mean (average) of all squared errors + sse / float n ///k-fold cross validation ///Calculates the average SSE of given data, the order used to fit the polynomial and the subset you want to leave out (k). @@ -445,7 +462,7 @@ module GoodnessOfFit = |> Array.unzip let dataLeftOut = x let fit = - Fitting.LinearRegression.OLS.Polynomial.fit order (vector subX) (vector subY) + Fitting.LinearRegression.OLS.Polynomial.fit order (subX) (subY) |> fun coeffs -> Fitting.LinearRegression.OLS.Polynomial.predict coeffs dataLeftOut |> Array.map (fun (xLO,yLO) -> pown (fit xLO - yLO) 2) From ebfe35eda4f9c9c7ecf11205d5d0bc7a1f6061fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20M=C3=BChlhaus?= Date: Wed, 9 Apr 2025 13:50:59 +0200 Subject: [PATCH 059/121] Integrate Clustering and new AlgTypes --- .../ML/Unsupervised/ClusterNumber.fs | 38 ++++++++++++------- .../ML/Unsupervised/IterativeClustering.fs | 2 +- 2 files changed, 26 insertions(+), 14 deletions(-) diff --git a/src/FSharp.Stats/ML/Unsupervised/ClusterNumber.fs b/src/FSharp.Stats/ML/Unsupervised/ClusterNumber.fs index 927af7367..1150da672 100644 --- a/src/FSharp.Stats/ML/Unsupervised/ClusterNumber.fs +++ b/src/FSharp.Stats/ML/Unsupervised/ClusterNumber.fs @@ -176,21 +176,22 @@ module ClusterNumber = ) ) - let contingencyMatrix: Matrix = compareall correctLabels clusteredLabels |> matrix + let contingencyMatrix: Matrix = + compareall correctLabels clusteredLabels + |> Matrix.ofJaggedArray let rowSum = contingencyMatrix - |> Matrix.Generic.mapRows Seq.sum - |> Vector.toArray + |> Matrix.getRows + |> Array.map Vector.sum let colSum = contingencyMatrix - |> Matrix.Generic.mapCols Seq.sum - |> RowVector.toArray + |> Matrix.getCols + |> Array.map Vector.sum let totalSum = - contingencyMatrix - |> Matrix.Generic.sum + contingencyMatrix.Data |> Vector.sum let pi = Array.map (fun i -> i / totalSum) rowSum @@ -303,8 +304,16 @@ https://www.datanovia.com/en/lessons/determining-the-optimal-number-of-clusters- /// let generateUniformPoints (rnd:System.Random) = fun (data:array) -> - let min = matrix data |> Matrix.mapiCols (fun i x -> Seq.min x) |> Array.ofSeq - let max = matrix data |> Matrix.mapiCols (fun i x -> Seq.max x) |> Array.ofSeq + let cols = + data + |> Matrix.ofJaggedArray + |> Matrix.getCols + let min = + cols + |> Array.map (fun v -> Vector.min v) + let max = + cols + |> Array.map (fun v -> Vector.max v) let range = Array.map2 (fun ma mi -> ma - mi) max min let generateUniform () = @@ -337,9 +346,12 @@ https://www.datanovia.com/en/lessons/determining-the-optimal-number-of-clusters- // |> Array.map (fun _ -> generateUniform s)) let dataMat = (JaggedArray.toArray2D data) let (u,s,vt) = Algebra.SVD.compute dataMat - let X' = (Matrix.ofJaggedArray data) * (Matrix.ofArray2D vt).Transpose - let min = X' |> Matrix.mapiCols (fun i x -> Seq.min x) |> Array.ofSeq - let max = X' |> Matrix.mapiCols (fun i x -> Seq.max x) |> Array.ofSeq + let X' = (Matrix.ofJaggedArray data) * (Matrix.ofArray2D vt).Transpose() + let colsX' = + X' + |> Matrix.getCols + let min = colsX' |> Array.map (fun v -> Vector.min v) + let max = colsX' |> Array.map (fun v -> Vector.max v) let range = Seq.map2 (fun ma mi -> ma - mi) max min |> Array.ofSeq let generateUniform () = min @@ -349,7 +361,7 @@ https://www.datanovia.com/en/lessons/determining-the-optimal-number-of-clusters- let generateUniformSVD = Array.init data.Length (fun x -> generateUniform()) //backtransform points to get reference data (Matrix.ofJaggedArray generateUniformSVD) * (Matrix.ofArray2D vt) - |> Matrix.toJaggedArray + |> fun m -> m.toJaggedArray() [] let generate_uniform_points_PCA (rnd:System.Random) = generateUniformPointsPCA rnd diff --git a/src/FSharp.Stats/ML/Unsupervised/IterativeClustering.fs b/src/FSharp.Stats/ML/Unsupervised/IterativeClustering.fs index ef4d04d64..695db9aea 100644 --- a/src/FSharp.Stats/ML/Unsupervised/IterativeClustering.fs +++ b/src/FSharp.Stats/ML/Unsupervised/IterativeClustering.fs @@ -62,7 +62,7 @@ module IterativeClustering = // cvmax - Algorithm by Moth’d Belal. Al-Daoud (Ref.: A New Algorithm for Cluster Initialization) let initCVMAX (sampleRows: float[] []) k = - let dmatrix = matrix sampleRows + let dmatrix = Matrix.ofJaggedArray sampleRows let cvmax = sampleRows |> JaggedArray.transpose From 6a3af6e2881136d4c5c71fda694072601f4d069f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20M=C3=BChlhaus?= Date: Wed, 9 Apr 2025 13:51:45 +0200 Subject: [PATCH 060/121] Refactor GLM into an external project with FSharp.Stats dependencies --- .../Fitting/GeneralisedLinearModel.fs | 697 ------------------ 1 file changed, 697 deletions(-) delete mode 100644 src/FSharp.Stats/Fitting/GeneralisedLinearModel.fs diff --git a/src/FSharp.Stats/Fitting/GeneralisedLinearModel.fs b/src/FSharp.Stats/Fitting/GeneralisedLinearModel.fs deleted file mode 100644 index 1653c5b4f..000000000 --- a/src/FSharp.Stats/Fitting/GeneralisedLinearModel.fs +++ /dev/null @@ -1,697 +0,0 @@ -namespace FSharp.Stats.Fitting.GLM - - -open System -open FSharp.Stats -open Algebra.LinearAlgebra - -/// -/// Represents the distribution families for Generalized Linear Models (GLMs). -/// -type GlmDistributionFamily = - /// Normal distribution family. - | Normal - /// Exponential distribution family. - | Exponential - /// Gamma distribution family. - | Gamma - /// Inverse Gaussian distribution family. - | InverseGaussian - /// Poisson distribution family. - | Poisson - /// Bernoulli distribution family. - | Bernouli - /// Binomial distribution family. - | Binomial - /// Categorical distribution family. - | Categorical - /// Multinomial distribution family. - | Multinomial - -/// -/// Represents a collection of link functions used in a generalized linear model. -/// -type LinkFunctions = - | GetLink of (float -> float) - | GetInvLink of (float -> float) - | GetInvLinkDerivative of (float -> float) - -/// -/// Represents a link function used in a generalized linear model. -/// -type LinkFunction = - { - /// Gets the link function. - getLink: float -> float - /// Gets the inverse link function. - getInvLink: float -> float - /// Gets the derivative of the link function. - getDeriv: float -> float - /// Gets the derivative of the inverse link function. - getInvLinkDerivative: float -> float - } - -/// -/// Represents the return type of a Generalised Linear Model (GLM). -/// -/// -/// This type contains the following elements: -/// -/// -/// -/// mX: The coefficients used in the GLM. -/// -/// -/// -/// -/// mu: The predicted mean values of the GLM. -/// -/// -/// -/// -type GLMReturn = - { - /// The coefficients used in the GLM. - mX: Vector - /// The predicted mean values of the GLM. - mu: Vector - } - -/// -/// Represents the statistics of a Generalised Linear Model (GLM). -/// -/// -/// This type contains the following elements: -/// -/// -/// -/// LogLikelihood: The log-likelihood of the GLM. -/// -/// -/// -/// -/// Deviance: The deviance of the GLM. -/// -/// -/// -/// -/// PearsonChi2: The Pearson chi-squared statistic of the GLM. -/// -/// -/// -/// -type GLMStatisticsModel = - { - /// The log-likelihood of the GLM. - LogLikelihood: float - /// The deviance of the GLM. - Deviance: float - /// The Pearson chi-squared statistic of the GLM. - PearsonChi2: float - //PseudoR2:float - } - -/// -/// Represents the parameters of a Generalised Linear Model (GLM). -/// -/// -/// This type contains the following elements: -/// -/// -/// -/// Coefficient: The coefficient of the parameter. -/// -/// -/// -/// -/// StandardError: The standard error of the parameter. -/// -/// -/// -/// -/// ZScore: The Z-score of the parameter. -/// -/// -/// -/// -/// PearsonOfZScore: The Pearson of the Z-score. -/// -/// -/// -/// -type GLMStatisticsPrameter = - { - //Name:string - /// The coefficient of the parameter. - Coefficient: float - /// The standard error of the parameter. - StandardError: float - /// The Z-score of the parameter. - ZScore: float - /// The Pearson of the Z-score. - PearsonOfZScore: float - } - -/// This module contains various link functions used in generalized linear models. -module LinkFunctions = - /// Clips the logistic values to avoid numerical instability. - let internal clipLogisticValues (p : float) = - let floatEps = 2.220446049250313e-16 - - max floatEps (min (1.0-floatEps) p) - - /// Clips the logistic values to avoid numerical instability. - let internal clipLogisticValues2 (p : float) = - let floatEps = 2.220446049250313e-16 - - max floatEps p - - /// The logit link function used in logistic regression. - let LogitLinkFunction : LinkFunction = - { - // Computes the link function value for a given parameter. - getLink = fun b -> - let p = clipLogisticValues b - System.Math.Log(p / (1.0 - p)) - // Computes the inverse link function value for a given parameter. - getInvLink = fun a -> - 1.0 / (1.0 + System.Math.Exp(-a)) - // Computes the derivative of the link function for a given parameter. - getDeriv = fun a -> - let p = clipLogisticValues a - 1./(p*(1.-p)) - // Computes the derivative of the inverse link function for a given parameter. - getInvLinkDerivative = fun a -> - let t = System.Math.Exp(a) - t / ((1.0 + t) * (1.0 + t)) - } - - /// The log link function used in Poisson regression. - let LogLinkFunction : LinkFunction = - { - // Computes the link function value for a given parameter. - getLink = fun b -> System.Math.Log((clipLogisticValues2 b)) - // Computes the inverse link function value for a given parameter. - getInvLink = fun a -> System.Math.Exp(a) - // Computes the derivative of the link function for a given parameter. - getDeriv = fun a -> 1./(clipLogisticValues2 a) - // Computes the derivative of the inverse link function for a given parameter. - getInvLinkDerivative = fun a -> System.Math.Exp(a) - } - - /// The inverse squared link function used in gamma regression. - let InverseSquaredLinkFunction: LinkFunction = - { - // Computes the link function value for a given parameter. - getLink = fun b -> Math.Pow(b,-2.)//1.0 / b - // Computes the inverse link function value for a given parameter. - getInvLink = fun a -> Math.Pow(a,(1./ -2.))//1.0 / a - // Computes the derivative of the link function for a given parameter. - getDeriv = fun a -> -2. * (Math.Pow(a,(-2.-1.))) - // Computes the derivative of the inverse link function for a given parameter. - getInvLinkDerivative = fun a -> - let inv1 = 1. - -2. - let inv2 = inv1 / -2. - let inv3 = Math.Pow(a,inv2) - inv3 / -2. - } - - /// The inverse link function used in inverse Gaussian regression. - let InverseLinkFunction: LinkFunction = - { - // Computes the link function value for a given parameter. - getLink = fun b -> Math.Pow(b,-1.)//1.0 / b - // Computes the inverse link function value for a given parameter. - getInvLink = fun a -> Math.Pow(a,-1.)//1.0 / a - // Computes the derivative of the link function for a given parameter. - getDeriv = fun a -> -1. * (Math.Pow(a,(-1.-1.))) - // Computes the derivative of the inverse link function for a given parameter. - getInvLinkDerivative = fun a -> - let inv1 = 1. - -1. - let inv2 = inv1 / -1. - let inv3 = Math.Pow(a,inv2) - inv3 / -1. - } - - /// The identity link function used in linear regression. - let IdentityLinkFunction: LinkFunction = - { - // Computes the link function value for a given parameter. - getLink = fun b -> b - // Computes the inverse link function value for a given parameter. - getInvLink = fun a -> a - // Computes the derivative of the link function for a given parameter. - getDeriv = fun a -> 1. - // Computes the derivative of the inverse link function for a given parameter. - getInvLinkDerivative = fun a -> 1. - } - - -module GlmDistributionFamily = - /// Cleans a floating-point value by replacing it with a minimum threshold value. - /// Returns the original value if it is greater than the threshold. - /// Otherwise, returns the threshold value. - let internal clean (p: float) = - let floatEps = 2.220446049250313e-16 - - max floatEps p - - /// Returns the sign of a floating-point value. - /// Returns 1.0 if the value is positive, 0.0 if it is zero, and -1.0 if it is negative. - let internal signFunction x = - if x > 0. then 1. - elif x = 0. then 0. - else -1. - - /// - /// Calculates the variance for a given distribution family and value. - /// - /// The distribution family. - /// The value for which to calculate the variance. - /// The variance for the given distribution family and value. - let getVariance (mDistributionFamily: GlmDistributionFamily) (g: float) = - - match mDistributionFamily with - | GlmDistributionFamily.Multinomial -> - g * (1.0 - g) - | GlmDistributionFamily.Gamma -> - (abs(g)) ** 2. - | GlmDistributionFamily.InverseGaussian -> - g * g * g - | GlmDistributionFamily.Normal -> - 1.0 - | GlmDistributionFamily.Poisson -> - (g) - | GlmDistributionFamily.Bernouli -> - g * (1.0 - g) - | GlmDistributionFamily.Binomial -> - let cleanG = max 1e-8 (min (1.0-1e-8) g) - cleanG * (1.0 - cleanG) - | GlmDistributionFamily.Categorical -> - g * (1.0 - g) - | GlmDistributionFamily.Exponential -> - g * (1.0 - g) - | _ -> - raise (System.NotImplementedException()) - - /// - /// Returns the link function associated with a distribution family. - /// - /// The distribution family. - /// The link function for the distribution family. - let getLinkFunction (mDistributionFamily: GlmDistributionFamily) = - match mDistributionFamily with - | GlmDistributionFamily.Multinomial -> - LinkFunctions.LogitLinkFunction - | GlmDistributionFamily.Gamma -> - LinkFunctions.InverseLinkFunction - | GlmDistributionFamily.InverseGaussian -> - LinkFunctions.InverseSquaredLinkFunction - | GlmDistributionFamily.Normal -> - LinkFunctions.IdentityLinkFunction - | GlmDistributionFamily.Poisson -> - LinkFunctions.LogLinkFunction - | GlmDistributionFamily.Exponential -> - LinkFunctions.LogitLinkFunction - | GlmDistributionFamily.Bernouli -> - LinkFunctions.LogitLinkFunction - | GlmDistributionFamily.Binomial -> - LinkFunctions.LogitLinkFunction - | GlmDistributionFamily.Categorical -> - LinkFunctions.LogitLinkFunction - | _ -> - raise (System.NotImplementedException()) - - /// - /// Returns the weights associated with a distribution family given the mean. - /// - /// The distribution family. - /// The mean vector. - /// The weights for the distribution family. - let getFamilyWeights (family: GlmDistributionFamily) (mu: Vector) = - let link = getLinkFunction family - let deriv = link.getDeriv - let variance = getVariance family - - mu - |> Vector.map(fun m -> - 1. / (((deriv m) ** 2) * (variance m)) - ) - - /// - /// Returns the residual deviance associated with a distribution family given the endogenous variable and the mean. - /// - /// The distribution family. - /// The endogenous variable. - /// The mean vector. - /// The residual deviance for the distribution family. - let getFamilyResidualDeviance (family: GlmDistributionFamily) (endog: Vector) (mu: Vector) = - match family with - | GlmDistributionFamily.Poisson -> - Vector.map2(fun endV muV -> - let a = clean(endV / muV) - let b = System.Math.Log(a) - let c = endV - muV - let d = endV * b - c - 2. * d - ) endog mu - |> Vector.sum - | GlmDistributionFamily.Normal -> - Vector.map2(fun endV muV -> - let a = endV - muV - a ** 2. - ) endog mu - |> Vector.sum - | GlmDistributionFamily.Gamma -> - Vector.map2(fun endV muV -> - let a = clean(endV / muV) - let b = System.Math.Log(a) - let c = endV - muV - let d = c / muV - let e = -b + d - 2. * d - ) endog mu - |> Vector.sum - // | GlmDistributionFamily.Binomial -> - // Vector.map2(fun endV muV -> - // let endogmu = clean(endV / (muV + 1e-20)) - // let nendogmu = clean((1. - endV) / (1. - muV + 1e-20)) - // endV * System.Math.Log(endogmu) + (1. - endV) * System.Math.Log(nendogmu) - // |> fun x -> 2. * x * tries - // ) endog mu - // |> Vector.sum - | GlmDistributionFamily.InverseGaussian -> - Vector.map2(fun endV muV -> - 1. / (endV * muV ** 2.) * (endV - muV) ** 2. - ) endog mu - |> Vector.sum - | _ -> - raise (System.NotImplementedException()) - - -module GLMStatistics = - - /// - /// Calculates the log-likelihood of a generalised linear model. - /// - /// The coefficient vector. - /// The mean vector. - /// The log-likelihood value. - let getLogLikelihood (b: Vector) (mu: Vector) = - Vector.mapi(fun i v -> - let y = b.[i] - let meanDist = v - y * System.Math.Log(meanDist) - meanDist - (SpecialFunctions.Gamma.gammaLn(y+1.0)) - ) mu - |> Vector.sum - - /// - /// Calculates the chi-square statistic for a generalised linear model. - /// - /// The coefficient vector. - /// The mean vector. - /// The distribution family. - /// The chi-square statistic value. - let getChi2 (b: Vector) (mu: Vector) (family: GlmDistributionFamily) = - Vector.map2(fun y yi -> - let a = y - yi - let nominator = a**2. - nominator / (GlmDistributionFamily.getVariance family yi) - ) b mu - |> Vector.sum - - /// - /// Calculates GLM statistics model. - /// - /// The coefficient vector. - /// The GLM return type. - /// The distribution family. - /// The GLM statistics model. - let getGLMStatisticsModel (b:Vector) (glmResult:GLMReturn) (family: GlmDistributionFamily) = - let logLikelihood = getLogLikelihood b glmResult.mu - let deviance = GlmDistributionFamily.getFamilyResidualDeviance family b glmResult.mu - let chi2 = getChi2 b glmResult.mu family - //let r2 = testR2 b (glmResult.mX * A) - - { - LogLikelihood=logLikelihood - Deviance=deviance - PearsonChi2=chi2 - //PseudoR2=0. - } - - /// - /// Calculates the standard errors for the coefficients in a generalized linear model. - /// The standard errors are calculated using the formula: sqrt(diagonal elements of (A^T * W * A)^-1) - /// where A is the design matrix, b is the response vector, and W is the weight vector. - /// - /// The design matrix. - /// The response vector. - /// The weight vector. - /// The standard errors. - let getStandardError (A: Matrix) (b: Vector) (W: Vector) = - let At :Matrix = Matrix.transpose A - let WMatrix = Matrix.diag W - let AtW = At * WMatrix - let AtWA :Matrix = AtW*A - let AtWAInv = Algebra.LinearAlgebra.Inverse AtWA - - let n = AtWAInv.NumRows - let m = Vector.length b - let stndErrors: Vector = - Vector.init n (fun v -> - Matrix.get AtWAInv v v - |> fun x -> System.Math.Sqrt(x) - ) - stndErrors - - /// - /// Calculates the Z-statistic for the coefficients in a generalized linear model. - /// The Z-statistic is calculated as the ratio of the coefficient estimate to its standard error. - /// - /// The coefficient vector. - /// The standard error vector. - /// The Z-statistic vector. - let getZStatistic (mx: Vector) (stndError: Vector) = - Vector.map2 (fun x y -> - x/y - ) mx stndError - - /// - /// Calculates the p-value using the z-statistic. - /// The p-value is calculated as 2 * (1 - phi), where phi is the cumulative distribution function (CDF) of the standard normal distribution. - /// The z-statistic is a vector of values for which the p-value is calculated. - /// - /// The Z-statistic vector. - /// The p-value vector. - let getPearsonOfZ (zStatistic: Vector) = - Vector.map(fun x -> - let phi = Distributions.Continuous.Normal.CDF 0. 1. (abs(x)) - let PearsonOfZScore = 2. * (1. - phi) - PearsonOfZScore - )zStatistic - - /// - /// Calculates the GLM parameter statistics. - /// - /// The design matrix. - /// The response vector. - /// The GLM return type. - /// The sequence of parameter names. - /// The sequence of parameter statistics for each element of the given coefficients - let getGLMParameterStatistics (A:Matrix) (b:Vector ) (solved:GLMReturn) (names:string seq) = - - let stndErrors = getStandardError A b solved.mu - let zStatistic = getZStatistic solved.mX stndErrors - let PearsonOfZScore = getPearsonOfZ zStatistic - Seq.init (Vector.length solved.mX) (fun i -> - Seq.item i names, - { - Coefficient=solved.mX.[i] - StandardError=stndErrors.[i] - ZScore=zStatistic.[i] - PearsonOfZScore=PearsonOfZScore.[i] - } - ) - -module internal QRSolver = - - /// - /// Performs a stepwise gain QR calculation for a generalised linear model. - /// This function calculates the cost, updated mean values, updated linear predictions, - /// weighted least squares results, and weighted least squares endogenous values for a given - /// matrix A, vector b, distribution family, vector t, vector mu, vector linPred, and old result. - /// - /// The design matrix. - /// The response vector. - /// The distribution family. - /// The vector t. - /// The mean vector. - /// The linear prediction vector. - /// The old result vector. - /// A tuple containing the cost, updated mean values, updated linear predictions, weighted least squares results, and weighted least squares endogenous values. - let stepwiseGainQR - (A: Matrix) - (b: Vector) - (mDistributionFamily: GlmDistributionFamily) - (t:Vector) - (mu:Vector) - (linPred:Vector) - (oldResult:Vector) - = - - let m = A.NumRows - let n = A.NumCols - - // Get the link function in accordance to the distribution type - let linkFunction= GlmDistributionFamily.getLinkFunction mDistributionFamily - - // Calculate the family weights for each observation - let famWeight = GlmDistributionFamily.getFamilyWeights mDistributionFamily mu - - // Calculate the self-weights for each observation - let selfWeights = - Vector.init m (fun i -> t[i] * (float 1.) * famWeight[i]) - - // Calculate the derivatives of the link function at each observation - let derivs = Vector.map(fun x -> linkFunction.getDeriv x) mu - - // Calculate the endogenous values for the weighted least squares - let wlsendog: Vector = Vector.init m (fun i -> linPred[i] + derivs[i] * (b[i]-mu[i])) - - // Calculate the weighted endogenous values and the weighted exogenous matrix - let wlsendog2,wlsexdog: Vector*Matrix = - let whalf = Vector.map(fun x -> System.Math.Sqrt(x)) selfWeights - let en = Vector.init m (fun i -> whalf[i] * wlsendog[i]) - let ex = - A - |> Matrix.toJaggedArray - |> Array.mapi(fun i x -> - x - |> Array.map(fun v -> v*whalf[i]) - ) - |> Matrix.ofJaggedArray - en,ex - - // Solve the linear system using QR decomposition - let (wlsResults: Vector),R = solveLinearQR wlsexdog wlsendog2 - - // Calculate the new linear predictions - let linPred_new: Vector = A * wlsResults - - // Calculate the new mean values - let mu_new = Vector.init m (fun i -> linkFunction.getInvLink(linPred_new[i])) - - // Calculate the cost of this step - let cost:float = - oldResult - wlsResults - |> Vector.norm - - cost,mu_new,linPred_new,wlsResults,wlsendog - - /// - /// This function performs a loop until the maximum number of iterations or until the cost for the gain is smaller than a given tolerance. - /// It uses a cost function to calculate the cost, update the parameters, and check the termination condition. - /// The loop stops when the maximum number of iterations is reached or when the cost is smaller than the tolerance. - /// Returns the final values of the parameters and intermediate results. - /// - /// The design matrix. - /// The response vector. - /// The distribution family. - /// The maximum number of iterations. - /// The tolerance for convergence. - /// The cost function. - /// A tuple containing the final values of the parameters and intermediate results. - let internal loopTilIterQR - (A: Matrix) - (b: Vector) - (mDistributionFamily: GlmDistributionFamily) - (maxIter: int) - (mTol: float) - (costFunction: - Matrix -> - Vector -> - GlmDistributionFamily -> - Vector -> - Vector -> - Vector -> - Vector -> - float * Vector * Vector * Vector * Vector - ) = - - let m = A.NumRows - let n = A.NumCols - - // Initialize an empty vector x - let t_original: Vector = Vector.init m (fun i -> 1.) - let bMean: float = Vector.mean b - let muStart:Vector = Vector.map(fun x -> ((x+bMean)/2.)) b - let linPredStart: Vector = Vector.init m (fun k -> GlmDistributionFamily.getLinkFunction(mDistributionFamily).getLink(muStart[k])) - - // Run the costFunction until maxIter has been reached or the cost for the gain is smaller than mTol - let rec loopTilMaxIter (t: Vector) (loopCount: int) (mu:Vector) (linPred:Vector) (wlsResult: Vector) (wlsendog: Vector) = - if loopCount = maxIter then - t_original,mu,linPred,wlsResult,wlsendog - else - let cost,mu_new,linPred_new,wlsResult_new,wlsendogNew = - costFunction - A - b - mDistributionFamily - t_original - mu - linPred - wlsResult - - if loopCount%10 = 0 then - printfn $"Iteration {loopCount}, Cost {cost}" - - if cost < mTol then - t_original,mu,linPred,wlsResult,wlsendog - else - loopTilMaxIter t_original (loopCount+1) mu_new linPred_new wlsResult_new wlsendogNew - - - loopTilMaxIter t_original 0 muStart linPredStart (Vector.zeroCreate n) (Vector.zeroCreate m) - - /// - /// Solves a generalized linear model using the QR decomposition and Newton's method. - /// - /// The design matrix. - /// The response vector. - /// The maximum number of iterations. - /// The distribution family of the model. - /// The tolerance for convergence. - /// The solved generalized linear model. - let solveQrNewton - (A: Matrix) - (b: Vector) - (maxIter: int) - (mDistributionFamily: GlmDistributionFamily) - (mTol: float) = - let m = A.NumRows - let n = A.NumCols - - System.Diagnostics.Debug.Assert(m >= n) - - let t,mu,linPred,wlsResult,wlsendog = - loopTilIterQR A b mDistributionFamily maxIter mTol stepwiseGainQR - - let mX,R = wlsResult,wlsendog - - {mX=mX;mu=mu} - -module SolveGLM = - - /// - /// Solves a generalized linear model using the QR decomposition and Newton's method. - /// - /// The design matrix. - /// The response vector. - /// The maximum number of iterations. - /// The distribution family of the model. - /// The tolerance for convergence. - /// The solved generalized linear model. - let solveQR (A: Matrix) (b: Vector) (maxIter: int) (mDistributionFamily: GlmDistributionFamily) (mTol: float) = - QRSolver.solveQrNewton (A: Matrix) (b: Vector) (maxIter: int) (mDistributionFamily: GlmDistributionFamily) (mTol: float) - From 068018379c708a194f3355ce48c2b3ec9cae4d4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20M=C3=BChlhaus?= Date: Wed, 9 Apr 2025 13:52:58 +0200 Subject: [PATCH 061/121] Integrate new AlgTypes --- src/FSharp.Stats/FSIPrinters.fs | 2 +- src/FSharp.Stats/Permutation.fs | 75 ++++++++++++++++++++++++--------- 2 files changed, 56 insertions(+), 21 deletions(-) diff --git a/src/FSharp.Stats/FSIPrinters.fs b/src/FSharp.Stats/FSIPrinters.fs index 16fbc0788..dc37f480f 100644 --- a/src/FSharp.Stats/FSIPrinters.fs +++ b/src/FSharp.Stats/FSIPrinters.fs @@ -34,7 +34,7 @@ module FSIPrinters = //print row with row index and vertical separator let printRow index = - let currentRow = mat.Row index + let currentRow = Matrix.getRow index mat let toString (rv) = rv |> Seq.map (fun x -> diff --git a/src/FSharp.Stats/Permutation.fs b/src/FSharp.Stats/Permutation.fs index 3e726d09d..9be2edc52 100644 --- a/src/FSharp.Stats/Permutation.fs +++ b/src/FSharp.Stats/Permutation.fs @@ -1,41 +1,76 @@ -// (c) Microsoft Corporation 2005-2009. - -//namespace Microsoft.FSharp.Math // old namespace namespace FSharp.Stats -open System + +/// +/// A permutation represented as a function from indices to indices. +/// If P is a Permutation, then P(i) gives the +/// new row index for row i (or vice versa). +/// type Permutation = int -> int -type permutation = int -> int +/// +/// The Permutation module defines a type and helper functions +/// for representing and constructing permutations from integer arrays. +/// [] [] module Permutation = - let invalidArg arg msg = raise (new System.ArgumentException((msg:string),(arg:string))) + /// + /// Validates that the given integer array is a valid + /// permutation of length n (i.e., it contains every integer from + /// 0 to n-1 exactly once), then returns a function + /// P(i) = arr[i].
+ /// Throws an exception if is invalid. + ///
+ /// + /// The array containing the permutation. Each element arr[i] must + /// be a unique integer in [0..n-1]. + /// + /// + /// A permutation function Permutation where P(i) = arr[i]. + /// + let ofFreshArray (arr: int[]) : Permutation = + let n = arr.Length + let visited = Array.create n false + + // Validate that arr[i] is unique and in [0..n-1]. + for i = 0 to n - 1 do + let x = arr.[i] + if x < 0 || x >= n then + invalidArg (nameof arr) "Permutation array contains out-of-range index." + if visited.[x] then + invalidArg (nameof arr) "Permutation array contains duplicate indices." + visited.[x] <- true - let ofFreshArray (arr:_[]) = - let arr2 = Array.zeroCreate arr.Length - for i = 0 to arr.Length - 1 do - let x = arr.[i] - if x < 0 || x >= arr.Length then invalidArg "arr" "invalid permutation" - arr2.[x] <- 1 - for i = 0 to arr.Length - 1 do - if arr2.[i] <> 1 then invalidArg "arr" "invalid permutation" - (fun k -> arr.[k]) + // Return a function P(i) = arr[i]. + fun i -> + if i < 0 || i >= n then + invalidArg "i" "Permutation function called with out-of-range index." + arr.[i] - let ofArray (arr:_[]) = arr |> Array.copy |> ofFreshArray + /// + /// Makes a copy of , then calls . + /// Useful for preserving the original array. + /// + /// An array of length n that should represent + /// a valid permutation of 0..n-1. + /// + /// A Permutation function representing the same reordering as + /// . + /// + let ofArray (arr: int[]) : Permutation = + // Defensive copy + let copy = Array.copy arr + ofFreshArray copy - [] - let of_array (arr:_[]) = ofArray arr let ofPairs (mappings: seq) = let p = dict mappings (fun k -> if p.ContainsKey k then p.[k] else k) - [] - let of_pairs (mappings: seq) = ofPairs mappings let swap (n:int) (m:int) = (fun k -> if k = n then m elif k = m then n else k) From 6ba1d50d5294488d10dad7890db6934091a003cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20M=C3=BChlhaus?= Date: Wed, 9 Apr 2025 14:08:43 +0200 Subject: [PATCH 062/121] Refactoring Interpolation --- src/FSharp.Stats/Interpolation.fs | 146 +++++++++++++++--------------- 1 file changed, 73 insertions(+), 73 deletions(-) diff --git a/src/FSharp.Stats/Interpolation.fs b/src/FSharp.Stats/Interpolation.fs index 536e89612..bc0555726 100644 --- a/src/FSharp.Stats/Interpolation.fs +++ b/src/FSharp.Stats/Interpolation.fs @@ -186,7 +186,7 @@ module Interpolation = pown xData.[i] j ) let b = yData - PolynomialCoef.Create (LinearAlgebra.SolveLinearSystem A b) + PolynomialCoef.Create (LinearAlgebra.solveLinearSystem A b) /// /// takes polynomial coefficients and x value to predict the corresponding interpolating y value @@ -1050,11 +1050,11 @@ module Interpolation = /// Contains x data, y data (c0), slopes (c1), curvatures (c2), and the third derivative at each knot /// type CubicSplineCoef = { - XData : vector + XData : Vector /// /// vector of [a0;b0;c0;d0;a1;b1;...;d(n-2)] where f_n(x) = (an)x^3 + (bn)x^2 + (cn)x + (dn) /// - C0_3 : vector} with + C0_3 : Vector} with static member Create x c = {XData=x;C0_3=c} /// @@ -1160,11 +1160,11 @@ module Interpolation = let (xVal,yVal) = let indices = xValues - |> Seq.indexed - |> Seq.sortBy snd - |> Seq.map fst - let sortedXValues = indices |> Seq.map (fun i -> xValues.[i]) |> vector - let sortedYValues = indices |> Seq.map (fun i -> yValues.[i]) |> vector + |> Array.indexed + |> Array.sortBy snd + |> Array.map fst + let sortedXValues = indices |> Array.map (fun i -> xValues.[i]) + let sortedYValues = indices |> Array.map (fun i -> yValues.[i]) sortedXValues,sortedYValues let intervalNumber = xVal.Length - 1 @@ -1194,12 +1194,12 @@ module Interpolation = let (xVal,yVal,c1) = let indices = xValues - |> Seq.indexed - |> Seq.sortBy snd - |> Seq.map fst - let sortedXValues = indices |> Seq.map (fun i -> xValues.[i]) |> vector - let sortedYValues = indices |> Seq.map (fun i -> yValues.[i]) |> vector - let sortedslopes = indices |> Seq.map (fun i -> slopes.[i]) |> vector + |> Array.indexed + |> Array.sortBy snd + |> Array.map fst + let sortedXValues = indices |> Array.map (fun i -> xValues.[i]) + let sortedYValues = indices |> Array.map (fun i -> yValues.[i]) + let sortedslopes = indices |> Array.map (fun i -> slopes.[i]) sortedXValues,sortedYValues,sortedslopes let intervalNumber = xVal.Length - 1 @@ -1232,11 +1232,11 @@ module Interpolation = let (xVal,yVal) = let indices = xValues - |> Seq.indexed - |> Seq.sortBy snd - |> Seq.map fst - let sortedXValues = indices |> Seq.map (fun i -> xValues.[i]) |> vector - let sortedYValues = indices |> Seq.map (fun i -> yValues.[i]) |> vector + |> Array.indexed + |> Array.sortBy snd + |> Array.map fst + let sortedXValues = indices |> Array.map (fun i -> xValues.[i]) + let sortedYValues = indices |> Array.map (fun i -> yValues.[i]) sortedXValues,sortedYValues let intervalNumber = xVal.Length - 1 @@ -1267,12 +1267,12 @@ module Interpolation = let (xVal,yVal,c2) = let indices = xValues - |> Seq.indexed - |> Seq.sortBy snd - |> Seq.map fst - let sortedXValues = indices |> Seq.map (fun i -> xValues.[i]) |> vector - let sortedYValues = indices |> Seq.map (fun i -> yValues.[i]) |> vector - let sortedslopes = indices |> Seq.map (fun i -> curvature.[i]) |> vector + |> Array.indexed + |> Array.sortBy snd + |> Array.map fst + let sortedXValues = indices |> Array.map (fun i -> xValues.[i]) + let sortedYValues = indices |> Array.map (fun i -> yValues.[i]) + let sortedslopes = indices |> Array.map (fun i -> curvature.[i]) sortedXValues,sortedYValues,sortedslopes let intervalNumber = xVal.Length - 1 @@ -1303,11 +1303,11 @@ module Interpolation = let (xVal,yVal) = let indices = xValues - |> Seq.indexed - |> Seq.sortBy snd - |> Seq.map fst - let sortedXValues = indices |> Seq.map (fun i -> xValues.[i]) |> vector - let sortedYValues = indices |> Seq.map (fun i -> yValues.[i]) |> vector + |> Array.indexed + |> Array.sortBy snd + |> Array.map fst + let sortedXValues = indices |> Array.map (fun i -> xValues.[i]) + let sortedYValues = indices |> Array.map (fun i -> yValues.[i]) sortedXValues,sortedYValues let intervalNumber = xVal.Length - 1 @@ -1331,43 +1331,43 @@ module Interpolation = /// /// Interpolates x and y coordinates with given slopes at the knots. Curvature cannot be set anymore /// - let interpolateWithSlopes (x: vector) (y: vector) (slopes: vector) = + let interpolateWithSlopes (x: Vector) (y: Vector) (slopes: Vector) = let x',y',s' = - let order = x |> Seq.indexed |> Seq.sortBy snd |> Seq.map fst + let order = x |> Array.indexed |> Array.sortBy snd |> Array.map fst let l = Seq.length order - Vector.init l (fun i -> x.[order |> Seq.item i]), - Vector.init l (fun i -> y.[order |> Seq.item i]), - Vector.init l (fun i -> slopes.[order |> Seq.item i]) + Vector.init l (fun i -> x.[order[i]]), + Vector.init l (fun i -> y.[order[i]]), + Vector.init l (fun i -> slopes.[order[i]]) let interpol,i = getInterpolatingConstraints x' y' let slopes,s = getFstDerivativeConstraints x' y' s' let (equations,solutions) = [|interpol;slopes|] |> Array.concat, [|i;s|] |> Array.concat let A = Matrix.ofJaggedArray equations - let b = Vector.ofArray solutions + let b = solutions - let coeffs = Algebra.LinearAlgebra.SolveLinearSystem A b + let coeffs = Algebra.LinearAlgebra.solveLinearSystem A b CubicSplineCoef.Create x coeffs /// /// Interpolates x and y coordinates with given slopes at the knots. Probably makes no sense because slope isnt continuous anymore /// - let interpolateWithCurvature (x: vector) (y: vector) (curvatures: vector) = + let interpolateWithCurvature (x: Vector) (y: Vector) (curvatures: Vector) = let x',y',c' = - let order = x |> Seq.indexed |> Seq.sortBy snd |> Seq.map fst - let l = Seq.length order - Vector.init l (fun i -> x.[order |> Seq.item i]), - Vector.init l (fun i -> y.[order |> Seq.item i]), - Vector.init l (fun i -> curvatures.[order |> Seq.item i]) + let order = x |> Array.indexed |> Array.sortBy snd |> Array.map fst + let l = Array.length order + Vector.init l (fun i -> x.[order[i]]), + Vector.init l (fun i -> y.[order[i]]), + Vector.init l (fun i -> curvatures.[order[i]]) let interpol,i = getInterpolatingConstraints x' y' let curv,c = getSndDerivativeConstraints x' y' c' let (equations,solutions) = [|interpol;curv|] |> Array.concat, [|i;c|] |> Array.concat let A = Matrix.ofJaggedArray equations - let b = Vector.ofArray solutions + let b = solutions - let coeffs = Algebra.LinearAlgebra.SolveLinearSystem A b + let coeffs = Algebra.LinearAlgebra.solveLinearSystem A b CubicSplineCoef.Create x coeffs /// @@ -1566,9 +1566,9 @@ module Interpolation = |> Array.unzip let A = Matrix.ofJaggedArray equations - let b = Vector.ofArray solutions + let b = solutions - let coeffs = Algebra.LinearAlgebra.SolveLinearSystem A b + let coeffs = Algebra.LinearAlgebra.solveLinearSystem A b CubicSplineCoef.Create xVal coeffs @@ -1753,11 +1753,11 @@ module Interpolation = type HermiteCoef = { /// sample points, sorted ascending - XValues : vector + XValues : Vector /// Zero order spline coefficients, intersects, y values - YValues : vector + YValues : Vector /// First order spline coefficients, slopes at knots - Slopes : vector + Slopes : Vector } with static member Create xValues yValues slopes = { XValues=xValues;YValues=yValues;Slopes=slopes @@ -1822,7 +1822,7 @@ module Interpolation = | t when x <= first -> calculate 0 x | _ -> let i = - match Array.tryFindIndexBack (fun xs -> xs <= x) (this.XValues |> Vector.toArray) with + match Array.tryFindIndexBack (fun xs -> xs <= x) (this.XValues) with | Some x -> x | None -> failwith "The given xValue is out of the range defined in xData" calculate i x @@ -1965,11 +1965,11 @@ module Interpolation = let (xVal,yVal) = let order = xData - |> Seq.indexed - |> Seq.sortBy snd - |> Seq.map fst - Vector.init xData.Length (fun i -> xData.[Seq.item i order]), - Vector.init xData.Length (fun i -> yData.[Seq.item i order]) + |> Array.indexed + |> Array.sortBy snd + |> Array.map fst + Vector.init xData.Length (fun i -> xData.[Array.item i order]), + Vector.init xData.Length (fun i -> yData.[Array.item i order]) let calcSlope i = let s1 = (xVal.[i+1] - xVal.[i]) / (yVal.[i+1] - yVal.[i]) @@ -1995,8 +1995,8 @@ module Interpolation = let slope = s1 - s2 slope - let slopes = loop 1 [slopeAtFstKnot] - HermiteCoef.Create xVal yVal (slopes |> vector) + let slopes = (loop 1 [slopeAtFstKnot]) |> Array.ofList + HermiteCoef.Create xVal yVal slopes /// @@ -2069,7 +2069,7 @@ module Interpolation = slope let slopes = loop 1 [slopeAtFstKnot] - slopes |> vector + slopes |> Array.ofList [] module Simple = @@ -2138,15 +2138,15 @@ module Interpolation = /// Bezier interpolates data between 2 points using a number of control points, which determine the degree of the interpolated curve. /// module Bezier = - let inline lerp (p1: vector) (p2: vector) (t: float) = - p1 + t * (p2 - p1) + let inline lerp (p1: Vector) (p2: Vector) (t: float) = + p1 .+ t .* (p2 .- p1) /// /// This implements Bezier interpolation using De Casteljau's algorithm. /// /// an array containg the starting point, the control points, and the end point to use for interpolation /// The generated interpolation function - let interpolate (values: vector []): (float -> vector) = + let interpolate (values: Vector []): (float -> Vector) = if values.Length < 2 then invalidArg (nameof values) "There must be at least 2 points" fun t -> let results = Array.copy values @@ -2219,7 +2219,7 @@ module Interpolation = center + halfrange * cos(Math.PI * (2. * (float i + 1.) - 1.)/(2. * float n)) ) |> Array.sort - |> vector + /// /// Creates a collection of ordered x values within a given interval. The spacing of the values is always the same. @@ -2247,11 +2247,11 @@ module Interpolation = match spacing with | Approximation.Equally -> let xVal = Approximation.equalNodes i n - let yVal = Vector.map f xVal + let yVal = Array.map f xVal Polynomial.interpolate xVal yVal | Approximation.Chebyshev -> let xVal = Approximation.chebyshevNodes i n - let yVal = Vector.map f xVal + let yVal = Array.map f xVal Polynomial.interpolate xVal yVal /// @@ -2270,14 +2270,14 @@ module Interpolation = let linearSplineCoeff = LinearSpline.interpolate (Array.ofSeq xData) (Array.ofSeq yData) let f = LinearSpline.predict linearSplineCoeff let xVal = Approximation.equalNodes i n - let yVal = Vector.map f xVal + let yVal = Array.map f xVal Polynomial.interpolate xVal yVal | Approximation.Chebyshev -> let i = Interval.ofSeq xData let linearSplineCoeff = LinearSpline.interpolate (Array.ofSeq xData) (Array.ofSeq yData) let f = LinearSpline.predict linearSplineCoeff let xVal = Approximation.chebyshevNodes i n - let yVal = Vector.map f xVal + let yVal = Array.map f xVal Polynomial.interpolate xVal yVal //open FSharp.Stats @@ -2337,7 +2337,7 @@ type HermiteMethod = /// Creates a spline from x,y coordinates. x,y coordinates are interpolated by cubic polynomialsbetween two knots. /// The slope at each knot is defined by a input slope vector. /// - | WithSlopes of vector + | WithSlopes of Vector /// /// Creates a spline from x,y coordinates. x,y coordinates are interpolated by cubic polynomials between two knots. /// If a region in the raw data is monotone, the resulting interpolator is monotone as well. @@ -2452,14 +2452,14 @@ type Interpolation() = match method with | InterpolationMethod.Step -> Step.interpolate xData yData |> InterpolationCoefficients.StepCoef | InterpolationMethod.LinearSpline -> LinearSpline.interpolate xData yData |> InterpolationCoefficients.LinearSplineCoef - | InterpolationMethod.Polynomial -> Polynomial.interpolate (vector xData) (vector yData) |> InterpolationCoefficients.PolynomialCoef - | InterpolationMethod.CubicSpline bc -> CubicSpline.interpolate bc (vector xData) (vector yData) |> InterpolationCoefficients.CubicSplineCoef + | InterpolationMethod.Polynomial -> Polynomial.interpolate xData yData |> InterpolationCoefficients.PolynomialCoef + | InterpolationMethod.CubicSpline bc -> CubicSpline.interpolate bc xData yData |> InterpolationCoefficients.CubicSplineCoef | InterpolationMethod.AkimaSubSpline -> Akima.interpolate xData yData |> InterpolationCoefficients.AkimaSubSplineCoef | InterpolationMethod.HermiteSpline s -> match s with - | HermiteMethod.CSpline -> CubicSpline.Hermite.interpolate (vector xData) (vector yData) |> InterpolationCoefficients.HermiteSplineCoef - | HermiteMethod.WithSlopes s -> CubicSpline.Hermite.interpolateWithSlopes (vector xData) (vector yData) s |> InterpolationCoefficients.HermiteSplineCoef - | HermiteMethod.PreserveMonotonicity -> CubicSpline.Hermite.interpolatePreserveMonotonicity (vector xData) (vector yData) |> InterpolationCoefficients.HermiteSplineCoef + | HermiteMethod.CSpline -> CubicSpline.Hermite.interpolate xData yData |> InterpolationCoefficients.HermiteSplineCoef + | HermiteMethod.WithSlopes s -> CubicSpline.Hermite.interpolateWithSlopes xData yData s |> InterpolationCoefficients.HermiteSplineCoef + | HermiteMethod.PreserveMonotonicity -> CubicSpline.Hermite.interpolatePreserveMonotonicity xData yData |> InterpolationCoefficients.HermiteSplineCoef interpolate method xValues yValues /// From 1681143ca4211f9e789025de743495f15a73f1e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20M=C3=BChlhaus?= Date: Wed, 9 Apr 2025 14:46:36 +0200 Subject: [PATCH 063/121] Updated savitzkyGolay --- src/FSharp.Stats/Signal/Filtering.fs | 158 +++++++++++++++++---------- 1 file changed, 98 insertions(+), 60 deletions(-) diff --git a/src/FSharp.Stats/Signal/Filtering.fs b/src/FSharp.Stats/Signal/Filtering.fs index ca337e139..353f4587b 100644 --- a/src/FSharp.Stats/Signal/Filtering.fs +++ b/src/FSharp.Stats/Signal/Filtering.fs @@ -2,7 +2,7 @@ open System open FSharp.Stats - +open FSharp.Stats.Algebra module Filtering = @@ -38,67 +38,105 @@ module Filtering = // let chebeshevFilter = // 0 - - - - /// Smooth (and optionally differentiate) data with a Savitzky-Golay filter.
The Savitzky-Golay filter is a type of low-pass filter and removes high frequency noise from data. - // Parameters - // ---------- - // data : array_like, shape (N,) - // the values of the time history of the signal. - // windowSize : int - // the length of the window. Must be an odd integer number. - // order : int - // the order of the polynomial used in the filtering. - // Must be less then `windowSize` - 1. - // deriv: int - // the order of the derivative to compute (default = 0 means only smoothing) - // - // The Savitzky-Golay is a type of low-pass filter, particularly suited for smoothing noisy data. - // The main idea behind this approach is to make for each point a least-square fit with a - // polynomial of high order over a odd-sized window centered at the point. - let savitzkyGolay (windowSize:int) (order:int) deriv rate (data:float[]) = - /// - let correlateValid (x:Vector) (y:Vector) = - if x.Length >= y.Length then - [|Vector.dot x y|] - else - let n = x.Length - [|for i=1 to y.Length-n do - yield Vector.dot x y.[i..i+n-1] |] - - + /// + /// "Valid" cross-correlation of a kernel with a signal . + /// Returns an array of length (signal.Length - kernel.Length + 1) if signal.Length >= kernel.Length, + /// otherwise a single dot product if kernel.Length > signal.Length. + /// + /// Vector of length K (FIR filter, etc.). + /// Vector of length N. + /// + /// An array of length max(1, N-K+1) with the "valid" correlation result. Typically used for FIR filtering. + /// + let correlateValid (kernel: Vector) (signal: Vector) : float[] = + let kLen = kernel.Length + let sLen = signal.Length + + if sLen < kLen then + // The original code returned a single dot if kernel longer than signal + [| Vector.dotProduct kernel signal |] + else + // We produce sLen - kLen + 1 outputs + let outLen = sLen - kLen + 1 + Array.init outLen (fun i -> + // dot kernel with signal[i.. i+kLen-1] + Vector.dotProduct kernel signal.[i .. i + kLen - 1] + ) + + + /// + /// Smooth (or differentiate) data with a Savitzky–Golay filter of given + /// and polynomial . The parameter specifies the + /// derivative order to compute (0 = smoothing only). The helps scale the + /// derivative if deriv > 0. + /// + /// Must be odd and at least (order+2) if deriving. + /// Polynomial order (must be >= deriv). A higher order can better fit curvature. + /// Order of derivative to compute (0 => smoothing). + /// Scaling factor for derivative, typically sampling rate = 1.0 if no special scale needed. + /// The data vector to filter (length N). + /// + /// A float[] array with the filtered (or derived) signal, of length = data.Length. + /// + let savitzkyGolay (windowSize:int) (order:int) (deriv:int) (rate:float) (data: Vector) : float[] = + // 0) Validate parameters if windowSize % 2 <> 1 || windowSize < 1 then - failwith "windowSize size must be a positive odd number" + failwith "windowSize must be a positive odd integer." if order < deriv then - failwith "order must be greater or equal to the used derivative" + failwith "Polynomial order must be >= derivative order." if windowSize < order + 2 then - failwith "windowSize is too small for the polynomials order" - //let orderRange = [0..order] + failwithf "windowSize (%d) is too small for polynomial order (%d)." windowSize order + + let n = data.Length + if n < windowSize then + failwithf "Data length (%d) smaller than windowSize (%d)." n windowSize + + // 1) Precompute "b" matrix of shape (windowSize × (order+1)). + // b[k, col] = (float(k - halfWindow))^(col) let halfWindow = (windowSize - 1) / 2 - // precompute coefficients - let b = Matrix.init (halfWindow*2 + 1) (order+1) (fun k coli -> float(k-halfWindow)**float(coli)) - - let m = (Algebra.LinearAlgebraManaged.pseudoInvers b).Row(deriv) * ((float(rate)**float(deriv)) * SpecialFunctions.Factorial.factorial(deriv)) - //pad the signal at the extremes with values taken from the signal itself - - let firstvals = - let length = halfWindow + 1 - Array.init length (fun i -> - data.[0] - (abs data.[length-i] - data.[0])) - - let lastvals = - Array.init halfWindow (fun i -> - data.[data.Length-1] - (abs data.[data.Length-(2+i)] - data.[data.Length-1]) ) - - let y = - Array.concat [firstvals; data; lastvals;] |> vector - - correlateValid m.Transpose y + let b = + Matrix.init windowSize (order + 1) (fun k col -> + // k goes 0..(windowSize-1), so "center" is k - halfWindow + let x = float (k - halfWindow) + x ** float col + ) + + // 2) Pseudoinverse of b => shape = ((order+1) × windowSize). + // Then we select row(deriv), which is shape (1 × windowSize). + // We'll scale it by (rate^deriv * factorial(deriv)) if derivative is requested. + let bInv = LinearAlgebra.pseudoInvers b + // The row we want is bInv.Row(deriv), which is a 1×windowSize slice -> treat as Vector + let rowDeriv = Matrix.getRow deriv bInv // shape (1, windowSize), but we can interpret as Vector + + // Scale row by factor = rate^deriv * factorial(deriv) + let factor = (rate ** float(deriv)) * float (FSharp.Stats.SpecialFunctions.Factorial.factorial deriv) + let m = factor .* rowDeriv // final FIR coefficients (length = windowSize) + + // 3) Build the padded signal array "y" at both ends to handle "valid" portion + // Pad with a reflection scheme: for the left side, reflect the first part of data; + // for the right side, reflect the last part. + let firstvals = + // halfWindow+1 elements for the left pad + Array.init (halfWindow) (fun i -> + let diff = data.[(halfWindow - i)] - data.[0] + data.[0] - diff + ) + |> Array.rev // ensure the left-most index is for i=0 + + let lastvals = + // halfWindow elements for the right pad + Array.init halfWindow (fun i -> + let diff = data.[n-1] - data.[(n-2 - i)] + data.[n-1] + diff + ) + + let yVec = Array.concat [ firstvals; data; lastvals ] + + // 4) Correlate "m" with padded "y" in "valid" mode, i.e. output length = data.Length + let result = correlateValid m yVec + + result - [] - let savitzky_golay (windowSize:int) (order:int) deriv rate (data:float[]) = - savitzkyGolay windowSize order deriv rate data /// Estimates the autocorrelation at lag 1 of a blank signal (containing only noise). Subsequently, the signal of interest is smoothed
several times by a savitzky golay filter using constant polynomial order and variing windowWidth. For each iteration, the deviation
of the smoothed to the original signal is computed and the autocorrelation at lag 1 of this residual noise is computed. The function returns the optimized
window width yielding a autocorrelation at lag 1 closest to the value computed for the blank signal.
/// Method is based on: https://doi.org/10.1021/ac0600196 @@ -112,15 +150,15 @@ module Filtering = /// /// let optimizeWindowWidth polOrder (windowWidthToTest:int[]) (blankSignal:float[]) (signalOfInterest:float[]) = - let signalOfInterest' = signalOfInterest |> vector - let noiseAutoCorr = Correlation.Vector.autoCorrelation 1 (blankSignal |> vector) + let signalOfInterest' = signalOfInterest + let noiseAutoCorr = Correlation.Vector.autoCorrelation 1 (blankSignal) let filterF w yData = savitzkyGolay w polOrder 0 0 yData let windowWidthToTest' = windowWidthToTest |> Array.filter (fun x -> x%2 <> 0) let optimizedWindowWidth = windowWidthToTest' |> Array.map (fun w -> let smoothedY = filterF w signalOfInterest - let noise = (vector smoothedY) - (signalOfInterest') + let noise = (smoothedY) .- (signalOfInterest') w, Correlation.Vector.autoCorrelation 1 noise ) |> Array.minBy (fun (w,ac) -> (ac - noiseAutoCorr) |> abs ) From 449d66aea1b27659f87f3adaefaa549c9dbff024 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20M=C3=BChlhaus?= Date: Wed, 9 Apr 2025 17:45:52 +0200 Subject: [PATCH 064/121] Normalization needs a revision --- src/FSharp.Stats/Signal/Normalization.fs | 239 +++++++++++------------ 1 file changed, 119 insertions(+), 120 deletions(-) diff --git a/src/FSharp.Stats/Signal/Normalization.fs b/src/FSharp.Stats/Signal/Normalization.fs index 5712150ba..6678980fe 100644 --- a/src/FSharp.Stats/Signal/Normalization.fs +++ b/src/FSharp.Stats/Signal/Normalization.fs @@ -16,10 +16,10 @@ module Normalization = /// /// /// Bortz J., Schuster C., Statistik für Human- und Sozialwissenschaftler, 7 (2010), p. 35 - let zScoreTransformPopulation (yVal:Vector) = + let zScoreTransformPopulation (yVal:Vector) : Vector = let yMean = Seq.mean yVal let std = Seq.stDevPopulation yVal - yVal |> Vector.map (fun x -> (x - yMean) / std) + yVal |> Array.map (fun x -> (x - yMean) / std) /// /// z score normalization/transformation using the sample standard deviation. Rarely used since variance is not equal to 1. @@ -33,135 +33,134 @@ module Normalization = /// /// /// Bortz J., Schuster C., Statistik für Human- und Sozialwissenschaftler, 7 (2010), p. 35 - let zScoreTransform (yVal:Vector) = + let zScoreTransform (yVal:Vector) : Vector = let yMean = Seq.mean yVal let std = Seq.stDev yVal - yVal |> Vector.map (fun x -> (x - yMean) / std) + yVal |> Array.map (fun x -> (x - yMean) / std) /// Summary of the median of ratios (mor) normalization with normed data, determined correctionfactors, and transformation function. type MorResult = { CorrFactors : seq NormedData : Matrix - NormFunction : matrix -> matrix + NormFunction : Matrix -> Matrix } with static member Create cf nd f = {CorrFactors=cf;NormedData=nd;NormFunction=f} - /// - /// Median of ratios normalization As used by Deseq2, see: https://github.com/hbctraining/DGE_workshop/blob/master/lessons/02_DGE_count_normalization.md . - /// Rows are genes, columns are samples - /// - /// The transformation function is applied on all values of the matrix before calculating the normalization factors. - /// data matrix with columns as features (samples,time points) and rows as measured entities (genes,proteins). - /// Normalized data matrix with correction factors and normalization function. - /// - /// - /// // raw data with proteins as rows and samples as columns - /// let myData = Matrix.init 500 5 (fun _ _ -> rnd.NextDouble()) - /// let normedData = Normalization.medianOfRatiosBy (fun x -> ln (x+1)) myData - /// - /// - let medianOfRatiosBy (f: float -> float) (data: Matrix) = - let sampleWiseCorrectionFactors = - data - |> Matrix.mapiRows (fun _ v -> - let v = RowVector.map f v - let geometricMean = Seq.meanGeometric v - RowVector.map (fun s -> s / geometricMean) v - ) - |> Matrix.ofRows - |> Matrix.mapiCols (fun _ v -> Vector.median v) - let normData m = - m - |> Matrix.mapi (fun r c v -> - v / sampleWiseCorrectionFactors.[c] - ) - MorResult.Create sampleWiseCorrectionFactors (normData data) normData + ///// + ///// Median of ratios normalization As used by Deseq2, see: https://github.com/hbctraining/DGE_workshop/blob/master/lessons/02_DGE_count_normalization.md . + ///// Rows are genes, columns are samples + ///// + ///// The transformation function is applied on all values of the matrix before calculating the normalization factors. + ///// data matrix with columns as features (samples,time points) and rows as measured entities (genes,proteins). + ///// Normalized data matrix with correction factors and normalization function. + ///// + ///// + ///// // raw data with proteins as rows and samples as columns + ///// let myData = Matrix.init 500 5 (fun _ _ -> rnd.NextDouble()) + ///// let normedData = Normalization.medianOfRatiosBy (fun x -> ln (x+1)) myData + ///// + ///// + //let medianOfRatiosBy (f: float -> float) (data: Matrix) = + // let sampleWiseCorrectionFactors = + // data + // |> Matrix.mapiRows (fun _ v -> + // let v = Array.map f v + // let geometricMean = Seq.meanGeometric v + // Array.map (fun s -> s / geometricMean) v + // ) + // |> Matrix.mapiCols (fun _ (v:Vector) -> Seq.median v) + // let normData m = + // m + // |> Matrix.mapi (fun r c v -> + // v / sampleWiseCorrectionFactors.[c] + // ) + // MorResult.Create sampleWiseCorrectionFactors (normData data) normData - /// - /// Median of ratios normalization As used by Deseq2, see: https://github.com/hbctraining/DGE_workshop/blob/master/lessons/02_DGE_count_normalization.md . - /// Rows are genes, columns are samples - /// - /// data matrix with columns as features (samples,time points) and rows as measured entities (genes,proteins). - /// Normalized data matrix with correction factors and normalization function. - /// - /// - /// // raw data with proteins as rows and samples as columns - /// let myData = Matrix.init 500 5 (fun _ _ -> rnd.NextDouble()) - /// let normedData = Normalization.medianOfRatios myData - /// - /// - let medianOfRatios (data:Matrix) = - medianOfRatiosBy id data + ///// + ///// Median of ratios normalization As used by Deseq2, see: https://github.com/hbctraining/DGE_workshop/blob/master/lessons/02_DGE_count_normalization.md . + ///// Rows are genes, columns are samples + ///// + ///// data matrix with columns as features (samples,time points) and rows as measured entities (genes,proteins). + ///// Normalized data matrix with correction factors and normalization function. + ///// + ///// + ///// // raw data with proteins as rows and samples as columns + ///// let myData = Matrix.init 500 5 (fun _ _ -> rnd.NextDouble()) + ///// let normedData = Normalization.medianOfRatios myData + ///// + ///// + //let medianOfRatios (data:Matrix) = + // medianOfRatiosBy id data - /// - /// Median of ratios normalization As used by Deseq2, see: https://github.com/hbctraining/DGE_workshop/blob/master/lessons/02_DGE_count_normalization.md . - /// Columns are genes, rows are samples - /// - /// The transformation function is applied on all values of the matrix before calculating the normalization factors. - /// data matrix with columns as measured entities and rows as features (samples,time points) (genes,proteins). - /// Normalized data matrix with correction factors and normalization function. - /// - /// - /// // raw data with proteins as columns and samples as rows - /// let myData = Matrix.init 5 500 (fun _ _ -> rnd.NextDouble()) - /// let normedData = Normalization.medianOfRatiosWideBy (fun x -> ln (x+1)) myData - /// - /// - let medianOfRatiosWideBy (f: float -> float) (data:Matrix) = - let sampleWiseCorrectionFactors = - data - |> Matrix.mapiCols (fun _ v -> - let v = Vector.map f v - let geometricMean = Seq.meanGeometric v - Vector.map (fun s -> s / geometricMean) v - ) - |> Matrix.ofCols - |> Matrix.mapiRows (fun _ v -> Seq.median v) - let normData m = - m - |> Matrix.mapi (fun r c v -> - v / sampleWiseCorrectionFactors.[r] - ) - MorResult.Create sampleWiseCorrectionFactors (normData data) normData + ///// + ///// Median of ratios normalization As used by Deseq2, see: https://github.com/hbctraining/DGE_workshop/blob/master/lessons/02_DGE_count_normalization.md . + ///// Columns are genes, rows are samples + ///// + ///// The transformation function is applied on all values of the matrix before calculating the normalization factors. + ///// data matrix with columns as measured entities and rows as features (samples,time points) (genes,proteins). + ///// Normalized data matrix with correction factors and normalization function. + ///// + ///// + ///// // raw data with proteins as columns and samples as rows + ///// let myData = Matrix.init 5 500 (fun _ _ -> rnd.NextDouble()) + ///// let normedData = Normalization.medianOfRatiosWideBy (fun x -> ln (x+1)) myData + ///// + ///// + //let medianOfRatiosWideBy (f: float -> float) (data:Matrix) = + // let sampleWiseCorrectionFactors = + // data + // |> Matrix.mapiCols (fun _ v -> + // let v = Vector.map f v + // let geometricMean = Seq.meanGeometric v + // Vector.map (fun s -> s / geometricMean) v + // ) + // |> Matrix.ofCols + // |> Matrix.mapiRows (fun _ v -> Seq.median v) + // let normData m = + // m + // |> Matrix.mapi (fun r c v -> + // v / sampleWiseCorrectionFactors.[r] + // ) + // MorResult.Create sampleWiseCorrectionFactors (normData data) normData - /// - /// Median of ratios normalization As used by Deseq2, see: https://github.com/hbctraining/DGE_workshop/blob/master/lessons/02_DGE_count_normalization.md . - /// Columns are genes, rows are samples - /// - /// data matrix with columns as measured entities and rows as features (samples,time points) (genes,proteins). - /// Normalized data matrix with correction factors and normalization function. - /// - /// - /// // raw data with proteins as columns and samples as rows - /// let myData = Matrix.init 5 500 (fun _ _ -> rnd.NextDouble()) - /// let normedData = Normalization.medianOfRatiosWide myData - /// - /// - let medianOfRatiosWide (data:Matrix) = - medianOfRatiosWideBy id data + ///// + ///// Median of ratios normalization As used by Deseq2, see: https://github.com/hbctraining/DGE_workshop/blob/master/lessons/02_DGE_count_normalization.md . + ///// Columns are genes, rows are samples + ///// + ///// data matrix with columns as measured entities and rows as features (samples,time points) (genes,proteins). + ///// Normalized data matrix with correction factors and normalization function. + ///// + ///// + ///// // raw data with proteins as columns and samples as rows + ///// let myData = Matrix.init 5 500 (fun _ _ -> rnd.NextDouble()) + ///// let normedData = Normalization.medianOfRatiosWide myData + ///// + ///// + //let medianOfRatiosWide (data:Matrix) = + // medianOfRatiosWideBy id data - /// - /// Quantile normalization with equal number of elements (rows) for each sample (column). - /// Column mean and column standard deviation are qual after normalization. - /// Rows are genes, columns are samples. - /// - /// data matrix with columns as measured entities and rows as features (samples,time points) (genes,proteins). - /// Normalized data matrix. - /// - /// - /// // raw data with proteins as rows and samples as columns - /// let myData = Matrix.init 500 5 (fun _ _ -> rnd.NextDouble()) - /// let normedData = Normalization.quantile myData - /// - /// - let quantile (data:Matrix) = - data - |> Matrix.mapCols (Seq.indexed >> Seq.sortBy snd) - |> Matrix.Generic.ofColSeq - |> Matrix.Generic.mapRows (fun row -> - let avg = Seq.meanBy snd row - row |> RowVector.Generic.map (fun (i,_) -> i,avg) - ) - |> Matrix.Generic.ofSeq - |> Matrix.Generic.mapCols (Seq.sortBy fst >> Seq.map snd >> vector) - |> Matrix.ofCols + ///// + ///// Quantile normalization with equal number of elements (rows) for each sample (column). + ///// Column mean and column standard deviation are qual after normalization. + ///// Rows are genes, columns are samples. + ///// + ///// data matrix with columns as measured entities and rows as features (samples,time points) (genes,proteins). + ///// Normalized data matrix. + ///// + ///// + ///// // raw data with proteins as rows and samples as columns + ///// let myData = Matrix.init 500 5 (fun _ _ -> rnd.NextDouble()) + ///// let normedData = Normalization.quantile myData + ///// + ///// + //let quantile (data:Matrix) = + // data + // |> Matrix.mapCols (Seq.indexed >> Seq.sortBy snd) + // |> Matrix.Generic.ofColSeq + // |> Matrix.Generic.mapRows (fun row -> + // let avg = Seq.meanBy snd row + // row |> RowVector.Generic.map (fun (i,_) -> i,avg) + // ) + // |> Matrix.Generic.ofSeq + // |> Matrix.Generic.mapCols (Seq.sortBy fst >> Seq.map snd >> vector) + // |> Matrix.ofCols From 79022bd9c3c1ca0e7434918799ca86bc1b20d851 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20M=C3=BChlhaus?= Date: Wed, 9 Apr 2025 17:49:19 +0200 Subject: [PATCH 065/121] Integrate in Signal --- src/FSharp.Stats/AlgTypes/MatrixExt.fs | 26 +++++++- src/FSharp.Stats/FSharp.Stats.fsproj | 29 +++------ src/FSharp.Stats/Signal/Baseline.fs | 62 +++++++++---------- src/FSharp.Stats/Signal/Convolution.fs | 2 +- src/FSharp.Stats/Signal/Outliers.fs | 84 +++++++++++++------------- src/FSharp.Stats/Signal/QQPlot.fs | 19 +++--- 6 files changed, 117 insertions(+), 105 deletions(-) diff --git a/src/FSharp.Stats/AlgTypes/MatrixExt.fs b/src/FSharp.Stats/AlgTypes/MatrixExt.fs index bf0acce03..aa3f95959 100644 --- a/src/FSharp.Stats/AlgTypes/MatrixExt.fs +++ b/src/FSharp.Stats/AlgTypes/MatrixExt.fs @@ -105,4 +105,28 @@ module Matrix = let srcRow = P i // Copy row srcRow from M into row i of the new matrix Array.blit M.Data (srcRow * c) newData (i * c) c - Matrix<'T>(r, c, newData) \ No newline at end of file + Matrix<'T>(r, c, newData) + + let ofRows (rows : 'T[][]) : Matrix<'T> = + Matrix.ofJaggedArray rows + + let mapiRows (f: int -> Vector<'T> -> Vector<'U>) (m:Matrix<'T>) : Matrix<'U> = + Matrix.getRows m + |> Array.mapi (fun i v -> f i v) + |> ofRows + + let ofCols (cols : 'T[][]) : Matrix<'T> = + Matrix.ofJaggedArray cols + |> fun m -> m.Transpose() + + let mapiCols (f: int -> Vector<'T> -> Vector<'U>) (m:Matrix<'T>) : Matrix<'U> = + let cols = + Array.init m.NumCols (fun j -> + let col = Array.zeroCreate<'T> m.NumRows + let mutable offset = j + for i = 0 to m.NumRows - 1 do + col.[i] <- m.Data.[offset] + offset <- offset + m.NumCols + f j col + ) + ofCols cols \ No newline at end of file diff --git a/src/FSharp.Stats/FSharp.Stats.fsproj b/src/FSharp.Stats/FSharp.Stats.fsproj index c0ee4e4f2..7565d7d93 100644 --- a/src/FSharp.Stats/FSharp.Stats.fsproj +++ b/src/FSharp.Stats/FSharp.Stats.fsproj @@ -28,29 +28,27 @@ + + + + + + + + - - - - - - - - - - @@ -64,16 +62,10 @@ + - - - - - - - @@ -152,15 +144,12 @@ - - - diff --git a/src/FSharp.Stats/Signal/Baseline.fs b/src/FSharp.Stats/Signal/Baseline.fs index 627cb8e49..cbdef104b 100644 --- a/src/FSharp.Stats/Signal/Baseline.fs +++ b/src/FSharp.Stats/Signal/Baseline.fs @@ -53,60 +53,60 @@ module Baseline = let baselineAls (maxiter:int) (lambda:int) (p:float) (data:float[]) = let dMatrix' = let dMatrix = Matrix.ofArray2D (diff 2 (diag data.Length 1.)) - (pown 10. lambda) * (dMatrix * dMatrix.Transpose) + (pown 10. lambda) * (dMatrix * dMatrix.Transpose()) - let wInitial = Vector.create (data.Length) 1. - let y = Vector.ofArray data + let wInitial = Array.create (data.Length) 1. + let y = data let rec loop niter (w:Vector) = if niter < 1 then - let wMatrix = Matrix.diag w + let wMatrix = Matrix.diagonal w let zMatrix = wMatrix + dMatrix' - Algebra.LinearAlgebra.SolveLinearSystem zMatrix (w .* y) + Algebra.LinearAlgebra.solveLinearSystem zMatrix (w .* y) //zMatrix.Solve(w .* y) else - let wMatrix = Matrix.diag w + let wMatrix = Matrix.diagonal w let zMatrix = wMatrix + dMatrix' //let z = zMatrix.Solve(w .* y) - let z = Algebra.LinearAlgebra.SolveLinearSystem zMatrix (w .* y) + let z = Algebra.LinearAlgebra.solveLinearSystem zMatrix (w .* y) // w = p * (y > z) + (1-p) * (y < z) - let w' = Vector.map2 (fun yi zi -> if yi > zi then p else (1.-p)) y z + let w' = Array.map2 (fun yi zi -> if yi > zi then p else (1.-p)) y z loop (niter-1) w' loop maxiter wInitial - /// Asymmetric Least Squares Smoothing using sparse Matrix - // by P. Eilers and H. Boelens in 2005 - let baselineAls' (maxiter:int) (lambda:int) (p:float) (data:float[]) = - let dMatrix' = - let dMatrix = - (diff 2 (diag data.Length 1.)) - |> Matrix.sparseOfArray2D - (10.**float lambda) * (dMatrix * dMatrix.Transpose) + ///// Asymmetric Least Squares Smoothing using sparse Matrix + //// by P. Eilers and H. Boelens in 2005 + //let baselineAls' (maxiter:int) (lambda:int) (p:float) (data:float[]) = + // let dMatrix' = + // let dMatrix = + // (diff 2 (diag data.Length 1.)) + // |> Matrix.sparseOfArray2D + // (10.**float lambda) * (dMatrix * dMatrix.Transpose) - let wInitial = Vector.create (data.Length) 1. - let y = Vector.ofArray data + // let wInitial = Vector.create (data.Length) 1. + // let y = Vector.ofArray data - let rec loop niter (w:Vector) = - if niter < 1 then - let wMatrix = Matrix.toSparse (Matrix.diag w) - let zMatrix = wMatrix + dMatrix' + // let rec loop niter (w:Vector) = + // if niter < 1 then + // let wMatrix = Matrix.toSparse (Matrix.diag w) + // let zMatrix = wMatrix + dMatrix' - FSharp.Stats.Algebra.LinearAlgebraManaged.leastSquares zMatrix (w .* y) - else - let wMatrix = Matrix.toSparse (Matrix.diag w) - let zMatrix = wMatrix + dMatrix' - let z = FSharp.Stats.Algebra.LinearAlgebraManaged.leastSquares zMatrix (w .* y) - // w = p * (y > z) + (1-p) * (y < z) - let w' = Vector.map2 (fun yi zi -> if yi > zi then p else (1.-p)) y z + // FSharp.Stats.Algebra.LinearAlgebraManaged.leastSquares zMatrix (w .* y) + // else + // let wMatrix = Matrix.toSparse (Matrix.diag w) + // let zMatrix = wMatrix + dMatrix' + // let z = FSharp.Stats.Algebra.LinearAlgebraManaged.leastSquares zMatrix (w .* y) + // // w = p * (y > z) + (1-p) * (y < z) + // let w' = Vector.map2 (fun yi zi -> if yi > zi then p else (1.-p)) y z - loop (niter-1) w' + // loop (niter-1) w' - loop maxiter wInitial + // loop maxiter wInitial diff --git a/src/FSharp.Stats/Signal/Convolution.fs b/src/FSharp.Stats/Signal/Convolution.fs index f8aa23e5d..fc1b56fff 100644 --- a/src/FSharp.Stats/Signal/Convolution.fs +++ b/src/FSharp.Stats/Signal/Convolution.fs @@ -15,7 +15,7 @@ module Convolution = /// /// /// - let convolve (v1:vector) (v2:vector) = + let convolve (v1:Vector<'T>) (v2:Vector<'T>) = let k = (v1.Length+v2.Length-1) let tmp = Vector.zeroCreate k for i = 0 to v1.Length-1 do diff --git a/src/FSharp.Stats/Signal/Outliers.fs b/src/FSharp.Stats/Signal/Outliers.fs index a209ceed5..5dda0ff2f 100644 --- a/src/FSharp.Stats/Signal/Outliers.fs +++ b/src/FSharp.Stats/Signal/Outliers.fs @@ -91,46 +91,46 @@ module Outliers = let s = Seq.stDev(ls) Interval.CreateClosed ((minZ * s + m),(maxZ * s + m)) - ///Returns Mahalanobi's distance for an individual observation in a matrix. - ///dataSource - Sample or Population. - /// orientation - RowWise or ColWise. - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - let mahalanobisDistanceOfEntry (dataMatrix:matrix) (dataSource:DataSource) (orientation:Orientation) (observation:seq) :float = - let sub (a:seq) b = Seq.map2 (fun xa xb -> xb - xa) a b - let invertedCovarianceMatrix = Algebra.LinearAlgebra.Inverse (covarianceMatrixOf dataSource orientation.Inverse dataMatrix) - let meanVector = Matrix.meanAsSeq orientation.Inverse dataMatrix - let subObsMean = Matrix.ofJaggedColSeq([sub observation meanVector]) - let multObsCov = Matrix.mul (subObsMean.Transpose) invertedCovarianceMatrix - let distance = Matrix.toScalar(Matrix.mul multObsCov subObsMean) - sqrt distance + /////Returns Mahalanobi's distance for an individual observation in a matrix. + /////dataSource - Sample or Population. + ///// orientation - RowWise or ColWise. + ///// + ///// + ///// + ///// + ///// + ///// + ///// + ///// + ///// + ///// + //let mahalanobisDistanceOfEntry (dataMatrix:Matrix) (dataSource:DataSource) (orientation:Orientation) (observation:seq) :float = + // let sub (a:seq) b = Seq.map2 (fun xa xb -> xb - xa) a b + // let invertedCovarianceMatrix = Algebra.LinearAlgebra.Inverse (covarianceMatrixOf dataSource orientation.Inverse dataMatrix) + // let meanVector = Matrix.meanAsSeq orientation.Inverse dataMatrix + // let subObsMean = Matrix.ofJaggedColSeq([sub observation meanVector]) + // let multObsCov = Matrix.mul (subObsMean.Transpose) invertedCovarianceMatrix + // let distance = Matrix.toScalar(Matrix.mul multObsCov subObsMean) + // sqrt distance - ///Returns Mahalanobi's distance for for every observation in a matrix. - ///dataSource - Sample or Population. - /// orientation - RowWise or ColWise. (RowWise orientation means that each row is a Vector) - /// - /// - /// - /// - /// - /// - /// - /// - /// - let mahalanobisDistances (dataSource:DataSource) (orientation:Orientation) (dataMatrix:matrix) = - let getObsList = - match orientation with - |ColWise -> - dataMatrix.Transpose - |> Matrix.toJaggedArray - |RowWise -> - dataMatrix |> Matrix.toJaggedArray - getObsList |> Array.map (mahalanobisDistanceOfEntry dataMatrix dataSource orientation) \ No newline at end of file + /////Returns Mahalanobi's distance for for every observation in a matrix. + /////dataSource - Sample or Population. + ///// orientation - RowWise or ColWise. (RowWise orientation means that each row is a Vector) + ///// + ///// + ///// + ///// + ///// + ///// + ///// + ///// + ///// + //let mahalanobisDistances (dataSource:DataSource) (orientation:Orientation) (dataMatrix:Matrix) = + // let getObsList = + // match orientation with + // |ColWise -> + // dataMatrix.Transpose + // |> Matrix.toJaggedArray + // |RowWise -> + // dataMatrix |> Matrix.toJaggedArray + // getObsList |> Array.map (mahalanobisDistanceOfEntry dataMatrix dataSource orientation) \ No newline at end of file diff --git a/src/FSharp.Stats/Signal/QQPlot.fs b/src/FSharp.Stats/Signal/QQPlot.fs index 679f59809..0014e2c85 100644 --- a/src/FSharp.Stats/Signal/QQPlot.fs +++ b/src/FSharp.Stats/Signal/QQPlot.fs @@ -70,16 +70,15 @@ module QQPlot = /// Computes the quantile quantile coordinates of a sample distributions against a normal distribution. /// The sample can be z transformed. StandardMethod = Rankit // tested against R qqnorm - let internal fromSampleToGauss method zTransformSample (sample:seq) = + let internal fromSampleToGauss method zTransformSample (sample:Vector) = let sampleLength = Seq.length sample |> float let standardizedData = if zTransformSample then - Signal.Normalization.zScoreTransformPopulation (vector sample) - |> Vector.toArray + Signal.Normalization.zScoreTransformPopulation sample else - sample |> Seq.toArray + sample let getQuantile rank = match method with @@ -109,15 +108,15 @@ module QQPlot = /// /// /// - let internal fromSampleToUniform method standardizeSample (sample:seq) = + let internal fromSampleToUniform method standardizeSample (sample:Vector) = let sampleLength = Seq.length sample |> float let standardizedSample = if standardizeSample then - let min = Seq.min sample - let max = Seq.max sample - sample |> Seq.map (fun x -> (x-min) / (max-min)) + let min = Vector.min sample + let max = Vector.max sample + sample |> Array.map (fun x -> (x-min) / (max-min)) else sample @@ -175,7 +174,7 @@ type QQPlot() = let standardize = defaultArg ZTransform false let method = defaultArg Method QQPlot.QuantileMethod.Rankit - fun (sample: seq) -> + fun (sample: Vector) -> QQPlot.fromSampleToGauss method standardize sample /// Computes the quantile quantile coordinates of a sample distributions against a normal distribution. @@ -185,7 +184,7 @@ type QQPlot() = let standardize = defaultArg Standardize false let method = defaultArg Method QQPlot.QuantileMethod.Rankit - fun (sample: seq) -> + fun (sample: Vector) -> QQPlot.fromSampleToUniform method standardize sample /// Computes the quantile quantile coordinates of a sample distributions against a specified inverseCDF function. You can derive an inverse CDF of any statistical distribution. From 5791442e69f00765406ce2fd97f5f6a05942f5ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20M=C3=BChlhaus?= Date: Fri, 11 Apr 2025 08:25:16 +0200 Subject: [PATCH 066/121] Change to Numeric. Compiles but without test! --- src/FSharp.Stats/AlgTypes/Matrix.fs | 59 +++++++++++ src/FSharp.Stats/AlgTypes/MatrixExt.fs | 64 +++++++++++- src/FSharp.Stats/AlgTypes/Vector.fs | 15 ++- src/FSharp.Stats/AlgTypes/VectorExt.fs | 19 +++- src/FSharp.Stats/AlgTypes/VectorOps.fs | 14 ++- src/FSharp.Stats/Algebra/LinearAlgebra.fs | 40 +++++++- src/FSharp.Stats/Correlation.fs | 38 ++++---- .../Continuous/MultivariateNormal.fs | 35 ++++--- .../Distributions/Discrete/Multinomial.fs | 20 ++-- .../Distributions/Distribution.fs | 4 +- src/FSharp.Stats/FSharp.Stats.fsproj | 4 +- src/FSharp.Stats/Fitting/CrossValidation.fs | 2 +- src/FSharp.Stats/Fitting/GoodnessOfFit.fs | 2 +- src/FSharp.Stats/Fitting/LinearRegression.fs | 10 +- .../Fitting/LogisticRegression.fs | 2 +- .../Fitting/NonLinearRegression.fs | 30 +++--- src/FSharp.Stats/Optimization/NelderMead.fs | 37 ++++--- src/FSharp.Stats/Permutation.fs | 16 +++ src/FSharp.Stats/Seq.fs | 10 +- src/FSharp.Stats/Signal/Filtering.fs | 4 +- src/FSharp.Stats/Testing/ConfusionMatrix.fs | 4 +- src/FSharp.Stats/Testing/RMT.fs | 2 +- src/FSharp.Stats/Testing/TTest.fs | 6 +- src/FSharp.Stats/Testing/Tables.fs | 97 +++++++++---------- 24 files changed, 363 insertions(+), 171 deletions(-) diff --git a/src/FSharp.Stats/AlgTypes/Matrix.fs b/src/FSharp.Stats/AlgTypes/Matrix.fs index a960e5b11..ccfd95f57 100644 --- a/src/FSharp.Stats/AlgTypes/Matrix.fs +++ b/src/FSharp.Stats/AlgTypes/Matrix.fs @@ -563,6 +563,64 @@ type Matrix<'T when 'T :> Numerics.INumber<'T> Matrix(m.NumRows, cols, resultData) + + /// + /// Computes row-vector v (length = mat.NumRows) times matrix mat (size = [NumRows × NumCols]), + /// returning a new vector of length mat.NumCols. Uses chunk-based SIMD with manual gather. + /// + static member inline multiplyRowVector<'T + when 'T :> Numerics.INumber<'T> + and 'T : struct + and 'T : (new : unit -> 'T) + and 'T :> ValueType> + (v: Vector<'T>) + (mat: Matrix<'T>) : Vector<'T> = + + let n = mat.NumRows + let m = mat.NumCols + if v.Length <> n then + invalidArg (nameof v) "Vector length must match mat.NumRows." + + let result = Vector.zeroCreate<'T> m + + // We'll chunk over v in blocks of 'simdSize'. For each column j, + // we gather that column's slice [ (i*m + j) for i in 0..n-1 ] in blocks. + let simdSize = Numerics.Vector<'T>.Count + + for j in 0 .. m - 1 do + // sumVec accumulates partial sums in vector-lanes + let mutable sumVec = Numerics.Vector<'T>.Zero + + // 1) Process as many full 'simdSize' blocks as possible + let blockCount = n / simdSize + let tailStart = blockCount * simdSize + + for blockIndex in 0 .. blockCount - 1 do + let baseIdx = blockIndex * simdSize + + // Gather the column’s elements for this block into 'gatherArr' + // These are mat.Data.[(baseIdx + s)*m + j] for s in [0..simdSize-1] + let gatherArr = Vector.zeroCreate<'T> simdSize + for s in 0 .. simdSize - 1 do + gatherArr.[s] <- mat.Data.[(baseIdx + s) * m + j] + + let colVec = Numerics.Vector<'T>(gatherArr) // column-block chunk + let rowVec = Numerics.Vector<'T>(v, baseIdx) // row vector chunk + sumVec <- sumVec + (rowVec * colVec) + + // 2) Reduce sumVec’s lanes into a scalar + let mutable colSum = 'T.Zero + for lane in 0 .. simdSize - 1 do + colSum <- colSum + sumVec.[lane] + + // 3) Handle any leftover elements (remainder) + for i in tailStart .. n - 1 do + colSum <- colSum + v.[i] * mat.Data.[i*m + j] + + result.[j] <- colSum + + result + // Matrix - matrix operations static member inline ( + ) (a: Matrix<'T>, b: Matrix<'T>) = Matrix.add a b static member inline ( - ) (a: Matrix<'T>, b: Matrix<'T>) = Matrix.subtract a b @@ -571,6 +629,7 @@ type Matrix<'T when 'T :> Numerics.INumber<'T> // Matrix - vector operations static member inline ( * ) (m: Matrix<'T>, v: Vector<'T>) = Matrix.muliplyVector m v + static member inline ( * ) (v: Vector<'T>, m: Matrix<'T>) = Matrix.multiplyRowVector v m // static member inline ( + ) (m: Matrix<'T>, colVector: Vector<'T>) = Matrix.addColVector m colVector // static member inline ( +| ) (m: Matrix<'T>, rowVector: Vector<'T>) = Matrix.addRowVector m rowVector diff --git a/src/FSharp.Stats/AlgTypes/MatrixExt.fs b/src/FSharp.Stats/AlgTypes/MatrixExt.fs index aa3f95959..d9cf579a3 100644 --- a/src/FSharp.Stats/AlgTypes/MatrixExt.fs +++ b/src/FSharp.Stats/AlgTypes/MatrixExt.fs @@ -98,13 +98,13 @@ module Matrix = /// /// A new matrix of the same dimensions r x c, with rows permuted by . /// - let permuteRowsBy (P: Permutation) (M: Matrix<'T>) : Matrix<'T> = - let r, c = M.NumRows, M.NumCols + let permuteRowsBy (P: Permutation) (m: Matrix<'T>) : Matrix<'T> = + let r, c = m.NumRows, m.NumCols let newData = Array.zeroCreate<'T> (r * c) for i = 0 to r - 1 do let srcRow = P i // Copy row srcRow from M into row i of the new matrix - Array.blit M.Data (srcRow * c) newData (i * c) c + Array.blit m.Data (srcRow * c) newData (i * c) c Matrix<'T>(r, c, newData) let ofRows (rows : 'T[][]) : Matrix<'T> = @@ -129,4 +129,60 @@ module Matrix = offset <- offset + m.NumCols f j col ) - ofCols cols \ No newline at end of file + ofCols cols + + /// + /// Applies a function to each element of the matrix, + /// returning a new matrix with updated values. The iteration occurs in + /// row-major order for performance. + /// + /// + /// A function taking (rowIndex, colIndex, oldValue) + /// and returning the new value for that position. + /// + /// A new Matrix with updated elements. + let mapi (f: int -> int -> 'T -> 'U) (A: Matrix<'T>) : Matrix<'U> = + let newData = Array.zeroCreate<'U> A.Data.Length + let rows, cols = A.NumRows, A.NumCols + for i in 0 .. rows - 1 do + let rowOffset = i * cols + for j in 0 .. cols - 1 do + let idx = rowOffset + j + newData.[idx] <- f i j A.Data.[idx] + Matrix<'U>(rows, cols, newData) + + + let map (f: 'T -> 'U) (m:Matrix<'T>) : Matrix<'U> = + let r, c = m.NumRows, m.NumCols + let newData = + m.Data |> Array.map f + Matrix<'U>(r, c, newData) + + + /// + /// Folds over each element in row-major order, accumulating a result of type 'State. + /// The callback receives (currentState, rowIndex, colIndex, elementValue), + /// and returns the new state. + /// + /// A function taking (state, i, j, value) -> newState. + /// The initial accumulation state. + /// The matrix to fold over. + /// The final accumulated state. + let foldi + (f : int -> int -> 'State -> 'T -> 'State ) + (initialState : 'State) + (A : Matrix<'T>) + : 'State = + + let mutable acc = initialState + let rows, cols = A.NumRows, A.NumCols + for i in 0 .. rows - 1 do + let rowOffset = i * cols + for j in 0 .. cols - 1 do + let idx = rowOffset + j + acc <- f i j acc A.Data.[idx] + acc + + /// Sums all elements in the matrix. + let sum (m:Matrix<'T>) : 'T = + m.Data |> Vector.sum \ No newline at end of file diff --git a/src/FSharp.Stats/AlgTypes/Vector.fs b/src/FSharp.Stats/AlgTypes/Vector.fs index eba35ac1d..29523787d 100644 --- a/src/FSharp.Stats/AlgTypes/Vector.fs +++ b/src/FSharp.Stats/AlgTypes/Vector.fs @@ -3,10 +3,15 @@ open System open System.Runtime.InteropServices -/// Vector as a Array type alias +/// Vector as an array type alias type Vector<'T when 'T :> Numerics.INumber<'T>> = 'T [] type Vector = + + + static member inline zeroCreate<'T when 'T :> Numerics.INumber<'T>> count : Vector<'T> = + Array.zeroCreate<'T> count + /// Adds two vectors element-wise. /// The first vector. @@ -184,18 +189,18 @@ type Vector = let sum = Vector.sum v LanguagePrimitives.DivideByInt<'T> sum v.Length - /// Computes the dot product of two vectors. + /// Computes the dot product ab^T of two vectors. /// The first vector. /// The second vector. /// The dot product of the two vectors. /// Thrown when the vectors have different lengths. - static member inline dotProduct<'T when 'T :> Numerics.INumber<'T> + static member inline dot<'T when 'T :> Numerics.INumber<'T> and 'T : (new: unit -> 'T) and 'T : struct and 'T :> ValueType> (v1 : Vector<'T>) (v2 : Vector<'T>) : 'T = if v1.Length <> v2.Length then - invalidArg "v2" "Arrays must have the same length." + invalidArg "v2" "Vector must have the same length to compute the dot product." if Numerics.Vector.IsHardwareAccelerated then let length = v1.Length let slotSize = Numerics.Vector<'T>.Count @@ -229,7 +234,7 @@ type Vector = and 'T :> Numerics.IRootFunctions<'T>> (v:Vector<'T>) : 'T = - let sumSquares = Vector.dotProduct v v + let sumSquares = Vector.dot v v 'T.Sqrt sumSquares static member inline min<'T when 'T :> Numerics.INumber<'T> diff --git a/src/FSharp.Stats/AlgTypes/VectorExt.fs b/src/FSharp.Stats/AlgTypes/VectorExt.fs index 3badfca7d..ed6ba70b2 100644 --- a/src/FSharp.Stats/AlgTypes/VectorExt.fs +++ b/src/FSharp.Stats/AlgTypes/VectorExt.fs @@ -6,8 +6,19 @@ open System.Runtime.InteropServices [] module Vector = - let inline zeroCreate<'T when 'T :> Numerics.INumber<'T>> count : Vector<'T> = - Array.zeroCreate<'T> count + /// Computes the vector cross product a^Tb + /// The first vector is column vector. + /// The second vector is the row vector. + /// The cross product of the two vectors. + let inline cross<'T when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T :> ValueType> (colvec: Vector<'T>) (rowvec:Vector<'T>) : Matrix<'T> = + if colvec.Length <> rowvec.Length then + invalidArg "" "Vector must have the same length to compute the dot product." + let data = Acceleration.SIMDUtils.map2Unchecked ( * ) ( * ) colvec rowvec + Matrix(colvec.Length,rowvec.Length,data) + /// Indexed fold over a vector let inline foldi<'T when 'T :> Numerics.INumber<'T>> f (state: 'T) (v: Vector<'T>) : 'T = @@ -145,8 +156,8 @@ module Vector = let n = v.Length let k = indices.Length - let nvi = zeroCreate<'T> k - let nv = zeroCreate<'T> (n - k) + let nvi = Vector.zeroCreate<'T> k + let nv = Vector.zeroCreate<'T> (n - k) let mutable iInd = 0 let mutable iNvi = 0 diff --git a/src/FSharp.Stats/AlgTypes/VectorOps.fs b/src/FSharp.Stats/AlgTypes/VectorOps.fs index 127395a1f..5d338291c 100644 --- a/src/FSharp.Stats/AlgTypes/VectorOps.fs +++ b/src/FSharp.Stats/AlgTypes/VectorOps.fs @@ -35,4 +35,16 @@ module VectorOpsSymbols = let inline (.+) a b = Plus.Invoke(a, b) let inline (.-) a b = Minus.Invoke(a, b) let inline (.*) a b = Multiply.Invoke(a, b) - let inline (./) a b = Divide.Invoke(a, b) \ No newline at end of file + let inline (./) a b = Divide.Invoke(a, b) + + +//// A type extension on `'T[]` so you can do `myArray.Transposed`. +//module ArrayExtensions = + +// type Array with + +// member this.Transpose + +// with get () = +// RowVector<'T>(this) + diff --git a/src/FSharp.Stats/Algebra/LinearAlgebra.fs b/src/FSharp.Stats/Algebra/LinearAlgebra.fs index 9dde6a896..e3cc65a1f 100644 --- a/src/FSharp.Stats/Algebra/LinearAlgebra.fs +++ b/src/FSharp.Stats/Algebra/LinearAlgebra.fs @@ -58,7 +58,7 @@ type LinearAlgebra = for i = 0 to j - 1 do let qi = qCols.[i] - let rij = Vector.dotProduct qi v + let rij = Vector.dot qi v r.[i, j] <- rij for k = 0 to m - 1 do v.[k] <- v.[k] - rij * qi.[k] @@ -629,3 +629,41 @@ type LinearAlgebra = false // Return sᵀ => the actual pseudoinverse shape (n×m) s.Transpose() + + + /// + /// Computes the determinant of a square matrix A by factoring A = P * L * U, + /// then det(A) = sign(P) * ∏ diag(U). + /// (Assumes L has diag=1, as in Doolittle.) + /// + static member inline determinant (A: Matrix) : float = + let n = A.NumRows + if n <> A.NumCols then + invalidArg (nameof A) "Matrix must be square." + + // 1) Factor A => (P, L, U) + let (P, L, U) = LinearAlgebra.luDecompose A + + // 2) Compute sign from the permutation P with domain size n + let permSign = Permutation.sign n P + + // 3) Product of diag(U) + let diagProd = + let mutable product = 1.0 + for i = 0 to n - 1 do + product <- product * U.Data.[i*n + i] + product + + // 4) Return sign(P) * product + permSign * diagProd + + + static member inline SVD (a:Matrix) = + let (umatrix,s,vmatrix) = SVD.computeInPlace (a.toArray2D()) + //Matrix.diag + s,Matrix.ofArray2D umatrix,Matrix.ofArray2D vmatrix + //(Matrix.ofArray2D umatrix,s,Matrix.ofArray2D vmatrix) + + static member inline symmetricEigenspectrum (a:Matrix) = + let (e,v,d) = EVD.symmetricEvd (a.toArray2D()) + (Matrix.ofArray2D v, d) diff --git a/src/FSharp.Stats/Correlation.fs b/src/FSharp.Stats/Correlation.fs index 40c122c5a..7651f1677 100644 --- a/src/FSharp.Stats/Correlation.fs +++ b/src/FSharp.Stats/Correlation.fs @@ -665,7 +665,7 @@ module Correlation = /// /// /// - let correlationOf (corrF: vector -> vector -> float) lag (v1:vector) (v2:vector) = + let correlationOf (corrF: Vector -> Vector -> float) lag (v1:Vector) (v2:Vector) = if v1.Length <> v2.Length then failwithf "Vectors need to have the same length." if lag >= v1.Length then failwithf "lag must be smaller than input length" let v1' = v1.[0..(v1.Length-1 - lag)] @@ -694,7 +694,7 @@ module Correlation = /// /// let autoCovariance lag seq = - correlationOf Vector.cov lag seq seq + correlationOf Array.cov lag seq seq /// computes the normalized (using pearson correlation) cross-correlation of signals v1 and v2 at a given lag. /// @@ -731,9 +731,9 @@ module Correlation = /// /// /// - let bicor (vec1:vector) (vec2:vector) = + let bicor (vec1:Vector) (vec2:Vector) = - let xs,ys = vec1.Values, vec2.Values + let xs,ys = vec1, vec2 let xMed = xs |> Array.median let xMad = xs |> Array.medianAbsoluteDev @@ -764,12 +764,10 @@ module Correlation = /// /// /// - let rv2 (x: matrix) (y: matrix) = - let xxt = x*x.Transpose - let yyt = y*y.Transpose - xxt |> Matrix.inplace_mapi (fun r c x -> if r = c then 0. else x) - yyt |> Matrix.inplace_mapi (fun r c x -> if r = c then 0. else x) - let num = (xxt*yyt).Diagonal |> Vector.sum + let rv2 (x: Matrix) (y: Matrix) = + let xxt = x*x.Transpose() |> Matrix.mapi (fun r c x -> if r = c then 0. else x) // change back to inplace + let yyt = y*y.Transpose() |> Matrix.mapi (fun r c x -> if r = c then 0. else x) + let num = (xxt*yyt) |> Matrix.getDiagonal |> Vector.sum let deno1 = xxt |> Matrix.map (fun x -> x**2.) |> Matrix.sum |> sqrt let deno2 = yyt |> Matrix.map (fun x -> x**2.) |> Matrix.sum |> sqrt num / (deno1 * deno2) @@ -783,15 +781,15 @@ module Correlation = /// /// /// - let rowWiseCorrelationMatrix (corrFunction : seq -> seq -> float) (m : matrix) = - let vectors = Matrix.toJaggedArray m + let rowWiseCorrelationMatrix (corrFunction : seq -> seq -> float) (m : Matrix) = + let vectors = m.toJaggedArray() let result : float [] [] = [|for i=0 to vectors.Length-1 do yield (Array.init vectors.Length (fun innerIndex -> if i=innerIndex then 1. else 0.))|] for i=0 to vectors.Length-1 do for j=i+1 to vectors.Length-1 do let corr = corrFunction vectors.[i] vectors.[j] result.[i].[j] <- corr result.[j].[i] <- corr - result |> matrix + result |> Matrix.ofRows /// computes a matrix that contains the metric given by the corrFunction parameter applied columnwise for every column against every other column of the input matrix /// @@ -803,8 +801,7 @@ module Correlation = /// /// let columnWiseCorrelationMatrix (corrFunction : seq -> seq -> float) (m : Matrix) = - m - |> Matrix.transpose + m.Transpose() |> (rowWiseCorrelationMatrix corrFunction) /// computes the rowwise pearson correlation matrix for the input matrix @@ -839,9 +836,9 @@ module Correlation = /// /// /// - let rowWiseBicor (m : matrix) = + let rowWiseBicor (m : Matrix) = - let vectors = Matrix.toJaggedArray m + let vectors = m.toJaggedArray() let result : float [] [] = [|for i=0 to vectors.Length-1 do yield (Array.init vectors.Length (fun innerIndex -> if i=innerIndex then 1. else 0.))|] let meds : float [] = Array.zeroCreate vectors.Length @@ -869,7 +866,7 @@ module Correlation = xs xWeights vectors.[j] weightss.[j] result.[i].[j] <- corr result.[j].[i] <- corr - result |> matrix + result |> Matrix.ofRows /// Computes the columnwise biweighted midcorrelation matrix for the input matrix /// @@ -879,9 +876,8 @@ module Correlation = /// /// /// - let columnWiseBicor (m : matrix) = - m - |> Matrix.transpose + let columnWiseBicor (m : Matrix) = + m.Transpose() |> rowWiseBicor ///// Computes rowise pearson correlation diff --git a/src/FSharp.Stats/Distributions/Continuous/MultivariateNormal.fs b/src/FSharp.Stats/Distributions/Continuous/MultivariateNormal.fs index 2076d1d03..eba88d822 100644 --- a/src/FSharp.Stats/Distributions/Continuous/MultivariateNormal.fs +++ b/src/FSharp.Stats/Distributions/Continuous/MultivariateNormal.fs @@ -14,50 +14,53 @@ open FSharp.Stats.Ops type MultivariateNormal = // multivariate normal distribution helper functions. - static member CheckParam (mu:vector) (sigma:matrix) = + static member CheckParam (mu:Vector) (sigma:Matrix) = // TODO Implement checkParam for MultivariateNormal if false then failwith "Multivariate normal distribution should be parametrized by " /// Computes the mean. - static member Mean (mu:vector) (sigma:matrix) = + static member Mean (mu:Vector) (sigma:Matrix) = MultivariateNormal.CheckParam mu sigma mu /// Computes the variance. - static member Variance (mu:vector) (sigma:matrix) = + static member Variance (mu:Vector) (sigma:Matrix) = MultivariateNormal.CheckParam mu sigma //sigma*sigma failwith "Not implemented yet." /// Computes the standard deviation. - static member StandardDeviation (mu:vector) (sigma:matrix) = + static member StandardDeviation (mu:Vector) (sigma:Matrix) = MultivariateNormal.CheckParam mu sigma //sigma failwith "Not implemented yet." /// Produces a random sample using the current random number generator (from GetSampleGenerator()). - static member Sample (mu:vector) (sigma:matrix) = - if Vector.length mu = 2 then - let a = Algebra.LinearAlgebra.Cholesky sigma - let z = Random.boxMullerTransform() |> fun (a,b) -> vector [a;b] - mu + a*z + static member Sample (mu:Vector) (sigma:Matrix) = + if Array.length mu = 2 then + let a = Algebra.LinearAlgebra.cholesky sigma + let z = Random.boxMullerTransform() |> fun (a,b) -> [|a;b|] + mu .+ a * z else failwith "Not implemented yet." /// Computes the probability density function. - static member PDF (mu:vector) (sigma:matrix) (x:vector) = + static member PDF (mu:Vector) (sigma:Matrix) (x:Vector) = MultivariateNormal.CheckParam mu sigma let k = Seq.length mu |> float - let ex = Math.Exp(-0.5 * (x - mu).Transpose * (Algebra.LinearAlgebra.Inverse sigma) * (x-mu)) - (2.*Math.PI)**(-k/2.) * (Algebra.LinearAlgebra.Determinant sigma ** (-0.5)) * ex + let tmp = x .- mu + let tmp' = -0.5 .* tmp * (Algebra.LinearAlgebra.inverse sigma) + let ex = Math.Exp(Vector.dot tmp' tmp) + (2.*Math.PI)**(-k/2.) * (Algebra.LinearAlgebra.determinant sigma ** (-0.5)) * ex + /// Computes the cumulative distribution function. - static member CDF (mu:vector) (sigma:matrix) (x:vector) = + static member CDF (mu:Vector) (sigma:Matrix) (x:Vector) = failwith "Not implemented yet." /// Computes the inverse cumulative distribution function (quantile function). - static member InvCDF (mu:vector) (sigma:matrix) (x:vector) = + static member InvCDF (mu:Vector) (sigma:Matrix) (x:Vector) = failwith "InvCDF not implemented yet." /// Initializes a multivariate normal distribution with mean mu and covariance matrix sigma - static member Init (mu:vector) (sigma:matrix) = - { new ContinuousDistribution with + static member Init (mu:Vector) (sigma:Matrix) = + { new ContinuousDistribution,Vector> with member d.Mode = MultivariateNormal.Mean mu sigma member d.Mean = MultivariateNormal.Mean mu sigma member d.StandardDeviation = MultivariateNormal.StandardDeviation mu sigma diff --git a/src/FSharp.Stats/Distributions/Discrete/Multinomial.fs b/src/FSharp.Stats/Distributions/Discrete/Multinomial.fs index 6dbf92cdc..8cc737607 100644 --- a/src/FSharp.Stats/Distributions/Discrete/Multinomial.fs +++ b/src/FSharp.Stats/Distributions/Discrete/Multinomial.fs @@ -12,7 +12,7 @@ open FSharp.Stats.SpecialFunctions type Multinomial = // Multinomial distribution helper functions. - static member CheckParam (p: vector) n = + static member CheckParam (p: Vector) n = if n < 0 then failwith "Multinomial distribution should be parametrized by n >= 0." let checkBetween p = @@ -28,9 +28,9 @@ type Multinomial = /// /// vector of event probabilities in each trial /// number of trails - static member Mean (p: vector) (n: int) = + static member Mean (p: Vector) (n: int) = Multinomial.CheckParam p n - p * float n + p .* float n /// Computes the variance vector /// @@ -44,9 +44,9 @@ type Multinomial = /// /// vector of event probabilities in each trial /// number of trails - static member StandardDeviation p n = + static member StandardDeviation p n : Vector = Multinomial.CheckParam p n - Vector.map sqrt (Multinomial.Variance p n) + Array.map sqrt (Multinomial.Variance p n) /// Produces a random sample using the current random number generator (from GetSampleGenerator()). No parameter checking! /// @@ -88,7 +88,7 @@ type Multinomial = /// // result: 0.118125 /// /// - static member PMF_Unchecked (p: vector) (x: Vector) = + static member PMF_Unchecked (p: Vector) (x: Vector) = //corresponds to function with gamma notation let n = x |> Seq.sum |> int let a = Factorial.factorialLn n @@ -96,7 +96,7 @@ type Multinomial = let c = p |> Seq.indexed |> Seq.fold (fun acc (i,pi) -> pi**x.[i] * acc) 1. floor (0.5 + Math.Exp(a - b)) * c // must be an integer, to compensate for floating point errors: floor +0.5 - static member PMF (p: vector) (x: Vector) = + static member PMF (p: Vector) (x: Vector) = let n = x |> Seq.sum |> int //checks Multinomial.CheckParam p n @@ -118,15 +118,15 @@ type Multinomial = /// /// /// - static member Support (p: vector) n = + static member Support (p: Vector) n = Multinomial.CheckParam p n - Vector.Generic.init p.Length (fun xi -> Interval.createClosedOfSize 0 n) + Array.init p.Length (fun xi -> Interval.createClosedOfSize 0 n) /// A string representation of the distribution. /// /// vector of event probabilities in each trial /// number of trails - static member ToString (p: vector) (n: int) = + static member ToString (p: Vector) (n: int) = sprintf "Multinomial(p = %A, n = %i,)" p n /// Initializes a Multinomial distribution diff --git a/src/FSharp.Stats/Distributions/Distribution.fs b/src/FSharp.Stats/Distributions/Distribution.fs index 71b55aa49..17ee2d05d 100644 --- a/src/FSharp.Stats/Distributions/Distribution.fs +++ b/src/FSharp.Stats/Distributions/Distribution.fs @@ -37,8 +37,8 @@ module Parameters = StandardDeviation : float} type MultivariateNormal = { - Mean : vector - StandardDeviation : matrix} + Mean : Vector + StandardDeviation : Matrix} type Exponential = { Lambda : float} diff --git a/src/FSharp.Stats/FSharp.Stats.fsproj b/src/FSharp.Stats/FSharp.Stats.fsproj index 7565d7d93..b5c4c4605 100644 --- a/src/FSharp.Stats/FSharp.Stats.fsproj +++ b/src/FSharp.Stats/FSharp.Stats.fsproj @@ -32,9 +32,9 @@ + - @@ -62,10 +62,10 @@ - + diff --git a/src/FSharp.Stats/Fitting/CrossValidation.fs b/src/FSharp.Stats/Fitting/CrossValidation.fs index ebc0a1ad6..8dab5a641 100644 --- a/src/FSharp.Stats/Fitting/CrossValidation.fs +++ b/src/FSharp.Stats/Fitting/CrossValidation.fs @@ -24,7 +24,7 @@ module CrossValidation = /// let ssr (y:Vector) (p:Vector)= let residuals = y .- p - Vector.dotProduct residuals residuals + Vector.dot residuals residuals /// Computes root mean square error (RMSE) /// diff --git a/src/FSharp.Stats/Fitting/GoodnessOfFit.fs b/src/FSharp.Stats/Fitting/GoodnessOfFit.fs index fdcf21bfe..8efdb100d 100644 --- a/src/FSharp.Stats/Fitting/GoodnessOfFit.fs +++ b/src/FSharp.Stats/Fitting/GoodnessOfFit.fs @@ -354,7 +354,7 @@ module GoodnessOfFit = Vector.init (order+1) (fun i -> pown x i) let calculateANOVA (order) (coef : Vector) (xData) (yData) = - let fitFunction x = Vector.dotProduct coef (vandermondeRow order x) + let fitFunction x = Vector.dot coef (vandermondeRow order x) calculateANOVA order fitFunction xData yData [] diff --git a/src/FSharp.Stats/Fitting/LinearRegression.fs b/src/FSharp.Stats/Fitting/LinearRegression.fs index a43f7a1e6..b02ab463b 100644 --- a/src/FSharp.Stats/Fitting/LinearRegression.fs +++ b/src/FSharp.Stats/Fitting/LinearRegression.fs @@ -57,12 +57,12 @@ module LinearRegression = /// Gets a x value and predicts the corresponding y value for the given polynomial coefficients. member this.Predict (x: 'T) = - Vector.dotProduct coefficients (vandermondeRow this.Degree x) + Vector.dot coefficients (vandermondeRow this.Degree x) /// Gets a x value vector and predicts the corresponding y value for the given polynomial coefficients. member this.Predict (x: Vector<'T>) = let tmp = Vector.init (x.Length + 1) (fun i -> if i = 0 then 'T.One else x.[i-1]) - Vector.dotProduct tmp coefficients + Vector.dot tmp coefficients /// Prints the polynomial function in a human readable form. override this.ToString() = @@ -483,7 +483,7 @@ module LinearRegression = /// let predict (coef: Coefficients) (x: Vector) = let tmp: Vector = Vector.init (x.Length+1) (fun i -> if i = 0 then 1. else x.[i-1]) - Vector.dotProduct tmp coef.Coefficients + Vector.dot tmp coef.Coefficients module RidgeRegression = @@ -518,7 +518,7 @@ module LinearRegression = /// let predict (coef : Coefficients) (x:Vector) = let tmp :Vector = Vector.init (x.Length+1) (fun i -> if i = 0 then 1. else x.[i-1]) - Vector.dotProduct tmp coef.Coefficients + Vector.dot tmp coef.Coefficients /// /// Linear regression using polynomials as regression function: f(x) = a + bx + cx^2 + .... @@ -640,7 +640,7 @@ module LinearRegression = /// /// If all coefficients are nonzero, the order is equal to the length of the coefficient vector! let predict (coef: Coefficients) (x: float) = - Vector.dotProduct coef.Coefficients (vandermondeRow coef.Degree x) + Vector.dot coef.Coefficients (vandermondeRow coef.Degree x) /// /// calculates derivative values at X=x with given polynomial coefficients. Level 1 = fst derivative; Level2 = snd derivative ... diff --git a/src/FSharp.Stats/Fitting/LogisticRegression.fs b/src/FSharp.Stats/Fitting/LogisticRegression.fs index 6fa01b3f7..ae03c4008 100644 --- a/src/FSharp.Stats/Fitting/LogisticRegression.fs +++ b/src/FSharp.Stats/Fitting/LogisticRegression.fs @@ -29,7 +29,7 @@ module LogisticRegression = // Build intercept-augmented obs let iobs = withIntercept obs // Dot product => logistic function - Vector.dotProduct weights iobs + Vector.dot weights iobs |> FSharp.Stats.SpecialFunctions.Logistic.standard /// Error = (label - prediction) diff --git a/src/FSharp.Stats/Fitting/NonLinearRegression.fs b/src/FSharp.Stats/Fitting/NonLinearRegression.fs index 0daaea611..daec51af3 100644 --- a/src/FSharp.Stats/Fitting/NonLinearRegression.fs +++ b/src/FSharp.Stats/Fitting/NonLinearRegression.fs @@ -192,10 +192,10 @@ module NonLinearRegression = let jacobian' = updateJacobianInplace model xData currentParamGuess jacobian let residualVector' = updateResidualVectorInPlace model xData yData currentParamGuess residualVector let hessian = jacobian'.Transpose() * jacobian' - let diagonal = Matrix.initDiagonal (Vector.map (fun x -> ((lambda)*x)) hessian.Diagonal) + let diagonal = Matrix.diagonal (Array.map (fun x -> ((lambda)*x)) (Matrix.getDiagonal hessian)) let modHessian = (hessian + diagonal) - let step = LinearAlgebra.solveLinearSystem modHessian (Matrix.mulV (jacobian'.Transpose) residualVector') - let newParamGuess = currentParamGuess - step + let step = LinearAlgebra.solveLinearSystem modHessian (Matrix.muliplyVector (jacobian'.Transpose()) residualVector') + let newParamGuess = currentParamGuess .- step let newValueRSS = getRSS model xData yData newParamGuess paramsAtIteration.Add(newParamGuess) if shouldTerminate currentValueRSS newValueRSS paramsAtIteration.Count currentParamGuess newParamGuess solverOptions then @@ -236,7 +236,7 @@ module NonLinearRegression = /// let private validateBounds (lowerBound: Vector) (upperBound: Vector) (parameters: Vector) = try - if Vector.map3 (fun l u x -> if l <= x && u >= x then x else nan) lowerBound upperBound parameters |> Vector.exists Ops.isNan then + if Array.map3 (fun l u x -> if l <= x && u >= x then x else nan) lowerBound upperBound parameters |> Array.exists Ops.isNan then failwith "initial parameters are not within Bounds" else () @@ -245,19 +245,19 @@ module NonLinearRegression = /// let private toInternalParameters (lowerBound: Vector) (upperBound: Vector) (extParameters: Vector) = - Vector.map3 (fun l u x -> + Array.map3 (fun l u x -> Math.Asin((2.0 * (x - l) / (u - l)) - 1.0) ) lowerBound upperBound extParameters /// let private toExternalParameters (lowerBound: Vector) (upperBound: Vector) (intParameters: Vector) = - Vector.map3 (fun l u x -> + Array.map3 (fun l u x -> l + (u / 2.0 - l / 2.0) * (Math.Sin(x) + 1.0) ) lowerBound upperBound intParameters /// let private calculateJacScaleFactors (lowerBound: Vector) (upperBound: Vector) (intParameters: Vector) = - Vector.map3 (fun l u x -> + Array.map3 (fun l u x -> (u - l) / 2.0 * Math.Cos(x) ) lowerBound upperBound intParameters @@ -285,7 +285,7 @@ module NonLinearRegression = /// /// /// - let estimatedParamsVerbose (model: Model) (solverOptions: SolverOptions) lambdaInitial lambdaFactor (lowerBound: vector) (upperBound: vector) (xData: float[]) (yData: float []) = + let estimatedParamsVerbose (model: Model) (solverOptions: SolverOptions) lambdaInitial lambdaFactor (lowerBound: Vector) (upperBound: Vector) (xData: float[]) (yData: float []) = let paramsAtIteration = new ResizeArray>() let initialParamGuess = solverOptions.InitialParamGuess validateBounds lowerBound upperBound initialParamGuess @@ -293,16 +293,16 @@ module NonLinearRegression = let residualVector = Vector.zeroCreate xData.Length let jacobian = Matrix.zeroCreate xData.Length solverOptions.InitialParamGuess.Length let initialValueRSS = getRSS model xData yData initialParamGuess - let rec loop lambda jacobian residualVector currentParamGuessExt currentParamGuessInt currentValueRSS (paramsAtIteration:ResizeArray) = + let rec loop lambda jacobian residualVector currentParamGuessExt currentParamGuessInt currentValueRSS (paramsAtIteration:ResizeArray>) = let scaleFactors = calculateJacScaleFactors lowerBound upperBound currentParamGuessInt let jacobian' = updateJacobianInplace model xData currentParamGuessExt jacobian let residualVector' = updateResidualVectorInPlace model xData yData currentParamGuessExt residualVector - let gradient = Matrix.mulV (jacobian'.Transpose) residualVector' |> scaleGradient scaleFactors - let hessian = jacobian'.Transpose * jacobian' |> scaleJacobian scaleFactors - let diagonal = Matrix.initDiagonal (Vector.map (fun x -> ((lambda)*x)) hessian.Diagonal) + let gradient = Matrix.muliplyVector (jacobian'.Transpose()) residualVector' |> scaleGradient scaleFactors + let hessian = jacobian'.Transpose() * jacobian' |> scaleJacobian scaleFactors + let diagonal = Matrix.diagonal (Array.map (fun x -> ((lambda)*x)) (hessian |> Matrix.getDiagonal)) let modHessian = (hessian + diagonal) - let step = FSharp.Stats.Algebra.LinearAlgebra.SolveLinearSystem modHessian gradient - let newParamGuessInt = currentParamGuessInt - step + let step = FSharp.Stats.Algebra.LinearAlgebra.solveLinearSystem modHessian gradient + let newParamGuessInt = currentParamGuessInt .- step let newParamGuessExt = toExternalParameters lowerBound upperBound newParamGuessInt let newValueRSS = getRSS model xData yData newParamGuessExt paramsAtIteration.Add(newParamGuessExt) @@ -543,7 +543,7 @@ module NonLinearRegression = //gets the linear representation of the problem and solves it by simple linear regression let initialParamGuess = let yLn : Vector = yData |> Array.map (fun x -> Math.Log(x)) - let linearReg = LinearRegression.OLS.Linear.Univariable.fit (vector xData) yLn + let linearReg = LinearRegression.OLS.Linear.Univariable.fit xData yLn let a = exp linearReg.Constant let b = linearReg.Linear [|a;b|] diff --git a/src/FSharp.Stats/Optimization/NelderMead.fs b/src/FSharp.Stats/Optimization/NelderMead.fs index 98848e2de..34235174e 100644 --- a/src/FSharp.Stats/Optimization/NelderMead.fs +++ b/src/FSharp.Stats/Optimization/NelderMead.fs @@ -4,7 +4,6 @@ module NelderMead = open FSharp.Stats open FSharp.Stats.Algebra - open FSharp.Stats.Algebra.LinearAlgebra type NmConfig = { /// Delta used to generate initial simplex for non-zero value elements @@ -51,12 +50,12 @@ module NelderMead = type NmInterationResult = { - Simplexes : vector [] + Simplexes : Vector [] Fx : float array - Vectors : vector [] + Vectors : Vector [] Values : float array GradientNorms : float array - SolutionVector : vector + SolutionVector : Vector Solution : float LastStep : StepType } @@ -64,11 +63,11 @@ module NelderMead = /// Create an initial simplex - let createSimplex (nmc : NmConfig) (x : vector) = + let createSimplex (nmc : NmConfig) (x : Vector) = let n = x.Length let simplex = Array.init (n+1) - (fun _ -> Vector.copy x ) + (fun _ -> Array.copy x ) for i = 1 to n do if (x[i - 1] <> 0) then simplex[i][i - 1] <- (1. + nmc.Delta) * x[i - 1] @@ -79,7 +78,7 @@ module NelderMead = // determine the values of each vertice in the initial simplex - let rankVertices (simplexes : vector[]) (fn : vector -> float) = + let rankVertices (simplexes : Vector[]) (fn : Vector -> float) = let x = Array.copy simplexes let fx = simplexes |> Array.map fn System.Array.Sort(fx,x) @@ -87,7 +86,7 @@ module NelderMead = - let update (nmc : NmConfig) (stopCounter:OptimizationStop.StopCounter) (fn : vector -> float) (nmInterResult : NmInterationResult) = + let update (nmc : NmConfig) (stopCounter:OptimizationStop.StopCounter) (fn : Vector -> float) (nmInterResult : NmInterationResult) = let simplexes = Array.copy nmInterResult.Simplexes // Copy necessary ??? let fx = nmInterResult.Fx let mutable laststep_ = nmInterResult.LastStep @@ -96,13 +95,13 @@ module NelderMead = let xbar = let mutable tmp = Vector.zeroCreate simplexes[0].Length for i = 0 to (simplexes.Length - 2) do - tmp <- tmp + simplexes[i] + tmp <- tmp .+ simplexes[i] let d = float (simplexes.Length - 1) - tmp |> Vector.map (fun v -> v / d) + tmp |> Array.map (fun v -> v / d) // Calculate reflection point - let xr = (1. + nmc.Rho) * xbar - nmc.Rho * simplexes[simplexes.Length - 1] + let xr = (1. + nmc.Rho) .* xbar .- nmc.Rho .* simplexes[simplexes.Length - 1] let fxr = fn xr stopCounter.IncFunctionEvaluationCounter() @@ -110,7 +109,7 @@ module NelderMead = // reflection point is better than worst point if (fxr < fx[0]) then //reflection point is better than best point - > expand - let xe = (1. + nmc.Rho * nmc.Chi) * xbar - nmc.Rho * nmc.Chi * simplexes[simplexes.Length - 1] + let xe = (1. + nmc.Rho * nmc.Chi) .* xbar .- nmc.Rho * nmc.Chi .* simplexes[simplexes.Length - 1] let fxe = fn xe stopCounter.IncFunctionEvaluationCounter() if (fxe < fxr) then @@ -136,7 +135,7 @@ module NelderMead = if ((fx[simplexes.Length - 2] <= fxr) && (fxr < fx[simplexes.Length - 1])) then // perform an outside contraction - let xc = (1. + nmc.Psi * nmc.Rho) * xbar - nmc.Psi * nmc.Rho * simplexes[simplexes.Length - 1] + let xc = (1. + nmc.Psi * nmc.Rho) .* xbar .- nmc.Psi * nmc.Rho .* simplexes[simplexes.Length - 1] let fxc = fn xc stopCounter.IncFunctionEvaluationCounter() if (fxc < fxr) then @@ -147,7 +146,7 @@ module NelderMead = else // perform a shrink step for i = 1 to (simplexes.Length - 1) do - simplexes[i] <- simplexes[0] + nmc.Sigma * (simplexes[i] - simplexes[0]) + simplexes[i] <- simplexes[0] .+ nmc.Sigma .* (simplexes[i] .- simplexes[0]) fx[i] <- fn simplexes[i] stopCounter.IncFunctionEvaluationCounter() @@ -155,7 +154,7 @@ module NelderMead = else // perform an inside contraction - let xcc = (1. - nmc.Psi) * xbar + nmc.Psi * simplexes[simplexes.Length - 1]; + let xcc = (1. - nmc.Psi) .* xbar .+ nmc.Psi .* simplexes[simplexes.Length - 1]; let fxcc = fn xcc stopCounter.IncFunctionEvaluationCounter() @@ -169,7 +168,7 @@ module NelderMead = // perform a shrink step for i = 1 to (simplexes.Length - 1) do - simplexes[i] <- simplexes[0] + nmc.Sigma * (simplexes[i] - simplexes[0]) + simplexes[i] <- simplexes[0] .+ nmc.Sigma .* (simplexes[i] .- simplexes[0]) fx[i] <- fn simplexes[i] stopCounter.IncFunctionEvaluationCounter() @@ -205,7 +204,7 @@ module NelderMead = /// Initialize the optimization method /// The use of this function is intended for testing/debugging purposes only - let initInteration (maxIteration:int) (initialsimplex :vector[]) (fn : vector -> float) = + let initInteration (maxIteration:int) (initialsimplex :Vector[]) (fn : Vector -> float) = let x,fx = rankVertices initialsimplex fn let evalFn = fn initialsimplex[0] @@ -235,7 +234,7 @@ module NelderMead = /// Minimize the given cost function and stop criteria - let minimizeWithStopCriteria (nmc : NmConfig) (x :vector) (fn : vector -> float) (stopCriteria:OptimizationStop.StopCriteria) = + let minimizeWithStopCriteria (nmc : NmConfig) (x :Vector) (fn : Vector -> float) (stopCriteria:OptimizationStop.StopCriteria) = // Action newMinimalValueFound) let initialsimplex = createSimplex nmc x @@ -266,5 +265,5 @@ module NelderMead = /// Minimize the given cost function and stop criteria - let minimize (nmc : NmConfig) (x :vector) (fn : vector -> float) = + let minimize (nmc : NmConfig) (x :Vector) (fn : Vector -> float) = minimizeWithStopCriteria nmc x fn OptimizationStop.defaultStopCriteria diff --git a/src/FSharp.Stats/Permutation.fs b/src/FSharp.Stats/Permutation.fs index 9be2edc52..5067b2992 100644 --- a/src/FSharp.Stats/Permutation.fs +++ b/src/FSharp.Stats/Permutation.fs @@ -66,6 +66,22 @@ module Permutation = let copy = Array.copy arr ofFreshArray copy + /// Computes the sign (+1.0 or -1.0) of a permutation P, + /// given its domain size n. sign(P) = (-1)^(n - numCycles). + let sign (n: int) (P: Permutation) : float = + let visited = Array.create n false + let mutable numCycles = 0 + for i in 0 .. n - 1 do + if not visited.[i] then + numCycles <- numCycles + 1 + let mutable current = i + while not visited.[current] do + visited.[current] <- true + current <- P current + let numTranspositions = n - numCycles + if numTranspositions % 2 = 0 then 1.0 else -1.0 + + let ofPairs (mappings: seq) = let p = dict mappings diff --git a/src/FSharp.Stats/Seq.fs b/src/FSharp.Stats/Seq.fs index 1853cfe1d..c0f93baa6 100644 --- a/src/FSharp.Stats/Seq.fs +++ b/src/FSharp.Stats/Seq.fs @@ -7,8 +7,6 @@ namespace FSharp.Stats [] module Seq = - module OpsS = SpecializedGenericImpl - /// /// Computes the range of the input sequence. /// @@ -814,8 +812,8 @@ module Seq = /// /// let inline covPopulation (seq1:seq<'T>) (seq2:seq<'T>) : 'U = - let v1 = seq1 |> OpsS.seqV - let v2 = seq2 |> OpsS.seqV + let v1 = seq1 |>Array.ofSeq + let v2 = seq2 |>Array.ofSeq if v1.Length <> v2.Length then failwith "Inputs need to have the same length." let zero = LanguagePrimitives.GenericZero<'U> let div = LanguagePrimitives.DivideByInt<'U> @@ -880,8 +878,8 @@ module Seq = /// /// let inline cov (seq1:seq<'T>) (seq2:seq<'T>) : 'U = - let v1 = seq1 |> OpsS.seqV - let v2 = seq2 |> OpsS.seqV + let v1 = seq1 |>Array.ofSeq + let v2 = seq2 |>Array.ofSeq if v1.Length <> v2.Length then failwith "Inputs need to have the same length." let zero = LanguagePrimitives.GenericZero<'U> let div = LanguagePrimitives.DivideByInt<'U> diff --git a/src/FSharp.Stats/Signal/Filtering.fs b/src/FSharp.Stats/Signal/Filtering.fs index 353f4587b..d70f09cad 100644 --- a/src/FSharp.Stats/Signal/Filtering.fs +++ b/src/FSharp.Stats/Signal/Filtering.fs @@ -54,13 +54,13 @@ module Filtering = if sLen < kLen then // The original code returned a single dot if kernel longer than signal - [| Vector.dotProduct kernel signal |] + [| Vector.dot kernel signal |] else // We produce sLen - kLen + 1 outputs let outLen = sLen - kLen + 1 Array.init outLen (fun i -> // dot kernel with signal[i.. i+kLen-1] - Vector.dotProduct kernel signal.[i .. i + kLen - 1] + Vector.dot kernel signal.[i .. i + kLen - 1] ) diff --git a/src/FSharp.Stats/Testing/ConfusionMatrix.fs b/src/FSharp.Stats/Testing/ConfusionMatrix.fs index bf25b4bc8..8290da7d1 100644 --- a/src/FSharp.Stats/Testing/ConfusionMatrix.fs +++ b/src/FSharp.Stats/Testing/ConfusionMatrix.fs @@ -114,7 +114,7 @@ type MultiLabelConfusionMatrix = { let zipped = Array.zip actual predictions let confusion = - Matrix.Generic.init labels.Length labels.Length (fun m n -> + Matrix.init labels.Length labels.Length (fun m n -> let labelM = labels[m] let labelN = labels[n] zipped @@ -131,7 +131,7 @@ type MultiLabelConfusionMatrix = { let labelIndex = Array.findIndex (fun x -> x = label) mlcm.Labels mlcm.Confusion - |> Matrix.Generic.foldi ( + |> Matrix.foldi ( fun rI cI cm elem -> match (rI, cI) with | (rI, cI) when rI = labelIndex && cI = labelIndex -> {cm with TP = cm.TP + elem} diff --git a/src/FSharp.Stats/Testing/RMT.fs b/src/FSharp.Stats/Testing/RMT.fs index 19ee135a5..405ab8535 100644 --- a/src/FSharp.Stats/Testing/RMT.fs +++ b/src/FSharp.Stats/Testing/RMT.fs @@ -34,7 +34,7 @@ module RMT = let computeChiSquared (bwQuantile : float) (m:Matrix) = let unfoldedEgv = - FSharp.Stats.Algebra.LinearAlgebra.EigenSpectrumWhenSymmetric m + Algebra.LinearAlgebra.symmetricEigenspectrum m |> fun (eigenvectors,eigenvalues) -> let spUnfold = eigenvalues diff --git a/src/FSharp.Stats/Testing/TTest.fs b/src/FSharp.Stats/Testing/TTest.fs index 37466956f..98017a682 100644 --- a/src/FSharp.Stats/Testing/TTest.fs +++ b/src/FSharp.Stats/Testing/TTest.fs @@ -40,8 +40,8 @@ module TTest = /// Computes a t-test or a Welch test (unequal variances) let twoSample (assumeEqualVariances:bool) sample1 sample2 = - let s1Stats = Vector.stats sample1 - let s2Stats = Vector.stats sample2 + let s1Stats = Seq.stats sample1 + let s2Stats = Seq.stats sample2 let v1 = SummaryStats.var s1Stats let v2 = SummaryStats.var s2Stats @@ -64,7 +64,7 @@ module TTest = //// Computes a paired t-test used to compare two population means where you have two samples in /// which observations in one sample can be paired with observations in the other sample. let twoSamplePaired (sample1:Vector) (sample2:Vector) = - let deltas = Vector.map2 (fun a b -> b - a) sample1 sample2 + let deltas = Array.map2 (fun a b -> b - a) sample1 sample2 oneSample deltas 0. /// Union type indicating whether One Tail or Two Tail Student's T critical value is desired. diff --git a/src/FSharp.Stats/Testing/Tables.fs b/src/FSharp.Stats/Testing/Tables.fs index f8f007a67..c7b071c27 100644 --- a/src/FSharp.Stats/Testing/Tables.fs +++ b/src/FSharp.Stats/Testing/Tables.fs @@ -10,53 +10,52 @@ module Tables = // and C. W. Dunnett, New Tables for Multiple Comparisons with a Control,Biometrics , Sep., 1964, Vol. 20, No. 3 (Sep., 1964), pp. 482-491 // df = totalcount - groupcount, k = number of means (including control) let dunnettsTwoSided095 = - matrix [ + Matrix.ofJaggedArray [| //d k 2; 3; 4; 5; 6; 7; 8; 9; 10 11 12 13 14 15 - (*1 *) [12.706; 17.369;20.034; 21.85; 23.209;24.285; 25.171;25.922; 26.57; nan; nan; nan; nan; 28.901;] - (*2 *) [4.303; 5.418; 6.065; 6.513; 6.852; 7.124; 7.349; 7.540; 7.707; nan; nan; nan; nan; 8.31 ;] - (*3 *) [3.182; 3.867; 4.263; 4.538; 4.748; 4.916; 5.056; 5.176; 5.280; nan; nan; nan; nan; 5.66 ;] - (*4 *) [2.776; 3.310; 3.618; 3.832; 3.994; 4.125; 4.235; 4.328; 4.410; nan; nan; nan; nan; 4.707 ;] - (*5 *) [2.571; 3.03 ; 3.293; 3.476; 3.615; 3.727; 3.821; 3.900; 3.970; nan; nan; nan; nan; 4.225 ;] - (*6 *) [2.447; 2.863; 3.099; 3.263; 3.388; 3.489; 3.573; 3.644; 3.707; nan; nan; nan; nan; 3.936 ;] - (*7 *) [2.365; 2.752; 2.971; 3.123; 3.238; 3.331; 3.408; 3.475; 3.533; nan; nan; nan; nan; 3.744 ;] - (*8 *) [2.306; 2.673; 2.880; 3.023; 3.131; 3.219; 3.292; 3.354; 3.408; nan; nan; nan; nan; 3.608 ;] - (*9 *) [2.262; 2.614; 2.812; 2.948; 3.052; 3.135; 3.205; 3.264; 3.316; nan; nan; nan; nan; 3.506 ;] - (*10 *) [2.228; 2.568; 2.759; 2.890; 2.990; 3.075; 3.137; 3.194; 3.244; nan; nan; nan; nan; 3.427 ;] - (*11 *) [2.201; 2.532; 2.717; 2.845; 2.941; 3.019; 3.084; 3.139; 3.187; nan; nan; nan; nan; 3.363 ;] - (*12 *) [2.179; 2.502; 2.683; 2.807; 2.901; 2.977; 3.040; 3.094; 3.140; nan; nan; nan; nan; 3.312 ;] - (*13 *) [2.160; 2.478; 2.654; 2.776; 2.868; 2.942; 3.003; 3.056; 3.102; nan; nan; nan; nan; 3.269 ;] - (*14 *) [2.145; 2.457; 2.631; 2.750; 2.840; 2.912; 2.973; 3.024; 3.069; nan; nan; nan; nan; 3.233 ;] - (*15 *) [2.131; 2.439; 2.610; 2.727; 2.816; 2.887; 2.946; 2.997; 3.041; nan; nan; nan; nan; 3.202 ;] - (*16 *) [2.120; 2.424; 2.592; 2.708; 2.798; 2.865; 2.924; 2.974; 3.017; nan; nan; nan; nan; 3.176 ;] - (*17 *) [2.110; 2.410; 2.577; 2.691; 2.777; 2.846; 2.904; 2.953; 2.996; nan; nan; nan; nan; 3.152 ;] - (*18 *) [2.101; 2.399; 2.563; 2.676; 2.761; 2.830; 2.887; 2.935; 2.977; nan; nan; nan; nan; 3.132 ;] - (*19 *) [2.093; 2.388; 2.551; 2.663; 2.747; 2.815; 2.871; 2.919; 2.961; nan; nan; nan; nan; 3.114 ;] - (*20 *) [2.086; 2.379; 2.540; 2.651; 2.735; 2.802; 2.857; 2.905; 2.946; nan; nan; nan; nan; 3.098 ;] - (*21 *) [2.080; 2.370; 2.531; 2.640; 2.723; 2.790; 2.845; 2.892; 2.933; nan; nan; nan; nan; 3.083 ;] - (*22 *) [2.074; 2.363; 2.522; 2.631; 2.713; 2.779; 2.832; 2.880; 2.921; nan; nan; nan; nan; 3.070 ;] - (*23 *) [2.069; 2.356; 2.514; 2.622; 2.704; 2.769; 2.824; 2.870; 2.910; nan; nan; nan; nan; 3.058 ;] - (*24 *) [2.064; 2.349; 2.507; 2.614; 2.695; 2.760; 2.814; 2.860; 2.900; nan; nan; nan; nan; 3.047 ;] - (*25 *) [2.060; 2.344; 2.500; 2.607; 2.688; 2.752; 2.806; 2.851; 2.891; nan; nan; nan; nan; 3.037 ;] - (*26 *) [2.056; 2.338; 2.494; 2.600; 2.680; 2.745; 2.798; 2.843; 2.883; nan; nan; nan; nan; 3.028 ;] - (*27 *) [2.052; 2.333; 2.488; 2.594; 2.674; 2.738; 2.791; 2.836; 2.875; nan; nan; nan; nan; 3.019 ;] - (*28 *) [2.048; 2.329; 2.483; 2.588; 2.668; 2.731; 2.784; 2.829; 2.868; nan; nan; nan; nan; 3.011 ;] - (*29 *) [2.045; 2.325; 2.478; 2.583; 2.662; 2.725; 2.778; 2.823; 2.862; nan; nan; nan; nan; 3.004 ;] - (*30 *) [2.042; 2.321; 2.474; 2.578; 2.657; 2.720; 2.772; 2.817; 2.856; nan; nan; nan; nan; 2.997 ;] - (*31 *) [2.040; 2.317; 2.469; 2.574; 2.652; 2.715; 2.767; 2.811; 2.850; nan; nan; nan; nan; 2.991 ;] - (*32 *) [2.037; 2.314; 2.466; 2.569; 2.647; 2.710; 2.762; 2.806; 2.845; nan; nan; nan; nan; 2.985 ;] - (*33 *) [2.035; 2.310; 2.462; 2.565; 2.643; 2.705; 2.757; 2.801; 2.840; nan; nan; nan; nan; 2.979 ;] - (*34 *) [2.032; 2.307; 2.458; 2.561; 2.639; 2.701; 2.753; 2.797; 2.835; nan; nan; nan; nan; 2.974 ;] - (*35 *) [2.030; 2.305; 2.455; 2.558; 2.635; 2.697; 2.748; 2.792; 2.830; nan; nan; nan; nan; 2.969 ;] - (*36 *) [2.028; 2.302; 2.452; 2.555; 2.632; 2.693; 2.745; 2.788; 2.826; nan; nan; nan; nan; 2.965 ;] - (*37 *) [2.026; 2.299; 2.449; 2.551; 2.628; 2.690; 2.741; 2.784; 2.822; nan; nan; nan; nan; 2.960 ;] - (*38 *) [2.024; 2.297; 2.447; 2.548; 2.625; 2.686; 2.737; 2.781; 2.819; nan; nan; nan; nan; 2.956 ;] - (*39 *) [2.023; 2.295; 2.444; 2.546; 2.622; 2.683; 2.734; 2.777; 2.815; nan; nan; nan; nan; 2.952 ;] - (*40 *) [2.021; 2.293; 2.441; 2.543; 2.619; 2.680; 2.731; 2.774; 2.812; nan; nan; nan; nan; 2.949 ;] - (*48 *) [2.011; 2.279; 2.426; 2.526; 2.601; 2.661; 2.711; 2.753; 2.790; nan; nan; nan; nan; 2.925 ;] - (*60 *) [2.000; 2.265; 2.410; 2.508; 2.582; 2.642; 2.691; 2.733; 2.769; nan; nan; nan; nan; 2.901 ;] - (*80 *) [1.990; 2.252; 2.394; 2.491; 2.564; 2.623; 2.671; 2.712; 2.748; nan; nan; nan; nan; 2.878 ;] - (*120*) [1.980; 2.238; 2.379; 2.475; 2.547; 2.604; 2.651; 2.692; 2.727; nan; nan; nan; nan; 2.855 ;] - (*240*) [1.970; 2.225; 2.364; 2.458; 2.529; 2.585; 2.632; 2.672; 2.707; nan; nan; nan; nan; 2.832 ;] - (*inf*) [1.960; 2.212; 2.349; 2.442; 2.511; 2.567; 2.613; 2.652; 2.686; nan; nan; nan; nan; 2.810 ;] - ] - + (*1 *) [|12.706; 17.369;20.034; 21.85; 23.209;24.285; 25.171;25.922; 26.57; nan; nan; nan; nan; 28.901;|] + (*2 *) [|4.303; 5.418; 6.065; 6.513; 6.852; 7.124; 7.349; 7.540; 7.707; nan; nan; nan; nan; 8.31 ;|] + (*3 *) [|3.182; 3.867; 4.263; 4.538; 4.748; 4.916; 5.056; 5.176; 5.280; nan; nan; nan; nan; 5.66 ;|] + (*4 *) [|2.776; 3.310; 3.618; 3.832; 3.994; 4.125; 4.235; 4.328; 4.410; nan; nan; nan; nan; 4.707 ;|] + (*5 *) [|2.571; 3.03 ; 3.293; 3.476; 3.615; 3.727; 3.821; 3.900; 3.970; nan; nan; nan; nan; 4.225 ;|] + (*6 *) [|2.447; 2.863; 3.099; 3.263; 3.388; 3.489; 3.573; 3.644; 3.707; nan; nan; nan; nan; 3.936 ;|] + (*7 *) [|2.365; 2.752; 2.971; 3.123; 3.238; 3.331; 3.408; 3.475; 3.533; nan; nan; nan; nan; 3.744 ;|] + (*8 *) [|2.306; 2.673; 2.880; 3.023; 3.131; 3.219; 3.292; 3.354; 3.408; nan; nan; nan; nan; 3.608 ;|] + (*9 *) [|2.262; 2.614; 2.812; 2.948; 3.052; 3.135; 3.205; 3.264; 3.316; nan; nan; nan; nan; 3.506 ;|] + (*10 *) [|2.228; 2.568; 2.759; 2.890; 2.990; 3.075; 3.137; 3.194; 3.244; nan; nan; nan; nan; 3.427 ;|] + (*11 *) [|2.201; 2.532; 2.717; 2.845; 2.941; 3.019; 3.084; 3.139; 3.187; nan; nan; nan; nan; 3.363 ;|] + (*12 *) [|2.179; 2.502; 2.683; 2.807; 2.901; 2.977; 3.040; 3.094; 3.140; nan; nan; nan; nan; 3.312 ;|] + (*13 *) [|2.160; 2.478; 2.654; 2.776; 2.868; 2.942; 3.003; 3.056; 3.102; nan; nan; nan; nan; 3.269 ;|] + (*14 *) [|2.145; 2.457; 2.631; 2.750; 2.840; 2.912; 2.973; 3.024; 3.069; nan; nan; nan; nan; 3.233 ;|] + (*15 *) [|2.131; 2.439; 2.610; 2.727; 2.816; 2.887; 2.946; 2.997; 3.041; nan; nan; nan; nan; 3.202 ;|] + (*16 *) [|2.120; 2.424; 2.592; 2.708; 2.798; 2.865; 2.924; 2.974; 3.017; nan; nan; nan; nan; 3.176 ;|] + (*17 *) [|2.110; 2.410; 2.577; 2.691; 2.777; 2.846; 2.904; 2.953; 2.996; nan; nan; nan; nan; 3.152 ;|] + (*18 *) [|2.101; 2.399; 2.563; 2.676; 2.761; 2.830; 2.887; 2.935; 2.977; nan; nan; nan; nan; 3.132 ;|] + (*19 *) [|2.093; 2.388; 2.551; 2.663; 2.747; 2.815; 2.871; 2.919; 2.961; nan; nan; nan; nan; 3.114 ;|] + (*20 *) [|2.086; 2.379; 2.540; 2.651; 2.735; 2.802; 2.857; 2.905; 2.946; nan; nan; nan; nan; 3.098 ;|] + (*21 *) [|2.080; 2.370; 2.531; 2.640; 2.723; 2.790; 2.845; 2.892; 2.933; nan; nan; nan; nan; 3.083 ;|] + (*22 *) [|2.074; 2.363; 2.522; 2.631; 2.713; 2.779; 2.832; 2.880; 2.921; nan; nan; nan; nan; 3.070 ;|] + (*23 *) [|2.069; 2.356; 2.514; 2.622; 2.704; 2.769; 2.824; 2.870; 2.910; nan; nan; nan; nan; 3.058 ;|] + (*24 *) [|2.064; 2.349; 2.507; 2.614; 2.695; 2.760; 2.814; 2.860; 2.900; nan; nan; nan; nan; 3.047 ;|] + (*25 *) [|2.060; 2.344; 2.500; 2.607; 2.688; 2.752; 2.806; 2.851; 2.891; nan; nan; nan; nan; 3.037 ;|] + (*26 *) [|2.056; 2.338; 2.494; 2.600; 2.680; 2.745; 2.798; 2.843; 2.883; nan; nan; nan; nan; 3.028 ;|] + (*27 *) [|2.052; 2.333; 2.488; 2.594; 2.674; 2.738; 2.791; 2.836; 2.875; nan; nan; nan; nan; 3.019 ;|] + (*28 *) [|2.048; 2.329; 2.483; 2.588; 2.668; 2.731; 2.784; 2.829; 2.868; nan; nan; nan; nan; 3.011 ;|] + (*29 *) [|2.045; 2.325; 2.478; 2.583; 2.662; 2.725; 2.778; 2.823; 2.862; nan; nan; nan; nan; 3.004 ;|] + (*30 *) [|2.042; 2.321; 2.474; 2.578; 2.657; 2.720; 2.772; 2.817; 2.856; nan; nan; nan; nan; 2.997 ;|] + (*31 *) [|2.040; 2.317; 2.469; 2.574; 2.652; 2.715; 2.767; 2.811; 2.850; nan; nan; nan; nan; 2.991 ;|] + (*32 *) [|2.037; 2.314; 2.466; 2.569; 2.647; 2.710; 2.762; 2.806; 2.845; nan; nan; nan; nan; 2.985 ;|] + (*33 *) [|2.035; 2.310; 2.462; 2.565; 2.643; 2.705; 2.757; 2.801; 2.840; nan; nan; nan; nan; 2.979 ;|] + (*34 *) [|2.032; 2.307; 2.458; 2.561; 2.639; 2.701; 2.753; 2.797; 2.835; nan; nan; nan; nan; 2.974 ;|] + (*35 *) [|2.030; 2.305; 2.455; 2.558; 2.635; 2.697; 2.748; 2.792; 2.830; nan; nan; nan; nan; 2.969 ;|] + (*36 *) [|2.028; 2.302; 2.452; 2.555; 2.632; 2.693; 2.745; 2.788; 2.826; nan; nan; nan; nan; 2.965 ;|] + (*37 *) [|2.026; 2.299; 2.449; 2.551; 2.628; 2.690; 2.741; 2.784; 2.822; nan; nan; nan; nan; 2.960 ;|] + (*38 *) [|2.024; 2.297; 2.447; 2.548; 2.625; 2.686; 2.737; 2.781; 2.819; nan; nan; nan; nan; 2.956 ;|] + (*39 *) [|2.023; 2.295; 2.444; 2.546; 2.622; 2.683; 2.734; 2.777; 2.815; nan; nan; nan; nan; 2.952 ;|] + (*40 *) [|2.021; 2.293; 2.441; 2.543; 2.619; 2.680; 2.731; 2.774; 2.812; nan; nan; nan; nan; 2.949 ;|] + (*48 *) [|2.011; 2.279; 2.426; 2.526; 2.601; 2.661; 2.711; 2.753; 2.790; nan; nan; nan; nan; 2.925 ;|] + (*60 *) [|2.000; 2.265; 2.410; 2.508; 2.582; 2.642; 2.691; 2.733; 2.769; nan; nan; nan; nan; 2.901 ;|] + (*80 *) [|1.990; 2.252; 2.394; 2.491; 2.564; 2.623; 2.671; 2.712; 2.748; nan; nan; nan; nan; 2.878 ;|] + (*120*) [|1.980; 2.238; 2.379; 2.475; 2.547; 2.604; 2.651; 2.692; 2.727; nan; nan; nan; nan; 2.855 ;|] + (*240*) [|1.970; 2.225; 2.364; 2.458; 2.529; 2.585; 2.632; 2.672; 2.707; nan; nan; nan; nan; 2.832 ;|] + (*inf*) [|1.960; 2.212; 2.349; 2.442; 2.511; 2.567; 2.613; 2.652; 2.686; nan; nan; nan; nan; 2.810 ;|] + |] From a967c81ddaaaec8565894f3961a4e7a9fd199cdc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20M=C3=BChlhaus?= Date: Fri, 11 Apr 2025 08:45:15 +0200 Subject: [PATCH 067/121] Exclude all Unit tests to successively update it --- .../FSharp.Stats.Tests.fsproj | 31 ------------------- 1 file changed, 31 deletions(-) diff --git a/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj b/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj index c8d7e411d..45a174267 100644 --- a/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj +++ b/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj @@ -5,37 +5,6 @@ false - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - From e1baf698aca37a277c4e5f68c3d59a3b008b6b14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20M=C3=BChlhaus?= Date: Fri, 11 Apr 2025 08:45:39 +0200 Subject: [PATCH 068/121] Update Test: Hypothesis Testing --- tests/FSharp.Stats.Tests/Testing.fs | 42 ++++++++++++++--------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/tests/FSharp.Stats.Tests/Testing.fs b/tests/FSharp.Stats.Tests/Testing.fs index 41edb81d3..18ab34a44 100644 --- a/tests/FSharp.Stats.Tests/Testing.fs +++ b/tests/FSharp.Stats.Tests/Testing.fs @@ -182,10 +182,10 @@ let wilcoxonTestTests = [] let tTestTests = // tested in SPSS version 27 - let groupA = vector [-5.;-3.;-3.;-4.;-5.;] - let groupB = vector [-2.;-4.;-4.;-6.;-6.;-6.;-5.;] - let groupC = vector [-3.;-7.;-8.;-4.;-2.; 1.;-1.;] - let groupD = vector [1.;-1.;0.;2.;2.;] + let groupA = [|-5.;-3.;-3.;-4.;-5.;|] + let groupB = [|-2.;-4.;-4.;-6.;-6.;-6.;-5.;|] + let groupC = [|-3.;-7.;-8.;-4.;-2.; 1.;-1.;|] + let groupD = [|1.;-1.;0.;2.;2.;|] let meanA = Seq.mean groupA let meanB = Seq.mean groupB @@ -271,8 +271,8 @@ let tTestTests = testCase "twoSamplePaired" <| fun () -> // tested with R function t.test(x, y, paired = TRUE, alternative = "two.sided") - let vectorX = vector [1.;2.;4.;8.] - let vectorY = vector [10.;23.;11;9.] + let vectorX = [|1.;2.;4.;8.|] + let vectorY = [|10.;23.;11;9.|] let expectedPval = 0.10836944173355316 let expectedStatistic = 2.26554660552391818 let twoSamplePaired = Testing.TTest.twoSamplePaired vectorX vectorY @@ -280,36 +280,36 @@ let tTestTests = Expect.floatClose Accuracy.high twoSamplePaired.Statistic expectedStatistic "t statistic should be equal." Expect.equal twoSamplePaired.DegreesOfFreedom 3. "df should be equal." - let vectorZ = vector [-5.;-9.;0.;-8.] + let vectorZ = [|-5.;-9.;0.;-8.|] let twoSamplePaired2 = Testing.TTest.twoSamplePaired vectorX vectorZ let expectedPval1 = 0.041226646225439562 let expectedStatistic1 = -3.44031028692427698 Expect.floatClose Accuracy.high twoSamplePaired2.PValue expectedPval1 "pValue should be equal." Expect.floatClose Accuracy.high twoSamplePaired2.Statistic expectedStatistic1 "t statistic should be equal." - let vectorNan = vector [nan;10.;23.;11.] + let vectorNan = [|nan;10.;23.;11.|] let twoSamplePaired3 = Testing.TTest.twoSamplePaired vectorX vectorNan Expect.isTrue (nan.Equals(twoSamplePaired3.PValue)) "pValue should be nan." Expect.isTrue (nan.Equals(twoSamplePaired3.Statistic)) "t statistic should be nan." - let vectorBefore = vector [10.;4.;15.;12.;6.] + let vectorBefore = [|10.;4.;15.;12.;6.|] let twoSamplePaired4() = Testing.TTest.twoSamplePaired vectorBefore vectorX |>ignore Expect.throws twoSamplePaired4 "Vectors of different length" // test if exception Test works // Expect.throws (fun _ -> Testing.TTest.twoSamplePaired vectorX vectorY|>ignore) "Vetors should have equal length" - let vectorWithInfinity = vector [infinity;4.;15.;12.] + let vectorWithInfinity = [|infinity;4.;15.;12.|] let twoSamplePairedInfinity = Testing.TTest.twoSamplePaired vectorWithInfinity vectorX Expect.isTrue (nan.Equals(twoSamplePairedInfinity.PValue)) "pValue should be nan." Expect.isTrue (nan.Equals(twoSamplePairedInfinity.Statistic)) "t statistic should be nan." - let vectorWithNegativeInfinity = vector [infinity;4.;15.;12.] + let vectorWithNegativeInfinity = [|infinity;4.;15.;12.|] let twoSampleNegativeInfinity = Testing.TTest.twoSamplePaired vectorWithNegativeInfinity vectorX Expect.isTrue (nan.Equals(twoSampleNegativeInfinity.PValue)) "pValue should be nan." Expect.isTrue (nan.Equals(twoSampleNegativeInfinity.Statistic)) "t statistic should be nan." - let vectorNull = vector [0;0;0;0] + let vectorNull = [|0.;0.;0.;0.|] let twoSamplePairedWithNullVector = Testing.TTest.twoSamplePaired vectorNull vectorY let expectedPval2 = 0.0272 let expectedStatistic2 = 4.0451 @@ -322,12 +322,12 @@ let tTestTests = let fTestTests = // F-Test validated against res.ftest <- var.test(samplea, sampleb, alternative = "two.sided") RStudio 2022.02.3+492 "Prairie Trillium" Release (1db809b8323ba0a87c148d16eb84efe39a8e7785, 2022-05-20) for Windows - let sampleFA = vector [|5.0; 6.0; 5.8; 5.7|] - let sampleFB = vector [|3.5; 3.7; 4.0; 3.3; 3.6|] - let sampleNaN = vector [|5.0; 6.0; 5.8; nan|] - let sampleInf = vector [|5.0; 6.0; 5.8; infinity|] - let sampleNegInf = vector [|5.0; 6.0; 5.8; -infinity|] - let sampleties = vector [|5.0; 5.0; 5.8; 5.3|] + let sampleFA = [|5.0; 6.0; 5.8; 5.7|] + let sampleFB = [|3.5; 3.7; 4.0; 3.3; 3.6|] + let sampleNaN = [|5.0; 6.0; 5.8; nan|] + let sampleInf = [|5.0; 6.0; 5.8; infinity|] + let sampleNegInf = [|5.0; 6.0; 5.8; -infinity|] + let sampleties = [|5.0; 5.0; 5.8; 5.3|] // calculation of the F test let fResult = FTest.testVariances sampleFA sampleFB @@ -672,7 +672,7 @@ let multiLabelConfusionMatrixTests = [2; 0; 4] ] |> array2D - |> Matrix.Generic.ofArray2D + |> Matrix.ofArray2D let expectedMLCM = { @@ -684,7 +684,7 @@ let multiLabelConfusionMatrixTests = [2; 0; 4] ] |> array2D - |> Matrix.Generic.ofArray2D + |> Matrix.ofArray2D } let multiLabelCM = MultiLabelConfusionMatrix.create([|"A";"B";"C"|], c) @@ -816,7 +816,7 @@ let comparisonMetricsTests = [2; 0; 4] ] |> array2D - |> Matrix.Generic.ofArray2D + |> Matrix.ofArray2D let multiLabelCM = MultiLabelConfusionMatrix.create([|"A";"B";"C"|], c) From 7d4777ea308f24a0e2a20778f87d6764b0c81ed0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20M=C3=BChlhaus?= Date: Fri, 11 Apr 2025 09:53:30 +0200 Subject: [PATCH 069/121] Add Matrix compare by value --- .github/workflows/build-and-test.yml | 8 ++-- build/build.fsproj | 4 ++ global.json | 4 +- src/FSharp.Stats/AlgTypes/Matrix.fs | 43 ++++++++++++++++++- src/FSharp.Stats/AlgTypes/VectorExt.fs | 1 + src/FSharp.Stats/Algebra/LinearAlgebra.fs | 3 ++ .../FSharp.Stats.Tests.fsproj | 4 ++ 7 files changed, 59 insertions(+), 8 deletions(-) diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml index 1e03eb3f9..ce45285cf 100644 --- a/.github/workflows/build-and-test.yml +++ b/.github/workflows/build-and-test.yml @@ -13,10 +13,10 @@ jobs: steps: - uses: actions/checkout@v2 - - name: Setup .NET 6 + - name: Setup .NET uses: actions/setup-dotnet@v1 with: - dotnet-version: '6.x.x' + dotnet-version: '9.x.x' - name: Restore local tools run: dotnet tool restore - name: make script executable @@ -31,10 +31,10 @@ jobs: steps: - uses: actions/checkout@v2 - - name: Setup .NET 6 + - name: Setup .NET uses: actions/setup-dotnet@v1 with: - dotnet-version: '6.x.x' + dotnet-version: '9.x.x' - name: Restore local tools run: dotnet tool restore - name: Build and test diff --git a/build/build.fsproj b/build/build.fsproj index b3f0ebf49..f978756ba 100644 --- a/build/build.fsproj +++ b/build/build.fsproj @@ -31,4 +31,8 @@ + + + + diff --git a/global.json b/global.json index 501e79a87..f15a95928 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "sdk": { - "version": "8.0.100", - "rollForward": "latestFeature" + "version": "9.0.100", + "rollForward": "latestMinor" } } \ No newline at end of file diff --git a/src/FSharp.Stats/AlgTypes/Matrix.fs b/src/FSharp.Stats/AlgTypes/Matrix.fs index ccfd95f57..13f95e15a 100644 --- a/src/FSharp.Stats/AlgTypes/Matrix.fs +++ b/src/FSharp.Stats/AlgTypes/Matrix.fs @@ -14,7 +14,8 @@ open System.Runtime.InteropServices type Matrix<'T when 'T :> Numerics.INumber<'T> and 'T : (new: unit -> 'T) and 'T : struct - and 'T :> ValueType> + and 'T :> ValueType + and 'T : equality> (rows: int, cols: int, data: Vector<'T>) = /// Exposes the raw underlying data array (row-major flattened). @@ -36,7 +37,45 @@ type Matrix<'T when 'T :> Numerics.INumber<'T> if i < 0 || i >= rows || j < 0 || j >= cols then invalidArg "index" $"Index out of range: ({i}, {j})" data.[i * cols + j] <- value - + + // Implement IEquatable so that F# structural equality can use it + interface IEquatable> with + member this.Equals(other: Matrix<'T>) = + + // 1) Check dimension + if rows <> other.NumRows || cols <> other.NumCols then + false + else + // 2) Compare all elements + let otherData = other.Data + let mutable i = 0 + let mutable eq = true + while eq && i < data.Length do + if data[i] <> otherData[i] then + eq <- false + i <- i + 1 + eq + + // Override Object.Equals + override this.Equals(obj: obj) = + match obj with + | :? Matrix<'T> as other -> + (this :> IEquatable>).Equals(other) + | _ -> false + + // Override Object.GetHashCode + override this.GetHashCode() = + // We'll combine the row/col count plus some portion of the data to avoid huge cost. + // There's no perfect hashing for big arrays, but here's a simple example: + + let mutable hash = HashCode() + hash.Add(rows) + hash.Add(cols) + // Optionally: incorporate some or all elements + // For big arrays, consider sampling or a rolling hash approach. + for i in 0 .. data.Length - 1 do + hash.Add(data[i]) + hash.ToHashCode() /// /// Returns a new Matrix<'T> that is the slice of rows [rowStart..rowEnd] diff --git a/src/FSharp.Stats/AlgTypes/VectorExt.fs b/src/FSharp.Stats/AlgTypes/VectorExt.fs index ed6ba70b2..46ce0dfa5 100644 --- a/src/FSharp.Stats/AlgTypes/VectorExt.fs +++ b/src/FSharp.Stats/AlgTypes/VectorExt.fs @@ -13,6 +13,7 @@ module Vector = let inline cross<'T when 'T :> Numerics.INumber<'T> and 'T : (new: unit -> 'T) and 'T : struct + and 'T : equality and 'T :> ValueType> (colvec: Vector<'T>) (rowvec:Vector<'T>) : Matrix<'T> = if colvec.Length <> rowvec.Length then invalidArg "" "Vector must have the same length to compute the dot product." diff --git a/src/FSharp.Stats/Algebra/LinearAlgebra.fs b/src/FSharp.Stats/Algebra/LinearAlgebra.fs index e3cc65a1f..a291897b0 100644 --- a/src/FSharp.Stats/Algebra/LinearAlgebra.fs +++ b/src/FSharp.Stats/Algebra/LinearAlgebra.fs @@ -43,6 +43,7 @@ type LinearAlgebra = static member inline qrModifiedGramSchmidt<'T when 'T :> Numerics.INumber<'T> and 'T : (new: unit -> 'T) and 'T : struct + and 'T : equality and 'T :> ValueType and 'T :> Numerics.IRootFunctions<'T>> (A: Matrix<'T>) : Matrix<'T> * Matrix<'T> = @@ -80,6 +81,7 @@ type LinearAlgebra = static member inline backSubstitute<'T when 'T :> Numerics.INumber<'T> and 'T : (new: unit -> 'T) and 'T : struct + and 'T : equality and 'T :> ValueType> (r: Matrix<'T>) (y: Vector<'T>) : Vector<'T> = @@ -106,6 +108,7 @@ type LinearAlgebra = static member inline solveLinearQR<'T when 'T :> Numerics.INumber<'T> and 'T : (new: unit -> 'T) and 'T : struct + and 'T : equality and 'T :> ValueType and 'T :> Numerics.IRootFunctions<'T>> (A: Matrix<'T>) diff --git a/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj b/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj index 45a174267..e213510c0 100644 --- a/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj +++ b/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj @@ -5,6 +5,10 @@ false + + + + From 1e85c6721072ddfc03d4950e0419cc5bb97ad52d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20M=C3=BChlhaus?= Date: Fri, 11 Apr 2025 14:43:15 +0200 Subject: [PATCH 070/121] Add some updated test cases --- .../AlgTypes/AlgTypesTopLevelOps.fs | 9 ++++ src/FSharp.Stats/AlgTypes/MatrixExt.fs | 24 +++++++++ src/FSharp.Stats/AlgTypes/VectorExt.fs | 4 ++ src/FSharp.Stats/FSharp.Stats.fsproj | 1 + tests/FSharp.Stats.Tests/Covariance.fs | 50 +++++++++---------- .../DistributionsContinuous.fs | 16 +++--- .../DistributionsDiscrete.fs | 36 ++++++------- .../FSharp.Stats.Tests.fsproj | 12 ++++- tests/FSharp.Stats.Tests/LinearAlgebra.fs | 13 +++-- 9 files changed, 106 insertions(+), 59 deletions(-) create mode 100644 src/FSharp.Stats/AlgTypes/AlgTypesTopLevelOps.fs diff --git a/src/FSharp.Stats/AlgTypes/AlgTypesTopLevelOps.fs b/src/FSharp.Stats/AlgTypes/AlgTypesTopLevelOps.fs new file mode 100644 index 000000000..9e2f89788 --- /dev/null +++ b/src/FSharp.Stats/AlgTypes/AlgTypesTopLevelOps.fs @@ -0,0 +1,9 @@ +namespace FSharp.Stats + + +[] +module AlgTypesTopLevelOps = + + let matrix ll = Matrix.ofRowSeq ll + let vector l = Vector.ofSeq l + //let rowvec l = RowVector.ofSeq l diff --git a/src/FSharp.Stats/AlgTypes/MatrixExt.fs b/src/FSharp.Stats/AlgTypes/MatrixExt.fs index d9cf579a3..5d4386ab6 100644 --- a/src/FSharp.Stats/AlgTypes/MatrixExt.fs +++ b/src/FSharp.Stats/AlgTypes/MatrixExt.fs @@ -110,6 +110,30 @@ module Matrix = let ofRows (rows : 'T[][]) : Matrix<'T> = Matrix.ofJaggedArray rows + /// Creates a matrix from a sequence of row sequences + let inline ofRowSeq (rows: seq<#seq<'T>>) : Matrix<'T> = + // Convert the outer seq to an array of row-seqs + let rowArr = rows |> Seq.toArray + if rowArr.Length = 0 then + invalidArg "rows" "Cannot create a matrix from an empty sequence of rows." + + // Determine the number of columns by checking the first row’s length + let colCount = rowArr.[0] |> Seq.length + + // Verify all rows have the same length + for i in 1 .. rowArr.Length - 1 do + let currentLen = rowArr.[i] |> Seq.length + if currentLen <> colCount then + invalidArg "rows" (sprintf "Row %d has length %d, expected %d." i currentLen colCount) + + // Flatten all row-seqs into a single array (row-major order) + let data = + rowArr + |> Array.collect (fun rowSeq -> rowSeq |> Seq.toArray) + + // Construct the matrix + Matrix<'T>(rowArr.Length, colCount, data) + let mapiRows (f: int -> Vector<'T> -> Vector<'U>) (m:Matrix<'T>) : Matrix<'U> = Matrix.getRows m |> Array.mapi (fun i v -> f i v) diff --git a/src/FSharp.Stats/AlgTypes/VectorExt.fs b/src/FSharp.Stats/AlgTypes/VectorExt.fs index 46ce0dfa5..cc9393c25 100644 --- a/src/FSharp.Stats/AlgTypes/VectorExt.fs +++ b/src/FSharp.Stats/AlgTypes/VectorExt.fs @@ -192,3 +192,7 @@ module Vector = for i = 0 to n - 1 do result.[i] <- b.[P i] result + + /// + let inline ofSeq (s:seq<'T>) : Vector<'T> = + s |> Array.ofSeq diff --git a/src/FSharp.Stats/FSharp.Stats.fsproj b/src/FSharp.Stats/FSharp.Stats.fsproj index b5c4c4605..542b345c4 100644 --- a/src/FSharp.Stats/FSharp.Stats.fsproj +++ b/src/FSharp.Stats/FSharp.Stats.fsproj @@ -36,6 +36,7 @@ + diff --git a/tests/FSharp.Stats.Tests/Covariance.fs b/tests/FSharp.Stats.Tests/Covariance.fs index 43f9c3a4e..93c0c93ec 100644 --- a/tests/FSharp.Stats.Tests/Covariance.fs +++ b/tests/FSharp.Stats.Tests/Covariance.fs @@ -107,31 +107,31 @@ let arrayTests = //tested in comparison with //https://www.itl.nist.gov/div898/handbook/pmc/section5/pmc541.htm -[] -let matrixTests = - let m = - [| - [|4.0;4.2;3.9;4.3;4.1|] - [|2.0;2.1;2.0;2.1;2.2|] - [|0.60;0.59;0.58;0.62;0.63|] - |] - |> matrix +//[] +//let matrixTests = +// let m = +// [| +// [|4.0;4.2;3.9;4.3;4.1|] +// [|2.0;2.1;2.0;2.1;2.2|] +// [|0.60;0.59;0.58;0.62;0.63|] +// |] +// |> matrix - testList "Matrix" [ - testCase "rowSampleCovarianceMatrixOf" <| fun () -> - let actual = Matrix.rowSampleCovarianceMatrixOf m - let expected = - [| - [|0.025; 0.0075; 0.00175|] - [|0.0075; 0.0070; 0.00135|] - [|0.00175;0.00135;0.00043|] - |] - |> matrix - let difference = - actual - expected - |> Matrix.mapiCols (fun i x -> Seq.max x) - |> Seq.max +// testList "Matrix" [ +// testCase "rowSampleCovarianceMatrixOf" <| fun () -> +// let actual = Matrix.rowSampleCovarianceMatrixOf m +// let expected = +// [| +// [|0.025; 0.0075; 0.00175|] +// [|0.0075; 0.0070; 0.00135|] +// [|0.00175;0.00135;0.00043|] +// |] +// |> matrix +// let difference = +// actual - expected +// |> Matrix.mapiCols (fun i x -> Seq.max x) +// |> Seq.max - Expect.floatClose Accuracy.high difference 0. "Should be equal (double precision)" - ] +// Expect.floatClose Accuracy.high difference 0. "Should be equal (double precision)" +// ] diff --git a/tests/FSharp.Stats.Tests/DistributionsContinuous.fs b/tests/FSharp.Stats.Tests/DistributionsContinuous.fs index 2a6b19c63..56f963b75 100644 --- a/tests/FSharp.Stats.Tests/DistributionsContinuous.fs +++ b/tests/FSharp.Stats.Tests/DistributionsContinuous.fs @@ -644,15 +644,15 @@ let chiTests = ] let multivariateNormalTests = - let mvn = Continuous.MultivariateNormal.Init (vector [0.;0.;0.;0.;0.]) (Matrix.identity 5) + let mvn = Continuous.MultivariateNormal.Init ([|0.;0.;0.;0.;0.|]) (Matrix.identity 5) let pdfs= [| - [0.537667139546100;3.578396939725760;-0.124144348216312;0.488893770311789;-1.068870458168032] - [0.318765239858981;0.725404224946106;0.671497133608080;0.293871467096658;0.325190539456195] - [-0.433592022305684;0.714742903826096;0.717238651328838;0.888395631757642;1.370298540095228] + [| 0.537667139546100;3.578396939725760;-0.124144348216312;0.488893770311789;-1.068870458168032 |] + [| 0.318765239858981;0.725404224946106;0.671497133608080;0.293871467096658;0.325190539456195 |] + [| -0.433592022305684;0.714742903826096;0.717238651328838;0.888395631757642;1.370298540095228 |] |] |> Array.map (fun v -> - mvn.PDF (vector v) + mvn.PDF v ) // TestCases from Matlab: (* @@ -665,10 +665,10 @@ let multivariateNormalTests = testList "Distributions.multivariateNormal" [ testCase "Parameters" <| fun () -> let param = - match (Continuous.MultivariateNormal.Init (vector [1.;0.4]) (matrix [[0.3;2.3];[1.2;4.3]])).Parameters with + match (Continuous.MultivariateNormal.Init ([|1.;0.4|]) (matrix [[0.3;2.3];[1.2;4.3]])).Parameters with | MultivariateNormal x -> x.Mean,x.StandardDeviation - | _ -> (vector [],matrix[]) - Expect.equal param ((vector [1.;0.4]),(matrix [[0.3;2.3];[1.2;4.3]])) "Distribution parameters are incorrect." + | _ -> ([||],matrix[]) + Expect.equal param (( [|1.;0.4|]),(matrix [[0.3;2.3];[1.2;4.3]])) "Distribution parameters are incorrect." testCase "PDF.testCase_1" <| fun () -> Expect.floatClose Accuracy.veryHigh 0.000007209186311 pdfs.[0] "Should be equal" testCase "PDF.testCase_2" <| fun () -> diff --git a/tests/FSharp.Stats.Tests/DistributionsDiscrete.fs b/tests/FSharp.Stats.Tests/DistributionsDiscrete.fs index a4f9ff8e9..029354c87 100644 --- a/tests/FSharp.Stats.Tests/DistributionsDiscrete.fs +++ b/tests/FSharp.Stats.Tests/DistributionsDiscrete.fs @@ -383,15 +383,15 @@ let binomialTests = [] let multinomialTests = // TestCases from R stats: dmultinom(prob, x) - let prob1 = vector [0.2;0.4;0.4;0.] - let x1 = Vector.Generic.ofList [2;4;2;0] + let prob1 = [|0.2;0.4;0.4;0.|] + let x1 = [|2;4;2;0|] - let prob2 = vector [0.02;0.04;0.02;0.;0.01;0.1;0.81] - let x2 = Vector.Generic.ofList [2;4;2;0;1;10;100] + let prob2 = [|0.02;0.04;0.02;0.;0.01;0.1;0.81|] + let x2 = [|2;4;2;0;1;10;100|] testList "Distributions.Discrete.Multinominal" [ testCase "Mean" <| fun () -> let testCase = Discrete.Multinomial.Mean prob1 100 - let means = vector [20.;40.;40.;0.] + let means = [|20.;40.;40.;0.|] TestExtensions.TestExtensions.sequenceEqual Accuracy.veryHigh testCase means @@ -399,7 +399,7 @@ let multinomialTests = testCase "Variance" <| fun () -> let testCase = Discrete.Multinomial.Variance prob2 119 - let variances = vector [2.3324;4.5696;2.3324;0;1.1781;10.71;18.3141] + let variances = [|2.3324;4.5696;2.3324;0;1.1781;10.71;18.3141|] TestExtensions.TestExtensions.sequenceEqual Accuracy.veryHigh testCase variances @@ -420,8 +420,8 @@ let multinomialTests = testCase pmf "Multinominal.PMF is incorrect" - let prob1 = vector [0.1;0.4;0.5] - let x = Vector.Generic.ofList [0;0;0] + let prob1 = [|0.1;0.4;0.5|] + let x = [|0;0;0|] let testCase3 = Discrete.Multinomial.PMF prob1 x Expect.floatClose Accuracy.veryHigh @@ -429,7 +429,7 @@ let multinomialTests = 1. "Multinominal.PMF is incorrect" - let testCase4 = Discrete.Multinomial.PMF (vector [|0.5; 0.5|]) (Vector.Generic.ofArray [|5; 5|]) + let testCase4 = Discrete.Multinomial.PMF [|0.5; 0.5|] [|5; 5|] let r_value4 = 0.2460937500001213 Expect.floatClose Accuracy.high @@ -438,7 +438,7 @@ let multinomialTests = "Multinomial.PMF (vector [|0.5; 0.5|]) (Vector.Generic.ofArray [|5; 5|]) should result in Binomial.PMF 0.5 10 5" - let testCase5 = Discrete.Multinomial.PMF (vector [|0.123; 0.877|]) (Vector.Generic.ofArray [|20; 180|]) + let testCase5 = Discrete.Multinomial.PMF [|0.123; 0.877|] [|20; 180|] Expect.floatClose Accuracy.high testCase5 @@ -448,26 +448,26 @@ let multinomialTests = testCase "Checks.pSum1" <| fun () -> - let prob2 = vector [0.1;0.3;0.5] - let x = Vector.Generic.ofList [1;2;3] + let prob2 = [|0.1;0.3;0.5|] + let x = [|1;2;3|] let testCase() = Discrete.Multinomial.PMF prob2 x Expect.throws (fun _ -> testCase() |> ignore) "p does not sum up to 1 but no error is thrown" testCase "Checks.UnequalInputLength" <| fun () -> - let prob3 = vector [0.1;0.4;0.5;0] - let x = Vector.Generic.ofList [1;2;3] + let prob3 = [|0.1;0.4;0.5;0|] + let x = [|1;2;3|] let testCase() = Discrete.Multinomial.PMF prob3 x Expect.throws (fun _ -> testCase() |> ignore) "input vectors are of unequal length" testCase "Checks.WrongProb" <| fun () -> - let prob4 = vector [1.;-0.5;0.5] - let x = Vector.Generic.ofList [1;2;3] + let prob4 = [|1.;-0.5;0.5|] + let x =[|1;2;3|] let testCase() = Discrete.Multinomial.PMF prob4 x Expect.throws (fun _ -> testCase() |> ignore) "probabilities are negative" testCase "Checks.SuccessAtProb0" <| fun () -> - let prob5 = vector [0.5;0;0.5] - let x = Vector.Generic.ofList [1;2;3] + let prob5 = [|0.5;0;0.5|] + let x = [|1;2;3|] let testCase() = Discrete.Multinomial.PMF prob5 x Expect.throws (fun _ -> testCase() |> ignore) "probabilities of 0 is associated to success event" ] diff --git a/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj b/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj index e213510c0..d889f4ce2 100644 --- a/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj +++ b/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj @@ -6,9 +6,19 @@ + + + + + + + + + + - + diff --git a/tests/FSharp.Stats.Tests/LinearAlgebra.fs b/tests/FSharp.Stats.Tests/LinearAlgebra.fs index 989ea81f0..f0a96db43 100644 --- a/tests/FSharp.Stats.Tests/LinearAlgebra.fs +++ b/tests/FSharp.Stats.Tests/LinearAlgebra.fs @@ -4,16 +4,15 @@ open Expecto open FSharp.Stats open FSharp.Stats.Algebra -open FSharp.Stats.Algebra.LinearAlgebraManaged open TestExtensions [] let managedSVDTests = let svdManaged A = - let s,u,vt = LinearAlgebraManaged.SVD A + let s,u,vt = LinearAlgebra.SVD A let sM = - let tmp= Matrix.create A.NumRows A.NumCols 0. + let tmp= Matrix.zeroCreate A.NumRows A.NumCols for i = 0 to s.Length-1 do tmp.[i,i] <- s.[i] tmp @@ -26,15 +25,15 @@ let managedSVDTests = testCase "m=n Matrix: Recover from decomposition" <| fun () -> let u,s,vt = svdManaged mEqualN let mEqualNRecov = (u * s * vt) - let m = mEqualN |> Matrix.toJaggedArray |> Array.concat - let m' = mEqualNRecov |> Matrix.toJaggedArray |> Array.concat + let m = mEqualN.toJaggedArray() |> Array.concat + let m' = mEqualNRecov.toJaggedArray() |> Array.concat TestExtensions.sequenceEqual Accuracy.high m m' "Matrices computed by SVD did not yield the initial matrix when multiplied." testCase "m=n Matrix: u and vt consist of unit vectors, row- and column- wise." <| fun () -> let u,s,vt = svdManaged mEqualN let vecNorms = [ - u |> Matrix.mapCols Vector.norm |> RowVector.toArray + u |> Matrix.mapiCols (fun _ v -> Vector.norm v) vt|> Matrix.mapCols Vector.norm |> RowVector.toArray u |> Matrix.mapRows (fun x -> x.Transpose |> Vector.norm) |> Vector.toArray vt|> Matrix.mapRows (fun x -> x.Transpose |> Vector.norm) |> Vector.toArray @@ -43,7 +42,7 @@ let managedSVDTests = TestExtensions.sequenceEqual Accuracy.high (Array.create vecNorms.Length 1.) vecNorms "Matrices computed by SVD did not consist of unit vectors, row- and column- wise." testCase "m=n Matrix: s contains correct singular values." <| fun () -> - let s,u,vt = LinearAlgebraManaged.SVD mEqualN + let s,u,vt = LinearAlgebra.SVD mEqualN TestExtensions.sequenceEqual Accuracy.high ([|15.81461344;2.213142934|]) s "Matrices computed by SVD did not yield correct singular values." testCase "m From 967a802c1c0e3869a32a00cd3d17b7c68ab1aa47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20M=C3=BChlhaus?= Date: Fri, 11 Apr 2025 16:01:17 +0200 Subject: [PATCH 071/121] Add Vector tests --- src/FSharp.Stats/AlgTypes/Vector.fs | 2 +- src/FSharp.Stats/AlgTypes/VectorExt.fs | 19 +- src/FSharp.Stats/Playground.fsx | 16 +- .../FSharp.Stats.Tests.fsproj | 1 + tests/FSharp.Stats.Tests/Vector.fs | 616 +++++++++++++++++- 5 files changed, 632 insertions(+), 22 deletions(-) diff --git a/src/FSharp.Stats/AlgTypes/Vector.fs b/src/FSharp.Stats/AlgTypes/Vector.fs index 29523787d..d32954d85 100644 --- a/src/FSharp.Stats/AlgTypes/Vector.fs +++ b/src/FSharp.Stats/AlgTypes/Vector.fs @@ -253,6 +253,6 @@ type Vector = and 'T :> ValueType> (v:Vector<'T>) : 'T = if v.Length = 0 then invalidArg "v" "Cannot compute min of empty vector." - Acceleration.SIMDUtils.fold (fun a b -> Numerics.Vector.Max(a, b)) min v.[0] v + Acceleration.SIMDUtils.fold (fun a b -> Numerics.Vector.Max(a, b)) max v.[0] v diff --git a/src/FSharp.Stats/AlgTypes/VectorExt.fs b/src/FSharp.Stats/AlgTypes/VectorExt.fs index cc9393c25..22be07622 100644 --- a/src/FSharp.Stats/AlgTypes/VectorExt.fs +++ b/src/FSharp.Stats/AlgTypes/VectorExt.fs @@ -9,16 +9,29 @@ module Vector = /// Computes the vector cross product a^Tb /// The first vector is column vector. /// The second vector is the row vector. - /// The cross product of the two vectors. + /// The cross product (or outer product) of the two vectors. let inline cross<'T when 'T :> Numerics.INumber<'T> and 'T : (new: unit -> 'T) and 'T : struct and 'T : equality and 'T :> ValueType> (colvec: Vector<'T>) (rowvec:Vector<'T>) : Matrix<'T> = + //TODO: SIMD Acceleration! + if colvec.Length <> rowvec.Length then invalidArg "" "Vector must have the same length to compute the dot product." - let data = Acceleration.SIMDUtils.map2Unchecked ( * ) ( * ) colvec rowvec - Matrix(colvec.Length,rowvec.Length,data) + let n = colvec.Length + let m = rowvec.Length + + // Allocate the n*m storage + let data = Array.zeroCreate<'T> (n * m) + + // Fill with colvec[i] * rowvec[j], typical row-major arrangement + for i in 0 .. n - 1 do + for j in 0 .. m - 1 do + data.[i * m + j] <- colvec.[i] * rowvec.[j] + + // Build the matrix (n x m) + Matrix<'T>(n, m, data) /// Indexed fold over a vector diff --git a/src/FSharp.Stats/Playground.fsx b/src/FSharp.Stats/Playground.fsx index a6b066450..31b063053 100644 --- a/src/FSharp.Stats/Playground.fsx +++ b/src/FSharp.Stats/Playground.fsx @@ -1,4 +1,4 @@ -#I "bin/Debug/netstandard2.0" +#I "bin/Release/.net8.0" #r "FSharp.Stats.dll" #r "nuget: Plotly.NET" @@ -7,6 +7,20 @@ open FSharp.Stats open FSharp.Stats.Distributions open Plotly.NET +let a = 1 % 3 // 1 +let b = 2 % 3 // 2 +let c = 3 % 3 // 0 + + +let colvec = [| 1.0; 2.0; 3.0 |] +let rowvec = [| 4.0; 5.0; 6.0 |] + +// The expected 3x3 matrix is computed by: +// [ [1.0*4.0, 1.0*5.0, 1.0*6.0] +// [2.0*4.0, 2.0*5.0, 2.0*6.0] +// [3.0*4.0, 3.0*5.0, 3.0*6.0] ] +let result = Vector.cross colvec rowvec + let alpha = 9.9 //0.4 let beta = 31 //4.2 diff --git a/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj b/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj index d889f4ce2..12e8b8030 100644 --- a/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj +++ b/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj @@ -18,6 +18,7 @@ + diff --git a/tests/FSharp.Stats.Tests/Vector.fs b/tests/FSharp.Stats.Tests/Vector.fs index 42009b896..70cfa5713 100644 --- a/tests/FSharp.Stats.Tests/Vector.fs +++ b/tests/FSharp.Stats.Tests/Vector.fs @@ -1,23 +1,605 @@ module VectorTests -open Expecto +open System +open Expecto open FSharp.Stats -open FSharp.Stats.Vector - -let private testVectorA = - let values = [|0.;3.;6.|] - Vector(Some (Instances.FloatNumerics :> INumeric),values) [] -let covarianceTests = - let x = vector [5.;12.;18.;-23.;45.] - let y = vector [2.;8.;18.;-20.;28.] - - testList "Vector" [ - testCase "cov" <| fun () -> - let cov = Vector.cov x y - Expect.floatClose Accuracy.high cov 434.90 "Should be equal (double precision)" - testCase "covPopulation" <| fun () -> - let covPop = Vector.covPopulation x y - Expect.floatClose Accuracy.high covPop 347.92 "Should be equal (double precision)" +let vectorTests = + testList "Vector Tests" [ + + // ====================================================================== + // INT TESTS + // ====================================================================== + testList "Integer Vector Tests" [ + + // ------------------------------------------------------------------ + // Add + // ------------------------------------------------------------------ + testCase "add: integer vectors of same length" <| fun _ -> + let v1 = [| 1; 2; 3 |] + let v2 = [| 4; 5; 6 |] + let result = Vector.add v1 v2 + let expected = [| 5; 7; 9 |] + Expect.equal result expected "Should add each element pairwise" + + testCase "add: throws on dimension mismatch" <| fun _ -> + let v1 = [| 1; 2 |] + let v2 = [| 1; 2; 3 |] + Expect.throwsT (fun () -> Vector.add v1 v2 |> ignore) + "Should throw ArgumentException when vectors differ in length" + + // ------------------------------------------------------------------ + // Subtract + // ------------------------------------------------------------------ + testCase "subtract: integer vectors of same length" <| fun _ -> + let v1 = [| 5; 5; 5 |] + let v2 = [| 1; 2; 3 |] + let result = Vector.subtract v1 v2 + let expected = [| 4; 3; 2 |] + Expect.equal result expected "Should subtract each element pairwise" + + testCase "subtract: throws on dimension mismatch" <| fun _ -> + let v1 = [| 1; 2; 3 |] + let v2 = [| 1; 2 |] + Expect.throwsT (fun () -> Vector.subtract v1 v2 |> ignore) + "Should throw ArgumentException when vectors differ in length" + + // ------------------------------------------------------------------ + // Multiply + // ------------------------------------------------------------------ + testCase "multiply: integer vectors of same length" <| fun _ -> + let v1 = [| 2; 2; 2 |] + let v2 = [| 3; 4; 5 |] + let result = Vector.multiply v1 v2 + let expected = [| 6; 8; 10 |] + Expect.equal result expected "Should multiply each element pairwise" + + testCase "multiply: throws on dimension mismatch" <| fun _ -> + let v1 = [| 2; 2 |] + let v2 = [| 3; 4; 5 |] + Expect.throwsT (fun () -> Vector.multiply v1 v2 |> ignore) + "Should throw ArgumentException when vectors differ in length" + + // ------------------------------------------------------------------ + // Divide + // ------------------------------------------------------------------ + testCase "divide: integer vectors of same length" <| fun _ -> + let v1 = [| 10; 20; 30 |] + let v2 = [| 2; 5; 5 |] + let result = Vector.divide v1 v2 + let expected = [| 5; 4; 6 |] + Expect.equal result expected "Should divide each element pairwise" + + testCase "divide: throws on dimension mismatch" <| fun _ -> + let v1 = [| 10; 20 |] + let v2 = [| 2; 5; 5 |] + Expect.throwsT (fun () -> Vector.divide v1 v2 |> ignore) + "Should throw ArgumentException when vectors differ in length" + + // ------------------------------------------------------------------ + // Scalar Operations + // ------------------------------------------------------------------ + testCase "addScalar: adds scalar to every element" <| fun _ -> + let v = [| 1; 2; 3 |] + let scalar = 5 + let result = Vector.addScalar v scalar + let expected = [| 6; 7; 8 |] + Expect.equal result expected "Should add the scalar to each element" + + testCase "subtractScalar: subtracts scalar from every element" <| fun _ -> + let v = [| 1; 2; 3 |] + let scalar = 1 + let result = Vector.subtractScalar v scalar + let expected = [| 0; 1; 2 |] + Expect.equal result expected "Should subtract the scalar from each element" + + testCase "multiplyScalar: multiplies scalar to every element" <| fun _ -> + let v = [| 2; 4; 6 |] + let scalar = 3 + let result = Vector.multiplyScalar v scalar + let expected = [| 6; 12; 18 |] + Expect.equal result expected "Should multiply the scalar with each element" + + testCase "divideScalar: divides every element by scalar" <| fun _ -> + let v = [| 10; 20; 30 |] + let scalar = 10 + let result = Vector.divideScalar v scalar + let expected = [| 1; 2; 3 |] + Expect.equal result expected "Should divide each element by the scalar" + + // ------------------------------------------------------------------ + // sum + // ------------------------------------------------------------------ + testCase "sum: sums all elements of an integer vector" <| fun _ -> + let v = [| 1; 2; 3; 4 |] + let result = Vector.sum v + Expect.equal result 10 "Should be the sum of all elements" + + testCase "sum: sums an empty integer vector (should be 0)" <| fun _ -> + let v : int[] = [||] + let result = Vector.sum v + Expect.equal result 0 "Sum of empty array should be 0" + + // ------------------------------------------------------------------ + // product + // ------------------------------------------------------------------ + testCase "product: multiplies all elements of an integer vector" <| fun _ -> + let v = [| 1; 2; 3; 4 |] + let result = Vector.product v + Expect.equal result 24 "Should be the product of all elements" + + testCase "product: empty integer vector (should be 1 for identity)" <| fun _ -> + let v : int[] = [||] + let result = Vector.product v + Expect.equal result 1 "Product of empty array should be 1" + + + // ------------------------------------------------------------------ + // dot + // ------------------------------------------------------------------ + testCase "dot: computes dot product of two integer vectors" <| fun _ -> + let v1 = [| 1; 2; 3 |] + let v2 = [| 4; 5; 6 |] + let result = Vector.dot v1 v2 + // Dot = 1*4 + 2*5 + 3*6 = 4 + 10 + 18 = 32 + Expect.equal result 32 "Dot product should match expected" + + testCase "dot: throws on dimension mismatch" <| fun _ -> + let v1 = [| 1; 2 |] + let v2 = [| 3; 4; 5 |] + Expect.throwsT (fun () -> Vector.dot v1 v2 |> ignore) + "Should throw ArgumentException when vectors differ in length" + + + // ------------------------------------------------------------------ + // min + // ------------------------------------------------------------------ + testCase "min: finds minimum in a non-empty integer vector" <| fun _ -> + let v = [| 10; 2; 30; 4 |] + let result = Vector.min v + Expect.equal result 2 "Should find the smallest integer in the array" + + testCase "min: throws on empty integer vector" <| fun _ -> + let v : int[] = [||] + Expect.throwsT (fun () -> Vector.min v |> ignore) + "Should throw ArgumentException for empty vector" + + // ------------------------------------------------------------------ + // max + // ------------------------------------------------------------------ + testCase "max: finds maximum in a non-empty integer vector" <| fun _ -> + let v = [| 10; 2; 30; 4 |] + let result = Vector.max v + Expect.equal result 30 "Should find the largest integer in the array" + + testCase "max: throws on empty integer vector" <| fun _ -> + let v : int[] = [||] + Expect.throwsT (fun () -> Vector.max v |> ignore) + "Should throw ArgumentException for empty vector" + + // ------------------------------------------------------------------ + // OPERATOR TESTS (Int) + // ------------------------------------------------------------------ + testCase "vector-vector operators (int): .+ .- .* ./" <| fun _ -> + let v1 = [| 1; 2; 3 |] + let v2 = [| 4; 5; 6 |] + + // .+ + let addResult = v1 .+ v2 + Expect.equal addResult [|5; 7; 9|] "v1 .+ v2 should match element-wise add" + + // .- + let subResult = v1 .- v2 + Expect.equal subResult [|-3; -3; -3|] "v1 .- v2 should match element-wise subtract" + + // .* + let mulResult = v1 .* v2 + Expect.equal mulResult [|4; 10; 18|] "v1 .* v2 should match element-wise multiply" + + // ./ + let divResult = [| 10; 20; 30 |] ./ [| 2; 5; 5 |] + Expect.equal divResult [|5; 4; 6|] "Should match element-wise division" + + testCase "vector-scalar operators (int): .+ .- .* ./" <| fun _ -> + let v = [| 2; 4; 6 |] + + // v .+ scalar + let addScalarResult = v .+ 2 + Expect.equal addScalarResult [|4; 6; 8|] "v .+ 2 should add 2 to all elements" + + // v .- scalar + let subScalarResult = v .- 2 + Expect.equal subScalarResult [|0; 2; 4|] "v .- 2 should subtract 2 from all elements" + + // v .* scalar + let mulScalarResult = v .* 3 + Expect.equal mulScalarResult [|6; 12; 18|] "v .* 3 should multiply all elements by 3" + + // v ./ scalar + let divScalarResult = [| 10; 20; 30 |] ./ 10 + Expect.equal divScalarResult [|1; 2; 3|] "Should divide all elements by 10" + ] + + + // ====================================================================== + // FLOAT TESTS + // ====================================================================== + testList "Float Vector Tests" [ + + // ------------------------------------------------------------------ + // Add + // ------------------------------------------------------------------ + testCase "add: float vectors of same length" <| fun _ -> + let v1 = [| 1.0; 2.0; 3.0 |] + let v2 = [| 4.0; 5.0; 6.0 |] + let result = Vector.add v1 v2 + let expected = [| 5.0; 7.0; 9.0 |] + Expect.equal result expected "Should add each element pairwise" + + testCase "add: throws on dimension mismatch" <| fun _ -> + let v1 = [| 1.0; 2.0 |] + let v2 = [| 1.0; 2.0; 3.0 |] + Expect.throwsT (fun () -> Vector.add v1 v2 |> ignore) + "Should throw ArgumentException when vectors differ in length" + + // ------------------------------------------------------------------ + // Subtract + // ------------------------------------------------------------------ + testCase "subtract: float vectors of same length" <| fun _ -> + let v1 = [| 5.5; 5.0; 5.75 |] + let v2 = [| 1.5; 2.0; 3.25 |] + let result = Vector.subtract v1 v2 + let expected = [| 4.0; 3.0; 2.5 |] + Expect.equal result expected "Should subtract each element pairwise" + + // ------------------------------------------------------------------ + // Multiply + // ------------------------------------------------------------------ + testCase "multiply: float vectors of same length" <| fun _ -> + let v1 = [| 2.0; 2.5; 3.0 |] + let v2 = [| 3.0; 4.0; 5.0 |] + let result = Vector.multiply v1 v2 + let expected = [| 6.0; 10.0; 15.0 |] + Expect.equal result expected "Should multiply each element pairwise" + + // ------------------------------------------------------------------ + // Divide + // ------------------------------------------------------------------ + testCase "divide: float vectors of same length" <| fun _ -> + let v1 = [| 10.0; 20.0; 30.0 |] + let v2 = [| 2.0; 5.0; 5.0 |] + let result = Vector.divide v1 v2 + let expected = [| 5.0; 4.0; 6.0 |] + Expect.equal result expected "Should divide each element pairwise" + + // ------------------------------------------------------------------ + // Scalar Operations + // ------------------------------------------------------------------ + testCase "addScalar: adds scalar to every float element" <| fun _ -> + let v = [| 1.0; 2.0; 3.0 |] + let scalar = 5.5 + let result = Vector.addScalar v scalar + let expected = [| 6.5; 7.5; 8.5 |] + Expect.equal result expected "Should add 5.5 to each element" + + testCase "subtractScalar: subtract scalar from every float element" <| fun _ -> + let v = [| 1.0; 2.5; 3.75 |] + let scalar = 1.25 + let result = Vector.subtractScalar v scalar + let expected = [| -0.25; 1.25; 2.5 |] + Expect.equal result expected "Should subtract 1.25 from each element" + + testCase "multiplyScalar: multiplies scalar with every float element" <| fun _ -> + let v = [| 2.5; 4.0; 6.0 |] + let scalar = 2.0 + let result = Vector.multiplyScalar v scalar + let expected = [| 5.0; 8.0; 12.0 |] + Expect.equal result expected "Should multiply each element by 2.0" + + testCase "divideScalar: divides every float element by scalar" <| fun _ -> + let v = [| 10.0; 20.0; 30.0 |] + let scalar = 2.0 + let result = Vector.divideScalar v scalar + let expected = [| 5.0; 10.0; 15.0 |] + Expect.equal result expected "Should divide each element by 2.0" + + // ------------------------------------------------------------------ + // sum + // ------------------------------------------------------------------ + testCase "sum: sums all elements of a float vector" <| fun _ -> + let v = [| 1.1; 2.2; 3.3; 4.4 |] + let result = Vector.sum v + // Expect exact or near: 1.1 + 2.2 + 3.3 + 4.4 = 11.0 + Expect.floatClose Accuracy.veryHigh 11.0 result "Sum of [1.1;2.2;3.3;4.4] = 11.0" + + testCase "sum: sums empty float vector (should be 0.0)" <| fun _ -> + let v : float[] = [||] + let result = Vector.sum v + Expect.equal result 0.0 "Sum of empty array should be 0.0" + + // ------------------------------------------------------------------ + // product + // ------------------------------------------------------------------ + testCase "product: multiplies all elements of a float vector" <| fun _ -> + let v = [| 1.0; 2.0; 3.0 |] + let result = Vector.product v + Expect.equal result 6.0 "1.0 * 2.0 * 3.0 = 6.0" + + testCase "product: empty float vector" <| fun _ -> + // By definition in your code, fold starts with 1. + let v : float[] = [||] + let result = Vector.product v + Expect.equal result 1.0 "Product of empty array should be 1.0" + + // ------------------------------------------------------------------ + // mean + // ------------------------------------------------------------------ + testCase "mean: computes mean of a float vector" <| fun _ -> + let v = [| 2.0; 4.0; 6.0; 8.0 |] + let result = Vector.mean v + // (2.0 + 4.0 + 6.0 + 8.0) / 4 = 5.0 + Expect.floatClose Accuracy.veryHigh 5.0 result "Mean should be 5.0" + + testCase "mean: throws on empty float vector" <| fun _ -> + let v : float[] = [||] + Expect.throwsT (fun () -> Vector.mean v |> ignore) + "Should throw ArgumentException when float vector is empty" + + // ------------------------------------------------------------------ + // dot + // ------------------------------------------------------------------ + testCase "dot: computes dot product of two float vectors" <| fun _ -> + let v1 = [| 1.0; 2.0; 3.0 |] + let v2 = [| 4.0; 5.0; 6.0 |] + let result = Vector.dot v1 v2 + // Dot = 1*4 + 2*5 + 3*6 = 4 + 10 + 18 = 32 + Expect.floatClose Accuracy.veryHigh 32.0 result "Dot product should be 32.0" + + // ------------------------------------------------------------------ + // norm + // ------------------------------------------------------------------ + testCase "norm: computes Euclidean norm of a 3-4-5 triangle (float)" <| fun _ -> + let v = [| 3.0; 4.0 |] + let result = Vector.norm v + Expect.floatClose Accuracy.veryHigh 5.0 result "Norm of [3.0;4.0] should be 5.0" + + // ------------------------------------------------------------------ + // min + // ------------------------------------------------------------------ + testCase "min: finds minimum in a non-empty float vector" <| fun _ -> + let v = [| 10.0; 2.0; 30.5; 4.1 |] + let result = Vector.min v + Expect.equal result 2.0 "Should find the smallest float in the array" + + testCase "min: throws on empty float vector" <| fun _ -> + let v : float[] = [||] + Expect.throwsT (fun () -> Vector.min v |> ignore) + "Should throw ArgumentException for empty vector" + + // ------------------------------------------------------------------ + // max + // ------------------------------------------------------------------ + testCase "max: finds maximum in a non-empty float vector" <| fun _ -> + let v = [| 10.0; 2.0; 30.5; 4.1 |] + let result = Vector.max v + Expect.equal result 30.5 "Should find the largest float in the array" + + testCase "max: throws on empty float vector" <| fun _ -> + let v : float[] = [||] + Expect.throwsT (fun () -> Vector.max v |> ignore) + "Should throw ArgumentException for empty vector" + + // ------------------------------------------------------------------ + // OPERATOR TESTS (Float) + // ------------------------------------------------------------------ + testCase "vector-vector operators (float): .+ .- .* ./" <| fun _ -> + let v1 = [| 1.0; 2.0; 3.0 |] + let v2 = [| 4.0; 5.0; 6.0 |] + + // .+ + let addResult = v1 .+ v2 + Expect.equal addResult [|5.0; 7.0; 9.0|] "v1 .+ v2 should match element-wise add" + + // .- + let subResult = v1 .- v2 + Expect.equal subResult [|-3.0; -3.0; -3.0|] "v1 .- v2 should match element-wise subtract" + + // .* + let mulResult = v1 .* v2 + Expect.equal mulResult [|4.0; 10.0; 18.0|] "v1 .* v2 should match element-wise multiply" + + // ./ + let divResult = [| 10.0; 20.0; 30.0 |] ./ [| 2.0; 5.0; 5.0 |] + Expect.equal divResult [|5.0; 4.0; 6.0|] "Should match element-wise division" + + testCase "vector-scalar operators (float): .+ .- .* ./" <| fun _ -> + let v = [| 2.5; 4.0; 6.0 |] + + // v .+ scalar + let addScalarResult = v .+ 2.0 + Expect.equal addScalarResult [|4.5; 6.0; 8.0|] "v .+ 2.0 should add 2.0 to all elements" + + // v .- scalar + let subScalarResult = v .- 0.5 + Expect.equal subScalarResult [|2.0; 3.5; 5.5|] "v .- 0.5 should subtract 0.5 from all elements" + + // v .* scalar + let mulScalarResult = v .* 1.5 + Expect.equal mulScalarResult [|3.75; 6.0; 9.0|] "v .* 1.5 should multiply all elements by 1.5" + + // v ./ scalar + let divScalarResult = [| 10.0; 20.0; 30.0 |] ./ 10.0 + Expect.equal divScalarResult [|1.0; 2.0; 3.0|] "Should divide all elements by 10.0" + + // ------------------------------------------------------------------ + // cross (outer) product + // ------------------------------------------------------------------ + testCase "cross: computes the outer product of two float vectors" <| fun _ -> + // 'Vector.cross' is assumed to produce a 2D array (matrix) + let colvec = [| 1.0; 2.0; 3.0 |] + let rowvec = [| 4.0; 5.0; 6.0 |] + + // The expected 3x3 matrix is computed by: + // [ [1.0*4.0, 1.0*5.0, 1.0*6.0] + // [2.0*4.0, 2.0*5.0, 2.0*6.0] + // [3.0*4.0, 3.0*5.0, 3.0*6.0] ] + let result = Vector.cross colvec rowvec + let expected = + [| [|4.0; 5.0; 6.0|] + [|8.0; 10.0; 12.0|] + [|12.0;15.0; 18.0|] |] |> matrix + + Expect.equal result expected "Expected outer product of colvec and rowvec" + ] + // ====================================================================== + // Vector manipulation tests + // ====================================================================== + testList "Vector manipulation Tests" [ + + test "foldi applies a function with index to a vector" { + let v = [|1; 2; 3|] + let result = Vector.foldi (fun i acc x -> acc + i * x) 0 v + Expect.equal result 8 "Expected indexed fold result" + } + + test "mapi applies a function with index to each element" { + let v = [|1; 2; 3|] + let result = Vector.mapi (fun i x -> x + i) v + Expect.equal result [|1; 3; 5|] "Expected indexed map result" + } + + test "filter filters elements by predicate" { + let v = [|1; 2; 3; 4|] + let result = Vector.filter (fun x -> x % 2 = 0) v + Expect.equal result [|2; 4|] "Expected filtered vector" + } + + test "init creates a vector using a generator function" { + let result = Vector.init 5 (fun i -> i * 2) + Expect.equal result [|0; 2; 4; 6; 8|] "Expected initialized vector" + } + + test "slice extracts a slice from a vector" { + let v = [|1; 2; 3; 4; 5|] + let result = Vector.slice 1 3 v + Expect.equal result [|2; 3; 4|] "Expected sliced vector" + } + + test "argmax finds the index of the maximum value" { + let v = [|1; 3; 2|] + let result = Vector.argmax v + Expect.equal result 1 "Expected index of maximum value" + } + + test "argmin finds the index of the minimum value" { + let v = [|3; 1; 2|] + let result = Vector.argmin v + Expect.equal result 1 "Expected index of minimum value" + } + + test "padRight pads a vector to a given length" { + let v = [|1; 2|] + let result = Vector.padRight 5 0 v + Expect.equal result [|1; 2; 0; 0; 0|] "Expected padded vector" + } + + test "zip combines two vectors with indices" { + let v1 = [|1; 2; 3|] + let v2 = [|4; 5; 6|] + let result = Vector.zip v1 v2 + Expect.equal result [|(0, 1, 4); (1, 2, 5); (2, 3, 6)|] "Expected zipped vector" + } + + test "argminBy finds the index of the minimum value using a projection" { + let v = [|1; 2; 3|] + let result = Vector.argminBy (fun x -> -x) v + Expect.equal result 2 "Expected index of minimum value by projection" + } + + test "argmaxBy finds the index of the maximum value using a projection" { + let v = [|1; 2; 3|] + let result = Vector.argmaxBy (fun x -> -x) v + Expect.equal result 0 "Expected index of maximum value by projection" + } + + test "tryFindIndex finds the index of the first matching element" { + let v = [|1; 2; 3|] + let result = Vector.tryFindIndex (fun x -> x = 2) v + Expect.equal result (Some 1) "Expected index of first matching element" + } + + test "findIndex finds the index of the first matching element or throws" { + let v = [|1; 2; 3|] + let result = Vector.findIndex (fun x -> x = 2) v + Expect.equal result 1 "Expected index of first matching element" + } + + test "enumerateNonZero enumerates non-zero elements with indices" { + let v = [|0; 1; 0; 2|] + let result = Vector.enumerateNonZero v + Expect.equal result [|(1, 1); (3, 2)|] "Expected non-zero elements with indices" + } + + test "split splits a vector into prefix and suffix" { + let v = [|1; 2; 3; 4|] + let prefix, suffix = Vector.split 2 v + Expect.equal prefix [|1; 2|] "Expected prefix" + Expect.equal suffix [|3; 4|] "Expected suffix" + } + + test "chunk chunks a vector into equally sized pieces" { + let v = [|1; 2; 3; 4; 5|] + let result = Vector.chunk 2 v + Expect.equal result [|[|1; 2|]; [|3; 4|]; [|5|]|] "Expected chunked vector" + } + + test "windowed creates a sliding window over the vector" { + let v = [|1; 2; 3; 4|] + let result = Vector.windowed 2 v + Expect.equal result [|[|1; 2|]; [|2; 3|]; [|3; 4|]|] "Expected sliding windows" + } + + test "splitVector splits a vector based on indices" { + let v = [|1; 2; 3; 4|] + let nvi, nv = Vector.splitVector [|1; 3|] v + Expect.equal nvi [|2; 4|] "Expected extracted elements" + Expect.equal nv [|1; 3|] "Expected remaining elements" + } + + test "permuteBy permutes a vector using a permutation function" { + let v = [|1; 2; 3|] + let result = Vector.permuteBy (fun i -> (i + 1) % 3) v // 1 2 0 + Expect.equal result [|2; 3; 1|] "Expected permuted vector" + } + + test "ofSeq converts a sequence to a vector" { + let seq = seq { 1; 2; 3 } + let result = Vector.ofSeq seq + Expect.equal result [|1; 2; 3|] "Expected vector from sequence" + } + ] + ] + + + + + +//let private testVectorA = +// let values = [|0.;3.;6.|] +// Vector(Some (Instances.FloatNumerics :> INumeric),values) + +//[] +//let covarianceTests = +// let x = vector [5.;12.;18.;-23.;45.] +// let y = vector [2.;8.;18.;-20.;28.] + +// testList "Vector" [ +// testCase "cov" <| fun () -> +// let cov = Vector.cov x y +// Expect.floatClose Accuracy.high cov 434.90 "Should be equal (double precision)" +// testCase "covPopulation" <| fun () -> +// let covPop = Vector.covPopulation x y +// Expect.floatClose Accuracy.high covPop 347.92 "Should be equal (double precision)" +// ] From fb2d0dd4af36ff89f072fb524bb5c2b5cc9bef1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20M=C3=BChlhaus?= Date: Fri, 11 Apr 2025 19:37:17 +0200 Subject: [PATCH 072/121] Add Matrix test cases --- src/FSharp.Stats/AlgTypes/Matrix.fs | 80 +- src/FSharp.Stats/AlgTypes/VectorOps.fs | 1 + src/FSharp.Stats/Playground.fsx | 16 +- .../FSharp.Stats.Tests.fsproj | 1 + tests/FSharp.Stats.Tests/Matrix.fs | 1626 +++-------------- 5 files changed, 371 insertions(+), 1353 deletions(-) diff --git a/src/FSharp.Stats/AlgTypes/Matrix.fs b/src/FSharp.Stats/AlgTypes/Matrix.fs index 13f95e15a..1512f91ae 100644 --- a/src/FSharp.Stats/AlgTypes/Matrix.fs +++ b/src/FSharp.Stats/AlgTypes/Matrix.fs @@ -14,8 +14,8 @@ open System.Runtime.InteropServices type Matrix<'T when 'T :> Numerics.INumber<'T> and 'T : (new: unit -> 'T) and 'T : struct - and 'T :> ValueType - and 'T : equality> + and 'T : equality + and 'T :> ValueType> (rows: int, cols: int, data: Vector<'T>) = /// Exposes the raw underlying data array (row-major flattened). @@ -421,7 +421,7 @@ type Matrix<'T when 'T :> Numerics.INumber<'T> Matrix.map2Unchecked (-) (-) a b - + /// Hadamard product static member inline multiply<'T when 'T :> Numerics.INumber<'T> and 'T : (new: unit -> 'T) @@ -660,11 +660,71 @@ type Matrix<'T when 'T :> Numerics.INumber<'T> result + /// + /// Standard matrix multiplication (A x B). + /// A is (M x K), B is (K x N) => result is (M x N). + /// Then each (row of A) .dot. (row of B^T) is done with Vector<'T> chunks. + /// + static member matmul + (A: Matrix<'T>) (B: Matrix<'T>) : Matrix<'T> = + + // 1) Dimension checks + if A.NumCols <> B.NumRows then + invalidArg (nameof B) + $"Inner dimensions mismatch. A is {A.NumRows}x{A.NumCols}, B is {B.NumRows}x{B.NumCols}" + + let M = A.NumRows + let K = A.NumCols + let N = B.NumCols + + // 2) Transpose B to get B^T => shape [N x K], row j of B^T is col j of B + let Btrans = B.Transpose() + let bTData = Btrans.Data // Now each "row" in bTData is length=K, contiguous + + // 3) We'll allocate result + let resultData = Array.zeroCreate<'T> (M * N) + let aData = A.Data + + // 4) For each row i in A, row j in B^T => element in [i*N + j] + // The row i in A is contiguous of length K => offset i*K in aData + // The row j in B^T is contiguous of length K => offset j*K in bTData + for i in 0 .. M - 1 do + let aRowOffset = i * K + let aRowSpan = aData.AsSpan(aRowOffset, K) + // Convert A's row to a "Vector<'T>" span + let aVecSpan = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(aRowSpan) + + for j in 0 .. N - 1 do + let bTRowOffset = j * K + let bTRowSpan = bTData.AsSpan(bTRowOffset, K) + // Convert B^T's row j to a "Vector<'T>" span + let bTVecSpan = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(bTRowSpan) + + // 4.a) Do the chunkwise vector multiply-add + let mutable accum = Numerics.Vector<'T>.Zero + for chunk in 0 .. aVecSpan.Length - 1 do + accum <- accum + (aVecSpan.[chunk] * bTVecSpan.[chunk]) + + // 4.b) Sum up the vector lanes to a single scalar + let mutable sum = Numerics.Vector.Sum(accum) + + // 4.c) Handle remainder elements if K not multiple of Vector<'T>.Count + let remainderStart = aVecSpan.Length * Numerics.Vector<'T>.Count + for r in remainderStart .. K - 1 do + sum <- sum + aRowSpan.[r] * bTRowSpan.[r] + + // 4.d) Place result into the final matrix + resultData.[i*N + j] <- sum + + Matrix(M, N, resultData) + + // Matrix - matrix operations - static member inline ( + ) (a: Matrix<'T>, b: Matrix<'T>) = Matrix.add a b - static member inline ( - ) (a: Matrix<'T>, b: Matrix<'T>) = Matrix.subtract a b - static member inline ( * ) (a: Matrix<'T>, b: Matrix<'T>) = Matrix.multiply a b - static member inline ( / ) (a: Matrix<'T>, b: Matrix<'T>) = Matrix.divide a b + static member inline ( + ) (a: Matrix<'T>, b: Matrix<'T>) = Matrix.add a b + static member inline ( - ) (a: Matrix<'T>, b: Matrix<'T>) = Matrix.subtract a b + static member inline ( .* ) (a: Matrix<'T>, b: Matrix<'T>) = Matrix.multiply a b + static member inline ( * ) (a: Matrix<'T>, b: Matrix<'T>) = Matrix.matmul a b + static member inline ( / ) (a: Matrix<'T>, b: Matrix<'T>) = Matrix.divide a b // Matrix - vector operations static member inline ( * ) (m: Matrix<'T>, v: Vector<'T>) = Matrix.muliplyVector m v @@ -687,11 +747,7 @@ type Matrix<'T when 'T :> Numerics.INumber<'T> - static member inline diagonal<'T - when 'T :> Numerics.INumber<'T> - and 'T : struct - and 'T : (new : unit -> 'T) - and 'T :> ValueType> + static member inline diagonal (diag: Vector<'T>) : Matrix<'T> = let n = diag.Length diff --git a/src/FSharp.Stats/AlgTypes/VectorOps.fs b/src/FSharp.Stats/AlgTypes/VectorOps.fs index 5d338291c..ab93bcd00 100644 --- a/src/FSharp.Stats/AlgTypes/VectorOps.fs +++ b/src/FSharp.Stats/AlgTypes/VectorOps.fs @@ -36,6 +36,7 @@ module VectorOpsSymbols = let inline (.-) a b = Minus.Invoke(a, b) let inline (.*) a b = Multiply.Invoke(a, b) let inline (./) a b = Divide.Invoke(a, b) + // Dot product ( @ ) //// A type extension on `'T[]` so you can do `myArray.Transposed`. diff --git a/src/FSharp.Stats/Playground.fsx b/src/FSharp.Stats/Playground.fsx index 31b063053..1087204b6 100644 --- a/src/FSharp.Stats/Playground.fsx +++ b/src/FSharp.Stats/Playground.fsx @@ -1,26 +1,14 @@ #I "bin/Release/.net8.0" #r "FSharp.Stats.dll" -#r "nuget: Plotly.NET" +//#r "nuget: Plotly.NET" open System open FSharp.Stats open FSharp.Stats.Distributions -open Plotly.NET +//open Plotly.NET -let a = 1 % 3 // 1 -let b = 2 % 3 // 2 -let c = 3 % 3 // 0 -let colvec = [| 1.0; 2.0; 3.0 |] -let rowvec = [| 4.0; 5.0; 6.0 |] - -// The expected 3x3 matrix is computed by: -// [ [1.0*4.0, 1.0*5.0, 1.0*6.0] -// [2.0*4.0, 2.0*5.0, 2.0*6.0] -// [3.0*4.0, 3.0*5.0, 3.0*6.0] ] -let result = Vector.cross colvec rowvec - let alpha = 9.9 //0.4 let beta = 31 //4.2 diff --git a/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj b/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj index 12e8b8030..df32e88d3 100644 --- a/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj +++ b/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj @@ -19,6 +19,7 @@ + diff --git a/tests/FSharp.Stats.Tests/Matrix.fs b/tests/FSharp.Stats.Tests/Matrix.fs index 754f450ef..a528aec77 100644 --- a/tests/FSharp.Stats.Tests/Matrix.fs +++ b/tests/FSharp.Stats.Tests/Matrix.fs @@ -1,1337 +1,309 @@ module MatrixTests -open Expecto +open System open FSharp.Stats -open FSharp.Stats.Matrix - -let private testRowVecA = - let values = [|1.;4.|] - RowVector(Some (Instances.FloatNumerics :> INumeric),values) - -let private testRowVecB = - let values = [|0.;3.;6.|] - RowVector(Some (Instances.FloatNumerics :> INumeric),values) - -let private testRowVecC = - let values = [|0.;3.;4.|] - RowVector(Some (Instances.FloatNumerics :> INumeric),values) - -let private testRowVecD = - let values = [|0.;0.;0.|] - RowVector(Some (Instances.FloatNumerics :> INumeric),values) - -let private testVectorA = - let values = [|0.;3.;6.|] - Vector(Some (Instances.FloatNumerics :> INumeric),values) - -let private testVectorB = - let values = [|0.;0.;0.|] - Vector(Some (Instances.FloatNumerics :> INumeric),values) - -let private testVector1LowerDiag = - let values = [|0.;5.|] - Vector(Some (Instances.FloatNumerics :> INumeric),values) - -let private testVector1UpperDiag = - let values = [|1.;4.|] - Vector(Some (Instances.FloatNumerics :> INumeric),values) - -let private testDiagonalMatrixA : Matrix = - let values = - Array2D.init - 3 - 3 - (fun i j -> - if i = j then - testVectorA.[i] - else 0. - ) - Matrix.DenseRepr - (DenseMatrix(Some (Instances.FloatNumerics :> INumeric),values)) - - -let private identity3Int : Matrix = - let values = - Array2D.init - 3 - 3 - (fun i j -> - if i = j then 1 else 0 - ) - Matrix.DenseRepr - (DenseMatrix(Some (Instances.Int32Numerics :> INumeric),values)) - - -let private identityFloat3 = - let values = - Array2D.init - 3 - 3 - (fun i j -> - if i = j then 1. else 0. - ) - Matrix.DenseRepr - (DenseMatrix(Some (Instances.FloatNumerics :> INumeric),values)) - - -let private testValuesArrRows = - [| - [|0.;1.;2.|] - [|0.;3.;4.|] - [|0.;5.;6.|] - |] - -let private testValuesArrCols = - [| - [|0.;0.;0.|] - [|1.;3.;5.|] - [|2.;4.;6.|] - |] - -let private testValues2x3 = - [| - [|0.;0.;0.|] - [|1.;3.;5.|] - |] - -let private testValues2x3Transposed = - [| - [|0.;1.|] - [|0.;3.|] - [|0.;5.|] - |] - -let private testValues3x2 = - [| - [|0.;0.|] - [|1.;3.|] - [|2.;4.|] - |] - -let private testSquareMatrixA : Matrix = - let values = - Array2D.init - 3 - 3 - (fun i j -> - testValuesArrRows.[i].[j] - ) - Matrix.DenseRepr - (DenseMatrix(Some (Instances.FloatNumerics :> INumeric),values)) - -let private testSquareMatrixB : Matrix = - let values = - Array2D.init - 3 - 3 - (fun i j -> - testValuesArrCols.[i].[j] - ) - Matrix.DenseRepr - (DenseMatrix(Some (Instances.FloatNumerics :> INumeric),values)) - - -let private test2x3Matrix : Matrix = - let values = - Array2D.init - 2 - 3 - (fun i j -> - testValues2x3.[i].[j] - ) - Matrix.DenseRepr - (DenseMatrix(Some (Instances.FloatNumerics :> INumeric),values)) - - - -let private test2x3MatrixTransposed : Matrix = - let values = - Array2D.init - 3 - 2 - (fun i j -> - testValues2x3Transposed.[i].[j] - ) - Matrix.DenseRepr - (DenseMatrix(Some (Instances.FloatNumerics :> INumeric),values)) - - -let private test3x2MatrixB : Matrix = - let values = - Array2D.init - 3 - 2 - (fun i j -> - testValues3x2.[i].[j] - ) - Matrix.DenseRepr - (DenseMatrix(Some (Instances.FloatNumerics :> INumeric),values)) - -let private testConstDiagMatrix : Matrix = - let values = - Array2D.init - 3 - 3 - (fun i j -> - if i = j then 3. else 0. - ) - Matrix.DenseRepr - (DenseMatrix(Some (Instances.FloatNumerics :> INumeric),values)) - -let private testConstMatrix : Matrix = - let values = - Array2D.init - 3 - 3 - (fun i j -> - 3. - ) - Matrix.DenseRepr - (DenseMatrix(Some (Instances.FloatNumerics :> INumeric),values)) +open Expecto -let private testScalarMatrix : Matrix = - let values = - Array2D.init - 1 - 1 - (fun i j -> - 3. - ) - Matrix.DenseRepr - (DenseMatrix(Some (Instances.FloatNumerics :> INumeric),values)) [] -let genericImplementationTests = - testList "Matrix.GenericImplementation" [ - //TO-DO: cover generic implementation here, using another numeric then float - testCase "" <| fun () -> - () - ] - -[] -let floatImplementationSparseTests = - testList "Matrix.FloatImplementation.Sparse" [ - //TO-DO: adapt all dense tests for sparse matrices - testCase "" <| fun () -> - () +let matrixTests = + testList "Matrix Tests" [ + + // ---------------------------------------------------------------------- + // Basic construction + // ---------------------------------------------------------------------- + testCase "ofJaggedArray creates matrix from jagged array" <| fun _ -> + let jagged = + [| [|0.0; 0.0|] + [|1.0; 3.0|] + [|2.0; 4.0|] |] + let mat = Matrix.ofJaggedArray jagged // We specifically test 'ofJaggedArray' here + Expect.equal mat.NumRows 3 "Matrix should have 3 rows" + Expect.equal mat.NumCols 2 "Matrix should have 2 columns" + Expect.equal mat.Data [|0.0; 0.0; 1.0; 3.0; 2.0; 4.0|] + "Flattened data should match row-major flattening" + + testCase "ofArray2D creates matrix from 2D array" <| fun _ -> + let arr2d = + array2D [ [ 1; 2 ] + [ 3; 4 ] + [ 5; 6 ] ] + let mat = Matrix.ofArray2D arr2d + Expect.equal mat.NumRows 3 "Matrix should have 3 rows" + Expect.equal mat.NumCols 2 "Matrix should have 2 columns" + Expect.equal mat.Data [|1; 2; 3; 4; 5; 6|] "Flattened data should match row-major order" + + testCase "init creates a matrix using a function of row,col" <| fun _ -> + let mat = Matrix.init 2 3 (fun r c -> float (r + c)) + // For r=0, c=0..2 => [0;1;2] + // For r=1, c=0..2 => [1;2;3] + // Flatten => [0;1;2; 1;2;3] + let expected = [|0.0; 1.0; 2.0; 1.0; 2.0; 3.0|] + Expect.equal mat.NumRows 2 "Rows = 2" + Expect.equal mat.NumCols 3 "Cols = 3" + Expect.equal mat.Data expected "Data should match the function r+c" + + testCase "ofJaggedArray throws on non-rectangular jagged input" <| fun _ -> + let jagged = + [| [|1.0; 2.0|] + [|3.0|] |] // 2nd row has length=1, first row has length=2 + Expect.throws (fun () -> Matrix.ofJaggedArray jagged |> ignore) + "Should throw due to inconsistent row lengths" + + // ---------------------------------------------------------------------- + // Access & Slicing + // ---------------------------------------------------------------------- + testCase "indexer get/set within bounds" <| fun _ -> + let mat = matrix [| [|1.0; 2.0|] + [|3.0; 4.0|] |] + Expect.equal mat.[0,0] 1.0 "Element (0,0) is 1.0" + mat.[1,1] <- 99.0 + Expect.equal mat.[1,1] 99.0 "Element (1,1) updated to 99.0" + + testCase "indexer throws on out-of-range access" <| fun _ -> + let mat = matrix [| [|1.0; 2.0|] + [|3.0; 4.0|] |] + Expect.throwsT (fun () -> let _ = mat.[999, 999] in ()) + "Indexer out of range should throw" + + testCase "GetSlice works with row and col start..end" <| fun _ -> + // 3x3 matrix + let mat = matrix [| + [|1.0; 2.0; 3.0|] + [|4.0; 5.0; 6.0|] + [|7.0; 8.0; 9.0|] + |] + // slice submatrix: rows [0..1], cols [1..2] + let subMat = mat.[0..1, 1..2] + // This submatrix should be: + // [ [2.0; 3.0] + // [5.0; 6.0] ] + Expect.equal subMat.NumRows 2 "2 rows" + Expect.equal subMat.NumCols 2 "2 cols" + Expect.equal subMat.Data [|2.0; 3.0; 5.0; 6.0|] "Flattened submatrix data" + + testCase "GetSlice throws on invalid slice range" <| fun _ -> + let mat = matrix [| [|1.;2.|] + [|3.;4.|] |] + Expect.throwsT (fun () -> mat.[0..99, *] |> ignore) + "Should throw due to invalid row end" + + // ---------------------------------------------------------------------- + // Arithmetic (element-wise) + // ---------------------------------------------------------------------- + testCase "add: element-wise addition of same-dimension matrices" <| fun _ -> + let m1 = matrix [| [|1.; 2.|] + [|3.; 4.|] |] + let m2 = matrix [| [|10.;20.|] + [|30.;40.|] |] + let result = Matrix.add m1 m2 + let expected = [| (1.+10.); (2.+20.); (3.+30.); (4.+40.) |] // => [11;22;33;44] + Expect.equal result.Data expected "Element-wise addition result" + + testCase "subtract: dimension mismatch throws" <| fun _ -> + let m1 = matrix [| [|1.;2.|] |] // 1x2 + let m2 = matrix [| [|1.;2.;3.|] |] // 1x3 + Expect.throwsT (fun () -> Matrix.subtract m1 m2 |> ignore) + "Subtract must throw if shapes differ" + + testCase "multiply & divide: element-wise" <| fun _ -> + let m1 = matrix [| [|2.;4.|] + [|6.;8.|] |] + let m2 = matrix [| [|1.;2.|] + [|3.;4.|] |] + + // multiply => [ [2.*1. , 4.*2.] ; [6.*3., 8.*4.] ] => [ [2.,8.]; [18.,32.] ] + let mulResult = Matrix.multiply m1 m2 + Expect.equal mulResult.Data [|2.; 8.; 18.; 32.|] "Element-wise multiply" + + // divide => [ [2./1., 4./2.]; [6./3., 8./4.] ] => [ [2.,2.]; [2.,2.] ] + let divResult = Matrix.divide m1 m2 + Expect.equal divResult.Data [|2.;2.;2.;2.|] "Element-wise divide" + + + // ---------------------------------------------------------------------- + // Standard matrix multiplication + // ---------------------------------------------------------------------- + testCase "matmul: 2x3 times 3x2 => 2x2 result" <| fun _ -> + // A=2x3, B=3x2 + let A = matrix [| [|1.0; 2.0; 3.0|] + [|4.0; 5.0; 6.0|] |] + let B = matrix [| [|7.0; 10.0|] + [|8.0; 11.0|] + [|9.0; 12.0|] |] + + // Expected: + // C[0,0] = 1*7 + 2*8 + 3*9 = 50 + // C[0,1] = 1*10+2*11+3*12 = 68 + // C[1,0] = 4*7 + 5*8 + 6*9 = 122 + // C[1,1] = 4*10+5*11+6*12 = 167 + let C = Matrix.matmul A B + Expect.equal C.NumRows 2 "Should have 2 rows" + Expect.equal C.NumCols 2 "Should have 2 cols" + Expect.equal C.Data [|50.0; 68.0; 122.0; 167.0|] "Check standard matmul result" + + + // ---------------------------------------------------------------------- + // Scalar Operations + // ---------------------------------------------------------------------- + testCase "addScalar, subtractScalar, multiplyScalar, divideScalar" <| fun _ -> + let m = matrix [| [|1.;2.|] + [|3.;4.|] |] + let addRes = Matrix.addScalar m 10.0 + Expect.equal addRes.Data [|11.;12.;13.;14.|] "Add 10.0 to all" + + let subRes = Matrix.subtractScalar m 1.0 + Expect.equal subRes.Data [|0.;1.;2.;3.|] "Subtract 1.0 from all" + + let mulRes = Matrix.multiplyScalar m 2.0 + Expect.equal mulRes.Data [|2.;4.;6.;8.|] "Multiply all by 2.0" + + let divRes = Matrix.divideScalar m 2.0 + Expect.equal divRes.Data [|0.5;1.;1.5;2.|] "Divide all by 2.0" + + // ---------------------------------------------------------------------- + // Matrix-Vector Multiply + // ---------------------------------------------------------------------- + testCase "m * v => standard matrix-vector product" <| fun _ -> + // 2x3 times vector of length 3 => vector of length 2 + // mat = [ [1.,2.,3.] + // [4.,5.,6.] ] + let mat = matrix [| [|1.;2.;3.|] + [|4.;5.;6.|] |] + let v = [| 10.; 20.; 30. |] + // result = [ + // row0 dot v => (1.*10. + 2.*20. + 3.*30.) = 140. + // row1 dot v => (4.*10. + 5.*20. + 6.*30.) = 320. + // ] + let result = mat * v + Expect.equal result [|140.; 320.|] "Matrix-vector product" + + testCase "v * m => row-vector times matrix => vector" <| fun _ -> + // 1x2 row vector times a 2x2 matrix => 1x2 vector + let v = [|2.; 3.|] // length=2 + let mat = matrix [| [|10.; 100.|] + [|20.; 200.|] |] + // v*m => [ (2.*10. + 3.*20.), (2.*100. + 3.*200.) ] + // => [ 2.*10. + 3.*20. , 2.*100. + 3.*200. ] + // => [ 20.+60., 200.+600. ] => [80., 800.] + let result = v * mat + Expect.equal result [|80.; 800.|] "Row-vector times matrix" + + testCase "m * v => dimension mismatch throws" <| fun _ -> + let mat = matrix [| [|1.;2.|] + [|3.;4.|] |] // 2x2 + let v = [|1.;2.;3.|] // length=3 + Expect.throwsT (fun () -> let _ = mat * v in ()) + "Matrix(2x2)*Vector(3) => dimension mismatch should throw" + + // ---------------------------------------------------------------------- + // Transpose + // ---------------------------------------------------------------------- + testCase "Transpose: changes shape and flips row<->col" <| fun _ -> + let mat = matrix [| [|1.;2.;3.|] + [|4.;5.;6.|] |] // 2x3 + let t = mat.Transpose() + Expect.equal t.NumRows 3 "Should have 3 rows" + Expect.equal t.NumCols 2 "Should have 2 cols" + Expect.equal t.Data [|1.;4.;2.;5.;3.;6.|] "Flattened transpose" + + // ---------------------------------------------------------------------- + // Identity, Diagonal, and Zero/Ones + // ---------------------------------------------------------------------- + testCase "identity n => NxN identity matrix" <| fun _ -> + let eye = Matrix.identity 3 + // => [1,0,0; 0,1,0; 0,0,1] + let expected = [|1.;0.;0.; 0.;1.;0.; 0.;0.;1.|] + Expect.equal eye.Data expected "3x3 identity" + + testCase "diagonal => builds NxN from diag vector" <| fun _ -> + let diagVec = [|10.; 20.; 30.|] + let mat = Matrix.diagonal diagVec + // => [ [10, 0, 0], + // [ 0,20, 0], + // [ 0, 0,30] ] + Expect.equal mat.NumRows 3 "3x3" + Expect.equal mat.NumCols 3 "3x3" + let expected = [|10.;0.;0.; 0.;20.;0.; 0.;0.;30.|] + Expect.equal mat.Data expected "Diagonal in main diagonal positions" + + testCase "ones => NxM matrix of all 1's" <| fun _ -> + let mat = Matrix.ones 2 3 + Expect.equal mat.Data [|1.;1.;1.;1.;1.;1.|] "2x3 of all 1." + + testCase "zeroCreate => NxM matrix of all 0's" <| fun _ -> + let mat = Matrix.zeroCreate 2 3 + Expect.equal mat.Data [|0.;0.;0.;0.;0.;0.|] "2x3 of all zero." + + // ---------------------------------------------------------------------- + // getRow / getCol + // ---------------------------------------------------------------------- + testCase "getRow gets row i as a vector" <| fun _ -> + let mat = matrix [| [|1.;2.|] + [|3.;4.|] |] + let row0 = Matrix.getRow 0 mat + let row1 = Matrix.getRow 1 mat + Expect.equal row0 [|1.;2.|] "Row 0" + Expect.equal row1 [|3.;4.|] "Row 1" + + testCase "getCol gets column j as a vector" <| fun _ -> + let mat = matrix [| [|1.;2.;3.|] + [|4.;5.;6.|] |] + let col0 = Matrix.getCol 0 mat + let col2 = Matrix.getCol 2 mat + Expect.equal col0 [|1.;4.|] "Column 0" + Expect.equal col2 [|3.;6.|] "Column 2" + + // ---------------------------------------------------------------------- + // Equality (IEquatable) + // ---------------------------------------------------------------------- + testCase "Equals returns true for same shape+elements" <| fun _ -> + let m1 = matrix [| [|1.;2.|] + [|3.;4.|] |] + // 'Matrix.create' constructs from a flattened array + let m2 = Matrix.create 2 2 [|1.;2.;3.;4.|] + Expect.isTrue (m1.Equals m2) "Matrices should be equal" + + testCase "Equals returns false for dimension mismatch" <| fun _ -> + let m1 = matrix [| [|1.;2.|] |] // 1x2 + let m2 = matrix [| [|1.;2.;3.|] |] // 1x3 + Expect.isFalse (m1.Equals m2) "Should be different shapes => not equal" + + testCase "Equals returns false for data difference" <| fun _ -> + let m1 = matrix [| [|1.;2.|] |] + let m2 = matrix [| [|1.;9.|] |] + Expect.isFalse (m1.Equals m2) "Same shape, different data => not equal" + + // ---------------------------------------------------------------------- + // Misc: toArray2D, toJaggedArray + // ---------------------------------------------------------------------- + testCase "toArray2D transforms a matrix into 2D array" <| fun _ -> + let mat = matrix [| [|1.;2.|] + [|3.;4.|] + [|5.;6.|] |] + let arr2d = mat.toArray2D() + Expect.equal (arr2d.GetLength(0)) 3 "3 rows in arr2d" + Expect.equal (arr2d.GetLength(1)) 2 "2 cols in arr2d" + Expect.equal arr2d.[2,1] 6.0 "Check element" + + testCase "toJaggedArray transforms a matrix into jagged array" <| fun _ -> + let mat = matrix [| [|7.;8.|] + [|9.;10.|] |] + let jagged = mat.toJaggedArray() + Expect.equal jagged.Length 2 "2 rows in jagged" + Expect.equal jagged.[1] [|9.;10.|] "Second row matches" + + // ---------------------------------------------------------------------- + // Slicing & Setting Row + // ---------------------------------------------------------------------- + testCase "SetRow updates row i" <| fun _ -> + let mat = matrix [| [|1.;2.|] + [|3.;4.|] |] + mat.SetRow(0, [|10.;20.|]) + Expect.equal mat.Data [|10.;20.;3.;4.|] "Row 0 replaced" + + // (Optional) More tests can be added for addRowVector, addColVector, etc. ] -[] -let floatImplementationDenseTests = - testList "Matrix.FloatImplementation.Dense" [ - //Tests for acessing and setting values in the underlying array2D - testList "Acessors" [ - - testCase "Get value" <| fun () -> - let actual = Matrix.get testSquareMatrixA 0 1 - Expect.equal actual 1. "Matrix.get returned wrong value" - - testCase "Getting value out of range should fail" <| fun () -> - Expect.throws (fun () -> Matrix.get testSquareMatrixA 0 7 |> ignore) "Getting value out of range should fail" - - testCase "Set value" <| fun () -> - - let actual = - Matrix.copy testSquareMatrixA - Matrix.set actual 0 0 1337. - - let expected = - [ - [1337.;1.;2.] - [0.;3.;4.] - [0.;5.;6.] - ] - |> matrix - - Expect.equal actual expected "Matrix.set mutated the wrong value" - - testCase "Setting value out of range should fail" <| fun () -> - Expect.throws (fun () -> Matrix.set (Matrix.copy testSquareMatrixA) 0 7 3. |> ignore) "Getting value out of range should fail" - ] - - testList "Creation" [ - - testCase "init" <| fun () -> - let actual = - Matrix.init 3 3 (fun i j -> testValuesArrRows.[i].[j]) - Expect.equal actual testSquareMatrixA "Matrix was not initialized correctly using Matrix.init" - - testCase "ofRows" <| fun () -> - let actual = - testValues2x3 - |> Array.map rowvec - |> Vector.Generic.ofSeq - |> Matrix.ofRows - - Expect.equal actual test2x3Matrix "Matrix was not initialized correctly using Matrix.ofRows" - - testCase "ofCols" <| fun () -> - let actual = - testValues2x3Transposed - |> Array.map vector - |> RowVector.Generic.ofSeq - |> Matrix.ofCols - - Expect.equal actual test2x3Matrix "Matrix was not initialized correctly using Matrix.ofCols" - - testCase "ofJaggedList" <| fun () -> - - let actual = - testValues2x3 - |> List.ofArray - |> List.map List.ofArray - |> Matrix.ofJaggedList - - Expect.equal actual test2x3Matrix "Matrix was not initialized correctly using Matrix.ofJaggedList" - - testCase "ofJaggedColList" <| fun () -> - let actual = - testValues2x3Transposed - |> List.ofArray - |> List.map List.ofArray - |> Matrix.ofJaggedColList - - Expect.equal actual test2x3Matrix "Matrix was not initialized correctly using Matrix.ofJaggedColList" - - - testCase "ofJaggedSeq" <| fun () -> - let actual = - testValues2x3 - |> Seq.ofArray - |> Seq.map Seq.ofArray - |> Matrix.ofJaggedSeq - - Expect.equal actual test2x3Matrix "Matrix was not initialized correctly using Matrix.ofJaggedSeq" - - - testCase "ofJaggedColSeq" <| fun () -> - let actual = - testValues2x3Transposed - |> Seq.ofArray - |> Seq.map Seq.ofArray - |> Matrix.ofJaggedColSeq - - Expect.equal actual test2x3Matrix "Matrix was not initialized correctly using Matrix.ofJaggedColSeq" - - - testCase "ofJaggedArray" <| fun () -> - let actual = - testValues2x3 - |> Matrix.ofJaggedArray - - Expect.equal actual test2x3Matrix "Matrix was not initialized correctly using Matrix.ofJaggedArray" - - - testCase "ofJaggedColArray" <| fun () -> - let actual = - testValues2x3Transposed - |> Matrix.ofJaggedColArray - - Expect.equal actual test2x3Matrix "Matrix was not initialized correctly using Matrix.ofJaggedColArray" - - - testCase "diag" <| fun () -> - let actual = Matrix.diag testVectorA - - Expect.equal actual testDiagonalMatrixA "Diagonal Matrix was not correctly initialized using Matrix.diag" - - testCase "initDiagonal" <| fun () -> - - let actual = Matrix.initDiagonal testVectorA - - Expect.equal actual testDiagonalMatrixA "Diagonal Matrix was not correctly initialized using Matrix.initDiag" - - testCase "constDiag" <| fun () -> - - let actual = Matrix.constDiag 3 3. - - Expect.equal actual testConstDiagMatrix "Constant diagonal matrix was not correctly initialized using Matrix.constDiag" - - - testCase "create" <| fun () -> - - let actual = Matrix.create 3 3 3. - - Expect.equal actual testConstMatrix "Constant matrix was not initialized correctly using Matrix.create" - - testCase "ofScalar" <| fun () -> - - let actual = Matrix.ofScalar 3. - - Expect.equal actual testScalarMatrix "1x1 Matrix was not correctly initialized using Matrix.ofScalar" - - testCase "ofArray2D" <| fun () -> - - let values = - Array2D.init - 3 - 3 - (fun i j -> - testValuesArrRows.[i].[j] - ) - - let actual = Matrix.ofArray2D values - - Expect.equal actual testSquareMatrixA "Matrix was not initialized correctly using Matrix.ofArray2D" - - testCase "toArray2D" <| fun () -> - - let expected = - Array2D.init - 3 - 3 - (fun i j -> - testValuesArrRows.[i].[j] - ) - - let actual = Matrix.toArray2D testSquareMatrixA - - Expect.equal actual expected "Matrix.toArray2D did not return the correct Array2D" - - testCase "toJaggedArray" <| fun () -> - let actual = Matrix.toJaggedArray testSquareMatrixA - Expect.equal actual testValuesArrRows "Matrix.toJaggedArray did not return the correct JaggedArray" - - testCase "toJaggedSeq" <| fun () -> - let actual = Matrix.toJaggedSeq testSquareMatrixA |> JaggedArray.ofJaggedSeq - Expect.equal actual testValuesArrRows "Matrix.toJaggedSeq did not return the correct JaggedSeq" - - testCase "toJaggedColArray" <| fun () -> - let actual = Matrix.toJaggedColArray testSquareMatrixA - Expect.equal actual testValuesArrCols "Matrix.toJaggedColArray did not return the correct JaggedArray" - - testCase "toJaggedColSeq" <| fun () -> - let actual = Matrix.toJaggedColSeq testSquareMatrixA |> JaggedArray.ofJaggedSeq - Expect.equal actual testValuesArrCols "Matrix.toJaggedColSeq did not return the correct JaggedSeq" - - - testCase "getDiagN 1 above diagonal" <| fun () -> - - let actual = Matrix.getDiagN testSquareMatrixA 1 - - Expect.equal actual testVector1UpperDiag "Matrix.getDiagN did not return the correct offset +1 diagonal" - - testCase "getDiag 1 below diagonal" <| fun () -> - - let actual = Matrix.getDiagN testSquareMatrixA -1 - - Expect.equal actual testVector1LowerDiag "Matrix.getDiagN did not return the correct offset -1 diagonal" - - ] - - testList "Operators" [ - - testList "add" [ - - testCase "Addition of 2 Matrices with the same dimensions" <| fun () -> - - let actual = Matrix.add testSquareMatrixA testSquareMatrixB - - let expected = - let values = - Array2D.init - 3 - 3 - (fun i j -> - testValuesArrRows.[i].[j] + testValuesArrCols.[i].[j] - ) - Matrix.DenseRepr - (DenseMatrix(Some (Instances.FloatNumerics :> INumeric),values)) - - Expect.equal actual expected "Matrix.add did not add the values of two matrices with the same dimensions correctly" - - testCase "Addition of matrices with different sizes should fail" <| fun () -> - - Expect.throws (fun () -> Matrix.add test2x3Matrix testSquareMatrixA |> ignore) "Addition of Matrices with different dimesnions did not fail although it should" - - ] - testList "sub" [ - - testCase "Substraction of 2 Matrices with the same dimensions" <| fun () -> - - let actual = Matrix.sub testSquareMatrixA testSquareMatrixB - - let expected = - let values = - Array2D.init - 3 - 3 - (fun i j -> - testValuesArrRows.[i].[j] - testValuesArrCols.[i].[j] - ) - Matrix.DenseRepr - (DenseMatrix(Some (Instances.FloatNumerics :> INumeric),values)) - - Expect.equal actual expected "Matrix.add did not add the values of two matrices with the same dimensions correctly" - - - testCase "Subtraction of matrices with different sizes should fail" <| fun () -> - - Expect.throws (fun () -> Matrix.sub test2x3Matrix testSquareMatrixA |> ignore) "Subtraction of Matrices with different dimesnions did not fail although it should" - ] - testList "mul" [ - - testCase "Matrix Multiplication with fitting dimensions" <| fun () -> - - let actual = Matrix.mul test2x3Matrix test3x2MatrixB - let expected = - let values = - [ - [0.;0.;] - [13.;29.] - ] - let valArr = - Array2D.init - 2 - 2 - (fun i j -> - values.[i].[j] - ) - Matrix.DenseRepr - (DenseMatrix(Some (Instances.FloatNumerics :> INumeric),valArr)) - - Expect.equal actual expected "Matrix multiplication of the 2x3 and 3x2 testmatrices did not return the correct result." - - testCase "Matrix Multiplication with non-fitting dimensions should fail" <| fun () -> - Expect.throws (fun () -> Matrix.mul testScalarMatrix testSquareMatrixA |> ignore) "Matrix multiplication with non-fitting dimensions did not fail although it should" - - ] - testList "mulV" [ - - testCase "Matrix (m*1)Vector multiplication with correct dimensions" <| fun () -> - let actual = Matrix.mulV testSquareMatrixA testVectorA - - let expected = - let values = [|15.;33.;51.|] - Vector(Some (Instances.FloatNumerics :> INumeric),values) - - Expect.equal actual expected "Matrix (m*1)Vector multiplication with correct dimensions did not return the correct result vector" - - testCase "Matrix (m*1)Vector multiplication with incorrect dimensions should fail" <| fun () -> - Expect.throws (fun () -> Matrix.mulV testSquareMatrixA testVector1UpperDiag |> ignore) "Matrix (m*1)Vector multiplication with incorrect dimensions should fail although it should" - ] - testList "mulRV" [ - - testCase "Matrix (1*n) RowVector multiplication with correct dimensions" <| fun () -> - let actual = Matrix.mulRV testRowVecB testSquareMatrixA - let expected = - let values = [|0.;39.;48.|] - RowVector(Some (Instances.FloatNumerics :> INumeric),values) - - Expect.equal actual expected "Matrix (1*n) RowVector multiplication with correct dimensions did not return the correct result rowVector" - - testCase "Matrix (1*n) RowVector multiplication with incorrect dimensions should fail" <| fun () -> - Expect.throws (fun () -> Matrix.mulRV testRowVecA testSquareMatrixA |> ignore) "Matrix (1*n) RowVector multiplication with incorrect dimensions didnt fail although it should" - - ] - testList "cptMul" [ - - testCase "Point wise multiplication of two matrices with the same dimensions" <| fun () -> - let actual = - Matrix.cptMul testSquareMatrixA testSquareMatrixB - - let expected = - let values = - Array2D.init - 3 - 3 - (fun i j -> - testValuesArrRows.[i].[j] * testValuesArrCols.[i].[j] - ) - Matrix.DenseRepr - (DenseMatrix(Some (Instances.FloatNumerics :> INumeric),values)) - Expect.equal actual expected "Point wise multiplication of two matrices with the same dimensions did not return the correct result matrix" - - testCase "Point wise multiplication of two matrices with different dimensions should fail" <| fun () -> - Expect.throws (fun () -> Matrix.cptMul testSquareMatrixA testScalarMatrix |> ignore) "Point wise multiplication of two matrices with different dimensions did not fail although it should" - ] - testList "cptMax" [ - testCase "Point wise maximization of two matrices with the same dimensions" <| fun () -> - let actual = - Matrix.cptMax testSquareMatrixA testSquareMatrixB - - let expected = - let values = - Array2D.init - 3 - 3 - (fun i j -> - max testValuesArrRows.[i].[j] testValuesArrCols.[i].[j] - ) - Matrix.DenseRepr - (DenseMatrix(Some (Instances.FloatNumerics :> INumeric),values)) - - Expect.equal actual expected "Point wise maximization of two matrices with the same dimensions did not return the correct result matrix" - - testCase "Point wise maximization of two matrices with different dimensions should fail" <| fun () -> - Expect.throws (fun () -> Matrix.cptMax testSquareMatrixA testScalarMatrix |> ignore) "Point wise maximization of two matrices with different dimensions did not fail although it should" - - - ] - testList "cptMin" [ - - testCase "Point wise minimization of two matrices with the same dimensions" <| fun () -> - let actual = - Matrix.cptMin testSquareMatrixA testSquareMatrixB - - let expected = - let values = - Array2D.init - 3 - 3 - (fun i j -> - min testValuesArrRows.[i].[j] testValuesArrCols.[i].[j] - ) - Matrix.DenseRepr - (DenseMatrix(Some (Instances.FloatNumerics :> INumeric),values)) - - Expect.equal actual expected "Point wise minimization of two matrices with the same dimensions did not return the correct result matrix" - - testCase "Point wise minimization of two matrices with different dimensions should fail" <| fun () -> - Expect.throws (fun () -> Matrix.cptMin testSquareMatrixA testScalarMatrix |> ignore) "Point wise minimization of two matrices with different dimensions did not fail although it should" - - - ] - testList "scale" [ - - testCase "scale" <| fun () -> - let actual = Matrix.scale 2. testSquareMatrixA - - let expected : Matrix = - let values = - Array2D.init - 3 - 3 - (fun i j -> - testValuesArrRows.[i].[j] * 2. - ) - Matrix.DenseRepr - (DenseMatrix(Some (Instances.FloatNumerics :> INumeric),values)) - - Expect.equal actual expected "Scaling a matrix by a scalar did not return the correctly scaled matrix" - ] - testList "neg" [ - - let actual = Matrix.neg testSquareMatrixA - - let expected : Matrix = - let values = - Array2D.init - 3 - 3 - (fun i j -> - testValuesArrRows.[i].[j] * -1. - ) - Matrix.DenseRepr - (DenseMatrix(Some (Instances.FloatNumerics :> INumeric),values)) - - Expect.equal actual expected "Negating a matrix did not return the correctly negated matrix" - - ] - testList "trace" [ - - testCase "Trace of a square matrix" <| fun () -> - let actual = Matrix.trace testSquareMatrixA - Expect.equal actual 9. "Trace of a square matrix was not calculated correctly" - - testCase "Trace of a non-square matrix should fail" <| fun () -> - Expect.throws (fun () -> Matrix.trace test2x3Matrix |> ignore) "Trace of a non-square matrix did not fail although it should" - - ] - testList "transpose" [ - - testCase "transpose of a square matrix" <| fun () -> - let actual = Matrix.transpose testSquareMatrixA - Expect.equal actual testSquareMatrixB "Transposing a test square matrix did not return the correct result" - - testCase "transpose of a non-square matrix" <| fun () -> - let actual = Matrix.transpose test2x3Matrix - Expect.equal actual test2x3MatrixTransposed "Transposing a test non-square matrix did not return the correct result" - ] - testList "forall" [ - - testCase "Check if all values in a matrix are >= 0. (expected to be true)" <| fun () -> - Expect.isTrue (Matrix.forall (fun elem -> elem >= 0.) testSquareMatrixA) "test matrix had all values => 0. but the Matrix.forall function failed to recognize" - - testCase "Check if all values in a matrix are >= 1. (expected to be false)" <| fun () -> - Expect.isFalse (Matrix.forall (fun elem -> elem >= 1.) testSquareMatrixA) "test matrix did not have all values => 1. but the Matrix.forall function failed to recognize" - - ] - testList "exists" [ - - testCase "Check if a testMatrix contains 0. (expected to be true)" <| fun () -> - Expect.isTrue (Matrix.exists (fun elem -> elem = 0.) testSquareMatrixA) "Test matrix was expected to contain a value 0., but Matrix.exists returned false" - - testCase "Check if a testMatrix contains 1337. (expected to be false)" <| fun () -> - Expect.isFalse (Matrix.exists (fun elem -> elem = 1337.) testSquareMatrixA) "Test matrix was not expected to contain a value 1337., but Matrix.exists returned true" - ] - testList "foralli" [ - - testCase "Check if all values in a matrix are >= 0. (expected to be true)" <| fun () -> - Expect.isTrue (Matrix.foralli (fun outerI innerI elem -> elem >= 0.) testSquareMatrixA) "test matrix had all values => 0. but the Matrix.forall function failed to recognize" - - testCase "Check if all values in a matrix are >= 1. (expected to be false)" <| fun () -> - Expect.isFalse (Matrix.foralli (fun outerI innerI elem -> elem >= 1.) testSquareMatrixA) "test matrix did not have all values => 1. but the Matrix.forall function failed to recognize" - - testCase "Check if values on the diagonal in a matrix are >= 0. (expected to be true)" <| fun () -> - Expect.isTrue (Matrix.foralli (fun outerI innerI elem -> if outerI = innerI then elem >= 0. else true) testSquareMatrixA) "test matrix had all diagonal values => 0. but the Matrix.forall function failed to recognize" - - testCase "Check if all non-diagonal values in a matrix are >= 1337. (expected to be false)" <| fun () -> - Expect.isFalse (Matrix.foralli (fun outerI innerI elem -> if outerI <> innerI then elem >= 1337. else true) testSquareMatrixA) "test matrix did not have all non-diagonal values => 1337. but the Matrix.foralli function failed to recognize" - - ] - testList "existsi" [ - - testCase "Check if a testMatrix contains 0. (expected to be true)" <| fun () -> - Expect.isTrue (Matrix.existsi (fun outerI innerI elem -> elem = 0.) testSquareMatrixA) "Test matrix was expected to contain a value 0., but Matrix.existsi returned false" - - testCase "Check if a testMatrix contains 1337. (expected to be false)" <| fun () -> - Expect.isFalse (Matrix.existsi (fun outerI innerI elem -> elem = 1337.) testSquareMatrixA) "Test matrix was not expected to contain a value 1337., but Matrix.existsi returned true" - - testCase "Check if a testMatrix contains 0. on the diagonal (expected to be true)" <| fun () -> - Expect.isTrue (Matrix.existsi (fun outerI innerI elem -> if outerI = innerI then elem = 0. else false) testSquareMatrixA) "Test matrix was expected to contain a diagonal value 0., but Matrix.existsi returned false" - - testCase "Check if a testMatrix contains a non diagonal value 1337. (expected to be false)" <| fun () -> - Expect.isFalse (Matrix.existsi (fun outerI innerI elem -> if outerI <> innerI then elem = 1337. else false) testSquareMatrixA) "Test matrix was not expected to contain a non-diagonal value 1337., but Matrix.existsi returned true" - ] - testList "map" [ - - testCase "map with (fun elem -> elem * 2)" <| fun () -> - let actual = - testSquareMatrixA - |> Matrix.map (fun elem -> elem * 2.) - - let expected = - let values = - Array2D.init - 3 - 3 - (fun i j -> - testValuesArrRows.[i].[j] * 2. - ) - Matrix.DenseRepr - (DenseMatrix(Some (Instances.FloatNumerics :> INumeric),values)) - - Expect.equal actual expected "Mapping the values of a test matrix with * 2. did not return the correct result" - - testCase "map with multiplication by constant should return the same result as matrix.scale" <| fun () -> - let actual = - testSquareMatrixA - |> Matrix.map (fun elem -> elem * 2.) - - let expected = - testSquareMatrixA - |> Matrix.scale 2. - - Expect.equal actual expected "map with multiplication by constant did not return the same result as Matrix.scale" - - testCase "map with multiplication by constant -1. should return the same result as matrix.neg" <| fun () -> - let actual = - testSquareMatrixA - |> Matrix.map (fun elem -> elem * -1.) - - let expected = - testSquareMatrixA - |> Matrix.neg - - Expect.equal actual expected "map with multiplication by constant did not return the same result as Matrix.neg" - - ] - testList "copy" [ - - testCase "Matrix copy created by Matrix.copy should equal original matrix" <| fun () -> - Expect.equal (Matrix.copy testSquareMatrixA) testSquareMatrixA "Matrix copy created by Matrix.copy was not equal to original matrix" - - testCase "Matrix copy created by Matrix.copy should stay the same when original matrix is mutated" <| fun () -> - let testCopyA = Matrix.copy testSquareMatrixA - let testCopyB = Matrix.copy testCopyA - Matrix.set testCopyA 0 0 1337. - Expect.notEqual testCopyA testCopyB "Matrix copy created by Matrix.copy did not stay the same when original matrix is mutated" - ] - testList "mapi" [ - - testCase "mapi with (fun elem -> elem * 2)" <| fun () -> - let actual = - testSquareMatrixA - |> Matrix.mapi (fun i j elem -> elem * 2.) - - let expected = - let values = - Array2D.init - 3 - 3 - (fun i j -> - testValuesArrRows.[i].[j] * 2. - ) - Matrix.DenseRepr - (DenseMatrix(Some (Instances.FloatNumerics :> INumeric),values)) - - Expect.equal actual expected "Mapping the values of a test matrix with * 2. did not return the correct result" - - testCase "map with multiplication by constant should return the same result as matrix.scale" <| fun () -> - let actual = - testSquareMatrixA - |> Matrix.mapi (fun i j elem -> elem * 2.) - - let expected = - testSquareMatrixA - |> Matrix.scale 2. - - Expect.equal actual expected "map with multiplication by constant did not return the same result as Matrix.scale" - - testCase "map with multiplication by constant -1. should return the same result as matrix.neg" <| fun () -> - let actual = - testSquareMatrixA - |> Matrix.mapi (fun i j elem -> elem * -1.) - - let expected = - testSquareMatrixA - |> Matrix.neg - - Expect.equal actual expected "map with multiplication by constant did not return the same result as Matrix.neg" - - testCase "create identity matrix using mapi" <| fun () -> - let actual = - testSquareMatrixA - |> Matrix.mapi - (fun i j elem -> - if i = j then - 1. - else - 0. - ) - Expect.equal actual identityFloat3 "creating identity matrix using Matrix.mapi failed" - - ] - testList "mapRows" [ - - testCase "map with Seq.mean" <| fun () -> - let actual = - testSquareMatrixA - |> Matrix.mapRows Seq.mean - - let expected = - Vector.init - 3 - (fun i -> Seq.mean testValuesArrRows.[i]) - - Expect.equal actual expected "Mapping the rows of a test matrix with Seq.mean did not return the correct result" - ] - testList "mapCols" [ - - testCase "map with Seq.mean" <| fun () -> - let actual = - testSquareMatrixA - |> Matrix.mapCols Seq.mean - - let expected = - RowVector.init 3 (fun i -> Seq.mean testValuesArrCols.[i]) - - Expect.equal actual expected "Mapping the cols of a test matrix with Seq.mean did not return the correct result" - ] - testList "mapiRows" [ - - testCase "mapi with Seq.mean" <| fun () -> - let actual = - testSquareMatrixA - |> Matrix.mapiRows (fun i x -> float i * Seq.mean x) - - let expected = - Vector.init 3 (fun i -> float i * Seq.average testValuesArrRows.[i]) - - Expect.equal actual expected "Mapping the rows of a test matrix with Seq.mean did not return the correct result" - ] - testList "mapiCols" [ - - testCase "mapi with Seq.mean" <| fun () -> - let actual = - testSquareMatrixA - |> Matrix.mapiCols (fun i x -> float i * Seq.mean x) - - let expected = - RowVector.init 3 (fun i -> float i * Seq.average testValuesArrCols.[i]) - - Expect.equal actual expected "Mapping the columns of a test matrix with Seq.mean did not return the correct result" - ] - testList "fold" [ - - testCase "Sum of all matrix entries using Matrix.fold" <| fun () -> - let actual = - testSquareMatrixA - |> Matrix.fold (fun acc elem -> acc + elem) 0. - - Expect.equal actual 21. "Sum of matrix elements was not correctly computed using Matrix.fold" - - testCase "count matrix entries using Matrix.fold" <| fun () -> - let actual = - testSquareMatrixA - |> Matrix.fold (fun acc _ -> acc + 1) 0 - - Expect.equal actual 9 "Matrix entries where not correctly counted using Matrix.fold" - ] - testList "foldi" [ - - testCase "Sum of all matrix entries using Matrix.foldi" <| fun () -> - let actual = - testSquareMatrixA - |> Matrix.foldi (fun i j acc elem -> acc + elem) 0. - - Expect.equal actual 21. "Sum of matrix elements was not correctly computed using Matrix.foldi" - - testCase "count matrix entries using Matrix.foldi" <| fun () -> - let actual = - testSquareMatrixA - |> Matrix.foldi (fun i j acc _ -> acc + 1) 0 - - Expect.equal actual 9 "Matrix entries where not correctly counted using Matrix.foldi" - - testCase "Calculation of Matrix trace using Matrix.foldi should be equal to the result of the Matrix.trace function" <| fun () -> - let actual = - testSquareMatrixA - |> Matrix.foldi - (fun i j acc elem -> - if i = j then - acc + elem - else - acc - ) - 0. - Expect.equal actual (Matrix.trace testSquareMatrixA) "Results of Matrix.trace and calculating matrix trace with Matrix.foldi where not equal" - ] - testList "filterRows" [ - testCase "simple filter by sum" <| fun () -> - let expected = - matrix [ - [1.;2.] - [2.;1.] - ] - let actual = - matrix [ - [5.;5.] - [1.;2.] - [5.;5.] - [2.;1.] - [5.;5.] - [5.;5.] - ] - |> Matrix.filterRows (fun r -> r |> Seq.sum = 3.) - Expect.equal actual expected "Matrix.filterRows did not return correct result" - - testCase "simple filter by contains" <| fun () -> - let expected = - matrix [ - [1.;100.] - [2.;100.] - ] - let actual = - matrix [ - [5.;5.] - [1.;2.] - [5.;5.] - [1.;100.] - [2.;100.] - [2.;1.] - [5.;5.] - [5.;5.] - ] - |> Matrix.filterRows (fun r -> r |> Seq.contains 100.) - Expect.equal actual expected "Matrix.filterRows did not return correct result" - ] - testList "filterCols" [ - testCase "simple filter by sum" <| fun () -> - let expected = - matrix [ - [1.;2.] - [2.;1.] - ] - let actual = - matrix [ - [5.;1.;6.;2.;0.] - [5.;2.;6.;1.;0.] - ] - |> Matrix.filterCols (fun c -> c |> Seq.sum = 3.) - Expect.equal actual expected "Matrix.filterCols did not return correct result" - - testCase "simple filter by contains" <| fun () -> - let expected = - matrix [ - [100.;2.] - [2.;100.] - ] - let actual = - matrix [ - [5.;100.;6.;2.;0.] - [5.;2.;6.;100.;0.] - ] - |> Matrix.filterCols (fun c -> c |> Seq.contains 100.) - Expect.equal actual expected "Matrix.filterCols did not return correct result" - ] - testList "filterCols" [ - - ] - testList "toDense" [ - - testCase "toDense" <| fun () -> - () - ] - testList "initDense" [ - - testCase "initDense" <| fun () -> - () - ] - testList "initSparse" [ - - testCase "initSparse" <| fun () -> - () - ] - testList "nonzero_entries" [ - - testCase "nonzero_entries" <| fun () -> - let actual = - Matrix.nonzero_entries testSquareMatrixA - |> Array.ofSeq - - let expected = - testValuesArrRows - |> Array.mapi - (fun outerI row -> - row - |> Array.mapi - (fun innerI elem -> - (outerI,innerI,elem) - ) - ) - |> Array.concat - |> Array.filter (fun (_,_,elem) -> elem > 0.) - - Expect.equal actual expected "Matrix.nonzero_entries returned the wron elements/indices" - - - ] - testList "zero" [ - - let actual = - Matrix.zero 3 3 - - let expected = - let values = - Array2D.init - 3 - 3 - (fun i j -> - 0. - ) - Matrix.DenseRepr - (DenseMatrix(Some (Instances.FloatNumerics :> INumeric),values)) - - Expect.equal actual expected "Matrix with zero entries was not initialized corrtectly" - - ] - testList "identity" [ - testCase "Create 3x3 identity matrix" <| fun () -> - let actual = Matrix.identity 3 - - Expect.equal actual identityFloat3 "Identity Matrix was not correctly initialized" - - ] - testList "ones" [ - - testCase "Create 3x3 Matrix with only 1. as entries" <| fun () -> - let actual = - Matrix.ones 3 3 - - let expected = - let values = - Array2D.init - 3 - 3 - (fun i j -> - 1. - ) - Matrix.DenseRepr - (DenseMatrix(Some (Instances.FloatNumerics :> INumeric),values)) - Expect.equal actual expected "Matrix with only 1. as entries was not initialized correctly" - ] - testList "getRow" [ - - testCase "getRow" <| fun () -> - let actual = Matrix.getRow testSquareMatrixA 1 - Expect.equal actual testRowVecC "Matrix.getRow did not return the correct rowvector" - - testCase "Getting row out of row range using Matrix.getRow should fail" <| fun () -> - Expect.throws (fun () -> Matrix.getRow testSquareMatrixA 1337 |> ignore) "Getting row out of row range using Matrix.getRow did not fail although it should" - - ] - testList "setRow" [ - - testCase "Set Row" <| fun () -> - - let actual = Matrix.copy testSquareMatrixA - Matrix.setRow actual 1 testVectorA - - let expected = - let rows = - [| - [|0.;1.;2.|] - [|0.;3.;6.|] - [|0.;5.;6.|] - |] - let values = - Array2D.init - 3 - 3 - (fun i j -> - rows.[i].[j] - ) - Matrix.DenseRepr - (DenseMatrix(Some (Instances.FloatNumerics :> INumeric),values)) - - Expect.equal actual expected "Matrix.getRow did not return the correct rowvector" - - testCase "Setting row out of row range using Matrix.setRow should fail" <| fun () -> - Expect.throws (fun () -> Matrix.setRow testSquareMatrixA 1337 testVectorA |> ignore) "Settingetting row out of row range using Matrix.getRow did not fail although it should" - - testCase "Setting row with vector of wrong length using Matrix.setRow should fail" <| fun () -> - Expect.throws (fun () -> Matrix.setRow testSquareMatrixA 1 testVector1LowerDiag |> ignore) "Setting row with vector of wrong length using Matrix.setRow did not fail although it should" - - ] - testList "getCol" [ - - testCase "getCol" <| fun () -> - let actual = Matrix.getCol testSquareMatrixA 0 - Expect.equal actual testVectorB "Matrix.getCol did nbot return the correct vector" - - testCase "Getting column out of col range using Matrix.getCol should fail" <| fun () -> - Expect.throws (fun () -> Matrix.getCol testSquareMatrixA 1337 |> ignore) "Getting Column out of col range using Matrix.getCol did not fail although it should" - - ] - testList "setCol" [ - - testCase "Set Column" <| fun () -> - - let actual = Matrix.copy testSquareMatrixA - Matrix.setCol actual 0 testVectorA - - let expected = - let rows = - [| - [|0.;1.;2.|] - [|3.;3.;4.|] - [|6.;5.;6.|] - |] - let values = - Array2D.init - 3 - 3 - (fun i j -> - rows.[i].[j] - ) - Matrix.DenseRepr - (DenseMatrix(Some (Instances.FloatNumerics :> INumeric),values)) - - Expect.equal actual expected "Matrix.setCol did not return the correct vector" - - testCase "Setting column out of col range using Matrix.setCol should fail" <| fun () -> - Expect.throws (fun () -> Matrix.setCol testSquareMatrixA 1337 testVectorA |> ignore) "Setting column out of col range using Matrix.setCol did not fail although it should" - - testCase "Setting column with vector of wrong length using Matrix.setCol should fail" <| fun () -> - Expect.throws (fun () -> Matrix.setCol testSquareMatrixA 1 testVector1LowerDiag |> ignore) "Setting row with vector of wrong length using Matrix.setRow did not fail although it should" - - testCase "Set Column non square" <| fun () -> - - let test2x3MatrixNonSquare : Matrix = - let values = - Array2D.init - 2 - 3 - (fun i j -> - 0. - ) - Matrix.DenseRepr - (DenseMatrix(Some (Instances.FloatNumerics :> INumeric),values)) - - Matrix.setCol test2x3MatrixNonSquare 0 ([1.;1.]|>Vector.ofList) - - let expected = - let rows = - [| - [|1.;0.;0.|] - [|1.;0.;0.|] - |] - let values = - Array2D.init - 2 - 3 - (fun i j -> - rows.[i].[j] - ) - Matrix.DenseRepr - (DenseMatrix(Some (Instances.FloatNumerics :> INumeric),values)) - - Expect.equal test2x3MatrixNonSquare expected "Matrix.setCol did not return the correct vector for non square Matrix" - - - ] - testList "getCols" [ - - testCase "getCols" <| fun () -> - () - ] - testList "getRows" [ - - testCase "getRows" <| fun () -> - () - ] - testList "removeCols" [ - testCase "removeColAt" <| fun () -> - let m = - [| - [|0.;1.|] - [|0.;3.|] - [|0.;5.|] - |] |> Matrix.ofJaggedArray - let actual = Matrix.removeColAt 0 m - let expected = - [| - [|1.|] - [|3.|] - [|5.|] - |] |> Matrix.ofJaggedArray - Expect.equal actual expected "Matrix.removeColAt did not return the correct matrix" - ] - testList "removeRows" [ - testCase "removeRowAt" <| fun () -> - let m = - [| - [|0.;0.;0.;|] - [|1.;3.;5.;|] - |] |> Matrix.ofJaggedArray - let actual = Matrix.removeRowAt 1 m - let expected = - [| - [|0.;0.;0.|] - |] |> Matrix.ofJaggedArray - Expect.equal actual expected "Matrix.removeRowAt did not return the correct matrix" - ] - testList "getRegion" [ - - testCase "get Region" <| fun () -> - - let actual = Matrix.getRegion testSquareMatrixA 0 0 3 2 - - Expect.equal actual test2x3MatrixTransposed "Matrix. getRegion did not return the correct matrix window" - ] - testList "rowRange" [ - - testCase "rowRange" <| fun () -> - Expect.equal (Matrix.rowRange testSquareMatrixA) (0,2) "Matrix.rowRange did not return the correct dimension" - ] - testList "colRange" [ - - testCase "colRange" <| fun () -> - Expect.equal (Matrix.colRange testSquareMatrixA) (0,2) "Matrix.colRange did not return the correct dimension" - ] - testList "wholeRegion" [ - - testCase "wholeRegion" <| fun () -> - Expect.equal (Matrix.wholeRegion testSquareMatrixA) ((0,2),(0,2)) "Matrix.wholeRange did not return the correct dimensions" - ] - testList "foldByRow" [ - - testCase "compute row sum vector" <| fun () -> - let actual = - testSquareMatrixA - |> Matrix.foldByRow (fun acc elem -> acc + elem) testVectorB - - let expected = - let values = [|3.;7.;11.|] - Vector(Some (Instances.FloatNumerics :> INumeric),values) - - Expect.equal actual expected "Matrix.foldByCol did not compute the correct row sum vector" - ] - testList "foldByCol" [ - - testCase "compute column sum vector" <| fun () -> - let actual = - testSquareMatrixA - |> Matrix.foldByCol (fun acc elem -> acc + elem) testRowVecD - - let expected = - let values = [|0.;9.;12.|] - RowVector(Some (Instances.FloatNumerics :> INumeric),values) - - Expect.equal actual expected "Matrix.foldByCol did not compute the correct column sum vector" - ] - testList "foldRow" [ - - testCase "compute sum of a row" <| fun () -> - let actual = Matrix.foldRow (fun acc elem -> acc + elem) 0. testSquareMatrixA 0 - Expect.equal actual 3. "Matrix.foldRow did not return the correct sum for a row" - ] - testList "foldCol" [ - - testCase "compute sum of a column" <| fun () -> - let actual = Matrix.foldCol (fun acc elem -> acc + elem) 0. testSquareMatrixA 0 - Expect.equal actual 0. "Matrix.foldRow did not return the correct sum for a column" - ] - testList "sum" [ - - testCase "Sum of all matrix entries using Matrix.sum" <| fun () -> - let actual = - testSquareMatrixA - |> Matrix.sum - - Expect.equal actual 21. "Sum of matrix elements was not correctly computed using Matrix.sum" - ] - testList "prod" [ - - testCase "Product of all matrix entries using Matrix.prod" <| fun () -> - let actual = - testSquareMatrixA - |> Matrix.prod - - Expect.equal actual 0. "Product of matrix elements was not correctly computed using Matrix.sum" - - ] - testList "mean" [ - testCase "meanRowWise" <| fun() -> - let testMat = matrix [ - [20.; 11.]; - [6.; 29.]; - [12.; 8.]; - ] - let correctList = [15.5; 17.5; 10.] - - let testlist = List.ofArray( Vector.toArray (Matrix.meanRowWise testMat)) - List.iter2 (fun a b -> Expect.floatClose Accuracy.high a b "means of matrix RowWise was calculated incorrectly") testlist correctList - - testCase "meanColumnWise"<| fun() -> - let testMat = matrix[ - [20.;6.;12.]; - [11.;29.;8.] - ] - let correctList = [15.5; 17.5; 10.] - let testlist = List.ofArray( RowVector.toArray (Matrix.meanColumnWise testMat)) - List.iter2 (fun a b -> Expect.floatClose Accuracy.high a b "means of matrix ColumnWise was calculated incorrectly") testlist correctList - - ] - testList "norm" [ - - testCase "norm" <| fun () -> - () - ] - testList "dot" [ - - testCase "dot" <| fun () -> - () - ] - testList "cptPow" [ - - testCase "cptPow" <| fun () -> - () - ] - - ] - ] From 9606473e0c5acb5ef9c87c950e7aac0d23be6a13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20M=C3=BChlhaus?= Date: Sat, 12 Apr 2025 12:20:37 +0200 Subject: [PATCH 073/121] Add Unit test for SummaryStats (former RunningStats) --- src/FSharp.Stats/AlgTypes/Matrix.fs | 7 +- src/FSharp.Stats/Algebra/LinearAlgebra.fs | 4 +- src/FSharp.Stats/FSharp.Stats.fsproj | 2 +- src/FSharp.Stats/Playground.fsx | 111 +- src/FSharp.Stats/RunningStats.fs | 132 --- src/FSharp.Stats/Seq.fs | 28 +- src/FSharp.Stats/SummaryStats.fs | 303 +++++ .../FSharp.Stats.Tests.fsproj | 8 + tests/FSharp.Stats.Tests/Interpolation.fs | 24 +- tests/FSharp.Stats.Tests/LinAlgebra.fs | 529 +++++++++ tests/FSharp.Stats.Tests/LinearAlgebra.fs | 1003 ++++++----------- tests/FSharp.Stats.Tests/Seq.fs | 54 +- tests/FSharp.Stats.Tests/Signal.fs | 2 +- tests/FSharp.Stats.Tests/SummaryStats.fs | 174 +++ 14 files changed, 1488 insertions(+), 893 deletions(-) delete mode 100644 src/FSharp.Stats/RunningStats.fs create mode 100644 src/FSharp.Stats/SummaryStats.fs create mode 100644 tests/FSharp.Stats.Tests/LinAlgebra.fs create mode 100644 tests/FSharp.Stats.Tests/SummaryStats.fs diff --git a/src/FSharp.Stats/AlgTypes/Matrix.fs b/src/FSharp.Stats/AlgTypes/Matrix.fs index 1512f91ae..0888bcaf9 100644 --- a/src/FSharp.Stats/AlgTypes/Matrix.fs +++ b/src/FSharp.Stats/AlgTypes/Matrix.fs @@ -209,7 +209,7 @@ type Matrix<'T when 'T :> Numerics.INumber<'T> /// Creates a new matrix by initializing each element with a function `f(row, col)`. - static member inline transpose<'T when 'T :> Numerics.INumber<'T> + static member inline private transposeByBlock<'T when 'T :> Numerics.INumber<'T> and 'T : (new: unit -> 'T) and 'T : struct and 'T :> ValueType> @@ -240,9 +240,12 @@ type Matrix<'T when 'T :> Numerics.INumber<'T> dst + static member inline transpose (m:Matrix<'T>) : Matrix<'T> = + m.Transpose() + member this.Transpose() = let blocksize = 16 - Matrix(this.NumCols, this.NumRows, Matrix.transpose this.NumRows this.NumCols this.Data blocksize) + Matrix(this.NumCols, this.NumRows, Matrix.transposeByBlock this.NumRows this.NumCols this.Data blocksize) static member init<'T when 'T :> Numerics.INumber<'T> and 'T : (new: unit -> 'T) diff --git a/src/FSharp.Stats/Algebra/LinearAlgebra.fs b/src/FSharp.Stats/Algebra/LinearAlgebra.fs index a291897b0..b5f0eac95 100644 --- a/src/FSharp.Stats/Algebra/LinearAlgebra.fs +++ b/src/FSharp.Stats/Algebra/LinearAlgebra.fs @@ -8,7 +8,7 @@ type LinearAlgebra = /// Subtract `scaleVal * src[srcOffset..srcOffset+count-1]` from /// `dst[dstOffset..dstOffset+count-1]` in place. - static member inline private subScaledRowInPlace + static member inline subScaledRowInPlace (scaleVal : 'T) (dstOffset : int) (srcOffset : int) @@ -27,7 +27,7 @@ type LinearAlgebra = d - (scaleVal * s) Acceleration.SIMDRangeUtils.map2RangeInPlace fv f dstOffset srcOffset count dst src - static member inline private householderTransform + static member inline householderTransform (A: Matrix<'T>) (i: int) : Vector<'T> = let n = A.NumRows let v = Vector.zeroCreate<'T> n diff --git a/src/FSharp.Stats/FSharp.Stats.fsproj b/src/FSharp.Stats/FSharp.Stats.fsproj index 542b345c4..31d570668 100644 --- a/src/FSharp.Stats/FSharp.Stats.fsproj +++ b/src/FSharp.Stats/FSharp.Stats.fsproj @@ -44,7 +44,7 @@ - + diff --git a/src/FSharp.Stats/Playground.fsx b/src/FSharp.Stats/Playground.fsx index 1087204b6..ed66d5edb 100644 --- a/src/FSharp.Stats/Playground.fsx +++ b/src/FSharp.Stats/Playground.fsx @@ -9,6 +9,72 @@ open FSharp.Stats.Distributions +let data = [|1.0; 2.0; 3.0; 4.0; 5.0|] + +SummaryStats.ofSeq data +SummaryStats.ofArray data + +let statsC = SummaryStats.ofSeq data +let calcMean = Seq.mean data +let calcSumOfSquares = Seq.sumBy (fun x -> x * x) data +let calcMin = Seq.min data +let calcMax = Seq.max data +let calcN = Seq.length data + + +open FSharp.Stats.Testing + +let groupA = [|-5.;-3.;-3.;-4.;-5.;|] +let groupB = [|-2.;-4.;-4.;-6.;-6.;-6.;-5.;|] + +let statsA = Seq.stats groupA +let statsB = Seq.stats groupB + + +let meanA = Seq.mean groupA +let meanB = Seq.mean groupB +let varA = Seq.var groupA +let varB = Seq.var groupB +let nA = float (Seq.length groupA) +let nB = float (Seq.length groupB) + +// calculation of the H test +let tTest1 = TTest.twoSample true groupA groupB +let tTest2 = TTest.twoSampleFromMeanAndVar true (meanA,varA,nA) (meanB,varB,nB) +let tTest3 = TTest.twoSample false groupA groupB + + + + + +let KDiagonal1 = + [| + [|1.;0.;0.|] + [|0.;1.;0.|] + [|0.;0.;1.|] + |] + |> Matrix.ofJaggedArray + +let BNegInf = + [| + [|-infinity;-infinity;-infinity|] + [|-infinity;-infinity;-infinity|] + [|-infinity;-infinity;-infinity|] + |] + |> Matrix.ofJaggedArray + + +Algebra.LinearAlgebra .solveTriangularLinearSystems KDiagonal1 BNegInf false + +//|> fun res -> +// let expected = +// matrix [| +// [|nan;nan;nan|]; +// [|nan;nan;nan|]; +// [|-infinity;-infinity;-infinity|] +// |] + + let alpha = 9.9 //0.4 let beta = 31 //4.2 @@ -40,12 +106,12 @@ let samplesHisto = Array.init 999999 (fun _ -> Continuous.Gamma.Sample alpha bet let bw = 1.//FSharp.Stats.Distributions.Bandwidth.forHistogram samplesHisto let histo = FSharp.Stats.Distributions.KernelDensity.estimate KernelDensity.Kernel.gaussian bw samplesHisto let histoPdf = histo |> Seq.map (fun (x,y) -> x,Continuous.Gamma.PDF alpha beta x) -[ - Chart.Column(histo) - Chart.Point(histoPdf) -] -|> Chart.combine -|> Chart.show +//[ +// Chart.Column(histo) +// Chart.Point(histoPdf) +//] +//|> Chart.combine +//|> Chart.show let alpha', beta' = Continuous.Gamma.Fit samplesHisto @@ -64,36 +130,3 @@ d.Mean -open FSharp.Stats -let rnd = new System.Random(69) - -let mDenseInt1 = Matrix.Generic.init 10 10 (fun r c -> $"{r}{c}" ) -let mDenseInt2 = Matrix.Generic.init 10 100 (fun r c -> $"{r}{c}" ) -let mDenseInt3 = Matrix.Generic.init 100 10 (fun r c -> $"{r}{c}" ) -let mDenseInt4 = Matrix.Generic.init 100 100 (fun r c -> $"{r}{c}" ) - -mDenseInt1.Format(false) -mDenseInt1.Format(true) -mDenseInt2.Format(false) -mDenseInt2.Format(true) -mDenseInt3.Format(false) -mDenseInt3.Format(true) -mDenseInt4.Format(false) -mDenseInt4.Format(true) - -let mDense1 = Matrix.init 10 10 (fun i j -> float i * float j * rnd.NextDouble()) -let mDense2 = Matrix.init 10 100 (fun i j -> float i * float j * rnd.NextDouble()) -let mDense3 = Matrix.init 100 10 (fun i j -> float i * float j * rnd.NextDouble()) -let mDense4 = Matrix.init 100 100 (fun i j -> float i * float j * rnd.NextDouble()) -let mDenseSpecial = matrix[[nan;100000000.;infinity;1.4];[1.337;-nan;4269420.42;-infinity]] - -mDense1.Format(false) -mDense1.Format(true) -mDense2.Format(false) -mDense2.Format(true) -mDense3.Format(false) -mDense3.Format(true) -mDense4.Format(false) -mDense4.Format(true) -mDenseSpecial.Format(false) -mDenseSpecial.Format(true) diff --git a/src/FSharp.Stats/RunningStats.fs b/src/FSharp.Stats/RunningStats.fs deleted file mode 100644 index b9f8d23fd..000000000 --- a/src/FSharp.Stats/RunningStats.fs +++ /dev/null @@ -1,132 +0,0 @@ -namespace FSharp.Stats - - -/// Module to compute common statistical measure on -module SummaryStats = - - type SummaryStats<'T> = { - N : 'T - Mean : 'T - SumOfSquares : 'T - Min : 'T - Max : 'T - } - - let createSummaryStats n mean sos min max = - {N=n;Mean=mean;SumOfSquares=sos;Min=min;Max=max} - - - /// - let inline mean sStats = sStats.Mean - /// - let inline varPopulation sStats = sStats.SumOfSquares / sStats.N - /// - let inline var (sStats:SummaryStats<'T>) = - let one = LanguagePrimitives.GenericOne<'T> - sStats.SumOfSquares / (sStats.N - one) - /// - let inline stDev (rStats:SummaryStats<'T>) = - sqrt (var rStats) - /// - let inline stDevPopulation (rStats:SummaryStats<'T>) = - sqrt (varPopulation rStats) - - - - -module RunningStats = - - type RunningStats<'T> = { - N : int - M1 : 'T - M2 : 'T - M3 : 'T - M4 : 'T - } - - let createRunningStats n m1 m2 m3 m4 = - {N=n;M1=m1;M2=m2;M3=m3;M4=m4} - - //let inline combine (a:RunningStats<'T>) (b:RunningStats<'T>) = - - // let (..*) n a = Ops.multByInt32 a n - - // let cn = a.N + b.N - // let delta = b.M1 - a.M1 - // let delta2 = delta * delta - // let delta3 = delta * delta2 - // let delta4 = delta2 * delta2 - - // let cM1 = LanguagePrimitives.DivideByInt<'T> ( (Ops.multByInt32 a.M1 a.N ) + (Ops.multByInt32 b.M1 b.N)) cn - // let cM2 = LanguagePrimitives.DivideByInt<'T> (Ops.multByInt32 (a.M2 + b.M2 + delta2) (a.N * b.N)) cn - // let cM3 = - // let tmp = LanguagePrimitives.DivideByInt<'T> (Ops.multByInt32 (a.M3 + b.M3 + delta3) (a.N * b.N * (a.N - b.N))) (cn * cn) - // tmp + LanguagePrimitives.DivideByInt<'T> ((Ops.multByInt32 delta 3) * (Ops.multByInt32 b.M2 a.N) - (Ops.multByInt32 a.M2 b.N)) cn - // let cM4 = - // let tmp = LanguagePrimitives.DivideByInt<'T> (Ops.multByInt32 (Ops.multByInt32 (a.M4 + b.M4 + delta4) (a.N*b.N)) (a.N*a.N - a.N*b.N + b.N*b.N)) (cn * cn * cn) - // //let tmp2 = LanguagePrimitives.DivideByInt<'T> ((Ops.multByInt32 delta2 6) * ((Ops.multByInt32 b.M2 (a.N * a.N)) + (Ops.multByInt32 a.M2 (b.N * b.N)))) (cn*cn) - // tmp + (LanguagePrimitives.DivideByInt<'T> (6 ..* delta2 * ( (a.N * a.N) ..* b.M2 + (b.N * b.N) ..* a.M2)) (cn*cn)) + LanguagePrimitives.DivideByInt<'T> (4 ..* delta * (a.N ..* b.M3 - b.N ..* a.M3)) cn - - // createRunningStats cn cM1 cM2 cM3 cM4 - - - - - let inline mean rStats = - rStats.M1 - /// - let inline varPopulation rStats = - LanguagePrimitives.DivideByInt rStats.M2 rStats.N - /// - let inline var (rStats:RunningStats<'T>) = - LanguagePrimitives.DivideByInt rStats.M2 (rStats.N-1) - /// - let inline stDev (rStats:RunningStats<'T>) = - sqrt (var rStats) - /// - let inline stDevPopulation (rStats:RunningStats<'T>) = - sqrt (varPopulation rStats) - -// ///Skewness -// let inline skewness (rStats:RunningStats<'T>) = -// sqrt(double(n)) * M3/ pown(M2, 1.5) -// sqrt (varPopulation rStats) - - /// Kurtosis -// let inline kurtosis (rStats:RunningStats<'T>) = -// let one = LanguagePrimitives.GenericOne< 'T > -// let tmp = Ops.multByInt32 rStats.M4 rStats.N -// tmp / (rStats.M2 * rStats.M2) - (one + one + one) - - - -// let inline ofSeq (items:seq<'T>) : RunningStats< 'U > = -// use e = items.GetEnumerator() -// let zero = LanguagePrimitives.GenericZero< 'U > -// //let one = LanguagePrimitives.GenericOne< 'U > - -// let rec loop n (m1:'U) (m2:'U) (m3:'U) (m4:'U) = -// match e.MoveNext() with -// | true -> -// let n' = n + 1 -// let delta = e.Current - m1 -// let delta_n = LanguagePrimitives.DivideByInt< 'U > delta n -// let delta_n2 = delta_n * delta_n -// let term1 = Ops.multByInt32 (delta * delta_n) n' -// let m1' = m1 + delta_n -// let m4' = m4 + (Ops.multByInt32 (term1 * delta_n2) (n'*n' - 3*n' + 3)) + (Ops.multByInt32 (delta_n2 * m2) 6) - (Ops.multByInt32 (delta_n * m3) 4) -// let m3' = m3 + (Ops.multByInt32 (term1 * m2) (n' - 2)) - (Ops.multByInt32 (delta_n * m2) 3 ) -//// let m4' = m4 + (term1 * delta_n2 * (n'*n' - 3*n' + 3) + 6 * delta_n2 * m2 - 4 * delta_n * m3) -//// let m3' = m3 + (term1 * delta_n * (n' - 2) - 3 * delta_n * m2) -// let m2' = term1 - -// loop (n + 1) m1' m2' m3' m4' -// | false -> -// if (n > 1) then -// createRunningStats n m1 m2 m3 m4 -// else -// let nanU = zero / zero -// createRunningStats n nanU nanU nanU nanU -// loop 0 zero zero zero zero - - diff --git a/src/FSharp.Stats/Seq.fs b/src/FSharp.Stats/Seq.fs index c0f93baa6..3cf9dc50f 100644 --- a/src/FSharp.Stats/Seq.fs +++ b/src/FSharp.Stats/Seq.fs @@ -1172,7 +1172,8 @@ module Seq = // /// /// Returns SummaryStats of the input sequence with N, mean, sum-of-squares, minimum and maximum. - /// + /// + /// Welfords online algorithm /// The input sequence. /// The SummaryStats of the input sequence. /// @@ -1181,35 +1182,14 @@ module Seq = /// let stats = Seq.stats values /// // returns SummaryStats with: /// // N = 5 - /// // Mean = 3.5 + /// // Mean = 3.0 /// // SumOfSquares = 5.0 /// // Minimum = 1.0 /// // Maximum = 5.0 /// /// let inline stats (items:seq<'T>) = - use e = items.GetEnumerator() - let zero = LanguagePrimitives.GenericZero< 'T > - let one = LanguagePrimitives.GenericOne< 'T > - - let rec loop n (minimum) (maximum) m1 m2 = - match e.MoveNext() with - | true -> - let current = e.Current - let delta = current - m1 - let deltaN = (delta / n) - //let delta_n2 = deltaN * deltaN - let m1' = m1 + deltaN - let m2' = m2 + delta * deltaN * (n-one) - loop (n + one) (min current minimum) (max current maximum) m1' m2' - | false -> SummaryStats.createSummaryStats n m1 m2 minimum maximum - - //Init by first value - match e.MoveNext() with - | true -> loop one e.Current e.Current zero zero - | false -> - let uNan = zero / zero - SummaryStats.createSummaryStats zero uNan uNan uNan uNan + SummaryStats.ofSeq items /// /// Calculates the sample means with a given number of replicates present in the sequence. diff --git a/src/FSharp.Stats/SummaryStats.fs b/src/FSharp.Stats/SummaryStats.fs new file mode 100644 index 000000000..315eb5389 --- /dev/null +++ b/src/FSharp.Stats/SummaryStats.fs @@ -0,0 +1,303 @@ +namespace FSharp.Stats + + +/// +/// Module to compute summary statistics for a collection of numeric values, +/// including the count, mean, M2 (sum of squared deviations), +/// minimum, and maximum. +/// +module SummaryStats = + + + /// + /// Represents summary statistics for a collection of numeric values, + /// including the count, mean, M2 (sum of squared deviations), + /// minimum, and maximum. + /// + type SummaryStats<'T> = + { + /// The number of data points observed. + N : 'T + /// The mean (average) of all observed data points. + Mean : 'T + /// The sum of squared deviations fom the mean + SumSqrdDevations : 'T + /// The minimum observed value. + Min : 'T + /// The maximum observed value. + Max : 'T + } + + /// + /// Creates a SummaryStats record from the given fields. + /// + /// The number of observed data points. + /// The running mean of the data points. + /// The sum of squared deviations fom the mean + /// The minimum observed value. + /// The maximum observed value. + /// A new SummaryStats record. + let createSummaryStats n mean sos min max = + {N=n;Mean=mean;SumSqrdDevations=sos;Min=min;Max=max} + + /// + /// Returns the mean (average) value from the specified summary statistics. + /// + /// A summary statistics record. + /// The mean of the observed data. + let inline mean sStats = + sStats.Mean + + /// + /// Returns the population variance from the specified summary statistics. + /// + /// + /// The population variance is defined as SumOfSquares / N, + /// where SumOfSquares is the sum of squared deviations (M2), + /// and N is the total count. + /// + /// A summary statistics record. + /// The population variance of the observed data. + let inline varPopulation sStats = + sStats.SumSqrdDevations / sStats.N + + /// + /// Returns the sample variance from the specified summary statistics, + /// using N - 1 in the denominator. + /// + /// + /// The sample variance is computed as SumOfSquares / (N - 1), + /// which is the unbiased estimator when N > 1. + /// + /// A summary statistics record. + /// The sample variance of the observed data. + let inline var (sStats: SummaryStats<'T>) = + let one = LanguagePrimitives.GenericOne<'T> + sStats.SumSqrdDevations / (sStats.N - one) + + /// + /// Returns the sample standard deviation from the specified summary statistics. + /// + /// + /// This is the square root of the sample variance. + /// + /// A summary statistics record. + /// The sample standard deviation of the observed data. + let inline stDev (sStats: SummaryStats<'T>) = + sqrt (var sStats) + + /// + /// Returns the population standard deviation from the specified summary statistics. + /// + /// + /// This is the square root of the population variance. + /// + /// A summary statistics record. + /// The population standard deviation of the observed data. + let inline stDevPopulation (sStats: SummaryStats<'T>) = + sqrt (varPopulation sStats) + + + /// + /// Computes Welford-based summary statistics (count, mean, sum of squares, min, max) + /// in a single pass for a given sequence of numeric data. + /// + /// + /// This function reads the sequence one item at a time (via its enumerator), + /// applying Welford's online update formula. It is generic over any numeric + /// type 'T that supports F# inlined arithmetic. + /// + /// A sequence of numeric data. + /// + /// A SummaryStats record containing the final count, mean, sum of squares, min, and max. + let inline ofSeq (items: seq<'T>) = + use e = items.GetEnumerator() + let zero = LanguagePrimitives.GenericZero<'T> + let one = LanguagePrimitives.GenericOne<'T> + + // Recursive loop for Welford’s algorithm + let rec loop n currentMin currentMax mean m2 = + match e.MoveNext() with + | true -> + let x = e.Current + // "delta" is how far the new value is from the old mean + let delta = x - mean + // n+1 is the new total number of data points + let n' = n + one + let mean' = mean + delta / n' + // Welford’s M2 update -> (M2) is the sum of squares of the differences from the mean + let m2' = m2 + delta * (x - mean') + loop n' (min x currentMin) (max x currentMax) mean' m2' + | false -> + // At the end, n is the total count of items, + // mean is the final mean, M2 is the sum of squared deviations, etc. + createSummaryStats n mean m2 currentMin currentMax + + // Pull the first item out before starting the loop. + match e.MoveNext() with + | true -> + let firstVal = e.Current + // n = 1, mean = firstVal, M2 = 0, min = max = firstVal + loop one firstVal firstVal firstVal zero + | false -> + // No data --> return "empty" stats + let nan = zero / zero + createSummaryStats zero nan nan nan nan + + + /// + /// Computes Welford-based summary statistics (count, mean, sum of squares, min, max) + /// in a single pass for a given array of numeric data. + /// + /// + /// This function iterates over the array exactly once. It is generic over any + /// numeric type 'T that supports F# inlined arithmetic. + /// + /// An array of numeric data. + /// + /// A SummaryStats record containing the final count, mean, sum of squares, min, and max. + /// + let inline ofArray (arr: 'T[]) = + // We'll need zero, one, etc. from generic operators: + let zero = LanguagePrimitives.GenericZero<'T> + let one = LanguagePrimitives.GenericOne<'T> + + // Define a "generic NaN" to handle empty arrays: + let uNan = zero / zero + + match arr.Length with + | 0 -> + // No elements, produce an all-NaN stats + createSummaryStats zero uNan uNan uNan uNan + + | _ -> + // Initialize with the first value + let mutable count = one + let mutable m1 = arr.[0] // mean + let mutable m2 = zero // sum of squared deviations + let mutable minVal = arr.[0] + let mutable maxVal = arr.[0] + + // Process the rest of the array + for i in 1 .. arr.Length - 1 do + + let x = arr.[i] + // "delta" is how far the new value is from the old mean + let delta = x - m1 + // n+1 is the new total number of data points + let n' = count + one + let mean' = m1 + delta / n' + // Welford’s M2 update -> (M2) is the sum of squares of the differences from the mean + let m2' = m2 + delta * (x - mean') + + // Update rolling state + count <- n' + m1 <- mean' + m2 <- m2' + + // Track min/max + if x < minVal then minVal <- x + if x > maxVal then maxVal <- x + + createSummaryStats count m1 m2 minVal maxVal + + + + + +//module RunningStats = + +// type RunningStats<'T> = { +// N : int +// M1 : 'T +// M2 : 'T +// M3 : 'T +// M4 : 'T +// } + +// let createRunningStats n m1 m2 m3 m4 = +// {N=n;M1=m1;M2=m2;M3=m3;M4=m4} + +// //let inline combine (a:RunningStats<'T>) (b:RunningStats<'T>) = + +// // let (..*) n a = Ops.multByInt32 a n + +// // let cn = a.N + b.N +// // let delta = b.M1 - a.M1 +// // let delta2 = delta * delta +// // let delta3 = delta * delta2 +// // let delta4 = delta2 * delta2 + +// // let cM1 = LanguagePrimitives.DivideByInt<'T> ( (Ops.multByInt32 a.M1 a.N ) + (Ops.multByInt32 b.M1 b.N)) cn +// // let cM2 = LanguagePrimitives.DivideByInt<'T> (Ops.multByInt32 (a.M2 + b.M2 + delta2) (a.N * b.N)) cn +// // let cM3 = +// // let tmp = LanguagePrimitives.DivideByInt<'T> (Ops.multByInt32 (a.M3 + b.M3 + delta3) (a.N * b.N * (a.N - b.N))) (cn * cn) +// // tmp + LanguagePrimitives.DivideByInt<'T> ((Ops.multByInt32 delta 3) * (Ops.multByInt32 b.M2 a.N) - (Ops.multByInt32 a.M2 b.N)) cn +// // let cM4 = +// // let tmp = LanguagePrimitives.DivideByInt<'T> (Ops.multByInt32 (Ops.multByInt32 (a.M4 + b.M4 + delta4) (a.N*b.N)) (a.N*a.N - a.N*b.N + b.N*b.N)) (cn * cn * cn) +// // //let tmp2 = LanguagePrimitives.DivideByInt<'T> ((Ops.multByInt32 delta2 6) * ((Ops.multByInt32 b.M2 (a.N * a.N)) + (Ops.multByInt32 a.M2 (b.N * b.N)))) (cn*cn) +// // tmp + (LanguagePrimitives.DivideByInt<'T> (6 ..* delta2 * ( (a.N * a.N) ..* b.M2 + (b.N * b.N) ..* a.M2)) (cn*cn)) + LanguagePrimitives.DivideByInt<'T> (4 ..* delta * (a.N ..* b.M3 - b.N ..* a.M3)) cn + +// // createRunningStats cn cM1 cM2 cM3 cM4 + + + + +// let inline mean rStats = +// rStats.M1 +// /// +// let inline varPopulation rStats = +// LanguagePrimitives.DivideByInt rStats.M2 rStats.N +// /// +// let inline var (rStats:RunningStats<'T>) = +// LanguagePrimitives.DivideByInt rStats.M2 (rStats.N-1) +// /// +// let inline stDev (rStats:RunningStats<'T>) = +// sqrt (var rStats) +// /// +// let inline stDevPopulation (rStats:RunningStats<'T>) = +// sqrt (varPopulation rStats) + +//// ///Skewness +//// let inline skewness (rStats:RunningStats<'T>) = +//// sqrt(double(n)) * M3/ pown(M2, 1.5) +//// sqrt (varPopulation rStats) + +// /// Kurtosis +//// let inline kurtosis (rStats:RunningStats<'T>) = +//// let one = LanguagePrimitives.GenericOne< 'T > +//// let tmp = Ops.multByInt32 rStats.M4 rStats.N +//// tmp / (rStats.M2 * rStats.M2) - (one + one + one) + + + +//// let inline ofSeq (items:seq<'T>) : RunningStats< 'U > = +//// use e = items.GetEnumerator() +//// let zero = LanguagePrimitives.GenericZero< 'U > +//// //let one = LanguagePrimitives.GenericOne< 'U > + +//// let rec loop n (m1:'U) (m2:'U) (m3:'U) (m4:'U) = +//// match e.MoveNext() with +//// | true -> +//// let n' = n + 1 +//// let delta = e.Current - m1 +//// let delta_n = LanguagePrimitives.DivideByInt< 'U > delta n +//// let delta_n2 = delta_n * delta_n +//// let term1 = Ops.multByInt32 (delta * delta_n) n' +//// let m1' = m1 + delta_n +//// let m4' = m4 + (Ops.multByInt32 (term1 * delta_n2) (n'*n' - 3*n' + 3)) + (Ops.multByInt32 (delta_n2 * m2) 6) - (Ops.multByInt32 (delta_n * m3) 4) +//// let m3' = m3 + (Ops.multByInt32 (term1 * m2) (n' - 2)) - (Ops.multByInt32 (delta_n * m2) 3 ) +////// let m4' = m4 + (term1 * delta_n2 * (n'*n' - 3*n' + 3) + 6 * delta_n2 * m2 - 4 * delta_n * m3) +////// let m3' = m3 + (term1 * delta_n * (n' - 2) - 3 * delta_n * m2) +//// let m2' = term1 + +//// loop (n + 1) m1' m2' m3' m4' +//// | false -> +//// if (n > 1) then +//// createRunningStats n m1 m2 m3 m4 +//// else +//// let nanU = zero / zero +//// createRunningStats n nanU nanU nanU nanU +//// loop 0 zero zero zero zero + + diff --git a/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj b/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj index df32e88d3..e832e8efb 100644 --- a/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj +++ b/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj @@ -21,6 +21,14 @@ + + + + + + + + diff --git a/tests/FSharp.Stats.Tests/Interpolation.fs b/tests/FSharp.Stats.Tests/Interpolation.fs index 486acb157..e97496a99 100644 --- a/tests/FSharp.Stats.Tests/Interpolation.fs +++ b/tests/FSharp.Stats.Tests/Interpolation.fs @@ -21,7 +21,7 @@ let cubicInterpolationTests = //https://columbiaeconomics.com/2010/01/20/how-economists-convert-quarterly-data-into-monthly-cubic-spline-interpolation/comment-page-1/ let coefficientsSpline = CubicSpline.interpolate CubicSpline.Natural t y - let fitOutPut = tt |> Vector.map (CubicSpline.predict coefficientsSpline) + let fitOutPut = tt |> Array.map (CubicSpline.predict coefficientsSpline) let expectedValues = vector [187.6; 186.4328125; 185.5425; 185.2059375; 185.7; 187.179375;189.31; 191.635625; 193.7; 195.1528125; 196.0675; 196.6234375;197.0] TestExtensions.sequenceEqual Accuracy.low expectedValues fitOutPut "Fitted Values and Expected Output should be equal (double precision)" @@ -43,7 +43,7 @@ let cubicInterpolationTests = CubicSpline.predict coeffParabolic x let genrateX = vector [20.0..25.0] - let interpParabolic = genrateX |> Vector.map fittingFuncParabolic + let interpParabolic = genrateX |> Array.map fittingFuncParabolic let parabolicSndDeriv x = CubicSpline.getSecondDerivative coeffParabolic x Expect.floatClose Accuracy.high (parabolicSndDeriv interpParabolic.[0]) (parabolicSndDeriv interpParabolic.[1]) "the second derivative at the first and second points should be equal (double precision)" @@ -101,7 +101,7 @@ let BezierInterpolationTests = let p1 = vector [|3.;2.;0.|] //point 1 that should be traversed let data = [|p0;p1|] let interpolate = Bezier.interpolate data - let expectedMiddle = p0 + 0.5 * (p1 - p0) + let expectedMiddle = p0 .+ 0.5 .* (p1 .- p0) TestExtensions.sequenceEqual(Accuracy.high) (interpolate 0.) p0 "Initial point should be equal (double precision)" TestExtensions.sequenceEqual(Accuracy.high) (interpolate 0.5) expectedMiddle "Middle point should be equal (double precision)" TestExtensions.sequenceEqual(Accuracy.high) (interpolate 1.) p1 "Final point should be equal (double precision)" @@ -112,9 +112,9 @@ let BezierInterpolationTests = let p1 = vector [|3.;2.;0.|] //point 1 that should be traversed let data = [|p0;c0;p1|] let interpolate = Bezier.interpolate data - let a = p0 + 0.5 * (c0 - p0) - let b = c0 + 0.5 * (p1 - c0) - let expectedMiddle = a + 0.5 * (b - a) + let a = p0 .+ 0.5 .* (c0 .- p0) + let b = c0 .+ 0.5 .* (p1 .- c0) + let expectedMiddle = a .+ 0.5 .* (b .- a) TestExtensions.sequenceEqual(Accuracy.high) (interpolate 0.) p0 "Initial point should be equal (double precision)" TestExtensions.sequenceEqual(Accuracy.high) (interpolate 0.5) expectedMiddle "Middle point should be equal (double precision)" TestExtensions.sequenceEqual(Accuracy.high) (interpolate 1.) p1 "Final point should be equal (double precision)" @@ -126,12 +126,12 @@ let BezierInterpolationTests = let p1 = vector [|3.;2.;0.|] //point 1 that should be traversed let data = [|p0;c0;c1;p1|] let interpolate = Bezier.interpolate data - let a = p0 + 0.5 * (c0 - p0) - let b = c0 + 0.5 * (c1 - c0) - let c = c1 + 0.5 * (p1 - c1) - let d = a + 0.5 * (b - a) - let e = b + 0.5 * (c - b) - let expectedMiddle = d + 0.5 * (e - d) + let a = p0 .+ 0.5 .* (c0 .- p0) + let b = c0 .+ 0.5 .* (c1 .- c0) + let c = c1 .+ 0.5 .* (p1 .- c1) + let d = a .+ 0.5 .* (b .- a) + let e = b .+ 0.5 .* (c .- b) + let expectedMiddle = d .+ 0.5 .* (e .- d) TestExtensions.sequenceEqual(Accuracy.high) (interpolate 0.) p0 "Initial point should be equal (double precision)" TestExtensions.sequenceEqual(Accuracy.high) (interpolate 0.5) expectedMiddle "Middle point should be equal (double precision)" TestExtensions.sequenceEqual(Accuracy.high) (interpolate 1.) p1 "Final point should be equal (double precision)" diff --git a/tests/FSharp.Stats.Tests/LinAlgebra.fs b/tests/FSharp.Stats.Tests/LinAlgebra.fs new file mode 100644 index 000000000..dc3dc3024 --- /dev/null +++ b/tests/FSharp.Stats.Tests/LinAlgebra.fs @@ -0,0 +1,529 @@ +module LinAlgebraTests + +open Expecto +open System +open FSharp.Stats +open FSharp.Stats.Algebra + +[] +let linearAlgebraTests = + testList "LinearAlgebra Tests" [ + + // ---------------------------------------------------------------------- + // Basic tests + // ---------------------------------------------------------------------- + + testCase "subScaledRowInPlace: subtract scaled portion of source row from destination row" <| fun _ -> + let dst = [|10.0; 20.0; 30.0|] + let src = [|1.0 ; 2.0 ; 3.0 |] + LinearAlgebra.subScaledRowInPlace 2.0 0 0 3 dst src + let expected = [|8.0; 16.0; 24.0|] + Expect.equal dst expected "dst should be updated correctly" + + testCase "householderTransform: returns a Householder vector for column i" <| fun _ -> + let matData = [| 1.0; 2.0; 3.0 + 4.0; 5.0; 6.0 + 7.0; 8.0; 9.0 |] + let A = Matrix(3, 3, matData) + let v = LinearAlgebra.householderTransform A 1 + Expect.equal v.Length 3 "Householder vector should have 3 elements" + Expect.isFalse (Double.IsNaN v.[1]) "v.[1] should not be NaN" + + testCase "qrModifiedGramSchmidt: Q*R reconstructs A (2x2 example)" <| fun _ -> + let A = Matrix(2, 2, [|1.0; 2.0; 3.0; 4.0|]) + let Q, R = LinearAlgebra.qrModifiedGramSchmidt A + // Multiply Q*R => 2x2 => compare with A + let APrime = Array.zeroCreate 4 + for i in 0..1 do + for j in 0..1 do + let mutable sum = 0.0 + for k in 0..1 do + sum <- sum + Q.[i,k] * R.[k,j] + APrime.[i*2 + j] <- sum + for idx in 0..3 do + Expect.floatClose Accuracy.high A.Data.[idx] APrime.[idx] + $"A' and A differ at idx={idx}" + + testCase "backSubstitute: solves R*x=y for x, R upper-triangular" <| fun _ -> + // R = [2,3; 0,4], y = [8,12] => x= [-0.5,3] + let R = Matrix(2, 2, [|2.0;3.0; 0.0;4.0|]) + let y = [|8.0;12.0|] + let x = LinearAlgebra.backSubstitute R y + let expected = [|-0.5;3.0|] + Expect.floatClose Accuracy.high expected.[0] x.[0] "x0 mismatch" + Expect.floatClose Accuracy.high expected.[1] x.[1] "x1 mismatch" + + testCase "solveLinearQR: solves A*x=b (2x2 system)" <| fun _ -> + // A= [1,2; 3,4], b= [5,11] => x= [1,2] + let A = Matrix(2,2,[|1.;2.;3.;4.|]) + let b = [|5.; 11.|] + let x = LinearAlgebra.solveLinearQR A b + let expected = [|1.;2.|] + Expect.floatClose Accuracy.high expected.[0] x.[0] "x[0] mismatch" + Expect.floatClose Accuracy.high expected.[1] x.[1] "x[1] mismatch" + + + // ====================================================================== + // EDGE CASES: Infinity, -Infinity, NaN + // ====================================================================== + testList "Edge Cases with Infinity, -Infinity, NaN" [ + + testCase "subScaledRowInPlace with scaleVal = +∞" <| fun _ -> + // Let dst[0] = +∞, and scaleVal= +∞. Then dst[0] = ∞ - ∞*something => usually NaN + // Also check second entry for leftover infinite results. + let dst = [| Double.PositiveInfinity; 10.0 |] + let src = [| 2.0; 1.0 |] + LinearAlgebra.subScaledRowInPlace Double.PositiveInfinity 0 0 2 dst src + // The math: + // dst[0] <- ∞ - (∞ * 2) => ∞ - ∞ => NaN + // dst[1] <- 10 - (∞ * 1) => 10 - ∞ => -∞ + Expect.isTrue (Double.IsNaN dst.[0]) "Expected NaN in dst.[0]" + Expect.isTrue (Double.IsNegativeInfinity dst.[1]) "Expected -∞ in dst.[1]" + + testCase "householderTransform with NaN in matrix" <| fun _ -> + // Insert a NaN into the matrix + let matData = [| 1.0; Double.NaN; 3.0 + 4.0; 5.0; 6.0 |] + // 2x3 matrix + let A = Matrix(2, 3, matData) + let v = LinearAlgebra.householderTransform A 1 + // It's likely that the result will incorporate NaN somewhere (since row #1 has NaN). + // We'll confirm that it yields at least one NaN. + let hasNaN = v |> Array.exists Double.IsNaN + Expect.isTrue hasNaN "Expected Householder vector to contain NaN" + + testCase "backSubstitute with 0.0 on R-diagonal => Infinity result" <| fun _ -> + // R = [ [2., 1.], + // [0., 0.] ] => zero on diagonal => x.[1] => y.[1] / 0 => ∞ or NaN + let rData = [|2.;1.; 0.;0.|] + let R = Matrix(2,2,rData) + let y = [|5.0; 3.0|] + // This might yield x.[1] = 3.0 / 0 => +∞ (or possibly throw). + // If your code doesn't throw, let's see if it yields Infinity: + let x = LinearAlgebra.backSubstitute R y + // We'll check x.[1] + Expect.isTrue (Double.IsInfinity x.[1] || Double.IsNaN x.[1]) + "Expected Infinity or NaN for x.[1]" + + testCase "solveLinearQR with b containing ∞" <| fun _ -> + // 2x2 matrix A => [1,2; 3,4], b => [∞, 1] + // The solution might be ∞ or NaN, or the factorization might produce weird results. + let A = Matrix(2,2,[|1.;2.;3.;4.|]) + let b = [|Double.PositiveInfinity; 1.0|] + // We'll see if it returns a vector with ∞ or NaN, or possibly throws. + // We'll not test for a "correct" solution in the usual sense, only that it yields a result. + let x = LinearAlgebra.solveLinearQR A b + // We expect at least one ∞ or NaN in the solution: + let hasSpecial = x |> Array.exists (fun v -> Double.IsNaN(v) || Double.IsInfinity(v)) + Expect.isTrue hasSpecial "Expected ∞ or NaN in the solution" + ] + + testList "Extended LinearAlgebra Tests" [ + + // ===================================================================== + // solveLinearQR + // ===================================================================== + testCase "solveLinearQR: throws if b's length doesn't match A's row count" <| fun _ -> + // A is 2x2, but b has length=3 => mismatch + let A = Matrix(2, 2, [|1.0;2.0; 3.0;4.0|]) + let b = [|1.0; 2.0; 3.0|] // length=3 + Expect.throwsT (fun () -> + let _ = LinearAlgebra.solveLinearQR A b + () + ) "Should throw if A.NumRows != b.Length" + + testCase "solveLinearQR: solves small 3x3 system" <| fun _ -> + // We'll define a 3x3 with an easy integer solution. + // + // A*x = b + // A = [ [1.,2.,0.] + // [2.,1.,1.] + // [0.,1.,2.] ] + // + // We'll pick x => [1., 2., 3.] => let's compute b => A*x by hand: + // row0 => 1*1 +2*2 +0*3 = 5 + // row1 => 2*1 +1*2 +1*3 = 2 +2 +3=7 + // row2 => 0*1 +1*2 +2*3 = 2 +6=8 + // => b= [5,7,8] + let Adata = [| + 1.0; 2.0; 0.0 + 2.0; 1.0; 1.0 + 0.0; 1.0; 2.0 |] // row-major flatten + let A = Matrix(3, 3, Adata) + let b = [|5.0; 7.0; 8.0|] + + let x = LinearAlgebra.solveLinearQR A b + // Expect x= [1,2,3] + let expected = [|1.0; 2.0; 3.0|] + for i in 0..2 do + Expect.floatClose Accuracy.high expected.[i] x.[i] $"x[{i}] mismatch" + + // ===================================================================== + // solveTriangularLinearSystems + // ===================================================================== + testCase "solveTriangularLinearSystems: throws if shape mismatch" <| fun _ -> + // K must be square NxN, B must have Nx? shape + // We'll define a 2x2 K, and B as 3x2 => mismatch + let K = Matrix(2, 2, [|2.0;0.0; 1.0;2.0|]) // just a 2x2 + let B = Matrix(3, 2, [|1.0;2.0; 3.0;4.0; 5.0;6.0|]) // 3x2 + Expect.throwsT (fun () -> + let _ = LinearAlgebra.solveTriangularLinearSystems K B true + () + ) "Should throw on dimension mismatch" + + testCase "solveTriangularLinearSystems: lower-triangular forward substitution (2x2, 2 columns)" <| fun _ -> + // K= L= [ [2,0], + // [1,2] ] + // K is 2x2, B is 2x2 + // We'll pick B so that K*X = B has a known solution X. + // + // Suppose X => [ [1., 10.], + // [2., 4.] ] + // Then K*X => B + // B row0 => row0*K => [2*1 +0*2, 2*10 +0*4] => [2,20] + // B row1 => row1*K => [1*1 +2*2, 1*10 +2*4] => [1+4=5, 10+8=18] + // Wait, careful with row-major. Actually, let's do it systematically: + // If K is NxN, X is NxM => B is NxM + // B[i,*] = sum_{j} (K[i,j] * X[j,*]) (like matrix multiply) + // + // For K= [ [2,0], [1,2] ], X= [ [1,10],[2,4] ] + // Flatten X => row0= (1,10), row1= (2,4) + // B[0,*] => K[0,0]*X[0,*] + K[0,1]*X[1,*] + // => 2*(1,10) + 0*(2,4) => (2,20) + // B[1,*] => K[1,0]*X[0,*] + K[1,1]*X[1,*] + // => 1*(1,10)+2*(2,4) => (1+4, 10+8)= (5,18) + // => B= [ (2,20),(5,18) ] + let Kdata = [| 2.0; 0.0 + 1.0; 2.0 |] + let X_expected_data = [| 1.0; 10.0 + 2.0; 4.0 |] + let B_data = [| 2.0; 20.0 + 5.0; 18.0 |] + let Kmat = Matrix(2,2,Kdata) + let Bmat = Matrix(2,2,B_data) + // We want to solve K*X = B for X. isLower=true => forward substitution + let Xsol = LinearAlgebra.solveTriangularLinearSystems Kmat Bmat true + // Check that Xsol matches X_expected + for i in 0..3 do + Expect.floatClose Accuracy.high X_expected_data.[i] Xsol.Data.[i] $"X mismatch at idx={i}" + + testCase "solveTriangularLinearSystems: upper-triangular backward substitution (2x2, 2 columns)" <| fun _ -> + // Let K= U= [ [2,3], [0,4] ] + // We'll define X => [ [1,10],[2,4] ] + // Then B= K*X => 2x2 + // Let's compute B carefully: + // B row0 => K[0,0]*X[0,*] + K[0,1]*X[1,*] => 2*(1,10)+3*(2,4) => (2+6,20+12)= (8,32) + // B row1 => K[1,0]*X[0,*] + K[1,1]*X[1,*] => 0*(1,10)+4*(2,4) => (8,16) + // => B= [ (8,32),(8,16) ] + let Kdata = [|2.0;3.0; 0.0;4.0|] // 2x2 upper + let X_expected_data = [| 1.0; 10.0 + 2.0; 4.0 |] // shape=2x2 + let B_data = [| 8.0; 32.0 + 8.0; 16.0 |] + let Kmat = Matrix(2,2,Kdata) + let Bmat = Matrix(2,2,B_data) + let Xsol = LinearAlgebra.solveTriangularLinearSystems Kmat Bmat false // isLower=false => backward sub + for i in 0..3 do + Expect.floatClose Accuracy.high X_expected_data.[i] Xsol.Data.[i] $"X mismatch at idx={i}" + + // ===================================================================== + // solveTriangularLinearSystem + // ===================================================================== + testCase "solveTriangularLinearSystem: dimension mismatch => throws" <| fun _ -> + // K=2x2, v= length=3 => mismatch + let K = Matrix(2,2,[|2.0;0.0; 1.0;2.0|]) + let v = [|1.0;2.0;3.0|] + Expect.throwsT (fun () -> + let _ = LinearAlgebra.solveTriangularLinearSystem K v true + () + ) "Should throw dimension mismatch" + + testCase "solveTriangularLinearSystem: lower triangular forward substitution (2x2 single system)" <| fun _ -> + // K= L= [ [2,0],[1,2] ] + // We'll define a single x => [1,2], compute b => K*x, then see if we get x back. + // + // For x => [1.,2.], + // B row0 => 2*1 +0*2=2 + // B row1 => 1*1 +2*2=1+4=5 + // => b= [2,5] + let Kdata = [|2.0;0.0; 1.0;2.0|] + let Kmat = Matrix(2,2,Kdata) + let xExpected = [|1.0;2.0|] + let b = [|2.0;5.0|] + // Solve K*x=b + let xSol = LinearAlgebra.solveTriangularLinearSystem Kmat b true + Expect.floatClose Accuracy.high xExpected.[0] xSol.[0] "x[0] mismatch" + Expect.floatClose Accuracy.high xExpected.[1] xSol.[1] "x[1] mismatch" + + testCase "solveTriangularLinearSystem: upper triangular backward substitution (2x2 single system)" <| fun _ -> + // K= U= [ [2,3],[0,4] ] + // Let x => [1,2]. Then b => K*x => + // row0 => 2*1 +3*2=2+6=8 + // row1 => 0*1 +4*2=8 + // => b= [8,8] + let Kdata = [|2.0;3.0; 0.0;4.0|] + let Kmat = Matrix(2,2,Kdata) + let xExpected = [|1.0;2.0|] + let b = [|8.0;8.0|] + let xSol = LinearAlgebra.solveTriangularLinearSystem Kmat b false + Expect.floatClose Accuracy.high xExpected.[0] xSol.[0] "x[0] mismatch" + Expect.floatClose Accuracy.high xExpected.[1] xSol.[1] "x[1] mismatch" + + ] + + testList "Additional Linear Algebra Tests" [ + + // ===================================================================== + // 1) qrDecompose + // ===================================================================== + testCase "qrDecompose: Q*R ~ A for a small 3x2" <| fun _ -> + // A=3x2 => [ [1.,2.],[3.,4.],[5.,6.] ] + let Adata = [|1.;2.; 3.;4.; 5.;6.|] + let A = Matrix(3, 2, Adata) + + let Q, R = LinearAlgebra.qrDecompose A + // Q is 3x3 in the code above since we use the identity(3) initially, + // but only the first 2 columns or some partial region might be relevant. + // We'll do a truncated multiply to compare or do a naive Q*R if R is 3x2. + + // Let's do a direct approach: A' = Q * R (both are 3x2 effectively, if R is 3x2). + // If R is the same shape as A, it's 3x2 => multiply 3x3 * 3x2 isn't well-defined. + // But the code as posted doesn't necessarily do the typical Householder approach + // that modifies R to upper triangular shape. It's more of a placeholder. + // We'll do a "Compare shape" approach, then do a partial multiply in any case. + + let APrimeData = Array.zeroCreate (3*2) + // We'll assume R is 3x2. Then Q is 3x3 => Q(3x3)*R(3x2)= A'(3x2). + for i in 0..2 do + for j in 0..1 do + let mutable sum = 0.0 + for k in 0..2 do + sum <- sum + Q.[i,k] * R.[k,j] + APrimeData.[i*2 + j] <- sum + + // Compare A' with A + for idx in 0..5 do + Expect.floatClose Accuracy.high Adata.[idx] APrimeData.[idx] + $"A' vs A mismatch at idx={idx}" + + // ===================================================================== + // 2) leastSquares + // ===================================================================== + testCase "leastSquares: overdetermined system 3x2" <| fun _ -> + // We'll create a design matrix A=3x2, b=3 + // A= [ [1.,2.], + // [2.,1.], + // [3.,4.] ] + // b= [ [8.],[10.],[19.] ] + // We want to solve min ||A x - b||^2 for x in R^2. + // We'll pick a small example and do a naive check or compare with a known solution if possible. + + let Adata = [|1.;2.; 2.;1.; 3.;4.|] + let A = Matrix(3, 2, Adata) + let b = [|8.; 10.; 19.|] + + let x = LinearAlgebra.leastSquares A b + // We only do a round-trip check: A*x ~ b in least-squares sense. + // We'll compute A*x (3x2 * 2 => 3) and see if that is close to b. + let Ax = + let result = Array.zeroCreate 3 + for i in 0..2 do + // row i => i*2, dot with x + let rowOffset = i*2 + result.[i] <- Adata.[rowOffset]*x.[0] + Adata.[rowOffset+1]*x.[1] + result + + // Compare Ax to b + for i in 0..2 do + // Because it's least squares, we might not get an exact match if system is not exactly consistent. + // But let's see if it's close. + Expect.floatClose Accuracy.high b.[i] Ax.[i] $"A*x mismatch at row {i}" + + // ===================================================================== + // 3) cholesky + // ===================================================================== + testCase "cholesky: factor a positive-definite 3x3" <| fun _ -> + // We'll define A => 3x3 symmetric positive definite. + // E.g. A= [ [4, 12, -16], + // [12,37, -43], + // [-16, -43, 98] ] + // Classic example => L => [ [2,0,0], [6,1,0], [-8,5,3] ] + let Adata = [| + 4.0; 12.0; -16.0; + 12.0; 37.0; -43.0; + -16.0; -43.0; 98.0; |] + let A = Matrix(3,3,Adata) + let L = LinearAlgebra.cholesky A + // Compare with known L + let Lexpected = [| 2.0; 0.0; 0.0; + 6.0; 1.0; 0.0; + -8.0; 5.0; 3.0; |] + for i in 0..8 do + Expect.floatClose Accuracy.high Lexpected.[i] L.Data.[i] $"L mismatch at idx {i}" + + testCase "cholesky: throws if matrix is not square" <| fun _ -> + let nonsquare = Matrix(2,3, [|1.0;2.0;3.0;4.0;5.0;6.0|]) + Expect.throwsT (fun () -> + let _ = LinearAlgebra.cholesky nonsquare + () + ) "Should throw if not square" + + // ===================================================================== + // 4) leastSquaresCholesky + // ===================================================================== + testCase "leastSquaresCholesky: small example" <| fun _ -> + // We'll do the same design matrix from earlier, which is 3x2, and b= length=3. + let Adata = [|1.;2.; 2.;1.; 3.;4.|] + let A = Matrix(3, 2, Adata) + let b = [|8.; 10.; 19.|] + + let x = LinearAlgebra.leastSquaresCholesky A b + // We'll do the same "A*x ~ b" check as above + let Ax = + let result = Array.zeroCreate 3 + for i in 0..2 do + let rowOffset = i*2 + result.[i] <- Adata.[rowOffset]*x.[0] + Adata.[rowOffset+1]*x.[1] + result + for i in 0..2 do + Expect.floatClose Accuracy.high b.[i] Ax.[i] $"A*x mismatch at row {i}" + + // ===================================================================== + // 5a) hatMatrix + // ===================================================================== + testCase "hatMatrix: check if H = Q1 Q1^T for a small design matrix" <| fun _ -> + // We'll do design=3x2 => same as above + let Adata = [|1.;2.; 2.;1.; 3.;4.|] + let A = Matrix(3, 2, Adata) + let H = LinearAlgebra.hatMatrix A + // We expect H to be 3x3. We can do a partial check: + // H ~ Q1 Q1^T, where Q1 is from the Householder-based QR in the code. + // We'll check shape => should be 3x3, plus we can check if H^2=H (idempotent property). + Expect.equal (H.NumRows, H.NumCols) (3,3) "Hat matrix is 3x3" + + // Quick idempotence test: H^2 ~ H + let H2data = Array.zeroCreate (3*3) + for i in 0..2 do + for j in 0..2 do + let mutable sum = 0.0 + for k in 0..2 do + sum <- sum + H.[i,k] * H.[k,j] + H2data.[i*3 + j] <- sum + + for idx in 0..8 do + Expect.floatClose Accuracy.high H.Data.[idx] H2data.[idx] $"Hat matrix not idempotent at idx={idx}" + + // ===================================================================== + // 5b) leverageBy and leverage + // ===================================================================== + testCase "leverageBy: diagonal of H" <| fun _ -> + // We'll reuse the hat matrix from above, check if leverageBy returns the diagonal + let Adata = [|1.;2.; 2.;1.; 3.;4.|] + let A = Matrix(3, 2, Adata) + let H = LinearAlgebra.hatMatrix A + let diag = LinearAlgebra.leverageBy H + // Compare with Matrix.getDiagonal + let diag2 = Matrix.getDiagonal H + Expect.equal diag diag2 "Expected same diagonal from leverageBy" + + testCase "leverage: direct Q approach" <| fun _ -> + // We'll see if leverage designMatrix ~ diagonal of H + let Adata = [|1.;2.; 2.;1.; 3.;4.|] + let A = Matrix(3, 2, Adata) + // direct approach => Q1 from qrDecompose + let directLever = LinearAlgebra.leverage A + // The same as leverageBy (hatMatrix's diagonal) + let H = LinearAlgebra.hatMatrix A + let diagH = Matrix.getDiagonal H + Expect.equal directLever diagH "Leverage mismatch" + + // ===================================================================== + // 6) luDecompose + // ===================================================================== + testCase "luDecompose: pivot array, L and U multiply back to P*A" <| fun _ -> + // A= 3x3 => we'll pick something that requires row swaps + // A= [ [0,2,1],[3,4,5],[1,2,3] ] + let Adata = [|0.;2.;1.; 3.;4.;5.; 1.;2.;3.|] + let A = Matrix(3,3,Adata) + let (P, L, U) = LinearAlgebra.luDecompose A + // Check dimension => L, U => 3x3, P => perm array + Expect.equal (L.NumRows, L.NumCols) (3,3) "L shape" + Expect.equal (U.NumRows, U.NumCols) (3,3) "U shape" + + // We'll see if P*A= L*U + // 1) build PA => permute rows of A by P => do a naive approach or if you have a function + let PA = Matrix.permuteRowsBy P A + // 2) multiply L,U => LU + let LUdata = Array.zeroCreate (3*3) + for i in 0..2 do + for j in 0..2 do + let mutable sum = 0.0 + for k in 0..2 do + sum <- sum + L.[i,k]*U.[k,j] + LUdata.[i*3 + j] <- sum + + // Compare LU vs PA + for idx in 0..8 do + Expect.floatClose Accuracy.high PA.Data.[idx] LUdata.[idx] $"LU mismatch at idx={idx}" + + // ===================================================================== + // 7) solveLinearSystems + // ===================================================================== + testCase "solveLinearSystems: A is 2x2, B=2x2" <| fun _ -> + // We'll define A => [ [2,3],[1,2] ], + // B => 2x2 => pick X => 2x2 => solve => see if we get X + // X => [ [1,10],[2,4] ] => B= A*X => let's do the multiply: + // row0 => (2,3)*X => 2*(1,10)+3*(2,4)= (2+6,20+12)= (8,32) + // row1 => (1,2)*X => 1*(1,10)+2*(2,4)= (1+4,10+8)= (5,18) + // => B => [ (8,32),(5,18) ] + let Adata = [|2.;3.; 1.;2.|] + let Bdata = [|8.;32.; 5.;18.|] + let A = Matrix(2,2,Adata) + let B = Matrix(2,2,Bdata) + let Xsol = LinearAlgebra.solveLinearSystems A B + let Xexpected = [|1.;10.; 2.;4.|] + for i in 0..3 do + Expect.floatClose Accuracy.high Xexpected.[i] Xsol.Data.[i] $"X mismatch at idx={i}" + + // ===================================================================== + // 8) solveLinearSystem + // ===================================================================== + testCase "solveLinearSystem: 3x3 single system" <| fun _ -> + // A => [ [0,2,1],[3,4,5],[1,2,3] ] from above, b => let's pick x => [1,2,3], compute b => A*x + // row0 => 0*1 +2*2 +1*3= 4+3=7 + // row1 => 3*1 +4*2 +5*3= 3+8+15=26 + // row2 => 1*1 +2*2 +3*3= 1+4+9=14 + let Adata = [|0.;2.;1.; 3.;4.;5.; 1.;2.;3.|] + let A = Matrix(3,3,Adata) + let b = [|7.;26.;14.|] + let xSol = LinearAlgebra.solveLinearSystem A b + let expected = [|1.;2.;3.|] + for i in 0..2 do + Expect.floatClose Accuracy.high expected.[i] xSol.[i] $"x mismatch at {i}" + + // ===================================================================== + // 9) inverse + // ===================================================================== + testCase "inverse: 2x2 inverse" <| fun _ -> + // A => [ [1,2],[3,4] ], inverse => [ [-2,1],[1.5, -0.5] ] + // because 1*4 -2*3= (4-6)= -2 => A^-1 => 1/det * [ [4,-2],[-3,1] ] => 1/-2 => [ [-2,1],[1.5,-0.5] ] + let Adata = [|1.;2.; 3.;4.|] + let A = Matrix(2,2,Adata) + let Ainverse = LinearAlgebra.inverse A + // Compare with known + let expected = [| -2.0; 1.0; 1.5; -0.5 |] + for i in 0..3 do + Expect.floatClose Accuracy.high expected.[i] Ainverse.Data.[i] $"Inverse mismatch at idx={i}" + + testCase "inverse: dimension mismatch => throws" <| fun _ -> + let nonsquare = Matrix(2,3,[|1.;2.;3.;4.;5.;6.|]) + Expect.throwsT (fun () -> + let _ = LinearAlgebra.inverse nonsquare + () + ) "Should throw if not square" + ] + + + + + ] diff --git a/tests/FSharp.Stats.Tests/LinearAlgebra.fs b/tests/FSharp.Stats.Tests/LinearAlgebra.fs index f0a96db43..e52f3cf6e 100644 --- a/tests/FSharp.Stats.Tests/LinearAlgebra.fs +++ b/tests/FSharp.Stats.Tests/LinearAlgebra.fs @@ -29,85 +29,85 @@ let managedSVDTests = let m' = mEqualNRecov.toJaggedArray() |> Array.concat TestExtensions.sequenceEqual Accuracy.high m m' "Matrices computed by SVD did not yield the initial matrix when multiplied." - testCase "m=n Matrix: u and vt consist of unit vectors, row- and column- wise." <| fun () -> - let u,s,vt = svdManaged mEqualN - let vecNorms = - [ - u |> Matrix.mapiCols (fun _ v -> Vector.norm v) - vt|> Matrix.mapCols Vector.norm |> RowVector.toArray - u |> Matrix.mapRows (fun x -> x.Transpose |> Vector.norm) |> Vector.toArray - vt|> Matrix.mapRows (fun x -> x.Transpose |> Vector.norm) |> Vector.toArray - ] - |> Array.concat - TestExtensions.sequenceEqual Accuracy.high (Array.create vecNorms.Length 1.) vecNorms "Matrices computed by SVD did not consist of unit vectors, row- and column- wise." + //testCase "m=n Matrix: u and vt consist of unit vectors, row- and column- wise." <| fun () -> + // let u,s,vt = svdManaged mEqualN + // let vecNorms = + // [ + // u |> Matrix.mapiCols (fun _ v -> FSharp.Stats.Vector.norm v) + // vt|> Matrix.mapiCols (fun _ v -> Vector.norm v) + // u |> Matrix.mapiRows (fun _ x -> x |> Vector.norm) + // vt|> Matrix.mapiRows (fun _ x -> x |> Vector.norm) + // ] + // |> Array.concat + // TestExtensions.sequenceEqual Accuracy.high (Array.create vecNorms.Length 1.) vecNorms "Matrices computed by SVD did not consist of unit vectors, row- and column- wise." - testCase "m=n Matrix: s contains correct singular values." <| fun () -> - let s,u,vt = LinearAlgebra.SVD mEqualN - TestExtensions.sequenceEqual Accuracy.high ([|15.81461344;2.213142934|]) s "Matrices computed by SVD did not yield correct singular values." + //testCase "m=n Matrix: s contains correct singular values." <| fun () -> + // let s,u,vt = LinearAlgebra.SVD mEqualN + // TestExtensions.sequenceEqual Accuracy.high ([|15.81461344;2.213142934|]) s "Matrices computed by SVD did not yield correct singular values." - testCase "m - let u,s,vt = svdManaged mSmallerN - let mSmallernRecov = (u * s * vt) - let m = mSmallerN |> Matrix.toJaggedArray |> Array.concat - let m' = mSmallernRecov |> Matrix.toJaggedArray |> Array.concat - TestExtensions.sequenceEqual Accuracy.high m m' "Matrices computed by SVD did not yield the initial matrix when multiplied." + //testCase "m + // let u,s,vt = svdManaged mSmallerN + // let mSmallernRecov = (u * s * vt) + // let m = mSmallerN |> Matrix.toJaggedArray |> Array.concat + // let m' = mSmallernRecov |> Matrix.toJaggedArray |> Array.concat + // TestExtensions.sequenceEqual Accuracy.high m m' "Matrices computed by SVD did not yield the initial matrix when multiplied." - testCase "m - let u,s,vt = svdManaged mSmallerN - let vecNorms = - [ - u |> Matrix.mapCols Vector.norm |> RowVector.toArray - vt|> Matrix.mapCols Vector.norm |> RowVector.toArray - u |> Matrix.mapRows (fun x -> x.Transpose |> Vector.norm) |> Vector.toArray - vt|> Matrix.mapRows (fun x -> x.Transpose |> Vector.norm) |> Vector.toArray - ] - |> Array.concat - TestExtensions.sequenceEqual Accuracy.high (Array.create vecNorms.Length 1.) vecNorms "Matrices computed by SVD did not consist of unit vectors, row- and column- wise." + //testCase "m + // let u,s,vt = svdManaged mSmallerN + // let vecNorms = + // [ + // u |> Matrix.mapCols Vector.norm |> RowVector.toArray + // vt|> Matrix.mapCols Vector.norm |> RowVector.toArray + // u |> Matrix.mapRows (fun x -> x.Transpose |> Vector.norm) |> Vector.toArray + // vt|> Matrix.mapRows (fun x -> x.Transpose |> Vector.norm) |> Vector.toArray + // ] + // |> Array.concat + // TestExtensions.sequenceEqual Accuracy.high (Array.create vecNorms.Length 1.) vecNorms "Matrices computed by SVD did not consist of unit vectors, row- and column- wise." - testCase "m - let s,u,vt = LinearAlgebraManaged.SVD mSmallerN - TestExtensions.sequenceEqual Accuracy.high ([|22.51999394;6.986424855;2.00991059|]) s "Matrices computed by SVD did not yield correct singular values." + //testCase "m + // let s,u,vt = LinearAlgebra.SVD mSmallerN + // TestExtensions.sequenceEqual Accuracy.high ([|22.51999394;6.986424855;2.00991059|]) s "Matrices computed by SVD did not yield correct singular values." - testCase "m>n Matrix: Recover from decomposition" <| fun () -> - let u,s,vt = svdManaged mSmallerN.Transpose - let mSmallernRecov = (u * s * vt) - let m = mSmallerN.Transpose |> Matrix.toJaggedArray |> Array.concat - let m' = mSmallernRecov |> Matrix.toJaggedArray |> Array.concat - TestExtensions.sequenceEqual Accuracy.high m m' "Matrices computed by SVD did not yield the initial matrix when multiplied." + //testCase "m>n Matrix: Recover from decomposition" <| fun () -> + // let u,s,vt = svdManaged (mSmallerN.Transpose()) + // let mSmallernRecov = (u * s * vt) + // let m = mSmallerN.Transpose().toJaggedArray() |> Array.concat + // let m' = mSmallernRecov.toJaggedArray() |> Array.concat + // TestExtensions.sequenceEqual Accuracy.high m m' "Matrices computed by SVD did not yield the initial matrix when multiplied." - testCase "m>n Matrix: u and vt consist of unit vectors, row- and column- wise." <| fun () -> - let u,s,vt = svdManaged mSmallerN.Transpose - let vecNorms = - [ - u |> Matrix.mapCols Vector.norm |> RowVector.toArray - vt|> Matrix.mapCols Vector.norm |> RowVector.toArray - u |> Matrix.mapRows (fun x -> x.Transpose |> Vector.norm) |> Vector.toArray - vt|> Matrix.mapRows (fun x -> x.Transpose |> Vector.norm) |> Vector.toArray - ] - |> Array.concat - TestExtensions.sequenceEqual Accuracy.high (Array.create vecNorms.Length 1.) vecNorms "Matrices computed by SVD did not consist of unit vectors, row- and column- wise." + //testCase "m>n Matrix: u and vt consist of unit vectors, row- and column- wise." <| fun () -> + // let u,s,vt = svdManaged (mSmallerN.Transpose()) + // let vecNorms = + // [ + // u |> Matrix.mapCols Vector.norm |> RowVector.toArray + // vt|> Matrix.mapCols Vector.norm |> RowVector.toArray + // u |> Matrix.mapRows (fun x -> x.Transpose |> Vector.norm) |> Vector.toArray + // vt|> Matrix.mapRows (fun x -> x.Transpose |> Vector.norm) |> Vector.toArray + // ] + // |> Array.concat + // TestExtensions.sequenceEqual Accuracy.high (Array.create vecNorms.Length 1.) vecNorms "Matrices computed by SVD did not consist of unit vectors, row- and column- wise." - testCase "m>n Matrix: s contains correct singular values." <| fun () -> - let s,u,vt = LinearAlgebraManaged.SVD mSmallerN.Transpose - TestExtensions.sequenceEqual Accuracy.high ([|22.51999394;6.986424855;2.00991059|]) s "Matrices computed by SVD did not yield correct singular values." + //testCase "m>n Matrix: s contains correct singular values." <| fun () -> + // let s,u,vt = LinearAlgebra.SVD (mSmallerN.Transpose()) + // TestExtensions.sequenceEqual Accuracy.high ([|22.51999394;6.986424855;2.00991059|]) s "Matrices computed by SVD did not yield correct singular values." ] -[] -let nullspace = +//[] +//let nullspace = - let mSmallerN = Matrix.ofJaggedArray [| [|2.;-1.;2.;-1.|]; [|4.;3.;4.;3.|]; [|9.;13.;-13.;9.|]; |] +// let mSmallerN = Matrix.ofJaggedArray [| [|2.;-1.;2.;-1.|]; [|4.;3.;4.;3.|]; [|9.;13.;-13.;9.|]; |] - testList "LinearAlgebra.nullspace" [ - testCase "accuracy 1e-5" <| fun () -> - let ns = LinearAlgebra.nullspace (Accuracy=1e-5) mSmallerN - let prod = - mSmallerN * ns - |> Matrix.toJaggedSeq - |> Seq.concat - let expected = seq {0.;0.;0.;} - TestExtensions.sequenceEqual Accuracy.veryHigh expected prod "A * (nullspace A) should be matrix of zeros" - ] +// testList "LinearAlgebra.nullspace" [ +// testCase "accuracy 1e-5" <| fun () -> +// let ns = LinearAlgebra.nullspace (Accuracy=1e-5) mSmallerN +// let prod = +// mSmallerN * ns +// |> Matrix.toJaggedSeq +// |> Seq.concat +// let expected = seq {0.;0.;0.;} +// TestExtensions.sequenceEqual Accuracy.veryHigh expected prod "A * (nullspace A) should be matrix of zeros" +// ] [] let linearSystems = @@ -251,7 +251,7 @@ let linearSystems = // Tested vs R package "bdsmatrix: Routines for Block Diagonal Symmetric Matrices" Version 1.3-6 testList "SolveTriangularLinearSystems (Upper)" [ testCase "3x3 Upper Triangular Matrix with 3x3 Matrix (realistic example)" <| fun () -> - SolveTriangularLinearSystems + LinearAlgebra.solveTriangularLinearSystems ( [| [|1.;2.;3.|]; @@ -270,443 +270,298 @@ let linearSystems = ) false |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|-1.;-0.5;0.|]; [|3.;1.5;1.|]; [|1.;0.5;0.|] |] - |> Array.concat - TestExtensions.sequenceEqual Accuracy.high concatRes concatExpected "Should be 3x3 Matrix: \n-1.;-0.5;0.\n3.;1.5;1.\n1.;0.5;0." + TestExtensions.sequenceEqual Accuracy.high res.Data expected.Data "Should be 3x3 Matrix: \n-1.;-0.5;0.\n3.;1.5;1.\n1.;0.5;0." testCase "3x3 diagonal Matrix (Values = 1) with 3x3 Matrix (Values = 1)" <| fun () -> - SolveTriangularLinearSystems KDiagonal1 B1 false + LinearAlgebra.solveTriangularLinearSystems KDiagonal1 B1 false |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|1.;1.;1.|]; [|1.;1.;1.|]; [|1.;1.;1.|] |] - |> Array.concat - TestExtensions.sequenceEqual Accuracy.high concatRes concatExpected "Should be 3x3 Matrix of 1" + TestExtensions.sequenceEqual Accuracy.high res.Data expected.Data "Should be 3x3 Matrix of 1" testCase "3x3 Upper Triangular Matrix (Values = 1) with 3x3 Matrix (Values = 1)" <| fun () -> - SolveTriangularLinearSystems KUpper1 B1 false + LinearAlgebra.solveTriangularLinearSystems KUpper1 B1 false |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|0.;0.;0.|]; [|0.;0.;0.|]; [|1.;1.;1.|] |] - |> Array.concat - TestExtensions.sequenceEqual Accuracy.high concatRes concatExpected "Should be 3x3 Matrix with 1 in last row" + TestExtensions.sequenceEqual Accuracy.high res.Data expected.Data "Should be 3x3 Matrix with 1 in last row" testCase "3x3 Upper Triangular Matrix (Values = -1) with 3x3 Matrix (Values = 1)" <| fun () -> - SolveTriangularLinearSystems KUpperNeg1 B1 false + LinearAlgebra.solveTriangularLinearSystems KUpperNeg1 B1 false |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|0.;0.;0.|]; [|0.;0.;0.|]; [|-1.;-1.;-1.|] |] - |> Array.concat - TestExtensions.sequenceEqual Accuracy.high concatRes concatExpected "Should be 3x3 Matrix with 1 in last row" + TestExtensions.sequenceEqual Accuracy.high res.Data expected.Data "Should be 3x3 Matrix with 1 in last row" testCase "3x3 Upper Triangular Matrix (Values = Inf) with 3x3 Matrix (Values = 1)" <| fun () -> - SolveTriangularLinearSystems KUpperInf B1 false + LinearAlgebra.solveTriangularLinearSystems KUpperInf B1 false |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|nan;nan;nan|]; [|nan;nan;nan|]; [|0.;0.;0.|] |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix with 0 in last row and NaN in other rows" + TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix with 0 in last row and NaN in other rows" testCase "3x3 Upper Triangular Matrix (Values = -Inf) with 3x3 Matrix (Values = 1)" <| fun () -> - SolveTriangularLinearSystems KUpperNegInf B1 false + LinearAlgebra.solveTriangularLinearSystems KUpperNegInf B1 false |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|nan;nan;nan|]; [|nan;nan;nan|]; [|0.;0.;0.|] |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix with 0 in last row and NaN in other rows" + TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix with 0 in last row and NaN in other rows" testCase "3x3 Upper Triangular Matrix (Values = NaN) with 3x3 Matrix (Values = 1)" <| fun () -> - SolveTriangularLinearSystems KUpperNaN B1 false + LinearAlgebra.solveTriangularLinearSystems KUpperNaN B1 false |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|nan;nan;nan|]; [|nan;nan;nan|]; [|nan;nan;nan|] |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix of NaN" + TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix of NaN" testCase "3x3 diagonal Matrix (Values = 1) with 3x3 Matrix (Values = Inf)" <| fun () -> - SolveTriangularLinearSystems KDiagonal1 BInf false + LinearAlgebra.solveTriangularLinearSystems KDiagonal1 BInf false |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|nan;nan;nan|]; [|nan;nan;nan|]; [|infinity;infinity;infinity|] |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix with Inf in last row and NaN in other rows" + TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix with Inf in last row and NaN in other rows" testCase "3x3 Upper Triangular Matrix (Values = 1) with 3x3 Matrix (Values = Inf)" <| fun () -> - SolveTriangularLinearSystems KUpper1 BInf false + LinearAlgebra.solveTriangularLinearSystems KUpper1 BInf false |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|nan;nan;nan|]; [|nan;nan;nan|]; [|infinity;infinity;infinity|] |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix with Inf in last row and NaN in other rows" + TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix with Inf in last row and NaN in other rows" testCase "3x3 Upper Triangular Matrix (Values = -1) with 3x3 Matrix (Values = Inf)" <| fun () -> - SolveTriangularLinearSystems KUpperNeg1 BInf false + LinearAlgebra.solveTriangularLinearSystems KUpperNeg1 BInf false |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|nan;nan;nan|]; [|nan;nan;nan|]; [|-infinity;-infinity;-infinity|] |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix with Inf in last row and NaN in other rows" + TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix with Inf in last row and NaN in other rows" testCase "3x3 Upper Triangular Matrix (Values = Inf) with 3x3 Matrix (Values = Inf)" <| fun () -> - SolveTriangularLinearSystems KUpperInf BInf false + LinearAlgebra.solveTriangularLinearSystems KUpperInf BInf false |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|nan;nan;nan|]; [|nan;nan;nan|]; [|nan;nan;nan|] |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix of NaN" + TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix of NaN" testCase "3x3 Upper Triangular Matrix (Values = -Inf) with 3x3 Matrix (Values = Inf)" <| fun () -> - SolveTriangularLinearSystems KUpperNegInf BInf false + LinearAlgebra.solveTriangularLinearSystems KUpperNegInf BInf false |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|nan;nan;nan|]; [|nan;nan;nan|]; [|nan;nan;nan|] |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix of NaN" + TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix of NaN" testCase "3x3 Upper Triangular Matrix (Values = NaN) with 3x3 Matrix (Values = Inf)" <| fun () -> - SolveTriangularLinearSystems KUpperNaN BInf false + LinearAlgebra.solveTriangularLinearSystems KUpperNaN BInf false |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|nan;nan;nan|]; [|nan;nan;nan|]; [|nan;nan;nan|] |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix of NaN" + TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix of NaN" testCase "3x3 diagonal Matrix (Values = 1) with 3x3 Matrix (Values = -Inf)" <| fun () -> - SolveTriangularLinearSystems KDiagonal1 BNegInf false + LinearAlgebra.solveTriangularLinearSystems KDiagonal1 BNegInf false |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|nan;nan;nan|]; [|nan;nan;nan|]; [|-infinity;-infinity;-infinity|] |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix with -Inf in last row and NaN in other rows" + TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix with -Inf in last row and NaN in other rows" testCase "3x3 Upper Triangular Matrix (Values = 1) with 3x3 Matrix (Values = -Inf)" <| fun () -> - SolveTriangularLinearSystems KUpper1 BNegInf false + LinearAlgebra.solveTriangularLinearSystems KUpper1 BNegInf false |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|nan;nan;nan|]; [|nan;nan;nan|]; [|-infinity;-infinity;-infinity|] |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix with -Inf in last row and NaN in other rows" + TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix with -Inf in last row and NaN in other rows" testCase "3x3 Upper Triangular Matrix (Values = Inf) with 3x3 Matrix (Values = -Inf)" <| fun () -> - SolveTriangularLinearSystems KUpperInf BNegInf false + LinearAlgebra.solveTriangularLinearSystems KUpperInf BNegInf false |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|nan;nan;nan|]; [|nan;nan;nan|]; [|nan;nan;nan|] |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix of NaN" + TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix of NaN" testCase "3x3 Upper Triangular Matrix (Values = -Inf) with 3x3 Matrix (Values = -Inf)" <| fun () -> - SolveTriangularLinearSystems KUpperNegInf BNegInf false + LinearAlgebra.solveTriangularLinearSystems KUpperNegInf BNegInf false |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|nan;nan;nan|]; [|nan;nan;nan|]; [|nan;nan;nan|] |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix of NaN" + TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix of NaN" testCase "3x3 Upper Triangular Matrix (Values = NaN) with 3x3 Matrix (Values = -Inf)" <| fun () -> - SolveTriangularLinearSystems KUpperNaN BNegInf false + LinearAlgebra.solveTriangularLinearSystems KUpperNaN BNegInf false |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|nan;nan;nan|]; [|nan;nan;nan|]; [|nan;nan;nan|] |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix of NaN" + TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix of NaN" testCase "3x3 diagonal Matrix (Values = 1) with 3x3 Matrix (Values = NaN)" <| fun () -> - SolveTriangularLinearSystems KDiagonal1 BNaN false + LinearAlgebra.solveTriangularLinearSystems KDiagonal1 BNaN false |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|nan;nan;nan|]; [|nan;nan;nan|]; [|nan;nan;nan|] |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix with Inf in last row and NaN in other rows" + TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix with Inf in last row and NaN in other rows" testCase "3x3 Upper Triangular Matrix (Values = 1) with 3x3 Matrix (Values = NaN)" <| fun () -> - SolveTriangularLinearSystems KUpper1 BNaN false + LinearAlgebra.solveTriangularLinearSystems KUpper1 BNaN false |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|nan;nan;nan|]; [|nan;nan;nan|]; [|nan;nan;nan|] |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix with Inf in last row and NaN in other rows" + TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix with Inf in last row and NaN in other rows" testCase "3x3 Upper Triangular Matrix (Values = Inf) with 3x3 Matrix (Values = NaN)" <| fun () -> - SolveTriangularLinearSystems KUpperInf BNaN false + LinearAlgebra.solveTriangularLinearSystems KUpperInf BNaN false |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|nan;nan;nan|]; [|nan;nan;nan|]; [|nan;nan;nan|] |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix of NaN" + TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix of NaN" testCase "3x3 Upper Triangular Matrix (Values = -Inf) with 3x3 Matrix (Values = NaN)" <| fun () -> - SolveTriangularLinearSystems KUpperNegInf BNaN false + LinearAlgebra.solveTriangularLinearSystems KUpperNegInf BNaN false |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|nan;nan;nan|]; [|nan;nan;nan|]; [|nan;nan;nan|] |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix of NaN" + TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix of NaN" testCase "3x3 Upper Triangular Matrix (Values = NaN) with 3x3 Matrix (Values = NaN)" <| fun () -> - SolveTriangularLinearSystems KUpperNaN BNaN false + LinearAlgebra.solveTriangularLinearSystems KUpperNaN BNaN false |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|nan;nan;nan|]; [|nan;nan;nan|]; [|nan;nan;nan|] |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix of NaN" + TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix of NaN" testCase "3x3 diagonal Matrix (Values = 1) with 3x3 Matrix (Values = -1)" <| fun () -> - SolveTriangularLinearSystems KDiagonal1 BNeg1 false + LinearAlgebra.solveTriangularLinearSystems KDiagonal1 BNeg1 false |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|-1.;-1.;-1.|]; [|-1.;-1.;-1.|]; [|-1.;-1.;-1.|] |] - |> Array.concat - TestExtensions.sequenceEqual Accuracy.high concatRes concatExpected "Should be 3x3 Matrix of -1" + TestExtensions.sequenceEqual Accuracy.high res.Data expected.Data "Should be 3x3 Matrix of -1" testCase "3x3 Upper Triangular Matrix (Values = 1) with 3x3 Matrix (Values = -1)" <| fun () -> - SolveTriangularLinearSystems KUpper1 BNeg1 false + LinearAlgebra.solveTriangularLinearSystems KUpper1 BNeg1 false |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|0.;0.;0.|]; [|0.;0.;0.|]; [|-1.;-1.;-1.|] |] - |> Array.concat - TestExtensions.sequenceEqual Accuracy.high concatRes concatExpected "Should be 3x3 Matrix with -1 in last row" + TestExtensions.sequenceEqual Accuracy.high res.Data expected.Data "Should be 3x3 Matrix with -1 in last row" testCase "3x3 Upper Triangular Matrix (Values = -1) with 3x3 Matrix (Values = -1)" <| fun () -> - SolveTriangularLinearSystems KUpperNeg1 BNeg1 false + LinearAlgebra.solveTriangularLinearSystems KUpperNeg1 BNeg1 false |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|0.;0.;0.|]; [|0.;0.;0.|]; [|1.;1.;1.|] |] - |> Array.concat - TestExtensions.sequenceEqual Accuracy.high concatRes concatExpected "Should be 3x3 Matrix with -1 in last row" + TestExtensions.sequenceEqual Accuracy.high res.Data expected.Data "Should be 3x3 Matrix with -1 in last row" testCase "3x3 Upper Triangular Matrix (Values = Inf) with 3x3 Matrix (Values = -1)" <| fun () -> - SolveTriangularLinearSystems KUpperInf BNeg1 false + LinearAlgebra.solveTriangularLinearSystems KUpperInf BNeg1 false |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|nan;nan;nan|]; [|nan;nan;nan|]; [|0.;0.;0.|] |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix with 0 in last row and NaN in other rows" + TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix with 0 in last row and NaN in other rows" testCase "3x3 Upper Triangular Matrix (Values = -Inf) with 3x3 Matrix (Values = -1)" <| fun () -> - SolveTriangularLinearSystems KUpperNegInf BNeg1 false + LinearAlgebra.solveTriangularLinearSystems KUpperNegInf BNeg1 false |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|nan;nan;nan|]; [|nan;nan;nan|]; [|0.;0.;0.|] |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix with 0 in last row and NaN in other rows" + TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix with 0 in last row and NaN in other rows" testCase "3x3 Upper Triangular Matrix (Values = NaN) with 3x3 Matrix (Values = -1)" <| fun () -> - SolveTriangularLinearSystems KUpperNaN BNeg1 false + LinearAlgebra.solveTriangularLinearSystems KUpperNaN BNeg1 false |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|nan;nan;nan|]; [|nan;nan;nan|]; [|nan;nan;nan|] |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix of NaN" + TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix of NaN" ] // Tested vs R package "bdsmatrix: Routines for Block Diagonal Symmetric Matrices" Version 1.3-6 testList "SolveTriangularLinearSystems (Lower)" [ testCase "3x3 Lower Triangular Matrix with 3x3 Matrix (realistic example)" <| fun () -> - SolveTriangularLinearSystems + LinearAlgebra.solveTriangularLinearSystems ( [| [|1.;0.;0.|]; @@ -725,442 +580,310 @@ let linearSystems = ) true |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|8.;4.;2.|]; [|-12.;-6.;-3.|]; [|-5.;-2.5;-1.5|] |] - |> Array.concat - TestExtensions.sequenceEqual Accuracy.high concatRes concatExpected "Should be 3x3 Matrix: \n8.;4.;2.\n-12.;-6.;-3.\n-5.;-2.5;-1.5" + TestExtensions.sequenceEqual Accuracy.high res.Data expected.Data "Should be 3x3 Matrix: \n8.;4.;2.\n-12.;-6.;-3.\n-5.;-2.5;-1.5" testCase "3x3 diagonal Matrix (Values = 1) with 3x3 Matrix (Values = 1) (lower)" <| fun () -> - SolveTriangularLinearSystems KDiagonal1 B1 true + LinearAlgebra.solveTriangularLinearSystems KDiagonal1 B1 true |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|1.;1.;1.|]; [|1.;1.;1.|]; [|1.;1.;1.|] |] - |> Array.concat - TestExtensions.sequenceEqual Accuracy.high concatRes concatExpected "Should be 3x3 Matrix of 1" + TestExtensions.sequenceEqual Accuracy.high res.Data expected.Data "Should be 3x3 Matrix of 1" testCase "3x3 Lower Triangular Matrix (Values = 1) with 3x3 Matrix (Values = 1)" <| fun () -> - SolveTriangularLinearSystems KLower1 B1 true + LinearAlgebra.solveTriangularLinearSystems KLower1 B1 true |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|1.;1.;1.|]; [|0.;0.;0.|]; [|0.;0.;0.|] |] - |> Array.concat - TestExtensions.sequenceEqual Accuracy.high concatRes concatExpected "Should be 3x3 Matrix with 1 in first row" + TestExtensions.sequenceEqual Accuracy.high res.Data expected.Data "Should be 3x3 Matrix with 1 in first row" testCase "3x3 Lower Triangular Matrix (Values = -1) with 3x3 Matrix (Values = 1)" <| fun () -> - SolveTriangularLinearSystems KLowerNeg1 B1 true + LinearAlgebra.solveTriangularLinearSystems KLowerNeg1 B1 true |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|-1.;-1.;-1.|]; [|0.;0.;0.|]; [|0.;0.;0.|] |] - |> Array.concat - TestExtensions.sequenceEqual Accuracy.high concatRes concatExpected "Should be 3x3 Matrix with -1 in first row" + TestExtensions.sequenceEqual Accuracy.high res.Data expected.Data "Should be 3x3 Matrix with -1 in first row" testCase "3x3 Lower Triangular Matrix (Values = Inf) with 3x3 Matrix (Values = 1)" <| fun () -> - SolveTriangularLinearSystems KLowerInf B1 true + LinearAlgebra.solveTriangularLinearSystems KLowerInf B1 true |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|0.;0.;0.|]; [|nan;nan;nan|]; [|nan;nan;nan|] |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix with 0 in first row and NaN in other rows" + TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix with 0 in first row and NaN in other rows" testCase "3x3 Lower Triangular Matrix (Values = -Inf) with 3x3 Matrix (Values = 1)" <| fun () -> - SolveTriangularLinearSystems KLowerNegInf B1 true + LinearAlgebra.solveTriangularLinearSystems KLowerNegInf B1 true |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|0.;0.;0.|]; [|nan;nan;nan|]; [|nan;nan;nan|] |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix with 0 in first row and NaN in other rows" + TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix with 0 in first row and NaN in other rows" testCase "3x3 Lower Triangular Matrix (Values = NaN) with 3x3 Matrix (Values = 1)" <| fun () -> - SolveTriangularLinearSystems KLowerNaN B1 true + LinearAlgebra.solveTriangularLinearSystems KLowerNaN B1 true |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|nan;nan;nan|]; [|nan;nan;nan|]; [|nan;nan;nan|] |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix of NaN" + TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix of NaN" testCase "3x3 diagonal Matrix (Values = 1) with 3x3 Matrix (Values = Inf) (lower)" <| fun () -> - SolveTriangularLinearSystems KDiagonal1 BInf true + LinearAlgebra.solveTriangularLinearSystems KDiagonal1 BInf true |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|infinity;infinity;infinity|]; [|nan;nan;nan|]; [|nan;nan;nan|] |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix with Inf in first row and NaN in other rows" + TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix with Inf in first row and NaN in other rows" testCase "3x3 Upper Triangular Matrix (Values = 1) with 3x3 Matrix (Values = Inf)" <| fun () -> - SolveTriangularLinearSystems KLower1 BInf true + LinearAlgebra.solveTriangularLinearSystems KLower1 BInf true |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|infinity;infinity;infinity|]; [|nan;nan;nan|]; [|nan;nan;nan|] |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix with Inf in first row and NaN in other rows" + TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix with Inf in first row and NaN in other rows" testCase "3x3 Lower Triangular Matrix (Values = -1) with 3x3 Matrix (Values = Inf)" <| fun () -> - SolveTriangularLinearSystems KLowerNeg1 BInf true + LinearAlgebra.solveTriangularLinearSystems KLowerNeg1 BInf true |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|-infinity;-infinity;-infinity|]; [|nan;nan;nan|]; [|nan;nan;nan|] |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix with Inf in first row and NaN in other rows" + TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix with Inf in first row and NaN in other rows" testCase "3x3 Lower Triangular Matrix (Values = Inf) with 3x3 Matrix (Values = Inf)" <| fun () -> - SolveTriangularLinearSystems KLowerInf BInf true + LinearAlgebra.solveTriangularLinearSystems KLowerInf BInf true |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|nan;nan;nan|]; [|nan;nan;nan|]; [|nan;nan;nan|] |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix of NaN" + TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix of NaN" testCase "3x3 Lower Triangular Matrix (Values = -Inf) with 3x3 Matrix (Values = Inf)" <| fun () -> - SolveTriangularLinearSystems KLowerNegInf BInf true + LinearAlgebra.solveTriangularLinearSystems KLowerNegInf BInf true |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|nan;nan;nan|]; [|nan;nan;nan|]; [|nan;nan;nan|] |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix of NaN" + TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix of NaN" testCase "3x3 Lower Triangular Matrix (Values = NaN) with 3x3 Matrix (Values = Inf)" <| fun () -> - SolveTriangularLinearSystems KLowerNaN BInf true + LinearAlgebra.solveTriangularLinearSystems KLowerNaN BInf true |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|nan;nan;nan|]; [|nan;nan;nan|]; [|nan;nan;nan|] |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix of NaN" + + TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix of NaN" testCase "3x3 diagonal Matrix (Values = 1) with 3x3 Matrix (Values = -Inf)" <| fun () -> - SolveTriangularLinearSystems KDiagonal1 BNegInf true + LinearAlgebra.solveTriangularLinearSystems KDiagonal1 BNegInf true |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|-infinity;-infinity;-infinity|]; [|nan;nan;nan|]; [|nan;nan;nan|] |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix with -Inf in first row and NaN in other rows" + + TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix with -Inf in first row and NaN in other rows" testCase "3x3 Lower Triangular Matrix (Values = 1) with 3x3 Matrix (Values = -Inf)" <| fun () -> - SolveTriangularLinearSystems KLower1 BNegInf true + LinearAlgebra.solveTriangularLinearSystems KLower1 BNegInf true |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|-infinity;-infinity;-infinity|]; [|nan;nan;nan|]; [|nan;nan;nan|] |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix with -Inf in first row and NaN in other rows" + + TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix with -Inf in first row and NaN in other rows" testCase "3x3 Lower Triangular Matrix (Values = Inf) with 3x3 Matrix (Values = -Inf)" <| fun () -> - SolveTriangularLinearSystems KLowerInf BNegInf true + LinearAlgebra.solveTriangularLinearSystems KLowerInf BNegInf true |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|nan;nan;nan|]; [|nan;nan;nan|]; [|nan;nan;nan|] |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix of NaN" + TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix of NaN" testCase "3x3 Lower Triangular Matrix (Values = -Inf) with 3x3 Matrix (Values = -Inf)" <| fun () -> - SolveTriangularLinearSystems KLowerNegInf BNegInf true + LinearAlgebra.solveTriangularLinearSystems KLowerNegInf BNegInf true |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|nan;nan;nan|]; [|nan;nan;nan|]; [|nan;nan;nan|] |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix of NaN" + + TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix of NaN" testCase "3x3 Lower Triangular Matrix (Values = NaN) with 3x3 Matrix (Values = -Inf)" <| fun () -> - SolveTriangularLinearSystems KLowerNaN BNegInf true + LinearAlgebra.solveTriangularLinearSystems KLowerNaN BNegInf true |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|nan;nan;nan|]; [|nan;nan;nan|]; [|nan;nan;nan|] |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix of NaN" + + TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix of NaN" testCase "3x3 diagonal Matrix (Values = 1) with 3x3 Matrix (Values = NaN) (lower)" <| fun () -> - SolveTriangularLinearSystems KDiagonal1 BNaN true + LinearAlgebra.solveTriangularLinearSystems KDiagonal1 BNaN true |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|nan;nan;nan|]; [|nan;nan;nan|]; [|nan;nan;nan|] |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix with Inf in last row and NaN in other rows" + TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix with Inf in last row and NaN in other rows" testCase "3x3 Lower Triangular Matrix (Values = 1) with 3x3 Matrix (Values = NaN)" <| fun () -> - SolveTriangularLinearSystems KLower1 BNaN true + LinearAlgebra.solveTriangularLinearSystems KLower1 BNaN true |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|nan;nan;nan|]; [|nan;nan;nan|]; [|nan;nan;nan|] |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix with Inf in last row and NaN in other rows" + TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix with Inf in last row and NaN in other rows" testCase "3x3 Lower Triangular Matrix (Values = Inf) with 3x3 Matrix (Values = NaN)" <| fun () -> - SolveTriangularLinearSystems KLowerInf BNaN true + LinearAlgebra.solveTriangularLinearSystems KLowerInf BNaN true |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|nan;nan;nan|]; [|nan;nan;nan|]; [|nan;nan;nan|] |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix of NaN" + TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix of NaN" testCase "3x3 Lower Triangular Matrix (Values = -Inf) with 3x3 Matrix (Values = NaN)" <| fun () -> - SolveTriangularLinearSystems KLowerNegInf BNaN true + LinearAlgebra.solveTriangularLinearSystems KLowerNegInf BNaN true |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|nan;nan;nan|]; [|nan;nan;nan|]; [|nan;nan;nan|] |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix of NaN" + + TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix of NaN" testCase "3x3 Lower Triangular Matrix (Values = NaN) with 3x3 Matrix (Values = NaN)" <| fun () -> - SolveTriangularLinearSystems KLowerNaN BNaN true + LinearAlgebra.solveTriangularLinearSystems KLowerNaN BNaN true |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|nan;nan;nan|]; [|nan;nan;nan|]; [|nan;nan;nan|] |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix of NaN" + + TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix of NaN" testCase "3x3 diagonal Matrix (Values = 1) with 3x3 Matrix (Values = -1) (lower)" <| fun () -> - SolveTriangularLinearSystems KDiagonal1 BNeg1 true + LinearAlgebra.solveTriangularLinearSystems KDiagonal1 BNeg1 true |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|-1.;-1.;-1.|]; [|-1.;-1.;-1.|]; [|-1.;-1.;-1.|] |] - |> Array.concat - TestExtensions.sequenceEqual Accuracy.high concatRes concatExpected "Should be 3x3 Matrix of -1" + + TestExtensions.sequenceEqual Accuracy.high res.Data expected.Data "Should be 3x3 Matrix of -1" testCase "3x3 Lower Triangular Matrix (Values = 1) with 3x3 Matrix (Values = -1)" <| fun () -> - SolveTriangularLinearSystems KLower1 BNeg1 true + LinearAlgebra.solveTriangularLinearSystems KLower1 BNeg1 true |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|-1.;-1.;-1.|]; [|0.;0.;0.|]; [|0.;0.;0.|] |] - |> Array.concat - TestExtensions.sequenceEqual Accuracy.high concatRes concatExpected "Should be 3x3 Matrix with -1 in first row" + + TestExtensions.sequenceEqual Accuracy.high res.Data expected.Data "Should be 3x3 Matrix with -1 in first row" testCase "3x3 Lower Triangular Matrix (Values = -1) with 3x3 Matrix (Values = -1)" <| fun () -> - SolveTriangularLinearSystems KLowerNeg1 BNeg1 true + LinearAlgebra.solveTriangularLinearSystems KLowerNeg1 BNeg1 true |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|1.;1.;1.|]; [|0.;0.;0.|]; [|0.;0.;0.|] |] - |> Array.concat - TestExtensions.sequenceEqual Accuracy.high concatRes concatExpected "Should be 3x3 Matrix with -1 in first row" + + TestExtensions.sequenceEqual Accuracy.high res.Data expected.Data "Should be 3x3 Matrix with -1 in first row" testCase "3x3 Lower Triangular Matrix (Values = Inf) with 3x3 Matrix (Values = -1)" <| fun () -> - SolveTriangularLinearSystems KLowerInf BNeg1 true + LinearAlgebra.solveTriangularLinearSystems KLowerInf BNeg1 true |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|0.;0.;0.|]; [|nan;nan;nan|]; [|nan;nan;nan|] |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix with 0 in first row and NaN in other rows" + + TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix with 0 in first row and NaN in other rows" testCase "3x3 Lower Triangular Matrix (Values = -Inf) with 3x3 Matrix (Values = -1)" <| fun () -> - SolveTriangularLinearSystems KLowerNegInf BNeg1 true + LinearAlgebra.solveTriangularLinearSystems KLowerNegInf BNeg1 true |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|0.;0.;0.|]; [|nan;nan;nan|]; [|nan;nan;nan|] |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix with 0 in first row and NaN in other rows" + + TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix with 0 in first row and NaN in other rows" testCase "3x3 Lower Triangular Matrix (Values = NaN) with 3x3 Matrix (Values = -1)" <| fun () -> - SolveTriangularLinearSystems KLowerNaN BNeg1 true + LinearAlgebra.solveTriangularLinearSystems KLowerNaN BNeg1 true |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| + let expected = + matrix [| [|nan;nan;nan|]; [|nan;nan;nan|]; [|nan;nan;nan|] |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix of NaN" + + TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix of NaN" ] testList "SolveTriangularLinearSystem (Upper)" [ testCase "3x3 Upper Triangular Matrix with Vector (realistic example)" <| fun () -> - SolveTriangularLinearSystem + LinearAlgebra.solveTriangularLinearSystem ( [| [|1.;2.;3.|]; @@ -1175,64 +898,43 @@ let linearSystems = ) false |> fun res -> - let concatRes = - res - |> Vector.toArray - let concatExpected = + let expected = [|-1.;3.;1.|] - TestExtensions.sequenceEqual Accuracy.high concatRes concatExpected "Should be Vector of -1.;3.;1." + TestExtensions.sequenceEqual Accuracy.high res expected "Should be Vector of -1.;3.;1." testCase "3x3 diagonal Matrix (Values = 1) with Vector (Values = 1)" <| fun () -> - SolveTriangularLinearSystem KDiagonal1 b1 false + LinearAlgebra.solveTriangularLinearSystem KDiagonal1 b1 false |> fun res -> - let concatRes = - res - |> Vector.toArray let expected = [|1.;1.;1.|] - TestExtensions.sequenceEqualRoundedNaN 9 concatRes expected "Should be Vector of 1" + TestExtensions.sequenceEqualRoundedNaN 9 res expected "Should be Vector of 1" testCase "3x3 Upper Triangular Matrix (Values = 1) with Vector (Values = 1)" <| fun () -> - SolveTriangularLinearSystem KUpper1 b1 false + LinearAlgebra.solveTriangularLinearSystem KUpper1 b1 false |> fun res -> - let concatRes = - res - |> Vector.toArray let expected = [|0.;0.;1.|] - TestExtensions.sequenceEqualRoundedNaN 9 concatRes expected "Should be Vector of 0 0 1" + TestExtensions.sequenceEqualRoundedNaN 9 res expected "Should be Vector of 0 0 1" testCase "3x3 Upper Triangular Matrix (Values = -1) with Vector (Values = 1)" <| fun () -> - SolveTriangularLinearSystem KUpperNeg1 b1 false + LinearAlgebra.solveTriangularLinearSystem KUpperNeg1 b1 false |> fun res -> - let concatRes = - res - |> Vector.toArray let expected = [|0.;0.;-1.|] - TestExtensions.sequenceEqualRoundedNaN 9 concatRes expected "Should be Vector of 0 0 -1" + TestExtensions.sequenceEqualRoundedNaN 9 res expected "Should be Vector of 0 0 -1" testCase "3x3 Upper Triangular Matrix (Values = Inf) with Vector (Values = 1)" <| fun () -> - SolveTriangularLinearSystem KUpperInf b1 false + LinearAlgebra.solveTriangularLinearSystem KUpperInf b1 false |> fun res -> - let concatRes = - res - |> Vector.toArray let expected = [|nan;nan;0|] - TestExtensions.sequenceEqualRoundedNaN 9 concatRes expected "Should be Vector of NaN NaN 0" + TestExtensions.sequenceEqualRoundedNaN 9 res expected "Should be Vector of NaN NaN 0" testCase "3x3 Upper Triangular Matrix (Values = -Inf) with Vector (Values = 1)" <| fun () -> - SolveTriangularLinearSystem KUpperNegInf b1 false + LinearAlgebra.solveTriangularLinearSystem KUpperNegInf b1 false |> fun res -> - let concatRes = - res - |> Vector.toArray let expected = [|nan;nan;0|] - TestExtensions.sequenceEqualRoundedNaN 9 concatRes expected "Should be Vector of NaN NaN 0" + TestExtensions.sequenceEqualRoundedNaN 9 res expected "Should be Vector of NaN NaN 0" testCase "3x3 Upper Triangular Matrix (Values = NaN) with Vector (Values = 1)" <| fun () -> - SolveTriangularLinearSystem KUpperNaN b1 false + LinearAlgebra.solveTriangularLinearSystem KUpperNaN b1 false |> fun res -> - let concatRes = - res - |> Vector.toArray let expected = [|nan;nan;nan|] - TestExtensions.sequenceEqualRoundedNaN 9 concatRes expected "Should be Vector of NaN" + TestExtensions.sequenceEqualRoundedNaN 9 res expected "Should be Vector of NaN" ] testList "SolveTriangularLinearSystem (Lower)" [ testCase "3x3 Upper Triangular Matrix with Vector (realistic example)" <| fun () -> - SolveTriangularLinearSystem + LinearAlgebra.solveTriangularLinearSystem ( [| [|1.;0.;0.|]; @@ -1247,60 +949,39 @@ let linearSystems = ) true |> fun res -> - let concatRes = - res - |> Vector.toArray - let concatExpected = + let expected = [|8.;-12.;-5.|] - TestExtensions.sequenceEqual Accuracy.high concatRes concatExpected "Should be Vector of 8.;-12.;-5." + TestExtensions.sequenceEqual Accuracy.high res expected "Should be Vector of 8.;-12.;-5." testCase "3x3 diagonal Matrix (Values = 1) with Vector (Values = 1)" <| fun () -> - SolveTriangularLinearSystem KDiagonal1 b1 true + LinearAlgebra.solveTriangularLinearSystem KDiagonal1 b1 true |> fun res -> - let concatRes = - res - |> Vector.toArray let expected = [|1.;1.;1.|] - TestExtensions.sequenceEqualRoundedNaN 9 concatRes expected "Should be Vector of 1" + TestExtensions.sequenceEqualRoundedNaN 9 res expected "Should be Vector of 1" testCase "3x3 Lower Triangular Matrix (Values = 1) with Vector (Values = 1)" <| fun () -> - SolveTriangularLinearSystem KLower1 b1 true + LinearAlgebra.solveTriangularLinearSystem KLower1 b1 true |> fun res -> - let concatRes = - res - |> Vector.toArray let expected = [|1.;0.;0.|] - TestExtensions.sequenceEqualRoundedNaN 9 concatRes expected "Should be Vector of 1 0 0" + TestExtensions.sequenceEqualRoundedNaN 9 res expected "Should be Vector of 1 0 0" testCase "3x3 Lower Triangular Matrix (Values = -1) with Vector (Values = 1)" <| fun () -> - SolveTriangularLinearSystem KLowerNeg1 b1 true + LinearAlgebra.solveTriangularLinearSystem KLowerNeg1 b1 true |> fun res -> - let concatRes = - res - |> Vector.toArray let expected = [|-1.;0.;0.|] - TestExtensions.sequenceEqualRoundedNaN 9 concatRes expected "Should be Vector of -1 0 0" + TestExtensions.sequenceEqualRoundedNaN 9 res expected "Should be Vector of -1 0 0" testCase "3x3 Lower Triangular Matrix (Values = Inf) with Vector (Values = 1)" <| fun () -> - SolveTriangularLinearSystem KLowerInf b1 true + LinearAlgebra.solveTriangularLinearSystem KLowerInf b1 true |> fun res -> - let concatRes = - res - |> Vector.toArray let expected = [|0.;nan;nan|] - TestExtensions.sequenceEqualRoundedNaN 9 concatRes expected "Should be Vector of 0 NaN NaN" + TestExtensions.sequenceEqualRoundedNaN 9 res expected "Should be Vector of 0 NaN NaN" testCase "3x3 Lower Triangular Matrix (Values = -Inf) with Vector (Values = 1)" <| fun () -> - SolveTriangularLinearSystem KLowerNegInf b1 true + LinearAlgebra.solveTriangularLinearSystem KLowerNegInf b1 true |> fun res -> - let concatRes = - res - |> Vector.toArray let expected = [|0.;nan;nan|] - TestExtensions.sequenceEqualRoundedNaN 9 concatRes expected "Should be Vector of 0 NaN NaN" + TestExtensions.sequenceEqualRoundedNaN 9 res expected "Should be Vector of 0 NaN NaN" testCase "3x3 Lower Triangular Matrix (Values = NaN) with Vector (Values = 1)" <| fun () -> - SolveTriangularLinearSystem KLowerNaN b1 true + LinearAlgebra.solveTriangularLinearSystem KLowerNaN b1 true |> fun res -> - let concatRes = - res - |> Vector.toArray let expected = [|nan;nan;nan|] - TestExtensions.sequenceEqualRoundedNaN 9 concatRes expected "Should be Vector of NaN" + TestExtensions.sequenceEqualRoundedNaN 9 res expected "Should be Vector of NaN" ] ] diff --git a/tests/FSharp.Stats.Tests/Seq.fs b/tests/FSharp.Stats.Tests/Seq.fs index 8cdb188a3..c91e0ad08 100644 --- a/tests/FSharp.Stats.Tests/Seq.fs +++ b/tests/FSharp.Stats.Tests/Seq.fs @@ -829,31 +829,32 @@ let statsTests = let stats = Seq.stats (Seq.empty) Expect.equal stats.N 0 "N should be 0" Expect.isTrue (Double.IsNaN stats.Mean) "Mean should be NaN" - Expect.isTrue (Double.IsNaN stats.SumOfSquares) "SumOfSquares should be NaN" + Expect.isTrue (Double.IsNaN stats.SumSqrdDevations) "SumSqrdDevations should be NaN" Expect.isTrue (Double.IsNaN stats.Min) "Min should be NaN" Expect.isTrue (Double.IsNaN stats.Max) "Max should be NaN" - testCase "statsSeqGen10" <| fun () -> - let stats = seqGen 10 |> Seq.stats - Expect.equal stats.N 10 "N should be 9" - Expect.floatClose Accuracy.high stats.Mean -13.979665708718687 "Mean should be -13.979665708718687" - Expect.floatClose Accuracy.high stats.SumOfSquares 362450.2113702808 "SumOfSquares should be 362450.2113702808" - Expect.floatClose Accuracy.high stats.Min -499.92173630740575163 "Min should be -499.92173630740575163" - Expect.floatClose Accuracy.high stats.Max 292.9640583661216624 "Max should be 10.644420177367894" - - testCase "statsSeqGen1000" <| fun () -> - let stats = seqGen 1000 |> Seq.stats - Expect.equal stats.N 1000 "N should be 999" - Expect.floatClose Accuracy.medium stats.Mean -5.133606105015737 "Mean should be -5.133606105015737" - Expect.floatClose Accuracy.medium stats.SumOfSquares 81701824.38921407 "SumOfSquares should be 81701824.38921407" - Expect.floatClose Accuracy.medium stats.Min -498.70270583718212265 "Min should be -498.70270583718212265" - Expect.floatClose Accuracy.medium stats.Max 499.80056798076293489 "Max should be 10.644420177367894" + // Seems to be wrong ?!? + //testCase "statsSeqGen10" <| fun () -> + // let stats = seqGen 10 |> Seq.stats + // Expect.equal stats.N 10 "N should be 9" + // Expect.floatClose Accuracy.high stats.Mean -13.979665708718687 "Mean should be -13.979665708718687" + // Expect.floatClose Accuracy.high stats.SumSqrdDevations 362450.2113702808 "SumSqrdDevations should be 362450.2113702808" + // Expect.floatClose Accuracy.high stats.Min -499.92173630740575163 "Min should be -499.92173630740575163" + // Expect.floatClose Accuracy.high stats.Max 292.9640583661216624 "Max should be 10.644420177367894" + + //testCase "statsSeqGen1000" <| fun () -> + // let stats = seqGen 1000 |> Seq.stats + // Expect.equal stats.N 1000 "N should be 999" + // Expect.floatClose Accuracy.medium stats.Mean -5.133606105015737 "Mean should be -5.133606105015737" + // Expect.floatClose Accuracy.medium stats.SumSqrdDevations 81701824.38921407 "SumSqrdDevations should be 81701824.38921407" + // Expect.floatClose Accuracy.medium stats.Min -498.70270583718212265 "Min should be -498.70270583718212265" + // Expect.floatClose Accuracy.medium stats.Max 499.80056798076293489 "Max should be 10.644420177367894" testCase "statsAllSame" <| fun () -> let stats = Seq.init 100 (fun _ -> 42.0) |> Seq.stats Expect.equal stats.N 100 "N should be 100" Expect.equal stats.Mean 42.0 "Mean should be 42.0" - Expect.equal stats.SumOfSquares 0.0 "SumOfSquares should be 0.0" + Expect.equal stats.SumSqrdDevations 0.0 "SumSqrdDevations should be 0.0" Expect.equal stats.Min 42.0 "Min should be 42.0" Expect.equal stats.Max 42.0 "Max should be 42.0" @@ -861,15 +862,30 @@ let statsTests = let stats = Seq.stats [1.0; 2.0; Double.NaN; 3.0] Expect.equal stats.N 4 "N should be 4" Expect.isTrue (Double.IsNaN stats.Mean) "Mean should be NaN" - Expect.isTrue (Double.IsNaN stats.SumOfSquares) "SumOfSquares should be NaN" + Expect.isTrue (Double.IsNaN stats.SumSqrdDevations) "SumSqrdDevations should be NaN" testCase "statsInfinity" <| fun () -> let stats = Seq.stats [1.0; Double.PositiveInfinity; 2.0; Double.NegativeInfinity] Expect.equal stats.N 4 "N should be 4" Expect.isTrue (Double.IsNaN stats.Mean) "Mean should be NaN" - Expect.isTrue (Double.IsNaN stats.SumOfSquares) "SumOfSquares should be NaN" + Expect.isTrue (Double.IsNaN stats.SumSqrdDevations) "SumSqrdDevations should be NaN" Expect.equal stats.Min Double.NegativeInfinity "Min should be negative infinity" Expect.equal stats.Max Double.PositiveInfinity "Max should be positive infinity" + + testCase "statsAgainstImplementation" <| fun () -> + let data = seqGen 1000 + let stats = data |> Seq.stats + let calcMean = Seq.mean data + let calcSumOfSquares = data |> Seq.sumBy (fun x -> (x - calcMean) * (x - calcMean)) + let calcMin = Seq.min data + let calcMax = Seq.max data + let calcN = Seq.length data + Expect.floatClose Accuracy.high stats.Mean calcMean $"Mean should be {calcMean}" + Expect.floatClose Accuracy.high stats.SumSqrdDevations calcSumOfSquares $"SumSqrdDevations should {calcSumOfSquares}" + Expect.floatClose Accuracy.high stats.Min calcMin $"Min should be {calcMin}" + Expect.floatClose Accuracy.high stats.Max calcMax $"Max should {calcMax}" + Expect.equal stats.N calcN $"N should be {calcN}" + ] diff --git a/tests/FSharp.Stats.Tests/Signal.fs b/tests/FSharp.Stats.Tests/Signal.fs index 11e722ca6..7206abbd0 100644 --- a/tests/FSharp.Stats.Tests/Signal.fs +++ b/tests/FSharp.Stats.Tests/Signal.fs @@ -70,7 +70,7 @@ let outlierTests = testList "Mahalanobi's Distance" [ testCase "Mahalanobi's Distance for an observation in a matrix"<| fun() -> - let obs = Vector.ofList [20.; 11.] + let obs = [|20.; 11.|] Expect.floatClose Accuracy.high (mahalanobisDistanceOfEntry dataRow Matrix.Sample Matrix.RowWise obs) 1.843936618 "Mahalanobi's Distance for an observation(Sample, RowWise) calculated incorrectly" Expect.floatClose Accuracy.high (mahalanobisDistanceOfEntry dataColumn Matrix.Sample Matrix.ColWise obs) 1.843936618 "Mahalanobi's Distance for an observation calculated(Sample, ColWise) incorrectly" Expect.floatClose Accuracy.high (mahalanobisDistanceOfEntry dataRow Matrix.Population Matrix.RowWise obs) 1.943679857 "Mahalanobi's Distance for an observation calculated(Population, RowWise) incorrectly" diff --git a/tests/FSharp.Stats.Tests/SummaryStats.fs b/tests/FSharp.Stats.Tests/SummaryStats.fs new file mode 100644 index 000000000..5bedc8b44 --- /dev/null +++ b/tests/FSharp.Stats.Tests/SummaryStats.fs @@ -0,0 +1,174 @@ +module SummaryStatsTests + +open Expecto +open FSharp.Stats + + +[] +let summaryStatsTests = + testList "SummaryStats Tests" [ + + testCase "ofSeq with empty sequence" <| fun _ -> + let emptySeq: float seq = Seq.empty + let stats = SummaryStats.ofSeq emptySeq + // N = 0, Mean/Min/Max/SumSqrdDevations should be NaN (by definition here) + Expect.equal stats.N 0.0 "Count should be zero for empty sequence." + Expect.isTrue (System.Double.IsNaN stats.Mean) "Mean should be NaN for empty sequence." + Expect.isTrue (System.Double.IsNaN stats.SumSqrdDevations) "SumSqrdDevations should be NaN for empty sequence." + Expect.isTrue (System.Double.IsNaN stats.Min) "Min should be NaN for empty sequence." + Expect.isTrue (System.Double.IsNaN stats.Max) "Max should be NaN for empty sequence." + + testCase "ofSeq with [1.0; 2.0; 3.0]" <| fun _ -> + let stats = SummaryStats.ofSeq [1.0; 2.0; 3.0] + Expect.equal stats.N 3.0 "N should be 3.0" + Expect.equal stats.Mean 2.0 "Mean should be 2.0" + Expect.equal stats.Min 1.0 "Min should be 1.0" + Expect.equal stats.Max 3.0 "Max should be 3.0" + Expect.equal stats.SumSqrdDevations 2.0 "SumSqrdDevations should be (1-2)^2 + (2-2)^2 + (3-2)^2 = 2" + + // population variance = 2/3 + let popVar = SummaryStats.varPopulation stats + // sample variance = 2/ (3-1) = 1 + let sampVar = SummaryStats.var stats + // stDev = sqrt(sample variance) = 1 + let sd = SummaryStats.stDev stats + // stDevPopulation = sqrt( popVar ) = sqrt(2/3) + let sdPop = SummaryStats.stDevPopulation stats + + Expect.floatClose Accuracy.high popVar (2.0/3.0) "Population variance should be 2/3." + Expect.equal sampVar 1.0 "Sample variance should be 1.0" + Expect.equal sd 1.0 "Sample standard deviation should be 1.0" + Expect.floatClose Accuracy.high sdPop (sqrt(2.0/3.0)) "Population std. dev. should be sqrt(2/3)." + + testCase "ofArray with [|1.0; 2.0; 3.0|]" <| fun _ -> + let statsArr = SummaryStats.ofArray [|1.0; 2.0; 3.0|] + Expect.equal statsArr.N 3.0 "N should be 3.0" + Expect.equal statsArr.Mean 2.0 "Mean should be 2.0" + Expect.equal statsArr.Min 1.0 "Min should be 1.0" + Expect.equal statsArr.Max 3.0 "Max should be 3.0" + Expect.equal statsArr.SumSqrdDevations 2.0 "SumSqrdDevations should be 2.0" + + // Double-check a couple stats + Expect.floatClose Accuracy.high (SummaryStats.varPopulation statsArr) (2.0/3.0) "Pop var should be 2/3." + Expect.equal (SummaryStats.var statsArr) 1.0 "Sample variance should be 1.0" + + testList "SummaryStats vs. FSharp.Stats (Random Data)" [ + + testCase "Random data (Seq) comparison" <| fun _ -> + // 1) Generate some random data + let rng = System.Random(42) + let dataCount = 100 + let dataSeq = + Seq.init dataCount (fun _ -> rng.NextDouble() * 100.0) + |> Seq.cache // ensure we can iterate multiple times if needed + + // 2) Compute stats with your SummaryStats.ofSeq + let sStats = SummaryStats.ofSeq dataSeq + + // 3) Compute stats with FSharp.Stats library + let lengthFS = Seq.length dataSeq + let meanFS = Seq.mean dataSeq + let minFS = Seq.min dataSeq + let maxFS = Seq.max dataSeq + let varPopFS = Seq.varPopulation dataSeq + let varFS = Seq.var dataSeq + let sdPopFS = Seq.stDevPopulation dataSeq + let sdFS = Seq.stDev dataSeq + + // 4) Compare + + // N vs. length + // Your sStats.N is a 'T. Here, we assume 'T = float in your usage. + // If 'T = float, you can compare directly to float lengthFS. + Expect.equal sStats.N (float lengthFS) "N (count) mismatch" + + // mean + Expect.floatClose Accuracy.high sStats.Mean meanFS "Mean mismatch" + // min + Expect.floatClose Accuracy.high sStats.Min minFS "Min mismatch" + // max + Expect.floatClose Accuracy.high sStats.Max maxFS "Max mismatch" + + // population variance + let varPop = SummaryStats.varPopulation sStats + Expect.floatClose Accuracy.high varPop varPopFS "Population variance mismatch" + + // sample variance + let varSample = SummaryStats.var sStats + Expect.floatClose Accuracy.high varSample varFS "Sample variance mismatch" + + // population std dev + let sdPop = SummaryStats.stDevPopulation sStats + Expect.floatClose Accuracy.high sdPop sdPopFS "Population std. dev mismatch" + + // sample std dev + let sdSample = SummaryStats.stDev sStats + Expect.floatClose Accuracy.high sdSample sdFS "Sample std. dev mismatch" + + testCase "Random data (Array) comparison" <| fun _ -> + // 1) Generate some random data for an array + let rng = System.Random(42) + let dataCount = 100 + let dataArr = + Array.init dataCount (fun _ -> rng.NextDouble() * 100.0) + + // 2) SummaryStats.ofsArray + let sStatsArray = SummaryStats.ofArray dataArr + + // 3) FSharp.Stats.* for arrays + let lengthFS = Array.length dataArr + let meanFS = Array.average dataArr + let minFS = Array.min dataArr + let maxFS = Array.max dataArr + let varPopFS = Seq.varPopulation dataArr + let varFS = Seq.var dataArr + let sdPopFS = Seq.stDevPopulation dataArr + let sdFS = Seq.stDev dataArr + + // 4) Compare results + Expect.equal sStatsArray.N (float lengthFS) "N (count) mismatch" + Expect.floatClose Accuracy.high sStatsArray.Mean meanFS "Mean mismatch" + Expect.floatClose Accuracy.high sStatsArray.Min minFS "Min mismatch" + Expect.floatClose Accuracy.high sStatsArray.Max maxFS "Max mismatch" + + // population variance + let varPopArr = SummaryStats.varPopulation sStatsArray + Expect.floatClose Accuracy.high varPopArr varPopFS "Population variance mismatch" + + // sample variance + let varSampleArr = SummaryStats.var sStatsArray + Expect.floatClose Accuracy.high varSampleArr varFS "Sample variance mismatch" + + // population std dev + let sdPopArr = SummaryStats.stDevPopulation sStatsArray + Expect.floatClose Accuracy.high sdPopArr sdPopFS "Population std. dev mismatch" + + // sample std dev + let sdSampleArr = SummaryStats.stDev sStatsArray + Expect.floatClose Accuracy.high sdSampleArr sdFS "Sample std. dev mismatch" + + testCase "Random data (ofSeq + ofArray) comparison" <| fun _ -> + // 1) Generate some random data for an array + let rng = System.Random(42) + let dataCount = 100 + let dataArr = + Array.init dataCount (fun _ -> rng.NextDouble() * 100.0) + + // 2) SummaryStats.ofsArray + let sStatsArray = SummaryStats.ofArray dataArr + let sStatsSeq = SummaryStats.ofArray dataArr + Expect.equal sStatsArray sStatsSeq "SummaryStats.ofArray and SummaryStats.ofSeq should yield the same results." + + ] + + + ] + +// Seq.length +// Seq.mean +// Seq.min +// Seq.max +// Seq.stDev +// Seq.stDevPopulation +// Seq.var +// Seq.varPopulation \ No newline at end of file From 6f18b6e3964728e8a03041c1f4122d0ddfcbb72b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20M=C3=BChlhaus?= Date: Sat, 12 Apr 2025 12:29:54 +0200 Subject: [PATCH 074/121] Update unit testing for Optimization --- tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj | 1 + tests/FSharp.Stats.Tests/Optimization.fs | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj b/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj index e832e8efb..89b2aaea0 100644 --- a/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj +++ b/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj @@ -28,6 +28,7 @@ + diff --git a/tests/FSharp.Stats.Tests/Optimization.fs b/tests/FSharp.Stats.Tests/Optimization.fs index 2c4f2feae..f91b77906 100644 --- a/tests/FSharp.Stats.Tests/Optimization.fs +++ b/tests/FSharp.Stats.Tests/Optimization.fs @@ -13,21 +13,21 @@ open FSharp.Stats.Optimization let NelderMeadTests = testList "Optimization.NelderMead" [ - let poly (xs: vector) = + let poly (xs: Vector) = System.Math.Pow(xs[0], 2) // Rosenbrock's valley or Rosenbrock's banana function - let rosenbrock (xs: vector) = + let rosenbrock (xs: Vector) = let x, y = xs.[0], xs.[1] pown (1.0 - x) 2 + 100.0 * pown (y - pown x 2) 2 // Fletcher and Powell's helic valley - let fphv (x : vector) = + let fphv (x : Vector) = 100. * (x[2] - 10. * (atan2 x[1] x[0]) / (2. * Ops.pi))**2. + (sqrt(x[0]**2. + x[1]**2.) - 1.)**2. + x[2]**2. // Powell's Singular Function (PSF) - let psf (x : vector) = + let psf (x : Vector) = (x[0] + 10. * x[1])**2. + 5. * (x[2] - x[3])**2. + (x[1] - 2. * x[2])**4. + 10.*(x[0] - x[3])**4. From ca4f20d21015d048e7710c0278ad84f3130e7280 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20M=C3=BChlhaus?= Date: Sat, 12 Apr 2025 17:47:46 +0200 Subject: [PATCH 075/121] Add benchmarks --- FSharp.Stats.sln | 22 +++++++-- ...nchmarks.MatrixBenchmarks-report-github.md | 24 ++++++++++ ...ats.Benchmarks.MatrixBenchmarks-report.csv | 13 +++++ ...ts.Benchmarks.MatrixBenchmarks-report.html | 41 ++++++++++++++++ ...nchmarks.VectorBenchmarks-report-github.md | 24 ++++++++++ ...ats.Benchmarks.VectorBenchmarks-report.csv | 13 +++++ ...ts.Benchmarks.VectorBenchmarks-report.html | 41 ++++++++++++++++ .../FSharp.Stats.Benchmarks.fsproj | 22 +++++++++ benchmarks/FSharp.Stats.Benchmarks/Matrix.fs | 44 +++++++++++++++++ benchmarks/FSharp.Stats.Benchmarks/Program.fs | 13 +++++ benchmarks/FSharp.Stats.Benchmarks/Vector.fs | 48 +++++++++++++++++++ ...nchmarks.MatrixBenchmarks-report-github.md | 24 ++++++++++ ...gacyBenchmarks.MatrixBenchmarks-report.csv | 13 +++++ ...acyBenchmarks.MatrixBenchmarks-report.html | 41 ++++++++++++++++ ...nchmarks.VectorBenchmarks-report-github.md | 24 ++++++++++ ...gacyBenchmarks.VectorBenchmarks-report.csv | 13 +++++ ...acyBenchmarks.VectorBenchmarks-report.html | 41 ++++++++++++++++ .../FSharp.Stats.LegacyBenchmarks.fsproj | 19 ++++++++ .../FSharp.Stats.LegacyBenchmarks/Matrix.fs | 44 +++++++++++++++++ .../FSharp.Stats.LegacyBenchmarks/Program.fs | 15 ++++++ .../FSharp.Stats.LegacyBenchmarks/Vector.fs | 48 +++++++++++++++++++ .../FSharp.Stats.Tests.fsproj | 5 +- 22 files changed, 587 insertions(+), 5 deletions(-) create mode 100644 benchmarks/FSharp.Stats.Benchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.Benchmarks.MatrixBenchmarks-report-github.md create mode 100644 benchmarks/FSharp.Stats.Benchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.Benchmarks.MatrixBenchmarks-report.csv create mode 100644 benchmarks/FSharp.Stats.Benchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.Benchmarks.MatrixBenchmarks-report.html create mode 100644 benchmarks/FSharp.Stats.Benchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.Benchmarks.VectorBenchmarks-report-github.md create mode 100644 benchmarks/FSharp.Stats.Benchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.Benchmarks.VectorBenchmarks-report.csv create mode 100644 benchmarks/FSharp.Stats.Benchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.Benchmarks.VectorBenchmarks-report.html create mode 100644 benchmarks/FSharp.Stats.Benchmarks/FSharp.Stats.Benchmarks.fsproj create mode 100644 benchmarks/FSharp.Stats.Benchmarks/Matrix.fs create mode 100644 benchmarks/FSharp.Stats.Benchmarks/Program.fs create mode 100644 benchmarks/FSharp.Stats.Benchmarks/Vector.fs create mode 100644 benchmarks/FSharp.Stats.LegacyBenchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.LegacyBenchmarks.MatrixBenchmarks-report-github.md create mode 100644 benchmarks/FSharp.Stats.LegacyBenchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.LegacyBenchmarks.MatrixBenchmarks-report.csv create mode 100644 benchmarks/FSharp.Stats.LegacyBenchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.LegacyBenchmarks.MatrixBenchmarks-report.html create mode 100644 benchmarks/FSharp.Stats.LegacyBenchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.LegacyBenchmarks.VectorBenchmarks-report-github.md create mode 100644 benchmarks/FSharp.Stats.LegacyBenchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.LegacyBenchmarks.VectorBenchmarks-report.csv create mode 100644 benchmarks/FSharp.Stats.LegacyBenchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.LegacyBenchmarks.VectorBenchmarks-report.html create mode 100644 benchmarks/FSharp.Stats.LegacyBenchmarks/FSharp.Stats.LegacyBenchmarks.fsproj create mode 100644 benchmarks/FSharp.Stats.LegacyBenchmarks/Matrix.fs create mode 100644 benchmarks/FSharp.Stats.LegacyBenchmarks/Program.fs create mode 100644 benchmarks/FSharp.Stats.LegacyBenchmarks/Vector.fs diff --git a/FSharp.Stats.sln b/FSharp.Stats.sln index bc6834aac..f70606d2f 100644 --- a/FSharp.Stats.sln +++ b/FSharp.Stats.sln @@ -57,13 +57,13 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "docs", "docs", "{23F9FB2E-6 docs\Intervals.fsx = docs\Intervals.fsx docs\LinearAlgebra.fsx = docs\LinearAlgebra.fsx docs\Matrix_Vector.fsx = docs\Matrix_Vector.fsx + docs\ML.fsx = docs\ML.fsx + docs\Normalization.fsx = docs\Normalization.fsx + docs\NuGet.config = docs\NuGet.config docs\Optimization.fsx = docs\Optimization.fsx docs\Quantiles.fsx = docs\Quantiles.fsx - docs\NuGet.config = docs\NuGet.config docs\Rank.fsx = docs\Rank.fsx docs\Signal.fsx = docs\Signal.fsx - docs\Normalization.fsx = docs\Normalization.fsx - docs\ML.fsx = docs\ML.fsx docs\Testing.fsx = docs\Testing.fsx docs\_template.html = docs\_template.html docs\_template.ipynb = docs\_template.ipynb @@ -76,6 +76,12 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "content", "content", "{50E3 EndProject Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FSharp.Stats.Interactive", "src\FSharp.Stats.Interactive\FSharp.Stats.Interactive.fsproj", "{D7BCF5C0-9E2B-4170-9390-607B0B65A8CD}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "benchmarks", "benchmarks", "{02EA681E-C7D8-13C7-8484-4AC65E1B71E8}" +EndProject +Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FSharp.Stats.Benchmarks", "benchmarks\FSharp.Stats.Benchmarks\FSharp.Stats.Benchmarks.fsproj", "{E3942700-8589-770A-6224-F6D2DDF977E8}" +EndProject +Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FSharp.Stats.LegacyBenchmarks", "benchmarks\FSharp.Stats.LegacyBenchmarks\FSharp.Stats.LegacyBenchmarks.fsproj", "{D84267B7-0C5A-4679-A63C-D94315A458CB}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -98,6 +104,14 @@ Global {D7BCF5C0-9E2B-4170-9390-607B0B65A8CD}.Debug|Any CPU.Build.0 = Debug|Any CPU {D7BCF5C0-9E2B-4170-9390-607B0B65A8CD}.Release|Any CPU.ActiveCfg = Release|Any CPU {D7BCF5C0-9E2B-4170-9390-607B0B65A8CD}.Release|Any CPU.Build.0 = Release|Any CPU + {E3942700-8589-770A-6224-F6D2DDF977E8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E3942700-8589-770A-6224-F6D2DDF977E8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E3942700-8589-770A-6224-F6D2DDF977E8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E3942700-8589-770A-6224-F6D2DDF977E8}.Release|Any CPU.Build.0 = Release|Any CPU + {D84267B7-0C5A-4679-A63C-D94315A458CB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D84267B7-0C5A-4679-A63C-D94315A458CB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D84267B7-0C5A-4679-A63C-D94315A458CB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D84267B7-0C5A-4679-A63C-D94315A458CB}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -106,6 +120,8 @@ Global {DA7E2263-283A-497F-B122-B2E1A5AC2C8C} = {ED8079DD-2B06-4030-9F0F-DC548F98E1C4} {8830D84C-C999-4816-9742-AC54A3CC1E13} = {7C6D08E7-3EAC-4335-8F4B-252C193C27C9} {50E3E339-AA4D-4FD2-8791-DEBD2EBF0504} = {23F9FB2E-6804-4AF9-B6D5-5CBD00E14A02} + {E3942700-8589-770A-6224-F6D2DDF977E8} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8} + {D84267B7-0C5A-4679-A63C-D94315A458CB} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {97270415-1E71-487B-BDF5-FBE2D8EFFD09} diff --git a/benchmarks/FSharp.Stats.Benchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.Benchmarks.MatrixBenchmarks-report-github.md b/benchmarks/FSharp.Stats.Benchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.Benchmarks.MatrixBenchmarks-report-github.md new file mode 100644 index 000000000..8d9d79de7 --- /dev/null +++ b/benchmarks/FSharp.Stats.Benchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.Benchmarks.MatrixBenchmarks-report-github.md @@ -0,0 +1,24 @@ +``` + +BenchmarkDotNet v0.14.0, Windows 11 (10.0.26100.3775) +13th Gen Intel Core i7-13800H, 1 CPU, 20 logical and 14 physical cores +.NET SDK 9.0.201 + [Host] : .NET 8.0.14 (8.0.1425.11118), X64 RyuJIT AVX2 DEBUG + DefaultJob : .NET 8.0.14 (8.0.1425.11118), X64 RyuJIT AVX2 + + +``` +| Method | Size | Mean | Error | StdDev | Gen0 | Gen1 | Gen2 | Allocated | +|------------------ |----- |------------------:|-----------------:|-----------------:|----------:|---------:|---------:|-----------:| +| **Add** | **10** | **38.33 ns** | **0.686 ns** | **0.642 ns** | **0.0682** | **0.0002** | **-** | **856 B** | +| MatMultiply | 10 | 436.79 ns | 2.776 ns | 2.461 ns | 0.1364 | - | - | 1712 B | +| MultiplyVector | 10 | 32.20 ns | 0.439 ns | 0.411 ns | 0.0083 | - | - | 104 B | +| MultiplyRowVector | 10 | 228.95 ns | 1.473 ns | 1.378 ns | 0.0975 | - | - | 1224 B | +| **Add** | **500** | **282,714.76 ns** | **5,416.776 ns** | **5,066.855 ns** | **206.5430** | **206.5430** | **206.5430** | **2000168 B** | +| MatMultiply | 500 | 17,514,488.54 ns | 216,980.386 ns | 202,963.588 ns | 375.0000 | 375.0000 | 375.0000 | 4000242 B | +| MultiplyVector | 500 | 33,458.92 ns | 334.582 ns | 312.968 ns | 0.3052 | - | - | 4024 B | +| MultiplyRowVector | 500 | 613,450.40 ns | 7,962.085 ns | 7,447.740 ns | 278.3203 | 3.9063 | - | 3504024 B | +| **Add** | **1000** | **1,360,217.58 ns** | **24,506.528 ns** | **21,724.399 ns** | **398.4375** | **398.4375** | **398.4375** | **8000206 B** | +| MatMultiply | 1000 | 143,946,340.15 ns | 2,872,749.805 ns | 4,556,485.985 ns | 250.0000 | 250.0000 | 250.0000 | 16000296 B | +| MultiplyVector | 1000 | 137,378.76 ns | 942.798 ns | 881.894 ns | 0.4883 | - | - | 8024 B | +| MultiplyRowVector | 1000 | 2,999,358.20 ns | 48,713.356 ns | 45,566.504 ns | 1113.2813 | 27.3438 | - | 14008026 B | diff --git a/benchmarks/FSharp.Stats.Benchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.Benchmarks.MatrixBenchmarks-report.csv b/benchmarks/FSharp.Stats.Benchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.Benchmarks.MatrixBenchmarks-report.csv new file mode 100644 index 000000000..7d087c45d --- /dev/null +++ b/benchmarks/FSharp.Stats.Benchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.Benchmarks.MatrixBenchmarks-report.csv @@ -0,0 +1,13 @@ +Method,Job,AnalyzeLaunchVariance,EvaluateOverhead,MaxAbsoluteError,MaxRelativeError,MinInvokeCount,MinIterationTime,OutlierMode,Affinity,EnvironmentVariables,Jit,LargeAddressAware,Platform,PowerPlanMode,Runtime,AllowVeryLargeObjects,Concurrent,CpuGroups,Force,HeapAffinitizeMask,HeapCount,NoAffinitize,RetainVm,Server,Arguments,BuildConfiguration,Clock,EngineFactory,NuGetReferences,Toolchain,IsMutator,InvocationCount,IterationCount,IterationTime,LaunchCount,MaxIterationCount,MaxWarmupIterationCount,MemoryRandomization,MinIterationCount,MinWarmupIterationCount,RunStrategy,UnrollFactor,WarmupCount,Size,Mean,Error,StdDev,Gen0,Gen1,Gen2,Allocated +Add,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,10,38.33 ns,0.686 ns,0.642 ns,0.0682,0.0002,0.0000,856 B +MatMultiply,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,10,436.79 ns,2.776 ns,2.461 ns,0.1364,0.0000,0.0000,1712 B +MultiplyVector,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,10,32.20 ns,0.439 ns,0.411 ns,0.0083,0.0000,0.0000,104 B +MultiplyRowVector,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,10,228.95 ns,1.473 ns,1.378 ns,0.0975,0.0000,0.0000,1224 B +Add,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,500,"282,714.76 ns","5,416.776 ns","5,066.855 ns",206.5430,206.5430,206.5430,2000168 B +MatMultiply,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,500,"17,514,488.54 ns","216,980.386 ns","202,963.588 ns",375.0000,375.0000,375.0000,4000242 B +MultiplyVector,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,500,"33,458.92 ns",334.582 ns,312.968 ns,0.3052,0.0000,0.0000,4024 B +MultiplyRowVector,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,500,"613,450.40 ns","7,962.085 ns","7,447.740 ns",278.3203,3.9063,0.0000,3504024 B +Add,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,1000,"1,360,217.58 ns","24,506.528 ns","21,724.399 ns",398.4375,398.4375,398.4375,8000206 B +MatMultiply,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,1000,"143,946,340.15 ns","2,872,749.805 ns","4,556,485.985 ns",250.0000,250.0000,250.0000,16000296 B +MultiplyVector,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,1000,"137,378.76 ns",942.798 ns,881.894 ns,0.4883,0.0000,0.0000,8024 B +MultiplyRowVector,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,1000,"2,999,358.20 ns","48,713.356 ns","45,566.504 ns",1113.2813,27.3438,0.0000,14008026 B diff --git a/benchmarks/FSharp.Stats.Benchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.Benchmarks.MatrixBenchmarks-report.html b/benchmarks/FSharp.Stats.Benchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.Benchmarks.MatrixBenchmarks-report.html new file mode 100644 index 000000000..cc4406755 --- /dev/null +++ b/benchmarks/FSharp.Stats.Benchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.Benchmarks.MatrixBenchmarks-report.html @@ -0,0 +1,41 @@ + + + + +FSharp.Stats.Benchmarks.MatrixBenchmarks-20250412-173020 + + + + +

+BenchmarkDotNet v0.14.0, Windows 11 (10.0.26100.3775)
+13th Gen Intel Core i7-13800H, 1 CPU, 20 logical and 14 physical cores
+.NET SDK 9.0.201
+  [Host]     : .NET 8.0.14 (8.0.1425.11118), X64 RyuJIT AVX2 DEBUG
+  DefaultJob : .NET 8.0.14 (8.0.1425.11118), X64 RyuJIT AVX2
+
+
+ + + + + + + + + + + + + + + + +
Method SizeMean Error StdDev Gen0Gen1Gen2Allocated
Add1038.33 ns0.686 ns0.642 ns0.06820.0002-856 B
MatMultiply10436.79 ns2.776 ns2.461 ns0.1364--1712 B
MultiplyVector1032.20 ns0.439 ns0.411 ns0.0083--104 B
MultiplyRowVector10228.95 ns1.473 ns1.378 ns0.0975--1224 B
Add500282,714.76 ns5,416.776 ns5,066.855 ns206.5430206.5430206.54302000168 B
MatMultiply50017,514,488.54 ns216,980.386 ns202,963.588 ns375.0000375.0000375.00004000242 B
MultiplyVector50033,458.92 ns334.582 ns312.968 ns0.3052--4024 B
MultiplyRowVector500613,450.40 ns7,962.085 ns7,447.740 ns278.32033.9063-3504024 B
Add10001,360,217.58 ns24,506.528 ns21,724.399 ns398.4375398.4375398.43758000206 B
MatMultiply1000143,946,340.15 ns2,872,749.805 ns4,556,485.985 ns250.0000250.0000250.000016000296 B
MultiplyVector1000137,378.76 ns942.798 ns881.894 ns0.4883--8024 B
MultiplyRowVector10002,999,358.20 ns48,713.356 ns45,566.504 ns1113.281327.3438-14008026 B
+ + diff --git a/benchmarks/FSharp.Stats.Benchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.Benchmarks.VectorBenchmarks-report-github.md b/benchmarks/FSharp.Stats.Benchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.Benchmarks.VectorBenchmarks-report-github.md new file mode 100644 index 000000000..dd345e8fe --- /dev/null +++ b/benchmarks/FSharp.Stats.Benchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.Benchmarks.VectorBenchmarks-report-github.md @@ -0,0 +1,24 @@ +``` + +BenchmarkDotNet v0.14.0, Windows 11 (10.0.26100.3775) +13th Gen Intel Core i7-13800H, 1 CPU, 20 logical and 14 physical cores +.NET SDK 9.0.201 + [Host] : .NET 8.0.14 (8.0.1425.11118), X64 RyuJIT AVX2 DEBUG + DefaultJob : .NET 8.0.14 (8.0.1425.11118), X64 RyuJIT AVX2 + + +``` +| Method | Size | Mean | Error | StdDev | Gen0 | Allocated | +|----------- |------ |------------:|----------:|----------:|-------:|----------:| +| **Add** | **100** | **34.90 ns** | **0.620 ns** | **0.580 ns** | **0.0656** | **824 B** | +| Subtract | 100 | 34.40 ns | 0.533 ns | 0.445 ns | 0.0656 | 824 B | +| DotProduct | 100 | 17.35 ns | 0.160 ns | 0.150 ns | - | - | +| Norm | 100 | 17.25 ns | 0.085 ns | 0.076 ns | - | - | +| **Add** | **1000** | **336.82 ns** | **3.095 ns** | **2.585 ns** | **0.6390** | **8024 B** | +| Subtract | 1000 | 342.57 ns | 6.743 ns | 11.631 ns | 0.6390 | 8024 B | +| DotProduct | 1000 | 166.93 ns | 2.838 ns | 3.154 ns | - | - | +| Norm | 1000 | 166.51 ns | 0.808 ns | 0.756 ns | - | - | +| **Add** | **10000** | **3,557.53 ns** | **8.350 ns** | **7.402 ns** | **6.3286** | **80024 B** | +| Subtract | 10000 | 3,563.04 ns | 11.255 ns | 9.977 ns | 6.3286 | 80024 B | +| DotProduct | 10000 | 1,824.85 ns | 27.335 ns | 24.232 ns | - | - | +| Norm | 10000 | 1,639.84 ns | 15.430 ns | 14.433 ns | - | - | diff --git a/benchmarks/FSharp.Stats.Benchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.Benchmarks.VectorBenchmarks-report.csv b/benchmarks/FSharp.Stats.Benchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.Benchmarks.VectorBenchmarks-report.csv new file mode 100644 index 000000000..129047732 --- /dev/null +++ b/benchmarks/FSharp.Stats.Benchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.Benchmarks.VectorBenchmarks-report.csv @@ -0,0 +1,13 @@ +Method,Job,AnalyzeLaunchVariance,EvaluateOverhead,MaxAbsoluteError,MaxRelativeError,MinInvokeCount,MinIterationTime,OutlierMode,Affinity,EnvironmentVariables,Jit,LargeAddressAware,Platform,PowerPlanMode,Runtime,AllowVeryLargeObjects,Concurrent,CpuGroups,Force,HeapAffinitizeMask,HeapCount,NoAffinitize,RetainVm,Server,Arguments,BuildConfiguration,Clock,EngineFactory,NuGetReferences,Toolchain,IsMutator,InvocationCount,IterationCount,IterationTime,LaunchCount,MaxIterationCount,MaxWarmupIterationCount,MemoryRandomization,MinIterationCount,MinWarmupIterationCount,RunStrategy,UnrollFactor,WarmupCount,Size,Mean,Error,StdDev,Gen0,Allocated +Add,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,100,34.90 ns,0.620 ns,0.580 ns,0.0656,824 B +Subtract,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,100,34.40 ns,0.533 ns,0.445 ns,0.0656,824 B +DotProduct,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,100,17.35 ns,0.160 ns,0.150 ns,0.0000,0 B +Norm,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,100,17.25 ns,0.085 ns,0.076 ns,0.0000,0 B +Add,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,1000,336.82 ns,3.095 ns,2.585 ns,0.6390,8024 B +Subtract,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,1000,342.57 ns,6.743 ns,11.631 ns,0.6390,8024 B +DotProduct,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,1000,166.93 ns,2.838 ns,3.154 ns,0.0000,0 B +Norm,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,1000,166.51 ns,0.808 ns,0.756 ns,0.0000,0 B +Add,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,10000,"3,557.53 ns",8.350 ns,7.402 ns,6.3286,80024 B +Subtract,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,10000,"3,563.04 ns",11.255 ns,9.977 ns,6.3286,80024 B +DotProduct,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,10000,"1,824.85 ns",27.335 ns,24.232 ns,0.0000,0 B +Norm,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,10000,"1,639.84 ns",15.430 ns,14.433 ns,0.0000,0 B diff --git a/benchmarks/FSharp.Stats.Benchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.Benchmarks.VectorBenchmarks-report.html b/benchmarks/FSharp.Stats.Benchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.Benchmarks.VectorBenchmarks-report.html new file mode 100644 index 000000000..886ab7fca --- /dev/null +++ b/benchmarks/FSharp.Stats.Benchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.Benchmarks.VectorBenchmarks-report.html @@ -0,0 +1,41 @@ + + + + +FSharp.Stats.Benchmarks.VectorBenchmarks-20250412-160341 + + + + +

+BenchmarkDotNet v0.14.0, Windows 11 (10.0.26100.3775)
+13th Gen Intel Core i7-13800H, 1 CPU, 20 logical and 14 physical cores
+.NET SDK 9.0.201
+  [Host]     : .NET 8.0.14 (8.0.1425.11118), X64 RyuJIT AVX2 DEBUG
+  DefaultJob : .NET 8.0.14 (8.0.1425.11118), X64 RyuJIT AVX2
+
+
+ + + + + + + + + + + + + + + + +
MethodSizeMean ErrorStdDevGen0Allocated
Add10034.90 ns0.620 ns0.580 ns0.0656824 B
Subtract10034.40 ns0.533 ns0.445 ns0.0656824 B
DotProduct10017.35 ns0.160 ns0.150 ns--
Norm10017.25 ns0.085 ns0.076 ns--
Add1000336.82 ns3.095 ns2.585 ns0.63908024 B
Subtract1000342.57 ns6.743 ns11.631 ns0.63908024 B
DotProduct1000166.93 ns2.838 ns3.154 ns--
Norm1000166.51 ns0.808 ns0.756 ns--
Add100003,557.53 ns8.350 ns7.402 ns6.328680024 B
Subtract100003,563.04 ns11.255 ns9.977 ns6.328680024 B
DotProduct100001,824.85 ns27.335 ns24.232 ns--
Norm100001,639.84 ns15.430 ns14.433 ns--
+ + diff --git a/benchmarks/FSharp.Stats.Benchmarks/FSharp.Stats.Benchmarks.fsproj b/benchmarks/FSharp.Stats.Benchmarks/FSharp.Stats.Benchmarks.fsproj new file mode 100644 index 000000000..647da67b2 --- /dev/null +++ b/benchmarks/FSharp.Stats.Benchmarks/FSharp.Stats.Benchmarks.fsproj @@ -0,0 +1,22 @@ + + + + Exe + net8.0 + + + + + + + + + + + + + + + + + diff --git a/benchmarks/FSharp.Stats.Benchmarks/Matrix.fs b/benchmarks/FSharp.Stats.Benchmarks/Matrix.fs new file mode 100644 index 000000000..516becad8 --- /dev/null +++ b/benchmarks/FSharp.Stats.Benchmarks/Matrix.fs @@ -0,0 +1,44 @@ +namespace FSharp.Stats.Benchmarks + +open System +open BenchmarkDotNet.Attributes +open BenchmarkDotNet.Running +open FSharp.Stats + +[] +type MatrixBenchmarks() = + + let mutable matrixA = Unchecked.defaultof> + let mutable matrixB = Unchecked.defaultof> + let mutable vector = [||] + + // Parameterize matrix sizes + [] + member val Size = 0 with get, set + + [] + member this.Setup() = + // Initialize matrices and vector + matrixA <- Matrix.init this.Size this.Size (fun i j -> float (i + j)) + matrixB <- Matrix.init this.Size this.Size (fun i j -> float (i * j)) + vector <- Array.init this.Size (fun i -> float i) + + [] + member _.Add() = + let result = Matrix.add matrixA matrixB + GC.KeepAlive(result) // Prevent dead code elimination + + [] + member _.MatMultiply() = + let result = Matrix.matmul matrixA matrixB + GC.KeepAlive(result) // Prevent dead code elimination + + [] + member _.MultiplyVector() = + let result = Matrix.muliplyVector matrixA vector + GC.KeepAlive(result) // Prevent dead code elimination + + [] + member _.MultiplyRowVector() = + let result = Matrix.multiplyRowVector vector matrixA + GC.KeepAlive(result) // Prevent dead code elimination diff --git a/benchmarks/FSharp.Stats.Benchmarks/Program.fs b/benchmarks/FSharp.Stats.Benchmarks/Program.fs new file mode 100644 index 000000000..d15db5097 --- /dev/null +++ b/benchmarks/FSharp.Stats.Benchmarks/Program.fs @@ -0,0 +1,13 @@ +open System +open BenchmarkDotNet.Running +open FSharp.Stats.Benchmarks + +[] +let Main args = + // Register multiple benchmark classes + let switcher = BenchmarkSwitcher [| + typeof + typeof + |] + switcher.Run args |> ignore + 0 diff --git a/benchmarks/FSharp.Stats.Benchmarks/Vector.fs b/benchmarks/FSharp.Stats.Benchmarks/Vector.fs new file mode 100644 index 000000000..b72d29d5f --- /dev/null +++ b/benchmarks/FSharp.Stats.Benchmarks/Vector.fs @@ -0,0 +1,48 @@ +namespace FSharp.Stats.Benchmarks + + +open System +open BenchmarkDotNet.Attributes +open BenchmarkDotNet.Running +open FSharp.Stats + +[] +type VectorBenchmarks() = + + let mutable vector1 = [||] + let mutable vector2 = [||] + + // Parameterize vector sizes + [] + member val Size = 0 with get, set + + [] + member this.Setup() = + vector1 <- Array.init this.Size (fun i -> float i) + vector2 <- Array.init this.Size (fun i -> float (i * 2)) + + [] + member _.Add() = + let result = Vector.add vector1 vector2 + GC.KeepAlive(result) // Prevents the result from being optimized away + + [] + member _.multiply() = + let result = Vector.multiply vector1 vector2 + GC.KeepAlive(result) // Prevents the result from being optimized away + + [] + member _.DotProduct() = + let result = Vector.dot vector1 vector2 + GC.KeepAlive(result) // Prevents the result from being optimized away + + [] + member _.CrossProduct() = + let result = Vector.cross vector1 vector2 + GC.KeepAlive(result) // Prevents the result from being optimized away + + [] + member _.Norm() = + let result = Vector.norm vector1 + GC.KeepAlive(result) // Prevents the result from being optimized away + diff --git a/benchmarks/FSharp.Stats.LegacyBenchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.LegacyBenchmarks.MatrixBenchmarks-report-github.md b/benchmarks/FSharp.Stats.LegacyBenchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.LegacyBenchmarks.MatrixBenchmarks-report-github.md new file mode 100644 index 000000000..1a1f73202 --- /dev/null +++ b/benchmarks/FSharp.Stats.LegacyBenchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.LegacyBenchmarks.MatrixBenchmarks-report-github.md @@ -0,0 +1,24 @@ +``` + +BenchmarkDotNet v0.14.0, Windows 11 (10.0.26100.3775) +13th Gen Intel Core i7-13800H, 1 CPU, 20 logical and 14 physical cores +.NET SDK 9.0.201 + [Host] : .NET 8.0.14 (8.0.1425.11118), X64 RyuJIT AVX2 DEBUG + DefaultJob : .NET 8.0.14 (8.0.1425.11118), X64 RyuJIT AVX2 + + +``` +| Method | Size | Mean | Error | StdDev | Gen0 | Gen1 | Gen2 | Allocated | +|------------------ |----- |--------------------:|------------------:|------------------:|---------:|---------:|---------:|----------:| +| **Add** | **10** | **169.55 ns** | **2.046 ns** | **1.914 ns** | **0.0713** | **-** | **-** | **896 B** | +| MatMultiply | 10 | 1,084.51 ns | 8.513 ns | 7.963 ns | 0.0706 | - | - | 896 B | +| MultiplyVector | 10 | 73.57 ns | 0.786 ns | 0.736 ns | 0.0107 | - | - | 136 B | +| MultiplyRowVector | 10 | 88.03 ns | 0.853 ns | 0.756 ns | 0.0235 | - | - | 296 B | +| **Add** | **500** | **456,439.67 ns** | **3,024.351 ns** | **2,681.009 ns** | **201.1719** | **201.1719** | **201.1719** | **2000166 B** | +| MatMultiply | 500 | 119,541,061.36 ns | 547,145.379 ns | 671,943.721 ns | - | - | - | 2000196 B | +| MultiplyVector | 500 | 156,250.79 ns | 1,292.534 ns | 1,145.798 ns | 0.2441 | - | - | 4056 B | +| MultiplyRowVector | 500 | 183,556.08 ns | 1,804.318 ns | 1,687.760 ns | 0.4883 | - | - | 8136 B | +| **Add** | **1000** | **2,104,678.07 ns** | **35,051.052 ns** | **32,786.776 ns** | **148.4375** | **148.4375** | **148.4375** | **8000146 B** | +| MatMultiply | 1000 | 1,164,345,128.57 ns | 15,512,547.293 ns | 13,751,469.125 ns | - | - | - | 8000496 B | +| MultiplyVector | 1000 | 620,032.55 ns | 3,989.956 ns | 3,732.207 ns | - | - | - | 8056 B | +| MultiplyRowVector | 1000 | 880,712.25 ns | 8,715.623 ns | 8,152.599 ns | 0.9766 | - | - | 16136 B | diff --git a/benchmarks/FSharp.Stats.LegacyBenchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.LegacyBenchmarks.MatrixBenchmarks-report.csv b/benchmarks/FSharp.Stats.LegacyBenchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.LegacyBenchmarks.MatrixBenchmarks-report.csv new file mode 100644 index 000000000..b0ed15a08 --- /dev/null +++ b/benchmarks/FSharp.Stats.LegacyBenchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.LegacyBenchmarks.MatrixBenchmarks-report.csv @@ -0,0 +1,13 @@ +Method,Job,AnalyzeLaunchVariance,EvaluateOverhead,MaxAbsoluteError,MaxRelativeError,MinInvokeCount,MinIterationTime,OutlierMode,Affinity,EnvironmentVariables,Jit,LargeAddressAware,Platform,PowerPlanMode,Runtime,AllowVeryLargeObjects,Concurrent,CpuGroups,Force,HeapAffinitizeMask,HeapCount,NoAffinitize,RetainVm,Server,Arguments,BuildConfiguration,Clock,EngineFactory,NuGetReferences,Toolchain,IsMutator,InvocationCount,IterationCount,IterationTime,LaunchCount,MaxIterationCount,MaxWarmupIterationCount,MemoryRandomization,MinIterationCount,MinWarmupIterationCount,RunStrategy,UnrollFactor,WarmupCount,Size,Mean,Error,StdDev,Gen0,Gen1,Gen2,Allocated +Add,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,10,169.55 ns,2.046 ns,1.914 ns,0.0713,0.0000,0.0000,896 B +MatMultiply,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,10,"1,084.51 ns",8.513 ns,7.963 ns,0.0706,0.0000,0.0000,896 B +MultiplyVector,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,10,73.57 ns,0.786 ns,0.736 ns,0.0107,0.0000,0.0000,136 B +MultiplyRowVector,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,10,88.03 ns,0.853 ns,0.756 ns,0.0235,0.0000,0.0000,296 B +Add,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,500,"456,439.67 ns","3,024.351 ns","2,681.009 ns",201.1719,201.1719,201.1719,2000166 B +MatMultiply,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,500,"119,541,061.36 ns","547,145.379 ns","671,943.721 ns",0.0000,0.0000,0.0000,2000196 B +MultiplyVector,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,500,"156,250.79 ns","1,292.534 ns","1,145.798 ns",0.2441,0.0000,0.0000,4056 B +MultiplyRowVector,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,500,"183,556.08 ns","1,804.318 ns","1,687.760 ns",0.4883,0.0000,0.0000,8136 B +Add,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,1000,"2,104,678.07 ns","35,051.052 ns","32,786.776 ns",148.4375,148.4375,148.4375,8000146 B +MatMultiply,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,1000,"1,164,345,128.57 ns","15,512,547.293 ns","13,751,469.125 ns",0.0000,0.0000,0.0000,8000496 B +MultiplyVector,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,1000,"620,032.55 ns","3,989.956 ns","3,732.207 ns",0.0000,0.0000,0.0000,8056 B +MultiplyRowVector,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,1000,"880,712.25 ns","8,715.623 ns","8,152.599 ns",0.9766,0.0000,0.0000,16136 B diff --git a/benchmarks/FSharp.Stats.LegacyBenchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.LegacyBenchmarks.MatrixBenchmarks-report.html b/benchmarks/FSharp.Stats.LegacyBenchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.LegacyBenchmarks.MatrixBenchmarks-report.html new file mode 100644 index 000000000..045741468 --- /dev/null +++ b/benchmarks/FSharp.Stats.LegacyBenchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.LegacyBenchmarks.MatrixBenchmarks-report.html @@ -0,0 +1,41 @@ + + + + +FSharp.Stats.LegacyBenchmarks.MatrixBenchmarks-20250412-172149 + + + + +

+BenchmarkDotNet v0.14.0, Windows 11 (10.0.26100.3775)
+13th Gen Intel Core i7-13800H, 1 CPU, 20 logical and 14 physical cores
+.NET SDK 9.0.201
+  [Host]     : .NET 8.0.14 (8.0.1425.11118), X64 RyuJIT AVX2 DEBUG
+  DefaultJob : .NET 8.0.14 (8.0.1425.11118), X64 RyuJIT AVX2
+
+
+ + + + + + + + + + + + + + + + +
Method SizeMean Error StdDev Gen0Gen1Gen2Allocated
Add10169.55 ns2.046 ns1.914 ns0.0713--896 B
MatMultiply101,084.51 ns8.513 ns7.963 ns0.0706--896 B
MultiplyVector1073.57 ns0.786 ns0.736 ns0.0107--136 B
MultiplyRowVector1088.03 ns0.853 ns0.756 ns0.0235--296 B
Add500456,439.67 ns3,024.351 ns2,681.009 ns201.1719201.1719201.17192000166 B
MatMultiply500119,541,061.36 ns547,145.379 ns671,943.721 ns---2000196 B
MultiplyVector500156,250.79 ns1,292.534 ns1,145.798 ns0.2441--4056 B
MultiplyRowVector500183,556.08 ns1,804.318 ns1,687.760 ns0.4883--8136 B
Add10002,104,678.07 ns35,051.052 ns32,786.776 ns148.4375148.4375148.43758000146 B
MatMultiply10001,164,345,128.57 ns15,512,547.293 ns13,751,469.125 ns---8000496 B
MultiplyVector1000620,032.55 ns3,989.956 ns3,732.207 ns---8056 B
MultiplyRowVector1000880,712.25 ns8,715.623 ns8,152.599 ns0.9766--16136 B
+ + diff --git a/benchmarks/FSharp.Stats.LegacyBenchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.LegacyBenchmarks.VectorBenchmarks-report-github.md b/benchmarks/FSharp.Stats.LegacyBenchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.LegacyBenchmarks.VectorBenchmarks-report-github.md new file mode 100644 index 000000000..4805e1c21 --- /dev/null +++ b/benchmarks/FSharp.Stats.LegacyBenchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.LegacyBenchmarks.VectorBenchmarks-report-github.md @@ -0,0 +1,24 @@ +``` + +BenchmarkDotNet v0.14.0, Windows 11 (10.0.26100.3775) +13th Gen Intel Core i7-13800H, 1 CPU, 20 logical and 14 physical cores +.NET SDK 9.0.201 + [Host] : .NET 8.0.14 (8.0.1425.11118), X64 RyuJIT AVX2 DEBUG + DefaultJob : .NET 8.0.14 (8.0.1425.11118), X64 RyuJIT AVX2 + + +``` +| Method | Size | Mean | Error | StdDev | Gen0 | Gen1 | Allocated | +|----------- |------ |-------------:|-----------:|-----------:|-------:|-------:|----------:| +| **Add** | **100** | **73.21 ns** | **0.966 ns** | **0.903 ns** | **0.0682** | **0.0001** | **856 B** | +| Subtract | 100 | 72.11 ns | 0.991 ns | 0.927 ns | 0.0682 | 0.0001 | 856 B | +| DotProduct | 100 | 47.26 ns | 0.188 ns | 0.176 ns | - | - | - | +| Norm | 100 | 206.61 ns | 0.945 ns | 0.789 ns | - | - | - | +| **Add** | **1000** | **599.70 ns** | **6.201 ns** | **5.497 ns** | **0.6418** | **0.0191** | **8056 B** | +| Subtract | 1000 | 596.90 ns | 7.515 ns | 7.030 ns | 0.6418 | 0.0191 | 8056 B | +| DotProduct | 1000 | 407.63 ns | 1.324 ns | 1.239 ns | - | - | - | +| Norm | 1000 | 2,007.79 ns | 18.324 ns | 17.140 ns | - | - | - | +| **Add** | **10000** | **6,141.20 ns** | **118.523 ns** | **110.867 ns** | **6.3629** | **1.5869** | **80056 B** | +| Subtract | 10000 | 6,006.92 ns | 76.595 ns | 71.647 ns | 6.3629 | 1.5869 | 80056 B | +| DotProduct | 10000 | 3,980.27 ns | 28.423 ns | 26.587 ns | - | - | - | +| Norm | 10000 | 20,024.93 ns | 137.963 ns | 129.050 ns | - | - | - | diff --git a/benchmarks/FSharp.Stats.LegacyBenchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.LegacyBenchmarks.VectorBenchmarks-report.csv b/benchmarks/FSharp.Stats.LegacyBenchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.LegacyBenchmarks.VectorBenchmarks-report.csv new file mode 100644 index 000000000..b3dcc06f3 --- /dev/null +++ b/benchmarks/FSharp.Stats.LegacyBenchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.LegacyBenchmarks.VectorBenchmarks-report.csv @@ -0,0 +1,13 @@ +Method,Job,AnalyzeLaunchVariance,EvaluateOverhead,MaxAbsoluteError,MaxRelativeError,MinInvokeCount,MinIterationTime,OutlierMode,Affinity,EnvironmentVariables,Jit,LargeAddressAware,Platform,PowerPlanMode,Runtime,AllowVeryLargeObjects,Concurrent,CpuGroups,Force,HeapAffinitizeMask,HeapCount,NoAffinitize,RetainVm,Server,Arguments,BuildConfiguration,Clock,EngineFactory,NuGetReferences,Toolchain,IsMutator,InvocationCount,IterationCount,IterationTime,LaunchCount,MaxIterationCount,MaxWarmupIterationCount,MemoryRandomization,MinIterationCount,MinWarmupIterationCount,RunStrategy,UnrollFactor,WarmupCount,Size,Mean,Error,StdDev,Gen0,Gen1,Allocated +Add,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,100,73.21 ns,0.966 ns,0.903 ns,0.0682,0.0001,856 B +Subtract,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,100,72.11 ns,0.991 ns,0.927 ns,0.0682,0.0001,856 B +DotProduct,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,100,47.26 ns,0.188 ns,0.176 ns,0.0000,0.0000,0 B +Norm,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,100,206.61 ns,0.945 ns,0.789 ns,0.0000,0.0000,0 B +Add,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,1000,599.70 ns,6.201 ns,5.497 ns,0.6418,0.0191,8056 B +Subtract,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,1000,596.90 ns,7.515 ns,7.030 ns,0.6418,0.0191,8056 B +DotProduct,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,1000,407.63 ns,1.324 ns,1.239 ns,0.0000,0.0000,0 B +Norm,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,1000,"2,007.79 ns",18.324 ns,17.140 ns,0.0000,0.0000,0 B +Add,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,10000,"6,141.20 ns",118.523 ns,110.867 ns,6.3629,1.5869,80056 B +Subtract,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,10000,"6,006.92 ns",76.595 ns,71.647 ns,6.3629,1.5869,80056 B +DotProduct,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,10000,"3,980.27 ns",28.423 ns,26.587 ns,0.0000,0.0000,0 B +Norm,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,10000,"20,024.93 ns",137.963 ns,129.050 ns,0.0000,0.0000,0 B diff --git a/benchmarks/FSharp.Stats.LegacyBenchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.LegacyBenchmarks.VectorBenchmarks-report.html b/benchmarks/FSharp.Stats.LegacyBenchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.LegacyBenchmarks.VectorBenchmarks-report.html new file mode 100644 index 000000000..72a750e35 --- /dev/null +++ b/benchmarks/FSharp.Stats.LegacyBenchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.LegacyBenchmarks.VectorBenchmarks-report.html @@ -0,0 +1,41 @@ + + + + +FSharp.Stats.LegacyBenchmarks.VectorBenchmarks-20250412-165006 + + + + +

+BenchmarkDotNet v0.14.0, Windows 11 (10.0.26100.3775)
+13th Gen Intel Core i7-13800H, 1 CPU, 20 logical and 14 physical cores
+.NET SDK 9.0.201
+  [Host]     : .NET 8.0.14 (8.0.1425.11118), X64 RyuJIT AVX2 DEBUG
+  DefaultJob : .NET 8.0.14 (8.0.1425.11118), X64 RyuJIT AVX2
+
+
+ + + + + + + + + + + + + + + + +
MethodSizeMean ErrorStdDevGen0Gen1Allocated
Add10073.21 ns0.966 ns0.903 ns0.06820.0001856 B
Subtract10072.11 ns0.991 ns0.927 ns0.06820.0001856 B
DotProduct10047.26 ns0.188 ns0.176 ns---
Norm100206.61 ns0.945 ns0.789 ns---
Add1000599.70 ns6.201 ns5.497 ns0.64180.01918056 B
Subtract1000596.90 ns7.515 ns7.030 ns0.64180.01918056 B
DotProduct1000407.63 ns1.324 ns1.239 ns---
Norm10002,007.79 ns18.324 ns17.140 ns---
Add100006,141.20 ns118.523 ns110.867 ns6.36291.586980056 B
Subtract100006,006.92 ns76.595 ns71.647 ns6.36291.586980056 B
DotProduct100003,980.27 ns28.423 ns26.587 ns---
Norm1000020,024.93 ns137.963 ns129.050 ns---
+ + diff --git a/benchmarks/FSharp.Stats.LegacyBenchmarks/FSharp.Stats.LegacyBenchmarks.fsproj b/benchmarks/FSharp.Stats.LegacyBenchmarks/FSharp.Stats.LegacyBenchmarks.fsproj new file mode 100644 index 000000000..98bde68c0 --- /dev/null +++ b/benchmarks/FSharp.Stats.LegacyBenchmarks/FSharp.Stats.LegacyBenchmarks.fsproj @@ -0,0 +1,19 @@ + + + + Exe + net8.0 + + + + + + + + + + + + + + diff --git a/benchmarks/FSharp.Stats.LegacyBenchmarks/Matrix.fs b/benchmarks/FSharp.Stats.LegacyBenchmarks/Matrix.fs new file mode 100644 index 000000000..8a566b79d --- /dev/null +++ b/benchmarks/FSharp.Stats.LegacyBenchmarks/Matrix.fs @@ -0,0 +1,44 @@ +namespace FSharp.Stats.LegacyBenchmarks + +open System +open BenchmarkDotNet.Attributes +open BenchmarkDotNet.Running +open FSharp.Stats + +[] +type MatrixBenchmarks() = + + let mutable matrixA = Unchecked.defaultof> + let mutable matrixB = Unchecked.defaultof> + let mutable vector = vector [||] + + // Parameterize matrix sizes + [] + member val Size = 0 with get, set + + [] + member this.Setup() = + // Initialize matrices and vector + matrixA <- Matrix.init this.Size this.Size (fun i j -> float (i + j)) + matrixB <- Matrix.init this.Size this.Size (fun i j -> float (i * j)) + vector <- Vector.init this.Size (fun i -> float i) + + [] + member _.Add() = + let result = Matrix.add matrixA matrixB + GC.KeepAlive(result) // Prevent dead code elimination + + [] + member _.MatMultiply() = + let result = Matrix.mul matrixA matrixB + GC.KeepAlive(result) // Prevent dead code elimination + + [] + member _.MultiplyVector() = + let result = Matrix.mulV matrixA vector + GC.KeepAlive(result) // Prevent dead code elimination + + [] + member _.MultiplyRowVector() = + let result = Matrix.mulRV vector.Transpose matrixA + GC.KeepAlive(result) // Prevent dead code elimination diff --git a/benchmarks/FSharp.Stats.LegacyBenchmarks/Program.fs b/benchmarks/FSharp.Stats.LegacyBenchmarks/Program.fs new file mode 100644 index 000000000..5a6658fd3 --- /dev/null +++ b/benchmarks/FSharp.Stats.LegacyBenchmarks/Program.fs @@ -0,0 +1,15 @@ + +open System +open BenchmarkDotNet.Attributes +open BenchmarkDotNet.Running +open FSharp.Stats.LegacyBenchmarks + +[] +let Main args = + // Register multiple benchmark classes + let switcher = BenchmarkSwitcher [| + typeof + typeof + |] + switcher.Run args |> ignore + 0 diff --git a/benchmarks/FSharp.Stats.LegacyBenchmarks/Vector.fs b/benchmarks/FSharp.Stats.LegacyBenchmarks/Vector.fs new file mode 100644 index 000000000..ebc866093 --- /dev/null +++ b/benchmarks/FSharp.Stats.LegacyBenchmarks/Vector.fs @@ -0,0 +1,48 @@ +namespace FSharp.Stats.LegacyBenchmarks + + +open System +open BenchmarkDotNet.Attributes +open BenchmarkDotNet.Running +open FSharp.Stats + +[] +type VectorBenchmarks() = + + let mutable vector1 = vector [||] + let mutable vector2 = vector [||] + + // Parameterize vector sizes + [] + member val Size = 0 with get, set + + [] + member this.Setup() = + vector1 <- Vector.init this.Size (fun i -> float i) + vector2 <- Vector.init this.Size (fun i -> float (i * 2)) + + [] + member _.Add() = + let result = Vector.add vector1 vector2 + GC.KeepAlive(result) // Prevents the result from being optimized away + + [] + member _.multiply() = + let result = Vector.cptMul vector1 vector2 + GC.KeepAlive(result) // Prevents the result from being optimized away + + [] + member _.DotProduct() = + let result = Vector.dot vector1 vector2 + GC.KeepAlive(result) // Prevents the result from being optimized away + + [] + member _.CrossProduct() = + let result = Vector.mulRVV vector1.Transpose vector2 + GC.KeepAlive(result) // Prevents the result from being optimized away + + [] + member _.Norm() = + let result = Vector.norm vector1 + GC.KeepAlive(result) // Prevents the result from being optimized away + diff --git a/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj b/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj index 89b2aaea0..88f81e4bd 100644 --- a/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj +++ b/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj @@ -6,20 +6,21 @@ + + - - + From c7edc67bd24e48275fb6f9c496d69198aaa7bdd3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20M=C3=BChlhaus?= Date: Sat, 12 Apr 2025 18:58:53 +0200 Subject: [PATCH 076/121] Improved Vector^T * Matrix with new benchmark --- ...nchmarks.MatrixBenchmarks-report-github.md | 28 ++++++------ ...ats.Benchmarks.MatrixBenchmarks-report.csv | 24 +++++----- ...ts.Benchmarks.MatrixBenchmarks-report.html | 26 +++++------ src/FSharp.Stats/AlgTypes/Matrix.fs | 44 ++++--------------- 4 files changed, 48 insertions(+), 74 deletions(-) diff --git a/benchmarks/FSharp.Stats.Benchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.Benchmarks.MatrixBenchmarks-report-github.md b/benchmarks/FSharp.Stats.Benchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.Benchmarks.MatrixBenchmarks-report-github.md index 8d9d79de7..6760521d6 100644 --- a/benchmarks/FSharp.Stats.Benchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.Benchmarks.MatrixBenchmarks-report-github.md +++ b/benchmarks/FSharp.Stats.Benchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.Benchmarks.MatrixBenchmarks-report-github.md @@ -8,17 +8,17 @@ BenchmarkDotNet v0.14.0, Windows 11 (10.0.26100.3775) ``` -| Method | Size | Mean | Error | StdDev | Gen0 | Gen1 | Gen2 | Allocated | -|------------------ |----- |------------------:|-----------------:|-----------------:|----------:|---------:|---------:|-----------:| -| **Add** | **10** | **38.33 ns** | **0.686 ns** | **0.642 ns** | **0.0682** | **0.0002** | **-** | **856 B** | -| MatMultiply | 10 | 436.79 ns | 2.776 ns | 2.461 ns | 0.1364 | - | - | 1712 B | -| MultiplyVector | 10 | 32.20 ns | 0.439 ns | 0.411 ns | 0.0083 | - | - | 104 B | -| MultiplyRowVector | 10 | 228.95 ns | 1.473 ns | 1.378 ns | 0.0975 | - | - | 1224 B | -| **Add** | **500** | **282,714.76 ns** | **5,416.776 ns** | **5,066.855 ns** | **206.5430** | **206.5430** | **206.5430** | **2000168 B** | -| MatMultiply | 500 | 17,514,488.54 ns | 216,980.386 ns | 202,963.588 ns | 375.0000 | 375.0000 | 375.0000 | 4000242 B | -| MultiplyVector | 500 | 33,458.92 ns | 334.582 ns | 312.968 ns | 0.3052 | - | - | 4024 B | -| MultiplyRowVector | 500 | 613,450.40 ns | 7,962.085 ns | 7,447.740 ns | 278.3203 | 3.9063 | - | 3504024 B | -| **Add** | **1000** | **1,360,217.58 ns** | **24,506.528 ns** | **21,724.399 ns** | **398.4375** | **398.4375** | **398.4375** | **8000206 B** | -| MatMultiply | 1000 | 143,946,340.15 ns | 2,872,749.805 ns | 4,556,485.985 ns | 250.0000 | 250.0000 | 250.0000 | 16000296 B | -| MultiplyVector | 1000 | 137,378.76 ns | 942.798 ns | 881.894 ns | 0.4883 | - | - | 8024 B | -| MultiplyRowVector | 1000 | 2,999,358.20 ns | 48,713.356 ns | 45,566.504 ns | 1113.2813 | 27.3438 | - | 14008026 B | +| Method | Size | Mean | Error | StdDev | Gen0 | Gen1 | Gen2 | Allocated | +|------------------ |----- |------------------:|-----------------:|-----------------:|---------:|---------:|---------:|-----------:| +| **Add** | **10** | **40.06 ns** | **0.550 ns** | **0.488 ns** | **0.0682** | **0.0002** | **-** | **856 B** | +| MatMultiply | 10 | 442.83 ns | 2.841 ns | 2.373 ns | 0.1364 | - | - | 1712 B | +| MultiplyVector | 10 | 33.28 ns | 0.425 ns | 0.397 ns | 0.0083 | - | - | 104 B | +| MultiplyRowVector | 10 | 50.55 ns | 0.500 ns | 0.468 ns | 0.0083 | - | - | 104 B | +| **Add** | **500** | **280,736.93 ns** | **5,376.045 ns** | **5,279.995 ns** | **212.4023** | **212.4023** | **212.4023** | **2000164 B** | +| MatMultiply | 500 | 17,572,322.92 ns | 318,470.458 ns | 297,897.464 ns | 375.0000 | 375.0000 | 375.0000 | 4000242 B | +| MultiplyVector | 500 | 31,726.43 ns | 202.403 ns | 189.328 ns | 0.3052 | - | - | 4024 B | +| MultiplyRowVector | 500 | 127,918.10 ns | 996.783 ns | 832.359 ns | 0.2441 | - | - | 4024 B | +| **Add** | **1000** | **1,377,902.79 ns** | **20,816.673 ns** | **18,453.438 ns** | **148.4375** | **148.4375** | **148.4375** | **8000105 B** | +| MatMultiply | 1000 | 143,300,325.00 ns | 1,445,291.857 ns | 1,606,438.070 ns | 250.0000 | 250.0000 | 250.0000 | 16000296 B | +| MultiplyVector | 1000 | 135,247.34 ns | 1,334.685 ns | 1,248.465 ns | 0.4883 | - | - | 8024 B | +| MultiplyRowVector | 1000 | 677,195.35 ns | 6,896.007 ns | 6,450.529 ns | - | - | - | 8024 B | diff --git a/benchmarks/FSharp.Stats.Benchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.Benchmarks.MatrixBenchmarks-report.csv b/benchmarks/FSharp.Stats.Benchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.Benchmarks.MatrixBenchmarks-report.csv index 7d087c45d..27e1571ed 100644 --- a/benchmarks/FSharp.Stats.Benchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.Benchmarks.MatrixBenchmarks-report.csv +++ b/benchmarks/FSharp.Stats.Benchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.Benchmarks.MatrixBenchmarks-report.csv @@ -1,13 +1,13 @@ Method,Job,AnalyzeLaunchVariance,EvaluateOverhead,MaxAbsoluteError,MaxRelativeError,MinInvokeCount,MinIterationTime,OutlierMode,Affinity,EnvironmentVariables,Jit,LargeAddressAware,Platform,PowerPlanMode,Runtime,AllowVeryLargeObjects,Concurrent,CpuGroups,Force,HeapAffinitizeMask,HeapCount,NoAffinitize,RetainVm,Server,Arguments,BuildConfiguration,Clock,EngineFactory,NuGetReferences,Toolchain,IsMutator,InvocationCount,IterationCount,IterationTime,LaunchCount,MaxIterationCount,MaxWarmupIterationCount,MemoryRandomization,MinIterationCount,MinWarmupIterationCount,RunStrategy,UnrollFactor,WarmupCount,Size,Mean,Error,StdDev,Gen0,Gen1,Gen2,Allocated -Add,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,10,38.33 ns,0.686 ns,0.642 ns,0.0682,0.0002,0.0000,856 B -MatMultiply,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,10,436.79 ns,2.776 ns,2.461 ns,0.1364,0.0000,0.0000,1712 B -MultiplyVector,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,10,32.20 ns,0.439 ns,0.411 ns,0.0083,0.0000,0.0000,104 B -MultiplyRowVector,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,10,228.95 ns,1.473 ns,1.378 ns,0.0975,0.0000,0.0000,1224 B -Add,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,500,"282,714.76 ns","5,416.776 ns","5,066.855 ns",206.5430,206.5430,206.5430,2000168 B -MatMultiply,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,500,"17,514,488.54 ns","216,980.386 ns","202,963.588 ns",375.0000,375.0000,375.0000,4000242 B -MultiplyVector,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,500,"33,458.92 ns",334.582 ns,312.968 ns,0.3052,0.0000,0.0000,4024 B -MultiplyRowVector,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,500,"613,450.40 ns","7,962.085 ns","7,447.740 ns",278.3203,3.9063,0.0000,3504024 B -Add,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,1000,"1,360,217.58 ns","24,506.528 ns","21,724.399 ns",398.4375,398.4375,398.4375,8000206 B -MatMultiply,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,1000,"143,946,340.15 ns","2,872,749.805 ns","4,556,485.985 ns",250.0000,250.0000,250.0000,16000296 B -MultiplyVector,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,1000,"137,378.76 ns",942.798 ns,881.894 ns,0.4883,0.0000,0.0000,8024 B -MultiplyRowVector,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,1000,"2,999,358.20 ns","48,713.356 ns","45,566.504 ns",1113.2813,27.3438,0.0000,14008026 B +Add,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,10,40.06 ns,0.550 ns,0.488 ns,0.0682,0.0002,0.0000,856 B +MatMultiply,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,10,442.83 ns,2.841 ns,2.373 ns,0.1364,0.0000,0.0000,1712 B +MultiplyVector,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,10,33.28 ns,0.425 ns,0.397 ns,0.0083,0.0000,0.0000,104 B +MultiplyRowVector,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,10,50.55 ns,0.500 ns,0.468 ns,0.0083,0.0000,0.0000,104 B +Add,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,500,"280,736.93 ns","5,376.045 ns","5,279.995 ns",212.4023,212.4023,212.4023,2000164 B +MatMultiply,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,500,"17,572,322.92 ns","318,470.458 ns","297,897.464 ns",375.0000,375.0000,375.0000,4000242 B +MultiplyVector,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,500,"31,726.43 ns",202.403 ns,189.328 ns,0.3052,0.0000,0.0000,4024 B +MultiplyRowVector,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,500,"127,918.10 ns",996.783 ns,832.359 ns,0.2441,0.0000,0.0000,4024 B +Add,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,1000,"1,377,902.79 ns","20,816.673 ns","18,453.438 ns",148.4375,148.4375,148.4375,8000105 B +MatMultiply,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,1000,"143,300,325.00 ns","1,445,291.857 ns","1,606,438.070 ns",250.0000,250.0000,250.0000,16000296 B +MultiplyVector,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,1000,"135,247.34 ns","1,334.685 ns","1,248.465 ns",0.4883,0.0000,0.0000,8024 B +MultiplyRowVector,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,1000,"677,195.35 ns","6,896.007 ns","6,450.529 ns",0.0000,0.0000,0.0000,8024 B diff --git a/benchmarks/FSharp.Stats.Benchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.Benchmarks.MatrixBenchmarks-report.html b/benchmarks/FSharp.Stats.Benchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.Benchmarks.MatrixBenchmarks-report.html index cc4406755..bcfdb6957 100644 --- a/benchmarks/FSharp.Stats.Benchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.Benchmarks.MatrixBenchmarks-report.html +++ b/benchmarks/FSharp.Stats.Benchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.Benchmarks.MatrixBenchmarks-report.html @@ -2,7 +2,7 @@ -FSharp.Stats.Benchmarks.MatrixBenchmarks-20250412-173020 +FSharp.Stats.Benchmarks.MatrixBenchmarks-20250412-175902 + + +

+BenchmarkDotNet v0.14.0, Windows 11 (10.0.26100.3775)
+13th Gen Intel Core i7-13800H, 1 CPU, 20 logical and 14 physical cores
+.NET SDK 9.0.201
+  [Host]     : .NET 8.0.14 (8.0.1425.11118), X64 RyuJIT AVX2 DEBUG
+  DefaultJob : .NET 8.0.14 (8.0.1425.11118), X64 RyuJIT AVX2
+
+
+ + + + + + + + + + + + +
Method NMean Error StdDevGen0Allocated
SolveTriangularSystemLower10186.3 ns1.23 ns1.09 ns0.0172216 B
SolveTriangularSystemUpper10185.9 ns1.33 ns1.18 ns0.0172216 B
SolveTriangularSystemLower500372,737.0 ns2,926.50 ns2,737.45 ns0.48838056 B
SolveTriangularSystemUpper500357,818.8 ns1,729.90 ns1,618.15 ns0.48838056 B
SolveTriangularSystemLower10001,510,031.5 ns7,131.73 ns6,671.03 ns-16057 B
SolveTriangularSystemUpper10001,422,197.8 ns8,642.37 ns8,084.08 ns-16057 B
SolveTriangularSystemLower20006,119,478.8 ns40,341.69 ns37,735.64 ns-32059 B
SolveTriangularSystemUpper20005,776,260.6 ns30,122.54 ns28,176.64 ns-32059 B
+ + diff --git a/benchmarks/FSharp.Stats.Benchmarks/FSharp.Stats.Benchmarks.fsproj b/benchmarks/FSharp.Stats.Benchmarks/FSharp.Stats.Benchmarks.fsproj index 647da67b2..28d22c175 100644 --- a/benchmarks/FSharp.Stats.Benchmarks/FSharp.Stats.Benchmarks.fsproj +++ b/benchmarks/FSharp.Stats.Benchmarks/FSharp.Stats.Benchmarks.fsproj @@ -8,6 +8,7 @@ + diff --git a/benchmarks/FSharp.Stats.Benchmarks/Program.fs b/benchmarks/FSharp.Stats.Benchmarks/Program.fs index d15db5097..ee69be2d0 100644 --- a/benchmarks/FSharp.Stats.Benchmarks/Program.fs +++ b/benchmarks/FSharp.Stats.Benchmarks/Program.fs @@ -8,6 +8,7 @@ let Main args = let switcher = BenchmarkSwitcher [| typeof typeof + typeof |] switcher.Run args |> ignore 0 diff --git a/benchmarks/FSharp.Stats.Benchmarks/TriangularSolver.fs b/benchmarks/FSharp.Stats.Benchmarks/TriangularSolver.fs new file mode 100644 index 000000000..6513e7d97 --- /dev/null +++ b/benchmarks/FSharp.Stats.Benchmarks/TriangularSolver.fs @@ -0,0 +1,48 @@ +namespace FSharp.Stats.Benchmarks + +open System +open BenchmarkDotNet.Attributes +open BenchmarkDotNet.Running +open FSharp.Stats +open FSharp.Stats.Algebra + +[] +type TriangularBenchmark() = + + + // We'll hold the test data here + let mutable K : Matrix = Unchecked.defaultof> + let mutable B : Matrix = Unchecked.defaultof> + + /// + /// We'll vary 'N' in [500, 1000, 2000] for the matrix dimension. + /// BenchmarkDotNet will run separate benchmarks for each N. + /// + [] + member val N = 0 with get, set + + [] + member this.Setup() = + // Use the parameter N to build NxN matrix K and NxM matrix B + let n = this.N + let m = 2 // or some other number of columns for B + let rnd = Random(1234) + + // Build K + let dataK = Array.init (n*n) (fun _ -> float(rnd.Next(1,10))) + K <- Matrix(n, n, dataK) + + // Build B + let dataB = Array.init (n*m) (fun _ -> float(rnd.Next(1,5))) + B <- Matrix(n, m, dataB) + + + [] + member this.SolveTriangularSystemLower() = + // The method we want to benchmark + LinearAlgebra.solveTriangularLinearSystems K B true + + [] + member this.SolveTriangularSystemUpper() = + // The method we want to benchmark + LinearAlgebra.solveTriangularLinearSystems K B false \ No newline at end of file diff --git a/benchmarks/FSharp.Stats.LegacyBenchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.LegacyBenchmarks.TriangularBenchmark-report-github.md b/benchmarks/FSharp.Stats.LegacyBenchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.LegacyBenchmarks.TriangularBenchmark-report-github.md new file mode 100644 index 000000000..ed728cb36 --- /dev/null +++ b/benchmarks/FSharp.Stats.LegacyBenchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.LegacyBenchmarks.TriangularBenchmark-report-github.md @@ -0,0 +1,20 @@ +``` + +BenchmarkDotNet v0.14.0, Windows 11 (10.0.26100.3775) +13th Gen Intel Core i7-13800H, 1 CPU, 20 logical and 14 physical cores +.NET SDK 9.0.201 + [Host] : .NET 8.0.14 (8.0.1425.11118), X64 RyuJIT AVX2 DEBUG + DefaultJob : .NET 8.0.14 (8.0.1425.11118), X64 RyuJIT AVX2 + + +``` +| Method | N | Mean | Error | StdDev | Gen0 | Gen1 | Gen2 | Allocated | +|--------------------------- |----- |----------------:|-------------:|--------------:|---------:|---------:|---------:|------------:| +| **SolveTriangularSystemLower** | **10** | **731.0 ns** | **5.15 ns** | **4.82 ns** | **0.1097** | **-** | **-** | **1.34 KB** | +| SolveTriangularSystemUpper | 10 | 665.6 ns | 5.93 ns | 5.54 ns | 0.1097 | - | - | 1.34 KB | +| **SolveTriangularSystemLower** | **500** | **1,474,179.5 ns** | **29,026.42 ns** | **32,262.78 ns** | **332.0313** | **330.0781** | **330.0781** | **1977.87 KB** | +| SolveTriangularSystemUpper | 500 | 1,508,533.3 ns | 25,877.28 ns | 24,205.62 ns | 333.9844 | 332.0313 | 332.0313 | 1977.72 KB | +| **SolveTriangularSystemLower** | **1000** | **6,405,608.8 ns** | **83,698.88 ns** | **78,291.99 ns** | **390.6250** | **390.6250** | **390.6250** | **7860.04 KB** | +| SolveTriangularSystemUpper | 1000 | 6,555,258.3 ns | 81,557.32 ns | 76,288.76 ns | 390.6250 | 390.6250 | 390.6250 | 7859.79 KB | +| **SolveTriangularSystemLower** | **2000** | **26,497,907.6 ns** | **81,721.04 ns** | **189,400.94 ns** | **875.0000** | **875.0000** | **875.0000** | **31344.14 KB** | +| SolveTriangularSystemUpper | 2000 | 27,361,796.9 ns | 98,627.77 ns | 196,970.33 ns | 875.0000 | 875.0000 | 875.0000 | 31344.14 KB | diff --git a/benchmarks/FSharp.Stats.LegacyBenchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.LegacyBenchmarks.TriangularBenchmark-report.csv b/benchmarks/FSharp.Stats.LegacyBenchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.LegacyBenchmarks.TriangularBenchmark-report.csv new file mode 100644 index 000000000..56d252a8c --- /dev/null +++ b/benchmarks/FSharp.Stats.LegacyBenchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.LegacyBenchmarks.TriangularBenchmark-report.csv @@ -0,0 +1,9 @@ +Method,Job,AnalyzeLaunchVariance,EvaluateOverhead,MaxAbsoluteError,MaxRelativeError,MinInvokeCount,MinIterationTime,OutlierMode,Affinity,EnvironmentVariables,Jit,LargeAddressAware,Platform,PowerPlanMode,Runtime,AllowVeryLargeObjects,Concurrent,CpuGroups,Force,HeapAffinitizeMask,HeapCount,NoAffinitize,RetainVm,Server,Arguments,BuildConfiguration,Clock,EngineFactory,NuGetReferences,Toolchain,IsMutator,InvocationCount,IterationCount,IterationTime,LaunchCount,MaxIterationCount,MaxWarmupIterationCount,MemoryRandomization,MinIterationCount,MinWarmupIterationCount,RunStrategy,UnrollFactor,WarmupCount,N,Mean,Error,StdDev,Gen0,Gen1,Gen2,Allocated +SolveTriangularSystemLower,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,10,731.0 ns,5.15 ns,4.82 ns,0.1097,0.0000,0.0000,1.34 KB +SolveTriangularSystemUpper,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,10,665.6 ns,5.93 ns,5.54 ns,0.1097,0.0000,0.0000,1.34 KB +SolveTriangularSystemLower,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,500,"1,474,179.5 ns","29,026.42 ns","32,262.78 ns",332.0313,330.0781,330.0781,1977.87 KB +SolveTriangularSystemUpper,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,500,"1,508,533.3 ns","25,877.28 ns","24,205.62 ns",333.9844,332.0313,332.0313,1977.72 KB +SolveTriangularSystemLower,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,1000,"6,405,608.8 ns","83,698.88 ns","78,291.99 ns",390.6250,390.6250,390.6250,7860.04 KB +SolveTriangularSystemUpper,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,1000,"6,555,258.3 ns","81,557.32 ns","76,288.76 ns",390.6250,390.6250,390.6250,7859.79 KB +SolveTriangularSystemLower,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,2000,"26,497,907.6 ns","81,721.04 ns","189,400.94 ns",875.0000,875.0000,875.0000,31344.14 KB +SolveTriangularSystemUpper,DefaultJob,False,Default,Default,Default,Default,Default,Default,11111111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,2000,"27,361,796.9 ns","98,627.77 ns","196,970.33 ns",875.0000,875.0000,875.0000,31344.14 KB diff --git a/benchmarks/FSharp.Stats.LegacyBenchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.LegacyBenchmarks.TriangularBenchmark-report.html b/benchmarks/FSharp.Stats.LegacyBenchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.LegacyBenchmarks.TriangularBenchmark-report.html new file mode 100644 index 000000000..faab41b07 --- /dev/null +++ b/benchmarks/FSharp.Stats.LegacyBenchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.LegacyBenchmarks.TriangularBenchmark-report.html @@ -0,0 +1,37 @@ + + + + +FSharp.Stats.LegacyBenchmarks.TriangularBenchmark-20250412-194859 + + + + +

+BenchmarkDotNet v0.14.0, Windows 11 (10.0.26100.3775)
+13th Gen Intel Core i7-13800H, 1 CPU, 20 logical and 14 physical cores
+.NET SDK 9.0.201
+  [Host]     : .NET 8.0.14 (8.0.1425.11118), X64 RyuJIT AVX2 DEBUG
+  DefaultJob : .NET 8.0.14 (8.0.1425.11118), X64 RyuJIT AVX2
+
+
+ + + + + + + + + + + + +
Method NMean Error StdDev Gen0Gen1Gen2Allocated
SolveTriangularSystemLower10731.0 ns5.15 ns4.82 ns0.1097--1.34 KB
SolveTriangularSystemUpper10665.6 ns5.93 ns5.54 ns0.1097--1.34 KB
SolveTriangularSystemLower5001,474,179.5 ns29,026.42 ns32,262.78 ns332.0313330.0781330.07811977.87 KB
SolveTriangularSystemUpper5001,508,533.3 ns25,877.28 ns24,205.62 ns333.9844332.0313332.03131977.72 KB
SolveTriangularSystemLower10006,405,608.8 ns83,698.88 ns78,291.99 ns390.6250390.6250390.62507860.04 KB
SolveTriangularSystemUpper10006,555,258.3 ns81,557.32 ns76,288.76 ns390.6250390.6250390.62507859.79 KB
SolveTriangularSystemLower200026,497,907.6 ns81,721.04 ns189,400.94 ns875.0000875.0000875.000031344.14 KB
SolveTriangularSystemUpper200027,361,796.9 ns98,627.77 ns196,970.33 ns875.0000875.0000875.000031344.14 KB
+ + diff --git a/benchmarks/FSharp.Stats.LegacyBenchmarks/FSharp.Stats.LegacyBenchmarks.fsproj b/benchmarks/FSharp.Stats.LegacyBenchmarks/FSharp.Stats.LegacyBenchmarks.fsproj index 98bde68c0..78b884d9d 100644 --- a/benchmarks/FSharp.Stats.LegacyBenchmarks/FSharp.Stats.LegacyBenchmarks.fsproj +++ b/benchmarks/FSharp.Stats.LegacyBenchmarks/FSharp.Stats.LegacyBenchmarks.fsproj @@ -6,8 +6,9 @@ - + + diff --git a/benchmarks/FSharp.Stats.LegacyBenchmarks/Program.fs b/benchmarks/FSharp.Stats.LegacyBenchmarks/Program.fs index 5a6658fd3..829e670f5 100644 --- a/benchmarks/FSharp.Stats.LegacyBenchmarks/Program.fs +++ b/benchmarks/FSharp.Stats.LegacyBenchmarks/Program.fs @@ -10,6 +10,7 @@ let Main args = let switcher = BenchmarkSwitcher [| typeof typeof + typeof |] switcher.Run args |> ignore 0 diff --git a/benchmarks/FSharp.Stats.LegacyBenchmarks/TriangularSolver.fs b/benchmarks/FSharp.Stats.LegacyBenchmarks/TriangularSolver.fs new file mode 100644 index 000000000..2a85e3f12 --- /dev/null +++ b/benchmarks/FSharp.Stats.LegacyBenchmarks/TriangularSolver.fs @@ -0,0 +1,46 @@ +namespace FSharp.Stats.LegacyBenchmarks + +open System +open BenchmarkDotNet.Attributes +open BenchmarkDotNet.Running +open FSharp.Stats +open FSharp.Stats.Algebra + +[] +type TriangularBenchmark() = + + + // We'll hold the test data here + let mutable K : Matrix = Unchecked.defaultof> + let mutable B : Matrix = Unchecked.defaultof> + + /// + /// We'll vary 'N' in [500, 1000, 2000] for the matrix dimension. + /// BenchmarkDotNet will run separate benchmarks for each N. + /// + [] + member val N = 0 with get, set + + [] + member this.Setup() = + // Use the parameter N to build NxN matrix K and NxM matrix B + let n = this.N + let m = 2 // or some other number of columns for B + let rnd = Random(1234) + + // Build K + K <- Matrix.init n n (fun _ _ -> float(rnd.Next(1,10))) + + // Build B + B <- Matrix.init n m (fun _ _ -> float(rnd.Next(1,5))) + + + [] + member this.SolveTriangularSystemLower() = + // The method we want to benchmark + LinearAlgebra.SolveTriangularLinearSystems K B true + + [] + member this.SolveTriangularSystemUpper() = + // The method we want to benchmark + LinearAlgebra.SolveTriangularLinearSystems K B false \ No newline at end of file From 0d87ed67691a8ac136e877d05e58a03c30e014ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20M=C3=BChlhaus?= Date: Sat, 12 Apr 2025 21:59:39 +0200 Subject: [PATCH 078/121] Add LinearAlgebra unit test cases --- src/FSharp.Stats/Algebra/LinearAlgebra.fs | 60 ++++++++---- src/FSharp.Stats/Playground.fsx | 57 ++++------- tests/FSharp.Stats.Tests/LinearAlgebra.fs | 111 +++++++++++----------- 3 files changed, 113 insertions(+), 115 deletions(-) diff --git a/src/FSharp.Stats/Algebra/LinearAlgebra.fs b/src/FSharp.Stats/Algebra/LinearAlgebra.fs index b5f0eac95..5a6e8b7a5 100644 --- a/src/FSharp.Stats/Algebra/LinearAlgebra.fs +++ b/src/FSharp.Stats/Algebra/LinearAlgebra.fs @@ -179,17 +179,17 @@ type LinearAlgebra = // Subtract scaled rows for j in [0..i-1] for j = 0 to i - 1 do let kij = Kdata.[i * n + j] // K[i,j] - if kij <> 'T.Zero then - let baseJ = j * m - // subScaledRowInPlace scaleVal dstOffset srcOffset count dst src - LinearAlgebra.subScaledRowInPlace - kij - baseI // row i offset in X - baseJ // row j offset in X - m // number of columns - Xdata - Xdata - //LinearAlgebra.subScaledRowInPlace + //if kij <> 'T.Zero then // normaly speed things up, but -inf * 0 = nan + let baseJ = j * m + // subScaledRowInPlace scaleVal dstOffset srcOffset count dst src + LinearAlgebra.subScaledRowInPlace + kij + baseI // row i offset in X + baseJ // row j offset in X + m // number of columns + Xdata + Xdata + //LinearAlgebra.subScaledRowInPlace // Xdata // baseI // row i offset in X // Xdata @@ -217,15 +217,15 @@ type LinearAlgebra = let baseI = i * m for j = i + 1 to n - 1 do let kij = Kdata.[i * n + j] // K[i,j] - if kij <> 'T.Zero then - let baseJ = j * m - LinearAlgebra.subScaledRowInPlace - kij - baseI - baseJ - m - Xdata - Xdata + //if kij <> 'T.Zero then // normaly speed things up, but -inf * 0 = nan + let baseJ = j * m + LinearAlgebra.subScaledRowInPlace + kij + baseI + baseJ + m + Xdata + Xdata let diag = Kdata.[i * n + i] let invDiag = 'T.One / diag scaleRowInPlace @@ -670,3 +670,23 @@ type LinearAlgebra = static member inline symmetricEigenspectrum (a:Matrix) = let (e,v,d) = EVD.symmetricEvd (a.toArray2D()) (Matrix.ofArray2D v, d) + + ///// Synonym: kernel / right null space. Returns an orthonormal basis for the null space of matrix A (Ax = 0).
The accuracy defines a threshold whether a singular value is considered as zero (default: 1e-08). + //static member nullspace(?Accuracy :float ) = + + // let accuracy = defaultArg Accuracy 1e-08 + + // fun (a: Matrix) -> + + // // Either MKL or fallback implementation of the full SVD + // let (sigma,U,Vt) = LinearAlgebra.SVD a + + // // The rank is the number of nonzero singular values + // let rank = + // sigma + // |> Seq.sumBy (fun x -> if x >= accuracy then 1 else 0) + + // let count = Vt.NumRows - rank + + // Matrix.getRows Vt rank count + // |> Matrix.transpose \ No newline at end of file diff --git a/src/FSharp.Stats/Playground.fsx b/src/FSharp.Stats/Playground.fsx index ed66d5edb..ac76cc2c3 100644 --- a/src/FSharp.Stats/Playground.fsx +++ b/src/FSharp.Stats/Playground.fsx @@ -6,46 +6,7 @@ open System open FSharp.Stats open FSharp.Stats.Distributions //open Plotly.NET - - - -let data = [|1.0; 2.0; 3.0; 4.0; 5.0|] - -SummaryStats.ofSeq data -SummaryStats.ofArray data - -let statsC = SummaryStats.ofSeq data -let calcMean = Seq.mean data -let calcSumOfSquares = Seq.sumBy (fun x -> x * x) data -let calcMin = Seq.min data -let calcMax = Seq.max data -let calcN = Seq.length data - - -open FSharp.Stats.Testing - -let groupA = [|-5.;-3.;-3.;-4.;-5.;|] -let groupB = [|-2.;-4.;-4.;-6.;-6.;-6.;-5.;|] - -let statsA = Seq.stats groupA -let statsB = Seq.stats groupB - - -let meanA = Seq.mean groupA -let meanB = Seq.mean groupB -let varA = Seq.var groupA -let varB = Seq.var groupB -let nA = float (Seq.length groupA) -let nB = float (Seq.length groupB) - -// calculation of the H test -let tTest1 = TTest.twoSample true groupA groupB -let tTest2 = TTest.twoSampleFromMeanAndVar true (meanA,varA,nA) (meanB,varB,nB) -let tTest3 = TTest.twoSample false groupA groupB - - - - +open FSharp.Stats.Algebra let KDiagonal1 = [| @@ -64,7 +25,21 @@ let BNegInf = |> Matrix.ofJaggedArray -Algebra.LinearAlgebra .solveTriangularLinearSystems KDiagonal1 BNegInf false +Algebra.LinearAlgebra.solveTriangularLinearSystems KDiagonal1 BNegInf false + + +KDiagonal1 +|> Matrix.mapiCols (fun i v -> + let m = Vector.norm v + [|m|]) + +let expected = + matrix [| + [|nan;nan;nan|]; + [|nan;nan;nan|]; + [|-infinity;-infinity;-infinity|] + |] + //|> fun res -> // let expected = diff --git a/tests/FSharp.Stats.Tests/LinearAlgebra.fs b/tests/FSharp.Stats.Tests/LinearAlgebra.fs index e52f3cf6e..3225fe876 100644 --- a/tests/FSharp.Stats.Tests/LinearAlgebra.fs +++ b/tests/FSharp.Stats.Tests/LinearAlgebra.fs @@ -29,67 +29,70 @@ let managedSVDTests = let m' = mEqualNRecov.toJaggedArray() |> Array.concat TestExtensions.sequenceEqual Accuracy.high m m' "Matrices computed by SVD did not yield the initial matrix when multiplied." - //testCase "m=n Matrix: u and vt consist of unit vectors, row- and column- wise." <| fun () -> - // let u,s,vt = svdManaged mEqualN - // let vecNorms = - // [ - // u |> Matrix.mapiCols (fun _ v -> FSharp.Stats.Vector.norm v) - // vt|> Matrix.mapiCols (fun _ v -> Vector.norm v) - // u |> Matrix.mapiRows (fun _ x -> x |> Vector.norm) - // vt|> Matrix.mapiRows (fun _ x -> x |> Vector.norm) - // ] - // |> Array.concat - // TestExtensions.sequenceEqual Accuracy.high (Array.create vecNorms.Length 1.) vecNorms "Matrices computed by SVD did not consist of unit vectors, row- and column- wise." + testCase "m=n Matrix: u and vt consist of unit vectors, row- and column- wise." <| fun () -> + let u,s,vt = svdManaged mEqualN + let vecNorms = + [| + u |> Matrix.mapiCols (fun _ v -> [|FSharp.Stats.Vector.norm v|]) + vt|> Matrix.mapiCols (fun _ v -> [|FSharp.Stats.Vector.norm v|]) + u |> Matrix.mapiRows (fun _ x -> [|FSharp.Stats.Vector.norm x|]) + vt|> Matrix.mapiRows (fun _ x -> [|FSharp.Stats.Vector.norm x|]) + |] + |> Array.map (fun m -> m.Data) + |> Array.concat + TestExtensions.sequenceEqual Accuracy.high (Array.create vecNorms.Length 1.) vecNorms "Matrices computed by SVD did not consist of unit vectors, row- and column- wise." - //testCase "m=n Matrix: s contains correct singular values." <| fun () -> - // let s,u,vt = LinearAlgebra.SVD mEqualN - // TestExtensions.sequenceEqual Accuracy.high ([|15.81461344;2.213142934|]) s "Matrices computed by SVD did not yield correct singular values." + testCase "m=n Matrix: s contains correct singular values." <| fun () -> + let s,u,vt = LinearAlgebra.SVD mEqualN + TestExtensions.sequenceEqual Accuracy.high ([|15.81461344;2.213142934|]) s "Matrices computed by SVD did not yield correct singular values." - //testCase "m - // let u,s,vt = svdManaged mSmallerN - // let mSmallernRecov = (u * s * vt) - // let m = mSmallerN |> Matrix.toJaggedArray |> Array.concat - // let m' = mSmallernRecov |> Matrix.toJaggedArray |> Array.concat - // TestExtensions.sequenceEqual Accuracy.high m m' "Matrices computed by SVD did not yield the initial matrix when multiplied." + testCase "m + let u,s,vt = svdManaged mSmallerN + let mSmallernRecov = (u * s * vt) + let m = mSmallerN.Data + let m' = mSmallernRecov.Data + TestExtensions.sequenceEqual Accuracy.high m m' "Matrices computed by SVD did not yield the initial matrix when multiplied." - //testCase "m - // let u,s,vt = svdManaged mSmallerN - // let vecNorms = - // [ - // u |> Matrix.mapCols Vector.norm |> RowVector.toArray - // vt|> Matrix.mapCols Vector.norm |> RowVector.toArray - // u |> Matrix.mapRows (fun x -> x.Transpose |> Vector.norm) |> Vector.toArray - // vt|> Matrix.mapRows (fun x -> x.Transpose |> Vector.norm) |> Vector.toArray - // ] - // |> Array.concat - // TestExtensions.sequenceEqual Accuracy.high (Array.create vecNorms.Length 1.) vecNorms "Matrices computed by SVD did not consist of unit vectors, row- and column- wise." + testCase "m + let u,s,vt = svdManaged mSmallerN + let vecNorms = + [| + u |> Matrix.mapiCols (fun _ v -> [|FSharp.Stats.Vector.norm v|]) + vt|> Matrix.mapiCols (fun _ v -> [|FSharp.Stats.Vector.norm v|]) + u |> Matrix.mapiRows (fun _ x -> [|FSharp.Stats.Vector.norm x|]) + vt|> Matrix.mapiRows (fun _ x -> [|FSharp.Stats.Vector.norm x|]) + |] + |> Array.map (fun m -> m.Data) + |> Array.concat + TestExtensions.sequenceEqual Accuracy.high (Array.create vecNorms.Length 1.) vecNorms "Matrices computed by SVD did not consist of unit vectors, row- and column- wise." - //testCase "m - // let s,u,vt = LinearAlgebra.SVD mSmallerN - // TestExtensions.sequenceEqual Accuracy.high ([|22.51999394;6.986424855;2.00991059|]) s "Matrices computed by SVD did not yield correct singular values." + testCase "m + let s,u,vt = LinearAlgebra.SVD mSmallerN + TestExtensions.sequenceEqual Accuracy.high ([|22.51999394;6.986424855;2.00991059|]) s "Matrices computed by SVD did not yield correct singular values." - //testCase "m>n Matrix: Recover from decomposition" <| fun () -> - // let u,s,vt = svdManaged (mSmallerN.Transpose()) - // let mSmallernRecov = (u * s * vt) - // let m = mSmallerN.Transpose().toJaggedArray() |> Array.concat - // let m' = mSmallernRecov.toJaggedArray() |> Array.concat - // TestExtensions.sequenceEqual Accuracy.high m m' "Matrices computed by SVD did not yield the initial matrix when multiplied." + testCase "m>n Matrix: Recover from decomposition" <| fun () -> + let u,s,vt = svdManaged (mSmallerN.Transpose()) + let mSmallernRecov = (u * s * vt) + let m = mSmallerN.Transpose().Data + let m' = mSmallernRecov.Data + TestExtensions.sequenceEqual Accuracy.high m m' "Matrices computed by SVD did not yield the initial matrix when multiplied." - //testCase "m>n Matrix: u and vt consist of unit vectors, row- and column- wise." <| fun () -> - // let u,s,vt = svdManaged (mSmallerN.Transpose()) - // let vecNorms = - // [ - // u |> Matrix.mapCols Vector.norm |> RowVector.toArray - // vt|> Matrix.mapCols Vector.norm |> RowVector.toArray - // u |> Matrix.mapRows (fun x -> x.Transpose |> Vector.norm) |> Vector.toArray - // vt|> Matrix.mapRows (fun x -> x.Transpose |> Vector.norm) |> Vector.toArray - // ] - // |> Array.concat - // TestExtensions.sequenceEqual Accuracy.high (Array.create vecNorms.Length 1.) vecNorms "Matrices computed by SVD did not consist of unit vectors, row- and column- wise." + testCase "m>n Matrix: u and vt consist of unit vectors, row- and column- wise." <| fun () -> + let u,s,vt = svdManaged (mSmallerN.Transpose()) + let vecNorms = + [| + u |> Matrix.mapiCols (fun _ v -> [|FSharp.Stats.Vector.norm v|]) + vt|> Matrix.mapiCols (fun _ v -> [|FSharp.Stats.Vector.norm v|]) + u |> Matrix.mapiRows (fun _ x -> [|FSharp.Stats.Vector.norm x|]) + vt|> Matrix.mapiRows (fun _ x -> [|FSharp.Stats.Vector.norm x|]) + |] + |> Array.map (fun m -> m.Data) + |> Array.concat + TestExtensions.sequenceEqual Accuracy.high (Array.create vecNorms.Length 1.) vecNorms "Matrices computed by SVD did not consist of unit vectors, row- and column- wise." - //testCase "m>n Matrix: s contains correct singular values." <| fun () -> - // let s,u,vt = LinearAlgebra.SVD (mSmallerN.Transpose()) - // TestExtensions.sequenceEqual Accuracy.high ([|22.51999394;6.986424855;2.00991059|]) s "Matrices computed by SVD did not yield correct singular values." + testCase "m>n Matrix: s contains correct singular values." <| fun () -> + let s,u,vt = LinearAlgebra.SVD (mSmallerN.Transpose()) + TestExtensions.sequenceEqual Accuracy.high ([|22.51999394;6.986424855;2.00991059|]) s "Matrices computed by SVD did not yield correct singular values." ] From 74384f4df275dc91b3ef6ce6fd15f0a9c4c87381 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20M=C3=BChlhaus?= Date: Sun, 13 Apr 2025 14:50:14 +0200 Subject: [PATCH 079/121] Add distribution Categorical --- src/FSharp.Stats/Algebra/LinearAlgebra.fs | 7 +- .../Distributions/Discrete/Categorical.fs | 160 ++++++++++++++++++ .../Discrete/LabelledCategorical.fs | 125 ++++++++++++++ src/FSharp.Stats/FSharp.Stats.fsproj | 2 + 4 files changed, 292 insertions(+), 2 deletions(-) create mode 100644 src/FSharp.Stats/Distributions/Discrete/Categorical.fs create mode 100644 src/FSharp.Stats/Distributions/Discrete/LabelledCategorical.fs diff --git a/src/FSharp.Stats/Algebra/LinearAlgebra.fs b/src/FSharp.Stats/Algebra/LinearAlgebra.fs index 5a6e8b7a5..7fe1807a6 100644 --- a/src/FSharp.Stats/Algebra/LinearAlgebra.fs +++ b/src/FSharp.Stats/Algebra/LinearAlgebra.fs @@ -6,8 +6,8 @@ open FSharp.Stats type LinearAlgebra = - /// Subtract `scaleVal * src[srcOffset..srcOffset+count-1]` from - /// `dst[dstOffset..dstOffset+count-1]` in place. + /// Subtract `scaleVal * src[srcOffset..srcOffset+count-1]` from + /// `dst[dstOffset..dstOffset+count-1]` in place. static member inline subScaledRowInPlace (scaleVal : 'T) (dstOffset : int) @@ -27,6 +27,7 @@ type LinearAlgebra = d - (scaleVal * s) Acceleration.SIMDRangeUtils.map2RangeInPlace fv f dstOffset srcOffset count dst src + static member inline householderTransform (A: Matrix<'T>) (i: int) : Vector<'T> = let n = A.NumRows @@ -38,6 +39,8 @@ type LinearAlgebra = if j <> i then v.[j] <- aCol.[j] v + + /// QR decomposition using modified Gram-Schmidt /// Returns Q and R such that A = QR static member inline qrModifiedGramSchmidt<'T when 'T :> Numerics.INumber<'T> diff --git a/src/FSharp.Stats/Distributions/Discrete/Categorical.fs b/src/FSharp.Stats/Distributions/Discrete/Categorical.fs new file mode 100644 index 000000000..08fb89c7e --- /dev/null +++ b/src/FSharp.Stats/Distributions/Discrete/Categorical.fs @@ -0,0 +1,160 @@ +namespace FSharp.Stats.Distributions.Discrete + +open FSharp.Stats +open FSharp.Stats.Distributions + +/// +/// Categorical distribution (finite discrete distribution over k categories with probabilities). +/// +type Categorical = + + /// Checks if the given probability vector is valid (all values ∈ [0,1] and sum to 1). + /// An array of probabilities over k categories. + static member CheckParam (probabilities: float[]) = + if probabilities.Length = 0 then failwith "Categorical distribution must have at least one category." + if probabilities |> Array.exists (fun p -> p < 0. || p > 1. || Ops.isNan(p)) then + failwith "All probabilities must be in [0, 1]." + let total = probabilities |> Array.sum + if abs (total - 1.0) > 1e-8 then + failwithf "Probabilities must sum to 1.0 (got %f)." total + + /// Computes the mean (expected index) of the categorical distribution. + /// An array of probabilities over k categories. + /// The weighted average of indices based on probabilities. + static member Mean (probabilities: float[]) = + Categorical.CheckParam probabilities + probabilities + |> Array.mapi (fun i p -> float i * p) + |> Array.sum + + /// Computes the variance of the categorical distribution. + /// An array of probabilities over k categories. + /// The variance: E[X²] - (E[X])². + static member Variance (probabilities: float[]) = + Categorical.CheckParam probabilities + let mean = Categorical.Mean probabilities + probabilities + |> Array.mapi (fun i p -> p * float i ** 2.0) + |> Array.sum + |> fun ex2 -> ex2 - mean ** 2.0 + + /// Generates a random sample from the categorical distribution. No parameter checking. + /// An array of probabilities over k categories. + /// An integer representing the sampled category index. + static member SampleUnchecked (probabilities: float[]) = + let rnd = Random.rndgen.NextFloat() + let rec search i acc = + if i >= probabilities.Length then probabilities.Length - 1 + elif acc + probabilities[i] >= rnd then i + else search (i + 1) (acc + probabilities[i]) + search 0 0.0 + + /// Generates a random sample from the categorical distribution. + /// An array of probabilities over k categories. + /// An integer representing the sampled category index. + static member Sample (probabilities: float[]) = + Categorical.CheckParam probabilities + Categorical.SampleUnchecked probabilities + + /// Computes the probability mass function at index k: P(X = k). + /// An array of probabilities over k categories. + /// The index to evaluate. + /// The probability of observing category k. + static member PMF (probabilities: float[]) (k:int) = + Categorical.CheckParam probabilities + if k < 0 || k >= probabilities.Length then 0.0 + else probabilities[k] + + /// Computes the cumulative distribution function at x: P(X ≤ x). + /// An array of probabilities over k categories. + /// A float value where CDF is evaluated (interpreted as an index). + /// The cumulative probability up to and including ⌊x⌋. + static member CDF (probabilities: float[]) (x: float) = + Categorical.CheckParam probabilities + if x < 0. then 0.0 + elif x >= float (probabilities.Length) then 1.0 + else + let k = floor x |> int + probabilities + |> Array.take (k + 1) + |> Array.sum + + /// Returns the support (valid outcome range) of the distribution: [0, k-1]. + /// An array of probabilities over k categories. + /// A closed interval [0, k-1]. + static member Support (probabilities: float[]) = + Categorical.CheckParam probabilities + Interval.CreateClosed(0, probabilities.Length - 1) + + /// Returns a string representation of the categorical distribution. + /// An array of probabilities over k categories. + /// A string describing the distribution. + static member ToString (probabilities: float[]) = + sprintf "Categorical(p = [%s])" (String.concat "; " (probabilities |> Array.map string)) + + /// Fits the categorical distribution to a set of integer observations (category indices). + /// Total number of categories. + /// Array of category indices (0-based). + /// Estimated probability vector. + static member Fit (numCategories:int) (observations:int[]) = + let counts = Array.zeroCreate numCategories + for i in observations do + if i < 0 || i >= numCategories then + failwithf "Observation index %d out of bounds [0, %d]" i (numCategories - 1) + counts[i] <- counts[i] + 1 + let total = float (Array.sum counts) + counts |> Array.map (fun c -> float c / total) + + /// Estimates a categorical distribution from observed category indices. + /// Total number of categories. + /// Array of category indices (0-based). + /// A categorical distribution fitted to the observations. + static member Estimate numCategories observations = + Categorical.Fit numCategories observations + |> fun probs -> Categorical.Init probs + + /// Initializes a categorical distribution instance from a given probability vector. + /// An array of probabilities over k categories. + /// A distribution implementing DiscreteDistribution<float, int>. + static member Init (probabilities: float[]) = + Categorical.CheckParam probabilities + { new DiscreteDistribution with + member d.Mean = Categorical.Mean probabilities + member d.Variance = Categorical.Variance probabilities + member d.StandardDeviation = sqrt (Categorical.Variance probabilities) + member d.Sample () = Categorical.Sample probabilities + member d.CDF x = Categorical.CDF probabilities x + member d.InvCDF x = failwith "InvCDF not implemented for Categorical" + member d.Mode = probabilities |> Array.mapi (fun i p -> i, p) |> Array.maxBy snd |> fst + member d.PMF k = Categorical.PMF probabilities k + member d.Parameters = DistributionParameters.Categorical probabilities + override d.ToString() = Categorical.ToString probabilities + } + + + /// + /// Converts a cumulative unnormalized weight array into a normalized PMF. + /// + /// An array of cumulative weights. + /// A normalized probability mass function. + static member CdfToPmf (cdf: float[]) = + if cdf.Length = 0 then failwith "CDF must not be empty." + if cdf |> Array.exists (fun x -> x < 0. || Ops.isNan x) then + failwith "CDF values must be non-negative." + let pmf = + Array.init cdf.Length (fun i -> + if i = 0 then cdf.[0] + else cdf.[i] - cdf.[i - 1]) + let total = Array.sum pmf + if total = 0.0 then failwith "CDF must contain non-zero mass." + pmf |> Array.map (fun x -> x / total) + + /// + /// Initializes a Categorical distribution from an unnormalized CDF. + /// + /// An array of cumulative unnormalized weights. + /// A normalized Categorical distribution. + static member FromCdfUnnormalized (cdf: float[]) = + let probs = Categorical.CdfToPmf cdf + Categorical.Init probs + diff --git a/src/FSharp.Stats/Distributions/Discrete/LabelledCategorical.fs b/src/FSharp.Stats/Distributions/Discrete/LabelledCategorical.fs new file mode 100644 index 000000000..ef8d194bf --- /dev/null +++ b/src/FSharp.Stats/Distributions/Discrete/LabelledCategorical.fs @@ -0,0 +1,125 @@ +namespace FSharp.Stats.Distributions.Discrete + +open FSharp.Stats +open FSharp.Stats.Distributions + +/// +/// A wrapper around the Categorical distribution that associates each probability with a custom label of type 'Label. +/// +/// The type used to label the categories (e.g., string, union, enum). +type LabelledCategorical<'Label when 'Label: comparison> private + ( + labelToIndex: Map<'Label, int>, + indexToLabel: 'Label[], + probs: float[] + ) = + + let dist = Categorical.Init probs + + /// + /// Initializes a new instance of the LabelledCategorical distribution using label-probability pairs. + /// + /// An array of labels for each category (must be unique). + /// An array of probabilities for each label (must sum to 1). + new (labels: 'Label[], probs: float[]) = + if labels.Length <> probs.Length then + failwith "Label and probability array must be the same length." + let labelToIndex = labels |> Array.mapi (fun i l -> l, i) |> Map.ofArray + LabelledCategorical(labelToIndex, labels, probs) + + /// + /// Gets the array of category labels. + /// + member _.Labels : 'Label[] = indexToLabel + + /// + /// Gets the array of probabilities associated with the labels. + /// + member _.Probabilities : float[] = probs + + /// + /// Returns the probability of a given label. + /// + /// The label to query. + /// The probability associated with the label, or 0.0 if the label is not found. + member _.PMF(label: 'Label) = + match Map.tryFind label labelToIndex with + | Some i -> dist.PMF i + | None -> 0.0 + + /// + /// Returns the cumulative probability up to and including the given label. + /// + /// The label to evaluate the cumulative probability up to. + /// The cumulative probability. + member _.CDF(label: 'Label) = + match Map.tryFind label labelToIndex with + | Some i -> probs |> Array.take (i + 1) |> Array.sum + | None -> 0.0 + + /// + /// Returns the array of labels (support of the distribution). + /// + member _.Support = indexToLabel + + /// + /// Draws a random sample from the distribution and returns the sampled label. + /// + /// A label corresponding to a sampled category. + member _.Sample() = + let i = dist.Sample() + indexToLabel[i] + + /// + /// Returns the label closest to the expected (mean) index of the distribution. + /// + /// The label whose index is closest to the mean. + member _.MeanLabel() = + let mi = dist.Mean |> round |> int + indexToLabel[mi] + + /// + /// Fits a LabelledCategorical distribution from a set of labeled observations. + /// + /// An array of observed labels. + /// A new LabelledCategorical distribution with probabilities estimated from observed frequencies. + static member Fit (observations: 'Label[]) = + observations + |> Array.countBy id + |> Array.sortBy fst + |> fun counts -> + let total = float observations.Length + let labelArray = counts |> Array.map fst + let probs = counts |> Array.map (fun (_, c) -> float c / total) + LabelledCategorical(labelArray, probs) + + /// + /// Estimates a distribution from labels and counts (frequencies). + /// + /// An array of labels. + /// An array of counts corresponding to each label. + /// A new LabelledCategorical distribution. + static member Estimate (labels: 'Label[]) (counts: int[]) = + if labels.Length <> counts.Length then + failwith "Labels and counts must be the same length." + let total = float (Array.sum counts) + let probs = counts |> Array.map (fun c -> float c / total) + LabelledCategorical(labels, probs) + + + /// + /// Initializes a LabelledCategorical distribution from labels and a cumulative unnormalized weight vector. + /// + /// Labels corresponding to cumulative weights. + /// Unnormalized cumulative weights (must be increasing). + /// A normalized LabelledCategorical distribution. + static member FromCdfUnnormalized(labels: 'Label[], cdf: float[]) = + if labels.Length <> cdf.Length then + failwith "Labels and cumulative weights must be the same length." + let deltas = + Array.init cdf.Length (fun i -> + if i = 0 then cdf.[0] + else cdf.[i] - cdf.[i - 1]) + let total = Array.sum deltas + let probs = deltas |> Array.map (fun x -> x / total) + LabelledCategorical(labels, probs) diff --git a/src/FSharp.Stats/FSharp.Stats.fsproj b/src/FSharp.Stats/FSharp.Stats.fsproj index 31d570668..00a4c4621 100644 --- a/src/FSharp.Stats/FSharp.Stats.fsproj +++ b/src/FSharp.Stats/FSharp.Stats.fsproj @@ -108,6 +108,8 @@ + + From 8ff9bb5c302bcd7cbc1c89624451533e1f61aff8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20M=C3=BChlhaus?= Date: Sun, 13 Apr 2025 16:44:35 +0200 Subject: [PATCH 080/121] Add sampling from multinomial distribution --- .../Distributions/Discrete/Multinomial.fs | 30 ++++++++++++++----- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/src/FSharp.Stats/Distributions/Discrete/Multinomial.fs b/src/FSharp.Stats/Distributions/Discrete/Multinomial.fs index 8cc737607..7660c19b9 100644 --- a/src/FSharp.Stats/Distributions/Discrete/Multinomial.fs +++ b/src/FSharp.Stats/Distributions/Discrete/Multinomial.fs @@ -48,17 +48,31 @@ type Multinomial = Multinomial.CheckParam p n Array.map sqrt (Multinomial.Variance p n) + /// + /// Converts a probability mass function into an unnormalized cumulative distribution function (CDF). + /// + /// An array of probabilities (not validated). + /// An array of cumulative probabilities. + static member ProbabilityMassToCumulativeDistribution (p : float[]) = + let cdfUnnormalized = Array.zeroCreate p.Length + cdfUnnormalized[0] <- p[0] + for i = 1 to p.Length - 1 do + cdfUnnormalized[i] <- cdfUnnormalized[i - 1] + p[i] + cdfUnnormalized + /// Produces a random sample using the current random number generator (from GetSampleGenerator()). No parameter checking! /// /// vector of event probabilities in each trial - /// number of trails - /// - /// - /// - /// - /// - static member internal SampleUnchecked p n = - failwithf "Not implemented yet" + /// number of trails(must be ≥ 0). + /// An array of counts per category. + static member SampleUnchecked (p : float[]) n = + let cp = Multinomial.ProbabilityMassToCumulativeDistribution p + let ret = Array.zeroCreate p.Length + for _ = 1 to n do + let idx = Categorical.SampleUnchecked cp + ret[idx] <- ret[idx] + 1 + ret + /// Produces a random sample using the current random number generator (from GetSampleGenerator()). /// From 386253c028cd7c958d299e4902b0148457058491 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20M=C3=BChlhaus?= Date: Sun, 13 Apr 2025 17:11:27 +0200 Subject: [PATCH 081/121] Add Unit testing categorical distribution --- .../Distributions/Distribution.fs | 1 + .../DistributionsDiscrete.fs | 120 ++++++++++++++++++ 2 files changed, 121 insertions(+) diff --git a/src/FSharp.Stats/Distributions/Distribution.fs b/src/FSharp.Stats/Distributions/Distribution.fs index 17ee2d05d..0952617de 100644 --- a/src/FSharp.Stats/Distributions/Distribution.fs +++ b/src/FSharp.Stats/Distributions/Distribution.fs @@ -92,6 +92,7 @@ type DistributionParameters = // Discrete distributions | Bernoulli of Parameters.Bernoulli | Binomial of Parameters.Binomial + | Categorical of float[] | NegativeBinomial of Parameters.NegativeBinomial | Hypergeometric of Parameters.Hypergeometric | Poisson of Parameters.Poisson diff --git a/tests/FSharp.Stats.Tests/DistributionsDiscrete.fs b/tests/FSharp.Stats.Tests/DistributionsDiscrete.fs index 029354c87..24a5feed8 100644 --- a/tests/FSharp.Stats.Tests/DistributionsDiscrete.fs +++ b/tests/FSharp.Stats.Tests/DistributionsDiscrete.fs @@ -379,6 +379,126 @@ let binomialTests = ] +[] +let categoricalTests = + testList "Categorical distribution tests" [ + + test "CheckParam should fail on invalid probabilities" { + let invalid1 = [| -0.1; 0.6; 0.5 |] + let invalid2 = [| 0.2; 0.3; 0.4 |] // sum ≠ 1.0 + Expect.throws (fun () -> Discrete.Categorical.CheckParam invalid1) "Negative probability should throw" + Expect.throws (fun () -> Discrete.Categorical.CheckParam invalid2) "Probabilities that do not sum to 1.0 should throw" + } + + test "PMF returns correct probability" { + let p = [| 0.2; 0.3; 0.5 |] + let d = Discrete.Categorical.Init p + Expect.floatClose Accuracy.high (d.PMF 0) 0.2 "PMF for category 0" + Expect.floatClose Accuracy.high (d.PMF 1) 0.3 "PMF for category 1" + Expect.floatClose Accuracy.high (d.PMF 2) 0.5 "PMF for category 2" + Expect.equal (d.PMF 3) 0.0 "PMF for out-of-range index" + } + + test "CDF returns correct cumulative probability" { + let p = [| 0.1; 0.2; 0.3; 0.4 |] + let d = Discrete.Categorical.Init p + Expect.floatClose Accuracy.high (d.CDF -1.0) 0.0 "CDF below 0" + Expect.floatClose Accuracy.high (d.CDF 0.0) 0.1 "CDF at 0" + Expect.floatClose Accuracy.high (d.CDF 1.0) 0.3 "CDF at 1" + Expect.floatClose Accuracy.high (d.CDF 2.0) 0.6 "CDF at 2" + Expect.floatClose Accuracy.high (d.CDF 3.0) 1.0 "CDF at 3" + Expect.floatClose Accuracy.high (d.CDF 4.0) 1.0 "CDF above max index" + } + + test "Sampling produces plausible frequencies" { + let p = [| 0.1; 0.3; 0.6 |] + let d = Discrete.Categorical.Init p + let samples = Array.init 10000 (fun _ -> d.Sample()) + let freqs = samples |> Array.countBy id |> Map.ofArray + let getFreq k = Map.tryFind k freqs |> Option.defaultValue 0 |> float + let total = float samples.Length + Expect.floatClose fittingAccuracy (getFreq 0 / total) 0.1 "Sample frequency for 0" + Expect.floatClose fittingAccuracy (getFreq 1 / total) 0.3 "Sample frequency for 1" + Expect.floatClose fittingAccuracy (getFreq 2 / total) 0.6 "Sample frequency for 2" + } + + test "Mean and variance are correctly computed" { + let p = [| 0.0; 0.5; 0.5 |] + let d =Discrete.Categorical.Init p + Expect.floatClose Accuracy.high d.Mean 1.5 "Mean should be 1.5" + Expect.floatClose Accuracy.high d.Variance 0.25 "Variance should be 0.25" + } + + test "Fit returns estimated probabilities from observations" { + let observations = [| 0; 1; 1; 2; 2; 2 |] + let est = Discrete.Categorical.Fit 3 observations + Expect.floatClose Accuracy.high est[0] (1.0/6.0) "P(0)" + Expect.floatClose Accuracy.high est[1] (2.0/6.0) "P(1)" + Expect.floatClose Accuracy.high est[2] (3.0/6.0) "P(2)" + } + + test "Estimate returns a distribution with valid PMFs" { + let observations = [| 0; 0; 1; 2; 2; 2 |] + let d = Discrete.Categorical.Estimate 3 observations + Expect.floatClose Accuracy.high (d.PMF 0) (2.0/6.0) "PMF for category 0" + Expect.floatClose Accuracy.high (d.PMF 1) (1.0/6.0) "PMF for category 1" + Expect.floatClose Accuracy.high (d.PMF 2) (3.0/6.0) "PMF for category 2" + } + + ] + + +[] +let labelledCategoricalTests = + testList "LabelledCategorical tests" [ + + test "PMF returns correct probability for labels" { + let labels = [| "A"; "B"; "C" |] + let probs = [| 0.2; 0.3; 0.5 |] + let d = Discrete.LabelledCategorical(labels, probs) + Expect.floatClose Accuracy.high (d.PMF "A") 0.2 "PMF A" + Expect.floatClose Accuracy.high (d.PMF "B") 0.3 "PMF B" + Expect.floatClose Accuracy.high (d.PMF "C") 0.5 "PMF C" + } + + test "CDF computes cumulative probabilities" { + let labels = [| "A"; "B"; "C" |] + let probs = [| 0.1; 0.2; 0.7 |] + let d = Discrete.LabelledCategorical(labels, probs) + Expect.floatClose Accuracy.high (d.CDF "A") 0.1 "CDF A" + Expect.floatClose Accuracy.high (d.CDF "B") 0.3 "CDF B" + Expect.floatClose Accuracy.high (d.CDF "C") 1.0 "CDF C" + } + + test "Sampling returns expected label frequencies" { + let labels = [| "Yes"; "No" |] + let probs = [| 0.7; 0.3 |] + let d = Discrete.LabelledCategorical(labels, probs) + let samples = Array.init 10000 (fun _ -> d.Sample()) + let freq = samples |> Array.countBy id |> Map.ofArray + let yesFreq = Map.tryFind "Yes" freq |> Option.defaultValue 0 |> float + Expect.floatClose fittingAccuracy (yesFreq / 10000.0) 0.7 "Sampling approx 70%" + } + + test "Fit estimates correct probabilities from observations" { + let observations = [| "X"; "X"; "Y"; "Z"; "Z"; "Z" |] + let d = Discrete.LabelledCategorical.Fit observations + Expect.floatClose Accuracy.high (d.PMF "X") (2.0/6.0) "P(X)" + Expect.floatClose Accuracy.high (d.PMF "Y") (1.0/6.0) "P(Y)" + Expect.floatClose Accuracy.high (d.PMF "Z") (3.0/6.0) "P(Z)" + } + + test "Estimate constructs distribution from labels and counts" { + let labels = [| "Red"; "Green"; "Blue" |] + let counts = [| 3; 1; 6 |] + let d = Discrete.LabelledCategorical.Estimate labels counts + Expect.floatClose Accuracy.high (d.PMF "Red") 0.3 "P(Red)" + Expect.floatClose Accuracy.high (d.PMF "Green") 0.1 "P(Green)" + Expect.floatClose Accuracy.high (d.PMF "Blue") 0.6 "P(Blue)" + } + + ] + [] let multinomialTests = From 8ebd28880241298afe8edcfe6bd55b53c5ea525b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20M=C3=BChlhaus?= Date: Sun, 13 Apr 2025 22:59:32 +0200 Subject: [PATCH 082/121] Add unit testing for Multinomial.sample --- .../Distributions/Discrete/Multinomial.fs | 4 +- src/FSharp.Stats/Playground.fsx | 78 +++++++++++++++++++ .../DistributionsDiscrete.fs | 15 ++++ 3 files changed, 95 insertions(+), 2 deletions(-) diff --git a/src/FSharp.Stats/Distributions/Discrete/Multinomial.fs b/src/FSharp.Stats/Distributions/Discrete/Multinomial.fs index 7660c19b9..c1b6bbda6 100644 --- a/src/FSharp.Stats/Distributions/Discrete/Multinomial.fs +++ b/src/FSharp.Stats/Distributions/Discrete/Multinomial.fs @@ -66,10 +66,10 @@ type Multinomial = /// number of trails(must be ≥ 0). /// An array of counts per category. static member SampleUnchecked (p : float[]) n = - let cp = Multinomial.ProbabilityMassToCumulativeDistribution p + //let cp = Multinomial.ProbabilityMassToCumulativeDistribution p let ret = Array.zeroCreate p.Length for _ = 1 to n do - let idx = Categorical.SampleUnchecked cp + let idx = Categorical.SampleUnchecked p ret[idx] <- ret[idx] + 1 ret diff --git a/src/FSharp.Stats/Playground.fsx b/src/FSharp.Stats/Playground.fsx index ac76cc2c3..89a1bf27f 100644 --- a/src/FSharp.Stats/Playground.fsx +++ b/src/FSharp.Stats/Playground.fsx @@ -8,6 +8,84 @@ open FSharp.Stats.Distributions //open Plotly.NET open FSharp.Stats.Algebra + + +let Categorical_SampleUnchecked (probabilities: float[]) = + let rnd = Random.rndgen.NextFloat() + let rec search i acc = + if i >= probabilities.Length then probabilities.Length - 1 + elif acc + probabilities[i] >= rnd then i + else search (i + 1) (acc + probabilities[i]) + search 0 0.0 + + + + +/// Helper function to sample many times and collect counts. +let sampleMany (times: int) (probabilities: float[]) = + let counts = Array.zeroCreate probabilities.Length + for _ in 1 .. times do + let idx = Categorical_SampleUnchecked probabilities + counts.[idx] <- counts.[idx] + 1 + counts + + + +let p = [| 0.2; 0.3; 0.5 |] +let iterations = 10000000 + +Array.init iterations (fun _ -> Categorical_SampleUnchecked p) +|> Array.countBy id + + + +// Act +let counts = sampleMany iterations p +float counts.[2] / float iterations + + +// Assert +// All indices should be between 0 and p.Length - 1 +// If out of range, an exception would occur while incrementing counts. +// So, if we got this far without an exception, the function is generating valid indices. +// We can add an extra check that the sum of counts equals 'iterations'. +let total = Array.sum counts + + +let SampleUnchecked (p : float[]) n = + //let cp = Discrete.Multinomial.ProbabilityMassToCumulativeDistribution p + let ret = Array.zeroCreate p.Length + for _ = 1 to n do + let idx = Discrete.Categorical.SampleUnchecked p + ret[idx] <- ret[idx] + 1 + ret + +let n = 100000 // Large n to reduce variance +let probabilities = [| 0.2; 0.3; 0.5 |] +//// Act +//let sampleCounts = Categorical_SampleUnchecked probabilities + +//probabilities +//|> Array.iteri (fun i p -> +// let observedProportion = float sampleCounts.[i] / float n +// printfn $"Probability of {i}: {p}, Observed proportion: {observedProportion}") + + + +//let n = 100000 // Larger n to reduce sampling variance +let sample = SampleUnchecked probabilities n + +let () = + probabilities + |> Array.iteri (fun i p -> + let observedProportion = float sample.[i] / float n + printfn $"Probability of {i}: {p}, Observed proportion: {observedProportion}") + + + +Discrete.Multinomial.ProbabilityMassToCumulativeDistribution probabilities + + let KDiagonal1 = [| [|1.;0.;0.|] diff --git a/tests/FSharp.Stats.Tests/DistributionsDiscrete.fs b/tests/FSharp.Stats.Tests/DistributionsDiscrete.fs index 24a5feed8..47280168a 100644 --- a/tests/FSharp.Stats.Tests/DistributionsDiscrete.fs +++ b/tests/FSharp.Stats.Tests/DistributionsDiscrete.fs @@ -590,6 +590,21 @@ let multinomialTests = let x = [|1;2;3|] let testCase() = Discrete.Multinomial.PMF prob5 x Expect.throws (fun _ -> testCase() |> ignore) "probabilities of 0 is associated to success event" + + test "Sample proportions should be close to the expected probabilities" { + let probabilities = [| 0.2; 0.3; 0.5 |] + let n = 100000 // Larger n to reduce sampling variance + let sample = Discrete.Multinomial.Sample probabilities n + probabilities + |> Array.iteri (fun i p -> + let observedProportion = float sample.[i] / float n + Expect.floatClose + Accuracy.low // or a custom `floatClose` config + observedProportion + p + $"Observed proportion ({observedProportion}) should be close to expected probability ({p})" + ) + } ] [] From 7a71caa92db065c69d0f764955dc109c1b322940 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20M=C3=BChlhaus?= Date: Sun, 13 Apr 2025 23:42:22 +0200 Subject: [PATCH 083/121] Add testing accuracy veryLow for random sampling tests --- tests/FSharp.Stats.Tests/DistributionsDiscrete.fs | 6 +++--- tests/FSharp.Stats.Tests/TestExtensions.fs | 5 +++++ 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/tests/FSharp.Stats.Tests/DistributionsDiscrete.fs b/tests/FSharp.Stats.Tests/DistributionsDiscrete.fs index 47280168a..d20692289 100644 --- a/tests/FSharp.Stats.Tests/DistributionsDiscrete.fs +++ b/tests/FSharp.Stats.Tests/DistributionsDiscrete.fs @@ -4,7 +4,7 @@ open Expecto open System open FSharp.Stats open FSharp.Stats.Distributions - +open TestExtensions // Defining an accuracy appropriate for testing random sampling and inference let fittingAccuracy : Accuracy = {absolute= 0.1 ;relative= 0.1} @@ -593,13 +593,13 @@ let multinomialTests = test "Sample proportions should be close to the expected probabilities" { let probabilities = [| 0.2; 0.3; 0.5 |] - let n = 100000 // Larger n to reduce sampling variance + let n = 1000000 // Larger n to reduce sampling variance let sample = Discrete.Multinomial.Sample probabilities n probabilities |> Array.iteri (fun i p -> let observedProportion = float sample.[i] / float n Expect.floatClose - Accuracy.low // or a custom `floatClose` config + Accuracy.veryLow // or a custom `floatClose` config observedProportion p $"Observed proportion ({observedProportion}) should be close to expected probability ({p})" diff --git a/tests/FSharp.Stats.Tests/TestExtensions.fs b/tests/FSharp.Stats.Tests/TestExtensions.fs index 09c1b8a0c..f427bc5f8 100644 --- a/tests/FSharp.Stats.Tests/TestExtensions.fs +++ b/tests/FSharp.Stats.Tests/TestExtensions.fs @@ -8,6 +8,11 @@ open System.Text open System.Reflection + module Accuracy = + /// veryLow accuracy: absolute = 1e-4, relative = 1e-1 + let veryLow = { absolute = 1e-4; relative = 1e-1 } + + type TestExtensions() = static member sequenceEqual(digits: int) = let round (v:float) = System.Math.Round(v,digits) From 1ce22d2a9dc886fade50a2be2aefaba2d1068f90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20M=C3=BChlhaus?= Date: Thu, 17 Apr 2025 18:13:23 +0200 Subject: [PATCH 084/121] Add Geometric distribution --- .../Distributions/Discrete/Geometric.fs | 154 ++++++++++++++++++ 1 file changed, 154 insertions(+) create mode 100644 src/FSharp.Stats/Distributions/Discrete/Geometric.fs diff --git a/src/FSharp.Stats/Distributions/Discrete/Geometric.fs b/src/FSharp.Stats/Distributions/Discrete/Geometric.fs new file mode 100644 index 000000000..c5504b69b --- /dev/null +++ b/src/FSharp.Stats/Distributions/Discrete/Geometric.fs @@ -0,0 +1,154 @@ +namespace FSharp.Stats.Distributions.Discrete + +open System +open System.Numerics +open FSharp.Stats +open FSharp.Stats.Distributions +open FSharp.Stats.GenericMath + +//IFloatingPoint + +/// +/// Geometric distribution (number of failures before the first success). +/// +type Geometric = + + /// Checks whether the parameter is valid (0.0 < p <= 1.0). + static member inline CheckParam<'T when 'T :> Numerics.INumber<'T> + and 'T : comparison + and 'T : (new : unit -> 'T)> + (p: 'T) = + if p <= 'T.Zero || p > 'T.One then + failwith "Geometric distribution requires 0.0 < p <= 1.0" + + /// Computes the mean: (1 - p) / p + static member inline Mean<'T when 'T :> Numerics.INumber<'T> + and 'T : comparison + and 'T : (new : unit -> 'T)> + (p: 'T) = + Geometric.CheckParam p + ('T.One - p) / p + + /// Computes the variance: (1 - p) / p^2 + static member inline Variance<'T when 'T :> Numerics.INumber<'T> + and 'T : comparison + and 'T : (new : unit -> 'T)> + (p: 'T) = + Geometric.CheckParam p + ('T.One - p) / (p * p) + + /// Computes the standard deviation. + static member inline StandardDeviation<'T when 'T :> Numerics.INumber<'T> + and Numerics.IRootFunctions<'T> + and 'T : comparison + and 'T : (new : unit -> 'T)> + (p: 'T) = + Geometric.CheckParam p + (( 'T.One - p ) / (p * p)) |> GenericMath.sqrt + + /// Computes the mode (always 0). + static member inline Mode<'T when 'T :> Numerics.INumber<'T> + and 'T : comparison + and 'T : (new : unit -> 'T)> + (p: 'T) = + Geometric.CheckParam p + LanguagePrimitives.GenericZero<'T> + + /// Computes the PMF: P(X = k) = (1 - p)^k * p + static member inline PMF<'T when 'T :> Numerics.INumber<'T> + and Numerics.IPowerFunctions<'T> + and 'T : comparison + and 'T : (new : unit -> 'T)> + (p: 'T) (k: int) : 'T = + Geometric.CheckParam p + if k < 0 then 'T.Zero + else + let q = 'T.One - p + p * q ** (T k) + + /// Computes the CDF: P(X ≤ k) = 1 - (1 - p)^(k + 1) + static member inline CDF<'T when 'T :> Numerics.INumber<'T> + and Numerics.IPowerFunctions<'T> + and 'T : comparison + and 'T : (new : unit -> 'T)> + (p: 'T) (k: int) : 'T = + Geometric.CheckParam p + if k < 0 then 'T.Zero + else + let q = 'T.One - p + let tmp = k + 1 + 'T.One - (GenericMath.pow q (T tmp)) + + /// Computes the inverse CDF (quantile function). + static member inline InvCDF<'T when 'T :> Numerics.IFloatingPoint<'T> + and Numerics.ILogarithmicFunctions<'T> + and 'T : comparison + and 'T : (new : unit -> 'T)> + (p: 'T) (x: 'T) = // : int = + Geometric.CheckParam p + if x < 'T.Zero || x > 'T.One then failwith "x must be in [0.0, 1.0]" + let oneMinusX = GenericMath.log ('T.One - x) + let oneMinusP = GenericMath.log ('T.One - p) + let raw = oneMinusX / oneMinusP + GenericMath.floor raw + |> Convert.ToInt32 + + /// samples a value using the built-in random number generator. + static member inline sample<'T when 'T :> Numerics.IFloatingPoint<'T> + and Numerics.ILogarithmicFunctions<'T> + and 'T : comparison + and 'T : (new : unit -> 'T)> + (p: 'T) : int = + Geometric.CheckParam p + let u = 'T.CreateTruncating(Random.rndgen.NextFloat()) + let oneMinusX = GenericMath.log ('T.One - u) + let oneMinusP = GenericMath.log ('T.One - p) + let raw = oneMinusX / oneMinusP + GenericMath.floor raw + |> Convert.ToInt32 + + /// Fits the distribution by estimating p = 1 / (mean + 1). + static member inline Fit<'T when 'T :> Numerics.IFloatingPoint<'T> + and 'T : (static member DivideByInt : 'T * int -> 'T) + and Numerics.ILogarithmicFunctions<'T> + and 'T : comparison + and 'T : (new : unit -> 'T) + and 'T : struct + and 'T :> ValueType> + (observations: 'T[], ?weights: 'T[]) : 'T = + let mean = + match weights with + | None -> Vector.mean observations + | Some w -> Array.weightedMean w observations + 'T.One / (mean + 'T.One) + + ///// Estimates and returns a new initialized distribution instance. + //static member inline Estimate(observations: 'T[], ?weights: 'T[]) = + // let p = Geometric.Fit(observations, ?weights = weights) + // Geometric.Init p + + ///// Returns the support of the geometric distribution: {0, 1, 2, ...}. + //static member inline Support(p: 'T) = + // Geometric.CheckParam p + // Interval.CreateLowerBounded(0) + + /// Returns a formatted string representation. + static member inline ToString(p: 'T) = + $"Geometric(p = {p})" + + ///// Initializes the generic geometric distribution. + //static member inline Init(p: 'T) = + // { new DiscreteDistribution<'T, int> with + // member _.Mean = Geometric.Mean p + // member _.Variance = Geometric.Variance p + // member _.StandardDeviation = Geometric.StandardDeviation p + // member _.CDF x = Geometric.CDF(p, x) + // member _.InvCDF x = Geometric.InvCDF(p, x) + // member _.Mode = Geometric.Mode p + // member _.Sample() = Geometric.Sample p + // member _.PMF x = Geometric.PMF(p, x) + // member _.Parameters = DistributionParameters.Geometric {P = float p} // Assumes parameter storage as float + // override _.ToString() = Geometric.ToString p + // } + + From 4751a015c1dac24b9aacb71782c3d89a1875bae4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20M=C3=BChlhaus?= Date: Thu, 17 Apr 2025 18:33:10 +0200 Subject: [PATCH 085/121] Add Vector.pow --- src/FSharp.Stats/AlgTypes/GenericMath.fs | 16 +++++++++------- src/FSharp.Stats/AlgTypes/VectorExt.fs | 5 +++++ src/FSharp.Stats/FSharp.Stats.fsproj | 1 + 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/FSharp.Stats/AlgTypes/GenericMath.fs b/src/FSharp.Stats/AlgTypes/GenericMath.fs index 8bb1e0543..8ed65f3ef 100644 --- a/src/FSharp.Stats/AlgTypes/GenericMath.fs +++ b/src/FSharp.Stats/AlgTypes/GenericMath.fs @@ -45,19 +45,21 @@ module GenericMath = let inline cos<'T when 'T :> Numerics.ITrigonometricFunctions<'T>> (x: 'T) : 'T = 'T.Cos(x) - // /// Generic pi constant - // let inline pi<'T when 'T :> Numerics.IFloatingPointConstants<'T> and 'T :> Numerics.INumber<'T>> () : 'T = - // pi<'T>() + /// Generic pi constant + let inline pi<'T when 'T :> Numerics.IFloatingPointConstants<'T> and 'T :> Numerics.INumber<'T>> () : 'T = + 'T.Pi /// Generic e constant (Euler's number) let inline e<'T when 'T :> Numerics.IFloatingPointConstants<'T>> () : 'T = 'T.E - // /// Generic tau constant (2 * pi) - // let inline tau<'T when 'T :> Numerics.IFloatingPointConstants<'T> and 'T :> Numerics.INumber<'T>> () : 'T = - // T<'T> 2.0 * pi<'T>() - + /// Generic tau constant (2 * pi) + let inline tau<'T when 'T :> Numerics.IFloatingPointConstants<'T> and 'T :> Numerics.INumber<'T>> () : 'T = + 'T.Tau + /// Generic floor function + let inline floor<'T when 'T :> Numerics.IFloatingPoint<'T>> (x: 'T) : 'T = + 'T. Floor(x) // let inline min x y = if x < y then x else y diff --git a/src/FSharp.Stats/AlgTypes/VectorExt.fs b/src/FSharp.Stats/AlgTypes/VectorExt.fs index 22be07622..e9a721997 100644 --- a/src/FSharp.Stats/AlgTypes/VectorExt.fs +++ b/src/FSharp.Stats/AlgTypes/VectorExt.fs @@ -209,3 +209,8 @@ module Vector = /// let inline ofSeq (s:seq<'T>) : Vector<'T> = s |> Array.ofSeq + + + /// + let inline pow (power: 'T) (v:Vector<'T>) : Vector<'T> = + v |> Array.map (fun x -> GenericMath.pow x power) diff --git a/src/FSharp.Stats/FSharp.Stats.fsproj b/src/FSharp.Stats/FSharp.Stats.fsproj index 00a4c4621..8ba72819e 100644 --- a/src/FSharp.Stats/FSharp.Stats.fsproj +++ b/src/FSharp.Stats/FSharp.Stats.fsproj @@ -109,6 +109,7 @@ + From 3dc4a5e6170e084022063e76368e86807822ac5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20M=C3=BChlhaus?= Date: Thu, 17 Apr 2025 18:33:35 +0200 Subject: [PATCH 086/121] Change Vector scalar parameter order --- src/FSharp.Stats/AlgTypes/Vector.fs | 12 ++++++++---- src/FSharp.Stats/AlgTypes/VectorOps.fs | 15 +++++++++------ src/FSharp.Stats/Algebra/LinearAlgebra.fs | 2 +- tests/FSharp.Stats.Tests/Vector.fs | 16 ++++++++-------- 4 files changed, 26 insertions(+), 19 deletions(-) diff --git a/src/FSharp.Stats/AlgTypes/Vector.fs b/src/FSharp.Stats/AlgTypes/Vector.fs index d32954d85..4d99f727e 100644 --- a/src/FSharp.Stats/AlgTypes/Vector.fs +++ b/src/FSharp.Stats/AlgTypes/Vector.fs @@ -95,7 +95,8 @@ type Vector = static member inline addScalar<'T when 'T :> Numerics.INumber<'T> and 'T : (new: unit -> 'T) and 'T : struct - and 'T :> ValueType> (v:Vector<'T>) (scalar:'T) : Vector<'T> = + and 'T :> ValueType> + (scalar:'T) (v:Vector<'T>) : Vector<'T> = if Numerics.Vector.IsHardwareAccelerated then Acceleration.SIMDUtils.mapScalar (+) (+) v scalar @@ -110,7 +111,8 @@ type Vector = static member inline subtractScalar<'T when 'T :> Numerics.INumber<'T> and 'T : (new: unit -> 'T) and 'T : struct - and 'T :> ValueType> (v:Vector<'T>) (scalar:'T) : Vector<'T> = + and 'T :> ValueType> + (scalar:'T) (v:Vector<'T>) : Vector<'T> = if Numerics.Vector.IsHardwareAccelerated then Acceleration.SIMDUtils.mapScalar (-) (-) v scalar else @@ -124,7 +126,8 @@ type Vector = static member inline multiplyScalar<'T when 'T :> Numerics.INumber<'T> and 'T : (new: unit -> 'T) and 'T : struct - and 'T :> ValueType> (v:Vector<'T>) (scalar:'T) : Vector<'T> = + and 'T :> ValueType> + (scalar:'T) (v:Vector<'T>) : Vector<'T> = if Numerics.Vector.IsHardwareAccelerated then Acceleration.SIMDUtils.mapScalar ( * ) ( * ) v scalar @@ -139,7 +142,8 @@ type Vector = static member inline divideScalar<'T when 'T :> Numerics.INumber<'T> and 'T : (new: unit -> 'T) and 'T : struct - and 'T :> ValueType> (v:Vector<'T>) (scalar:'T) : Vector<'T> = + and 'T :> ValueType> + (scalar:'T) (v:Vector<'T>) : Vector<'T> = if Numerics.Vector.IsHardwareAccelerated then Acceleration.SIMDUtils.mapScalar ( / ) ( / ) v scalar diff --git a/src/FSharp.Stats/AlgTypes/VectorOps.fs b/src/FSharp.Stats/AlgTypes/VectorOps.fs index ab93bcd00..6ca4e458b 100644 --- a/src/FSharp.Stats/AlgTypes/VectorOps.fs +++ b/src/FSharp.Stats/AlgTypes/VectorOps.fs @@ -7,20 +7,21 @@ type VectorOps = static member inline Plus (a: Vector<'T>, b: Vector<'T>) = Vector.add a b - static member inline Plus (a: Vector<'T>, b: 'T) = Vector.addScalar a b - static member inline Plus (a: 'T, b: Vector<'T>) = Vector.addScalar b a + static member inline Plus (a: Vector<'T>, b: 'T) = Vector.addScalar b a + static member inline Plus (a: 'T, b: Vector<'T>) = Vector.addScalar a b static member inline Minus (a: Vector<'T>, b: Vector<'T>) = Vector.subtract a b - static member inline Minus (a: Vector<'T>, b: 'T) = Vector.subtractScalar a b + static member inline Minus (a: Vector<'T>, b: 'T) = Vector.subtractScalar b a static member inline Multiply (a: Vector<'T>, b: Vector<'T>) = Vector.multiply a b - static member inline Multiply (a: Vector<'T>, b: 'T) = Vector.multiplyScalar a b - static member inline Multiply (a: 'T, b: Vector<'T>) = Vector.multiplyScalar b a + static member inline Multiply (a: Vector<'T>, b: 'T) = Vector.multiplyScalar b a + static member inline Multiply (a: 'T, b: Vector<'T>) = Vector.multiplyScalar a b static member inline Divide (a: Vector<'T>, b: Vector<'T>) = Vector.divide a b - static member inline Divide (a: Vector<'T>, b: 'T) = Vector.divideScalar a b + static member inline Divide (a: Vector<'T>, b: 'T) = Vector.divideScalar b a + static member inline Power (a: Vector<'T>, power: 'T) = Vector.pow power a // Dispatcher types (Instance resolution) @@ -28,6 +29,7 @@ type Plus = static member inline Invoke (a: ^A, b: ^B) = ((^A or ^B or VectorOps type Minus = static member inline Invoke (a: ^A, b: ^B) = ((^A or ^B or VectorOps) : (static member Minus : ^A * ^B -> _)(a, b)) type Multiply = static member inline Invoke (a: ^A, b: ^B) = ((^A or ^B or VectorOps) : (static member Multiply : ^A * ^B -> _)(a, b)) type Divide = static member inline Invoke (a: ^A, b: ^B) = ((^A or ^B or VectorOps) : (static member Divide : ^A * ^B -> _)(a, b)) +type Power = static member inline Invoke (a: ^A, b: ^B) = ((^A or ^B or VectorOps) : (static member Power : ^A * ^B -> _)(a, b)) // Operators [] @@ -36,6 +38,7 @@ module VectorOpsSymbols = let inline (.-) a b = Minus.Invoke(a, b) let inline (.*) a b = Multiply.Invoke(a, b) let inline (./) a b = Divide.Invoke(a, b) + let inline (.^) a b = Power.Invoke(a, b) // Dot product ( @ ) diff --git a/src/FSharp.Stats/Algebra/LinearAlgebra.fs b/src/FSharp.Stats/Algebra/LinearAlgebra.fs index 7fe1807a6..9bf636a4b 100644 --- a/src/FSharp.Stats/Algebra/LinearAlgebra.fs +++ b/src/FSharp.Stats/Algebra/LinearAlgebra.fs @@ -69,7 +69,7 @@ type LinearAlgebra = let norm = Vector.norm v r.[j, j] <- norm - let qj = Vector.divideScalar v norm + let qj = Vector.divideScalar norm v qCols.[j] <- qj let qData = Array.zeroCreate (m * n) diff --git a/tests/FSharp.Stats.Tests/Vector.fs b/tests/FSharp.Stats.Tests/Vector.fs index 70cfa5713..5d6e313be 100644 --- a/tests/FSharp.Stats.Tests/Vector.fs +++ b/tests/FSharp.Stats.Tests/Vector.fs @@ -83,28 +83,28 @@ let vectorTests = testCase "addScalar: adds scalar to every element" <| fun _ -> let v = [| 1; 2; 3 |] let scalar = 5 - let result = Vector.addScalar v scalar + let result = Vector.addScalar scalar v let expected = [| 6; 7; 8 |] Expect.equal result expected "Should add the scalar to each element" testCase "subtractScalar: subtracts scalar from every element" <| fun _ -> let v = [| 1; 2; 3 |] let scalar = 1 - let result = Vector.subtractScalar v scalar + let result = Vector.subtractScalar scalar v let expected = [| 0; 1; 2 |] Expect.equal result expected "Should subtract the scalar from each element" testCase "multiplyScalar: multiplies scalar to every element" <| fun _ -> let v = [| 2; 4; 6 |] let scalar = 3 - let result = Vector.multiplyScalar v scalar + let result = Vector.multiplyScalar scalar v let expected = [| 6; 12; 18 |] Expect.equal result expected "Should multiply the scalar with each element" testCase "divideScalar: divides every element by scalar" <| fun _ -> let v = [| 10; 20; 30 |] let scalar = 10 - let result = Vector.divideScalar v scalar + let result = Vector.divideScalar scalar v let expected = [| 1; 2; 3 |] Expect.equal result expected "Should divide each element by the scalar" @@ -279,28 +279,28 @@ let vectorTests = testCase "addScalar: adds scalar to every float element" <| fun _ -> let v = [| 1.0; 2.0; 3.0 |] let scalar = 5.5 - let result = Vector.addScalar v scalar + let result = Vector.addScalar scalar v let expected = [| 6.5; 7.5; 8.5 |] Expect.equal result expected "Should add 5.5 to each element" testCase "subtractScalar: subtract scalar from every float element" <| fun _ -> let v = [| 1.0; 2.5; 3.75 |] let scalar = 1.25 - let result = Vector.subtractScalar v scalar + let result = Vector.subtractScalar scalar v let expected = [| -0.25; 1.25; 2.5 |] Expect.equal result expected "Should subtract 1.25 from each element" testCase "multiplyScalar: multiplies scalar with every float element" <| fun _ -> let v = [| 2.5; 4.0; 6.0 |] let scalar = 2.0 - let result = Vector.multiplyScalar v scalar + let result = Vector.multiplyScalar scalar v let expected = [| 5.0; 8.0; 12.0 |] Expect.equal result expected "Should multiply each element by 2.0" testCase "divideScalar: divides every float element by scalar" <| fun _ -> let v = [| 10.0; 20.0; 30.0 |] let scalar = 2.0 - let result = Vector.divideScalar v scalar + let result = Vector.divideScalar scalar v let expected = [| 5.0; 10.0; 15.0 |] Expect.equal result expected "Should divide each element by 2.0" From c1834e309593897a11e5284e6657b7a522008134 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20M=C3=BChlhaus?= Date: Thu, 24 Apr 2025 11:43:10 +0200 Subject: [PATCH 087/121] Add Gamma inverse CDF --- .../Distributions/Continuous/Gamma.fs | 62 +++++++++++++++---- .../DistributionsContinuous.fs | 47 ++++++++++++++ 2 files changed, 97 insertions(+), 12 deletions(-) diff --git a/src/FSharp.Stats/Distributions/Continuous/Gamma.fs b/src/FSharp.Stats/Distributions/Continuous/Gamma.fs index 852f8d8ce..b654725e2 100644 --- a/src/FSharp.Stats/Distributions/Continuous/Gamma.fs +++ b/src/FSharp.Stats/Distributions/Continuous/Gamma.fs @@ -189,19 +189,57 @@ type Gamma = else SpecialFunctions.Gamma.lowerIncompleteRegularized alpha (x / beta) - /// Computes the inverse cumulative distribution function (quantile function). - /// - /// - /// - /// - /// - /// - /// - /// - /// - static member InvCDF alpha beta x = + /// Inverse CDF (quantile function) for the Gamma(α, β) distribution. + /// + /// Uses numerical root-finding (bisection) to solve CDF(x) = p. + /// Requires Gamma.CDF(alpha, beta, x) to be defined. + /// + /// Shape parameter α (must be > 0). + /// Rate parameter β (must be > 0). + /// Cumulative probability in [0, 1]. + /// The quantile value x such that P(X ≤ x) = p. + static member InvCDF + (alpha: float) (beta: float) (p: float) : float = + Gamma.CheckParam alpha beta - failwithf "not implemented yet" + + // Trivial cases + if p = 0. then 0. + elif p = 1. then + inf + //'T.CreateTruncating(1e10) // simulate ∞ + + else + let tolerance = 1e-10//'T.CreateTruncating(1e-10) + let maxIter = 100 + let mutable low = 0. // 'T.Zero + let mutable high = 1. //'T.One + + // Increase high bound until CDF(high) > p + while SpecialFunctions.Gamma.lowerIncompleteRegularized alpha (high / beta) < p do + high <- high * 2. //'T.CreateTruncating(2.0) + + // Bisection loop + let mutable iter = 0 + let mutable result = 0. //'T.Zero + + while iter < maxIter do + let mid = (low + high) / 2. //'T.CreateTruncating(2.0) + let cdfMid = + SpecialFunctions.Gamma.lowerIncompleteRegularized alpha (mid / beta) + + if abs (cdfMid - p) < tolerance then + result <- mid + iter <- maxIter + elif cdfMid < p then + low <- mid + else + high <- mid + + iter <- iter + 1 + + result + /// Fits the underlying distribution to a given set of observations. static member Fit(observations:float[],?maxIter,?tolerance) = diff --git a/tests/FSharp.Stats.Tests/DistributionsContinuous.fs b/tests/FSharp.Stats.Tests/DistributionsContinuous.fs index 56f963b75..6dafe0baf 100644 --- a/tests/FSharp.Stats.Tests/DistributionsContinuous.fs +++ b/tests/FSharp.Stats.Tests/DistributionsContinuous.fs @@ -118,6 +118,53 @@ let GammaDistributionTests = "Gamma Distribution Fit" Expect.floatClose fittingAccuracy beta beta' "Gamma Distribution Fit" + + testList "Gamma.InvCDF tests" [ + + test "Gamma.InvCDF returns 0.0 for p=0.0" { + let alpha = 2.0 + let beta = 1.0 + let p = 0.0 + let x = Gamma.InvCDF alpha beta p + Expect.equal x 0.0 "Quantile at p=0 should be 0" + } + + test "Gamma.InvCDF returns ~∞ for p=1.0" { + let alpha = 2.0 + let beta = 1.0 + let p = 1.0 + let x = Gamma.InvCDF alpha beta p + Expect.isGreaterThan x 1e6 "Quantile at p=1 should be very large" + } + + test "Gamma.InvCDF round-trip at p=0.5" { + let alpha = 3.0 + let beta = 2.0 + let p = 0.5 + let x = Gamma.InvCDF alpha beta p + let p2 = Gamma.CDF alpha beta x + Expect.floatClose Accuracy.high p p2 "CDF(InvCDF(p)) ≈ p" + } + + test "Gamma.InvCDF round-trip at p=0.95" { + let alpha = 5.0 + let beta = 1.0 + let p = 0.95 + let x = Gamma.InvCDF alpha beta p + let p2 = Gamma.CDF alpha beta x + Expect.floatClose Accuracy.high p p2 "CDF(InvCDF(p)) ≈ p" + } + + test "Gamma.InvCDF round-trip at p=0.01" { + let alpha = 2.0 + let beta = 0.5 + let p = 0.01 + let x = Gamma.InvCDF alpha beta p + let p2 = Gamma.CDF alpha beta x + Expect.floatClose Accuracy.high p p2 "CDF(InvCDF(p)) ≈ p" + } + ] + ] From c536fb144c0921e800185df709bb9a814ef0891f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20M=C3=BChlhaus?= Date: Thu, 24 Apr 2025 11:43:35 +0200 Subject: [PATCH 088/121] Add sample from ChiSquared --- .../Distributions/Continuous/ChiSquared.fs | 53 ++++++++++++++----- src/FSharp.Stats/Playground.fsx | 6 +++ 2 files changed, 45 insertions(+), 14 deletions(-) diff --git a/src/FSharp.Stats/Distributions/Continuous/ChiSquared.fs b/src/FSharp.Stats/Distributions/Continuous/ChiSquared.fs index da9f09ef3..393c70c5d 100644 --- a/src/FSharp.Stats/Distributions/Continuous/ChiSquared.fs +++ b/src/FSharp.Stats/Distributions/Continuous/ChiSquared.fs @@ -66,6 +66,15 @@ type ChiSquared = static member StandardDeviation dof = ChiSquared.CheckParam dof sqrt (dof * 2.) + + /// Degrees of freedom (must be positive). + /// A sample from χ²(dof), interpreted as Gamma(dof/2, 2). + static member SampleUnchecked (dof: float) : float = + let alpha = dof / 2.0 + let beta = 1. / 2.0 + Gamma.SampleUnchecked alpha beta + + /// Produces a random sample using the current random number generator (from GetSampleGenerator()). /// /// @@ -76,8 +85,7 @@ type ChiSquared = /// static member Sample dof = ChiSquared.CheckParam dof - //rndgen.NextFloat() * (max - min) + min - raise (NotImplementedException()) + ChiSquared.SampleUnchecked dof /// Computes the probability density function. /// @@ -127,18 +135,14 @@ type ChiSquared = elif isNan x then nan else Gamma.lowerIncompleteRegularized (dof/2.) (x/2.) - /// Computes the inverse cumulative distribution function (quantile function). - /// - /// - /// - /// - /// - /// - /// - /// - static member InvCDF dof x = - ChiSquared.CheckParam dof - failwithf "InvCDF not implemented yet" + /// Computes the inverse CDF (quantile function). + /// Degrees of freedom. + /// The probability value in [0.0, 1.0]. + /// The quantile corresponding to the cumulative probability p. + static member InvCDF (dof: float) (p: float) : float = + let alpha = dof / 2.0 + let beta = 1. / 2.0 + Gamma.InvCDF alpha beta p /// Returns the support of the exponential distribution: [0, Positive Infinity). /// @@ -164,6 +168,27 @@ type ChiSquared = static member ToString dof = sprintf "ChiSquared(dof = %f)" dof + + /// Fits a Chi-squared distribution by method-of-moments from raw observations. + /// An array of observed values. + /// Optional weights. + /// Estimated degrees of freedom k. + static member inline Fit(observations: 'T[], ?weights: 'T[]) : 'T = + let mean = + match weights with + | None -> Array.average observations + | Some w -> Array.weightedMean w observations + // Mean = k ⇒ k = mean + mean + + /// Estimates the Chi-squared distribution from data. + /// An array of observed values. + /// Optional weights. + /// An initialized Chi-squared distribution with estimated k. + static member inline Estimate(observations: 'T[], ?weights: 'T[]) = + let k = ChiSquared.Fit(observations, ?weights = weights) + ChiSquared.Init k + /// Initializes a ChiSquared distribution /// /// diff --git a/src/FSharp.Stats/Playground.fsx b/src/FSharp.Stats/Playground.fsx index 89a1bf27f..c38b6e8d6 100644 --- a/src/FSharp.Stats/Playground.fsx +++ b/src/FSharp.Stats/Playground.fsx @@ -7,6 +7,12 @@ open FSharp.Stats open FSharp.Stats.Distributions //open Plotly.NET open FSharp.Stats.Algebra +open FSharp.Stats.Distributions.Continuous + +let alpha = 5.0 +let beta = 1.0 +let p = 0.95 +let x = Gamma.InvCDF alpha beta p From 791dc76ce5129e02c2d036aa33231b45c74238d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20M=C3=BChlhaus?= Date: Thu, 24 Apr 2025 12:15:07 +0200 Subject: [PATCH 089/121] Change Gamma.InvCDF using Newton-Raphson refinement --- .../Distributions/Continuous/Gamma.fs | 112 ++++++++++++------ src/FSharp.Stats/SpecialFunctions/Gamma.fs | 1 + 2 files changed, 77 insertions(+), 36 deletions(-) diff --git a/src/FSharp.Stats/Distributions/Continuous/Gamma.fs b/src/FSharp.Stats/Distributions/Continuous/Gamma.fs index b654725e2..b7770795f 100644 --- a/src/FSharp.Stats/Distributions/Continuous/Gamma.fs +++ b/src/FSharp.Stats/Distributions/Continuous/Gamma.fs @@ -191,54 +191,94 @@ type Gamma = /// Inverse CDF (quantile function) for the Gamma(α, β) distribution. /// - /// Uses numerical root-finding (bisection) to solve CDF(x) = p. - /// Requires Gamma.CDF(alpha, beta, x) to be defined. + /// Uses tail-recursive Newton-Raphson refinement /// /// Shape parameter α (must be > 0). /// Rate parameter β (must be > 0). /// Cumulative probability in [0, 1]. /// The quantile value x such that P(X ≤ x) = p. - static member InvCDF - (alpha: float) (beta: float) (p: float) : float = - + static member InvCDF(alpha: float) (beta: float) (p: float) : float = Gamma.CheckParam alpha beta - // Trivial cases + if p < 0.0 || p > 1.0 then failwith "p must be in [0, 1]" if p = 0. then 0. - elif p = 1. then - inf - //'T.CreateTruncating(1e10) // simulate ∞ - + elif p = 1. then Double.PositiveInfinity else - let tolerance = 1e-10//'T.CreateTruncating(1e-10) - let maxIter = 100 - let mutable low = 0. // 'T.Zero - let mutable high = 1. //'T.One - - // Increase high bound until CDF(high) > p - while SpecialFunctions.Gamma.lowerIncompleteRegularized alpha (high / beta) < p do - high <- high * 2. //'T.CreateTruncating(2.0) - - // Bisection loop - let mutable iter = 0 - let mutable result = 0. //'T.Zero - - while iter < maxIter do - let mid = (low + high) / 2. //'T.CreateTruncating(2.0) - let cdfMid = - SpecialFunctions.Gamma.lowerIncompleteRegularized alpha (mid / beta) - - if abs (cdfMid - p) < tolerance then - result <- mid - iter <- maxIter - elif cdfMid < p then - low <- mid + // Initial approximation using Wilson–Hilferty for alpha > 1 + let initialGuess = + if alpha > 1.0 then + let z = Normal.InvCDF 0. 1. p + let a = 1.0 / (9.0 * alpha) + let t = 1.0 - a + z * sqrt a + beta * alpha * t * t * t + else + let g = SpecialFunctions.Gamma.gamma alpha + beta * (g * p) ** (1.0 / alpha) + + // Recursive Newton-Raphson refinement + let rec refine x iter = + if iter >= 20 then x else - high <- mid + let fx = SpecialFunctions.Gamma.lowerIncompleteRegularized alpha (x / beta) - p + let dfx = Gamma.PDF alpha beta x + + if dfx = 0.0 then x + else + let dx = fx / dfx + let x' = x - dx + if abs dx < 1e-10 then x' + else refine x' (iter + 1) + + refine initialGuess 0 + + + //static member InvCDF + // (alpha: float) (beta: float) (p: float) : float = + + // Gamma.CheckParam alpha beta + + // // Trivial cases + // if p = 0. then 0. + // elif p = 1. then + // inf + // //'T.CreateTruncating(1e10) // simulate ∞ + + // else + // let tolerance = 1e-10//'T.CreateTruncating(1e-10) + // let maxIter = 100 + // let mutable low = 0. // 'T.Zero + // let mutable high = 1. //'T.One + + // // Increase high bound until CDF(high) > p + // while SpecialFunctions.Gamma.lowerIncompleteRegularized alpha (high / beta) < p do + // high <- high * 2. //'T.CreateTruncating(2.0) + + // // Bisection loop + // let mutable iter = 0 + // let mutable result = 0. //'T.Zero + + // while iter < maxIter do + // let mid = (low + high) / 2. //'T.CreateTruncating(2.0) + // let cdfMid = + // SpecialFunctions.Gamma.lowerIncompleteRegularized alpha (mid / beta) + + // if abs (cdfMid - p) < tolerance then + // result <- mid + // iter <- maxIter + // elif cdfMid < p then + // low <- mid + // else + // high <- mid + + // iter <- iter + 1 + + // result + + + + - iter <- iter + 1 - result /// Fits the underlying distribution to a given set of observations. diff --git a/src/FSharp.Stats/SpecialFunctions/Gamma.fs b/src/FSharp.Stats/SpecialFunctions/Gamma.fs index 91a7dd8ce..189af2aa9 100644 --- a/src/FSharp.Stats/SpecialFunctions/Gamma.fs +++ b/src/FSharp.Stats/SpecialFunctions/Gamma.fs @@ -60,6 +60,7 @@ module Gamma = /// /// The function input for approximating Γ(z) let gamma z = + //TODO: maybe rename in "complete" for consisteny match z with | z when (infinity.Equals(z)) -> infinity | z when ((-infinity).Equals(z)) -> nan From 6ac3745bc4bfeb90de6fd4b075a2734e997187b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20M=C3=BChlhaus?= Date: Sun, 27 Jul 2025 16:22:16 +0200 Subject: [PATCH 090/121] ADd ChiSquare contingency table --- src/FSharp.Stats/AlgTypes/GenericMath.fs | 5 +- src/FSharp.Stats/AlgTypes/SIMDUtils.fs | 41 +++ src/FSharp.Stats/AlgTypes/Vector.fs | 10 +- src/FSharp.Stats/Algebra/SVD.fs | 259 ++++++++++++++++++ src/FSharp.Stats/FSharp.Stats.fsproj | 2 + src/FSharp.Stats/Playground.fsx | 48 +++- src/FSharp.Stats/Table.fs | 158 +++++++++++ src/FSharp.Stats/Testing/ChiSquareTest.fs | 65 ++++- src/FSharp.Stats/Testing/ContingencyTable.fs | 247 +++++++++++++++++ .../FSharp.Stats.Tests.fsproj | 1 + tests/FSharp.Stats.Tests/SVD.fs | 205 ++++++++++++++ 11 files changed, 1030 insertions(+), 11 deletions(-) create mode 100644 src/FSharp.Stats/Table.fs create mode 100644 src/FSharp.Stats/Testing/ContingencyTable.fs create mode 100644 tests/FSharp.Stats.Tests/SVD.fs diff --git a/src/FSharp.Stats/AlgTypes/GenericMath.fs b/src/FSharp.Stats/AlgTypes/GenericMath.fs index 8ed65f3ef..0dea3c597 100644 --- a/src/FSharp.Stats/AlgTypes/GenericMath.fs +++ b/src/FSharp.Stats/AlgTypes/GenericMath.fs @@ -61,7 +61,10 @@ module GenericMath = let inline floor<'T when 'T :> Numerics.IFloatingPoint<'T>> (x: 'T) : 'T = 'T. Floor(x) - + /// Generic floor function + let inline epsilon<'T when 'T :> Numerics.IFloatingPoint<'T>> () : 'T = + 'T.CreateTruncating System.Double.Epsilon + // let inline min x y = if x < y then x else y // let inline max x y = if x > y then x else y diff --git a/src/FSharp.Stats/AlgTypes/SIMDUtils.fs b/src/FSharp.Stats/AlgTypes/SIMDUtils.fs index 54aabfeec..2d12c9d19 100644 --- a/src/FSharp.Stats/AlgTypes/SIMDUtils.fs +++ b/src/FSharp.Stats/AlgTypes/SIMDUtils.fs @@ -5,6 +5,9 @@ open System.Runtime.InteropServices open System.Runtime.CompilerServices + + + /// /// A utility class for performing SIMD (Single Instruction, Multiple Data) operations on arrays. /// @@ -155,6 +158,44 @@ type SIMDUtils() = results + static member inline mapFoldUnchecked<'T + when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T :> ValueType> + (fMapSimd: Numerics.Vector<'T> -> Numerics.Vector<'T>, + fMap: 'T -> 'T, + fReduceSimd: Numerics.Vector<'T> -> Numerics.Vector<'T> -> Numerics.Vector<'T>, + fReduceScalar: 'T -> 'T -> 'T, + zero: 'T, + input: ReadOnlySpan<'T>) + : 'T = + + let len = input.Length + let simdSize = Numerics.Vector<'T>.Count + let simdBlocks = len / simdSize + let tailStart = simdBlocks * simdSize + + // SIMD map + accumulation + let mutable accVec = Numerics.Vector<'T>(zero) + let inputVec = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(input) + + for i = 0 to simdBlocks - 1 do + let mapped = fMapSimd inputVec[i] + accVec <- fReduceSimd accVec mapped + + // Reduce SIMD accumulator to scalar + let mutable acc = accVec.[0] + for i = 1 to simdSize - 1 do + acc <- fReduceScalar acc accVec.[i] + + // Scalar tail + for i = tailStart to len - 1 do + acc <- fReduceScalar acc (fMap input[i]) + + acc + + type SIMDRangeUtils = diff --git a/src/FSharp.Stats/AlgTypes/Vector.fs b/src/FSharp.Stats/AlgTypes/Vector.fs index 4d99f727e..7107c5387 100644 --- a/src/FSharp.Stats/AlgTypes/Vector.fs +++ b/src/FSharp.Stats/AlgTypes/Vector.fs @@ -211,15 +211,17 @@ type Vector = let slotCount = length / slotSize let ceiling = slotSize * slotCount - let mutable result = Numerics.Vector<'T>.Zero let v1Span = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(v1.AsSpan()) let v2Span = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(v2.AsSpan()) - let mutable scalarResult = LanguagePrimitives.GenericZero<'T> + let mutable result = Numerics.Vector<'T>.Zero + //let mutable scalarResult = LanguagePrimitives.GenericZero<'T> for i = 0 to slotCount - 1 do result <- Numerics.Vector.Add(result, Numerics.Vector.Multiply(v1Span.[i], v2Span.[i])) - scalarResult <- Numerics.Vector.Sum result - + //scalarResult <- Numerics.Vector.Sum result + + let mutable scalarResult = Numerics.Vector.Sum result + for i = ceiling to v1.Length - 1 do scalarResult <- scalarResult + (v1.[i] * v2.[i]) diff --git a/src/FSharp.Stats/Algebra/SVD.fs b/src/FSharp.Stats/Algebra/SVD.fs index cbe44bcbd..820d025d1 100644 --- a/src/FSharp.Stats/Algebra/SVD.fs +++ b/src/FSharp.Stats/Algebra/SVD.fs @@ -1,6 +1,265 @@ namespace FSharp.Stats.Algebra + +open System open FSharp.Stats +open FSharp.Stats.Acceleration + +[] +type Householder<'T when 'T :> Numerics.INumber<'T>> = + { + V: Vector<'T> + Tau: 'T + Beta: 'T + } + + +type Householder() = + + static member inline create<'T when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T : comparison + and 'T :> ValueType + and 'T :> Numerics.IRootFunctions<'T>> + (x: Vector<'T>) : Householder<'T> = + + let xSpan = x.AsSpan() + let alpha = xSpan[0] + let tail = xSpan.Slice(1) + + let zero = GenericMath.zero<'T> + let one = GenericMath.one<'T> + + let sigma = + SIMDUtils.mapFoldUnchecked( + (fun v -> v * v), + (fun x -> x * x), + (+), + (+), + zero, + tail + ) + + if sigma.Equals(zero) then + let v = Vector.zeroCreate x.Length + v.[0] <- one + { + V = v + Tau = zero + Beta = alpha + } + else + let sum = alpha * alpha + sigma + let beta = GenericMath.sqrt sum + + let v0 = + if alpha <= zero then alpha - beta + else -sigma / (alpha + beta) + + let tau = + let v0Sq = v0 * v0 + (v0Sq + v0Sq) / (sigma + v0Sq) + + let v = Vector.divideScalar v0 x // SIMD-aware scalar division + v.[0] <- one + + { + V = v + Tau = tau + Beta = beta + } + + static member inline applyLeft<'T when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T : equality + and 'T :> ValueType> + (h: Householder<'T>, A: Matrix<'T>, rowOffset: int) = + + let v = h.V + let tau = h.Tau + let m = A.NumRows + let n = A.NumCols + let vLen = v.Length + + for j = 0 to n - 1 do + let mutable dot = GenericMath.zero<'T> + for i = 0 to vLen - 1 do + dot <- dot + v.[i] * A.[rowOffset + i, j] + let scale = tau * dot + for i = 0 to vLen - 1 do + A.[rowOffset + i, j] <- A.[rowOffset + i, j] - scale * v.[i] + + + static member inline applyRight<'T when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T : equality + and 'T :> ValueType> + (h: Householder<'T>, A: Matrix<'T>, colOffset: int) = + + let v = h.V + let tau = h.Tau + let m = A.NumRows + let vLen = v.Length + + for i = 0 to m - 1 do + let mutable dot = GenericMath.zero<'T> + for j = 0 to vLen - 1 do + dot <- dot + A.[i, colOffset + j] * v.[j] + let scale = tau * dot + for j = 0 to vLen - 1 do + A.[i, colOffset + j] <- A.[i, colOffset + j] - scale * v.[j] + +type Bidiagonalization() = + + static member inline bidiagonalizeInPlace<'T + when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T : comparison + and 'T :> ValueType + and 'T :> Numerics.IRootFunctions<'T>> + (A: Matrix<'T>) : unit = + + let m = A.NumCols + let n = A.NumRows + let minMN = min m n + + for k = 0 to minMN - 1 do + // --- LEFT REFLECTION: Column k (zero below diagonal) --- + let colLen = m - k + let colVector = Array.init colLen (fun i -> A.[k + i, k]) + let hLeft = Householder.create colVector + + Householder.applyLeft(hLeft, A, k) + + // Overwrite A[k..,k] with Householder beta at top and zeros below + A.[k, k] <- hLeft.Beta + for i = k + 1 to m - 1 do + A.[i, k] <- GenericMath.zero<'T> + + + + // --- RIGHT REFLECTION: Row k (zero right of superdiagonal) --- + if k < n - 1 then + let rowLen = n - (k + 1) + let rowVector = Array.init rowLen (fun j -> A.[k, k + 1 + j]) + let hRight = Householder.create rowVector + + Householder.applyRight(hRight, A, k + 1) + + // Overwrite A[k,k+1..] with Householder beta at front, zeros right + A.[k, k + 1] <- hRight.Beta + for j = k + 2 to n - 1 do + A.[k, j] <- GenericMath.zero<'T> + + +[] +type Bidiagonal<'T when 'T :> Numerics.INumber<'T>> = { + D : Vector<'T> // main diagonal + E : Vector<'T> // superdiagonal (length n-1) +} + + +/// Givens Rotation (Generic) +module Givens = + + let inline compute<'T + when 'T :> Numerics.INumber<'T> + and 'T : comparison + and 'T :> Numerics.IRootFunctions<'T> + and 'T :> Numerics.IFloatingPointIeee754<'T>> + (a: 'T) (b: 'T) : 'T * 'T = + + if b = GenericMath.zero then GenericMath.one, GenericMath.zero + elif GenericMath.abs b > GenericMath.abs a then + let t = a / b + let s = GenericMath.one / GenericMath.sqrt(GenericMath.one + t * t) + s * t, s + else + let t = b / a + let c = GenericMath.one / GenericMath.sqrt(GenericMath.one + t * t) + c, c * t + +module GolubKahan = + + let inline diagonalize<'T + when 'T :> Numerics.INumber<'T> + and 'T :> Numerics.IRootFunctions<'T> + and 'T :> Numerics.IFloatingPointIeee754<'T> + and 'T : comparison + and 'T : struct + and 'T : (new: unit -> 'T) + and 'T :> ValueType> + (b: Bidiagonal<'T>) : Vector<'T> = + + let d = Array.copy b.D + let e = Array.copy b.E + let n = d.Length + let eps = GenericMath.epsilon() + let two = GenericMath.one + GenericMath.one + + let mutable iter = 0 + let maxIter = 1000 + let mutable doneIterating = false + + + + while iter < maxIter && not doneIterating do + let mutable converged = true + + for i = 0 to n - 2 do + let tolerance = eps * (GenericMath.abs d.[i] + GenericMath.abs d.[i + 1]) + if abs e.[i] > tolerance then + converged <- false + + if converged then + doneIterating <- true + else + // Wilkinson shift + let m = n - 1 + let dm1 = d.[m - 1] + let dm = d.[m] + let em1 = e.[m - 1] + + let delta = (dm1 - dm) / two + let sign = + if delta >= GenericMath.zero then GenericMath.one + else -GenericMath.one + + let denom = abs delta + sqrt (delta * delta + em1 * em1) + let mu = dm - sign * (em1 * em1) / denom + + // Initial bulge + let mutable x = d.[0] * d.[0] - mu * mu + let mutable z = d.[0] * e.[0] + + for k = 0 to n - 2 do + let c, s = Givens.compute x z + + let dk = d.[k] + let ek = e.[k] + let dk1 = d.[k + 1] + + let tau1 = c * dk + s * ek + let tau2 = -s * dk1 + + d.[k] <- c * tau1 + s * tau2 + e.[k] <- c * ek - s * dk1 + d.[k + 1] <- s * tau1 - c * tau2 + + if k < n - 2 then + x <- e.[k] + z <- -s * e.[k + 1] + e.[k + 1] <- c * e.[k + 1] + + iter <- iter + 1 + + d + + module SVD = diff --git a/src/FSharp.Stats/FSharp.Stats.fsproj b/src/FSharp.Stats/FSharp.Stats.fsproj index 8ba72819e..580bef79e 100644 --- a/src/FSharp.Stats/FSharp.Stats.fsproj +++ b/src/FSharp.Stats/FSharp.Stats.fsproj @@ -56,6 +56,7 @@ + @@ -123,6 +124,7 @@ + diff --git a/src/FSharp.Stats/Playground.fsx b/src/FSharp.Stats/Playground.fsx index c38b6e8d6..884d62f9b 100644 --- a/src/FSharp.Stats/Playground.fsx +++ b/src/FSharp.Stats/Playground.fsx @@ -9,13 +9,59 @@ open FSharp.Stats.Distributions open FSharp.Stats.Algebra open FSharp.Stats.Distributions.Continuous +let d = [| 4.0; 3.0 |] +let e = [| 2.0 |] + +let bidiag = { + D = d + E = e +} + +let sigma = GolubKahan.diagonalize bidiag + + +let A = + matrix [| + [| 4.0; 1.0; 2.0 |] + [| 3.0; 1.0; 0.0 |] + [| 5.0; 1.0; 3.0 |] + |] + +// Extract column 0 +let colVector = [| A.[0, 0]; A.[1, 0]; A.[2, 0] |] +let h = Householder.create colVector + +// Overwrite A[0..,0] with [β; 0; 0] +A.[0, 0] <- h.Beta +for i = 1 to 2 do + A.[i, 0] <- 0.0 + +Householder.applyLeft(h, A, 0) + +A.[1, 0] + +//let input = +// matrix [| +// [| 1.0; 2.0; 3.0 |] +// [| 4.0; 5.0; 6.0 |] +// [| 7.0; 8.0; 9.0 |] +// |] + +//let A = input |> Matrix.copy + +//Bidiagonalization.bidiagonalizeInPlace A +//A + + + +// Apply reflector from the left to matrix A starting at row 0 + let alpha = 5.0 let beta = 1.0 let p = 0.95 let x = Gamma.InvCDF alpha beta p - let Categorical_SampleUnchecked (probabilities: float[]) = let rnd = Random.rndgen.NextFloat() let rec search i acc = diff --git a/src/FSharp.Stats/Table.fs b/src/FSharp.Stats/Table.fs new file mode 100644 index 000000000..793ac42e5 --- /dev/null +++ b/src/FSharp.Stats/Table.fs @@ -0,0 +1,158 @@ +namespace FSharp.Stats + + +open System +open FSharp.Stats + + +open System +open System.Collections.Generic +open System.Runtime.InteropServices +open System.Numerics +open System.Text + + +/// A general read-only 2D table abstraction. +type ITable<'R,'C,'T> = + /// All row labels (in order). + abstract RowKeys : 'R[] + /// All column labels (in order). + abstract ColKeys : 'C[] + /// Number of rows + abstract NumRows : int + /// Number of columns + abstract NumCols : int + /// Get the value at (rowLabel, colLabel) + abstract Get : rowLabel:'R * colLabel:'C -> 'T + /// Enumerate a single row as (colLabel * value) seq + abstract GetRow : rowLabel:'R -> seq<'C * 'T> + /// Enumerate a single column as (rowLabel * value) seq + abstract GetColumn : colLabel:'C -> seq<'R * 'T> + +/// A read/write extension (if you need mutability) +type ITableMutable<'R,'C,'T> = + inherit ITable<'R,'C,'T> + /// Set the value at (rowLabel, colLabel) + abstract Set : rowLabel:'R * colLabel:'C * value:'T -> unit + + + + + + + + +/// A 2D table with generic row‐labels and column‐labels, +/// backed by a flattened Matrix<'T> +type Table<'R,'C,'T + when 'R : comparison + and 'C : comparison + and 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T : equality + and 'T :> ValueType> + ( rowKeys : 'R[], + colKeys : 'C[], + dataMatrix : Matrix<'T> ) = + + // validate shapes + do + if rowKeys.Length <> dataMatrix.NumRows then + invalidArg "rowKeys" $"Length of rowKeys ({rowKeys.Length}) <> data.NumRows ({dataMatrix.NumRows})" + if colKeys.Length <> dataMatrix.NumCols then + invalidArg "colKeys" $"Length of colKeys ({colKeys.Length}) <> data.NumCols ({dataMatrix.NumCols})" + + // build fast lookup maps + let rowIndexMap = + rowKeys |> Array.mapi (fun i k -> k,i) |> dict<'R,int> + let colIndexMap = + colKeys |> Array.mapi (fun j k -> k,j) |> dict<'C,int> + + /// All row labels in order. + member _.RowKeys = rowKeys + + /// All column labels in order. + member _.ColKeys = colKeys + + /// Underlying matrix storage. + member _.DataMatrix = dataMatrix + + /// Underlying data storage. + member _.Data = dataMatrix.Data + + /// Number of rows. + member _.NumRows = rowKeys.Length + + /// Number of columns. + member _.NumCols = colKeys.Length + + /// Indexer by integer coordinates (0-based). + member this.Item + with get (i:int, j:int) = + dataMatrix.[i, j] + and set (i:int, j:int) (v:'T) = + dataMatrix.[i, j] <- v + + /// Indexer by label keys. + member this.Item + with get (r:'R, c:'C) = + let i = + match rowIndexMap.TryGetValue r with + | true, idx -> idx + | _ -> invalidArg "r" $"Invalid row label: {r}" + let j = + match colIndexMap.TryGetValue c with + | true, idx -> idx + | _ -> invalidArg "c" $"Invalid column label: {c}" + dataMatrix.[i, j] + and set (r:'R, c:'C) (v:'T) = + let i = + match rowIndexMap.TryGetValue r with + | true, idx -> idx + | _ -> invalidArg "r" $"Invalid row label: {r}" + let j = + match colIndexMap.TryGetValue c with + | true, idx -> idx + | _ -> invalidArg "c" $"Invalid column label: {c}" + dataMatrix.[i, j] <- v + + /// Slice out a row (as array of label * value). + member this.GetRow (r:'R) : ('C * 'T)[] = + // ToDo: leaverage the Matrix based Matrix.getRows for accelaration + let i = + match rowIndexMap.TryGetValue r with + | true, idx -> idx + | _ -> invalidArg "r" $"Invalid row label: {r}" + colKeys + |> Array.mapi (fun j c -> c, dataMatrix.[i,j]) + + /// Slice out a column (as array of label * value). + member this.GetColumn (c:'C) : ('R * 'T)[] = + let j = + match colIndexMap.TryGetValue c with + | true, idx -> idx + | _ -> invalidArg "c" $"Invalid column label: {c}" + rowKeys + |> Array.mapi (fun i r -> r, dataMatrix.[i,j]) + + /// Pretty‐print with headers and labels. + override this.ToString() = + let sb = StringBuilder() + + // Header row: blank corner + column keys + sb.Append("\t") |> ignore + for c in colKeys do + sb.Append(c.ToString()).Append("\t") |> ignore + sb.AppendLine() |> ignore + + // Each data row: row key + its values + for i in 0 .. this.NumRows - 1 do + let r = rowKeys.[i] + sb.Append(r.ToString()).Append("\t") |> ignore + for j in 0 .. this.NumCols - 1 do + sb.Append(dataMatrix.[i, j].ToString()).Append("\t") |> ignore + sb.AppendLine() |> ignore + + sb.ToString() + diff --git a/src/FSharp.Stats/Testing/ChiSquareTest.fs b/src/FSharp.Stats/Testing/ChiSquareTest.fs index 7d1db8c04..a701711df 100644 --- a/src/FSharp.Stats/Testing/ChiSquareTest.fs +++ b/src/FSharp.Stats/Testing/ChiSquareTest.fs @@ -1,5 +1,8 @@ namespace FSharp.Stats.Testing +open System +open FSharp.Stats + /// /// Two-Sample (Goodness-of-fit) Chi-Square Test (Upper Tail) @@ -31,14 +34,12 @@ /// /// /// -module ChiSquareTest = - - open System - open FSharp.Stats +type ChiSquareTest = + /// Computes the Chi-Square test /// n data points -> degrees of freedom = n - 1 - let compute (degreesOfFreedom:int) (expected:seq) (observed:seq) = + static member compute (degreesOfFreedom:int) (expected:seq) (observed:seq) = //let chechParams = // if expected |> Seq.exists (fun x -> abs x < 5.) then printfn "Warning: A value less than 5 is present in expected values. Results may not be correct!" // let sumEx = Seq.sum expected @@ -52,5 +53,59 @@ module ChiSquareTest = TestStatistics.createChiSquare chi2 (float degreesOfFreedom) + static member pearsonChiSquared (table:ContingencyTable<_,_>) = + 42. + + static member pearsonChiSquared (table:Contingency2x2<_,_>) = + let apply o e = + let diff = abs (o - e) + diff * diff / e + let a = table.A + let b = table.B + let c = table.C + let d = table.D + + let N = float (a + b + c + d) + let rowSums = [| float (a + b); float (c + d) |] + let colSums = [| float (a + c); float (b + d) |] + + // compute Σ (O – E)²/E (with Yates) + let chi2 = + [| for i in 0..1 do + for j in 0..1 do + let O = float table.[i,j] + let E = rowSums.[i] * colSums.[j] / N + yield apply O E |] + |> Array.sum + + let df = 1 // (2–1)*(2–1) + TestStatistics.createChiSquare chi2 (float df) + + + /// Pearson χ² test with **Yates’s continuity correction** (only for 2×2). + static member pearsonChiSquaredWithYates (table:Contingency2x2<_,_>) = + let applyYates o e = + let diff = abs (o - e) - 0.5 + diff * diff / e + + let a = table.A + let b = table.B + let c = table.C + let d = table.D + + let N = float (a + b + c + d) + let rowSums = [| float (a + b); float (c + d) |] + let colSums = [| float (a + c); float (b + d) |] + + // compute Σ (O – E)²/E (with Yates) + let chi2 = + [| for i in 0..1 do + for j in 0..1 do + let O = float table.[i,j] + let E = rowSums.[i] * colSums.[j] / N + yield applyYates O E |] + |> Array.sum + let df = 1 // (2–1)*(2–1) + TestStatistics.createChiSquare chi2 (float df) diff --git a/src/FSharp.Stats/Testing/ContingencyTable.fs b/src/FSharp.Stats/Testing/ContingencyTable.fs new file mode 100644 index 000000000..71a93608d --- /dev/null +++ b/src/FSharp.Stats/Testing/ContingencyTable.fs @@ -0,0 +1,247 @@ +namespace FSharp.Stats.Testing + +open System +open System.Collections.Generic +open FSharp.Stats + + +/// An estimate with its standard‐error uncertainty. +type UncertainValue = { + Estimate : float + Uncertainty : float +} + + +///// A contingency-specific interface on top of ITable<_,_,int> +//type IContingencyTable<'R,'C> = +// inherit ITable<'R,'C,int> +// /// Sum of counts in one row +// abstract RowTotal : 'R -> int +// /// Sum of counts in one column +// abstract ColumnTotal : 'C -> int +// /// Grand total +// abstract Total : unit -> int +// ///// Probability of a single cell (with uncertainty) +// //abstract ProbabilityOf : 'R * 'C -> UncertainValue + + +/// Alias: a contingency table is just a Table<'R,'C,int> +type ContingencyTable<'R,'C when 'R : comparison and 'C : comparison> = Table<'R,'C,int> + + +/// A strictly 2×2 contingency table with generic row and column labels. +type Contingency2x2<'R,'C when 'R : comparison and 'C : comparison> + ( rowKeys : 'R * 'R, + colKeys : 'C * 'C, + counts : int * int * int * int ) = + + let (r1, r2) = rowKeys + let (c1, c2) = colKeys + let (a, b, c, d) = counts + + do if a<0 || b<0 || c<0 || d<0 then + invalidArg "counts" "All cell counts must be non‐negative" + + /// First row label + member _.Row1 = r1 + /// Second row label + member _.Row2 = r2 + /// First column label + member _.Col1 = c1 + /// Second column label + member _.Col2 = c2 + + /// Cell a = (r1,c1) + member _.A = a + /// Cell b = (r1,c2) + member _.B = b + /// Cell c = (r2,c1) + member _.C = c + /// Cell d = (r2,c2) + member _.D = d + + /// Index by zero‐based coordinates 0..1 × 0..1 + member _.Item + with get(i,j) = + match i,j with + | 0,0 -> a | 0,1 -> b + | 1,0 -> c | 1,1 -> d + | _ -> invalidArg "i,j" "Indices must be 0 or 1" + + /// Index by labels + member this.Item + with get(row: 'R, col: 'C) = + match (row,col) with + | (x,y) when x = r1 && y = c1 -> a + | (x,y) when x = r1 && y = c2 -> b + | (x,y) when x = r2 && y = c1 -> c + | (x,y) when x = r2 && y = c2 -> d + | _ -> invalidArg "r,c" "Invalid row or column label" + + //interface IContingencyTable<'R,'C> with + // member _.RowKeys = [| r1; r2 |] + // member _.ColKeys = [| c1; c2 |] + // member _.NumRows = 2 + // member _.NumCols = 2 + // member this.Get(row,col) = this.[row,col] + // member this.GetRow(row) = [| c1, this.[row,c1]; c2, this.[row,c2] |] + // member this.GetColumn(col)= [| r1, this.[r1,col]; r2, this.[r2,col] |] + // member _.RowTotal(row) = if row = r1 then a+b else c+d + // member _.ColumnTotal(col)= if col = c1 then a+c else b+d + // member _.Total() = a + b + c + d + + /// Odds ratio = (a·d)/(b·c) + member _.OddsRatio() = + if b = 0 || c = 0 then + invalidOp "Cannot compute odds‐ratio with a zero cell in denominator." + float a * float d / (float b * float c) + + + +module Contingency = + + let create (rows: 'R []) (cols: 'C []) (data: int[]) : ContingencyTable<'R,'C> = + // validate shapes + if rows.Length * cols.Length <> data.Length then + invalidArg "data" $"Length of data ({data.Length}) does not match rows × cols ({rows.Length}×{cols.Length})" + // build the table + Table( rows, cols, Matrix(rows.Length, cols.Length, data) ) + + /// Create a zero‐filled table for the given row & column labels. + let zeroCreate (rows: 'R []) (cols: 'C []) : ContingencyTable<'R,'C> = + // zero‐filled flat data + let data = Matrix.zeroCreate rows.Length cols.Length + Table( rows, cols, data ) + + + /// Build a ContingencyTable<'R,'C> of counts from a sequence of category‐pairs. + let ofDataSeq + (rows: seq<'R>) + (cols: seq<'C>) + (data: seq<'R * 'C>) + : ContingencyTable<'R,'C> = + + // 1) Materialize the label sets + let rowKeys = rows |> Seq.distinct |> Seq.toArray + let colKeys = cols |> Seq.distinct |> Seq.toArray + + // 2) Start with all zeros + let table = zeroCreate rowKeys colKeys + + // 3) Tally each occurrence + for (r,c) in data do + let curr = table.[r,c] + table.[r, c] <- curr + 1 + + table + + /// Build from a 2D integer array (rows × columns), zero‐based. + /// Throws if any entry is negative. + let ofArray (data2d: int[,]) : ContingencyTable = + let numRows = data2d.GetLength 0 + let numCols = data2d.GetLength 1 + // flatten row-major + let flat = Array.zeroCreate (numRows * numCols) + for i in 0..numRows-1 do + for j in 0..numCols-1 do + let v = data2d.[i,j] + if v < 0 then + invalidArg "data2d" $"Negative entry at (%d{i},%d{j})" + flat.[i * numCols + j] <- v + let matrix = Matrix(numRows,numCols,flat) + Table( Array.init numRows id, Array.init numCols id, matrix ) + + /// Get the count in cell (r,c). Throws if (r,c) not a valid key. + let getCount (r:'R) (c:'C) (t:ContingencyTable<'R,'C>) = + t.[r, c] + + /// Set the count in (r,c) to a non‐negative value, returning a new table. + let setCount (r:'R) (c:'C) (value:int) (t:ContingencyTable<'R,'C>) = + if value < 0 then invalidArg "value" "Count must be ≥0" + // clone the flat array, update the one entry + let data' = Array.copy t.Data + // find the zero-based indices + let i = Array.findIndex ((=) r) t.RowKeys + let j = Array.findIndex ((=) c) t.ColKeys + data'.[i * t.NumCols + j] <- value + Table( t.RowKeys, t.ColKeys, Matrix(t.RowKeys.Length,t.ColKeys.Length, data') ) + + /// Increment cell (r,c) by 1. + let increment (r:'R) (c:'C) (t:ContingencyTable<'R,'C>) = + let old = getCount r c t + setCount r c (old + 1) t + + /// Decrement cell (r,c) by 1 (throws if it would go below zero). + let decrement (r:'R) (c:'C) (t:ContingencyTable<'R,'C>) = + let old = getCount r c t + if old < 1 then invalidOp "Cell count is already zero." + setCount r c (old - 1) t + + /// Sum of counts in a given row. + let rowTotal (r:'R) (t:ContingencyTable<'R,'C>) = + t.ColKeys |> Array.sumBy (fun c -> getCount r c t) + + /// Sum of counts in a given column. + let columnTotal (c:'C) (t:ContingencyTable<'R,'C>) = + t.RowKeys |> Array.sumBy (fun r -> getCount r c t) + + /// Total count in the whole table. + let total (t:ContingencyTable<'R,'C>) = + t.RowKeys |> Array.sumBy (fun r -> rowTotal r t) + + + /// Uncertainty = sqrt(p*(1-p)/N), binomial approximation. + let private uncertainty (p:float) (N:float) = + sqrt (p * (1.0 - p) / N) + + /// Probability of a single cell. + let probabilityOf (r:'R) (c:'C) (t:ContingencyTable<'R,'C>) : UncertainValue = + let n = float (getCount r c t) + let N = float (total t) + let p = n / N + { Estimate = p; Uncertainty = uncertainty p N } + + /// Probability of a row. + let probabilityOfRow (r:'R) (t:ContingencyTable<'R,'C>) : UncertainValue = + let n = float (rowTotal r t) + let N = float (total t) + let p = n / N + { Estimate = p; Uncertainty = uncertainty p N } + + /// Probability of a column. + let probabilityOfColumn (c:'C) (t:ContingencyTable<'R,'C>) : UncertainValue = + let n = float (columnTotal c t) + let N = float (total t) + let p = n / N + { Estimate = p; Uncertainty = uncertainty p N } + + /// Probability of row given column. + let probabilityRowGivenColumn (r:'R) (c:'C) (t:ContingencyTable<'R,'C>) : UncertainValue = + let nrc = float (getCount r c t) + let Nc = float (columnTotal c t) + let p = nrc / Nc + { Estimate = p; Uncertainty = uncertainty p Nc } + + /// Probability of column given row. + let probabilityColumnGivenRow (c:'C) (r:'R) (t:ContingencyTable<'R,'C>) : UncertainValue = + let nrc = float (getCount r c t) + let Nr = float (rowTotal r t) + let p = nrc / Nr + { Estimate = p; Uncertainty = uncertainty p Nr } + + /// Ensure it's 2×2; throws otherwise. + let ensure2x2 (t:ContingencyTable<'R,'C>) = + if t.NumRows <> 2 || t.NumCols <> 2 then + invalidArg "t" "ContingencyTable must be 2×2." + t + + let as2x2 (t: Table<'R,'C,int>) : Contingency2x2<'R,'C> = + if t.NumRows <> 2 || t.NumCols <> 2 then + invalidArg "t" "Must be 2×2" + let rkeys = t.RowKeys.[0], t.RowKeys.[1] + let ckeys = t.ColKeys.[0], t.ColKeys.[1] + let a = t.DataMatrix.[0,0] + let b = t.DataMatrix.[0,1] + let c = t.DataMatrix.[1,0] + let d = t.DataMatrix.[1,1] + Contingency2x2( rowKeys = rkeys, colKeys = ckeys, counts = (a,b,c,d)) \ No newline at end of file diff --git a/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj b/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj index 88f81e4bd..26f01cfc4 100644 --- a/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj +++ b/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj @@ -31,6 +31,7 @@ + diff --git a/tests/FSharp.Stats.Tests/SVD.fs b/tests/FSharp.Stats.Tests/SVD.fs new file mode 100644 index 000000000..c2b886af2 --- /dev/null +++ b/tests/FSharp.Stats.Tests/SVD.fs @@ -0,0 +1,205 @@ +module SVDTests + +open Expecto +open System +open FSharp.Stats +open FSharp.Stats.Algebra + +module MatrixUtils = + + let inline isApproxZero<'T when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T : comparison + and 'T :> ValueType> + (epsilon: 'T) (x: 'T) = + (GenericMath.abs x) < epsilon + + let inline isUpperBidiagonalWithTolerance<'T when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T : comparison + and 'T :> ValueType> + (epsilon: 'T) + (A: Matrix<'T>) : bool = + let m = A.NumCols + let n = A.NumRows + + let mutable ok = true + for i = 0 to m - 1 do + for j = 0 to n - 1 do + let onDiagonal = j = i + let onSuperDiagonal = j = i + 1 + let aij = A.[i, j] + if not (onDiagonal || onSuperDiagonal) && not (isApproxZero epsilon aij) then + ok <- false + ok + + +[] +let householderCreateTest = + test "Householder.create" { + let x = [| 4.0; 3.0; 0.0 |] + let h = Householder.create x + + let v = h.V + let tau = h.Tau + let n = v.Length + + // Compute Hx = (I - τ v vᵗ) x + // First: dot(v, x) + let dot = Vector.dot v x + + // Then: Hx = x - τ * dot * v + let hx = Array.init n (fun i -> x.[i] - tau * dot * v.[i]) + + // We expect: hx = [±||x||; 0; 0] + let norm = sqrt (Array.sumBy (fun xi -> xi * xi) x) + Expect.floatClose Accuracy.high hx.[0] norm "Should be equal (double precision)" + Expect.floatClose Accuracy.high hx.[1] 0.0 "Should be equal (double precision)" + Expect.floatClose Accuracy.high hx.[2] 0.0 "Should be equal (double precision)" + } + //test " zeroes out tail of vector" { + // Expect.floatClose Accuracy.high hx.[0] norm "Should be equal (double precision)" + //} + //test " zeroes out tail of vector" { + // Expect.floatClose Accuracy.high hx.[1] 0.0 "Should be equal (double precision)" + //} + //test " zeroes out tail of vector" { + // Expect.floatClose Accuracy.high hx.[2] 0.0 "Should be equal (double precision)" + //} + //] + +[] +let applyLeftTest = + test "Householder.applyLeft zeroes out subdiagonal column elements" { + // Define 3x3 test matrix + let A = + matrix [| + [| 4.0; 2.0; 1.0 |] + [| 3.0; 0.0; 0.0 |] + [| 0.0; 0.0; 0.0 |] + |] + + // Create Householder vector from column 0 (x = [4; 3; 0]) + let x = [| A.[0, 0]; A.[1, 0]; A.[2, 0] |] + let h = Householder.create x + + // Apply reflector from the left to matrix A starting at row 0 + Householder.applyLeft(h, A, 0) + + // Check: entries below A[0][0] should be zero + //let eps = 1e-10 + Expect.floatClose Accuracy.high A.[1, 0] 0.0 "Should be equal (double precision)" + Expect.floatClose Accuracy.high A.[2, 0] 0.0 "Should be equal (double precision)" + + // Optionally check the first value matches h.Beta + Expect.floatClose Accuracy.high A.[0, 0] h.Beta "Should be equal (double precision)" + } + +let applyRightTest = + test "Householder.applyRight zeroes out row tail elements" { + // Define 3x3 test matrix + let A = + matrix [| + [| 1.0; 4.0; 3.0 |] + [| 0.0; 0.0; 0.0 |] + [| 0.0; 0.0; 0.0 |] + |] + + // Take the row vector to the right of the diagonal: [4.0; 3.0] + let x = [| A.[0, 1]; A.[0, 2] |] + let h = Householder.create x + + // Apply the Householder from the right starting at column 1 + Householder.applyRight(h, A, 1) + + // Check that A[0].[2] is now approximately 0 + //let eps = 1e-10 + Expect.floatClose Accuracy.high A.[0, 2] 0.0 "Should be equal (double precision)" + + // Check that A[0].[1] is updated to h.Beta + Expect.floatClose Accuracy.high A.[0, 1] h.Beta "Should be equal (double precision)" + } + + +[] +let bidiagonalizationTest = + testList "bidiagonalization" [ + test "First step of bidiagonalization (applyLeft to column 0) works" { + // Full-rank 3x3 matrix + let A = + matrix [| + [| 4.0; 1.0; 2.0 |] + [| 3.0; 1.0; 0.0 |] + [| 5.0; 1.0; 3.0 |] + |] + + // Extract column 0 + let colVector = [| A.[0, 0]; A.[1, 0]; A.[2, 0] |] + let h = Householder.create colVector + + Householder.applyLeft(h, A, 0) + + // Overwrite A[0..,0] with [β; 0; 0] + A.[0, 0] <- h.Beta + for i = 1 to 2 do + A.[i, 0] <- 0.0 + + // Check column 0 + Expect.floatClose Accuracy.high A.[1, 0] 0.0 "Should be equal (double precision)" + Expect.floatClose Accuracy.high A.[2, 0] 0.0 "Should be equal (double precision)" + Expect.floatClose Accuracy.high A.[0, 0] h.Beta "Should be equal (double precision)" + } + + + + test "bidiagonalizeInPlace produces upper bidiagonal matrix" { + let input = + matrix [| + [| 1.0; 2.0; 3.0 |] + [| 4.0; 5.0; 6.0 |] + [| 7.0; 8.0; 9.0 |] + |] + + let A = input |> Matrix.copy + + Bidiagonalization.bidiagonalizeInPlace A + + let isBidiagonal = MatrixUtils.isUpperBidiagonalWithTolerance 1e-10 A + + Expect.isTrue isBidiagonal "Matrix should be upper bidiagonal after bidiagonalization" + } + ] + + +//[] +//let golubKahanTests = +// testList "Golub-Kahan Diagonalization" [ + +// test "Diagonalize 2x2 upper bidiagonal matrix" { +// // Construct bidiagonal: [ [4, 2]; [0, 3] ] +// let d = [| 4.0; 3.0 |] +// let e = [| 2.0 |] + +// let bidiag = { +// D = d +// E = e +// } + +// let sigma = GolubKahan.diagonalize bidiag + +// // Expected from NumPy SVD +// let expected = [| 4.74341649; 2.5355339 |] +// let eps = 1e-6 + +// // Compare sorted values (SVD is unordered) +// let actualSorted = Array.sortDescending sigma +// let expectedSorted = Array.sortDescending expected + +// for i in 0 .. expected.Length - 1 do +// Expect.floatClose Accuracy.high actualSorted.[i] expectedSorted.[i] $"Singular value {i} mismatch" +// } + +// // You can add more tests here for larger bidiagonal matrices or edge cases +// ] \ No newline at end of file From 6e7da1c14f6dd70b79363ce92d80dd9ff1722b27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20M=C3=BChlhaus?= Date: Mon, 28 Jul 2025 21:57:42 +0200 Subject: [PATCH 091/121] fix qrDecompose --- src/FSharp.Stats/AlgTypes/Householder.fs | 126 +++ src/FSharp.Stats/AlgTypes/Vector.fs | 2 + src/FSharp.Stats/AlgTypes/VectorExt.fs | 10 + src/FSharp.Stats/Algebra/LinearAlgebra.fs | 217 +++-- src/FSharp.Stats/Algebra/SVD.fs | 107 --- src/FSharp.Stats/FSharp.Stats.fsproj | 1 + src/FSharp.Stats/Fitting/Spline.fs | 2 +- src/FSharp.Stats/Playground.fsx | 743 +++++++++++++----- tests/FSharp.Stats.Tests/Acceleration.fs | 49 ++ .../FSharp.Stats.Tests.fsproj | 2 + tests/FSharp.Stats.Tests/LinearAlgebra.fs | 528 +++++++++++++ tests/FSharp.Stats.Tests/TestExtensions.fs | 7 + 12 files changed, 1457 insertions(+), 337 deletions(-) create mode 100644 src/FSharp.Stats/AlgTypes/Householder.fs create mode 100644 tests/FSharp.Stats.Tests/Acceleration.fs diff --git a/src/FSharp.Stats/AlgTypes/Householder.fs b/src/FSharp.Stats/AlgTypes/Householder.fs new file mode 100644 index 000000000..a68931fe6 --- /dev/null +++ b/src/FSharp.Stats/AlgTypes/Householder.fs @@ -0,0 +1,126 @@ +namespace FSharp.Stats.Algebra + + +open System +open FSharp.Stats +open FSharp.Stats.Acceleration + +[] +type Householder<'T when 'T :> Numerics.INumber<'T>> = + { + V: Vector<'T> + Tau: 'T + Beta: 'T + } + + +type Householder() = + + static member inline create<'T when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T : comparison + and 'T :> ValueType + and 'T :> Numerics.IRootFunctions<'T>> + (x: Vector<'T>) : Householder<'T> = + + let xSpan = x.AsSpan() + let alpha = xSpan[0] + let tail = xSpan.Slice(1) + + let zero = GenericMath.zero<'T> + let one = GenericMath.one<'T> + + let sigma = + SIMDUtils.mapFoldUnchecked( + (fun v -> v * v), + (fun x -> x * x), + (+), + (+), + zero, + tail + ) + + if sigma.Equals(zero) then + let v = Vector.zeroCreate x.Length + v.[0] <- one + { + V = v + Tau = zero + Beta = alpha + } + else + let sum = alpha * alpha + sigma + let beta = GenericMath.sqrt sum + + let v0 = + if alpha <= zero then alpha - beta + else -sigma / (alpha + beta) + + let tau = + let v0Sq = v0 * v0 + (v0Sq + v0Sq) / (sigma + v0Sq) + + let v = Vector.divideScalar v0 x // SIMD-aware scalar division + v.[0] <- one + + { + V = v + Tau = tau + Beta = beta + } + + static member inline applyLeft<'T when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T : equality + and 'T :> ValueType> + (h: Householder<'T>, A: Matrix<'T>, rowOffset: int) = + + let v = h.V + let tau = h.Tau + let m = A.NumRows + let n = A.NumCols + let vLen = v.Length + + //for j = 0 to n - 1 do + // let mutable dot = GenericMath.zero<'T> + // for i = 0 to vLen - 1 do + // dot <- dot + v.[i] * A.[rowOffset + i, j] + // let scale = tau * dot + // for i = 0 to vLen - 1 do + // A.[rowOffset + i, j] <- A.[rowOffset + i, j] - scale * v.[i] + + for j = 0 to n - 1 do + let mutable dot = GenericMath.zero<'T> + for i = 0 to vLen - 1 do + let row = rowOffset + i + if row < m then + dot <- dot + v.[i] * A.[row, j] + let scale = tau * dot + for i = 0 to vLen - 1 do + let row = rowOffset + i + if row < m then + A.[row, j] <- A.[row, j] - scale * v.[i] + + + static member inline applyRight<'T when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T : equality + and 'T :> ValueType> + (h: Householder<'T>, A: Matrix<'T>, colOffset: int) = + + let v = h.V + let tau = h.Tau + let m = A.NumRows + let vLen = v.Length + + for i = 0 to m - 1 do + let mutable dot = GenericMath.zero<'T> + for j = 0 to vLen - 1 do + dot <- dot + A.[i, colOffset + j] * v.[j] + let scale = tau * dot + for j = 0 to vLen - 1 do + A.[i, colOffset + j] <- A.[i, colOffset + j] - scale * v.[j] + diff --git a/src/FSharp.Stats/AlgTypes/Vector.fs b/src/FSharp.Stats/AlgTypes/Vector.fs index 7107c5387..5171c0a8b 100644 --- a/src/FSharp.Stats/AlgTypes/Vector.fs +++ b/src/FSharp.Stats/AlgTypes/Vector.fs @@ -6,6 +6,7 @@ open System.Runtime.InteropServices /// Vector as an array type alias type Vector<'T when 'T :> Numerics.INumber<'T>> = 'T [] + type Vector = @@ -23,6 +24,7 @@ type Vector = and 'T : struct and 'T :> ValueType> (v1 : Vector<'T>) (v2 : Vector<'T>) : Vector<'T> = + if v1.Length <> v2.Length then invalidArg "" "Cannot add two vectors of different dimensions." diff --git a/src/FSharp.Stats/AlgTypes/VectorExt.fs b/src/FSharp.Stats/AlgTypes/VectorExt.fs index e9a721997..3c72a6f84 100644 --- a/src/FSharp.Stats/AlgTypes/VectorExt.fs +++ b/src/FSharp.Stats/AlgTypes/VectorExt.fs @@ -214,3 +214,13 @@ module Vector = /// let inline pow (power: 'T) (v:Vector<'T>) : Vector<'T> = v |> Array.map (fun x -> GenericMath.pow x power) + + + /// Returns a subvector from offset i to the end of the vector. + let inline sub (i: int) (v: Vector<'T>) : Vector<'T> = + if i < 0 || i > v.Length then + invalidArg (nameof i) "Index out of bounds." + let len = v.Length - i + let res = Array.zeroCreate<'T> len + Array.blit v i res 0 len + res \ No newline at end of file diff --git a/src/FSharp.Stats/Algebra/LinearAlgebra.fs b/src/FSharp.Stats/Algebra/LinearAlgebra.fs index 9bf636a4b..9585ee434 100644 --- a/src/FSharp.Stats/Algebra/LinearAlgebra.fs +++ b/src/FSharp.Stats/Algebra/LinearAlgebra.fs @@ -28,18 +28,19 @@ type LinearAlgebra = Acceleration.SIMDRangeUtils.map2RangeInPlace fv f dstOffset srcOffset count dst src - static member inline householderTransform - (A: Matrix<'T>) (i: int) : Vector<'T> = - let n = A.NumRows - let v = Vector.zeroCreate<'T> n - let aCol = Matrix.getCol i A - let norm = Vector.norm aCol - v.[i] <- aCol.[i] + if aCol.[i] >= 'T.Zero then -norm else norm - for j = 0 to n - 1 do - if j <> i then - v.[j] <- aCol.[j] - v - + //static member inline householderTransform + // (A: Matrix<'T>) (i: int) : Vector<'T> = + // let n = A.NumRows + + // let v = Vector.zeroCreate<'T> n + // let aCol = Matrix.getCol i A + // let norm = Vector.norm aCol.[i..] // ToDO: use a more efficient norm calculation + // v.[i] <- aCol.[i] + if aCol.[i] >= 'T.Zero then norm else -norm + // for j = i + 1 to n - 1 do + // v.[j] <- aCol.[j] + // v + + /// QR decomposition using modified Gram-Schmidt /// Returns Q and R such that A = QR @@ -52,6 +53,10 @@ type LinearAlgebra = (A: Matrix<'T>) : Matrix<'T> * Matrix<'T> = let m, n = A.NumRows, A.NumCols + + if m < n then + invalidArg "A" $"QR decomposition via Modified Gram-Schmidt requires m ≥ n, but got {m}×{n} matrix." + let r = Matrix.zeroCreate n n let qCols: Vector<'T>[] = Array.zeroCreate n @@ -100,7 +105,10 @@ type LinearAlgebra = let mutable sum = y.[i] for j = i + 1 to n - 1 do sum <- sum - r.[i, j] * x.[j] - x.[i] <- sum / r.[i, i] + let diag = r.[i, i] + if diag = 'T.Zero then + invalidArg $"r[{i},{i}]" "Diagonal element is zero. Cannot divide." + x.[i] <- sum / diag x @@ -269,6 +277,8 @@ type LinearAlgebra = for j = 0 to i - 1 do s <- s - (Kdata.[rowOffset + j] * x.[j]) let diag = Kdata.[rowOffset + i] + if diag = 'T.Zero then + invalidArg $"K[{i},{i}]" "Diagonal element is zero. Cannot divide." x.[i] <- s / diag else // For i in [n-1..downto..0]: @@ -279,50 +289,119 @@ type LinearAlgebra = for j = i + 1 to nK - 1 do s <- s - (Kdata.[rowOffset + j] * x.[j]) let diag = Kdata.[rowOffset + i] + if diag = 'T.Zero then + invalidArg $"K[{i},{i}]" "Diagonal element is zero. Cannot divide." x.[i] <- s / diag x - /// QR decomposition using Householder reflections - static member inline qrDecompose (A : Matrix<'T>) : (Matrix<'T> * Matrix<'T>) = - // former QR - let UpdateQ (Q : Matrix<'T>) (v : Vector<'T>) = - let nQ, mQ = Q.NumRows, Q.NumCols - let n = v.Length - let Qv = Vector.zeroCreate<'T> nQ - for i = 0 to nQ - 1 do - // offset in Q.Data for row i is i*mQ - let rowOffset = i * mQ + (mQ - n) - // Dot the subrange Q[i, mQ-n..mQ-1] with v[0..n-1] - Qv.[i] <- Acceleration.SIMDRangeUtils.dotRange Q.Data rowOffset v 0 n + ///// QR decomposition using Householder reflections + //static member inline qrDecompose (A : Matrix<'T>) : (Matrix<'T> * Matrix<'T>) = + //// former QR + // let updateQ (Q : Matrix<'T>) (v : Vector<'T>) = + // let nQ, mQ = Q.NumRows, Q.NumCols + // let n = v.Length + // let Qv = Vector.zeroCreate<'T> nQ + // for i = 0 to nQ - 1 do + // // offset in Q.Data for row i is i*mQ + // let rowOffset = i * mQ + (mQ - n) + // // Dot the subrange Q[i, mQ-n..mQ-1] with v[0..n-1] + // Qv.[i] <- Acceleration.SIMDRangeUtils.dotRange Q.Data rowOffset v 0 n + + // // Update each row i in the subrange of columns [mQ-n..mQ-1] + // // Q[i, j] -= 2 * Qv[i] * v[j - (mQ - n)] + // for i = 0 to nQ - 1 do + // let alpha = Qv.[i] + Qv.[i] + // // We want to do a row operation: Q[i, (mQ-n)..(mQ-1)] + // // = Q[i, (mQ-n)..(mQ-1)] - alpha * v[0..n-1]. + // let rowOffset = i * mQ + (mQ - n) + // //LinearAlgebra.subScaledRowInPlace Q.Data rowOffset v 0 n alpha + // LinearAlgebra.subScaledRowInPlace alpha rowOffset 0 n Q.Data v + + // // TODO: Refector in Householder module + // let normalize (v: Vector<'T>) : Vector<'T> = + // let norm = Vector.norm v + // if norm = 'T.Zero then v + // else + // Array.map (fun x -> x / norm) v + + // let m, n = A.NumRows, A.NumCols + + // // Q starts as identity(n) + // let Q = Matrix.identity m + // let R = Matrix.copy A + + // for i = 0 to (min n m) - 1 do + // let x = [| for k in i .. m - 1 -> R.[k, i] |] + // //let a = Matrix.getCol i R + // let hh = Householder.create x //a.[i..] Create Householder reflector for column i + // let v = hh.V |> normalize + // updateQ Q v + // Householder.applyLeft(hh, R, i) - // Update each row i in the subrange of columns [mQ-n..mQ-1] - // Q[i, j] -= 2 * Qv[i] * v[j - (mQ - n)] - for i = 0 to nQ - 1 do - let alpha = Qv.[i] + Qv.[i] - // We want to do a row operation: Q[i, (mQ-n)..(mQ-1)] - // = Q[i, (mQ-n)..(mQ-1)] - alpha * v[0..n-1]. - let rowOffset = i * mQ + (mQ - n) - //LinearAlgebra.subScaledRowInPlace Q.Data rowOffset v 0 n alpha - LinearAlgebra.subScaledRowInPlace alpha rowOffset 0 n Q.Data v + // Q, R - let (n, m) = (A.NumRows, A.NumCols) + /// QR decomposition using Householder reflections + static member inline qrDecompose (A : Matrix<'T>) : (Matrix<'T> * Matrix<'T>) = + // former QR + + /// Compute normalized Householder vector from a subcolumn x + let householderVector (x: 'T[]) : 'T[] = + let norm = sqrt (Array.sumBy (fun xi -> xi * xi) x) + let v = Array.copy x + v.[0] <- v.[0] + (if x.[0] >= 'T.Zero then norm else -norm) + let norm_v = sqrt (Array.sumBy (fun vi -> vi * vi) v) + if norm_v = 'T.Zero then v + else Array.map (fun vi -> vi / norm_v) v + + /// Update Q: Q ← Q * Hᵢ using Householder vector v (from column i) + let updateQ (Q: Matrix<'T>) (v: 'T[]) (i: int) = + let nQ, mQ = Q.NumRows, Q.NumCols + for row = 0 to nQ - 1 do + let mutable dot = 'T.Zero + for k = 0 to v.Length - 1 do + dot <- dot + Q.[row, i + k] * v.[k] + let alpha = dot + dot + for k = 0 to v.Length - 1 do + Q.[row, i + k] <- Q.[row, i + k] - alpha * v.[k] + + /// Apply Hᵢ to R from the left: R ← H * R + let applyHouseholderLeft (R: Matrix<'T>) (v: 'T[]) (i: int) = + let m, n = R.NumRows, R.NumCols + for col = i to n - 1 do + let mutable dot = 'T.Zero + for k = 0 to v.Length - 1 do + let row = i + k + if row < m then + dot <- dot + v.[k] * R.[row, col] + let alpha = dot + dot + for k = 0 to v.Length - 1 do + let row = i + k + if row < m then + R.[row, col] <- R.[row, col] - alpha * v.[k] + + /// Main QR decomposition function + let qrDecompose (A: Matrix<'T>) : Matrix<'T> * Matrix<'T> = + let m, n = A.NumRows, A.NumCols + let Q = Matrix.identity m + let R = Matrix.copy A + + for i = 0 to min m n - 1 do + let x = [| for k in i .. m - 1 -> R.[k, i] |] + let v = householderVector x + updateQ Q v i + applyHouseholderLeft R v i + + Q, R + + qrDecompose A - // Q starts as identity(n) - let Q = Matrix.identity n - let R = Matrix.copy A - for i = 0 to (min n m) - 1 do - // 1) Compute Householder transform v for column i - let v = LinearAlgebra.householderTransform R i - // 2) Update Q - UpdateQ Q v - Q, R /// Given A[m,n] and B[m] solves AX = B for X[n].
/// When m => n, have over constrained system, finds least squares solution for X.
@@ -330,17 +409,46 @@ type LinearAlgebra = static member inline leastSquares (A : Matrix<'T>) (b: Vector<'T>) = - + // Maybe rename to leastSquaresQR? let (m,n) = A.NumRows, A.NumCols - let Qm, R = LinearAlgebra.qrDecompose A - let Qtb = Qm.Transpose() * b - + // Is this an overdetermined or underdetermined system? - if m > n then + if m >= n then + //printfn "Least squares: solving %dx%d system with %d equations." m n n + let Qm, R = LinearAlgebra.qrDecompose A + let Qtb = Qm.Transpose() * b LinearAlgebra.solveTriangularLinearSystem R.[0..n-1,0..n-1] Qtb.[0..n-1] false else - let s = LinearAlgebra.solveTriangularLinearSystem R.[0..m-1,0..m-1] Qtb false - Vector.init n (fun i -> if i < m then s.[i] else 'T.Zero) + // underdetermined: solve A^T * x = 0 with min ||x|| + //printfn "underdetermined- Least squares: solving %dx%d system with %d equations." m n n + let AT = A.Transpose() + let Q, R = LinearAlgebra.qrDecompose AT + let RT = R.Transpose() + let s = LinearAlgebra.solveTriangularLinearSystem RT.[0..m-1, 0..m-1] b true + Q.[0.., 0..m-1] * s + + //let AT = A.Transpose() + //let Q, R = LinearAlgebra.qrDecompose AT + //let y = Q.Transpose() * b + //let s = LinearAlgebra.solveTriangularLinearSystem R.[0..m-1, 0..m-1] y.[0..m-1] false + + //Q.[0..n,0..m] * s + + + + + //let AT = A.Transpose() + //let QT, RT = LinearAlgebra.qrDecompose AT + //let y = QT.Transpose() * b + //let s = LinearAlgebra.solveTriangularLinearSystem RT.[0..m-1, 0..m-1] y.[0..m-1] false + //let s = LinearAlgebra.solveTriangularLinearSystem R.[0..m-1,0..m-1] Qtb false + //Vector.init n (fun i -> if i < m then s.[i] else 'T.Zero) + + //// underdetermined: solve min ||x|| such that Ax = b + //let AT = A.Transpose() + //let QT, RT = LinearAlgebra.qrDecompose AT + //let y = LinearAlgebra.solveTriangularLinearSystem (RT.Transpose().[0..m-1, 0..m-1]) b false + //QT.[*, 0..m-1] * y /// @@ -398,13 +506,16 @@ type LinearAlgebra = (A : Matrix<'T>) (b: Vector<'T>) = + if b.Length <> A.NumRows then + invalidArg "b" "Length of b must match the number of rows of A." + let AT = A.Transpose() let upper = (AT * A) |> LinearAlgebra.cholesky let gamma = - LinearAlgebra.solveTriangularLinearSystem(upper.Transpose()) (AT * b) true + LinearAlgebra.solveTriangularLinearSystem(upper) (AT * b) true let beta = - LinearAlgebra.solveTriangularLinearSystem upper gamma false + LinearAlgebra.solveTriangularLinearSystem (upper.Transpose()) gamma false beta diff --git a/src/FSharp.Stats/Algebra/SVD.fs b/src/FSharp.Stats/Algebra/SVD.fs index 820d025d1..35a9408ea 100644 --- a/src/FSharp.Stats/Algebra/SVD.fs +++ b/src/FSharp.Stats/Algebra/SVD.fs @@ -5,113 +5,6 @@ open System open FSharp.Stats open FSharp.Stats.Acceleration -[] -type Householder<'T when 'T :> Numerics.INumber<'T>> = - { - V: Vector<'T> - Tau: 'T - Beta: 'T - } - - -type Householder() = - - static member inline create<'T when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T : comparison - and 'T :> ValueType - and 'T :> Numerics.IRootFunctions<'T>> - (x: Vector<'T>) : Householder<'T> = - - let xSpan = x.AsSpan() - let alpha = xSpan[0] - let tail = xSpan.Slice(1) - - let zero = GenericMath.zero<'T> - let one = GenericMath.one<'T> - - let sigma = - SIMDUtils.mapFoldUnchecked( - (fun v -> v * v), - (fun x -> x * x), - (+), - (+), - zero, - tail - ) - - if sigma.Equals(zero) then - let v = Vector.zeroCreate x.Length - v.[0] <- one - { - V = v - Tau = zero - Beta = alpha - } - else - let sum = alpha * alpha + sigma - let beta = GenericMath.sqrt sum - - let v0 = - if alpha <= zero then alpha - beta - else -sigma / (alpha + beta) - - let tau = - let v0Sq = v0 * v0 - (v0Sq + v0Sq) / (sigma + v0Sq) - - let v = Vector.divideScalar v0 x // SIMD-aware scalar division - v.[0] <- one - - { - V = v - Tau = tau - Beta = beta - } - - static member inline applyLeft<'T when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T : equality - and 'T :> ValueType> - (h: Householder<'T>, A: Matrix<'T>, rowOffset: int) = - - let v = h.V - let tau = h.Tau - let m = A.NumRows - let n = A.NumCols - let vLen = v.Length - - for j = 0 to n - 1 do - let mutable dot = GenericMath.zero<'T> - for i = 0 to vLen - 1 do - dot <- dot + v.[i] * A.[rowOffset + i, j] - let scale = tau * dot - for i = 0 to vLen - 1 do - A.[rowOffset + i, j] <- A.[rowOffset + i, j] - scale * v.[i] - - - static member inline applyRight<'T when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T : equality - and 'T :> ValueType> - (h: Householder<'T>, A: Matrix<'T>, colOffset: int) = - - let v = h.V - let tau = h.Tau - let m = A.NumRows - let vLen = v.Length - - for i = 0 to m - 1 do - let mutable dot = GenericMath.zero<'T> - for j = 0 to vLen - 1 do - dot <- dot + A.[i, colOffset + j] * v.[j] - let scale = tau * dot - for j = 0 to vLen - 1 do - A.[i, colOffset + j] <- A.[i, colOffset + j] - scale * v.[j] - type Bidiagonalization() = static member inline bidiagonalizeInPlace<'T diff --git a/src/FSharp.Stats/FSharp.Stats.fsproj b/src/FSharp.Stats/FSharp.Stats.fsproj index 580bef79e..db80f410f 100644 --- a/src/FSharp.Stats/FSharp.Stats.fsproj +++ b/src/FSharp.Stats/FSharp.Stats.fsproj @@ -37,6 +37,7 @@ + diff --git a/src/FSharp.Stats/Fitting/Spline.fs b/src/FSharp.Stats/Fitting/Spline.fs index 656793a10..7dbef668d 100644 --- a/src/FSharp.Stats/Fitting/Spline.fs +++ b/src/FSharp.Stats/Fitting/Spline.fs @@ -59,7 +59,7 @@ module Spline = // Construct the matrices we need let Bt = Matrix.init n' n (fun c r -> basis.[c] xdata.[r]) - let BtB = Bt * Bt.Transpose() + let BtB = Bt * (Bt.Transpose()) let penaltyFunc r c = let xi = xdata.[-2+min r c] let xj = xdata.[-2+max r c] diff --git a/src/FSharp.Stats/Playground.fsx b/src/FSharp.Stats/Playground.fsx index 884d62f9b..7eb5fbae0 100644 --- a/src/FSharp.Stats/Playground.fsx +++ b/src/FSharp.Stats/Playground.fsx @@ -9,220 +9,611 @@ open FSharp.Stats.Distributions open FSharp.Stats.Algebra open FSharp.Stats.Distributions.Continuous -let d = [| 4.0; 3.0 |] -let e = [| 2.0 |] +let canonicalizeQR (Q: Matrix, R: Matrix) = + let m, n = R.NumRows, R.NumCols + for j = 0 to min m n - 1 do + if R.[j, j] < 0.0 then + // Flip column j of Q + for i = 0 to Q.NumRows - 1 do + Q.[i, j] <- -Q.[i, j] + // Flip row j of R + for k = 0 to R.NumCols - 1 do + R.[j, k] <- -R.[j, k] + Q, R + +// TODO: Refector in Householder module +let normalize (v: Vector) : Vector = + let norm = Vector.norm v + if norm = 0. then v + else + Array.map (fun x -> x / norm) v + + +let leastSquares (A : Matrix) (b: Vector) = +// Maybe rename to leastSquaresQR? + let (m,n) = A.NumRows, A.NumCols + + // Is this an overdetermined or underdetermined system? + if m >= n then + //printfn "Least squares: solving %dx%d system with %d equations." m n n + let Qm, R = LinearAlgebra.qrDecompose A + let Qtb = Qm.Transpose() * b + LinearAlgebra.solveTriangularLinearSystem R.[0..n-1,0..n-1] Qtb.[0..n-1] false + + + else + // underdetermined: solve A^T * x = 0 with min ||x|| + let AT = A.Transpose() + let Q, R = LinearAlgebra.qrDecompose AT + let RT = R.Transpose() + let s = LinearAlgebra.solveTriangularLinearSystem RT.[0..m-1, 0..m-1] b true + Q.[0.., 0..m-1] * s + + + +let A = Matrix(2, 3, [| 1.0; 2.0; 0.0; + 0.0; 1.0; 1.0 |]) +let b = [| 3.0; 2.0 |] +let x = leastSquares A b + + + +let Q, R = LinearAlgebra.qrDecompose A +Q * R + +//let A = Matrix(2, 2, [| 2.0; 1.0; +// 1.0; 3.0 |]) +//let b = [| 5.0; 10.0 |] +//let x = LinearAlgebra.leastSquares A b +//let expected = [| 1.0; 3.0 |] + +//let Q, R = LinearAlgebra.qrDecompose A + + +//let A = Matrix(2, 2, [| 2.0; 1.0; +// 1.0; 3.0 |]) +//let Q, R = LinearAlgebra.qrDecompose A |> canonicalizeQR +//let QR = Q * R + + + + + + + +////let UpdateQ_Debug (Q : Matrix) (v : float[]) = +//// let nQ, mQ = Q.NumRows, Q.NumCols +//// let n = v.Length +//// let Qv = Array.zeroCreate nQ + +//// printfn "=== UpdateQ_Debug ===" +//// printfn "Input matrix Q:" +//// printfn "%A" Q +//// printfn "Householder vector v: [%s]" (String.Join("; ", v |> Array.map (fun x -> x.ToString("F3")))) + +//// // Step 1: Compute Qv = Q * v over trailing n columns +//// for i = 0 to nQ - 1 do +//// let rowOffset = i * mQ + (mQ - n) +//// let dot = Acceleration.SIMDRangeUtils.dotRange Q.Data rowOffset v 0 n +//// //let rowOffset = i * mQ + i +//// //let dot = Acceleration.SIMDRangeUtils.dotRange Q.Data rowOffset v 0 n +//// Qv.[i] <- dot +//// printfn $"Row {i}: dot(Q[{i}, {mQ-n}..], v) = {dot:F3}" + +//// // Step 2: Apply in-place update to Q +//// for i = 0 to nQ - 1 do +//// let alpha = 2.0 * Qv.[i] +//// let rowOffset = i * mQ + (mQ - n) +//// let tmp1 = (Q.Data.[rowOffset .. rowOffset + n - 1] |> Array.map (fun x -> x.ToString()) |> String.concat("; ")) +//// printfn $"Row {i}: alpha = 2 * {Qv.[i]:F3} = {alpha:F3}" +//// printfn $"Before update Q[{i}, {mQ-n}..]: [{tmp1}]" + + +//// LinearAlgebra.subScaledRowInPlace alpha rowOffset 0 (n - i) Q.Data v//alpha rowOffset 0 n Q.Data v +//// let tmp2 = (Q.Data.[rowOffset .. rowOffset + n - 1] |> Array.map (fun x -> x.ToString()) |> String.concat("; ")) +//// printfn $"After update Q[{i}, {mQ-n}..]: [{tmp2}]" + + +//// printfn "Updated Q matrix:" +//// printfn "%A" (Q) +//// printfn "=== End UpdateQ_Debug ===" + + + +////let applyHouseholderLeft (R: Matrix<'T>) (v: Vector<'T>) (i: int) = +//// let m, n = R.NumRows, R.NumCols +//// let nV = v.Length + +//// for col = i to n - 1 do +//// // Compute projection of column onto v +//// let mutable dot = LanguagePrimitives.GenericZero<'T> +//// for k = 0 to nV - 1 do +//// let row = i + k +//// if row < m then +//// dot <- dot + v.[k] * R.[row, col] + +//// let alpha = dot + dot + +//// // Update R[i.., col] +//// for k = 0 to nV - 1 do +//// let row = i + k +//// if row < m then +//// R.[row, col] <- R.[row, col] - alpha * v.[k] + +///// Apply Householder reflector from the left: R ← H * R +///// Only modifies the submatrix R[i.., i..] +//let applyHouseholderLeft (R: Matrix) (v: Vector) (i: int) = +// let m, n = R.NumRows, R.NumCols +// let nV = v.Length + +// for col = i to n - 1 do +// // Compute dot product: vᵗ * R[i.., col] +// let mutable dot = 0.0 +// for k = 0 to nV - 1 do +// let row = i + k +// if row < m then +// dot <- dot + v.[k] * R.[row, col] + +// let alpha = 2.0 * dot -let bidiag = { - D = d - E = e -} +// // Apply reflection to R[i.., col] +// for k = 0 to nV - 1 do +// let row = i + k +// if row < m then +// R.[row, col] <- R.[row, col] - alpha * v.[k] + + + +//let UpdateQ_Debug (Q : Matrix<'T>) (v : Vector<'T>) = +// let nQ, mQ = Q.NumRows, Q.NumCols +// let n = v.Length // Length of Householder vector +// let i = mQ - n // Starting column (pivot position) +// let Qv = Vector.zeroCreate<'T> nQ // Holds dot products for each row + +// // Compute Qv[i] = Q[i, i..] ⋅ v +// for row = 0 to nQ - 1 do +// let rowOffset = row * mQ + i +// Qv.[row] <- Acceleration.SIMDRangeUtils.dotRange Q.Data rowOffset v 0 n + +// // Apply the Householder update to the trailing part of each row +// for row = 0 to nQ - 1 do +// let alpha = Qv.[row] + Qv.[row] // 2 * dot product +// let rowOffset = row * mQ + i +// LinearAlgebra.subScaledRowInPlace alpha rowOffset 0 n Q.Data v + + + + +//type Testing() = +// /// QR decomposition using Householder reflections +// static member inline qrDecompose (A : Matrix<'T>) : (Matrix<'T> * Matrix<'T>) = +// // former QR +// let UpdateQ (Q : Matrix<'T>) (v : Vector<'T>) = +// let nQ, mQ = Q.NumRows, Q.NumCols +// let n = v.Length +// let Qv = Vector.zeroCreate<'T> nQ +// for i = 0 to nQ - 1 do +// // offset in Q.Data for row i is i*mQ +// let rowOffset = i * mQ + (mQ - n) +// // Dot the subrange Q[i, mQ-n..mQ-1] with v[0..n-1] +// Qv.[i] <- Acceleration.SIMDRangeUtils.dotRange Q.Data rowOffset v 0 n + +// // Update each row i in the subrange of columns [mQ-n..mQ-1] +// // Q[i, j] -= 2 * Qv[i] * v[j - (mQ - n)] +// for i = 0 to nQ - 1 do +// let alpha = Qv.[i] + Qv.[i] +// // We want to do a row operation: Q[i, (mQ-n)..(mQ-1)] +// // = Q[i, (mQ-n)..(mQ-1)] - alpha * v[0..n-1]. +// let rowOffset = i * mQ + (mQ - n) +// //LinearAlgebra.subScaledRowInPlace Q.Data rowOffset v 0 n alpha +// LinearAlgebra.subScaledRowInPlace alpha rowOffset 0 n Q.Data v + +// let normalize (v: Vector<'T>) : Vector<'T> = +// let norm = Vector.norm v +// if norm = 'T.Zero then +// invalidArg "v" "Cannot normalize a zero vector." +// Array.map (fun x -> x / norm) v + +// let (n, m) = (A.NumRows, A.NumCols) + +// // Q starts as identity(n) +// let Q = Matrix.identity n +// let R = Matrix.copy A + +// for i = 0 to (min n m) - 1 do +// // 1) Compute Householder transform v for column i +// let v = LinearAlgebra.householderTransform R i |> normalize +// // 2) Update Q +// UpdateQ Q v +// applyHouseholderLeft R v i + +// Q, R + + +// //static member inline householderTransform +// // (A: Matrix<'T>) (i: int) : Vector<'T> = +// // let n = A.NumRows + +// // let v = Vector.zeroCreate<'T> n +// // let aCol = Matrix.getCol i A +// // let norm = Vector.norm aCol // ToDO: use a more efficient norm calculation +// // v.[i] <- aCol.[i] + if aCol.[i] >= 'T.Zero then norm else -norm +// // for j = i + 1 to n - 1 do +// // v.[j] <- aCol.[j] +// // v + + +////let Q :Matrix = Matrix.identity 3 +////let v = [| 1.0; 2.0; 3.0 |] +////UpdateQ Q v + +////Q = +////[[ 1.073 -2.0 -2.0 ] +//// [ 1.464 -1.0 -2.0 ] +//// [ 1.464 -2.0 -1.0 ]] + +//module Testing = + +// open System + +// /// Compute normalized Householder vector from a subcolumn x +// let householderVector (x: float[]) : float[] = +// let norm = sqrt (Array.sumBy (fun xi -> xi * xi) x) +// let v = Array.copy x +// v.[0] <- v.[0] + (if x.[0] >= 0.0 then norm else -norm) +// let norm_v = sqrt (Array.sumBy (fun vi -> vi * vi) v) +// if norm_v = 0.0 then v +// else Array.map (fun vi -> vi / norm_v) v + +// let householderTransform +// (A: Matrix) (i: int) : Vector = +// let n = A.NumRows + +// let aCol = Matrix.getCol i A +// let v = aCol[i..] +// let norm = Vector.norm v // ToDO: use a more efficient norm calculation +// v.[0] <- v.[0] + (if v.[0] >= 0. then norm else -norm) +// v + +// let normalize (v: Vector) : Vector = +// let norm = Vector.norm v +// if norm = 0. then v +// else +// Array.map (fun x -> x / norm) v + +// /// Update Q: Q ← Q * Hᵢ using Householder vector v (from column i) +// let updateQ (Q: Matrix) (v: float[]) (i: int) = +// let nQ, mQ = Q.NumRows, Q.NumCols +// for row = 0 to nQ - 1 do +// let mutable dot = 0.0 +// for k = 0 to v.Length - 1 do +// dot <- dot + Q.[row, i + k] * v.[k] +// let alpha = 2.0 * dot +// for k = 0 to v.Length - 1 do +// Q.[row, i + k] <- Q.[row, i + k] - alpha * v.[k] + + +// let update_Q (Q : Matrix<'T>) (v : Vector<'T>) = +// let nQ, mQ = Q.NumRows, Q.NumCols +// let n = v.Length +// let Qv = Vector.zeroCreate<'T> nQ +// for i = 0 to nQ - 1 do +// // offset in Q.Data for row i is i*mQ +// let rowOffset = i * mQ + (mQ - n) +// // Dot the subrange Q[i, mQ-n..mQ-1] with v[0..n-1] +// Qv.[i] <- Acceleration.SIMDRangeUtils.dotRange Q.Data rowOffset v 0 n + +// // Update each row i in the subrange of columns [mQ-n..mQ-1] +// // Q[i, j] -= 2 * Qv[i] * v[j - (mQ - n)] +// for i = 0 to nQ - 1 do +// let alpha = Qv.[i] + Qv.[i] +// // We want to do a row operation: Q[i, (mQ-n)..(mQ-1)] +// // = Q[i, (mQ-n)..(mQ-1)] - alpha * v[0..n-1]. +// let rowOffset = i * mQ + (mQ - n) +// //LinearAlgebra.subScaledRowInPlace Q.Data rowOffset v 0 n alpha +// LinearAlgebra.subScaledRowInPlace alpha rowOffset 0 n Q.Data v + +// /// Apply Hᵢ to R from the left: R ← H * R +// let applyHouseholderLeft (R: Matrix) (v: float[]) (i: int) = +// let m, n = R.NumRows, R.NumCols +// for col = i to n - 1 do +// let mutable dot = 0.0 +// for k = 0 to v.Length - 1 do +// let row = i + k +// if row < m then +// dot <- dot + v.[k] * R.[row, col] +// let alpha = 2.0 * dot +// for k = 0 to v.Length - 1 do +// let row = i + k +// if row < m then +// R.[row, col] <- R.[row, col] - alpha * v.[k] + + + + +// /// Main QR decomposition function +// let qrDecompose (A: Matrix) : Matrix * Matrix = +// let m, n = A.NumRows, A.NumCols +// let Q = Matrix.identity m +// let R = Matrix.copy A + +// for i = 0 to n - 1 do +// //let x = [| for k in i .. m - 1 -> R.[k, i] |] +// let x = Matrix.getCol i R +// let hh = Householder.create x.[i..] // Create Householder reflector for column i +// let v = hh.V |> normalize +// //let v = householderTransform R i |> normalize // householderVector x +// update_Q Q v +// //applyHouseholderLeft R v i +// Householder.applyLeft(hh, R, i) + +// Q, R + + + +//let A = Matrix(3, 2, [| 1.0; 1.0; +// 1.0; 2.0; +// 1.0; 3.0 |]) +//let Q, R = Testing.qrDecompose A + +//let QR = Matrix.matmul Q R + +//let t:Vector = Matrix.getCol 1 A +//t.[0] <- nan + +//let i = 1 +//let m, n = A.NumRows, A.NumCols +//[| for k in i .. m - 1 -> A.[k, i] |] + +//let v = Testing.householderTransform A 0 |> normalize + +//Vector.norm v + +//let H = +// let n = v.Length +// let I : Matrix = Matrix.identity n +// let outer = Matrix.init n n (fun i j -> v.[i] * v.[j]) +// I - (outer * 2.0) +// (outer * 2.0) -let sigma = GolubKahan.diagonalize bidiag +//let R1 = Matrix.matmul H A +//let (n, m) = (A.NumRows, A.NumCols) -let A = - matrix [| - [| 4.0; 1.0; 2.0 |] - [| 3.0; 1.0; 0.0 |] - [| 5.0; 1.0; 3.0 |] - |] +//let Q : Matrix = Matrix.identity n +//let R = Matrix.copy A +//UpdateQ_Debug Q v +//applyHouseholderLeft R v 0 -// Extract column 0 -let colVector = [| A.[0, 0]; A.[1, 0]; A.[2, 0] |] -let h = Householder.create colVector -// Overwrite A[0..,0] with [β; 0; 0] -A.[0, 0] <- h.Beta -for i = 1 to 2 do - A.[i, 0] <- 0.0 -Householder.applyLeft(h, A, 0) -A.[1, 0] -//let input = + +//let Q : Matrix = Matrix.identity 3 +//let v = [| 1.0; 2.0; 3.0 |] +//UpdateQ_Debug Q v + +//let A = Matrix(3, 2, [| 1.0; 1.0; +// 1.0; 2.0; +// 1.0; 3.0 |]) + +//let v = LinearAlgebra.householderTransform A 1 + +//let d = [| 4.0; 3.0 |] +//let e = [| 2.0 |] + +//let bidiag = { +// D = d +// E = e +//} + +//let sigma = GolubKahan.diagonalize bidiag + + +//let A = // matrix [| -// [| 1.0; 2.0; 3.0 |] -// [| 4.0; 5.0; 6.0 |] -// [| 7.0; 8.0; 9.0 |] +// [| 4.0; 1.0; 2.0 |] +// [| 3.0; 1.0; 0.0 |] +// [| 5.0; 1.0; 3.0 |] // |] -//let A = input |> Matrix.copy +//// Extract column 0 +//let colVector = [| A.[0, 0]; A.[1, 0]; A.[2, 0] |] +//let h = Householder.create colVector -//Bidiagonalization.bidiagonalizeInPlace A -//A +//// Overwrite A[0..,0] with [β; 0; 0] +//A.[0, 0] <- h.Beta +//for i = 1 to 2 do +// A.[i, 0] <- 0.0 +//Householder.applyLeft(h, A, 0) +//A.[1, 0] -// Apply reflector from the left to matrix A starting at row 0 +////let input = +//// matrix [| +//// [| 1.0; 2.0; 3.0 |] +//// [| 4.0; 5.0; 6.0 |] +//// [| 7.0; 8.0; 9.0 |] +//// |] -let alpha = 5.0 -let beta = 1.0 -let p = 0.95 -let x = Gamma.InvCDF alpha beta p +////let A = input |> Matrix.copy +////Bidiagonalization.bidiagonalizeInPlace A +////A -let Categorical_SampleUnchecked (probabilities: float[]) = - let rnd = Random.rndgen.NextFloat() - let rec search i acc = - if i >= probabilities.Length then probabilities.Length - 1 - elif acc + probabilities[i] >= rnd then i - else search (i + 1) (acc + probabilities[i]) - search 0 0.0 +//// Apply reflector from the left to matrix A starting at row 0 +//let alpha = 5.0 +//let beta = 1.0 +//let p = 0.95 +//let x = Gamma.InvCDF alpha beta p -/// Helper function to sample many times and collect counts. -let sampleMany (times: int) (probabilities: float[]) = - let counts = Array.zeroCreate probabilities.Length - for _ in 1 .. times do - let idx = Categorical_SampleUnchecked probabilities - counts.[idx] <- counts.[idx] + 1 - counts +//let Categorical_SampleUnchecked (probabilities: float[]) = +// let rnd = Random.rndgen.NextFloat() +// let rec search i acc = +// if i >= probabilities.Length then probabilities.Length - 1 +// elif acc + probabilities[i] >= rnd then i +// else search (i + 1) (acc + probabilities[i]) +// search 0 0.0 -let p = [| 0.2; 0.3; 0.5 |] -let iterations = 10000000 -Array.init iterations (fun _ -> Categorical_SampleUnchecked p) -|> Array.countBy id +///// Helper function to sample many times and collect counts. +//let sampleMany (times: int) (probabilities: float[]) = +// let counts = Array.zeroCreate probabilities.Length +// for _ in 1 .. times do +// let idx = Categorical_SampleUnchecked probabilities +// counts.[idx] <- counts.[idx] + 1 +// counts -// Act -let counts = sampleMany iterations p -float counts.[2] / float iterations +//let p = [| 0.2; 0.3; 0.5 |] +//let iterations = 10000000 -// Assert -// All indices should be between 0 and p.Length - 1 -// If out of range, an exception would occur while incrementing counts. -// So, if we got this far without an exception, the function is generating valid indices. -// We can add an extra check that the sum of counts equals 'iterations'. -let total = Array.sum counts +//Array.init iterations (fun _ -> Categorical_SampleUnchecked p) +//|> Array.countBy id -let SampleUnchecked (p : float[]) n = - //let cp = Discrete.Multinomial.ProbabilityMassToCumulativeDistribution p - let ret = Array.zeroCreate p.Length - for _ = 1 to n do - let idx = Discrete.Categorical.SampleUnchecked p - ret[idx] <- ret[idx] + 1 - ret -let n = 100000 // Large n to reduce variance -let probabilities = [| 0.2; 0.3; 0.5 |] //// Act -//let sampleCounts = Categorical_SampleUnchecked probabilities - -//probabilities -//|> Array.iteri (fun i p -> -// let observedProportion = float sampleCounts.[i] / float n -// printfn $"Probability of {i}: {p}, Observed proportion: {observedProportion}") +//let counts = sampleMany iterations p +//float counts.[2] / float iterations + + +//// Assert +//// All indices should be between 0 and p.Length - 1 +//// If out of range, an exception would occur while incrementing counts. +//// So, if we got this far without an exception, the function is generating valid indices. +//// We can add an extra check that the sum of counts equals 'iterations'. +//let total = Array.sum counts + + +//let SampleUnchecked (p : float[]) n = +// //let cp = Discrete.Multinomial.ProbabilityMassToCumulativeDistribution p +// let ret = Array.zeroCreate p.Length +// for _ = 1 to n do +// let idx = Discrete.Categorical.SampleUnchecked p +// ret[idx] <- ret[idx] + 1 +// ret + +//let n = 100000 // Large n to reduce variance +//let probabilities = [| 0.2; 0.3; 0.5 |] +////// Act +////let sampleCounts = Categorical_SampleUnchecked probabilities + +////probabilities +////|> Array.iteri (fun i p -> +//// let observedProportion = float sampleCounts.[i] / float n +//// printfn $"Probability of {i}: {p}, Observed proportion: {observedProportion}") + + + +////let n = 100000 // Larger n to reduce sampling variance +//let sample = SampleUnchecked probabilities n + +//let () = +// probabilities +// |> Array.iteri (fun i p -> +// let observedProportion = float sample.[i] / float n +// printfn $"Probability of {i}: {p}, Observed proportion: {observedProportion}") + + + +//Discrete.Multinomial.ProbabilityMassToCumulativeDistribution probabilities + + +//let KDiagonal1 = +// [| +// [|1.;0.;0.|] +// [|0.;1.;0.|] +// [|0.;0.;1.|] +// |] +// |> Matrix.ofJaggedArray + +//let BNegInf = +// [| +// [|-infinity;-infinity;-infinity|] +// [|-infinity;-infinity;-infinity|] +// [|-infinity;-infinity;-infinity|] +// |] +// |> Matrix.ofJaggedArray + + +//Algebra.LinearAlgebra.solveTriangularLinearSystems KDiagonal1 BNegInf false + + +//KDiagonal1 +//|> Matrix.mapiCols (fun i v -> +// let m = Vector.norm v +// [|m|]) + +//let expected = +// matrix [| +// [|nan;nan;nan|]; +// [|nan;nan;nan|]; +// [|-infinity;-infinity;-infinity|] +// |] - -//let n = 100000 // Larger n to reduce sampling variance -let sample = SampleUnchecked probabilities n - -let () = - probabilities - |> Array.iteri (fun i p -> - let observedProportion = float sample.[i] / float n - printfn $"Probability of {i}: {p}, Observed proportion: {observedProportion}") - - - -Discrete.Multinomial.ProbabilityMassToCumulativeDistribution probabilities - - -let KDiagonal1 = - [| - [|1.;0.;0.|] - [|0.;1.;0.|] - [|0.;0.;1.|] - |] - |> Matrix.ofJaggedArray - -let BNegInf = - [| - [|-infinity;-infinity;-infinity|] - [|-infinity;-infinity;-infinity|] - [|-infinity;-infinity;-infinity|] - |] - |> Matrix.ofJaggedArray - - -Algebra.LinearAlgebra.solveTriangularLinearSystems KDiagonal1 BNegInf false - - -KDiagonal1 -|> Matrix.mapiCols (fun i v -> - let m = Vector.norm v - [|m|]) - -let expected = - matrix [| - [|nan;nan;nan|]; - [|nan;nan;nan|]; - [|-infinity;-infinity;-infinity|] - |] - - -//|> fun res -> -// let expected = -// matrix [| -// [|nan;nan;nan|]; -// [|nan;nan;nan|]; -// [|-infinity;-infinity;-infinity|] -// |] - - - -let alpha = 9.9 //0.4 -let beta = 31 //4.2 -// https://keisan.casio.com/exec/system/1180573216 -let pdfs = [| 0.987113653; 0.635929273; 0.486870787; 0.400046182; 0.341683319; - 0.299071263; 0.266235685; 0.239955525; 0.218322701; 0.200126249; - 0.184555971; 0.171046668; 0.159190450; 0.148684554; 0.139298865; - 0.130854902; 0.123211796; 0.116256647; 0.109897748; 0.104059710; - 0.098679897; 0.093705765; 0.089092854; 0.084803247; 0.080804376; - 0.077068078; 0.073569861; 0.070288299; 0.067204554; 0.064301989; - 0.061565838; 0.058982949; 0.056541557; 0.054231102; 0.052042076; - 0.049965886; 0.047994748; 0.046121587; 0.044339960; 0.042643979; - 0.041028256; 0.039487846; 0.038018205; 0.036615142; 0.035274793; - 0.033993583; 0.032768200; 0.031595571; 0.030472842; 0.029397355; - 0.028366635; 0.027378369; 0.026430398; 0.025520703; 0.024647389; - 0.023808683; 0.023002918; 0.022228528; 0.021484040; 0.020768066; - 0.020079300; 0.019416507; 0.018778524; 0.018164249; 0.017572643; - 0.017002719; 0.016453546; 0.015924240; 0.015413961; 0.014921914; - 0.014447344; 0.013989532; 0.013547795; 0.013121484; 0.012709981; - 0.012312696; 0.011929068; 0.011558563; 0.011200670; 0.010854903; - 0.010520795; 0.010197904; 0.009885805; 0.009584092; 0.009292377; - 0.009010290; 0.008737475; 0.008473592; 0.008218316; 0.007971333; - 0.007732346; 0.007501068; 0.007277223; 0.007060548; 0.006850789; - 0.006647704; 0.006451059; 0.006260630; 0.006076203; 0.005897569; |] - -//let xy_pdf = pdfs |> Array.mapi (fun i v -> (float (i + 1) / 10.), Continuous.Gamma.PDF alpha beta (float (i + 1) / 10.)) -let samplesHisto = Array.init 999999 (fun _ -> Continuous.Gamma.Sample alpha beta) - -let bw = 1.//FSharp.Stats.Distributions.Bandwidth.forHistogram samplesHisto -let histo = FSharp.Stats.Distributions.KernelDensity.estimate KernelDensity.Kernel.gaussian bw samplesHisto -let histoPdf = histo |> Seq.map (fun (x,y) -> x,Continuous.Gamma.PDF alpha beta x) -//[ -// Chart.Column(histo) -// Chart.Point(histoPdf) -//] -//|> Chart.combine -//|> Chart.show - - -let alpha', beta' = Continuous.Gamma.Fit samplesHisto - -let d = Continuous.Gamma.Estimate pdfs -d.Mean +////|> fun res -> +//// let expected = +//// matrix [| +//// [|nan;nan;nan|]; +//// [|nan;nan;nan|]; +//// [|-infinity;-infinity;-infinity|] +//// |] + + + +//let alpha = 9.9 //0.4 +//let beta = 31 //4.2 +//// https://keisan.casio.com/exec/system/1180573216 +//let pdfs = [| 0.987113653; 0.635929273; 0.486870787; 0.400046182; 0.341683319; +// 0.299071263; 0.266235685; 0.239955525; 0.218322701; 0.200126249; +// 0.184555971; 0.171046668; 0.159190450; 0.148684554; 0.139298865; +// 0.130854902; 0.123211796; 0.116256647; 0.109897748; 0.104059710; +// 0.098679897; 0.093705765; 0.089092854; 0.084803247; 0.080804376; +// 0.077068078; 0.073569861; 0.070288299; 0.067204554; 0.064301989; +// 0.061565838; 0.058982949; 0.056541557; 0.054231102; 0.052042076; +// 0.049965886; 0.047994748; 0.046121587; 0.044339960; 0.042643979; +// 0.041028256; 0.039487846; 0.038018205; 0.036615142; 0.035274793; +// 0.033993583; 0.032768200; 0.031595571; 0.030472842; 0.029397355; +// 0.028366635; 0.027378369; 0.026430398; 0.025520703; 0.024647389; +// 0.023808683; 0.023002918; 0.022228528; 0.021484040; 0.020768066; +// 0.020079300; 0.019416507; 0.018778524; 0.018164249; 0.017572643; +// 0.017002719; 0.016453546; 0.015924240; 0.015413961; 0.014921914; +// 0.014447344; 0.013989532; 0.013547795; 0.013121484; 0.012709981; +// 0.012312696; 0.011929068; 0.011558563; 0.011200670; 0.010854903; +// 0.010520795; 0.010197904; 0.009885805; 0.009584092; 0.009292377; +// 0.009010290; 0.008737475; 0.008473592; 0.008218316; 0.007971333; +// 0.007732346; 0.007501068; 0.007277223; 0.007060548; 0.006850789; +// 0.006647704; 0.006451059; 0.006260630; 0.006076203; 0.005897569; |] + +////let xy_pdf = pdfs |> Array.mapi (fun i v -> (float (i + 1) / 10.), Continuous.Gamma.PDF alpha beta (float (i + 1) / 10.)) +//let samplesHisto = Array.init 999999 (fun _ -> Continuous.Gamma.Sample alpha beta) + +//let bw = 1.//FSharp.Stats.Distributions.Bandwidth.forHistogram samplesHisto +//let histo = FSharp.Stats.Distributions.KernelDensity.estimate KernelDensity.Kernel.gaussian bw samplesHisto +//let histoPdf = histo |> Seq.map (fun (x,y) -> x,Continuous.Gamma.PDF alpha beta x) +////[ +//// Chart.Column(histo) +//// Chart.Point(histoPdf) +////] +////|> Chart.combine +////|> Chart.show + + +//let alpha', beta' = Continuous.Gamma.Fit samplesHisto + +//let d = Continuous.Gamma.Estimate pdfs +//d.Mean diff --git a/tests/FSharp.Stats.Tests/Acceleration.fs b/tests/FSharp.Stats.Tests/Acceleration.fs new file mode 100644 index 000000000..4c7b45014 --- /dev/null +++ b/tests/FSharp.Stats.Tests/Acceleration.fs @@ -0,0 +1,49 @@ +module AccelerationTests + +open Expecto +open System +open FSharp.Stats +open TestExtensions + +open Expecto + +[] +let dotRangeTests = + testList "dotRange tests" [ + + test "Basic dot product with zero offset" { + let a = [| 1.0; 2.0; 3.0 |] + let b = [| 4.0; 5.0; 6.0 |] + let result = Acceleration.SIMDRangeUtils.dotRange a 0 b 0 3 + Expect.floatClose Accuracy.high result 32.0 "Dot product mismatch" + } + + test "Dot product with offset in first array" { + let a = [| 0.0; 1.0; 2.0; 3.0 |] // use 1.0, 2.0, 3.0 + let b = [| 4.0; 5.0; 6.0 |] + let result = Acceleration.SIMDRangeUtils.dotRange a 1 b 0 3 + Expect.floatClose Accuracy.high result 32.0 "Offset dot mismatch" + } + + test "Dot product with both arrays offset" { + let a = [| 0.0; 1.0; 2.0; 3.0 |] + let b = [| 0.0; 4.0; 5.0; 6.0 |] + let result = Acceleration.SIMDRangeUtils.dotRange a 1 b 1 3 + Expect.floatClose Accuracy.high result 32.0 "Offset-dot mismatch" + } + + test "Dot with zero-length" { + let a = [| 1.0; 2.0; 3.0 |] + let b = [| 4.0; 5.0; 6.0 |] + let result = Acceleration.SIMDRangeUtils.dotRange a 0 b 0 0 + Expect.equal result 0.0 "Zero-length dot should be 0" + } + + test "Out of bounds throws" { + let a = [| 1.0; 2.0 |] + let b = [| 1.0; 2.0 |] + Expect.throws (fun () -> + Acceleration.SIMDRangeUtils.dotRange a 1 b 1 2 |> ignore) + "Should throw on out-of-bounds" + } + ] diff --git a/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj b/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj index 26f01cfc4..d9aaf0f95 100644 --- a/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj +++ b/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj @@ -6,6 +6,7 @@ + @@ -17,6 +18,7 @@ + diff --git a/tests/FSharp.Stats.Tests/LinearAlgebra.fs b/tests/FSharp.Stats.Tests/LinearAlgebra.fs index 3225fe876..48d7d5aa2 100644 --- a/tests/FSharp.Stats.Tests/LinearAlgebra.fs +++ b/tests/FSharp.Stats.Tests/LinearAlgebra.fs @@ -6,6 +6,534 @@ open FSharp.Stats open FSharp.Stats.Algebra open TestExtensions + +[] +let householderTests = + testList "Householder tests" [ + + test "Householder reflection zeros subcolumn (3x2 matrix)" { + let A = Matrix(3, 2, [| 4.0; 1.0; + 2.0; 3.0; + 6.0; 5.0 |]) + let R = Matrix.copy A + let x = Matrix.getCol 0 R |> Vector.sub 0 + + let h = Householder.create x + Householder.applyLeft(h, R, 0) + + // After application, first column should be [beta, 0, 0] + Expect.floatClose Accuracy.high R.[1,0] 0.0 "R[1,0] should be zero" + Expect.floatClose Accuracy.high R.[2,0] 0.0 "R[2,0] should be zero" + + // Check tau and beta match known values (approximate) + let expectedBeta = sqrt (4.0**2 + 2.0**2 + 6.0**2) // ||x|| + Expect.floatClose Accuracy.high (float h.Beta) expectedBeta "Beta should match norm" + Expect.isTrue (float h.Tau > 0.0 && float h.Tau < 2.0) "Tau should be in (0, 2)" + } + + test "Householder reflection zeros subcolumn (2x2 matrix)" { + let A = Matrix(2, 2, [| 3.0; 1.0; + 4.0; 5.0 |]) + let R = Matrix.copy A + let x = Matrix.getCol 0 R |> Vector.sub 0 + + let h = Householder.create x + Householder.applyLeft(h, R, 0) + + Expect.floatClose Accuracy.high R.[1,0] 0.0 "R[1,0] should be zero" + let expectedBeta = sqrt (3.0**2 + 4.0**2) + Expect.floatClose Accuracy.high (float h.Beta) expectedBeta "Beta should match norm" + } + + test "Tau and v correctness on a known input" { + let x = [| 3.0; 4.0 |] + let h = Householder.create x + + // We expect: + // - v[0] = 1 + // - v[1] = (4 / v0), since we normalize the vector to have v[0] = 1 + // - tau e (0, 2), beta = ||x|| + Expect.equal h.V.[0] 1.0 "v[0] should be 1.0" + Expect.isTrue (float h.Tau > 0.0 && float h.Tau < 2.0) "Tau should be reasonable" + Expect.floatClose Accuracy.high (float h.Beta) 5.0 "Beta should be ||x|| = 5.0" + } + + test "Degenerate vector returns trivial Householder" { + let x = [| 0.0; 0.0; 0.0 |] + let h = Householder.create x + Expect.equal h.Tau 0.0 "Tau should be 0.0" + Expect.equal h.Beta 0.0 "Beta should be 0.0" + Expect.sequenceEqual h.V [| 1.0; 0.0; 0.0 |] "v should be unit vector" + } + + ] + + + + +[] +let subScaledRowInPlaceTests = + testList "subScaledRowInPlace" [ + + test "Basic subtraction (no offset)" { + let dst = [| 10.0; 20.0; 30.0 |] + let src = [| 1.0; 2.0; 3.0 |] + LinearAlgebra.subScaledRowInPlace 2.0 0 0 3 dst src + let expected = [| 8.0; 16.0; 24.0 |] + Expect.sequenceEqual dst expected "Subtraction incorrect" + } + + test "With dst and src offset" { + let dst = [| 0.0; 10.0; 20.0; 30.0; 0.0 |] + let src = [| 0.0; 1.0; 2.0; 3.0; 0.0 |] + // Subtract 2src[1..3] from dst[1..3] + LinearAlgebra.subScaledRowInPlace 2.0 1 1 3 dst src + let expected = [| 0.0; 8.0; 16.0; 24.0; 0.0 |] + Expect.sequenceEqual dst expected "Offset subtraction incorrect" + } + + test "Single element (scalar fallback)" { + let dst = [| 42.0 |] + let src = [| 2.0 |] + LinearAlgebra.subScaledRowInPlace 3.0 0 0 1 dst src + let expected = [| 36.0 |] + Expect.sequenceEqual dst expected "Scalar fallback incorrect" + } + + test "No modification outside range" { + let dst = [| 1.0; 2.0; 3.0; 4.0 |] + let src = [| 0.0; 1.0; 1.0; 0.0 |] + LinearAlgebra.subScaledRowInPlace 2.0 1 1 2 dst src + let expected = [| 1.0; 0.0; 1.0; 4.0 |] + Expect.sequenceEqual dst expected "Boundary elements modified" + } + + test "basic 3-element row subtraction" { + let dst = [| 1.0; 2.0; 3.0 |] + let src = [| 4.0; 5.0; 6.0 |] + let alpha = 2.0 + let expected = [| -7.0; -8.0; -9.0 |] + + LinearAlgebra.subScaledRowInPlace alpha 0 0 3 dst src + + Expect.sequenceEqual dst expected "Result should be elementwise dst - alpha * src" + } + + test "offsets respected correctly" { + let dst = [| 0.0; 1.0; 2.0; 3.0; 4.0 |] + let src = [| 0.0; 0.0; 1.0; 2.0; 3.0 |] + let alpha = 2.0 + let expected = [| 0.0; 1.0; 0.0; -1.0; -2.0 |] + + // Only update dst[2..4] = [2.0; 3.0; 4.0] with src[2..4] = [1.0; 2.0; 3.0] + LinearAlgebra.subScaledRowInPlace alpha 2 2 3 dst src + + Expect.sequenceEqual dst expected "Offsets should target the correct subarrays" + } + + ] + +[] +let qrDecompositionTests = + testList "QR Decomposition (Modified Gram-Schmidt)" [ + + test "Decompose identity matrix" { + let A = Matrix.identity 3 + let Q, R = LinearAlgebra.qrModifiedGramSchmidt A + let I = Matrix.identity 3 + TestExtensions.floatMatrixClose Accuracy.high Q I "Q should be identity" + TestExtensions.floatMatrixClose Accuracy.high R I "R should be identity" + } + + test "Reconstruct original matrix from Q * R" { + let A = Matrix(3, 2, [| 1.0; 0.0; + 1.0; 1.0; + 0.0; 1.0 |]) + let Q, R = LinearAlgebra.qrModifiedGramSchmidt A + let QR = Matrix.matmul Q R + TestExtensions.floatMatrixClose Accuracy.high QR A "Q * R should reconstruct A" + } + + test "Q has orthonormal columns" { + let A = Matrix(3, 2, [| 1.0; 0.0; + 1.0; 1.0; + 0.0; 1.0 |]) + let Q, _ = LinearAlgebra.qrModifiedGramSchmidt A + let QTQ = Matrix.matmul (Matrix.transpose Q) Q + let I = Matrix.identity 2 + TestExtensions.floatMatrixClose Accuracy.high QTQ I "Q^TQ should be identity" + } + + test "R is upper triangular" { + let A = Matrix(3, 2, [| 1.0; 0.0; + 1.0; 1.0; + 0.0; 1.0 |]) + let _, R = LinearAlgebra.qrModifiedGramSchmidt A + for i in 0 .. R.NumRows - 1 do + for j in 0 .. i - 1 do + Expect.floatClose Accuracy.high R.[i, j] 0.0 $"R[{i},{j}] should be zero" + } + + test "Tall matrix 4x2 decomposition" { + let A = Matrix(4, 2, [| 1.0; 2.0; + 3.0; 4.0; + 5.0; 6.0; + 7.0; 8.0 |]) + let Q, R = LinearAlgebra.qrModifiedGramSchmidt A + let QR = Matrix.matmul Q R + TestExtensions.floatMatrixClose Accuracy.medium QR A "QR ~ A for tall matrix" + } + + test "Wide matrix throws or truncates" { + let A = Matrix(2, 3, [| 1.0; 2.0; 3.0; + 4.0; 5.0; 6.0 |]) + Expect.throws (fun () -> LinearAlgebra.qrModifiedGramSchmidt A |> ignore) + "Wide matrices are not supported (m < n)" + } + ] + +[] +let backSubstituteTests = + testList "Back substitution tests" [ + + test "Solve simple upper triangular system" { + // R = [2 1] + // [0 3] + let r = Matrix(2, 2, [| 2.0; 1.0; + 0.0; 3.0 |]) + let y = [| 5.0; 6.0 |] + let x = LinearAlgebra. backSubstitute r y + // Solve: 3x1 = 6 -> x1 = 2 + // Then: 2x0 + x1 = 5 -> x0 = (5 - 1*2)/2 = 1.5 + let expected = [| 1.5; 2.0 |] + for i in 0..1 do + Expect.floatClose Accuracy.high x.[i] expected.[i] $"x[{i}] incorrect" + } + + test "Identity matrix returns y as solution" { + let r = Matrix.identity 3 + let y = [| 4.0; -2.0; 0.5 |] + let x = LinearAlgebra.backSubstitute r y + Expect.sequenceEqual x y "Identity matrix should return y = x" + } + + test "Upper triangular with zeros below diagonal" { + // R = [1 2 3] + // [0 4 5] + // [0 0 6] + let r = Matrix(3, 3, [| 1.0; 2.0; 3.0; + 0.0; 4.0; 5.0; + 0.0; 0.0; 6.0 |]) + let y = [| 14.0; 23.0; 18.0 |] + let x = LinearAlgebra.backSubstitute r y + let expected = [| 1.0; 2.0; 3.0 |] + for i in 0..2 do + Expect.floatClose Accuracy.high x.[i] expected.[i] $"x[{i}] incorrect" + } + + test "Throws on non-square R" { + let r = Matrix(2, 3, [| 1.0; 2.0; 3.0; + 0.0; 4.0; 5.0 |]) + let y = [| 1.0; 2.0 |] + Expect.throws (fun () -> LinearAlgebra.backSubstitute r y |> ignore) + "Should throw on non-square R" + } + + test "Throws on mismatched dimensions with y" { + let r = Matrix.identity 3 + let y = [| 1.0; 2.0 |] + Expect.throws (fun () -> LinearAlgebra.backSubstitute r y |> ignore) + "Should throw on mismatched y length" + } + + test "Throws on zero diagonal entry (division by zero)" { + let r = Matrix(2, 2, [| 0.0; 1.0; + 0.0; 2.0 |]) + let y = [| 3.0; 4.0 |] + Expect.throws (fun () -> LinearAlgebra.backSubstitute r y |> ignore) + "Should throw on division by zero" + } + ] + +// solveLinearQR +// solveTriangularLinearSystems + + +[] +let solveTriangularLinearSystemTests = + testList "solveTriangularLinearSystem tests" [ + + test "Solve L x = b (lower triangular)" { + // L = [1 0 0; 2 1 0; 3 4 1] + let L = Matrix(3, 3, [| 1.0; 0.0; 0.0; + 2.0; 1.0; 0.0; + 3.0; 4.0; 1.0 |]) + let b = [| 2.0; 5.0; 20.0 |] + let x = LinearAlgebra.solveTriangularLinearSystem L b true + // Solve: Lx = b -> x = [2; 1; 5] + let expected = [| 2.0; 1.0; 10.0 |] + for i in 0..2 do + Expect.floatClose Accuracy.high x.[i] expected.[i] $"x[{i}] incorrect" + } + + test "Solve L^T x = b (upper triangular)" { + // L = [1 0 0; 2 1 0; 3 4 1] + // L^T = [1 2 3; 0 1 4; 0 0 1] + let L = Matrix(3, 3, [| 1.0; 0.0; 0.0; + 2.0; 1.0; 0.0; + 3.0; 4.0; 1.0 |]) + + let b = [| 23.0; 9.0; 1.0 |] + let LT = Matrix.transpose L + let x = LinearAlgebra.solveTriangularLinearSystem LT b false + // Solve L^T x = b -> x = [1; 2; 1] + let expected = [| 10.0; 5.0; 1.0 |] + for i in 0..2 do + Expect.floatClose Accuracy.high x.[i] expected.[i] $"x[{i}] incorrect" + } + + test "Throws on mismatched dimensions" { + let L = Matrix.identity 3 + let b = [| 1.0; 2.0 |] + Expect.throws (fun () -> LinearAlgebra.solveTriangularLinearSystem L b true |> ignore) + "Should throw if dimensions don't match" + } + + test "Throws on zero diagonal (division by zero)" { + let L = Matrix(2, 2, [| 0.0; 0.0; + 1.0; 1.0 |]) + let b = [| 1.0; 2.0 |] + Expect.throws (fun () -> LinearAlgebra.solveTriangularLinearSystem L b true |> ignore) + "Should throw on division by zero" + } + ] + +[] +let qrTests = + testList "QR decomposition via Householder" [ + + test "Q * R reconstructs A" { + let A = Matrix(3, 2, [| 1.0; 1.0; + 1.0; 2.0; + 1.0; 3.0 |]) + let Q, R = LinearAlgebra.qrDecompose A + let QR = Matrix.matmul Q R + TestExtensions.floatMatrixClose Accuracy.high QR A "QR ~ A" + } + + test "Q is orthogonal: Q^TQ = I" { + let A = Matrix(3, 2, [| 1.0; 0.0; + 1.0; 1.0; + 1.0; 2.0 |]) + let Q, _ = LinearAlgebra.qrDecompose A + let QtQ = Matrix.matmul (Matrix.transpose Q) Q + let I = Matrix.identity Q.NumCols + TestExtensions.floatMatrixClose Accuracy.high QtQ I "Q^TQ ~ I" + } + + test "R is upper triangular" { + let A = Matrix(3, 2, [| 1.0; 0.0; + 2.0; 1.0; + 3.0; 2.0 |]) + let _, R = LinearAlgebra.qrDecompose A + for i = 0 to R.NumRows - 1 do + for j = 0 to i - 1 do + Expect.floatClose Accuracy.veryHigh R.[i,j] 0.0 $"R[{i},{j}] should be zero" + } + + test "QR of square matrix" { + let A = Matrix(3, 3, [| 1.0; 2.0; 3.0; + 4.0; 5.0; 6.0; + 7.0; 8.0; 9.0 |]) + let Q, R = LinearAlgebra.qrDecompose A + let QR = Q * R + TestExtensions.floatMatrixClose Accuracy.medium QR A "QR ~ A" + } + + test "QR of small square matrix" { + let A = Matrix(2, 2, [| 2.0; 1.0; + 1.0; 3.0 |]) + let Q, R = LinearAlgebra.qrDecompose A + let QR = Q * R + TestExtensions.floatMatrixClose Accuracy.medium QR A "QR ~ A" + } + + ] + +[] +let leastSquaresQRTests = + testList "Least squares (QR-based)" [ + + test "Overdetermined 3x2 system" { + let A = Matrix(3, 2, [| 1.0; 1.0; + 1.0; 2.0; + 1.0; 3.0 |]) + let b = [| 6.0; 0.0; 0.0 |] + let x = LinearAlgebra.leastSquares A b + let expected = [| 8.0; -3.0 |] + for i in 0..1 do + Expect.floatClose Accuracy.medium x.[i] expected.[i] $"x[{i}] incorrect" + } + + test "Underdetermined 2x3 system (minimum norm)" { + let A = Matrix(2, 3, [| 1.0; 2.0; 0.0; + 0.0; 1.0; 1.0 |]) + let b = [| 3.0; 2.0 |] + let x = LinearAlgebra.leastSquares A b + + // There are infinite solutions, but least norm solution is: + // min ||x|| such that Ax = b + // numpy gives: [0.33333333, 1.33333333, 0.66666667] + let expected = [| 0.33333333; 1.33333333; 0.66666667 |] + for i in 0..2 do + Expect.floatClose Accuracy.medium x.[i] expected.[i] $"x[{i}] incorrect" + } + + test "Square system returns exact solution" { + let A = Matrix(2, 2, [| 2.0; 1.0; + 1.0; 3.0 |]) + let b = [| 5.0; 10.0 |] + let x = LinearAlgebra.leastSquares A b + let expected = [| 1.0; 3.0 |] + for i in 0..1 do + Expect.floatClose Accuracy.high x.[i] expected.[i] $"x[{i}] incorrect" + } + + test "Residual Ax ~ projection of b" { + let A = Matrix(3, 2, [| 1.0; 1.0; + 1.0; 2.0; + 1.0; 3.0 |]) + let b = [| 6.0; 0.0; 0.0 |] + let x = LinearAlgebra.leastSquares A b + let Ax = Matrix.muliplyVector A x + let expected = [| 5.0; 2.0; -1.0 |] + for i in 0..2 do + Expect.floatClose Accuracy.medium Ax.[i] expected.[i] $"Ax[{i}] incorrect" + } + ] + + +[] +let choleskyTests = + testList "Cholesky decomposition tests" [ + + test "Decompose identity matrix" { + let I = Matrix.identity 3 + let L = LinearAlgebra.cholesky I + TestExtensions.floatMatrixClose Accuracy.high L I "L should be identity for identity input" + } + + test "Decompose known positive-definite matrix" { + // A = [4 2; 2 3] -> L = [2 0; 1 1.4142] + let A = Matrix(2, 2, [| 4.0; 2.0; + 2.0; 3.0 |]) + let L = LinearAlgebra.cholesky A + let expected = Matrix(2, 2, [| 2.0; 0.0; + 1.0; sqrt 2.0 |]) + for i in 0..1 do + for j in 0..1 do + Expect.floatClose Accuracy.medium L.[i,j] expected.[i,j] $"L[{i},{j}] incorrect" + } + + test "Reconstruct A from L * L^T" { + let A = Matrix(3, 3, [| 25.0; 15.0; -5.0; + 15.0; 18.0; 0.0; + -5.0; 0.0; 11.0 |]) + let L = LinearAlgebra.cholesky A + let LT = Matrix.transpose L + let reconstructed = Matrix.matmul L LT + TestExtensions.floatMatrixClose Accuracy.high reconstructed A "Reconstructed A <> original" + } + test "Throws on non-positive-definite matrix" { + // Not positive-definite: eigenvalues are [1, -1] + let A = Matrix(2, 2, [| 0.0; 1.0; + 1.0; 0.0 |]) + Expect.throws (fun () -> LinearAlgebra.cholesky A |> ignore) + "Should throw on non-positive-definite matrix" + } + + test "Throws on non-square matrix" { + let A = Matrix(2, 3, [| 1.0; 2.0; 3.0; + 2.0; 5.0; 6.0 |]) + Expect.throws (fun () -> LinearAlgebra.cholesky A |> ignore) + "Should throw on non-square matrix" + } + + test "Zero matrix throws (not positive-definite)" { + let A : Matrix = Matrix.zeroCreate 3 3 + Expect.throws (fun () -> LinearAlgebra.cholesky A |> ignore) + "Should throw on zero matrix" + } + + ] + +[] +let leastSquaresTests = + testList "Least Squares via Cholesky" [ + + test "Solve overdetermined 3x2 system" { + // A = [1 1; 1 2; 1 3], b = [6; 0; 0] + // Should find least-squares fit: beta = [8.0; -3.0] + let A = Matrix(3, 2, [| 1.0; 1.0; + 1.0; 2.0; + 1.0; 3.0 |]) + let b = [| 6.0; 0.0; 0.0 |] + let beta = LinearAlgebra.leastSquaresCholesky A b + let expected = [| 8.0; -3.0 |] + for i in 0..1 do + Expect.floatClose Accuracy.medium beta.[i] expected.[i] $"beta[{i}] incorrect" + } + + test "Reconstruction A * beta ~ projection of b" { + // Same setup as above + let A = Matrix(3, 2, [| 1.0; 1.0; + 1.0; 2.0; + 1.0; 3.0 |]) + let b = [| 6.0; 0.0; 0.0 |] + let beta = LinearAlgebra.leastSquaresCholesky A b + let predicted = Matrix.muliplyVector A beta + // Expected projection of b onto Col(A): A * (A' b) + let expected = [| 5.0; 2.0; -1.0 |] + for i in 0..2 do + Expect.floatClose Accuracy.medium predicted.[i] expected.[i] $"predicted[{i}] incorrect" + } + + test "Throws on dimension mismatch A and b" { + let A = Matrix.identity 3 + let b = [| 1.0; 2.0 |] + Expect.throws (fun () -> LinearAlgebra.leastSquaresCholesky A b |> ignore) + "Should throw if A.NumRows <> b.Length" + } + + test "Exact solution when A is square and full-rank" { + let A = Matrix(2, 2, [| 2.0; 1.0; + 1.0; 3.0 |]) + let b = [| 5.0; 10.0 |] + let beta = LinearAlgebra.leastSquaresCholesky A b + let expected = [| 1.0; 3.0 |] + for i in 0..1 do + Expect.floatClose Accuracy.high beta.[i] expected.[i] $"beta[{i}] incorrect" + } + + ] + + + +// hatMatrix +// leverageBy +// leverage +// luDecompose +// solveLinearSystems (LU) +// solveLinearSystem (LU) + + + + + + + + + [] let managedSVDTests = diff --git a/tests/FSharp.Stats.Tests/TestExtensions.fs b/tests/FSharp.Stats.Tests/TestExtensions.fs index f427bc5f8..4d917f9e6 100644 --- a/tests/FSharp.Stats.Tests/TestExtensions.fs +++ b/tests/FSharp.Stats.Tests/TestExtensions.fs @@ -37,6 +37,13 @@ actual expected + static member floatMatrixClose accuracy (A: Matrix) (B: Matrix) message = + Expect.equal A.NumCols B.NumCols "Column count mismatch" + Expect.equal A.NumRows B.NumRows "Row count mismatch" + for i = 0 to A.NumRows - 1 do + for j = 0 to A.NumCols - 1 do + Expect.floatClose accuracy A.[i, j] B.[i, j] $"{message} at ({i},{j})" + let assembly = Assembly.GetExecutingAssembly() let resnames = assembly.GetManifestResourceNames(); let readEmbeddedRessource (name:string) = From 789223f13792702ce3f1a4f1530a3905ead945ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20M=C3=BChlhaus?= Date: Fri, 8 Aug 2025 13:11:00 +0200 Subject: [PATCH 092/121] Refactoring towards FsMath dependency --- FSharp.Stats.sln | 3 - benchmarks/FSharp.Stats.Benchmarks/Matrix.fs | 2 + .../TriangularSolver.fs | 3 +- benchmarks/FSharp.Stats.Benchmarks/Vector.fs | 7 +- docs/BasicStats.fsx | 3 +- docs/Clustering.fsx | 3 +- docs/ComparisonMetrics.fsx | 2 + docs/Correlation.fsx | 2 + docs/Covariance.fsx | 2 + docs/CrossValidation.fsx | 2 + docs/Differentiation.fsx | 2 + docs/Distributions.fsx | 2 + docs/Fitting.fsx | 2 + docs/GoodnessOfFit.fsx | 2 + docs/GrowthCurve.fsx | 2 + docs/Imputation.fsx | 4 + docs/Integration.fsx | 2 + docs/Interpolation.fsx | 2 + docs/Intervals.fsx | 2 + docs/LinearAlgebra.fsx | 74 - docs/ML.fsx | 122 -- docs/Matrix_Vector.fsx | 290 ---- docs/Normalization.fsx | 2 + docs/Optimization.fsx | 2 + docs/Quantiles.fsx | 2 + docs/Rank.fsx | 2 + docs/Signal.fsx | 2 + docs/Testing.fsx | 2 + docs/index.fsx | 2 + .../AlgTypes/AlgTypesTopLevelOps.fs | 9 - src/FSharp.Stats/AlgTypes/GenericMath.fs | 73 - src/FSharp.Stats/AlgTypes/Householder.fs | 126 -- src/FSharp.Stats/AlgTypes/Matrix.fs | 923 ---------- src/FSharp.Stats/AlgTypes/MatrixExt.fs | 212 --- src/FSharp.Stats/AlgTypes/SIMDUtils.fs | 445 ----- src/FSharp.Stats/AlgTypes/Vector.fs | 266 --- src/FSharp.Stats/AlgTypes/VectorExt.fs | 226 --- src/FSharp.Stats/AlgTypes/VectorOps.fs | 54 - src/FSharp.Stats/Algebra/EVD.fs | 257 --- src/FSharp.Stats/Algebra/LinearAlgebra.fs | 806 --------- src/FSharp.Stats/Algebra/SVD.fs | 567 ------ src/FSharp.Stats/Correlation.fs | 3 + src/FSharp.Stats/DistanceMetrics.fs | 2 + .../Continuous/MultivariateNormal.fs | 6 +- .../Distributions/Discrete/Geometric.fs | 3 +- .../Distributions/Discrete/Multinomial.fs | 2 + .../Distributions/Distribution.fs | 2 + src/FSharp.Stats/FSIPrinters.fs | 1 + src/FSharp.Stats/FSharp.Stats.fsproj | 21 +- src/FSharp.Stats/Fitting/CrossValidation.fs | 2 + src/FSharp.Stats/Fitting/GoodnessOfFit.fs | 3 + src/FSharp.Stats/Fitting/LinearRegression.fs | 3 +- .../Fitting/LogisticRegression.fs | 1 + .../Fitting/NonLinearRegression.fs | 5 +- src/FSharp.Stats/Fitting/Spline.fs | 3 +- src/FSharp.Stats/Interpolation.fs | 3 +- src/FSharp.Stats/ML/DistanceMetrics.fs | 2 + .../ML/Unsupervised/ClusterNumber.fs | 2 + .../ML/Unsupervised/IterativeClustering.fs | 1 + src/FSharp.Stats/Optimization/NelderMead.fs | 3 +- src/FSharp.Stats/Signal/Baseline.fs | 2 +- src/FSharp.Stats/Signal/Convolution.fs | 2 +- src/FSharp.Stats/Signal/Filtering.fs | 3 +- src/FSharp.Stats/Signal/Normalization.fs | 1 + src/FSharp.Stats/Signal/Outliers.fs | 2 +- src/FSharp.Stats/Signal/PeakDetection.fs | 3 +- src/FSharp.Stats/Signal/QQPlot.fs | 2 + src/FSharp.Stats/Table.fs | 5 +- src/FSharp.Stats/Testing/ConfusionMatrix.fs | 2 + src/FSharp.Stats/Testing/ContingencyTable.fs | 2 +- src/FSharp.Stats/Testing/FTest.fs | 2 + src/FSharp.Stats/Testing/PostHoc.fs | 1 + src/FSharp.Stats/Testing/RMT.fs | 2 + src/FSharp.Stats/Testing/TTest.fs | 1 + src/FSharp.Stats/Testing/Tables.fs | 2 + tests/FSharp.Stats.Tests/Acceleration.fs | 49 - tests/FSharp.Stats.Tests/DistanceMetrics.fs | 1 + .../DistributionsContinuous.fs | 1 + .../FSharp.Stats.Tests.fsproj | 5 - tests/FSharp.Stats.Tests/Fitting.fs | 2 +- tests/FSharp.Stats.Tests/Interpolation.fs | 1 + tests/FSharp.Stats.Tests/LinAlgebra.fs | 529 ------ tests/FSharp.Stats.Tests/LinearAlgebra.fs | 1518 ----------------- tests/FSharp.Stats.Tests/Matrix.fs | 309 ---- tests/FSharp.Stats.Tests/Optimization.fs | 1 + tests/FSharp.Stats.Tests/RowVector.fs | 28 - tests/FSharp.Stats.Tests/SVD.fs | 205 --- tests/FSharp.Stats.Tests/TestExtensions.fs | 1 + tests/FSharp.Stats.Tests/Testing.fs | 5 +- tests/FSharp.Stats.Tests/Vector.fs | 605 ------- 90 files changed, 134 insertions(+), 7739 deletions(-) delete mode 100644 docs/LinearAlgebra.fsx delete mode 100644 docs/ML.fsx delete mode 100644 docs/Matrix_Vector.fsx delete mode 100644 src/FSharp.Stats/AlgTypes/AlgTypesTopLevelOps.fs delete mode 100644 src/FSharp.Stats/AlgTypes/GenericMath.fs delete mode 100644 src/FSharp.Stats/AlgTypes/Householder.fs delete mode 100644 src/FSharp.Stats/AlgTypes/Matrix.fs delete mode 100644 src/FSharp.Stats/AlgTypes/MatrixExt.fs delete mode 100644 src/FSharp.Stats/AlgTypes/SIMDUtils.fs delete mode 100644 src/FSharp.Stats/AlgTypes/Vector.fs delete mode 100644 src/FSharp.Stats/AlgTypes/VectorExt.fs delete mode 100644 src/FSharp.Stats/AlgTypes/VectorOps.fs delete mode 100644 src/FSharp.Stats/Algebra/EVD.fs delete mode 100644 src/FSharp.Stats/Algebra/LinearAlgebra.fs delete mode 100644 src/FSharp.Stats/Algebra/SVD.fs delete mode 100644 tests/FSharp.Stats.Tests/Acceleration.fs delete mode 100644 tests/FSharp.Stats.Tests/LinAlgebra.fs delete mode 100644 tests/FSharp.Stats.Tests/LinearAlgebra.fs delete mode 100644 tests/FSharp.Stats.Tests/Matrix.fs delete mode 100644 tests/FSharp.Stats.Tests/RowVector.fs delete mode 100644 tests/FSharp.Stats.Tests/SVD.fs delete mode 100644 tests/FSharp.Stats.Tests/Vector.fs diff --git a/FSharp.Stats.sln b/FSharp.Stats.sln index f70606d2f..2c18d0e23 100644 --- a/FSharp.Stats.sln +++ b/FSharp.Stats.sln @@ -55,9 +55,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "docs", "docs", "{23F9FB2E-6 docs\Integration.fsx = docs\Integration.fsx docs\Interpolation.fsx = docs\Interpolation.fsx docs\Intervals.fsx = docs\Intervals.fsx - docs\LinearAlgebra.fsx = docs\LinearAlgebra.fsx - docs\Matrix_Vector.fsx = docs\Matrix_Vector.fsx - docs\ML.fsx = docs\ML.fsx docs\Normalization.fsx = docs\Normalization.fsx docs\NuGet.config = docs\NuGet.config docs\Optimization.fsx = docs\Optimization.fsx diff --git a/benchmarks/FSharp.Stats.Benchmarks/Matrix.fs b/benchmarks/FSharp.Stats.Benchmarks/Matrix.fs index 516becad8..cab6c1a95 100644 --- a/benchmarks/FSharp.Stats.Benchmarks/Matrix.fs +++ b/benchmarks/FSharp.Stats.Benchmarks/Matrix.fs @@ -4,6 +4,8 @@ open System open BenchmarkDotNet.Attributes open BenchmarkDotNet.Running open FSharp.Stats +open FsMath +open FsMath.Algebra [] type MatrixBenchmarks() = diff --git a/benchmarks/FSharp.Stats.Benchmarks/TriangularSolver.fs b/benchmarks/FSharp.Stats.Benchmarks/TriangularSolver.fs index 6513e7d97..e71072935 100644 --- a/benchmarks/FSharp.Stats.Benchmarks/TriangularSolver.fs +++ b/benchmarks/FSharp.Stats.Benchmarks/TriangularSolver.fs @@ -4,7 +4,8 @@ open System open BenchmarkDotNet.Attributes open BenchmarkDotNet.Running open FSharp.Stats -open FSharp.Stats.Algebra +open FsMath +open FsMath.Algebra [] type TriangularBenchmark() = diff --git a/benchmarks/FSharp.Stats.Benchmarks/Vector.fs b/benchmarks/FSharp.Stats.Benchmarks/Vector.fs index b72d29d5f..6276b5dd5 100644 --- a/benchmarks/FSharp.Stats.Benchmarks/Vector.fs +++ b/benchmarks/FSharp.Stats.Benchmarks/Vector.fs @@ -5,6 +5,8 @@ open System open BenchmarkDotNet.Attributes open BenchmarkDotNet.Running open FSharp.Stats +open FsMath + [] type VectorBenchmarks() = @@ -36,11 +38,6 @@ type VectorBenchmarks() = let result = Vector.dot vector1 vector2 GC.KeepAlive(result) // Prevents the result from being optimized away - [] - member _.CrossProduct() = - let result = Vector.cross vector1 vector2 - GC.KeepAlive(result) // Prevents the result from being optimized away - [] member _.Norm() = let result = Vector.norm vector1 diff --git a/docs/BasicStats.fsx b/docs/BasicStats.fsx index 34cacd0c2..e03c4106f 100644 --- a/docs/BasicStats.fsx +++ b/docs/BasicStats.fsx @@ -11,7 +11,8 @@ categoryindex: 0 (*** condition: prepare ***) #r "../src/FSharp.Stats/bin/Release/netstandard2.0/FSharp.Stats.dll" - +#r "nuget: FsMath, 0.0.1" +open FsMath (*** condition: ipynb ***) #if IPYNB #r "nuget: FSharp.Stats" diff --git a/docs/Clustering.fsx b/docs/Clustering.fsx index d20ebea16..4491a7d73 100644 --- a/docs/Clustering.fsx +++ b/docs/Clustering.fsx @@ -16,7 +16,8 @@ categoryindex: 0 #r "nuget: FSharpAux, 1.0.0" #r "nuget: Cyjs.NET" #r "nuget: OptimizedPriorityQueue, 5.1.0" - +#r "nuget: FsMath, 0.0.1" +open FsMath Plotly.NET.Defaults.DefaultDisplayOptions <- Plotly.NET.DisplayOptions.init (PlotlyJSReference = Plotly.NET.PlotlyJSReference.NoReference) diff --git a/docs/ComparisonMetrics.fsx b/docs/ComparisonMetrics.fsx index a95d0b8b9..9920c443f 100644 --- a/docs/ComparisonMetrics.fsx +++ b/docs/ComparisonMetrics.fsx @@ -13,6 +13,8 @@ categoryindex: 0 #I "../src/FSharp.Stats/bin/Release/netstandard2.0/" #r "FSharp.Stats.dll" #r "nuget: Plotly.NET, 4.0.0" +#r "nuget: FsMath, 0.0.1" +open FsMath Plotly.NET.Defaults.DefaultDisplayOptions <- Plotly.NET.DisplayOptions.init (PlotlyJSReference = Plotly.NET.PlotlyJSReference.NoReference) diff --git a/docs/Correlation.fsx b/docs/Correlation.fsx index 3b22549dd..cbaddadd8 100644 --- a/docs/Correlation.fsx +++ b/docs/Correlation.fsx @@ -13,6 +13,8 @@ categoryindex: 0 #I "../src/FSharp.Stats/bin/Release/netstandard2.0/" #r "FSharp.Stats.dll" #r "nuget: Plotly.NET, 4.0.0" +#r "nuget: FsMath, 0.0.1" +open FsMath Plotly.NET.Defaults.DefaultDisplayOptions <- Plotly.NET.DisplayOptions.init (PlotlyJSReference = Plotly.NET.PlotlyJSReference.NoReference) diff --git a/docs/Covariance.fsx b/docs/Covariance.fsx index 18007f55f..41b35d0d6 100644 --- a/docs/Covariance.fsx +++ b/docs/Covariance.fsx @@ -13,6 +13,8 @@ categoryindex: 0 #I "../src/FSharp.Stats/bin/Release/netstandard2.0/" #r "FSharp.Stats.dll" #r "nuget: Plotly.NET, 4.0.0" +#r "nuget: FsMath, 0.0.1" +open FsMath Plotly.NET.Defaults.DefaultDisplayOptions <- Plotly.NET.DisplayOptions.init (PlotlyJSReference = Plotly.NET.PlotlyJSReference.NoReference) diff --git a/docs/CrossValidation.fsx b/docs/CrossValidation.fsx index 566b7dd8c..f78da9e08 100644 --- a/docs/CrossValidation.fsx +++ b/docs/CrossValidation.fsx @@ -14,6 +14,8 @@ categoryindex: 0 #I "../src/FSharp.Stats/bin/Release/netstandard2.0/" #r "FSharp.Stats.dll" #r "nuget: Plotly.NET, 4.0.0" +#r "nuget: FsMath, 0.0.1" +open FsMath Plotly.NET.Defaults.DefaultDisplayOptions <- Plotly.NET.DisplayOptions.init (PlotlyJSReference = Plotly.NET.PlotlyJSReference.NoReference) diff --git a/docs/Differentiation.fsx b/docs/Differentiation.fsx index e393ee430..25eda0fb4 100644 --- a/docs/Differentiation.fsx +++ b/docs/Differentiation.fsx @@ -13,6 +13,8 @@ categoryindex: 0 #I "../src/FSharp.Stats/bin/Release/netstandard2.0/" #r "FSharp.Stats.dll" #r "nuget: Plotly.NET, 4.0.0" +#r "nuget: FsMath, 0.0.1" +open FsMath Plotly.NET.Defaults.DefaultDisplayOptions <- Plotly.NET.DisplayOptions.init (PlotlyJSReference = Plotly.NET.PlotlyJSReference.NoReference) diff --git a/docs/Distributions.fsx b/docs/Distributions.fsx index 4eb559af4..5a631acd1 100644 --- a/docs/Distributions.fsx +++ b/docs/Distributions.fsx @@ -14,6 +14,8 @@ categoryindex: 0 #I "../src/FSharp.Stats/bin/Release/netstandard2.0/" #r "FSharp.Stats.dll" #r "nuget: Plotly.NET, 4.0.0" +#r "nuget: FsMath, 0.0.1" +open FsMath Plotly.NET.Defaults.DefaultDisplayOptions <- Plotly.NET.DisplayOptions.init (PlotlyJSReference = Plotly.NET.PlotlyJSReference.NoReference) diff --git a/docs/Fitting.fsx b/docs/Fitting.fsx index 7e79432d5..666aaf7e2 100644 --- a/docs/Fitting.fsx +++ b/docs/Fitting.fsx @@ -15,6 +15,8 @@ categoryindex: 0 #r "nuget: DynamicObj, 2.0.0" #r "nuget: Giraffe.ViewEngine, 1.4.0" #r "nuget: Plotly.NET, 4.0.0" +#r "nuget: FsMath, 0.0.1" +open FsMath Plotly.NET.Defaults.DefaultDisplayOptions <- Plotly.NET.DisplayOptions.init (PlotlyJSReference = Plotly.NET.PlotlyJSReference.NoReference) diff --git a/docs/GoodnessOfFit.fsx b/docs/GoodnessOfFit.fsx index 6331c49d0..307e2e733 100644 --- a/docs/GoodnessOfFit.fsx +++ b/docs/GoodnessOfFit.fsx @@ -13,6 +13,8 @@ categoryindex: 0 #I "../src/FSharp.Stats/bin/Release/netstandard2.0/" #r "FSharp.Stats.dll" #r "nuget: Plotly.NET, 4.0.0" +#r "nuget: FsMath, 0.0.1" +open FsMath Plotly.NET.Defaults.DefaultDisplayOptions <- Plotly.NET.DisplayOptions.init (PlotlyJSReference = Plotly.NET.PlotlyJSReference.NoReference) diff --git a/docs/GrowthCurve.fsx b/docs/GrowthCurve.fsx index fe22176ca..520fa5dfe 100644 --- a/docs/GrowthCurve.fsx +++ b/docs/GrowthCurve.fsx @@ -13,6 +13,8 @@ categoryindex: 0 #I "../src/FSharp.Stats/bin/Release/netstandard2.0/" #r "FSharp.Stats.dll" #r "nuget: Plotly.NET, 4.0.0" +#r "nuget: FsMath, 0.0.1" +open FsMath Plotly.NET.Defaults.DefaultDisplayOptions <- Plotly.NET.DisplayOptions.init (PlotlyJSReference = Plotly.NET.PlotlyJSReference.NoReference) diff --git a/docs/Imputation.fsx b/docs/Imputation.fsx index a33c29386..92b646902 100644 --- a/docs/Imputation.fsx +++ b/docs/Imputation.fsx @@ -13,6 +13,8 @@ categoryindex: 0 #I "../src/FSharp.Stats/bin/Release/netstandard2.0/" #r "FSharp.Stats.dll" #r "nuget: Plotly.NET, 4.0.0" +#r "nuget: FsMath, 0.0.1" +open FsMath Plotly.NET.Defaults.DefaultDisplayOptions <- Plotly.NET.DisplayOptions.init (PlotlyJSReference = Plotly.NET.PlotlyJSReference.NoReference) @@ -22,6 +24,8 @@ Plotly.NET.Defaults.DefaultDisplayOptions <- #r "nuget: Plotly.NET, 4.0.0" #r "nuget: Plotly.NET.Interactive, 4.0.0" #r "nuget: FSharp.Stats" +#r "nuget: FsMath, 0.0.1" +open FsMath open Plotly.NET #endif // IPYNB diff --git a/docs/Integration.fsx b/docs/Integration.fsx index 4615e5b53..2e201f0f0 100644 --- a/docs/Integration.fsx +++ b/docs/Integration.fsx @@ -13,6 +13,8 @@ categoryindex: 0 #I "../src/FSharp.Stats/bin/Release/netstandard2.0/" #r "FSharp.Stats.dll" #r "nuget: Plotly.NET, 4.0.0" +#r "nuget: FsMath, 0.0.1" +open FsMath Plotly.NET.Defaults.DefaultDisplayOptions <- Plotly.NET.DisplayOptions.init (PlotlyJSReference = Plotly.NET.PlotlyJSReference.NoReference) diff --git a/docs/Interpolation.fsx b/docs/Interpolation.fsx index 657cdf9f0..ddc4eb368 100644 --- a/docs/Interpolation.fsx +++ b/docs/Interpolation.fsx @@ -13,6 +13,8 @@ categoryindex: 0 #I "../src/FSharp.Stats/bin/Release/netstandard2.0/" #r "FSharp.Stats.dll" #r "nuget: Plotly.NET, 4.0.0" +#r "nuget: FsMath, 0.0.1" +open FsMath Plotly.NET.Defaults.DefaultDisplayOptions <- Plotly.NET.DisplayOptions.init (PlotlyJSReference = Plotly.NET.PlotlyJSReference.NoReference) diff --git a/docs/Intervals.fsx b/docs/Intervals.fsx index ec50b1e16..13e90c87f 100644 --- a/docs/Intervals.fsx +++ b/docs/Intervals.fsx @@ -13,6 +13,8 @@ categoryindex: 0 #I "../src/FSharp.Stats/bin/Release/netstandard2.0/" #r "FSharp.Stats.dll" #r "nuget: Plotly.NET, 4.0.0" +#r "nuget: FsMath, 0.0.1" +open FsMath Plotly.NET.Defaults.DefaultDisplayOptions <- Plotly.NET.DisplayOptions.init (PlotlyJSReference = Plotly.NET.PlotlyJSReference.NoReference) diff --git a/docs/LinearAlgebra.fsx b/docs/LinearAlgebra.fsx deleted file mode 100644 index b666e271a..000000000 --- a/docs/LinearAlgebra.fsx +++ /dev/null @@ -1,74 +0,0 @@ -(** ---- -title: Linear Algebra -index: 4 -category: Documentation -categoryindex: 0 ---- -*) - -(*** hide ***) - -(*** condition: prepare ***) -#I "../src/FSharp.Stats/bin/Release/netstandard2.0/" -#r "FSharp.Stats.dll" -#r "nuget: Plotly.NET, 4.0.0" - -Plotly.NET.Defaults.DefaultDisplayOptions <- - Plotly.NET.DisplayOptions.init (PlotlyJSReference = Plotly.NET.PlotlyJSReference.NoReference) - - -(*** condition: ipynb ***) -#if IPYNB -#r "nuget: Plotly.NET, 4.0.0" -#r "nuget: Plotly.NET.Interactive, 4.0.0" -#r "nuget: FSharp.Stats" - -open Plotly.NET -#endif // IPYNB - - -(** -# Linear Algebra - -Some algorithms such as SVD, EVD, or QR are implemented as a managed version in F# for a full list check the [API reference](https://fslab.org/FSharp.Stats/reference/fsharp-stats-algebra.html) -[![Notebook]({{root}}img/badge-notebook.svg)]({{root}}{{fsdocs-source-basename}}.ipynb) -*) - -open FSharp.Stats -open FSharp.Stats.Algebra - -let A = - matrix [ [ 1.0; 1.0; -1.0 ] - [ 1.0; -2.0; -3.0 ] - [ 2.0; 3.0; 1.0 ] ] - -let B = - matrix [ [ 4.0; ] - [ -6.0; ] - [ 7.0; ] ] - -let svdRes = LinearAlgebra.SVD A - -(***include-value:svdRes***) - -(** - -## Using unmanaged optimized linear algebra functions - -Additionally, we provide some bindings for [LAPACK]() routines. This is currently only tested on windows. - -**Attention**: These bindings are highly incomplete and will most likely be dropped for something like MKL.NET. [See issue#](https://github.com/fslaborg/FSharp.Stats/issues/91) - -the native libraries are contained in the nuget package at the `netlib_LAPACK` path. Include that one instead of the `/../../lib` pth used here. - -*) - -ServiceLocator.setEnvironmentPathVariable (__SOURCE_DIRECTORY__ + "/../../lib") //"D:/Source/FSharp.Stats/lib" - -// initialize the native service provider. This will search on many system paths for the needed binaries. -LinearAlgebra.Service() - -let svdResLapack = LinearAlgebra.SVD A - - diff --git a/docs/ML.fsx b/docs/ML.fsx deleted file mode 100644 index b98296be4..000000000 --- a/docs/ML.fsx +++ /dev/null @@ -1,122 +0,0 @@ -(** ---- -title: Machine Learning -index: 22 -category: Documentation -categoryindex: 0 ---- -*) - -(*** hide ***) - -(*** condition: prepare ***) -#I "../src/FSharp.Stats/bin/Release/netstandard2.0/" -#r "FSharp.Stats.dll" -#r "nuget: Plotly.NET, 4.0.0" - -Plotly.NET.Defaults.DefaultDisplayOptions <- - Plotly.NET.DisplayOptions.init (PlotlyJSReference = Plotly.NET.PlotlyJSReference.NoReference) - - -(*** condition: ipynb ***) -#if IPYNB -#r "nuget: Plotly.NET, 4.0.0" -#r "nuget: Plotly.NET.Interactive, 4.0.0" -#r "nuget: FSharp.Stats" - -open Plotly.NET -#endif // IPYNB - - -(** - -# Machine Learning - -[![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/fslaborg/FSharp.Stats/gh-pages?urlpath=/tree/home/jovyan/Signal.ipynb) -[![Notebook]({{root}}img/badge-notebook.svg)]({{root}}{{fsdocs-source-basename}}.ipynb) - -_Summary:_ this tutorial demonstrates functionality relevant in the context of machine learning. - -### Table of contents - - - [Dimensionality Reduction](#Dimensionality-Reduction) - - [PCA](#PCA) - -## Dimensionality Reduction - -### PCA - -A common approach for to reduce the dimensionality of large data sets is the use of Principal component analyis. - -*) -open Plotly.NET -open FSharp.Stats -open FSharp.Stats.ML.Unsupervised - -let data = - [ - [1.0; 2.0;1.0; 2.0;]; - [1.1; 2.1;1.1; 2.1;]; - [-1.0; -2.0;1.0; 2.0;]; - [-1.1; -2.1;1.1; 2.1;]; - [-1.15; -2.15;1.15; 2.15;]; - ] - |> FSharp.Stats.Matrix.ofJaggedList - -// The PCA implementation expects column wise centered data, which can be generated by calling: -let dc = PCA.center data - -// Calling compute will compute the PCA of the centered data matrix. Relevant information is stored in the result object. -let pca = PCA.compute dc - -// The result of the PCA allows to visualize the analyzed data set projected onto the principal axis: - -// extract components 1 and 2 -let pcs = pca.PrincipalComponents |> Matrix.mapiRows (fun i v -> v.[0],v.[1]) - -// typical PCA "score" plot of components 1 and 2 with the explained variance indicated -let scorePlot = - Chart.Point(pcs) - |> Chart.withTemplate ChartTemplates.lightMirrored - |> Chart.withXAxisStyle (sprintf "PC1, Var explained %f" pca.VarExplainedByComponentIndividual.[0]) - |> Chart.withYAxisStyle (sprintf "PC2, Var explained %f" pca.VarExplainedByComponentIndividual.[1]) - |> Chart.withTitle "Score Plot" - -(*** condition: ipynb ***) -#if IPYNB -scorePlot -#endif // IPYNB - -(***hide***) -scorePlot |> GenericChart.toChartHTML -(***include-it-raw***) - -// Additionally the variable loadings can be visualized: -// Disclaimer: there is a certain ambiguity when it comes to the use of the term loading. -// To stay consistent with other implementations the term loading is used. - -/// Extract loadings of the variables onto the first and second principal component -let loadings = - pca.Loadings - |> Matrix.mapRows (fun v -> v.[0],v.[1]) - - -// typical PCA "loading" plot -let loadingPlot = - loadings - |> Seq.map (fun l -> [0.,0.;l]) - |> Seq.map Chart.Line - |> Chart.combine - |> Chart.withTemplate ChartTemplates.lightMirrored - |> Chart.withXAxisStyle "PC1" - |> Chart.withYAxisStyle "PC2" - |> Chart.withTitle "Loading Plot" - -(*** condition: ipynb ***) -#if IPYNB -loadingPlot -#endif // IPYNB - -(***hide***) -loadingPlot |> GenericChart.toChartHTML -(***include-it-raw***) \ No newline at end of file diff --git a/docs/Matrix_Vector.fsx b/docs/Matrix_Vector.fsx deleted file mode 100644 index 6801bf291..000000000 --- a/docs/Matrix_Vector.fsx +++ /dev/null @@ -1,290 +0,0 @@ -(** ---- -title: Matrix and Vector -index: 3 -category: Documentation -categoryindex: 0 ---- -*) - - -(*** hide ***) - -(*** condition: prepare ***) -#I "../src/FSharp.Stats/bin/Release/netstandard2.0/" -#r "FSharp.Stats.dll" - -(*** condition: ipynb ***) -#if IPYNB -#r "nuget: FSharp.Stats" -#endif // IPYNB - -(** -# Matrix and Vector - -[![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/fslaborg/FSharp.Stats/gh-pages?urlpath=/tree/home/jovyan/Matrix_Vector.ipynb) -[![Notebook]({{root}}img/badge-notebook.svg)]({{root}}{{fsdocs-source-basename}}.ipynb) - -_Summary:_ this tutorial demonstrates some of the functionality for matrices and vectors provided by FSharp.Stats. - -## Vector -*) -open FSharp.Stats - -let v = - vector [|2.0; 20.0; 1.|] - -(*** include-value:v ***) - -let rv = - rowvec [|2.0; 20.0; 1.|] - -(*** include-value:rv ***) - -(***hide***) -let exmp13 = v + 1. -let exmp14 = rv + 1. - -(**Addition to every element of vector.*) -v + 1. - -(*** include-value:exmp13 ***) - -(**Addition to every element of row vector.*) -rv + 1. - -(*** include-value:exmp14 ***) - - -(** - -## Matrix - -### Creating Matrices with FSharp.Stats. -Matrices will also be printed with the FSharp.Stats.FSIPrinters.matrix function to get a nice console output. -*) -open FSharp.Stats - -// http://fdatamining.blogspot.de/2010/03/matrix-and-linear-algebra-in-f-part-i-f.html -// http://fdatamining.blogspot.de/search/label/linear%20algebra - -let A = - matrix [ [ 1.0; 7.0; 2.0 ] - [ 1.0; 3.0; 1.0 ] - [ 2.0; 9.0; 1.0 ] ] - -(***hide***) -let APrint = - FSharp.Stats.FSIPrinters.matrix A - -(*** include-value:APrint ***) - -let B = - matrix [ [ 10.0; 70.0; 20.0 ] - [ 10.0; 30.0; 10.0 ] - [ 20.0; 90.0; 10.0 ] ] - -(***hide***) -let BPrint = - FSharp.Stats.FSIPrinters.matrix B - -(*** include-value:BPrint ***) - - -(** -### Calculation Examples for Matrices -*) - -(***hide***) -let exmp1 = - A - |> Matrix.Generic.mapRows (Seq.sum) - -(**Get sum of each row.*) -A -|> Matrix.Generic.mapRows (Seq.sum) - -(*** include-value:exmp1 ***) - -(***hide***) -let exmp2 = - A - |> Matrix.mapiCols (fun i r -> r) - -(**Create seq of vectors of matrix columns.*) -A -|> Matrix.mapiCols (fun i r -> r) - -(*** include-value:exmp2 ***) - -(***hide***) -let exmp3 = A + B |> FSharp.Stats.FSIPrinters.matrix -let exmp4 = A - B|> FSharp.Stats.FSIPrinters.matrix -let exmp5 = A * B|> FSharp.Stats.FSIPrinters.matrix -let exmp6 = A.*B|> FSharp.Stats.FSIPrinters.matrix -let exmp7 = A * 2.0|> FSharp.Stats.FSIPrinters.matrix -let exmp9 = -A|> FSharp.Stats.FSIPrinters.matrix -let exmp10 = A * v -let exmp11 = Matrix.dot A B -let exmp12 = A + 1.|> FSharp.Stats.FSIPrinters.matrix - - -(**Sum of two matrices.*) -A + B - -(*** include-value:exmp3 ***) - -(**Difference between two matrices.*) -A - B - -(*** include-value:exmp4 ***) - -(**Product of two matrices.*) -A * B - -(*** include-value:exmp5 ***) - -(**Element-wise product of two matrices*) -A .* B - -(*** include-value:exmp6 ***) - -(**Scalar product of a matrix.*) -A * 2.0 -2.0 * A // also ok, gives same result - -(*** include-value:exmp7 ***) - -(**Negation of a matrix*) --A - -(*** include-value:exmp9 ***) - -(**Product of a matrix-vector.*) -A * v - -(*** include-value:exmp10 ***) - -(**Dot product of two matrices.*) -Matrix.dot A B - -(*** include-value:exmp11 ***) - -(**Addition to every element of matrix.*) -A + 1. - -(*** include-value:exmp12 ***) - - -(***hide***) -//let () = -// let assemblyProbeDirectory = "D:/Source/FSharp.Stats/lib" -// System.IO.Directory.SetCurrentDirectory(assemblyProbeDirectory) - -(***hide***) -//// Linear regression -//let cost theta X (y:vector) = -// let tmp = Matrix.dot X theta -// y -// |> Vector.fold (fun sum v -> -// let error = v - tmp -// sum + (error * error) ) 0. -// |> (/) (float y.Length * 2.0) - -(***hide***) -//let inline (.-) a b = -// a |> Matrix.map (fun x -> x - b) - -(***hide***) -//let estimateCoefficientsBySGD (X:matrix) y theta alpha = // rate nEpoch (data:array>) -// //let delta = Vector.create (X.NumCols) 1. -// let cost' = cost theta X y -// let rec loop delta = -// match (delta.Values|> Array.maxBy abs > 1e-6) with -// | false -> theta -// | true -> -// let error = -// let tmp = Matrix.dot X theta -// y |> Vector.map (fun v -> v - y) -// let delta' = -// Matrix.dot X.Transpose error -// |> (/) (float y.Length) -// let trial_theta = theta - alpha * delta -// let trial_cost = cost trial_theta X y -// loop delta' -// let rec wloop (theta:vector) (ttheta:vector) (tcost:vector) (pcost:vector) = -// let ttheta' = (theta + ttheta) / 2. -// let tcost' = cost ttheta X y -// //while (np.max(np.abs(delta)) > 1e-6) do -// // 1. - - - -(***hide***) -//// F# Numerics Interface -//// http://fdatamining.blogspot.de/2010/03/f-inumerics-interface-and-matrix-class.html - -(***hide***) -//// Service Provider model pattern -//// -//// http://blog.ploeh.dk/2011/04/27/Providerisnotapattern/ -//// http://blog.ploeh.dk/2011/04/27/Providerisnotapattern/ - -(***hide***) -//open System.Runtime.InteropServices - -(***hide***) -//// [] -//[] -//extern void dgemm_ -// ( char *transa, char *transb, -// int *m, int *n, int *k, -// double *alpha, double *a, int *lda, -// double *b, int *ldb, double *beta, -// double *c, int *ldc ); - - - -(***hide***) -//#nowarn "51" -//open Microsoft.FSharp.NativeInterop - -(***hide***) -//let matmul_blas (a:float[,]) (b:float[,]) = -// // Get dimensions of the input matrices -// let m = Array2D.length1 a -// let k = Array2D.length2 a -// let n = Array2D.length2 b -// // Allocate array for the result -// let c = Array2D.create n m 0.0 -// // Declare arguments for the call -// let mutable arg_transa = 't' -// let mutable arg_transb = 't' -// let mutable arg_m = m -// let mutable arg_n = n -// let mutable arg_k = k -// let mutable arg_alpha = 1.0 -// let mutable arg_ldk = k -// let mutable arg_ldn = n -// let mutable arg_beta = 1.0 -// let mutable arg_ldm = m - -(***hide***) -// // Temporarily pin the arrays -// use arg_a = PinnedArray2.of_array2D(a) -// use arg_b = PinnedArray2.of_array2D(b) -// use arg_c = PinnedArray2.of_array2D(c) -// // Invoke the native routine -// dgemm_( &&arg_transa, &&arg_transb, -// &&arg_m, &&arg_n, &&arg_k, -// &&arg_alpha, arg_a.Ptr, &&arg_ldk, -// arg_b.Ptr, &&arg_ldn, &&arg_beta, -// arg_c.Ptr, &&arg_ldm ) -// // Transpose the result to get m*n matrix -// Array2D.init m n (fun i j -> c.[j,i]) - - - -(***hide***) -//matmul_blas (A.ToArray2D()) (B.ToArray2D()) - diff --git a/docs/Normalization.fsx b/docs/Normalization.fsx index 61692ec23..3bd51bfd4 100644 --- a/docs/Normalization.fsx +++ b/docs/Normalization.fsx @@ -13,6 +13,8 @@ categoryindex: 0 #I "../src/FSharp.Stats/bin/Release/netstandard2.0/" #r "FSharp.Stats.dll" #r "nuget: Plotly.NET, 4.0.0" +#r "nuget: FsMath, 0.0.1" +open FsMath Plotly.NET.Defaults.DefaultDisplayOptions <- Plotly.NET.DisplayOptions.init (PlotlyJSReference = Plotly.NET.PlotlyJSReference.NoReference) diff --git a/docs/Optimization.fsx b/docs/Optimization.fsx index 0509eb3bf..c175a8f07 100644 --- a/docs/Optimization.fsx +++ b/docs/Optimization.fsx @@ -13,6 +13,8 @@ categoryindex: 0 #I "../src/FSharp.Stats/bin/Release/netstandard2.0/" #r "FSharp.Stats.dll" #r "nuget: Plotly.NET, 4.0.0" +#r "nuget: FsMath, 0.0.1" +open FsMath Plotly.NET.Defaults.DefaultDisplayOptions <- Plotly.NET.DisplayOptions.init (PlotlyJSReference = Plotly.NET.PlotlyJSReference.NoReference) diff --git a/docs/Quantiles.fsx b/docs/Quantiles.fsx index 605313385..9e2102e77 100644 --- a/docs/Quantiles.fsx +++ b/docs/Quantiles.fsx @@ -13,6 +13,8 @@ categoryindex: 0 #I "../src/FSharp.Stats/bin/Release/netstandard2.0/" #r "FSharp.Stats.dll" #r "nuget: Plotly.NET, 4.0.0" +#r "nuget: FsMath, 0.0.1" +open FsMath Plotly.NET.Defaults.DefaultDisplayOptions <- Plotly.NET.DisplayOptions.init (PlotlyJSReference = Plotly.NET.PlotlyJSReference.NoReference) diff --git a/docs/Rank.fsx b/docs/Rank.fsx index cbeefbc94..7b7af6534 100644 --- a/docs/Rank.fsx +++ b/docs/Rank.fsx @@ -13,6 +13,8 @@ categoryindex: 0 #I "../src/FSharp.Stats/bin/Release/netstandard2.0/" #r "FSharp.Stats.dll" #r "nuget: Plotly.NET, 4.0.0" +#r "nuget: FsMath, 0.0.1" +open FsMath Plotly.NET.Defaults.DefaultDisplayOptions <- Plotly.NET.DisplayOptions.init (PlotlyJSReference = Plotly.NET.PlotlyJSReference.NoReference) diff --git a/docs/Signal.fsx b/docs/Signal.fsx index c97228c16..cdf566238 100644 --- a/docs/Signal.fsx +++ b/docs/Signal.fsx @@ -13,6 +13,8 @@ categoryindex: 0 #I "../src/FSharp.Stats/bin/Release/netstandard2.0/" #r "FSharp.Stats.dll" #r "nuget: Plotly.NET, 4.0.0" +#r "nuget: FsMath, 0.0.1" +open FsMath Plotly.NET.Defaults.DefaultDisplayOptions <- Plotly.NET.DisplayOptions.init (PlotlyJSReference = Plotly.NET.PlotlyJSReference.NoReference) diff --git a/docs/Testing.fsx b/docs/Testing.fsx index ed9a456c2..ba709a690 100644 --- a/docs/Testing.fsx +++ b/docs/Testing.fsx @@ -15,6 +15,8 @@ categoryindex: 0 #r "nuget: Plotly.NET, 4.0.0" #r "nuget: FSharpAux, 1.1.0" #r "nuget: Deedle, 3.0.0" +#r "nuget: FsMath, 0.0.1" +open FsMath Plotly.NET.Defaults.DefaultDisplayOptions <- Plotly.NET.DisplayOptions.init (PlotlyJSReference = Plotly.NET.PlotlyJSReference.NoReference) diff --git a/docs/index.fsx b/docs/index.fsx index 770a8887d..f53b10a9e 100644 --- a/docs/index.fsx +++ b/docs/index.fsx @@ -4,6 +4,8 @@ #I "../src/FSharp.Stats/bin/Release/netstandard2.0/" #r "FSharp.Stats.dll" #r "nuget: Plotly.NET, 4.0.0" +#r "nuget: FsMath, 0.0.1" +open FsMath Plotly.NET.Defaults.DefaultDisplayOptions <- Plotly.NET.DisplayOptions.init (PlotlyJSReference = Plotly.NET.PlotlyJSReference.NoReference) diff --git a/src/FSharp.Stats/AlgTypes/AlgTypesTopLevelOps.fs b/src/FSharp.Stats/AlgTypes/AlgTypesTopLevelOps.fs deleted file mode 100644 index 9e2f89788..000000000 --- a/src/FSharp.Stats/AlgTypes/AlgTypesTopLevelOps.fs +++ /dev/null @@ -1,9 +0,0 @@ -namespace FSharp.Stats - - -[] -module AlgTypesTopLevelOps = - - let matrix ll = Matrix.ofRowSeq ll - let vector l = Vector.ofSeq l - //let rowvec l = RowVector.ofSeq l diff --git a/src/FSharp.Stats/AlgTypes/GenericMath.fs b/src/FSharp.Stats/AlgTypes/GenericMath.fs deleted file mode 100644 index 0dea3c597..000000000 --- a/src/FSharp.Stats/AlgTypes/GenericMath.fs +++ /dev/null @@ -1,73 +0,0 @@ -namespace FSharp.Stats - -open System -open System.Runtime.InteropServices - -module GenericMath = - - /// Generic Zero - let inline zero<'T when 'T :> Numerics.INumber<'T>> = - 'T.Zero - - /// Generic One - let inline one<'T when 'T :> Numerics.INumber<'T>> = - 'T.One - - /// Generic float conversion - let inline T<'T when 'T :> Numerics.INumber<'T>> (x: float) : 'T = - 'T.CreateChecked x - - /// Generic square root - let inline sqrt<'T when 'T :> Numerics.IRootFunctions<'T>> (x: 'T) : 'T = - 'T.Sqrt(x) - - /// Generic exponentiation (e^x) - let inline exp<'T when 'T :> Numerics.IExponentialFunctions<'T>> (x: 'T) : 'T = - 'T.Exp(x) - - /// Generic power function (x^y) - let inline pow<'T when 'T :> Numerics.IPowerFunctions<'T>> (x: 'T) (y: 'T) : 'T = - 'T.Pow(x, y) - - /// Generic natural logarithm - let inline log<'T when 'T :> Numerics.ILogarithmicFunctions<'T>> (x: 'T) : 'T = - 'T.Log(x) - - /// Generic absolute value - let inline abs<'T when 'T :> Numerics.INumber<'T>> (x: 'T) : 'T = - 'T.Abs(x) - - /// Generic sine - let inline sin<'T when 'T :> Numerics.ITrigonometricFunctions<'T>> (x: 'T) : 'T = - 'T.Sin(x) - - /// Generic cosine - let inline cos<'T when 'T :> Numerics.ITrigonometricFunctions<'T>> (x: 'T) : 'T = - 'T.Cos(x) - - /// Generic pi constant - let inline pi<'T when 'T :> Numerics.IFloatingPointConstants<'T> and 'T :> Numerics.INumber<'T>> () : 'T = - 'T.Pi - - /// Generic e constant (Euler's number) - let inline e<'T when 'T :> Numerics.IFloatingPointConstants<'T>> () : 'T = - 'T.E - - /// Generic tau constant (2 * pi) - let inline tau<'T when 'T :> Numerics.IFloatingPointConstants<'T> and 'T :> Numerics.INumber<'T>> () : 'T = - 'T.Tau - - /// Generic floor function - let inline floor<'T when 'T :> Numerics.IFloatingPoint<'T>> (x: 'T) : 'T = - 'T. Floor(x) - - /// Generic floor function - let inline epsilon<'T when 'T :> Numerics.IFloatingPoint<'T>> () : 'T = - 'T.CreateTruncating System.Double.Epsilon - - // let inline min x y = if x < y then x else y - // let inline max x y = if x > y then x else y - - // let inline clamp minVal maxVal x = - // if x < minVal then minVal elif x > maxVal then maxVal else x - diff --git a/src/FSharp.Stats/AlgTypes/Householder.fs b/src/FSharp.Stats/AlgTypes/Householder.fs deleted file mode 100644 index a68931fe6..000000000 --- a/src/FSharp.Stats/AlgTypes/Householder.fs +++ /dev/null @@ -1,126 +0,0 @@ -namespace FSharp.Stats.Algebra - - -open System -open FSharp.Stats -open FSharp.Stats.Acceleration - -[] -type Householder<'T when 'T :> Numerics.INumber<'T>> = - { - V: Vector<'T> - Tau: 'T - Beta: 'T - } - - -type Householder() = - - static member inline create<'T when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T : comparison - and 'T :> ValueType - and 'T :> Numerics.IRootFunctions<'T>> - (x: Vector<'T>) : Householder<'T> = - - let xSpan = x.AsSpan() - let alpha = xSpan[0] - let tail = xSpan.Slice(1) - - let zero = GenericMath.zero<'T> - let one = GenericMath.one<'T> - - let sigma = - SIMDUtils.mapFoldUnchecked( - (fun v -> v * v), - (fun x -> x * x), - (+), - (+), - zero, - tail - ) - - if sigma.Equals(zero) then - let v = Vector.zeroCreate x.Length - v.[0] <- one - { - V = v - Tau = zero - Beta = alpha - } - else - let sum = alpha * alpha + sigma - let beta = GenericMath.sqrt sum - - let v0 = - if alpha <= zero then alpha - beta - else -sigma / (alpha + beta) - - let tau = - let v0Sq = v0 * v0 - (v0Sq + v0Sq) / (sigma + v0Sq) - - let v = Vector.divideScalar v0 x // SIMD-aware scalar division - v.[0] <- one - - { - V = v - Tau = tau - Beta = beta - } - - static member inline applyLeft<'T when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T : equality - and 'T :> ValueType> - (h: Householder<'T>, A: Matrix<'T>, rowOffset: int) = - - let v = h.V - let tau = h.Tau - let m = A.NumRows - let n = A.NumCols - let vLen = v.Length - - //for j = 0 to n - 1 do - // let mutable dot = GenericMath.zero<'T> - // for i = 0 to vLen - 1 do - // dot <- dot + v.[i] * A.[rowOffset + i, j] - // let scale = tau * dot - // for i = 0 to vLen - 1 do - // A.[rowOffset + i, j] <- A.[rowOffset + i, j] - scale * v.[i] - - for j = 0 to n - 1 do - let mutable dot = GenericMath.zero<'T> - for i = 0 to vLen - 1 do - let row = rowOffset + i - if row < m then - dot <- dot + v.[i] * A.[row, j] - let scale = tau * dot - for i = 0 to vLen - 1 do - let row = rowOffset + i - if row < m then - A.[row, j] <- A.[row, j] - scale * v.[i] - - - static member inline applyRight<'T when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T : equality - and 'T :> ValueType> - (h: Householder<'T>, A: Matrix<'T>, colOffset: int) = - - let v = h.V - let tau = h.Tau - let m = A.NumRows - let vLen = v.Length - - for i = 0 to m - 1 do - let mutable dot = GenericMath.zero<'T> - for j = 0 to vLen - 1 do - dot <- dot + A.[i, colOffset + j] * v.[j] - let scale = tau * dot - for j = 0 to vLen - 1 do - A.[i, colOffset + j] <- A.[i, colOffset + j] - scale * v.[j] - diff --git a/src/FSharp.Stats/AlgTypes/Matrix.fs b/src/FSharp.Stats/AlgTypes/Matrix.fs deleted file mode 100644 index f9c878579..000000000 --- a/src/FSharp.Stats/AlgTypes/Matrix.fs +++ /dev/null @@ -1,923 +0,0 @@ -namespace FSharp.Stats - -open System -open System.Runtime.InteropServices - -// let blockSize = -// match sizeof<'T> with -// | 4 -> 32 // float32 or int -// | 8 -> 16 // float64 -// | _ -> 16 // fallback - - -/// Matrix type to hold values of a matrix in a 1D Arrays (Flattened Representation) -type Matrix<'T when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T : equality - and 'T :> ValueType> - (rows: int, cols: int, data: Vector<'T>) = - - /// Exposes the raw underlying data array (row-major flattened). - member _.Data = data - - /// Number of rows in the matrix. - member _.NumRows = rows - - /// Number of columns in the matrix. - member _.NumCols = cols - - /// Matrix indexer for getting and setting elements at (i, j). - member this.Item - with get (i, j) = - if i < 0 || i >= rows || j < 0 || j >= cols then - invalidArg "index" $"Index out of range: ({i}, {j})" - data.[i * cols + j] - and set (i, j) value = - if i < 0 || i >= rows || j < 0 || j >= cols then - invalidArg "index" $"Index out of range: ({i}, {j})" - data.[i * cols + j] <- value - - // Implement IEquatable so that F# structural equality can use it - interface IEquatable> with - member this.Equals(other: Matrix<'T>) = - - // 1) Check dimension - if rows <> other.NumRows || cols <> other.NumCols then - false - else - // 2) Compare all elements - let otherData = other.Data - let mutable i = 0 - let mutable eq = true - while eq && i < data.Length do - if data[i] <> otherData[i] then - eq <- false - i <- i + 1 - eq - - // Override Object.Equals - override this.Equals(obj: obj) = - match obj with - | :? Matrix<'T> as other -> - (this :> IEquatable>).Equals(other) - | _ -> false - - // Override Object.GetHashCode - override this.GetHashCode() = - // We'll combine the row/col count plus some portion of the data to avoid huge cost. - // There's no perfect hashing for big arrays, but here's a simple example: - - let mutable hash = HashCode() - hash.Add(rows) - hash.Add(cols) - // Optionally: incorporate some or all elements - // For big arrays, consider sampling or a rolling hash approach. - for i in 0 .. data.Length - 1 do - hash.Add(data[i]) - hash.ToHashCode() - - /// - /// Returns a new Matrix<'T> that is the slice of rows [rowStart..rowEnd] - /// and columns [colStart..colEnd]. If any of these bounds is omitted, - /// it defaults to the full range in that dimension. - /// - /// Optional start row (inclusive) - /// Optional end row (inclusive) - /// Optional start column (inclusive) - /// Optional end column (inclusive) - /// A new submatrix copy. - member this.GetSlice - (rowStart: int option, rowEnd: int option, - colStart: int option, colEnd: int option) : Matrix<'T> = - - // 1) Determine actual start/end indices - let r1 = defaultArg rowStart 0 - let r2 = defaultArg rowEnd (rows - 1) - let c1 = defaultArg colStart 0 - let c2 = defaultArg colEnd (cols - 1) - - // 2) Validate them - if r1 < 0 || r2 < r1 || r2 >= rows then - invalidArg "row range" $"Invalid row slice range: {r1}..{r2}" - if c1 < 0 || c2 < c1 || c2 >= cols then - invalidArg "col range" $"Invalid column slice range: {c1}..{c2}" - - let subRows = r2 - r1 + 1 - let subCols = c2 - c1 + 1 - - // 3) Allocate new array for the submatrix - let subData = Array.zeroCreate<'T> (subRows * subCols) - - // 4) Copy row by row - for rr in 0 .. subRows - 1 do - let srcIndex = (r1 + rr) * cols + c1 - let dstIndex = rr * subCols - // Copy from data[srcIndex..(srcIndex+subCols-1)] - // to subData[dstIndex..(dstIndex+subCols-1)] - Array.blit data srcIndex subData dstIndex subCols - - // 5) Return a new Matrix with the submatrix data - Matrix<'T>(subRows, subCols, subData) - - /// - /// Convenience "slice indexer" for F# syntax: mat.[r1..r2, c1..c2]. - /// Internally calls GetSlice(...). - /// - member this.GetSlice - (rowRange: Range, colRange: Range) : Matrix<'T> = - - // Convert the F# Range type into int option pairs - let rowStart, rowEnd = - (if rowRange.Start = System.Index.Start then None else Some rowRange.Start.Value), - (if rowRange.End = System.Index.End then None else Some rowRange.End.Value) - - let colStart, colEnd = - (if colRange.Start = System.Index.Start then None else Some colRange.Start.Value), - (if colRange.End = System.Index.End then None else Some colRange.End.Value) - - // Use the primary GetSlice overload - this.GetSlice(rowStart, rowEnd, colStart, colEnd) - - - static member inline map2Unchecked<'T when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T :> ValueType> - (fVec: Numerics.Vector<'T> -> Numerics.Vector<'T> -> Numerics.Vector<'T>) - (fScalar: 'T -> 'T -> 'T) - (a: Matrix<'T>) - (b: Matrix<'T>) - : Matrix<'T> = - - // if a.Rows <> b.Rows || a.Cols <> b.Cols then - // invalidArg "b" "Matrix dimensions must match" - - let len = a.Data.Length - let result = Array.zeroCreate<'T> len - - let simdSize = Numerics.Vector<'T>.Count - let simdCount = len / simdSize - let tailStart = simdCount * simdSize - - // Cast arrays to Vector<'T> spans - let aVec = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(a.Data.AsSpan()) - let bVec = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(b.Data.AsSpan()) - let rVec = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(result.AsSpan()) - - for i = 0 to simdCount - 1 do - rVec.[i] <- fVec aVec.[i] bVec.[i] - - for i = tailStart to len - 1 do - result.[i] <- fScalar a.Data.[i] b.Data.[i] - - Matrix(a.NumRows, a.NumCols, result) - - - static member inline mapScalar<'T when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T :> ValueType> - (fv: Numerics.Vector<'T> -> Numerics.Vector<'T> -> Numerics.Vector<'T>) - (f: 'T -> 'T -> 'T) - (matrix: Matrix<'T>) - (scalar: 'T) - : Matrix<'T> = - - let length = matrix.Data.Length - let result = Array.zeroCreate<'T> length - - let slotSize = Numerics.Vector<'T>.Count - let slotCount = length / slotSize - let ceiling = slotCount * slotSize - - let scalarVec = Numerics.Vector<'T>(scalar) - - let mSpan = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(matrix.Data.AsSpan()) - let rSpan = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(result.AsSpan()) - - // SIMD chunk-wise operation - for i = 0 to slotCount - 1 do - rSpan.[i] <- fv mSpan.[i] scalarVec - - // Scalar fallback for remainder - for i = ceiling to length - 1 do - result.[i] <- f matrix.Data.[i] scalar - - Matrix(matrix.NumRows, matrix.NumCols, result) - - - - /// Creates a new matrix by initializing each element with a function `f(row, col)`. - static member inline private transposeByBlock<'T when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T :> ValueType> - (rows : int) - (cols : int) - (data: 'T[]) - (blockSize: int) = - - //let blockSize = defaultArg blockSize 16 - - let src = data - let dst = Array.zeroCreate<'T> (rows * cols) - - let vectorSize = Numerics.Vector<'T>.Count - - // Process the matrix in blocks - for i0 in 0 .. blockSize .. rows - 1 do - for j0 in 0 .. blockSize .. cols - 1 do - - let iMax = min (i0 + blockSize) rows - let jMax = min (j0 + blockSize) cols - - for i in i0 .. iMax - 1 do - let srcOffset = i * cols - for j in j0 .. jMax - 1 do - let v = src.[srcOffset + j] - dst.[j * rows + i] <- v - - dst - - static member inline transpose (m:Matrix<'T>) : Matrix<'T> = - m.Transpose() - - member this.Transpose() = - let blocksize = 16 - Matrix(this.NumCols, this.NumRows, Matrix.transposeByBlock this.NumRows this.NumCols this.Data blocksize) - - static member init<'T when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T :> ValueType> - (rows: int) - (cols: int) - (f: int -> int -> 'T) = - let data = Array.init (rows * cols) (fun idx -> f (idx / cols) (idx % cols)) - Matrix(rows, cols, data) - - static member create<'T when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T :> ValueType> - (rows: int) - (cols: int) - (data: 'T[]) : Matrix<'T> = - - Matrix(rows, cols, data) - - - /// Constructs a matrix from a 2D array. - static member ofArray2D<'T when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T :> ValueType> - (arr2D: 'T[,]) = - let rows = arr2D.GetLength(0) - let cols = arr2D.GetLength(1) - let length = rows * cols - - let flat = Array.zeroCreate<'T> length - let sourceSpan = MemoryMarshal.CreateSpan(&arr2D.[0, 0], length) - sourceSpan.CopyTo(flat.AsSpan()) - - Matrix(rows, cols, flat) - - /// Converts this matrix into a 2D array. - member this.toArray2D() = - let arr2D = Array2D.zeroCreate<'T> this.NumRows this.NumCols - let targetSpan = MemoryMarshal.CreateSpan(&arr2D.[0, 0], this.NumRows * this.NumCols) - this.Data.AsSpan().CopyTo(targetSpan) - arr2D - - - /// Constructs a matrix from a jagged array (`'T[][]`), assuming a rectangular structure. - static member ofJaggedArray<'T when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T :> ValueType> - (jagged: 'T[][]) = - let rows = jagged.Length - let cols = if rows > 0 then jagged.[0].Length else 0 - - // Optional safety check for rectangular shape - for row in jagged do - if row.Length <> cols then - invalidArg "jagged" "All rows in jagged array must have the same length." - - let flat = Array.zeroCreate<'T> (rows * cols) - - for i = 0 to rows - 1 do - let source = jagged.[i].AsSpan() - let target = flat.AsSpan(i * cols, cols) - source.CopyTo(target) - - Matrix(rows, cols, flat) - - /// Converts this matrix into a jagged array (`'T[][]`). - member this.toJaggedArray() = - let result = Array.zeroCreate<'T[]> this.NumRows - let dataSpan = this.Data.AsSpan() - - for i = 0 to this.NumRows - 1 do - let row = Array.zeroCreate<'T> this.NumCols - dataSpan.Slice(i * this.NumCols, this.NumCols).CopyTo(row.AsSpan()) - result.[i] <- row - - result - - - /// Pretty string representation with formatting and truncation, using StringBuilder. - /// Supports optional scientific notation for floating point types. - member this.toFormattedString(?maxRows: int, ?maxCols: int, ?floatFormat: string, ?useScientific: bool) = - let maxRows = defaultArg maxRows 10 - let maxCols = defaultArg maxCols 10 - let useScientific = defaultArg useScientific false - let floatFormat = - match floatFormat with - | Some f -> f - | None -> if useScientific then "0.##E+0" else "0.##" - - if this.NumRows = 0 || this.NumCols = 0 then - "Matrix (empty)" - else - let rowsToShow = min this.NumRows maxRows - let colsToShow = min this.NumCols maxCols - - // Format a single cell - let formatCell (value: 'T) = - match box value with - | :? float as f -> f.ToString(floatFormat) - | :? float32 as f -> f.ToString(floatFormat) - | _ -> string value - - let formattedCells = - Array.init rowsToShow (fun i -> - Array.init colsToShow (fun j -> - formatCell this.[i, j] - ) - ) - - let colWidths = - Array.init colsToShow (fun j -> - Array.init rowsToShow (fun i -> formattedCells.[i].[j].Length) - |> Array.max - ) - - let divider = - colWidths - |> Array.map (fun w -> String.replicate w "─") - |> String.concat "─┼─" - - let sb = Text.StringBuilder() - sb.AppendLine($"Matrix {this.NumRows}x{this.NumCols}:") |> ignore - sb.AppendLine("┌ " + divider + " ┐") |> ignore - - for i = 0 to rowsToShow - 1 do - sb.Append("│ ") |> ignore - for j = 0 to colsToShow - 1 do - let cell = formattedCells.[i].[j].PadLeft(colWidths.[j]) - sb.Append(cell) |> ignore - if j < colsToShow - 1 then sb.Append(" │ ") |> ignore - sb.AppendLine(" │") |> ignore - - if this.NumRows > rowsToShow || this.NumCols > colsToShow then - sb.AppendLine($"│ ... truncated ({this.NumRows}x{this.NumCols}) │") |> ignore - - sb.AppendLine("└ " + divider + " ┘") |> ignore - sb.ToString() - - - /// Default string representation (truncated, human-readable) - override this.ToString() = this.toFormattedString() - - static member inline checkSameShape<'T when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T :> ValueType> - (a: Matrix<'T>) (b: Matrix<'T>) = - if a.NumRows <> b.NumRows || a.NumCols <> b.NumCols then - invalidArg "b" $"Matrix dimensions must match. A is {a.NumRows}x{a.NumCols}, B is {b.NumRows}x{b.NumCols}" - - /// Element-wise addition - static member inline add<'T when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T :> ValueType> - (a: Matrix<'T>) - (b: Matrix<'T>) : Matrix<'T> = - - Matrix.checkSameShape a b - let data = - Acceleration.SIMDUtils.map2Unchecked (+) (+) a.Data b.Data - Matrix(a.NumRows, a.NumCols, data) - - static member inline subtract<'T when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T :> ValueType> - (a: Matrix<'T>) - (b: Matrix<'T>) : Matrix<'T> = - - Matrix.checkSameShape a b - Matrix.map2Unchecked (-) (-) a b - - - /// Hadamard product - static member inline multiply<'T - when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T :> ValueType> - (a: Matrix<'T>) - (b: Matrix<'T>) : Matrix<'T> = - - Matrix.checkSameShape a b - Matrix.map2Unchecked (*) (*) a b - - - static member inline divide<'T - when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T :> ValueType> - (a: Matrix<'T>) - (b: Matrix<'T>) : Matrix<'T> = - - Matrix.checkSameShape a b - Matrix.map2Unchecked (/) (/) a b - - - static member inline addScalar<'T when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T :> ValueType> - (m: Matrix<'T>) (scalar: 'T) : Matrix<'T> = - - Matrix.mapScalar (+) (+) m scalar - - - - static member inline subtractScalar<'T - when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T :> ValueType> - (m: Matrix<'T>) - (scalar: 'T) : Matrix<'T> = - - Matrix.mapScalar (-) (-) m scalar - - - static member inline multiplyScalar<'T - when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T :> ValueType> - (m: Matrix<'T>) - (scalar: 'T) : Matrix<'T> = - - Matrix.mapScalar (*) (*) m scalar - - - static member inline divideScalar<'T - when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T :> ValueType> - (m: Matrix<'T>) - (scalar: 'T) : Matrix<'T> = - - Matrix.mapScalar (/) (/) m scalar - - - /// Standard matrix-vector product - static member inline muliplyVector<'T - when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T :> ValueType> - (m: Matrix<'T>) - (v: Vector<'T>) : Vector<'T> = - - if m.NumCols <> v.Length then - invalidArg "v" $"Vector length {v.Length} must match matrix column count {m.NumCols}" - - let result: Vector<'T> = Array.zeroCreate m.NumRows - let zero = LanguagePrimitives.GenericZero<'T> - - let simdSize = Numerics.Vector<'T>.Count - let vSpan = v.AsSpan() - let vSimd = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(vSpan) - - let tailStart = (v.Length / simdSize) * simdSize - - for row = 0 to m.NumRows - 1 do - let rowOffset = row * m.NumCols - let rowSpan = m.Data.AsSpan(rowOffset, m.NumCols) - let rowSimd = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(rowSpan) - - let mutable acc = Numerics.Vector<'T>(zero) - - for i = 0 to vSimd.Length - 1 do - acc <- acc + rowSimd.[i] * vSimd.[i] - - let mutable tail = zero - for i = tailStart to m.NumCols - 1 do - tail <- tail + m.Data.[rowOffset + i] * v.[i] - - result.[row] <- Numerics.Vector.Sum(acc) + tail - - result - - static member inline addRowVector<'T - when 'T :> Numerics.INumber<'T> - and 'T : struct - and 'T : (new : unit -> 'T) - and 'T :> ValueType> - (m: Matrix<'T>) - (v: Vector<'T>) : Matrix<'T> = - - if v.Length <> m.NumCols then - invalidArg "v" $"Row vector length {v.Length} must match matrix column count {m.NumCols}" - - let resultData = Array.zeroCreate<'T> (m.NumRows * m.NumCols) - let simdSize = Numerics.Vector<'T>.Count - let simdCount = m.NumCols / simdSize - let scalarStart = simdCount * simdSize - - let vSimd = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(v.AsSpan()) - - for row = 0 to m.NumRows - 1 do - let offset = row * m.NumCols - let srcSpan = m.Data.AsSpan(offset, m.NumCols) - let dstSpan = resultData.AsSpan(offset, m.NumCols) - - let srcSimd = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(srcSpan) - let dstSimd = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(dstSpan) - - // SIMD part - for i = 0 to simdCount - 1 do - dstSimd.[i] <- srcSimd.[i] + vSimd.[i] - - // Tail (scalar) - for i = scalarStart to m.NumCols - 1 do - dstSpan.[i] <- srcSpan.[i] + v.[i] - - Matrix(m.NumRows, m.NumCols, resultData) - - - static member inline addColVector<'T - when 'T :> Numerics.INumber<'T> - and 'T : struct - and 'T : (new : unit -> 'T) - and 'T :> ValueType> - (m: Matrix<'T>) - (v: Vector<'T>) : Matrix<'T> = - - if v.Length <> m.NumRows then - invalidArg "v" $"Column vector length {v.Length} must match matrix row count {m.NumRows}" - - let cols = m.NumCols - let resultData = Array.zeroCreate<'T> (m.NumRows * cols) - let simdSize = Numerics.Vector<'T>.Count - - for row = 0 to m.NumRows - 1 do - let rowOffset = row * cols - let srcRow = m.Data.AsSpan(rowOffset, cols) - let dstRow = resultData.AsSpan(rowOffset, cols) - - let simdRow = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(srcRow) - let simdDst = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(dstRow) - - let broadcast = Numerics.Vector<'T>(v.[row]) - let simdCount = cols / simdSize - let scalarStart = simdCount * simdSize - - // SIMD-add: row + broadcast vector - for i = 0 to simdCount - 1 do - simdDst.[i] <- simdRow.[i] + broadcast - - // Scalar tail - for i = scalarStart to cols - 1 do - dstRow.[i] <- srcRow.[i] + v.[row] - - Matrix(m.NumRows, cols, resultData) - - - /// - /// Computes row-vector v (length = mat.NumRows) times matrix mat (size = [NumRows × NumCols]), - /// returning a new vector of length mat.NumCols. Uses chunk-based SIMD with manual gather. - /// - static member inline multiplyRowVector<'T - when 'T :> Numerics.INumber<'T> - and 'T : struct - and 'T : (new : unit -> 'T) - and 'T :> ValueType> - (v: Vector<'T>) - (mat: Matrix<'T>) : Vector<'T> = - - // 1) Dimension checks - let n = mat.NumRows - let m = mat.NumCols - if v.Length <> n then - invalidArg (nameof v) "Vector length must match mat.NumRows." - - let result = Vector.zeroCreate<'T> m - let data = mat.Data // row-major: element (i,j) is data.[i*m + j] - - // O(n*m) nested loops (not SIMD seems to be faster in the row-layout matrix) - for j = 0 to m - 1 do - let mutable sum = 'T.Zero - for i = 0 to n - 1 do - sum <- sum + (v.[i] * data.[i*m + j]) - result.[j] <- sum - - result - - - /// - /// Standard matrix multiplication (A x B). - /// A is (M x K), B is (K x N) => result is (M x N). - /// Then each (row of A) .dot. (row of B^T) is done with Vector<'T> chunks. - /// - static member matmul - (A: Matrix<'T>) (B: Matrix<'T>) : Matrix<'T> = - - // 1) Dimension checks - if A.NumCols <> B.NumRows then - invalidArg (nameof B) - $"Inner dimensions mismatch. A is {A.NumRows}x{A.NumCols}, B is {B.NumRows}x{B.NumCols}" - - let M = A.NumRows - let K = A.NumCols - let N = B.NumCols - - // 2) Transpose B to get B^T => shape [N x K], row j of B^T is col j of B - let Btrans = B.Transpose() - let bTData = Btrans.Data // Now each "row" in bTData is length=K, contiguous - - // 3) We'll allocate result - let resultData = Array.zeroCreate<'T> (M * N) - let aData = A.Data - - // 4) For each row i in A, row j in B^T => element in [i*N + j] - // The row i in A is contiguous of length K => offset i*K in aData - // The row j in B^T is contiguous of length K => offset j*K in bTData - for i in 0 .. M - 1 do - let aRowOffset = i * K - let aRowSpan = aData.AsSpan(aRowOffset, K) - // Convert A's row to a "Vector<'T>" span - let aVecSpan = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(aRowSpan) - - for j in 0 .. N - 1 do - let bTRowOffset = j * K - let bTRowSpan = bTData.AsSpan(bTRowOffset, K) - // Convert B^T's row j to a "Vector<'T>" span - let bTVecSpan = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(bTRowSpan) - - // 4.a) Do the chunkwise vector multiply-add - let mutable accum = Numerics.Vector<'T>.Zero - for chunk in 0 .. aVecSpan.Length - 1 do - accum <- accum + (aVecSpan.[chunk] * bTVecSpan.[chunk]) - - // 4.b) Sum up the vector lanes to a single scalar - let mutable sum = Numerics.Vector.Sum(accum) - - // 4.c) Handle remainder elements if K not multiple of Vector<'T>.Count - let remainderStart = aVecSpan.Length * Numerics.Vector<'T>.Count - for r in remainderStart .. K - 1 do - sum <- sum + aRowSpan.[r] * bTRowSpan.[r] - - // 4.d) Place result into the final matrix - resultData.[i*N + j] <- sum - - Matrix(M, N, resultData) - - - // Matrix - matrix operations - static member inline ( + ) (a: Matrix<'T>, b: Matrix<'T>) = Matrix.add a b - static member inline ( - ) (a: Matrix<'T>, b: Matrix<'T>) = Matrix.subtract a b - static member inline ( .* ) (a: Matrix<'T>, b: Matrix<'T>) = Matrix.multiply a b - static member inline ( * ) (a: Matrix<'T>, b: Matrix<'T>) = Matrix.matmul a b - static member inline ( / ) (a: Matrix<'T>, b: Matrix<'T>) = Matrix.divide a b - - // Matrix - vector operations - static member inline ( * ) (m: Matrix<'T>, v: Vector<'T>) = Matrix.muliplyVector m v - static member inline ( * ) (v: Vector<'T>, m: Matrix<'T>) = Matrix.multiplyRowVector v m - // static member inline ( + ) (m: Matrix<'T>, colVector: Vector<'T>) = Matrix.addColVector m colVector - // static member inline ( +| ) (m: Matrix<'T>, rowVector: Vector<'T>) = Matrix.addRowVector m rowVector - - // Matrix - scalar operations - static member inline (+) (m: Matrix<'T>, s: 'T) = Matrix.addScalar m s - static member inline (+) (s: 'T, m: Matrix<'T>) = Matrix.addScalar m s - - static member inline (-) (m: Matrix<'T>, s: 'T) = Matrix.subtractScalar m s - static member inline (-) (s: 'T, m: Matrix<'T>) = Matrix.subtractScalar m s - - static member inline (*) (m: Matrix<'T>, s: 'T) = Matrix.multiplyScalar m s - static member inline (*) (s: 'T, m: Matrix<'T>) = Matrix.multiplyScalar m s - - static member inline (/) (m: Matrix<'T>, s: 'T) = Matrix.divideScalar m s - static member inline (/) (s: 'T, m: Matrix<'T>) = Matrix.divideScalar m s - - - - static member inline diagonal - (diag: Vector<'T>) : Matrix<'T> = - - let n = diag.Length - let data = Array.zeroCreate<'T> (n * n) - for i = 0 to n - 1 do - data.[i * n + i] <- diag.[i] - Matrix(n, n, data) - - /// - /// Returns the diagonal elements of this matrix as an array of length = min(NumRows, NumCols). - /// - static member inline getDiagonal - (m:Matrix<'T>) : Vector<'T> = - let n = min m.NumRows m.NumCols - let diag = Array.zeroCreate<'T> n - for i = 0 to n - 1 do - // The diagonal element at row i, col i is stored at offset i * cols + i - diag.[i] <- m.Data.[i * m.NumCols + i] - diag - - - static member inline identity<'T - when 'T :> Numerics.INumber<'T> - and 'T : struct - and 'T : (new : unit -> 'T) - and 'T :> ValueType> - (n: int) : Matrix<'T> = - - let data = Array.zeroCreate<'T> (n * n) - for i = 0 to n - 1 do - data.[i * n + i] <- 'T.One - Matrix(n, n, data) - - static member inline zeroCreate<'T - when 'T :> Numerics.INumber<'T> - and 'T : struct - and 'T : (new : unit -> 'T) - and 'T :> ValueType> - (rows: int) - (cols: int) : Matrix<'T> = - - let data = Array.zeroCreate<'T> (rows * cols) - Matrix(rows, cols, data) - - static member inline ones<'T - when 'T :> Numerics.INumber<'T> - and 'T : struct - and 'T : (new : unit -> 'T) - and 'T :> ValueType> - (rows: int) - (cols: int) : Matrix<'T> = - - let size = rows * cols - let data = Array.zeroCreate<'T> size - let simdSize = Numerics.Vector<'T>.Count - let simdCount = size / simdSize - - let vOne = Numerics.Vector<'T>('T.One) - let span = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(data.AsSpan()) - - for i = 0 to simdCount - 1 do - span.[i] <- vOne - - for i = simdCount * simdSize to size - 1 do - data.[i] <- 'T.One - - Matrix(rows, cols, data) - - static member inline getRow<'T - when 'T :> Numerics.INumber<'T> - and 'T : struct - and 'T : (new : unit -> 'T) - and 'T :> ValueType> - (i: int) - (m: Matrix<'T>) : Vector<'T> = - - if i < 0 || i >= m.NumRows then - invalidArg "i" $"Row index out of bounds: {i}" - - let rowSpan = m.Data.AsSpan(i * m.NumCols, m.NumCols) - let result = Array.zeroCreate<'T> m.NumCols - rowSpan.CopyTo(result.AsSpan()) - result - - static member inline getRows (m: Matrix<'T>) : Vector<'T>[] = - Array.init m.NumRows (fun i -> Matrix.getRow i m) - - - static member inline getCol<'T - when 'T :> Numerics.INumber<'T> - and 'T : struct - and 'T : (new : unit -> 'T) - and 'T :> ValueType> - (j: int) - (m: Matrix<'T>) : Vector<'T> = - - if j < 0 || j >= m.NumCols then - invalidArg "j" $"Column index out of bounds: {j}" - - let result = Array.zeroCreate<'T> m.NumRows - let mutable offset = j - for i = 0 to m.NumRows - 1 do - result.[i] <- m.Data.[offset] - offset <- offset + m.NumCols - - result - - static member inline getCols<'T - when 'T :> Numerics.INumber<'T> - and 'T : struct - and 'T : (new : unit -> 'T) - and 'T :> ValueType> - (m: Matrix<'T>) : Vector<'T>[] = - - Array.init m.NumCols (fun j -> - let col = Array.zeroCreate<'T> m.NumRows - let mutable offset = j - for i = 0 to m.NumRows - 1 do - col.[i] <- m.Data.[offset] - offset <- offset + m.NumCols - col - ) - - - /// - /// Sets row of this matrix to the contents of . - /// The length of must match the number of columns in this matrix. - /// - /// The zero-based row index to set. - /// An array of new values for the row, of length equal to . - /// Thrown if is out of range. - /// Thrown if has incorrect length. - member this.SetRow(i: int, rowData: 'T[]) = - if i < 0 || i >= rows then - invalidArg (nameof i) "Row index out of range." - if rowData.Length <> cols then - invalidArg (nameof rowData) $"rowData must have length = {cols}." - - let offset = i * cols - Array.blit rowData 0 data offset cols - - - - - - // static member MatrixMultiply - - // (a: Matrix<'T>, b: Matrix<'T>, ?blockSize: int) : Matrix<'T> - // when 'T : struct - // and 'T : (new : unit -> 'T) - // and 'T :> INumber<'T> - // and 'T :> ValueType = - - // if a.Cols <> b.Rows then - // invalidArg "b" "Matrix dimensions must agree: a.Cols must equal b.Rows." - - // let blockSize = defaultArg blockSize 32 - - // let m = a.Rows - // let n = b.Cols - // let k = a.Cols - - // let result = Array.zeroCreate<'T> (m * n) - // let aData = a.Data - // let bData = b.Data - // let rData = result - - // let vSize = Vector<'T>.Count - - // // Blocked GEMM - // for i0 in 0 .. blockSize .. m - 1 do - // let iMax = min (i0 + blockSize) m - // for j0 in 0 .. blockSize .. n - 1 do - // let jMax = min (j0 + blockSize) n - // for k0 in 0 .. blockSize .. k - 1 do - // let kMax = min (k0 + blockSize) k - - // // Iterate over block - // for i in i0 .. iMax - 1 do - // for j in j0 .. jMax - 1 do - // let mutable sum = 'T.Zero - // let mutable kk = k0 - - // // SIMD accumulation - // while kk <= kMax - vSize do - // let aVec = Vector<'T>(aData, i * k + kk) - // let bVec = Vector<'T>([| for offset in 0 .. vSize - 1 -> bData.[(kk + offset) * n + j] |]) - // sum <- sum + Vector.Dot(aVec, bVec) - // kk <- kk + vSize - - // // Scalar tail - // while kk < kMax do - // sum <- sum + aData.[i * k + kk] * bData.[kk * n + j] - // kk <- kk + 1 - - // rData.[i * n + j] <- rData.[i * n + j] + sum diff --git a/src/FSharp.Stats/AlgTypes/MatrixExt.fs b/src/FSharp.Stats/AlgTypes/MatrixExt.fs deleted file mode 100644 index 5d4386ab6..000000000 --- a/src/FSharp.Stats/AlgTypes/MatrixExt.fs +++ /dev/null @@ -1,212 +0,0 @@ -namespace FSharp.Stats - -open System -open System.Runtime.InteropServices - - -[] -module Matrix = - -// /// Indexed fold over a matrix -// let inline foldi<'T when 'T :> Numerics.INumber<'T>> f (state: 'T) (m: Matrix<'T>) : 'T = -// let mutable acc = state -// for i = 0 to m.NumRows - 1 do -// for j = 0 to m.NumCols - 1 do -// acc <- f i j acc m.[i, j] -// acc - - - /// - /// Creates and returns a new with the same dimensions - /// as this matrix and a copy of the underlying data. - /// - let inline copy (m:Matrix<'T>) : Matrix<'T> = - // Make a copy of the data array - let newData = Array.copy m.Data - Matrix<'T>(m.NumRows, m.NumCols, newData) - - - /// Splits a matrix along row direction according to given indices. Returns (matrix including rows according to indices, rest) - /// - /// - /// - /// - /// - /// - /// - /// - let splitRows (indices:int[]) (m:Matrix<'T>) = - - let nRows,nCols = m.NumRows,m.NumCols - //let nm = Matrix.Generic.zero (nRows-indices.Length) nCols - //let nmi = Matrix.Generic.zero indices.Length nCols - let nm = Matrix.zeroCreate (nRows-indices.Length) nCols - let nmi = Matrix.zeroCreate indices.Length nCols - indices |> Array.sortInPlace - let rec loop nRowI nRowIi rowI = - match rowI with - | i as rowI when rowI < 0 -> nmi,nm - | i as rowI when nRowIi >= 0 && rowI = indices.[nRowIi] -> - for colI=0 to nCols-1 do - nmi.[nRowIi,colI] <- m.[rowI,colI] - loop (nRowI) (nRowIi-1) (rowI-1) - | _ -> //i as rowI when rowI <> indices.[ii] -> - for colI=0 to nCols-1 do - nm.[nRowI,colI] <- m.[rowI,colI] - loop (nRowI-1) (nRowIi) (rowI-1) - - loop (nRows-1-indices.Length) (indices.Length-1) (nRows-1) - - /// Splits a matrix along column direction according to given indices. Returns (matrix including cols according to indices, rest) - /// - /// - /// - /// - /// - /// - /// - /// - let splitCols (indices:int[]) (m:Matrix<_>) = - let nRows,nCols = m.NumRows,m.NumCols - //let nm = Matrix.Generic.zero nRows (nCols-indices.Length) - //let nmi = Matrix.Generic.zero nRows indices.Length - let nm = Matrix.zeroCreate nRows (nCols-indices.Length) - let nmi = Matrix.zeroCreate nRows indices.Length - indices |> Array.sortInPlace - let rec loop nColI nColIi colI = - match colI with - | i as colI when colI < 0 -> nmi,nm - | i as colI when nColIi >= 0 && colI = indices.[nColIi] -> - for rowI=0 to nRows-1 do - nmi.[rowI,nColIi] <- m.[rowI,colI] - loop (nColI) (nColIi-1) (colI-1) - | _ -> //i as rowI when rowI <> indices.[ii] -> - for rowI=0 to nRows-1 do - nm.[rowI,nColI] <- m.[rowI,colI] - loop (nColI-1) (nColIi) (colI-1) - - loop (nCols-1-indices.Length) (indices.Length-1) (nCols-1) - - /// - /// Creates a new matrix by permuting the rows of matrix according - /// to the permutation . That is, row i of the result is row - /// P(i) of . - /// - /// A permutation function that maps row indices. Should be valid - /// An r x c matrix whose rows will be reordered. - /// for all i in [0..r-1]. - /// - /// A new matrix of the same dimensions r x c, with rows permuted by . - /// - let permuteRowsBy (P: Permutation) (m: Matrix<'T>) : Matrix<'T> = - let r, c = m.NumRows, m.NumCols - let newData = Array.zeroCreate<'T> (r * c) - for i = 0 to r - 1 do - let srcRow = P i - // Copy row srcRow from M into row i of the new matrix - Array.blit m.Data (srcRow * c) newData (i * c) c - Matrix<'T>(r, c, newData) - - let ofRows (rows : 'T[][]) : Matrix<'T> = - Matrix.ofJaggedArray rows - - /// Creates a matrix from a sequence of row sequences - let inline ofRowSeq (rows: seq<#seq<'T>>) : Matrix<'T> = - // Convert the outer seq to an array of row-seqs - let rowArr = rows |> Seq.toArray - if rowArr.Length = 0 then - invalidArg "rows" "Cannot create a matrix from an empty sequence of rows." - - // Determine the number of columns by checking the first row’s length - let colCount = rowArr.[0] |> Seq.length - - // Verify all rows have the same length - for i in 1 .. rowArr.Length - 1 do - let currentLen = rowArr.[i] |> Seq.length - if currentLen <> colCount then - invalidArg "rows" (sprintf "Row %d has length %d, expected %d." i currentLen colCount) - - // Flatten all row-seqs into a single array (row-major order) - let data = - rowArr - |> Array.collect (fun rowSeq -> rowSeq |> Seq.toArray) - - // Construct the matrix - Matrix<'T>(rowArr.Length, colCount, data) - - let mapiRows (f: int -> Vector<'T> -> Vector<'U>) (m:Matrix<'T>) : Matrix<'U> = - Matrix.getRows m - |> Array.mapi (fun i v -> f i v) - |> ofRows - - let ofCols (cols : 'T[][]) : Matrix<'T> = - Matrix.ofJaggedArray cols - |> fun m -> m.Transpose() - - let mapiCols (f: int -> Vector<'T> -> Vector<'U>) (m:Matrix<'T>) : Matrix<'U> = - let cols = - Array.init m.NumCols (fun j -> - let col = Array.zeroCreate<'T> m.NumRows - let mutable offset = j - for i = 0 to m.NumRows - 1 do - col.[i] <- m.Data.[offset] - offset <- offset + m.NumCols - f j col - ) - ofCols cols - - /// - /// Applies a function to each element of the matrix, - /// returning a new matrix with updated values. The iteration occurs in - /// row-major order for performance. - /// - /// - /// A function taking (rowIndex, colIndex, oldValue) - /// and returning the new value for that position. - /// - /// A new Matrix with updated elements. - let mapi (f: int -> int -> 'T -> 'U) (A: Matrix<'T>) : Matrix<'U> = - let newData = Array.zeroCreate<'U> A.Data.Length - let rows, cols = A.NumRows, A.NumCols - for i in 0 .. rows - 1 do - let rowOffset = i * cols - for j in 0 .. cols - 1 do - let idx = rowOffset + j - newData.[idx] <- f i j A.Data.[idx] - Matrix<'U>(rows, cols, newData) - - - let map (f: 'T -> 'U) (m:Matrix<'T>) : Matrix<'U> = - let r, c = m.NumRows, m.NumCols - let newData = - m.Data |> Array.map f - Matrix<'U>(r, c, newData) - - - /// - /// Folds over each element in row-major order, accumulating a result of type 'State. - /// The callback receives (currentState, rowIndex, colIndex, elementValue), - /// and returns the new state. - /// - /// A function taking (state, i, j, value) -> newState. - /// The initial accumulation state. - /// The matrix to fold over. - /// The final accumulated state. - let foldi - (f : int -> int -> 'State -> 'T -> 'State ) - (initialState : 'State) - (A : Matrix<'T>) - : 'State = - - let mutable acc = initialState - let rows, cols = A.NumRows, A.NumCols - for i in 0 .. rows - 1 do - let rowOffset = i * cols - for j in 0 .. cols - 1 do - let idx = rowOffset + j - acc <- f i j acc A.Data.[idx] - acc - - /// Sums all elements in the matrix. - let sum (m:Matrix<'T>) : 'T = - m.Data |> Vector.sum \ No newline at end of file diff --git a/src/FSharp.Stats/AlgTypes/SIMDUtils.fs b/src/FSharp.Stats/AlgTypes/SIMDUtils.fs deleted file mode 100644 index 2d12c9d19..000000000 --- a/src/FSharp.Stats/AlgTypes/SIMDUtils.fs +++ /dev/null @@ -1,445 +0,0 @@ -namespace FSharp.Stats.Acceleration - -open System -open System.Runtime.InteropServices -open System.Runtime.CompilerServices - - - - - -/// -/// A utility class for performing SIMD (Single Instruction, Multiple Data) operations on arrays. -/// -type SIMDUtils() = - - /// - /// Applies a safe element-wise unary operation on an array using SIMD for performance. - /// - /// The numeric type of the array elements. - /// A function that performs the SIMD operation on a vector. - /// A fallback function for scalar operations. - /// The input array. - /// An array with the operation applied to each element. - static member inline map<'T when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T :> ValueType> - (fv:Numerics.Vector<'T> -> Numerics.Vector<'T>) - (f: 'T -> 'T) - (v: 'T[]) : 'T[] = - - let length = v.Length - let slotSize = Numerics.Vector<'T>.Count - let slotCount = length / slotSize - let ceiling = slotSize * slotCount - - let results = Array.zeroCreate<'T> length - let rsSpan = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(results.AsSpan()) - let vSpan = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(v.AsSpan()) - - for i = 0 to slotCount - 1 do - rsSpan.[i] <- fv vSpan[i] - - for i = ceiling to length - 1 do - results.[i] <- f v.[i] - - results - - /// - /// Applies an element-wise binary operation on two arrays using SIMD for performance. - /// - /// The numeric type of the array elements. - /// A function that performs the SIMD operation on two vectors. - /// A fallback function for scalar operations. - /// The first input array. - /// The second input array. - /// An array with the operation applied to each pair of elements. - static member inline map2Unchecked<'T when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T :> ValueType> - (fv:Numerics.Vector<'T> -> Numerics.Vector<'T> -> Numerics.Vector<'T>) - (f:'T -> 'T -> 'T) - (v1: 'T[]) - (v2: 'T[]) = - - let length = v1.Length - let slotSize= Numerics.Vector<'T>.Count - let slotCount = length / slotSize - let ceiling = slotSize * slotCount - - let results = Array.zeroCreate<'T> length - let rsSpan = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(results.AsSpan()) - let v1Span = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(v1.AsSpan()) - let v2Span = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(v2.AsSpan()) - - for i=0 to slotCount - 1 do - rsSpan.[i] <- fv v1Span[i] v2Span[i] - - for i=ceiling to v1.Length - 1 do - results.[i] <- f v1.[i] v2[i] - - results - - /// - /// Reduces an array to a single value using a binary operation, with SIMD optimization. - /// - /// The numeric type of the array elements. - /// A function that performs the SIMD reduction on two vectors. - /// A fallback function for scalar reduction. - /// The initial value for the reduction. - /// The input array. - /// The result of the reduction. - static member inline fold<'T when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T :> ValueType> - (fv:Numerics.Vector<'T> -> Numerics.Vector<'T> -> Numerics.Vector<'T>) - (f: 'T -> 'T -> 'T) - (zero: 'T) - (v: 'T[]) : 'T = - - let length = v.Length - let slotSize = Numerics.Vector<'T>.Count - let slotCount = length / slotSize - let ceiling = slotSize * slotCount - - let vSpan: Span> = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(v.AsSpan()) - - let mutable accVec = Numerics.Vector<'T>(zero) - - for i = 0 to slotCount - 1 do - accVec <- fv accVec vSpan[i] - - let mutable acc = accVec.[0] - for i = 1 to slotSize - 1 do - acc <- f acc accVec.[i] - - for i = ceiling to length - 1 do - acc <- f acc v[i] - - acc - - /// - /// Applies an element-wise binary operation between an array and a scalar using SIMD for performance. - /// - /// The numeric type of the array elements. - /// A function that performs the SIMD operation on a vector and a scalar vector. - /// A fallback function for scalar operations. - /// The input array. - /// The scalar value. - /// An array with the operation applied to each element and the scalar. - static member inline mapScalar<'T when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T :> ValueType> - (fv:Numerics.Vector<'T> -> Numerics.Vector<'T> -> Numerics.Vector<'T> ) - (f:'T -> 'T -> 'T) - (v1:'T[]) - (scalar:'T) : 'T[] = - - let length = v1.Length - let slotSize= Numerics.Vector<'T>.Count - let slotCount = length / slotSize - let ceiling = slotSize * slotCount - - let results = Array.zeroCreate<'T> length - let rsSpan = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(results.AsSpan()) - let v1Span = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(v1.AsSpan()) - let scalarVec = Numerics.Vector(scalar) - - for i=0 to slotCount - 1 do - rsSpan.[i] <- fv v1Span[i] scalarVec - - for i=ceiling to v1.Length - 1 do - results.[i] <- f v1.[i] scalar - - results - - - static member inline mapFoldUnchecked<'T - when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T :> ValueType> - (fMapSimd: Numerics.Vector<'T> -> Numerics.Vector<'T>, - fMap: 'T -> 'T, - fReduceSimd: Numerics.Vector<'T> -> Numerics.Vector<'T> -> Numerics.Vector<'T>, - fReduceScalar: 'T -> 'T -> 'T, - zero: 'T, - input: ReadOnlySpan<'T>) - : 'T = - - let len = input.Length - let simdSize = Numerics.Vector<'T>.Count - let simdBlocks = len / simdSize - let tailStart = simdBlocks * simdSize - - // SIMD map + accumulation - let mutable accVec = Numerics.Vector<'T>(zero) - let inputVec = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(input) - - for i = 0 to simdBlocks - 1 do - let mapped = fMapSimd inputVec[i] - accVec <- fReduceSimd accVec mapped - - // Reduce SIMD accumulator to scalar - let mutable acc = accVec.[0] - for i = 1 to simdSize - 1 do - acc <- fReduceScalar acc accVec.[i] - - // Scalar tail - for i = tailStart to len - 1 do - acc <- fReduceScalar acc (fMap input[i]) - - acc - - - -type SIMDRangeUtils = - - /// In-place transformation of v[startIndex..(startIndex + count - 1)] - /// using a SIMD operation (fv) for chunked parts and a scalar function (f) for leftovers. - static member inline mapRangeInPlace<'T when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T :> ValueType> - (fv : Numerics.Vector<'T> -> Numerics.Vector<'T>) - (f : 'T -> 'T) - (startIndex : int) - (count : int) - (v : 'T[]) : unit = - - // 1) Validate parameters - if startIndex < 0 || count < 0 || (startIndex + count) > v.Length then - invalidArg (nameof count) "Invalid start index or count." - - // 2) Early exit if there's nothing to do - if count = 0 then - // nothing to do - () - - else - // 3) Compute how many full Vector<'T>.Count chunks we can process - let simdSize = Numerics.Vector<'T>.Count - let simdCount = count / simdSize - let tailStart = simdCount * simdSize - - // 4) Slice the relevant portion of v - let span = v.AsSpan(startIndex, count) - // 5) Interpret that span as a span of Vector<'T> - let vecSpan = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(span) - - // 6) Apply fv to each SIMD chunk - for i in 0 .. simdCount - 1 do - vecSpan.[i] <- fv vecSpan.[i] - - // 7) Handle leftover elements with f - for i in tailStart .. count - 1 do - let idx = startIndex + i - v.[idx] <- f v.[idx] - - - - /// In-place combination of two arrays (dst, src) over 'count' elements, - /// starting from 'dstStartIndex' and 'srcStartIndex' respectively. - /// Uses 'fv' for chunked SIMD processing and 'f' for leftover scalar elements. - static member inline map2RangeInPlace<'T when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T :> ValueType> - (fv : Numerics.Vector<'T> -> Numerics.Vector<'T> -> Numerics.Vector<'T>) - (f : 'T -> 'T -> 'T) - (dstStartIndex : int) - (srcStartIndex : int) - (count : int) - (dst : 'T[]) - (src : 'T[]) : unit = - - // 1) Validate parameters - if dstStartIndex < 0 || srcStartIndex < 0 || count < 0 then - invalidArg (nameof count) "Start indices and count must be non-negative." - if dstStartIndex + count > dst.Length then - invalidArg (nameof dstStartIndex) "Destination range out of bounds." - if srcStartIndex + count > src.Length then - invalidArg (nameof srcStartIndex) "Source range out of bounds." - - // 2) Early exit if there's nothing to do - if count = 0 then - () - else - // 3) How many full 'Vector<'T>' chunks fit into 'count'? - let simdSize = Numerics.Vector<'T>.Count - let simdCount = count / simdSize - let tailStart = simdCount * simdSize - - // 4) Create Spans for the subranges - let dstSpan = dst.AsSpan(dstStartIndex, count) - let srcSpan = src.AsSpan(srcStartIndex, count) - - // 5) Cast to Span> for chunked SIMD ops - let dstVecSpan = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(dstSpan) - let srcVecSpan = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(srcSpan) - - // 6) Apply 'fv' to each pair of SIMD chunks - for i = 0 to simdCount - 1 do - dstVecSpan.[i] <- fv dstVecSpan.[i] srcVecSpan.[i] - - // 7) Handle leftover scalar elements - for i = tailStart to count - 1 do - let dstIdx = dstStartIndex + i - let srcIdx = srcStartIndex + i - dst.[dstIdx] <- f dst.[dstIdx] src.[srcIdx] - - - /// Dot product of arr1[off1..off1+count-1] and arr2[off2..off2+count-1]. - /// Uses SIMD if available; otherwise a naive loop. - static member inline dotRange<'T when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T :> ValueType> - (arr1: 'T[]) (off1: int) - (arr2: 'T[]) (off2: int) - (count: int) = - - if Numerics.Vector.IsHardwareAccelerated && count >= Numerics.Vector<'T>.Count then - let simdSize = Numerics.Vector<'T>.Count - let simdCount = count / simdSize - let tailStart = simdCount * simdSize - - let mutable sumVec = Numerics.Vector<'T>.Zero - - let span1 = arr1.AsSpan(off1, count) - let span2 = arr2.AsSpan(off2, count) - - let vec1 = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(span1) - let vec2 = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(span2) - - for i = 0 to simdCount - 1 do - sumVec <- sumVec + (vec1.[i] * vec2.[i]) - - // Reduce the SIMD lanes - let mutable simdSum = LanguagePrimitives.GenericZero<'T> - for lane = 0 to simdSize - 1 do - simdSum <- simdSum + sumVec.[lane] - - // Handle leftover tail - let mutable tailSum = LanguagePrimitives.GenericZero<'T> - for i = tailStart to count - 1 do - tailSum <- tailSum + arr1.[off1 + i] * arr2.[off2 + i] - - simdSum + tailSum - else - // Fallback naive loop - let mutable acc = LanguagePrimitives.GenericZero<'T> - for i = 0 to count - 1 do - acc <- acc + arr1.[off1 + i] * arr2.[off2 + i] - acc - - -// - -// // -// static member map2Unchecked<'T when 'T :> Numerics.INumber<'T> -// and 'T : (new: unit -> 'T) -// and 'T : struct -// and 'T :> ValueType> -// (fv:Numerics.Vector<'T> -> Numerics.Vector<'T> -> Numerics.Vector<'T>) -// (f:'T -> 'T -> 'T) -// (v1: 'T[]) -// (v2: 'T[]) : 'T[] = - - -// // Gets the total number of elements of this vector -// let length = v1.Length -// // -// let slotSize= Numerics.Vector<'T>.Count -// // Number of slots (rasterized vectors) -// let slotCount = length / slotSize -// // Index at which the non rasterd remain starts -// let ceiling = slotSize * slotCount - -// // Allocate the result array -// let results = Array.zeroCreate<'T> length -// let rsSpan = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(results.AsSpan()) -// let v1Span = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(v1.AsSpan()) -// let v2Span = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(v2.AsSpan()) - -// // Perform SIMD addition for chunks -// for i=0 to slotCount - 1 do -// rsSpan.[i] <- fv v1Span[i] v2Span[i] - -// // Handle the remaining elements -// for i=ceiling to v1.Length - 1 do -// results.[i] <- f v1.[i] v2[i] - -// results - -// type SIMDMatrixUtils() = - -// static member map2<'T when 'T :> Numerics.INumber<'T> -// and 'T : (new: unit -> 'T) -// and 'T : struct -// and 'T :> ValueType> -// (fVec: Numerics.Vector<'T> -> Numerics.Vector<'T> -> Numerics.Vector<'T>) -// (fScalar: 'T -> 'T -> 'T) -// (a: Matrix<'T>) -// (b: Matrix<'T>) -// : Matrix<'T> = - -// if a.Rows <> b.Rows || a.Cols <> b.Cols then -// invalidArg "b" "Matrix dimensions must match" - -// let len = a.Data.Length -// let result = Array.zeroCreate<'T> len - -// let simdSize = Numerics.Vector<'T>.Count -// let simdCount = len / simdSize -// let tailStart = simdCount * simdSize - -// // Cast arrays to Vector<'T> spans -// let aVec = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(a.Data.AsSpan()) -// let bVec = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(b.Data.AsSpan()) -// let rVec = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(result.AsSpan()) - -// for i = 0 to simdCount - 1 do -// rVec.[i] <- fVec aVec.[i] bVec.[i] - -// for i = tailStart to len - 1 do -// result.[i] <- fScalar a.Data.[i] b.Data.[i] - -// Matrix(a.Rows, a.Cols, result) - - -// static member mapScalar<'T when 'T :> Numerics.INumber<'T> -// and 'T : (new: unit -> 'T) -// and 'T : struct -// and 'T :> ValueType> -// (fv: Numerics.Vector<'T> -> Numerics.Vector<'T> -> Numerics.Vector<'T>) -// (f: 'T -> 'T -> 'T) -// (matrix: Matrix<'T>) -// (scalar: 'T) -// : Matrix<'T> = - -// let length = matrix.Data.Length -// let result = Array.zeroCreate<'T> length - -// let slotSize = Numerics.Vector<'T>.Count -// let slotCount = length / slotSize -// let ceiling = slotCount * slotSize - -// let scalarVec = Numerics.Vector<'T>(scalar) - -// let mSpan = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(matrix.Data.AsSpan()) -// let rSpan = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(result.AsSpan()) - -// // SIMD chunk-wise operation -// for i = 0 to slotCount - 1 do -// rSpan.[i] <- fv mSpan.[i] scalarVec - -// // Scalar fallback for remainder -// for i = ceiling to length - 1 do -// result.[i] <- f matrix.Data.[i] scalar - -// Matrix(matrix.Rows, matrix.Cols, result) diff --git a/src/FSharp.Stats/AlgTypes/Vector.fs b/src/FSharp.Stats/AlgTypes/Vector.fs deleted file mode 100644 index 5171c0a8b..000000000 --- a/src/FSharp.Stats/AlgTypes/Vector.fs +++ /dev/null @@ -1,266 +0,0 @@ -namespace FSharp.Stats - -open System -open System.Runtime.InteropServices - -/// Vector as an array type alias -type Vector<'T when 'T :> Numerics.INumber<'T>> = 'T [] - - -type Vector = - - - static member inline zeroCreate<'T when 'T :> Numerics.INumber<'T>> count : Vector<'T> = - Array.zeroCreate<'T> count - - - /// Adds two vectors element-wise. - /// The first vector. - /// The second vector. - /// A new vector containing the element-wise sum of the two input vectors. - /// Thrown when the vectors have different lengths. - static member inline add<'T when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T :> ValueType> (v1 : Vector<'T>) (v2 : Vector<'T>) : Vector<'T> = - - - if v1.Length <> v2.Length then - invalidArg "" "Cannot add two vectors of different dimensions." - - if Numerics.Vector.IsHardwareAccelerated then - Acceleration.SIMDUtils.map2Unchecked (+) (+) v1 v2 - else - Array.map2 (+) v1 v2 - - - /// Subtracts the second vector from the first vector element-wise. - /// The first vector. - /// The second vector. - /// A new vector containing the element-wise difference of the two input vectors. - /// Thrown when the vectors have different lengths. - static member inline subtract<'T when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T :> ValueType> (v1 : Vector<'T>) (v2 : Vector<'T>) : Vector<'T> = - - if v1.Length <> v2.Length then - invalidArg "" "Cannot subtract two vectors of different dimensions." - - if Numerics.Vector.IsHardwareAccelerated then - Acceleration.SIMDUtils.map2Unchecked (-) (-) v1 v2 - else - Array.map2 (-) v1 v2 - - - /// Multiplies two vectors element-wise. - /// The first vector. - /// The second vector. - /// A new vector containing the element-wise product of the two input vectors. - /// Thrown when the vectors have different lengths. - static member inline multiply<'T when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T :> ValueType> (v1 : Vector<'T>) (v2 : Vector<'T>) : Vector<'T> = - - if v1.Length <> v2.Length then - invalidArg "" "Cannot multiply two vectors of different dimensions." - - if Numerics.Vector.IsHardwareAccelerated then - Acceleration.SIMDUtils.map2Unchecked ( * ) ( * ) v1 v2 - else - Array.map2 ( * ) v1 v2 - - - /// Divides the first vector by the second vector element-wise. - /// The first vector. - /// The second vector. - /// A new vector containing the element-wise division of the two input vectors. - /// Thrown when the vectors have different lengths. - static member inline divide<'T when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T :> ValueType> (v1 : Vector<'T>) (v2 : Vector<'T>) : Vector<'T> = - if v1.Length <> v2.Length then - invalidArg "" "Cannot divide two vectors of different dimensions." - - if Numerics.Vector.IsHardwareAccelerated then - Acceleration.SIMDUtils.map2Unchecked ( / ) ( / ) v1 v2 - else - Array.map2 ( / ) v1 v2 - - - /// Adds a scalar to each element of the vector. - /// The vector. - /// The scalar value to add. - /// A new vector with the scalar added to each element. - static member inline addScalar<'T when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T :> ValueType> - (scalar:'T) (v:Vector<'T>) : Vector<'T> = - - if Numerics.Vector.IsHardwareAccelerated then - Acceleration.SIMDUtils.mapScalar (+) (+) v scalar - else - Array.map (fun x -> x + scalar) v - - - /// Subtracts a scalar from each element of the vector. - /// The vector. - /// The scalar value to subtract. - /// A new vector with the scalar subtracted from each element. - static member inline subtractScalar<'T when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T :> ValueType> - (scalar:'T) (v:Vector<'T>) : Vector<'T> = - if Numerics.Vector.IsHardwareAccelerated then - Acceleration.SIMDUtils.mapScalar (-) (-) v scalar - else - Array.map (fun x -> x - scalar) v - - - /// Multiplies each element of the vector by a scalar. - /// The vector. - /// The scalar value to multiply by. - /// A new vector with each element multiplied by the scalar. - static member inline multiplyScalar<'T when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T :> ValueType> - (scalar:'T) (v:Vector<'T>) : Vector<'T> = - - if Numerics.Vector.IsHardwareAccelerated then - Acceleration.SIMDUtils.mapScalar ( * ) ( * ) v scalar - else - Array.map (fun x -> x * scalar) v - - - /// Divides each element of the vector by a scalar. - /// The vector. - /// The scalar value to divide by. - /// A new vector with each element divided by the scalar. - static member inline divideScalar<'T when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T :> ValueType> - (scalar:'T) (v:Vector<'T>) : Vector<'T> = - - if Numerics.Vector.IsHardwareAccelerated then - Acceleration.SIMDUtils.mapScalar ( / ) ( / ) v scalar - else - Array.map (fun x -> x / scalar) v - - /// Computes the sum of all elements in the vector. - /// The vector. - /// The sum of all elements in the vector. - static member inline sum<'T when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T :> ValueType> - (v:Vector<'T>) : 'T = - let zero = LanguagePrimitives.GenericZero<'T> - if Numerics.Vector.IsHardwareAccelerated then - Acceleration.SIMDUtils.fold (+) (+) zero v - else - Array.sum v - - /// Computes the product of all elements in the vector. - /// The vector. - /// The product of all elements in the vector. - static member inline product<'T when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T :> ValueType> - (v:Vector<'T>) : 'T = - let one = LanguagePrimitives.GenericOne<'T> - if Numerics.Vector.IsHardwareAccelerated then - Acceleration.SIMDUtils.fold (*) (*) one v - else - Array.fold ( * ) one v - - - /// Computes the mean of the elements in the vector. - /// The vector. - /// The mean of the elements in the vector. - /// Thrown when the vector is empty. - static member inline mean<'T when 'T :> Numerics.INumber<'T> - and 'T : (static member DivideByInt : 'T * int -> 'T) - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T :> ValueType> - (v: Vector<'T>) : 'T = - if v.Length = 0 then invalidArg "v" "Cannot compute mean of empty vector." - let sum = Vector.sum v - LanguagePrimitives.DivideByInt<'T> sum v.Length - - /// Computes the dot product ab^T of two vectors. - /// The first vector. - /// The second vector. - /// The dot product of the two vectors. - /// Thrown when the vectors have different lengths. - static member inline dot<'T when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T :> ValueType> (v1 : Vector<'T>) (v2 : Vector<'T>) : 'T = - - if v1.Length <> v2.Length then - invalidArg "v2" "Vector must have the same length to compute the dot product." - if Numerics.Vector.IsHardwareAccelerated then - let length = v1.Length - let slotSize = Numerics.Vector<'T>.Count - let slotCount = length / slotSize - let ceiling = slotSize * slotCount - - let v1Span = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(v1.AsSpan()) - let v2Span = MemoryMarshal.Cast<'T, Numerics.Vector<'T>>(v2.AsSpan()) - let mutable result = Numerics.Vector<'T>.Zero - //let mutable scalarResult = LanguagePrimitives.GenericZero<'T> - - for i = 0 to slotCount - 1 do - result <- Numerics.Vector.Add(result, Numerics.Vector.Multiply(v1Span.[i], v2Span.[i])) - //scalarResult <- Numerics.Vector.Sum result - - let mutable scalarResult = Numerics.Vector.Sum result - - for i = ceiling to v1.Length - 1 do - scalarResult <- scalarResult + (v1.[i] * v2.[i]) - - scalarResult - else - Array.fold2 (fun acc x y -> acc + (x * y)) LanguagePrimitives.GenericZero v1 v2 - - - /// Computes the Euclidean norm (magnitude) of the vector. - /// The vector. - /// The Euclidean norm of the vector. - static member inline norm<'T when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T :> ValueType - and 'T :> Numerics.IRootFunctions<'T>> - (v:Vector<'T>) : 'T = - - let sumSquares = Vector.dot v v - 'T.Sqrt sumSquares - - static member inline min<'T when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T : comparison - and 'T :> ValueType> - (v:Vector<'T>) : 'T = - if v.Length = 0 then invalidArg "v" "Cannot compute min of empty vector." - Acceleration.SIMDUtils.fold (fun a b -> Numerics.Vector.Min(a, b)) min v.[0] v - - static member inline max<'T when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T : comparison - and 'T :> ValueType> - (v:Vector<'T>) : 'T = - if v.Length = 0 then invalidArg "v" "Cannot compute min of empty vector." - Acceleration.SIMDUtils.fold (fun a b -> Numerics.Vector.Max(a, b)) max v.[0] v - - diff --git a/src/FSharp.Stats/AlgTypes/VectorExt.fs b/src/FSharp.Stats/AlgTypes/VectorExt.fs deleted file mode 100644 index 3c72a6f84..000000000 --- a/src/FSharp.Stats/AlgTypes/VectorExt.fs +++ /dev/null @@ -1,226 +0,0 @@ -namespace FSharp.Stats - -open System -open System.Runtime.InteropServices - -[] -module Vector = - - /// Computes the vector cross product a^Tb - /// The first vector is column vector. - /// The second vector is the row vector. - /// The cross product (or outer product) of the two vectors. - let inline cross<'T when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T : equality - and 'T :> ValueType> (colvec: Vector<'T>) (rowvec:Vector<'T>) : Matrix<'T> = - //TODO: SIMD Acceleration! - - if colvec.Length <> rowvec.Length then - invalidArg "" "Vector must have the same length to compute the dot product." - let n = colvec.Length - let m = rowvec.Length - - // Allocate the n*m storage - let data = Array.zeroCreate<'T> (n * m) - - // Fill with colvec[i] * rowvec[j], typical row-major arrangement - for i in 0 .. n - 1 do - for j in 0 .. m - 1 do - data.[i * m + j] <- colvec.[i] * rowvec.[j] - - // Build the matrix (n x m) - Matrix<'T>(n, m, data) - - - /// Indexed fold over a vector - let inline foldi<'T when 'T :> Numerics.INumber<'T>> f (state: 'T) (v: Vector<'T>) : 'T = - let mutable acc = state - for i = 0 to v.Length - 1 do - acc <- f i acc v.[i] - acc - - /// Indexed map over a vector - let inline mapi<'T when 'T :> Numerics.INumber<'T>> (f: int -> 'T -> 'T) (v: Vector<'T>) : Vector<'T> = - Array.mapi f v - - /// Filter vector elements by predicate - let inline filter<'T when 'T :> Numerics.INumber<'T>> (predicate: 'T -> bool) (v: Vector<'T>) : Vector<'T> = - Array.filter predicate v - - /// Initialize vector by index-based generator - let inline init<'T when 'T :> Numerics.INumber<'T>> (n: int) (f: int -> 'T) : Vector<'T> = - Array.init n f - - /// Extract a slice from a vector - let inline slice<'T when 'T :> Numerics.INumber<'T>> (start: int) (length: int) (v: Vector<'T>) : Vector<'T> = - Array.sub v start length - - /// Find index of maximum value - let inline argmax<'T when 'T :> Numerics.INumber<'T> and 'T : comparison> (v: Vector<'T>) : int = - let mutable maxIdx = 0 - let mutable maxVal = v.[0] - for i = 1 to v.Length - 1 do - if v.[i] > maxVal then - maxVal <- v.[i] - maxIdx <- i - maxIdx - - /// Find index of minimum value - let inline argmin<'T when 'T :> Numerics.INumber<'T> and 'T : comparison> (v: Vector<'T>) : int = - let mutable minIdx = 0 - let mutable minVal = v.[0] - for i = 1 to v.Length - 1 do - if v.[i] < minVal then - minVal <- v.[i] - minIdx <- i - minIdx - - /// Pad vector to a given length with a constant value - let inline padRight<'T when 'T :> Numerics.INumber<'T>> (length: int) (value: 'T) (v: Vector<'T>) : Vector<'T> = - if v.Length >= length then v - else - Array.init length (fun i -> if i < v.Length then v.[i] else value) - - /// Zip two vectors into (index, left, right) - let inline zip<'T when 'T :> Numerics.INumber<'T>> (v1: Vector<'T>) (v2: Vector<'T>) : (int * 'T * 'T)[] = - Array.init (min v1.Length v2.Length) (fun i -> i, v1.[i], v2.[i]) - - - - /// Find index of minimum value using projection - let inline argminBy<'T, 'U - when 'T :> Numerics.INumber<'T> and 'U : comparison> - (f: 'T -> 'U) (v: Vector<'T>) : int = - let mutable minIdx = 0 - let mutable minVal = f v.[0] - for i = 1 to v.Length - 1 do - let candidate = f v.[i] - if candidate < minVal then - minVal <- candidate - minIdx <- i - minIdx - - /// Find index of maximum value using projection - let inline argmaxBy<'T, 'U - when 'T :> Numerics.INumber<'T> and 'U : comparison> - (f: 'T -> 'U) (v: Vector<'T>) : int = - let mutable maxIdx = 0 - let mutable maxVal = f v.[0] - for i = 1 to v.Length - 1 do - let candidate = f v.[i] - if candidate > maxVal then - maxVal <- candidate - maxIdx <- i - maxIdx - - /// Try to find index of first matching element - let inline tryFindIndex<'T when 'T :> Numerics.INumber<'T>> (predicate: 'T -> bool) (v: Vector<'T>) : int option = - let mutable i = 0 - let mutable found = false - while i < v.Length && not found do - if predicate v.[i] then found <- true - else i <- i + 1 - if found then Some i else None - - /// Find index of first matching element or throw - let inline findIndex<'T when 'T :> Numerics.INumber<'T>> (predicate: 'T -> bool) (v: Vector<'T>) : int = - match tryFindIndex predicate v with - | Some i -> i - | None -> failwith "Element not found." - - /// Enumerate non-zero elements with index - let inline enumerateNonZero<'T when 'T :> Numerics.INumber<'T> and 'T : equality> (v: Vector<'T>) : (int * 'T)[] = - v - |> Array.mapi (fun i x -> i, x) - |> Array.filter (fun (_, x) -> x <> 'T.Zero) - - /// Split a vector into prefix and suffix at a given index - let inline split<'T when 'T :> Numerics.INumber<'T>> (index: int) (v: Vector<'T>) : Vector<'T> * Vector<'T> = - Array.sub v 0 index, Array.sub v index (v.Length - index) - - /// Chunk a vector into equally sized pieces (last may be shorter) - let inline chunk<'T when 'T :> Numerics.INumber<'T>> (chunkSize: int) (v: Vector<'T>) : Vector<'T>[] = - let len = v.Length - [| for i in 0 .. chunkSize .. len - 1 -> - let size = min chunkSize (len - i) - Array.sub v i size |] - - /// Sliding window over the vector - let inline windowed<'T when 'T :> Numerics.INumber<'T>> (windowSize: int) (v: Vector<'T>) : Vector<'T>[] = - if windowSize > v.Length then [||] - else - [| for i in 0 .. v.Length - windowSize -> - Array.sub v i windowSize |] - - - /// - /// Splits the vector `v` into two parts based on `indices`. - /// The elements at positions in `indices` end up in `nvi`, - /// all others go into `nv`. - /// - /// Zero-based positions to extract from `v`. - /// The full vector to split. - /// (nvi, nv): nvi contains the elements at `indices`, nv contains the rest. - let splitVector (indices: int[]) (v: Vector<'T>) = - - Array.sortInPlace indices - - let n = v.Length - let k = indices.Length - - let nvi = Vector.zeroCreate<'T> k - let nv = Vector.zeroCreate<'T> (n - k) - - let mutable iInd = 0 - let mutable iNvi = 0 - let mutable iNv = 0 - - for i = 0 to n - 1 do - // If we've not exhausted the `indices` array AND the current i matches indices.[iInd] - if iInd < k && i = indices.[iInd] then - nvi.[iNvi] <- v.[i] - iNvi <- iNvi + 1 - iInd <- iInd + 1 - else - nv.[iNv] <- v.[i] - iNv <- iNv + 1 - - nvi, nv - - /// - /// Creates a new vector that is the result of applying the permutation - /// to the vector . The element result.[i] becomes b.[P(i)]. - /// - /// A permutation function of type int -> int, - /// The original vector to be permuted. Must have length n. - /// typically created by Permutation.ofArray or Permutation.ofFreshArray. - /// - /// A new vector of the same length n, reordered according to . - /// - let permuteBy (P: Permutation) (b: Vector<'T>) : Vector<'T> = - let n = b.Length - let result = Array.zeroCreate<'T> n - for i = 0 to n - 1 do - result.[i] <- b.[P i] - result - - /// - let inline ofSeq (s:seq<'T>) : Vector<'T> = - s |> Array.ofSeq - - - /// - let inline pow (power: 'T) (v:Vector<'T>) : Vector<'T> = - v |> Array.map (fun x -> GenericMath.pow x power) - - - /// Returns a subvector from offset i to the end of the vector. - let inline sub (i: int) (v: Vector<'T>) : Vector<'T> = - if i < 0 || i > v.Length then - invalidArg (nameof i) "Index out of bounds." - let len = v.Length - i - let res = Array.zeroCreate<'T> len - Array.blit v i res 0 len - res \ No newline at end of file diff --git a/src/FSharp.Stats/AlgTypes/VectorOps.fs b/src/FSharp.Stats/AlgTypes/VectorOps.fs deleted file mode 100644 index 6ca4e458b..000000000 --- a/src/FSharp.Stats/AlgTypes/VectorOps.fs +++ /dev/null @@ -1,54 +0,0 @@ -namespace FSharp.Stats - -open System - -// Fallback implementation container (Type class) -type VectorOps = - - - static member inline Plus (a: Vector<'T>, b: Vector<'T>) = Vector.add a b - static member inline Plus (a: Vector<'T>, b: 'T) = Vector.addScalar b a - static member inline Plus (a: 'T, b: Vector<'T>) = Vector.addScalar a b - - static member inline Minus (a: Vector<'T>, b: Vector<'T>) = Vector.subtract a b - static member inline Minus (a: Vector<'T>, b: 'T) = Vector.subtractScalar b a - - - static member inline Multiply (a: Vector<'T>, b: Vector<'T>) = Vector.multiply a b - static member inline Multiply (a: Vector<'T>, b: 'T) = Vector.multiplyScalar b a - static member inline Multiply (a: 'T, b: Vector<'T>) = Vector.multiplyScalar a b - - static member inline Divide (a: Vector<'T>, b: Vector<'T>) = Vector.divide a b - static member inline Divide (a: Vector<'T>, b: 'T) = Vector.divideScalar b a - - static member inline Power (a: Vector<'T>, power: 'T) = Vector.pow power a - - -// Dispatcher types (Instance resolution) -type Plus = static member inline Invoke (a: ^A, b: ^B) = ((^A or ^B or VectorOps) : (static member Plus : ^A * ^B -> _)(a, b)) -type Minus = static member inline Invoke (a: ^A, b: ^B) = ((^A or ^B or VectorOps) : (static member Minus : ^A * ^B -> _)(a, b)) -type Multiply = static member inline Invoke (a: ^A, b: ^B) = ((^A or ^B or VectorOps) : (static member Multiply : ^A * ^B -> _)(a, b)) -type Divide = static member inline Invoke (a: ^A, b: ^B) = ((^A or ^B or VectorOps) : (static member Divide : ^A * ^B -> _)(a, b)) -type Power = static member inline Invoke (a: ^A, b: ^B) = ((^A or ^B or VectorOps) : (static member Power : ^A * ^B -> _)(a, b)) - -// Operators -[] -module VectorOpsSymbols = - let inline (.+) a b = Plus.Invoke(a, b) - let inline (.-) a b = Minus.Invoke(a, b) - let inline (.*) a b = Multiply.Invoke(a, b) - let inline (./) a b = Divide.Invoke(a, b) - let inline (.^) a b = Power.Invoke(a, b) - // Dot product ( @ ) - - -//// A type extension on `'T[]` so you can do `myArray.Transposed`. -//module ArrayExtensions = - -// type Array with - -// member this.Transpose - -// with get () = -// RowVector<'T>(this) - diff --git a/src/FSharp.Stats/Algebra/EVD.fs b/src/FSharp.Stats/Algebra/EVD.fs deleted file mode 100644 index c641aad12..000000000 --- a/src/FSharp.Stats/Algebra/EVD.fs +++ /dev/null @@ -1,257 +0,0 @@ -namespace FSharp.Stats.Algebra - -open FSharp.Stats - -module EVD = - - /// Symmetric Householder reduction to tridiagonal form. - /// - /// - /// - /// - /// - /// - /// - /// - /// - let private tred2Inplace (d:float[]) (e:float[]) (v:float [,]) = - - // This is derived from the Algol procedures tred2 by - // Bowdler, Martin, Reinsch, and Wilkinson, Handbook for - // Auto. Comp., Vol.ii-Linear Algebra, and the corresponding - // Fortran subroutine in EISPACK. - - let n = v.GetLength(1) // cols count v - - for i = n - 1 downto 1 do - // Scale to avoid under/overflow. - - let mutable scale = 0.0; - let mutable h = 0.0; - for k = 0 to i-1 do - scale <- scale + abs (d.[k]) - - if scale = 0.0 then - e.[i] <- d.[i - 1] - for j = 0 to i-1 do - d.[j] <- v.[i - 1,j] - v.[i,j] <- 0.0 - v.[j,i] <- 0.0 - else - // Generate Householder vector. - - for k = 0 to i-1 do - d.[k] <- d.[k] / scale - h <- h + d.[k] * d.[k] - let mutable f = d.[i - 1] - let mutable g = if (f > 0.) then -sqrt(h) else sqrt(h) - e.[i] <- scale*g - h <- h - f*g - d.[i - 1] <- f - g - for j = 0 to i-1 do - e.[j] <- 0.0 - - // Apply similarity transformation to remaining columns. - - for j = 0 to i-1 do - f <- d.[j] - v.[j,i] <- f - g <- e.[j] + v.[j,j]*f - for k = j + 1 to i - 1 do - g <- g + v.[k,j]*d.[k] - e.[k] <- e.[k] + v.[k,j]*f - - e.[j] <- g - - f <- 0.0 - for j = 0 to i-1 do - e.[j] <- e.[j] / h - f <- f + e.[j] * d.[j] - let hh = f/(h + h) - for j = 0 to i-1 do - e.[j] <- e.[j] - hh*d.[j] - - for j = 0 to i-1 do - f <- d.[j] - g <- e.[j] - for k = j to i - 1 do - v.[k,j] <- v.[k,j] - (f*e.[k] + g*d.[k]) - - d.[j] <- v.[i - 1,j] - v.[i,j] <- 0.0 - d.[i] <- h - - // Accumulate transformations. - for i = 0 to n - 2 do - v.[n - 1,i] <- v.[i,i] - v.[i,i] <- 1.0; - let h = d.[i + 1] - if (h <> 0.0) then - for k = 0 to i do - d.[k] <- v.[k,i + 1]/h - for j = 0 to i do - let mutable g = 0.0 - for k = 0 to i do - g <- g + v.[k,i + 1]*v.[k,j] - for k = 0 to i do - v.[k,j] <- v.[k,j] - g*d.[k] - for k = 0 to i do - v.[k,i + 1] <- 0.0 - - for j = 0 to n-1 do - d.[j] <- v.[n - 1,j] - v.[n - 1,j] <- 0.0 - - v.[n - 1,n - 1] <- 1.0 - e.[0] <- 0.0 - - - /// Symmetric tridiagonal QL algorithm. - /// - /// - /// - /// - /// - /// - /// - /// - /// - let private tql2Inplace (d:float[]) (e:float[]) (v:float [,]) = - - // This is derived from the Algol procedures tql2, by - // Bowdler, Martin, Reinsch, and Wilkinson, Handbook for - // Auto. Comp., Vol.ii-Linear Algebra, and the corresponding - // Fortran subroutine in EISPACK. - - let n = v.GetLength(1) // cols count v - - for i = 1 to n-1 do - e.[i - 1] <- e.[i] - e.[n - 1] <- 0.0 - - let mutable f = 0.0 - let mutable tst1 = 0.0 - let mutable eps = 2.0**(-52.0) - for l = 0 to n-1 do - // Find small subdiagonal element - - tst1 <- max tst1 (abs(d.[l]) + abs(e.[l])) - let m = - let rec loop m = - if m > n-2 || (abs(e.[m]) <= eps*tst1) then - m - else - loop (m+1) - loop l - - // If m == l, d.[l] is an eigenvalue, - // otherwise, iterate. - - if (m > l) then - let rec loop iter = - // (Could check iteration count here.) - - // Compute implicit shift - - let mutable g = d.[l] - let mutable p = (d.[l + 1] - g)/(2.0*e.[l]) - let mutable r = if (p < 0.) then -(Geometry.hypot p 1.0) else Geometry.hypot p 1.0 - d.[l] <- e.[l]/(p + r) - d.[l + 1] <- e.[l]*(p + r) - let dl1 = d.[l + 1]; - let mutable h = g - d.[l] - for i = l + 2 to n-1 do - d.[i] <- d.[i] - h; - - f <- f + h - - // Implicit QL transformation. - - p <- d.[m]; - let mutable c = 1.0 - let mutable c2 = c - let mutable c3 = c - let mutable el1 = e.[l + 1] - let mutable s = 0.0 - let mutable s2 = 0.0 - for i = m-1 downto l do - c3 <- c2 - c2 <- c - s2 <- s - g <- c*e.[i] - h <- c*p - r <- Geometry.hypot p e.[i] - e.[i + 1] <- s*r - s <- e.[i]/r - c <- p/r - p <- c*d.[i] - s*g - d.[i + 1] <- h + s*(c*g + s*d.[i]) - - // Accumulate transformation. - - for k = 0 to n-1 do - h <- v.[k,i + 1] - v.[k,i + 1] <- s*v.[k,i] + c*h - v.[k,i] <- c*v.[k,i] - s*h - - p <- -s*s2*c3*el1*e.[l]/dl1 - e.[l] <- s*p - d.[l] <- c*p - - // Check for convergence. - if (abs(e.[l]) > eps*tst1) then - loop (iter+1) - loop 0 - - d.[l] <- d.[l] + f - e.[l] <- 0.0 - - - // Sort eigenvalues and corresponding vectors. - for i = 0 to n-2 do - let mutable k = i - let mutable p = d.[i] - for j = i+1 to n-1 do - if (d.[j] < p) then - k <- j - p <- d.[j] - - if (k <> i) then - d.[k] <- d.[i]; - d.[i] <- p; - for j = 0 to n-1 do - p <- v.[j,i] - v.[j,i] <- v.[j,k] - v.[j,k] <- p - - /// Computes the - /// - /// - /// - /// - /// - /// - /// - let symmetricEvd (a:float[,]) = - - // number of columns in A - let n = a.GetLength(1) - // Init array for the real parts of the eigenvalues - let d = Array.init n (fun j -> a.[n - 1,j]) - // Init array for the imaginary parts of the eigenvalues - let e = Array.zeroCreate n - - // Eigenvalue matrix - let v = Array2D.copy a - - // Tridiagonalize. - tred2Inplace d e v - // Diagonalize. - tql2Inplace d e v - - (e,v,d) - - let getRealEigenvalues (e,v,d) = d - let getImaginaryEigenvalues (e,v,d) = e - let getEigenvalueMAtrix (e,v,d) = v - diff --git a/src/FSharp.Stats/Algebra/LinearAlgebra.fs b/src/FSharp.Stats/Algebra/LinearAlgebra.fs deleted file mode 100644 index 9585ee434..000000000 --- a/src/FSharp.Stats/Algebra/LinearAlgebra.fs +++ /dev/null @@ -1,806 +0,0 @@ -namespace FSharp.Stats.Algebra - - -open System -open FSharp.Stats - -type LinearAlgebra = - - /// Subtract `scaleVal * src[srcOffset..srcOffset+count-1]` from - /// `dst[dstOffset..dstOffset+count-1]` in place. - static member inline subScaledRowInPlace - (scaleVal : 'T) - (dstOffset : int) - (srcOffset : int) - (count : int) - (dst : 'T[]) - (src : 'T[]) = - - let scaleVec = Numerics.Vector<'T>(scaleVal) - - // Vector-level callback: dstVec - (scaleVal * srcVec) - let fv (dstVec: Numerics.Vector<'T>) (srcVec: Numerics.Vector<'T>) = - dstVec - (scaleVec * srcVec) - - // Scalar fallback: d - (scaleVal * s) - let f (d: 'T) (s: 'T) = - d - (scaleVal * s) - Acceleration.SIMDRangeUtils.map2RangeInPlace fv f dstOffset srcOffset count dst src - - - //static member inline householderTransform - // (A: Matrix<'T>) (i: int) : Vector<'T> = - // let n = A.NumRows - - // let v = Vector.zeroCreate<'T> n - // let aCol = Matrix.getCol i A - // let norm = Vector.norm aCol.[i..] // ToDO: use a more efficient norm calculation - // v.[i] <- aCol.[i] + if aCol.[i] >= 'T.Zero then norm else -norm - // for j = i + 1 to n - 1 do - // v.[j] <- aCol.[j] - // v - - - - /// QR decomposition using modified Gram-Schmidt - /// Returns Q and R such that A = QR - static member inline qrModifiedGramSchmidt<'T when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T : equality - and 'T :> ValueType - and 'T :> Numerics.IRootFunctions<'T>> - (A: Matrix<'T>) : Matrix<'T> * Matrix<'T> = - - let m, n = A.NumRows, A.NumCols - - if m < n then - invalidArg "A" $"QR decomposition via Modified Gram-Schmidt requires m ≥ n, but got {m}×{n} matrix." - - - let r = Matrix.zeroCreate n n - let qCols: Vector<'T>[] = Array.zeroCreate n - let aCols = Matrix.getCols A - - for j = 0 to n - 1 do - let v = Array.copy aCols.[j] - - for i = 0 to j - 1 do - let qi = qCols.[i] - let rij = Vector.dot qi v - r.[i, j] <- rij - for k = 0 to m - 1 do - v.[k] <- v.[k] - rij * qi.[k] - - let norm = Vector.norm v - r.[j, j] <- norm - let qj = Vector.divideScalar norm v - qCols.[j] <- qj - - let qData = Array.zeroCreate (m * n) - for j = 0 to n - 1 do - for i = 0 to m - 1 do - qData.[i * n + j] <- qCols.[j].[i] - - Matrix(m, n, qData), r - - /// Back substitute to solve R * x = y - /// R is upper triangular - static member inline backSubstitute<'T when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T : equality - and 'T :> ValueType> - (r: Matrix<'T>) - (y: Vector<'T>) : Vector<'T> = - - let n = r.NumRows - - if r.NumCols <> n || y.Length <> n then - invalidArg "dimensions" "R must be square and match the length of y" - - let x = Array.zeroCreate<'T> n - - for i = n - 1 downto 0 do - let mutable sum = y.[i] - for j = i + 1 to n - 1 do - sum <- sum - r.[i, j] * x.[j] - let diag = r.[i, i] - if diag = 'T.Zero then - invalidArg $"r[{i},{i}]" "Diagonal element is zero. Cannot divide." - x.[i] <- sum / diag - - x - - - - - /// Solve A * x = b for x, where A is a square matrix (n×n) and b is a vector (length n). - static member inline solveLinearQR<'T when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T : equality - and 'T :> ValueType - and 'T :> Numerics.IRootFunctions<'T>> - (A: Matrix<'T>) - (b: Vector<'T>) : Vector<'T> = - - if A.NumRows <> b.Length then - invalidArg "b" "Vector length must match number of rows in matrix A" - - let Q, R = LinearAlgebra.qrModifiedGramSchmidt A - let Qt = Q.Transpose() - let y = Matrix.muliplyVector Qt b - LinearAlgebra.backSubstitute R y - - - - /// Solve K * X = B for X, where K is a triangular matrix (lower or upper). - /// K is square of size n×n; B is n×m. Returns an n×m result X. - static member inline solveTriangularLinearSystems - (K : Matrix<'T>) - (B : Matrix<'T>) - (isLower : bool) - : Matrix<'T> = - - /// Multiply `arr[offset..offset+count-1]` by `scaleVal` in place - let inline scaleRowInPlace - (scaleVal : 'T) - (offset : int) - (count : int) - (arr : 'T[]) = - - let scaleVec = Numerics.Vector<'T>(scaleVal) - - // Vector-level callback: chunk * scaleVal - let fv (chunk: Numerics.Vector<'T>) = - chunk * scaleVec - - // Scalar fallback: x * scaleVal - let f (x: 'T) = x * scaleVal - - // mapRangeInPlace fv f offset count arr - Acceleration.SIMDRangeUtils.mapRangeInPlace fv f offset count arr - - // Check shape consistency - let nK, mK = K.NumRows, K.NumCols - let nB, mB = B.NumRows, B.NumCols - if nK <> mK || nB <> nK then - invalidArg "Matrix" "K must be square and B must have matching row count for K" - - // Copy B into a new matrix X (the solution) - let X = Matrix<'T>(B.NumRows, B.NumCols, Array.copy B.Data) - - let n = nK // size of the NxN triangular matrix K - let m = mB // # of columns in B (and thus X) - - let Kdata = K.Data - let Xdata = X.Data - - // For row i, the contiguous slice in Xdata is [i*m .. i*m + m - 1] - // => offset = i*m, length = m - - if isLower then - // ------ Forward Substitution ------ - // for i in [0..n-1]: - // X[i,*] <- X[i,*] - Σ_{j=0..i-1} [K[i,j] * X[j,*]] - // then scale row i by 1/K[i,i] - for i = 0 to n - 1 do - let baseI = i * m - // Subtract scaled rows for j in [0..i-1] - for j = 0 to i - 1 do - let kij = Kdata.[i * n + j] // K[i,j] - //if kij <> 'T.Zero then // normaly speed things up, but -inf * 0 = nan - let baseJ = j * m - // subScaledRowInPlace scaleVal dstOffset srcOffset count dst src - LinearAlgebra.subScaledRowInPlace - kij - baseI // row i offset in X - baseJ // row j offset in X - m // number of columns - Xdata - Xdata - //LinearAlgebra.subScaledRowInPlace - // Xdata - // baseI // row i offset in X - // Xdata - // baseJ // row j offset in X - // m // number of columns - // kij - - - - // Divide row i by the diagonal K[i,i] - let diag = Kdata.[i * n + i] - let invDiag = 'T.One / diag - // scaleRowInPlace scaleVal offset count arr - scaleRowInPlace - invDiag - baseI - m - Xdata - else - // ------ Backward Substitution ------ - // for i in [n-1..0]: - // X[i,*] <- X[i,*] - Σ_{j=i+1..n-1} [K[i,j] * X[j,*]] - // then scale row i by 1/K[i,i] - for i = n - 1 downto 0 do - let baseI = i * m - for j = i + 1 to n - 1 do - let kij = Kdata.[i * n + j] // K[i,j] - //if kij <> 'T.Zero then // normaly speed things up, but -inf * 0 = nan - let baseJ = j * m - LinearAlgebra.subScaledRowInPlace - kij - baseI - baseJ - m - Xdata - Xdata - let diag = Kdata.[i * n + i] - let invDiag = 'T.One / diag - scaleRowInPlace - invDiag - baseI - m - Xdata - - X - - - - /// Solve K * x = v (triangular system) in-place, returning a copy of x. - /// K must be n×n, v must be length n. - /// isLower = true => forward substitution - /// isLower = false => backward substitution - static member inline solveTriangularLinearSystem - (K : Matrix<'T>) - (v : Vector<'T>) - (isLower : bool) - : Vector<'T> = - - let nK, mK = K.NumRows, K.NumCols - let nV = v.Length - if nK <> mK || nV <> nK then - invalidArg (nameof K) "K must be square, and v must match its dimension." - - let x = Array.copy v - let Kdata = K.Data // row-major flattened - - // Forward or backward substitution - if isLower then - // For i in [0..n-1]: - // x[i] <- ( x[i] - sum_{j=0..i-1}(K[i,j] * x[j]) ) / K[i,i] - for i = 0 to nK - 1 do - let mutable s = x.[i] - let rowOffset = i * nK - for j = 0 to i - 1 do - s <- s - (Kdata.[rowOffset + j] * x.[j]) - let diag = Kdata.[rowOffset + i] - if diag = 'T.Zero then - invalidArg $"K[{i},{i}]" "Diagonal element is zero. Cannot divide." - x.[i] <- s / diag - else - // For i in [n-1..downto..0]: - // x[i] <- ( x[i] - sum_{j=i+1..n-1}(K[i,j] * x[j]) ) / K[i,i] - for i = nK - 1 downto 0 do - let mutable s = x.[i] - let rowOffset = i * nK - for j = i + 1 to nK - 1 do - s <- s - (Kdata.[rowOffset + j] * x.[j]) - let diag = Kdata.[rowOffset + i] - if diag = 'T.Zero then - invalidArg $"K[{i},{i}]" "Diagonal element is zero. Cannot divide." - x.[i] <- s / diag - - x - - - - ///// QR decomposition using Householder reflections - //static member inline qrDecompose (A : Matrix<'T>) : (Matrix<'T> * Matrix<'T>) = - //// former QR - // let updateQ (Q : Matrix<'T>) (v : Vector<'T>) = - // let nQ, mQ = Q.NumRows, Q.NumCols - // let n = v.Length - // let Qv = Vector.zeroCreate<'T> nQ - // for i = 0 to nQ - 1 do - // // offset in Q.Data for row i is i*mQ - // let rowOffset = i * mQ + (mQ - n) - // // Dot the subrange Q[i, mQ-n..mQ-1] with v[0..n-1] - // Qv.[i] <- Acceleration.SIMDRangeUtils.dotRange Q.Data rowOffset v 0 n - - // // Update each row i in the subrange of columns [mQ-n..mQ-1] - // // Q[i, j] -= 2 * Qv[i] * v[j - (mQ - n)] - // for i = 0 to nQ - 1 do - // let alpha = Qv.[i] + Qv.[i] - // // We want to do a row operation: Q[i, (mQ-n)..(mQ-1)] - // // = Q[i, (mQ-n)..(mQ-1)] - alpha * v[0..n-1]. - // let rowOffset = i * mQ + (mQ - n) - // //LinearAlgebra.subScaledRowInPlace Q.Data rowOffset v 0 n alpha - // LinearAlgebra.subScaledRowInPlace alpha rowOffset 0 n Q.Data v - - // // TODO: Refector in Householder module - // let normalize (v: Vector<'T>) : Vector<'T> = - // let norm = Vector.norm v - // if norm = 'T.Zero then v - // else - // Array.map (fun x -> x / norm) v - - // let m, n = A.NumRows, A.NumCols - - // // Q starts as identity(n) - // let Q = Matrix.identity m - // let R = Matrix.copy A - - // for i = 0 to (min n m) - 1 do - // let x = [| for k in i .. m - 1 -> R.[k, i] |] - // //let a = Matrix.getCol i R - // let hh = Householder.create x //a.[i..] Create Householder reflector for column i - // let v = hh.V |> normalize - // updateQ Q v - // Householder.applyLeft(hh, R, i) - - - // Q, R - - - /// QR decomposition using Householder reflections - static member inline qrDecompose (A : Matrix<'T>) : (Matrix<'T> * Matrix<'T>) = - // former QR - - /// Compute normalized Householder vector from a subcolumn x - let householderVector (x: 'T[]) : 'T[] = - let norm = sqrt (Array.sumBy (fun xi -> xi * xi) x) - let v = Array.copy x - v.[0] <- v.[0] + (if x.[0] >= 'T.Zero then norm else -norm) - let norm_v = sqrt (Array.sumBy (fun vi -> vi * vi) v) - if norm_v = 'T.Zero then v - else Array.map (fun vi -> vi / norm_v) v - - /// Update Q: Q ← Q * Hᵢ using Householder vector v (from column i) - let updateQ (Q: Matrix<'T>) (v: 'T[]) (i: int) = - let nQ, mQ = Q.NumRows, Q.NumCols - for row = 0 to nQ - 1 do - let mutable dot = 'T.Zero - for k = 0 to v.Length - 1 do - dot <- dot + Q.[row, i + k] * v.[k] - let alpha = dot + dot - for k = 0 to v.Length - 1 do - Q.[row, i + k] <- Q.[row, i + k] - alpha * v.[k] - - /// Apply Hᵢ to R from the left: R ← H * R - let applyHouseholderLeft (R: Matrix<'T>) (v: 'T[]) (i: int) = - let m, n = R.NumRows, R.NumCols - for col = i to n - 1 do - let mutable dot = 'T.Zero - for k = 0 to v.Length - 1 do - let row = i + k - if row < m then - dot <- dot + v.[k] * R.[row, col] - let alpha = dot + dot - for k = 0 to v.Length - 1 do - let row = i + k - if row < m then - R.[row, col] <- R.[row, col] - alpha * v.[k] - - /// Main QR decomposition function - let qrDecompose (A: Matrix<'T>) : Matrix<'T> * Matrix<'T> = - let m, n = A.NumRows, A.NumCols - let Q = Matrix.identity m - let R = Matrix.copy A - - for i = 0 to min m n - 1 do - let x = [| for k in i .. m - 1 -> R.[k, i] |] - let v = householderVector x - updateQ Q v i - applyHouseholderLeft R v i - - Q, R - - qrDecompose A - - - - - /// Given A[m,n] and B[m] solves AX = B for X[n].
- /// When m => n, have over constrained system, finds least squares solution for X.
- /// When m < n, have under constrained system, finds least norm solution for X.
- static member inline leastSquares - (A : Matrix<'T>) - (b: Vector<'T>) = - // Maybe rename to leastSquaresQR? - let (m,n) = A.NumRows, A.NumCols - - // Is this an overdetermined or underdetermined system? - if m >= n then - //printfn "Least squares: solving %dx%d system with %d equations." m n n - let Qm, R = LinearAlgebra.qrDecompose A - let Qtb = Qm.Transpose() * b - LinearAlgebra.solveTriangularLinearSystem R.[0..n-1,0..n-1] Qtb.[0..n-1] false - else - // underdetermined: solve A^T * x = 0 with min ||x|| - //printfn "underdetermined- Least squares: solving %dx%d system with %d equations." m n n - let AT = A.Transpose() - let Q, R = LinearAlgebra.qrDecompose AT - let RT = R.Transpose() - let s = LinearAlgebra.solveTriangularLinearSystem RT.[0..m-1, 0..m-1] b true - Q.[0.., 0..m-1] * s - - //let AT = A.Transpose() - //let Q, R = LinearAlgebra.qrDecompose AT - //let y = Q.Transpose() * b - //let s = LinearAlgebra.solveTriangularLinearSystem R.[0..m-1, 0..m-1] y.[0..m-1] false - - //Q.[0..n,0..m] * s - - - - - //let AT = A.Transpose() - //let QT, RT = LinearAlgebra.qrDecompose AT - //let y = QT.Transpose() * b - //let s = LinearAlgebra.solveTriangularLinearSystem RT.[0..m-1, 0..m-1] y.[0..m-1] false - //let s = LinearAlgebra.solveTriangularLinearSystem R.[0..m-1,0..m-1] Qtb false - //Vector.init n (fun i -> if i < m then s.[i] else 'T.Zero) - - //// underdetermined: solve min ||x|| such that Ax = b - //let AT = A.Transpose() - //let QT, RT = LinearAlgebra.qrDecompose AT - //let y = LinearAlgebra.solveTriangularLinearSystem (RT.Transpose().[0..m-1, 0..m-1]) b false - //QT.[*, 0..m-1] * y - - - /// - /// Computes the Cholesky factor L of a symmetric positive-definite matrix A, - /// returning L as a lower-triangular such that A = L * L^T. - /// Throws if A is not positive-definite (i.e., if any diagonal element ≤ 0). - /// - static member inline cholesky - (A : Matrix<'T>) - : Matrix<'T> = - - let n = A.NumRows - let m = A.NumCols - if n <> m then - invalidArg (nameof A) "Cholesky: matrix must be square." - - let dataA = A.Data - // We'll create an n×n zeroed matrix for L - let Ldata = Array.zeroCreate<'T> (n * n) - - // Helper function for indexing row-major arrays: - let inline idx r c = r * n + c - - for j = 0 to n - 1 do - // 1) Diagonal element L[j,j] - // L[j,j] = sqrt(A[j,j] - ∑(k=0..j-1) L[j,k]^2) - let mutable sumjj = dataA.[idx j j] - for k = 0 to j - 1 do - let ljk = Ldata.[idx j k] - sumjj <- sumjj - (ljk * ljk) - - // Check positivity - if sumjj <= 'T.Zero then - invalidArg "A" "Cholesky: matrix not positive-definite (diagonal <= 0)." - - let ljj = GenericMath.sqrt sumjj - Ldata.[idx j j] <- ljj - - // 2) Off-diagonal: L[i,j] for i=j+1..n-1 - // L[i,j] = (A[i,j] - ∑(k=0..j-1) L[i,k]*L[j,k]) / L[j,j] - for i = j + 1 to n - 1 do - let mutable sumij = dataA.[idx i j] - for k = 0 to j - 1 do - sumij <- sumij - (Ldata.[idx i k] * Ldata.[idx j k]) - Ldata.[idx i j] <- sumij / ljj - - Matrix<'T>(n, n, Ldata) - - - /// Given A[m,n] and b[m] solves AX = b for X[n].
- /// When the system is under constrained,
- /// for example when the columns of A are not linearly independent,
- /// then it will not give sensible results.
- static member inline leastSquaresCholesky - (A : Matrix<'T>) - (b: Vector<'T>) = - - if b.Length <> A.NumRows then - invalidArg "b" "Length of b must match the number of rows of A." - - let AT = A.Transpose() - - let upper = (AT * A) |> LinearAlgebra.cholesky - let gamma = - LinearAlgebra.solveTriangularLinearSystem(upper) (AT * b) true - let beta = - LinearAlgebra.solveTriangularLinearSystem (upper.Transpose()) gamma false - beta - - - /// computes the hat matrix by the QR decomposition of the designmatrix used in ordinary least squares approaches - static member inline hatMatrix - (designMatrix: Matrix<'T>) = - let qm,R = LinearAlgebra.qrDecompose designMatrix - let q1 = qm.GetSlice ((Some 0),(Some (qm.NumRows-1)),(Some 0),(Some (R.NumCols-1))) - // computes the hatmatrix - q1 * q1.Transpose() - - - /// computes the leverages of every dataPoint of a dataSet given by the diagonal of the hat matrix. - static member inline leverageBy - (hatMatrix: Matrix<'T>) = - - Matrix.getDiagonal hatMatrix - - - /// computes the leverage directly by QR decomposition of the designmatrix used in ordinary least squares approaches
- /// and computing of the diagnonal entries of the Hat matrix, known as the leverages of the regressors
- static member inline leverage - (designMatrix: Matrix<'T>) = - - let qm,R = LinearAlgebra.qrDecompose designMatrix - let q1 = qm.GetSlice ((Some 0),(Some (qm.NumRows-1)),(Some 0),(Some (R.NumCols-1))) - - Vector.init q1.NumRows (fun i -> - let mutable sumOfSquares = 'T.Zero - for j = 0 to q1.NumCols - 1 do - let x = q1.[i, j] - sumOfSquares <- sumOfSquares + x * x - sumOfSquares - ) - - - /// - /// Computes the LU factorization of a square matrix A with partial pivoting. - /// That is, P * A = L * U, where P is a permutation, and L, U are lower/upper triangular. - /// Returns (Permutation P, L, U). - /// - static member inline luDecompose (A : Matrix<'T>) = - let n, m = A.NumRows, A.NumCols - if n <> m then - invalidArg (nameof A) "LU: A must be square." - - let U = Matrix.copy A // We'll transform U in place. - let L = Matrix.zeroCreate n n // We'll fill L below the diagonal. - let P = [| 0 .. n-1 |] // Pivot array - - // Row-swap function for U: swap entire row i, row j - let swapRows (M: Matrix<'T>) i j = - let rowI = i - let rowJ = j - for col = 0 to m - 1 do - let tmp = M.[rowI, col] - M.[rowI, col] <- M.[rowJ, col] - M.[rowJ, col] <- tmp - - // Row-swap function for L: only swap the columns up to i-1 (since the rest is not yet set). - // Because in Doolittle's method, columns [0..i-1] of L are already determined at pivot step i. - let swapRowsPartial (M: Matrix<'T>) i j pivotCol = - for col = 0 to pivotCol - 1 do - let tmp = M.[i, col] - M.[i, col] <- M.[j, col] - M.[j, col] <- tmp - - // Perform the decomposition - for i = 0 to n - 2 do - // 1) Find pivot row by max absolute value in U column i - let mutable pivotRow = i - let mutable pivotVal = abs(U.[pivotRow, i]) - for r = i + 1 to n - 1 do - let candidate = abs(U.[r, i]) - if candidate > pivotVal then - pivotVal <- candidate - pivotRow <- r - - // 2) If pivotRow != i, swap rows in U, swap partial in L, and update pivot array - if pivotRow <> i then - swapRows U i pivotRow - swapRowsPartial L i pivotRow i - let tmp = P.[i] - P.[i] <- P.[pivotRow] - P.[pivotRow] <- tmp - - // 3) Eliminate below pivot - for j = i + 1 to n - 1 do - // L[j,i] = U[j,i] / U[i,i] - L.[j,i] <- U.[j,i] / U.[i,i] - // Update row j of U - for k = i + 1 to n - 1 do - U.[j,k] <- U.[j,k] - L.[j,i] * U.[i,k] - U.[j,i] <- 'T.Zero - - // Add identity to L (so diagonal = 1.0) - // i.e., L[i,i] <- 1.0 - for i = 0 to n - 1 do - L.[i,i] <- 'T.One - - // Return the permutation (as an array or your custom Permutation type), - // plus the final L and U - (Permutation.ofArray P, L, U) - - /// - /// Solves the system of linear equations A * X = B using LU factorization. - /// A must be square; B must have the same number of rows as A. - /// Returns a matrix X s.t. A*X = B. - /// - static member inline solveLinearSystems (A: Matrix<'T>) (B: Matrix<'T>) = - let nA, mA = A.NumRows, A.NumCols - let nB, mB = B.NumRows, B.NumCols - - // 1) Check shape: A must be square, B's rows must match A's rows - if nA <> mA then - invalidArg (nameof A) "Matrix A must be square." - if nB <> nA then - invalidArg (nameof B) "Matrix B must have same number of rows as A." - - // 2) Factor A -> (P, L, U) - let (P, L, U) = LinearAlgebra.luDecompose A - - // 3) Permute B according to P (i.e., reorder rows) - let Bpermuted = B |> Matrix.permuteRowsBy P - - // 4) Forward substitution: solve L * Y = Bpermuted - let Y = LinearAlgebra.solveTriangularLinearSystems L Bpermuted true // isLower = true - - // 5) Back substitution: solve U * X = Y - let X = LinearAlgebra.solveTriangularLinearSystems U Y false // isLower = false - - X - - /// - /// Solves the system A * x = b for x, using LU factorization with partial pivoting. - /// A must be square, and b must have length = A.NumRows. - /// - static member inline solveLinearSystem (A : Matrix<'T>) (b : Vector<'T>) = - let n, m = A.NumRows, A.NumCols - if n <> m then - invalidArg (nameof A) "Matrix A must be square." - if b.Length <> n then - invalidArg (nameof b) "Vector b must have length = A.NumRows." - - // 1) Factor A => (P, L, U) - let (P, L, U) = LinearAlgebra.luDecompose A - - // 2) Permute b according to P - let bPermuted = b |> Vector.permuteBy P - - // 3) Forward solve: L * y = bPermuted - let y = LinearAlgebra.solveTriangularLinearSystem L bPermuted true // isLower = true - - // 4) Back solve: U * x = y - let x = LinearAlgebra.solveTriangularLinearSystem U y false // isLower = false - - x - - /// - /// Computes the inverse of a square matrix A using its LU factorization. - /// If A is n×n, we factor A = P * L * U, then solve A * X = I for X, returning X = A^-1. - /// - /// A square matrix of size n×n. - /// The inverse of A, an n×n matrix. - /// - /// Thrown if A is not square, or if factorization fails (e.g., if A is singular). - /// - static member inline inverse (A: Matrix<'T>) : Matrix<'T> = - let n, m = A.NumRows, A.NumCols - if n <> m then - invalidArg (nameof A) "Matrix must be square when computing its inverse." - - // 1) Factor A => P, L, U - let (P, L, U) = LinearAlgebra.luDecompose A - - // 2) Build the identity matrix I, size n - let I = Matrix.identity n - - // 3) Permute I's rows by P (so effectively P*I) - let IPerm = I |> Matrix.permuteRowsBy P - - // 4) Forward substitution: solve L * Y = IPerm - let Y = LinearAlgebra.solveTriangularLinearSystems L IPerm true - - // 5) Back substitution: solve U * X = Y - let X = LinearAlgebra.solveTriangularLinearSystems U Y false - - // X is A^-1 - X - - - /// - /// Computes the Moore-Penrose pseudoinverse of a matrix using a QR-based approach. - /// If the matrix is overdetermined (m > n), returns (R⁻¹ Qᵀ) for A = Q R with A[m×n]. - /// If underdetermined (m < n), uses the transpose trick, then returns the transpose of the partial solution. - /// - /// An m×n matrix. - /// The (n×m) pseudoinverse of . - static member inline pseudoInvers (matrix: Matrix<'T>) = - let m, n = matrix.NumRows, matrix.NumCols - - // Overdetermined: A is m×n with m > n - if m > n then - // A = Q (m×m) * R (m×n) [or economy size Q (m×n), R (n×n)] - let qm, R = LinearAlgebra.qrDecompose matrix - // Instead of multiplying qm.Transpose by identity(m×m), just use qm.Transpose - // Next, we want sub-blocks: R is m×n, but we only need the top n×n portion, - // and we want the top-left n×m portion of qm.Transpose. - let Qt = qm.Transpose() - // Solve R[0..n-1, 0..n-1] * X = Qt[0..n-1, 0..m-1] (back-substitution) - LinearAlgebra.solveTriangularLinearSystems - R.[0..n-1, 0..n-1] - Qt.[0..n-1, 0..m-1] - false - - // Underdetermined: A is m×n with m < n - else - // We do matrix.Transpose => n×m - // Then QR => qm (n×n?), R (n×m?), etc. - let qm, R = LinearAlgebra.qrDecompose (matrix.Transpose()) - // Again skip identity multiply: just use qm.Transpose - let Qt = qm.Transpose() - // Solve R[0..m-1, 0..m-1] * X = Qt[0..m-1, 0..n-1] - let s = - LinearAlgebra.solveTriangularLinearSystems - R.[0..m-1, 0..m-1] - Qt.[0..m-1, 0..n-1] - false - // Return sᵀ => the actual pseudoinverse shape (n×m) - s.Transpose() - - - /// - /// Computes the determinant of a square matrix A by factoring A = P * L * U, - /// then det(A) = sign(P) * ∏ diag(U). - /// (Assumes L has diag=1, as in Doolittle.) - /// - static member inline determinant (A: Matrix) : float = - let n = A.NumRows - if n <> A.NumCols then - invalidArg (nameof A) "Matrix must be square." - - // 1) Factor A => (P, L, U) - let (P, L, U) = LinearAlgebra.luDecompose A - - // 2) Compute sign from the permutation P with domain size n - let permSign = Permutation.sign n P - - // 3) Product of diag(U) - let diagProd = - let mutable product = 1.0 - for i = 0 to n - 1 do - product <- product * U.Data.[i*n + i] - product - - // 4) Return sign(P) * product - permSign * diagProd - - - static member inline SVD (a:Matrix) = - let (umatrix,s,vmatrix) = SVD.computeInPlace (a.toArray2D()) - //Matrix.diag - s,Matrix.ofArray2D umatrix,Matrix.ofArray2D vmatrix - //(Matrix.ofArray2D umatrix,s,Matrix.ofArray2D vmatrix) - - static member inline symmetricEigenspectrum (a:Matrix) = - let (e,v,d) = EVD.symmetricEvd (a.toArray2D()) - (Matrix.ofArray2D v, d) - - ///// Synonym: kernel / right null space. Returns an orthonormal basis for the null space of matrix A (Ax = 0).
The accuracy defines a threshold whether a singular value is considered as zero (default: 1e-08). - //static member nullspace(?Accuracy :float ) = - - // let accuracy = defaultArg Accuracy 1e-08 - - // fun (a: Matrix) -> - - // // Either MKL or fallback implementation of the full SVD - // let (sigma,U,Vt) = LinearAlgebra.SVD a - - // // The rank is the number of nonzero singular values - // let rank = - // sigma - // |> Seq.sumBy (fun x -> if x >= accuracy then 1 else 0) - - // let count = Vt.NumRows - rank - - // Matrix.getRows Vt rank count - // |> Matrix.transpose \ No newline at end of file diff --git a/src/FSharp.Stats/Algebra/SVD.fs b/src/FSharp.Stats/Algebra/SVD.fs deleted file mode 100644 index 35a9408ea..000000000 --- a/src/FSharp.Stats/Algebra/SVD.fs +++ /dev/null @@ -1,567 +0,0 @@ -namespace FSharp.Stats.Algebra - - -open System -open FSharp.Stats -open FSharp.Stats.Acceleration - -type Bidiagonalization() = - - static member inline bidiagonalizeInPlace<'T - when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T : comparison - and 'T :> ValueType - and 'T :> Numerics.IRootFunctions<'T>> - (A: Matrix<'T>) : unit = - - let m = A.NumCols - let n = A.NumRows - let minMN = min m n - - for k = 0 to minMN - 1 do - // --- LEFT REFLECTION: Column k (zero below diagonal) --- - let colLen = m - k - let colVector = Array.init colLen (fun i -> A.[k + i, k]) - let hLeft = Householder.create colVector - - Householder.applyLeft(hLeft, A, k) - - // Overwrite A[k..,k] with Householder beta at top and zeros below - A.[k, k] <- hLeft.Beta - for i = k + 1 to m - 1 do - A.[i, k] <- GenericMath.zero<'T> - - - - // --- RIGHT REFLECTION: Row k (zero right of superdiagonal) --- - if k < n - 1 then - let rowLen = n - (k + 1) - let rowVector = Array.init rowLen (fun j -> A.[k, k + 1 + j]) - let hRight = Householder.create rowVector - - Householder.applyRight(hRight, A, k + 1) - - // Overwrite A[k,k+1..] with Householder beta at front, zeros right - A.[k, k + 1] <- hRight.Beta - for j = k + 2 to n - 1 do - A.[k, j] <- GenericMath.zero<'T> - - -[] -type Bidiagonal<'T when 'T :> Numerics.INumber<'T>> = { - D : Vector<'T> // main diagonal - E : Vector<'T> // superdiagonal (length n-1) -} - - -/// Givens Rotation (Generic) -module Givens = - - let inline compute<'T - when 'T :> Numerics.INumber<'T> - and 'T : comparison - and 'T :> Numerics.IRootFunctions<'T> - and 'T :> Numerics.IFloatingPointIeee754<'T>> - (a: 'T) (b: 'T) : 'T * 'T = - - if b = GenericMath.zero then GenericMath.one, GenericMath.zero - elif GenericMath.abs b > GenericMath.abs a then - let t = a / b - let s = GenericMath.one / GenericMath.sqrt(GenericMath.one + t * t) - s * t, s - else - let t = b / a - let c = GenericMath.one / GenericMath.sqrt(GenericMath.one + t * t) - c, c * t - -module GolubKahan = - - let inline diagonalize<'T - when 'T :> Numerics.INumber<'T> - and 'T :> Numerics.IRootFunctions<'T> - and 'T :> Numerics.IFloatingPointIeee754<'T> - and 'T : comparison - and 'T : struct - and 'T : (new: unit -> 'T) - and 'T :> ValueType> - (b: Bidiagonal<'T>) : Vector<'T> = - - let d = Array.copy b.D - let e = Array.copy b.E - let n = d.Length - let eps = GenericMath.epsilon() - let two = GenericMath.one + GenericMath.one - - let mutable iter = 0 - let maxIter = 1000 - let mutable doneIterating = false - - - - while iter < maxIter && not doneIterating do - let mutable converged = true - - for i = 0 to n - 2 do - let tolerance = eps * (GenericMath.abs d.[i] + GenericMath.abs d.[i + 1]) - if abs e.[i] > tolerance then - converged <- false - - if converged then - doneIterating <- true - else - // Wilkinson shift - let m = n - 1 - let dm1 = d.[m - 1] - let dm = d.[m] - let em1 = e.[m - 1] - - let delta = (dm1 - dm) / two - let sign = - if delta >= GenericMath.zero then GenericMath.one - else -GenericMath.one - - let denom = abs delta + sqrt (delta * delta + em1 * em1) - let mu = dm - sign * (em1 * em1) / denom - - // Initial bulge - let mutable x = d.[0] * d.[0] - mu * mu - let mutable z = d.[0] * e.[0] - - for k = 0 to n - 2 do - let c, s = Givens.compute x z - - let dk = d.[k] - let ek = e.[k] - let dk1 = d.[k + 1] - - let tau1 = c * dk + s * ek - let tau2 = -s * dk1 - - d.[k] <- c * tau1 + s * tau2 - e.[k] <- c * ek - s * dk1 - d.[k + 1] <- s * tau1 - c * tau2 - - if k < n - 2 then - x <- e.[k] - z <- -s * e.[k + 1] - e.[k + 1] <- c * e.[k + 1] - - iter <- iter + 1 - - d - - - -module SVD = - - type private SvdCase = - // 1 if s(p) and e[k-1] are negligible and k

a.[j,i]) - - let computeInPlace (a:float[,]) = - let transposeBeforeSVD = - let m = a.GetLength(0) - let n = a.GetLength(1) - m < n - let a = if transposeBeforeSVD then transpose a else a - //let a = Array2D.copy A - // number of rows in A - let m = a.GetLength(0) - // number of columns in A - let n = a.GetLength(1) - // * Apparently the failing cases are only a proper subset of (m= n") } - let nu = min m n - let s = Array.zeroCreate (min (m+1) n) - let umatrix = Array2D.zeroCreate m m - let vmatrix = Array2D.zeroCreate n n - let e = Array.zeroCreate n - let work = Array.zeroCreate m - let mutable wantu = true - let mutable wantv = true - - // Reduce A to bidiagonal form, storing the diagonal elements - // in s and the super-diagonal elements in e. - - let nct = min (m - 1) n - let nrt = max 0 (min (n - 2) m) - for k = 0 to (max nct nrt) do - if (k < nct) then - // Compute the transformation for the k-th column and - // place the k-th diagonal in s.[k]. - // Compute 2-norm of k-th column without under/overflow. - s.[k] <- 0. - for i = k to m-1 do - s.[k] <- Geometry.hypot s.[k] a.[i,k] - - if (s.[k] <> 0.0) then - if (a.[k,k] < 0.0) then - s.[k] <- -s.[k] - - for i = k to m-1 do - a.[i,k] <- a.[i,k] / s.[k] - - a.[k,k] <- a.[k,k] + 1.0 - - s.[k] <- -s.[k] - - for j = k+1 to n-1 do - if ((k < nct) && (s.[k] <> 0.0)) then - // Apply the transformation. - - let mutable t = 0. - for i = k to m-1 do - t <- t + a.[i,k] * a.[i,j] - - t <- -t / a.[k,k] - for i = k to m-1 do - a.[i,j] <- a.[i,j] + t * a.[i,k] - - - // Place the k-th row of A into e for the - // subsequent calculation of the row transformation. - - e.[j] <- a.[k,j] - - if (wantu && (k < nct)) then - - // Place the transformation in U for subsequent back - // multiplication. - - for i = k to m-1 do - umatrix.[i,k] <- a.[i,k] - - if (k < nrt) then - // Compute the k-th row transformation and place the - // k-th super-diagonal in e[k]. - // Compute 2-norm without under/overflow. - e.[k] <- 0. - for i = k+1 to n-1 do - e.[k] <- Geometry.hypot e.[k] e.[i] - - if (e.[k] <> 0.0) then - if (e.[k + 1] < 0.0) then - e.[k] <- -e.[k] - - for i = k+1 to n-1 do - e.[i] <- e.[i] / e.[k] - - e.[k + 1] <- e.[k + 1] + 1.0 - - e.[k] <- -e.[k] - if ((k + 1 < m) && (e.[k] <> 0.0)) then - // Apply the transformation. - for i = k+1 to m-1 do - work.[i] <- 0.0 - - for j = k+1 to n-1 do - for i = k+1 to m-1 do - work.[i] <- work.[i] + e.[j] * a.[i,j] - - for j = k+1 to n-1 do - let t = -e.[j] / e.[k + 1] - for i = k+1 to m-1 do - a.[i,j] <- a.[i,j] + t * work.[i] - - - if (wantv) then - // Place the transformation in V for subsequent - // back multiplication. - for i = k+1 to n-1 do - vmatrix.[i,k] <- e.[i] - - - // Set up the final bidiagonal matrix or order p. - let mutable p = min n (m + 1) - if (nct < n) then - s.[nct] <- a.[nct,nct] - - if (m < p) then - s.[p - 1] <- 0.0 - - if (nrt + 1 < p) then - e.[nrt] <- a.[nrt,p - 1] - - e.[p - 1] <- 0.0 - - // If required, generate U. - if (wantu) then - for j = nct to m-1 do - for i = 0 to m-1 do - umatrix.[i,j] <- 0.0 - umatrix.[j,j] <- 1.0 - - for k = nct-1 downto 0 do - if (s.[k] <> 0.0) then - for j = k+1 to m-1 do - let mutable t = 0. - for i = k to m-1 do - t <- t + umatrix.[i,k] * umatrix.[i,j] - - t <- -t / umatrix.[k,k] - for i = k to m-1 do - umatrix.[i,j] <- umatrix.[i,j] + t * umatrix.[i,k] - - for i = k to m-1 do - umatrix.[i,k] <- -umatrix.[i,k] - - umatrix.[k,k] <- 1.0 + umatrix.[k,k] - for i = 0 to k-2 do - umatrix.[i,k] <- 0.0 - - else - for i = 0 to m-1 do - umatrix.[i,k] <- 0.0 - - umatrix.[k,k] <- 1.0 - - - // If required, generate V. - - if (wantv) then - for k = n-1 downto 0 do - if ((k < nrt) && (e.[k] <> 0.0)) then - for j = k+1 to nu-1 do - let mutable t = 0. - for i = k+1 to n-1 do - t <- t + vmatrix.[i,k] * vmatrix.[i,j] - - t <- -t / vmatrix.[k + 1,k] - for i = k+1 to n-1 do - vmatrix.[i,j] <- vmatrix.[i,j] + t * vmatrix.[i,k] - - for i = 0 to n-1 do - vmatrix.[i,k] <- 0.0 - vmatrix.[k,k] <- 1.0 - - // Main iteration loop for the singular values. - // TODO: rec - let mutable pp = p - 1 - let mutable iter = 0 - let eps = System.Math.Pow(2.0, -52.0) - let tiny = System.Math.Pow(2.0, -966.0) - while (p > 0) do - let mutable k = -1 - let mutable case = -1 - - // Here is where a test for too many iterations would go. - - // This section of the program inspects for - // negligible elements in the s and e arrays. On - // completion the variables case and k are set as follows. - - // case = 1 if s(p) and e[k-1] are negligible and k

() - - if (k = p - 2) then - case <- 4 - else - let mutable ks = p-1 - try - for ks' = p-1 downto k do - ks <- ks' - if (ks = k) then - raise BreakException - let mutable t = (if ks <> p then (abs e.[ks]) else 0.0) + - (if ks <> k+1 then (abs e.[ks-1]) else 0.0) - if ((abs s.[ks]) <= tiny + eps*t) then - s.[ks] <- 0.0 - raise BreakException - - with BreakException -> () - - if (ks = k) then case <- 3 - elif (ks = p-1) then case <- 1 - else - case <- 2 - k <- ks - k <- k + 1 - // Perform the task indicated by case. - - match case with - | 1 -> - // Deflate negligible s(p). - //printfn "case 1" - let mutable f = e.[p - 2] - e.[p - 2] <- 0.0 - for j = p-2 downto k do - let mutable t = Geometry.hypot s.[j] f - printfn "t : %A - f: %A" t f - let cs = s.[j] / t - let sn = f / t - s.[j] <- t - if (j <> k) then - f <- -sn * e.[j - 1] - e.[j - 1] <- cs * e.[j - 1] - - if (wantv) then - for i = 0 to n-1 do - t <- cs * vmatrix.[i,j] + sn*vmatrix.[i,p - 1] - vmatrix.[i,p - 1] <- -sn * vmatrix.[i,j] + cs * vmatrix.[i,p - 1] - vmatrix.[i,j] <- t - - | 2 -> - // Split at negligible s(k). - //printfn "case 2" - let mutable f = e.[k - 1] - e.[k - 1] <- 0.0 - for j = k to p-1 do - let mutable t = Geometry.hypot s.[j] f - let cs = s.[j]/t - let sn = f/t - s.[j] <- t - f <- -sn*e.[j] - e.[j] <- cs*e.[j] - if (wantu) then - for i = 0 to m-1 do - t <- cs*umatrix.[i,j] + sn*umatrix.[i,k - 1] - umatrix.[i,k - 1] <- -sn*umatrix.[i,j] + cs*umatrix.[i,k - 1] - umatrix.[i,j] <- t - // Perform one qr step. - | 3 -> - // Calculate the shift. - //printfn "case 3" - let scale = - max (abs s.[p - 1]) (abs s.[p - 2]) - |> max (abs e.[p - 2]) - |> max (abs s.[k]) - |> max (abs e.[k]) - - let sp = s.[p - 1]/scale - let spm1 = s.[p - 2]/scale - let epm1 = e.[p - 2]/scale - let sk = s.[k]/scale - let ek = e.[k]/scale - let b = ((spm1 + sp)*(spm1 - sp) + epm1*epm1)/2.0 - let c = (sp*epm1)*(sp*epm1) - let mutable shift = 0.0 - if ((b <> 0.0) || (c <> 0.0)) then - shift <- sqrt (b*b + c) - if (b < 0.0) then - shift <- -shift - shift <- c/(b + shift) - - let mutable f = (sk + sp)*(sk - sp) + shift - let mutable g = sk*ek - - // Chase zeros. - for j = k to p-2 do - let mutable t = Geometry.hypot f g - let mutable cs = f/t - let mutable sn = g/t - if (j <> k) then - e.[j - 1] <- t - - f <- cs*s.[j] + sn*e.[j] - e.[j] <- cs*e.[j] - sn*s.[j] - g <- sn*s.[j + 1] - s.[j + 1] <- cs*s.[j + 1] - if (wantv) then - for i = 0 to n-1 do - t <- cs*vmatrix.[i,j] + sn*vmatrix.[i,j + 1] - vmatrix.[i,j + 1] <- -sn*vmatrix.[i,j] + cs*vmatrix.[i,j + 1] - vmatrix.[i,j] <- t - - - t <- Geometry.hypot f g - cs <- f/t - sn <- g/t - s.[j] <- t - f <- cs*e.[j] + sn*s.[j + 1] - s.[j + 1] <- -sn*e.[j] + cs*s.[j + 1] - g <- sn*e.[j + 1] - e.[j + 1] <- cs*e.[j + 1] - if (wantu && (j < m - 1)) then - for i = 0 to m-1 do - t <- cs*umatrix.[i,j] + sn*umatrix.[i,j + 1] - umatrix.[i,j + 1] <- -sn*umatrix.[i,j] + cs*umatrix.[i,j + 1] - umatrix.[i,j] <- t - - - - e.[p - 2] <- f - iter <- iter + 1 - - // Convergence. - | 4 -> - // Make the singular values positive. - //printfn "case 4" - if (s.[k] <= 0.0) then - s.[k] <- (if s.[k] < 0.0 then -s.[k] else 0.0) - if (wantv) then - for i = 0 to pp do - vmatrix.[i,k] <- -vmatrix.[i,k] - - - - // Order the singular values. - try - while (k < pp) do - - if (s.[k] >= s.[k + 1]) then raise BreakException - - let t = s.[k] - s.[k] <- s.[k + 1] - s.[k + 1] <- t - if (wantv && (k < n - 1)) then - for i = 0 to n-1 do - let t = vmatrix.[i,k + 1] // mutable - vmatrix.[i,k + 1] <- vmatrix.[i,k] - vmatrix.[i,k] <- t - - if (wantu && (k < m - 1)) then - for i = 0 to m-1 do - let t = umatrix.[i,k + 1] - umatrix.[i,k + 1] <- umatrix.[i,k] - umatrix.[i,k] <- t - - k <- k+1 - - with BreakException -> () - - iter <- 0 - p <- p - 1 - | _ -> failwithf "case %i does not exist" case - - if transposeBeforeSVD then - (vmatrix,s,transpose umatrix) - else - (umatrix,s,transpose vmatrix) - - - - let compute (a:float[,]) = - Array2D.copy a - |> computeInPlace - - \ No newline at end of file diff --git a/src/FSharp.Stats/Correlation.fs b/src/FSharp.Stats/Correlation.fs index 7651f1677..805000d38 100644 --- a/src/FSharp.Stats/Correlation.fs +++ b/src/FSharp.Stats/Correlation.fs @@ -1,4 +1,7 @@ namespace FSharp.Stats + +open FsMath + /// Contains correlation functions for different data types module Correlation = diff --git a/src/FSharp.Stats/DistanceMetrics.fs b/src/FSharp.Stats/DistanceMetrics.fs index 85c94a613..aa2f0ff20 100644 --- a/src/FSharp.Stats/DistanceMetrics.fs +++ b/src/FSharp.Stats/DistanceMetrics.fs @@ -1,5 +1,7 @@ namespace FSharp.Stats +open FsMath + ///Functions for computing distances of elements or sets module DistanceMetrics = diff --git a/src/FSharp.Stats/Distributions/Continuous/MultivariateNormal.fs b/src/FSharp.Stats/Distributions/Continuous/MultivariateNormal.fs index eba88d822..bef59dddd 100644 --- a/src/FSharp.Stats/Distributions/Continuous/MultivariateNormal.fs +++ b/src/FSharp.Stats/Distributions/Continuous/MultivariateNormal.fs @@ -1,9 +1,13 @@ namespace FSharp.Stats.Distributions.Continuous + open System open FSharp.Stats open FSharp.Stats.Distributions -open FSharp.Stats.Ops + +open FsMath +open FsMath.Algebra + // ###### // Multivariate normal distribution diff --git a/src/FSharp.Stats/Distributions/Discrete/Geometric.fs b/src/FSharp.Stats/Distributions/Discrete/Geometric.fs index c5504b69b..b43b4678c 100644 --- a/src/FSharp.Stats/Distributions/Discrete/Geometric.fs +++ b/src/FSharp.Stats/Distributions/Discrete/Geometric.fs @@ -4,7 +4,8 @@ open System open System.Numerics open FSharp.Stats open FSharp.Stats.Distributions -open FSharp.Stats.GenericMath +open FsMath +open FsMath.GenericMath //IFloatingPoint diff --git a/src/FSharp.Stats/Distributions/Discrete/Multinomial.fs b/src/FSharp.Stats/Distributions/Discrete/Multinomial.fs index c1b6bbda6..0b12baf4a 100644 --- a/src/FSharp.Stats/Distributions/Discrete/Multinomial.fs +++ b/src/FSharp.Stats/Distributions/Discrete/Multinomial.fs @@ -4,6 +4,8 @@ open System open FSharp.Stats open FSharp.Stats.Distributions open FSharp.Stats.SpecialFunctions +open FsMath + // n is the number of trails, // k is the vector of observed successes diff --git a/src/FSharp.Stats/Distributions/Distribution.fs b/src/FSharp.Stats/Distributions/Distribution.fs index 0952617de..901dc15a5 100644 --- a/src/FSharp.Stats/Distributions/Distribution.fs +++ b/src/FSharp.Stats/Distributions/Distribution.fs @@ -1,6 +1,8 @@ namespace FSharp.Stats.Distributions open FSharp.Stats +open FsMath + module Parameters = diff --git a/src/FSharp.Stats/FSIPrinters.fs b/src/FSharp.Stats/FSIPrinters.fs index dc37f480f..2b1babbdf 100644 --- a/src/FSharp.Stats/FSIPrinters.fs +++ b/src/FSharp.Stats/FSIPrinters.fs @@ -3,6 +3,7 @@ module FSIPrinters = open System open System.Linq + open FsMath let matrix (mat: Matrix<_>) = //TODO: Difficult to read because of all exceptions. Simplified version! diff --git a/src/FSharp.Stats/FSharp.Stats.fsproj b/src/FSharp.Stats/FSharp.Stats.fsproj index db80f410f..bc175d2b9 100644 --- a/src/FSharp.Stats/FSharp.Stats.fsproj +++ b/src/FSharp.Stats/FSharp.Stats.fsproj @@ -29,15 +29,6 @@ - - - - - - - - - @@ -66,9 +57,6 @@ - - - @@ -171,10 +159,19 @@ + + + + + + + + + diff --git a/src/FSharp.Stats/Fitting/CrossValidation.fs b/src/FSharp.Stats/Fitting/CrossValidation.fs index 8dab5a641..6e724ac76 100644 --- a/src/FSharp.Stats/Fitting/CrossValidation.fs +++ b/src/FSharp.Stats/Fitting/CrossValidation.fs @@ -1,5 +1,7 @@ namespace FSharp.Stats.Fitting +open FsMath + (* diff --git a/src/FSharp.Stats/Fitting/GoodnessOfFit.fs b/src/FSharp.Stats/Fitting/GoodnessOfFit.fs index 8efdb100d..48783c81d 100644 --- a/src/FSharp.Stats/Fitting/GoodnessOfFit.fs +++ b/src/FSharp.Stats/Fitting/GoodnessOfFit.fs @@ -8,6 +8,9 @@ we estimate the relationship of one variable with another by expressing one in t module GoodnessOfFit = open FSharp.Stats open System + open FsMath + + /// Three sum of squares type SumOfSquares = { /// Regression sum of squares (SSR: explained); Sum((yFit-yMean)**2.) diff --git a/src/FSharp.Stats/Fitting/LinearRegression.fs b/src/FSharp.Stats/Fitting/LinearRegression.fs index b02ab463b..0d89702c5 100644 --- a/src/FSharp.Stats/Fitting/LinearRegression.fs +++ b/src/FSharp.Stats/Fitting/LinearRegression.fs @@ -3,7 +3,8 @@ namespace FSharp.Stats.Fitting open System open FSharp.Stats -open FSharp.Stats.Algebra +open FsMath +open FsMath.Algebra ///

/// Linear regression is used to estimate the relationship of one variable (y) with another (x) by expressing y in terms of a linear function of x. diff --git a/src/FSharp.Stats/Fitting/LogisticRegression.fs b/src/FSharp.Stats/Fitting/LogisticRegression.fs index ae03c4008..873c1a639 100644 --- a/src/FSharp.Stats/Fitting/LogisticRegression.fs +++ b/src/FSharp.Stats/Fitting/LogisticRegression.fs @@ -9,6 +9,7 @@ open FSharp.Stats module LogisticRegression = open System + open FsMath /// Creates a new vector (length = obs.Length + 1) whose /// first element is 1.0 (for the intercept), followed by obs's elements. diff --git a/src/FSharp.Stats/Fitting/NonLinearRegression.fs b/src/FSharp.Stats/Fitting/NonLinearRegression.fs index daec51af3..54c5234ca 100644 --- a/src/FSharp.Stats/Fitting/NonLinearRegression.fs +++ b/src/FSharp.Stats/Fitting/NonLinearRegression.fs @@ -7,7 +7,8 @@ we estimate the relationship of one variable with another by expressing one in t *) module NonLinearRegression = open FSharp.Stats - open FSharp.Stats.Algebra + open FsMath + open FsMath.Algebra /// let standardErrorOfPrediction dOF (predicted:float []) (actual:float []) = @@ -301,7 +302,7 @@ module NonLinearRegression = let hessian = jacobian'.Transpose() * jacobian' |> scaleJacobian scaleFactors let diagonal = Matrix.diagonal (Array.map (fun x -> ((lambda)*x)) (hessian |> Matrix.getDiagonal)) let modHessian = (hessian + diagonal) - let step = FSharp.Stats.Algebra.LinearAlgebra.solveLinearSystem modHessian gradient + let step = LinearAlgebra.solveLinearSystem modHessian gradient let newParamGuessInt = currentParamGuessInt .- step let newParamGuessExt = toExternalParameters lowerBound upperBound newParamGuessInt let newValueRSS = getRSS model xData yData newParamGuessExt diff --git a/src/FSharp.Stats/Fitting/Spline.fs b/src/FSharp.Stats/Fitting/Spline.fs index 7dbef668d..80eaa661c 100644 --- a/src/FSharp.Stats/Fitting/Spline.fs +++ b/src/FSharp.Stats/Fitting/Spline.fs @@ -4,7 +4,8 @@ namespace FSharp.Stats.Fitting module Spline = open FSharp.Stats - open FSharp.Stats.Algebra + open FsMath + open FsMath.Algebra /// Some preprocessing of the input data /// diff --git a/src/FSharp.Stats/Interpolation.fs b/src/FSharp.Stats/Interpolation.fs index bc0555726..dfbe59bbe 100644 --- a/src/FSharp.Stats/Interpolation.fs +++ b/src/FSharp.Stats/Interpolation.fs @@ -2,7 +2,8 @@ open System open FSharp.Stats -open FSharp.Stats.Algebra +open FsMath +open FsMath.Algebra /// /// This module contains functionalities to perform various interpolation methods for two dimensional data. diff --git a/src/FSharp.Stats/ML/DistanceMetrics.fs b/src/FSharp.Stats/ML/DistanceMetrics.fs index e0e1c4be4..a9c034a2a 100644 --- a/src/FSharp.Stats/ML/DistanceMetrics.fs +++ b/src/FSharp.Stats/ML/DistanceMetrics.fs @@ -2,6 +2,8 @@ open System open FSharp.Stats +open FsMath + [] module DistanceMetrics = diff --git a/src/FSharp.Stats/ML/Unsupervised/ClusterNumber.fs b/src/FSharp.Stats/ML/Unsupervised/ClusterNumber.fs index 1150da672..e9fe0579b 100644 --- a/src/FSharp.Stats/ML/Unsupervised/ClusterNumber.fs +++ b/src/FSharp.Stats/ML/Unsupervised/ClusterNumber.fs @@ -3,6 +3,8 @@ namespace FSharp.Stats.ML.Unsupervised open System open FSharp.Stats open FSharpAux +open FsMath + module ClusterNumber = diff --git a/src/FSharp.Stats/ML/Unsupervised/IterativeClustering.fs b/src/FSharp.Stats/ML/Unsupervised/IterativeClustering.fs index 695db9aea..9c4a286ea 100644 --- a/src/FSharp.Stats/ML/Unsupervised/IterativeClustering.fs +++ b/src/FSharp.Stats/ML/Unsupervised/IterativeClustering.fs @@ -6,6 +6,7 @@ module IterativeClustering = open FSharp.Stats open FSharp.Stats.DistanceMetrics + open FsMath diff --git a/src/FSharp.Stats/Optimization/NelderMead.fs b/src/FSharp.Stats/Optimization/NelderMead.fs index 34235174e..e0a39b90e 100644 --- a/src/FSharp.Stats/Optimization/NelderMead.fs +++ b/src/FSharp.Stats/Optimization/NelderMead.fs @@ -3,7 +3,8 @@ module NelderMead = open FSharp.Stats - open FSharp.Stats.Algebra + open FsMath + open FsMath.Algebra type NmConfig = { /// Delta used to generate initial simplex for non-zero value elements diff --git a/src/FSharp.Stats/Signal/Baseline.fs b/src/FSharp.Stats/Signal/Baseline.fs index cbdef104b..c2dea6112 100644 --- a/src/FSharp.Stats/Signal/Baseline.fs +++ b/src/FSharp.Stats/Signal/Baseline.fs @@ -1,7 +1,7 @@ namespace FSharp.Stats.Signal open FSharp.Stats - +open FsMath module Baseline = diff --git a/src/FSharp.Stats/Signal/Convolution.fs b/src/FSharp.Stats/Signal/Convolution.fs index fc1b56fff..fa10b4f83 100644 --- a/src/FSharp.Stats/Signal/Convolution.fs +++ b/src/FSharp.Stats/Signal/Convolution.fs @@ -1,7 +1,7 @@ namespace FSharp.Stats.Signal open FSharp.Stats - +open FsMath module Convolution = diff --git a/src/FSharp.Stats/Signal/Filtering.fs b/src/FSharp.Stats/Signal/Filtering.fs index d70f09cad..41fb4d257 100644 --- a/src/FSharp.Stats/Signal/Filtering.fs +++ b/src/FSharp.Stats/Signal/Filtering.fs @@ -2,7 +2,8 @@ open System open FSharp.Stats -open FSharp.Stats.Algebra +open FsMath +open FsMath.Algebra module Filtering = diff --git a/src/FSharp.Stats/Signal/Normalization.fs b/src/FSharp.Stats/Signal/Normalization.fs index 6678980fe..de46e6568 100644 --- a/src/FSharp.Stats/Signal/Normalization.fs +++ b/src/FSharp.Stats/Signal/Normalization.fs @@ -1,6 +1,7 @@ namespace FSharp.Stats.Signal open FSharp.Stats +open FsMath module Normalization = diff --git a/src/FSharp.Stats/Signal/Outliers.fs b/src/FSharp.Stats/Signal/Outliers.fs index 5dda0ff2f..a2f166a8f 100644 --- a/src/FSharp.Stats/Signal/Outliers.fs +++ b/src/FSharp.Stats/Signal/Outliers.fs @@ -3,7 +3,7 @@ module Outliers = open FSharp.Stats - open Matrix + open FsMath /// Tukey's fences based on interquartile range. c defines the magnitude of interquartile range that is added/subtracted to Q3 and Q1 respectively.
Commonly c is 1.5 for outliers and 3 for points 'far out' (Tukey 1977).
/// diff --git a/src/FSharp.Stats/Signal/PeakDetection.fs b/src/FSharp.Stats/Signal/PeakDetection.fs index d6a42ef76..a011d4865 100644 --- a/src/FSharp.Stats/Signal/PeakDetection.fs +++ b/src/FSharp.Stats/Signal/PeakDetection.fs @@ -2,7 +2,8 @@ namespace FSharp.Stats.Signal open FSharp.Stats open System - +open FsMath +open FsMath.Algebra module PeakDetection = diff --git a/src/FSharp.Stats/Signal/QQPlot.fs b/src/FSharp.Stats/Signal/QQPlot.fs index 0014e2c85..160a231c3 100644 --- a/src/FSharp.Stats/Signal/QQPlot.fs +++ b/src/FSharp.Stats/Signal/QQPlot.fs @@ -6,6 +6,8 @@ open System open FSharp.Stats.SpecialFunctions open FSharp.Stats.Quantile open FSharp.Stats.Interpolation +open FsMath + module QQPlot = diff --git a/src/FSharp.Stats/Table.fs b/src/FSharp.Stats/Table.fs index 793ac42e5..3212a0b55 100644 --- a/src/FSharp.Stats/Table.fs +++ b/src/FSharp.Stats/Table.fs @@ -3,7 +3,8 @@ open System open FSharp.Stats - +open FsMath +open FsMath.Algebra open System open System.Collections.Generic @@ -50,7 +51,7 @@ type Table<'R,'C,'T and 'T :> Numerics.INumber<'T> and 'T : (new: unit -> 'T) and 'T : struct - and 'T : equality + and 'T : comparison and 'T :> ValueType> ( rowKeys : 'R[], colKeys : 'C[], diff --git a/src/FSharp.Stats/Testing/ConfusionMatrix.fs b/src/FSharp.Stats/Testing/ConfusionMatrix.fs index 8290da7d1..dd3f0af50 100644 --- a/src/FSharp.Stats/Testing/ConfusionMatrix.fs +++ b/src/FSharp.Stats/Testing/ConfusionMatrix.fs @@ -1,5 +1,7 @@ namespace FSharp.Stats.Testing open FSharp.Stats +open FsMath + /// Confusion matrix for binary classification type BinaryConfusionMatrix = { diff --git a/src/FSharp.Stats/Testing/ContingencyTable.fs b/src/FSharp.Stats/Testing/ContingencyTable.fs index 71a93608d..c92083d70 100644 --- a/src/FSharp.Stats/Testing/ContingencyTable.fs +++ b/src/FSharp.Stats/Testing/ContingencyTable.fs @@ -3,7 +3,7 @@ open System open System.Collections.Generic open FSharp.Stats - +open FsMath /// An estimate with its standard‐error uncertainty. type UncertainValue = { diff --git a/src/FSharp.Stats/Testing/FTest.fs b/src/FSharp.Stats/Testing/FTest.fs index 83c144258..f9c3e3fa1 100644 --- a/src/FSharp.Stats/Testing/FTest.fs +++ b/src/FSharp.Stats/Testing/FTest.fs @@ -1,5 +1,7 @@ namespace FSharp.Stats.Testing +open FsMath + module FTest = open FSharp.Stats diff --git a/src/FSharp.Stats/Testing/PostHoc.fs b/src/FSharp.Stats/Testing/PostHoc.fs index 072332307..2b4968563 100644 --- a/src/FSharp.Stats/Testing/PostHoc.fs +++ b/src/FSharp.Stats/Testing/PostHoc.fs @@ -1,6 +1,7 @@ namespace FSharp.Stats.Testing open FSharp.Stats +open FsMath module PostHoc = diff --git a/src/FSharp.Stats/Testing/RMT.fs b/src/FSharp.Stats/Testing/RMT.fs index 405ab8535..1e5922a61 100644 --- a/src/FSharp.Stats/Testing/RMT.fs +++ b/src/FSharp.Stats/Testing/RMT.fs @@ -1,5 +1,7 @@ namespace FSharp.Stats.Testing +open FsMath + module RMT = // implementation from: diff --git a/src/FSharp.Stats/Testing/TTest.fs b/src/FSharp.Stats/Testing/TTest.fs index 98017a682..8733d86ae 100644 --- a/src/FSharp.Stats/Testing/TTest.fs +++ b/src/FSharp.Stats/Testing/TTest.fs @@ -4,6 +4,7 @@ namespace FSharp.Stats.Testing module TTest = open System open FSharp.Stats + open FsMath /// Equal or unequal sample sizes, assume nothing about variance. /// input: (mean1,variance1,N1) (mean2,variance2,N3) diff --git a/src/FSharp.Stats/Testing/Tables.fs b/src/FSharp.Stats/Testing/Tables.fs index c7b071c27..42c10a406 100644 --- a/src/FSharp.Stats/Testing/Tables.fs +++ b/src/FSharp.Stats/Testing/Tables.fs @@ -1,6 +1,8 @@ namespace FSharp.Stats.Testing open FSharp.Stats +open FsMath + /// Some statistical tests lack in distributions for exact p value calculation. In order to enable the usage of these tests module Tables = diff --git a/tests/FSharp.Stats.Tests/Acceleration.fs b/tests/FSharp.Stats.Tests/Acceleration.fs deleted file mode 100644 index 4c7b45014..000000000 --- a/tests/FSharp.Stats.Tests/Acceleration.fs +++ /dev/null @@ -1,49 +0,0 @@ -module AccelerationTests - -open Expecto -open System -open FSharp.Stats -open TestExtensions - -open Expecto - -[] -let dotRangeTests = - testList "dotRange tests" [ - - test "Basic dot product with zero offset" { - let a = [| 1.0; 2.0; 3.0 |] - let b = [| 4.0; 5.0; 6.0 |] - let result = Acceleration.SIMDRangeUtils.dotRange a 0 b 0 3 - Expect.floatClose Accuracy.high result 32.0 "Dot product mismatch" - } - - test "Dot product with offset in first array" { - let a = [| 0.0; 1.0; 2.0; 3.0 |] // use 1.0, 2.0, 3.0 - let b = [| 4.0; 5.0; 6.0 |] - let result = Acceleration.SIMDRangeUtils.dotRange a 1 b 0 3 - Expect.floatClose Accuracy.high result 32.0 "Offset dot mismatch" - } - - test "Dot product with both arrays offset" { - let a = [| 0.0; 1.0; 2.0; 3.0 |] - let b = [| 0.0; 4.0; 5.0; 6.0 |] - let result = Acceleration.SIMDRangeUtils.dotRange a 1 b 1 3 - Expect.floatClose Accuracy.high result 32.0 "Offset-dot mismatch" - } - - test "Dot with zero-length" { - let a = [| 1.0; 2.0; 3.0 |] - let b = [| 4.0; 5.0; 6.0 |] - let result = Acceleration.SIMDRangeUtils.dotRange a 0 b 0 0 - Expect.equal result 0.0 "Zero-length dot should be 0" - } - - test "Out of bounds throws" { - let a = [| 1.0; 2.0 |] - let b = [| 1.0; 2.0 |] - Expect.throws (fun () -> - Acceleration.SIMDRangeUtils.dotRange a 1 b 1 2 |> ignore) - "Should throw on out-of-bounds" - } - ] diff --git a/tests/FSharp.Stats.Tests/DistanceMetrics.fs b/tests/FSharp.Stats.Tests/DistanceMetrics.fs index 4d4cafd0b..f3700eac7 100644 --- a/tests/FSharp.Stats.Tests/DistanceMetrics.fs +++ b/tests/FSharp.Stats.Tests/DistanceMetrics.fs @@ -2,6 +2,7 @@ open Expecto open FSharp.Stats open FSharp.Stats.DistanceMetrics.Vector +open FsMath open FSharp.Stats.DistanceMetrics [] let hammingfunctiontests = diff --git a/tests/FSharp.Stats.Tests/DistributionsContinuous.fs b/tests/FSharp.Stats.Tests/DistributionsContinuous.fs index 6dafe0baf..6d13c751c 100644 --- a/tests/FSharp.Stats.Tests/DistributionsContinuous.fs +++ b/tests/FSharp.Stats.Tests/DistributionsContinuous.fs @@ -2,6 +2,7 @@ open Expecto open System +open FsMath open FSharp.Stats open FSharp.Stats.Distributions open FSharp.Stats.Distributions.Continuous diff --git a/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj b/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj index d9aaf0f95..2fe8dc70b 100644 --- a/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj +++ b/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj @@ -6,7 +6,6 @@ - @@ -20,9 +19,6 @@ - - - @@ -33,7 +29,6 @@ - diff --git a/tests/FSharp.Stats.Tests/Fitting.fs b/tests/FSharp.Stats.Tests/Fitting.fs index 84fc56dd0..91111c405 100644 --- a/tests/FSharp.Stats.Tests/Fitting.fs +++ b/tests/FSharp.Stats.Tests/Fitting.fs @@ -1,7 +1,7 @@ module FittingTests open Expecto - +open FsMath open FSharp.Stats open FSharp.Stats.Fitting open FSharp.Stats.Fitting.NonLinearRegression diff --git a/tests/FSharp.Stats.Tests/Interpolation.fs b/tests/FSharp.Stats.Tests/Interpolation.fs index e97496a99..6a8054813 100644 --- a/tests/FSharp.Stats.Tests/Interpolation.fs +++ b/tests/FSharp.Stats.Tests/Interpolation.fs @@ -1,6 +1,7 @@ module InterpolationTests open Expecto +open FsMath open FSharp.Stats open FSharp.Stats.Interpolation diff --git a/tests/FSharp.Stats.Tests/LinAlgebra.fs b/tests/FSharp.Stats.Tests/LinAlgebra.fs deleted file mode 100644 index dc3dc3024..000000000 --- a/tests/FSharp.Stats.Tests/LinAlgebra.fs +++ /dev/null @@ -1,529 +0,0 @@ -module LinAlgebraTests - -open Expecto -open System -open FSharp.Stats -open FSharp.Stats.Algebra - -[] -let linearAlgebraTests = - testList "LinearAlgebra Tests" [ - - // ---------------------------------------------------------------------- - // Basic tests - // ---------------------------------------------------------------------- - - testCase "subScaledRowInPlace: subtract scaled portion of source row from destination row" <| fun _ -> - let dst = [|10.0; 20.0; 30.0|] - let src = [|1.0 ; 2.0 ; 3.0 |] - LinearAlgebra.subScaledRowInPlace 2.0 0 0 3 dst src - let expected = [|8.0; 16.0; 24.0|] - Expect.equal dst expected "dst should be updated correctly" - - testCase "householderTransform: returns a Householder vector for column i" <| fun _ -> - let matData = [| 1.0; 2.0; 3.0 - 4.0; 5.0; 6.0 - 7.0; 8.0; 9.0 |] - let A = Matrix(3, 3, matData) - let v = LinearAlgebra.householderTransform A 1 - Expect.equal v.Length 3 "Householder vector should have 3 elements" - Expect.isFalse (Double.IsNaN v.[1]) "v.[1] should not be NaN" - - testCase "qrModifiedGramSchmidt: Q*R reconstructs A (2x2 example)" <| fun _ -> - let A = Matrix(2, 2, [|1.0; 2.0; 3.0; 4.0|]) - let Q, R = LinearAlgebra.qrModifiedGramSchmidt A - // Multiply Q*R => 2x2 => compare with A - let APrime = Array.zeroCreate 4 - for i in 0..1 do - for j in 0..1 do - let mutable sum = 0.0 - for k in 0..1 do - sum <- sum + Q.[i,k] * R.[k,j] - APrime.[i*2 + j] <- sum - for idx in 0..3 do - Expect.floatClose Accuracy.high A.Data.[idx] APrime.[idx] - $"A' and A differ at idx={idx}" - - testCase "backSubstitute: solves R*x=y for x, R upper-triangular" <| fun _ -> - // R = [2,3; 0,4], y = [8,12] => x= [-0.5,3] - let R = Matrix(2, 2, [|2.0;3.0; 0.0;4.0|]) - let y = [|8.0;12.0|] - let x = LinearAlgebra.backSubstitute R y - let expected = [|-0.5;3.0|] - Expect.floatClose Accuracy.high expected.[0] x.[0] "x0 mismatch" - Expect.floatClose Accuracy.high expected.[1] x.[1] "x1 mismatch" - - testCase "solveLinearQR: solves A*x=b (2x2 system)" <| fun _ -> - // A= [1,2; 3,4], b= [5,11] => x= [1,2] - let A = Matrix(2,2,[|1.;2.;3.;4.|]) - let b = [|5.; 11.|] - let x = LinearAlgebra.solveLinearQR A b - let expected = [|1.;2.|] - Expect.floatClose Accuracy.high expected.[0] x.[0] "x[0] mismatch" - Expect.floatClose Accuracy.high expected.[1] x.[1] "x[1] mismatch" - - - // ====================================================================== - // EDGE CASES: Infinity, -Infinity, NaN - // ====================================================================== - testList "Edge Cases with Infinity, -Infinity, NaN" [ - - testCase "subScaledRowInPlace with scaleVal = +∞" <| fun _ -> - // Let dst[0] = +∞, and scaleVal= +∞. Then dst[0] = ∞ - ∞*something => usually NaN - // Also check second entry for leftover infinite results. - let dst = [| Double.PositiveInfinity; 10.0 |] - let src = [| 2.0; 1.0 |] - LinearAlgebra.subScaledRowInPlace Double.PositiveInfinity 0 0 2 dst src - // The math: - // dst[0] <- ∞ - (∞ * 2) => ∞ - ∞ => NaN - // dst[1] <- 10 - (∞ * 1) => 10 - ∞ => -∞ - Expect.isTrue (Double.IsNaN dst.[0]) "Expected NaN in dst.[0]" - Expect.isTrue (Double.IsNegativeInfinity dst.[1]) "Expected -∞ in dst.[1]" - - testCase "householderTransform with NaN in matrix" <| fun _ -> - // Insert a NaN into the matrix - let matData = [| 1.0; Double.NaN; 3.0 - 4.0; 5.0; 6.0 |] - // 2x3 matrix - let A = Matrix(2, 3, matData) - let v = LinearAlgebra.householderTransform A 1 - // It's likely that the result will incorporate NaN somewhere (since row #1 has NaN). - // We'll confirm that it yields at least one NaN. - let hasNaN = v |> Array.exists Double.IsNaN - Expect.isTrue hasNaN "Expected Householder vector to contain NaN" - - testCase "backSubstitute with 0.0 on R-diagonal => Infinity result" <| fun _ -> - // R = [ [2., 1.], - // [0., 0.] ] => zero on diagonal => x.[1] => y.[1] / 0 => ∞ or NaN - let rData = [|2.;1.; 0.;0.|] - let R = Matrix(2,2,rData) - let y = [|5.0; 3.0|] - // This might yield x.[1] = 3.0 / 0 => +∞ (or possibly throw). - // If your code doesn't throw, let's see if it yields Infinity: - let x = LinearAlgebra.backSubstitute R y - // We'll check x.[1] - Expect.isTrue (Double.IsInfinity x.[1] || Double.IsNaN x.[1]) - "Expected Infinity or NaN for x.[1]" - - testCase "solveLinearQR with b containing ∞" <| fun _ -> - // 2x2 matrix A => [1,2; 3,4], b => [∞, 1] - // The solution might be ∞ or NaN, or the factorization might produce weird results. - let A = Matrix(2,2,[|1.;2.;3.;4.|]) - let b = [|Double.PositiveInfinity; 1.0|] - // We'll see if it returns a vector with ∞ or NaN, or possibly throws. - // We'll not test for a "correct" solution in the usual sense, only that it yields a result. - let x = LinearAlgebra.solveLinearQR A b - // We expect at least one ∞ or NaN in the solution: - let hasSpecial = x |> Array.exists (fun v -> Double.IsNaN(v) || Double.IsInfinity(v)) - Expect.isTrue hasSpecial "Expected ∞ or NaN in the solution" - ] - - testList "Extended LinearAlgebra Tests" [ - - // ===================================================================== - // solveLinearQR - // ===================================================================== - testCase "solveLinearQR: throws if b's length doesn't match A's row count" <| fun _ -> - // A is 2x2, but b has length=3 => mismatch - let A = Matrix(2, 2, [|1.0;2.0; 3.0;4.0|]) - let b = [|1.0; 2.0; 3.0|] // length=3 - Expect.throwsT (fun () -> - let _ = LinearAlgebra.solveLinearQR A b - () - ) "Should throw if A.NumRows != b.Length" - - testCase "solveLinearQR: solves small 3x3 system" <| fun _ -> - // We'll define a 3x3 with an easy integer solution. - // - // A*x = b - // A = [ [1.,2.,0.] - // [2.,1.,1.] - // [0.,1.,2.] ] - // - // We'll pick x => [1., 2., 3.] => let's compute b => A*x by hand: - // row0 => 1*1 +2*2 +0*3 = 5 - // row1 => 2*1 +1*2 +1*3 = 2 +2 +3=7 - // row2 => 0*1 +1*2 +2*3 = 2 +6=8 - // => b= [5,7,8] - let Adata = [| - 1.0; 2.0; 0.0 - 2.0; 1.0; 1.0 - 0.0; 1.0; 2.0 |] // row-major flatten - let A = Matrix(3, 3, Adata) - let b = [|5.0; 7.0; 8.0|] - - let x = LinearAlgebra.solveLinearQR A b - // Expect x= [1,2,3] - let expected = [|1.0; 2.0; 3.0|] - for i in 0..2 do - Expect.floatClose Accuracy.high expected.[i] x.[i] $"x[{i}] mismatch" - - // ===================================================================== - // solveTriangularLinearSystems - // ===================================================================== - testCase "solveTriangularLinearSystems: throws if shape mismatch" <| fun _ -> - // K must be square NxN, B must have Nx? shape - // We'll define a 2x2 K, and B as 3x2 => mismatch - let K = Matrix(2, 2, [|2.0;0.0; 1.0;2.0|]) // just a 2x2 - let B = Matrix(3, 2, [|1.0;2.0; 3.0;4.0; 5.0;6.0|]) // 3x2 - Expect.throwsT (fun () -> - let _ = LinearAlgebra.solveTriangularLinearSystems K B true - () - ) "Should throw on dimension mismatch" - - testCase "solveTriangularLinearSystems: lower-triangular forward substitution (2x2, 2 columns)" <| fun _ -> - // K= L= [ [2,0], - // [1,2] ] - // K is 2x2, B is 2x2 - // We'll pick B so that K*X = B has a known solution X. - // - // Suppose X => [ [1., 10.], - // [2., 4.] ] - // Then K*X => B - // B row0 => row0*K => [2*1 +0*2, 2*10 +0*4] => [2,20] - // B row1 => row1*K => [1*1 +2*2, 1*10 +2*4] => [1+4=5, 10+8=18] - // Wait, careful with row-major. Actually, let's do it systematically: - // If K is NxN, X is NxM => B is NxM - // B[i,*] = sum_{j} (K[i,j] * X[j,*]) (like matrix multiply) - // - // For K= [ [2,0], [1,2] ], X= [ [1,10],[2,4] ] - // Flatten X => row0= (1,10), row1= (2,4) - // B[0,*] => K[0,0]*X[0,*] + K[0,1]*X[1,*] - // => 2*(1,10) + 0*(2,4) => (2,20) - // B[1,*] => K[1,0]*X[0,*] + K[1,1]*X[1,*] - // => 1*(1,10)+2*(2,4) => (1+4, 10+8)= (5,18) - // => B= [ (2,20),(5,18) ] - let Kdata = [| 2.0; 0.0 - 1.0; 2.0 |] - let X_expected_data = [| 1.0; 10.0 - 2.0; 4.0 |] - let B_data = [| 2.0; 20.0 - 5.0; 18.0 |] - let Kmat = Matrix(2,2,Kdata) - let Bmat = Matrix(2,2,B_data) - // We want to solve K*X = B for X. isLower=true => forward substitution - let Xsol = LinearAlgebra.solveTriangularLinearSystems Kmat Bmat true - // Check that Xsol matches X_expected - for i in 0..3 do - Expect.floatClose Accuracy.high X_expected_data.[i] Xsol.Data.[i] $"X mismatch at idx={i}" - - testCase "solveTriangularLinearSystems: upper-triangular backward substitution (2x2, 2 columns)" <| fun _ -> - // Let K= U= [ [2,3], [0,4] ] - // We'll define X => [ [1,10],[2,4] ] - // Then B= K*X => 2x2 - // Let's compute B carefully: - // B row0 => K[0,0]*X[0,*] + K[0,1]*X[1,*] => 2*(1,10)+3*(2,4) => (2+6,20+12)= (8,32) - // B row1 => K[1,0]*X[0,*] + K[1,1]*X[1,*] => 0*(1,10)+4*(2,4) => (8,16) - // => B= [ (8,32),(8,16) ] - let Kdata = [|2.0;3.0; 0.0;4.0|] // 2x2 upper - let X_expected_data = [| 1.0; 10.0 - 2.0; 4.0 |] // shape=2x2 - let B_data = [| 8.0; 32.0 - 8.0; 16.0 |] - let Kmat = Matrix(2,2,Kdata) - let Bmat = Matrix(2,2,B_data) - let Xsol = LinearAlgebra.solveTriangularLinearSystems Kmat Bmat false // isLower=false => backward sub - for i in 0..3 do - Expect.floatClose Accuracy.high X_expected_data.[i] Xsol.Data.[i] $"X mismatch at idx={i}" - - // ===================================================================== - // solveTriangularLinearSystem - // ===================================================================== - testCase "solveTriangularLinearSystem: dimension mismatch => throws" <| fun _ -> - // K=2x2, v= length=3 => mismatch - let K = Matrix(2,2,[|2.0;0.0; 1.0;2.0|]) - let v = [|1.0;2.0;3.0|] - Expect.throwsT (fun () -> - let _ = LinearAlgebra.solveTriangularLinearSystem K v true - () - ) "Should throw dimension mismatch" - - testCase "solveTriangularLinearSystem: lower triangular forward substitution (2x2 single system)" <| fun _ -> - // K= L= [ [2,0],[1,2] ] - // We'll define a single x => [1,2], compute b => K*x, then see if we get x back. - // - // For x => [1.,2.], - // B row0 => 2*1 +0*2=2 - // B row1 => 1*1 +2*2=1+4=5 - // => b= [2,5] - let Kdata = [|2.0;0.0; 1.0;2.0|] - let Kmat = Matrix(2,2,Kdata) - let xExpected = [|1.0;2.0|] - let b = [|2.0;5.0|] - // Solve K*x=b - let xSol = LinearAlgebra.solveTriangularLinearSystem Kmat b true - Expect.floatClose Accuracy.high xExpected.[0] xSol.[0] "x[0] mismatch" - Expect.floatClose Accuracy.high xExpected.[1] xSol.[1] "x[1] mismatch" - - testCase "solveTriangularLinearSystem: upper triangular backward substitution (2x2 single system)" <| fun _ -> - // K= U= [ [2,3],[0,4] ] - // Let x => [1,2]. Then b => K*x => - // row0 => 2*1 +3*2=2+6=8 - // row1 => 0*1 +4*2=8 - // => b= [8,8] - let Kdata = [|2.0;3.0; 0.0;4.0|] - let Kmat = Matrix(2,2,Kdata) - let xExpected = [|1.0;2.0|] - let b = [|8.0;8.0|] - let xSol = LinearAlgebra.solveTriangularLinearSystem Kmat b false - Expect.floatClose Accuracy.high xExpected.[0] xSol.[0] "x[0] mismatch" - Expect.floatClose Accuracy.high xExpected.[1] xSol.[1] "x[1] mismatch" - - ] - - testList "Additional Linear Algebra Tests" [ - - // ===================================================================== - // 1) qrDecompose - // ===================================================================== - testCase "qrDecompose: Q*R ~ A for a small 3x2" <| fun _ -> - // A=3x2 => [ [1.,2.],[3.,4.],[5.,6.] ] - let Adata = [|1.;2.; 3.;4.; 5.;6.|] - let A = Matrix(3, 2, Adata) - - let Q, R = LinearAlgebra.qrDecompose A - // Q is 3x3 in the code above since we use the identity(3) initially, - // but only the first 2 columns or some partial region might be relevant. - // We'll do a truncated multiply to compare or do a naive Q*R if R is 3x2. - - // Let's do a direct approach: A' = Q * R (both are 3x2 effectively, if R is 3x2). - // If R is the same shape as A, it's 3x2 => multiply 3x3 * 3x2 isn't well-defined. - // But the code as posted doesn't necessarily do the typical Householder approach - // that modifies R to upper triangular shape. It's more of a placeholder. - // We'll do a "Compare shape" approach, then do a partial multiply in any case. - - let APrimeData = Array.zeroCreate (3*2) - // We'll assume R is 3x2. Then Q is 3x3 => Q(3x3)*R(3x2)= A'(3x2). - for i in 0..2 do - for j in 0..1 do - let mutable sum = 0.0 - for k in 0..2 do - sum <- sum + Q.[i,k] * R.[k,j] - APrimeData.[i*2 + j] <- sum - - // Compare A' with A - for idx in 0..5 do - Expect.floatClose Accuracy.high Adata.[idx] APrimeData.[idx] - $"A' vs A mismatch at idx={idx}" - - // ===================================================================== - // 2) leastSquares - // ===================================================================== - testCase "leastSquares: overdetermined system 3x2" <| fun _ -> - // We'll create a design matrix A=3x2, b=3 - // A= [ [1.,2.], - // [2.,1.], - // [3.,4.] ] - // b= [ [8.],[10.],[19.] ] - // We want to solve min ||A x - b||^2 for x in R^2. - // We'll pick a small example and do a naive check or compare with a known solution if possible. - - let Adata = [|1.;2.; 2.;1.; 3.;4.|] - let A = Matrix(3, 2, Adata) - let b = [|8.; 10.; 19.|] - - let x = LinearAlgebra.leastSquares A b - // We only do a round-trip check: A*x ~ b in least-squares sense. - // We'll compute A*x (3x2 * 2 => 3) and see if that is close to b. - let Ax = - let result = Array.zeroCreate 3 - for i in 0..2 do - // row i => i*2, dot with x - let rowOffset = i*2 - result.[i] <- Adata.[rowOffset]*x.[0] + Adata.[rowOffset+1]*x.[1] - result - - // Compare Ax to b - for i in 0..2 do - // Because it's least squares, we might not get an exact match if system is not exactly consistent. - // But let's see if it's close. - Expect.floatClose Accuracy.high b.[i] Ax.[i] $"A*x mismatch at row {i}" - - // ===================================================================== - // 3) cholesky - // ===================================================================== - testCase "cholesky: factor a positive-definite 3x3" <| fun _ -> - // We'll define A => 3x3 symmetric positive definite. - // E.g. A= [ [4, 12, -16], - // [12,37, -43], - // [-16, -43, 98] ] - // Classic example => L => [ [2,0,0], [6,1,0], [-8,5,3] ] - let Adata = [| - 4.0; 12.0; -16.0; - 12.0; 37.0; -43.0; - -16.0; -43.0; 98.0; |] - let A = Matrix(3,3,Adata) - let L = LinearAlgebra.cholesky A - // Compare with known L - let Lexpected = [| 2.0; 0.0; 0.0; - 6.0; 1.0; 0.0; - -8.0; 5.0; 3.0; |] - for i in 0..8 do - Expect.floatClose Accuracy.high Lexpected.[i] L.Data.[i] $"L mismatch at idx {i}" - - testCase "cholesky: throws if matrix is not square" <| fun _ -> - let nonsquare = Matrix(2,3, [|1.0;2.0;3.0;4.0;5.0;6.0|]) - Expect.throwsT (fun () -> - let _ = LinearAlgebra.cholesky nonsquare - () - ) "Should throw if not square" - - // ===================================================================== - // 4) leastSquaresCholesky - // ===================================================================== - testCase "leastSquaresCholesky: small example" <| fun _ -> - // We'll do the same design matrix from earlier, which is 3x2, and b= length=3. - let Adata = [|1.;2.; 2.;1.; 3.;4.|] - let A = Matrix(3, 2, Adata) - let b = [|8.; 10.; 19.|] - - let x = LinearAlgebra.leastSquaresCholesky A b - // We'll do the same "A*x ~ b" check as above - let Ax = - let result = Array.zeroCreate 3 - for i in 0..2 do - let rowOffset = i*2 - result.[i] <- Adata.[rowOffset]*x.[0] + Adata.[rowOffset+1]*x.[1] - result - for i in 0..2 do - Expect.floatClose Accuracy.high b.[i] Ax.[i] $"A*x mismatch at row {i}" - - // ===================================================================== - // 5a) hatMatrix - // ===================================================================== - testCase "hatMatrix: check if H = Q1 Q1^T for a small design matrix" <| fun _ -> - // We'll do design=3x2 => same as above - let Adata = [|1.;2.; 2.;1.; 3.;4.|] - let A = Matrix(3, 2, Adata) - let H = LinearAlgebra.hatMatrix A - // We expect H to be 3x3. We can do a partial check: - // H ~ Q1 Q1^T, where Q1 is from the Householder-based QR in the code. - // We'll check shape => should be 3x3, plus we can check if H^2=H (idempotent property). - Expect.equal (H.NumRows, H.NumCols) (3,3) "Hat matrix is 3x3" - - // Quick idempotence test: H^2 ~ H - let H2data = Array.zeroCreate (3*3) - for i in 0..2 do - for j in 0..2 do - let mutable sum = 0.0 - for k in 0..2 do - sum <- sum + H.[i,k] * H.[k,j] - H2data.[i*3 + j] <- sum - - for idx in 0..8 do - Expect.floatClose Accuracy.high H.Data.[idx] H2data.[idx] $"Hat matrix not idempotent at idx={idx}" - - // ===================================================================== - // 5b) leverageBy and leverage - // ===================================================================== - testCase "leverageBy: diagonal of H" <| fun _ -> - // We'll reuse the hat matrix from above, check if leverageBy returns the diagonal - let Adata = [|1.;2.; 2.;1.; 3.;4.|] - let A = Matrix(3, 2, Adata) - let H = LinearAlgebra.hatMatrix A - let diag = LinearAlgebra.leverageBy H - // Compare with Matrix.getDiagonal - let diag2 = Matrix.getDiagonal H - Expect.equal diag diag2 "Expected same diagonal from leverageBy" - - testCase "leverage: direct Q approach" <| fun _ -> - // We'll see if leverage designMatrix ~ diagonal of H - let Adata = [|1.;2.; 2.;1.; 3.;4.|] - let A = Matrix(3, 2, Adata) - // direct approach => Q1 from qrDecompose - let directLever = LinearAlgebra.leverage A - // The same as leverageBy (hatMatrix's diagonal) - let H = LinearAlgebra.hatMatrix A - let diagH = Matrix.getDiagonal H - Expect.equal directLever diagH "Leverage mismatch" - - // ===================================================================== - // 6) luDecompose - // ===================================================================== - testCase "luDecompose: pivot array, L and U multiply back to P*A" <| fun _ -> - // A= 3x3 => we'll pick something that requires row swaps - // A= [ [0,2,1],[3,4,5],[1,2,3] ] - let Adata = [|0.;2.;1.; 3.;4.;5.; 1.;2.;3.|] - let A = Matrix(3,3,Adata) - let (P, L, U) = LinearAlgebra.luDecompose A - // Check dimension => L, U => 3x3, P => perm array - Expect.equal (L.NumRows, L.NumCols) (3,3) "L shape" - Expect.equal (U.NumRows, U.NumCols) (3,3) "U shape" - - // We'll see if P*A= L*U - // 1) build PA => permute rows of A by P => do a naive approach or if you have a function - let PA = Matrix.permuteRowsBy P A - // 2) multiply L,U => LU - let LUdata = Array.zeroCreate (3*3) - for i in 0..2 do - for j in 0..2 do - let mutable sum = 0.0 - for k in 0..2 do - sum <- sum + L.[i,k]*U.[k,j] - LUdata.[i*3 + j] <- sum - - // Compare LU vs PA - for idx in 0..8 do - Expect.floatClose Accuracy.high PA.Data.[idx] LUdata.[idx] $"LU mismatch at idx={idx}" - - // ===================================================================== - // 7) solveLinearSystems - // ===================================================================== - testCase "solveLinearSystems: A is 2x2, B=2x2" <| fun _ -> - // We'll define A => [ [2,3],[1,2] ], - // B => 2x2 => pick X => 2x2 => solve => see if we get X - // X => [ [1,10],[2,4] ] => B= A*X => let's do the multiply: - // row0 => (2,3)*X => 2*(1,10)+3*(2,4)= (2+6,20+12)= (8,32) - // row1 => (1,2)*X => 1*(1,10)+2*(2,4)= (1+4,10+8)= (5,18) - // => B => [ (8,32),(5,18) ] - let Adata = [|2.;3.; 1.;2.|] - let Bdata = [|8.;32.; 5.;18.|] - let A = Matrix(2,2,Adata) - let B = Matrix(2,2,Bdata) - let Xsol = LinearAlgebra.solveLinearSystems A B - let Xexpected = [|1.;10.; 2.;4.|] - for i in 0..3 do - Expect.floatClose Accuracy.high Xexpected.[i] Xsol.Data.[i] $"X mismatch at idx={i}" - - // ===================================================================== - // 8) solveLinearSystem - // ===================================================================== - testCase "solveLinearSystem: 3x3 single system" <| fun _ -> - // A => [ [0,2,1],[3,4,5],[1,2,3] ] from above, b => let's pick x => [1,2,3], compute b => A*x - // row0 => 0*1 +2*2 +1*3= 4+3=7 - // row1 => 3*1 +4*2 +5*3= 3+8+15=26 - // row2 => 1*1 +2*2 +3*3= 1+4+9=14 - let Adata = [|0.;2.;1.; 3.;4.;5.; 1.;2.;3.|] - let A = Matrix(3,3,Adata) - let b = [|7.;26.;14.|] - let xSol = LinearAlgebra.solveLinearSystem A b - let expected = [|1.;2.;3.|] - for i in 0..2 do - Expect.floatClose Accuracy.high expected.[i] xSol.[i] $"x mismatch at {i}" - - // ===================================================================== - // 9) inverse - // ===================================================================== - testCase "inverse: 2x2 inverse" <| fun _ -> - // A => [ [1,2],[3,4] ], inverse => [ [-2,1],[1.5, -0.5] ] - // because 1*4 -2*3= (4-6)= -2 => A^-1 => 1/det * [ [4,-2],[-3,1] ] => 1/-2 => [ [-2,1],[1.5,-0.5] ] - let Adata = [|1.;2.; 3.;4.|] - let A = Matrix(2,2,Adata) - let Ainverse = LinearAlgebra.inverse A - // Compare with known - let expected = [| -2.0; 1.0; 1.5; -0.5 |] - for i in 0..3 do - Expect.floatClose Accuracy.high expected.[i] Ainverse.Data.[i] $"Inverse mismatch at idx={i}" - - testCase "inverse: dimension mismatch => throws" <| fun _ -> - let nonsquare = Matrix(2,3,[|1.;2.;3.;4.;5.;6.|]) - Expect.throwsT (fun () -> - let _ = LinearAlgebra.inverse nonsquare - () - ) "Should throw if not square" - ] - - - - - ] diff --git a/tests/FSharp.Stats.Tests/LinearAlgebra.fs b/tests/FSharp.Stats.Tests/LinearAlgebra.fs deleted file mode 100644 index 48d7d5aa2..000000000 --- a/tests/FSharp.Stats.Tests/LinearAlgebra.fs +++ /dev/null @@ -1,1518 +0,0 @@ -module LinearAlgebraTests - -open Expecto - -open FSharp.Stats -open FSharp.Stats.Algebra -open TestExtensions - - -[] -let householderTests = - testList "Householder tests" [ - - test "Householder reflection zeros subcolumn (3x2 matrix)" { - let A = Matrix(3, 2, [| 4.0; 1.0; - 2.0; 3.0; - 6.0; 5.0 |]) - let R = Matrix.copy A - let x = Matrix.getCol 0 R |> Vector.sub 0 - - let h = Householder.create x - Householder.applyLeft(h, R, 0) - - // After application, first column should be [beta, 0, 0] - Expect.floatClose Accuracy.high R.[1,0] 0.0 "R[1,0] should be zero" - Expect.floatClose Accuracy.high R.[2,0] 0.0 "R[2,0] should be zero" - - // Check tau and beta match known values (approximate) - let expectedBeta = sqrt (4.0**2 + 2.0**2 + 6.0**2) // ||x|| - Expect.floatClose Accuracy.high (float h.Beta) expectedBeta "Beta should match norm" - Expect.isTrue (float h.Tau > 0.0 && float h.Tau < 2.0) "Tau should be in (0, 2)" - } - - test "Householder reflection zeros subcolumn (2x2 matrix)" { - let A = Matrix(2, 2, [| 3.0; 1.0; - 4.0; 5.0 |]) - let R = Matrix.copy A - let x = Matrix.getCol 0 R |> Vector.sub 0 - - let h = Householder.create x - Householder.applyLeft(h, R, 0) - - Expect.floatClose Accuracy.high R.[1,0] 0.0 "R[1,0] should be zero" - let expectedBeta = sqrt (3.0**2 + 4.0**2) - Expect.floatClose Accuracy.high (float h.Beta) expectedBeta "Beta should match norm" - } - - test "Tau and v correctness on a known input" { - let x = [| 3.0; 4.0 |] - let h = Householder.create x - - // We expect: - // - v[0] = 1 - // - v[1] = (4 / v0), since we normalize the vector to have v[0] = 1 - // - tau e (0, 2), beta = ||x|| - Expect.equal h.V.[0] 1.0 "v[0] should be 1.0" - Expect.isTrue (float h.Tau > 0.0 && float h.Tau < 2.0) "Tau should be reasonable" - Expect.floatClose Accuracy.high (float h.Beta) 5.0 "Beta should be ||x|| = 5.0" - } - - test "Degenerate vector returns trivial Householder" { - let x = [| 0.0; 0.0; 0.0 |] - let h = Householder.create x - Expect.equal h.Tau 0.0 "Tau should be 0.0" - Expect.equal h.Beta 0.0 "Beta should be 0.0" - Expect.sequenceEqual h.V [| 1.0; 0.0; 0.0 |] "v should be unit vector" - } - - ] - - - - -[] -let subScaledRowInPlaceTests = - testList "subScaledRowInPlace" [ - - test "Basic subtraction (no offset)" { - let dst = [| 10.0; 20.0; 30.0 |] - let src = [| 1.0; 2.0; 3.0 |] - LinearAlgebra.subScaledRowInPlace 2.0 0 0 3 dst src - let expected = [| 8.0; 16.0; 24.0 |] - Expect.sequenceEqual dst expected "Subtraction incorrect" - } - - test "With dst and src offset" { - let dst = [| 0.0; 10.0; 20.0; 30.0; 0.0 |] - let src = [| 0.0; 1.0; 2.0; 3.0; 0.0 |] - // Subtract 2src[1..3] from dst[1..3] - LinearAlgebra.subScaledRowInPlace 2.0 1 1 3 dst src - let expected = [| 0.0; 8.0; 16.0; 24.0; 0.0 |] - Expect.sequenceEqual dst expected "Offset subtraction incorrect" - } - - test "Single element (scalar fallback)" { - let dst = [| 42.0 |] - let src = [| 2.0 |] - LinearAlgebra.subScaledRowInPlace 3.0 0 0 1 dst src - let expected = [| 36.0 |] - Expect.sequenceEqual dst expected "Scalar fallback incorrect" - } - - test "No modification outside range" { - let dst = [| 1.0; 2.0; 3.0; 4.0 |] - let src = [| 0.0; 1.0; 1.0; 0.0 |] - LinearAlgebra.subScaledRowInPlace 2.0 1 1 2 dst src - let expected = [| 1.0; 0.0; 1.0; 4.0 |] - Expect.sequenceEqual dst expected "Boundary elements modified" - } - - test "basic 3-element row subtraction" { - let dst = [| 1.0; 2.0; 3.0 |] - let src = [| 4.0; 5.0; 6.0 |] - let alpha = 2.0 - let expected = [| -7.0; -8.0; -9.0 |] - - LinearAlgebra.subScaledRowInPlace alpha 0 0 3 dst src - - Expect.sequenceEqual dst expected "Result should be elementwise dst - alpha * src" - } - - test "offsets respected correctly" { - let dst = [| 0.0; 1.0; 2.0; 3.0; 4.0 |] - let src = [| 0.0; 0.0; 1.0; 2.0; 3.0 |] - let alpha = 2.0 - let expected = [| 0.0; 1.0; 0.0; -1.0; -2.0 |] - - // Only update dst[2..4] = [2.0; 3.0; 4.0] with src[2..4] = [1.0; 2.0; 3.0] - LinearAlgebra.subScaledRowInPlace alpha 2 2 3 dst src - - Expect.sequenceEqual dst expected "Offsets should target the correct subarrays" - } - - ] - -[] -let qrDecompositionTests = - testList "QR Decomposition (Modified Gram-Schmidt)" [ - - test "Decompose identity matrix" { - let A = Matrix.identity 3 - let Q, R = LinearAlgebra.qrModifiedGramSchmidt A - let I = Matrix.identity 3 - TestExtensions.floatMatrixClose Accuracy.high Q I "Q should be identity" - TestExtensions.floatMatrixClose Accuracy.high R I "R should be identity" - } - - test "Reconstruct original matrix from Q * R" { - let A = Matrix(3, 2, [| 1.0; 0.0; - 1.0; 1.0; - 0.0; 1.0 |]) - let Q, R = LinearAlgebra.qrModifiedGramSchmidt A - let QR = Matrix.matmul Q R - TestExtensions.floatMatrixClose Accuracy.high QR A "Q * R should reconstruct A" - } - - test "Q has orthonormal columns" { - let A = Matrix(3, 2, [| 1.0; 0.0; - 1.0; 1.0; - 0.0; 1.0 |]) - let Q, _ = LinearAlgebra.qrModifiedGramSchmidt A - let QTQ = Matrix.matmul (Matrix.transpose Q) Q - let I = Matrix.identity 2 - TestExtensions.floatMatrixClose Accuracy.high QTQ I "Q^TQ should be identity" - } - - test "R is upper triangular" { - let A = Matrix(3, 2, [| 1.0; 0.0; - 1.0; 1.0; - 0.0; 1.0 |]) - let _, R = LinearAlgebra.qrModifiedGramSchmidt A - for i in 0 .. R.NumRows - 1 do - for j in 0 .. i - 1 do - Expect.floatClose Accuracy.high R.[i, j] 0.0 $"R[{i},{j}] should be zero" - } - - test "Tall matrix 4x2 decomposition" { - let A = Matrix(4, 2, [| 1.0; 2.0; - 3.0; 4.0; - 5.0; 6.0; - 7.0; 8.0 |]) - let Q, R = LinearAlgebra.qrModifiedGramSchmidt A - let QR = Matrix.matmul Q R - TestExtensions.floatMatrixClose Accuracy.medium QR A "QR ~ A for tall matrix" - } - - test "Wide matrix throws or truncates" { - let A = Matrix(2, 3, [| 1.0; 2.0; 3.0; - 4.0; 5.0; 6.0 |]) - Expect.throws (fun () -> LinearAlgebra.qrModifiedGramSchmidt A |> ignore) - "Wide matrices are not supported (m < n)" - } - ] - -[] -let backSubstituteTests = - testList "Back substitution tests" [ - - test "Solve simple upper triangular system" { - // R = [2 1] - // [0 3] - let r = Matrix(2, 2, [| 2.0; 1.0; - 0.0; 3.0 |]) - let y = [| 5.0; 6.0 |] - let x = LinearAlgebra. backSubstitute r y - // Solve: 3x1 = 6 -> x1 = 2 - // Then: 2x0 + x1 = 5 -> x0 = (5 - 1*2)/2 = 1.5 - let expected = [| 1.5; 2.0 |] - for i in 0..1 do - Expect.floatClose Accuracy.high x.[i] expected.[i] $"x[{i}] incorrect" - } - - test "Identity matrix returns y as solution" { - let r = Matrix.identity 3 - let y = [| 4.0; -2.0; 0.5 |] - let x = LinearAlgebra.backSubstitute r y - Expect.sequenceEqual x y "Identity matrix should return y = x" - } - - test "Upper triangular with zeros below diagonal" { - // R = [1 2 3] - // [0 4 5] - // [0 0 6] - let r = Matrix(3, 3, [| 1.0; 2.0; 3.0; - 0.0; 4.0; 5.0; - 0.0; 0.0; 6.0 |]) - let y = [| 14.0; 23.0; 18.0 |] - let x = LinearAlgebra.backSubstitute r y - let expected = [| 1.0; 2.0; 3.0 |] - for i in 0..2 do - Expect.floatClose Accuracy.high x.[i] expected.[i] $"x[{i}] incorrect" - } - - test "Throws on non-square R" { - let r = Matrix(2, 3, [| 1.0; 2.0; 3.0; - 0.0; 4.0; 5.0 |]) - let y = [| 1.0; 2.0 |] - Expect.throws (fun () -> LinearAlgebra.backSubstitute r y |> ignore) - "Should throw on non-square R" - } - - test "Throws on mismatched dimensions with y" { - let r = Matrix.identity 3 - let y = [| 1.0; 2.0 |] - Expect.throws (fun () -> LinearAlgebra.backSubstitute r y |> ignore) - "Should throw on mismatched y length" - } - - test "Throws on zero diagonal entry (division by zero)" { - let r = Matrix(2, 2, [| 0.0; 1.0; - 0.0; 2.0 |]) - let y = [| 3.0; 4.0 |] - Expect.throws (fun () -> LinearAlgebra.backSubstitute r y |> ignore) - "Should throw on division by zero" - } - ] - -// solveLinearQR -// solveTriangularLinearSystems - - -[] -let solveTriangularLinearSystemTests = - testList "solveTriangularLinearSystem tests" [ - - test "Solve L x = b (lower triangular)" { - // L = [1 0 0; 2 1 0; 3 4 1] - let L = Matrix(3, 3, [| 1.0; 0.0; 0.0; - 2.0; 1.0; 0.0; - 3.0; 4.0; 1.0 |]) - let b = [| 2.0; 5.0; 20.0 |] - let x = LinearAlgebra.solveTriangularLinearSystem L b true - // Solve: Lx = b -> x = [2; 1; 5] - let expected = [| 2.0; 1.0; 10.0 |] - for i in 0..2 do - Expect.floatClose Accuracy.high x.[i] expected.[i] $"x[{i}] incorrect" - } - - test "Solve L^T x = b (upper triangular)" { - // L = [1 0 0; 2 1 0; 3 4 1] - // L^T = [1 2 3; 0 1 4; 0 0 1] - let L = Matrix(3, 3, [| 1.0; 0.0; 0.0; - 2.0; 1.0; 0.0; - 3.0; 4.0; 1.0 |]) - - let b = [| 23.0; 9.0; 1.0 |] - let LT = Matrix.transpose L - let x = LinearAlgebra.solveTriangularLinearSystem LT b false - // Solve L^T x = b -> x = [1; 2; 1] - let expected = [| 10.0; 5.0; 1.0 |] - for i in 0..2 do - Expect.floatClose Accuracy.high x.[i] expected.[i] $"x[{i}] incorrect" - } - - test "Throws on mismatched dimensions" { - let L = Matrix.identity 3 - let b = [| 1.0; 2.0 |] - Expect.throws (fun () -> LinearAlgebra.solveTriangularLinearSystem L b true |> ignore) - "Should throw if dimensions don't match" - } - - test "Throws on zero diagonal (division by zero)" { - let L = Matrix(2, 2, [| 0.0; 0.0; - 1.0; 1.0 |]) - let b = [| 1.0; 2.0 |] - Expect.throws (fun () -> LinearAlgebra.solveTriangularLinearSystem L b true |> ignore) - "Should throw on division by zero" - } - ] - -[] -let qrTests = - testList "QR decomposition via Householder" [ - - test "Q * R reconstructs A" { - let A = Matrix(3, 2, [| 1.0; 1.0; - 1.0; 2.0; - 1.0; 3.0 |]) - let Q, R = LinearAlgebra.qrDecompose A - let QR = Matrix.matmul Q R - TestExtensions.floatMatrixClose Accuracy.high QR A "QR ~ A" - } - - test "Q is orthogonal: Q^TQ = I" { - let A = Matrix(3, 2, [| 1.0; 0.0; - 1.0; 1.0; - 1.0; 2.0 |]) - let Q, _ = LinearAlgebra.qrDecompose A - let QtQ = Matrix.matmul (Matrix.transpose Q) Q - let I = Matrix.identity Q.NumCols - TestExtensions.floatMatrixClose Accuracy.high QtQ I "Q^TQ ~ I" - } - - test "R is upper triangular" { - let A = Matrix(3, 2, [| 1.0; 0.0; - 2.0; 1.0; - 3.0; 2.0 |]) - let _, R = LinearAlgebra.qrDecompose A - for i = 0 to R.NumRows - 1 do - for j = 0 to i - 1 do - Expect.floatClose Accuracy.veryHigh R.[i,j] 0.0 $"R[{i},{j}] should be zero" - } - - test "QR of square matrix" { - let A = Matrix(3, 3, [| 1.0; 2.0; 3.0; - 4.0; 5.0; 6.0; - 7.0; 8.0; 9.0 |]) - let Q, R = LinearAlgebra.qrDecompose A - let QR = Q * R - TestExtensions.floatMatrixClose Accuracy.medium QR A "QR ~ A" - } - - test "QR of small square matrix" { - let A = Matrix(2, 2, [| 2.0; 1.0; - 1.0; 3.0 |]) - let Q, R = LinearAlgebra.qrDecompose A - let QR = Q * R - TestExtensions.floatMatrixClose Accuracy.medium QR A "QR ~ A" - } - - ] - -[] -let leastSquaresQRTests = - testList "Least squares (QR-based)" [ - - test "Overdetermined 3x2 system" { - let A = Matrix(3, 2, [| 1.0; 1.0; - 1.0; 2.0; - 1.0; 3.0 |]) - let b = [| 6.0; 0.0; 0.0 |] - let x = LinearAlgebra.leastSquares A b - let expected = [| 8.0; -3.0 |] - for i in 0..1 do - Expect.floatClose Accuracy.medium x.[i] expected.[i] $"x[{i}] incorrect" - } - - test "Underdetermined 2x3 system (minimum norm)" { - let A = Matrix(2, 3, [| 1.0; 2.0; 0.0; - 0.0; 1.0; 1.0 |]) - let b = [| 3.0; 2.0 |] - let x = LinearAlgebra.leastSquares A b - - // There are infinite solutions, but least norm solution is: - // min ||x|| such that Ax = b - // numpy gives: [0.33333333, 1.33333333, 0.66666667] - let expected = [| 0.33333333; 1.33333333; 0.66666667 |] - for i in 0..2 do - Expect.floatClose Accuracy.medium x.[i] expected.[i] $"x[{i}] incorrect" - } - - test "Square system returns exact solution" { - let A = Matrix(2, 2, [| 2.0; 1.0; - 1.0; 3.0 |]) - let b = [| 5.0; 10.0 |] - let x = LinearAlgebra.leastSquares A b - let expected = [| 1.0; 3.0 |] - for i in 0..1 do - Expect.floatClose Accuracy.high x.[i] expected.[i] $"x[{i}] incorrect" - } - - test "Residual Ax ~ projection of b" { - let A = Matrix(3, 2, [| 1.0; 1.0; - 1.0; 2.0; - 1.0; 3.0 |]) - let b = [| 6.0; 0.0; 0.0 |] - let x = LinearAlgebra.leastSquares A b - let Ax = Matrix.muliplyVector A x - let expected = [| 5.0; 2.0; -1.0 |] - for i in 0..2 do - Expect.floatClose Accuracy.medium Ax.[i] expected.[i] $"Ax[{i}] incorrect" - } - ] - - -[] -let choleskyTests = - testList "Cholesky decomposition tests" [ - - test "Decompose identity matrix" { - let I = Matrix.identity 3 - let L = LinearAlgebra.cholesky I - TestExtensions.floatMatrixClose Accuracy.high L I "L should be identity for identity input" - } - - test "Decompose known positive-definite matrix" { - // A = [4 2; 2 3] -> L = [2 0; 1 1.4142] - let A = Matrix(2, 2, [| 4.0; 2.0; - 2.0; 3.0 |]) - let L = LinearAlgebra.cholesky A - let expected = Matrix(2, 2, [| 2.0; 0.0; - 1.0; sqrt 2.0 |]) - for i in 0..1 do - for j in 0..1 do - Expect.floatClose Accuracy.medium L.[i,j] expected.[i,j] $"L[{i},{j}] incorrect" - } - - test "Reconstruct A from L * L^T" { - let A = Matrix(3, 3, [| 25.0; 15.0; -5.0; - 15.0; 18.0; 0.0; - -5.0; 0.0; 11.0 |]) - let L = LinearAlgebra.cholesky A - let LT = Matrix.transpose L - let reconstructed = Matrix.matmul L LT - TestExtensions.floatMatrixClose Accuracy.high reconstructed A "Reconstructed A <> original" - } - test "Throws on non-positive-definite matrix" { - // Not positive-definite: eigenvalues are [1, -1] - let A = Matrix(2, 2, [| 0.0; 1.0; - 1.0; 0.0 |]) - Expect.throws (fun () -> LinearAlgebra.cholesky A |> ignore) - "Should throw on non-positive-definite matrix" - } - - test "Throws on non-square matrix" { - let A = Matrix(2, 3, [| 1.0; 2.0; 3.0; - 2.0; 5.0; 6.0 |]) - Expect.throws (fun () -> LinearAlgebra.cholesky A |> ignore) - "Should throw on non-square matrix" - } - - test "Zero matrix throws (not positive-definite)" { - let A : Matrix = Matrix.zeroCreate 3 3 - Expect.throws (fun () -> LinearAlgebra.cholesky A |> ignore) - "Should throw on zero matrix" - } - - ] - -[] -let leastSquaresTests = - testList "Least Squares via Cholesky" [ - - test "Solve overdetermined 3x2 system" { - // A = [1 1; 1 2; 1 3], b = [6; 0; 0] - // Should find least-squares fit: beta = [8.0; -3.0] - let A = Matrix(3, 2, [| 1.0; 1.0; - 1.0; 2.0; - 1.0; 3.0 |]) - let b = [| 6.0; 0.0; 0.0 |] - let beta = LinearAlgebra.leastSquaresCholesky A b - let expected = [| 8.0; -3.0 |] - for i in 0..1 do - Expect.floatClose Accuracy.medium beta.[i] expected.[i] $"beta[{i}] incorrect" - } - - test "Reconstruction A * beta ~ projection of b" { - // Same setup as above - let A = Matrix(3, 2, [| 1.0; 1.0; - 1.0; 2.0; - 1.0; 3.0 |]) - let b = [| 6.0; 0.0; 0.0 |] - let beta = LinearAlgebra.leastSquaresCholesky A b - let predicted = Matrix.muliplyVector A beta - // Expected projection of b onto Col(A): A * (A' b) - let expected = [| 5.0; 2.0; -1.0 |] - for i in 0..2 do - Expect.floatClose Accuracy.medium predicted.[i] expected.[i] $"predicted[{i}] incorrect" - } - - test "Throws on dimension mismatch A and b" { - let A = Matrix.identity 3 - let b = [| 1.0; 2.0 |] - Expect.throws (fun () -> LinearAlgebra.leastSquaresCholesky A b |> ignore) - "Should throw if A.NumRows <> b.Length" - } - - test "Exact solution when A is square and full-rank" { - let A = Matrix(2, 2, [| 2.0; 1.0; - 1.0; 3.0 |]) - let b = [| 5.0; 10.0 |] - let beta = LinearAlgebra.leastSquaresCholesky A b - let expected = [| 1.0; 3.0 |] - for i in 0..1 do - Expect.floatClose Accuracy.high beta.[i] expected.[i] $"beta[{i}] incorrect" - } - - ] - - - -// hatMatrix -// leverageBy -// leverage -// luDecompose -// solveLinearSystems (LU) -// solveLinearSystem (LU) - - - - - - - - - -[] -let managedSVDTests = - - let svdManaged A = - let s,u,vt = LinearAlgebra.SVD A - let sM = - let tmp= Matrix.zeroCreate A.NumRows A.NumCols - for i = 0 to s.Length-1 do - tmp.[i,i] <- s.[i] - tmp - u,sM,vt - - let mSmallerN = Matrix.ofJaggedArray [| [|2.;-1.;2.;-1.|]; [|4.;3.;4.;3.|]; [|9.;13.;-13.;9.|]; |] - let mEqualN = Matrix.ofJaggedArray [| [|2.;-1.|]; [|9.;13.|]; |] - - testList "LinearAlgebra.LinearAlgebraManaged.SVD" [ - testCase "m=n Matrix: Recover from decomposition" <| fun () -> - let u,s,vt = svdManaged mEqualN - let mEqualNRecov = (u * s * vt) - let m = mEqualN.toJaggedArray() |> Array.concat - let m' = mEqualNRecov.toJaggedArray() |> Array.concat - TestExtensions.sequenceEqual Accuracy.high m m' "Matrices computed by SVD did not yield the initial matrix when multiplied." - - testCase "m=n Matrix: u and vt consist of unit vectors, row- and column- wise." <| fun () -> - let u,s,vt = svdManaged mEqualN - let vecNorms = - [| - u |> Matrix.mapiCols (fun _ v -> [|FSharp.Stats.Vector.norm v|]) - vt|> Matrix.mapiCols (fun _ v -> [|FSharp.Stats.Vector.norm v|]) - u |> Matrix.mapiRows (fun _ x -> [|FSharp.Stats.Vector.norm x|]) - vt|> Matrix.mapiRows (fun _ x -> [|FSharp.Stats.Vector.norm x|]) - |] - |> Array.map (fun m -> m.Data) - |> Array.concat - TestExtensions.sequenceEqual Accuracy.high (Array.create vecNorms.Length 1.) vecNorms "Matrices computed by SVD did not consist of unit vectors, row- and column- wise." - - testCase "m=n Matrix: s contains correct singular values." <| fun () -> - let s,u,vt = LinearAlgebra.SVD mEqualN - TestExtensions.sequenceEqual Accuracy.high ([|15.81461344;2.213142934|]) s "Matrices computed by SVD did not yield correct singular values." - - testCase "m - let u,s,vt = svdManaged mSmallerN - let mSmallernRecov = (u * s * vt) - let m = mSmallerN.Data - let m' = mSmallernRecov.Data - TestExtensions.sequenceEqual Accuracy.high m m' "Matrices computed by SVD did not yield the initial matrix when multiplied." - - testCase "m - let u,s,vt = svdManaged mSmallerN - let vecNorms = - [| - u |> Matrix.mapiCols (fun _ v -> [|FSharp.Stats.Vector.norm v|]) - vt|> Matrix.mapiCols (fun _ v -> [|FSharp.Stats.Vector.norm v|]) - u |> Matrix.mapiRows (fun _ x -> [|FSharp.Stats.Vector.norm x|]) - vt|> Matrix.mapiRows (fun _ x -> [|FSharp.Stats.Vector.norm x|]) - |] - |> Array.map (fun m -> m.Data) - |> Array.concat - TestExtensions.sequenceEqual Accuracy.high (Array.create vecNorms.Length 1.) vecNorms "Matrices computed by SVD did not consist of unit vectors, row- and column- wise." - - testCase "m - let s,u,vt = LinearAlgebra.SVD mSmallerN - TestExtensions.sequenceEqual Accuracy.high ([|22.51999394;6.986424855;2.00991059|]) s "Matrices computed by SVD did not yield correct singular values." - - testCase "m>n Matrix: Recover from decomposition" <| fun () -> - let u,s,vt = svdManaged (mSmallerN.Transpose()) - let mSmallernRecov = (u * s * vt) - let m = mSmallerN.Transpose().Data - let m' = mSmallernRecov.Data - TestExtensions.sequenceEqual Accuracy.high m m' "Matrices computed by SVD did not yield the initial matrix when multiplied." - - testCase "m>n Matrix: u and vt consist of unit vectors, row- and column- wise." <| fun () -> - let u,s,vt = svdManaged (mSmallerN.Transpose()) - let vecNorms = - [| - u |> Matrix.mapiCols (fun _ v -> [|FSharp.Stats.Vector.norm v|]) - vt|> Matrix.mapiCols (fun _ v -> [|FSharp.Stats.Vector.norm v|]) - u |> Matrix.mapiRows (fun _ x -> [|FSharp.Stats.Vector.norm x|]) - vt|> Matrix.mapiRows (fun _ x -> [|FSharp.Stats.Vector.norm x|]) - |] - |> Array.map (fun m -> m.Data) - |> Array.concat - TestExtensions.sequenceEqual Accuracy.high (Array.create vecNorms.Length 1.) vecNorms "Matrices computed by SVD did not consist of unit vectors, row- and column- wise." - - testCase "m>n Matrix: s contains correct singular values." <| fun () -> - let s,u,vt = LinearAlgebra.SVD (mSmallerN.Transpose()) - TestExtensions.sequenceEqual Accuracy.high ([|22.51999394;6.986424855;2.00991059|]) s "Matrices computed by SVD did not yield correct singular values." - ] - - -//[] -//let nullspace = - -// let mSmallerN = Matrix.ofJaggedArray [| [|2.;-1.;2.;-1.|]; [|4.;3.;4.;3.|]; [|9.;13.;-13.;9.|]; |] - -// testList "LinearAlgebra.nullspace" [ -// testCase "accuracy 1e-5" <| fun () -> -// let ns = LinearAlgebra.nullspace (Accuracy=1e-5) mSmallerN -// let prod = -// mSmallerN * ns -// |> Matrix.toJaggedSeq -// |> Seq.concat -// let expected = seq {0.;0.;0.;} -// TestExtensions.sequenceEqual Accuracy.veryHigh expected prod "A * (nullspace A) should be matrix of zeros" -// ] - -[] -let linearSystems = - - let KDiagonal1 = - [| - [|1.;0.;0.|] - [|0.;1.;0.|] - [|0.;0.;1.|] - |] - |> Matrix.ofJaggedArray - - let KUpper1 = - [| - [|1.;1.;1.|] - [|0.;1.;1.|] - [|0.;0.;1.|] - |] - |> Matrix.ofJaggedArray - - let KUpperNeg1 = - [| - [|-1.;-1.;-1.|] - [|0.;-1.;-1.|] - [|0.;0.;-1.|] - |] - |> Matrix.ofJaggedArray - - let KUpperInf = - [| - [|infinity;infinity;infinity|] - [|0.;infinity;infinity|] - [|0.;0.;infinity|] - |] - |> Matrix.ofJaggedArray - - let KUpperNegInf = - [| - [|-infinity;-infinity;-infinity|] - [|0.;-infinity;-infinity|] - [|0.;0.;-infinity|] - |] - |> Matrix.ofJaggedArray - - let KUpperNaN = - [| - [|nan;nan;nan|] - [|0.;nan;nan|] - [|0.;0.;nan|] - |] - |> Matrix.ofJaggedArray - - let KLower1 = - [| - [|1.;1.;1.|] - [|0.;1.;1.|] - [|0.;0.;1.|] - |] - |> Matrix.ofJaggedArray - |> Matrix.transpose - - let KLowerNeg1 = - [| - [|-1.;-1.;-1.|] - [|0.;-1.;-1.|] - [|0.;0.;-1.|] - |] - |> Matrix.ofJaggedArray - |> Matrix.transpose - - let KLowerInf = - [| - [|infinity;infinity;infinity|] - [|0.;infinity;infinity|] - [|0.;0.;infinity|] - |] - |> Matrix.ofJaggedArray - |> Matrix.transpose - - let KLowerNegInf = - [| - [|-infinity;-infinity;-infinity|] - [|0.;-infinity;-infinity|] - [|0.;0.;-infinity|] - |] - |> Matrix.ofJaggedArray - |> Matrix.transpose - - let KLowerNaN = - [| - [|nan;nan;nan|] - [|0.;nan;nan|] - [|0.;0.;nan|] - |] - |> Matrix.ofJaggedArray - |> Matrix.transpose - - let B1 = - [| - [|1.;1.;1.|] - [|1.;1.;1.|] - [|1.;1.;1.|] - |] - |> Matrix.ofJaggedArray - - let BNeg1 = - [| - [|-1.;-1.;-1.|] - [|-1.;-1.;-1.|] - [|-1.;-1.;-1.|] - |] - |> Matrix.ofJaggedArray - - let BInf = - [| - [|infinity;infinity;infinity|] - [|infinity;infinity;infinity|] - [|infinity;infinity;infinity|] - |] - |> Matrix.ofJaggedArray - - let BNegInf = - [| - [|-infinity;-infinity;-infinity|] - [|-infinity;-infinity;-infinity|] - [|-infinity;-infinity;-infinity|] - |] - |> Matrix.ofJaggedArray - - let BNaN = - [| - [|nan;nan;nan|] - [|nan;nan;nan|] - [|nan;nan;nan|] - |] - |> Matrix.ofJaggedArray - - let b1 = vector [|1.;1.;1.|] - - testList "Triangular Linear Systems" [ - // Tested vs R package "bdsmatrix: Routines for Block Diagonal Symmetric Matrices" Version 1.3-6 - testList "SolveTriangularLinearSystems (Upper)" [ - testCase "3x3 Upper Triangular Matrix with 3x3 Matrix (realistic example)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems - ( - [| - [|1.;2.;3.|]; - [|0.;1.;1.|]; - [|0.;0.;2.|] - |] - |> Matrix.ofJaggedArray - ) - ( - [| - [|8.;4.;2.|]; - [|4.;2.;1.|]; - [|2.;1.;0.|] - |] - |> Matrix.ofJaggedArray - ) - false - |> fun res -> - let expected = - matrix [| - [|-1.;-0.5;0.|]; - [|3.;1.5;1.|]; - [|1.;0.5;0.|] - |] - TestExtensions.sequenceEqual Accuracy.high res.Data expected.Data "Should be 3x3 Matrix: \n-1.;-0.5;0.\n3.;1.5;1.\n1.;0.5;0." - testCase "3x3 diagonal Matrix (Values = 1) with 3x3 Matrix (Values = 1)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KDiagonal1 B1 false - |> fun res -> - let expected = - matrix [| - [|1.;1.;1.|]; - [|1.;1.;1.|]; - [|1.;1.;1.|] - |] - TestExtensions.sequenceEqual Accuracy.high res.Data expected.Data "Should be 3x3 Matrix of 1" - testCase "3x3 Upper Triangular Matrix (Values = 1) with 3x3 Matrix (Values = 1)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KUpper1 B1 false - |> fun res -> - let expected = - matrix [| - [|0.;0.;0.|]; - [|0.;0.;0.|]; - [|1.;1.;1.|] - |] - TestExtensions.sequenceEqual Accuracy.high res.Data expected.Data "Should be 3x3 Matrix with 1 in last row" - testCase "3x3 Upper Triangular Matrix (Values = -1) with 3x3 Matrix (Values = 1)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KUpperNeg1 B1 false - |> fun res -> - let expected = - matrix [| - [|0.;0.;0.|]; - [|0.;0.;0.|]; - [|-1.;-1.;-1.|] - |] - TestExtensions.sequenceEqual Accuracy.high res.Data expected.Data "Should be 3x3 Matrix with 1 in last row" - testCase "3x3 Upper Triangular Matrix (Values = Inf) with 3x3 Matrix (Values = 1)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KUpperInf B1 false - |> fun res -> - let expected = - matrix [| - [|nan;nan;nan|]; - [|nan;nan;nan|]; - [|0.;0.;0.|] - |] - TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix with 0 in last row and NaN in other rows" - testCase "3x3 Upper Triangular Matrix (Values = -Inf) with 3x3 Matrix (Values = 1)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KUpperNegInf B1 false - |> fun res -> - let expected = - matrix [| - [|nan;nan;nan|]; - [|nan;nan;nan|]; - [|0.;0.;0.|] - |] - TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix with 0 in last row and NaN in other rows" - testCase "3x3 Upper Triangular Matrix (Values = NaN) with 3x3 Matrix (Values = 1)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KUpperNaN B1 false - |> fun res -> - let expected = - matrix [| - [|nan;nan;nan|]; - [|nan;nan;nan|]; - [|nan;nan;nan|] - |] - TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix of NaN" - testCase "3x3 diagonal Matrix (Values = 1) with 3x3 Matrix (Values = Inf)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KDiagonal1 BInf false - |> fun res -> - let expected = - matrix [| - [|nan;nan;nan|]; - [|nan;nan;nan|]; - [|infinity;infinity;infinity|] - |] - TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix with Inf in last row and NaN in other rows" - testCase "3x3 Upper Triangular Matrix (Values = 1) with 3x3 Matrix (Values = Inf)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KUpper1 BInf false - |> fun res -> - let expected = - matrix [| - [|nan;nan;nan|]; - [|nan;nan;nan|]; - [|infinity;infinity;infinity|] - |] - TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix with Inf in last row and NaN in other rows" - testCase "3x3 Upper Triangular Matrix (Values = -1) with 3x3 Matrix (Values = Inf)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KUpperNeg1 BInf false - |> fun res -> - let expected = - matrix [| - [|nan;nan;nan|]; - [|nan;nan;nan|]; - [|-infinity;-infinity;-infinity|] - |] - TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix with Inf in last row and NaN in other rows" - testCase "3x3 Upper Triangular Matrix (Values = Inf) with 3x3 Matrix (Values = Inf)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KUpperInf BInf false - |> fun res -> - let expected = - matrix [| - [|nan;nan;nan|]; - [|nan;nan;nan|]; - [|nan;nan;nan|] - |] - TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix of NaN" - testCase "3x3 Upper Triangular Matrix (Values = -Inf) with 3x3 Matrix (Values = Inf)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KUpperNegInf BInf false - |> fun res -> - let expected = - matrix [| - [|nan;nan;nan|]; - [|nan;nan;nan|]; - [|nan;nan;nan|] - |] - TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix of NaN" - testCase "3x3 Upper Triangular Matrix (Values = NaN) with 3x3 Matrix (Values = Inf)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KUpperNaN BInf false - |> fun res -> - let expected = - matrix [| - [|nan;nan;nan|]; - [|nan;nan;nan|]; - [|nan;nan;nan|] - |] - TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix of NaN" - testCase "3x3 diagonal Matrix (Values = 1) with 3x3 Matrix (Values = -Inf)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KDiagonal1 BNegInf false - |> fun res -> - let expected = - matrix [| - [|nan;nan;nan|]; - [|nan;nan;nan|]; - [|-infinity;-infinity;-infinity|] - |] - TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix with -Inf in last row and NaN in other rows" - testCase "3x3 Upper Triangular Matrix (Values = 1) with 3x3 Matrix (Values = -Inf)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KUpper1 BNegInf false - |> fun res -> - let expected = - matrix [| - [|nan;nan;nan|]; - [|nan;nan;nan|]; - [|-infinity;-infinity;-infinity|] - |] - TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix with -Inf in last row and NaN in other rows" - testCase "3x3 Upper Triangular Matrix (Values = Inf) with 3x3 Matrix (Values = -Inf)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KUpperInf BNegInf false - |> fun res -> - let expected = - matrix [| - [|nan;nan;nan|]; - [|nan;nan;nan|]; - [|nan;nan;nan|] - |] - TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix of NaN" - testCase "3x3 Upper Triangular Matrix (Values = -Inf) with 3x3 Matrix (Values = -Inf)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KUpperNegInf BNegInf false - |> fun res -> - let expected = - matrix [| - [|nan;nan;nan|]; - [|nan;nan;nan|]; - [|nan;nan;nan|] - |] - TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix of NaN" - testCase "3x3 Upper Triangular Matrix (Values = NaN) with 3x3 Matrix (Values = -Inf)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KUpperNaN BNegInf false - |> fun res -> - let expected = - matrix [| - [|nan;nan;nan|]; - [|nan;nan;nan|]; - [|nan;nan;nan|] - |] - TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix of NaN" - testCase "3x3 diagonal Matrix (Values = 1) with 3x3 Matrix (Values = NaN)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KDiagonal1 BNaN false - |> fun res -> - let expected = - matrix [| - [|nan;nan;nan|]; - [|nan;nan;nan|]; - [|nan;nan;nan|] - |] - TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix with Inf in last row and NaN in other rows" - testCase "3x3 Upper Triangular Matrix (Values = 1) with 3x3 Matrix (Values = NaN)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KUpper1 BNaN false - |> fun res -> - let expected = - matrix [| - [|nan;nan;nan|]; - [|nan;nan;nan|]; - [|nan;nan;nan|] - |] - TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix with Inf in last row and NaN in other rows" - testCase "3x3 Upper Triangular Matrix (Values = Inf) with 3x3 Matrix (Values = NaN)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KUpperInf BNaN false - |> fun res -> - let expected = - matrix [| - [|nan;nan;nan|]; - [|nan;nan;nan|]; - [|nan;nan;nan|] - |] - TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix of NaN" - testCase "3x3 Upper Triangular Matrix (Values = -Inf) with 3x3 Matrix (Values = NaN)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KUpperNegInf BNaN false - |> fun res -> - let expected = - matrix [| - [|nan;nan;nan|]; - [|nan;nan;nan|]; - [|nan;nan;nan|] - |] - TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix of NaN" - testCase "3x3 Upper Triangular Matrix (Values = NaN) with 3x3 Matrix (Values = NaN)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KUpperNaN BNaN false - |> fun res -> - let expected = - matrix [| - [|nan;nan;nan|]; - [|nan;nan;nan|]; - [|nan;nan;nan|] - |] - TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix of NaN" - testCase "3x3 diagonal Matrix (Values = 1) with 3x3 Matrix (Values = -1)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KDiagonal1 BNeg1 false - |> fun res -> - let expected = - matrix [| - [|-1.;-1.;-1.|]; - [|-1.;-1.;-1.|]; - [|-1.;-1.;-1.|] - |] - TestExtensions.sequenceEqual Accuracy.high res.Data expected.Data "Should be 3x3 Matrix of -1" - testCase "3x3 Upper Triangular Matrix (Values = 1) with 3x3 Matrix (Values = -1)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KUpper1 BNeg1 false - |> fun res -> - let expected = - matrix [| - [|0.;0.;0.|]; - [|0.;0.;0.|]; - [|-1.;-1.;-1.|] - |] - TestExtensions.sequenceEqual Accuracy.high res.Data expected.Data "Should be 3x3 Matrix with -1 in last row" - testCase "3x3 Upper Triangular Matrix (Values = -1) with 3x3 Matrix (Values = -1)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KUpperNeg1 BNeg1 false - |> fun res -> - let expected = - matrix [| - [|0.;0.;0.|]; - [|0.;0.;0.|]; - [|1.;1.;1.|] - |] - TestExtensions.sequenceEqual Accuracy.high res.Data expected.Data "Should be 3x3 Matrix with -1 in last row" - testCase "3x3 Upper Triangular Matrix (Values = Inf) with 3x3 Matrix (Values = -1)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KUpperInf BNeg1 false - |> fun res -> - let expected = - matrix [| - [|nan;nan;nan|]; - [|nan;nan;nan|]; - [|0.;0.;0.|] - |] - TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix with 0 in last row and NaN in other rows" - testCase "3x3 Upper Triangular Matrix (Values = -Inf) with 3x3 Matrix (Values = -1)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KUpperNegInf BNeg1 false - |> fun res -> - let expected = - matrix [| - [|nan;nan;nan|]; - [|nan;nan;nan|]; - [|0.;0.;0.|] - |] - TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix with 0 in last row and NaN in other rows" - testCase "3x3 Upper Triangular Matrix (Values = NaN) with 3x3 Matrix (Values = -1)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KUpperNaN BNeg1 false - |> fun res -> - let expected = - matrix [| - [|nan;nan;nan|]; - [|nan;nan;nan|]; - [|nan;nan;nan|] - |] - TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix of NaN" - ] - // Tested vs R package "bdsmatrix: Routines for Block Diagonal Symmetric Matrices" Version 1.3-6 - testList "SolveTriangularLinearSystems (Lower)" [ - testCase "3x3 Lower Triangular Matrix with 3x3 Matrix (realistic example)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems - ( - [| - [|1.;0.;0.|]; - [|2.;1.;0.|]; - [|3.;1.;2.|] - |] - |> Matrix.ofJaggedArray - ) - ( - [| - [|8.;4.;2.|]; - [|4.;2.;1.|]; - [|2.;1.;0.|] - |] - |> Matrix.ofJaggedArray - ) - true - |> fun res -> - let expected = - matrix [| - [|8.;4.;2.|]; - [|-12.;-6.;-3.|]; - [|-5.;-2.5;-1.5|] - |] - TestExtensions.sequenceEqual Accuracy.high res.Data expected.Data "Should be 3x3 Matrix: \n8.;4.;2.\n-12.;-6.;-3.\n-5.;-2.5;-1.5" - testCase "3x3 diagonal Matrix (Values = 1) with 3x3 Matrix (Values = 1) (lower)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KDiagonal1 B1 true - |> fun res -> - let expected = - matrix [| - [|1.;1.;1.|]; - [|1.;1.;1.|]; - [|1.;1.;1.|] - |] - TestExtensions.sequenceEqual Accuracy.high res.Data expected.Data "Should be 3x3 Matrix of 1" - testCase "3x3 Lower Triangular Matrix (Values = 1) with 3x3 Matrix (Values = 1)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KLower1 B1 true - |> fun res -> - let expected = - matrix [| - [|1.;1.;1.|]; - [|0.;0.;0.|]; - [|0.;0.;0.|] - |] - TestExtensions.sequenceEqual Accuracy.high res.Data expected.Data "Should be 3x3 Matrix with 1 in first row" - testCase "3x3 Lower Triangular Matrix (Values = -1) with 3x3 Matrix (Values = 1)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KLowerNeg1 B1 true - |> fun res -> - let expected = - matrix [| - [|-1.;-1.;-1.|]; - [|0.;0.;0.|]; - [|0.;0.;0.|] - |] - TestExtensions.sequenceEqual Accuracy.high res.Data expected.Data "Should be 3x3 Matrix with -1 in first row" - testCase "3x3 Lower Triangular Matrix (Values = Inf) with 3x3 Matrix (Values = 1)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KLowerInf B1 true - |> fun res -> - let expected = - matrix [| - [|0.;0.;0.|]; - [|nan;nan;nan|]; - [|nan;nan;nan|] - |] - TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix with 0 in first row and NaN in other rows" - testCase "3x3 Lower Triangular Matrix (Values = -Inf) with 3x3 Matrix (Values = 1)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KLowerNegInf B1 true - |> fun res -> - let expected = - matrix [| - [|0.;0.;0.|]; - [|nan;nan;nan|]; - [|nan;nan;nan|] - |] - TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix with 0 in first row and NaN in other rows" - testCase "3x3 Lower Triangular Matrix (Values = NaN) with 3x3 Matrix (Values = 1)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KLowerNaN B1 true - |> fun res -> - let expected = - matrix [| - [|nan;nan;nan|]; - [|nan;nan;nan|]; - [|nan;nan;nan|] - |] - TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix of NaN" - testCase "3x3 diagonal Matrix (Values = 1) with 3x3 Matrix (Values = Inf) (lower)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KDiagonal1 BInf true - |> fun res -> - let expected = - matrix [| - [|infinity;infinity;infinity|]; - [|nan;nan;nan|]; - [|nan;nan;nan|] - |] - TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix with Inf in first row and NaN in other rows" - testCase "3x3 Upper Triangular Matrix (Values = 1) with 3x3 Matrix (Values = Inf)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KLower1 BInf true - |> fun res -> - let expected = - matrix [| - [|infinity;infinity;infinity|]; - [|nan;nan;nan|]; - [|nan;nan;nan|] - |] - TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix with Inf in first row and NaN in other rows" - testCase "3x3 Lower Triangular Matrix (Values = -1) with 3x3 Matrix (Values = Inf)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KLowerNeg1 BInf true - |> fun res -> - let expected = - matrix [| - [|-infinity;-infinity;-infinity|]; - [|nan;nan;nan|]; - [|nan;nan;nan|] - |] - TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix with Inf in first row and NaN in other rows" - testCase "3x3 Lower Triangular Matrix (Values = Inf) with 3x3 Matrix (Values = Inf)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KLowerInf BInf true - |> fun res -> - let expected = - matrix [| - [|nan;nan;nan|]; - [|nan;nan;nan|]; - [|nan;nan;nan|] - |] - TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix of NaN" - testCase "3x3 Lower Triangular Matrix (Values = -Inf) with 3x3 Matrix (Values = Inf)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KLowerNegInf BInf true - |> fun res -> - let expected = - matrix [| - [|nan;nan;nan|]; - [|nan;nan;nan|]; - [|nan;nan;nan|] - |] - TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix of NaN" - testCase "3x3 Lower Triangular Matrix (Values = NaN) with 3x3 Matrix (Values = Inf)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KLowerNaN BInf true - |> fun res -> - let expected = - matrix [| - [|nan;nan;nan|]; - [|nan;nan;nan|]; - [|nan;nan;nan|] - |] - - TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix of NaN" - testCase "3x3 diagonal Matrix (Values = 1) with 3x3 Matrix (Values = -Inf)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KDiagonal1 BNegInf true - |> fun res -> - let expected = - matrix [| - [|-infinity;-infinity;-infinity|]; - [|nan;nan;nan|]; - [|nan;nan;nan|] - |] - - TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix with -Inf in first row and NaN in other rows" - testCase "3x3 Lower Triangular Matrix (Values = 1) with 3x3 Matrix (Values = -Inf)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KLower1 BNegInf true - |> fun res -> - let expected = - matrix [| - [|-infinity;-infinity;-infinity|]; - [|nan;nan;nan|]; - [|nan;nan;nan|] - |] - - TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix with -Inf in first row and NaN in other rows" - testCase "3x3 Lower Triangular Matrix (Values = Inf) with 3x3 Matrix (Values = -Inf)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KLowerInf BNegInf true - |> fun res -> - let expected = - matrix [| - [|nan;nan;nan|]; - [|nan;nan;nan|]; - [|nan;nan;nan|] - |] - TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix of NaN" - testCase "3x3 Lower Triangular Matrix (Values = -Inf) with 3x3 Matrix (Values = -Inf)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KLowerNegInf BNegInf true - |> fun res -> - let expected = - matrix [| - [|nan;nan;nan|]; - [|nan;nan;nan|]; - [|nan;nan;nan|] - |] - - TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix of NaN" - testCase "3x3 Lower Triangular Matrix (Values = NaN) with 3x3 Matrix (Values = -Inf)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KLowerNaN BNegInf true - |> fun res -> - let expected = - matrix [| - [|nan;nan;nan|]; - [|nan;nan;nan|]; - [|nan;nan;nan|] - |] - - TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix of NaN" - testCase "3x3 diagonal Matrix (Values = 1) with 3x3 Matrix (Values = NaN) (lower)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KDiagonal1 BNaN true - |> fun res -> - let expected = - matrix [| - [|nan;nan;nan|]; - [|nan;nan;nan|]; - [|nan;nan;nan|] - |] - TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix with Inf in last row and NaN in other rows" - testCase "3x3 Lower Triangular Matrix (Values = 1) with 3x3 Matrix (Values = NaN)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KLower1 BNaN true - |> fun res -> - let expected = - matrix [| - [|nan;nan;nan|]; - [|nan;nan;nan|]; - [|nan;nan;nan|] - |] - TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix with Inf in last row and NaN in other rows" - testCase "3x3 Lower Triangular Matrix (Values = Inf) with 3x3 Matrix (Values = NaN)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KLowerInf BNaN true - |> fun res -> - let expected = - matrix [| - [|nan;nan;nan|]; - [|nan;nan;nan|]; - [|nan;nan;nan|] - |] - TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix of NaN" - testCase "3x3 Lower Triangular Matrix (Values = -Inf) with 3x3 Matrix (Values = NaN)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KLowerNegInf BNaN true - |> fun res -> - let expected = - matrix [| - [|nan;nan;nan|]; - [|nan;nan;nan|]; - [|nan;nan;nan|] - |] - - TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix of NaN" - testCase "3x3 Lower Triangular Matrix (Values = NaN) with 3x3 Matrix (Values = NaN)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KLowerNaN BNaN true - |> fun res -> - let expected = - matrix [| - [|nan;nan;nan|]; - [|nan;nan;nan|]; - [|nan;nan;nan|] - |] - - TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix of NaN" - testCase "3x3 diagonal Matrix (Values = 1) with 3x3 Matrix (Values = -1) (lower)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KDiagonal1 BNeg1 true - |> fun res -> - let expected = - matrix [| - [|-1.;-1.;-1.|]; - [|-1.;-1.;-1.|]; - [|-1.;-1.;-1.|] - |] - - TestExtensions.sequenceEqual Accuracy.high res.Data expected.Data "Should be 3x3 Matrix of -1" - testCase "3x3 Lower Triangular Matrix (Values = 1) with 3x3 Matrix (Values = -1)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KLower1 BNeg1 true - |> fun res -> - let expected = - matrix [| - [|-1.;-1.;-1.|]; - [|0.;0.;0.|]; - [|0.;0.;0.|] - |] - - TestExtensions.sequenceEqual Accuracy.high res.Data expected.Data "Should be 3x3 Matrix with -1 in first row" - testCase "3x3 Lower Triangular Matrix (Values = -1) with 3x3 Matrix (Values = -1)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KLowerNeg1 BNeg1 true - |> fun res -> - let expected = - matrix [| - [|1.;1.;1.|]; - [|0.;0.;0.|]; - [|0.;0.;0.|] - |] - - TestExtensions.sequenceEqual Accuracy.high res.Data expected.Data "Should be 3x3 Matrix with -1 in first row" - testCase "3x3 Lower Triangular Matrix (Values = Inf) with 3x3 Matrix (Values = -1)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KLowerInf BNeg1 true - |> fun res -> - let expected = - matrix [| - [|0.;0.;0.|]; - [|nan;nan;nan|]; - [|nan;nan;nan|] - |] - - TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix with 0 in first row and NaN in other rows" - testCase "3x3 Lower Triangular Matrix (Values = -Inf) with 3x3 Matrix (Values = -1)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KLowerNegInf BNeg1 true - |> fun res -> - let expected = - matrix [| - [|0.;0.;0.|]; - [|nan;nan;nan|]; - [|nan;nan;nan|] - |] - - TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix with 0 in first row and NaN in other rows" - testCase "3x3 Lower Triangular Matrix (Values = NaN) with 3x3 Matrix (Values = -1)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystems KLowerNaN BNeg1 true - |> fun res -> - let expected = - matrix [| - [|nan;nan;nan|]; - [|nan;nan;nan|]; - [|nan;nan;nan|] - |] - - TestExtensions.sequenceEqualRoundedNaN 9 res.Data expected.Data "Should be 3x3 Matrix of NaN" - ] - testList "SolveTriangularLinearSystem (Upper)" [ - testCase "3x3 Upper Triangular Matrix with Vector (realistic example)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystem - ( - [| - [|1.;2.;3.|]; - [|0.;1.;1.|]; - [|0.;0.;2.|] - |] - |> Matrix.ofJaggedArray - ) - ( - [|8.;4.;2.|] - |> vector - ) - false - |> fun res -> - let expected = - [|-1.;3.;1.|] - TestExtensions.sequenceEqual Accuracy.high res expected "Should be Vector of -1.;3.;1." - testCase "3x3 diagonal Matrix (Values = 1) with Vector (Values = 1)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystem KDiagonal1 b1 false - |> fun res -> - let expected = [|1.;1.;1.|] - TestExtensions.sequenceEqualRoundedNaN 9 res expected "Should be Vector of 1" - testCase "3x3 Upper Triangular Matrix (Values = 1) with Vector (Values = 1)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystem KUpper1 b1 false - |> fun res -> - let expected = [|0.;0.;1.|] - TestExtensions.sequenceEqualRoundedNaN 9 res expected "Should be Vector of 0 0 1" - testCase "3x3 Upper Triangular Matrix (Values = -1) with Vector (Values = 1)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystem KUpperNeg1 b1 false - |> fun res -> - let expected = [|0.;0.;-1.|] - TestExtensions.sequenceEqualRoundedNaN 9 res expected "Should be Vector of 0 0 -1" - testCase "3x3 Upper Triangular Matrix (Values = Inf) with Vector (Values = 1)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystem KUpperInf b1 false - |> fun res -> - let expected = [|nan;nan;0|] - TestExtensions.sequenceEqualRoundedNaN 9 res expected "Should be Vector of NaN NaN 0" - testCase "3x3 Upper Triangular Matrix (Values = -Inf) with Vector (Values = 1)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystem KUpperNegInf b1 false - |> fun res -> - let expected = [|nan;nan;0|] - TestExtensions.sequenceEqualRoundedNaN 9 res expected "Should be Vector of NaN NaN 0" - testCase "3x3 Upper Triangular Matrix (Values = NaN) with Vector (Values = 1)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystem KUpperNaN b1 false - |> fun res -> - let expected = [|nan;nan;nan|] - TestExtensions.sequenceEqualRoundedNaN 9 res expected "Should be Vector of NaN" - ] - testList "SolveTriangularLinearSystem (Lower)" [ - testCase "3x3 Upper Triangular Matrix with Vector (realistic example)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystem - ( - [| - [|1.;0.;0.|]; - [|2.;1.;0.|]; - [|3.;1.;2.|] - |] - |> Matrix.ofJaggedArray - ) - ( - [|8.;4.;2.|] - |> vector - ) - true - |> fun res -> - let expected = - [|8.;-12.;-5.|] - TestExtensions.sequenceEqual Accuracy.high res expected "Should be Vector of 8.;-12.;-5." - testCase "3x3 diagonal Matrix (Values = 1) with Vector (Values = 1)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystem KDiagonal1 b1 true - |> fun res -> - let expected = [|1.;1.;1.|] - TestExtensions.sequenceEqualRoundedNaN 9 res expected "Should be Vector of 1" - testCase "3x3 Lower Triangular Matrix (Values = 1) with Vector (Values = 1)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystem KLower1 b1 true - |> fun res -> - let expected = [|1.;0.;0.|] - TestExtensions.sequenceEqualRoundedNaN 9 res expected "Should be Vector of 1 0 0" - testCase "3x3 Lower Triangular Matrix (Values = -1) with Vector (Values = 1)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystem KLowerNeg1 b1 true - |> fun res -> - let expected = [|-1.;0.;0.|] - TestExtensions.sequenceEqualRoundedNaN 9 res expected "Should be Vector of -1 0 0" - testCase "3x3 Lower Triangular Matrix (Values = Inf) with Vector (Values = 1)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystem KLowerInf b1 true - |> fun res -> - let expected = [|0.;nan;nan|] - TestExtensions.sequenceEqualRoundedNaN 9 res expected "Should be Vector of 0 NaN NaN" - testCase "3x3 Lower Triangular Matrix (Values = -Inf) with Vector (Values = 1)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystem KLowerNegInf b1 true - |> fun res -> - let expected = [|0.;nan;nan|] - TestExtensions.sequenceEqualRoundedNaN 9 res expected "Should be Vector of 0 NaN NaN" - testCase "3x3 Lower Triangular Matrix (Values = NaN) with Vector (Values = 1)" <| fun () -> - LinearAlgebra.solveTriangularLinearSystem KLowerNaN b1 true - |> fun res -> - let expected = [|nan;nan;nan|] - TestExtensions.sequenceEqualRoundedNaN 9 res expected "Should be Vector of NaN" - ] - ] - diff --git a/tests/FSharp.Stats.Tests/Matrix.fs b/tests/FSharp.Stats.Tests/Matrix.fs deleted file mode 100644 index a528aec77..000000000 --- a/tests/FSharp.Stats.Tests/Matrix.fs +++ /dev/null @@ -1,309 +0,0 @@ -module MatrixTests - -open System -open FSharp.Stats -open Expecto - - -[] -let matrixTests = - testList "Matrix Tests" [ - - // ---------------------------------------------------------------------- - // Basic construction - // ---------------------------------------------------------------------- - testCase "ofJaggedArray creates matrix from jagged array" <| fun _ -> - let jagged = - [| [|0.0; 0.0|] - [|1.0; 3.0|] - [|2.0; 4.0|] |] - let mat = Matrix.ofJaggedArray jagged // We specifically test 'ofJaggedArray' here - Expect.equal mat.NumRows 3 "Matrix should have 3 rows" - Expect.equal mat.NumCols 2 "Matrix should have 2 columns" - Expect.equal mat.Data [|0.0; 0.0; 1.0; 3.0; 2.0; 4.0|] - "Flattened data should match row-major flattening" - - testCase "ofArray2D creates matrix from 2D array" <| fun _ -> - let arr2d = - array2D [ [ 1; 2 ] - [ 3; 4 ] - [ 5; 6 ] ] - let mat = Matrix.ofArray2D arr2d - Expect.equal mat.NumRows 3 "Matrix should have 3 rows" - Expect.equal mat.NumCols 2 "Matrix should have 2 columns" - Expect.equal mat.Data [|1; 2; 3; 4; 5; 6|] "Flattened data should match row-major order" - - testCase "init creates a matrix using a function of row,col" <| fun _ -> - let mat = Matrix.init 2 3 (fun r c -> float (r + c)) - // For r=0, c=0..2 => [0;1;2] - // For r=1, c=0..2 => [1;2;3] - // Flatten => [0;1;2; 1;2;3] - let expected = [|0.0; 1.0; 2.0; 1.0; 2.0; 3.0|] - Expect.equal mat.NumRows 2 "Rows = 2" - Expect.equal mat.NumCols 3 "Cols = 3" - Expect.equal mat.Data expected "Data should match the function r+c" - - testCase "ofJaggedArray throws on non-rectangular jagged input" <| fun _ -> - let jagged = - [| [|1.0; 2.0|] - [|3.0|] |] // 2nd row has length=1, first row has length=2 - Expect.throws (fun () -> Matrix.ofJaggedArray jagged |> ignore) - "Should throw due to inconsistent row lengths" - - // ---------------------------------------------------------------------- - // Access & Slicing - // ---------------------------------------------------------------------- - testCase "indexer get/set within bounds" <| fun _ -> - let mat = matrix [| [|1.0; 2.0|] - [|3.0; 4.0|] |] - Expect.equal mat.[0,0] 1.0 "Element (0,0) is 1.0" - mat.[1,1] <- 99.0 - Expect.equal mat.[1,1] 99.0 "Element (1,1) updated to 99.0" - - testCase "indexer throws on out-of-range access" <| fun _ -> - let mat = matrix [| [|1.0; 2.0|] - [|3.0; 4.0|] |] - Expect.throwsT (fun () -> let _ = mat.[999, 999] in ()) - "Indexer out of range should throw" - - testCase "GetSlice works with row and col start..end" <| fun _ -> - // 3x3 matrix - let mat = matrix [| - [|1.0; 2.0; 3.0|] - [|4.0; 5.0; 6.0|] - [|7.0; 8.0; 9.0|] - |] - // slice submatrix: rows [0..1], cols [1..2] - let subMat = mat.[0..1, 1..2] - // This submatrix should be: - // [ [2.0; 3.0] - // [5.0; 6.0] ] - Expect.equal subMat.NumRows 2 "2 rows" - Expect.equal subMat.NumCols 2 "2 cols" - Expect.equal subMat.Data [|2.0; 3.0; 5.0; 6.0|] "Flattened submatrix data" - - testCase "GetSlice throws on invalid slice range" <| fun _ -> - let mat = matrix [| [|1.;2.|] - [|3.;4.|] |] - Expect.throwsT (fun () -> mat.[0..99, *] |> ignore) - "Should throw due to invalid row end" - - // ---------------------------------------------------------------------- - // Arithmetic (element-wise) - // ---------------------------------------------------------------------- - testCase "add: element-wise addition of same-dimension matrices" <| fun _ -> - let m1 = matrix [| [|1.; 2.|] - [|3.; 4.|] |] - let m2 = matrix [| [|10.;20.|] - [|30.;40.|] |] - let result = Matrix.add m1 m2 - let expected = [| (1.+10.); (2.+20.); (3.+30.); (4.+40.) |] // => [11;22;33;44] - Expect.equal result.Data expected "Element-wise addition result" - - testCase "subtract: dimension mismatch throws" <| fun _ -> - let m1 = matrix [| [|1.;2.|] |] // 1x2 - let m2 = matrix [| [|1.;2.;3.|] |] // 1x3 - Expect.throwsT (fun () -> Matrix.subtract m1 m2 |> ignore) - "Subtract must throw if shapes differ" - - testCase "multiply & divide: element-wise" <| fun _ -> - let m1 = matrix [| [|2.;4.|] - [|6.;8.|] |] - let m2 = matrix [| [|1.;2.|] - [|3.;4.|] |] - - // multiply => [ [2.*1. , 4.*2.] ; [6.*3., 8.*4.] ] => [ [2.,8.]; [18.,32.] ] - let mulResult = Matrix.multiply m1 m2 - Expect.equal mulResult.Data [|2.; 8.; 18.; 32.|] "Element-wise multiply" - - // divide => [ [2./1., 4./2.]; [6./3., 8./4.] ] => [ [2.,2.]; [2.,2.] ] - let divResult = Matrix.divide m1 m2 - Expect.equal divResult.Data [|2.;2.;2.;2.|] "Element-wise divide" - - - // ---------------------------------------------------------------------- - // Standard matrix multiplication - // ---------------------------------------------------------------------- - testCase "matmul: 2x3 times 3x2 => 2x2 result" <| fun _ -> - // A=2x3, B=3x2 - let A = matrix [| [|1.0; 2.0; 3.0|] - [|4.0; 5.0; 6.0|] |] - let B = matrix [| [|7.0; 10.0|] - [|8.0; 11.0|] - [|9.0; 12.0|] |] - - // Expected: - // C[0,0] = 1*7 + 2*8 + 3*9 = 50 - // C[0,1] = 1*10+2*11+3*12 = 68 - // C[1,0] = 4*7 + 5*8 + 6*9 = 122 - // C[1,1] = 4*10+5*11+6*12 = 167 - let C = Matrix.matmul A B - Expect.equal C.NumRows 2 "Should have 2 rows" - Expect.equal C.NumCols 2 "Should have 2 cols" - Expect.equal C.Data [|50.0; 68.0; 122.0; 167.0|] "Check standard matmul result" - - - // ---------------------------------------------------------------------- - // Scalar Operations - // ---------------------------------------------------------------------- - testCase "addScalar, subtractScalar, multiplyScalar, divideScalar" <| fun _ -> - let m = matrix [| [|1.;2.|] - [|3.;4.|] |] - let addRes = Matrix.addScalar m 10.0 - Expect.equal addRes.Data [|11.;12.;13.;14.|] "Add 10.0 to all" - - let subRes = Matrix.subtractScalar m 1.0 - Expect.equal subRes.Data [|0.;1.;2.;3.|] "Subtract 1.0 from all" - - let mulRes = Matrix.multiplyScalar m 2.0 - Expect.equal mulRes.Data [|2.;4.;6.;8.|] "Multiply all by 2.0" - - let divRes = Matrix.divideScalar m 2.0 - Expect.equal divRes.Data [|0.5;1.;1.5;2.|] "Divide all by 2.0" - - // ---------------------------------------------------------------------- - // Matrix-Vector Multiply - // ---------------------------------------------------------------------- - testCase "m * v => standard matrix-vector product" <| fun _ -> - // 2x3 times vector of length 3 => vector of length 2 - // mat = [ [1.,2.,3.] - // [4.,5.,6.] ] - let mat = matrix [| [|1.;2.;3.|] - [|4.;5.;6.|] |] - let v = [| 10.; 20.; 30. |] - // result = [ - // row0 dot v => (1.*10. + 2.*20. + 3.*30.) = 140. - // row1 dot v => (4.*10. + 5.*20. + 6.*30.) = 320. - // ] - let result = mat * v - Expect.equal result [|140.; 320.|] "Matrix-vector product" - - testCase "v * m => row-vector times matrix => vector" <| fun _ -> - // 1x2 row vector times a 2x2 matrix => 1x2 vector - let v = [|2.; 3.|] // length=2 - let mat = matrix [| [|10.; 100.|] - [|20.; 200.|] |] - // v*m => [ (2.*10. + 3.*20.), (2.*100. + 3.*200.) ] - // => [ 2.*10. + 3.*20. , 2.*100. + 3.*200. ] - // => [ 20.+60., 200.+600. ] => [80., 800.] - let result = v * mat - Expect.equal result [|80.; 800.|] "Row-vector times matrix" - - testCase "m * v => dimension mismatch throws" <| fun _ -> - let mat = matrix [| [|1.;2.|] - [|3.;4.|] |] // 2x2 - let v = [|1.;2.;3.|] // length=3 - Expect.throwsT (fun () -> let _ = mat * v in ()) - "Matrix(2x2)*Vector(3) => dimension mismatch should throw" - - // ---------------------------------------------------------------------- - // Transpose - // ---------------------------------------------------------------------- - testCase "Transpose: changes shape and flips row<->col" <| fun _ -> - let mat = matrix [| [|1.;2.;3.|] - [|4.;5.;6.|] |] // 2x3 - let t = mat.Transpose() - Expect.equal t.NumRows 3 "Should have 3 rows" - Expect.equal t.NumCols 2 "Should have 2 cols" - Expect.equal t.Data [|1.;4.;2.;5.;3.;6.|] "Flattened transpose" - - // ---------------------------------------------------------------------- - // Identity, Diagonal, and Zero/Ones - // ---------------------------------------------------------------------- - testCase "identity n => NxN identity matrix" <| fun _ -> - let eye = Matrix.identity 3 - // => [1,0,0; 0,1,0; 0,0,1] - let expected = [|1.;0.;0.; 0.;1.;0.; 0.;0.;1.|] - Expect.equal eye.Data expected "3x3 identity" - - testCase "diagonal => builds NxN from diag vector" <| fun _ -> - let diagVec = [|10.; 20.; 30.|] - let mat = Matrix.diagonal diagVec - // => [ [10, 0, 0], - // [ 0,20, 0], - // [ 0, 0,30] ] - Expect.equal mat.NumRows 3 "3x3" - Expect.equal mat.NumCols 3 "3x3" - let expected = [|10.;0.;0.; 0.;20.;0.; 0.;0.;30.|] - Expect.equal mat.Data expected "Diagonal in main diagonal positions" - - testCase "ones => NxM matrix of all 1's" <| fun _ -> - let mat = Matrix.ones 2 3 - Expect.equal mat.Data [|1.;1.;1.;1.;1.;1.|] "2x3 of all 1." - - testCase "zeroCreate => NxM matrix of all 0's" <| fun _ -> - let mat = Matrix.zeroCreate 2 3 - Expect.equal mat.Data [|0.;0.;0.;0.;0.;0.|] "2x3 of all zero." - - // ---------------------------------------------------------------------- - // getRow / getCol - // ---------------------------------------------------------------------- - testCase "getRow gets row i as a vector" <| fun _ -> - let mat = matrix [| [|1.;2.|] - [|3.;4.|] |] - let row0 = Matrix.getRow 0 mat - let row1 = Matrix.getRow 1 mat - Expect.equal row0 [|1.;2.|] "Row 0" - Expect.equal row1 [|3.;4.|] "Row 1" - - testCase "getCol gets column j as a vector" <| fun _ -> - let mat = matrix [| [|1.;2.;3.|] - [|4.;5.;6.|] |] - let col0 = Matrix.getCol 0 mat - let col2 = Matrix.getCol 2 mat - Expect.equal col0 [|1.;4.|] "Column 0" - Expect.equal col2 [|3.;6.|] "Column 2" - - // ---------------------------------------------------------------------- - // Equality (IEquatable) - // ---------------------------------------------------------------------- - testCase "Equals returns true for same shape+elements" <| fun _ -> - let m1 = matrix [| [|1.;2.|] - [|3.;4.|] |] - // 'Matrix.create' constructs from a flattened array - let m2 = Matrix.create 2 2 [|1.;2.;3.;4.|] - Expect.isTrue (m1.Equals m2) "Matrices should be equal" - - testCase "Equals returns false for dimension mismatch" <| fun _ -> - let m1 = matrix [| [|1.;2.|] |] // 1x2 - let m2 = matrix [| [|1.;2.;3.|] |] // 1x3 - Expect.isFalse (m1.Equals m2) "Should be different shapes => not equal" - - testCase "Equals returns false for data difference" <| fun _ -> - let m1 = matrix [| [|1.;2.|] |] - let m2 = matrix [| [|1.;9.|] |] - Expect.isFalse (m1.Equals m2) "Same shape, different data => not equal" - - // ---------------------------------------------------------------------- - // Misc: toArray2D, toJaggedArray - // ---------------------------------------------------------------------- - testCase "toArray2D transforms a matrix into 2D array" <| fun _ -> - let mat = matrix [| [|1.;2.|] - [|3.;4.|] - [|5.;6.|] |] - let arr2d = mat.toArray2D() - Expect.equal (arr2d.GetLength(0)) 3 "3 rows in arr2d" - Expect.equal (arr2d.GetLength(1)) 2 "2 cols in arr2d" - Expect.equal arr2d.[2,1] 6.0 "Check element" - - testCase "toJaggedArray transforms a matrix into jagged array" <| fun _ -> - let mat = matrix [| [|7.;8.|] - [|9.;10.|] |] - let jagged = mat.toJaggedArray() - Expect.equal jagged.Length 2 "2 rows in jagged" - Expect.equal jagged.[1] [|9.;10.|] "Second row matches" - - // ---------------------------------------------------------------------- - // Slicing & Setting Row - // ---------------------------------------------------------------------- - testCase "SetRow updates row i" <| fun _ -> - let mat = matrix [| [|1.;2.|] - [|3.;4.|] |] - mat.SetRow(0, [|10.;20.|]) - Expect.equal mat.Data [|10.;20.;3.;4.|] "Row 0 replaced" - - // (Optional) More tests can be added for addRowVector, addColVector, etc. - ] - - - diff --git a/tests/FSharp.Stats.Tests/Optimization.fs b/tests/FSharp.Stats.Tests/Optimization.fs index f91b77906..a4205bccb 100644 --- a/tests/FSharp.Stats.Tests/Optimization.fs +++ b/tests/FSharp.Stats.Tests/Optimization.fs @@ -3,6 +3,7 @@ open Expecto open System +open FsMath open FSharp.Stats open FSharp.Stats.Optimization diff --git a/tests/FSharp.Stats.Tests/RowVector.fs b/tests/FSharp.Stats.Tests/RowVector.fs deleted file mode 100644 index 82a436a81..000000000 --- a/tests/FSharp.Stats.Tests/RowVector.fs +++ /dev/null @@ -1,28 +0,0 @@ -module RowVectorTests -open Expecto - -open FSharp.Stats -open FSharp.Stats.RowVector - -let private testRowVectorA = - let values = [|5.;12.;18.;-23.;45.|] - RowVector(Some (Instances.FloatNumerics :> INumeric),values) - -let private testArrayA = - [|5.;12.;18.;-23.;45.|] - -[] -let floatImplementationTests = - let testRowVectorASquare = rowvec [25.0; 144.0; 324.0; 529.0; 2025.] - - testList "RowVector" [ - testCase "map" <| fun () -> - let actual = testRowVectorA |> RowVector.map (fun x -> x**2.) - Expect.equal actual testRowVectorASquare "RowVectors should be equal" - - testCase "init" <| fun () -> - let actual = RowVector.init testArrayA.Length (fun i -> testArrayA.[i]) - Expect.equal actual testRowVectorA "RowVectors should be equal" - ] - - diff --git a/tests/FSharp.Stats.Tests/SVD.fs b/tests/FSharp.Stats.Tests/SVD.fs deleted file mode 100644 index c2b886af2..000000000 --- a/tests/FSharp.Stats.Tests/SVD.fs +++ /dev/null @@ -1,205 +0,0 @@ -module SVDTests - -open Expecto -open System -open FSharp.Stats -open FSharp.Stats.Algebra - -module MatrixUtils = - - let inline isApproxZero<'T when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T : comparison - and 'T :> ValueType> - (epsilon: 'T) (x: 'T) = - (GenericMath.abs x) < epsilon - - let inline isUpperBidiagonalWithTolerance<'T when 'T :> Numerics.INumber<'T> - and 'T : (new: unit -> 'T) - and 'T : struct - and 'T : comparison - and 'T :> ValueType> - (epsilon: 'T) - (A: Matrix<'T>) : bool = - let m = A.NumCols - let n = A.NumRows - - let mutable ok = true - for i = 0 to m - 1 do - for j = 0 to n - 1 do - let onDiagonal = j = i - let onSuperDiagonal = j = i + 1 - let aij = A.[i, j] - if not (onDiagonal || onSuperDiagonal) && not (isApproxZero epsilon aij) then - ok <- false - ok - - -[] -let householderCreateTest = - test "Householder.create" { - let x = [| 4.0; 3.0; 0.0 |] - let h = Householder.create x - - let v = h.V - let tau = h.Tau - let n = v.Length - - // Compute Hx = (I - τ v vᵗ) x - // First: dot(v, x) - let dot = Vector.dot v x - - // Then: Hx = x - τ * dot * v - let hx = Array.init n (fun i -> x.[i] - tau * dot * v.[i]) - - // We expect: hx = [±||x||; 0; 0] - let norm = sqrt (Array.sumBy (fun xi -> xi * xi) x) - Expect.floatClose Accuracy.high hx.[0] norm "Should be equal (double precision)" - Expect.floatClose Accuracy.high hx.[1] 0.0 "Should be equal (double precision)" - Expect.floatClose Accuracy.high hx.[2] 0.0 "Should be equal (double precision)" - } - //test " zeroes out tail of vector" { - // Expect.floatClose Accuracy.high hx.[0] norm "Should be equal (double precision)" - //} - //test " zeroes out tail of vector" { - // Expect.floatClose Accuracy.high hx.[1] 0.0 "Should be equal (double precision)" - //} - //test " zeroes out tail of vector" { - // Expect.floatClose Accuracy.high hx.[2] 0.0 "Should be equal (double precision)" - //} - //] - -[] -let applyLeftTest = - test "Householder.applyLeft zeroes out subdiagonal column elements" { - // Define 3x3 test matrix - let A = - matrix [| - [| 4.0; 2.0; 1.0 |] - [| 3.0; 0.0; 0.0 |] - [| 0.0; 0.0; 0.0 |] - |] - - // Create Householder vector from column 0 (x = [4; 3; 0]) - let x = [| A.[0, 0]; A.[1, 0]; A.[2, 0] |] - let h = Householder.create x - - // Apply reflector from the left to matrix A starting at row 0 - Householder.applyLeft(h, A, 0) - - // Check: entries below A[0][0] should be zero - //let eps = 1e-10 - Expect.floatClose Accuracy.high A.[1, 0] 0.0 "Should be equal (double precision)" - Expect.floatClose Accuracy.high A.[2, 0] 0.0 "Should be equal (double precision)" - - // Optionally check the first value matches h.Beta - Expect.floatClose Accuracy.high A.[0, 0] h.Beta "Should be equal (double precision)" - } - -let applyRightTest = - test "Householder.applyRight zeroes out row tail elements" { - // Define 3x3 test matrix - let A = - matrix [| - [| 1.0; 4.0; 3.0 |] - [| 0.0; 0.0; 0.0 |] - [| 0.0; 0.0; 0.0 |] - |] - - // Take the row vector to the right of the diagonal: [4.0; 3.0] - let x = [| A.[0, 1]; A.[0, 2] |] - let h = Householder.create x - - // Apply the Householder from the right starting at column 1 - Householder.applyRight(h, A, 1) - - // Check that A[0].[2] is now approximately 0 - //let eps = 1e-10 - Expect.floatClose Accuracy.high A.[0, 2] 0.0 "Should be equal (double precision)" - - // Check that A[0].[1] is updated to h.Beta - Expect.floatClose Accuracy.high A.[0, 1] h.Beta "Should be equal (double precision)" - } - - -[] -let bidiagonalizationTest = - testList "bidiagonalization" [ - test "First step of bidiagonalization (applyLeft to column 0) works" { - // Full-rank 3x3 matrix - let A = - matrix [| - [| 4.0; 1.0; 2.0 |] - [| 3.0; 1.0; 0.0 |] - [| 5.0; 1.0; 3.0 |] - |] - - // Extract column 0 - let colVector = [| A.[0, 0]; A.[1, 0]; A.[2, 0] |] - let h = Householder.create colVector - - Householder.applyLeft(h, A, 0) - - // Overwrite A[0..,0] with [β; 0; 0] - A.[0, 0] <- h.Beta - for i = 1 to 2 do - A.[i, 0] <- 0.0 - - // Check column 0 - Expect.floatClose Accuracy.high A.[1, 0] 0.0 "Should be equal (double precision)" - Expect.floatClose Accuracy.high A.[2, 0] 0.0 "Should be equal (double precision)" - Expect.floatClose Accuracy.high A.[0, 0] h.Beta "Should be equal (double precision)" - } - - - - test "bidiagonalizeInPlace produces upper bidiagonal matrix" { - let input = - matrix [| - [| 1.0; 2.0; 3.0 |] - [| 4.0; 5.0; 6.0 |] - [| 7.0; 8.0; 9.0 |] - |] - - let A = input |> Matrix.copy - - Bidiagonalization.bidiagonalizeInPlace A - - let isBidiagonal = MatrixUtils.isUpperBidiagonalWithTolerance 1e-10 A - - Expect.isTrue isBidiagonal "Matrix should be upper bidiagonal after bidiagonalization" - } - ] - - -//[] -//let golubKahanTests = -// testList "Golub-Kahan Diagonalization" [ - -// test "Diagonalize 2x2 upper bidiagonal matrix" { -// // Construct bidiagonal: [ [4, 2]; [0, 3] ] -// let d = [| 4.0; 3.0 |] -// let e = [| 2.0 |] - -// let bidiag = { -// D = d -// E = e -// } - -// let sigma = GolubKahan.diagonalize bidiag - -// // Expected from NumPy SVD -// let expected = [| 4.74341649; 2.5355339 |] -// let eps = 1e-6 - -// // Compare sorted values (SVD is unordered) -// let actualSorted = Array.sortDescending sigma -// let expectedSorted = Array.sortDescending expected - -// for i in 0 .. expected.Length - 1 do -// Expect.floatClose Accuracy.high actualSorted.[i] expectedSorted.[i] $"Singular value {i} mismatch" -// } - -// // You can add more tests here for larger bidiagonal matrices or edge cases -// ] \ No newline at end of file diff --git a/tests/FSharp.Stats.Tests/TestExtensions.fs b/tests/FSharp.Stats.Tests/TestExtensions.fs index 4d917f9e6..ac7cd49d8 100644 --- a/tests/FSharp.Stats.Tests/TestExtensions.fs +++ b/tests/FSharp.Stats.Tests/TestExtensions.fs @@ -1,6 +1,7 @@ module TestExtensions open Expecto + open FsMath open FSharp.Stats open FSharp.Stats.Testing open System diff --git a/tests/FSharp.Stats.Tests/Testing.fs b/tests/FSharp.Stats.Tests/Testing.fs index 18ab34a44..e0593d73e 100644 --- a/tests/FSharp.Stats.Tests/Testing.fs +++ b/tests/FSharp.Stats.Tests/Testing.fs @@ -1,8 +1,11 @@ module TestingTests open Expecto open System -open FSharp.Stats.Testing + +open FsMath open FSharp.Stats +open FSharp.Stats.Testing + open TestExtensions open FSharp.Stats.Testing.SAM open Deedle diff --git a/tests/FSharp.Stats.Tests/Vector.fs b/tests/FSharp.Stats.Tests/Vector.fs deleted file mode 100644 index 5d6e313be..000000000 --- a/tests/FSharp.Stats.Tests/Vector.fs +++ /dev/null @@ -1,605 +0,0 @@ -module VectorTests - -open System -open Expecto -open FSharp.Stats - -[] -let vectorTests = - testList "Vector Tests" [ - - // ====================================================================== - // INT TESTS - // ====================================================================== - testList "Integer Vector Tests" [ - - // ------------------------------------------------------------------ - // Add - // ------------------------------------------------------------------ - testCase "add: integer vectors of same length" <| fun _ -> - let v1 = [| 1; 2; 3 |] - let v2 = [| 4; 5; 6 |] - let result = Vector.add v1 v2 - let expected = [| 5; 7; 9 |] - Expect.equal result expected "Should add each element pairwise" - - testCase "add: throws on dimension mismatch" <| fun _ -> - let v1 = [| 1; 2 |] - let v2 = [| 1; 2; 3 |] - Expect.throwsT (fun () -> Vector.add v1 v2 |> ignore) - "Should throw ArgumentException when vectors differ in length" - - // ------------------------------------------------------------------ - // Subtract - // ------------------------------------------------------------------ - testCase "subtract: integer vectors of same length" <| fun _ -> - let v1 = [| 5; 5; 5 |] - let v2 = [| 1; 2; 3 |] - let result = Vector.subtract v1 v2 - let expected = [| 4; 3; 2 |] - Expect.equal result expected "Should subtract each element pairwise" - - testCase "subtract: throws on dimension mismatch" <| fun _ -> - let v1 = [| 1; 2; 3 |] - let v2 = [| 1; 2 |] - Expect.throwsT (fun () -> Vector.subtract v1 v2 |> ignore) - "Should throw ArgumentException when vectors differ in length" - - // ------------------------------------------------------------------ - // Multiply - // ------------------------------------------------------------------ - testCase "multiply: integer vectors of same length" <| fun _ -> - let v1 = [| 2; 2; 2 |] - let v2 = [| 3; 4; 5 |] - let result = Vector.multiply v1 v2 - let expected = [| 6; 8; 10 |] - Expect.equal result expected "Should multiply each element pairwise" - - testCase "multiply: throws on dimension mismatch" <| fun _ -> - let v1 = [| 2; 2 |] - let v2 = [| 3; 4; 5 |] - Expect.throwsT (fun () -> Vector.multiply v1 v2 |> ignore) - "Should throw ArgumentException when vectors differ in length" - - // ------------------------------------------------------------------ - // Divide - // ------------------------------------------------------------------ - testCase "divide: integer vectors of same length" <| fun _ -> - let v1 = [| 10; 20; 30 |] - let v2 = [| 2; 5; 5 |] - let result = Vector.divide v1 v2 - let expected = [| 5; 4; 6 |] - Expect.equal result expected "Should divide each element pairwise" - - testCase "divide: throws on dimension mismatch" <| fun _ -> - let v1 = [| 10; 20 |] - let v2 = [| 2; 5; 5 |] - Expect.throwsT (fun () -> Vector.divide v1 v2 |> ignore) - "Should throw ArgumentException when vectors differ in length" - - // ------------------------------------------------------------------ - // Scalar Operations - // ------------------------------------------------------------------ - testCase "addScalar: adds scalar to every element" <| fun _ -> - let v = [| 1; 2; 3 |] - let scalar = 5 - let result = Vector.addScalar scalar v - let expected = [| 6; 7; 8 |] - Expect.equal result expected "Should add the scalar to each element" - - testCase "subtractScalar: subtracts scalar from every element" <| fun _ -> - let v = [| 1; 2; 3 |] - let scalar = 1 - let result = Vector.subtractScalar scalar v - let expected = [| 0; 1; 2 |] - Expect.equal result expected "Should subtract the scalar from each element" - - testCase "multiplyScalar: multiplies scalar to every element" <| fun _ -> - let v = [| 2; 4; 6 |] - let scalar = 3 - let result = Vector.multiplyScalar scalar v - let expected = [| 6; 12; 18 |] - Expect.equal result expected "Should multiply the scalar with each element" - - testCase "divideScalar: divides every element by scalar" <| fun _ -> - let v = [| 10; 20; 30 |] - let scalar = 10 - let result = Vector.divideScalar scalar v - let expected = [| 1; 2; 3 |] - Expect.equal result expected "Should divide each element by the scalar" - - // ------------------------------------------------------------------ - // sum - // ------------------------------------------------------------------ - testCase "sum: sums all elements of an integer vector" <| fun _ -> - let v = [| 1; 2; 3; 4 |] - let result = Vector.sum v - Expect.equal result 10 "Should be the sum of all elements" - - testCase "sum: sums an empty integer vector (should be 0)" <| fun _ -> - let v : int[] = [||] - let result = Vector.sum v - Expect.equal result 0 "Sum of empty array should be 0" - - // ------------------------------------------------------------------ - // product - // ------------------------------------------------------------------ - testCase "product: multiplies all elements of an integer vector" <| fun _ -> - let v = [| 1; 2; 3; 4 |] - let result = Vector.product v - Expect.equal result 24 "Should be the product of all elements" - - testCase "product: empty integer vector (should be 1 for identity)" <| fun _ -> - let v : int[] = [||] - let result = Vector.product v - Expect.equal result 1 "Product of empty array should be 1" - - - // ------------------------------------------------------------------ - // dot - // ------------------------------------------------------------------ - testCase "dot: computes dot product of two integer vectors" <| fun _ -> - let v1 = [| 1; 2; 3 |] - let v2 = [| 4; 5; 6 |] - let result = Vector.dot v1 v2 - // Dot = 1*4 + 2*5 + 3*6 = 4 + 10 + 18 = 32 - Expect.equal result 32 "Dot product should match expected" - - testCase "dot: throws on dimension mismatch" <| fun _ -> - let v1 = [| 1; 2 |] - let v2 = [| 3; 4; 5 |] - Expect.throwsT (fun () -> Vector.dot v1 v2 |> ignore) - "Should throw ArgumentException when vectors differ in length" - - - // ------------------------------------------------------------------ - // min - // ------------------------------------------------------------------ - testCase "min: finds minimum in a non-empty integer vector" <| fun _ -> - let v = [| 10; 2; 30; 4 |] - let result = Vector.min v - Expect.equal result 2 "Should find the smallest integer in the array" - - testCase "min: throws on empty integer vector" <| fun _ -> - let v : int[] = [||] - Expect.throwsT (fun () -> Vector.min v |> ignore) - "Should throw ArgumentException for empty vector" - - // ------------------------------------------------------------------ - // max - // ------------------------------------------------------------------ - testCase "max: finds maximum in a non-empty integer vector" <| fun _ -> - let v = [| 10; 2; 30; 4 |] - let result = Vector.max v - Expect.equal result 30 "Should find the largest integer in the array" - - testCase "max: throws on empty integer vector" <| fun _ -> - let v : int[] = [||] - Expect.throwsT (fun () -> Vector.max v |> ignore) - "Should throw ArgumentException for empty vector" - - // ------------------------------------------------------------------ - // OPERATOR TESTS (Int) - // ------------------------------------------------------------------ - testCase "vector-vector operators (int): .+ .- .* ./" <| fun _ -> - let v1 = [| 1; 2; 3 |] - let v2 = [| 4; 5; 6 |] - - // .+ - let addResult = v1 .+ v2 - Expect.equal addResult [|5; 7; 9|] "v1 .+ v2 should match element-wise add" - - // .- - let subResult = v1 .- v2 - Expect.equal subResult [|-3; -3; -3|] "v1 .- v2 should match element-wise subtract" - - // .* - let mulResult = v1 .* v2 - Expect.equal mulResult [|4; 10; 18|] "v1 .* v2 should match element-wise multiply" - - // ./ - let divResult = [| 10; 20; 30 |] ./ [| 2; 5; 5 |] - Expect.equal divResult [|5; 4; 6|] "Should match element-wise division" - - testCase "vector-scalar operators (int): .+ .- .* ./" <| fun _ -> - let v = [| 2; 4; 6 |] - - // v .+ scalar - let addScalarResult = v .+ 2 - Expect.equal addScalarResult [|4; 6; 8|] "v .+ 2 should add 2 to all elements" - - // v .- scalar - let subScalarResult = v .- 2 - Expect.equal subScalarResult [|0; 2; 4|] "v .- 2 should subtract 2 from all elements" - - // v .* scalar - let mulScalarResult = v .* 3 - Expect.equal mulScalarResult [|6; 12; 18|] "v .* 3 should multiply all elements by 3" - - // v ./ scalar - let divScalarResult = [| 10; 20; 30 |] ./ 10 - Expect.equal divScalarResult [|1; 2; 3|] "Should divide all elements by 10" - ] - - - // ====================================================================== - // FLOAT TESTS - // ====================================================================== - testList "Float Vector Tests" [ - - // ------------------------------------------------------------------ - // Add - // ------------------------------------------------------------------ - testCase "add: float vectors of same length" <| fun _ -> - let v1 = [| 1.0; 2.0; 3.0 |] - let v2 = [| 4.0; 5.0; 6.0 |] - let result = Vector.add v1 v2 - let expected = [| 5.0; 7.0; 9.0 |] - Expect.equal result expected "Should add each element pairwise" - - testCase "add: throws on dimension mismatch" <| fun _ -> - let v1 = [| 1.0; 2.0 |] - let v2 = [| 1.0; 2.0; 3.0 |] - Expect.throwsT (fun () -> Vector.add v1 v2 |> ignore) - "Should throw ArgumentException when vectors differ in length" - - // ------------------------------------------------------------------ - // Subtract - // ------------------------------------------------------------------ - testCase "subtract: float vectors of same length" <| fun _ -> - let v1 = [| 5.5; 5.0; 5.75 |] - let v2 = [| 1.5; 2.0; 3.25 |] - let result = Vector.subtract v1 v2 - let expected = [| 4.0; 3.0; 2.5 |] - Expect.equal result expected "Should subtract each element pairwise" - - // ------------------------------------------------------------------ - // Multiply - // ------------------------------------------------------------------ - testCase "multiply: float vectors of same length" <| fun _ -> - let v1 = [| 2.0; 2.5; 3.0 |] - let v2 = [| 3.0; 4.0; 5.0 |] - let result = Vector.multiply v1 v2 - let expected = [| 6.0; 10.0; 15.0 |] - Expect.equal result expected "Should multiply each element pairwise" - - // ------------------------------------------------------------------ - // Divide - // ------------------------------------------------------------------ - testCase "divide: float vectors of same length" <| fun _ -> - let v1 = [| 10.0; 20.0; 30.0 |] - let v2 = [| 2.0; 5.0; 5.0 |] - let result = Vector.divide v1 v2 - let expected = [| 5.0; 4.0; 6.0 |] - Expect.equal result expected "Should divide each element pairwise" - - // ------------------------------------------------------------------ - // Scalar Operations - // ------------------------------------------------------------------ - testCase "addScalar: adds scalar to every float element" <| fun _ -> - let v = [| 1.0; 2.0; 3.0 |] - let scalar = 5.5 - let result = Vector.addScalar scalar v - let expected = [| 6.5; 7.5; 8.5 |] - Expect.equal result expected "Should add 5.5 to each element" - - testCase "subtractScalar: subtract scalar from every float element" <| fun _ -> - let v = [| 1.0; 2.5; 3.75 |] - let scalar = 1.25 - let result = Vector.subtractScalar scalar v - let expected = [| -0.25; 1.25; 2.5 |] - Expect.equal result expected "Should subtract 1.25 from each element" - - testCase "multiplyScalar: multiplies scalar with every float element" <| fun _ -> - let v = [| 2.5; 4.0; 6.0 |] - let scalar = 2.0 - let result = Vector.multiplyScalar scalar v - let expected = [| 5.0; 8.0; 12.0 |] - Expect.equal result expected "Should multiply each element by 2.0" - - testCase "divideScalar: divides every float element by scalar" <| fun _ -> - let v = [| 10.0; 20.0; 30.0 |] - let scalar = 2.0 - let result = Vector.divideScalar scalar v - let expected = [| 5.0; 10.0; 15.0 |] - Expect.equal result expected "Should divide each element by 2.0" - - // ------------------------------------------------------------------ - // sum - // ------------------------------------------------------------------ - testCase "sum: sums all elements of a float vector" <| fun _ -> - let v = [| 1.1; 2.2; 3.3; 4.4 |] - let result = Vector.sum v - // Expect exact or near: 1.1 + 2.2 + 3.3 + 4.4 = 11.0 - Expect.floatClose Accuracy.veryHigh 11.0 result "Sum of [1.1;2.2;3.3;4.4] = 11.0" - - testCase "sum: sums empty float vector (should be 0.0)" <| fun _ -> - let v : float[] = [||] - let result = Vector.sum v - Expect.equal result 0.0 "Sum of empty array should be 0.0" - - // ------------------------------------------------------------------ - // product - // ------------------------------------------------------------------ - testCase "product: multiplies all elements of a float vector" <| fun _ -> - let v = [| 1.0; 2.0; 3.0 |] - let result = Vector.product v - Expect.equal result 6.0 "1.0 * 2.0 * 3.0 = 6.0" - - testCase "product: empty float vector" <| fun _ -> - // By definition in your code, fold starts with 1. - let v : float[] = [||] - let result = Vector.product v - Expect.equal result 1.0 "Product of empty array should be 1.0" - - // ------------------------------------------------------------------ - // mean - // ------------------------------------------------------------------ - testCase "mean: computes mean of a float vector" <| fun _ -> - let v = [| 2.0; 4.0; 6.0; 8.0 |] - let result = Vector.mean v - // (2.0 + 4.0 + 6.0 + 8.0) / 4 = 5.0 - Expect.floatClose Accuracy.veryHigh 5.0 result "Mean should be 5.0" - - testCase "mean: throws on empty float vector" <| fun _ -> - let v : float[] = [||] - Expect.throwsT (fun () -> Vector.mean v |> ignore) - "Should throw ArgumentException when float vector is empty" - - // ------------------------------------------------------------------ - // dot - // ------------------------------------------------------------------ - testCase "dot: computes dot product of two float vectors" <| fun _ -> - let v1 = [| 1.0; 2.0; 3.0 |] - let v2 = [| 4.0; 5.0; 6.0 |] - let result = Vector.dot v1 v2 - // Dot = 1*4 + 2*5 + 3*6 = 4 + 10 + 18 = 32 - Expect.floatClose Accuracy.veryHigh 32.0 result "Dot product should be 32.0" - - // ------------------------------------------------------------------ - // norm - // ------------------------------------------------------------------ - testCase "norm: computes Euclidean norm of a 3-4-5 triangle (float)" <| fun _ -> - let v = [| 3.0; 4.0 |] - let result = Vector.norm v - Expect.floatClose Accuracy.veryHigh 5.0 result "Norm of [3.0;4.0] should be 5.0" - - // ------------------------------------------------------------------ - // min - // ------------------------------------------------------------------ - testCase "min: finds minimum in a non-empty float vector" <| fun _ -> - let v = [| 10.0; 2.0; 30.5; 4.1 |] - let result = Vector.min v - Expect.equal result 2.0 "Should find the smallest float in the array" - - testCase "min: throws on empty float vector" <| fun _ -> - let v : float[] = [||] - Expect.throwsT (fun () -> Vector.min v |> ignore) - "Should throw ArgumentException for empty vector" - - // ------------------------------------------------------------------ - // max - // ------------------------------------------------------------------ - testCase "max: finds maximum in a non-empty float vector" <| fun _ -> - let v = [| 10.0; 2.0; 30.5; 4.1 |] - let result = Vector.max v - Expect.equal result 30.5 "Should find the largest float in the array" - - testCase "max: throws on empty float vector" <| fun _ -> - let v : float[] = [||] - Expect.throwsT (fun () -> Vector.max v |> ignore) - "Should throw ArgumentException for empty vector" - - // ------------------------------------------------------------------ - // OPERATOR TESTS (Float) - // ------------------------------------------------------------------ - testCase "vector-vector operators (float): .+ .- .* ./" <| fun _ -> - let v1 = [| 1.0; 2.0; 3.0 |] - let v2 = [| 4.0; 5.0; 6.0 |] - - // .+ - let addResult = v1 .+ v2 - Expect.equal addResult [|5.0; 7.0; 9.0|] "v1 .+ v2 should match element-wise add" - - // .- - let subResult = v1 .- v2 - Expect.equal subResult [|-3.0; -3.0; -3.0|] "v1 .- v2 should match element-wise subtract" - - // .* - let mulResult = v1 .* v2 - Expect.equal mulResult [|4.0; 10.0; 18.0|] "v1 .* v2 should match element-wise multiply" - - // ./ - let divResult = [| 10.0; 20.0; 30.0 |] ./ [| 2.0; 5.0; 5.0 |] - Expect.equal divResult [|5.0; 4.0; 6.0|] "Should match element-wise division" - - testCase "vector-scalar operators (float): .+ .- .* ./" <| fun _ -> - let v = [| 2.5; 4.0; 6.0 |] - - // v .+ scalar - let addScalarResult = v .+ 2.0 - Expect.equal addScalarResult [|4.5; 6.0; 8.0|] "v .+ 2.0 should add 2.0 to all elements" - - // v .- scalar - let subScalarResult = v .- 0.5 - Expect.equal subScalarResult [|2.0; 3.5; 5.5|] "v .- 0.5 should subtract 0.5 from all elements" - - // v .* scalar - let mulScalarResult = v .* 1.5 - Expect.equal mulScalarResult [|3.75; 6.0; 9.0|] "v .* 1.5 should multiply all elements by 1.5" - - // v ./ scalar - let divScalarResult = [| 10.0; 20.0; 30.0 |] ./ 10.0 - Expect.equal divScalarResult [|1.0; 2.0; 3.0|] "Should divide all elements by 10.0" - - // ------------------------------------------------------------------ - // cross (outer) product - // ------------------------------------------------------------------ - testCase "cross: computes the outer product of two float vectors" <| fun _ -> - // 'Vector.cross' is assumed to produce a 2D array (matrix) - let colvec = [| 1.0; 2.0; 3.0 |] - let rowvec = [| 4.0; 5.0; 6.0 |] - - // The expected 3x3 matrix is computed by: - // [ [1.0*4.0, 1.0*5.0, 1.0*6.0] - // [2.0*4.0, 2.0*5.0, 2.0*6.0] - // [3.0*4.0, 3.0*5.0, 3.0*6.0] ] - let result = Vector.cross colvec rowvec - let expected = - [| [|4.0; 5.0; 6.0|] - [|8.0; 10.0; 12.0|] - [|12.0;15.0; 18.0|] |] |> matrix - - Expect.equal result expected "Expected outer product of colvec and rowvec" - ] - // ====================================================================== - // Vector manipulation tests - // ====================================================================== - testList "Vector manipulation Tests" [ - - test "foldi applies a function with index to a vector" { - let v = [|1; 2; 3|] - let result = Vector.foldi (fun i acc x -> acc + i * x) 0 v - Expect.equal result 8 "Expected indexed fold result" - } - - test "mapi applies a function with index to each element" { - let v = [|1; 2; 3|] - let result = Vector.mapi (fun i x -> x + i) v - Expect.equal result [|1; 3; 5|] "Expected indexed map result" - } - - test "filter filters elements by predicate" { - let v = [|1; 2; 3; 4|] - let result = Vector.filter (fun x -> x % 2 = 0) v - Expect.equal result [|2; 4|] "Expected filtered vector" - } - - test "init creates a vector using a generator function" { - let result = Vector.init 5 (fun i -> i * 2) - Expect.equal result [|0; 2; 4; 6; 8|] "Expected initialized vector" - } - - test "slice extracts a slice from a vector" { - let v = [|1; 2; 3; 4; 5|] - let result = Vector.slice 1 3 v - Expect.equal result [|2; 3; 4|] "Expected sliced vector" - } - - test "argmax finds the index of the maximum value" { - let v = [|1; 3; 2|] - let result = Vector.argmax v - Expect.equal result 1 "Expected index of maximum value" - } - - test "argmin finds the index of the minimum value" { - let v = [|3; 1; 2|] - let result = Vector.argmin v - Expect.equal result 1 "Expected index of minimum value" - } - - test "padRight pads a vector to a given length" { - let v = [|1; 2|] - let result = Vector.padRight 5 0 v - Expect.equal result [|1; 2; 0; 0; 0|] "Expected padded vector" - } - - test "zip combines two vectors with indices" { - let v1 = [|1; 2; 3|] - let v2 = [|4; 5; 6|] - let result = Vector.zip v1 v2 - Expect.equal result [|(0, 1, 4); (1, 2, 5); (2, 3, 6)|] "Expected zipped vector" - } - - test "argminBy finds the index of the minimum value using a projection" { - let v = [|1; 2; 3|] - let result = Vector.argminBy (fun x -> -x) v - Expect.equal result 2 "Expected index of minimum value by projection" - } - - test "argmaxBy finds the index of the maximum value using a projection" { - let v = [|1; 2; 3|] - let result = Vector.argmaxBy (fun x -> -x) v - Expect.equal result 0 "Expected index of maximum value by projection" - } - - test "tryFindIndex finds the index of the first matching element" { - let v = [|1; 2; 3|] - let result = Vector.tryFindIndex (fun x -> x = 2) v - Expect.equal result (Some 1) "Expected index of first matching element" - } - - test "findIndex finds the index of the first matching element or throws" { - let v = [|1; 2; 3|] - let result = Vector.findIndex (fun x -> x = 2) v - Expect.equal result 1 "Expected index of first matching element" - } - - test "enumerateNonZero enumerates non-zero elements with indices" { - let v = [|0; 1; 0; 2|] - let result = Vector.enumerateNonZero v - Expect.equal result [|(1, 1); (3, 2)|] "Expected non-zero elements with indices" - } - - test "split splits a vector into prefix and suffix" { - let v = [|1; 2; 3; 4|] - let prefix, suffix = Vector.split 2 v - Expect.equal prefix [|1; 2|] "Expected prefix" - Expect.equal suffix [|3; 4|] "Expected suffix" - } - - test "chunk chunks a vector into equally sized pieces" { - let v = [|1; 2; 3; 4; 5|] - let result = Vector.chunk 2 v - Expect.equal result [|[|1; 2|]; [|3; 4|]; [|5|]|] "Expected chunked vector" - } - - test "windowed creates a sliding window over the vector" { - let v = [|1; 2; 3; 4|] - let result = Vector.windowed 2 v - Expect.equal result [|[|1; 2|]; [|2; 3|]; [|3; 4|]|] "Expected sliding windows" - } - - test "splitVector splits a vector based on indices" { - let v = [|1; 2; 3; 4|] - let nvi, nv = Vector.splitVector [|1; 3|] v - Expect.equal nvi [|2; 4|] "Expected extracted elements" - Expect.equal nv [|1; 3|] "Expected remaining elements" - } - - test "permuteBy permutes a vector using a permutation function" { - let v = [|1; 2; 3|] - let result = Vector.permuteBy (fun i -> (i + 1) % 3) v // 1 2 0 - Expect.equal result [|2; 3; 1|] "Expected permuted vector" - } - - test "ofSeq converts a sequence to a vector" { - let seq = seq { 1; 2; 3 } - let result = Vector.ofSeq seq - Expect.equal result [|1; 2; 3|] "Expected vector from sequence" - } - ] - - ] - - - - - -//let private testVectorA = -// let values = [|0.;3.;6.|] -// Vector(Some (Instances.FloatNumerics :> INumeric),values) - -//[] -//let covarianceTests = -// let x = vector [5.;12.;18.;-23.;45.] -// let y = vector [2.;8.;18.;-20.;28.] - -// testList "Vector" [ -// testCase "cov" <| fun () -> -// let cov = Vector.cov x y -// Expect.floatClose Accuracy.high cov 434.90 "Should be equal (double precision)" -// testCase "covPopulation" <| fun () -> -// let covPop = Vector.covPopulation x y -// Expect.floatClose Accuracy.high covPop 347.92 "Should be equal (double precision)" -// ] From fa5ae9a731b889332a14762cf76eb57e9d1f7d74 Mon Sep 17 00:00:00 2001 From: Kevin Schneider Date: Thu, 18 Jul 2024 17:10:07 +0200 Subject: [PATCH 093/121] use .net 8, update fsdocs, adapt exisiting docs --- .config/dotnet-tools.json | 16 +- FSharp.Stats.sln | 8 +- build/PackageTasks.fs | 5 + build/TestTasks.fs | 18 +- build/build.fsproj | 9 + docs/BasicStats.fsx | 23 +- docs/Clustering.fsx | 30 +- docs/ComparisonMetrics.fsx | 107 +- docs/Correlation.fsx | 10 +- docs/Covariance.fsx | 4 + docs/CrossValidation.fsx | 13 +- docs/Differentiation.fsx | 4 + docs/Distributions.fsx | 22 +- docs/Fitting.fsx | 21 +- docs/GoodnessOfFit.fsx | 11 +- docs/GrowthCurve.fsx | 26 +- docs/Imputation.fsx | 4 + docs/Integration.fsx | 4 + docs/Interpolation.fsx | 15 +- docs/Intervals.fsx | 6 +- docs/Normalization.fsx | 9 +- docs/Optimization.fsx | 9 +- docs/Quantiles.fsx | 14 +- docs/Rank.fsx | 4 + docs/Signal.fsx | 14 +- docs/Testing.fsx | 28 +- docs/_head.html | 25 + docs/_template.html | 83 - docs/content/fsdocs-custom.css | 13636 ------------------------------- docs/content/fsdocs-theme.css | 40 + docs/index.fsx | 4 + docs/reference/_template.html | 82 - global.json | 4 +- 33 files changed, 246 insertions(+), 14062 deletions(-) create mode 100644 docs/_head.html delete mode 100644 docs/_template.html delete mode 100644 docs/content/fsdocs-custom.css create mode 100644 docs/content/fsdocs-theme.css delete mode 100644 docs/reference/_template.html diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index ae432524b..ac5ebfd1f 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -2,17 +2,19 @@ "version": 1, "isRoot": true, "tools": { - "fsdocs-tool": { - "version": "16.1.1", - "commands": [ - "fsdocs" - ] - }, "fantomas": { "version": "6.1.1", "commands": [ "fantomas" - ] + ], + "rollForward": false + }, + "fsdocs-tool": { + "version": "20.0.1", + "commands": [ + "fsdocs" + ], + "rollForward": false } } } \ No newline at end of file diff --git a/FSharp.Stats.sln b/FSharp.Stats.sln index 2c18d0e23..f61a9bb29 100644 --- a/FSharp.Stats.sln +++ b/FSharp.Stats.sln @@ -55,6 +55,9 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "docs", "docs", "{23F9FB2E-6 docs\Integration.fsx = docs\Integration.fsx docs\Interpolation.fsx = docs\Interpolation.fsx docs\Intervals.fsx = docs\Intervals.fsx + docs\LinearAlgebra.fsx = docs\LinearAlgebra.fsx + docs\Matrix_Vector.fsx = docs\Matrix_Vector.fsx + docs\ML.fsx = docs\ML.fsx docs\Normalization.fsx = docs\Normalization.fsx docs\NuGet.config = docs\NuGet.config docs\Optimization.fsx = docs\Optimization.fsx @@ -62,13 +65,12 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "docs", "docs", "{23F9FB2E-6 docs\Rank.fsx = docs\Rank.fsx docs\Signal.fsx = docs\Signal.fsx docs\Testing.fsx = docs\Testing.fsx - docs\_template.html = docs\_template.html - docs\_template.ipynb = docs\_template.ipynb + docs\_head.html = docs\_head.html EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "content", "content", "{50E3E339-AA4D-4FD2-8791-DEBD2EBF0504}" ProjectSection(SolutionItems) = preProject - docs\content\fsdocs-custom.css = docs\content\fsdocs-custom.css + docs\content\fsdocs-theme.css = docs\content\fsdocs-theme.css EndProjectSection EndProject Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FSharp.Stats.Interactive", "src\FSharp.Stats.Interactive\FSharp.Stats.Interactive.fsproj", "{D7BCF5C0-9E2B-4170-9390-607B0B65A8CD}" diff --git a/build/PackageTasks.fs b/build/PackageTasks.fs index af6517842..7edc74f81 100644 --- a/build/PackageTasks.fs +++ b/build/PackageTasks.fs @@ -8,6 +8,7 @@ open TestTasks open BlackFox.Fake open Fake.Core +open Fake.DotNet open Fake.IO.Globbing.Operators let pack = BuildTask.create "Pack" [clean; build; runTests] { @@ -23,12 +24,14 @@ let pack = BuildTask.create "Pack" [clean; build; runTests] { "Version",stableVersionTag "PackageReleaseNotes", (release.Notes |> String.concat "\r\n") ] @ p.MSBuildParams.Properties) + DisableInternalBinLog = true } { p with MSBuildParams = msBuildParams OutputPath = Some pkgDir } + |> DotNet.Options.withCustomParams (Some "--no-dependencies -tl") )) else failwith "aborted" } @@ -46,6 +49,7 @@ let packPrerelease = BuildTask.create "PackPrerelease" [setPrereleaseTag; clean; "Version", prereleaseTag "PackageReleaseNotes", (release.Notes |> String.toLines ) ] @ p.MSBuildParams.Properties) + DisableInternalBinLog = true } { p with @@ -53,6 +57,7 @@ let packPrerelease = BuildTask.create "PackPrerelease" [setPrereleaseTag; clean; OutputPath = Some pkgDir MSBuildParams = msBuildParams } + |> DotNet.Options.withCustomParams (Some "--no-dependencies -tl") )) else failwith "aborted" diff --git a/build/TestTasks.fs b/build/TestTasks.fs index d79c6d935..4ddb58cd4 100644 --- a/build/TestTasks.fs +++ b/build/TestTasks.fs @@ -7,16 +7,16 @@ open ProjectInfo open BasicTasks let runTests = BuildTask.create "RunTests" [clean; build] { - testProject - |> Fake.DotNet.DotNet.test (fun testParams -> - { testParams with - Logger = Some "console;verbosity=detailed" - Configuration = DotNet.BuildConfiguration.fromString configuration - NoBuild = true - MSBuildParams = { testParams.MSBuildParams with DisableInternalBinLog = true } + Fake.DotNet.DotNet.test(fun testParams -> + { + testParams with + Logger = Some "console;verbosity=detailed" + Configuration = DotNet.BuildConfiguration.fromString configuration + NoBuild = true + MSBuildParams = { testParams.MSBuildParams with DisableInternalBinLog = true } } |> DotNet.Options.withCustomParams (Some "-tl") - ) + ) testProject } // to do: use this once we have actual tests @@ -27,12 +27,12 @@ let runTestsWithCodeCov = BuildTask.create "RunTestsWithCodeCov" [clean; build] testParams with MSBuildParams = { standardParams with - DisableInternalBinLog = true Properties = [ "AltCover","true" "AltCoverCobertura","../../codeCov.xml" "AltCoverForce","true" ] + DisableInternalBinLog = true }; Logger = Some "console;verbosity=detailed" } diff --git a/build/build.fsproj b/build/build.fsproj index f978756ba..21200ae87 100644 --- a/build/build.fsproj +++ b/build/build.fsproj @@ -33,6 +33,15 @@ + + + + + + + + + diff --git a/docs/BasicStats.fsx b/docs/BasicStats.fsx index e03c4106f..4d3f5a6a2 100644 --- a/docs/BasicStats.fsx +++ b/docs/BasicStats.fsx @@ -10,9 +10,13 @@ categoryindex: 0 (*** hide ***) (*** condition: prepare ***) -#r "../src/FSharp.Stats/bin/Release/netstandard2.0/FSharp.Stats.dll" -#r "nuget: FsMath, 0.0.1" -open FsMath +#r "nuget: FSharpAux.Core, 2.0.0" +#r "nuget: FSharpAux, 2.0.0" +#r "nuget: FSharpAux.IO, 2.0.0" +#r "nuget: OptimizedPriorityQueue, 5.1.0" +#I "../src/FSharp.Stats/bin/Release/netstandard2.0/" +#r "FSharp.Stats.dll" + (*** condition: ipynb ***) #if IPYNB #r "nuget: FSharp.Stats" @@ -27,19 +31,6 @@ open FsMath _Summary:_ this tutorial gives an overview over how to do some of the basic statistical measurements with FSharp.Stats. -### Table of contents - - - [Central tendency](#Central-tendency) - - [Mean](#Mean) - - [Truncated mean](#Truncated-mean) - - [Median](#Median) - - [Harmonic mean](#Harmonic-mean) - - [Geometric mean](#Geometric-mean) - - [Dispersion](#Dispersion) - - [Range](#Range) - - [Variance and Standard Deviation](#Variance-and-standard-deviation) - - [Coefficient of variation](#Coefficient-of-variation) - ## Central tendency A [central tendency](https://en.wikipedia.org/wiki/Central_tendency) (or measure of central tendency) is a central or typical value for a probability distribution. diff --git a/docs/Clustering.fsx b/docs/Clustering.fsx index 4491a7d73..7146b91f9 100644 --- a/docs/Clustering.fsx +++ b/docs/Clustering.fsx @@ -10,25 +10,23 @@ categoryindex: 0 (*** hide ***) (*** condition: prepare ***) +#r "nuget: FSharpAux.Core, 2.0.0" +#r "nuget: FSharpAux, 2.0.0" +#r "nuget: FSharpAux.IO, 2.0.0" +#r "nuget: OptimizedPriorityQueue, 5.1.0" #I "../src/FSharp.Stats/bin/Release/netstandard2.0/" #r "FSharp.Stats.dll" #r "nuget: Plotly.NET, 4.0.0" -#r "nuget: FSharpAux, 1.0.0" #r "nuget: Cyjs.NET" -#r "nuget: OptimizedPriorityQueue, 5.1.0" -#r "nuget: FsMath, 0.0.1" -open FsMath + Plotly.NET.Defaults.DefaultDisplayOptions <- Plotly.NET.DisplayOptions.init (PlotlyJSReference = Plotly.NET.PlotlyJSReference.NoReference) (*** condition: ipynb ***) #if IPYNB -#r "nuget: Plotly.NET, 4.0.0" -#r "nuget: Plotly.NET.Interactive, 4.0.0" -#r "nuget: OptimizedPriorityQueue, 5.1.0" -#r "nuget: FSharpAux, 1.0.0" #r "nuget: FSharp.Stats" +#r "nuget: Plotly.NET, 4.0.0" #r "nuget: Cyjs.NET" #endif // IPYNB @@ -40,22 +38,6 @@ Plotly.NET.Defaults.DefaultDisplayOptions <- _Summary:_ this tutorial demonstrates several clustering methods in FSharp.Stats and how to visualize the results with Plotly.NET. -### Table of contents - - - [Iterative Clustering](#Iterative-Clustering) - - [k-means clustering](#k-means-clustering) - - [Density based clustering](#Density-based-clustering) - - [DBSCAN](#DBSCAN) - - [Hierarchical clustering](#Hierarchical-Clustering) - - [Distance measures](#Distance-measures) - - [Linkages](#Linkages) - - [Determining the optimal number of clusters](#Determining-the-optimal-number-of-clusters) - - [Rule of thumb](#Rule-of-thumb) - - [Elbow criterion](#Elbow-criterion) - - [AIC](#AIC) - - [Silhouette coefficient](#Silhouette-coefficient) - - [GapStatistics](#GapStatistics) - Clustering methods can be used to group elements of a huge data set based on their similarity. Elements sharing similar properties cluster together and can be reported as coherent group. **Column wise standardization** diff --git a/docs/ComparisonMetrics.fsx b/docs/ComparisonMetrics.fsx index 9920c443f..ebdb93214 100644 --- a/docs/ComparisonMetrics.fsx +++ b/docs/ComparisonMetrics.fsx @@ -10,6 +10,10 @@ categoryindex: 0 (***hide***) (*** condition: prepare ***) +#r "nuget: FSharpAux.Core, 2.0.0" +#r "nuget: FSharpAux, 2.0.0" +#r "nuget: FSharpAux.IO, 2.0.0" +#r "nuget: OptimizedPriorityQueue, 5.1.0" #I "../src/FSharp.Stats/bin/Release/netstandard2.0/" #r "FSharp.Stats.dll" #r "nuget: Plotly.NET, 4.0.0" @@ -32,20 +36,6 @@ Plotly.NET.Defaults.DefaultDisplayOptions <- [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/fslaborg/FSharp.Stats/gh-pages?urlpath=/tree/home/jovyan/Integration.ipynb) [![Notebook]({{root}}img/badge-notebook.svg)]({{root}}{{fsdocs-source-basename}}.ipynb) -#### Table of contents -- [Confusion matrices](#Confusion-matrices) - - [Binary confusion matrix](#Binary-confusion-matrix) - - [Multi-label confusion matrix](#Multi-label-confusion-matrix) -- [Comparison-Metric](#Comparison-Metrics) - - [ComparisonMetrics for binary comparisons](#ComparisonMetrics-for-binary-comparisons) - - [ComparisonMetrics for multi-label comparisons](#ComparisonMetrics-for-multi-label-comparisons) - - [Macro-averaging metrics](#Macro-averaging-metrics) - - [Micro-averaging metrics](#Micro-averaging-metrics) - - [Creating threshold-dependent metric maps](#Creating-threshold-dependent-metric-maps) - - [For binary predictions](#For-binary-predictions) - - [For multi-label predictions](#For-multi-label-predictions) - - [ROC curve example](#ROC-curve-example) - FSharp.Stats contains a collection for assessing both binary and multi-label comparisons, for example the results of a binary/multi-label classification or the results of a statistical test. Usually, using the functions provided by the `ComparisonMetrics` module should be enough, but for clarity this documentation also introduces the `BinaryConfusionMatrix` and `MultiLabelConfusionMatrix` types that are used to derive the `ComparisonMetrics.` @@ -72,11 +62,11 @@ $$predicted = (1,1,1,0,1,0,0)$$ a binary confusion matrix can be filled by comparing actual and predicted values at their respective indices: -| | | predicted | | -| --- | --- | --- | --- | -| | | True | False | -|actual | True | 3 | 1 | -| | False| 1 | 2 | +| | | **Predicted**| | +| --- | --- | --- | --- | +| | | True | False | +|**Actual** | True | 3 | 1 | +| | False| 1 | 2 | A whole array of prediction/test evaluation metrics can be derived from binary confusion matrices, which are all based on the 4 values of the confusion matrix: @@ -85,11 +75,12 @@ A whole array of prediction/test evaluation metrics can be derived from binary c - FP (False Positives, the actual false labels incorrectly predicted as true) - TP (False Negatives, the actual true labels incorrectly predicted as false) -| | | Predicted | | -| --- | --- | --- | --- | -| | | True | False | -|Actual | True | TP | FN | -| | False| FP | TN | +| | | **Predicted**| | +| --- | --- | --- | --- | +| | | True | False | +|**Actual** | True | TP | FN | +| | False| FP | TN | + These 4 base metrics are in principle what comprises the record type `BinaryConfusionMatrix`. @@ -138,12 +129,12 @@ $$predicted = (A,A,A,B,C,B,B,A,C,C,C,C,A,A)$$ a multi-label confusion matrix can be filled by comparing actual and predicted values at their respective indices: -| | | Predicted | | | -| --- | --- | --- | --- | --- | -| | | Label A | Label B | Label C | -| Actual | Label A | 3 | 1 | 1 | -| | Label B | 1 | 2 | 0 | -| | Label C | 2 | 0 | 4 | +| | | **Predicted** | | | +| --- | --- | --- | --- | --- | +| | | Label A | Label B | Label C | +| **Actual** | Label A | 3 | 1 | 1 | +| | Label B | 1 | 2 | 0 | +| | Label C | 2 | 0 | 4 | A `MultiLabelConfusionMatrix` can be created either @@ -186,11 +177,11 @@ This is done by taking all occurences of the label in the actual labels as posit As an example, the derived binary confusion matrix for `Label A` in above example would be: -| | | Predicted | | -| --- |--- | --- | --- | -| | | is A | is not A | -|Actual | is A | 3 | 2 | -| | is not A | 3 | 6 | +| | | **Predicted** | | +| --- |--- | --- | --- | +| | | is A | is not A | +|**Actual** | is A | 3 | 2 | +| | is not A | 3 | 6 | Programmatically, this can be done via `MultiLabelConfusionMatrix.oneVsRest` *) @@ -214,29 +205,29 @@ mlcm It also provides static methods to perform calculation of individual metrics derived from a BinaryConfusionMatrix via the `ComparisonMetrics.calculate` functions: -| Metric | Formula | API reference | -| --- |--- | --- | -|Sensitivity (TPR) | $TPR = \frac{TP}{TP+TN}$ | [ComparisonMetrics.calculateSensitivity ](/reference/fsharp-stats-testing-comparisonmetrics.html#calculateSensitivity ) | -|Specificity (TNR) | $TNR = \frac{TN}{TN+TP}$ | [ComparisonMetrics.calculateSpecificity ](/reference/fsharp-stats-testing-comparisonmetrics.html#calculateSpecificity ) | -|Precision (PPV) | $PPV = \frac{TP}{TP+FP}$ | [ComparisonMetrics.calculatePrecision ](/reference/fsharp-stats-testing-comparisonmetrics.html#calculatePrecision ) | -|NegativePredictiveValue (NPV) | $NPV = \frac{TN}{TN+FN}$ | [ComparisonMetrics.calculateNegativePredictiveValue](/reference/fsharp-stats-testing-comparisonmetrics.html#calculateNegativePredictiveValue) | -|Missrate (FNR) | $FNR = \frac{FN}{FN+TP}$ | [ComparisonMetrics.calculateMissrate ](/reference/fsharp-stats-testing-comparisonmetrics.html#calculateMissrate ) | -|FallOut (FPR) | $FPR = \frac{FP}{FP+TN}$ | [ComparisonMetrics.calculateFallOut ](/reference/fsharp-stats-testing-comparisonmetrics.html#calculateFallOut ) | -|FalseDiscoveryRate (FDR) | $FDR = \frac{FP}{FP+TP}$ | [ComparisonMetrics.calculateFalseDiscoveryRate ](/reference/fsharp-stats-testing-comparisonmetrics.html#calculateFalseDiscoveryRate ) | -|FalseOmissionRate (FOR) | $FOR = \frac{FN}{FN+TN}$ | [ComparisonMetrics.calculateFalseOmissionRate ](/reference/fsharp-stats-testing-comparisonmetrics.html#calculateFalseOmissionRate ) | -|PositiveLikelihoodRatio (LR+) | $LR+ = \frac{TPR}{FPR}$ | [ComparisonMetrics.calculatePositiveLikelihoodRatio](/reference/fsharp-stats-testing-comparisonmetrics.html#calculatePositiveLikelihoodRatio) | -|NegativeLikelihoodRatio (LR-) | $LR- = \frac{FNR}{TNR}$ | [ComparisonMetrics.calculateNegativeLikelihoodRatio](/reference/fsharp-stats-testing-comparisonmetrics.html#calculateNegativeLikelihoodRatio) | -|PrevalenceThreshold (PT) | $PT = \frac{\sqrt{FPR}}{\sqrt{TPR}+\sqrt{FPR}}$ | [ComparisonMetrics.calculatePrevalenceThreshold ](/reference/fsharp-stats-testing-comparisonmetrics.html#calculatePrevalenceThreshold ) | -|ThreatScore (TS) | $TS = \frac{TP}{TP+FN+FP}$ | [ComparisonMetrics.calculateThreatScore ](/reference/fsharp-stats-testing-comparisonmetrics.html#calculateThreatScore ) | -|Prevalence | $Prevalence = \frac{P}{P+N}$ | [ComparisonMetrics.calculatePrevalence ](/reference/fsharp-stats-testing-comparisonmetrics.html#calculatePrevalence ) | -|Accuracy (ACC) | $ACC = \frac{TP+TN}{TP+TN+FP+FN}$ | [ComparisonMetrics.calculateAccuracy ](/reference/fsharp-stats-testing-comparisonmetrics.html#calculateAccuracy ) | -|BalancedAccuracy (BA) | $BA = \frac{TPR+TNR}{2}$ | [ComparisonMetrics.calculateBalancedAccuracy ](/reference/fsharp-stats-testing-comparisonmetrics.html#calculateBalancedAccuracy ) | -|F1 Score | $F1 = \frac{2TP}{2TP+FP+FN}$ | [ComparisonMetrics.calculateF1 ](/reference/fsharp-stats-testing-comparisonmetrics.html#calculateF1 ) | -|PhiCoefficient (MCC) | $MCC = \frac{TP*TN-FP*FN}{\sqrt{(TP+FP)(TP+FN)(TN+FP)(TN+FN)}}$ | [ComparisonMetrics.calculatePhiCoefficient ](/reference/fsharp-stats-testing-comparisonmetrics.html#calculatePhiCoefficient ) | -|FowlkesMallowsIndex (FM) | $FM = \frac{}{}$ | [ComparisonMetrics.calculateFowlkesMallowsIndex ](/reference/fsharp-stats-testing-comparisonmetrics.html#calculateFowlkesMallowsIndex ) | -|Informedness (BM) | $BM = \frac{}{}$ | [ComparisonMetrics.calculateInformedness ](/reference/fsharp-stats-testing-comparisonmetrics.html#calculateInformedness ) | -|Markedness (MK) | $MK = \frac{}{}$ | [ComparisonMetrics.calculateMarkedness ](/reference/fsharp-stats-testing-comparisonmetrics.html#calculateMarkedness ) | -|DiagnosticOddsRatio (DOR) | $DOR = \frac{}{}$ | [ComparisonMetrics.calculateDiagnosticOddsRatio ](/reference/fsharp-stats-testing-comparisonmetrics.html#calculateDiagnosticOddsRatio ) | +| Metric | Formula | API reference | +| --- |--- | --- | +|Sensitivity (**TPR**) | $TPR = \frac{TP}{TP+TN}$ | [ComparisonMetrics.calculateSensitivity ](/reference/fsharp-stats-testing-comparisonmetrics.html#calculateSensitivity ) | +|Specificity (**TNR**) | $TNR = \frac{TN}{TN+TP}$ | [ComparisonMetrics.calculateSpecificity ](/reference/fsharp-stats-testing-comparisonmetrics.html#calculateSpecificity ) | +|Precision (**PPV**) | $PPV = \frac{TP}{TP+FP}$ | [ComparisonMetrics.calculatePrecision ](/reference/fsharp-stats-testing-comparisonmetrics.html#calculatePrecision ) | +|NegativePredictiveValue (**NPV**) | $NPV = \frac{TN}{TN+FN}$ | [ComparisonMetrics.calculateNegativePredictiveValue](/reference/fsharp-stats-testing-comparisonmetrics.html#calculateNegativePredictiveValue) | +|Missrate (**FNR**) | $FNR = \frac{FN}{FN+TP}$ | [ComparisonMetrics.calculateMissrate ](/reference/fsharp-stats-testing-comparisonmetrics.html#calculateMissrate ) | +|FallOut (**FPR**) | $FPR = \frac{FP}{FP+TN}$ | [ComparisonMetrics.calculateFallOut ](/reference/fsharp-stats-testing-comparisonmetrics.html#calculateFallOut ) | +|FalseDiscoveryRate (**FDR**) | $FDR = \frac{FP}{FP+TP}$ | [ComparisonMetrics.calculateFalseDiscoveryRate ](/reference/fsharp-stats-testing-comparisonmetrics.html#calculateFalseDiscoveryRate ) | +|FalseOmissionRate (**FOR**) | $FOR = \frac{FN}{FN+TN}$ | [ComparisonMetrics.calculateFalseOmissionRate ](/reference/fsharp-stats-testing-comparisonmetrics.html#calculateFalseOmissionRate ) | +|PositiveLikelihoodRatio (**LR+**) | $LR+ = \frac{TPR}{FPR}$ | [ComparisonMetrics.calculatePositiveLikelihoodRatio](/reference/fsharp-stats-testing-comparisonmetrics.html#calculatePositiveLikelihoodRatio) | +|NegativeLikelihoodRatio (**LR-**) | $LR- = \frac{FNR}{TNR}$ | [ComparisonMetrics.calculateNegativeLikelihoodRatio](/reference/fsharp-stats-testing-comparisonmetrics.html#calculateNegativeLikelihoodRatio) | +|PrevalenceThreshold (**PT**) | $PT = \frac{\sqrt{FPR}}{\sqrt{TPR}+\sqrt{FPR}}$ | [ComparisonMetrics.calculatePrevalenceThreshold ](/reference/fsharp-stats-testing-comparisonmetrics.html#calculatePrevalenceThreshold ) | +|ThreatScore (**TS**) | $TS = \frac{TP}{TP+FN+FP}$ | [ComparisonMetrics.calculateThreatScore ](/reference/fsharp-stats-testing-comparisonmetrics.html#calculateThreatScore ) | +|Prevalence | $Prevalence = \frac{P}{P+N}$ | [ComparisonMetrics.calculatePrevalence ](/reference/fsharp-stats-testing-comparisonmetrics.html#calculatePrevalence ) | +|Accuracy (**ACC**) | $ACC = \frac{TP+TN}{TP+TN+FP+FN}$ | [ComparisonMetrics.calculateAccuracy ](/reference/fsharp-stats-testing-comparisonmetrics.html#calculateAccuracy ) | +|BalancedAccuracy (**BA**) | $BA = \frac{TPR+TNR}{2}$ | [ComparisonMetrics.calculateBalancedAccuracy ](/reference/fsharp-stats-testing-comparisonmetrics.html#calculateBalancedAccuracy ) | +|F1 Score | $F1 = \frac{2TP}{2TP+FP+FN}$ | [ComparisonMetrics.calculateF1 ](/reference/fsharp-stats-testing-comparisonmetrics.html#calculateF1 ) | +|PhiCoefficient (**MCC**) | $MCC = \frac{TP*TN-FP*FN}{\sqrt{(TP+FP)(TP+FN)(TN+FP)(TN+FN)}}$ | [ComparisonMetrics.calculatePhiCoefficient ](/reference/fsharp-stats-testing-comparisonmetrics.html#calculatePhiCoefficient ) | +|FowlkesMallowsIndex (**FM**) | $FM = \frac{}{}$ | [ComparisonMetrics.calculateFowlkesMallowsIndex ](/reference/fsharp-stats-testing-comparisonmetrics.html#calculateFowlkesMallowsIndex ) | +|Informedness (**BM**) | $BM = \frac{}{}$ | [ComparisonMetrics.calculateInformedness ](/reference/fsharp-stats-testing-comparisonmetrics.html#calculateInformedness ) | +|Markedness (**MK**) | $MK = \frac{}{}$ | [ComparisonMetrics.calculateMarkedness ](/reference/fsharp-stats-testing-comparisonmetrics.html#calculateMarkedness ) | +|DiagnosticOddsRatio (**DOR**) | $DOR = \frac{}{}$ | [ComparisonMetrics.calculateDiagnosticOddsRatio ](/reference/fsharp-stats-testing-comparisonmetrics.html#calculateDiagnosticOddsRatio ) | ### ComparisonMetrics for binary comparisons diff --git a/docs/Correlation.fsx b/docs/Correlation.fsx index cbaddadd8..a59f6fe24 100644 --- a/docs/Correlation.fsx +++ b/docs/Correlation.fsx @@ -10,6 +10,10 @@ categoryindex: 0 (*** hide ***) (*** condition: prepare ***) +#r "nuget: FSharpAux.Core, 2.0.0" +#r "nuget: FSharpAux, 2.0.0" +#r "nuget: FSharpAux.IO, 2.0.0" +#r "nuget: OptimizedPriorityQueue, 5.1.0" #I "../src/FSharp.Stats/bin/Release/netstandard2.0/" #r "FSharp.Stats.dll" #r "nuget: Plotly.NET, 4.0.0" @@ -36,12 +40,6 @@ Plotly.NET.Defaults.DefaultDisplayOptions <- _Summary_: This tutorial demonstrates how to calculate correlation coefficients in FSharp.Stats -### Table of contents - - - [Sequence correlations](#Sequence correlations) - - [Matrix correlations](#Matrix correlations) - - [Autocorrelation](#Autocorrelation) - ## Sequence correlations *) diff --git a/docs/Covariance.fsx b/docs/Covariance.fsx index 41b35d0d6..14b6f8b89 100644 --- a/docs/Covariance.fsx +++ b/docs/Covariance.fsx @@ -10,6 +10,10 @@ categoryindex: 0 (*** hide ***) (*** condition: prepare ***) +#r "nuget: FSharpAux.Core, 2.0.0" +#r "nuget: FSharpAux, 2.0.0" +#r "nuget: FSharpAux.IO, 2.0.0" +#r "nuget: OptimizedPriorityQueue, 5.1.0" #I "../src/FSharp.Stats/bin/Release/netstandard2.0/" #r "FSharp.Stats.dll" #r "nuget: Plotly.NET, 4.0.0" diff --git a/docs/CrossValidation.fsx b/docs/CrossValidation.fsx index f78da9e08..ea59baa63 100644 --- a/docs/CrossValidation.fsx +++ b/docs/CrossValidation.fsx @@ -11,6 +11,10 @@ categoryindex: 0 (*** hide ***) (*** condition: prepare ***) +#r "nuget: FSharpAux.Core, 2.0.0" +#r "nuget: FSharpAux, 2.0.0" +#r "nuget: FSharpAux.IO, 2.0.0" +#r "nuget: OptimizedPriorityQueue, 5.1.0" #I "../src/FSharp.Stats/bin/Release/netstandard2.0/" #r "FSharp.Stats.dll" #r "nuget: Plotly.NET, 4.0.0" @@ -35,15 +39,6 @@ Plotly.NET.Defaults.DefaultDisplayOptions <- _Summary:_ this tutorial demonstrates how to perform several types of cross validation with FSharp.Stats. -### Table of contents - - - [Leave-one-out cross validation (LOOCV)](#Leave-one-out-cross-validation-LOOCV) - - [Procedure](#Procedure) - - [Polynomial loocv](#Polynomial-loocv) - - [Smoothing spline loocv](#Smoothing-spline-loocv) - - [k fold cross validation](#k-fold-cross-validation) - - [Shuffle and split cross validation](#Shuffle-and-split-cross-validation) - ## Leave-one-out cross validation (LOOCV) When fitting a data set it often comes down to the selection of the optimal fitting parameter(s). diff --git a/docs/Differentiation.fsx b/docs/Differentiation.fsx index 25eda0fb4..3d99734bc 100644 --- a/docs/Differentiation.fsx +++ b/docs/Differentiation.fsx @@ -10,6 +10,10 @@ categoryindex: 0 (*** hide ***) (*** condition: prepare ***) +#r "nuget: FSharpAux.Core, 2.0.0" +#r "nuget: FSharpAux, 2.0.0" +#r "nuget: FSharpAux.IO, 2.0.0" +#r "nuget: OptimizedPriorityQueue, 5.1.0" #I "../src/FSharp.Stats/bin/Release/netstandard2.0/" #r "FSharp.Stats.dll" #r "nuget: Plotly.NET, 4.0.0" diff --git a/docs/Distributions.fsx b/docs/Distributions.fsx index 5a631acd1..64778c1f8 100644 --- a/docs/Distributions.fsx +++ b/docs/Distributions.fsx @@ -11,6 +11,10 @@ categoryindex: 0 (*** hide ***) (*** condition: prepare ***) +#r "nuget: FSharpAux.Core, 2.0.0" +#r "nuget: FSharpAux, 2.0.0" +#r "nuget: FSharpAux.IO, 2.0.0" +#r "nuget: OptimizedPriorityQueue, 5.1.0" #I "../src/FSharp.Stats/bin/Release/netstandard2.0/" #r "FSharp.Stats.dll" #r "nuget: Plotly.NET, 4.0.0" @@ -36,24 +40,6 @@ Plotly.NET.Defaults.DefaultDisplayOptions <- _Summary:_ this tutorial shows how to use the various types of probability distributions in FSharp.Stats. -### Table of contents - -- [Continuous](#Continuous) - - [Normal distribution](#Normal-distribution) - - [Multivariate normal distribution](#Multivariate-normal-distribution) - - [F distribution](#F-distribution) -- [Discrete](#Discrete) - - [Bernoulli distribution](#Bernoulli-distribution) - - [Binomial distribution](#Binomial-distribution) - - [Multinomial distribution](#Multinomial-distribution) - - [Hypergerometric distribution](#Hypergerometric-distribution) - - [Poisson distribution](#Poisson-distribution) - - [Gamma distribution](#Gamma-distribution) - - [Negative binomial distribution](#Negative-binomial-distribution) -- [Empirical](#Empirical) -- [Density estimation](#Density-estimation) -- [Distance](#Distance) - FSharp.Stats provides a wide range of probability distributions. Given the distribution parameters they can be used to investigate their statistical properties or to sample non-uniform random numbers. diff --git a/docs/Fitting.fsx b/docs/Fitting.fsx index 666aaf7e2..ee5ca77a5 100644 --- a/docs/Fitting.fsx +++ b/docs/Fitting.fsx @@ -10,10 +10,12 @@ categoryindex: 0 (*** hide ***) (*** condition: prepare ***) -#r "../src/FSharp.Stats/bin/Release/netstandard2.0/FSharp.Stats.dll" -#r "nuget: Newtonsoft.JSON, 13.0.1" -#r "nuget: DynamicObj, 2.0.0" -#r "nuget: Giraffe.ViewEngine, 1.4.0" +#r "nuget: FSharpAux.Core, 2.0.0" +#r "nuget: FSharpAux, 2.0.0" +#r "nuget: FSharpAux.IO, 2.0.0" +#r "nuget: OptimizedPriorityQueue, 5.1.0" +#I "../src/FSharp.Stats/bin/Release/netstandard2.0/" +#r "FSharp.Stats.dll" #r "nuget: Plotly.NET, 4.0.0" #r "nuget: FsMath, 0.0.1" open FsMath @@ -40,17 +42,6 @@ Plotly.NET.Defaults.DefaultDisplayOptions <- _Summary:_ this tutorial will walk through several ways of fitting data with FSharp.Stats. -### Table of contents - - [Linear Regression](#Linear-Regression) - - [Summary](#Summary) - - [Simple Linear Regression](#Simple-Linear-Regression) - - [Univariable](#Univariable) - - [Multivariable](#Multivariable) - - [Polynomial Regression](#Polynomial-Regression) - - [Nonlinear Regression](#Nonlinear-Regression) - - [LevenbergMarquardtConstrained](#LevenbergMarquardtConstrained) - - [Smoothing spline](#Smoothing-spline) - ## Linear Regression In Linear Regression a linear system of equations is generated. The coefficients obtained by the solution to this equation diff --git a/docs/GoodnessOfFit.fsx b/docs/GoodnessOfFit.fsx index 307e2e733..1ffde9059 100644 --- a/docs/GoodnessOfFit.fsx +++ b/docs/GoodnessOfFit.fsx @@ -10,6 +10,10 @@ categoryindex: 0 (*** hide ***) (*** condition: prepare ***) +#r "nuget: FSharpAux.Core, 2.0.0" +#r "nuget: FSharpAux, 2.0.0" +#r "nuget: FSharpAux.IO, 2.0.0" +#r "nuget: OptimizedPriorityQueue, 5.1.0" #I "../src/FSharp.Stats/bin/Release/netstandard2.0/" #r "FSharp.Stats.dll" #r "nuget: Plotly.NET, 4.0.0" @@ -39,13 +43,6 @@ open Plotly.NET _Summary:_ this tutorial shows how to assess fit quality with FSharp.Stats -### Table of contents - - - [Linear regression report](#Linear-regression-report) - - [Confidence bands](#Confidence-bands) - - [Prediction bands](#Prediction-bands) - - [Cook's distance](#Cook-s-distance) - ## Linear regression report Consider this simple linear regression: diff --git a/docs/GrowthCurve.fsx b/docs/GrowthCurve.fsx index 520fa5dfe..31df001ac 100644 --- a/docs/GrowthCurve.fsx +++ b/docs/GrowthCurve.fsx @@ -10,8 +10,11 @@ categoryindex: 0 (*** hide ***) (*** condition: prepare ***) -#I "../src/FSharp.Stats/bin/Release/netstandard2.0/" -#r "FSharp.Stats.dll" +#r "../src/FSharp.Stats/bin/Release/netstandard2.0/FSharp.Stats.dll" +#r "nuget: FSharpAux.Core, 2.0.0" +#r "nuget: FSharpAux, 2.0.0" +#r "nuget: FSharpAux.IO, 2.0.0" +#r "nuget: OptimizedPriorityQueue, 5.1.0" #r "nuget: Plotly.NET, 4.0.0" #r "nuget: FsMath, 0.0.1" open FsMath @@ -37,25 +40,6 @@ open Plotly.NET _Summary:_ this tutorial demonstrates variou way to model growth curves, a commong task in any (micro)biological lab -### Table of contents - - - [Modelling](#Modelling) - - [Manual phase selection](#Manual-phase-selection) - - [Gompertz model](#Gompertz-model) - - [Generation time calculation](#Generation-time-calculation) - - [Other models](#Other-models) - - [Richards curve](#Richards-curve) - - [Weibull](#Weibull) - - [Janoschek](#Janoschek) - - [Exponential](#Exponential) - - [Verhulst](#Verhulst) - - [Morgan-Mercer-Flodin](#Morgan-Mercer-Flodin) - - [von Bertalanffy](#von-Bertalanffy) - - [Comparison between all models](Comparison-between-all-models) - - [Fit function](#Fit-function) - - [Generation time](#Generation-time) - - [Model examples](#Model-examples) - ## Modelling Growth and other physiological parameters like size/weight/length can be modeled as function of time. diff --git a/docs/Imputation.fsx b/docs/Imputation.fsx index 92b646902..e8a123f25 100644 --- a/docs/Imputation.fsx +++ b/docs/Imputation.fsx @@ -10,6 +10,10 @@ categoryindex: 0 (*** hide ***) (*** condition: prepare ***) +#r "nuget: FSharpAux.Core, 2.0.0" +#r "nuget: FSharpAux, 2.0.0" +#r "nuget: FSharpAux.IO, 2.0.0" +#r "nuget: OptimizedPriorityQueue, 5.1.0" #I "../src/FSharp.Stats/bin/Release/netstandard2.0/" #r "FSharp.Stats.dll" #r "nuget: Plotly.NET, 4.0.0" diff --git a/docs/Integration.fsx b/docs/Integration.fsx index 2e201f0f0..32e31949a 100644 --- a/docs/Integration.fsx +++ b/docs/Integration.fsx @@ -10,6 +10,10 @@ categoryindex: 0 (*** hide ***) (*** condition: prepare ***) +#r "nuget: FSharpAux.Core, 2.0.0" +#r "nuget: FSharpAux, 2.0.0" +#r "nuget: FSharpAux.IO, 2.0.0" +#r "nuget: OptimizedPriorityQueue, 5.1.0" #I "../src/FSharp.Stats/bin/Release/netstandard2.0/" #r "FSharp.Stats.dll" #r "nuget: Plotly.NET, 4.0.0" diff --git a/docs/Interpolation.fsx b/docs/Interpolation.fsx index ddc4eb368..c00823f32 100644 --- a/docs/Interpolation.fsx +++ b/docs/Interpolation.fsx @@ -10,6 +10,10 @@ categoryindex: 0 (*** hide ***) (*** condition: prepare ***) +#r "nuget: FSharpAux.Core, 2.0.0" +#r "nuget: FSharpAux, 2.0.0" +#r "nuget: FSharpAux.IO, 2.0.0" +#r "nuget: OptimizedPriorityQueue, 5.1.0" #I "../src/FSharp.Stats/bin/Release/netstandard2.0/" #r "FSharp.Stats.dll" #r "nuget: Plotly.NET, 4.0.0" @@ -37,17 +41,6 @@ open Plotly.NET _Summary:_ This tutorial demonstrates several ways of interpolating with FSharp.Stats -### Table of contents - -- [Summary](#Summary) -- [Polynomial interpolation](#Polynomial-interpolation) -- [Cubic interpolating spline](#Cubic-spline-interpolation) -- [Akima interpolating subspline](#Akima-subspline-interpolation) -- [Hermite interpolation](#Hermite-interpolation) -- [Bezier interpolation](#Bezier-interpolation) -- [Chebyshev function approximation](#Chebyshev-function-approximation) - - ## Summary With the `FSharp.Stats.Interpolation` module you can apply various interpolation methods. While interpolating functions always go through the input points (knots), methods to predict function values diff --git a/docs/Intervals.fsx b/docs/Intervals.fsx index 13e90c87f..a374a000e 100644 --- a/docs/Intervals.fsx +++ b/docs/Intervals.fsx @@ -10,6 +10,10 @@ categoryindex: 0 (*** hide ***) (*** condition: prepare ***) +#r "nuget: FSharpAux.Core, 2.0.0" +#r "nuget: FSharpAux, 2.0.0" +#r "nuget: FSharpAux.IO, 2.0.0" +#r "nuget: OptimizedPriorityQueue, 5.1.0" #I "../src/FSharp.Stats/bin/Release/netstandard2.0/" #r "FSharp.Stats.dll" #r "nuget: Plotly.NET, 4.0.0" @@ -50,7 +54,7 @@ The interval module enables working with closed intervals. A closed interval inc open FSharp.Stats open Plotly.NET -let myInterval = Interval.CreateLeftOpen (-3.,2.) +let myInterval = Interval.CreateLeftOpen (-3.,2.) let loi = sprintf "myInterval is: %s" (myInterval.ToString()) diff --git a/docs/Normalization.fsx b/docs/Normalization.fsx index 3bd51bfd4..f63b7d095 100644 --- a/docs/Normalization.fsx +++ b/docs/Normalization.fsx @@ -10,6 +10,10 @@ categoryindex: 0 (*** hide ***) (*** condition: prepare ***) +#r "nuget: FSharpAux.Core, 2.0.0" +#r "nuget: FSharpAux, 2.0.0" +#r "nuget: FSharpAux.IO, 2.0.0" +#r "nuget: OptimizedPriorityQueue, 5.1.0" #I "../src/FSharp.Stats/bin/Release/netstandard2.0/" #r "FSharp.Stats.dll" #r "nuget: Plotly.NET, 4.0.0" @@ -43,11 +47,6 @@ open Plotly.NET.LayoutObjects _Summary:_ this tutorial demonstrates multiple ways of data normalization accross several samples -### Table of contents - - [Introduction](#Introduction) - - [Median of Ratios](#Median-of-ratios) - - [Quantile normalization](#Quantile-normalization) - ## Introduction When you want to compare e.g. intensity measurements of elements between samples, you often have to normalize the samples in order diff --git a/docs/Optimization.fsx b/docs/Optimization.fsx index c175a8f07..1ea8ac936 100644 --- a/docs/Optimization.fsx +++ b/docs/Optimization.fsx @@ -10,6 +10,10 @@ categoryindex: 0 (*** hide ***) (*** condition: prepare ***) +#r "nuget: FSharpAux.Core, 2.0.0" +#r "nuget: FSharpAux, 2.0.0" +#r "nuget: FSharpAux.IO, 2.0.0" +#r "nuget: OptimizedPriorityQueue, 5.1.0" #I "../src/FSharp.Stats/bin/Release/netstandard2.0/" #r "FSharp.Stats.dll" #r "nuget: Plotly.NET, 4.0.0" @@ -39,13 +43,8 @@ open Plotly.NET _Summary:_ This tutorial teaches how to use optimization methods within FSharp.Stats -### Table of contents - - - [Nelder-Mead](#Nelder-Mead) - ## Nelder-Mead - The Nelder-Mead method (also downhill simplex method) can be used to find the minimum or maximum of an objective function. Please check out Mathias' blog post about the [nelder mead algorithm](https://brandewinder.com/2022/03/31/breaking-down-Nelder-Mead/). diff --git a/docs/Quantiles.fsx b/docs/Quantiles.fsx index 9e2102e77..450f5f468 100644 --- a/docs/Quantiles.fsx +++ b/docs/Quantiles.fsx @@ -10,6 +10,10 @@ categoryindex: 0 (*** hide ***) (*** condition: prepare ***) +#r "nuget: FSharpAux.Core, 2.0.0" +#r "nuget: FSharpAux, 2.0.0" +#r "nuget: FSharpAux.IO, 2.0.0" +#r "nuget: OptimizedPriorityQueue, 5.1.0" #I "../src/FSharp.Stats/bin/Release/netstandard2.0/" #r "FSharp.Stats.dll" #r "nuget: Plotly.NET, 4.0.0" @@ -37,16 +41,6 @@ Plotly.NET.Defaults.DefaultDisplayOptions <- _Summary:_ this tutorial demonstrates how to handle quantiles and QQ-Plots -### Table of contents - - - [Quantiles](#Quantiles) - - [QQ plot](#QQ-plot) - - [Comparing two sample distributions](#Comparing-two-sample-distributions) - - [Comparing a sample against a distribution](#Comparing-a-sample-against-a-distribution) - - [Normal distribution](#Normal-distribution) - - [Uniform Distribution](#Uniform-Distribution) -- [Quantile normalization](#Quantile-normalization) - ## Quantiles Quantiles are values that divide data into equally spaced groups. Percentiles are just quantiles that divide the data in 100 equally sized groups. diff --git a/docs/Rank.fsx b/docs/Rank.fsx index 7b7af6534..1604451de 100644 --- a/docs/Rank.fsx +++ b/docs/Rank.fsx @@ -10,6 +10,10 @@ categoryindex: 0 (*** hide ***) (*** condition: prepare ***) +#r "nuget: FSharpAux.Core, 2.0.0" +#r "nuget: FSharpAux, 2.0.0" +#r "nuget: FSharpAux.IO, 2.0.0" +#r "nuget: OptimizedPriorityQueue, 5.1.0" #I "../src/FSharp.Stats/bin/Release/netstandard2.0/" #r "FSharp.Stats.dll" #r "nuget: Plotly.NET, 4.0.0" diff --git a/docs/Signal.fsx b/docs/Signal.fsx index cdf566238..031b8c1aa 100644 --- a/docs/Signal.fsx +++ b/docs/Signal.fsx @@ -10,6 +10,10 @@ categoryindex: 0 (*** hide ***) (*** condition: prepare ***) +#r "nuget: FSharpAux.Core, 2.0.0" +#r "nuget: FSharpAux, 2.0.0" +#r "nuget: FSharpAux.IO, 2.0.0" +#r "nuget: OptimizedPriorityQueue, 5.1.0" #I "../src/FSharp.Stats/bin/Release/netstandard2.0/" #r "FSharp.Stats.dll" #r "nuget: Plotly.NET, 4.0.0" @@ -43,16 +47,6 @@ open Plotly.NET.LayoutObjects _Summary:_ this tutorial demonstrates multiple ways of signal processing with FSharp.Stats. -### Table of contents - - [Outliers](#Outliers) - - [Tukey's fences](#Tukey-s-fences) - - [Filtering](#Filtering) - - [Padding](#Padding) - - [Wavelet](#Wavelet) - - [Continuous Wavelet](#Continuous-Wavelet) - - [Continuous Wavelet 3D](#Continuous-Wavelet-3D) - - [Fast Fourier transform](#Fast-Fourier-transform) - ## Outliers ### Tukey's fences diff --git a/docs/Testing.fsx b/docs/Testing.fsx index ba709a690..f68b24cbe 100644 --- a/docs/Testing.fsx +++ b/docs/Testing.fsx @@ -10,10 +10,13 @@ categoryindex: 0 (*** hide ***) (*** condition: prepare ***) +#r "nuget: FSharpAux.Core, 2.0.0" +#r "nuget: FSharpAux, 2.0.0" +#r "nuget: FSharpAux.IO, 2.0.0" +#r "nuget: OptimizedPriorityQueue, 5.1.0" #I "../src/FSharp.Stats/bin/Release/netstandard2.0/" #r "FSharp.Stats.dll" #r "nuget: Plotly.NET, 4.0.0" -#r "nuget: FSharpAux, 1.1.0" #r "nuget: Deedle, 3.0.0" #r "nuget: FsMath, 0.0.1" open FsMath @@ -26,7 +29,6 @@ Plotly.NET.Defaults.DefaultDisplayOptions <- #r "nuget: Plotly.NET, 4.0.0" #r "nuget: Plotly.NET.Interactive, 4.0.0" #r "nuget: FSharp.Stats" -#r "nuget: FSharpAux, 1.1.0" #r "nuget: Deedle, 3.0.0" open Plotly.NET @@ -47,28 +49,6 @@ open Deedle _Summary:_ this tutorial explains how to perform various statistical tests with FSharp.Stats. -### Table of contents - - - [Test Statistics](#Test-Statistics) - - [T-Test](#T-Test) - - [Anova](#Anova) - - [F-Test](#F-Test) - - [H-Test](#H-Test) - - [Friedman-Test](#Friedman-Test) - - [Wilcoxon signed-rank Test](#Wilcoxon-Test) - - [Chi-Squared Test](#Chi-Squared-Test) - - [Bartlett](#Bartlett) - - [PostHoc](#PostHoc) - - [Fisher's LSD](#Fisher-s-LSD) - - [Hays](#Hays) - - [Tukey HSD](#Tukey-HSD) - - [Dunnetts test](#Dunnetts-test) - - [Fisher Hotelling](#Fisher-Hotelling) -- [Multiple testing](#Multiple-testing) - - [Benjamini-Hochberg](#Benjamini-Hochberg) - - [Q Value](#Q-Value) - - [SAM](#SAM) - FSharp.Stats provides hypothesis tests for different applications. A hypothesis test is a statistical test that is used to determine whether there is enough evidence in a sample of data to infer that a certain condition is true for the entire population. diff --git a/docs/_head.html b/docs/_head.html new file mode 100644 index 000000000..b4c501468 --- /dev/null +++ b/docs/_head.html @@ -0,0 +1,25 @@ + +{{fsdocs-page-title}} + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs/_template.html b/docs/_template.html deleted file mode 100644 index 9fd0e8331..000000000 --- a/docs/_template.html +++ /dev/null @@ -1,83 +0,0 @@ - - - - - - {{fsdocs-page-title}} - - - - - - - - - - - - - - - - {{fsdocs-watch-script}} - - - -
-
- -
-
-
-
- {{fsdocs-content}} -
-
-
- {{fsdocs-tooltips}} -
- - - - - - - - - - - \ No newline at end of file diff --git a/docs/content/fsdocs-custom.css b/docs/content/fsdocs-custom.css deleted file mode 100644 index f8b2d7df5..000000000 --- a/docs/content/fsdocs-custom.css +++ /dev/null @@ -1,13636 +0,0 @@ -@import url("https://fonts.googleapis.com/css?family=Nunito+Sans:400,700"); -/*! bulma.io v0.9.2 | MIT License | github.com/jgthms/bulma */ -/* Bulma Utilities */ -.pagination-previous, -.pagination-next, -.pagination-link, -.pagination-ellipsis, .file-cta, -.file-name, .select select, .textarea, .input, .button { - -moz-appearance: none; - -webkit-appearance: none; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - border: 1px solid transparent; - border-radius: 4px; - -webkit-box-shadow: none; - box-shadow: none; - display: -webkit-inline-box; - display: -ms-inline-flexbox; - display: inline-flex; - font-size: 1rem; - height: 2.5em; - -webkit-box-pack: start; - -ms-flex-pack: start; - justify-content: flex-start; - line-height: 1.5; - padding-bottom: calc(0.5em - 1px); - padding-left: calc(0.75em - 1px); - padding-right: calc(0.75em - 1px); - padding-top: calc(0.5em - 1px); - position: relative; - vertical-align: top; -} - - .pagination-previous:focus, - .pagination-next:focus, - .pagination-link:focus, - .pagination-ellipsis:focus, .file-cta:focus, - .file-name:focus, .select select:focus, .textarea:focus, .input:focus, .button:focus, .is-focused.pagination-previous, - .is-focused.pagination-next, - .is-focused.pagination-link, - .is-focused.pagination-ellipsis, .is-focused.file-cta, - .is-focused.file-name, .select select.is-focused, .is-focused.textarea, .is-focused.input, .is-focused.button, .pagination-previous:active, - .pagination-next:active, - .pagination-link:active, - .pagination-ellipsis:active, .file-cta:active, - .file-name:active, .select select:active, .textarea:active, .input:active, .button:active, .is-active.pagination-previous, .pagination-previous.active, - .is-active.pagination-next, - .pagination-next.active, - .is-active.pagination-link, - .pagination-link.active, - .is-active.pagination-ellipsis, - .pagination-ellipsis.active, .is-active.file-cta, .file-cta.active, - .is-active.file-name, - .file-name.active, .select select.is-active, .select select.active, .is-active.textarea, .textarea.active, .is-active.input, .input.active, .is-active.button, .button.active { - outline: none; - } - - [disabled].pagination-previous, - [disabled].pagination-next, - [disabled].pagination-link, - [disabled].pagination-ellipsis, [disabled].file-cta, - [disabled].file-name, .select select[disabled], [disabled].textarea, [disabled].input, [disabled].button, fieldset[disabled] .pagination-previous, - fieldset[disabled] .pagination-next, - fieldset[disabled] .pagination-link, - fieldset[disabled] .pagination-ellipsis, fieldset[disabled] .file-cta, - fieldset[disabled] .file-name, fieldset[disabled] .select select, .select fieldset[disabled] select, fieldset[disabled] .textarea, fieldset[disabled] .input, fieldset[disabled] .button { - cursor: not-allowed; - } - -.is-unselectable, .tabs, .pagination-previous, -.pagination-next, -.pagination-link, -.pagination-ellipsis, .breadcrumb, .file, .button { - -webkit-touch-callout: none; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; -} - -.navbar-link:not(.is-arrowless)::after, .select:not(.is-multiple):not(.is-loading)::after { - border: 3px solid transparent; - border-radius: 2px; - border-right: 0; - border-top: 0; - content: " "; - display: block; - height: 0.625em; - margin-top: -0.4375em; - pointer-events: none; - position: absolute; - top: 50%; - -webkit-transform: rotate(-45deg); - -ms-transform: rotate(-45deg); - transform: rotate(-45deg); - -webkit-transform-origin: center; - -ms-transform-origin: center; - transform-origin: center; - width: 0.625em; -} - -.tabs:not(:last-child), .pagination:not(:last-child), .message:not(:last-child), .level:not(:last-child), .breadcrumb:not(:last-child), .highlight:not(:last-child), .block:not(:last-child), .title:not(:last-child), -.subtitle:not(:last-child), .table-container:not(:last-child), .table:not(:last-child), table:not(:last-child), .progress:not(:last-child), .notification:not(:last-child), .content:not(:last-child), .box:not(:last-child) { - margin-bottom: 1.5rem; -} - -.modal-close, .delete { - -webkit-touch-callout: none; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - -moz-appearance: none; - -webkit-appearance: none; - background-color: rgba(10, 10, 10, 0.2); - border: none; - border-radius: 290486px; - cursor: pointer; - pointer-events: auto; - display: inline-block; - -webkit-box-flex: 0; - -ms-flex-positive: 0; - flex-grow: 0; - -ms-flex-negative: 0; - flex-shrink: 0; - font-size: 0; - height: 20px; - max-height: 20px; - max-width: 20px; - min-height: 20px; - min-width: 20px; - outline: none; - position: relative; - vertical-align: top; - width: 20px; -} - - .modal-close::before, .delete::before, .modal-close::after, .delete::after { - background-color: white; - content: ""; - display: block; - left: 50%; - position: absolute; - top: 50%; - -webkit-transform: translateX(-50%) translateY(-50%) rotate(45deg); - -ms-transform: translateX(-50%) translateY(-50%) rotate(45deg); - transform: translateX(-50%) translateY(-50%) rotate(45deg); - -webkit-transform-origin: center center; - -ms-transform-origin: center center; - transform-origin: center center; - } - - .modal-close::before, .delete::before { - height: 2px; - width: 50%; - } - - .modal-close::after, .delete::after { - height: 50%; - width: 2px; - } - - .modal-close:hover, .delete:hover, .modal-close:focus, .delete:focus { - background-color: rgba(10, 10, 10, 0.3); - } - - .modal-close:active, .delete:active { - background-color: rgba(10, 10, 10, 0.4); - } - -.is-small.modal-close, .is-small.delete { - height: 16px; - max-height: 16px; - max-width: 16px; - min-height: 16px; - min-width: 16px; - width: 16px; -} - -.is-medium.modal-close, .is-medium.delete { - height: 24px; - max-height: 24px; - max-width: 24px; - min-height: 24px; - min-width: 24px; - width: 24px; -} - -.is-large.modal-close, .is-large.delete { - height: 32px; - max-height: 32px; - max-width: 32px; - min-height: 32px; - min-width: 32px; - width: 32px; -} - -.control.is-loading::after, .select.is-loading::after, .loader, .button.is-loading::after { - -webkit-animation: spinAround 500ms infinite linear; - animation: spinAround 500ms infinite linear; - border: 2px solid #dbdbdb; - border-radius: 290486px; - border-right-color: transparent; - border-top-color: transparent; - content: ""; - display: block; - height: 1em; - position: relative; - width: 1em; -} - -.hero-video, .is-overlay, .modal-background, .modal, .image.is-square img, -.image.is-square .has-ratio, .image.is-1by1 img, -.image.is-1by1 .has-ratio, .image.is-5by4 img, -.image.is-5by4 .has-ratio, .image.is-4by3 img, -.image.is-4by3 .has-ratio, .image.is-3by2 img, -.image.is-3by2 .has-ratio, .image.is-5by3 img, -.image.is-5by3 .has-ratio, .image.is-16by9 img, -.image.is-16by9 .has-ratio, .image.is-2by1 img, -.image.is-2by1 .has-ratio, .image.is-3by1 img, -.image.is-3by1 .has-ratio, .image.is-4by5 img, -.image.is-4by5 .has-ratio, .image.is-3by4 img, -.image.is-3by4 .has-ratio, .image.is-2by3 img, -.image.is-2by3 .has-ratio, .image.is-3by5 img, -.image.is-3by5 .has-ratio, .image.is-9by16 img, -.image.is-9by16 .has-ratio, .image.is-1by2 img, -.image.is-1by2 .has-ratio, .image.is-1by3 img, -.image.is-1by3 .has-ratio { - bottom: 0; - left: 0; - position: absolute; - right: 0; - top: 0; -} - -/* Bulma Base */ -/*! minireset.css v0.0.6 | MIT License | github.com/jgthms/minireset.css */ -html, -body, -p, -ol, -ul, -li, -dl, -dt, -dd, -blockquote, -figure, -fieldset, -legend, -textarea, -pre, -iframe, -hr, -h1, -h2, -h3, -h4, -h5, -h6 { - margin: 0; - padding: 0; -} - -h1, -h2, -h3, -h4, -h5, -h6 { - font-size: 100%; - font-weight: normal; -} - -ul { - list-style: none; -} - -button, -input, -select, -textarea { - margin: 0; -} - -html { - -webkit-box-sizing: border-box; - box-sizing: border-box; -} - -*, *::before, *::after { - -webkit-box-sizing: inherit; - box-sizing: inherit; -} - -img, -video { - height: auto; - max-width: 100%; -} - -iframe { - border: 0; -} - -table { - border-collapse: collapse; - border-spacing: 0; -} - -td, -th { - padding: 0; -} - - td:not([align]), - th:not([align]) { - text-align: inherit; - } - -html { - background-color: white; - font-size: 16px; - -moz-osx-font-smoothing: grayscale; - -webkit-font-smoothing: antialiased; - min-width: 300px; - overflow-x: hidden; - overflow-y: scroll; - text-rendering: optimizeLegibility; - -webkit-text-size-adjust: 100%; - -moz-text-size-adjust: 100%; - -ms-text-size-adjust: 100%; - text-size-adjust: 100%; -} - -article, -aside, -figure, -footer, -header, -hgroup, -section { - display: block; -} - -body, -button, -input, -optgroup, -select, -textarea { - font-family: "Nunito", sans-serif; -} - -code, -pre { - -moz-osx-font-smoothing: auto; - -webkit-font-smoothing: auto; - font-family: monospace; -} - -body { - color: #4a4a4a; - font-size: 1em; - font-weight: 400; - line-height: 1.5; -} - -a { - color: #378BBA; - cursor: pointer; - text-decoration: none; -} - - a strong { - color: currentColor; - } - - a:hover { - color: #A00975; - } - -code { - background-color: whitesmoke; - color: #da1039; - font-size: 0.875em; - font-weight: normal; - padding: 0.25em 0.5em 0.25em; -} - -hr { - background-color: whitesmoke; - border: none; - display: block; - height: 2px; - margin: 1.5rem 0; -} - -img { - height: auto; - max-width: 100%; -} - -input[type="checkbox"], -input[type="radio"] { - vertical-align: baseline; -} - -small { - font-size: 0.875em; -} - -span { - font-style: inherit; - font-weight: inherit; -} - -strong { - color: #363636; - font-weight: 700; -} - -fieldset { - border: none; -} - -pre { - -webkit-overflow-scrolling: touch; - background-color: whitesmoke; - color: #4a4a4a; - font-size: 0.875em; - overflow-x: auto; - padding: 1.25rem 1.5rem; - white-space: pre; - word-wrap: normal; -} - - pre code { - background-color: transparent; - color: currentColor; - font-size: 1em; - padding: 0; - } - -table td, -table th { - vertical-align: top; -} - - table td:not([align]), - table th:not([align]) { - text-align: inherit; - } - -table th { - color: #363636; -} - -@-webkit-keyframes spinAround { - from { - -webkit-transform: rotate(0deg); - transform: rotate(0deg); - } - - to { - -webkit-transform: rotate(359deg); - transform: rotate(359deg); - } -} - -@keyframes spinAround { - from { - -webkit-transform: rotate(0deg); - transform: rotate(0deg); - } - - to { - -webkit-transform: rotate(359deg); - transform: rotate(359deg); - } -} - -/* Bulma Elements */ -.box { - background-color: white; - border-radius: 6px; - -webkit-box-shadow: 0 0.5em 1em -0.125em rgba(10, 10, 10, 0.1), 0 0px 0 1px rgba(10, 10, 10, 0.02); - box-shadow: 0 0.5em 1em -0.125em rgba(10, 10, 10, 0.1), 0 0px 0 1px rgba(10, 10, 10, 0.02); - color: #4a4a4a; - display: block; - padding: 1.25rem; -} - -a.box:hover, a.box:focus { - -webkit-box-shadow: 0 0.5em 1em -0.125em rgba(10, 10, 10, 0.1), 0 0 0 1px #378BBA; - box-shadow: 0 0.5em 1em -0.125em rgba(10, 10, 10, 0.1), 0 0 0 1px #378BBA; -} - -a.box:active { - -webkit-box-shadow: inset 0 1px 2px rgba(10, 10, 10, 0.2), 0 0 0 1px #378BBA; - box-shadow: inset 0 1px 2px rgba(10, 10, 10, 0.2), 0 0 0 1px #378BBA; -} - -.button { - background-color: white; - border-color: #dbdbdb; - border-width: 1px; - color: #363636; - cursor: pointer; - -webkit-box-pack: center; - -ms-flex-pack: center; - justify-content: center; - padding-bottom: calc(0.5em - 1px); - padding-left: 1em; - padding-right: 1em; - padding-top: calc(0.5em - 1px); - text-align: center; - white-space: nowrap; -} - - .button strong { - color: inherit; - } - - .button .icon, .button .icon.is-small, .button .icon.is-medium, .button .icon.is-large { - height: 1.5em; - width: 1.5em; - } - - .button .icon:first-child:not(:last-child) { - margin-left: calc(-0.5em - 1px); - margin-right: 0.25em; - } - - .button .icon:last-child:not(:first-child) { - margin-left: 0.25em; - margin-right: calc(-0.5em - 1px); - } - - .button .icon:first-child:last-child { - margin-left: calc(-0.5em - 1px); - margin-right: calc(-0.5em - 1px); - } - - .button:hover, .button.is-hovered { - border-color: #b5b5b5; - color: #A00975; - } - - .button:focus, .button.is-focused { - border-color: #3273dc; - color: #363636; - } - - .button:focus:not(:active), .button.is-focused:not(:active) { - -webkit-box-shadow: 0 0 0 0.125em rgba(55, 139, 186, 0.25); - box-shadow: 0 0 0 0.125em rgba(55, 139, 186, 0.25); - } - - .button:active, .button.is-active, .button.active { - border-color: #4a4a4a; - color: #363636; - } - - .button.is-text { - background-color: transparent; - border-color: transparent; - color: #4a4a4a; - text-decoration: underline; - } - - .button.is-text:hover, .button.is-text.is-hovered, .button.is-text:focus, .button.is-text.is-focused { - background-color: whitesmoke; - color: #363636; - } - - .button.is-text:active, .button.is-text.is-active, .is-text.active { - background-color: #e8e8e8; - color: #363636; - } - - .button.is-text[disabled], fieldset[disabled] .button.is-text { - background-color: transparent; - border-color: transparent; - -webkit-box-shadow: none; - box-shadow: none; - } - - .button.is-ghost { - background: none; - border-color: transparent; - color: #378BBA; - text-decoration: none; - } - - .button.is-ghost:hover, .button.is-ghost.is-hovered { - color: #378BBA; - text-decoration: underline; - } - - .button.is-white { - background-color: white; - border-color: transparent; - color: #0a0a0a; - } - - .button.is-white:hover, .button.is-white.is-hovered { - background-color: #f9f9f9; - border-color: transparent; - color: #0a0a0a; - } - - .button.is-white:focus, .button.is-white.is-focused { - border-color: transparent; - color: #0a0a0a; - } - - .button.is-white:focus:not(:active), .button.is-white.is-focused:not(:active) { - -webkit-box-shadow: 0 0 0 0.125em rgba(255, 255, 255, 0.25); - box-shadow: 0 0 0 0.125em rgba(255, 255, 255, 0.25); - } - - .button.is-white:active, .button.is-white.is-active, .is-white.active { - background-color: #f2f2f2; - border-color: transparent; - color: #0a0a0a; - } - - .button.is-white[disabled], fieldset[disabled] .button.is-white { - background-color: white; - border-color: transparent; - -webkit-box-shadow: none; - box-shadow: none; - } - - .button.is-white.is-inverted { - background-color: #0a0a0a; - color: white; - } - - .button.is-white.is-inverted:hover, .button.is-white.is-inverted.is-hovered { - background-color: black; - } - - .button.is-white.is-inverted[disabled], fieldset[disabled] .button.is-white.is-inverted { - background-color: #0a0a0a; - border-color: transparent; - -webkit-box-shadow: none; - box-shadow: none; - color: white; - } - - .button.is-white.is-loading::after { - border-color: transparent transparent #0a0a0a #0a0a0a !important; - } - - .button.is-white.is-outlined { - background-color: transparent; - border-color: white; - color: white; - } - - .button.is-white.is-outlined:hover, .button.is-white.is-outlined.is-hovered, .button.is-white.is-outlined:focus, .button.is-white.is-outlined.is-focused { - background-color: white; - border-color: white; - color: #0a0a0a; - } - - .button.is-white.is-outlined.is-loading::after { - border-color: transparent transparent white white !important; - } - - .button.is-white.is-outlined.is-loading:hover::after, .button.is-white.is-outlined.is-loading.is-hovered::after, .button.is-white.is-outlined.is-loading:focus::after, .button.is-white.is-outlined.is-loading.is-focused::after { - border-color: transparent transparent #0a0a0a #0a0a0a !important; - } - - .button.is-white.is-outlined[disabled], fieldset[disabled] .button.is-white.is-outlined { - background-color: transparent; - border-color: white; - -webkit-box-shadow: none; - box-shadow: none; - color: white; - } - - .button.is-white.is-inverted.is-outlined { - background-color: transparent; - border-color: #0a0a0a; - color: #0a0a0a; - } - - .button.is-white.is-inverted.is-outlined:hover, .button.is-white.is-inverted.is-outlined.is-hovered, .button.is-white.is-inverted.is-outlined:focus, .button.is-white.is-inverted.is-outlined.is-focused { - background-color: #0a0a0a; - color: white; - } - - .button.is-white.is-inverted.is-outlined.is-loading:hover::after, .button.is-white.is-inverted.is-outlined.is-loading.is-hovered::after, .button.is-white.is-inverted.is-outlined.is-loading:focus::after, .button.is-white.is-inverted.is-outlined.is-loading.is-focused::after { - border-color: transparent transparent white white !important; - } - - .button.is-white.is-inverted.is-outlined[disabled], fieldset[disabled] .button.is-white.is-inverted.is-outlined { - background-color: transparent; - border-color: #0a0a0a; - -webkit-box-shadow: none; - box-shadow: none; - color: #0a0a0a; - } - - .button.is-black { - background-color: #0a0a0a; - border-color: transparent; - color: white; - } - - .button.is-black:hover, .button.is-black.is-hovered { - background-color: #040404; - border-color: transparent; - color: white; - } - - .button.is-black:focus, .button.is-black.is-focused { - border-color: transparent; - color: white; - } - - .button.is-black:focus:not(:active), .button.is-black.is-focused:not(:active) { - -webkit-box-shadow: 0 0 0 0.125em rgba(10, 10, 10, 0.25); - box-shadow: 0 0 0 0.125em rgba(10, 10, 10, 0.25); - } - - .button.is-black:active, .button.is-black.is-active, .is-black.active { - background-color: black; - border-color: transparent; - color: white; - } - - .button.is-black[disabled], fieldset[disabled] .button.is-black { - background-color: #0a0a0a; - border-color: transparent; - -webkit-box-shadow: none; - box-shadow: none; - } - - .button.is-black.is-inverted { - background-color: white; - color: #0a0a0a; - } - - .button.is-black.is-inverted:hover, .button.is-black.is-inverted.is-hovered { - background-color: #f2f2f2; - } - - .button.is-black.is-inverted[disabled], fieldset[disabled] .button.is-black.is-inverted { - background-color: white; - border-color: transparent; - -webkit-box-shadow: none; - box-shadow: none; - color: #0a0a0a; - } - - .button.is-black.is-loading::after { - border-color: transparent transparent white white !important; - } - - .button.is-black.is-outlined { - background-color: transparent; - border-color: #0a0a0a; - color: #0a0a0a; - } - - .button.is-black.is-outlined:hover, .button.is-black.is-outlined.is-hovered, .button.is-black.is-outlined:focus, .button.is-black.is-outlined.is-focused { - background-color: #0a0a0a; - border-color: #0a0a0a; - color: white; - } - - .button.is-black.is-outlined.is-loading::after { - border-color: transparent transparent #0a0a0a #0a0a0a !important; - } - - .button.is-black.is-outlined.is-loading:hover::after, .button.is-black.is-outlined.is-loading.is-hovered::after, .button.is-black.is-outlined.is-loading:focus::after, .button.is-black.is-outlined.is-loading.is-focused::after { - border-color: transparent transparent white white !important; - } - - .button.is-black.is-outlined[disabled], fieldset[disabled] .button.is-black.is-outlined { - background-color: transparent; - border-color: #0a0a0a; - -webkit-box-shadow: none; - box-shadow: none; - color: #0a0a0a; - } - - .button.is-black.is-inverted.is-outlined { - background-color: transparent; - border-color: white; - color: white; - } - - .button.is-black.is-inverted.is-outlined:hover, .button.is-black.is-inverted.is-outlined.is-hovered, .button.is-black.is-inverted.is-outlined:focus, .button.is-black.is-inverted.is-outlined.is-focused { - background-color: white; - color: #0a0a0a; - } - - .button.is-black.is-inverted.is-outlined.is-loading:hover::after, .button.is-black.is-inverted.is-outlined.is-loading.is-hovered::after, .button.is-black.is-inverted.is-outlined.is-loading:focus::after, .button.is-black.is-inverted.is-outlined.is-loading.is-focused::after { - border-color: transparent transparent #0a0a0a #0a0a0a !important; - } - - .button.is-black.is-inverted.is-outlined[disabled], fieldset[disabled] .button.is-black.is-inverted.is-outlined { - background-color: transparent; - border-color: white; - -webkit-box-shadow: none; - box-shadow: none; - color: white; - } - - .button.is-light { - background-color: whitesmoke; - border-color: transparent; - color: rgba(0, 0, 0, 0.7); - } - - .button.is-light:hover, .button.is-light.is-hovered { - background-color: #eeeeee; - border-color: transparent; - color: rgba(0, 0, 0, 0.7); - } - - .button.is-light:focus, .button.is-light.is-focused { - border-color: transparent; - color: rgba(0, 0, 0, 0.7); - } - - .button.is-light:focus:not(:active), .button.is-light.is-focused:not(:active) { - -webkit-box-shadow: 0 0 0 0.125em rgba(245, 245, 245, 0.25); - box-shadow: 0 0 0 0.125em rgba(245, 245, 245, 0.25); - } - - .button.is-light:active, .button.is-light.is-active, .is-light.active { - background-color: #e8e8e8; - border-color: transparent; - color: rgba(0, 0, 0, 0.7); - } - - .button.is-light[disabled], fieldset[disabled] .button.is-light { - background-color: whitesmoke; - border-color: transparent; - -webkit-box-shadow: none; - box-shadow: none; - } - - .button.is-light.is-inverted { - background-color: rgba(0, 0, 0, 0.7); - color: whitesmoke; - } - - .button.is-light.is-inverted:hover, .button.is-light.is-inverted.is-hovered { - background-color: rgba(0, 0, 0, 0.7); - } - - .button.is-light.is-inverted[disabled], fieldset[disabled] .button.is-light.is-inverted { - background-color: rgba(0, 0, 0, 0.7); - border-color: transparent; - -webkit-box-shadow: none; - box-shadow: none; - color: whitesmoke; - } - - .button.is-light.is-loading::after { - border-color: transparent transparent rgba(0, 0, 0, 0.7) rgba(0, 0, 0, 0.7) !important; - } - - .button.is-light.is-outlined { - background-color: transparent; - border-color: whitesmoke; - color: whitesmoke; - } - - .button.is-light.is-outlined:hover, .button.is-light.is-outlined.is-hovered, .button.is-light.is-outlined:focus, .button.is-light.is-outlined.is-focused { - background-color: whitesmoke; - border-color: whitesmoke; - color: rgba(0, 0, 0, 0.7); - } - - .button.is-light.is-outlined.is-loading::after { - border-color: transparent transparent whitesmoke whitesmoke !important; - } - - .button.is-light.is-outlined.is-loading:hover::after, .button.is-light.is-outlined.is-loading.is-hovered::after, .button.is-light.is-outlined.is-loading:focus::after, .button.is-light.is-outlined.is-loading.is-focused::after { - border-color: transparent transparent rgba(0, 0, 0, 0.7) rgba(0, 0, 0, 0.7) !important; - } - - .button.is-light.is-outlined[disabled], fieldset[disabled] .button.is-light.is-outlined { - background-color: transparent; - border-color: whitesmoke; - -webkit-box-shadow: none; - box-shadow: none; - color: whitesmoke; - } - - .button.is-light.is-inverted.is-outlined { - background-color: transparent; - border-color: rgba(0, 0, 0, 0.7); - color: rgba(0, 0, 0, 0.7); - } - - .button.is-light.is-inverted.is-outlined:hover, .button.is-light.is-inverted.is-outlined.is-hovered, .button.is-light.is-inverted.is-outlined:focus, .button.is-light.is-inverted.is-outlined.is-focused { - background-color: rgba(0, 0, 0, 0.7); - color: whitesmoke; - } - - .button.is-light.is-inverted.is-outlined.is-loading:hover::after, .button.is-light.is-inverted.is-outlined.is-loading.is-hovered::after, .button.is-light.is-inverted.is-outlined.is-loading:focus::after, .button.is-light.is-inverted.is-outlined.is-loading.is-focused::after { - border-color: transparent transparent whitesmoke whitesmoke !important; - } - - .button.is-light.is-inverted.is-outlined[disabled], fieldset[disabled] .button.is-light.is-inverted.is-outlined { - background-color: transparent; - border-color: rgba(0, 0, 0, 0.7); - -webkit-box-shadow: none; - box-shadow: none; - color: rgba(0, 0, 0, 0.7); - } - - .button.is-dark { - background-color: #200117; - border-color: transparent; - color: #fff; - } - - .button.is-dark:hover, .button.is-dark.is-hovered { - background-color: #14010e; - border-color: transparent; - color: #fff; - } - - .button.is-dark:focus, .button.is-dark.is-focused { - border-color: transparent; - color: #fff; - } - - .button.is-dark:focus:not(:active), .button.is-dark.is-focused:not(:active) { - -webkit-box-shadow: 0 0 0 0.125em rgba(32, 1, 23, 0.25); - box-shadow: 0 0 0 0.125em rgba(32, 1, 23, 0.25); - } - - .button.is-dark:active, .button.is-dark.is-active, .is-dark.active { - background-color: #070005; - border-color: transparent; - color: #fff; - } - - .button.is-dark[disabled], fieldset[disabled] .button.is-dark { - background-color: #200117; - border-color: transparent; - -webkit-box-shadow: none; - box-shadow: none; - } - - .button.is-dark.is-inverted { - background-color: #fff; - color: #200117; - } - - .button.is-dark.is-inverted:hover, .button.is-dark.is-inverted.is-hovered { - background-color: #f2f2f2; - } - - .button.is-dark.is-inverted[disabled], fieldset[disabled] .button.is-dark.is-inverted { - background-color: #fff; - border-color: transparent; - -webkit-box-shadow: none; - box-shadow: none; - color: #200117; - } - - .button.is-dark.is-loading::after { - border-color: transparent transparent #fff #fff !important; - } - - .button.is-dark.is-outlined { - background-color: transparent; - border-color: #200117; - color: #200117; - } - - .button.is-dark.is-outlined:hover, .button.is-dark.is-outlined.is-hovered, .button.is-dark.is-outlined:focus, .button.is-dark.is-outlined.is-focused { - background-color: #200117; - border-color: #200117; - color: #fff; - } - - .button.is-dark.is-outlined.is-loading::after { - border-color: transparent transparent #200117 #200117 !important; - } - - .button.is-dark.is-outlined.is-loading:hover::after, .button.is-dark.is-outlined.is-loading.is-hovered::after, .button.is-dark.is-outlined.is-loading:focus::after, .button.is-dark.is-outlined.is-loading.is-focused::after { - border-color: transparent transparent #fff #fff !important; - } - - .button.is-dark.is-outlined[disabled], fieldset[disabled] .button.is-dark.is-outlined { - background-color: transparent; - border-color: #200117; - -webkit-box-shadow: none; - box-shadow: none; - color: #200117; - } - - .button.is-dark.is-inverted.is-outlined { - background-color: transparent; - border-color: #fff; - color: #fff; - } - - .button.is-dark.is-inverted.is-outlined:hover, .button.is-dark.is-inverted.is-outlined.is-hovered, .button.is-dark.is-inverted.is-outlined:focus, .button.is-dark.is-inverted.is-outlined.is-focused { - background-color: #fff; - color: #200117; - } - - .button.is-dark.is-inverted.is-outlined.is-loading:hover::after, .button.is-dark.is-inverted.is-outlined.is-loading.is-hovered::after, .button.is-dark.is-inverted.is-outlined.is-loading:focus::after, .button.is-dark.is-inverted.is-outlined.is-loading.is-focused::after { - border-color: transparent transparent #200117 #200117 !important; - } - - .button.is-dark.is-inverted.is-outlined[disabled], fieldset[disabled] .button.is-dark.is-inverted.is-outlined { - background-color: transparent; - border-color: #fff; - -webkit-box-shadow: none; - box-shadow: none; - color: #fff; - } - - .button.is-primary { - background-color: #A00975; - border-color: transparent; - color: #fff; - } - - .button.is-primary:hover, .button.is-primary.is-hovered { - background-color: #94086c; - border-color: transparent; - color: #fff; - } - - .button.is-primary:focus, .button.is-primary.is-focused { - border-color: transparent; - color: #fff; - } - - .button.is-primary:focus:not(:active), .button.is-primary.is-focused:not(:active) { - -webkit-box-shadow: 0 0 0 0.125em rgba(160, 9, 117, 0.25); - box-shadow: 0 0 0 0.125em rgba(160, 9, 117, 0.25); - } - - .button.is-primary:active, .button.is-primary.is-active, .is-primary.active { - background-color: #880863; - border-color: transparent; - color: #fff; - } - - .button.is-primary[disabled], fieldset[disabled] .button.is-primary { - background-color: #A00975; - border-color: transparent; - -webkit-box-shadow: none; - box-shadow: none; - } - - .button.is-primary.is-inverted { - background-color: #fff; - color: #A00975; - } - - .button.is-primary.is-inverted:hover, .button.is-primary.is-inverted.is-hovered { - background-color: #f2f2f2; - } - - .button.is-primary.is-inverted[disabled], fieldset[disabled] .button.is-primary.is-inverted { - background-color: #fff; - border-color: transparent; - -webkit-box-shadow: none; - box-shadow: none; - color: #A00975; - } - - .button.is-primary.is-loading::after { - border-color: transparent transparent #fff #fff !important; - } - - .button.is-primary.is-outlined { - background-color: transparent; - border-color: #A00975; - color: #A00975; - } - - .button.is-primary.is-outlined:hover, .button.is-primary.is-outlined.is-hovered, .button.is-primary.is-outlined:focus, .button.is-primary.is-outlined.is-focused { - background-color: #A00975; - border-color: #A00975; - color: #fff; - } - - .button.is-primary.is-outlined.is-loading::after { - border-color: transparent transparent #A00975 #A00975 !important; - } - - .button.is-primary.is-outlined.is-loading:hover::after, .button.is-primary.is-outlined.is-loading.is-hovered::after, .button.is-primary.is-outlined.is-loading:focus::after, .button.is-primary.is-outlined.is-loading.is-focused::after { - border-color: transparent transparent #fff #fff !important; - } - - .button.is-primary.is-outlined[disabled], fieldset[disabled] .button.is-primary.is-outlined { - background-color: transparent; - border-color: #A00975; - -webkit-box-shadow: none; - box-shadow: none; - color: #A00975; - } - - .button.is-primary.is-inverted.is-outlined { - background-color: transparent; - border-color: #fff; - color: #fff; - } - - .button.is-primary.is-inverted.is-outlined:hover, .button.is-primary.is-inverted.is-outlined.is-hovered, .button.is-primary.is-inverted.is-outlined:focus, .button.is-primary.is-inverted.is-outlined.is-focused { - background-color: #fff; - color: #A00975; - } - - .button.is-primary.is-inverted.is-outlined.is-loading:hover::after, .button.is-primary.is-inverted.is-outlined.is-loading.is-hovered::after, .button.is-primary.is-inverted.is-outlined.is-loading:focus::after, .button.is-primary.is-inverted.is-outlined.is-loading.is-focused::after { - border-color: transparent transparent #A00975 #A00975 !important; - } - - .button.is-primary.is-inverted.is-outlined[disabled], fieldset[disabled] .button.is-primary.is-inverted.is-outlined { - background-color: transparent; - border-color: #fff; - -webkit-box-shadow: none; - box-shadow: none; - color: #fff; - } - - .button.is-primary.is-light { - background-color: #feecf9; - color: #f212b2; - } - - .button.is-primary.is-light:hover, .button.is-primary.is-light.is-hovered { - background-color: #fde0f5; - border-color: transparent; - color: #f212b2; - } - - .button.is-primary.is-light:active, .button.is-primary.is-light.is-active, .is-light.active { - background-color: #fdd4f1; - border-color: transparent; - color: #f212b2; - } - - .button.is-link { - background-color: #378BBA; - border-color: transparent; - color: #fff; - } - - .button.is-link:hover, .button.is-link.is-hovered { - background-color: #3484b0; - border-color: transparent; - color: #fff; - } - - .button.is-link:focus, .button.is-link.is-focused { - border-color: transparent; - color: #fff; - } - - .button.is-link:focus:not(:active), .button.is-link.is-focused:not(:active) { - -webkit-box-shadow: 0 0 0 0.125em rgba(55, 139, 186, 0.25); - box-shadow: 0 0 0 0.125em rgba(55, 139, 186, 0.25); - } - - .button.is-link:active, .button.is-link.is-active, .is-link.active { - background-color: #317ca6; - border-color: transparent; - color: #fff; - } - - .button.is-link[disabled], fieldset[disabled] .button.is-link { - background-color: #378BBA; - border-color: transparent; - -webkit-box-shadow: none; - box-shadow: none; - } - - .button.is-link.is-inverted { - background-color: #fff; - color: #378BBA; - } - - .button.is-link.is-inverted:hover, .button.is-link.is-inverted.is-hovered { - background-color: #f2f2f2; - } - - .button.is-link.is-inverted[disabled], fieldset[disabled] .button.is-link.is-inverted { - background-color: #fff; - border-color: transparent; - -webkit-box-shadow: none; - box-shadow: none; - color: #378BBA; - } - - .button.is-link.is-loading::after { - border-color: transparent transparent #fff #fff !important; - } - - .button.is-link.is-outlined { - background-color: transparent; - border-color: #378BBA; - color: #378BBA; - } - - .button.is-link.is-outlined:hover, .button.is-link.is-outlined.is-hovered, .button.is-link.is-outlined:focus, .button.is-link.is-outlined.is-focused { - background-color: #378BBA; - border-color: #378BBA; - color: #fff; - } - - .button.is-link.is-outlined.is-loading::after { - border-color: transparent transparent #378BBA #378BBA !important; - } - - .button.is-link.is-outlined.is-loading:hover::after, .button.is-link.is-outlined.is-loading.is-hovered::after, .button.is-link.is-outlined.is-loading:focus::after, .button.is-link.is-outlined.is-loading.is-focused::after { - border-color: transparent transparent #fff #fff !important; - } - - .button.is-link.is-outlined[disabled], fieldset[disabled] .button.is-link.is-outlined { - background-color: transparent; - border-color: #378BBA; - -webkit-box-shadow: none; - box-shadow: none; - color: #378BBA; - } - - .button.is-link.is-inverted.is-outlined { - background-color: transparent; - border-color: #fff; - color: #fff; - } - - .button.is-link.is-inverted.is-outlined:hover, .button.is-link.is-inverted.is-outlined.is-hovered, .button.is-link.is-inverted.is-outlined:focus, .button.is-link.is-inverted.is-outlined.is-focused { - background-color: #fff; - color: #378BBA; - } - - .button.is-link.is-inverted.is-outlined.is-loading:hover::after, .button.is-link.is-inverted.is-outlined.is-loading.is-hovered::after, .button.is-link.is-inverted.is-outlined.is-loading:focus::after, .button.is-link.is-inverted.is-outlined.is-loading.is-focused::after { - border-color: transparent transparent #378BBA #378BBA !important; - } - - .button.is-link.is-inverted.is-outlined[disabled], fieldset[disabled] .button.is-link.is-inverted.is-outlined { - background-color: transparent; - border-color: #fff; - -webkit-box-shadow: none; - box-shadow: none; - color: #fff; - } - - .button.is-link.is-light { - background-color: #eff6fa; - color: #317ca5; - } - - .button.is-link.is-light:hover, .button.is-link.is-light.is-hovered { - background-color: #e5f1f7; - border-color: transparent; - color: #317ca5; - } - - .button.is-link.is-light:active, .button.is-link.is-light.is-active, .is-light.active { - background-color: #dcecf5; - border-color: transparent; - color: #317ca5; - } - - .button.is-info { - background-color: #3298dc; - border-color: transparent; - color: #fff; - } - - .button.is-info:hover, .button.is-info.is-hovered { - background-color: #2793da; - border-color: transparent; - color: #fff; - } - - .button.is-info:focus, .button.is-info.is-focused { - border-color: transparent; - color: #fff; - } - - .button.is-info:focus:not(:active), .button.is-info.is-focused:not(:active) { - -webkit-box-shadow: 0 0 0 0.125em rgba(50, 152, 220, 0.25); - box-shadow: 0 0 0 0.125em rgba(50, 152, 220, 0.25); - } - - .button.is-info:active, .button.is-info.is-active, .is-info.active { - background-color: #238cd1; - border-color: transparent; - color: #fff; - } - - .button.is-info[disabled], fieldset[disabled] .button.is-info { - background-color: #3298dc; - border-color: transparent; - -webkit-box-shadow: none; - box-shadow: none; - } - - .button.is-info.is-inverted { - background-color: #fff; - color: #3298dc; - } - - .button.is-info.is-inverted:hover, .button.is-info.is-inverted.is-hovered { - background-color: #f2f2f2; - } - - .button.is-info.is-inverted[disabled], fieldset[disabled] .button.is-info.is-inverted { - background-color: #fff; - border-color: transparent; - -webkit-box-shadow: none; - box-shadow: none; - color: #3298dc; - } - - .button.is-info.is-loading::after { - border-color: transparent transparent #fff #fff !important; - } - - .button.is-info.is-outlined { - background-color: transparent; - border-color: #3298dc; - color: #3298dc; - } - - .button.is-info.is-outlined:hover, .button.is-info.is-outlined.is-hovered, .button.is-info.is-outlined:focus, .button.is-info.is-outlined.is-focused { - background-color: #3298dc; - border-color: #3298dc; - color: #fff; - } - - .button.is-info.is-outlined.is-loading::after { - border-color: transparent transparent #3298dc #3298dc !important; - } - - .button.is-info.is-outlined.is-loading:hover::after, .button.is-info.is-outlined.is-loading.is-hovered::after, .button.is-info.is-outlined.is-loading:focus::after, .button.is-info.is-outlined.is-loading.is-focused::after { - border-color: transparent transparent #fff #fff !important; - } - - .button.is-info.is-outlined[disabled], fieldset[disabled] .button.is-info.is-outlined { - background-color: transparent; - border-color: #3298dc; - -webkit-box-shadow: none; - box-shadow: none; - color: #3298dc; - } - - .button.is-info.is-inverted.is-outlined { - background-color: transparent; - border-color: #fff; - color: #fff; - } - - .button.is-info.is-inverted.is-outlined:hover, .button.is-info.is-inverted.is-outlined.is-hovered, .button.is-info.is-inverted.is-outlined:focus, .button.is-info.is-inverted.is-outlined.is-focused { - background-color: #fff; - color: #3298dc; - } - - .button.is-info.is-inverted.is-outlined.is-loading:hover::after, .button.is-info.is-inverted.is-outlined.is-loading.is-hovered::after, .button.is-info.is-inverted.is-outlined.is-loading:focus::after, .button.is-info.is-inverted.is-outlined.is-loading.is-focused::after { - border-color: transparent transparent #3298dc #3298dc !important; - } - - .button.is-info.is-inverted.is-outlined[disabled], fieldset[disabled] .button.is-info.is-inverted.is-outlined { - background-color: transparent; - border-color: #fff; - -webkit-box-shadow: none; - box-shadow: none; - color: #fff; - } - - .button.is-info.is-light { - background-color: #eef6fc; - color: #1d72aa; - } - - .button.is-info.is-light:hover, .button.is-info.is-light.is-hovered { - background-color: #e3f1fa; - border-color: transparent; - color: #1d72aa; - } - - .button.is-info.is-light:active, .button.is-info.is-light.is-active, .is-light.active { - background-color: #d8ebf8; - border-color: transparent; - color: #1d72aa; - } - - .button.is-success { - background-color: #48c774; - border-color: transparent; - color: #fff; - } - - .button.is-success:hover, .button.is-success.is-hovered { - background-color: #3ec46d; - border-color: transparent; - color: #fff; - } - - .button.is-success:focus, .button.is-success.is-focused { - border-color: transparent; - color: #fff; - } - - .button.is-success:focus:not(:active), .button.is-success.is-focused:not(:active) { - -webkit-box-shadow: 0 0 0 0.125em rgba(72, 199, 116, 0.25); - box-shadow: 0 0 0 0.125em rgba(72, 199, 116, 0.25); - } - - .button.is-success:active, .button.is-success.is-active, .is-success.active { - background-color: #3abb67; - border-color: transparent; - color: #fff; - } - - .button.is-success[disabled], fieldset[disabled] .button.is-success { - background-color: #48c774; - border-color: transparent; - -webkit-box-shadow: none; - box-shadow: none; - } - - .button.is-success.is-inverted { - background-color: #fff; - color: #48c774; - } - - .button.is-success.is-inverted:hover, .button.is-success.is-inverted.is-hovered { - background-color: #f2f2f2; - } - - .button.is-success.is-inverted[disabled], fieldset[disabled] .button.is-success.is-inverted { - background-color: #fff; - border-color: transparent; - -webkit-box-shadow: none; - box-shadow: none; - color: #48c774; - } - - .button.is-success.is-loading::after { - border-color: transparent transparent #fff #fff !important; - } - - .button.is-success.is-outlined { - background-color: transparent; - border-color: #48c774; - color: #48c774; - } - - .button.is-success.is-outlined:hover, .button.is-success.is-outlined.is-hovered, .button.is-success.is-outlined:focus, .button.is-success.is-outlined.is-focused { - background-color: #48c774; - border-color: #48c774; - color: #fff; - } - - .button.is-success.is-outlined.is-loading::after { - border-color: transparent transparent #48c774 #48c774 !important; - } - - .button.is-success.is-outlined.is-loading:hover::after, .button.is-success.is-outlined.is-loading.is-hovered::after, .button.is-success.is-outlined.is-loading:focus::after, .button.is-success.is-outlined.is-loading.is-focused::after { - border-color: transparent transparent #fff #fff !important; - } - - .button.is-success.is-outlined[disabled], fieldset[disabled] .button.is-success.is-outlined { - background-color: transparent; - border-color: #48c774; - -webkit-box-shadow: none; - box-shadow: none; - color: #48c774; - } - - .button.is-success.is-inverted.is-outlined { - background-color: transparent; - border-color: #fff; - color: #fff; - } - - .button.is-success.is-inverted.is-outlined:hover, .button.is-success.is-inverted.is-outlined.is-hovered, .button.is-success.is-inverted.is-outlined:focus, .button.is-success.is-inverted.is-outlined.is-focused { - background-color: #fff; - color: #48c774; - } - - .button.is-success.is-inverted.is-outlined.is-loading:hover::after, .button.is-success.is-inverted.is-outlined.is-loading.is-hovered::after, .button.is-success.is-inverted.is-outlined.is-loading:focus::after, .button.is-success.is-inverted.is-outlined.is-loading.is-focused::after { - border-color: transparent transparent #48c774 #48c774 !important; - } - - .button.is-success.is-inverted.is-outlined[disabled], fieldset[disabled] .button.is-success.is-inverted.is-outlined { - background-color: transparent; - border-color: #fff; - -webkit-box-shadow: none; - box-shadow: none; - color: #fff; - } - - .button.is-success.is-light { - background-color: #effaf3; - color: #257942; - } - - .button.is-success.is-light:hover, .button.is-success.is-light.is-hovered { - background-color: #e6f7ec; - border-color: transparent; - color: #257942; - } - - .button.is-success.is-light:active, .button.is-success.is-light.is-active, .is-light.active { - background-color: #dcf4e4; - border-color: transparent; - color: #257942; - } - - .button.is-warning { - background-color: #ffdd57; - border-color: transparent; - color: rgba(0, 0, 0, 0.7); - } - - .button.is-warning:hover, .button.is-warning.is-hovered { - background-color: #ffdb4a; - border-color: transparent; - color: rgba(0, 0, 0, 0.7); - } - - .button.is-warning:focus, .button.is-warning.is-focused { - border-color: transparent; - color: rgba(0, 0, 0, 0.7); - } - - .button.is-warning:focus:not(:active), .button.is-warning.is-focused:not(:active) { - -webkit-box-shadow: 0 0 0 0.125em rgba(255, 221, 87, 0.25); - box-shadow: 0 0 0 0.125em rgba(255, 221, 87, 0.25); - } - - .button.is-warning:active, .button.is-warning.is-active, .is-warning.active { - background-color: #ffd83d; - border-color: transparent; - color: rgba(0, 0, 0, 0.7); - } - - .button.is-warning[disabled], fieldset[disabled] .button.is-warning { - background-color: #ffdd57; - border-color: transparent; - -webkit-box-shadow: none; - box-shadow: none; - } - - .button.is-warning.is-inverted { - background-color: rgba(0, 0, 0, 0.7); - color: #ffdd57; - } - - .button.is-warning.is-inverted:hover, .button.is-warning.is-inverted.is-hovered { - background-color: rgba(0, 0, 0, 0.7); - } - - .button.is-warning.is-inverted[disabled], fieldset[disabled] .button.is-warning.is-inverted { - background-color: rgba(0, 0, 0, 0.7); - border-color: transparent; - -webkit-box-shadow: none; - box-shadow: none; - color: #ffdd57; - } - - .button.is-warning.is-loading::after { - border-color: transparent transparent rgba(0, 0, 0, 0.7) rgba(0, 0, 0, 0.7) !important; - } - - .button.is-warning.is-outlined { - background-color: transparent; - border-color: #ffdd57; - color: #ffdd57; - } - - .button.is-warning.is-outlined:hover, .button.is-warning.is-outlined.is-hovered, .button.is-warning.is-outlined:focus, .button.is-warning.is-outlined.is-focused { - background-color: #ffdd57; - border-color: #ffdd57; - color: rgba(0, 0, 0, 0.7); - } - - .button.is-warning.is-outlined.is-loading::after { - border-color: transparent transparent #ffdd57 #ffdd57 !important; - } - - .button.is-warning.is-outlined.is-loading:hover::after, .button.is-warning.is-outlined.is-loading.is-hovered::after, .button.is-warning.is-outlined.is-loading:focus::after, .button.is-warning.is-outlined.is-loading.is-focused::after { - border-color: transparent transparent rgba(0, 0, 0, 0.7) rgba(0, 0, 0, 0.7) !important; - } - - .button.is-warning.is-outlined[disabled], fieldset[disabled] .button.is-warning.is-outlined { - background-color: transparent; - border-color: #ffdd57; - -webkit-box-shadow: none; - box-shadow: none; - color: #ffdd57; - } - - .button.is-warning.is-inverted.is-outlined { - background-color: transparent; - border-color: rgba(0, 0, 0, 0.7); - color: rgba(0, 0, 0, 0.7); - } - - .button.is-warning.is-inverted.is-outlined:hover, .button.is-warning.is-inverted.is-outlined.is-hovered, .button.is-warning.is-inverted.is-outlined:focus, .button.is-warning.is-inverted.is-outlined.is-focused { - background-color: rgba(0, 0, 0, 0.7); - color: #ffdd57; - } - - .button.is-warning.is-inverted.is-outlined.is-loading:hover::after, .button.is-warning.is-inverted.is-outlined.is-loading.is-hovered::after, .button.is-warning.is-inverted.is-outlined.is-loading:focus::after, .button.is-warning.is-inverted.is-outlined.is-loading.is-focused::after { - border-color: transparent transparent #ffdd57 #ffdd57 !important; - } - - .button.is-warning.is-inverted.is-outlined[disabled], fieldset[disabled] .button.is-warning.is-inverted.is-outlined { - background-color: transparent; - border-color: rgba(0, 0, 0, 0.7); - -webkit-box-shadow: none; - box-shadow: none; - color: rgba(0, 0, 0, 0.7); - } - - .button.is-warning.is-light { - background-color: #fffbeb; - color: #947600; - } - - .button.is-warning.is-light:hover, .button.is-warning.is-light.is-hovered { - background-color: #fff8de; - border-color: transparent; - color: #947600; - } - - .button.is-warning.is-light:active, .button.is-warning.is-light.is-active, .is-light.active { - background-color: #fff6d1; - border-color: transparent; - color: #947600; - } - - .button.is-danger { - background-color: #f14668; - border-color: transparent; - color: #fff; - } - - .button.is-danger:hover, .button.is-danger.is-hovered { - background-color: #f03a5f; - border-color: transparent; - color: #fff; - } - - .button.is-danger:focus, .button.is-danger.is-focused { - border-color: transparent; - color: #fff; - } - - .button.is-danger:focus:not(:active), .button.is-danger.is-focused:not(:active) { - -webkit-box-shadow: 0 0 0 0.125em rgba(241, 70, 104, 0.25); - box-shadow: 0 0 0 0.125em rgba(241, 70, 104, 0.25); - } - - .button.is-danger:active, .button.is-danger.is-active, .is-danger.active { - background-color: #ef2e55; - border-color: transparent; - color: #fff; - } - - .button.is-danger[disabled], fieldset[disabled] .button.is-danger { - background-color: #f14668; - border-color: transparent; - -webkit-box-shadow: none; - box-shadow: none; - } - - .button.is-danger.is-inverted { - background-color: #fff; - color: #f14668; - } - - .button.is-danger.is-inverted:hover, .button.is-danger.is-inverted.is-hovered { - background-color: #f2f2f2; - } - - .button.is-danger.is-inverted[disabled], fieldset[disabled] .button.is-danger.is-inverted { - background-color: #fff; - border-color: transparent; - -webkit-box-shadow: none; - box-shadow: none; - color: #f14668; - } - - .button.is-danger.is-loading::after { - border-color: transparent transparent #fff #fff !important; - } - - .button.is-danger.is-outlined { - background-color: transparent; - border-color: #f14668; - color: #f14668; - } - - .button.is-danger.is-outlined:hover, .button.is-danger.is-outlined.is-hovered, .button.is-danger.is-outlined:focus, .button.is-danger.is-outlined.is-focused { - background-color: #f14668; - border-color: #f14668; - color: #fff; - } - - .button.is-danger.is-outlined.is-loading::after { - border-color: transparent transparent #f14668 #f14668 !important; - } - - .button.is-danger.is-outlined.is-loading:hover::after, .button.is-danger.is-outlined.is-loading.is-hovered::after, .button.is-danger.is-outlined.is-loading:focus::after, .button.is-danger.is-outlined.is-loading.is-focused::after { - border-color: transparent transparent #fff #fff !important; - } - - .button.is-danger.is-outlined[disabled], fieldset[disabled] .button.is-danger.is-outlined { - background-color: transparent; - border-color: #f14668; - -webkit-box-shadow: none; - box-shadow: none; - color: #f14668; - } - - .button.is-danger.is-inverted.is-outlined { - background-color: transparent; - border-color: #fff; - color: #fff; - } - - .button.is-danger.is-inverted.is-outlined:hover, .button.is-danger.is-inverted.is-outlined.is-hovered, .button.is-danger.is-inverted.is-outlined:focus, .button.is-danger.is-inverted.is-outlined.is-focused { - background-color: #fff; - color: #f14668; - } - - .button.is-danger.is-inverted.is-outlined.is-loading:hover::after, .button.is-danger.is-inverted.is-outlined.is-loading.is-hovered::after, .button.is-danger.is-inverted.is-outlined.is-loading:focus::after, .button.is-danger.is-inverted.is-outlined.is-loading.is-focused::after { - border-color: transparent transparent #f14668 #f14668 !important; - } - - .button.is-danger.is-inverted.is-outlined[disabled], fieldset[disabled] .button.is-danger.is-inverted.is-outlined { - background-color: transparent; - border-color: #fff; - -webkit-box-shadow: none; - box-shadow: none; - color: #fff; - } - - .button.is-danger.is-light { - background-color: #feecf0; - color: #cc0f35; - } - - .button.is-danger.is-light:hover, .button.is-danger.is-light.is-hovered { - background-color: #fde0e6; - border-color: transparent; - color: #cc0f35; - } - - .button.is-danger.is-light:active, .button.is-danger.is-light.is-active, .is-light.active { - background-color: #fcd4dc; - border-color: transparent; - color: #cc0f35; - } - - .button.is-small { - font-size: 0.75rem; - } - - .button.is-small:not(.is-rounded) { - border-radius: 2px; - } - - .button.is-normal { - font-size: 1rem; - } - - .button.is-medium { - font-size: 1.25rem; - } - - .button.is-large { - font-size: 1.5rem; - } - - .button[disabled], fieldset[disabled] .button { - background-color: white; - border-color: #dbdbdb; - -webkit-box-shadow: none; - box-shadow: none; - opacity: 0.5; - } - - .button.is-fullwidth { - display: -webkit-box; - display: -ms-flexbox; - display: flex; - width: 100%; - } - - .button.is-loading { - color: transparent !important; - pointer-events: none; - } - - .button.is-loading::after { - position: absolute; - left: calc(50% - (1em / 2)); - top: calc(50% - (1em / 2)); - position: absolute !important; - } - - .button.is-static { - background-color: whitesmoke; - border-color: #dbdbdb; - color: #7a7a7a; - -webkit-box-shadow: none; - box-shadow: none; - pointer-events: none; - } - - .button.is-rounded { - border-radius: 290486px; - padding-left: calc(1em + 0.25em); - padding-right: calc(1em + 0.25em); - } - -.buttons { - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - display: -webkit-box; - display: -ms-flexbox; - display: flex; - -ms-flex-wrap: wrap; - flex-wrap: wrap; - -webkit-box-pack: start; - -ms-flex-pack: start; - justify-content: flex-start; -} - - .buttons .button { - margin-bottom: 0.5rem; - } - - .buttons .button:not(:last-child):not(.is-fullwidth) { - margin-right: 0.5rem; - } - - .buttons:last-child { - margin-bottom: -0.5rem; - } - - .buttons:not(:last-child) { - margin-bottom: 1rem; - } - - .buttons.are-small .button:not(.is-normal):not(.is-medium):not(.is-large) { - font-size: 0.75rem; - } - - .buttons.are-small .button:not(.is-normal):not(.is-medium):not(.is-large):not(.is-rounded) { - border-radius: 2px; - } - - .buttons.are-medium .button:not(.is-small):not(.is-normal):not(.is-large) { - font-size: 1.25rem; - } - - .buttons.are-large .button:not(.is-small):not(.is-normal):not(.is-medium) { - font-size: 1.5rem; - } - - .buttons.has-addons .button:not(:first-child) { - border-bottom-left-radius: 0; - border-top-left-radius: 0; - } - - .buttons.has-addons .button:not(:last-child) { - border-bottom-right-radius: 0; - border-top-right-radius: 0; - margin-right: -1px; - } - - .buttons.has-addons .button:last-child { - margin-right: 0; - } - - .buttons.has-addons .button:hover, .buttons.has-addons .button.is-hovered { - z-index: 2; - } - - .buttons.has-addons .button:focus, .buttons.has-addons .button.is-focused, .buttons.has-addons .button:active, .buttons.has-addons .button.is-active, .buttons.has-addons .button.active, .buttons.has-addons .button.is-selected { - z-index: 3; - } - - .buttons.has-addons .button:focus:hover, .buttons.has-addons .button.is-focused:hover, .buttons.has-addons .button:active:hover, .buttons.has-addons .button.is-active:hover, .buttons.has-addons .button.active:hover, .buttons.has-addons .button.is-selected:hover { - z-index: 4; - } - - .buttons.has-addons .button.is-expanded { - -webkit-box-flex: 1; - -ms-flex-positive: 1; - flex-grow: 1; - -ms-flex-negative: 1; - flex-shrink: 1; - } - - .buttons.is-centered { - -webkit-box-pack: center; - -ms-flex-pack: center; - justify-content: center; - } - - .buttons.is-centered:not(.has-addons) .button:not(.is-fullwidth) { - margin-left: 0.25rem; - margin-right: 0.25rem; - } - - .buttons.is-right { - -webkit-box-pack: end; - -ms-flex-pack: end; - justify-content: flex-end; - } - - .buttons.is-right:not(.has-addons) .button:not(.is-fullwidth) { - margin-left: 0.25rem; - margin-right: 0.25rem; - } - -.container { - -webkit-box-flex: 1; - -ms-flex-positive: 1; - flex-grow: 1; - margin: 0 auto; - position: relative; - width: auto; -} - - .container.is-fluid { - max-width: none !important; - padding-left: 32px; - padding-right: 32px; - width: 100%; - } - -@media screen and (min-width: 1024px) { - .container { - max-width: 960px; - } -} - -@media screen and (max-width: 1215px) { - .container.is-widescreen:not(.is-max-desktop) { - max-width: 1152px; - } -} - -@media screen and (max-width: 1407px) { - .container.is-fullhd:not(.is-max-desktop):not(.is-max-widescreen) { - max-width: 1344px; - } -} - -@media screen and (min-width: 1216px) { - .container:not(.is-max-desktop) { - max-width: 1152px; - } -} - -@media screen and (min-width: 1408px) { - .container:not(.is-max-desktop):not(.is-max-widescreen) { - max-width: 1344px; - } -} - -.content li + li { - margin-top: 0.25em; -} - -.content p:not(:last-child), -.content dl:not(:last-child), -.content ol:not(:last-child), -.content ul:not(:last-child), -.content blockquote:not(:last-child), -.content pre:not(:last-child), -.content table:not(:last-child) { - margin-bottom: 1em; -} - -.content h1, -.content h2, -.content h3, -.content h4, -.content h5, -.content h6 { - color: #363636; - font-weight: 600; - line-height: 1.125; -} - -.content h1 { - font-size: 2em; - margin-bottom: 0.5em; -} - - .content h1:not(:first-child) { - margin-top: 1em; - } - -.content h2 { - font-size: 1.75em; - margin-bottom: 0.5714em; -} - - .content h2:not(:first-child) { - margin-top: 1.1428em; - } - -.content h3 { - font-size: 1.5em; - margin-bottom: 0.6666em; -} - - .content h3:not(:first-child) { - margin-top: 1.3333em; - } - -.content h4 { - font-size: 1.25em; - margin-bottom: 0.8em; -} - -.content h5 { - font-size: 1.125em; - margin-bottom: 0.8888em; -} - -.content h6 { - font-size: 1em; - margin-bottom: 1em; -} - -.content blockquote { - background-color: whitesmoke; - border-left: 5px solid #dbdbdb; - padding: 1.25em 1.5em; -} - -.content ol { - list-style-position: outside; - margin-left: 2em; - margin-top: 1em; -} - - .content ol:not([type]) { - list-style-type: decimal; - } - - .content ol:not([type]).is-lower-alpha { - list-style-type: lower-alpha; - } - - .content ol:not([type]).is-lower-roman { - list-style-type: lower-roman; - } - - .content ol:not([type]).is-upper-alpha { - list-style-type: upper-alpha; - } - - .content ol:not([type]).is-upper-roman { - list-style-type: upper-roman; - } - -.content ul { - list-style: disc outside; - margin-left: 2em; - margin-top: 1em; -} - - .content ul ul { - list-style-type: circle; - margin-top: 0.5em; - } - - .content ul ul ul { - list-style-type: square; - } - -.content dd { - margin-left: 2em; -} - -.content figure { - margin-left: 2em; - margin-right: 2em; - text-align: center; -} - - .content figure:not(:first-child) { - margin-top: 2em; - } - - .content figure:not(:last-child) { - margin-bottom: 2em; - } - - .content figure img { - display: inline-block; - } - - .content figure figcaption { - font-style: italic; - } - -.content pre { - -webkit-overflow-scrolling: touch; - overflow-x: auto; - padding: 1.25em 1.5em; - white-space: pre; - word-wrap: normal; -} - -.content sup, -.content sub { - font-size: 75%; -} - -.content table { - width: 100%; -} - - .content table td, - .content table th { - border: 1px solid #dbdbdb; - border-width: 0 0 1px; - padding: 0.5em 0.75em; - vertical-align: top; - } - - .content table th { - color: #363636; - } - - .content table th:not([align]) { - text-align: inherit; - } - - .content table thead td, - .content table thead th { - border-width: 0 0 2px; - color: #363636; - } - - .content table tfoot td, - .content table tfoot th { - border-width: 2px 0 0; - color: #363636; - } - - .content table tbody tr:last-child td, - .content table tbody tr:last-child th { - border-bottom-width: 0; - } - -.content .tabs li + li { - margin-top: 0; -} - -.content.is-small { - font-size: 0.75rem; -} - -.content.is-medium { - font-size: 1.25rem; -} - -.content.is-large { - font-size: 1.5rem; -} - -.icon { - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - display: -webkit-inline-box; - display: -ms-inline-flexbox; - display: inline-flex; - -webkit-box-pack: center; - -ms-flex-pack: center; - justify-content: center; - height: 1.5rem; - width: 1.5rem; -} - - .icon.is-small { - height: 1rem; - width: 1rem; - } - - .icon.is-medium { - height: 2rem; - width: 2rem; - } - - .icon.is-large { - height: 3rem; - width: 3rem; - } - -.icon-text { - -webkit-box-align: start; - -ms-flex-align: start; - align-items: flex-start; - color: inherit; - display: -webkit-inline-box; - display: -ms-inline-flexbox; - display: inline-flex; - -ms-flex-wrap: wrap; - flex-wrap: wrap; - line-height: 1.5rem; - vertical-align: top; -} - - .icon-text .icon { - -webkit-box-flex: 0; - -ms-flex-positive: 0; - flex-grow: 0; - -ms-flex-negative: 0; - flex-shrink: 0; - } - - .icon-text .icon:not(:last-child) { - margin-right: 0.25em; - } - - .icon-text .icon:not(:first-child) { - margin-left: 0.25em; - } - -div.icon-text { - display: -webkit-box; - display: -ms-flexbox; - display: flex; -} - -.image { - display: block; - position: relative; -} - - .image img { - display: block; - height: auto; - width: 100%; - } - - .image img.is-rounded { - border-radius: 290486px; - } - - .image.is-fullwidth { - width: 100%; - } - - .image.is-square img, - .image.is-square .has-ratio, .image.is-1by1 img, - .image.is-1by1 .has-ratio, .image.is-5by4 img, - .image.is-5by4 .has-ratio, .image.is-4by3 img, - .image.is-4by3 .has-ratio, .image.is-3by2 img, - .image.is-3by2 .has-ratio, .image.is-5by3 img, - .image.is-5by3 .has-ratio, .image.is-16by9 img, - .image.is-16by9 .has-ratio, .image.is-2by1 img, - .image.is-2by1 .has-ratio, .image.is-3by1 img, - .image.is-3by1 .has-ratio, .image.is-4by5 img, - .image.is-4by5 .has-ratio, .image.is-3by4 img, - .image.is-3by4 .has-ratio, .image.is-2by3 img, - .image.is-2by3 .has-ratio, .image.is-3by5 img, - .image.is-3by5 .has-ratio, .image.is-9by16 img, - .image.is-9by16 .has-ratio, .image.is-1by2 img, - .image.is-1by2 .has-ratio, .image.is-1by3 img, - .image.is-1by3 .has-ratio { - height: 100%; - width: 100%; - } - - .image.is-square, .image.is-1by1 { - padding-top: 100%; - } - - .image.is-5by4 { - padding-top: 80%; - } - - .image.is-4by3 { - padding-top: 75%; - } - - .image.is-3by2 { - padding-top: 66.6666%; - } - - .image.is-5by3 { - padding-top: 60%; - } - - .image.is-16by9 { - padding-top: 56.25%; - } - - .image.is-2by1 { - padding-top: 50%; - } - - .image.is-3by1 { - padding-top: 33.3333%; - } - - .image.is-4by5 { - padding-top: 125%; - } - - .image.is-3by4 { - padding-top: 133.3333%; - } - - .image.is-2by3 { - padding-top: 150%; - } - - .image.is-3by5 { - padding-top: 166.6666%; - } - - .image.is-9by16 { - padding-top: 177.7777%; - } - - .image.is-1by2 { - padding-top: 200%; - } - - .image.is-1by3 { - padding-top: 300%; - } - - .image.is-16x16 { - height: 16px; - width: 16px; - } - - .image.is-24x24 { - height: 24px; - width: 24px; - } - - .image.is-32x32 { - height: 32px; - width: 32px; - } - - .image.is-48x48 { - height: 48px; - width: 48px; - } - - .image.is-64x64 { - height: 64px; - width: 64px; - } - - .image.is-96x96 { - height: 96px; - width: 96px; - } - - .image.is-128x128 { - height: 128px; - width: 128px; - } - -.notification { - background-color: whitesmoke; - border-radius: 4px; - position: relative; - padding: 1.25rem 2.5rem 1.25rem 1.5rem; -} - - .notification a:not(.button):not(.dropdown-item) { - color: currentColor; - text-decoration: underline; - } - - .notification strong { - color: currentColor; - } - - .notification code, - .notification pre { - background: white; - } - - .notification pre code { - background: transparent; - } - - .notification > .delete { - right: 0.5rem; - position: absolute; - top: 0.5rem; - } - - .notification .title, - .notification .subtitle, - .notification .content { - color: currentColor; - } - - .notification.is-white { - background-color: white; - color: #0a0a0a; - } - - .notification.is-black { - background-color: #0a0a0a; - color: white; - } - - .notification.is-light { - background-color: whitesmoke; - color: rgba(0, 0, 0, 0.7); - } - - .notification.is-dark { - background-color: #200117; - color: #fff; - } - - .notification.is-primary { - background-color: #A00975; - color: #fff; - } - - .notification.is-primary.is-light { - background-color: #feecf9; - color: #f212b2; - } - - .notification.is-link { - background-color: #378BBA; - color: #fff; - } - - .notification.is-link.is-light { - background-color: #eff6fa; - color: #317ca5; - } - - .notification.is-info { - background-color: #3298dc; - color: #fff; - } - - .notification.is-info.is-light { - background-color: #eef6fc; - color: #1d72aa; - } - - .notification.is-success { - background-color: #48c774; - color: #fff; - } - - .notification.is-success.is-light { - background-color: #effaf3; - color: #257942; - } - - .notification.is-warning { - background-color: #ffdd57; - color: rgba(0, 0, 0, 0.7); - } - - .notification.is-warning.is-light { - background-color: #fffbeb; - color: #947600; - } - - .notification.is-danger { - background-color: #f14668; - color: #fff; - } - - .notification.is-danger.is-light { - background-color: #feecf0; - color: #cc0f35; - } - -.progress { - -moz-appearance: none; - -webkit-appearance: none; - border: none; - border-radius: 290486px; - display: block; - height: 1rem; - overflow: hidden; - padding: 0; - width: 100%; -} - - .progress::-webkit-progress-bar { - background-color: #ededed; - } - - .progress::-webkit-progress-value { - background-color: #4a4a4a; - } - - .progress::-moz-progress-bar { - background-color: #4a4a4a; - } - - .progress::-ms-fill { - background-color: #4a4a4a; - border: none; - } - - .progress.is-white::-webkit-progress-value { - background-color: white; - } - - .progress.is-white::-moz-progress-bar { - background-color: white; - } - - .progress.is-white::-ms-fill { - background-color: white; - } - - .progress.is-white:indeterminate { - background-image: -webkit-gradient(linear, left top, right top, color-stop(30%, white), color-stop(30%, #ededed)); - background-image: -o-linear-gradient(left, white 30%, #ededed 30%); - background-image: linear-gradient(to right, white 30%, #ededed 30%); - } - - .progress.is-black::-webkit-progress-value { - background-color: #0a0a0a; - } - - .progress.is-black::-moz-progress-bar { - background-color: #0a0a0a; - } - - .progress.is-black::-ms-fill { - background-color: #0a0a0a; - } - - .progress.is-black:indeterminate { - background-image: -webkit-gradient(linear, left top, right top, color-stop(30%, #0a0a0a), color-stop(30%, #ededed)); - background-image: -o-linear-gradient(left, #0a0a0a 30%, #ededed 30%); - background-image: linear-gradient(to right, #0a0a0a 30%, #ededed 30%); - } - - .progress.is-light::-webkit-progress-value { - background-color: whitesmoke; - } - - .progress.is-light::-moz-progress-bar { - background-color: whitesmoke; - } - - .progress.is-light::-ms-fill { - background-color: whitesmoke; - } - - .progress.is-light:indeterminate { - background-image: -webkit-gradient(linear, left top, right top, color-stop(30%, whitesmoke), color-stop(30%, #ededed)); - background-image: -o-linear-gradient(left, whitesmoke 30%, #ededed 30%); - background-image: linear-gradient(to right, whitesmoke 30%, #ededed 30%); - } - - .progress.is-dark::-webkit-progress-value { - background-color: #200117; - } - - .progress.is-dark::-moz-progress-bar { - background-color: #200117; - } - - .progress.is-dark::-ms-fill { - background-color: #200117; - } - - .progress.is-dark:indeterminate { - background-image: -webkit-gradient(linear, left top, right top, color-stop(30%, #200117), color-stop(30%, #ededed)); - background-image: -o-linear-gradient(left, #200117 30%, #ededed 30%); - background-image: linear-gradient(to right, #200117 30%, #ededed 30%); - } - - .progress.is-primary::-webkit-progress-value { - background-color: #A00975; - } - - .progress.is-primary::-moz-progress-bar { - background-color: #A00975; - } - - .progress.is-primary::-ms-fill { - background-color: #A00975; - } - - .progress.is-primary:indeterminate { - background-image: -webkit-gradient(linear, left top, right top, color-stop(30%, #A00975), color-stop(30%, #ededed)); - background-image: -o-linear-gradient(left, #A00975 30%, #ededed 30%); - background-image: linear-gradient(to right, #A00975 30%, #ededed 30%); - } - - .progress.is-link::-webkit-progress-value { - background-color: #378BBA; - } - - .progress.is-link::-moz-progress-bar { - background-color: #378BBA; - } - - .progress.is-link::-ms-fill { - background-color: #378BBA; - } - - .progress.is-link:indeterminate { - background-image: -webkit-gradient(linear, left top, right top, color-stop(30%, #378BBA), color-stop(30%, #ededed)); - background-image: -o-linear-gradient(left, #378BBA 30%, #ededed 30%); - background-image: linear-gradient(to right, #378BBA 30%, #ededed 30%); - } - - .progress.is-info::-webkit-progress-value { - background-color: #3298dc; - } - - .progress.is-info::-moz-progress-bar { - background-color: #3298dc; - } - - .progress.is-info::-ms-fill { - background-color: #3298dc; - } - - .progress.is-info:indeterminate { - background-image: -webkit-gradient(linear, left top, right top, color-stop(30%, #3298dc), color-stop(30%, #ededed)); - background-image: -o-linear-gradient(left, #3298dc 30%, #ededed 30%); - background-image: linear-gradient(to right, #3298dc 30%, #ededed 30%); - } - - .progress.is-success::-webkit-progress-value { - background-color: #48c774; - } - - .progress.is-success::-moz-progress-bar { - background-color: #48c774; - } - - .progress.is-success::-ms-fill { - background-color: #48c774; - } - - .progress.is-success:indeterminate { - background-image: -webkit-gradient(linear, left top, right top, color-stop(30%, #48c774), color-stop(30%, #ededed)); - background-image: -o-linear-gradient(left, #48c774 30%, #ededed 30%); - background-image: linear-gradient(to right, #48c774 30%, #ededed 30%); - } - - .progress.is-warning::-webkit-progress-value { - background-color: #ffdd57; - } - - .progress.is-warning::-moz-progress-bar { - background-color: #ffdd57; - } - - .progress.is-warning::-ms-fill { - background-color: #ffdd57; - } - - .progress.is-warning:indeterminate { - background-image: -webkit-gradient(linear, left top, right top, color-stop(30%, #ffdd57), color-stop(30%, #ededed)); - background-image: -o-linear-gradient(left, #ffdd57 30%, #ededed 30%); - background-image: linear-gradient(to right, #ffdd57 30%, #ededed 30%); - } - - .progress.is-danger::-webkit-progress-value { - background-color: #f14668; - } - - .progress.is-danger::-moz-progress-bar { - background-color: #f14668; - } - - .progress.is-danger::-ms-fill { - background-color: #f14668; - } - - .progress.is-danger:indeterminate { - background-image: -webkit-gradient(linear, left top, right top, color-stop(30%, #f14668), color-stop(30%, #ededed)); - background-image: -o-linear-gradient(left, #f14668 30%, #ededed 30%); - background-image: linear-gradient(to right, #f14668 30%, #ededed 30%); - } - - .progress:indeterminate { - -webkit-animation-duration: 1.5s; - animation-duration: 1.5s; - -webkit-animation-iteration-count: infinite; - animation-iteration-count: infinite; - -webkit-animation-name: moveIndeterminate; - animation-name: moveIndeterminate; - -webkit-animation-timing-function: linear; - animation-timing-function: linear; - background-color: #ededed; - background-image: -webkit-gradient(linear, left top, right top, color-stop(30%, #4a4a4a), color-stop(30%, #ededed)); - background-image: -o-linear-gradient(left, #4a4a4a 30%, #ededed 30%); - background-image: linear-gradient(to right, #4a4a4a 30%, #ededed 30%); - background-position: top left; - background-repeat: no-repeat; - background-size: 150% 150%; - } - - .progress:indeterminate::-webkit-progress-bar { - background-color: transparent; - } - - .progress:indeterminate::-moz-progress-bar { - background-color: transparent; - } - - .progress:indeterminate::-ms-fill { - animation-name: none; - } - - .progress.is-small { - height: 0.75rem; - } - - .progress.is-medium { - height: 1.25rem; - } - - .progress.is-large { - height: 1.5rem; - } - -@-webkit-keyframes moveIndeterminate { - from { - background-position: 200% 0; - } - - to { - background-position: -200% 0; - } -} - -@keyframes moveIndeterminate { - from { - background-position: 200% 0; - } - - to { - background-position: -200% 0; - } -} - -.table, table { - background-color: white; - color: #363636; -} - - .table td, table td, - .table th, - table th { - border: 1px solid #200117; - border-width: 0 0 1px; - padding: 0.5em 0.75em; - vertical-align: top; - } - - .table td.is-white, table td.is-white, - .table th.is-white, - table th.is-white { - background-color: white; - border-color: white; - color: #0a0a0a; - } - - .table td.is-black, table td.is-black, - .table th.is-black, - table th.is-black { - background-color: #0a0a0a; - border-color: #0a0a0a; - color: white; - } - - .table td.is-light, table td.is-light, - .table th.is-light, - table th.is-light { - background-color: whitesmoke; - border-color: whitesmoke; - color: rgba(0, 0, 0, 0.7); - } - - .table td.is-dark, table td.is-dark, - .table th.is-dark, - table th.is-dark { - background-color: #200117; - border-color: #200117; - color: #fff; - } - - .table td.is-primary, table td.is-primary, - .table th.is-primary, - table th.is-primary { - background-color: #A00975; - border-color: #A00975; - color: #fff; - } - - .table td.is-link, table td.is-link, - .table th.is-link, - table th.is-link { - background-color: #378BBA; - border-color: #378BBA; - color: #fff; - } - - .table td.is-info, table td.is-info, - .table th.is-info, - table th.is-info { - background-color: #3298dc; - border-color: #3298dc; - color: #fff; - } - - .table td.is-success, table td.is-success, - .table th.is-success, - table th.is-success { - background-color: #48c774; - border-color: #48c774; - color: #fff; - } - - .table td.is-warning, table td.is-warning, - .table th.is-warning, - table th.is-warning { - background-color: #ffdd57; - border-color: #ffdd57; - color: rgba(0, 0, 0, 0.7); - } - - .table td.is-danger, table td.is-danger, - .table th.is-danger, - table th.is-danger { - background-color: #f14668; - border-color: #f14668; - color: #fff; - } - - .table td.is-narrow, table td.is-narrow, - .table th.is-narrow, - table th.is-narrow { - white-space: nowrap; - width: 1%; - } - - .table td.is-selected, table td.is-selected, - .table th.is-selected, - table th.is-selected { - background-color: #A00975; - color: #fff; - } - - .table td.is-selected a, table td.is-selected a, - .table td.is-selected strong, - table td.is-selected strong, - .table th.is-selected a, - table th.is-selected a, - .table th.is-selected strong, - table th.is-selected strong { - color: currentColor; - } - - .table td.is-vcentered, table td.is-vcentered, - .table th.is-vcentered, - table th.is-vcentered { - vertical-align: middle; - } - - .table th, table th { - color: #A00975; - } - - .table th:not([align]), table th:not([align]) { - text-align: inherit; - } - - .table tr.is-selected, table tr.is-selected { - background-color: #A00975; - color: #fff; - } - - .table tr.is-selected a, table tr.is-selected a, - .table tr.is-selected strong, - table tr.is-selected strong { - color: currentColor; - } - - .table tr.is-selected td, table tr.is-selected td, - .table tr.is-selected th, - table tr.is-selected th { - border-color: #fff; - color: currentColor; - } - - .table thead, table thead { - background-color: transparent; - } - - .table thead td, table thead td, - .table thead th, - table thead th { - border-width: 0 0 2px; - color: #A00975; - } - - .table tfoot, table tfoot { - background-color: transparent; - } - - .table tfoot td, table tfoot td, - .table tfoot th, - table tfoot th { - border-width: 2px 0 0; - color: #363636; - } - - .table tbody, table tbody { - background-color: transparent; - } - - .table tbody tr:last-child td, table tbody tr:last-child td, - .table tbody tr:last-child th, - table tbody tr:last-child th { - border-bottom-width: 0; - } - - .table.is-bordered td, table.is-bordered td, - .table.is-bordered th, - table.is-bordered th { - border-width: 1px; - } - - .table.is-bordered tr:last-child td, table.is-bordered tr:last-child td, - .table.is-bordered tr:last-child th, - table.is-bordered tr:last-child th { - border-bottom-width: 1px; - } - - .table.is-fullwidth, table.is-fullwidth { - width: 100%; - } - - .table.is-hoverable tbody tr:not(.is-selected):hover, table.is-hoverable tbody tr:not(.is-selected):hover { - background-color: #fafafa; - } - - .table.is-hoverable.is-striped tbody tr:not(.is-selected):hover, table.is-hoverable tbody tr:not(.is-selected):hover { - background-color: #fafafa; - } - - .table.is-hoverable.is-striped tbody tr:not(.is-selected):hover:nth-child(even), table.is-hoverable tbody tr:not(.is-selected):hover:nth-child(even) { - background-color: whitesmoke; - } - - .table.is-narrow td, table.is-narrow td, - .table.is-narrow th, - table.is-narrow th { - padding: 0.25em 0.5em; - } - - .table.is-striped tbody tr:not(.is-selected):nth-child(even), table tbody tr:not(.is-selected):nth-child(even) { - background-color: #fafafa; - } - -.table-container { - -webkit-overflow-scrolling: touch; - overflow: auto; - overflow-y: hidden; - max-width: 100%; -} - -.tags { - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - display: -webkit-box; - display: -ms-flexbox; - display: flex; - -ms-flex-wrap: wrap; - flex-wrap: wrap; - -webkit-box-pack: start; - -ms-flex-pack: start; - justify-content: flex-start; -} - - .tags .tag { - margin-bottom: 0.5rem; - } - - .tags .tag:not(:last-child) { - margin-right: 0.5rem; - } - - .tags:last-child { - margin-bottom: -0.5rem; - } - - .tags:not(:last-child) { - margin-bottom: 1rem; - } - - .tags.are-medium .tag:not(.is-normal):not(.is-large) { - font-size: 1rem; - } - - .tags.are-large .tag:not(.is-normal):not(.is-medium) { - font-size: 1.25rem; - } - - .tags.is-centered { - -webkit-box-pack: center; - -ms-flex-pack: center; - justify-content: center; - } - - .tags.is-centered .tag { - margin-right: 0.25rem; - margin-left: 0.25rem; - } - - .tags.is-right { - -webkit-box-pack: end; - -ms-flex-pack: end; - justify-content: flex-end; - } - - .tags.is-right .tag:not(:first-child) { - margin-left: 0.5rem; - } - - .tags.is-right .tag:not(:last-child) { - margin-right: 0; - } - - .tags.has-addons .tag { - margin-right: 0; - } - - .tags.has-addons .tag:not(:first-child) { - margin-left: 0; - border-top-left-radius: 0; - border-bottom-left-radius: 0; - } - - .tags.has-addons .tag:not(:last-child) { - border-top-right-radius: 0; - border-bottom-right-radius: 0; - } - -.tag:not(body) { - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - background-color: whitesmoke; - border-radius: 4px; - color: #4a4a4a; - display: -webkit-inline-box; - display: -ms-inline-flexbox; - display: inline-flex; - font-size: 0.75rem; - height: 2em; - -webkit-box-pack: center; - -ms-flex-pack: center; - justify-content: center; - line-height: 1.5; - padding-left: 0.75em; - padding-right: 0.75em; - white-space: nowrap; -} - - .tag:not(body) .delete { - margin-left: 0.25rem; - margin-right: -0.375rem; - } - - .tag:not(body).is-white { - background-color: white; - color: #0a0a0a; - } - - .tag:not(body).is-black { - background-color: #0a0a0a; - color: white; - } - - .tag:not(body).is-light { - background-color: whitesmoke; - color: rgba(0, 0, 0, 0.7); - } - - .tag:not(body).is-dark { - background-color: #200117; - color: #fff; - } - - .tag:not(body).is-primary { - background-color: #A00975; - color: #fff; - } - - .tag:not(body).is-primary.is-light { - background-color: #feecf9; - color: #f212b2; - } - - .tag:not(body).is-link { - background-color: #378BBA; - color: #fff; - } - - .tag:not(body).is-link.is-light { - background-color: #eff6fa; - color: #317ca5; - } - - .tag:not(body).is-info { - background-color: #3298dc; - color: #fff; - } - - .tag:not(body).is-info.is-light { - background-color: #eef6fc; - color: #1d72aa; - } - - .tag:not(body).is-success { - background-color: #48c774; - color: #fff; - } - - .tag:not(body).is-success.is-light { - background-color: #effaf3; - color: #257942; - } - - .tag:not(body).is-warning { - background-color: #ffdd57; - color: rgba(0, 0, 0, 0.7); - } - - .tag:not(body).is-warning.is-light { - background-color: #fffbeb; - color: #947600; - } - - .tag:not(body).is-danger { - background-color: #f14668; - color: #fff; - } - - .tag:not(body).is-danger.is-light { - background-color: #feecf0; - color: #cc0f35; - } - - .tag:not(body).is-normal { - font-size: 0.75rem; - } - - .tag:not(body).is-medium { - font-size: 1rem; - } - - .tag:not(body).is-large { - font-size: 1.25rem; - } - - .tag:not(body) .icon:first-child:not(:last-child) { - margin-left: -0.375em; - margin-right: 0.1875em; - } - - .tag:not(body) .icon:last-child:not(:first-child) { - margin-left: 0.1875em; - margin-right: -0.375em; - } - - .tag:not(body) .icon:first-child:last-child { - margin-left: -0.375em; - margin-right: -0.375em; - } - - .tag:not(body).is-delete { - margin-left: 1px; - padding: 0; - position: relative; - width: 2em; - } - - .tag:not(body).is-delete::before, .tag:not(body).is-delete::after { - background-color: currentColor; - content: ""; - display: block; - left: 50%; - position: absolute; - top: 50%; - -webkit-transform: translateX(-50%) translateY(-50%) rotate(45deg); - -ms-transform: translateX(-50%) translateY(-50%) rotate(45deg); - transform: translateX(-50%) translateY(-50%) rotate(45deg); - -webkit-transform-origin: center center; - -ms-transform-origin: center center; - transform-origin: center center; - } - - .tag:not(body).is-delete::before { - height: 1px; - width: 50%; - } - - .tag:not(body).is-delete::after { - height: 50%; - width: 1px; - } - - .tag:not(body).is-delete:hover, .tag:not(body).is-delete:focus { - background-color: #e8e8e8; - } - - .tag:not(body).is-delete:active { - background-color: #dbdbdb; - } - - .tag:not(body).is-rounded { - border-radius: 290486px; - } - -a.tag:hover { - text-decoration: underline; -} - -.title, -.subtitle { - word-break: break-word; -} - - .title em, - .title span, - .subtitle em, - .subtitle span { - font-weight: inherit; - } - - .title sub, - .subtitle sub { - font-size: 0.75em; - } - - .title sup, - .subtitle sup { - font-size: 0.75em; - } - - .title .tag, - .subtitle .tag { - vertical-align: middle; - } - -.title { - color: #363636; - font-size: 2rem; - font-weight: 600; - line-height: 1.125; -} - - .title strong { - color: inherit; - font-weight: inherit; - } - - .title + .highlight { - margin-top: -0.75rem; - } - - .title:not(.is-spaced) + .subtitle { - margin-top: -1.25rem; - } - - .title.is-1 { - font-size: 3rem; - } - - .title.is-2 { - font-size: 2.5rem; - } - - .title.is-3 { - font-size: 2rem; - } - - .title.is-4 { - font-size: 1.5rem; - } - - .title.is-5 { - font-size: 1.25rem; - } - - .title.is-6 { - font-size: 1rem; - } - - .title.is-7 { - font-size: 0.75rem; - } - -.subtitle { - color: #4a4a4a; - font-size: 1.25rem; - font-weight: 400; - line-height: 1.25; -} - - .subtitle strong { - color: #363636; - font-weight: 600; - } - - .subtitle:not(.is-spaced) + .title { - margin-top: -1.25rem; - } - - .subtitle.is-1 { - font-size: 3rem; - } - - .subtitle.is-2 { - font-size: 2.5rem; - } - - .subtitle.is-3 { - font-size: 2rem; - } - - .subtitle.is-4 { - font-size: 1.5rem; - } - - .subtitle.is-5 { - font-size: 1.25rem; - } - - .subtitle.is-6 { - font-size: 1rem; - } - - .subtitle.is-7 { - font-size: 0.75rem; - } - -.heading { - display: block; - font-size: 11px; - letter-spacing: 1px; - margin-bottom: 5px; - text-transform: uppercase; -} - -.highlight { - font-weight: 400; - max-width: 100%; - overflow: hidden; - padding: 0; -} - - .highlight pre { - overflow: auto; - max-width: 100%; - } - -.number { - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - background-color: whitesmoke; - border-radius: 290486px; - display: -webkit-inline-box; - display: -ms-inline-flexbox; - display: inline-flex; - font-size: 1.25rem; - height: 2em; - -webkit-box-pack: center; - -ms-flex-pack: center; - justify-content: center; - margin-right: 1.5rem; - min-width: 2.5em; - padding: 0.25rem 0.5rem; - text-align: center; - vertical-align: top; -} - -/* Bulma Form */ -.select select, .textarea, .input { - background-color: white; - border-color: #dbdbdb; - border-radius: 4px; - color: #363636; -} - - .select select::-moz-placeholder, .textarea::-moz-placeholder, .input::-moz-placeholder { - color: rgba(54, 54, 54, 0.3); - } - - .select select::-webkit-input-placeholder, .textarea::-webkit-input-placeholder, .input::-webkit-input-placeholder { - color: rgba(54, 54, 54, 0.3); - } - - .select select:-moz-placeholder, .textarea:-moz-placeholder, .input:-moz-placeholder { - color: rgba(54, 54, 54, 0.3); - } - - .select select:-ms-input-placeholder, .textarea:-ms-input-placeholder, .input:-ms-input-placeholder { - color: rgba(54, 54, 54, 0.3); - } - - .select select:hover, .textarea:hover, .input:hover, .select select.is-hovered, .is-hovered.textarea, .is-hovered.input { - border-color: #b5b5b5; - } - - .select select:focus, .textarea:focus, .input:focus, .select select.is-focused, .is-focused.textarea, .is-focused.input, .select select:active, .textarea:active, .input:active, .select select.is-active, .select select.active, .is-active.textarea, .textarea.active, .is-active.input, .input.active { - border-color: #378BBA; - -webkit-box-shadow: 0 0 0 0.125em rgba(55, 139, 186, 0.25); - box-shadow: 0 0 0 0.125em rgba(55, 139, 186, 0.25); - } - - .select select[disabled], [disabled].textarea, [disabled].input, fieldset[disabled] .select select, .select fieldset[disabled] select, fieldset[disabled] .textarea, fieldset[disabled] .input { - background-color: whitesmoke; - border-color: whitesmoke; - -webkit-box-shadow: none; - box-shadow: none; - color: #7a7a7a; - } - - .select select[disabled]::-moz-placeholder, [disabled].textarea::-moz-placeholder, [disabled].input::-moz-placeholder, fieldset[disabled] .select select::-moz-placeholder, .select fieldset[disabled] select::-moz-placeholder, fieldset[disabled] .textarea::-moz-placeholder, fieldset[disabled] .input::-moz-placeholder { - color: rgba(122, 122, 122, 0.3); - } - - .select select[disabled]::-webkit-input-placeholder, [disabled].textarea::-webkit-input-placeholder, [disabled].input::-webkit-input-placeholder, fieldset[disabled] .select select::-webkit-input-placeholder, .select fieldset[disabled] select::-webkit-input-placeholder, fieldset[disabled] .textarea::-webkit-input-placeholder, fieldset[disabled] .input::-webkit-input-placeholder { - color: rgba(122, 122, 122, 0.3); - } - - .select select[disabled]:-moz-placeholder, [disabled].textarea:-moz-placeholder, [disabled].input:-moz-placeholder, fieldset[disabled] .select select:-moz-placeholder, .select fieldset[disabled] select:-moz-placeholder, fieldset[disabled] .textarea:-moz-placeholder, fieldset[disabled] .input:-moz-placeholder { - color: rgba(122, 122, 122, 0.3); - } - - .select select[disabled]:-ms-input-placeholder, [disabled].textarea:-ms-input-placeholder, [disabled].input:-ms-input-placeholder, fieldset[disabled] .select select:-ms-input-placeholder, .select fieldset[disabled] select:-ms-input-placeholder, fieldset[disabled] .textarea:-ms-input-placeholder, fieldset[disabled] .input:-ms-input-placeholder { - color: rgba(122, 122, 122, 0.3); - } - -.textarea, .input { - -webkit-box-shadow: inset 0 0.0625em 0.125em rgba(10, 10, 10, 0.05); - box-shadow: inset 0 0.0625em 0.125em rgba(10, 10, 10, 0.05); - max-width: 100%; - width: 100%; -} - -[readonly].textarea, [readonly].input { - -webkit-box-shadow: none; - box-shadow: none; -} - -.is-white.textarea, .is-white.input { - border-color: white; -} - - .is-white.textarea:focus, .is-white.input:focus, .is-white.is-focused.textarea, .is-white.is-focused.input, .is-white.textarea:active, .is-white.input:active, .is-white.active, .is-white.is-active.textarea, .is-white.is-active.input { - -webkit-box-shadow: 0 0 0 0.125em rgba(255, 255, 255, 0.25); - box-shadow: 0 0 0 0.125em rgba(255, 255, 255, 0.25); - } - -.is-black.textarea, .is-black.input { - border-color: #0a0a0a; -} - - .is-black.textarea:focus, .is-black.input:focus, .is-black.is-focused.textarea, .is-black.is-focused.input, .is-black.textarea:active, .is-black.input:active, .is-black.active, .is-black.is-active.textarea, .is-black.is-active.input { - -webkit-box-shadow: 0 0 0 0.125em rgba(10, 10, 10, 0.25); - box-shadow: 0 0 0 0.125em rgba(10, 10, 10, 0.25); - } - -.is-light.textarea, .is-light.input { - border-color: whitesmoke; -} - - .is-light.textarea:focus, .is-light.input:focus, .is-light.is-focused.textarea, .is-light.is-focused.input, .is-light.textarea:active, .is-light.input:active, .is-light.active, .is-light.is-active.textarea, .is-light.is-active.input { - -webkit-box-shadow: 0 0 0 0.125em rgba(245, 245, 245, 0.25); - box-shadow: 0 0 0 0.125em rgba(245, 245, 245, 0.25); - } - -.is-dark.textarea, .is-dark.input { - border-color: #200117; -} - - .is-dark.textarea:focus, .is-dark.input:focus, .is-dark.is-focused.textarea, .is-dark.is-focused.input, .is-dark.textarea:active, .is-dark.input:active, .is-dark.active, .is-dark.is-active.textarea, .is-dark.is-active.input { - -webkit-box-shadow: 0 0 0 0.125em rgba(32, 1, 23, 0.25); - box-shadow: 0 0 0 0.125em rgba(32, 1, 23, 0.25); - } - -.is-primary.textarea, .is-primary.input { - border-color: #A00975; -} - - .is-primary.textarea:focus, .is-primary.input:focus, .is-primary.is-focused.textarea, .is-primary.is-focused.input, .is-primary.textarea:active, .is-primary.input:active, .is-primary.active, .is-primary.is-active.textarea, .is-primary.is-active.input { - -webkit-box-shadow: 0 0 0 0.125em rgba(160, 9, 117, 0.25); - box-shadow: 0 0 0 0.125em rgba(160, 9, 117, 0.25); - } - -.is-link.textarea, .is-link.input { - border-color: #378BBA; -} - - .is-link.textarea:focus, .is-link.input:focus, .is-link.is-focused.textarea, .is-link.is-focused.input, .is-link.textarea:active, .is-link.input:active, .is-link.active, .is-link.is-active.textarea, .is-link.is-active.input { - -webkit-box-shadow: 0 0 0 0.125em rgba(55, 139, 186, 0.25); - box-shadow: 0 0 0 0.125em rgba(55, 139, 186, 0.25); - } - -.is-info.textarea, .is-info.input { - border-color: #3298dc; -} - - .is-info.textarea:focus, .is-info.input:focus, .is-info.is-focused.textarea, .is-info.is-focused.input, .is-info.textarea:active, .is-info.input:active, .is-info.active, .is-info.is-active.textarea, .is-info.is-active.input { - -webkit-box-shadow: 0 0 0 0.125em rgba(50, 152, 220, 0.25); - box-shadow: 0 0 0 0.125em rgba(50, 152, 220, 0.25); - } - -.is-success.textarea, .is-success.input { - border-color: #48c774; -} - - .is-success.textarea:focus, .is-success.input:focus, .is-success.is-focused.textarea, .is-success.is-focused.input, .is-success.textarea:active, .is-success.input:active, .is-success.active, .is-success.is-active.textarea, .is-success.is-active.input { - -webkit-box-shadow: 0 0 0 0.125em rgba(72, 199, 116, 0.25); - box-shadow: 0 0 0 0.125em rgba(72, 199, 116, 0.25); - } - -.is-warning.textarea, .is-warning.input { - border-color: #ffdd57; -} - - .is-warning.textarea:focus, .is-warning.input:focus, .is-warning.is-focused.textarea, .is-warning.is-focused.input, .is-warning.textarea:active, .is-warning.input:active, .is-warning.active, .is-warning.is-active.textarea, .is-warning.is-active.input { - -webkit-box-shadow: 0 0 0 0.125em rgba(255, 221, 87, 0.25); - box-shadow: 0 0 0 0.125em rgba(255, 221, 87, 0.25); - } - -.is-danger.textarea, .is-danger.input { - border-color: #f14668; -} - - .is-danger.textarea:focus, .is-danger.input:focus, .is-danger.is-focused.textarea, .is-danger.is-focused.input, .is-danger.textarea:active, .is-danger.input:active, .is-danger.active, .is-danger.is-active.textarea, .is-danger.is-active.input { - -webkit-box-shadow: 0 0 0 0.125em rgba(241, 70, 104, 0.25); - box-shadow: 0 0 0 0.125em rgba(241, 70, 104, 0.25); - } - -.is-small.textarea, .is-small.input { - border-radius: 2px; - font-size: 0.75rem; -} - -.is-medium.textarea, .is-medium.input { - font-size: 1.25rem; -} - -.is-large.textarea, .is-large.input { - font-size: 1.5rem; -} - -.is-fullwidth.textarea, .is-fullwidth.input { - display: block; - width: 100%; -} - -.is-inline.textarea, .is-inline.input { - display: inline; - width: auto; -} - -.input.is-rounded { - border-radius: 290486px; - padding-left: calc(calc(0.75em - 1px) + 0.375em); - padding-right: calc(calc(0.75em - 1px) + 0.375em); -} - -.input.is-static { - background-color: transparent; - border-color: transparent; - -webkit-box-shadow: none; - box-shadow: none; - padding-left: 0; - padding-right: 0; -} - -.textarea { - display: block; - max-width: 100%; - min-width: 100%; - padding: calc(0.75em - 1px); - resize: vertical; -} - - .textarea:not([rows]) { - max-height: 40em; - min-height: 8em; - } - - .textarea[rows] { - height: initial; - } - - .textarea.has-fixed-size { - resize: none; - } - -.radio, .checkbox { - cursor: pointer; - display: inline-block; - line-height: 1.25; - position: relative; -} - - .radio input, .checkbox input { - cursor: pointer; - } - - .radio:hover, .checkbox:hover { - color: #363636; - } - - [disabled].radio, [disabled].checkbox, fieldset[disabled] .radio, fieldset[disabled] .checkbox, - .radio input[disabled], - .checkbox input[disabled] { - color: #7a7a7a; - cursor: not-allowed; - } - - .radio + .radio { - margin-left: 0.5em; - } - -.select { - display: inline-block; - max-width: 100%; - position: relative; - vertical-align: top; -} - - .select:not(.is-multiple) { - height: 2.5em; - } - - .select:not(.is-multiple):not(.is-loading)::after { - border-color: #378BBA; - right: 1.125em; - z-index: 4; - } - - .select.is-rounded select { - border-radius: 290486px; - padding-left: 1em; - } - - .select select { - cursor: pointer; - display: block; - font-size: 1em; - max-width: 100%; - outline: none; - } - - .select select::-ms-expand { - display: none; - } - - .select select[disabled]:hover, fieldset[disabled] .select select:hover { - border-color: whitesmoke; - } - - .select select:not([multiple]) { - padding-right: 2.5em; - } - - .select select[multiple] { - height: auto; - padding: 0; - } - - .select select[multiple] option { - padding: 0.5em 1em; - } - - .select:not(.is-multiple):not(.is-loading):hover::after { - border-color: #363636; - } - - .select.is-white:not(:hover)::after { - border-color: white; - } - - .select.is-white select { - border-color: white; - } - - .select.is-white select:hover, .select.is-white select.is-hovered { - border-color: #f2f2f2; - } - - .select.is-white select:focus, .select.is-white select.is-focused, .select.is-white select:active, .select.is-white select.is-active, .select.is-white select.active { - -webkit-box-shadow: 0 0 0 0.125em rgba(255, 255, 255, 0.25); - box-shadow: 0 0 0 0.125em rgba(255, 255, 255, 0.25); - } - - .select.is-black:not(:hover)::after { - border-color: #0a0a0a; - } - - .select.is-black select { - border-color: #0a0a0a; - } - - .select.is-black select:hover, .select.is-black select.is-hovered { - border-color: black; - } - - .select.is-black select:focus, .select.is-black select.is-focused, .select.is-black select:active, .select.is-black select.is-active, .select.is-black select.active { - -webkit-box-shadow: 0 0 0 0.125em rgba(10, 10, 10, 0.25); - box-shadow: 0 0 0 0.125em rgba(10, 10, 10, 0.25); - } - - .select.is-light:not(:hover)::after { - border-color: whitesmoke; - } - - .select.is-light select { - border-color: whitesmoke; - } - - .select.is-light select:hover, .select.is-light select.is-hovered { - border-color: #e8e8e8; - } - - .select.is-light select:focus, .select.is-light select.is-focused, .select.is-light select:active, .select.is-light select.is-active, .select.is-light select.active { - -webkit-box-shadow: 0 0 0 0.125em rgba(245, 245, 245, 0.25); - box-shadow: 0 0 0 0.125em rgba(245, 245, 245, 0.25); - } - - .select.is-dark:not(:hover)::after { - border-color: #200117; - } - - .select.is-dark select { - border-color: #200117; - } - - .select.is-dark select:hover, .select.is-dark select.is-hovered { - border-color: #070005; - } - - .select.is-dark select:focus, .select.is-dark select.is-focused, .select.is-dark select:active, .select.is-dark select.is-active, .select.is-dark select.active { - -webkit-box-shadow: 0 0 0 0.125em rgba(32, 1, 23, 0.25); - box-shadow: 0 0 0 0.125em rgba(32, 1, 23, 0.25); - } - - .select.is-primary:not(:hover)::after { - border-color: #A00975; - } - - .select.is-primary select { - border-color: #A00975; - } - - .select.is-primary select:hover, .select.is-primary select.is-hovered { - border-color: #880863; - } - - .select.is-primary select:focus, .select.is-primary select.is-focused, .select.is-primary select:active, .select.is-primary select.is-active, .select.is-primary select.active { - -webkit-box-shadow: 0 0 0 0.125em rgba(160, 9, 117, 0.25); - box-shadow: 0 0 0 0.125em rgba(160, 9, 117, 0.25); - } - - .select.is-link:not(:hover)::after { - border-color: #378BBA; - } - - .select.is-link select { - border-color: #378BBA; - } - - .select.is-link select:hover, .select.is-link select.is-hovered { - border-color: #317ca6; - } - - .select.is-link select:focus, .select.is-link select.is-focused, .select.is-link select:active, .select.is-link select.is-active, .select.is-link select.active { - -webkit-box-shadow: 0 0 0 0.125em rgba(55, 139, 186, 0.25); - box-shadow: 0 0 0 0.125em rgba(55, 139, 186, 0.25); - } - - .select.is-info:not(:hover)::after { - border-color: #3298dc; - } - - .select.is-info select { - border-color: #3298dc; - } - - .select.is-info select:hover, .select.is-info select.is-hovered { - border-color: #238cd1; - } - - .select.is-info select:focus, .select.is-info select.is-focused, .select.is-info select:active, .select.is-info select.is-active, .select.is-info select.active { - -webkit-box-shadow: 0 0 0 0.125em rgba(50, 152, 220, 0.25); - box-shadow: 0 0 0 0.125em rgba(50, 152, 220, 0.25); - } - - .select.is-success:not(:hover)::after { - border-color: #48c774; - } - - .select.is-success select { - border-color: #48c774; - } - - .select.is-success select:hover, .select.is-success select.is-hovered { - border-color: #3abb67; - } - - .select.is-success select:focus, .select.is-success select.is-focused, .select.is-success select:active, .select.is-success select.is-active, .select.is-success select.active { - -webkit-box-shadow: 0 0 0 0.125em rgba(72, 199, 116, 0.25); - box-shadow: 0 0 0 0.125em rgba(72, 199, 116, 0.25); - } - - .select.is-warning:not(:hover)::after { - border-color: #ffdd57; - } - - .select.is-warning select { - border-color: #ffdd57; - } - - .select.is-warning select:hover, .select.is-warning select.is-hovered { - border-color: #ffd83d; - } - - .select.is-warning select:focus, .select.is-warning select.is-focused, .select.is-warning select:active, .select.is-warning select.is-active, .select.is-warning select.active { - -webkit-box-shadow: 0 0 0 0.125em rgba(255, 221, 87, 0.25); - box-shadow: 0 0 0 0.125em rgba(255, 221, 87, 0.25); - } - - .select.is-danger:not(:hover)::after { - border-color: #f14668; - } - - .select.is-danger select { - border-color: #f14668; - } - - .select.is-danger select:hover, .select.is-danger select.is-hovered { - border-color: #ef2e55; - } - - .select.is-danger select:focus, .select.is-danger select.is-focused, .select.is-danger select:active, .select.is-danger select.is-active, .select.is-danger select.active { - -webkit-box-shadow: 0 0 0 0.125em rgba(241, 70, 104, 0.25); - box-shadow: 0 0 0 0.125em rgba(241, 70, 104, 0.25); - } - - .select.is-small { - border-radius: 2px; - font-size: 0.75rem; - } - - .select.is-medium { - font-size: 1.25rem; - } - - .select.is-large { - font-size: 1.5rem; - } - - .select.is-disabled::after { - border-color: #7a7a7a; - } - - .select.is-fullwidth { - width: 100%; - } - - .select.is-fullwidth select { - width: 100%; - } - - .select.is-loading::after { - margin-top: 0; - position: absolute; - right: 0.625em; - top: 0.625em; - -webkit-transform: none; - -ms-transform: none; - transform: none; - } - - .select.is-loading.is-small:after { - font-size: 0.75rem; - } - - .select.is-loading.is-medium:after { - font-size: 1.25rem; - } - - .select.is-loading.is-large:after { - font-size: 1.5rem; - } - -.file { - -webkit-box-align: stretch; - -ms-flex-align: stretch; - align-items: stretch; - display: -webkit-box; - display: -ms-flexbox; - display: flex; - -webkit-box-pack: start; - -ms-flex-pack: start; - justify-content: flex-start; - position: relative; -} - - .file.is-white .file-cta { - background-color: white; - border-color: transparent; - color: #0a0a0a; - } - - .file.is-white:hover .file-cta, .file.is-white.is-hovered .file-cta { - background-color: #f9f9f9; - border-color: transparent; - color: #0a0a0a; - } - - .file.is-white:focus .file-cta, .file.is-white.is-focused .file-cta { - border-color: transparent; - -webkit-box-shadow: 0 0 0.5em rgba(255, 255, 255, 0.25); - box-shadow: 0 0 0.5em rgba(255, 255, 255, 0.25); - color: #0a0a0a; - } - - .file.is-white:active .file-cta, .file.is-white.is-active .file-cta, .is-white.active .file-cta { - background-color: #f2f2f2; - border-color: transparent; - color: #0a0a0a; - } - - .file.is-black .file-cta { - background-color: #0a0a0a; - border-color: transparent; - color: white; - } - - .file.is-black:hover .file-cta, .file.is-black.is-hovered .file-cta { - background-color: #040404; - border-color: transparent; - color: white; - } - - .file.is-black:focus .file-cta, .file.is-black.is-focused .file-cta { - border-color: transparent; - -webkit-box-shadow: 0 0 0.5em rgba(10, 10, 10, 0.25); - box-shadow: 0 0 0.5em rgba(10, 10, 10, 0.25); - color: white; - } - - .file.is-black:active .file-cta, .file.is-black.is-active .file-cta, .is-black.active .file-cta { - background-color: black; - border-color: transparent; - color: white; - } - - .file.is-light .file-cta { - background-color: whitesmoke; - border-color: transparent; - color: rgba(0, 0, 0, 0.7); - } - - .file.is-light:hover .file-cta, .file.is-light.is-hovered .file-cta { - background-color: #eeeeee; - border-color: transparent; - color: rgba(0, 0, 0, 0.7); - } - - .file.is-light:focus .file-cta, .file.is-light.is-focused .file-cta { - border-color: transparent; - -webkit-box-shadow: 0 0 0.5em rgba(245, 245, 245, 0.25); - box-shadow: 0 0 0.5em rgba(245, 245, 245, 0.25); - color: rgba(0, 0, 0, 0.7); - } - - .file.is-light:active .file-cta, .file.is-light.is-active .file-cta, .is-light.active .file-cta { - background-color: #e8e8e8; - border-color: transparent; - color: rgba(0, 0, 0, 0.7); - } - - .file.is-dark .file-cta { - background-color: #200117; - border-color: transparent; - color: #fff; - } - - .file.is-dark:hover .file-cta, .file.is-dark.is-hovered .file-cta { - background-color: #14010e; - border-color: transparent; - color: #fff; - } - - .file.is-dark:focus .file-cta, .file.is-dark.is-focused .file-cta { - border-color: transparent; - -webkit-box-shadow: 0 0 0.5em rgba(32, 1, 23, 0.25); - box-shadow: 0 0 0.5em rgba(32, 1, 23, 0.25); - color: #fff; - } - - .file.is-dark:active .file-cta, .file.is-dark.is-active .file-cta, .is-dark.active .file-cta { - background-color: #070005; - border-color: transparent; - color: #fff; - } - - .file.is-primary .file-cta { - background-color: #A00975; - border-color: transparent; - color: #fff; - } - - .file.is-primary:hover .file-cta, .file.is-primary.is-hovered .file-cta { - background-color: #94086c; - border-color: transparent; - color: #fff; - } - - .file.is-primary:focus .file-cta, .file.is-primary.is-focused .file-cta { - border-color: transparent; - -webkit-box-shadow: 0 0 0.5em rgba(160, 9, 117, 0.25); - box-shadow: 0 0 0.5em rgba(160, 9, 117, 0.25); - color: #fff; - } - - .file.is-primary:active .file-cta, .file.is-primary.is-active .file-cta, .is-primary.active .file-cta { - background-color: #880863; - border-color: transparent; - color: #fff; - } - - .file.is-link .file-cta { - background-color: #378BBA; - border-color: transparent; - color: #fff; - } - - .file.is-link:hover .file-cta, .file.is-link.is-hovered .file-cta { - background-color: #3484b0; - border-color: transparent; - color: #fff; - } - - .file.is-link:focus .file-cta, .file.is-link.is-focused .file-cta { - border-color: transparent; - -webkit-box-shadow: 0 0 0.5em rgba(55, 139, 186, 0.25); - box-shadow: 0 0 0.5em rgba(55, 139, 186, 0.25); - color: #fff; - } - - .file.is-link:active .file-cta, .file.is-link.is-active .file-cta, .is-link.active .file-cta { - background-color: #317ca6; - border-color: transparent; - color: #fff; - } - - .file.is-info .file-cta { - background-color: #3298dc; - border-color: transparent; - color: #fff; - } - - .file.is-info:hover .file-cta, .file.is-info.is-hovered .file-cta { - background-color: #2793da; - border-color: transparent; - color: #fff; - } - - .file.is-info:focus .file-cta, .file.is-info.is-focused .file-cta { - border-color: transparent; - -webkit-box-shadow: 0 0 0.5em rgba(50, 152, 220, 0.25); - box-shadow: 0 0 0.5em rgba(50, 152, 220, 0.25); - color: #fff; - } - - .file.is-info:active .file-cta, .file.is-info.is-active .file-cta, .is-info.active .file-cta { - background-color: #238cd1; - border-color: transparent; - color: #fff; - } - - .file.is-success .file-cta { - background-color: #48c774; - border-color: transparent; - color: #fff; - } - - .file.is-success:hover .file-cta, .file.is-success.is-hovered .file-cta { - background-color: #3ec46d; - border-color: transparent; - color: #fff; - } - - .file.is-success:focus .file-cta, .file.is-success.is-focused .file-cta { - border-color: transparent; - -webkit-box-shadow: 0 0 0.5em rgba(72, 199, 116, 0.25); - box-shadow: 0 0 0.5em rgba(72, 199, 116, 0.25); - color: #fff; - } - - .file.is-success:active .file-cta, .file.is-success.is-active .file-cta, .is-success.active .file-cta { - background-color: #3abb67; - border-color: transparent; - color: #fff; - } - - .file.is-warning .file-cta { - background-color: #ffdd57; - border-color: transparent; - color: rgba(0, 0, 0, 0.7); - } - - .file.is-warning:hover .file-cta, .file.is-warning.is-hovered .file-cta { - background-color: #ffdb4a; - border-color: transparent; - color: rgba(0, 0, 0, 0.7); - } - - .file.is-warning:focus .file-cta, .file.is-warning.is-focused .file-cta { - border-color: transparent; - -webkit-box-shadow: 0 0 0.5em rgba(255, 221, 87, 0.25); - box-shadow: 0 0 0.5em rgba(255, 221, 87, 0.25); - color: rgba(0, 0, 0, 0.7); - } - - .file.is-warning:active .file-cta, .file.is-warning.is-active .file-cta, .is-warning.active .file-cta { - background-color: #ffd83d; - border-color: transparent; - color: rgba(0, 0, 0, 0.7); - } - - .file.is-danger .file-cta { - background-color: #f14668; - border-color: transparent; - color: #fff; - } - - .file.is-danger:hover .file-cta, .file.is-danger.is-hovered .file-cta { - background-color: #f03a5f; - border-color: transparent; - color: #fff; - } - - .file.is-danger:focus .file-cta, .file.is-danger.is-focused .file-cta { - border-color: transparent; - -webkit-box-shadow: 0 0 0.5em rgba(241, 70, 104, 0.25); - box-shadow: 0 0 0.5em rgba(241, 70, 104, 0.25); - color: #fff; - } - - .file.is-danger:active .file-cta, .file.is-danger.is-active .file-cta, .is-danger.active .file-cta { - background-color: #ef2e55; - border-color: transparent; - color: #fff; - } - - .file.is-small { - font-size: 0.75rem; - } - - .file.is-medium { - font-size: 1.25rem; - } - - .file.is-medium .file-icon .fa { - font-size: 21px; - } - - .file.is-large { - font-size: 1.5rem; - } - - .file.is-large .file-icon .fa { - font-size: 28px; - } - - .file.has-name .file-cta { - border-bottom-right-radius: 0; - border-top-right-radius: 0; - } - - .file.has-name .file-name { - border-bottom-left-radius: 0; - border-top-left-radius: 0; - } - - .file.has-name.is-empty .file-cta { - border-radius: 4px; - } - - .file.has-name.is-empty .file-name { - display: none; - } - - .file.is-boxed .file-label { - -webkit-box-orient: vertical; - -webkit-box-direction: normal; - -ms-flex-direction: column; - flex-direction: column; - } - - .file.is-boxed .file-cta { - -webkit-box-orient: vertical; - -webkit-box-direction: normal; - -ms-flex-direction: column; - flex-direction: column; - height: auto; - padding: 1em 3em; - } - - .file.is-boxed .file-name { - border-width: 0 1px 1px; - } - - .file.is-boxed .file-icon { - height: 1.5em; - width: 1.5em; - } - - .file.is-boxed .file-icon .fa { - font-size: 21px; - } - - .file.is-boxed.is-small .file-icon .fa { - font-size: 14px; - } - - .file.is-boxed.is-medium .file-icon .fa { - font-size: 28px; - } - - .file.is-boxed.is-large .file-icon .fa { - font-size: 35px; - } - - .file.is-boxed.has-name .file-cta { - border-radius: 4px 4px 0 0; - } - - .file.is-boxed.has-name .file-name { - border-radius: 0 0 4px 4px; - border-width: 0 1px 1px; - } - - .file.is-centered { - -webkit-box-pack: center; - -ms-flex-pack: center; - justify-content: center; - } - - .file.is-fullwidth .file-label { - width: 100%; - } - - .file.is-fullwidth .file-name { - -webkit-box-flex: 1; - -ms-flex-positive: 1; - flex-grow: 1; - max-width: none; - } - - .file.is-right { - -webkit-box-pack: end; - -ms-flex-pack: end; - justify-content: flex-end; - } - - .file.is-right .file-cta { - border-radius: 0 4px 4px 0; - } - - .file.is-right .file-name { - border-radius: 4px 0 0 4px; - border-width: 1px 0 1px 1px; - -webkit-box-ordinal-group: 0; - -ms-flex-order: -1; - order: -1; - } - -.file-label { - -webkit-box-align: stretch; - -ms-flex-align: stretch; - align-items: stretch; - display: -webkit-box; - display: -ms-flexbox; - display: flex; - cursor: pointer; - -webkit-box-pack: start; - -ms-flex-pack: start; - justify-content: flex-start; - overflow: hidden; - position: relative; -} - - .file-label:hover .file-cta { - background-color: #eeeeee; - color: #363636; - } - - .file-label:hover .file-name { - border-color: #d5d5d5; - } - - .file-label:active .file-cta { - background-color: #e8e8e8; - color: #363636; - } - - .file-label:active .file-name { - border-color: #cfcfcf; - } - -.file-input { - height: 100%; - left: 0; - opacity: 0; - outline: none; - position: absolute; - top: 0; - width: 100%; -} - -.file-cta, -.file-name { - border-color: #dbdbdb; - border-radius: 4px; - font-size: 1em; - padding-left: 1em; - padding-right: 1em; - white-space: nowrap; -} - -.file-cta { - background-color: whitesmoke; - color: #4a4a4a; -} - -.file-name { - border-color: #dbdbdb; - border-style: solid; - border-width: 1px 1px 1px 0; - display: block; - max-width: 16em; - overflow: hidden; - text-align: inherit; - -o-text-overflow: ellipsis; - text-overflow: ellipsis; -} - -.file-icon { - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - display: -webkit-box; - display: -ms-flexbox; - display: flex; - height: 1em; - -webkit-box-pack: center; - -ms-flex-pack: center; - justify-content: center; - margin-right: 0.5em; - width: 1em; -} - - .file-icon .fa { - font-size: 14px; - } - -.label { - color: #363636; - display: block; - font-size: 1rem; - font-weight: 700; -} - - .label:not(:last-child) { - margin-bottom: 0.5em; - } - - .label.is-small { - font-size: 0.75rem; - } - - .label.is-medium { - font-size: 1.25rem; - } - - .label.is-large { - font-size: 1.5rem; - } - -.help { - display: block; - font-size: 0.75rem; - margin-top: 0.25rem; -} - - .help.is-white { - color: white; - } - - .help.is-black { - color: #0a0a0a; - } - - .help.is-light { - color: whitesmoke; - } - - .help.is-dark { - color: #200117; - } - - .help.is-primary { - color: #A00975; - } - - .help.is-link { - color: #378BBA; - } - - .help.is-info { - color: #3298dc; - } - - .help.is-success { - color: #48c774; - } - - .help.is-warning { - color: #ffdd57; - } - - .help.is-danger { - color: #f14668; - } - -.field:not(:last-child) { - margin-bottom: 0.75rem; -} - -.field.has-addons { - display: -webkit-box; - display: -ms-flexbox; - display: flex; - -webkit-box-pack: start; - -ms-flex-pack: start; - justify-content: flex-start; -} - - .field.has-addons .control:not(:last-child) { - margin-right: -1px; - } - - .field.has-addons .control:not(:first-child):not(:last-child) .button, - .field.has-addons .control:not(:first-child):not(:last-child) .input, - .field.has-addons .control:not(:first-child):not(:last-child) .select select { - border-radius: 0; - } - - .field.has-addons .control:first-child:not(:only-child) .button, - .field.has-addons .control:first-child:not(:only-child) .input, - .field.has-addons .control:first-child:not(:only-child) .select select { - border-bottom-right-radius: 0; - border-top-right-radius: 0; - } - - .field.has-addons .control:last-child:not(:only-child) .button, - .field.has-addons .control:last-child:not(:only-child) .input, - .field.has-addons .control:last-child:not(:only-child) .select select { - border-bottom-left-radius: 0; - border-top-left-radius: 0; - } - - .field.has-addons .control .button:not([disabled]):hover, .field.has-addons .control .button:not([disabled]).is-hovered, - .field.has-addons .control .input:not([disabled]):hover, - .field.has-addons .control .input:not([disabled]).is-hovered, - .field.has-addons .control .select select:not([disabled]):hover, - .field.has-addons .control .select select:not([disabled]).is-hovered { - z-index: 2; - } - - .field.has-addons .control .button:not([disabled]):focus, .field.has-addons .control .button:not([disabled]).is-focused, .field.has-addons .control .button:not([disabled]):active, .field.has-addons .control .button:not([disabled]).is-active, .field.has-addons .control .active:not([disabled]), - .field.has-addons .control .input:not([disabled]):focus, - .field.has-addons .control .input:not([disabled]).is-focused, - .field.has-addons .control .input:not([disabled]):active, - .field.has-addons .control .input:not([disabled]).is-active, - .field.has-addons .control .select select:not([disabled]):focus, - .field.has-addons .control .select select:not([disabled]).is-focused, - .field.has-addons .control .select select:not([disabled]):active, - .field.has-addons .control .select select:not([disabled]).is-active { - z-index: 3; - } - - .field.has-addons .control .button:not([disabled]):focus:hover, .field.has-addons .control .button:not([disabled]).is-focused:hover, .field.has-addons .control .button:not([disabled]):active:hover, .field.has-addons .control .button:not([disabled]).is-active:hover, .field.has-addons .control .active:not([disabled]):hover, - .field.has-addons .control .input:not([disabled]):focus:hover, - .field.has-addons .control .input:not([disabled]).is-focused:hover, - .field.has-addons .control .input:not([disabled]):active:hover, - .field.has-addons .control .input:not([disabled]).is-active:hover, - .field.has-addons .control .select select:not([disabled]):focus:hover, - .field.has-addons .control .select select:not([disabled]).is-focused:hover, - .field.has-addons .control .select select:not([disabled]):active:hover, - .field.has-addons .control .select select:not([disabled]).is-active:hover { - z-index: 4; - } - - .field.has-addons .control.is-expanded { - -webkit-box-flex: 1; - -ms-flex-positive: 1; - flex-grow: 1; - -ms-flex-negative: 1; - flex-shrink: 1; - } - - .field.has-addons.has-addons-centered { - -webkit-box-pack: center; - -ms-flex-pack: center; - justify-content: center; - } - - .field.has-addons.has-addons-right { - -webkit-box-pack: end; - -ms-flex-pack: end; - justify-content: flex-end; - } - - .field.has-addons.has-addons-fullwidth .control { - -webkit-box-flex: 1; - -ms-flex-positive: 1; - flex-grow: 1; - -ms-flex-negative: 0; - flex-shrink: 0; - } - -.field.is-grouped { - display: -webkit-box; - display: -ms-flexbox; - display: flex; - -webkit-box-pack: start; - -ms-flex-pack: start; - justify-content: flex-start; -} - - .field.is-grouped > .control { - -ms-flex-negative: 0; - flex-shrink: 0; - } - - .field.is-grouped > .control:not(:last-child) { - margin-bottom: 0; - margin-right: 0.75rem; - } - - .field.is-grouped > .control.is-expanded { - -webkit-box-flex: 1; - -ms-flex-positive: 1; - flex-grow: 1; - -ms-flex-negative: 1; - flex-shrink: 1; - } - - .field.is-grouped.is-grouped-centered { - -webkit-box-pack: center; - -ms-flex-pack: center; - justify-content: center; - } - - .field.is-grouped.is-grouped-right { - -webkit-box-pack: end; - -ms-flex-pack: end; - justify-content: flex-end; - } - - .field.is-grouped.is-grouped-multiline { - -ms-flex-wrap: wrap; - flex-wrap: wrap; - } - - .field.is-grouped.is-grouped-multiline > .control:last-child, .field.is-grouped.is-grouped-multiline > .control:not(:last-child) { - margin-bottom: 0.75rem; - } - - .field.is-grouped.is-grouped-multiline:last-child { - margin-bottom: -0.75rem; - } - - .field.is-grouped.is-grouped-multiline:not(:last-child) { - margin-bottom: 0; - } - -@media screen and (min-width: 769px), print { - .field.is-horizontal { - display: -webkit-box; - display: -ms-flexbox; - display: flex; - } -} - -.field-label .label { - font-size: inherit; -} - -@media screen and (max-width: 768px) { - .field-label { - margin-bottom: 0.5rem; - } -} - -@media screen and (min-width: 769px), print { - .field-label { - -ms-flex-preferred-size: 0; - flex-basis: 0; - -webkit-box-flex: 1; - -ms-flex-positive: 1; - flex-grow: 1; - -ms-flex-negative: 0; - flex-shrink: 0; - margin-right: 1.5rem; - text-align: right; - } - - .field-label.is-small { - font-size: 0.75rem; - padding-top: 0.375em; - } - - .field-label.is-normal { - padding-top: 0.375em; - } - - .field-label.is-medium { - font-size: 1.25rem; - padding-top: 0.375em; - } - - .field-label.is-large { - font-size: 1.5rem; - padding-top: 0.375em; - } -} - -.field-body .field .field { - margin-bottom: 0; -} - -@media screen and (min-width: 769px), print { - .field-body { - display: -webkit-box; - display: -ms-flexbox; - display: flex; - -ms-flex-preferred-size: 0; - flex-basis: 0; - -webkit-box-flex: 5; - -ms-flex-positive: 5; - flex-grow: 5; - -ms-flex-negative: 1; - flex-shrink: 1; - } - - .field-body .field { - margin-bottom: 0; - } - - .field-body > .field { - -ms-flex-negative: 1; - flex-shrink: 1; - } - - .field-body > .field:not(.is-narrow) { - -webkit-box-flex: 1; - -ms-flex-positive: 1; - flex-grow: 1; - } - - .field-body > .field:not(:last-child) { - margin-right: 0.75rem; - } -} - -.control { - -webkit-box-sizing: border-box; - box-sizing: border-box; - clear: both; - font-size: 1rem; - position: relative; - text-align: inherit; -} - - .control.has-icons-left .input:focus ~ .icon, - .control.has-icons-left .select:focus ~ .icon, .control.has-icons-right .input:focus ~ .icon, - .control.has-icons-right .select:focus ~ .icon { - color: #4a4a4a; - } - - .control.has-icons-left .input.is-small ~ .icon, - .control.has-icons-left .select.is-small ~ .icon, .control.has-icons-right .input.is-small ~ .icon, - .control.has-icons-right .select.is-small ~ .icon { - font-size: 0.75rem; - } - - .control.has-icons-left .input.is-medium ~ .icon, - .control.has-icons-left .select.is-medium ~ .icon, .control.has-icons-right .input.is-medium ~ .icon, - .control.has-icons-right .select.is-medium ~ .icon { - font-size: 1.25rem; - } - - .control.has-icons-left .input.is-large ~ .icon, - .control.has-icons-left .select.is-large ~ .icon, .control.has-icons-right .input.is-large ~ .icon, - .control.has-icons-right .select.is-large ~ .icon { - font-size: 1.5rem; - } - - .control.has-icons-left .icon, .control.has-icons-right .icon { - color: #dbdbdb; - height: 2.5em; - pointer-events: none; - position: absolute; - top: 0; - width: 2.5em; - z-index: 4; - } - - .control.has-icons-left .input, - .control.has-icons-left .select select { - padding-left: 2.5em; - } - - .control.has-icons-left .icon.is-left { - left: 0; - } - - .control.has-icons-right .input, - .control.has-icons-right .select select { - padding-right: 2.5em; - } - - .control.has-icons-right .icon.is-right { - right: 0; - } - - .control.is-loading::after { - position: absolute !important; - right: 0.625em; - top: 0.625em; - z-index: 4; - } - - .control.is-loading.is-small:after { - font-size: 0.75rem; - } - - .control.is-loading.is-medium:after { - font-size: 1.25rem; - } - - .control.is-loading.is-large:after { - font-size: 1.5rem; - } - -/* Bulma Components */ -.breadcrumb { - font-size: 1rem; - white-space: nowrap; -} - - .breadcrumb a { - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - color: #378BBA; - display: -webkit-box; - display: -ms-flexbox; - display: flex; - -webkit-box-pack: center; - -ms-flex-pack: center; - justify-content: center; - padding: 0 0.75em; - } - - .breadcrumb a:hover { - color: #A00975; - } - - .breadcrumb li { - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - display: -webkit-box; - display: -ms-flexbox; - display: flex; - } - - .breadcrumb li:first-child a { - padding-left: 0; - } - - .breadcrumb li.is-active a, .breadcrumb li.active a { - color: #363636; - cursor: default; - pointer-events: none; - } - - .breadcrumb li + li::before { - color: #b5b5b5; - content: "\0002f"; - } - - .breadcrumb ul, - .breadcrumb ol { - -webkit-box-align: start; - -ms-flex-align: start; - align-items: flex-start; - display: -webkit-box; - display: -ms-flexbox; - display: flex; - -ms-flex-wrap: wrap; - flex-wrap: wrap; - -webkit-box-pack: start; - -ms-flex-pack: start; - justify-content: flex-start; - } - - .breadcrumb .icon:first-child { - margin-right: 0.5em; - } - - .breadcrumb .icon:last-child { - margin-left: 0.5em; - } - - .breadcrumb.is-centered ol, - .breadcrumb.is-centered ul { - -webkit-box-pack: center; - -ms-flex-pack: center; - justify-content: center; - } - - .breadcrumb.is-right ol, - .breadcrumb.is-right ul { - -webkit-box-pack: end; - -ms-flex-pack: end; - justify-content: flex-end; - } - - .breadcrumb.is-small { - font-size: 0.75rem; - } - - .breadcrumb.is-medium { - font-size: 1.25rem; - } - - .breadcrumb.is-large { - font-size: 1.5rem; - } - - .breadcrumb.has-arrow-separator li + li::before { - content: "\02192"; - } - - .breadcrumb.has-bullet-separator li + li::before { - content: "\02022"; - } - - .breadcrumb.has-dot-separator li + li::before { - content: "\000b7"; - } - - .breadcrumb.has-succeeds-separator li + li::before { - content: "\0227B"; - } - -.card { - background-color: white; - border-radius: 0.25rem; - -webkit-box-shadow: 0 0.5em 1em -0.125em rgba(10, 10, 10, 0.1), 0 0px 0 1px rgba(10, 10, 10, 0.02); - box-shadow: 0 0.5em 1em -0.125em rgba(10, 10, 10, 0.1), 0 0px 0 1px rgba(10, 10, 10, 0.02); - color: #4a4a4a; - max-width: 100%; - position: relative; -} - -.card-footer:first-child, .card-content:first-child, .card-header:first-child { - border-top-left-radius: 0.25rem; - border-top-right-radius: 0.25rem; -} - -.card-footer:last-child, .card-content:last-child, .card-header:last-child { - border-bottom-left-radius: 0.25rem; - border-bottom-right-radius: 0.25rem; -} - -.card-header { - background-color: transparent; - -webkit-box-align: stretch; - -ms-flex-align: stretch; - align-items: stretch; - -webkit-box-shadow: 0 0.125em 0.25em rgba(10, 10, 10, 0.1); - box-shadow: 0 0.125em 0.25em rgba(10, 10, 10, 0.1); - display: -webkit-box; - display: -ms-flexbox; - display: flex; -} - -.card-header-title { - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - color: #363636; - display: -webkit-box; - display: -ms-flexbox; - display: flex; - -webkit-box-flex: 1; - -ms-flex-positive: 1; - flex-grow: 1; - font-weight: 700; - padding: 0.75rem 1rem; -} - - .card-header-title.is-centered { - -webkit-box-pack: center; - -ms-flex-pack: center; - justify-content: center; - } - -.card-header-icon { - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - cursor: pointer; - display: -webkit-box; - display: -ms-flexbox; - display: flex; - -webkit-box-pack: center; - -ms-flex-pack: center; - justify-content: center; - padding: 0.75rem 1rem; -} - -.card-image { - display: block; - position: relative; -} - - .card-image:first-child img { - border-top-left-radius: 0.25rem; - border-top-right-radius: 0.25rem; - } - - .card-image:last-child img { - border-bottom-left-radius: 0.25rem; - border-bottom-right-radius: 0.25rem; - } - -.card-content { - background-color: transparent; - padding: 1.5rem; -} - -.card-footer { - background-color: transparent; - border-top: 1px solid #ededed; - -webkit-box-align: stretch; - -ms-flex-align: stretch; - align-items: stretch; - display: -webkit-box; - display: -ms-flexbox; - display: flex; -} - -.card-footer-item { - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - display: -webkit-box; - display: -ms-flexbox; - display: flex; - -ms-flex-preferred-size: 0; - flex-basis: 0; - -webkit-box-flex: 1; - -ms-flex-positive: 1; - flex-grow: 1; - -ms-flex-negative: 0; - flex-shrink: 0; - -webkit-box-pack: center; - -ms-flex-pack: center; - justify-content: center; - padding: 0.75rem; -} - - .card-footer-item:not(:last-child) { - border-right: 1px solid #ededed; - } - -.card .media:not(:last-child) { - margin-bottom: 1.5rem; -} - -.dropdown { - display: -webkit-inline-box; - display: -ms-inline-flexbox; - display: inline-flex; - position: relative; - vertical-align: top; -} - - .dropdown.is-active .dropdown-menu, .dropdown.active .dropdown-menu, .dropdown.is-hoverable:hover .dropdown-menu { - display: block; - } - - .dropdown.is-right .dropdown-menu { - left: auto; - right: 0; - } - - .dropdown.is-up .dropdown-menu { - bottom: 100%; - padding-bottom: 4px; - padding-top: initial; - top: auto; - } - -.dropdown-menu { - display: none; - left: 0; - min-width: 12rem; - padding-top: 4px; - position: absolute; - top: 100%; - z-index: 20; -} - -.dropdown-content { - background-color: white; - border-radius: 4px; - -webkit-box-shadow: 0 0.5em 1em -0.125em rgba(10, 10, 10, 0.1), 0 0px 0 1px rgba(10, 10, 10, 0.02); - box-shadow: 0 0.5em 1em -0.125em rgba(10, 10, 10, 0.1), 0 0px 0 1px rgba(10, 10, 10, 0.02); - padding-bottom: 0.5rem; - padding-top: 0.5rem; -} - -.dropdown-item { - color: #4a4a4a; - display: block; - font-size: 0.875rem; - line-height: 1.5; - padding: 0.375rem 1rem; - position: relative; -} - -a.dropdown-item, -button.dropdown-item { - padding-right: 3rem; - text-align: inherit; - white-space: nowrap; - width: 100%; -} - - a.dropdown-item:hover, - button.dropdown-item:hover { - background-color: whitesmoke; - color: #0a0a0a; - } - - a.dropdown-item.is-active, .dropdown-item.active, - button.dropdown-item.is-active { - background-color: #378BBA; - color: #fff; - } - -.dropdown-divider { - background-color: #ededed; - border: none; - display: block; - height: 1px; - margin: 0.5rem 0; -} - -.level { - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-pack: justify; - -ms-flex-pack: justify; - justify-content: space-between; -} - - .level code { - border-radius: 4px; - } - - .level img { - display: inline-block; - vertical-align: top; - } - - .level.is-mobile { - display: -webkit-box; - display: -ms-flexbox; - display: flex; - } - - .level.is-mobile .level-left, - .level.is-mobile .level-right { - display: -webkit-box; - display: -ms-flexbox; - display: flex; - } - - .level.is-mobile .level-left + .level-right { - margin-top: 0; - } - - .level.is-mobile .level-item:not(:last-child) { - margin-bottom: 0; - margin-right: 0.75rem; - } - - .level.is-mobile .level-item:not(.is-narrow) { - -webkit-box-flex: 1; - -ms-flex-positive: 1; - flex-grow: 1; - } - -@media screen and (min-width: 769px), print { - .level { - display: -webkit-box; - display: -ms-flexbox; - display: flex; - } - - .level > .level-item:not(.is-narrow) { - -webkit-box-flex: 1; - -ms-flex-positive: 1; - flex-grow: 1; - } -} - -.level-item { - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - display: -webkit-box; - display: -ms-flexbox; - display: flex; - -ms-flex-preferred-size: auto; - flex-basis: auto; - -webkit-box-flex: 0; - -ms-flex-positive: 0; - flex-grow: 0; - -ms-flex-negative: 0; - flex-shrink: 0; - -webkit-box-pack: center; - -ms-flex-pack: center; - justify-content: center; -} - - .level-item .title, - .level-item .subtitle { - margin-bottom: 0; - } - -@media screen and (max-width: 768px) { - .level-item:not(:last-child) { - margin-bottom: 0.75rem; - } -} - -.level-left, -.level-right { - -ms-flex-preferred-size: auto; - flex-basis: auto; - -webkit-box-flex: 0; - -ms-flex-positive: 0; - flex-grow: 0; - -ms-flex-negative: 0; - flex-shrink: 0; -} - - .level-left .level-item.is-flexible, - .level-right .level-item.is-flexible { - -webkit-box-flex: 1; - -ms-flex-positive: 1; - flex-grow: 1; - } - -@media screen and (min-width: 769px), print { - .level-left .level-item:not(:last-child), - .level-right .level-item:not(:last-child) { - margin-right: 0.75rem; - } -} - -.level-left { - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-pack: start; - -ms-flex-pack: start; - justify-content: flex-start; -} - -@media screen and (max-width: 768px) { - .level-left + .level-right { - margin-top: 1.5rem; - } -} - -@media screen and (min-width: 769px), print { - .level-left { - display: -webkit-box; - display: -ms-flexbox; - display: flex; - } -} - -.level-right { - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-pack: end; - -ms-flex-pack: end; - justify-content: flex-end; -} - -@media screen and (min-width: 769px), print { - .level-right { - display: -webkit-box; - display: -ms-flexbox; - display: flex; - } -} - -.media { - -webkit-box-align: start; - -ms-flex-align: start; - align-items: flex-start; - display: -webkit-box; - display: -ms-flexbox; - display: flex; - text-align: inherit; -} - - .media .content:not(:last-child) { - margin-bottom: 0.75rem; - } - - .media .media { - border-top: 1px solid rgba(219, 219, 219, 0.5); - display: -webkit-box; - display: -ms-flexbox; - display: flex; - padding-top: 0.75rem; - } - - .media .media .content:not(:last-child), - .media .media .control:not(:last-child) { - margin-bottom: 0.5rem; - } - - .media .media .media { - padding-top: 0.5rem; - } - - .media .media .media + .media { - margin-top: 0.5rem; - } - - .media + .media { - border-top: 1px solid rgba(219, 219, 219, 0.5); - margin-top: 1rem; - padding-top: 1rem; - } - - .media.is-large + .media { - margin-top: 1.5rem; - padding-top: 1.5rem; - } - -.media-left, -.media-right { - -ms-flex-preferred-size: auto; - flex-basis: auto; - -webkit-box-flex: 0; - -ms-flex-positive: 0; - flex-grow: 0; - -ms-flex-negative: 0; - flex-shrink: 0; -} - -.media-left { - margin-right: 1rem; -} - -.media-right { - margin-left: 1rem; -} - -.media-content { - -ms-flex-preferred-size: auto; - flex-basis: auto; - -webkit-box-flex: 1; - -ms-flex-positive: 1; - flex-grow: 1; - -ms-flex-negative: 1; - flex-shrink: 1; - text-align: inherit; -} - -@media screen and (max-width: 768px) { - .media-content { - overflow-x: auto; - } -} - -.menu { - font-size: 1rem; -} - - .menu.is-small { - font-size: 0.75rem; - } - - .menu.is-medium { - font-size: 1.25rem; - } - - .menu.is-large { - font-size: 1.5rem; - } - -.menu-list, .navbar-nav { - line-height: 1.25; -} - - .menu-list a, .navbar-nav a { - border-radius: 2px; - color: #4a4a4a; - display: block; - padding: 0.5em 0.75em; - } - - .menu-list a:hover, .navbar-nav a:hover { - background-color: whitesmoke; - color: #363636; - } - - .menu-list a.is-active, .menu-list a.active, .navbar-nav a.is-active, .navbar-nav a.active { - background-color: #378BBA; - color: #fff; - } - - .menu-list li ul, .navbar-nav li ul { - border-left: 1px solid #dbdbdb; - margin: 0.75em; - padding-left: 0.75em; - } - -.menu-label, .nav-header { - color: #7a7a7a; - font-size: 0.75em; - letter-spacing: 0.1em; - text-transform: uppercase; -} - - .menu-label:not(:first-child), .nav-header:not(:first-child) { - margin-top: 1em; - } - - .menu-label:not(:last-child), .nav-header:not(:last-child) { - margin-bottom: 1em; - } - -.message { - background-color: whitesmoke; - border-radius: 4px; - font-size: 1rem; -} - - .message strong { - color: currentColor; - } - - .message a:not(.button):not(.tag):not(.dropdown-item) { - color: currentColor; - text-decoration: underline; - } - - .message.is-small { - font-size: 0.75rem; - } - - .message.is-medium { - font-size: 1.25rem; - } - - .message.is-large { - font-size: 1.5rem; - } - - .message.is-white { - background-color: white; - } - - .message.is-white .message-header { - background-color: white; - color: #0a0a0a; - } - - .message.is-white .message-body { - border-color: white; - } - - .message.is-black { - background-color: #fafafa; - } - - .message.is-black .message-header { - background-color: #0a0a0a; - color: white; - } - - .message.is-black .message-body { - border-color: #0a0a0a; - } - - .message.is-light { - background-color: #fafafa; - } - - .message.is-light .message-header { - background-color: whitesmoke; - color: rgba(0, 0, 0, 0.7); - } - - .message.is-light .message-body { - border-color: whitesmoke; - } - - .message.is-dark { - background-color: #fff5fc; - } - - .message.is-dark .message-header { - background-color: #200117; - color: #fff; - } - - .message.is-dark .message-body { - border-color: #200117; - } - - .message.is-primary { - background-color: #feecf9; - } - - .message.is-primary .message-header { - background-color: #A00975; - color: #fff; - } - - .message.is-primary .message-body { - border-color: #A00975; - color: #f212b2; - } - - .message.is-link { - background-color: #eff6fa; - } - - .message.is-link .message-header { - background-color: #378BBA; - color: #fff; - } - - .message.is-link .message-body { - border-color: #378BBA; - color: #317ca5; - } - - .message.is-info { - background-color: #eef6fc; - } - - .message.is-info .message-header { - background-color: #3298dc; - color: #fff; - } - - .message.is-info .message-body { - border-color: #3298dc; - color: #1d72aa; - } - - .message.is-success { - background-color: #effaf3; - } - - .message.is-success .message-header { - background-color: #48c774; - color: #fff; - } - - .message.is-success .message-body { - border-color: #48c774; - color: #257942; - } - - .message.is-warning { - background-color: #fffbeb; - } - - .message.is-warning .message-header { - background-color: #ffdd57; - color: rgba(0, 0, 0, 0.7); - } - - .message.is-warning .message-body { - border-color: #ffdd57; - color: #947600; - } - - .message.is-danger { - background-color: #feecf0; - } - - .message.is-danger .message-header { - background-color: #f14668; - color: #fff; - } - - .message.is-danger .message-body { - border-color: #f14668; - color: #cc0f35; - } - -.message-header { - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - background-color: #4a4a4a; - border-radius: 4px 4px 0 0; - color: #fff; - display: -webkit-box; - display: -ms-flexbox; - display: flex; - font-weight: 700; - -webkit-box-pack: justify; - -ms-flex-pack: justify; - justify-content: space-between; - line-height: 1.25; - padding: 0.75em 1em; - position: relative; -} - - .message-header .delete { - -webkit-box-flex: 0; - -ms-flex-positive: 0; - flex-grow: 0; - -ms-flex-negative: 0; - flex-shrink: 0; - margin-left: 0.75em; - } - - .message-header + .message-body { - border-width: 0; - border-top-left-radius: 0; - border-top-right-radius: 0; - } - -.message-body { - border-color: #dbdbdb; - border-radius: 4px; - border-style: solid; - border-width: 0 0 0 4px; - color: #4a4a4a; - padding: 1.25em 1.5em; -} - - .message-body code, - .message-body pre { - background-color: white; - } - - .message-body pre code { - background-color: transparent; - } - -.modal { - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - display: none; - -webkit-box-orient: vertical; - -webkit-box-direction: normal; - -ms-flex-direction: column; - flex-direction: column; - -webkit-box-pack: center; - -ms-flex-pack: center; - justify-content: center; - overflow: hidden; - position: fixed; - z-index: 40; -} - - .modal.is-active, .modal.active { - display: -webkit-box; - display: -ms-flexbox; - display: flex; - } - -.modal-background { - background-color: rgba(10, 10, 10, 0.86); -} - -.modal-content, -.modal-card { - margin: 0 20px; - max-height: calc(100vh - 160px); - overflow: auto; - position: relative; - width: 100%; -} - -@media screen and (min-width: 769px) { - .modal-content, - .modal-card { - margin: 0 auto; - max-height: calc(100vh - 40px); - width: 640px; - } -} - -.modal-close { - background: none; - height: 40px; - position: fixed; - right: 20px; - top: 20px; - width: 40px; -} - -.modal-card { - display: -webkit-box; - display: -ms-flexbox; - display: flex; - -webkit-box-orient: vertical; - -webkit-box-direction: normal; - -ms-flex-direction: column; - flex-direction: column; - max-height: calc(100vh - 40px); - overflow: hidden; - -ms-overflow-y: visible; -} - -.modal-card-head, -.modal-card-foot { - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - background-color: whitesmoke; - display: -webkit-box; - display: -ms-flexbox; - display: flex; - -ms-flex-negative: 0; - flex-shrink: 0; - -webkit-box-pack: start; - -ms-flex-pack: start; - justify-content: flex-start; - padding: 20px; - position: relative; -} - -.modal-card-head { - border-bottom: 1px solid #dbdbdb; - border-top-left-radius: 6px; - border-top-right-radius: 6px; -} - -.modal-card-title { - color: #363636; - -webkit-box-flex: 1; - -ms-flex-positive: 1; - flex-grow: 1; - -ms-flex-negative: 0; - flex-shrink: 0; - font-size: 1.5rem; - line-height: 1; -} - -.modal-card-foot { - border-bottom-left-radius: 6px; - border-bottom-right-radius: 6px; - border-top: 1px solid #dbdbdb; -} - - .modal-card-foot .button:not(:last-child) { - margin-right: 0.5em; - } - -.modal-card-body { - -webkit-overflow-scrolling: touch; - background-color: white; - -webkit-box-flex: 1; - -ms-flex-positive: 1; - flex-grow: 1; - -ms-flex-negative: 1; - flex-shrink: 1; - overflow: auto; - padding: 20px; -} - -.navbar { - background-color: white; - min-height: 3.25rem; - position: relative; - z-index: 30; -} - - .navbar.is-white { - background-color: white; - color: #0a0a0a; - } - - .navbar.is-white .navbar-brand > .navbar-item, - .navbar.is-white .navbar-brand .navbar-link { - color: #0a0a0a; - } - - .navbar.is-white .navbar-brand > a.navbar-item:focus, .navbar.is-white .navbar-brand > a.navbar-item:hover, .navbar.is-white .navbar-brand > a.navbar-item.is-active, .navbar.is-white .navbar-brand > .navbar-item.active, - .navbar.is-white .navbar-brand .navbar-link:focus, - .navbar.is-white .navbar-brand .navbar-link:hover, - .navbar.is-white .navbar-brand .navbar-link.is-active, - .navbar.is-white .navbar-brand .navbar-link.active { - background-color: #f2f2f2; - color: #0a0a0a; - } - - .navbar.is-white .navbar-brand .navbar-link::after { - border-color: #0a0a0a; - } - - .navbar.is-white .navbar-burger { - color: #0a0a0a; - } - -@media screen and (min-width: 1024px) { - .navbar.is-white .navbar-start > .navbar-item, - .navbar.is-white .navbar-start .navbar-link, - .navbar.is-white .navbar-end > .navbar-item, - .navbar.is-white .navbar-end .navbar-link { - color: #0a0a0a; - } - - .navbar.is-white .navbar-start > a.navbar-item:focus, .navbar.is-white .navbar-start > a.navbar-item:hover, .navbar.is-white .navbar-start > a.navbar-item.is-active, .navbar.is-white .navbar-start > .navbar-item.active, - .navbar.is-white .navbar-start .navbar-link:focus, - .navbar.is-white .navbar-start .navbar-link:hover, - .navbar.is-white .navbar-start .navbar-link.is-active, - .navbar.is-white .navbar-start .navbar-link.active, - .navbar.is-white .navbar-end > a.navbar-item:focus, - .navbar.is-white .navbar-end > a.navbar-item:hover, - .navbar.is-white .navbar-end > a.navbar-item.is-active, - .navbar.is-white .navbar-end > .navbar-item.active, - .navbar.is-white .navbar-end .navbar-link:focus, - .navbar.is-white .navbar-end .navbar-link:hover, - .navbar.is-white .navbar-end .navbar-link.is-active, - .navbar.is-white .navbar-end .navbar-link.active { - background-color: #f2f2f2; - color: #0a0a0a; - } - - .navbar.is-white .navbar-start .navbar-link::after, - .navbar.is-white .navbar-end .navbar-link::after { - border-color: #0a0a0a; - } - - .navbar.is-white .navbar-item.has-dropdown:focus .navbar-link, - .navbar.is-white .navbar-item.has-dropdown:hover .navbar-link, - .navbar.is-white .navbar-item.has-dropdown.is-active .navbar-link, - .navbar.is-white .has-dropdown.active .navbar-link { - background-color: #f2f2f2; - color: #0a0a0a; - } - - .navbar.is-white .navbar-dropdown a.navbar-item.is-active, .navbar.is-white .navbar-dropdown .navbar-item.active { - background-color: white; - color: #0a0a0a; - } -} - -.navbar.is-black { - background-color: #0a0a0a; - color: white; -} - - .navbar.is-black .navbar-brand > .navbar-item, - .navbar.is-black .navbar-brand .navbar-link { - color: white; - } - - .navbar.is-black .navbar-brand > a.navbar-item:focus, .navbar.is-black .navbar-brand > a.navbar-item:hover, .navbar.is-black .navbar-brand > a.navbar-item.is-active, .navbar.is-black .navbar-brand > .navbar-item.active, - .navbar.is-black .navbar-brand .navbar-link:focus, - .navbar.is-black .navbar-brand .navbar-link:hover, - .navbar.is-black .navbar-brand .navbar-link.is-active, - .navbar.is-black .navbar-brand .navbar-link.active { - background-color: black; - color: white; - } - - .navbar.is-black .navbar-brand .navbar-link::after { - border-color: white; - } - - .navbar.is-black .navbar-burger { - color: white; - } - -@media screen and (min-width: 1024px) { - .navbar.is-black .navbar-start > .navbar-item, - .navbar.is-black .navbar-start .navbar-link, - .navbar.is-black .navbar-end > .navbar-item, - .navbar.is-black .navbar-end .navbar-link { - color: white; - } - - .navbar.is-black .navbar-start > a.navbar-item:focus, .navbar.is-black .navbar-start > a.navbar-item:hover, .navbar.is-black .navbar-start > a.navbar-item.is-active, .navbar.is-black .navbar-start > .navbar-item.active, - .navbar.is-black .navbar-start .navbar-link:focus, - .navbar.is-black .navbar-start .navbar-link:hover, - .navbar.is-black .navbar-start .navbar-link.is-active, - .navbar.is-black .navbar-start .navbar-link.active, - .navbar.is-black .navbar-end > a.navbar-item:focus, - .navbar.is-black .navbar-end > a.navbar-item:hover, - .navbar.is-black .navbar-end > a.navbar-item.is-active, - .navbar.is-black .navbar-end > .navbar-item.active, - .navbar.is-black .navbar-end .navbar-link:focus, - .navbar.is-black .navbar-end .navbar-link:hover, - .navbar.is-black .navbar-end .navbar-link.is-active, - .navbar.is-black .navbar-end .navbar-link.active { - background-color: black; - color: white; - } - - .navbar.is-black .navbar-start .navbar-link::after, - .navbar.is-black .navbar-end .navbar-link::after { - border-color: white; - } - - .navbar.is-black .navbar-item.has-dropdown:focus .navbar-link, - .navbar.is-black .navbar-item.has-dropdown:hover .navbar-link, - .navbar.is-black .navbar-item.has-dropdown.is-active .navbar-link, - .navbar.is-black .has-dropdown.active .navbar-link { - background-color: black; - color: white; - } - - .navbar.is-black .navbar-dropdown a.navbar-item.is-active, .navbar.is-black .navbar-dropdown .navbar-item.active { - background-color: #0a0a0a; - color: white; - } -} - -.navbar.is-light { - background-color: whitesmoke; - color: rgba(0, 0, 0, 0.7); -} - - .navbar.is-light .navbar-brand > .navbar-item, - .navbar.is-light .navbar-brand .navbar-link { - color: rgba(0, 0, 0, 0.7); - } - - .navbar.is-light .navbar-brand > a.navbar-item:focus, .navbar.is-light .navbar-brand > a.navbar-item:hover, .navbar.is-light .navbar-brand > a.navbar-item.is-active, .navbar.is-light .navbar-brand > .navbar-item.active, - .navbar.is-light .navbar-brand .navbar-link:focus, - .navbar.is-light .navbar-brand .navbar-link:hover, - .navbar.is-light .navbar-brand .navbar-link.is-active, - .navbar.is-light .navbar-brand .navbar-link.active { - background-color: #e8e8e8; - color: rgba(0, 0, 0, 0.7); - } - - .navbar.is-light .navbar-brand .navbar-link::after { - border-color: rgba(0, 0, 0, 0.7); - } - - .navbar.is-light .navbar-burger { - color: rgba(0, 0, 0, 0.7); - } - -@media screen and (min-width: 1024px) { - .navbar.is-light .navbar-start > .navbar-item, - .navbar.is-light .navbar-start .navbar-link, - .navbar.is-light .navbar-end > .navbar-item, - .navbar.is-light .navbar-end .navbar-link { - color: rgba(0, 0, 0, 0.7); - } - - .navbar.is-light .navbar-start > a.navbar-item:focus, .navbar.is-light .navbar-start > a.navbar-item:hover, .navbar.is-light .navbar-start > a.navbar-item.is-active, .navbar.is-light .navbar-start > .navbar-item.active, - .navbar.is-light .navbar-start .navbar-link:focus, - .navbar.is-light .navbar-start .navbar-link:hover, - .navbar.is-light .navbar-start .navbar-link.is-active, - .navbar.is-light .navbar-start .navbar-link.active, - .navbar.is-light .navbar-end > a.navbar-item:focus, - .navbar.is-light .navbar-end > a.navbar-item:hover, - .navbar.is-light .navbar-end > a.navbar-item.is-active, - .navbar.is-light .navbar-end > .navbar-item.active, - .navbar.is-light .navbar-end .navbar-link:focus, - .navbar.is-light .navbar-end .navbar-link:hover, - .navbar.is-light .navbar-end .navbar-link.is-active, - .navbar.is-light .navbar-end .navbar-link.active { - background-color: #e8e8e8; - color: rgba(0, 0, 0, 0.7); - } - - .navbar.is-light .navbar-start .navbar-link::after, - .navbar.is-light .navbar-end .navbar-link::after { - border-color: rgba(0, 0, 0, 0.7); - } - - .navbar.is-light .navbar-item.has-dropdown:focus .navbar-link, - .navbar.is-light .navbar-item.has-dropdown:hover .navbar-link, - .navbar.is-light .navbar-item.has-dropdown.is-active .navbar-link, - .navbar.is-light .has-dropdown.active .navbar-link { - background-color: #e8e8e8; - color: rgba(0, 0, 0, 0.7); - } - - .navbar.is-light .navbar-dropdown a.navbar-item.is-active, .navbar.is-light .navbar-dropdown .navbar-item.active { - background-color: whitesmoke; - color: rgba(0, 0, 0, 0.7); - } -} - -.navbar.is-dark { - background-color: #200117; - color: #fff; -} - - .navbar.is-dark .navbar-brand > .navbar-item, - .navbar.is-dark .navbar-brand .navbar-link { - color: #fff; - } - - .navbar.is-dark .navbar-brand > a.navbar-item:focus, .navbar.is-dark .navbar-brand > a.navbar-item:hover, .navbar.is-dark .navbar-brand > a.navbar-item.is-active, .navbar.is-dark .navbar-brand > .navbar-item.active, - .navbar.is-dark .navbar-brand .navbar-link:focus, - .navbar.is-dark .navbar-brand .navbar-link:hover, - .navbar.is-dark .navbar-brand .navbar-link.is-active, - .navbar.is-dark .navbar-brand .navbar-link.active { - background-color: #070005; - color: #fff; - } - - .navbar.is-dark .navbar-brand .navbar-link::after { - border-color: #fff; - } - - .navbar.is-dark .navbar-burger { - color: #fff; - } - -@media screen and (min-width: 1024px) { - .navbar.is-dark .navbar-start > .navbar-item, - .navbar.is-dark .navbar-start .navbar-link, - .navbar.is-dark .navbar-end > .navbar-item, - .navbar.is-dark .navbar-end .navbar-link { - color: #fff; - } - - .navbar.is-dark .navbar-start > a.navbar-item:focus, .navbar.is-dark .navbar-start > a.navbar-item:hover, .navbar.is-dark .navbar-start > a.navbar-item.is-active, .navbar.is-dark .navbar-start > .navbar-item.active, - .navbar.is-dark .navbar-start .navbar-link:focus, - .navbar.is-dark .navbar-start .navbar-link:hover, - .navbar.is-dark .navbar-start .navbar-link.is-active, - .navbar.is-dark .navbar-start .navbar-link.active, - .navbar.is-dark .navbar-end > a.navbar-item:focus, - .navbar.is-dark .navbar-end > a.navbar-item:hover, - .navbar.is-dark .navbar-end > a.navbar-item.is-active, - .navbar.is-dark .navbar-end > .navbar-item.active, - .navbar.is-dark .navbar-end .navbar-link:focus, - .navbar.is-dark .navbar-end .navbar-link:hover, - .navbar.is-dark .navbar-end .navbar-link.is-active, - .navbar.is-dark .navbar-end .navbar-link.active { - background-color: #070005; - color: #fff; - } - - .navbar.is-dark .navbar-start .navbar-link::after, - .navbar.is-dark .navbar-end .navbar-link::after { - border-color: #fff; - } - - .navbar.is-dark .navbar-item.has-dropdown:focus .navbar-link, - .navbar.is-dark .navbar-item.has-dropdown:hover .navbar-link, - .navbar.is-dark .navbar-item.has-dropdown.is-active .navbar-link, - .navbar.is-dark .has-dropdown.active .navbar-link { - background-color: #070005; - color: #fff; - } - - .navbar.is-dark .navbar-dropdown a.navbar-item.is-active, .navbar.is-dark .navbar-dropdown .navbar-item.active { - background-color: #200117; - color: #fff; - } -} - -.navbar.is-primary { - background-color: #A00975; - color: #fff; -} - - .navbar.is-primary .navbar-brand > .navbar-item, - .navbar.is-primary .navbar-brand .navbar-link { - color: #fff; - } - - .navbar.is-primary .navbar-brand > a.navbar-item:focus, .navbar.is-primary .navbar-brand > a.navbar-item:hover, .navbar.is-primary .navbar-brand > a.navbar-item.is-active, .navbar.is-primary .navbar-brand > .navbar-item.active, - .navbar.is-primary .navbar-brand .navbar-link:focus, - .navbar.is-primary .navbar-brand .navbar-link:hover, - .navbar.is-primary .navbar-brand .navbar-link.is-active, - .navbar.is-primary .navbar-brand .navbar-link.active { - background-color: #880863; - color: #fff; - } - - .navbar.is-primary .navbar-brand .navbar-link::after { - border-color: #fff; - } - - .navbar.is-primary .navbar-burger { - color: #fff; - } - -@media screen and (min-width: 1024px) { - .navbar.is-primary .navbar-start > .navbar-item, - .navbar.is-primary .navbar-start .navbar-link, - .navbar.is-primary .navbar-end > .navbar-item, - .navbar.is-primary .navbar-end .navbar-link { - color: #fff; - } - - .navbar.is-primary .navbar-start > a.navbar-item:focus, .navbar.is-primary .navbar-start > a.navbar-item:hover, .navbar.is-primary .navbar-start > a.navbar-item.is-active, .navbar.is-primary .navbar-start > .navbar-item.active, - .navbar.is-primary .navbar-start .navbar-link:focus, - .navbar.is-primary .navbar-start .navbar-link:hover, - .navbar.is-primary .navbar-start .navbar-link.is-active, - .navbar.is-primary .navbar-start .navbar-link.active, - .navbar.is-primary .navbar-end > a.navbar-item:focus, - .navbar.is-primary .navbar-end > a.navbar-item:hover, - .navbar.is-primary .navbar-end > a.navbar-item.is-active, - .navbar.is-primary .navbar-end > .navbar-item.active, - .navbar.is-primary .navbar-end .navbar-link:focus, - .navbar.is-primary .navbar-end .navbar-link:hover, - .navbar.is-primary .navbar-end .navbar-link.is-active, - .navbar.is-primary .navbar-end .navbar-link.active { - background-color: #880863; - color: #fff; - } - - .navbar.is-primary .navbar-start .navbar-link::after, - .navbar.is-primary .navbar-end .navbar-link::after { - border-color: #fff; - } - - .navbar.is-primary .navbar-item.has-dropdown:focus .navbar-link, - .navbar.is-primary .navbar-item.has-dropdown:hover .navbar-link, - .navbar.is-primary .navbar-item.has-dropdown.is-active .navbar-link, - .navbar.is-primary .has-dropdown.active .navbar-link { - background-color: #880863; - color: #fff; - } - - .navbar.is-primary .navbar-dropdown a.navbar-item.is-active, .navbar.is-primary .navbar-dropdown .navbar-item.active { - background-color: #A00975; - color: #fff; - } -} - -.navbar.is-link { - background-color: #378BBA; - color: #fff; -} - - .navbar.is-link .navbar-brand > .navbar-item, - .navbar.is-link .navbar-brand .navbar-link { - color: #fff; - } - - .navbar.is-link .navbar-brand > a.navbar-item:focus, .navbar.is-link .navbar-brand > a.navbar-item:hover, .navbar.is-link .navbar-brand > a.navbar-item.is-active, .navbar.is-link .navbar-brand > .navbar-item.active, - .navbar.is-link .navbar-brand .navbar-link:focus, - .navbar.is-link .navbar-brand .navbar-link:hover, - .navbar.is-link .navbar-brand .navbar-link.is-active, - .navbar.is-link .navbar-brand .navbar-link.active { - background-color: #317ca6; - color: #fff; - } - - .navbar.is-link .navbar-brand .navbar-link::after { - border-color: #fff; - } - - .navbar.is-link .navbar-burger { - color: #fff; - } - -@media screen and (min-width: 1024px) { - .navbar.is-link .navbar-start > .navbar-item, - .navbar.is-link .navbar-start .navbar-link, - .navbar.is-link .navbar-end > .navbar-item, - .navbar.is-link .navbar-end .navbar-link { - color: #fff; - } - - .navbar.is-link .navbar-start > a.navbar-item:focus, .navbar.is-link .navbar-start > a.navbar-item:hover, .navbar.is-link .navbar-start > a.navbar-item.is-active, .navbar.is-link .navbar-start > .navbar-item.active, - .navbar.is-link .navbar-start .navbar-link:focus, - .navbar.is-link .navbar-start .navbar-link:hover, - .navbar.is-link .navbar-start .navbar-link.is-active, - .navbar.is-link .navbar-start .navbar-link.active, - .navbar.is-link .navbar-end > a.navbar-item:focus, - .navbar.is-link .navbar-end > a.navbar-item:hover, - .navbar.is-link .navbar-end > a.navbar-item.is-active, - .navbar.is-link .navbar-end > .navbar-item.active, - .navbar.is-link .navbar-end .navbar-link:focus, - .navbar.is-link .navbar-end .navbar-link:hover, - .navbar.is-link .navbar-end .navbar-link.is-active, - .navbar.is-link .navbar-end .navbar-link.active { - background-color: #317ca6; - color: #fff; - } - - .navbar.is-link .navbar-start .navbar-link::after, - .navbar.is-link .navbar-end .navbar-link::after { - border-color: #fff; - } - - .navbar.is-link .navbar-item.has-dropdown:focus .navbar-link, - .navbar.is-link .navbar-item.has-dropdown:hover .navbar-link, - .navbar.is-link .navbar-item.has-dropdown.is-active .navbar-link, - .navbar.is-link .has-dropdown.active .navbar-link { - background-color: #317ca6; - color: #fff; - } - - .navbar.is-link .navbar-dropdown a.navbar-item.is-active, .navbar.is-link .navbar-dropdown .navbar-item.active { - background-color: #378BBA; - color: #fff; - } -} - -.navbar.is-info { - background-color: #3298dc; - color: #fff; -} - - .navbar.is-info .navbar-brand > .navbar-item, - .navbar.is-info .navbar-brand .navbar-link { - color: #fff; - } - - .navbar.is-info .navbar-brand > a.navbar-item:focus, .navbar.is-info .navbar-brand > a.navbar-item:hover, .navbar.is-info .navbar-brand > a.navbar-item.is-active, .navbar.is-info .navbar-brand > .navbar-item.active, - .navbar.is-info .navbar-brand .navbar-link:focus, - .navbar.is-info .navbar-brand .navbar-link:hover, - .navbar.is-info .navbar-brand .navbar-link.is-active, - .navbar.is-info .navbar-brand .navbar-link.active { - background-color: #238cd1; - color: #fff; - } - - .navbar.is-info .navbar-brand .navbar-link::after { - border-color: #fff; - } - - .navbar.is-info .navbar-burger { - color: #fff; - } - -@media screen and (min-width: 1024px) { - .navbar.is-info .navbar-start > .navbar-item, - .navbar.is-info .navbar-start .navbar-link, - .navbar.is-info .navbar-end > .navbar-item, - .navbar.is-info .navbar-end .navbar-link { - color: #fff; - } - - .navbar.is-info .navbar-start > a.navbar-item:focus, .navbar.is-info .navbar-start > a.navbar-item:hover, .navbar.is-info .navbar-start > a.navbar-item.is-active, .navbar.is-info .navbar-start > .navbar-item.active, - .navbar.is-info .navbar-start .navbar-link:focus, - .navbar.is-info .navbar-start .navbar-link:hover, - .navbar.is-info .navbar-start .navbar-link.is-active, - .navbar.is-info .navbar-start .navbar-link.active, - .navbar.is-info .navbar-end > a.navbar-item:focus, - .navbar.is-info .navbar-end > a.navbar-item:hover, - .navbar.is-info .navbar-end > a.navbar-item.is-active, - .navbar.is-info .navbar-end > .navbar-item.active, - .navbar.is-info .navbar-end .navbar-link:focus, - .navbar.is-info .navbar-end .navbar-link:hover, - .navbar.is-info .navbar-end .navbar-link.is-active, - .navbar.is-info .navbar-end .navbar-link.active { - background-color: #238cd1; - color: #fff; - } - - .navbar.is-info .navbar-start .navbar-link::after, - .navbar.is-info .navbar-end .navbar-link::after { - border-color: #fff; - } - - .navbar.is-info .navbar-item.has-dropdown:focus .navbar-link, - .navbar.is-info .navbar-item.has-dropdown:hover .navbar-link, - .navbar.is-info .navbar-item.has-dropdown.is-active .navbar-link, - .navbar.is-info .has-dropdown.active .navbar-link { - background-color: #238cd1; - color: #fff; - } - - .navbar.is-info .navbar-dropdown a.navbar-item.is-active, .navbar.is-info .navbar-dropdown .navbar-item.active { - background-color: #3298dc; - color: #fff; - } -} - -.navbar.is-success { - background-color: #48c774; - color: #fff; -} - - .navbar.is-success .navbar-brand > .navbar-item, - .navbar.is-success .navbar-brand .navbar-link { - color: #fff; - } - - .navbar.is-success .navbar-brand > a.navbar-item:focus, .navbar.is-success .navbar-brand > a.navbar-item:hover, .navbar.is-success .navbar-brand > a.navbar-item.is-active, .navbar.is-success .navbar-brand > .navbar-item.active, - .navbar.is-success .navbar-brand .navbar-link:focus, - .navbar.is-success .navbar-brand .navbar-link:hover, - .navbar.is-success .navbar-brand .navbar-link.is-active, - .navbar.is-success .navbar-brand .navbar-link.active { - background-color: #3abb67; - color: #fff; - } - - .navbar.is-success .navbar-brand .navbar-link::after { - border-color: #fff; - } - - .navbar.is-success .navbar-burger { - color: #fff; - } - -@media screen and (min-width: 1024px) { - .navbar.is-success .navbar-start > .navbar-item, - .navbar.is-success .navbar-start .navbar-link, - .navbar.is-success .navbar-end > .navbar-item, - .navbar.is-success .navbar-end .navbar-link { - color: #fff; - } - - .navbar.is-success .navbar-start > a.navbar-item:focus, .navbar.is-success .navbar-start > a.navbar-item:hover, .navbar.is-success .navbar-start > a.navbar-item.is-active, .navbar.is-success .navbar-start > .navbar-item.active, - .navbar.is-success .navbar-start .navbar-link:focus, - .navbar.is-success .navbar-start .navbar-link:hover, - .navbar.is-success .navbar-start .navbar-link.is-active, - .navbar.is-success .navbar-start .navbar-link.active, - .navbar.is-success .navbar-end > a.navbar-item:focus, - .navbar.is-success .navbar-end > a.navbar-item:hover, - .navbar.is-success .navbar-end > a.navbar-item.is-active, - .navbar.is-success .navbar-end > .navbar-item.active, - .navbar.is-success .navbar-end .navbar-link:focus, - .navbar.is-success .navbar-end .navbar-link:hover, - .navbar.is-success .navbar-end .navbar-link.is-active, - .navbar.is-success .navbar-end .navbar-link.active { - background-color: #3abb67; - color: #fff; - } - - .navbar.is-success .navbar-start .navbar-link::after, - .navbar.is-success .navbar-end .navbar-link::after { - border-color: #fff; - } - - .navbar.is-success .navbar-item.has-dropdown:focus .navbar-link, - .navbar.is-success .navbar-item.has-dropdown:hover .navbar-link, - .navbar.is-success .navbar-item.has-dropdown.is-active .navbar-link, - .navbar.is-success .has-dropdown.active .navbar-link { - background-color: #3abb67; - color: #fff; - } - - .navbar.is-success .navbar-dropdown a.navbar-item.is-active, .navbar.is-success .navbar-dropdown .navbar-item.active { - background-color: #48c774; - color: #fff; - } -} - -.navbar.is-warning { - background-color: #ffdd57; - color: rgba(0, 0, 0, 0.7); -} - - .navbar.is-warning .navbar-brand > .navbar-item, - .navbar.is-warning .navbar-brand .navbar-link { - color: rgba(0, 0, 0, 0.7); - } - - .navbar.is-warning .navbar-brand > a.navbar-item:focus, .navbar.is-warning .navbar-brand > a.navbar-item:hover, .navbar.is-warning .navbar-brand > a.navbar-item.is-active, .navbar.is-warning .navbar-brand > .navbar-item.active, - .navbar.is-warning .navbar-brand .navbar-link:focus, - .navbar.is-warning .navbar-brand .navbar-link:hover, - .navbar.is-warning .navbar-brand .navbar-link.is-active, - .navbar.is-warning .navbar-brand .navbar-link.active { - background-color: #ffd83d; - color: rgba(0, 0, 0, 0.7); - } - - .navbar.is-warning .navbar-brand .navbar-link::after { - border-color: rgba(0, 0, 0, 0.7); - } - - .navbar.is-warning .navbar-burger { - color: rgba(0, 0, 0, 0.7); - } - -@media screen and (min-width: 1024px) { - .navbar.is-warning .navbar-start > .navbar-item, - .navbar.is-warning .navbar-start .navbar-link, - .navbar.is-warning .navbar-end > .navbar-item, - .navbar.is-warning .navbar-end .navbar-link { - color: rgba(0, 0, 0, 0.7); - } - - .navbar.is-warning .navbar-start > a.navbar-item:focus, .navbar.is-warning .navbar-start > a.navbar-item:hover, .navbar.is-warning .navbar-start > a.navbar-item.is-active, .navbar.is-warning .navbar-start > .navbar-item.active, - .navbar.is-warning .navbar-start .navbar-link:focus, - .navbar.is-warning .navbar-start .navbar-link:hover, - .navbar.is-warning .navbar-start .navbar-link.is-active, - .navbar.is-warning .navbar-start .navbar-link.active, - .navbar.is-warning .navbar-end > a.navbar-item:focus, - .navbar.is-warning .navbar-end > a.navbar-item:hover, - .navbar.is-warning .navbar-end > a.navbar-item.is-active, - .navbar.is-warning .navbar-end > .navbar-item.active, - .navbar.is-warning .navbar-end .navbar-link:focus, - .navbar.is-warning .navbar-end .navbar-link:hover, - .navbar.is-warning .navbar-end .navbar-link.is-active, - .navbar.is-warning .navbar-end .navbar-link.active { - background-color: #ffd83d; - color: rgba(0, 0, 0, 0.7); - } - - .navbar.is-warning .navbar-start .navbar-link::after, - .navbar.is-warning .navbar-end .navbar-link::after { - border-color: rgba(0, 0, 0, 0.7); - } - - .navbar.is-warning .navbar-item.has-dropdown:focus .navbar-link, - .navbar.is-warning .navbar-item.has-dropdown:hover .navbar-link, - .navbar.is-warning .navbar-item.has-dropdown.is-active .navbar-link, - .navbar.is-warning .has-dropdown.active .navbar-link { - background-color: #ffd83d; - color: rgba(0, 0, 0, 0.7); - } - - .navbar.is-warning .navbar-dropdown a.navbar-item.is-active, .navbar.is-warning .navbar-dropdown .navbar-item.active { - background-color: #ffdd57; - color: rgba(0, 0, 0, 0.7); - } -} - -.navbar.is-danger { - background-color: #f14668; - color: #fff; -} - - .navbar.is-danger .navbar-brand > .navbar-item, - .navbar.is-danger .navbar-brand .navbar-link { - color: #fff; - } - - .navbar.is-danger .navbar-brand > a.navbar-item:focus, .navbar.is-danger .navbar-brand > a.navbar-item:hover, .navbar.is-danger .navbar-brand > a.navbar-item.is-active, .navbar.is-danger .navbar-brand > .navbar-item.active, - .navbar.is-danger .navbar-brand .navbar-link:focus, - .navbar.is-danger .navbar-brand .navbar-link:hover, - .navbar.is-danger .navbar-brand .navbar-link.is-active, - .navbar.is-danger .navbar-brand .navbar-link.active { - background-color: #ef2e55; - color: #fff; - } - - .navbar.is-danger .navbar-brand .navbar-link::after { - border-color: #fff; - } - - .navbar.is-danger .navbar-burger { - color: #fff; - } - -@media screen and (min-width: 1024px) { - .navbar.is-danger .navbar-start > .navbar-item, - .navbar.is-danger .navbar-start .navbar-link, - .navbar.is-danger .navbar-end > .navbar-item, - .navbar.is-danger .navbar-end .navbar-link { - color: #fff; - } - - .navbar.is-danger .navbar-start > a.navbar-item:focus, .navbar.is-danger .navbar-start > a.navbar-item:hover, .navbar.is-danger .navbar-start > a.navbar-item.is-active, .navbar.is-danger .navbar-start > .navbar-item.active, - .navbar.is-danger .navbar-start .navbar-link:focus, - .navbar.is-danger .navbar-start .navbar-link:hover, - .navbar.is-danger .navbar-start .navbar-link.is-active, - .navbar.is-danger .navbar-start .navbar-link.active, - .navbar.is-danger .navbar-end > a.navbar-item:focus, - .navbar.is-danger .navbar-end > a.navbar-item:hover, - .navbar.is-danger .navbar-end > a.navbar-item.is-active, - .navbar.is-danger .navbar-end > .navbar-item.active, - .navbar.is-danger .navbar-end .navbar-link:focus, - .navbar.is-danger .navbar-end .navbar-link:hover, - .navbar.is-danger .navbar-end .navbar-link.is-active, - .navbar.is-danger .navbar-end .navbar-link.active { - background-color: #ef2e55; - color: #fff; - } - - .navbar.is-danger .navbar-start .navbar-link::after, - .navbar.is-danger .navbar-end .navbar-link::after { - border-color: #fff; - } - - .navbar.is-danger .navbar-item.has-dropdown:focus .navbar-link, - .navbar.is-danger .navbar-item.has-dropdown:hover .navbar-link, - .navbar.is-danger .navbar-item.has-dropdown.is-active .navbar-link, - .navbar.is-danger .has-dropdown.active .navbar-link { - background-color: #ef2e55; - color: #fff; - } - - .navbar.is-danger .navbar-dropdown a.navbar-item.is-active, .navbar.is-danger .navbar-dropdown .navbar-item.active { - background-color: #f14668; - color: #fff; - } -} - -.navbar > .container { - -webkit-box-align: stretch; - -ms-flex-align: stretch; - align-items: stretch; - display: -webkit-box; - display: -ms-flexbox; - display: flex; - min-height: 3.25rem; - width: 100%; -} - -.navbar.has-shadow { - -webkit-box-shadow: 0 2px 0 0 whitesmoke; - box-shadow: 0 2px 0 0 whitesmoke; -} - -.navbar.is-fixed-bottom, .navbar.is-fixed-top { - left: 0; - position: fixed; - right: 0; - z-index: 30; -} - -.navbar.is-fixed-bottom { - bottom: 0; -} - - .navbar.is-fixed-bottom.has-shadow { - -webkit-box-shadow: 0 -2px 0 0 whitesmoke; - box-shadow: 0 -2px 0 0 whitesmoke; - } - -.navbar.is-fixed-top { - top: 0; -} - -html.has-navbar-fixed-top, -body.has-navbar-fixed-top { - padding-top: 3.25rem; -} - -html.has-navbar-fixed-bottom, -body.has-navbar-fixed-bottom { - padding-bottom: 3.25rem; -} - -.navbar-brand, -.navbar-tabs { - -webkit-box-align: stretch; - -ms-flex-align: stretch; - align-items: stretch; - display: -webkit-box; - display: -ms-flexbox; - display: flex; - -ms-flex-negative: 0; - flex-shrink: 0; - min-height: 3.25rem; -} - - .navbar-brand a.navbar-item:focus, .navbar-brand a.navbar-item:hover { - background-color: transparent; - } - -.navbar-tabs { - -webkit-overflow-scrolling: touch; - max-width: 100vw; - overflow-x: auto; - overflow-y: hidden; -} - -.navbar-burger { - color: #4a4a4a; - cursor: pointer; - display: block; - height: 3.25rem; - position: relative; - width: 3.25rem; - margin-left: auto; -} - - .navbar-burger span { - background-color: currentColor; - display: block; - height: 1px; - left: calc(50% - 8px); - position: absolute; - -webkit-transform-origin: center; - -ms-transform-origin: center; - transform-origin: center; - -webkit-transition-duration: 86ms; - -o-transition-duration: 86ms; - transition-duration: 86ms; - -webkit-transition-property: background-color, opacity, -webkit-transform; - transition-property: background-color, opacity, -webkit-transform; - -o-transition-property: background-color, opacity, transform; - transition-property: background-color, opacity, transform; - transition-property: background-color, opacity, transform, -webkit-transform; - -webkit-transition-timing-function: ease-out; - -o-transition-timing-function: ease-out; - transition-timing-function: ease-out; - width: 16px; - } - - .navbar-burger span:nth-child(1) { - top: calc(50% - 6px); - } - - .navbar-burger span:nth-child(2) { - top: calc(50% - 1px); - } - - .navbar-burger span:nth-child(3) { - top: calc(50% + 4px); - } - - .navbar-burger:hover { - background-color: rgba(0, 0, 0, 0.05); - } - - .navbar-burger.is-active span:nth-child(1), .navbar-burger.active span:nth-child(1) { - -webkit-transform: translateY(5px) rotate(45deg); - -ms-transform: translateY(5px) rotate(45deg); - transform: translateY(5px) rotate(45deg); - } - - .navbar-burger.is-active span:nth-child(2), .navbar-burger.active span:nth-child(2) { - opacity: 0; - } - - .navbar-burger.is-active span:nth-child(3), .navbar-burger.active span:nth-child(3) { - -webkit-transform: translateY(-5px) rotate(-45deg); - -ms-transform: translateY(-5px) rotate(-45deg); - transform: translateY(-5px) rotate(-45deg); - } - -.navbar-menu { - display: none; -} - -.navbar-item, -.navbar-link { - color: #4a4a4a; - display: block; - line-height: 1.5; - padding: 0.5rem 0.75rem; - position: relative; -} - - .navbar-item .icon:only-child, - .navbar-link .icon:only-child { - margin-left: -0.25rem; - margin-right: -0.25rem; - } - -a.navbar-item, -.navbar-link { - cursor: pointer; -} - - a.navbar-item:focus, a.navbar-item:focus-within, a.navbar-item:hover, a.navbar-item.is-active, .navbar-item.active, - .navbar-link:focus, - .navbar-link:focus-within, - .navbar-link:hover, - .navbar-link.is-active, - .navbar-link.active { - background-color: #fafafa; - color: #378BBA; - } - -.navbar-item { - -webkit-box-flex: 0; - -ms-flex-positive: 0; - flex-grow: 0; - -ms-flex-negative: 0; - flex-shrink: 0; -} - - .navbar-item img { - max-height: 1.75rem; - } - - .navbar-item.has-dropdown { - padding: 0; - } - - .navbar-item.is-expanded { - -webkit-box-flex: 1; - -ms-flex-positive: 1; - flex-grow: 1; - -ms-flex-negative: 1; - flex-shrink: 1; - } - - .navbar-item.is-tab { - border-bottom: 1px solid transparent; - min-height: 3.25rem; - padding-bottom: calc(0.5rem - 1px); - } - - .navbar-item.is-tab:focus, .navbar-item.is-tab:hover { - background-color: transparent; - border-bottom-color: #378BBA; - } - - .navbar-item.is-tab.is-active, .is-tab.active { - background-color: transparent; - border-bottom-color: #378BBA; - border-bottom-style: solid; - border-bottom-width: 3px; - color: #378BBA; - padding-bottom: calc(0.5rem - 3px); - } - -.navbar-content { - -webkit-box-flex: 1; - -ms-flex-positive: 1; - flex-grow: 1; - -ms-flex-negative: 1; - flex-shrink: 1; -} - -.navbar-link:not(.is-arrowless) { - padding-right: 2.5em; -} - - .navbar-link:not(.is-arrowless)::after { - border-color: #378BBA; - margin-top: -0.375em; - right: 1.125em; - } - -.navbar-dropdown { - font-size: 0.875rem; - padding-bottom: 0.5rem; - padding-top: 0.5rem; -} - - .navbar-dropdown .navbar-item { - padding-left: 1.5rem; - padding-right: 1.5rem; - } - -.navbar-divider { - background-color: whitesmoke; - border: none; - display: none; - height: 2px; - margin: 0.5rem 0; -} - -@media screen and (max-width: 1023px) { - .navbar > .container { - display: block; - } - - .navbar-brand .navbar-item, - .navbar-tabs .navbar-item { - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - display: -webkit-box; - display: -ms-flexbox; - display: flex; - } - - .navbar-link::after { - display: none; - } - - .navbar-menu { - background-color: white; - -webkit-box-shadow: 0 8px 16px rgba(10, 10, 10, 0.1); - box-shadow: 0 8px 16px rgba(10, 10, 10, 0.1); - padding: 0.5rem 0; - } - - .navbar-menu.is-active, .navbar-menu.active { - display: block; - } - - .navbar.is-fixed-bottom-touch, .navbar.is-fixed-top-touch { - left: 0; - position: fixed; - right: 0; - z-index: 30; - } - - .navbar.is-fixed-bottom-touch { - bottom: 0; - } - - .navbar.is-fixed-bottom-touch.has-shadow { - -webkit-box-shadow: 0 -2px 3px rgba(10, 10, 10, 0.1); - box-shadow: 0 -2px 3px rgba(10, 10, 10, 0.1); - } - - .navbar.is-fixed-top-touch { - top: 0; - } - - .navbar.is-fixed-top .navbar-menu, .navbar.is-fixed-top-touch .navbar-menu { - -webkit-overflow-scrolling: touch; - max-height: calc(100vh - 3.25rem); - overflow: auto; - } - - html.has-navbar-fixed-top-touch, - body.has-navbar-fixed-top-touch { - padding-top: 3.25rem; - } - - html.has-navbar-fixed-bottom-touch, - body.has-navbar-fixed-bottom-touch { - padding-bottom: 3.25rem; - } -} - -@media screen and (min-width: 1024px) { - .navbar, - .navbar-menu, - .navbar-start, - .navbar-end { - -webkit-box-align: stretch; - -ms-flex-align: stretch; - align-items: stretch; - display: -webkit-box; - display: -ms-flexbox; - display: flex; - } - - .navbar { - min-height: 3.25rem; - } - - .navbar.is-spaced { - padding: 1rem 2rem; - } - - .navbar.is-spaced .navbar-start, - .navbar.is-spaced .navbar-end { - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - } - - .navbar.is-spaced a.navbar-item, - .navbar.is-spaced .navbar-link { - border-radius: 4px; - } - - .navbar.is-transparent a.navbar-item:focus, .navbar.is-transparent a.navbar-item:hover, .navbar.is-transparent a.navbar-item.is-active, .navbar.is-transparent .navbar-item.active, - .navbar.is-transparent .navbar-link:focus, - .navbar.is-transparent .navbar-link:hover, - .navbar.is-transparent .navbar-link.is-active, - .navbar.is-transparent .navbar-link.active { - background-color: transparent !important; - } - - .navbar.is-transparent .navbar-item.has-dropdown.is-active .navbar-link, .navbar.is-transparent .has-dropdown.active .navbar-link, .navbar.is-transparent .navbar-item.has-dropdown.is-hoverable:focus .navbar-link, .navbar.is-transparent .navbar-item.has-dropdown.is-hoverable:focus-within .navbar-link, .navbar.is-transparent .navbar-item.has-dropdown.is-hoverable:hover .navbar-link { - background-color: transparent !important; - } - - .navbar.is-transparent .navbar-dropdown a.navbar-item:focus, .navbar.is-transparent .navbar-dropdown a.navbar-item:hover { - background-color: whitesmoke; - color: #0a0a0a; - } - - .navbar.is-transparent .navbar-dropdown a.navbar-item.is-active, .navbar.is-transparent .navbar-dropdown .navbar-item.active { - background-color: whitesmoke; - color: #378BBA; - } - - .navbar-burger { - display: none; - } - - .navbar-item, - .navbar-link { - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - display: -webkit-box; - display: -ms-flexbox; - display: flex; - } - - .navbar-item.has-dropdown { - -webkit-box-align: stretch; - -ms-flex-align: stretch; - align-items: stretch; - } - - .navbar-item.has-dropdown-up .navbar-link::after { - -webkit-transform: rotate(135deg) translate(0.25em, -0.25em); - -ms-transform: rotate(135deg) translate(0.25em, -0.25em); - transform: rotate(135deg) translate(0.25em, -0.25em); - } - - .navbar-item.has-dropdown-up .navbar-dropdown { - border-bottom: 2px solid #dbdbdb; - border-radius: 6px 6px 0 0; - border-top: none; - bottom: 100%; - -webkit-box-shadow: 0 -8px 8px rgba(10, 10, 10, 0.1); - box-shadow: 0 -8px 8px rgba(10, 10, 10, 0.1); - top: auto; - } - - .navbar-item.is-active .navbar-dropdown, .navbar-item.active .navbar-dropdown, .navbar-item.is-hoverable:focus .navbar-dropdown, .navbar-item.is-hoverable:focus-within .navbar-dropdown, .navbar-item.is-hoverable:hover .navbar-dropdown { - display: block; - } - - .navbar.is-spaced .navbar-item.is-active .navbar-dropdown, .navbar.is-spaced .navbar-item.active .navbar-dropdown, .navbar-item.is-active .navbar-dropdown.is-boxed, .navbar-item.active .navbar-dropdown.is-boxed, .navbar.is-spaced .navbar-item.is-hoverable:focus .navbar-dropdown, .navbar-item.is-hoverable:focus .navbar-dropdown.is-boxed, .navbar.is-spaced .navbar-item.is-hoverable:focus-within .navbar-dropdown, .navbar-item.is-hoverable:focus-within .navbar-dropdown.is-boxed, .navbar.is-spaced .navbar-item.is-hoverable:hover .navbar-dropdown, .navbar-item.is-hoverable:hover .navbar-dropdown.is-boxed { - opacity: 1; - pointer-events: auto; - -webkit-transform: translateY(0); - -ms-transform: translateY(0); - transform: translateY(0); - } - - .navbar-menu { - -webkit-box-flex: 1; - -ms-flex-positive: 1; - flex-grow: 1; - -ms-flex-negative: 0; - flex-shrink: 0; - } - - .navbar-start { - -webkit-box-pack: start; - -ms-flex-pack: start; - justify-content: flex-start; - margin-right: auto; - } - - .navbar-end { - -webkit-box-pack: end; - -ms-flex-pack: end; - justify-content: flex-end; - margin-left: auto; - } - - .navbar-dropdown { - background-color: white; - border-bottom-left-radius: 6px; - border-bottom-right-radius: 6px; - border-top: 2px solid #dbdbdb; - -webkit-box-shadow: 0 8px 8px rgba(10, 10, 10, 0.1); - box-shadow: 0 8px 8px rgba(10, 10, 10, 0.1); - display: none; - font-size: 0.875rem; - left: 0; - min-width: 100%; - position: absolute; - top: 100%; - z-index: 20; - } - - .navbar-dropdown .navbar-item { - padding: 0.375rem 1rem; - white-space: nowrap; - } - - .navbar-dropdown a.navbar-item { - padding-right: 3rem; - } - - .navbar-dropdown a.navbar-item:focus, .navbar-dropdown a.navbar-item:hover { - background-color: whitesmoke; - color: #0a0a0a; - } - - .navbar-dropdown a.navbar-item.is-active, .navbar-dropdown .navbar-item.active { - background-color: whitesmoke; - color: #378BBA; - } - - .navbar.is-spaced .navbar-dropdown, .navbar-dropdown.is-boxed { - border-radius: 6px; - border-top: none; - -webkit-box-shadow: 0 8px 8px rgba(10, 10, 10, 0.1), 0 0 0 1px rgba(10, 10, 10, 0.1); - box-shadow: 0 8px 8px rgba(10, 10, 10, 0.1), 0 0 0 1px rgba(10, 10, 10, 0.1); - display: block; - opacity: 0; - pointer-events: none; - top: calc(100% + (-4px)); - -webkit-transform: translateY(-5px); - -ms-transform: translateY(-5px); - transform: translateY(-5px); - -webkit-transition-duration: 86ms; - -o-transition-duration: 86ms; - transition-duration: 86ms; - -webkit-transition-property: opacity, -webkit-transform; - transition-property: opacity, -webkit-transform; - -o-transition-property: opacity, transform; - transition-property: opacity, transform; - transition-property: opacity, transform, -webkit-transform; - } - - .navbar-dropdown.is-right { - left: auto; - right: 0; - } - - .navbar-divider { - display: block; - } - - .navbar > .container .navbar-brand, - .container > .navbar .navbar-brand { - margin-left: -0.75rem; - } - - .navbar > .container .navbar-menu, - .container > .navbar .navbar-menu { - margin-right: -0.75rem; - } - - .navbar.is-fixed-bottom-desktop, .navbar.is-fixed-top-desktop { - left: 0; - position: fixed; - right: 0; - z-index: 30; - } - - .navbar.is-fixed-bottom-desktop { - bottom: 0; - } - - .navbar.is-fixed-bottom-desktop.has-shadow { - -webkit-box-shadow: 0 -2px 3px rgba(10, 10, 10, 0.1); - box-shadow: 0 -2px 3px rgba(10, 10, 10, 0.1); - } - - .navbar.is-fixed-top-desktop { - top: 0; - } - - html.has-navbar-fixed-top-desktop, - body.has-navbar-fixed-top-desktop { - padding-top: 3.25rem; - } - - html.has-navbar-fixed-bottom-desktop, - body.has-navbar-fixed-bottom-desktop { - padding-bottom: 3.25rem; - } - - html.has-spaced-navbar-fixed-top, - body.has-spaced-navbar-fixed-top { - padding-top: 5.25rem; - } - - html.has-spaced-navbar-fixed-bottom, - body.has-spaced-navbar-fixed-bottom { - padding-bottom: 5.25rem; - } - - a.navbar-item.is-active, .navbar-item.active, - .navbar-link.is-active, - .navbar-link.active { - color: #0a0a0a; - } - - a.navbar-item.is-active:not(:focus):not(:hover), .navbar-item.active:not(:focus):not(:hover), - .navbar-link.is-active:not(:focus):not(:hover), - .navbar-link.active:not(:focus):not(:hover) { - background-color: transparent; - } - - .navbar-item.has-dropdown:focus .navbar-link, .navbar-item.has-dropdown:hover .navbar-link, .navbar-item.has-dropdown.is-active .navbar-link, .has-dropdown.active .navbar-link { - background-color: #fafafa; - } -} - -.hero.is-fullheight-with-navbar { - min-height: calc(100vh - 3.25rem); -} - -.pagination { - font-size: 1rem; - margin: -0.25rem; -} - - .pagination.is-small { - font-size: 0.75rem; - } - - .pagination.is-medium { - font-size: 1.25rem; - } - - .pagination.is-large { - font-size: 1.5rem; - } - - .pagination.is-rounded .pagination-previous, - .pagination.is-rounded .pagination-next { - padding-left: 1em; - padding-right: 1em; - border-radius: 290486px; - } - - .pagination.is-rounded .pagination-link { - border-radius: 290486px; - } - -.pagination, -.pagination-list { - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - display: -webkit-box; - display: -ms-flexbox; - display: flex; - -webkit-box-pack: center; - -ms-flex-pack: center; - justify-content: center; - text-align: center; -} - -.pagination-previous, -.pagination-next, -.pagination-link, -.pagination-ellipsis { - font-size: 1em; - -webkit-box-pack: center; - -ms-flex-pack: center; - justify-content: center; - margin: 0.25rem; - padding-left: 0.5em; - padding-right: 0.5em; - text-align: center; -} - -.pagination-previous, -.pagination-next, -.pagination-link { - border-color: #dbdbdb; - color: #363636; - min-width: 2.5em; -} - - .pagination-previous:hover, - .pagination-next:hover, - .pagination-link:hover { - border-color: #b5b5b5; - color: #A00975; - } - - .pagination-previous:focus, - .pagination-next:focus, - .pagination-link:focus { - border-color: #3273dc; - } - - .pagination-previous:active, - .pagination-next:active, - .pagination-link:active { - -webkit-box-shadow: inset 0 1px 2px rgba(10, 10, 10, 0.2); - box-shadow: inset 0 1px 2px rgba(10, 10, 10, 0.2); - } - - .pagination-previous[disabled], - .pagination-next[disabled], - .pagination-link[disabled] { - background-color: #dbdbdb; - border-color: #dbdbdb; - -webkit-box-shadow: none; - box-shadow: none; - color: #7a7a7a; - opacity: 0.5; - } - -.pagination-previous, -.pagination-next { - padding-left: 0.75em; - padding-right: 0.75em; - white-space: nowrap; -} - -.pagination-link.is-current { - background-color: #378BBA; - border-color: #378BBA; - color: #fff; -} - -.pagination-ellipsis { - color: #b5b5b5; - pointer-events: none; -} - -.pagination-list { - -ms-flex-wrap: wrap; - flex-wrap: wrap; -} - - .pagination-list li { - list-style: none; - } - -@media screen and (max-width: 768px) { - .pagination { - -ms-flex-wrap: wrap; - flex-wrap: wrap; - } - - .pagination-previous, - .pagination-next { - -webkit-box-flex: 1; - -ms-flex-positive: 1; - flex-grow: 1; - -ms-flex-negative: 1; - flex-shrink: 1; - } - - .pagination-list li { - -webkit-box-flex: 1; - -ms-flex-positive: 1; - flex-grow: 1; - -ms-flex-negative: 1; - flex-shrink: 1; - } -} - -@media screen and (min-width: 769px), print { - .pagination-list { - -webkit-box-flex: 1; - -ms-flex-positive: 1; - flex-grow: 1; - -ms-flex-negative: 1; - flex-shrink: 1; - -webkit-box-pack: start; - -ms-flex-pack: start; - justify-content: flex-start; - -webkit-box-ordinal-group: 2; - -ms-flex-order: 1; - order: 1; - } - - .pagination-previous { - -webkit-box-ordinal-group: 3; - -ms-flex-order: 2; - order: 2; - } - - .pagination-next { - -webkit-box-ordinal-group: 4; - -ms-flex-order: 3; - order: 3; - } - - .pagination { - -webkit-box-pack: justify; - -ms-flex-pack: justify; - justify-content: space-between; - } - - .pagination.is-centered .pagination-previous { - -webkit-box-ordinal-group: 2; - -ms-flex-order: 1; - order: 1; - } - - .pagination.is-centered .pagination-list { - -webkit-box-pack: center; - -ms-flex-pack: center; - justify-content: center; - -webkit-box-ordinal-group: 3; - -ms-flex-order: 2; - order: 2; - } - - .pagination.is-centered .pagination-next { - -webkit-box-ordinal-group: 4; - -ms-flex-order: 3; - order: 3; - } - - .pagination.is-right .pagination-previous { - -webkit-box-ordinal-group: 2; - -ms-flex-order: 1; - order: 1; - } - - .pagination.is-right .pagination-next { - -webkit-box-ordinal-group: 3; - -ms-flex-order: 2; - order: 2; - } - - .pagination.is-right .pagination-list { - -webkit-box-pack: end; - -ms-flex-pack: end; - justify-content: flex-end; - -webkit-box-ordinal-group: 4; - -ms-flex-order: 3; - order: 3; - } -} - -.panel { - border-radius: 6px; - -webkit-box-shadow: 0 0.5em 1em -0.125em rgba(10, 10, 10, 0.1), 0 0px 0 1px rgba(10, 10, 10, 0.02); - box-shadow: 0 0.5em 1em -0.125em rgba(10, 10, 10, 0.1), 0 0px 0 1px rgba(10, 10, 10, 0.02); - font-size: 1rem; -} - - .panel:not(:last-child) { - margin-bottom: 1.5rem; - } - - .panel.is-white .panel-heading { - background-color: white; - color: #0a0a0a; - } - - .panel.is-white .panel-tabs a.is-active, .panel.is-white .panel-tabs a.active { - border-bottom-color: white; - } - - .panel.is-white .panel-block.is-active .panel-icon, .panel.is-white .panel-block.active .panel-icon { - color: white; - } - - .panel.is-black .panel-heading { - background-color: #0a0a0a; - color: white; - } - - .panel.is-black .panel-tabs a.is-active, .panel.is-black .panel-tabs a.active { - border-bottom-color: #0a0a0a; - } - - .panel.is-black .panel-block.is-active .panel-icon, .panel.is-black .panel-block.active .panel-icon { - color: #0a0a0a; - } - - .panel.is-light .panel-heading { - background-color: whitesmoke; - color: rgba(0, 0, 0, 0.7); - } - - .panel.is-light .panel-tabs a.is-active, .panel.is-light .panel-tabs a.active { - border-bottom-color: whitesmoke; - } - - .panel.is-light .panel-block.is-active .panel-icon, .panel.is-light .panel-block.active .panel-icon { - color: whitesmoke; - } - - .panel.is-dark .panel-heading { - background-color: #200117; - color: #fff; - } - - .panel.is-dark .panel-tabs a.is-active, .panel.is-dark .panel-tabs a.active { - border-bottom-color: #200117; - } - - .panel.is-dark .panel-block.is-active .panel-icon, .panel.is-dark .panel-block.active .panel-icon { - color: #200117; - } - - .panel.is-primary .panel-heading { - background-color: #A00975; - color: #fff; - } - - .panel.is-primary .panel-tabs a.is-active, .panel.is-primary .panel-tabs a.active { - border-bottom-color: #A00975; - } - - .panel.is-primary .panel-block.is-active .panel-icon, .panel.is-primary .panel-block.active .panel-icon { - color: #A00975; - } - - .panel.is-link .panel-heading { - background-color: #378BBA; - color: #fff; - } - - .panel.is-link .panel-tabs a.is-active, .panel.is-link .panel-tabs a.active { - border-bottom-color: #378BBA; - } - - .panel.is-link .panel-block.is-active .panel-icon, .panel.is-link .panel-block.active .panel-icon { - color: #378BBA; - } - - .panel.is-info .panel-heading { - background-color: #3298dc; - color: #fff; - } - - .panel.is-info .panel-tabs a.is-active, .panel.is-info .panel-tabs a.active { - border-bottom-color: #3298dc; - } - - .panel.is-info .panel-block.is-active .panel-icon, .panel.is-info .panel-block.active .panel-icon { - color: #3298dc; - } - - .panel.is-success .panel-heading { - background-color: #48c774; - color: #fff; - } - - .panel.is-success .panel-tabs a.is-active, .panel.is-success .panel-tabs a.active { - border-bottom-color: #48c774; - } - - .panel.is-success .panel-block.is-active .panel-icon, .panel.is-success .panel-block.active .panel-icon { - color: #48c774; - } - - .panel.is-warning .panel-heading { - background-color: #ffdd57; - color: rgba(0, 0, 0, 0.7); - } - - .panel.is-warning .panel-tabs a.is-active, .panel.is-warning .panel-tabs a.active { - border-bottom-color: #ffdd57; - } - - .panel.is-warning .panel-block.is-active .panel-icon, .panel.is-warning .panel-block.active .panel-icon { - color: #ffdd57; - } - - .panel.is-danger .panel-heading { - background-color: #f14668; - color: #fff; - } - - .panel.is-danger .panel-tabs a.is-active, .panel.is-danger .panel-tabs a.active { - border-bottom-color: #f14668; - } - - .panel.is-danger .panel-block.is-active .panel-icon, .panel.is-danger .panel-block.active .panel-icon { - color: #f14668; - } - -.panel-tabs:not(:last-child), -.panel-block:not(:last-child) { - border-bottom: 1px solid #ededed; -} - -.panel-heading { - background-color: #ededed; - border-radius: 6px 6px 0 0; - color: #363636; - font-size: 1.25em; - font-weight: 700; - line-height: 1.25; - padding: 0.75em 1em; -} - -.panel-tabs { - -webkit-box-align: end; - -ms-flex-align: end; - align-items: flex-end; - display: -webkit-box; - display: -ms-flexbox; - display: flex; - font-size: 0.875em; - -webkit-box-pack: center; - -ms-flex-pack: center; - justify-content: center; -} - - .panel-tabs a { - border-bottom: 1px solid #dbdbdb; - margin-bottom: -1px; - padding: 0.5em; - } - - .panel-tabs a.is-active, .panel-tabs a.active { - border-bottom-color: #4a4a4a; - color: #363636; - } - -.panel-list a { - color: #4a4a4a; -} - - .panel-list a:hover { - color: #378BBA; - } - -.panel-block { - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - color: #363636; - display: -webkit-box; - display: -ms-flexbox; - display: flex; - -webkit-box-pack: start; - -ms-flex-pack: start; - justify-content: flex-start; - padding: 0.5em 0.75em; -} - - .panel-block input[type="checkbox"] { - margin-right: 0.75em; - } - - .panel-block > .control { - -webkit-box-flex: 1; - -ms-flex-positive: 1; - flex-grow: 1; - -ms-flex-negative: 1; - flex-shrink: 1; - width: 100%; - } - - .panel-block.is-wrapped { - -ms-flex-wrap: wrap; - flex-wrap: wrap; - } - - .panel-block.is-active, .panel-block.active { - border-left-color: #378BBA; - color: #363636; - } - - .panel-block.is-active .panel-icon, .panel-block.active .panel-icon { - color: #378BBA; - } - - .panel-block:last-child { - border-bottom-left-radius: 6px; - border-bottom-right-radius: 6px; - } - -a.panel-block, -label.panel-block { - cursor: pointer; -} - - a.panel-block:hover, - label.panel-block:hover { - background-color: whitesmoke; - } - -.panel-icon { - display: inline-block; - font-size: 14px; - height: 1em; - line-height: 1em; - text-align: center; - vertical-align: top; - width: 1em; - color: #7a7a7a; - margin-right: 0.75em; -} - - .panel-icon .fa { - font-size: inherit; - line-height: inherit; - } - -.tabs { - -webkit-overflow-scrolling: touch; - -webkit-box-align: stretch; - -ms-flex-align: stretch; - align-items: stretch; - display: -webkit-box; - display: -ms-flexbox; - display: flex; - font-size: 1rem; - -webkit-box-pack: justify; - -ms-flex-pack: justify; - justify-content: space-between; - overflow: hidden; - overflow-x: auto; - white-space: nowrap; -} - - .tabs a { - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - border-bottom-color: #dbdbdb; - border-bottom-style: solid; - border-bottom-width: 1px; - color: #4a4a4a; - display: -webkit-box; - display: -ms-flexbox; - display: flex; - -webkit-box-pack: center; - -ms-flex-pack: center; - justify-content: center; - margin-bottom: -1px; - padding: 0.5em 1em; - vertical-align: top; - } - - .tabs a:hover { - border-bottom-color: #363636; - color: #363636; - } - - .tabs li { - display: block; - } - - .tabs li.is-active a, .tabs li.active a { - border-bottom-color: #378BBA; - color: #378BBA; - } - - .tabs ul { - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - border-bottom-color: #dbdbdb; - border-bottom-style: solid; - border-bottom-width: 1px; - display: -webkit-box; - display: -ms-flexbox; - display: flex; - -webkit-box-flex: 1; - -ms-flex-positive: 1; - flex-grow: 1; - -ms-flex-negative: 0; - flex-shrink: 0; - -webkit-box-pack: start; - -ms-flex-pack: start; - justify-content: flex-start; - } - - .tabs ul.is-left { - padding-right: 0.75em; - } - - .tabs ul.is-center { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - -webkit-box-pack: center; - -ms-flex-pack: center; - justify-content: center; - padding-left: 0.75em; - padding-right: 0.75em; - } - - .tabs ul.is-right { - -webkit-box-pack: end; - -ms-flex-pack: end; - justify-content: flex-end; - padding-left: 0.75em; - } - - .tabs .icon:first-child { - margin-right: 0.5em; - } - - .tabs .icon:last-child { - margin-left: 0.5em; - } - - .tabs.is-centered ul { - -webkit-box-pack: center; - -ms-flex-pack: center; - justify-content: center; - } - - .tabs.is-right ul { - -webkit-box-pack: end; - -ms-flex-pack: end; - justify-content: flex-end; - } - - .tabs.is-boxed a { - border: 1px solid transparent; - border-radius: 4px 4px 0 0; - } - - .tabs.is-boxed a:hover { - background-color: whitesmoke; - border-bottom-color: #dbdbdb; - } - - .tabs.is-boxed li.is-active a, .tabs.is-boxed li.active a { - background-color: white; - border-color: #dbdbdb; - border-bottom-color: transparent !important; - } - - .tabs.is-fullwidth li { - -webkit-box-flex: 1; - -ms-flex-positive: 1; - flex-grow: 1; - -ms-flex-negative: 0; - flex-shrink: 0; - } - - .tabs.is-toggle a { - border-color: #dbdbdb; - border-style: solid; - border-width: 1px; - margin-bottom: 0; - position: relative; - } - - .tabs.is-toggle a:hover { - background-color: whitesmoke; - border-color: #b5b5b5; - z-index: 2; - } - - .tabs.is-toggle li + li { - margin-left: -1px; - } - - .tabs.is-toggle li:first-child a { - border-top-left-radius: 4px; - border-bottom-left-radius: 4px; - } - - .tabs.is-toggle li:last-child a { - border-top-right-radius: 4px; - border-bottom-right-radius: 4px; - } - - .tabs.is-toggle li.is-active a, .tabs.is-toggle li.active a { - background-color: #378BBA; - border-color: #378BBA; - color: #fff; - z-index: 1; - } - - .tabs.is-toggle ul { - border-bottom: none; - } - - .tabs.is-toggle.is-toggle-rounded li:first-child a { - border-bottom-left-radius: 290486px; - border-top-left-radius: 290486px; - padding-left: 1.25em; - } - - .tabs.is-toggle.is-toggle-rounded li:last-child a { - border-bottom-right-radius: 290486px; - border-top-right-radius: 290486px; - padding-right: 1.25em; - } - - .tabs.is-small { - font-size: 0.75rem; - } - - .tabs.is-medium { - font-size: 1.25rem; - } - - .tabs.is-large { - font-size: 1.5rem; - } - -/* Bulma Grid */ -.column { - display: block; - -ms-flex-preferred-size: 0; - flex-basis: 0; - -webkit-box-flex: 1; - -ms-flex-positive: 1; - flex-grow: 1; - -ms-flex-negative: 1; - flex-shrink: 1; - padding: 0.75rem; -} - -.columns.is-mobile > .column.is-narrow { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: unset; -} - -.columns.is-mobile > .column.is-full { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 100%; -} - -.columns.is-mobile > .column.is-three-quarters { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 75%; -} - -.columns.is-mobile > .column.is-two-thirds { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 66.6666%; -} - -.columns.is-mobile > .column.is-half { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 50%; -} - -.columns.is-mobile > .column.is-one-third { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 33.3333%; -} - -.columns.is-mobile > .column.is-one-quarter { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 25%; -} - -.columns.is-mobile > .column.is-one-fifth { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 20%; -} - -.columns.is-mobile > .column.is-two-fifths { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 40%; -} - -.columns.is-mobile > .column.is-three-fifths { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 60%; -} - -.columns.is-mobile > .column.is-four-fifths { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 80%; -} - -.columns.is-mobile > .column.is-offset-three-quarters { - margin-left: 75%; -} - -.columns.is-mobile > .column.is-offset-two-thirds { - margin-left: 66.6666%; -} - -.columns.is-mobile > .column.is-offset-half { - margin-left: 50%; -} - -.columns.is-mobile > .column.is-offset-one-third { - margin-left: 33.3333%; -} - -.columns.is-mobile > .column.is-offset-one-quarter { - margin-left: 25%; -} - -.columns.is-mobile > .column.is-offset-one-fifth { - margin-left: 20%; -} - -.columns.is-mobile > .column.is-offset-two-fifths { - margin-left: 40%; -} - -.columns.is-mobile > .column.is-offset-three-fifths { - margin-left: 60%; -} - -.columns.is-mobile > .column.is-offset-four-fifths { - margin-left: 80%; -} - -.columns.is-mobile > .column.is-0 { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 0%; -} - -.columns.is-mobile > .column.is-offset-0 { - margin-left: 0%; -} - -.columns.is-mobile > .column.is-1 { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 8.33333%; -} - -.columns.is-mobile > .column.is-offset-1 { - margin-left: 8.33333%; -} - -.columns.is-mobile > .column.is-2 { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 16.66667%; -} - -.columns.is-mobile > .column.is-offset-2 { - margin-left: 16.66667%; -} - -.columns.is-mobile > .column.is-3 { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 25%; -} - -.columns.is-mobile > .column.is-offset-3 { - margin-left: 25%; -} - -.columns.is-mobile > .column.is-4 { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 33.33333%; -} - -.columns.is-mobile > .column.is-offset-4 { - margin-left: 33.33333%; -} - -.columns.is-mobile > .column.is-5 { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 41.66667%; -} - -.columns.is-mobile > .column.is-offset-5 { - margin-left: 41.66667%; -} - -.columns.is-mobile > .column.is-6 { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 50%; -} - -.columns.is-mobile > .column.is-offset-6 { - margin-left: 50%; -} - -.columns.is-mobile > .column.is-7 { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 58.33333%; -} - -.columns.is-mobile > .column.is-offset-7 { - margin-left: 58.33333%; -} - -.columns.is-mobile > .column.is-8 { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 66.66667%; -} - -.columns.is-mobile > .column.is-offset-8 { - margin-left: 66.66667%; -} - -.columns.is-mobile > .column.is-9 { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 75%; -} - -.columns.is-mobile > .column.is-offset-9 { - margin-left: 75%; -} - -.columns.is-mobile > .column.is-10 { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 83.33333%; -} - -.columns.is-mobile > .column.is-offset-10 { - margin-left: 83.33333%; -} - -.columns.is-mobile > .column.is-11 { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 91.66667%; -} - -.columns.is-mobile > .column.is-offset-11 { - margin-left: 91.66667%; -} - -.columns.is-mobile > .column.is-12 { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 100%; -} - -.columns.is-mobile > .column.is-offset-12 { - margin-left: 100%; -} - -@media screen and (max-width: 768px) { - .column.is-narrow-mobile { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: unset; - } - - .column.is-full-mobile { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 100%; - } - - .column.is-three-quarters-mobile { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 75%; - } - - .column.is-two-thirds-mobile { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 66.6666%; - } - - .column.is-half-mobile { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 50%; - } - - .column.is-one-third-mobile { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 33.3333%; - } - - .column.is-one-quarter-mobile { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 25%; - } - - .column.is-one-fifth-mobile { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 20%; - } - - .column.is-two-fifths-mobile { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 40%; - } - - .column.is-three-fifths-mobile { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 60%; - } - - .column.is-four-fifths-mobile { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 80%; - } - - .column.is-offset-three-quarters-mobile { - margin-left: 75%; - } - - .column.is-offset-two-thirds-mobile { - margin-left: 66.6666%; - } - - .column.is-offset-half-mobile { - margin-left: 50%; - } - - .column.is-offset-one-third-mobile { - margin-left: 33.3333%; - } - - .column.is-offset-one-quarter-mobile { - margin-left: 25%; - } - - .column.is-offset-one-fifth-mobile { - margin-left: 20%; - } - - .column.is-offset-two-fifths-mobile { - margin-left: 40%; - } - - .column.is-offset-three-fifths-mobile { - margin-left: 60%; - } - - .column.is-offset-four-fifths-mobile { - margin-left: 80%; - } - - .column.is-0-mobile { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 0%; - } - - .column.is-offset-0-mobile { - margin-left: 0%; - } - - .column.is-1-mobile { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 8.33333%; - } - - .column.is-offset-1-mobile { - margin-left: 8.33333%; - } - - .column.is-2-mobile { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 16.66667%; - } - - .column.is-offset-2-mobile { - margin-left: 16.66667%; - } - - .column.is-3-mobile { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 25%; - } - - .column.is-offset-3-mobile { - margin-left: 25%; - } - - .column.is-4-mobile { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 33.33333%; - } - - .column.is-offset-4-mobile { - margin-left: 33.33333%; - } - - .column.is-5-mobile { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 41.66667%; - } - - .column.is-offset-5-mobile { - margin-left: 41.66667%; - } - - .column.is-6-mobile { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 50%; - } - - .column.is-offset-6-mobile { - margin-left: 50%; - } - - .column.is-7-mobile { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 58.33333%; - } - - .column.is-offset-7-mobile { - margin-left: 58.33333%; - } - - .column.is-8-mobile { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 66.66667%; - } - - .column.is-offset-8-mobile { - margin-left: 66.66667%; - } - - .column.is-9-mobile { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 75%; - } - - .column.is-offset-9-mobile { - margin-left: 75%; - } - - .column.is-10-mobile { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 83.33333%; - } - - .column.is-offset-10-mobile { - margin-left: 83.33333%; - } - - .column.is-11-mobile { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 91.66667%; - } - - .column.is-offset-11-mobile { - margin-left: 91.66667%; - } - - .column.is-12-mobile { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 100%; - } - - .column.is-offset-12-mobile { - margin-left: 100%; - } -} - -@media screen and (min-width: 769px), print { - .column.is-narrow, .column.is-narrow-tablet { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: unset; - } - - .column.is-full, .column.is-full-tablet { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 100%; - } - - .column.is-three-quarters, .column.is-three-quarters-tablet { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 75%; - } - - .column.is-two-thirds, .column.is-two-thirds-tablet { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 66.6666%; - } - - .column.is-half, .column.is-half-tablet { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 50%; - } - - .column.is-one-third, .column.is-one-third-tablet { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 33.3333%; - } - - .column.is-one-quarter, .column.is-one-quarter-tablet { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 25%; - } - - .column.is-one-fifth, .column.is-one-fifth-tablet { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 20%; - } - - .column.is-two-fifths, .column.is-two-fifths-tablet { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 40%; - } - - .column.is-three-fifths, .column.is-three-fifths-tablet { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 60%; - } - - .column.is-four-fifths, .column.is-four-fifths-tablet { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 80%; - } - - .column.is-offset-three-quarters, .column.is-offset-three-quarters-tablet { - margin-left: 75%; - } - - .column.is-offset-two-thirds, .column.is-offset-two-thirds-tablet { - margin-left: 66.6666%; - } - - .column.is-offset-half, .column.is-offset-half-tablet { - margin-left: 50%; - } - - .column.is-offset-one-third, .column.is-offset-one-third-tablet { - margin-left: 33.3333%; - } - - .column.is-offset-one-quarter, .column.is-offset-one-quarter-tablet { - margin-left: 25%; - } - - .column.is-offset-one-fifth, .column.is-offset-one-fifth-tablet { - margin-left: 20%; - } - - .column.is-offset-two-fifths, .column.is-offset-two-fifths-tablet { - margin-left: 40%; - } - - .column.is-offset-three-fifths, .column.is-offset-three-fifths-tablet { - margin-left: 60%; - } - - .column.is-offset-four-fifths, .column.is-offset-four-fifths-tablet { - margin-left: 80%; - } - - .column.is-0, .column.is-0-tablet { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 0%; - } - - .column.is-offset-0, .column.is-offset-0-tablet { - margin-left: 0%; - } - - .column.is-1, .column.is-1-tablet { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 8.33333%; - } - - .column.is-offset-1, .column.is-offset-1-tablet { - margin-left: 8.33333%; - } - - .column.is-2, .column.is-2-tablet { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 16.66667%; - } - - .column.is-offset-2, .column.is-offset-2-tablet { - margin-left: 16.66667%; - } - - .column.is-3, .column.is-3-tablet { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 25%; - } - - .column.is-offset-3, .column.is-offset-3-tablet { - margin-left: 25%; - } - - .column.is-4, .column.is-4-tablet { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 33.33333%; - } - - .column.is-offset-4, .column.is-offset-4-tablet { - margin-left: 33.33333%; - } - - .column.is-5, .column.is-5-tablet { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 41.66667%; - } - - .column.is-offset-5, .column.is-offset-5-tablet { - margin-left: 41.66667%; - } - - .column.is-6, .column.is-6-tablet { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 50%; - } - - .column.is-offset-6, .column.is-offset-6-tablet { - margin-left: 50%; - } - - .column.is-7, .column.is-7-tablet { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 58.33333%; - } - - .column.is-offset-7, .column.is-offset-7-tablet { - margin-left: 58.33333%; - } - - .column.is-8, .column.is-8-tablet { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 66.66667%; - } - - .column.is-offset-8, .column.is-offset-8-tablet { - margin-left: 66.66667%; - } - - .column.is-9, .column.is-9-tablet { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 75%; - } - - .column.is-offset-9, .column.is-offset-9-tablet { - margin-left: 75%; - } - - .column.is-10, .column.is-10-tablet { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 83.33333%; - } - - .column.is-offset-10, .column.is-offset-10-tablet { - margin-left: 83.33333%; - } - - .column.is-11, .column.is-11-tablet { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 91.66667%; - } - - .column.is-offset-11, .column.is-offset-11-tablet { - margin-left: 91.66667%; - } - - .column.is-12, .column.is-12-tablet { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 100%; - } - - .column.is-offset-12, .column.is-offset-12-tablet { - margin-left: 100%; - } -} - -@media screen and (max-width: 1023px) { - .column.is-narrow-touch { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: unset; - } - - .column.is-full-touch { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 100%; - } - - .column.is-three-quarters-touch { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 75%; - } - - .column.is-two-thirds-touch { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 66.6666%; - } - - .column.is-half-touch { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 50%; - } - - .column.is-one-third-touch { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 33.3333%; - } - - .column.is-one-quarter-touch { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 25%; - } - - .column.is-one-fifth-touch { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 20%; - } - - .column.is-two-fifths-touch { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 40%; - } - - .column.is-three-fifths-touch { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 60%; - } - - .column.is-four-fifths-touch { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 80%; - } - - .column.is-offset-three-quarters-touch { - margin-left: 75%; - } - - .column.is-offset-two-thirds-touch { - margin-left: 66.6666%; - } - - .column.is-offset-half-touch { - margin-left: 50%; - } - - .column.is-offset-one-third-touch { - margin-left: 33.3333%; - } - - .column.is-offset-one-quarter-touch { - margin-left: 25%; - } - - .column.is-offset-one-fifth-touch { - margin-left: 20%; - } - - .column.is-offset-two-fifths-touch { - margin-left: 40%; - } - - .column.is-offset-three-fifths-touch { - margin-left: 60%; - } - - .column.is-offset-four-fifths-touch { - margin-left: 80%; - } - - .column.is-0-touch { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 0%; - } - - .column.is-offset-0-touch { - margin-left: 0%; - } - - .column.is-1-touch { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 8.33333%; - } - - .column.is-offset-1-touch { - margin-left: 8.33333%; - } - - .column.is-2-touch { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 16.66667%; - } - - .column.is-offset-2-touch { - margin-left: 16.66667%; - } - - .column.is-3-touch { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 25%; - } - - .column.is-offset-3-touch { - margin-left: 25%; - } - - .column.is-4-touch { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 33.33333%; - } - - .column.is-offset-4-touch { - margin-left: 33.33333%; - } - - .column.is-5-touch { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 41.66667%; - } - - .column.is-offset-5-touch { - margin-left: 41.66667%; - } - - .column.is-6-touch { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 50%; - } - - .column.is-offset-6-touch { - margin-left: 50%; - } - - .column.is-7-touch { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 58.33333%; - } - - .column.is-offset-7-touch { - margin-left: 58.33333%; - } - - .column.is-8-touch { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 66.66667%; - } - - .column.is-offset-8-touch { - margin-left: 66.66667%; - } - - .column.is-9-touch { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 75%; - } - - .column.is-offset-9-touch { - margin-left: 75%; - } - - .column.is-10-touch { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 83.33333%; - } - - .column.is-offset-10-touch { - margin-left: 83.33333%; - } - - .column.is-11-touch { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 91.66667%; - } - - .column.is-offset-11-touch { - margin-left: 91.66667%; - } - - .column.is-12-touch { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 100%; - } - - .column.is-offset-12-touch { - margin-left: 100%; - } -} - -@media screen and (min-width: 1024px) { - .column.is-narrow-desktop { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: unset; - } - - .column.is-full-desktop { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 100%; - } - - .column.is-three-quarters-desktop { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 75%; - } - - .column.is-two-thirds-desktop { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 66.6666%; - } - - .column.is-half-desktop { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 50%; - } - - .column.is-one-third-desktop { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 33.3333%; - } - - .column.is-one-quarter-desktop { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 25%; - } - - .column.is-one-fifth-desktop { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 20%; - } - - .column.is-two-fifths-desktop { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 40%; - } - - .column.is-three-fifths-desktop { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 60%; - } - - .column.is-four-fifths-desktop { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 80%; - } - - .column.is-offset-three-quarters-desktop { - margin-left: 75%; - } - - .column.is-offset-two-thirds-desktop { - margin-left: 66.6666%; - } - - .column.is-offset-half-desktop { - margin-left: 50%; - } - - .column.is-offset-one-third-desktop { - margin-left: 33.3333%; - } - - .column.is-offset-one-quarter-desktop { - margin-left: 25%; - } - - .column.is-offset-one-fifth-desktop { - margin-left: 20%; - } - - .column.is-offset-two-fifths-desktop { - margin-left: 40%; - } - - .column.is-offset-three-fifths-desktop { - margin-left: 60%; - } - - .column.is-offset-four-fifths-desktop { - margin-left: 80%; - } - - .column.is-0-desktop { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 0%; - } - - .column.is-offset-0-desktop { - margin-left: 0%; - } - - .column.is-1-desktop { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 8.33333%; - } - - .column.is-offset-1-desktop { - margin-left: 8.33333%; - } - - .column.is-2-desktop { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 16.66667%; - } - - .column.is-offset-2-desktop { - margin-left: 16.66667%; - } - - .column.is-3-desktop { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 25%; - } - - .column.is-offset-3-desktop { - margin-left: 25%; - } - - .column.is-4-desktop { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 33.33333%; - } - - .column.is-offset-4-desktop { - margin-left: 33.33333%; - } - - .column.is-5-desktop { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 41.66667%; - } - - .column.is-offset-5-desktop { - margin-left: 41.66667%; - } - - .column.is-6-desktop { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 50%; - } - - .column.is-offset-6-desktop { - margin-left: 50%; - } - - .column.is-7-desktop { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 58.33333%; - } - - .column.is-offset-7-desktop { - margin-left: 58.33333%; - } - - .column.is-8-desktop { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 66.66667%; - } - - .column.is-offset-8-desktop { - margin-left: 66.66667%; - } - - .column.is-9-desktop { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 75%; - } - - .column.is-offset-9-desktop { - margin-left: 75%; - } - - .column.is-10-desktop { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 83.33333%; - } - - .column.is-offset-10-desktop { - margin-left: 83.33333%; - } - - .column.is-11-desktop { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 91.66667%; - } - - .column.is-offset-11-desktop { - margin-left: 91.66667%; - } - - .column.is-12-desktop { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 100%; - } - - .column.is-offset-12-desktop { - margin-left: 100%; - } -} - -@media screen and (min-width: 1216px) { - .column.is-narrow-widescreen { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: unset; - } - - .column.is-full-widescreen { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 100%; - } - - .column.is-three-quarters-widescreen { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 75%; - } - - .column.is-two-thirds-widescreen { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 66.6666%; - } - - .column.is-half-widescreen { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 50%; - } - - .column.is-one-third-widescreen { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 33.3333%; - } - - .column.is-one-quarter-widescreen { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 25%; - } - - .column.is-one-fifth-widescreen { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 20%; - } - - .column.is-two-fifths-widescreen { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 40%; - } - - .column.is-three-fifths-widescreen { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 60%; - } - - .column.is-four-fifths-widescreen { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 80%; - } - - .column.is-offset-three-quarters-widescreen { - margin-left: 75%; - } - - .column.is-offset-two-thirds-widescreen { - margin-left: 66.6666%; - } - - .column.is-offset-half-widescreen { - margin-left: 50%; - } - - .column.is-offset-one-third-widescreen { - margin-left: 33.3333%; - } - - .column.is-offset-one-quarter-widescreen { - margin-left: 25%; - } - - .column.is-offset-one-fifth-widescreen { - margin-left: 20%; - } - - .column.is-offset-two-fifths-widescreen { - margin-left: 40%; - } - - .column.is-offset-three-fifths-widescreen { - margin-left: 60%; - } - - .column.is-offset-four-fifths-widescreen { - margin-left: 80%; - } - - .column.is-0-widescreen { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 0%; - } - - .column.is-offset-0-widescreen { - margin-left: 0%; - } - - .column.is-1-widescreen { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 8.33333%; - } - - .column.is-offset-1-widescreen { - margin-left: 8.33333%; - } - - .column.is-2-widescreen { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 16.66667%; - } - - .column.is-offset-2-widescreen { - margin-left: 16.66667%; - } - - .column.is-3-widescreen { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 25%; - } - - .column.is-offset-3-widescreen { - margin-left: 25%; - } - - .column.is-4-widescreen { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 33.33333%; - } - - .column.is-offset-4-widescreen { - margin-left: 33.33333%; - } - - .column.is-5-widescreen { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 41.66667%; - } - - .column.is-offset-5-widescreen { - margin-left: 41.66667%; - } - - .column.is-6-widescreen { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 50%; - } - - .column.is-offset-6-widescreen { - margin-left: 50%; - } - - .column.is-7-widescreen { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 58.33333%; - } - - .column.is-offset-7-widescreen { - margin-left: 58.33333%; - } - - .column.is-8-widescreen { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 66.66667%; - } - - .column.is-offset-8-widescreen { - margin-left: 66.66667%; - } - - .column.is-9-widescreen { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 75%; - } - - .column.is-offset-9-widescreen { - margin-left: 75%; - } - - .column.is-10-widescreen { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 83.33333%; - } - - .column.is-offset-10-widescreen { - margin-left: 83.33333%; - } - - .column.is-11-widescreen { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 91.66667%; - } - - .column.is-offset-11-widescreen { - margin-left: 91.66667%; - } - - .column.is-12-widescreen { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 100%; - } - - .column.is-offset-12-widescreen { - margin-left: 100%; - } -} - -@media screen and (min-width: 1408px) { - .column.is-narrow-fullhd { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: unset; - } - - .column.is-full-fullhd { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 100%; - } - - .column.is-three-quarters-fullhd { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 75%; - } - - .column.is-two-thirds-fullhd { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 66.6666%; - } - - .column.is-half-fullhd { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 50%; - } - - .column.is-one-third-fullhd { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 33.3333%; - } - - .column.is-one-quarter-fullhd { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 25%; - } - - .column.is-one-fifth-fullhd { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 20%; - } - - .column.is-two-fifths-fullhd { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 40%; - } - - .column.is-three-fifths-fullhd { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 60%; - } - - .column.is-four-fifths-fullhd { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 80%; - } - - .column.is-offset-three-quarters-fullhd { - margin-left: 75%; - } - - .column.is-offset-two-thirds-fullhd { - margin-left: 66.6666%; - } - - .column.is-offset-half-fullhd { - margin-left: 50%; - } - - .column.is-offset-one-third-fullhd { - margin-left: 33.3333%; - } - - .column.is-offset-one-quarter-fullhd { - margin-left: 25%; - } - - .column.is-offset-one-fifth-fullhd { - margin-left: 20%; - } - - .column.is-offset-two-fifths-fullhd { - margin-left: 40%; - } - - .column.is-offset-three-fifths-fullhd { - margin-left: 60%; - } - - .column.is-offset-four-fifths-fullhd { - margin-left: 80%; - } - - .column.is-0-fullhd { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 0%; - } - - .column.is-offset-0-fullhd { - margin-left: 0%; - } - - .column.is-1-fullhd { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 8.33333%; - } - - .column.is-offset-1-fullhd { - margin-left: 8.33333%; - } - - .column.is-2-fullhd { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 16.66667%; - } - - .column.is-offset-2-fullhd { - margin-left: 16.66667%; - } - - .column.is-3-fullhd { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 25%; - } - - .column.is-offset-3-fullhd { - margin-left: 25%; - } - - .column.is-4-fullhd { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 33.33333%; - } - - .column.is-offset-4-fullhd { - margin-left: 33.33333%; - } - - .column.is-5-fullhd { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 41.66667%; - } - - .column.is-offset-5-fullhd { - margin-left: 41.66667%; - } - - .column.is-6-fullhd { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 50%; - } - - .column.is-offset-6-fullhd { - margin-left: 50%; - } - - .column.is-7-fullhd { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 58.33333%; - } - - .column.is-offset-7-fullhd { - margin-left: 58.33333%; - } - - .column.is-8-fullhd { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 66.66667%; - } - - .column.is-offset-8-fullhd { - margin-left: 66.66667%; - } - - .column.is-9-fullhd { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 75%; - } - - .column.is-offset-9-fullhd { - margin-left: 75%; - } - - .column.is-10-fullhd { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 83.33333%; - } - - .column.is-offset-10-fullhd { - margin-left: 83.33333%; - } - - .column.is-11-fullhd { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 91.66667%; - } - - .column.is-offset-11-fullhd { - margin-left: 91.66667%; - } - - .column.is-12-fullhd { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 100%; - } - - .column.is-offset-12-fullhd { - margin-left: 100%; - } -} - -.columns { - margin-left: -0.75rem; - margin-right: -0.75rem; - margin-top: -0.75rem; -} - - .columns:last-child { - margin-bottom: -0.75rem; - } - - .columns:not(:last-child) { - margin-bottom: calc(1.5rem - 0.75rem); - } - - .columns.is-centered { - -webkit-box-pack: center; - -ms-flex-pack: center; - justify-content: center; - } - - .columns.is-gapless { - margin-left: 0; - margin-right: 0; - margin-top: 0; - } - - .columns.is-gapless > .column { - margin: 0; - padding: 0 !important; - } - - .columns.is-gapless:not(:last-child) { - margin-bottom: 1.5rem; - } - - .columns.is-gapless:last-child { - margin-bottom: 0; - } - - .columns.is-mobile { - display: -webkit-box; - display: -ms-flexbox; - display: flex; - } - - .columns.is-multiline { - -ms-flex-wrap: wrap; - flex-wrap: wrap; - } - - .columns.is-vcentered { - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - } - -@media screen and (min-width: 769px), print { - .columns:not(.is-desktop) { - display: -webkit-box; - display: -ms-flexbox; - display: flex; - } -} - -@media screen and (min-width: 1024px) { - .columns.is-desktop { - display: -webkit-box; - display: -ms-flexbox; - display: flex; - } -} - -.columns.is-variable { - --columnGap: 0.75rem; - margin-left: calc(-1 * var(--columnGap)); - margin-right: calc(-1 * var(--columnGap)); -} - - .columns.is-variable > .column { - padding-left: var(--columnGap); - padding-right: var(--columnGap); - } - - .columns.is-variable.is-0 { - --columnGap: 0rem; - } - -@media screen and (max-width: 768px) { - .columns.is-variable.is-0-mobile { - --columnGap: 0rem; - } -} - -@media screen and (min-width: 769px), print { - .columns.is-variable.is-0-tablet { - --columnGap: 0rem; - } -} - -@media screen and (min-width: 769px) and (max-width: 1023px) { - .columns.is-variable.is-0-tablet-only { - --columnGap: 0rem; - } -} - -@media screen and (max-width: 1023px) { - .columns.is-variable.is-0-touch { - --columnGap: 0rem; - } -} - -@media screen and (min-width: 1024px) { - .columns.is-variable.is-0-desktop { - --columnGap: 0rem; - } -} - -@media screen and (min-width: 1024px) and (max-width: 1215px) { - .columns.is-variable.is-0-desktop-only { - --columnGap: 0rem; - } -} - -@media screen and (min-width: 1216px) { - .columns.is-variable.is-0-widescreen { - --columnGap: 0rem; - } -} - -@media screen and (min-width: 1216px) and (max-width: 1407px) { - .columns.is-variable.is-0-widescreen-only { - --columnGap: 0rem; - } -} - -@media screen and (min-width: 1408px) { - .columns.is-variable.is-0-fullhd { - --columnGap: 0rem; - } -} - -.columns.is-variable.is-1 { - --columnGap: 0.25rem; -} - -@media screen and (max-width: 768px) { - .columns.is-variable.is-1-mobile { - --columnGap: 0.25rem; - } -} - -@media screen and (min-width: 769px), print { - .columns.is-variable.is-1-tablet { - --columnGap: 0.25rem; - } -} - -@media screen and (min-width: 769px) and (max-width: 1023px) { - .columns.is-variable.is-1-tablet-only { - --columnGap: 0.25rem; - } -} - -@media screen and (max-width: 1023px) { - .columns.is-variable.is-1-touch { - --columnGap: 0.25rem; - } -} - -@media screen and (min-width: 1024px) { - .columns.is-variable.is-1-desktop { - --columnGap: 0.25rem; - } -} - -@media screen and (min-width: 1024px) and (max-width: 1215px) { - .columns.is-variable.is-1-desktop-only { - --columnGap: 0.25rem; - } -} - -@media screen and (min-width: 1216px) { - .columns.is-variable.is-1-widescreen { - --columnGap: 0.25rem; - } -} - -@media screen and (min-width: 1216px) and (max-width: 1407px) { - .columns.is-variable.is-1-widescreen-only { - --columnGap: 0.25rem; - } -} - -@media screen and (min-width: 1408px) { - .columns.is-variable.is-1-fullhd { - --columnGap: 0.25rem; - } -} - -.columns.is-variable.is-2 { - --columnGap: 0.5rem; -} - -@media screen and (max-width: 768px) { - .columns.is-variable.is-2-mobile { - --columnGap: 0.5rem; - } -} - -@media screen and (min-width: 769px), print { - .columns.is-variable.is-2-tablet { - --columnGap: 0.5rem; - } -} - -@media screen and (min-width: 769px) and (max-width: 1023px) { - .columns.is-variable.is-2-tablet-only { - --columnGap: 0.5rem; - } -} - -@media screen and (max-width: 1023px) { - .columns.is-variable.is-2-touch { - --columnGap: 0.5rem; - } -} - -@media screen and (min-width: 1024px) { - .columns.is-variable.is-2-desktop { - --columnGap: 0.5rem; - } -} - -@media screen and (min-width: 1024px) and (max-width: 1215px) { - .columns.is-variable.is-2-desktop-only { - --columnGap: 0.5rem; - } -} - -@media screen and (min-width: 1216px) { - .columns.is-variable.is-2-widescreen { - --columnGap: 0.5rem; - } -} - -@media screen and (min-width: 1216px) and (max-width: 1407px) { - .columns.is-variable.is-2-widescreen-only { - --columnGap: 0.5rem; - } -} - -@media screen and (min-width: 1408px) { - .columns.is-variable.is-2-fullhd { - --columnGap: 0.5rem; - } -} - -.columns.is-variable.is-3 { - --columnGap: 0.75rem; -} - -@media screen and (max-width: 768px) { - .columns.is-variable.is-3-mobile { - --columnGap: 0.75rem; - } -} - -@media screen and (min-width: 769px), print { - .columns.is-variable.is-3-tablet { - --columnGap: 0.75rem; - } -} - -@media screen and (min-width: 769px) and (max-width: 1023px) { - .columns.is-variable.is-3-tablet-only { - --columnGap: 0.75rem; - } -} - -@media screen and (max-width: 1023px) { - .columns.is-variable.is-3-touch { - --columnGap: 0.75rem; - } -} - -@media screen and (min-width: 1024px) { - .columns.is-variable.is-3-desktop { - --columnGap: 0.75rem; - } -} - -@media screen and (min-width: 1024px) and (max-width: 1215px) { - .columns.is-variable.is-3-desktop-only { - --columnGap: 0.75rem; - } -} - -@media screen and (min-width: 1216px) { - .columns.is-variable.is-3-widescreen { - --columnGap: 0.75rem; - } -} - -@media screen and (min-width: 1216px) and (max-width: 1407px) { - .columns.is-variable.is-3-widescreen-only { - --columnGap: 0.75rem; - } -} - -@media screen and (min-width: 1408px) { - .columns.is-variable.is-3-fullhd { - --columnGap: 0.75rem; - } -} - -.columns.is-variable.is-4 { - --columnGap: 1rem; -} - -@media screen and (max-width: 768px) { - .columns.is-variable.is-4-mobile { - --columnGap: 1rem; - } -} - -@media screen and (min-width: 769px), print { - .columns.is-variable.is-4-tablet { - --columnGap: 1rem; - } -} - -@media screen and (min-width: 769px) and (max-width: 1023px) { - .columns.is-variable.is-4-tablet-only { - --columnGap: 1rem; - } -} - -@media screen and (max-width: 1023px) { - .columns.is-variable.is-4-touch { - --columnGap: 1rem; - } -} - -@media screen and (min-width: 1024px) { - .columns.is-variable.is-4-desktop { - --columnGap: 1rem; - } -} - -@media screen and (min-width: 1024px) and (max-width: 1215px) { - .columns.is-variable.is-4-desktop-only { - --columnGap: 1rem; - } -} - -@media screen and (min-width: 1216px) { - .columns.is-variable.is-4-widescreen { - --columnGap: 1rem; - } -} - -@media screen and (min-width: 1216px) and (max-width: 1407px) { - .columns.is-variable.is-4-widescreen-only { - --columnGap: 1rem; - } -} - -@media screen and (min-width: 1408px) { - .columns.is-variable.is-4-fullhd { - --columnGap: 1rem; - } -} - -.columns.is-variable.is-5 { - --columnGap: 1.25rem; -} - -@media screen and (max-width: 768px) { - .columns.is-variable.is-5-mobile { - --columnGap: 1.25rem; - } -} - -@media screen and (min-width: 769px), print { - .columns.is-variable.is-5-tablet { - --columnGap: 1.25rem; - } -} - -@media screen and (min-width: 769px) and (max-width: 1023px) { - .columns.is-variable.is-5-tablet-only { - --columnGap: 1.25rem; - } -} - -@media screen and (max-width: 1023px) { - .columns.is-variable.is-5-touch { - --columnGap: 1.25rem; - } -} - -@media screen and (min-width: 1024px) { - .columns.is-variable.is-5-desktop { - --columnGap: 1.25rem; - } -} - -@media screen and (min-width: 1024px) and (max-width: 1215px) { - .columns.is-variable.is-5-desktop-only { - --columnGap: 1.25rem; - } -} - -@media screen and (min-width: 1216px) { - .columns.is-variable.is-5-widescreen { - --columnGap: 1.25rem; - } -} - -@media screen and (min-width: 1216px) and (max-width: 1407px) { - .columns.is-variable.is-5-widescreen-only { - --columnGap: 1.25rem; - } -} - -@media screen and (min-width: 1408px) { - .columns.is-variable.is-5-fullhd { - --columnGap: 1.25rem; - } -} - -.columns.is-variable.is-6 { - --columnGap: 1.5rem; -} - -@media screen and (max-width: 768px) { - .columns.is-variable.is-6-mobile { - --columnGap: 1.5rem; - } -} - -@media screen and (min-width: 769px), print { - .columns.is-variable.is-6-tablet { - --columnGap: 1.5rem; - } -} - -@media screen and (min-width: 769px) and (max-width: 1023px) { - .columns.is-variable.is-6-tablet-only { - --columnGap: 1.5rem; - } -} - -@media screen and (max-width: 1023px) { - .columns.is-variable.is-6-touch { - --columnGap: 1.5rem; - } -} - -@media screen and (min-width: 1024px) { - .columns.is-variable.is-6-desktop { - --columnGap: 1.5rem; - } -} - -@media screen and (min-width: 1024px) and (max-width: 1215px) { - .columns.is-variable.is-6-desktop-only { - --columnGap: 1.5rem; - } -} - -@media screen and (min-width: 1216px) { - .columns.is-variable.is-6-widescreen { - --columnGap: 1.5rem; - } -} - -@media screen and (min-width: 1216px) and (max-width: 1407px) { - .columns.is-variable.is-6-widescreen-only { - --columnGap: 1.5rem; - } -} - -@media screen and (min-width: 1408px) { - .columns.is-variable.is-6-fullhd { - --columnGap: 1.5rem; - } -} - -.columns.is-variable.is-7 { - --columnGap: 1.75rem; -} - -@media screen and (max-width: 768px) { - .columns.is-variable.is-7-mobile { - --columnGap: 1.75rem; - } -} - -@media screen and (min-width: 769px), print { - .columns.is-variable.is-7-tablet { - --columnGap: 1.75rem; - } -} - -@media screen and (min-width: 769px) and (max-width: 1023px) { - .columns.is-variable.is-7-tablet-only { - --columnGap: 1.75rem; - } -} - -@media screen and (max-width: 1023px) { - .columns.is-variable.is-7-touch { - --columnGap: 1.75rem; - } -} - -@media screen and (min-width: 1024px) { - .columns.is-variable.is-7-desktop { - --columnGap: 1.75rem; - } -} - -@media screen and (min-width: 1024px) and (max-width: 1215px) { - .columns.is-variable.is-7-desktop-only { - --columnGap: 1.75rem; - } -} - -@media screen and (min-width: 1216px) { - .columns.is-variable.is-7-widescreen { - --columnGap: 1.75rem; - } -} - -@media screen and (min-width: 1216px) and (max-width: 1407px) { - .columns.is-variable.is-7-widescreen-only { - --columnGap: 1.75rem; - } -} - -@media screen and (min-width: 1408px) { - .columns.is-variable.is-7-fullhd { - --columnGap: 1.75rem; - } -} - -.columns.is-variable.is-8 { - --columnGap: 2rem; -} - -@media screen and (max-width: 768px) { - .columns.is-variable.is-8-mobile { - --columnGap: 2rem; - } -} - -@media screen and (min-width: 769px), print { - .columns.is-variable.is-8-tablet { - --columnGap: 2rem; - } -} - -@media screen and (min-width: 769px) and (max-width: 1023px) { - .columns.is-variable.is-8-tablet-only { - --columnGap: 2rem; - } -} - -@media screen and (max-width: 1023px) { - .columns.is-variable.is-8-touch { - --columnGap: 2rem; - } -} - -@media screen and (min-width: 1024px) { - .columns.is-variable.is-8-desktop { - --columnGap: 2rem; - } -} - -@media screen and (min-width: 1024px) and (max-width: 1215px) { - .columns.is-variable.is-8-desktop-only { - --columnGap: 2rem; - } -} - -@media screen and (min-width: 1216px) { - .columns.is-variable.is-8-widescreen { - --columnGap: 2rem; - } -} - -@media screen and (min-width: 1216px) and (max-width: 1407px) { - .columns.is-variable.is-8-widescreen-only { - --columnGap: 2rem; - } -} - -@media screen and (min-width: 1408px) { - .columns.is-variable.is-8-fullhd { - --columnGap: 2rem; - } -} - -.tile { - -webkit-box-align: stretch; - -ms-flex-align: stretch; - align-items: stretch; - display: block; - -ms-flex-preferred-size: 0; - flex-basis: 0; - -webkit-box-flex: 1; - -ms-flex-positive: 1; - flex-grow: 1; - -ms-flex-negative: 1; - flex-shrink: 1; - min-height: -webkit-min-content; - min-height: -moz-min-content; - min-height: min-content; -} - - .tile.is-ancestor { - margin-left: -0.75rem; - margin-right: -0.75rem; - margin-top: -0.75rem; - } - - .tile.is-ancestor:last-child { - margin-bottom: -0.75rem; - } - - .tile.is-ancestor:not(:last-child) { - margin-bottom: 0.75rem; - } - - .tile.is-child { - margin: 0 !important; - } - - .tile.is-parent { - padding: 0.75rem; - } - - .tile.is-vertical { - -webkit-box-orient: vertical; - -webkit-box-direction: normal; - -ms-flex-direction: column; - flex-direction: column; - } - - .tile.is-vertical > .tile.is-child:not(:last-child) { - margin-bottom: 1.5rem !important; - } - -@media screen and (min-width: 769px), print { - .tile:not(.is-child) { - display: -webkit-box; - display: -ms-flexbox; - display: flex; - } - - .tile.is-1 { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 8.33333%; - } - - .tile.is-2 { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 16.66667%; - } - - .tile.is-3 { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 25%; - } - - .tile.is-4 { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 33.33333%; - } - - .tile.is-5 { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 41.66667%; - } - - .tile.is-6 { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 50%; - } - - .tile.is-7 { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 58.33333%; - } - - .tile.is-8 { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 66.66667%; - } - - .tile.is-9 { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 75%; - } - - .tile.is-10 { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 83.33333%; - } - - .tile.is-11 { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 91.66667%; - } - - .tile.is-12 { - -webkit-box-flex: 0; - -ms-flex: none; - flex: none; - width: 100%; - } -} -/* Bulma Helpers */ -.has-text-white { - color: white !important; -} - -a.has-text-white:hover, a.has-text-white:focus { - color: #e6e6e6 !important; -} - -.has-background-white { - background-color: white !important; -} - -.has-text-black { - color: #0a0a0a !important; -} - -a.has-text-black:hover, a.has-text-black:focus { - color: black !important; -} - -.has-background-black { - background-color: #0a0a0a !important; -} - -.has-text-light { - color: whitesmoke !important; -} - -a.has-text-light:hover, a.has-text-light:focus { - color: #dbdbdb !important; -} - -.has-background-light { - background-color: whitesmoke !important; -} - -.has-text-dark { - color: #200117 !important; -} - -a.has-text-dark:hover, a.has-text-dark:focus { - color: black !important; -} - -.has-background-dark { - background-color: #200117 !important; -} - -.has-text-primary { - color: #A00975 !important; -} - -a.has-text-primary:hover, a.has-text-primary:focus { - color: #700652 !important; -} - -.has-background-primary { - background-color: #A00975 !important; -} - -.has-text-primary-light { - color: #feecf9 !important; -} - -a.has-text-primary-light:hover, a.has-text-primary-light:focus { - color: #fbbbe9 !important; -} - -.has-background-primary-light { - background-color: #feecf9 !important; -} - -.has-text-primary-dark { - color: #f212b2 !important; -} - -a.has-text-primary-dark:hover, a.has-text-primary-dark:focus { - color: #f443c2 !important; -} - -.has-background-primary-dark { - background-color: #f212b2 !important; -} - -.has-text-link { - color: #378BBA !important; -} - -a.has-text-link:hover, a.has-text-link:focus { - color: #2b6e93 !important; -} - -.has-background-link { - background-color: #378BBA !important; -} - -.has-text-link-light { - color: #eff6fa !important; -} - -a.has-text-link-light:hover, a.has-text-link-light:focus { - color: #c8e1ef !important; -} - -.has-background-link-light { - background-color: #eff6fa !important; -} - -.has-text-link-dark { - color: #317ca5 !important; -} - -a.has-text-link-dark:hover, a.has-text-link-dark:focus { - color: #4297c7 !important; -} - -.has-background-link-dark { - background-color: #317ca5 !important; -} - -.has-text-info { - color: #3298dc !important; -} - -a.has-text-info:hover, a.has-text-info:focus { - color: #207dbc !important; -} - -.has-background-info { - background-color: #3298dc !important; -} - -.has-text-info-light { - color: #eef6fc !important; -} - -a.has-text-info-light:hover, a.has-text-info-light:focus { - color: #c2e0f5 !important; -} - -.has-background-info-light { - background-color: #eef6fc !important; -} - -.has-text-info-dark { - color: #1d72aa !important; -} - -a.has-text-info-dark:hover, a.has-text-info-dark:focus { - color: #248fd6 !important; -} - -.has-background-info-dark { - background-color: #1d72aa !important; -} - -.has-text-success { - color: #48c774 !important; -} - -a.has-text-success:hover, a.has-text-success:focus { - color: #34a85c !important; -} - -.has-background-success { - background-color: #48c774 !important; -} - -.has-text-success-light { - color: #effaf3 !important; -} - -a.has-text-success-light:hover, a.has-text-success-light:focus { - color: #c8eed6 !important; -} - -.has-background-success-light { - background-color: #effaf3 !important; -} - -.has-text-success-dark { - color: #257942 !important; -} - -a.has-text-success-dark:hover, a.has-text-success-dark:focus { - color: #31a058 !important; -} - -.has-background-success-dark { - background-color: #257942 !important; -} - -.has-text-warning { - color: #ffdd57 !important; -} - -a.has-text-warning:hover, a.has-text-warning:focus { - color: #ffd324 !important; -} - -.has-background-warning { - background-color: #ffdd57 !important; -} - -.has-text-warning-light { - color: #fffbeb !important; -} - -a.has-text-warning-light:hover, a.has-text-warning-light:focus { - color: #fff1b8 !important; -} - -.has-background-warning-light { - background-color: #fffbeb !important; -} - -.has-text-warning-dark { - color: #947600 !important; -} - -a.has-text-warning-dark:hover, a.has-text-warning-dark:focus { - color: #c79f00 !important; -} - -.has-background-warning-dark { - background-color: #947600 !important; -} - -.has-text-danger { - color: #f14668 !important; -} - -a.has-text-danger:hover, a.has-text-danger:focus { - color: #ee1742 !important; -} - -.has-background-danger { - background-color: #f14668 !important; -} - -.has-text-danger-light { - color: #feecf0 !important; -} - -a.has-text-danger-light:hover, a.has-text-danger-light:focus { - color: #fabdc9 !important; -} - -.has-background-danger-light { - background-color: #feecf0 !important; -} - -.has-text-danger-dark { - color: #cc0f35 !important; -} - -a.has-text-danger-dark:hover, a.has-text-danger-dark:focus { - color: #ee2049 !important; -} - -.has-background-danger-dark { - background-color: #cc0f35 !important; -} - -.has-text-black-bis { - color: #121212 !important; -} - -.has-background-black-bis { - background-color: #121212 !important; -} - -.has-text-black-ter { - color: #242424 !important; -} - -.has-background-black-ter { - background-color: #242424 !important; -} - -.has-text-grey-darker { - color: #363636 !important; -} - -.has-background-grey-darker { - background-color: #363636 !important; -} - -.has-text-grey-dark { - color: #4a4a4a !important; -} - -.has-background-grey-dark { - background-color: #4a4a4a !important; -} - -.has-text-grey { - color: #7a7a7a !important; -} - -.has-background-grey { - background-color: #7a7a7a !important; -} - -.has-text-grey-light { - color: #b5b5b5 !important; -} - -.has-background-grey-light { - background-color: #b5b5b5 !important; -} - -.has-text-grey-lighter { - color: #dbdbdb !important; -} - -.has-background-grey-lighter { - background-color: #dbdbdb !important; -} - -.has-text-white-ter { - color: whitesmoke !important; -} - -.has-background-white-ter { - background-color: whitesmoke !important; -} - -.has-text-white-bis { - color: #fafafa !important; -} - -.has-background-white-bis { - background-color: #fafafa !important; -} - -.is-flex-direction-row { - -webkit-box-orient: horizontal !important; - -webkit-box-direction: normal !important; - -ms-flex-direction: row !important; - flex-direction: row !important; -} - -.is-flex-direction-row-reverse { - -webkit-box-orient: horizontal !important; - -webkit-box-direction: reverse !important; - -ms-flex-direction: row-reverse !important; - flex-direction: row-reverse !important; -} - -.is-flex-direction-column { - -webkit-box-orient: vertical !important; - -webkit-box-direction: normal !important; - -ms-flex-direction: column !important; - flex-direction: column !important; -} - -.is-flex-direction-column-reverse { - -webkit-box-orient: vertical !important; - -webkit-box-direction: reverse !important; - -ms-flex-direction: column-reverse !important; - flex-direction: column-reverse !important; -} - -.is-flex-wrap-nowrap { - -ms-flex-wrap: nowrap !important; - flex-wrap: nowrap !important; -} - -.is-flex-wrap-wrap { - -ms-flex-wrap: wrap !important; - flex-wrap: wrap !important; -} - -.is-flex-wrap-wrap-reverse { - -ms-flex-wrap: wrap-reverse !important; - flex-wrap: wrap-reverse !important; -} - -.is-justify-content-flex-start { - -webkit-box-pack: start !important; - -ms-flex-pack: start !important; - justify-content: flex-start !important; -} - -.is-justify-content-flex-end { - -webkit-box-pack: end !important; - -ms-flex-pack: end !important; - justify-content: flex-end !important; -} - -.is-justify-content-center { - -webkit-box-pack: center !important; - -ms-flex-pack: center !important; - justify-content: center !important; -} - -.is-justify-content-space-between { - -webkit-box-pack: justify !important; - -ms-flex-pack: justify !important; - justify-content: space-between !important; -} - -.is-justify-content-space-around { - -ms-flex-pack: distribute !important; - justify-content: space-around !important; -} - -.is-justify-content-space-evenly { - -webkit-box-pack: space-evenly !important; - -ms-flex-pack: space-evenly !important; - justify-content: space-evenly !important; -} - -.is-justify-content-start { - -webkit-box-pack: start !important; - -ms-flex-pack: start !important; - justify-content: start !important; -} - -.is-justify-content-end { - -webkit-box-pack: end !important; - -ms-flex-pack: end !important; - justify-content: end !important; -} - -.is-justify-content-left { - -webkit-box-pack: left !important; - -ms-flex-pack: left !important; - justify-content: left !important; -} - -.is-justify-content-right { - -webkit-box-pack: right !important; - -ms-flex-pack: right !important; - justify-content: right !important; -} - -.is-align-content-flex-start { - -ms-flex-line-pack: start !important; - align-content: flex-start !important; -} - -.is-align-content-flex-end { - -ms-flex-line-pack: end !important; - align-content: flex-end !important; -} - -.is-align-content-center { - -ms-flex-line-pack: center !important; - align-content: center !important; -} - -.is-align-content-space-between { - -ms-flex-line-pack: justify !important; - align-content: space-between !important; -} - -.is-align-content-space-around { - -ms-flex-line-pack: distribute !important; - align-content: space-around !important; -} - -.is-align-content-space-evenly { - -ms-flex-line-pack: space-evenly !important; - align-content: space-evenly !important; -} - -.is-align-content-stretch { - -ms-flex-line-pack: stretch !important; - align-content: stretch !important; -} - -.is-align-content-start { - -ms-flex-line-pack: start !important; - align-content: start !important; -} - -.is-align-content-end { - -ms-flex-line-pack: end !important; - align-content: end !important; -} - -.is-align-content-baseline { - -ms-flex-line-pack: baseline !important; - align-content: baseline !important; -} - -.is-align-items-stretch { - -webkit-box-align: stretch !important; - -ms-flex-align: stretch !important; - align-items: stretch !important; -} - -.is-align-items-flex-start { - -webkit-box-align: start !important; - -ms-flex-align: start !important; - align-items: flex-start !important; -} - -.is-align-items-flex-end { - -webkit-box-align: end !important; - -ms-flex-align: end !important; - align-items: flex-end !important; -} - -.is-align-items-center { - -webkit-box-align: center !important; - -ms-flex-align: center !important; - align-items: center !important; -} - -.is-align-items-baseline { - -webkit-box-align: baseline !important; - -ms-flex-align: baseline !important; - align-items: baseline !important; -} - -.is-align-items-start { - -webkit-box-align: start !important; - -ms-flex-align: start !important; - align-items: start !important; -} - -.is-align-items-end { - -webkit-box-align: end !important; - -ms-flex-align: end !important; - align-items: end !important; -} - -.is-align-items-self-start { - -webkit-box-align: self-start !important; - -ms-flex-align: self-start !important; - align-items: self-start !important; -} - -.is-align-items-self-end { - -webkit-box-align: self-end !important; - -ms-flex-align: self-end !important; - align-items: self-end !important; -} - -.is-align-self-auto { - -ms-flex-item-align: auto !important; - align-self: auto !important; -} - -.is-align-self-flex-start { - -ms-flex-item-align: start !important; - align-self: flex-start !important; -} - -.is-align-self-flex-end { - -ms-flex-item-align: end !important; - align-self: flex-end !important; -} - -.is-align-self-center { - -ms-flex-item-align: center !important; - align-self: center !important; -} - -.is-align-self-baseline { - -ms-flex-item-align: baseline !important; - align-self: baseline !important; -} - -.is-align-self-stretch { - -ms-flex-item-align: stretch !important; - align-self: stretch !important; -} - -.is-flex-grow-0 { - -webkit-box-flex: 0 !important; - -ms-flex-positive: 0 !important; - flex-grow: 0 !important; -} - -.is-flex-grow-1 { - -webkit-box-flex: 1 !important; - -ms-flex-positive: 1 !important; - flex-grow: 1 !important; -} - -.is-flex-grow-2 { - -webkit-box-flex: 2 !important; - -ms-flex-positive: 2 !important; - flex-grow: 2 !important; -} - -.is-flex-grow-3 { - -webkit-box-flex: 3 !important; - -ms-flex-positive: 3 !important; - flex-grow: 3 !important; -} - -.is-flex-grow-4 { - -webkit-box-flex: 4 !important; - -ms-flex-positive: 4 !important; - flex-grow: 4 !important; -} - -.is-flex-grow-5 { - -webkit-box-flex: 5 !important; - -ms-flex-positive: 5 !important; - flex-grow: 5 !important; -} - -.is-flex-shrink-0 { - -ms-flex-negative: 0 !important; - flex-shrink: 0 !important; -} - -.is-flex-shrink-1 { - -ms-flex-negative: 1 !important; - flex-shrink: 1 !important; -} - -.is-flex-shrink-2 { - -ms-flex-negative: 2 !important; - flex-shrink: 2 !important; -} - -.is-flex-shrink-3 { - -ms-flex-negative: 3 !important; - flex-shrink: 3 !important; -} - -.is-flex-shrink-4 { - -ms-flex-negative: 4 !important; - flex-shrink: 4 !important; -} - -.is-flex-shrink-5 { - -ms-flex-negative: 5 !important; - flex-shrink: 5 !important; -} - -.is-clearfix::after { - clear: both; - content: " "; - display: table; -} - -.is-pulled-left { - float: left !important; -} - -.is-pulled-right { - float: right !important; -} - -.is-radiusless { - border-radius: 0 !important; -} - -.is-shadowless { - -webkit-box-shadow: none !important; - box-shadow: none !important; -} - -.is-clickable { - cursor: pointer !important; - pointer-events: all !important; -} - -.is-clipped { - overflow: hidden !important; -} - -.is-relative { - position: relative !important; -} - -.is-marginless { - margin: 0 !important; -} - -.is-paddingless { - padding: 0 !important; -} - -.m-0 { - margin: 0 !important; -} - -.mt-0 { - margin-top: 0 !important; -} - -.mr-0 { - margin-right: 0 !important; -} - -.mb-0 { - margin-bottom: 0 !important; -} - -.ml-0 { - margin-left: 0 !important; -} - -.mx-0 { - margin-left: 0 !important; - margin-right: 0 !important; -} - -.my-0 { - margin-top: 0 !important; - margin-bottom: 0 !important; -} - -.m-1 { - margin: 0.25rem !important; -} - -.mt-1 { - margin-top: 0.25rem !important; -} - -.mr-1 { - margin-right: 0.25rem !important; -} - -.mb-1 { - margin-bottom: 0.25rem !important; -} - -.ml-1 { - margin-left: 0.25rem !important; -} - -.mx-1 { - margin-left: 0.25rem !important; - margin-right: 0.25rem !important; -} - -.my-1 { - margin-top: 0.25rem !important; - margin-bottom: 0.25rem !important; -} - -.m-2 { - margin: 0.5rem !important; -} - -.mt-2 { - margin-top: 0.5rem !important; -} - -.mr-2 { - margin-right: 0.5rem !important; -} - -.mb-2 { - margin-bottom: 0.5rem !important; -} - -.ml-2 { - margin-left: 0.5rem !important; -} - -.mx-2 { - margin-left: 0.5rem !important; - margin-right: 0.5rem !important; -} - -.my-2, #fsdocs-content p { - margin-top: 0.5rem !important; - margin-bottom: 0.5rem !important; -} - -.m-3 { - margin: 0.75rem !important; -} - -.mt-3 { - margin-top: 0.75rem !important; -} - -.mr-3 { - margin-right: 0.75rem !important; -} - -.mb-3 { - margin-bottom: 0.75rem !important; -} - -.ml-3 { - margin-left: 0.75rem !important; -} - -.mx-3 { - margin-left: 0.75rem !important; - margin-right: 0.75rem !important; -} - -.my-3 { - margin-top: 0.75rem !important; - margin-bottom: 0.75rem !important; -} - -.m-4 { - margin: 1rem !important; -} - -.mt-4 { - margin-top: 1rem !important; -} - -.mr-4 { - margin-right: 1rem !important; -} - -.mb-4 { - margin-bottom: 1rem !important; -} - -.ml-4 { - margin-left: 1rem !important; -} - -.mx-4 { - margin-left: 1rem !important; - margin-right: 1rem !important; -} - -.my-4 { - margin-top: 1rem !important; - margin-bottom: 1rem !important; -} - -.m-5 { - margin: 1.5rem !important; -} - -.mt-5 { - margin-top: 1.5rem !important; -} - -.mr-5 { - margin-right: 1.5rem !important; -} - -.mb-5 { - margin-bottom: 1.5rem !important; -} - -.ml-5 { - margin-left: 1.5rem !important; -} - -.mx-5 { - margin-left: 1.5rem !important; - margin-right: 1.5rem !important; -} - -.my-5 { - margin-top: 1.5rem !important; - margin-bottom: 1.5rem !important; -} - -.m-6 { - margin: 3rem !important; -} - -.mt-6 { - margin-top: 3rem !important; -} - -.mr-6 { - margin-right: 3rem !important; -} - -.mb-6 { - margin-bottom: 3rem !important; -} - -.ml-6 { - margin-left: 3rem !important; -} - -.mx-6 { - margin-left: 3rem !important; - margin-right: 3rem !important; -} - -.my-6 { - margin-top: 3rem !important; - margin-bottom: 3rem !important; -} - -.p-0 { - padding: 0 !important; -} - -.pt-0 { - padding-top: 0 !important; -} - -.pr-0 { - padding-right: 0 !important; -} - -.pb-0 { - padding-bottom: 0 !important; -} - -.pl-0 { - padding-left: 0 !important; -} - -.px-0 { - padding-left: 0 !important; - padding-right: 0 !important; -} - -.py-0 { - padding-top: 0 !important; - padding-bottom: 0 !important; -} - -.p-1 { - padding: 0.25rem !important; -} - -.pt-1 { - padding-top: 0.25rem !important; -} - -.pr-1 { - padding-right: 0.25rem !important; -} - -.pb-1 { - padding-bottom: 0.25rem !important; -} - -.pl-1 { - padding-left: 0.25rem !important; -} - -.px-1 { - padding-left: 0.25rem !important; - padding-right: 0.25rem !important; -} - -.py-1 { - padding-top: 0.25rem !important; - padding-bottom: 0.25rem !important; -} - -.p-2 { - padding: 0.5rem !important; -} - -.pt-2 { - padding-top: 0.5rem !important; -} - -.pr-2 { - padding-right: 0.5rem !important; -} - -.pb-2 { - padding-bottom: 0.5rem !important; -} - -.pl-2 { - padding-left: 0.5rem !important; -} - -.px-2 { - padding-left: 0.5rem !important; - padding-right: 0.5rem !important; -} - -.py-2 { - padding-top: 0.5rem !important; - padding-bottom: 0.5rem !important; -} - -.p-3 { - padding: 0.75rem !important; -} - -.pt-3 { - padding-top: 0.75rem !important; -} - -.pr-3 { - padding-right: 0.75rem !important; -} - -.pb-3 { - padding-bottom: 0.75rem !important; -} - -.pl-3 { - padding-left: 0.75rem !important; -} - -.px-3 { - padding-left: 0.75rem !important; - padding-right: 0.75rem !important; -} - -.py-3 { - padding-top: 0.75rem !important; - padding-bottom: 0.75rem !important; -} - -.p-4, #fsdocs-content blockquote { - padding: 1rem !important; -} - -.pt-4 { - padding-top: 1rem !important; -} - -.pr-4 { - padding-right: 1rem !important; -} - -.pb-4 { - padding-bottom: 1rem !important; -} - -.pl-4 { - padding-left: 1rem !important; -} - -.px-4 { - padding-left: 1rem !important; - padding-right: 1rem !important; -} - -.py-4 { - padding-top: 1rem !important; - padding-bottom: 1rem !important; -} - -.p-5 { - padding: 1.5rem !important; -} - -.pt-5 { - padding-top: 1.5rem !important; -} - -.pr-5 { - padding-right: 1.5rem !important; -} - -.pb-5 { - padding-bottom: 1.5rem !important; -} - -.pl-5 { - padding-left: 1.5rem !important; -} - -.px-5 { - padding-left: 1.5rem !important; - padding-right: 1.5rem !important; -} - -.py-5 { - padding-top: 1.5rem !important; - padding-bottom: 1.5rem !important; -} - -.p-6 { - padding: 3rem !important; -} - -.pt-6 { - padding-top: 3rem !important; -} - -.pr-6 { - padding-right: 3rem !important; -} - -.pb-6 { - padding-bottom: 3rem !important; -} - -.pl-6 { - padding-left: 3rem !important; -} - -.px-6 { - padding-left: 3rem !important; - padding-right: 3rem !important; -} - -.py-6 { - padding-top: 3rem !important; - padding-bottom: 3rem !important; -} - -.is-size-1 { - font-size: 3rem !important; -} - -.is-size-2 { - font-size: 2.5rem !important; -} - -.is-size-3 { - font-size: 2rem !important; -} - -.is-size-4 { - font-size: 1.5rem !important; -} - -.is-size-5 { - font-size: 1.25rem !important; -} - -.is-size-6 { - font-size: 1rem !important; -} - -.is-size-7 { - font-size: 0.75rem !important; -} - -@media screen and (max-width: 768px) { - .is-size-1-mobile { - font-size: 3rem !important; - } - - .is-size-2-mobile { - font-size: 2.5rem !important; - } - - .is-size-3-mobile { - font-size: 2rem !important; - } - - .is-size-4-mobile { - font-size: 1.5rem !important; - } - - .is-size-5-mobile { - font-size: 1.25rem !important; - } - - .is-size-6-mobile { - font-size: 1rem !important; - } - - .is-size-7-mobile { - font-size: 0.75rem !important; - } -} - -@media screen and (min-width: 769px), print { - .is-size-1-tablet { - font-size: 3rem !important; - } - - .is-size-2-tablet { - font-size: 2.5rem !important; - } - - .is-size-3-tablet { - font-size: 2rem !important; - } - - .is-size-4-tablet { - font-size: 1.5rem !important; - } - - .is-size-5-tablet { - font-size: 1.25rem !important; - } - - .is-size-6-tablet { - font-size: 1rem !important; - } - - .is-size-7-tablet { - font-size: 0.75rem !important; - } -} - -@media screen and (max-width: 1023px) { - .is-size-1-touch { - font-size: 3rem !important; - } - - .is-size-2-touch { - font-size: 2.5rem !important; - } - - .is-size-3-touch { - font-size: 2rem !important; - } - - .is-size-4-touch { - font-size: 1.5rem !important; - } - - .is-size-5-touch { - font-size: 1.25rem !important; - } - - .is-size-6-touch { - font-size: 1rem !important; - } - - .is-size-7-touch { - font-size: 0.75rem !important; - } -} - -@media screen and (min-width: 1024px) { - .is-size-1-desktop { - font-size: 3rem !important; - } - - .is-size-2-desktop { - font-size: 2.5rem !important; - } - - .is-size-3-desktop { - font-size: 2rem !important; - } - - .is-size-4-desktop { - font-size: 1.5rem !important; - } - - .is-size-5-desktop { - font-size: 1.25rem !important; - } - - .is-size-6-desktop { - font-size: 1rem !important; - } - - .is-size-7-desktop { - font-size: 0.75rem !important; - } -} - -@media screen and (min-width: 1216px) { - .is-size-1-widescreen { - font-size: 3rem !important; - } - - .is-size-2-widescreen { - font-size: 2.5rem !important; - } - - .is-size-3-widescreen { - font-size: 2rem !important; - } - - .is-size-4-widescreen { - font-size: 1.5rem !important; - } - - .is-size-5-widescreen { - font-size: 1.25rem !important; - } - - .is-size-6-widescreen { - font-size: 1rem !important; - } - - .is-size-7-widescreen { - font-size: 0.75rem !important; - } -} - -@media screen and (min-width: 1408px) { - .is-size-1-fullhd { - font-size: 3rem !important; - } - - .is-size-2-fullhd { - font-size: 2.5rem !important; - } - - .is-size-3-fullhd { - font-size: 2rem !important; - } - - .is-size-4-fullhd { - font-size: 1.5rem !important; - } - - .is-size-5-fullhd { - font-size: 1.25rem !important; - } - - .is-size-6-fullhd { - font-size: 1rem !important; - } - - .is-size-7-fullhd { - font-size: 0.75rem !important; - } -} - -.has-text-centered { - text-align: center !important; -} - -.has-text-justified { - text-align: justify !important; -} - -.has-text-left { - text-align: left !important; -} - -.has-text-right { - text-align: right !important; -} - -@media screen and (max-width: 768px) { - .has-text-centered-mobile { - text-align: center !important; - } -} - -@media screen and (min-width: 769px), print { - .has-text-centered-tablet { - text-align: center !important; - } -} - -@media screen and (min-width: 769px) and (max-width: 1023px) { - .has-text-centered-tablet-only { - text-align: center !important; - } -} - -@media screen and (max-width: 1023px) { - .has-text-centered-touch { - text-align: center !important; - } -} - -@media screen and (min-width: 1024px) { - .has-text-centered-desktop { - text-align: center !important; - } -} - -@media screen and (min-width: 1024px) and (max-width: 1215px) { - .has-text-centered-desktop-only { - text-align: center !important; - } -} - -@media screen and (min-width: 1216px) { - .has-text-centered-widescreen { - text-align: center !important; - } -} - -@media screen and (min-width: 1216px) and (max-width: 1407px) { - .has-text-centered-widescreen-only { - text-align: center !important; - } -} - -@media screen and (min-width: 1408px) { - .has-text-centered-fullhd { - text-align: center !important; - } -} - -@media screen and (max-width: 768px) { - .has-text-justified-mobile { - text-align: justify !important; - } -} - -@media screen and (min-width: 769px), print { - .has-text-justified-tablet { - text-align: justify !important; - } -} - -@media screen and (min-width: 769px) and (max-width: 1023px) { - .has-text-justified-tablet-only { - text-align: justify !important; - } -} - -@media screen and (max-width: 1023px) { - .has-text-justified-touch { - text-align: justify !important; - } -} - -@media screen and (min-width: 1024px) { - .has-text-justified-desktop { - text-align: justify !important; - } -} - -@media screen and (min-width: 1024px) and (max-width: 1215px) { - .has-text-justified-desktop-only { - text-align: justify !important; - } -} - -@media screen and (min-width: 1216px) { - .has-text-justified-widescreen { - text-align: justify !important; - } -} - -@media screen and (min-width: 1216px) and (max-width: 1407px) { - .has-text-justified-widescreen-only { - text-align: justify !important; - } -} - -@media screen and (min-width: 1408px) { - .has-text-justified-fullhd { - text-align: justify !important; - } -} - -@media screen and (max-width: 768px) { - .has-text-left-mobile { - text-align: left !important; - } -} - -@media screen and (min-width: 769px), print { - .has-text-left-tablet { - text-align: left !important; - } -} - -@media screen and (min-width: 769px) and (max-width: 1023px) { - .has-text-left-tablet-only { - text-align: left !important; - } -} - -@media screen and (max-width: 1023px) { - .has-text-left-touch { - text-align: left !important; - } -} - -@media screen and (min-width: 1024px) { - .has-text-left-desktop { - text-align: left !important; - } -} - -@media screen and (min-width: 1024px) and (max-width: 1215px) { - .has-text-left-desktop-only { - text-align: left !important; - } -} - -@media screen and (min-width: 1216px) { - .has-text-left-widescreen { - text-align: left !important; - } -} - -@media screen and (min-width: 1216px) and (max-width: 1407px) { - .has-text-left-widescreen-only { - text-align: left !important; - } -} - -@media screen and (min-width: 1408px) { - .has-text-left-fullhd { - text-align: left !important; - } -} - -@media screen and (max-width: 768px) { - .has-text-right-mobile { - text-align: right !important; - } -} - -@media screen and (min-width: 769px), print { - .has-text-right-tablet { - text-align: right !important; - } -} - -@media screen and (min-width: 769px) and (max-width: 1023px) { - .has-text-right-tablet-only { - text-align: right !important; - } -} - -@media screen and (max-width: 1023px) { - .has-text-right-touch { - text-align: right !important; - } -} - -@media screen and (min-width: 1024px) { - .has-text-right-desktop { - text-align: right !important; - } -} - -@media screen and (min-width: 1024px) and (max-width: 1215px) { - .has-text-right-desktop-only { - text-align: right !important; - } -} - -@media screen and (min-width: 1216px) { - .has-text-right-widescreen { - text-align: right !important; - } -} - -@media screen and (min-width: 1216px) and (max-width: 1407px) { - .has-text-right-widescreen-only { - text-align: right !important; - } -} - -@media screen and (min-width: 1408px) { - .has-text-right-fullhd { - text-align: right !important; - } -} - -.is-capitalized { - text-transform: capitalize !important; -} - -.is-lowercase { - text-transform: lowercase !important; -} - -.is-uppercase { - text-transform: uppercase !important; -} - -.is-italic { - font-style: italic !important; -} - -.has-text-weight-light { - font-weight: 300 !important; -} - -.has-text-weight-normal { - font-weight: 400 !important; -} - -.has-text-weight-medium { - font-weight: 500 !important; -} - -.has-text-weight-semibold { - font-weight: 600 !important; -} - -.has-text-weight-bold { - font-weight: 700 !important; -} - -.is-family-primary { - font-family: "Nunito", sans-serif !important; -} - -.is-family-secondary { - font-family: "Nunito", sans-serif !important; -} - -.is-family-sans-serif { - font-family: "Nunito", sans-serif !important; -} - -.is-family-monospace { - font-family: monospace !important; -} - -.is-family-code { - font-family: monospace !important; -} - -.is-block { - display: block !important; -} - -@media screen and (max-width: 768px) { - .is-block-mobile { - display: block !important; - } -} - -@media screen and (min-width: 769px), print { - .is-block-tablet { - display: block !important; - } -} - -@media screen and (min-width: 769px) and (max-width: 1023px) { - .is-block-tablet-only { - display: block !important; - } -} - -@media screen and (max-width: 1023px) { - .is-block-touch { - display: block !important; - } -} - -@media screen and (min-width: 1024px) { - .is-block-desktop { - display: block !important; - } -} - -@media screen and (min-width: 1024px) and (max-width: 1215px) { - .is-block-desktop-only { - display: block !important; - } -} - -@media screen and (min-width: 1216px) { - .is-block-widescreen { - display: block !important; - } -} - -@media screen and (min-width: 1216px) and (max-width: 1407px) { - .is-block-widescreen-only { - display: block !important; - } -} - -@media screen and (min-width: 1408px) { - .is-block-fullhd { - display: block !important; - } -} - -.is-flex { - display: -webkit-box !important; - display: -ms-flexbox !important; - display: flex !important; -} - -@media screen and (max-width: 768px) { - .is-flex-mobile { - display: -webkit-box !important; - display: -ms-flexbox !important; - display: flex !important; - } -} - -@media screen and (min-width: 769px), print { - .is-flex-tablet { - display: -webkit-box !important; - display: -ms-flexbox !important; - display: flex !important; - } -} - -@media screen and (min-width: 769px) and (max-width: 1023px) { - .is-flex-tablet-only { - display: -webkit-box !important; - display: -ms-flexbox !important; - display: flex !important; - } -} - -@media screen and (max-width: 1023px) { - .is-flex-touch { - display: -webkit-box !important; - display: -ms-flexbox !important; - display: flex !important; - } -} - -@media screen and (min-width: 1024px) { - .is-flex-desktop { - display: -webkit-box !important; - display: -ms-flexbox !important; - display: flex !important; - } -} - -@media screen and (min-width: 1024px) and (max-width: 1215px) { - .is-flex-desktop-only { - display: -webkit-box !important; - display: -ms-flexbox !important; - display: flex !important; - } -} - -@media screen and (min-width: 1216px) { - .is-flex-widescreen { - display: -webkit-box !important; - display: -ms-flexbox !important; - display: flex !important; - } -} - -@media screen and (min-width: 1216px) and (max-width: 1407px) { - .is-flex-widescreen-only { - display: -webkit-box !important; - display: -ms-flexbox !important; - display: flex !important; - } -} - -@media screen and (min-width: 1408px) { - .is-flex-fullhd { - display: -webkit-box !important; - display: -ms-flexbox !important; - display: flex !important; - } -} - -.is-inline { - display: inline !important; -} - -@media screen and (max-width: 768px) { - .is-inline-mobile { - display: inline !important; - } -} - -@media screen and (min-width: 769px), print { - .is-inline-tablet { - display: inline !important; - } -} - -@media screen and (min-width: 769px) and (max-width: 1023px) { - .is-inline-tablet-only { - display: inline !important; - } -} - -@media screen and (max-width: 1023px) { - .is-inline-touch { - display: inline !important; - } -} - -@media screen and (min-width: 1024px) { - .is-inline-desktop { - display: inline !important; - } -} - -@media screen and (min-width: 1024px) and (max-width: 1215px) { - .is-inline-desktop-only { - display: inline !important; - } -} - -@media screen and (min-width: 1216px) { - .is-inline-widescreen { - display: inline !important; - } -} - -@media screen and (min-width: 1216px) and (max-width: 1407px) { - .is-inline-widescreen-only { - display: inline !important; - } -} - -@media screen and (min-width: 1408px) { - .is-inline-fullhd { - display: inline !important; - } -} - -.is-inline-block { - display: inline-block !important; -} - -@media screen and (max-width: 768px) { - .is-inline-block-mobile { - display: inline-block !important; - } -} - -@media screen and (min-width: 769px), print { - .is-inline-block-tablet { - display: inline-block !important; - } -} - -@media screen and (min-width: 769px) and (max-width: 1023px) { - .is-inline-block-tablet-only { - display: inline-block !important; - } -} - -@media screen and (max-width: 1023px) { - .is-inline-block-touch { - display: inline-block !important; - } -} - -@media screen and (min-width: 1024px) { - .is-inline-block-desktop { - display: inline-block !important; - } -} - -@media screen and (min-width: 1024px) and (max-width: 1215px) { - .is-inline-block-desktop-only { - display: inline-block !important; - } -} - -@media screen and (min-width: 1216px) { - .is-inline-block-widescreen { - display: inline-block !important; - } -} - -@media screen and (min-width: 1216px) and (max-width: 1407px) { - .is-inline-block-widescreen-only { - display: inline-block !important; - } -} - -@media screen and (min-width: 1408px) { - .is-inline-block-fullhd { - display: inline-block !important; - } -} - -.is-inline-flex { - display: -webkit-inline-box !important; - display: -ms-inline-flexbox !important; - display: inline-flex !important; -} - -@media screen and (max-width: 768px) { - .is-inline-flex-mobile { - display: -webkit-inline-box !important; - display: -ms-inline-flexbox !important; - display: inline-flex !important; - } -} - -@media screen and (min-width: 769px), print { - .is-inline-flex-tablet { - display: -webkit-inline-box !important; - display: -ms-inline-flexbox !important; - display: inline-flex !important; - } -} - -@media screen and (min-width: 769px) and (max-width: 1023px) { - .is-inline-flex-tablet-only { - display: -webkit-inline-box !important; - display: -ms-inline-flexbox !important; - display: inline-flex !important; - } -} - -@media screen and (max-width: 1023px) { - .is-inline-flex-touch { - display: -webkit-inline-box !important; - display: -ms-inline-flexbox !important; - display: inline-flex !important; - } -} - -@media screen and (min-width: 1024px) { - .is-inline-flex-desktop { - display: -webkit-inline-box !important; - display: -ms-inline-flexbox !important; - display: inline-flex !important; - } -} - -@media screen and (min-width: 1024px) and (max-width: 1215px) { - .is-inline-flex-desktop-only { - display: -webkit-inline-box !important; - display: -ms-inline-flexbox !important; - display: inline-flex !important; - } -} - -@media screen and (min-width: 1216px) { - .is-inline-flex-widescreen { - display: -webkit-inline-box !important; - display: -ms-inline-flexbox !important; - display: inline-flex !important; - } -} - -@media screen and (min-width: 1216px) and (max-width: 1407px) { - .is-inline-flex-widescreen-only { - display: -webkit-inline-box !important; - display: -ms-inline-flexbox !important; - display: inline-flex !important; - } -} - -@media screen and (min-width: 1408px) { - .is-inline-flex-fullhd { - display: -webkit-inline-box !important; - display: -ms-inline-flexbox !important; - display: inline-flex !important; - } -} - -.is-hidden { - display: none !important; -} - -.is-sr-only { - border: none !important; - clip: rect(0, 0, 0, 0) !important; - height: 0.01em !important; - overflow: hidden !important; - padding: 0 !important; - position: absolute !important; - white-space: nowrap !important; - width: 0.01em !important; -} - -@media screen and (max-width: 768px) { - .is-hidden-mobile { - display: none !important; - } -} - -@media screen and (min-width: 769px), print { - .is-hidden-tablet { - display: none !important; - } -} - -@media screen and (min-width: 769px) and (max-width: 1023px) { - .is-hidden-tablet-only { - display: none !important; - } -} - -@media screen and (max-width: 1023px) { - .is-hidden-touch { - display: none !important; - } -} - -@media screen and (min-width: 1024px) { - .is-hidden-desktop { - display: none !important; - } -} - -@media screen and (min-width: 1024px) and (max-width: 1215px) { - .is-hidden-desktop-only { - display: none !important; - } -} - -@media screen and (min-width: 1216px) { - .is-hidden-widescreen { - display: none !important; - } -} - -@media screen and (min-width: 1216px) and (max-width: 1407px) { - .is-hidden-widescreen-only { - display: none !important; - } -} - -@media screen and (min-width: 1408px) { - .is-hidden-fullhd { - display: none !important; - } -} - -.is-invisible { - visibility: hidden !important; -} - -@media screen and (max-width: 768px) { - .is-invisible-mobile { - visibility: hidden !important; - } -} - -@media screen and (min-width: 769px), print { - .is-invisible-tablet { - visibility: hidden !important; - } -} - -@media screen and (min-width: 769px) and (max-width: 1023px) { - .is-invisible-tablet-only { - visibility: hidden !important; - } -} - -@media screen and (max-width: 1023px) { - .is-invisible-touch { - visibility: hidden !important; - } -} - -@media screen and (min-width: 1024px) { - .is-invisible-desktop { - visibility: hidden !important; - } -} - -@media screen and (min-width: 1024px) and (max-width: 1215px) { - .is-invisible-desktop-only { - visibility: hidden !important; - } -} - -@media screen and (min-width: 1216px) { - .is-invisible-widescreen { - visibility: hidden !important; - } -} - -@media screen and (min-width: 1216px) and (max-width: 1407px) { - .is-invisible-widescreen-only { - visibility: hidden !important; - } -} - -@media screen and (min-width: 1408px) { - .is-invisible-fullhd { - visibility: hidden !important; - } -} - -/* Bulma Layout */ -.hero { - -webkit-box-align: stretch; - -ms-flex-align: stretch; - align-items: stretch; - display: -webkit-box; - display: -ms-flexbox; - display: flex; - -webkit-box-orient: vertical; - -webkit-box-direction: normal; - -ms-flex-direction: column; - flex-direction: column; - -webkit-box-pack: justify; - -ms-flex-pack: justify; - justify-content: space-between; -} - - .hero .navbar { - background: none; - } - - .hero .tabs ul { - border-bottom: none; - } - - .hero.is-white { - background-color: white; - color: #0a0a0a; - } - - .hero.is-white a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current), - .hero.is-white strong { - color: inherit; - } - - .hero.is-white .title { - color: #0a0a0a; - } - - .hero.is-white .subtitle { - color: rgba(10, 10, 10, 0.9); - } - - .hero.is-white .subtitle a:not(.button), - .hero.is-white .subtitle strong { - color: #0a0a0a; - } - -@media screen and (max-width: 1023px) { - .hero.is-white .navbar-menu { - background-color: white; - } -} - -.hero.is-white .navbar-item, -.hero.is-white .navbar-link { - color: rgba(10, 10, 10, 0.7); -} - - .hero.is-white a.navbar-item:hover, .hero.is-white a.navbar-item.is-active, .hero.is-white .navbar-item.active, - .hero.is-white .navbar-link:hover, - .hero.is-white .navbar-link.is-active, - .hero.is-white .navbar-link.active { - background-color: #f2f2f2; - color: #0a0a0a; - } - -.hero.is-white .tabs a { - color: #0a0a0a; - opacity: 0.9; -} - - .hero.is-white .tabs a:hover { - opacity: 1; - } - -.hero.is-white .tabs li.is-active a, .hero.is-white .tabs li.active a { - opacity: 1; -} - -.hero.is-white .tabs.is-boxed a, .hero.is-white .tabs.is-toggle a { - color: #0a0a0a; -} - - .hero.is-white .tabs.is-boxed a:hover, .hero.is-white .tabs.is-toggle a:hover { - background-color: rgba(10, 10, 10, 0.1); - } - -.hero.is-white .tabs.is-boxed li.is-active a, .hero.is-white .tabs.is-boxed li.active a, .hero.is-white .tabs.is-boxed li.is-active a:hover, .hero.is-white .tabs.is-toggle li.is-active a, .hero.is-white .tabs.is-toggle li.active a, .hero.is-white .tabs.is-toggle li.is-active a:hover { - background-color: #0a0a0a; - border-color: #0a0a0a; - color: white; -} - -.hero.is-white.is-bold { - background-image: -o-linear-gradient(309deg, #e8e3e4 0%, white 71%, white 100%); - background-image: linear-gradient(141deg, #e8e3e4 0%, white 71%, white 100%); -} - -@media screen and (max-width: 768px) { - .hero.is-white.is-bold .navbar-menu { - background-image: -o-linear-gradient(309deg, #e8e3e4 0%, white 71%, white 100%); - background-image: linear-gradient(141deg, #e8e3e4 0%, white 71%, white 100%); - } -} - -.hero.is-black { - background-color: #0a0a0a; - color: white; -} - - .hero.is-black a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current), - .hero.is-black strong { - color: inherit; - } - - .hero.is-black .title { - color: white; - } - - .hero.is-black .subtitle { - color: rgba(255, 255, 255, 0.9); - } - - .hero.is-black .subtitle a:not(.button), - .hero.is-black .subtitle strong { - color: white; - } - -@media screen and (max-width: 1023px) { - .hero.is-black .navbar-menu { - background-color: #0a0a0a; - } -} - -.hero.is-black .navbar-item, -.hero.is-black .navbar-link { - color: rgba(255, 255, 255, 0.7); -} - - .hero.is-black a.navbar-item:hover, .hero.is-black a.navbar-item.is-active, .hero.is-black .navbar-item.active, - .hero.is-black .navbar-link:hover, - .hero.is-black .navbar-link.is-active, - .hero.is-black .navbar-link.active { - background-color: black; - color: white; - } - -.hero.is-black .tabs a { - color: white; - opacity: 0.9; -} - - .hero.is-black .tabs a:hover { - opacity: 1; - } - -.hero.is-black .tabs li.is-active a, .hero.is-black .tabs li.active a { - opacity: 1; -} - -.hero.is-black .tabs.is-boxed a, .hero.is-black .tabs.is-toggle a { - color: white; -} - - .hero.is-black .tabs.is-boxed a:hover, .hero.is-black .tabs.is-toggle a:hover { - background-color: rgba(10, 10, 10, 0.1); - } - -.hero.is-black .tabs.is-boxed li.is-active a, .hero.is-black .tabs.is-boxed li.active a, .hero.is-black .tabs.is-boxed li.is-active a:hover, .hero.is-black .tabs.is-toggle li.is-active a, .hero.is-black .tabs.is-toggle li.active a, .hero.is-black .tabs.is-toggle li.is-active a:hover { - background-color: white; - border-color: white; - color: #0a0a0a; -} - -.hero.is-black.is-bold { - background-image: -o-linear-gradient(309deg, black 0%, #0a0a0a 71%, #181616 100%); - background-image: linear-gradient(141deg, black 0%, #0a0a0a 71%, #181616 100%); -} - -@media screen and (max-width: 768px) { - .hero.is-black.is-bold .navbar-menu { - background-image: -o-linear-gradient(309deg, black 0%, #0a0a0a 71%, #181616 100%); - background-image: linear-gradient(141deg, black 0%, #0a0a0a 71%, #181616 100%); - } -} - -.hero.is-light { - background-color: whitesmoke; - color: rgba(0, 0, 0, 0.7); -} - - .hero.is-light a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current), - .hero.is-light strong { - color: inherit; - } - - .hero.is-light .title { - color: rgba(0, 0, 0, 0.7); - } - - .hero.is-light .subtitle { - color: rgba(0, 0, 0, 0.9); - } - - .hero.is-light .subtitle a:not(.button), - .hero.is-light .subtitle strong { - color: rgba(0, 0, 0, 0.7); - } - -@media screen and (max-width: 1023px) { - .hero.is-light .navbar-menu { - background-color: whitesmoke; - } -} - -.hero.is-light .navbar-item, -.hero.is-light .navbar-link { - color: rgba(0, 0, 0, 0.7); -} - - .hero.is-light a.navbar-item:hover, .hero.is-light a.navbar-item.is-active, .hero.is-light .navbar-item.active, - .hero.is-light .navbar-link:hover, - .hero.is-light .navbar-link.is-active, - .hero.is-light .navbar-link.active { - background-color: #e8e8e8; - color: rgba(0, 0, 0, 0.7); - } - -.hero.is-light .tabs a { - color: rgba(0, 0, 0, 0.7); - opacity: 0.9; -} - - .hero.is-light .tabs a:hover { - opacity: 1; - } - -.hero.is-light .tabs li.is-active a, .hero.is-light .tabs li.active a { - opacity: 1; -} - -.hero.is-light .tabs.is-boxed a, .hero.is-light .tabs.is-toggle a { - color: rgba(0, 0, 0, 0.7); -} - - .hero.is-light .tabs.is-boxed a:hover, .hero.is-light .tabs.is-toggle a:hover { - background-color: rgba(10, 10, 10, 0.1); - } - -.hero.is-light .tabs.is-boxed li.is-active a, .hero.is-light .tabs.is-boxed li.active a, .hero.is-light .tabs.is-boxed li.is-active a:hover, .hero.is-light .tabs.is-toggle li.is-active a, .hero.is-light .tabs.is-toggle li.active a, .hero.is-light .tabs.is-toggle li.is-active a:hover { - background-color: rgba(0, 0, 0, 0.7); - border-color: rgba(0, 0, 0, 0.7); - color: whitesmoke; -} - -.hero.is-light.is-bold { - background-image: -o-linear-gradient(309deg, #dfd8d9 0%, whitesmoke 71%, white 100%); - background-image: linear-gradient(141deg, #dfd8d9 0%, whitesmoke 71%, white 100%); -} - -@media screen and (max-width: 768px) { - .hero.is-light.is-bold .navbar-menu { - background-image: -o-linear-gradient(309deg, #dfd8d9 0%, whitesmoke 71%, white 100%); - background-image: linear-gradient(141deg, #dfd8d9 0%, whitesmoke 71%, white 100%); - } -} - -.hero.is-dark { - background-color: #200117; - color: #fff; -} - - .hero.is-dark a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current), - .hero.is-dark strong { - color: inherit; - } - - .hero.is-dark .title { - color: #fff; - } - - .hero.is-dark .subtitle { - color: rgba(255, 255, 255, 0.9); - } - - .hero.is-dark .subtitle a:not(.button), - .hero.is-dark .subtitle strong { - color: #fff; - } - -@media screen and (max-width: 1023px) { - .hero.is-dark .navbar-menu { - background-color: #200117; - } -} - -.hero.is-dark .navbar-item, -.hero.is-dark .navbar-link { - color: rgba(255, 255, 255, 0.7); -} - - .hero.is-dark a.navbar-item:hover, .hero.is-dark a.navbar-item.is-active, .hero.is-dark .navbar-item.active, - .hero.is-dark .navbar-link:hover, - .hero.is-dark .navbar-link.is-active, - .hero.is-dark .navbar-link.active { - background-color: #070005; - color: #fff; - } - -.hero.is-dark .tabs a { - color: #fff; - opacity: 0.9; -} - - .hero.is-dark .tabs a:hover { - opacity: 1; - } - -.hero.is-dark .tabs li.is-active a, .hero.is-dark .tabs li.active a { - opacity: 1; -} - -.hero.is-dark .tabs.is-boxed a, .hero.is-dark .tabs.is-toggle a { - color: #fff; -} - - .hero.is-dark .tabs.is-boxed a:hover, .hero.is-dark .tabs.is-toggle a:hover { - background-color: rgba(10, 10, 10, 0.1); - } - -.hero.is-dark .tabs.is-boxed li.is-active a, .hero.is-dark .tabs.is-boxed li.active a, .hero.is-dark .tabs.is-boxed li.is-active a:hover, .hero.is-dark .tabs.is-toggle li.is-active a, .hero.is-dark .tabs.is-toggle li.active a, .hero.is-dark .tabs.is-toggle li.is-active a:hover { - background-color: #fff; - border-color: #fff; - color: #200117; -} - -.hero.is-dark.is-bold { - background-image: -o-linear-gradient(309deg, black 0%, #200117 71%, #3a0020 100%); - background-image: linear-gradient(141deg, black 0%, #200117 71%, #3a0020 100%); -} - -@media screen and (max-width: 768px) { - .hero.is-dark.is-bold .navbar-menu { - background-image: -o-linear-gradient(309deg, black 0%, #200117 71%, #3a0020 100%); - background-image: linear-gradient(141deg, black 0%, #200117 71%, #3a0020 100%); - } -} - -.hero.is-primary { - background-color: #A00975; - color: #fff; -} - - .hero.is-primary a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current), - .hero.is-primary strong { - color: inherit; - } - - .hero.is-primary .title { - color: #fff; - } - - .hero.is-primary .subtitle { - color: rgba(255, 255, 255, 0.9); - } - - .hero.is-primary .subtitle a:not(.button), - .hero.is-primary .subtitle strong { - color: #fff; - } - -@media screen and (max-width: 1023px) { - .hero.is-primary .navbar-menu { - background-color: #A00975; - } -} - -.hero.is-primary .navbar-item, -.hero.is-primary .navbar-link { - color: rgba(255, 255, 255, 0.7); -} - - .hero.is-primary a.navbar-item:hover, .hero.is-primary a.navbar-item.is-active, .hero.is-primary .navbar-item.active, - .hero.is-primary .navbar-link:hover, - .hero.is-primary .navbar-link.is-active, - .hero.is-primary .navbar-link.active { - background-color: #880863; - color: #fff; - } - -.hero.is-primary .tabs a { - color: #fff; - opacity: 0.9; -} - - .hero.is-primary .tabs a:hover { - opacity: 1; - } - -.hero.is-primary .tabs li.is-active a, .hero.is-primary .tabs li.active a { - opacity: 1; -} - -.hero.is-primary .tabs.is-boxed a, .hero.is-primary .tabs.is-toggle a { - color: #fff; -} - - .hero.is-primary .tabs.is-boxed a:hover, .hero.is-primary .tabs.is-toggle a:hover { - background-color: rgba(10, 10, 10, 0.1); - } - -.hero.is-primary .tabs.is-boxed li.is-active a, .hero.is-primary .tabs.is-boxed li.active a, .hero.is-primary .tabs.is-boxed li.is-active a:hover, .hero.is-primary .tabs.is-toggle li.is-active a, .hero.is-primary .tabs.is-toggle li.active a, .hero.is-primary .tabs.is-toggle li.is-active a:hover { - background-color: #fff; - border-color: #fff; - color: #A00975; -} - -.hero.is-primary.is-bold { - background-image: -o-linear-gradient(309deg, #760068 0%, #A00975 71%, #bd056a 100%); - background-image: linear-gradient(141deg, #760068 0%, #A00975 71%, #bd056a 100%); -} - -@media screen and (max-width: 768px) { - .hero.is-primary.is-bold .navbar-menu { - background-image: -o-linear-gradient(309deg, #760068 0%, #A00975 71%, #bd056a 100%); - background-image: linear-gradient(141deg, #760068 0%, #A00975 71%, #bd056a 100%); - } -} - -.hero.is-link { - background-color: #378BBA; - color: #fff; -} - - .hero.is-link a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current), - .hero.is-link strong { - color: inherit; - } - - .hero.is-link .title { - color: #fff; - } - - .hero.is-link .subtitle { - color: rgba(255, 255, 255, 0.9); - } - - .hero.is-link .subtitle a:not(.button), - .hero.is-link .subtitle strong { - color: #fff; - } - -@media screen and (max-width: 1023px) { - .hero.is-link .navbar-menu { - background-color: #378BBA; - } -} - -.hero.is-link .navbar-item, -.hero.is-link .navbar-link { - color: rgba(255, 255, 255, 0.7); -} - - .hero.is-link a.navbar-item:hover, .hero.is-link a.navbar-item.is-active, .hero.is-link .navbar-item.active, - .hero.is-link .navbar-link:hover, - .hero.is-link .navbar-link.is-active, - .hero.is-link .navbar-link.active { - background-color: #317ca6; - color: #fff; - } - -.hero.is-link .tabs a { - color: #fff; - opacity: 0.9; -} - - .hero.is-link .tabs a:hover { - opacity: 1; - } - -.hero.is-link .tabs li.is-active a, .hero.is-link .tabs li.active a { - opacity: 1; -} - -.hero.is-link .tabs.is-boxed a, .hero.is-link .tabs.is-toggle a { - color: #fff; -} - - .hero.is-link .tabs.is-boxed a:hover, .hero.is-link .tabs.is-toggle a:hover { - background-color: rgba(10, 10, 10, 0.1); - } - -.hero.is-link .tabs.is-boxed li.is-active a, .hero.is-link .tabs.is-boxed li.active a, .hero.is-link .tabs.is-boxed li.is-active a:hover, .hero.is-link .tabs.is-toggle li.is-active a, .hero.is-link .tabs.is-toggle li.active a, .hero.is-link .tabs.is-toggle li.is-active a:hover { - background-color: #fff; - border-color: #fff; - color: #378BBA; -} - -.hero.is-link.is-bold { - background-image: -o-linear-gradient(309deg, #22859c 0%, #378BBA 71%, #3d82ce 100%); - background-image: linear-gradient(141deg, #22859c 0%, #378BBA 71%, #3d82ce 100%); -} - -@media screen and (max-width: 768px) { - .hero.is-link.is-bold .navbar-menu { - background-image: -o-linear-gradient(309deg, #22859c 0%, #378BBA 71%, #3d82ce 100%); - background-image: linear-gradient(141deg, #22859c 0%, #378BBA 71%, #3d82ce 100%); - } -} - -.hero.is-info { - background-color: #3298dc; - color: #fff; -} - - .hero.is-info a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current), - .hero.is-info strong { - color: inherit; - } - - .hero.is-info .title { - color: #fff; - } - - .hero.is-info .subtitle { - color: rgba(255, 255, 255, 0.9); - } - - .hero.is-info .subtitle a:not(.button), - .hero.is-info .subtitle strong { - color: #fff; - } - -@media screen and (max-width: 1023px) { - .hero.is-info .navbar-menu { - background-color: #3298dc; - } -} - -.hero.is-info .navbar-item, -.hero.is-info .navbar-link { - color: rgba(255, 255, 255, 0.7); -} - - .hero.is-info a.navbar-item:hover, .hero.is-info a.navbar-item.is-active, .hero.is-info .navbar-item.active, - .hero.is-info .navbar-link:hover, - .hero.is-info .navbar-link.is-active, - .hero.is-info .navbar-link.active { - background-color: #238cd1; - color: #fff; - } - -.hero.is-info .tabs a { - color: #fff; - opacity: 0.9; -} - - .hero.is-info .tabs a:hover { - opacity: 1; - } - -.hero.is-info .tabs li.is-active a, .hero.is-info .tabs li.active a { - opacity: 1; -} - -.hero.is-info .tabs.is-boxed a, .hero.is-info .tabs.is-toggle a { - color: #fff; -} - - .hero.is-info .tabs.is-boxed a:hover, .hero.is-info .tabs.is-toggle a:hover { - background-color: rgba(10, 10, 10, 0.1); - } - -.hero.is-info .tabs.is-boxed li.is-active a, .hero.is-info .tabs.is-boxed li.active a, .hero.is-info .tabs.is-boxed li.is-active a:hover, .hero.is-info .tabs.is-toggle li.is-active a, .hero.is-info .tabs.is-toggle li.active a, .hero.is-info .tabs.is-toggle li.is-active a:hover { - background-color: #fff; - border-color: #fff; - color: #3298dc; -} - -.hero.is-info.is-bold { - background-image: -o-linear-gradient(309deg, #159dc6 0%, #3298dc 71%, #4389e5 100%); - background-image: linear-gradient(141deg, #159dc6 0%, #3298dc 71%, #4389e5 100%); -} - -@media screen and (max-width: 768px) { - .hero.is-info.is-bold .navbar-menu { - background-image: -o-linear-gradient(309deg, #159dc6 0%, #3298dc 71%, #4389e5 100%); - background-image: linear-gradient(141deg, #159dc6 0%, #3298dc 71%, #4389e5 100%); - } -} - -.hero.is-success { - background-color: #48c774; - color: #fff; -} - - .hero.is-success a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current), - .hero.is-success strong { - color: inherit; - } - - .hero.is-success .title { - color: #fff; - } - - .hero.is-success .subtitle { - color: rgba(255, 255, 255, 0.9); - } - - .hero.is-success .subtitle a:not(.button), - .hero.is-success .subtitle strong { - color: #fff; - } - -@media screen and (max-width: 1023px) { - .hero.is-success .navbar-menu { - background-color: #48c774; - } -} - -.hero.is-success .navbar-item, -.hero.is-success .navbar-link { - color: rgba(255, 255, 255, 0.7); -} - - .hero.is-success a.navbar-item:hover, .hero.is-success a.navbar-item.is-active, .hero.is-success .navbar-item.active, - .hero.is-success .navbar-link:hover, - .hero.is-success .navbar-link.is-active, - .hero.is-success .navbar-link.active { - background-color: #3abb67; - color: #fff; - } - -.hero.is-success .tabs a { - color: #fff; - opacity: 0.9; -} - - .hero.is-success .tabs a:hover { - opacity: 1; - } - -.hero.is-success .tabs li.is-active a, .hero.is-success .tabs li.active a { - opacity: 1; -} - -.hero.is-success .tabs.is-boxed a, .hero.is-success .tabs.is-toggle a { - color: #fff; -} - - .hero.is-success .tabs.is-boxed a:hover, .hero.is-success .tabs.is-toggle a:hover { - background-color: rgba(10, 10, 10, 0.1); - } - -.hero.is-success .tabs.is-boxed li.is-active a, .hero.is-success .tabs.is-boxed li.active a, .hero.is-success .tabs.is-boxed li.is-active a:hover, .hero.is-success .tabs.is-toggle li.is-active a, .hero.is-success .tabs.is-toggle li.active a, .hero.is-success .tabs.is-toggle li.is-active a:hover { - background-color: #fff; - border-color: #fff; - color: #48c774; -} - -.hero.is-success.is-bold { - background-image: -o-linear-gradient(309deg, #29b342 0%, #48c774 71%, #56d296 100%); - background-image: linear-gradient(141deg, #29b342 0%, #48c774 71%, #56d296 100%); -} - -@media screen and (max-width: 768px) { - .hero.is-success.is-bold .navbar-menu { - background-image: -o-linear-gradient(309deg, #29b342 0%, #48c774 71%, #56d296 100%); - background-image: linear-gradient(141deg, #29b342 0%, #48c774 71%, #56d296 100%); - } -} - -.hero.is-warning { - background-color: #ffdd57; - color: rgba(0, 0, 0, 0.7); -} - - .hero.is-warning a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current), - .hero.is-warning strong { - color: inherit; - } - - .hero.is-warning .title { - color: rgba(0, 0, 0, 0.7); - } - - .hero.is-warning .subtitle { - color: rgba(0, 0, 0, 0.9); - } - - .hero.is-warning .subtitle a:not(.button), - .hero.is-warning .subtitle strong { - color: rgba(0, 0, 0, 0.7); - } - -@media screen and (max-width: 1023px) { - .hero.is-warning .navbar-menu { - background-color: #ffdd57; - } -} - -.hero.is-warning .navbar-item, -.hero.is-warning .navbar-link { - color: rgba(0, 0, 0, 0.7); -} - - .hero.is-warning a.navbar-item:hover, .hero.is-warning a.navbar-item.is-active, .hero.is-warning .navbar-item.active, - .hero.is-warning .navbar-link:hover, - .hero.is-warning .navbar-link.is-active, - .hero.is-warning .navbar-link.active { - background-color: #ffd83d; - color: rgba(0, 0, 0, 0.7); - } - -.hero.is-warning .tabs a { - color: rgba(0, 0, 0, 0.7); - opacity: 0.9; -} - - .hero.is-warning .tabs a:hover { - opacity: 1; - } - -.hero.is-warning .tabs li.is-active a, .hero.is-warning .tabs li.active a { - opacity: 1; -} - -.hero.is-warning .tabs.is-boxed a, .hero.is-warning .tabs.is-toggle a { - color: rgba(0, 0, 0, 0.7); -} - - .hero.is-warning .tabs.is-boxed a:hover, .hero.is-warning .tabs.is-toggle a:hover { - background-color: rgba(10, 10, 10, 0.1); - } - -.hero.is-warning .tabs.is-boxed li.is-active a, .hero.is-warning .tabs.is-boxed li.active a, .hero.is-warning .tabs.is-boxed li.is-active a:hover, .hero.is-warning .tabs.is-toggle li.is-active a, .hero.is-warning .tabs.is-toggle li.active a, .hero.is-warning .tabs.is-toggle li.is-active a:hover { - background-color: rgba(0, 0, 0, 0.7); - border-color: rgba(0, 0, 0, 0.7); - color: #ffdd57; -} - -.hero.is-warning.is-bold { - background-image: -o-linear-gradient(309deg, #ffaf24 0%, #ffdd57 71%, #fffa70 100%); - background-image: linear-gradient(141deg, #ffaf24 0%, #ffdd57 71%, #fffa70 100%); -} - -@media screen and (max-width: 768px) { - .hero.is-warning.is-bold .navbar-menu { - background-image: -o-linear-gradient(309deg, #ffaf24 0%, #ffdd57 71%, #fffa70 100%); - background-image: linear-gradient(141deg, #ffaf24 0%, #ffdd57 71%, #fffa70 100%); - } -} - -.hero.is-danger { - background-color: #f14668; - color: #fff; -} - - .hero.is-danger a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current), - .hero.is-danger strong { - color: inherit; - } - - .hero.is-danger .title { - color: #fff; - } - - .hero.is-danger .subtitle { - color: rgba(255, 255, 255, 0.9); - } - - .hero.is-danger .subtitle a:not(.button), - .hero.is-danger .subtitle strong { - color: #fff; - } - -@media screen and (max-width: 1023px) { - .hero.is-danger .navbar-menu { - background-color: #f14668; - } -} - -.hero.is-danger .navbar-item, -.hero.is-danger .navbar-link { - color: rgba(255, 255, 255, 0.7); -} - - .hero.is-danger a.navbar-item:hover, .hero.is-danger a.navbar-item.is-active, .hero.is-danger .navbar-item.active, - .hero.is-danger .navbar-link:hover, - .hero.is-danger .navbar-link.is-active, - .hero.is-danger .navbar-link.active { - background-color: #ef2e55; - color: #fff; - } - -.hero.is-danger .tabs a { - color: #fff; - opacity: 0.9; -} - - .hero.is-danger .tabs a:hover { - opacity: 1; - } - -.hero.is-danger .tabs li.is-active a, .hero.is-danger .tabs li.active a { - opacity: 1; -} - -.hero.is-danger .tabs.is-boxed a, .hero.is-danger .tabs.is-toggle a { - color: #fff; -} - - .hero.is-danger .tabs.is-boxed a:hover, .hero.is-danger .tabs.is-toggle a:hover { - background-color: rgba(10, 10, 10, 0.1); - } - -.hero.is-danger .tabs.is-boxed li.is-active a, .hero.is-danger .tabs.is-boxed li.active a, .hero.is-danger .tabs.is-boxed li.is-active a:hover, .hero.is-danger .tabs.is-toggle li.is-active a, .hero.is-danger .tabs.is-toggle li.active a, .hero.is-danger .tabs.is-toggle li.is-active a:hover { - background-color: #fff; - border-color: #fff; - color: #f14668; -} - -.hero.is-danger.is-bold { - background-image: -o-linear-gradient(309deg, #fa0a62 0%, #f14668 71%, #f7595f 100%); - background-image: linear-gradient(141deg, #fa0a62 0%, #f14668 71%, #f7595f 100%); -} - -@media screen and (max-width: 768px) { - .hero.is-danger.is-bold .navbar-menu { - background-image: -o-linear-gradient(309deg, #fa0a62 0%, #f14668 71%, #f7595f 100%); - background-image: linear-gradient(141deg, #fa0a62 0%, #f14668 71%, #f7595f 100%); - } -} - -.hero.is-small .hero-body { - padding: 1.5rem; -} - -@media screen and (min-width: 769px), print { - .hero.is-medium .hero-body { - padding: 9rem 1.5rem; - } -} - -@media screen and (min-width: 769px), print { - .hero.is-large .hero-body { - padding: 18rem 1.5rem; - } -} - -.hero.is-halfheight .hero-body, .hero.is-fullheight .hero-body, .hero.is-fullheight-with-navbar .hero-body { - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - display: -webkit-box; - display: -ms-flexbox; - display: flex; -} - - .hero.is-halfheight .hero-body > .container, .hero.is-fullheight .hero-body > .container, .hero.is-fullheight-with-navbar .hero-body > .container { - -webkit-box-flex: 1; - -ms-flex-positive: 1; - flex-grow: 1; - -ms-flex-negative: 1; - flex-shrink: 1; - } - -.hero.is-halfheight { - min-height: 50vh; -} - -.hero.is-fullheight { - min-height: 100vh; -} - -.hero-video { - overflow: hidden; -} - - .hero-video video { - left: 50%; - min-height: 100%; - min-width: 100%; - position: absolute; - top: 50%; - -webkit-transform: translate3d(-50%, -50%, 0); - transform: translate3d(-50%, -50%, 0); - } - - .hero-video.is-transparent { - opacity: 0.3; - } - -@media screen and (max-width: 768px) { - .hero-video { - display: none; - } -} - -.hero-buttons { - margin-top: 1.5rem; -} - -@media screen and (max-width: 768px) { - .hero-buttons .button { - display: -webkit-box; - display: -ms-flexbox; - display: flex; - } - - .hero-buttons .button:not(:last-child) { - margin-bottom: 0.75rem; - } -} - -@media screen and (min-width: 769px), print { - .hero-buttons { - display: -webkit-box; - display: -ms-flexbox; - display: flex; - -webkit-box-pack: center; - -ms-flex-pack: center; - justify-content: center; - } - - .hero-buttons .button:not(:last-child) { - margin-right: 1.5rem; - } -} - -.hero-head, -.hero-foot { - -webkit-box-flex: 0; - -ms-flex-positive: 0; - flex-grow: 0; - -ms-flex-negative: 0; - flex-shrink: 0; -} - -.hero-body { - -webkit-box-flex: 1; - -ms-flex-positive: 1; - flex-grow: 1; - -ms-flex-negative: 0; - flex-shrink: 0; - padding: 3rem 1.5rem; -} - -.section { - padding: 3rem 1.5rem; -} - -@media screen and (min-width: 1024px) { - .section.is-medium { - padding: 9rem 1.5rem; - } - - .section.is-large { - padding: 18rem 1.5rem; - } -} - -.footer { - background-color: #fafafa; - padding: 3rem 1.5rem 6rem; -} - -#fsdocs-searchbox { - margin: 0 auto; -} - -@media screen and (min-width: 768px) { - #fsdocs-menu { - border-right: 1px solid #200117; - position: sticky; - display: inline-block; - vertical-align: top; - height: 100vh; - top: 0; - bottom: 0; - overflow-y: auto; - background-color: whitesmoke; - } -} - -@media screen and (max-width: 768px) { - #fsdocs-menu { - background-color: #ededed; - } - - #fsdocs-menu #fsdocs-menu { - border: none; - } -} - -.nav-header { - border-bottom: 1px dashed #A00975; - list-style: none; - color: #A00975; -} - -#fsdocs-content h1 a, #fsdocs-content h1 a:hover, #fsdocs-content h1 a:focus, -#fsdocs-content h2 a, #fsdocs-content h2 a:hover, #fsdocs-content h2 a:focus, -#fsdocs-content h3 a, #fsdocs-content h3 a:hover, #fsdocs-content h3 a:focus, -#fsdocs-content h4 a, #fsdocs-content h4 a:hover, #fsdocs-content h4 a:focus, -#fsdocs-content h5 a, #fsdocs-content h5 a:hover, #fsdocs-content h5 a:focus, -#fsdocs-content h6 a, #fsdocs-content h6 a:hover, #fsdocs-content h6 a:focus { - color: #A00975; -} - -#fsdocs-content h1 a { - border-bottom: 8px solid #200117; -} - -#fsdocs-content h2 a { - border-bottom: 5px solid #200117; -} - -#fsdocs-content h3 a, -#fsdocs-content h4 a { - border-bottom: 2px solid #200117; -} - -#fsdocs-content h5 a, -#fsdocs-content h6 a { - border-bottom: 1px solid #200117; -} - -#fsdocs-content li { - margin: initial; -} - -strong { - border-bottom: 2px solid #A00975; -} - -em { - color: #A00975; -} - -#fsdocs-content ul { - -webkit-padding-start: 40px; - padding-inline-start: 40px; - list-style-type: disc; -} - -#fsdocs-content ol { - -webkit-padding-start: 40px; - padding-inline-start: 40px; - list-style-type: decimal; -} - -#fsdocs-content blockquote { - display: block; - -webkit-margin-before: 1em; - margin-block-start: 1em; - -webkit-margin-after: 1em; - margin-block-end: 1em; - -webkit-margin-start: 40px; - margin-inline-start: 40px; - -webkit-margin-end: 40px; - margin-inline-end: 40px; - background-color: whitesmoke; - border-left: 4px solid #A00975; -} - -#fsdocs-content table.pre, #fsdocs-content pre.fssnip, #fsdocs-content pre { - background-color: #200117 !important; - color: #fafafa !important; - overflow-x: auto; - display: block; - font-weight: initial; -} - - #fsdocs-content pre.fssnip code { - font: 0.85rem 'Roboto Mono', monospace; - font-weight: initial; - } - -#fsdocs-menu::-webkit-scrollbar { - width: 1px; -} - -#fsdocs-menu::-webkit-scrollbar-thumb { - border-radius: 5px; - background-color: #200117; -} - -#fsdocs-content table.pre::-webkit-scrollbar-track, -#fsdocs-content pre.fssnip ::-webkit-scrollbar-track, -#fsdocs-content pre ::-webkit-scrollbar-track { - box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3); - -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3); - border-radius: 5px; - background-color: #200117; -} - -#fsdocs-content table.pre::-webkit-scrollbar, -#fsdocs-content pre.fssnip ::-webkit-scrollbar, -#fsdocs-content pre ::-webkit-scrollbar { - height: 8px; - background-color: #200117; - border-radius: 5px; -} - -#fsdocs-content table.pre::-webkit-scrollbar-thumb, -#fsdocs-content pre.fssnip ::-webkit-scrollbar-thumb, -#fsdocs-content pre ::-webkit-scrollbar-thumb { - border-radius: 5px; - box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3); - -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3); - background-color: #A00975; -} - -/*-------------------------------------------------------------------------- - Formatting for F# code snippets -/*--------------------------------------------------------------------------*/ -.fsdocs-param-name, -.fsdocs-return-name, -.fsdocs-param { - font-weight: 900; - font-size: 0.85rem; - font-family: 'Roboto Mono', monospace; -} - -/* strings --- and stlyes for other string related formats */ -#fsdocs-content span.s { - color: #d59a1b; -} - -/* printf formatters */ -#fsdocs-content span.pf { - color: #A00975; -} - -/* escaped chars */ -#fsdocs-content span.e { - color: #d59a1b; -} - -/* identifiers --- and styles for more specific identifier types */ -#fsdocs-content span.id { - color: #fafafa; -} - -/* module */ -#fsdocs-content span.m { - color: #44d57f; -} - -/* reference type */ -#fsdocs-content span.rt { - color: #44d57f; -} - -/* value type */ -#fsdocs-content span.vt { - color: #44d57f; -} - -/* interface */ -#fsdocs-content span.if { - color: #44d57f; -} - -/* type argument */ -#fsdocs-content span.ta { - color: #44d57f; -} - -/* disposable */ -#fsdocs-content span.d { - color: #c6ffdd; -} - -/* property */ -#fsdocs-content span.prop { - color: #fafafa; -} - -/* punctuation */ -#fsdocs-content span.p { - color: #fafafa; -} - -#fsdocs-content span.pn { - color: #fafafa; -} - -#fsdocs-content span.f { - color: #fafafa; -} - -#fsdocs-content span.fn { - color: #d2c572; -} - -/* active pattern */ -#fsdocs-content span.pat { - color: #438AFE; -} - -/* union case */ -#fsdocs-content span.u { - color: #44d57f; -} - -/* enumeration */ -#fsdocs-content span.e { - color: #44d57f; -} - -/* keywords */ -#fsdocs-content span.k { - color: #F99BDE; -} - -/* comment */ -#fsdocs-content span.c { - color: #6A9955; -} - -#fsdocs-content span.o { - color: #D12F67; -} - -/* numbers */ -#fsdocs-content span.n { - color: #c6ffdd; -} - -/* line number */ -#fsdocs-content span.l { - color: #fafafa; -} - -/* mutable var or ref cell */ -#fsdocs-content span.v { - color: #d2c572; - font-weight: bold; -} - -/* inactive code */ -#fsdocs-content span.inactive { - color: #808080; -} - -/* preprocessor */ -#fsdocs-content span.prep { - color: #ff9b9b; -} - -/* fsi output */ -#fsdocs-content span.fsi { - color: #fafafa; -} - -/* tool tip */ -div.fsdocs-tip { - background: #475b5f; - border-radius: 4px; - font: 11pt 'Droid Sans', arial, sans-serif; - padding: 6px 8px 6px 8px; - display: none; - color: #d1d1d1; - pointer-events: none; -} - - div.fsdocs-tip code { - color: #d1d1d1; - font: 11pt 'Droid Sans', arial, sans-serif; - } - - div.fsdocs-tip em { - color: #6A9955; - } - -/*# sourceMappingURL=C:\Users\schne\source\repos\fslaborg\docs-template\Content\docs\content\fsdocs-custom.css.map */ diff --git a/docs/content/fsdocs-theme.css b/docs/content/fsdocs-theme.css new file mode 100644 index 000000000..ff15d1a6e --- /dev/null +++ b/docs/content/fsdocs-theme.css @@ -0,0 +1,40 @@ +:root { + /* fslab colors */ + --fslab-magenta: #A00975; + --fslab-magenta-light: #F99BDE; + --fslab-magenta-dark: #3D1244; + --fslab-magenta-darkest: #200117; + --fslab-blue: #438AFE; + --fslab-yellow: #FABC2A; + /* theme customization */ + --heading-color: var(--fslab-magenta-dark); + --link-color: var(--fslab-blue); + --link-hover: var(--fslab-magenta); + /* dark theme */ +} + +[data-theme=dark] { + --heading-color: var(--fslab-magenta-light); +} + +table { + border-collapse: collapse; + border-spacing: 0; + min-width: 50%; +} + +thead { + background-color: var(--code-background); +} + +tr:nth-child(even) { + background-color: var(--code-background); +} + +td { + text-align: center; +} + +svg { + display: unset +} \ No newline at end of file diff --git a/docs/index.fsx b/docs/index.fsx index f53b10a9e..937cd4856 100644 --- a/docs/index.fsx +++ b/docs/index.fsx @@ -1,6 +1,10 @@ (*** hide ***) (*** condition: prepare ***) +#r "nuget: FSharpAux.Core, 2.0.0" +#r "nuget: FSharpAux, 2.0.0" +#r "nuget: FSharpAux.IO, 2.0.0" +#r "nuget: OptimizedPriorityQueue, 5.1.0" #I "../src/FSharp.Stats/bin/Release/netstandard2.0/" #r "FSharp.Stats.dll" #r "nuget: Plotly.NET, 4.0.0" diff --git a/docs/reference/_template.html b/docs/reference/_template.html deleted file mode 100644 index 287a6ac74..000000000 --- a/docs/reference/_template.html +++ /dev/null @@ -1,82 +0,0 @@ - - - - - - {{fsdocs-page-title}} - - - - - - - - - - - - - - - - {{fsdocs-watch-script}} - - - -
-
- -
-
-
-
- {{fsdocs-content}} -
-
-
- {{fsdocs-tooltips}} -
- - - - - - - - - - - \ No newline at end of file diff --git a/global.json b/global.json index f15a95928..501e79a87 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "sdk": { - "version": "9.0.100", - "rollForward": "latestMinor" + "version": "8.0.100", + "rollForward": "latestFeature" } } \ No newline at end of file From 72ca9589170d2e0907e9cbe3348146fd7d73b357 Mon Sep 17 00:00:00 2001 From: Kevin Schneider Date: Thu, 18 Jul 2024 17:18:59 +0200 Subject: [PATCH 094/121] setup .net 8 in ci --- .github/workflows/build-and-test.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml index ce45285cf..6a8a6dee0 100644 --- a/.github/workflows/build-and-test.yml +++ b/.github/workflows/build-and-test.yml @@ -13,10 +13,10 @@ jobs: steps: - uses: actions/checkout@v2 - - name: Setup .NET - uses: actions/setup-dotnet@v1 + - name: Setup .NET 8 + uses: actions/setup-dotnet@v4 with: - dotnet-version: '9.x.x' + dotnet-version: '8.x.x' - name: Restore local tools run: dotnet tool restore - name: make script executable @@ -30,11 +30,11 @@ jobs: runs-on: windows-latest steps: - - uses: actions/checkout@v2 - - name: Setup .NET - uses: actions/setup-dotnet@v1 + - uses: actions/checkout@v4 + - name: Setup .NET 8 + uses: actions/setup-dotnet@v4 with: - dotnet-version: '9.x.x' + dotnet-version: '8.x.x' - name: Restore local tools run: dotnet tool restore - name: Build and test From b16911ff5c4cf2911cfb574f6b1be1107c5bfd6c Mon Sep 17 00:00:00 2001 From: Kevin Schneider Date: Sat, 9 Aug 2025 14:07:43 +0200 Subject: [PATCH 095/121] fix docs references --- build/BasicTasks.fs | 12 +++++++++++- build/PackageTasks.fs | 2 -- build/build.fsproj | 13 ------------- docs/BasicStats.fsx | 4 ++-- docs/Clustering.fsx | 3 ++- docs/ComparisonMetrics.fsx | 4 ++-- docs/Correlation.fsx | 3 ++- docs/Covariance.fsx | 4 ++-- docs/CrossValidation.fsx | 4 ++-- docs/Differentiation.fsx | 4 ++-- docs/Distributions.fsx | 6 +++--- docs/Fitting.fsx | 4 ++-- docs/GoodnessOfFit.fsx | 4 ++-- docs/GrowthCurve.fsx | 5 +++-- docs/Imputation.fsx | 4 ++-- docs/Integration.fsx | 4 ++-- docs/Interpolation.fsx | 4 ++-- docs/Intervals.fsx | 4 ++-- docs/Normalization.fsx | 4 ++-- docs/NuGet.config | 14 -------------- docs/Optimization.fsx | 4 ++-- docs/Quantiles.fsx | 4 ++-- docs/Rank.fsx | 4 ++-- docs/Signal.fsx | 4 ++-- docs/Testing.fsx | 4 ++-- docs/index.fsx | 7 ++----- 26 files changed, 57 insertions(+), 76 deletions(-) delete mode 100644 docs/NuGet.config diff --git a/build/BasicTasks.fs b/build/BasicTasks.fs index 65cb69bf2..c1d6c05f0 100644 --- a/build/BasicTasks.fs +++ b/build/BasicTasks.fs @@ -28,7 +28,17 @@ let clean = BuildTask.create "Clean" [] { let build = BuildTask.create "Build" [clean] { solutionFile |> DotNet.build (fun p -> - { p with MSBuildParams = { p.MSBuildParams with DisableInternalBinLog = true }} + let msBuildParams = + {p.MSBuildParams with + Properties = ([ + "warnon", "3390" + ]) + DisableInternalBinLog = true + } + { + p with + MSBuildParams = msBuildParams + } |> DotNet.Options.withCustomParams (Some "-tl") ) } \ No newline at end of file diff --git a/build/PackageTasks.fs b/build/PackageTasks.fs index 7edc74f81..db16ad2c6 100644 --- a/build/PackageTasks.fs +++ b/build/PackageTasks.fs @@ -19,7 +19,6 @@ let pack = BuildTask.create "Pack" [clean; build; runTests] { |> Seq.iter (Fake.DotNet.DotNet.pack (fun p -> let msBuildParams = {p.MSBuildParams with - DisableInternalBinLog = true Properties = ([ "Version",stableVersionTag "PackageReleaseNotes", (release.Notes |> String.concat "\r\n") @@ -44,7 +43,6 @@ let packPrerelease = BuildTask.create "PackPrerelease" [setPrereleaseTag; clean; |> Seq.iter (Fake.DotNet.DotNet.pack (fun p -> let msBuildParams = {p.MSBuildParams with - DisableInternalBinLog = true Properties = ([ "Version", prereleaseTag "PackageReleaseNotes", (release.Notes |> String.toLines ) diff --git a/build/build.fsproj b/build/build.fsproj index 21200ae87..b3f0ebf49 100644 --- a/build/build.fsproj +++ b/build/build.fsproj @@ -31,17 +31,4 @@
- - - - - - - - - - - - - diff --git a/docs/BasicStats.fsx b/docs/BasicStats.fsx index 4d3f5a6a2..fe1a11be8 100644 --- a/docs/BasicStats.fsx +++ b/docs/BasicStats.fsx @@ -14,9 +14,9 @@ categoryindex: 0 #r "nuget: FSharpAux, 2.0.0" #r "nuget: FSharpAux.IO, 2.0.0" #r "nuget: OptimizedPriorityQueue, 5.1.0" -#I "../src/FSharp.Stats/bin/Release/netstandard2.0/" +#r "nuget: FsMath, 0.0.1" +#I "../src/FSharp.Stats/bin/Release/.net8.0/" #r "FSharp.Stats.dll" - (*** condition: ipynb ***) #if IPYNB #r "nuget: FSharp.Stats" diff --git a/docs/Clustering.fsx b/docs/Clustering.fsx index 7146b91f9..d846b6c65 100644 --- a/docs/Clustering.fsx +++ b/docs/Clustering.fsx @@ -14,7 +14,8 @@ categoryindex: 0 #r "nuget: FSharpAux, 2.0.0" #r "nuget: FSharpAux.IO, 2.0.0" #r "nuget: OptimizedPriorityQueue, 5.1.0" -#I "../src/FSharp.Stats/bin/Release/netstandard2.0/" +#r "nuget: FsMath, 0.0.1" +#I "../src/FSharp.Stats/bin/Release/.net8.0/" #r "FSharp.Stats.dll" #r "nuget: Plotly.NET, 4.0.0" #r "nuget: Cyjs.NET" diff --git a/docs/ComparisonMetrics.fsx b/docs/ComparisonMetrics.fsx index ebdb93214..8eac4a019 100644 --- a/docs/ComparisonMetrics.fsx +++ b/docs/ComparisonMetrics.fsx @@ -14,10 +14,10 @@ categoryindex: 0 #r "nuget: FSharpAux, 2.0.0" #r "nuget: FSharpAux.IO, 2.0.0" #r "nuget: OptimizedPriorityQueue, 5.1.0" -#I "../src/FSharp.Stats/bin/Release/netstandard2.0/" +#r "nuget: FsMath, 0.0.1" +#I "../src/FSharp.Stats/bin/Release/.net8.0/" #r "FSharp.Stats.dll" #r "nuget: Plotly.NET, 4.0.0" -#r "nuget: FsMath, 0.0.1" open FsMath Plotly.NET.Defaults.DefaultDisplayOptions <- diff --git a/docs/Correlation.fsx b/docs/Correlation.fsx index a59f6fe24..3280468aa 100644 --- a/docs/Correlation.fsx +++ b/docs/Correlation.fsx @@ -14,7 +14,8 @@ categoryindex: 0 #r "nuget: FSharpAux, 2.0.0" #r "nuget: FSharpAux.IO, 2.0.0" #r "nuget: OptimizedPriorityQueue, 5.1.0" -#I "../src/FSharp.Stats/bin/Release/netstandard2.0/" +#r "nuget: FsMath, 0.0.1" +#I "../src/FSharp.Stats/bin/Release/.net8.0/" #r "FSharp.Stats.dll" #r "nuget: Plotly.NET, 4.0.0" #r "nuget: FsMath, 0.0.1" diff --git a/docs/Covariance.fsx b/docs/Covariance.fsx index 14b6f8b89..f80728d3d 100644 --- a/docs/Covariance.fsx +++ b/docs/Covariance.fsx @@ -14,10 +14,10 @@ categoryindex: 0 #r "nuget: FSharpAux, 2.0.0" #r "nuget: FSharpAux.IO, 2.0.0" #r "nuget: OptimizedPriorityQueue, 5.1.0" -#I "../src/FSharp.Stats/bin/Release/netstandard2.0/" +#r "nuget: FsMath, 0.0.1" +#I "../src/FSharp.Stats/bin/Release/.net8.0/" #r "FSharp.Stats.dll" #r "nuget: Plotly.NET, 4.0.0" -#r "nuget: FsMath, 0.0.1" open FsMath Plotly.NET.Defaults.DefaultDisplayOptions <- diff --git a/docs/CrossValidation.fsx b/docs/CrossValidation.fsx index ea59baa63..6b6001c7a 100644 --- a/docs/CrossValidation.fsx +++ b/docs/CrossValidation.fsx @@ -15,10 +15,10 @@ categoryindex: 0 #r "nuget: FSharpAux, 2.0.0" #r "nuget: FSharpAux.IO, 2.0.0" #r "nuget: OptimizedPriorityQueue, 5.1.0" -#I "../src/FSharp.Stats/bin/Release/netstandard2.0/" +#r "nuget: FsMath, 0.0.1" +#I "../src/FSharp.Stats/bin/Release/.net8.0/" #r "FSharp.Stats.dll" #r "nuget: Plotly.NET, 4.0.0" -#r "nuget: FsMath, 0.0.1" open FsMath Plotly.NET.Defaults.DefaultDisplayOptions <- diff --git a/docs/Differentiation.fsx b/docs/Differentiation.fsx index 3d99734bc..6484e9a45 100644 --- a/docs/Differentiation.fsx +++ b/docs/Differentiation.fsx @@ -14,10 +14,10 @@ categoryindex: 0 #r "nuget: FSharpAux, 2.0.0" #r "nuget: FSharpAux.IO, 2.0.0" #r "nuget: OptimizedPriorityQueue, 5.1.0" -#I "../src/FSharp.Stats/bin/Release/netstandard2.0/" +#r "nuget: FsMath, 0.0.1" +#I "../src/FSharp.Stats/bin/Release/.net8.0/" #r "FSharp.Stats.dll" #r "nuget: Plotly.NET, 4.0.0" -#r "nuget: FsMath, 0.0.1" open FsMath Plotly.NET.Defaults.DefaultDisplayOptions <- diff --git a/docs/Distributions.fsx b/docs/Distributions.fsx index 64778c1f8..b3282ced5 100644 --- a/docs/Distributions.fsx +++ b/docs/Distributions.fsx @@ -15,10 +15,10 @@ categoryindex: 0 #r "nuget: FSharpAux, 2.0.0" #r "nuget: FSharpAux.IO, 2.0.0" #r "nuget: OptimizedPriorityQueue, 5.1.0" -#I "../src/FSharp.Stats/bin/Release/netstandard2.0/" -#r "FSharp.Stats.dll" -#r "nuget: Plotly.NET, 4.0.0" #r "nuget: FsMath, 0.0.1" +#r "nuget: Plotly.NET, 4.0.0" +#I "../src/FSharp.Stats/bin/Release/.net8.0/" +#r "FSharp.Stats.dll" open FsMath Plotly.NET.Defaults.DefaultDisplayOptions <- diff --git a/docs/Fitting.fsx b/docs/Fitting.fsx index ee5ca77a5..9b2495417 100644 --- a/docs/Fitting.fsx +++ b/docs/Fitting.fsx @@ -14,10 +14,10 @@ categoryindex: 0 #r "nuget: FSharpAux, 2.0.0" #r "nuget: FSharpAux.IO, 2.0.0" #r "nuget: OptimizedPriorityQueue, 5.1.0" -#I "../src/FSharp.Stats/bin/Release/netstandard2.0/" +#r "nuget: FsMath, 0.0.1" +#I "../src/FSharp.Stats/bin/Release/.net8.0/" #r "FSharp.Stats.dll" #r "nuget: Plotly.NET, 4.0.0" -#r "nuget: FsMath, 0.0.1" open FsMath Plotly.NET.Defaults.DefaultDisplayOptions <- diff --git a/docs/GoodnessOfFit.fsx b/docs/GoodnessOfFit.fsx index 1ffde9059..bcfb23238 100644 --- a/docs/GoodnessOfFit.fsx +++ b/docs/GoodnessOfFit.fsx @@ -14,10 +14,10 @@ categoryindex: 0 #r "nuget: FSharpAux, 2.0.0" #r "nuget: FSharpAux.IO, 2.0.0" #r "nuget: OptimizedPriorityQueue, 5.1.0" -#I "../src/FSharp.Stats/bin/Release/netstandard2.0/" +#r "nuget: FsMath, 0.0.1" +#I "../src/FSharp.Stats/bin/Release/.net8.0/" #r "FSharp.Stats.dll" #r "nuget: Plotly.NET, 4.0.0" -#r "nuget: FsMath, 0.0.1" open FsMath Plotly.NET.Defaults.DefaultDisplayOptions <- diff --git a/docs/GrowthCurve.fsx b/docs/GrowthCurve.fsx index 31df001ac..a8a6d3cc5 100644 --- a/docs/GrowthCurve.fsx +++ b/docs/GrowthCurve.fsx @@ -10,13 +10,14 @@ categoryindex: 0 (*** hide ***) (*** condition: prepare ***) -#r "../src/FSharp.Stats/bin/Release/netstandard2.0/FSharp.Stats.dll" #r "nuget: FSharpAux.Core, 2.0.0" #r "nuget: FSharpAux, 2.0.0" #r "nuget: FSharpAux.IO, 2.0.0" #r "nuget: OptimizedPriorityQueue, 5.1.0" -#r "nuget: Plotly.NET, 4.0.0" #r "nuget: FsMath, 0.0.1" +#I "../src/FSharp.Stats/bin/Release/.net8.0/" +#r "FSharp.Stats.dll" +#r "nuget: Plotly.NET, 4.0.0" open FsMath Plotly.NET.Defaults.DefaultDisplayOptions <- diff --git a/docs/Imputation.fsx b/docs/Imputation.fsx index e8a123f25..528f065e8 100644 --- a/docs/Imputation.fsx +++ b/docs/Imputation.fsx @@ -14,10 +14,10 @@ categoryindex: 0 #r "nuget: FSharpAux, 2.0.0" #r "nuget: FSharpAux.IO, 2.0.0" #r "nuget: OptimizedPriorityQueue, 5.1.0" -#I "../src/FSharp.Stats/bin/Release/netstandard2.0/" +#r "nuget: FsMath, 0.0.1" +#I "../src/FSharp.Stats/bin/Release/.net8.0/" #r "FSharp.Stats.dll" #r "nuget: Plotly.NET, 4.0.0" -#r "nuget: FsMath, 0.0.1" open FsMath Plotly.NET.Defaults.DefaultDisplayOptions <- diff --git a/docs/Integration.fsx b/docs/Integration.fsx index 32e31949a..78523e311 100644 --- a/docs/Integration.fsx +++ b/docs/Integration.fsx @@ -14,10 +14,10 @@ categoryindex: 0 #r "nuget: FSharpAux, 2.0.0" #r "nuget: FSharpAux.IO, 2.0.0" #r "nuget: OptimizedPriorityQueue, 5.1.0" -#I "../src/FSharp.Stats/bin/Release/netstandard2.0/" +#r "nuget: FsMath, 0.0.1" +#I "../src/FSharp.Stats/bin/Release/.net8.0/" #r "FSharp.Stats.dll" #r "nuget: Plotly.NET, 4.0.0" -#r "nuget: FsMath, 0.0.1" open FsMath Plotly.NET.Defaults.DefaultDisplayOptions <- diff --git a/docs/Interpolation.fsx b/docs/Interpolation.fsx index c00823f32..0431b2e49 100644 --- a/docs/Interpolation.fsx +++ b/docs/Interpolation.fsx @@ -14,10 +14,10 @@ categoryindex: 0 #r "nuget: FSharpAux, 2.0.0" #r "nuget: FSharpAux.IO, 2.0.0" #r "nuget: OptimizedPriorityQueue, 5.1.0" -#I "../src/FSharp.Stats/bin/Release/netstandard2.0/" +#r "nuget: FsMath, 0.0.1" +#I "../src/FSharp.Stats/bin/Release/.net8.0/" #r "FSharp.Stats.dll" #r "nuget: Plotly.NET, 4.0.0" -#r "nuget: FsMath, 0.0.1" open FsMath Plotly.NET.Defaults.DefaultDisplayOptions <- diff --git a/docs/Intervals.fsx b/docs/Intervals.fsx index a374a000e..51c2b1ca5 100644 --- a/docs/Intervals.fsx +++ b/docs/Intervals.fsx @@ -14,10 +14,10 @@ categoryindex: 0 #r "nuget: FSharpAux, 2.0.0" #r "nuget: FSharpAux.IO, 2.0.0" #r "nuget: OptimizedPriorityQueue, 5.1.0" -#I "../src/FSharp.Stats/bin/Release/netstandard2.0/" +#r "nuget: FsMath, 0.0.1" +#I "../src/FSharp.Stats/bin/Release/.net8.0/" #r "FSharp.Stats.dll" #r "nuget: Plotly.NET, 4.0.0" -#r "nuget: FsMath, 0.0.1" open FsMath Plotly.NET.Defaults.DefaultDisplayOptions <- diff --git a/docs/Normalization.fsx b/docs/Normalization.fsx index f63b7d095..fd38656ae 100644 --- a/docs/Normalization.fsx +++ b/docs/Normalization.fsx @@ -14,10 +14,10 @@ categoryindex: 0 #r "nuget: FSharpAux, 2.0.0" #r "nuget: FSharpAux.IO, 2.0.0" #r "nuget: OptimizedPriorityQueue, 5.1.0" -#I "../src/FSharp.Stats/bin/Release/netstandard2.0/" +#r "nuget: FsMath, 0.0.1" +#I "../src/FSharp.Stats/bin/Release/.net8.0/" #r "FSharp.Stats.dll" #r "nuget: Plotly.NET, 4.0.0" -#r "nuget: FsMath, 0.0.1" open FsMath Plotly.NET.Defaults.DefaultDisplayOptions <- diff --git a/docs/NuGet.config b/docs/NuGet.config deleted file mode 100644 index cf1ace51a..000000000 --- a/docs/NuGet.config +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - \ No newline at end of file diff --git a/docs/Optimization.fsx b/docs/Optimization.fsx index 1ea8ac936..82539e69a 100644 --- a/docs/Optimization.fsx +++ b/docs/Optimization.fsx @@ -14,10 +14,10 @@ categoryindex: 0 #r "nuget: FSharpAux, 2.0.0" #r "nuget: FSharpAux.IO, 2.0.0" #r "nuget: OptimizedPriorityQueue, 5.1.0" -#I "../src/FSharp.Stats/bin/Release/netstandard2.0/" +#r "nuget: FsMath, 0.0.1" +#I "../src/FSharp.Stats/bin/Release/.net8.0/" #r "FSharp.Stats.dll" #r "nuget: Plotly.NET, 4.0.0" -#r "nuget: FsMath, 0.0.1" open FsMath Plotly.NET.Defaults.DefaultDisplayOptions <- diff --git a/docs/Quantiles.fsx b/docs/Quantiles.fsx index 450f5f468..a175be6d1 100644 --- a/docs/Quantiles.fsx +++ b/docs/Quantiles.fsx @@ -14,10 +14,10 @@ categoryindex: 0 #r "nuget: FSharpAux, 2.0.0" #r "nuget: FSharpAux.IO, 2.0.0" #r "nuget: OptimizedPriorityQueue, 5.1.0" -#I "../src/FSharp.Stats/bin/Release/netstandard2.0/" +#r "nuget: FsMath, 0.0.1" +#I "../src/FSharp.Stats/bin/Release/.net8.0/" #r "FSharp.Stats.dll" #r "nuget: Plotly.NET, 4.0.0" -#r "nuget: FsMath, 0.0.1" open FsMath Plotly.NET.Defaults.DefaultDisplayOptions <- diff --git a/docs/Rank.fsx b/docs/Rank.fsx index 1604451de..63ee06197 100644 --- a/docs/Rank.fsx +++ b/docs/Rank.fsx @@ -14,10 +14,10 @@ categoryindex: 0 #r "nuget: FSharpAux, 2.0.0" #r "nuget: FSharpAux.IO, 2.0.0" #r "nuget: OptimizedPriorityQueue, 5.1.0" -#I "../src/FSharp.Stats/bin/Release/netstandard2.0/" +#r "nuget: FsMath, 0.0.1" +#I "../src/FSharp.Stats/bin/Release/.net8.0/" #r "FSharp.Stats.dll" #r "nuget: Plotly.NET, 4.0.0" -#r "nuget: FsMath, 0.0.1" open FsMath Plotly.NET.Defaults.DefaultDisplayOptions <- diff --git a/docs/Signal.fsx b/docs/Signal.fsx index 031b8c1aa..ce3e7f2d5 100644 --- a/docs/Signal.fsx +++ b/docs/Signal.fsx @@ -14,10 +14,10 @@ categoryindex: 0 #r "nuget: FSharpAux, 2.0.0" #r "nuget: FSharpAux.IO, 2.0.0" #r "nuget: OptimizedPriorityQueue, 5.1.0" -#I "../src/FSharp.Stats/bin/Release/netstandard2.0/" +#r "nuget: FsMath, 0.0.1" +#I "../src/FSharp.Stats/bin/Release/.net8.0/" #r "FSharp.Stats.dll" #r "nuget: Plotly.NET, 4.0.0" -#r "nuget: FsMath, 0.0.1" open FsMath Plotly.NET.Defaults.DefaultDisplayOptions <- diff --git a/docs/Testing.fsx b/docs/Testing.fsx index f68b24cbe..2e33df7d0 100644 --- a/docs/Testing.fsx +++ b/docs/Testing.fsx @@ -14,11 +14,11 @@ categoryindex: 0 #r "nuget: FSharpAux, 2.0.0" #r "nuget: FSharpAux.IO, 2.0.0" #r "nuget: OptimizedPriorityQueue, 5.1.0" -#I "../src/FSharp.Stats/bin/Release/netstandard2.0/" +#r "nuget: FsMath, 0.0.1" +#I "../src/FSharp.Stats/bin/Release/.net8.0/" #r "FSharp.Stats.dll" #r "nuget: Plotly.NET, 4.0.0" #r "nuget: Deedle, 3.0.0" -#r "nuget: FsMath, 0.0.1" open FsMath Plotly.NET.Defaults.DefaultDisplayOptions <- diff --git a/docs/index.fsx b/docs/index.fsx index 937cd4856..5b6146af2 100644 --- a/docs/index.fsx +++ b/docs/index.fsx @@ -5,10 +5,10 @@ #r "nuget: FSharpAux, 2.0.0" #r "nuget: FSharpAux.IO, 2.0.0" #r "nuget: OptimizedPriorityQueue, 5.1.0" -#I "../src/FSharp.Stats/bin/Release/netstandard2.0/" +#r "nuget: FsMath, 0.0.1" +#I "../src/FSharp.Stats/bin/Release/.net8.0/" #r "FSharp.Stats.dll" #r "nuget: Plotly.NET, 4.0.0" -#r "nuget: FsMath, 0.0.1" open FsMath Plotly.NET.Defaults.DefaultDisplayOptions <- @@ -111,9 +111,6 @@ let vecB = vector [19.;11.;35.] // create a matrix let matA = matrix [[3.;4.;0.];[1.;2.;2.];[5.;0.;5.]] -// solve the linear system of equations -let vecX = FSharp.Stats.Algebra.LinearAlgebra.SolveLinearSystem matA vecB - (*** include-value:vecX ***) (** From 2a4cc636a0eb9b50df4dd1ac642c3822125bbba7 Mon Sep 17 00:00:00 2001 From: Kevin Schneider Date: Sat, 9 Aug 2025 14:07:53 +0200 Subject: [PATCH 096/121] fix some xml docs --- FSharp.Stats.sln | 4 ---- src/FSharp.Stats/Array.fs | 4 ++-- src/FSharp.Stats/Ops.fs | 6 +++--- src/FSharp.Stats/SummaryStats.fs | 9 +++++---- 4 files changed, 10 insertions(+), 13 deletions(-) diff --git a/FSharp.Stats.sln b/FSharp.Stats.sln index f61a9bb29..d1b9bdc5c 100644 --- a/FSharp.Stats.sln +++ b/FSharp.Stats.sln @@ -55,11 +55,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "docs", "docs", "{23F9FB2E-6 docs\Integration.fsx = docs\Integration.fsx docs\Interpolation.fsx = docs\Interpolation.fsx docs\Intervals.fsx = docs\Intervals.fsx - docs\LinearAlgebra.fsx = docs\LinearAlgebra.fsx - docs\Matrix_Vector.fsx = docs\Matrix_Vector.fsx - docs\ML.fsx = docs\ML.fsx docs\Normalization.fsx = docs\Normalization.fsx - docs\NuGet.config = docs\NuGet.config docs\Optimization.fsx = docs\Optimization.fsx docs\Quantiles.fsx = docs\Quantiles.fsx docs\Rank.fsx = docs\Rank.fsx diff --git a/src/FSharp.Stats/Array.fs b/src/FSharp.Stats/Array.fs index ebaed80db..e7c7e1f1c 100644 --- a/src/FSharp.Stats/Array.fs +++ b/src/FSharp.Stats/Array.fs @@ -645,7 +645,7 @@ module ArrayExtension = ///
/// start value (is included) /// end value (by default is included ) - /// sets the number of elements in the array. If not set, stepsize = 1. + /// sets the number of elements in the array. If not set, stepsize = 1. /// If false, the array does not contain the stop value static member linspace(start:float,stop:float,num:int,?IncludeEndpoint:bool) : float [] = @@ -658,7 +658,7 @@ module ArrayExtension = ///
/// start value (is included) /// end value (by default is included) - /// sets the number of elements in the array. Defaults to 50. + /// sets the number of elements in the array. Defaults to 50. /// If false, the array does not contain the stop value. Defaults to true. static member geomspace(start:float,stop:float,num:int,?IncludeEndpoint:bool) : float array = let includeEndpoint = defaultArg IncludeEndpoint true diff --git a/src/FSharp.Stats/Ops.fs b/src/FSharp.Stats/Ops.fs index c7ba5b903..4a0516712 100644 --- a/src/FSharp.Stats/Ops.fs +++ b/src/FSharp.Stats/Ops.fs @@ -59,7 +59,7 @@ module Ops = /// Returs true if x is infinity (generics) /// - /// + /// /// /// /// @@ -71,7 +71,7 @@ module Ops = /// Returs true if x is positive infinity (generics) /// - /// + /// /// /// /// @@ -83,7 +83,7 @@ module Ops = /// Returs true if x is positive infinity (generics) /// - /// + /// /// /// /// diff --git a/src/FSharp.Stats/SummaryStats.fs b/src/FSharp.Stats/SummaryStats.fs index 315eb5389..e82183c08 100644 --- a/src/FSharp.Stats/SummaryStats.fs +++ b/src/FSharp.Stats/SummaryStats.fs @@ -31,11 +31,11 @@ module SummaryStats = /// /// Creates a SummaryStats record from the given fields. /// - /// The number of observed data points. + /// The number of observed data points. /// The running mean of the data points. - /// The sum of squared deviations fom the mean - /// The minimum observed value. - /// The maximum observed value. + /// The sum of squared deviations fom the mean + /// The minimum observed value. + /// The maximum observed value. /// A new SummaryStats record. let createSummaryStats n mean sos min max = {N=n;Mean=mean;SumSqrdDevations=sos;Min=min;Max=max} @@ -110,6 +110,7 @@ module SummaryStats = /// A sequence of numeric data. /// /// A SummaryStats record containing the final count, mean, sum of squares, min, and max. + /// let inline ofSeq (items: seq<'T>) = use e = items.GetEnumerator() let zero = LanguagePrimitives.GenericZero<'T> From 4e7f49492c9a8b2b5e2067e96af9169bb47fab74 Mon Sep 17 00:00:00 2001 From: David Zimmer Date: Sat, 9 Aug 2025 17:13:33 +0200 Subject: [PATCH 097/121] add Holm and Hochberg FWER correction --- src/FSharp.Stats/Testing/MultipleTesting.fs | 72 + .../FSharp.Stats.Tests.fsproj | 3 + tests/FSharp.Stats.Tests/TestExtensions.fs | 1 - tests/FSharp.Stats.Tests/Testing.fs | 82 ++ .../data/fwer_hochberg_results.csv | 1231 +++++++++++++++++ .../data/fwer_holm_results.csv | 1231 +++++++++++++++++ .../data/holmHochberg_Input_nan.csv | 1231 +++++++++++++++++ 7 files changed, 3850 insertions(+), 1 deletion(-) create mode 100644 tests/FSharp.Stats.Tests/data/fwer_hochberg_results.csv create mode 100644 tests/FSharp.Stats.Tests/data/fwer_holm_results.csv create mode 100644 tests/FSharp.Stats.Tests/data/holmHochberg_Input_nan.csv diff --git a/src/FSharp.Stats/Testing/MultipleTesting.fs b/src/FSharp.Stats/Testing/MultipleTesting.fs index f9ad8d23e..9088ffae4 100644 --- a/src/FSharp.Stats/Testing/MultipleTesting.fs +++ b/src/FSharp.Stats/Testing/MultipleTesting.fs @@ -1,11 +1,83 @@ namespace FSharp.Stats.Testing +open System open FSharp.Stats /// This module contains functions to adjust for multiple testing errors in statistical tests. module MultipleTesting = + /// Holm–Bonferroni (step-down) FWER adjustment (NaN-safe) + /// NaN p-values are ignored in the computation and preserved at their original indices. + let inline holmFWER (p : float[]) : float[] = + let m = p.Length + let indexed = p |> Array.mapi (fun i v -> i, v) + + // keep only finite p-values for the adjustment + let valid = indexed |> Array.filter (fun (_, v) -> not (Double.IsNaN v)) + let nValid = valid.Length + + // start with an all-NaN result and fill only valid positions + let result = Array.create m Double.NaN + + if nValid = 0 then result else + let sorted = valid |> Array.sortBy snd + + // (nValid - i)·p_(i) for i = 0…nValid-1 + let raw = + sorted + |> Array.mapi (fun i (_, pv) -> float (nValid - i) * pv) + + // running max from the left, capped at 1.0 + let adjAsc = + raw + |> Array.scan (fun runningMax r -> max runningMax r) 0.0 + |> Array.tail + |> Array.map (min 1.0) + + // write adjusted values back into their original indices + Array.zip (sorted |> Array.map fst) adjAsc + |> Array.iter (fun (i, adj) -> result.[i] <- adj) + + result + + /// Hochberg (step-up) FWER adjustment (NaN-safe) + /// NaN p-values are ignored in the computation and preserved at their original indices. + let inline hochbergFWER (p : float[]) : float[] = + let m = p.Length + let indexed = p |> Array.mapi (fun i v -> i, v) + + // keep only finite p-values for the adjustment + let valid = indexed |> Array.filter (fun (_, v) -> not (Double.IsNaN v)) + let nValid = valid.Length + + // start with an all-NaN result and fill only valid positions + let result = Array.create m Double.NaN + + if nValid = 0 then result else + let sorted = valid |> Array.sortBy snd + + // (nValid - i)·p_(i), same raw values pattern as Holm + let raw = + sorted + |> Array.mapi (fun i (_, pv) -> float (nValid - i) * pv) + + // running min from the right, capped at 1.0 + let adjDesc = + raw + |> Array.rev + |> Array.scan (fun runningMin r -> min runningMin r) 1.0 + |> Array.tail + |> Array.rev + |> Array.map (min 1.0) + + // write adjusted values back into their original indices + Array.zip (sorted |> Array.map fst) adjDesc + |> Array.iter (fun (i, adj) -> result.[i] <- adj) + + result + + /// Benjamini-Hochberg Correction (BH) /// 'projection' should return a tuple of any identifier and the pValues as float, when applied to 'rawP' /// This function applies the Benjamini-Hochberg multiple testing correcture and returns all False Discovery Rates to which the given p-values are still diff --git a/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj b/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj index 2fe8dc70b..dfcdb5fdc 100644 --- a/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj +++ b/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj @@ -62,6 +62,9 @@ + + +
diff --git a/tests/FSharp.Stats.Tests/TestExtensions.fs b/tests/FSharp.Stats.Tests/TestExtensions.fs index ac7cd49d8..3c7ce678d 100644 --- a/tests/FSharp.Stats.Tests/TestExtensions.fs +++ b/tests/FSharp.Stats.Tests/TestExtensions.fs @@ -66,7 +66,6 @@ | [|a;b|] -> a, float b | _ -> failwith "invalid csv format" ) - let comparisonMetricsEqualRounded (digits : int) (actual: ComparisonMetrics) (expected: ComparisonMetrics) message = let actual = diff --git a/tests/FSharp.Stats.Tests/Testing.fs b/tests/FSharp.Stats.Tests/Testing.fs index e0593d73e..9a51a9679 100644 --- a/tests/FSharp.Stats.Tests/Testing.fs +++ b/tests/FSharp.Stats.Tests/Testing.fs @@ -403,6 +403,88 @@ let pearsonTests = ] +[] +let holmTests = + + + let largeSetnan = + Frame.ReadCsv(location = @"data/holmHochberg_Input_nan.csv",hasHeaders = true,separators = ",").GetColumn("pValues") + |> Series.valuesAll + |> Array.ofSeq + |> Array.map (fun x -> if x.IsSome then x.Value else nan ) + + let largeSet = + largeSetnan |> Array.filter (fun x -> not (nan.Equals x)) + + let largeSet_Expectednan = + Frame.ReadCsv(location = @"data/fwer_holm_results.csv",hasHeaders = true,separators = ",").GetColumn("pValues") + |> Series.valuesAll + |> Array.ofSeq + |> Array.map (fun x -> if x.IsSome then x.Value else nan ) + + let largeSet_Expected = + largeSet_Expectednan + |> Array.filter (fun x -> not (nan.Equals x)) + + testList "Testing.MultipleTesting.holmFWER" [ + + testCase "testHolmLarge" (fun () -> + Expect.sequenceEqual + (largeSet |> MultipleTesting.holmFWER |> Seq.map (fun x -> Math.Round(x,9))) + (largeSet_Expected |> Seq.map (fun x -> Math.Round(x,9))) + "adjusted pValues should be equal to the reference implementation." + ) + + testCase "testHolmLargeNaN" (fun () -> + TestExtensions.sequenceEqualRoundedNaN 9 + (largeSetnan |> MultipleTesting.holmFWER |> Seq.ofArray) + (largeSet_Expectednan |> Seq.ofArray) + "adjusted pValues should be equal to the reference implementation." + ) + + ] + +[] +let hochbergTests = + + + let largeSetnan = + Frame.ReadCsv(location = @"data/holmHochberg_Input_nan.csv",hasHeaders = true,separators = ",").GetColumn("pValues") + |> Series.valuesAll + |> Array.ofSeq + |> Array.map (fun x -> if x.IsSome then x.Value else nan ) + + let largeSet = + largeSetnan |> Array.filter (fun x -> not (nan.Equals x)) + + let largeSet_Expectednan = + Frame.ReadCsv(location = @"data/fwer_hochberg_results.csv",hasHeaders = true,separators = ",").GetColumn("pValues") + |> Series.valuesAll + |> Array.ofSeq + |> Array.map (fun x -> if x.IsSome then x.Value else nan ) + + let largeSet_Expected = + largeSet_Expectednan + |> Array.filter (fun x -> not (nan.Equals x)) + + testList "Testing.MultipleTesting.hochbergFWER" [ + + testCase "testHochbergLarge" (fun () -> + Expect.sequenceEqual + (largeSet |> MultipleTesting.hochbergFWER |> Seq.map (fun x -> Math.Round(x,9))) + (largeSet_Expected |> Seq.map (fun x -> Math.Round(x,9))) + "adjusted pValues should be equal to the reference implementation." + ) + + testCase "testHochbergLargeNaN" (fun () -> + TestExtensions.sequenceEqualRoundedNaN 9 + (largeSetnan |> MultipleTesting.hochbergFWER |> Seq.ofArray) + (largeSet_Expectednan |> Seq.ofArray) + "adjusted pValues should be equal to the reference implementation." + ) + + ] + [] let benjaminiHochbergTests = diff --git a/tests/FSharp.Stats.Tests/data/fwer_hochberg_results.csv b/tests/FSharp.Stats.Tests/data/fwer_hochberg_results.csv new file mode 100644 index 000000000..c69c4b305 --- /dev/null +++ b/tests/FSharp.Stats.Tests/data/fwer_hochberg_results.csv @@ -0,0 +1,1231 @@ +Key,pValues +CON__P00761,nan +CON__P07477,nan +CON__P15636,nan +CON__P35908v2;CON__P35908;CON__Q6IFZ6;CON__Q7Z794;CON__Q6NXH9,nan +Cre01.g000350.t1.1,0.9993188644999806 +Cre01.g000900.t1.2,0.9993188644999806 +Cre01.g001100.t1.2,0.9993188644999806 +Cre01.g002300.t1.2,0.9993188644999806 +Cre01.g002451.t1.1,0.9993188644999806 +Cre01.g002500.t1.2,0.9993188644999806 +Cre01.g004300.t1.2,0.9993188644999806 +Cre01.g004350.t1.2,0.9993188644999806 +Cre01.g004450.t1.2,0.5291382880932265 +Cre01.g004500.t1.2,0.9993188644999806 +Cre01.g004900.t1.2,0.9993188644999806 +Cre01.g004950.t1.1,0.9993188644999806 +Cre01.g005050.t1.1,0.9993188644999806 +Cre01.g005150.t1.1,0.9993188644999806 +Cre01.g005850.t1.2,0.9993188644999806 +Cre01.g006950.t2.1;Cre01.g006950.t1.1,0.9993188644999806 +Cre01.g007700.t1.1,0.9993188644999806 +Cre01.g010400.t1.2,0.9993188644999806 +Cre01.g010900.t1.2,0.9993188644999806 +Cre01.g011000.t1.2,0.5876655984410618 +Cre01.g012150.t1.2,0.9993188644999806 +Cre01.g013700.t2.1;Cre01.g013700.t1.2,0.9993188644999806 +Cre01.g014000.t1.2,0.9993188644999806 +Cre01.g014050.t1.2,0.9993188644999806 +Cre01.g014350.t1.2,0.9993188644999806 +Cre01.g015000.t1.2,0.9993188644999806 +Cre01.g015350.t1.1,0.9993188644999806 +Cre01.g015600.t1.1,0.9993188644999806 +Cre01.g016050.t1.2,0.9993188644999806 +Cre01.g016300.t1.1,0.9993188644999806 +Cre01.g016514.t1.1,0.9993188644999806 +Cre01.g016528.t1.1,0.9993188644999806 +Cre01.g016850.t1.2,0.9993188644999806 +Cre01.g016900.t1.2,0.9993188644999806 +Cre01.g017300.t1.2,0.9993188644999806 +Cre01.g019250.t1.2,0.9993188644999806 +Cre01.g020350.t1.2,0.9993188644999806 +Cre01.g020918.t1.1,0.9993188644999806 +Cre01.g021251.t1.1,0.9993188644999806 +Cre01.g021600.t1.2,0.9993188644999806 +Cre01.g023350.t1.1,0.05007875393687041 +Cre01.g025250.t1.1,0.9993188644999806 +Cre01.g026450.t1.2,0.9993188644999806 +Cre01.g026550.t1.1;REV__Cre13.g583972.t1.1,0.9993188644999806 +Cre01.g026600.t1.2,0.9993188644999806 +Cre01.g027000.t1.2,0.9993188644999806 +Cre01.g027550.t1.1,0.9993188644999806 +Cre01.g027800.t1.2,0.9993188644999806 +Cre01.g028550.t1.2,0.9993188644999806 +Cre01.g029300.t1.2,0.9993188644999806 +Cre01.g029650.t1.1,0.9993188644999806 +Cre01.g029750.t1.1,0.9993188644999806 +Cre01.g030850.t1.2,0.9993188644999806 +Cre01.g031100.t1.2,0.9993188644999806 +Cre01.g032300.t1.2,0.9993188644999806 +Cre01.g032650.t2.1;Cre01.g032650.t1.2,0.9993188644999806 +Cre01.g033550.t1.2,0.010092379479815766 +Cre01.g034000.t1.2,0.9993188644999806 +Cre01.g034400.t1.1,0.9993188644999806 +Cre01.g035350.t1.2,0.9993188644999806 +Cre01.g037850.t1.1,0.9993188644999806 +Cre01.g038400.t1.2,0.6344000363251011 +Cre01.g038850.t1.1,0.9993188644999806 +Cre01.g039250.t2.1;Cre01.g039250.t1.1,0.11681899128172679 +Cre01.g039300.t1.2,0.9993188644999806 +Cre01.g040000.t1.2,0.9993188644999806 +Cre01.g042750.t1.2,0.9993188644999806 +Cre01.g042800.t1.2,0.9993188644999806 +Cre01.g044800.t1.2,0.18065267165577942 +Cre01.g045550.t1.2,0.9993188644999806 +Cre01.g046652.t1.1,0.9993188644999806 +Cre01.g047700.t1.2,0.9993188644999806 +Cre01.g047750.t1.2,0.9993188644999806 +Cre01.g047800.t1.1,0.9993188644999806 +Cre01.g048950.t1.2,0.9993188644999806 +Cre01.g049000.t1.2,0.6344000363251011 +Cre01.g049500.t1.2,0.9993188644999806 +Cre01.g050100.t1.2,0.9993188644999806 +Cre01.g050850.t2.1;Cre01.g050850.t1.2,0.9993188644999806 +Cre01.g050950.t1.2,0.9993188644999806 +Cre01.g051500.t1.2,0.9993188644999806 +Cre01.g051900.t1.2,0.9993188644999806 +Cre01.g052100.t1.2,0.9993188644999806 +Cre01.g052250.t1.2,0.9993188644999806 +Cre01.g054150.t1.2,0.9993188644999806 +Cre01.g054500.t1.2,0.1586892392675976 +Cre01.g054850.t1.2,0.9993188644999806 +Cre01.g055408.t1.1,0.9993188644999806 +Cre01.g055453.t1.1,0.9993188644999806 +Cre01.g061077.t1.1,0.9993188644999806 +Cre01.g066917.t1.1,0.9993188644999806 +Cre01.g071662.t1.1,0.9993188644999806 +Cre02.g073550.t1.2,0.9993188644999806 +Cre02.g075700.t1.2,0.9993188644999806 +Cre02.g076250.t1.1,0.9993188644999806 +Cre02.g076300.t1.1,0.9993188644999806 +Cre02.g076350.t1.2,0.9993188644999806 +Cre02.g077100.t1.2,0.9993188644999806 +Cre02.g077300.t1.2,0.9993188644999806 +Cre02.g077350.t1.2,0.9993188644999806 +Cre02.g077800.t1.2,0.9993188644999806 +Cre02.g077850.t1.2,0.9993188644999806 +Cre02.g078100.t1.1,0.9993188644999806 +Cre02.g078300.t1.1,0.9993188644999806 +Cre02.g079400.t1.2,0.9993188644999806 +Cre02.g079550.t1.2,0.9993188644999806 +Cre02.g079600.t1.2,0.9993188644999806 +Cre02.g079700.t1.2,0.9993188644999806 +Cre02.g079800.t1.2,0.9993188644999806 +Cre02.g080200.t1.2,0.9993188644999806 +Cre02.g080350.t1.1,0.9993188644999806 +Cre02.g080650.t1.2,0.04454032259352383 +Cre02.g080700.t1.2,0.01951578593004504 +Cre02.g080900.t1.2,0.9993188644999806 +Cre02.g081050.t1.2,0.0014468871498838354 +Cre02.g081250.t1.2,0.9993188644999806 +Cre02.g082250.t1.1;Cre02.g082150.t1.1,0.9993188644999806 +Cre02.g082500.t1.1,0.9993188644999806 +Cre02.g082550.t1.2,0.9993188644999806 +Cre02.g082852.t1.1;Cre02.g082750.t1.2,0.9993188644999806 +Cre02.g083800.t2.1;Cre02.g083800.t1.2,0.9993188644999806 +Cre02.g083950.t1.1,0.9993188644999806 +Cre02.g084000.t1.2,0.9993188644999806 +Cre02.g085450.t1.2,0.9993188644999806 +Cre02.g085900.t1.2,0.9993188644999806 +Cre02.g085950.t1.2,0.9993188644999806 +Cre02.g087700.t1.2,0.9993188644999806 +Cre02.g087950.t1.2,0.9993188644999806 +Cre02.g088000.t1.2,0.9993188644999806 +Cre02.g088200.t1.2,0.9993188644999806 +Cre02.g088600.t1.2,0.9993188644999806 +Cre02.g088850.t1.2,0.9993188644999806 +Cre02.g088900.t1.2;Cre06.g278090.t1.1,0.9993188644999806 +Cre02.g089100.t1.2,0.9993188644999806 +Cre02.g090850.t1.1;REV__Cre12.g528450.t1.2,0.9993188644999806 +Cre02.g091050.t1.2,0.9993188644999806 +Cre02.g091100.t1.2,0.9993188644999806 +Cre02.g091550.t1.2,0.9993188644999806 +Cre02.g092400.t1.1,0.9993188644999806 +Cre02.g092900.t1.2,0.9993188644999806 +Cre02.g093450.t1.2,0.9993188644999806 +Cre02.g093650.t1.2,0.9993188644999806 +Cre02.g094100.t1.2,0.9993188644999806 +Cre02.g095146.t1.1,0.9993188644999806 +Cre02.g096150.t1.2,0.22271752893023758 +Cre02.g097400.t1.2,0.9993188644999806 +Cre02.g097550.t1.2,0.9993188644999806 +Cre02.g097650.t1.2,0.9993188644999806 +Cre02.g097900.t1.2,0.9993188644999806 +Cre02.g098250.t1.2,0.9993188644999806 +Cre02.g098450.t1.2,0.9993188644999806 +Cre02.g099150.t1.2,0.9993188644999806 +Cre02.g099850.t1.1,0.9993188644999806 +Cre02.g100200.t1.2,0.9993188644999806 +Cre02.g101350.t1.2,0.9993188644999806 +Cre02.g101400.t1.2,0.9993188644999806 +Cre02.g102250.t1.2,0.9993188644999806 +Cre02.g103550.t1.2,0.9993188644999806 +Cre02.g104900.t1.2,0.120403237313319 +Cre02.g106600.t1.2;Cre17.g733650.t1.1,0.4882057725056157 +Cre02.g107300.t1.2,0.9993188644999806 +Cre02.g108450.t1.2,0.9993188644999806 +Cre02.g108850.t1.2,0.9993188644999806 +Cre02.g109550.t1.2,0.9993188644999806 +Cre02.g110350.t1.2;Cre12.g485200.t1.1;Cre11.g467595.t1.1,0.9993188644999806 +Cre02.g111450.t1.2,0.9993188644999806 +Cre02.g111700.t1.2,0.9993188644999806 +Cre02.g113200.t1.1,0.9993188644999806 +Cre02.g114450.t1.2,0.9993188644999806 +Cre02.g114600.t1.2,0.9993188644999806 +Cre02.g115200.t1.2,0.9993188644999806 +Cre02.g116750.t2.1;Cre02.g116750.t1.1,0.9993188644999806 +Cre02.g118500.t1.1,0.9993188644999806 +Cre02.g118850.t1.2,0.9993188644999806 +Cre02.g118950.t1.2,0.9733314015580261 +Cre02.g119550.t1.2,0.9993188644999806 +Cre02.g120150.t1.2,0.9993188644999806 +Cre02.g120250.t2.1;Cre02.g120250.t1.1;Cre02.g120200.t1.2,0.9993188644999806 +Cre02.g141400.t1.2,0.9993188644999806 +Cre02.g141500.t1.2,0.9993188644999806 +Cre02.g142146.t1.1,0.9993188644999806 +Cre02.g142206.t1.1,0.9993188644999806 +Cre02.g142352.t1.1,0.9993188644999806 +Cre12.g486250.t1.2;Cre02.g142687.t2.1;Cre02.g142687.t1.1,0.9993188644999806 +Cre02.g142800.t1.2,0.9993188644999806 +Cre02.g143000.t1.2,0.9993188644999806 +Cre02.g143050.t1.2,0.9993188644999806 +Cre02.g143200.t1.1;Cre12.g547000.t1.2,0.9993188644999806 +Cre02.g143250.t1.2,0.9993188644999806 +Cre02.g143307.t1.1,0.9993188644999806 +Cre02.g143550.t1.2,0.9993188644999806 +Cre02.g145800.t1.2,0.9993188644999806 +Cre02.g146250.t1.2,0.9993188644999806 +Cre02.g147302.t1.1,0.188932128818238 +Cre02.g147900.t4.1;Cre02.g147900.t2.1;Cre02.g147900.t1.1;Cre02.g147900.t3.1,0.9993188644999806 +Cre03.g143887.t1.1,0.9993188644999806 +Cre03.g144627.t1.1,0.9993188644999806 +Cre03.g144807.t1.1;REV__Cre01.g020918.t1.1,0.9993188644999806 +Cre03.g144847.t1.1,0.9993188644999806 +Cre03.g144967.t1.1,0.9993188644999806 +Cre03.g145507.t1.1,0.9993188644999806 +Cre03.g145547.t1.1,0.9993188644999806 +Cre03.g145647.t1.1,0.9993188644999806 +Cre03.g145727.t1.1,0.9993188644999806 +Cre03.g145747.t1.1,0.9993188644999806 +Cre03.g145967.t1.1,0.9993188644999806 +Cre03.g146167.t1.1,0.9993188644999806 +Cre03.g146187.t1.1,0.9993188644999806 +Cre03.g146247.t1.1,0.9993188644999806 +Cre03.g146487.t1.1,0.9993188644999806 +Cre03.g146527.t1.1,0.9993188644999806 +Cre03.g149100.t1.2,0.9993188644999806 +Cre03.g150300.t1.2,0.9993188644999806 +Cre03.g152150.t1.2,0.9993188644999806 +Cre03.g153450.t1.2,0.9993188644999806 +Cre03.g154550.t1.1,0.9993188644999806 +Cre03.g156050.t1.2,0.9993188644999806 +Cre03.g156250.t1.2,0.9993188644999806 +Cre03.g156600.t1.2,0.9993188644999806 +Cre03.g156750.t1.2,0.9993188644999806 +Cre03.g156900.t1.2,0.9993188644999806 +Cre03.g156950.t1.1,0.9993188644999806 +Cre03.g157700.t1.2,0.9993188644999806 +Cre03.g158000.t1.2,0.9993188644999806 +Cre03.g158750.t1.1,0.9993188644999806 +Cre03.g158800.t3.1;Cre03.g158800.t2.1;Cre03.g158800.t1.1,0.5184298369121135 +Cre03.g158900.t1.2,0.9993188644999806 +Cre03.g160500.t1.2,0.9993188644999806 +Cre03.g161400.t1.2,0.9993188644999806 +Cre03.g164000.t1.2,0.9993188644999806 +Cre03.g164600.t1.2;Cre03.g165050.t1.2,0.0618285316541185 +Cre03.g164700.t1.2,0.9993188644999806 +Cre03.g166050.t1.2,0.9993188644999806 +Cre03.g168450.t1.2,0.9993188644999806 +Cre03.g168700.t1.2,0.9993188644999806 +Cre03.g169400.t1.2,0.9993188644999806 +Cre03.g169850.t1.2,0.9993188644999806 +Cre03.g169900.t1.2,0.9993188644999806 +Cre03.g171100.t1.1,0.9993188644999806 +Cre03.g171950.t1.1,0.9993188644999806 +Cre03.g172000.t1.2,0.9993188644999806 +Cre03.g172300.t1.2,0.9993188644999806 +Cre03.g172850.t1.2,0.9993188644999806 +Cre03.g172950.t1.2,0.9993188644999806 +Cre03.g173350.t2.1;Cre03.g173350.t1.2,0.9993188644999806 +Cre03.g175200.t1.2,0.9993188644999806 +Cre03.g175400.t2.1,0.9993188644999806 +Cre03.g176100.t1.2,0.9993188644999806 +Cre03.g176250.t1.2,0.9993188644999806 +Cre03.g177053.t1.1,0.9993188644999806 +Cre03.g177200.t1.2,0.9993188644999806 +Cre03.g178150.t1.1,0.9993188644999806 +Cre03.g178250.t1.2,0.9993188644999806 +Cre03.g178450.t1.2,0.016034797170714505 +Cre03.g180750.t1.2,6.922527196984164e-05 +Cre03.g180800.t1.1,0.9993188644999806 +Cre03.g181300.t1.2,0.9993188644999806 +Cre03.g181500.t1.2,0.9993188644999806 +Cre03.g182050.t1.2,0.9993188644999806 +Cre03.g182150.t1.2,0.3704075467177008 +Cre03.g182450.t1.2,0.9993188644999806 +Cre03.g182500.t1.2,0.9993188644999806 +Cre03.g182551.t1.2,0.07261771598620761 +Cre03.g182950.t1.2;Cre12.g520150.t1.1,0.9993188644999806 +Cre03.g183100.t1.2,0.9993188644999806 +Cre03.g183400.t1.1,0.9993188644999806 +Cre03.g184550.t1.2,0.9993188644999806 +Cre03.g185550.t1.2,0.9993188644999806 +Cre03.g187450.t1.2,0.9993188644999806 +Cre03.g188250.t1.2,0.9993188644999806 +Cre03.g189250.t1.2,0.9993188644999806 +Cre03.g189300.t1.1,0.5263674988725072 +Cre03.g189400.t1.2,0.9993188644999806 +Cre03.g189500.t1.2,0.9993188644999806 +Cre03.g189800.t1.2,0.9993188644999806 +Cre03.g189950.t1.2,0.9690472855533361 +Cre03.g190100.t1.1,0.9993188644999806 +Cre03.g190500.t1.2,0.9993188644999806 +Cre04.g216850.t1.2;Cre03.g190950.t1.2,0.1796500458321692 +Cre03.g191050.t1.2,0.9993188644999806 +Cre03.g193750.t1.1,0.9993188644999806 +Cre03.g193800.t1.1,0.9993188644999806 +Cre03.g193850.t1.2,0.9993188644999806 +Cre03.g193950.t1.2,0.9993188644999806 +Cre03.g194200.t1.2,0.9993188644999806 +Cre03.g194350.t1.2,0.9993188644999806 +Cre03.g194400.t1.2,0.9993188644999806 +Cre03.g194850.t1.2,0.9993188644999806 +Cre03.g195650.t1.2,0.9993188644999806 +Cre03.g197500.t2.1;Cre03.g197500.t1.2,0.9993188644999806 +Cre03.g198850.t1.2;Cre03.g198863.t1.1,0.9993188644999806 +Cre03.g198950.t1.2,0.9993188644999806 +Cre03.g199000.t1.2,0.9993188644999806 +Cre03.g199423.t1.1,0.9993188644999806 +Cre03.g199535.t1.1,0.9993188644999806 +Cre03.g199647.t1.1,0.9993188644999806 +Cre03.g199759.t2.1;Cre03.g199759.t1.1,0.9993188644999806 +Cre03.g199900.t1.2,0.9993188644999806 +Cre03.g199983.t1.1,0.9993188644999806 +Cre03.g200250.t1.2,0.9993188644999806 +Cre03.g202950.t1.1;Cre10.g419400.t1.1,0.9993188644999806 +Cre03.g203450.t1.2,0.9993188644999806 +Cre03.g203850.t1.2,0.9993188644999806 +Cre03.g204250.t1.2,0.9306660967040172 +Cre03.g204350.t1.2,0.9993188644999806 +Cre03.g204601.t1.1,0.9993188644999806 +Cre03.g206600.t1.2,0.9993188644999806 +Cre03.g207700.t1.1,0.9993188644999806 +Cre03.g213537.t1.1,0.9993188644999806 +Cre04.g213250.t1.2,0.9993188644999806 +Cre04.g214150.t1.1,0.9993188644999806 +Cre04.g214500.t1.1,0.9993188644999806 +Cre04.g214501.t1.1,0.9993188644999806 +Cre04.g214502.t1.1,0.9993188644999806 +Cre04.g215150.t2.1;Cre04.g215150.t1.2,0.36332361135879837 +Cre04.g215850.t1.2;REV__Cre13.g576600.t1.2,0.9993188644999806 +Cre04.g217550.t1.1,0.9993188644999806 +Cre04.g217921.t1.1,0.9993188644999806 +Cre04.g218100.t1.2,0.9993188644999806 +Cre04.g218250.t1.2,0.9993188644999806 +Cre04.g220200.t3.1;Cre04.g220200.t2.1;Cre04.g220200.t1.2,0.9993188644999806 +Cre04.g220350.t2.1;Cre04.g220350.t1.2,0.9993188644999806 +Cre04.g221400.t1.2,0.9993188644999806 +Cre04.g222700.t1.2,0.020664635250159824 +Cre04.g223100.t1.2,0.9993188644999806 +Cre04.g223850.t1.2,0.9993188644999806 +Cre04.g226850.t1.2,0.9993188644999806 +Cre04.g229300.t1.1,0.19067453301813908 +Cre04.g229700.t1.2,0.2247880975772978 +Cre04.g231026.t1.1,0.9993188644999806 +Cre04.g231222.t2.1;Cre04.g231222.t1.1,0.029951665151665714 +Cre04.g232104.t1.1,0.155879556910526 +Cre05.g232002.t2.1;Cre05.g232002.t1.1,0.9993188644999806 +Cre05.g232200.t1.2,0.9993188644999806 +Cre05.g232750.t1.2,0.9993188644999806 +Cre05.g233050.t1.2,0.9993188644999806 +Cre05.g233303.t2.1;Cre05.g233303.t1.1,0.9993188644999806 +Cre05.g233305.t2.1;Cre05.g233305.t1.1,0.9993188644999806 +Cre05.g233800.t1.2,0.9993188644999806 +Cre05.g233900.t1.2,0.9993188644999806 +Cre05.g233950.t1.2,0.9993188644999806 +Cre05.g234550.t2.1;Cre05.g234550.t1.2,0.9993188644999806 +Cre05.g234637.t1.1,0.9993188644999806 +Cre05.g234638.t1.1,0.9993188644999806 +Cre05.g234639.t1.1,0.9993188644999806 +Cre05.g234652.t1.1,0.9993188644999806 +Cre05.g237400.t1.2,0.9993188644999806 +Cre05.g237450.t1.2,0.9993188644999806 +Cre05.g238322.t1.1,0.9993188644999806 +Cre05.g238332.t1.1,0.9993188644999806 +Cre05.g238687.t1.1,0.9993188644999806 +Cre05.g240800.t1.2,0.9993188644999806 +Cre05.g240850.t1.2,0.4824573142179865 +Cre05.g241450.t1.2,0.9993188644999806 +Cre05.g241850.t1.2,0.9993188644999806 +Cre05.g241950.t1.2,0.9993188644999806 +Cre05.g242000.t1.2,0.9993188644999806 +Cre05.g242300.t1.2,0.9993188644999806 +Cre05.g242350.t1.2,0.9993188644999806 +Cre05.g243050.t1.2,0.9993188644999806 +Cre05.g243800.t1.2,0.9993188644999806 +Cre05.g245158.t1.1;Cre24.g755097.t1.1,0.9993188644999806 +Cre05.g245900.t1.2,0.9993188644999806 +Cre05.g245950.t1.1,0.9993188644999806 +Cre05.g247450.t1.2,0.9993188644999806 +Cre05.g247600.t1.2,0.9993188644999806 +Cre05.g247950.t1.2,0.9993188644999806 +Cre05.g248450.t1.2;Cre05.g248400.t1.2,0.9806968773269642 +Cre06.g249250.t1.2,0.9993188644999806 +Cre06.g250100.t1.2,0.04081067455631378 +Cre06.g250200.t1.2,0.9993188644999806 +Cre06.g250250.t1.2,0.9993188644999806 +Cre06.g250800.t2.1;Cre06.g250800.t1.1,0.9993188644999806 +Cre06.g250902.t1.1,0.9993188644999806 +Cre06.g251400.t1.2,0.9993188644999806 +Cre06.g251500.t1.2,0.9993188644999806 +Cre06.g252200.t1.2,0.9993188644999806 +Cre06.g252450.t1.1,0.9993188644999806 +Cre06.g252550.t1.1,0.9993188644999806 +Cre06.g252650.t1.2,0.9993188644999806 +Cre06.g253350.t1.2,0.9993188644999806 +Cre06.g254400.t1.1,0.9993188644999806 +Cre06.g255100.t1.1,0.9993188644999806 +Cre06.g256250.t1.2,0.9993188644999806 +Cre06.g257150.t1.2,0.9993188644999806 +Cre06.g257500.t1.2,0.9993188644999806 +Cre06.g257601.t1.2,0.1483918569864822 +Cre06.g257850.t1.2,0.9993188644999806 +Cre06.g257950.t1.2,0.9993188644999806 +Cre06.g258700.t1.1,0.9993188644999806 +Cre06.g258733.t2.1;Cre06.g258733.t1.1,0.9993188644999806 +Cre06.g258800.t1.1,0.9993188644999806 +Cre06.g259100.t1.1,0.9993188644999806 +Cre06.g259150.t1.2,0.9993188644999806 +Cre06.g259401.t1.1,0.9993188644999806 +Cre06.g259450.t1.2,0.9993188644999806 +Cre06.g259850.t1.2,0.9993188644999806 +Cre06.g259900.t1.2,0.008708700992422935 +Cre06.g261000.t1.2,0.9993188644999806 +Cre06.g261450.t1.2,0.504155999283102 +Cre06.g261500.t1.2,0.9414868256903144 +Cre06.g261650.t1.1,0.9993188644999806 +Cre06.g261800.t1.2,0.9993188644999806 +Cre06.g262100.t1.1,0.9993188644999806 +Cre06.g262700.t1.1,0.9993188644999806 +Cre06.g263250.t1.1,0.9993188644999806 +Cre06.g263300.t1.2,0.9993188644999806 +Cre12.g498600.t1.2;Cre06.g263450.t1.2;Cre06.g263450.t2.1,0.9993188644999806 +Cre06.g264200.t1.2,0.9993188644999806 +Cre06.g264300.t1.2,0.9993188644999806 +Cre06.g264350.t1.2,0.9993188644999806 +Cre06.g264600.t1.2;Cre12.g504850.t1.2;Cre17.g714600.t1.2;Cre17.g714000.t1.2;Cre17.g713500.t1.2;Cre17.g711800.t1.2;Cre17.g710500.t1.2;Cre17.g709100.t1.2;Cre17.g708650.t1.2;Cre17.g708200.t1.2;Cre16.g650250.t1.2;Cre16.g649950.t1.2;Cre12.g506450.t1.2;Cre12.g506350.t1.2;Cre12.g505450.t1.2;Cre12.g504600.t1.2;Cre06.g276800.t1.2;Cre06.g276650.t1.2;Cre06.g275700.t1.2;Cre06.g274900.t1.2;Cre06.g274300.t1.2;Cre06.g274150.t1.2;Cre06.g273950.t1.2;Cre06.g271300.t1.2;Cre06.g268400.t1.2;Cre06.g268000.t1.2;Cre06.g266600.t1.2;Cre06.g265450.t1.2;Cre06.g265200.t1.2;Cre06.g265050.t1.2;Cre13.g570000.t1.2;Cre13.g570000.t2.1,0.9993188644999806 +Cre06.g264650.t1.2;Cre12.g505500.t1.2;Cre06.g265000.t1.2;Cre17.g713950.t1.2;Cre17.g713550.t1.2;Cre17.g711850.t1.2;Cre17.g710550.t1.2;Cre17.g709050.t1.2;Cre17.g708700.t1.2;Cre17.g708150.t1.2;Cre16.g650300.t1.2;Cre16.g649900.t1.1;Cre16.g648500.t1.2;Cre13.g569950.t1.2;Cre12.g506500.t1.2;Cre12.g506300.t1.2;Cre12.g504800.t1.2;Cre17.g714650.t1.2;Cre12.g504650.t1.2;Cre06.g276850.t1.2;Cre06.g276600.t1.2;Cre06.g275750.t1.2;Cre06.g274850.t1.2;Cre06.g274350.t1.2;Cre06.g274101.t1.1;Cre06.g274000.t1.2;Cre06.g271250.t1.2;Cre06.g268350.t1.2;Cre06.g267950.t1.2;Cre06.g266650.t1.2;Cre06.g265500.t1.2;Cre06.g265250.t1.2;Cre02.g104800.t1.1,0.9993188644999806 +Cre06.g264750.t1.2;Cre17.g708550.t1.2;Cre06.g264950.t1.2;Cre06.g265350.t1.2;Cre06.g266700.t1.2;Cre06.g268050.t1.2;Cre13.g591150.t1.2;Cre13.g590800.t1.2;Cre12.g506250.t1.2;Cre12.g505550.t1.2;Cre12.g504750.t1.2;Cre12.g504500.t1.2;Cre06.g268300.t1.2;Cre06.g274800.t1.2;Cre06.g273900.t1.2;Cre06.g271350.t1.2;Cre06.g275850.t1.2;Cre17.g714100.t1.2;Cre17.g713400.t1.2;Cre17.g711700.t1.2;Cre17.g710400.t1.2;Cre17.g709200.t1.2;Cre06.g276500.t1.2;Cre13.g570100.t1.2;Cre06.g274200.t1.2;Cre17.g714500.t1.2;Cre06.g276950.t1.2;Cre06.g278088.t1.1,0.9993188644999806 +Cre06.g265800.t1.2,0.9993188644999806 +Cre06.g268600.t1.2,0.9993188644999806 +Cre06.g269050.t1.2,0.7315423597972802 +Cre06.g269450.t1.2,0.9993188644999806 +Cre06.g269650.t1.2;Cre06.g269601.t1.1,0.9993188644999806 +Cre06.g269950.t1.2,0.9993188644999806 +Cre06.g272050.t1.2,0.9993188644999806 +Cre06.g272650.t1.2,0.9993188644999806 +Cre06.g272800.t1.2,0.9993188644999806 +Cre06.g272850.t1.2;Cre10.g449700.t1.1,0.9993188644999806 +Cre06.g272900.t1.2,0.9993188644999806 +Cre06.g272950.t1.1,0.03894708556119043 +Cre06.g273000.t1.2,0.9993188644999806 +Cre06.g273300.t1.2,0.9993188644999806 +Cre06.g273550.t1.2,0.9993188644999806 +Cre06.g273700.t1.2,0.9993188644999806 +Cre06.g274650.t1.1,0.9993188644999806 +Cre06.g275100.t1.2,0.5781754372814029 +Cre06.g278087.t1.1;Cre06.g278089.t1.1,0.9993188644999806 +Cre06.g278125.t1.1,0.9993188644999806 +Cre06.g278135.t1.1,0.9993188644999806 +Cre06.g278148.t1.1,0.9993188644999806 +Cre06.g278162.t1.1,0.9993188644999806 +Cre06.g278163.t1.1,0.9993188644999806 +Cre06.g278169.t1.1,0.9993188644999806 +Cre06.g278170.t1.1,0.9993188644999806 +Cre06.g278185.t1.1,0.2954390747875814 +Cre06.g278195.t1.1,0.9993188644999806 +Cre06.g278210.t1.1,0.039827393261135643 +Cre06.g278211.t1.1,0.9993188644999806 +Cre06.g278213.t1.1,0.9993188644999806 +Cre06.g278221.t1.1,0.9993188644999806 +Cre06.g278222.t1.1,0.9993188644999806 +Cre06.g278239.t2.1;Cre06.g278239.t1.1,0.9993188644999806 +Cre06.g278255.t1.1,0.9993188644999806 +Cre06.g278256.t1.1,0.9993188644999806 +Cre06.g278750.t1.2,0.9993188644999806 +Cre06.g279150.t1.2,0.34621650587379 +Cre06.g279400.t1.2,0.9993188644999806 +Cre06.g280650.t1.2,0.9993188644999806 +Cre06.g280950.t1.2,0.9993188644999806 +Cre06.g282000.t1.1;Cre06.g282000.t2.1,0.9993188644999806 +Cre06.g282500.t1.2,0.9993188644999806 +Cre06.g282800.t1.2,0.9993188644999806 +Cre06.g283050.t1.2,0.9993188644999806 +Cre06.g283950.t1.2,0.944077313516506 +Cre06.g284750.t1.2,0.9993188644999806 +Cre06.g284900.t2.1;Cre06.g284900.t1.2,0.9993188644999806 +Cre06.g285250.t1.2,0.9993188644999806 +Cre06.g285401.t1.1,0.9993188644999806 +Cre06.g286250.t1.2,0.9993188644999806 +Cre06.g288700.t1.2,0.9993188644999806 +Cre06.g289550.t1.2,0.9993188644999806 +Cre06.g290950.t1.2,0.9993188644999806 +Cre06.g292000.t1.1,0.2938991543998476 +Cre06.g293150.t1.2,0.9993188644999806 +Cre06.g293582.t1.1,0.9993188644999806 +Cre06.g293850.t1.2,0.9993188644999806 +Cre06.g293950.t1.2,0.005647377312504531 +Cre06.g294650.t1.2,0.26325793063843106 +Cre06.g294750.t1.2,0.9993188644999806 +Cre06.g294950.t1.1,0.9993188644999806 +Cre06.g295450.t1.2,0.9993188644999806 +Cre06.g296500.t1.2,0.9993188644999806 +Cre06.g298100.t1.2,0.9993188644999806 +Cre06.g298350.t1.2,0.9993188644999806 +Cre06.g298650.t1.2,0.9993188644999806 +Cre06.g299000.t1.2,0.9993188644999806 +Cre06.g299650.t1.2,0.9993188644999806 +Cre06.g300550.t1.2,0.9993188644999806 +Cre06.g300700.t1.1,0.9993188644999806 +Cre06.g300800.t1.2,0.9993188644999806 +Cre06.g302700.t1.1,0.9993188644999806 +Cre06.g304300.t1.2,0.9993188644999806 +Cre06.g304350.t1.2,0.9993188644999806 +Cre06.g304500.t1.2,0.9993188644999806 +Cre06.g306300.t1.2,0.9993188644999806 +Cre06.g306601.t1.1,0.9993188644999806 +Cre06.g307450.t1.2,0.9993188644999806 +Cre06.g307500.t1.1,0.2241659341184489 +Cre06.g308250.t1.2,0.1532882972455294 +Cre06.g308450.t1.2,0.9993188644999806 +Cre06.g308500.t1.2,0.9993188644999806 +Cre06.g308850.t1.2,0.9993188644999806 +Cre06.g308950.t1.2,0.9993188644999806 +Cre06.g309100.t1.2,0.9993188644999806 +Cre06.g310750.t1.2,0.9993188644999806 +Cre06.g311900.t1.2,0.9993188644999806 +Cre07.g313700.t1.1,0.9993188644999806 +Cre07.g314150.t1.2,0.9993188644999806 +Cre07.g316000.t1.2,0.9993188644999806 +Cre07.g318450.t1.2,0.9993188644999806 +Cre07.g318750.t1.2,0.9993188644999806 +Cre07.g324200.t1.2;REV__Cre13.g602800.t1.1,0.4064780458042206 +Cre07.g325400.t1.2,0.9993188644999806 +Cre07.g325500.t1.1,0.9993188644999806 +Cre07.g325734.t1.1,0.9993188644999806 +Cre07.g325736.t1.1,0.6065691546836469 +Cre07.g325746.t1.1,0.9993188644999806 +Cre07.g325755.t1.1,0.07422203585299571 +Cre07.g326800.t1.1,0.9993188644999806 +Cre07.g326950.t1.1,0.9993188644999806 +Cre07.g327350.t1.2,0.9993188644999806 +Cre07.g327400.t1.1,0.9993188644999806 +Cre07.g328150.t2.1;Cre07.g328150.t1.1,0.9993188644999806 +Cre07.g328200.t1.2,0.9993188644999806 +Cre07.g328900.t1.2,0.9993188644999806 +Cre07.g329700.t1.2,0.9993188644999806 +Cre07.g330250.t1.2,0.9993188644999806 +Cre07.g331500.t1.1,0.9993188644999806 +Cre07.g331550.t1.2,0.9993188644999806 +Cre07.g331900.t1.2,0.9993188644999806 +Cre07.g332450.t1.2,0.6520110519748924 +Cre07.g334900.t1.1,0.9993188644999806 +Cre07.g335400.t1.1,0.9993188644999806 +Cre07.g336450.t1.2,0.9993188644999806 +Cre07.g336950.t1.1,0.04318942430152387 +Cre07.g337650.t1.2,0.9993188644999806 +Cre07.g338050.t1.2,0.9993188644999806 +Cre07.g338451.t1.1,0.332378207618691 +Cre07.g339150.t1.1,0.1259389880442656 +Cre07.g339700.t1.2,0.9993188644999806 +Cre07.g340200.t1.1,0.9993188644999806 +Cre07.g340350.t1.1,0.9993188644999806 +Cre07.g341550.t1.2,0.9993188644999806 +Cre07.g341600.t2.1,0.01640041110839864 +Cre07.g342150.t1.2,0.9993188644999806 +Cre07.g342250.t1.2,0.9993188644999806 +Cre07.g343700.t1.2;Cre07.g343433.t1.1,0.9993188644999806 +Cre07.g344400.t1.2,0.9993188644999806 +Cre07.g344550.t1.2,0.9993188644999806 +Cre07.g344950.t1.2,0.9993188644999806 +Cre07.g346050.t2.1;Cre07.g346050.t1.2,0.9993188644999806 +Cre07.g347150.t1.2,0.9993188644999806 +Cre07.g349350.t1.2,0.9993188644999806 +Cre07.g350500.t1.2,0.17593493569192417 +Cre07.g352650.t1.2,0.9993188644999806 +Cre07.g352850.t1.2,0.9993188644999806 +Cre07.g353450.t1.2,0.9993188644999806 +Cre07.g356350.t1.1,0.9993188644999806 +Cre07.g356400.t1.2,0.9993188644999806 +Cre07.g356600.t1.2,0.9993188644999806 +Cre07.g357200.t1.2,0.9993188644999806 +Cre07.g357350.t1.2,0.9993188644999806 +Cre07.g357850.t1.2,0.9993188644999806 +Cre08.g358526.t1.1,0.332378207618691 +Cre08.g358562.t1.1,0.09430296377528288 +Cre08.g358580.t1.1,0.9993188644999806 +Cre08.g359350.t1.2,0.9993188644999806 +Cre08.g359750.t2.1;Cre08.g359750.t1.2,0.5971147249485951 +Cre08.g360900.t1.2,0.9993188644999806 +Cre08.g361850.t1.2,0.9993188644999806 +Cre08.g362450.t1.2,0.9993188644999806 +Cre08.g364650.t1.1,0.9993188644999806 +Cre08.g364800.t1.2,0.6373268095582125 +Cre08.g365400.t1.2,0.9993188644999806 +Cre08.g365632.t1.1,0.9993188644999806 +Cre08.g365692.t1.1,0.9993188644999806 +Cre08.g366400.t2.1;Cre08.g366400.t1.2,0.9993188644999806 +Cre08.g367500.t1.1;Cre08.g367400.t1.1,0.7119842539865409 +Cre08.g368400.t1.2,0.9993188644999806 +Cre08.g368900.t2.1;Cre08.g368900.t1.2,0.9993188644999806 +Cre08.g368950.t1.2,0.9993188644999806 +Cre08.g370450.t1.2,0.9993188644999806 +Cre08.g370650.t1.2,0.9038374329343172 +Cre08.g372100.t1.2,0.012422753187091976 +Cre08.g372450.t1.2,0.9993188644999806 +Cre08.g372950.t1.2,0.9993188644999806 +Cre08.g373100.t1.1,0.9993188644999806 +Cre08.g375200.t2.1;Cre08.g375200.t1.2,0.9993188644999806 +Cre08.g376100.t1.2,0.9993188644999806 +Cre08.g378000.t1.2,0.9993188644999806 +Cre08.g378050.t1.2,0.9993188644999806 +Cre08.g378850.t1.2,0.9993188644999806 +Cre08.g379200.t1.1;Cre08.g379175.t1.1,0.9993188644999806 +Cre08.g380201.t1.1,0.9993188644999806 +Cre08.g382500.t1.2,0.9993188644999806 +Cre08.g384000.t1.1,0.9993188644999806 +Cre09.g386200.t1.1,0.9993188644999806 +Cre09.g386400.t1.2,0.9993188644999806 +Cre09.g386650.t2.1;Cre09.g386650.t1.2,0.9993188644999806 +Cre09.g386735.t1.1,0.9993188644999806 +Cre09.g386750.t1.2,0.1571270661439956 +Cre09.g386758.t1.1,0.9993188644999806 +Cre09.g387171.t2.1;Cre09.g387171.t1.1,0.9993188644999806 +Cre09.g387393.t1.1,0.9993188644999806 +Cre09.g387726.t1.1,0.9993188644999806 +Cre09.g387800.t1.2,0.9993188644999806 +Cre09.g387875.t1.1,0.9993188644999806 +Cre09.g388200.t1.1,0.9993188644999806 +Cre09.g388467.t1.1,0.9993188644999806 +Cre09.g388726.t1.1;Cre09.g388726.t2.1;Cre09.g388726.t3.1;Cre09.g388726.t4.1,0.1504500367476816 +Cre09.g389430.t1.1,0.9993188644999806 +Cre09.g389689.t1.1,0.9993188644999806 +Cre09.g390050.t1.2,0.9993188644999806 +Cre09.g390763.t1.1,0.9993188644999806 +Cre09.g391023.t1.1,0.9993188644999806 +Cre09.g391097.t2.1;Cre09.g391097.t1.1,0.9993188644999806 +Cre09.g391900.t1.1,0.9993188644999806 +Cre09.g392350.t2.1;Cre09.g392350.t1.2,0.07708311087015218 +Cre09.g392500.t1.2,0.9993188644999806 +Cre09.g393150.t1.2,0.21549544376965798 +Cre09.g393173.t1.1,0.9993188644999806 +Cre09.g393200.t1.2,0.9134652306565516 +Cre09.g393358.t1.1,0.9993188644999806 +Cre09.g393543.t1.1,0.9993188644999806 +Cre09.g393765.t1.1,0.9993188644999806 +Cre09.g394102.t1.1,0.9993188644999806 +Cre09.g394200.t1.1,0.9993188644999806 +Cre09.g394436.t1.1,0.9993188644999806 +Cre09.g394450.t1.2,0.850554371360229 +Cre09.g394547.t1.1,0.9993188644999806 +Cre09.g394550.t1.2,0.9993188644999806 +Cre09.g394750.t1.2,0.9993188644999806 +Cre09.g394850.t1.2,0.9993188644999806 +Cre09.g395350.t1.1,0.9993188644999806 +Cre09.g396213.t1.1,0.9993188644999806 +Cre09.g396252.t1.1,0.9993188644999806 +Cre09.g396300.t1.2,0.9993188644999806 +Cre09.g396400.t1.2;Cre01.g007051.t1.2;Cre11.g467567.t1.1,0.9993188644999806 +Cre09.g396650.t1.2,0.9993188644999806 +Cre09.g397200.t1.2,0.9993188644999806 +Cre09.g397549.t1.1,0.9993188644999806 +Cre09.g397697.t1.1,0.9993188644999806 +Cre09.g398067.t1.1,0.04689792257178644 +Cre09.g398900.t1.1,0.9993188644999806 +Cre09.g400050.t1.1,0.9993188644999806 +Cre09.g400650.t1.2,0.9993188644999806 +Cre09.g401515.t1.1,0.9993188644999806 +Cre09.g401886.t1.1,0.9993188644999806 +Cre09.g401900.t1.2,0.9993188644999806 +Cre09.g402300.t1.2,0.9993188644999806 +Cre09.g402450.t1.2,0.9993188644999806 +Cre09.g402500.t1.2,0.9993188644999806 +Cre09.g402775.t1.1,0.9993188644999806 +Cre09.g402950.t1.1,0.9993188644999806 +Cre09.g403800.t1.2,0.9993188644999806 +Cre09.g403900.t1.2,0.9993188644999806 +Cre09.g404000.t1.1,0.9993188644999806 +Cre09.g405050.t1.2,0.9993188644999806 +Cre09.g405800.t1.2,0.9993188644999806 +Cre09.g405850.t1.1,0.9993188644999806 +Cre09.g406200.t1.2,0.9993188644999806 +Cre09.g406600.t1.1,0.007461884476826212 +Cre09.g406983.t1.1,0.9993188644999806 +Cre09.g407600.t1.2,0.9993188644999806 +Cre09.g408200.t1.2,0.9993188644999806 +Cre09.g409100.t1.2,0.9993188644999806 +Cre09.g409350.t1.2,0.9993188644999806 +Cre09.g409500.t1.2,0.9993188644999806 +Cre09.g410650.t1.2;Cre09.g410650.t2.1;Cre09.g410650.t3.1,0.9993188644999806 +Cre09.g410700.t1.2,0.9993188644999806 +Cre09.g411100.t2.1;Cre09.g411100.t1.2,0.1757447572162625 +Cre09.g411200.t1.2,0.9993188644999806 +Cre09.g411900.t1.1,0.9993188644999806 +Cre09.g412100.t1.2,0.9993188644999806 +Cre09.g414050.t1.2,0.9993188644999806 +Cre09.g415550.t1.2,0.9993188644999806 +Cre09.g415700.t1.2,0.9993188644999806 +Cre09.g415800.t1.2,0.9993188644999806 +Cre09.g415850.t1.2,0.9993188644999806 +Cre09.g415950.t1.2,0.9993188644999806 +Cre09.g416050.t1.2,0.9993188644999806 +Cre09.g416150.t1.2,0.9993188644999806 +Cre09.g416350.t1.2,0.9993188644999806 +Cre09.g416750.t1.2,0.9993188644999806 +Cre09.g416850.t1.2,0.9993188644999806 +Cre09.g417150.t1.2,0.9993188644999806 +Cre09.g417200.t1.2,0.9993188644999806 +Cre-1.g000035.t1.p1,0.9993188644999806 +Cre-1.g2716952.t1.p1,0.9993188644999806 +Cre-1.g2716955.t1.p1,0.9993188644999806 +Cre-1.g2716958.t1.p1,0.9993188644999806 +Cre-1.g2716959.t1.p1,0.9993188644999806 +Cre-1.g2716961.t1.p1,0.9993188644999806 +Cre-1.g2716963.t1.p1,0.6373268095582125 +Cre-1.g2716972.t1.p1,0.9993188644999806 +Cre-1.g2716979.t1.p1,0.9993188644999806 +Cre-1.g2716983.t1.p1,0.04192120256676257 +Cre-1.g2716987.t1.p1,0.9993188644999806 +Cre-1.g2716989.t1.p1,0.9993188644999806 +Cre-1.g2716990.t1.p1,0.9993188644999806 +Cre-1.g2716994.t1.p1,0.9993188644999806 +Cre-1.g2716997.t1.p1,0.9993188644999806 +Cre-1.g2717000.t1.p1,0.9993188644999806 +Cre-1.g2717002.t1.p1,0.9993188644999806 +Cre-1.g2717005.t1.p1;REV__Cre24.g755297.t1.1;Cre01.g027764.t1.2;REV__Cre07.g352400.t1.2,0.9993188644999806 +Cre-1.g2717006.t1.p1,0.9993188644999806 +Cre-1.g2717008.t1.p1,0.9993188644999806 +Cre-1.g2717009.t1.p1,0.9993188644999806 +Cre-1.g2717010.t1.p1,0.9993188644999806 +Cre-1.g2717015.t1.p1,0.9993188644999806 +Cre-1.g2717017.t1.p1,0.9993188644999806 +Cre-1.g2717021.t1.p1,0.9993188644999806 +Cre-1.g2717030.t1.p1,0.9993188644999806 +Cre-1.g2717034.t1.p1,0.04413314008357516 +Cre-1.g2717038.t1.p1,0.9993188644999806 +Cre-1.g2717040.t1.p1,0.9993188644999806 +Cre-1.g2717041.t1.p1,0.11003667463466393 +Cre-1.g2717044.t1.p1,0.9993188644999806 +Cre-1.g2717046.t1.p1,0.9993188644999806 +Cre-1.g2717054.t1.p1,0.9993188644999806 +Cre-1.g2717055.t1.p1,0.9993188644999806 +Cre-1.g2717056.t1.p1,0.9993188644999806 +Cre-1.g2717057.t1.p1,0.9993188644999806 +Cre-1.g2717058.t1.p1,0.859393862449768 +Cre-1.g2717059.t1.p1,0.5195363300062164 +Cre10.g417700.t1.2,0.9993188644999806 +Cre10.g418100.t1.1,0.9993188644999806 +Cre10.g418450.t1.2,0.9993188644999806 +Cre10.g419950.t1.1,0.9993188644999806 +Cre10.g420350.t1.2,0.9993188644999806 +Cre10.g420750.t1.2,0.9993188644999806 +Cre10.g421600.t1.2,0.9993188644999806 +Cre10.g422300.t1.2,0.5957035459575027 +Cre10.g422600.t1.1,0.9993188644999806 +Cre10.g423250.t1.2,0.9993188644999806 +Cre10.g423500.t1.2,0.9993188644999806 +Cre10.g423650.t1.2,0.21251489662998319 +Cre10.g424100.t1.2,0.9993188644999806 +Cre10.g424450.t1.2,0.9993188644999806 +Cre10.g425900.t1.2,0.9993188644999806 +Cre10.g425950.t1.2,0.9993188644999806 +Cre10.g427250.t1.2,0.9993188644999806 +Cre10.g427700.t1.2,0.2924747171696484 +Cre10.g428200.t1.2,0.9993188644999806 +Cre10.g428750.t1.1,0.9993188644999806 +Cre10.g429100.t1.2,0.9993188644999806 +Cre10.g430000.t1.1,0.9993188644999806 +Cre10.g430150.t1.2,0.9993188644999806 +Cre10.g430501.t1.1;Cre09.g388430.t1.1;Cre10.g449200.t1.1,0.336271118666643 +Cre10.g432800.t1.2,0.9993188644999806 +Cre10.g433000.t1.1,0.9993188644999806 +Cre10.g433600.t1.2,0.9993188644999806 +Cre10.g433950.t1.1,0.9993188644999806 +Cre10.g434200.t1.1,0.9993188644999806 +Cre10.g434450.t1.2,0.9993188644999806 +Cre10.g434750.t1.2,0.9993188644999806 +Cre10.g435300.t2.1;Cre10.g435300.t1.2,0.9993188644999806 +Cre10.g435800.t1.2,0.9993188644999806 +Cre10.g435850.t1.2,0.9993188644999806 +Cre10.g436050.t1.2,0.708823427875808 +Cre10.g436350.t1.1,0.9993188644999806 +Cre10.g436500.t1.2,0.9993188644999806 +Cre10.g436550.t1.2,0.9993188644999806 +Cre10.g439100.t1.2,0.9993188644999806 +Cre10.g439150.t1.2,0.9993188644999806 +Cre10.g439400.t1.1,0.9993188644999806 +Cre10.g439850.t1.2,0.9993188644999806 +Cre10.g439900.t1.2;Cre18.g749547.t1.1,0.9993188644999806 +Cre10.g440050.t1.2;REV__Cre10.g463700.t1.1,0.9993188644999806 +Cre10.g440450.t1.2,0.9993188644999806 +Cre10.g441200.t1.2,0.9993188644999806 +Cre10.g441400.t1.2,0.9993188644999806 +Cre10.g442700.t1.2,0.9993188644999806 +Cre10.g443250.t1.2,0.9993188644999806 +Cre10.g444700.t1.1,0.9993188644999806 +Cre10.g444800.t1.2,0.9993188644999806 +Cre10.g446550.t1.2,0.9993188644999806 +Cre10.g447100.t1.2,0.9993188644999806 +Cre10.g449550.t1.2,0.9993188644999806 +Cre10.g450400.t1.2,0.9993188644999806 +Cre10.g451900.t1.1,0.9993188644999806 +Cre10.g451950.t1.2,0.9993188644999806 +Cre10.g452050.t1.2,0.9993188644999806 +Cre10.g452450.t1.2,0.9993188644999806 +Cre10.g452800.t1.2,0.9993188644999806 +Cre10.g456000.t1.2,0.9993188644999806 +Cre10.g456050.t2.1;Cre10.g456050.t1.2,0.9993188644999806 +Cre10.g456200.t1.2,0.9993188644999806 +Cre10.g456750.t1.2,0.9993188644999806 +Cre10.g457700.t1.2,0.9993188644999806 +Cre10.g458550.t1.2,0.9993188644999806 +Cre10.g459200.t1.2,0.9993188644999806 +Cre10.g459250.t1.2,0.9993188644999806 +Cre10.g461050.t1.2,0.9993188644999806 +Cre10.g461250.t1.1,0.9993188644999806 +Cre10.g462250.t1.2,0.9993188644999806 +Cre10.g465550.t1.1,0.9993188644999806 +Cre11.g467350.t1.2,0.9993188644999806 +Cre11.g467400.t1.2,0.9993188644999806 +Cre11.g467535.t1.1;Cre16.g658850.t1.1,0.9993188644999806 +Cre11.g467547.t1.1,0.9993188644999806 +Cre11.g467550.t1.2,0.9993188644999806 +Cre11.g467569.t1.1,0.9993188644999806 +Cre11.g467573.t1.1,0.9993188644999806 +Cre11.g467578.t1.1,0.7501527658478415 +Cre11.g467617.t1.1,0.9993188644999806 +Cre11.g467640.t1.1,0.9993188644999806 +Cre11.g467668.t1.1,0.9993188644999806 +Cre11.g467689.t1.1,0.9993188644999806 +Cre11.g467699.t1.1,0.9993188644999806 +Cre11.g467700.t1.1,0.9993188644999806 +Cre11.g467707.t1.1,0.9993188644999806 +Cre11.g467723.t2.1;Cre11.g467723.t1.1,0.9993188644999806 +Cre11.g467767.t1.1,0.9993188644999806 +Cre11.g467770.t1.1,0.9993188644999806 +Cre11.g467773.t1.1,0.9993188644999806 +Cre11.g467778.t1.1,0.9993188644999806 +Cre11.g468300.t1.2,0.9993188644999806 +Cre11.g468359.t1.1,0.9993188644999806 +Cre11.g468450.t1.2,0.9993188644999806 +Cre11.g468550.t1.2,0.9993188644999806 +Cre11.g468750.t1.2,0.9993188644999806 +Cre11.g468950.t1.2,0.9993188644999806 +Cre11.g469150.t1.2,0.9993188644999806 +Cre11.g476550.t1.2,0.41397970800958617 +Cre11.g476750.t1.2,0.9993188644999806 +Cre11.g477300.t1.1,0.9993188644999806 +Cre11.g477850.t1.1,0.3419954982806312 +Cre11.g477950.t1.1,0.9993188644999806 +Cre11.g478156.t2.1;Cre11.g478156.t1.1,0.9993188644999806 +Cre11.g478700.t1.2,0.9993188644999806 +Cre11.g479050.t1.2,0.9993188644999806 +Cre11.g479250.t1.2,0.9993188644999806 +Cre11.g479500.t1.2,0.30169700902912194 +Cre11.g479750.t1.2,0.9993188644999806 +Cre11.g480150.t1.2,0.20781060276933208 +Cre11.g481126.t1.1,0.9993188644999806 +Cre11.g481450.t1.2,0.9993188644999806 +Cre11.g481500.t1.2,0.9993188644999806 +Cre12.g483650.t1.2,0.9993188644999806 +Cre12.g483700.t2.1;Cre12.g483700.t1.2,0.7081528813483741 +Cre12.g483850.t1.2;REV__Cre12.g542100.t1.2;REV__Cre12.g541800.t1.2,0.9993188644999806 +Cre12.g483950.t1.2,0.9993188644999806 +Cre12.g484000.t1.2,0.9993188644999806 +Cre12.g484050.t1.2,0.9993188644999806 +Cre12.g484200.t1.2,0.9993188644999806 +Cre12.g485150.t1.2,0.9993188644999806 +Cre12.g485800.t1.2,0.9993188644999806 +Cre12.g486100.t1.2,0.9993188644999806 +Cre12.g486300.t1.2,0.9993188644999806 +Cre12.g487100.t1.2,0.9993188644999806 +Cre12.g488850.t2.1;Cre12.g488850.t1.1,0.9993188644999806 +Cre12.g489153.t1.1,0.9993188644999806 +Cre12.g489700.t1.2,0.9993188644999806 +Cre12.g490000.t1.2,0.9993188644999806 +Cre12.g490350.t1.1,0.9993188644999806 +Cre12.g490500.t1.2,0.9993188644999806 +Cre12.g492300.t1.2,0.9993188644999806 +Cre12.g492600.t1.2,0.9993188644999806 +Cre12.g492650.t1.2,0.9993188644999806 +Cre12.g493250.t1.2,0.9993188644999806 +Cre12.g493950.t1.2,0.9993188644999806 +Cre12.g494050.t1.2,0.9993188644999806 +Cre12.g494100.t1.1,0.9993188644999806 +Cre12.g494450.t1.2,0.9993188644999806 +Cre12.g494750.t1.2,0.9993188644999806 +Cre12.g494850.t1.2,0.9993188644999806 +Cre12.g495650.t1.2,0.9993188644999806 +Cre12.g495850.t1.2,0.9993188644999806 +Cre12.g495951.t2.1;Cre12.g495951.t1.1,0.9993188644999806 +Cre12.g496750.t1.2,0.9993188644999806 +Cre12.g497300.t2.1;Cre12.g497300.t1.2,0.02329849828379049 +Cre12.g497700.t1.2,0.9993188644999806 +Cre12.g498100.t1.2,0.9993188644999806 +Cre12.g498250.t1.2,0.9993188644999806 +Cre12.g498450.t1.2,0.9993188644999806 +Cre12.g498550.t1.1,0.09047715620234587 +Cre12.g498900.t1.2,0.9993188644999806 +Cre12.g498950.t1.2,0.9993188644999806 +Cre12.g499800.t1.2,0.9993188644999806 +Cre12.g500150.t1.1,0.9993188644999806 +Cre12.g500500.t2.1;Cre12.g500500.t1.1,0.194020008518072 +Cre12.g500950.t1.2,0.9993188644999806 +Cre12.g501200.t1.2,0.9993188644999806 +Cre12.g503300.t1.2,0.9993188644999806 +Cre12.g503550.t1.2,0.9993188644999806 +Cre12.g504200.t1.2,0.9993188644999806 +Cre12.g505850.t1.2,0.04541911763276443 +Cre12.g507400.t1.2,0.9993188644999806 +Cre12.g507650.t2.1;Cre12.g507650.t1.2,0.9993188644999806 +Cre12.g508000.t1.1,0.9993188644999806 +Cre12.g508500.t1.2,0.9993188644999806 +Cre12.g508750.t1.2,0.9993188644999806 +Cre12.g509050.t1.1,0.75193949549862 +Cre12.g509650.t1.2,0.9993188644999806 +Cre12.g509750.t1.2,0.9993188644999806 +Cre12.g510050.t1.2,0.9993188644999806 +Cre12.g510400.t1.1,0.9993188644999806 +Cre12.g510450.t1.2,0.9993188644999806 +Cre12.g510650.t1.2,0.9993188644999806 +Cre12.g510800.t1.2,0.9993188644999806 +Cre12.g510850.t1.2,0.1766275154965851 +Cre12.g511850.t1.2,0.9993188644999806 +Cre12.g511900.t1.2,0.9993188644999806 +Cre12.g512000.t1.1,0.9993188644999806 +Cre12.g512600.t1.2,0.9993188644999806 +Cre12.g513150.t1.2;REV__Cre09.g395646.t1.2,0.9993188644999806 +Cre12.g513200.t1.2,0.9993188644999806 +Cre12.g513750.t1.1,0.9993188644999806 +Cre12.g513950.t1.2,0.9993188644999806 +Cre12.g514050.t1.2,0.9993188644999806 +Cre12.g514200.t1.2,0.9993188644999806 +Cre12.g514500.t1.2,0.9993188644999806 +Cre12.g514750.t1.2,0.9993188644999806 +Cre12.g514850.t1.2,0.038543373354825994 +Cre12.g515650.t1.2,0.9993188644999806 +Cre12.g515850.t1.2,0.9993188644999806 +Cre12.g516200.t1.2,0.859393862449768 +Cre12.g516450.t1.2,0.9993188644999806 +Cre12.g517100.t1.1,0.4972830561665652 +Cre12.g517150.t1.1,0.9993188644999806 +Cre12.g517400.t1.2,0.9993188644999806 +Cre12.g517900.t1.1;Cre12.g518000.t1.1;Cre12.g518000.t2.1,0.9993188644999806 +Cre12.g519100.t1.2,0.9993188644999806 +Cre12.g519180.t2.1;Cre12.g519180.t1.1;Cre12.g519180.t3.1;Cre12.g519180.t4.1,0.9993188644999806 +Cre12.g519300.t1.2,0.9993188644999806 +Cre12.g519350.t1.2,0.9993188644999806 +Cre12.g519900.t1.2,0.9993188644999806 +Cre12.g520500.t1.1,0.9993188644999806 +Cre12.g520600.t1.2,0.9993188644999806 +Cre12.g522350.t1.2,0.9993188644999806 +Cre12.g522450.t1.2,0.9993188644999806 +Cre12.g522600.t1.2,0.9993188644999806 +Cre12.g523150.t1.2,0.9993188644999806 +Cre12.g523300.t1.2,0.9993188644999806 +Cre12.g523850.t1.2,0.9993188644999806 +Cre12.g524400.t1.2,0.9993188644999806 +Cre12.g525200.t1.2,0.9993188644999806 +Cre12.g526800.t1.2,0.9993188644999806 +Cre12.g527550.t1.2,0.9993188644999806 +Cre12.g528000.t1.2,0.9993188644999806 +Cre12.g528700.t1.2,0.9993188644999806 +Cre12.g528750.t1.2,0.06317369299214892 +Cre12.g529400.t1.2,0.9993188644999806 +Cre12.g529651.t1.1,0.9993188644999806 +Cre12.g529950.t1.2,0.9993188644999806 +Cre12.g530300.t1.2,0.9993188644999806 +Cre12.g530650.t1.1;Cre12.g530650.t2.1;Cre12.g530600.t1.1,0.9993188644999806 +Cre12.g531550.t1.2,0.9993188644999806 +Cre12.g532550.t1.1,0.9993188644999806 +Cre12.g533351.t1.1,0.9993188644999806 +Cre12.g533550.t1.1,0.9993188644999806 +Cre12.g534450.t1.1,0.9365082204661731 +Cre12.g534600.t1.2,0.9993188644999806 +Cre12.g534700.t1.2,0.9993188644999806 +Cre12.g534800.t1.1,0.9993188644999806 +Cre12.g535851.t1.1,0.9993188644999806 +Cre12.g535950.t1.2,0.9993188644999806 +Cre12.g537100.t1.2,0.9993188644999806 +Cre12.g537200.t1.2,0.9993188644999806 +Cre12.g537450.t1.2,0.9993188644999806 +Cre12.g537581.t1.1,0.9993188644999806 +Cre12.g537800.t1.2,0.9993188644999806 +Cre12.g549550.t1.2;Cre12.g542250.t1.1,0.270643939853364 +Cre12.g543350.t3.1;Cre12.g543350.t2.1;Cre12.g543350.t1.1;Cre12.g543400.t1.2,0.9993188644999806 +Cre12.g544150.t1.2;Cre12.g544114.t1.1,0.9993188644999806 +Cre12.g546050.t1.2,0.9993188644999806 +Cre12.g546550.t1.1,0.9993188644999806 +Cre12.g546600.t1.1,0.9993188644999806 +Cre12.g548950.t1.2;Cre12.g548400.t1.2,0.0839067259874093 +Cre12.g549350.t1.2,0.9993188644999806 +Cre12.g549852.t1.1,0.9993188644999806 +Cre12.g550400.t1.2,0.9993188644999806 +Cre12.g550850.t1.2,0.9993188644999806 +Cre12.g551800.t1.2,0.9993188644999806 +Cre12.g551900.t1.2,0.9993188644999806 +Cre12.g551950.t1.2,0.9993188644999806 +Cre12.g552200.t1.2,0.9993188644999806 +Cre12.g553250.t1.2,0.9993188644999806 +Cre12.g554800.t1.2,0.9993188644999806 +Cre12.g555250.t1.2,0.9993188644999806 +Cre12.g556050.t1.2,0.9993188644999806 +Cre12.g556250.t1.2,0.9993188644999806 +Cre12.g557600.t1.1,0.9993188644999806 +Cre12.g558100.t1.2,0.9993188644999806 +Cre12.g558900.t1.2,0.9993188644999806 +Cre12.g559250.t1.2,0.9993188644999806 +Cre12.g560150.t1.2,0.9993188644999806 +Cre12.g560300.t3.1;Cre12.g560300.t2.1;Cre12.g560300.t1.2,0.9993188644999806 +Cre12.g560950.t1.2,0.9993188644999806 +Cre13.g562850.t1.2,0.9993188644999806 +Cre13.g564250.t1.2,0.9993188644999806 +Cre13.g565450.t1.2;Cre13.g565321.t1.1,0.9993188644999806 +Cre13.g565800.t1.2,0.4842454023554576 +Cre13.g565850.t1.1,0.9993188644999806 +Cre13.g566000.t1.2;REV__Cre01.g008500.t1.2,0.9811544970404044 +Cre13.g566050.t1.2,0.9993188644999806 +Cre13.g566650.t2.1;Cre13.g566650.t1.2,0.913003746791322 +Cre13.g566700.t1.1,0.9993188644999806 +Cre13.g567600.t1.2,0.9993188644999806 +Cre13.g567700.t1.2,0.9993188644999806 +Cre13.g567850.t1.2;REV__Cre03.g197900.t1.1,0.9993188644999806 +Cre13.g567950.t1.2,0.9993188644999806 +Cre13.g568650.t1.2,0.9993188644999806 +Cre13.g568800.t1.2,0.9993188644999806 +Cre13.g568900.t1.2,0.9993188644999806 +Cre13.g571500.t1.2,0.9993188644999806 +Cre13.g572900.t2.1;Cre13.g572900.t1.1,0.9993188644999806 +Cre13.g573250.t1.2,0.9993188644999806 +Cre13.g573351.t1.2,0.9993188644999806 +Cre13.g573400.t1.2,0.9993188644999806 +Cre13.g577100.t1.2,0.9993188644999806 +Cre13.g578451.t1.1,0.9993188644999806 +Cre13.g579550.t1.1,0.9993188644999806 +Cre13.g581600.t1.2,0.9993188644999806 +Cre13.g581650.t1.2,0.9993188644999806 +Cre13.g583550.t1.2,0.9993188644999806 +Cre13.g584850.t1.1,0.9993188644999806 +Cre13.g585150.t1.2,0.9993188644999806 +Cre13.g585900.t1.2,0.9993188644999806 +Cre13.g586300.t1.2,0.9993188644999806 +Cre13.g587050.t1.2,0.9993188644999806 +Cre13.g588100.t1.2,0.9993188644999806 +Cre13.g590650.t1.2,0.9993188644999806 +Cre13.g592200.t1.2,0.0008354558919287935 +Cre13.g592450.t1.2,0.9993188644999806 +Cre13.g602350.t1.2,0.9993188644999806 +Cre13.g602450.t1.2,0.9993188644999806 +Cre13.g602650.t1.2,0.8437959853692104 +Cre13.g603225.t1.1,0.9993188644999806 +Cre13.g603500.t1.2,0.9993188644999806 +Cre13.g603700.t1.2;Cre12.g542900.t1.1,0.9993188644999806 +Cre13.g603900.t1.2,0.9993188644999806 +Cre13.g604650.t2.1;Cre13.g604650.t1.2,0.9993188644999806 +Cre13.g605150.t1.2,0.9993188644999806 +Cre13.g605650.t1.2,0.9993188644999806 +Cre13.g607050.t1.2,0.9993188644999806 +Cre13.g608000.t1.2,0.9993188644999806 +Cre14.g610950.t1.2,0.9993188644999806 +Cre14.g612450.t1.2;REV__Cre05.g240650.t1.2,0.9993188644999806 +Cre14.g612800.t1.2,0.1695315198548906 +Cre14.g614300.t1.2,0.9993188644999806 +Cre14.g614900.t2.1;Cre14.g614900.t1.2,0.9993188644999806 +Cre14.g615950.t1.1,0.5048762089854979 +Cre14.g616100.t1.1,0.9993188644999806 +Cre14.g616600.t1.2,0.9993188644999806 +Cre14.g617450.t1.2,0.9993188644999806 +Cre14.g617826.t1.1,0.9993188644999806 +Cre14.g617900.t1.2,0.6573237559719884 +Cre14.g619100.t1.2,0.9993188644999806 +Cre14.g619133.t1.1,0.9993188644999806 +Cre14.g619166.t1.1,0.9993188644999806 +Cre14.g619550.t2.1;Cre14.g619550.t1.2,0.9993188644999806 +Cre14.g620600.t1.2;Cre14.g620702.t1.1,0.9993188644999806 +Cre14.g621450.t1.2,0.07609953892506027 +Cre14.g621650.t1.1,0.9993188644999806 +Cre14.g621751.t1.1,0.9993188644999806 +Cre14.g623000.t1.1,0.9993188644999806 +Cre14.g624201.t1.1,0.9993188644999806 +Cre14.g625400.t1.1,0.9993188644999806 +Cre14.g625750.t2.1;Cre14.g625750.t1.2,0.9993188644999806 +Cre14.g626900.t1.2,0.9993188644999806 +Cre14.g627850.t1.2,0.9993188644999806 +Cre14.g628100.t1.2,0.9993188644999806 +Cre14.g629550.t1.2,0.9993188644999806 +Cre14.g630100.t1.2,0.708823427875808 +Cre14.g630400.t1.2,0.9993188644999806 +Cre14.g630847.t1.1;Cre14.g630835.t1.1,0.9993188644999806 +Cre14.g632775.t1.1,0.9993188644999806 +Cre14.g632950.t1.2,0.9993188644999806 +Cre14.g633750.t1.1,0.9993188644999806 +Cre15.g635600.t1.2,0.9993188644999806 +Cre15.g635650.t2.1;Cre15.g635650.t1.2,0.008680189752543477 +Cre15.g635850.t2.1;Cre15.g635850.t1.2,0.9993188644999806 +Cre15.g636050.t1.2,0.9993188644999806 +Cre15.g638400.t1.2,0.9993188644999806 +Cre15.g638500.t1.2,0.9993188644999806 +Cre15.g639150.t2.1;Cre15.g639150.t1.1,0.9993188644999806 +Cre15.g643550.t1.2,0.9993188644999806 +Cre15.g643600.t1.2,0.9993188644999806 +Cre15.g644051.t1.1,0.9993188644999806 +Cre16.g650550.t2.1;Cre16.g650550.t1.2,0.9993188644999806 +Cre16.g651550.t1.2,0.9993188644999806 +Cre16.g651750.t1.2,0.9993188644999806 +Cre16.g651923.t1.2,0.9993188644999806 +Cre16.g652550.t1.2,0.9993188644999806 +Cre16.g654500.t1.1,0.9993188644999806 +Cre16.g655150.t1.2,0.9993188644999806 +Cre16.g656400.t1.2,0.9993188644999806 +Cre16.g658650.t1.1,0.9993188644999806 +Cre16.g659350.t1.2,0.9993188644999806 +Cre16.g659950.t1.1,0.17023124458861918 +Cre16.g660150.t1.2,0.9993188644999806 +Cre16.g661050.t1.2,0.9993188644999806 +Cre16.g661350.t1.2,0.9993188644999806 +Cre16.g661750.t1.2;Cre16.g661850.t1.1,0.9993188644999806 +Cre16.g662600.t1.2,0.9993188644999806 +Cre16.g662702.t1.1,0.9993188644999806 +Cre16.g663500.t1.2,0.9993188644999806 +Cre16.g663900.t1.2,0.9993188644999806 +Cre16.g664550.t1.2,0.9993188644999806 +Cre16.g665250.t1.2,0.9993188644999806 +Cre16.g669650.t1.2,0.9993188644999806 +Cre16.g670300.t2.1;Cre16.g670300.t1.2,0.9993188644999806 +Cre16.g671900.t1.1,0.9993188644999806 +Cre16.g672385.t1.1,0.9993188644999806 +Cre16.g672650.t1.2,0.9993188644999806 +Cre16.g672750.t1.2,0.9993188644999806 +Cre16.g672800.t1.2,0.9993188644999806 +Cre16.g673550.t1.1,0.9993188644999806 +Cre16.g673650.t1.1,0.9993188644999806 +Cre16.g673729.t1.1,0.9993188644999806 +Cre16.g673852.t1.1;Cre11.g476325.t1.1;REV__Cre12.g522700.t1.2,0.9993188644999806 +Cre16.g675550.t3.1;Cre16.g675550.t2.1;Cre16.g675550.t1.2,0.9993188644999806 +Cre16.g675637.t1.1,0.9993188644999806 +Cre16.g675650.t1.2,0.9993188644999806 +Cre16.g676197.t1.1,0.9993188644999806 +Cre16.g676314.t1.1,0.9993188644999806 +Cre16.g677000.t1.2,0.9993188644999806 +Cre16.g677026.t1.1,0.9993188644999806 +Cre16.g677450.t1.2,0.9993188644999806 +Cre16.g677500.t1.2,0.9993188644999806 +Cre16.g679500.t1.2,0.9993188644999806 +Cre16.g679600.t1.2,0.9993188644999806 +Cre16.g679800.t1.2;Cre16.g679750.t1.2,0.9993188644999806 +Cre16.g680000.t1.2,0.9993188644999806 +Cre16.g680700.t1.2,0.4945732646962974 +Cre16.g682725.t1.1,0.9993188644999806 +Cre16.g684150.t1.2,0.9993188644999806 +Cre16.g684300.t1.2,0.9993188644999806 +Cre16.g684350.t1.2;Cre16.g684550.t1.1,0.9993188644999806 +Cre16.g685400.t1.2,0.9993188644999806 +Cre16.g685550.t1.2,0.9993188644999806 +Cre16.g685901.t1.1,0.9993188644999806 +Cre16.g687300.t1.2,0.9993188644999806 +Cre16.g687900.t1.2,0.9993188644999806 +Cre16.g688050.t1.1,0.9993188644999806 +Cre16.g688550.t1.2,0.9993188644999806 +Cre16.g689087.t1.1,0.9993188644999806 +Cre16.g689871.t1.1,0.9993188644999806 +Cre16.g690431.t2.1;Cre16.g690431.t1.1,0.9993188644999806 +Cre16.g691000.t1.2,0.04532394591050837 +Cre16.g691800.t1.1,0.9993188644999806 +Cre16.g691850.t1.2,0.9993188644999806 +Cre16.g692901.t1.1,0.9993188644999806 +Cre16.g693600.t2.1;Cre16.g693600.t1.2,0.9993188644999806 +Cre16.g694850.t1.2,0.9993188644999806 +Cre16.g695050.t1.2,0.9993188644999806 +Cre16.g695100.t1.1,0.9993188644999806 +Cre16.g696000.t1.2,0.9993188644999806 +Cre17.g696250.t1.1;Cre17.g696250.t2.1,0.9993188644999806 +Cre17.g696850.t1.2,0.9993188644999806 +Cre17.g697450.t1.2,0.9993188644999806 +Cre17.g698000.t1.2,0.9993188644999806 +Cre17.g698450.t1.2,0.9993188644999806 +Cre17.g699000.t2.1;Cre17.g699000.t1.2,0.9993188644999806 +Cre17.g701200.t2.1;Cre17.g701200.t1.2,0.9993188644999806 +Cre17.g701500.t1.2,0.9993188644999806 +Cre17.g701650.t1.2,0.9993188644999806 +Cre17.g701700.t2.1;Cre17.g701700.t1.2,0.9993188644999806 +Cre17.g702200.t1.2,0.036602420368794165 +Cre17.g702750.t1.2,0.9993188644999806 +Cre17.g703700.t1.1,0.9993188644999806 +Cre17.g704850.t1.2,0.9993188644999806 +Cre17.g705000.t1.2,0.9993188644999806 +Cre17.g705400.t1.2,0.9993188644999806 +Cre17.g706600.t1.2,0.9993188644999806 +Cre17.g707900.t1.2,0.9993188644999806 +Cre17.g708300.t1.2,0.9993188644999806 +Cre17.g708750.t1.2,0.9993188644999806 +Cre17.g708800.t1.1,0.9993188644999806 +Cre17.g710150.t1.2,0.9993188644999806 +Cre17.g711650.t1.2,0.9993188644999806 +Cre17.g712100.t1.2,0.9993188644999806 +Cre17.g713200.t1.1;Cre17.g713350.t1.2,0.9993188644999806 +Cre17.g713450.t1.2;Cre17.g714050.t1.2;Cre17.g714550.t1.2,0.06314009528492193 +Cre17.g715250.t1.2,0.9993188644999806 +Cre17.g715500.t1.2,0.9993188644999806 +Cre17.g719000.t1.2,0.9993188644999806 +Cre17.g719900.t1.2,0.9993188644999806 +Cre17.g720050.t1.2,0.9993188644999806 +Cre17.g720250.t1.2,0.9993188644999806 +Cre17.g720450.t1.1,0.9993188644999806 +Cre17.g721300.t1.2,0.9993188644999806 +Cre17.g721500.t1.2,0.9993188644999806 +Cre17.g722150.t1.2,0.9993188644999806 +Cre17.g722750.t1.2,0.9993188644999806 +Cre17.g723250.t1.2,0.9993188644999806 +Cre17.g723650.t1.2,0.9993188644999806 +Cre17.g724200.t1.2,0.9993188644999806 +Cre17.g724300.t1.2,0.9993188644999806 +Cre17.g724350.t1.2,0.9993188644999806 +Cre17.g725350.t1.1;Cre17.g725350.t2.1,0.9993188644999806 +Cre17.g726750.t1.2,0.9993188644999806 +Cre17.g727950.t1.1,0.9993188644999806 +Cre17.g728800.t1.2,0.9993188644999806 +Cre17.g729150.t1.2,0.9993188644999806 +Cre17.g729800.t1.2,0.9993188644999806 +Cre17.g732300.t1.2,0.9993188644999806 +Cre17.g734100.t1.2,0.9993188644999806 +Cre17.g734200.t1.2,0.9993188644999806 +Cre17.g734300.t2.1;Cre17.g734300.t1.1,0.9993188644999806 +Cre17.g734400.t1.1,0.9993188644999806 +Cre17.g734450.t1.2,0.9993188644999806 +Cre17.g734500.t1.2,0.9993188644999806 +Cre17.g734516.t1.1,0.9993188644999806 +Cre17.g734548.t1.1;Cre10.g424750.t1.2,0.9993188644999806 +Cre17.g734612.t1.1,0.9993188644999806 +Cre17.g734900.t2.1;Cre17.g734900.t1.2,0.9993188644999806 +Cre17.g737250.t1.2,0.9993188644999806 +Cre17.g738300.t1.2,0.9993188644999806 +Cre17.g741000.t1.2,0.9993188644999806 +Cre17.g741450.t1.2,0.3380903993460096 +Cre17.g741850.t1.2,0.9993188644999806 +Cre17.g742200.t1.1,0.9993188644999806 +Cre17.g742300.t1.1,0.9993188644999806 +Cre17.g742450.t1.1,0.9993188644999806 +Cre17.g743897.t1.1,0.9993188644999806 +Cre17.g744147.t1.1,0.9993188644999806 +Cre17.g746997.t1.1;Cre16.g669150.t1.2;Cre16.g669125.t1.1,0.6344000363251011 +Cre18.g749447.t2.1;Cre18.g749447.t1.1,0.9993188644999806 +Cre18.g749497.t1.1;Cre18.g749647.t1.1,0.9993188644999806 +Cre18.g749847.t2.1;Cre18.g749847.t1.1,0.9993188644999806 +Cre18.g750047.t1.1,0.0036490885310087595 +Cre19.g750547.t4.1;Cre19.g750547.t3.1;Cre19.g750547.t2.1;Cre19.g750547.t1.1,0.9993188644999806 +Cre19.g751247.t2.1;Cre19.g751247.t1.1,0.9993188644999806 +Cre-2.g801495.t1.p1,0.9993188644999806 +Cre26.g756797.t1.1,0.9993188644999806 +Cre43.g760497.t1.1,0.9993188644999806 +Cre48.g761197.t1.1;Cre01.g050316.t2.1;Cre01.g050316.t1.1,0.9993188644999806 diff --git a/tests/FSharp.Stats.Tests/data/fwer_holm_results.csv b/tests/FSharp.Stats.Tests/data/fwer_holm_results.csv new file mode 100644 index 000000000..3c15c01ad --- /dev/null +++ b/tests/FSharp.Stats.Tests/data/fwer_holm_results.csv @@ -0,0 +1,1231 @@ +Key,pValues +CON__P00761,nan +CON__P07477,nan +CON__P15636,nan +CON__P35908v2;CON__P35908;CON__Q6IFZ6;CON__Q7Z794;CON__Q6NXH9,nan +Cre01.g000350.t1.1,1.0 +Cre01.g000900.t1.2,1.0 +Cre01.g001100.t1.2,1.0 +Cre01.g002300.t1.2,1.0 +Cre01.g002451.t1.1,1.0 +Cre01.g002500.t1.2,1.0 +Cre01.g004300.t1.2,1.0 +Cre01.g004350.t1.2,1.0 +Cre01.g004450.t1.2,0.5291382880932265 +Cre01.g004500.t1.2,1.0 +Cre01.g004900.t1.2,1.0 +Cre01.g004950.t1.1,1.0 +Cre01.g005050.t1.1,1.0 +Cre01.g005150.t1.1,1.0 +Cre01.g005850.t1.2,1.0 +Cre01.g006950.t2.1;Cre01.g006950.t1.1,1.0 +Cre01.g007700.t1.1,1.0 +Cre01.g010400.t1.2,1.0 +Cre01.g010900.t1.2,1.0 +Cre01.g011000.t1.2,0.5876655984410618 +Cre01.g012150.t1.2,1.0 +Cre01.g013700.t2.1;Cre01.g013700.t1.2,1.0 +Cre01.g014000.t1.2,1.0 +Cre01.g014050.t1.2,1.0 +Cre01.g014350.t1.2,1.0 +Cre01.g015000.t1.2,1.0 +Cre01.g015350.t1.1,1.0 +Cre01.g015600.t1.1,1.0 +Cre01.g016050.t1.2,1.0 +Cre01.g016300.t1.1,1.0 +Cre01.g016514.t1.1,1.0 +Cre01.g016528.t1.1,1.0 +Cre01.g016850.t1.2,1.0 +Cre01.g016900.t1.2,1.0 +Cre01.g017300.t1.2,1.0 +Cre01.g019250.t1.2,1.0 +Cre01.g020350.t1.2,1.0 +Cre01.g020918.t1.1,1.0 +Cre01.g021251.t1.1,1.0 +Cre01.g021600.t1.2,1.0 +Cre01.g023350.t1.1,0.05007875393687041 +Cre01.g025250.t1.1,1.0 +Cre01.g026450.t1.2,1.0 +Cre01.g026550.t1.1;REV__Cre13.g583972.t1.1,1.0 +Cre01.g026600.t1.2,1.0 +Cre01.g027000.t1.2,1.0 +Cre01.g027550.t1.1,1.0 +Cre01.g027800.t1.2,1.0 +Cre01.g028550.t1.2,1.0 +Cre01.g029300.t1.2,1.0 +Cre01.g029650.t1.1,1.0 +Cre01.g029750.t1.1,1.0 +Cre01.g030850.t1.2,1.0 +Cre01.g031100.t1.2,1.0 +Cre01.g032300.t1.2,1.0 +Cre01.g032650.t2.1;Cre01.g032650.t1.2,1.0 +Cre01.g033550.t1.2,0.010092379479815766 +Cre01.g034000.t1.2,1.0 +Cre01.g034400.t1.1,1.0 +Cre01.g035350.t1.2,1.0 +Cre01.g037850.t1.1,1.0 +Cre01.g038400.t1.2,0.6349108313510784 +Cre01.g038850.t1.1,1.0 +Cre01.g039250.t2.1;Cre01.g039250.t1.1,0.11681899128172679 +Cre01.g039300.t1.2,1.0 +Cre01.g040000.t1.2,1.0 +Cre01.g042750.t1.2,1.0 +Cre01.g042800.t1.2,1.0 +Cre01.g044800.t1.2,0.18065267165577942 +Cre01.g045550.t1.2,1.0 +Cre01.g046652.t1.1,1.0 +Cre01.g047700.t1.2,1.0 +Cre01.g047750.t1.2,1.0 +Cre01.g047800.t1.1,1.0 +Cre01.g048950.t1.2,1.0 +Cre01.g049000.t1.2,0.6349108313510784 +Cre01.g049500.t1.2,1.0 +Cre01.g050100.t1.2,1.0 +Cre01.g050850.t2.1;Cre01.g050850.t1.2,1.0 +Cre01.g050950.t1.2,1.0 +Cre01.g051500.t1.2,1.0 +Cre01.g051900.t1.2,1.0 +Cre01.g052100.t1.2,1.0 +Cre01.g052250.t1.2,1.0 +Cre01.g054150.t1.2,1.0 +Cre01.g054500.t1.2,0.1586892392675976 +Cre01.g054850.t1.2,1.0 +Cre01.g055408.t1.1,1.0 +Cre01.g055453.t1.1,1.0 +Cre01.g061077.t1.1,1.0 +Cre01.g066917.t1.1,1.0 +Cre01.g071662.t1.1,1.0 +Cre02.g073550.t1.2,1.0 +Cre02.g075700.t1.2,1.0 +Cre02.g076250.t1.1,1.0 +Cre02.g076300.t1.1,1.0 +Cre02.g076350.t1.2,1.0 +Cre02.g077100.t1.2,1.0 +Cre02.g077300.t1.2,1.0 +Cre02.g077350.t1.2,1.0 +Cre02.g077800.t1.2,1.0 +Cre02.g077850.t1.2,1.0 +Cre02.g078100.t1.1,1.0 +Cre02.g078300.t1.1,1.0 +Cre02.g079400.t1.2,1.0 +Cre02.g079550.t1.2,1.0 +Cre02.g079600.t1.2,1.0 +Cre02.g079700.t1.2,1.0 +Cre02.g079800.t1.2,1.0 +Cre02.g080200.t1.2,1.0 +Cre02.g080350.t1.1,1.0 +Cre02.g080650.t1.2,0.04454032259352383 +Cre02.g080700.t1.2,0.01951578593004504 +Cre02.g080900.t1.2,1.0 +Cre02.g081050.t1.2,0.0014468871498838354 +Cre02.g081250.t1.2,1.0 +Cre02.g082250.t1.1;Cre02.g082150.t1.1,1.0 +Cre02.g082500.t1.1,1.0 +Cre02.g082550.t1.2,1.0 +Cre02.g082852.t1.1;Cre02.g082750.t1.2,1.0 +Cre02.g083800.t2.1;Cre02.g083800.t1.2,1.0 +Cre02.g083950.t1.1,1.0 +Cre02.g084000.t1.2,1.0 +Cre02.g085450.t1.2,1.0 +Cre02.g085900.t1.2,1.0 +Cre02.g085950.t1.2,1.0 +Cre02.g087700.t1.2,1.0 +Cre02.g087950.t1.2,1.0 +Cre02.g088000.t1.2,1.0 +Cre02.g088200.t1.2,1.0 +Cre02.g088600.t1.2,1.0 +Cre02.g088850.t1.2,1.0 +Cre02.g088900.t1.2;Cre06.g278090.t1.1,1.0 +Cre02.g089100.t1.2,1.0 +Cre02.g090850.t1.1;REV__Cre12.g528450.t1.2,1.0 +Cre02.g091050.t1.2,1.0 +Cre02.g091100.t1.2,1.0 +Cre02.g091550.t1.2,1.0 +Cre02.g092400.t1.1,1.0 +Cre02.g092900.t1.2,1.0 +Cre02.g093450.t1.2,1.0 +Cre02.g093650.t1.2,1.0 +Cre02.g094100.t1.2,1.0 +Cre02.g095146.t1.1,1.0 +Cre02.g096150.t1.2,0.22271752893023758 +Cre02.g097400.t1.2,1.0 +Cre02.g097550.t1.2,1.0 +Cre02.g097650.t1.2,1.0 +Cre02.g097900.t1.2,1.0 +Cre02.g098250.t1.2,1.0 +Cre02.g098450.t1.2,1.0 +Cre02.g099150.t1.2,1.0 +Cre02.g099850.t1.1,1.0 +Cre02.g100200.t1.2,1.0 +Cre02.g101350.t1.2,1.0 +Cre02.g101400.t1.2,1.0 +Cre02.g102250.t1.2,1.0 +Cre02.g103550.t1.2,1.0 +Cre02.g104900.t1.2,0.120403237313319 +Cre02.g106600.t1.2;Cre17.g733650.t1.1,0.4882057725056157 +Cre02.g107300.t1.2,1.0 +Cre02.g108450.t1.2,1.0 +Cre02.g108850.t1.2,1.0 +Cre02.g109550.t1.2,1.0 +Cre02.g110350.t1.2;Cre12.g485200.t1.1;Cre11.g467595.t1.1,1.0 +Cre02.g111450.t1.2,1.0 +Cre02.g111700.t1.2,1.0 +Cre02.g113200.t1.1,1.0 +Cre02.g114450.t1.2,1.0 +Cre02.g114600.t1.2,1.0 +Cre02.g115200.t1.2,1.0 +Cre02.g116750.t2.1;Cre02.g116750.t1.1,1.0 +Cre02.g118500.t1.1,1.0 +Cre02.g118850.t1.2,1.0 +Cre02.g118950.t1.2,0.9733314015580261 +Cre02.g119550.t1.2,1.0 +Cre02.g120150.t1.2,1.0 +Cre02.g120250.t2.1;Cre02.g120250.t1.1;Cre02.g120200.t1.2,1.0 +Cre02.g141400.t1.2,1.0 +Cre02.g141500.t1.2,1.0 +Cre02.g142146.t1.1,1.0 +Cre02.g142206.t1.1,1.0 +Cre02.g142352.t1.1,1.0 +Cre12.g486250.t1.2;Cre02.g142687.t2.1;Cre02.g142687.t1.1,1.0 +Cre02.g142800.t1.2,1.0 +Cre02.g143000.t1.2,1.0 +Cre02.g143050.t1.2,1.0 +Cre02.g143200.t1.1;Cre12.g547000.t1.2,1.0 +Cre02.g143250.t1.2,1.0 +Cre02.g143307.t1.1,1.0 +Cre02.g143550.t1.2,1.0 +Cre02.g145800.t1.2,1.0 +Cre02.g146250.t1.2,1.0 +Cre02.g147302.t1.1,0.188932128818238 +Cre02.g147900.t4.1;Cre02.g147900.t2.1;Cre02.g147900.t1.1;Cre02.g147900.t3.1,1.0 +Cre03.g143887.t1.1,1.0 +Cre03.g144627.t1.1,1.0 +Cre03.g144807.t1.1;REV__Cre01.g020918.t1.1,1.0 +Cre03.g144847.t1.1,1.0 +Cre03.g144967.t1.1,1.0 +Cre03.g145507.t1.1,1.0 +Cre03.g145547.t1.1,1.0 +Cre03.g145647.t1.1,1.0 +Cre03.g145727.t1.1,1.0 +Cre03.g145747.t1.1,1.0 +Cre03.g145967.t1.1,1.0 +Cre03.g146167.t1.1,1.0 +Cre03.g146187.t1.1,1.0 +Cre03.g146247.t1.1,1.0 +Cre03.g146487.t1.1,1.0 +Cre03.g146527.t1.1,1.0 +Cre03.g149100.t1.2,1.0 +Cre03.g150300.t1.2,1.0 +Cre03.g152150.t1.2,1.0 +Cre03.g153450.t1.2,1.0 +Cre03.g154550.t1.1,1.0 +Cre03.g156050.t1.2,1.0 +Cre03.g156250.t1.2,1.0 +Cre03.g156600.t1.2,1.0 +Cre03.g156750.t1.2,1.0 +Cre03.g156900.t1.2,1.0 +Cre03.g156950.t1.1,1.0 +Cre03.g157700.t1.2,1.0 +Cre03.g158000.t1.2,1.0 +Cre03.g158750.t1.1,1.0 +Cre03.g158800.t3.1;Cre03.g158800.t2.1;Cre03.g158800.t1.1,0.5184298369121135 +Cre03.g158900.t1.2,1.0 +Cre03.g160500.t1.2,1.0 +Cre03.g161400.t1.2,1.0 +Cre03.g164000.t1.2,1.0 +Cre03.g164600.t1.2;Cre03.g165050.t1.2,0.0618285316541185 +Cre03.g164700.t1.2,1.0 +Cre03.g166050.t1.2,1.0 +Cre03.g168450.t1.2,1.0 +Cre03.g168700.t1.2,1.0 +Cre03.g169400.t1.2,1.0 +Cre03.g169850.t1.2,1.0 +Cre03.g169900.t1.2,1.0 +Cre03.g171100.t1.1,1.0 +Cre03.g171950.t1.1,1.0 +Cre03.g172000.t1.2,1.0 +Cre03.g172300.t1.2,1.0 +Cre03.g172850.t1.2,1.0 +Cre03.g172950.t1.2,1.0 +Cre03.g173350.t2.1;Cre03.g173350.t1.2,1.0 +Cre03.g175200.t1.2,1.0 +Cre03.g175400.t2.1,1.0 +Cre03.g176100.t1.2,1.0 +Cre03.g176250.t1.2,1.0 +Cre03.g177053.t1.1,1.0 +Cre03.g177200.t1.2,1.0 +Cre03.g178150.t1.1,1.0 +Cre03.g178250.t1.2,1.0 +Cre03.g178450.t1.2,0.016034797170714505 +Cre03.g180750.t1.2,6.922527196984164e-05 +Cre03.g180800.t1.1,1.0 +Cre03.g181300.t1.2,1.0 +Cre03.g181500.t1.2,1.0 +Cre03.g182050.t1.2,1.0 +Cre03.g182150.t1.2,0.3704075467177008 +Cre03.g182450.t1.2,1.0 +Cre03.g182500.t1.2,1.0 +Cre03.g182551.t1.2,0.07261771598620761 +Cre03.g182950.t1.2;Cre12.g520150.t1.1,1.0 +Cre03.g183100.t1.2,1.0 +Cre03.g183400.t1.1,1.0 +Cre03.g184550.t1.2,1.0 +Cre03.g185550.t1.2,1.0 +Cre03.g187450.t1.2,1.0 +Cre03.g188250.t1.2,1.0 +Cre03.g189250.t1.2,1.0 +Cre03.g189300.t1.1,0.5263674988725072 +Cre03.g189400.t1.2,1.0 +Cre03.g189500.t1.2,1.0 +Cre03.g189800.t1.2,1.0 +Cre03.g189950.t1.2,0.9690472855533361 +Cre03.g190100.t1.1,1.0 +Cre03.g190500.t1.2,1.0 +Cre04.g216850.t1.2;Cre03.g190950.t1.2,0.1796500458321692 +Cre03.g191050.t1.2,1.0 +Cre03.g193750.t1.1,1.0 +Cre03.g193800.t1.1,1.0 +Cre03.g193850.t1.2,1.0 +Cre03.g193950.t1.2,1.0 +Cre03.g194200.t1.2,1.0 +Cre03.g194350.t1.2,1.0 +Cre03.g194400.t1.2,1.0 +Cre03.g194850.t1.2,1.0 +Cre03.g195650.t1.2,1.0 +Cre03.g197500.t2.1;Cre03.g197500.t1.2,1.0 +Cre03.g198850.t1.2;Cre03.g198863.t1.1,1.0 +Cre03.g198950.t1.2,1.0 +Cre03.g199000.t1.2,1.0 +Cre03.g199423.t1.1,1.0 +Cre03.g199535.t1.1,1.0 +Cre03.g199647.t1.1,1.0 +Cre03.g199759.t2.1;Cre03.g199759.t1.1,1.0 +Cre03.g199900.t1.2,1.0 +Cre03.g199983.t1.1,1.0 +Cre03.g200250.t1.2,1.0 +Cre03.g202950.t1.1;Cre10.g419400.t1.1,1.0 +Cre03.g203450.t1.2,1.0 +Cre03.g203850.t1.2,1.0 +Cre03.g204250.t1.2,0.9306660967040172 +Cre03.g204350.t1.2,1.0 +Cre03.g204601.t1.1,1.0 +Cre03.g206600.t1.2,1.0 +Cre03.g207700.t1.1,1.0 +Cre03.g213537.t1.1,1.0 +Cre04.g213250.t1.2,1.0 +Cre04.g214150.t1.1,1.0 +Cre04.g214500.t1.1,1.0 +Cre04.g214501.t1.1,1.0 +Cre04.g214502.t1.1,1.0 +Cre04.g215150.t2.1;Cre04.g215150.t1.2,0.36332361135879837 +Cre04.g215850.t1.2;REV__Cre13.g576600.t1.2,1.0 +Cre04.g217550.t1.1,1.0 +Cre04.g217921.t1.1,1.0 +Cre04.g218100.t1.2,1.0 +Cre04.g218250.t1.2,1.0 +Cre04.g220200.t3.1;Cre04.g220200.t2.1;Cre04.g220200.t1.2,1.0 +Cre04.g220350.t2.1;Cre04.g220350.t1.2,1.0 +Cre04.g221400.t1.2,1.0 +Cre04.g222700.t1.2,0.020664635250159824 +Cre04.g223100.t1.2,1.0 +Cre04.g223850.t1.2,1.0 +Cre04.g226850.t1.2,1.0 +Cre04.g229300.t1.1,0.19067453301813908 +Cre04.g229700.t1.2,0.2247880975772978 +Cre04.g231026.t1.1,1.0 +Cre04.g231222.t2.1;Cre04.g231222.t1.1,0.029951665151665714 +Cre04.g232104.t1.1,0.155879556910526 +Cre05.g232002.t2.1;Cre05.g232002.t1.1,1.0 +Cre05.g232200.t1.2,1.0 +Cre05.g232750.t1.2,1.0 +Cre05.g233050.t1.2,1.0 +Cre05.g233303.t2.1;Cre05.g233303.t1.1,1.0 +Cre05.g233305.t2.1;Cre05.g233305.t1.1,1.0 +Cre05.g233800.t1.2,1.0 +Cre05.g233900.t1.2,1.0 +Cre05.g233950.t1.2,1.0 +Cre05.g234550.t2.1;Cre05.g234550.t1.2,1.0 +Cre05.g234637.t1.1,1.0 +Cre05.g234638.t1.1,1.0 +Cre05.g234639.t1.1,1.0 +Cre05.g234652.t1.1,1.0 +Cre05.g237400.t1.2,1.0 +Cre05.g237450.t1.2,1.0 +Cre05.g238322.t1.1,1.0 +Cre05.g238332.t1.1,1.0 +Cre05.g238687.t1.1,1.0 +Cre05.g240800.t1.2,1.0 +Cre05.g240850.t1.2,0.4824573142179865 +Cre05.g241450.t1.2,1.0 +Cre05.g241850.t1.2,1.0 +Cre05.g241950.t1.2,1.0 +Cre05.g242000.t1.2,1.0 +Cre05.g242300.t1.2,1.0 +Cre05.g242350.t1.2,1.0 +Cre05.g243050.t1.2,1.0 +Cre05.g243800.t1.2,1.0 +Cre05.g245158.t1.1;Cre24.g755097.t1.1,1.0 +Cre05.g245900.t1.2,1.0 +Cre05.g245950.t1.1,1.0 +Cre05.g247450.t1.2,1.0 +Cre05.g247600.t1.2,1.0 +Cre05.g247950.t1.2,1.0 +Cre05.g248450.t1.2;Cre05.g248400.t1.2,0.9806968773269642 +Cre06.g249250.t1.2,1.0 +Cre06.g250100.t1.2,0.04081067455631378 +Cre06.g250200.t1.2,1.0 +Cre06.g250250.t1.2,1.0 +Cre06.g250800.t2.1;Cre06.g250800.t1.1,1.0 +Cre06.g250902.t1.1,1.0 +Cre06.g251400.t1.2,1.0 +Cre06.g251500.t1.2,1.0 +Cre06.g252200.t1.2,1.0 +Cre06.g252450.t1.1,1.0 +Cre06.g252550.t1.1,1.0 +Cre06.g252650.t1.2,1.0 +Cre06.g253350.t1.2,1.0 +Cre06.g254400.t1.1,1.0 +Cre06.g255100.t1.1,1.0 +Cre06.g256250.t1.2,1.0 +Cre06.g257150.t1.2,1.0 +Cre06.g257500.t1.2,1.0 +Cre06.g257601.t1.2,0.1483918569864822 +Cre06.g257850.t1.2,1.0 +Cre06.g257950.t1.2,1.0 +Cre06.g258700.t1.1,1.0 +Cre06.g258733.t2.1;Cre06.g258733.t1.1,1.0 +Cre06.g258800.t1.1,1.0 +Cre06.g259100.t1.1,1.0 +Cre06.g259150.t1.2,1.0 +Cre06.g259401.t1.1,1.0 +Cre06.g259450.t1.2,1.0 +Cre06.g259850.t1.2,1.0 +Cre06.g259900.t1.2,0.008708700992422935 +Cre06.g261000.t1.2,1.0 +Cre06.g261450.t1.2,0.504155999283102 +Cre06.g261500.t1.2,0.9414868256903144 +Cre06.g261650.t1.1,1.0 +Cre06.g261800.t1.2,1.0 +Cre06.g262100.t1.1,1.0 +Cre06.g262700.t1.1,1.0 +Cre06.g263250.t1.1,1.0 +Cre06.g263300.t1.2,1.0 +Cre12.g498600.t1.2;Cre06.g263450.t1.2;Cre06.g263450.t2.1,1.0 +Cre06.g264200.t1.2,1.0 +Cre06.g264300.t1.2,1.0 +Cre06.g264350.t1.2,1.0 +Cre06.g264600.t1.2;Cre12.g504850.t1.2;Cre17.g714600.t1.2;Cre17.g714000.t1.2;Cre17.g713500.t1.2;Cre17.g711800.t1.2;Cre17.g710500.t1.2;Cre17.g709100.t1.2;Cre17.g708650.t1.2;Cre17.g708200.t1.2;Cre16.g650250.t1.2;Cre16.g649950.t1.2;Cre12.g506450.t1.2;Cre12.g506350.t1.2;Cre12.g505450.t1.2;Cre12.g504600.t1.2;Cre06.g276800.t1.2;Cre06.g276650.t1.2;Cre06.g275700.t1.2;Cre06.g274900.t1.2;Cre06.g274300.t1.2;Cre06.g274150.t1.2;Cre06.g273950.t1.2;Cre06.g271300.t1.2;Cre06.g268400.t1.2;Cre06.g268000.t1.2;Cre06.g266600.t1.2;Cre06.g265450.t1.2;Cre06.g265200.t1.2;Cre06.g265050.t1.2;Cre13.g570000.t1.2;Cre13.g570000.t2.1,1.0 +Cre06.g264650.t1.2;Cre12.g505500.t1.2;Cre06.g265000.t1.2;Cre17.g713950.t1.2;Cre17.g713550.t1.2;Cre17.g711850.t1.2;Cre17.g710550.t1.2;Cre17.g709050.t1.2;Cre17.g708700.t1.2;Cre17.g708150.t1.2;Cre16.g650300.t1.2;Cre16.g649900.t1.1;Cre16.g648500.t1.2;Cre13.g569950.t1.2;Cre12.g506500.t1.2;Cre12.g506300.t1.2;Cre12.g504800.t1.2;Cre17.g714650.t1.2;Cre12.g504650.t1.2;Cre06.g276850.t1.2;Cre06.g276600.t1.2;Cre06.g275750.t1.2;Cre06.g274850.t1.2;Cre06.g274350.t1.2;Cre06.g274101.t1.1;Cre06.g274000.t1.2;Cre06.g271250.t1.2;Cre06.g268350.t1.2;Cre06.g267950.t1.2;Cre06.g266650.t1.2;Cre06.g265500.t1.2;Cre06.g265250.t1.2;Cre02.g104800.t1.1,1.0 +Cre06.g264750.t1.2;Cre17.g708550.t1.2;Cre06.g264950.t1.2;Cre06.g265350.t1.2;Cre06.g266700.t1.2;Cre06.g268050.t1.2;Cre13.g591150.t1.2;Cre13.g590800.t1.2;Cre12.g506250.t1.2;Cre12.g505550.t1.2;Cre12.g504750.t1.2;Cre12.g504500.t1.2;Cre06.g268300.t1.2;Cre06.g274800.t1.2;Cre06.g273900.t1.2;Cre06.g271350.t1.2;Cre06.g275850.t1.2;Cre17.g714100.t1.2;Cre17.g713400.t1.2;Cre17.g711700.t1.2;Cre17.g710400.t1.2;Cre17.g709200.t1.2;Cre06.g276500.t1.2;Cre13.g570100.t1.2;Cre06.g274200.t1.2;Cre17.g714500.t1.2;Cre06.g276950.t1.2;Cre06.g278088.t1.1,1.0 +Cre06.g265800.t1.2,1.0 +Cre06.g268600.t1.2,1.0 +Cre06.g269050.t1.2,0.7315423597972802 +Cre06.g269450.t1.2,1.0 +Cre06.g269650.t1.2;Cre06.g269601.t1.1,1.0 +Cre06.g269950.t1.2,1.0 +Cre06.g272050.t1.2,1.0 +Cre06.g272650.t1.2,1.0 +Cre06.g272800.t1.2,1.0 +Cre06.g272850.t1.2;Cre10.g449700.t1.1,1.0 +Cre06.g272900.t1.2,1.0 +Cre06.g272950.t1.1,0.03894708556119043 +Cre06.g273000.t1.2,1.0 +Cre06.g273300.t1.2,1.0 +Cre06.g273550.t1.2,1.0 +Cre06.g273700.t1.2,1.0 +Cre06.g274650.t1.1,1.0 +Cre06.g275100.t1.2,0.5781754372814029 +Cre06.g278087.t1.1;Cre06.g278089.t1.1,1.0 +Cre06.g278125.t1.1,1.0 +Cre06.g278135.t1.1,1.0 +Cre06.g278148.t1.1,1.0 +Cre06.g278162.t1.1,1.0 +Cre06.g278163.t1.1,1.0 +Cre06.g278169.t1.1,1.0 +Cre06.g278170.t1.1,1.0 +Cre06.g278185.t1.1,0.2954390747875814 +Cre06.g278195.t1.1,1.0 +Cre06.g278210.t1.1,0.039827393261135643 +Cre06.g278211.t1.1,1.0 +Cre06.g278213.t1.1,1.0 +Cre06.g278221.t1.1,1.0 +Cre06.g278222.t1.1,1.0 +Cre06.g278239.t2.1;Cre06.g278239.t1.1,1.0 +Cre06.g278255.t1.1,1.0 +Cre06.g278256.t1.1,1.0 +Cre06.g278750.t1.2,1.0 +Cre06.g279150.t1.2,0.34621650587379 +Cre06.g279400.t1.2,1.0 +Cre06.g280650.t1.2,1.0 +Cre06.g280950.t1.2,1.0 +Cre06.g282000.t1.1;Cre06.g282000.t2.1,1.0 +Cre06.g282500.t1.2,1.0 +Cre06.g282800.t1.2,1.0 +Cre06.g283050.t1.2,1.0 +Cre06.g283950.t1.2,0.944077313516506 +Cre06.g284750.t1.2,1.0 +Cre06.g284900.t2.1;Cre06.g284900.t1.2,1.0 +Cre06.g285250.t1.2,1.0 +Cre06.g285401.t1.1,1.0 +Cre06.g286250.t1.2,1.0 +Cre06.g288700.t1.2,1.0 +Cre06.g289550.t1.2,1.0 +Cre06.g290950.t1.2,1.0 +Cre06.g292000.t1.1,0.2938991543998476 +Cre06.g293150.t1.2,1.0 +Cre06.g293582.t1.1,1.0 +Cre06.g293850.t1.2,1.0 +Cre06.g293950.t1.2,0.005647377312504531 +Cre06.g294650.t1.2,0.26325793063843106 +Cre06.g294750.t1.2,1.0 +Cre06.g294950.t1.1,1.0 +Cre06.g295450.t1.2,1.0 +Cre06.g296500.t1.2,1.0 +Cre06.g298100.t1.2,1.0 +Cre06.g298350.t1.2,1.0 +Cre06.g298650.t1.2,1.0 +Cre06.g299000.t1.2,1.0 +Cre06.g299650.t1.2,1.0 +Cre06.g300550.t1.2,1.0 +Cre06.g300700.t1.1,1.0 +Cre06.g300800.t1.2,1.0 +Cre06.g302700.t1.1,1.0 +Cre06.g304300.t1.2,1.0 +Cre06.g304350.t1.2,1.0 +Cre06.g304500.t1.2,1.0 +Cre06.g306300.t1.2,1.0 +Cre06.g306601.t1.1,1.0 +Cre06.g307450.t1.2,1.0 +Cre06.g307500.t1.1,0.2241659341184489 +Cre06.g308250.t1.2,0.1532882972455294 +Cre06.g308450.t1.2,1.0 +Cre06.g308500.t1.2,1.0 +Cre06.g308850.t1.2,1.0 +Cre06.g308950.t1.2,1.0 +Cre06.g309100.t1.2,1.0 +Cre06.g310750.t1.2,1.0 +Cre06.g311900.t1.2,1.0 +Cre07.g313700.t1.1,1.0 +Cre07.g314150.t1.2,1.0 +Cre07.g316000.t1.2,1.0 +Cre07.g318450.t1.2,1.0 +Cre07.g318750.t1.2,1.0 +Cre07.g324200.t1.2;REV__Cre13.g602800.t1.1,0.4064780458042206 +Cre07.g325400.t1.2,1.0 +Cre07.g325500.t1.1,1.0 +Cre07.g325734.t1.1,1.0 +Cre07.g325736.t1.1,0.6065691546836469 +Cre07.g325746.t1.1,1.0 +Cre07.g325755.t1.1,0.07422203585299571 +Cre07.g326800.t1.1,1.0 +Cre07.g326950.t1.1,1.0 +Cre07.g327350.t1.2,1.0 +Cre07.g327400.t1.1,1.0 +Cre07.g328150.t2.1;Cre07.g328150.t1.1,1.0 +Cre07.g328200.t1.2,1.0 +Cre07.g328900.t1.2,1.0 +Cre07.g329700.t1.2,1.0 +Cre07.g330250.t1.2,1.0 +Cre07.g331500.t1.1,1.0 +Cre07.g331550.t1.2,1.0 +Cre07.g331900.t1.2,1.0 +Cre07.g332450.t1.2,0.6520110519748924 +Cre07.g334900.t1.1,1.0 +Cre07.g335400.t1.1,1.0 +Cre07.g336450.t1.2,1.0 +Cre07.g336950.t1.1,0.04318942430152387 +Cre07.g337650.t1.2,1.0 +Cre07.g338050.t1.2,1.0 +Cre07.g338451.t1.1,0.33247964172642447 +Cre07.g339150.t1.1,0.1259389880442656 +Cre07.g339700.t1.2,1.0 +Cre07.g340200.t1.1,1.0 +Cre07.g340350.t1.1,1.0 +Cre07.g341550.t1.2,1.0 +Cre07.g341600.t2.1,0.01640041110839864 +Cre07.g342150.t1.2,1.0 +Cre07.g342250.t1.2,1.0 +Cre07.g343700.t1.2;Cre07.g343433.t1.1,1.0 +Cre07.g344400.t1.2,1.0 +Cre07.g344550.t1.2,1.0 +Cre07.g344950.t1.2,1.0 +Cre07.g346050.t2.1;Cre07.g346050.t1.2,1.0 +Cre07.g347150.t1.2,1.0 +Cre07.g349350.t1.2,1.0 +Cre07.g350500.t1.2,0.17593493569192417 +Cre07.g352650.t1.2,1.0 +Cre07.g352850.t1.2,1.0 +Cre07.g353450.t1.2,1.0 +Cre07.g356350.t1.1,1.0 +Cre07.g356400.t1.2,1.0 +Cre07.g356600.t1.2,1.0 +Cre07.g357200.t1.2,1.0 +Cre07.g357350.t1.2,1.0 +Cre07.g357850.t1.2,1.0 +Cre08.g358526.t1.1,0.33247964172642447 +Cre08.g358562.t1.1,0.09430296377528288 +Cre08.g358580.t1.1,1.0 +Cre08.g359350.t1.2,1.0 +Cre08.g359750.t2.1;Cre08.g359750.t1.2,0.5971147249485951 +Cre08.g360900.t1.2,1.0 +Cre08.g361850.t1.2,1.0 +Cre08.g362450.t1.2,1.0 +Cre08.g364650.t1.1,1.0 +Cre08.g364800.t1.2,0.6377505488597608 +Cre08.g365400.t1.2,1.0 +Cre08.g365632.t1.1,1.0 +Cre08.g365692.t1.1,1.0 +Cre08.g366400.t2.1;Cre08.g366400.t1.2,1.0 +Cre08.g367500.t1.1;Cre08.g367400.t1.1,0.7119842539865409 +Cre08.g368400.t1.2,1.0 +Cre08.g368900.t2.1;Cre08.g368900.t1.2,1.0 +Cre08.g368950.t1.2,1.0 +Cre08.g370450.t1.2,1.0 +Cre08.g370650.t1.2,0.9038374329343172 +Cre08.g372100.t1.2,0.012422753187091976 +Cre08.g372450.t1.2,1.0 +Cre08.g372950.t1.2,1.0 +Cre08.g373100.t1.1,1.0 +Cre08.g375200.t2.1;Cre08.g375200.t1.2,1.0 +Cre08.g376100.t1.2,1.0 +Cre08.g378000.t1.2,1.0 +Cre08.g378050.t1.2,1.0 +Cre08.g378850.t1.2,1.0 +Cre08.g379200.t1.1;Cre08.g379175.t1.1,1.0 +Cre08.g380201.t1.1,1.0 +Cre08.g382500.t1.2,1.0 +Cre08.g384000.t1.1,1.0 +Cre09.g386200.t1.1,1.0 +Cre09.g386400.t1.2,1.0 +Cre09.g386650.t2.1;Cre09.g386650.t1.2,1.0 +Cre09.g386735.t1.1,1.0 +Cre09.g386750.t1.2,0.1571270661439956 +Cre09.g386758.t1.1,1.0 +Cre09.g387171.t2.1;Cre09.g387171.t1.1,1.0 +Cre09.g387393.t1.1,1.0 +Cre09.g387726.t1.1,1.0 +Cre09.g387800.t1.2,1.0 +Cre09.g387875.t1.1,1.0 +Cre09.g388200.t1.1,1.0 +Cre09.g388467.t1.1,1.0 +Cre09.g388726.t1.1;Cre09.g388726.t2.1;Cre09.g388726.t3.1;Cre09.g388726.t4.1,0.1504500367476816 +Cre09.g389430.t1.1,1.0 +Cre09.g389689.t1.1,1.0 +Cre09.g390050.t1.2,1.0 +Cre09.g390763.t1.1,1.0 +Cre09.g391023.t1.1,1.0 +Cre09.g391097.t2.1;Cre09.g391097.t1.1,1.0 +Cre09.g391900.t1.1,1.0 +Cre09.g392350.t2.1;Cre09.g392350.t1.2,0.07708311087015218 +Cre09.g392500.t1.2,1.0 +Cre09.g393150.t1.2,0.21549544376965798 +Cre09.g393173.t1.1,1.0 +Cre09.g393200.t1.2,0.9134652306565516 +Cre09.g393358.t1.1,1.0 +Cre09.g393543.t1.1,1.0 +Cre09.g393765.t1.1,1.0 +Cre09.g394102.t1.1,1.0 +Cre09.g394200.t1.1,1.0 +Cre09.g394436.t1.1,1.0 +Cre09.g394450.t1.2,0.850554371360229 +Cre09.g394547.t1.1,1.0 +Cre09.g394550.t1.2,1.0 +Cre09.g394750.t1.2,1.0 +Cre09.g394850.t1.2,1.0 +Cre09.g395350.t1.1,1.0 +Cre09.g396213.t1.1,1.0 +Cre09.g396252.t1.1,1.0 +Cre09.g396300.t1.2,1.0 +Cre09.g396400.t1.2;Cre01.g007051.t1.2;Cre11.g467567.t1.1,1.0 +Cre09.g396650.t1.2,1.0 +Cre09.g397200.t1.2,1.0 +Cre09.g397549.t1.1,1.0 +Cre09.g397697.t1.1,1.0 +Cre09.g398067.t1.1,0.04689792257178644 +Cre09.g398900.t1.1,1.0 +Cre09.g400050.t1.1,1.0 +Cre09.g400650.t1.2,1.0 +Cre09.g401515.t1.1,1.0 +Cre09.g401886.t1.1,1.0 +Cre09.g401900.t1.2,1.0 +Cre09.g402300.t1.2,1.0 +Cre09.g402450.t1.2,1.0 +Cre09.g402500.t1.2,1.0 +Cre09.g402775.t1.1,1.0 +Cre09.g402950.t1.1,1.0 +Cre09.g403800.t1.2,1.0 +Cre09.g403900.t1.2,1.0 +Cre09.g404000.t1.1,1.0 +Cre09.g405050.t1.2,1.0 +Cre09.g405800.t1.2,1.0 +Cre09.g405850.t1.1,1.0 +Cre09.g406200.t1.2,1.0 +Cre09.g406600.t1.1,0.007461884476826212 +Cre09.g406983.t1.1,1.0 +Cre09.g407600.t1.2,1.0 +Cre09.g408200.t1.2,1.0 +Cre09.g409100.t1.2,1.0 +Cre09.g409350.t1.2,1.0 +Cre09.g409500.t1.2,1.0 +Cre09.g410650.t1.2;Cre09.g410650.t2.1;Cre09.g410650.t3.1,1.0 +Cre09.g410700.t1.2,1.0 +Cre09.g411100.t2.1;Cre09.g411100.t1.2,0.1757447572162625 +Cre09.g411200.t1.2,1.0 +Cre09.g411900.t1.1,1.0 +Cre09.g412100.t1.2,1.0 +Cre09.g414050.t1.2,1.0 +Cre09.g415550.t1.2,1.0 +Cre09.g415700.t1.2,1.0 +Cre09.g415800.t1.2,1.0 +Cre09.g415850.t1.2,1.0 +Cre09.g415950.t1.2,1.0 +Cre09.g416050.t1.2,1.0 +Cre09.g416150.t1.2,1.0 +Cre09.g416350.t1.2,1.0 +Cre09.g416750.t1.2,1.0 +Cre09.g416850.t1.2,1.0 +Cre09.g417150.t1.2,1.0 +Cre09.g417200.t1.2,1.0 +Cre-1.g000035.t1.p1,1.0 +Cre-1.g2716952.t1.p1,1.0 +Cre-1.g2716955.t1.p1,1.0 +Cre-1.g2716958.t1.p1,1.0 +Cre-1.g2716959.t1.p1,1.0 +Cre-1.g2716961.t1.p1,1.0 +Cre-1.g2716963.t1.p1,0.6377505488597608 +Cre-1.g2716972.t1.p1,1.0 +Cre-1.g2716979.t1.p1,1.0 +Cre-1.g2716983.t1.p1,0.04192120256676257 +Cre-1.g2716987.t1.p1,1.0 +Cre-1.g2716989.t1.p1,1.0 +Cre-1.g2716990.t1.p1,1.0 +Cre-1.g2716994.t1.p1,1.0 +Cre-1.g2716997.t1.p1,1.0 +Cre-1.g2717000.t1.p1,1.0 +Cre-1.g2717002.t1.p1,1.0 +Cre-1.g2717005.t1.p1;REV__Cre24.g755297.t1.1;Cre01.g027764.t1.2;REV__Cre07.g352400.t1.2,1.0 +Cre-1.g2717006.t1.p1,1.0 +Cre-1.g2717008.t1.p1,1.0 +Cre-1.g2717009.t1.p1,1.0 +Cre-1.g2717010.t1.p1,1.0 +Cre-1.g2717015.t1.p1,1.0 +Cre-1.g2717017.t1.p1,1.0 +Cre-1.g2717021.t1.p1,1.0 +Cre-1.g2717030.t1.p1,1.0 +Cre-1.g2717034.t1.p1,0.04413314008357516 +Cre-1.g2717038.t1.p1,1.0 +Cre-1.g2717040.t1.p1,1.0 +Cre-1.g2717041.t1.p1,0.11003667463466393 +Cre-1.g2717044.t1.p1,1.0 +Cre-1.g2717046.t1.p1,1.0 +Cre-1.g2717054.t1.p1,1.0 +Cre-1.g2717055.t1.p1,1.0 +Cre-1.g2717056.t1.p1,1.0 +Cre-1.g2717057.t1.p1,1.0 +Cre-1.g2717058.t1.p1,0.8597176126185088 +Cre-1.g2717059.t1.p1,0.5195363300062164 +Cre10.g417700.t1.2,1.0 +Cre10.g418100.t1.1,1.0 +Cre10.g418450.t1.2,1.0 +Cre10.g419950.t1.1,1.0 +Cre10.g420350.t1.2,1.0 +Cre10.g420750.t1.2,1.0 +Cre10.g421600.t1.2,1.0 +Cre10.g422300.t1.2,0.5957035459575027 +Cre10.g422600.t1.1,1.0 +Cre10.g423250.t1.2,1.0 +Cre10.g423500.t1.2,1.0 +Cre10.g423650.t1.2,0.21251489662998319 +Cre10.g424100.t1.2,1.0 +Cre10.g424450.t1.2,1.0 +Cre10.g425900.t1.2,1.0 +Cre10.g425950.t1.2,1.0 +Cre10.g427250.t1.2,1.0 +Cre10.g427700.t1.2,0.2924747171696484 +Cre10.g428200.t1.2,1.0 +Cre10.g428750.t1.1,1.0 +Cre10.g429100.t1.2,1.0 +Cre10.g430000.t1.1,1.0 +Cre10.g430150.t1.2,1.0 +Cre10.g430501.t1.1;Cre09.g388430.t1.1;Cre10.g449200.t1.1,0.336271118666643 +Cre10.g432800.t1.2,1.0 +Cre10.g433000.t1.1,1.0 +Cre10.g433600.t1.2,1.0 +Cre10.g433950.t1.1,1.0 +Cre10.g434200.t1.1,1.0 +Cre10.g434450.t1.2,1.0 +Cre10.g434750.t1.2,1.0 +Cre10.g435300.t2.1;Cre10.g435300.t1.2,1.0 +Cre10.g435800.t1.2,1.0 +Cre10.g435850.t1.2,1.0 +Cre10.g436050.t1.2,0.7089224919646874 +Cre10.g436350.t1.1,1.0 +Cre10.g436500.t1.2,1.0 +Cre10.g436550.t1.2,1.0 +Cre10.g439100.t1.2,1.0 +Cre10.g439150.t1.2,1.0 +Cre10.g439400.t1.1,1.0 +Cre10.g439850.t1.2,1.0 +Cre10.g439900.t1.2;Cre18.g749547.t1.1,1.0 +Cre10.g440050.t1.2;REV__Cre10.g463700.t1.1,1.0 +Cre10.g440450.t1.2,1.0 +Cre10.g441200.t1.2,1.0 +Cre10.g441400.t1.2,1.0 +Cre10.g442700.t1.2,1.0 +Cre10.g443250.t1.2,1.0 +Cre10.g444700.t1.1,1.0 +Cre10.g444800.t1.2,1.0 +Cre10.g446550.t1.2,1.0 +Cre10.g447100.t1.2,1.0 +Cre10.g449550.t1.2,1.0 +Cre10.g450400.t1.2,1.0 +Cre10.g451900.t1.1,1.0 +Cre10.g451950.t1.2,1.0 +Cre10.g452050.t1.2,1.0 +Cre10.g452450.t1.2,1.0 +Cre10.g452800.t1.2,1.0 +Cre10.g456000.t1.2,1.0 +Cre10.g456050.t2.1;Cre10.g456050.t1.2,1.0 +Cre10.g456200.t1.2,1.0 +Cre10.g456750.t1.2,1.0 +Cre10.g457700.t1.2,1.0 +Cre10.g458550.t1.2,1.0 +Cre10.g459200.t1.2,1.0 +Cre10.g459250.t1.2,1.0 +Cre10.g461050.t1.2,1.0 +Cre10.g461250.t1.1,1.0 +Cre10.g462250.t1.2,1.0 +Cre10.g465550.t1.1,1.0 +Cre11.g467350.t1.2,1.0 +Cre11.g467400.t1.2,1.0 +Cre11.g467535.t1.1;Cre16.g658850.t1.1,1.0 +Cre11.g467547.t1.1,1.0 +Cre11.g467550.t1.2,1.0 +Cre11.g467569.t1.1,1.0 +Cre11.g467573.t1.1,1.0 +Cre11.g467578.t1.1,0.7501527658478415 +Cre11.g467617.t1.1,1.0 +Cre11.g467640.t1.1,1.0 +Cre11.g467668.t1.1,1.0 +Cre11.g467689.t1.1,1.0 +Cre11.g467699.t1.1,1.0 +Cre11.g467700.t1.1,1.0 +Cre11.g467707.t1.1,1.0 +Cre11.g467723.t2.1;Cre11.g467723.t1.1,1.0 +Cre11.g467767.t1.1,1.0 +Cre11.g467770.t1.1,1.0 +Cre11.g467773.t1.1,1.0 +Cre11.g467778.t1.1,1.0 +Cre11.g468300.t1.2,1.0 +Cre11.g468359.t1.1,1.0 +Cre11.g468450.t1.2,1.0 +Cre11.g468550.t1.2,1.0 +Cre11.g468750.t1.2,1.0 +Cre11.g468950.t1.2,1.0 +Cre11.g469150.t1.2,1.0 +Cre11.g476550.t1.2,0.41397970800958617 +Cre11.g476750.t1.2,1.0 +Cre11.g477300.t1.1,1.0 +Cre11.g477850.t1.1,0.3419954982806312 +Cre11.g477950.t1.1,1.0 +Cre11.g478156.t2.1;Cre11.g478156.t1.1,1.0 +Cre11.g478700.t1.2,1.0 +Cre11.g479050.t1.2,1.0 +Cre11.g479250.t1.2,1.0 +Cre11.g479500.t1.2,0.30169700902912194 +Cre11.g479750.t1.2,1.0 +Cre11.g480150.t1.2,0.20781060276933208 +Cre11.g481126.t1.1,1.0 +Cre11.g481450.t1.2,1.0 +Cre11.g481500.t1.2,1.0 +Cre12.g483650.t1.2,1.0 +Cre12.g483700.t2.1;Cre12.g483700.t1.2,0.7081528813483741 +Cre12.g483850.t1.2;REV__Cre12.g542100.t1.2;REV__Cre12.g541800.t1.2,1.0 +Cre12.g483950.t1.2,1.0 +Cre12.g484000.t1.2,1.0 +Cre12.g484050.t1.2,1.0 +Cre12.g484200.t1.2,1.0 +Cre12.g485150.t1.2,1.0 +Cre12.g485800.t1.2,1.0 +Cre12.g486100.t1.2,1.0 +Cre12.g486300.t1.2,1.0 +Cre12.g487100.t1.2,1.0 +Cre12.g488850.t2.1;Cre12.g488850.t1.1,1.0 +Cre12.g489153.t1.1,1.0 +Cre12.g489700.t1.2,1.0 +Cre12.g490000.t1.2,1.0 +Cre12.g490350.t1.1,1.0 +Cre12.g490500.t1.2,1.0 +Cre12.g492300.t1.2,1.0 +Cre12.g492600.t1.2,1.0 +Cre12.g492650.t1.2,1.0 +Cre12.g493250.t1.2,1.0 +Cre12.g493950.t1.2,1.0 +Cre12.g494050.t1.2,1.0 +Cre12.g494100.t1.1,1.0 +Cre12.g494450.t1.2,1.0 +Cre12.g494750.t1.2,1.0 +Cre12.g494850.t1.2,1.0 +Cre12.g495650.t1.2,1.0 +Cre12.g495850.t1.2,1.0 +Cre12.g495951.t2.1;Cre12.g495951.t1.1,1.0 +Cre12.g496750.t1.2,1.0 +Cre12.g497300.t2.1;Cre12.g497300.t1.2,0.02329849828379049 +Cre12.g497700.t1.2,1.0 +Cre12.g498100.t1.2,1.0 +Cre12.g498250.t1.2,1.0 +Cre12.g498450.t1.2,1.0 +Cre12.g498550.t1.1,0.09047715620234587 +Cre12.g498900.t1.2,1.0 +Cre12.g498950.t1.2,1.0 +Cre12.g499800.t1.2,1.0 +Cre12.g500150.t1.1,1.0 +Cre12.g500500.t2.1;Cre12.g500500.t1.1,0.194020008518072 +Cre12.g500950.t1.2,1.0 +Cre12.g501200.t1.2,1.0 +Cre12.g503300.t1.2,1.0 +Cre12.g503550.t1.2,1.0 +Cre12.g504200.t1.2,1.0 +Cre12.g505850.t1.2,0.04541911763276443 +Cre12.g507400.t1.2,1.0 +Cre12.g507650.t2.1;Cre12.g507650.t1.2,1.0 +Cre12.g508000.t1.1,1.0 +Cre12.g508500.t1.2,1.0 +Cre12.g508750.t1.2,1.0 +Cre12.g509050.t1.1,0.75193949549862 +Cre12.g509650.t1.2,1.0 +Cre12.g509750.t1.2,1.0 +Cre12.g510050.t1.2,1.0 +Cre12.g510400.t1.1,1.0 +Cre12.g510450.t1.2,1.0 +Cre12.g510650.t1.2,1.0 +Cre12.g510800.t1.2,1.0 +Cre12.g510850.t1.2,0.1766275154965851 +Cre12.g511850.t1.2,1.0 +Cre12.g511900.t1.2,1.0 +Cre12.g512000.t1.1,1.0 +Cre12.g512600.t1.2,1.0 +Cre12.g513150.t1.2;REV__Cre09.g395646.t1.2,1.0 +Cre12.g513200.t1.2,1.0 +Cre12.g513750.t1.1,1.0 +Cre12.g513950.t1.2,1.0 +Cre12.g514050.t1.2,1.0 +Cre12.g514200.t1.2,1.0 +Cre12.g514500.t1.2,1.0 +Cre12.g514750.t1.2,1.0 +Cre12.g514850.t1.2,0.038543373354825994 +Cre12.g515650.t1.2,1.0 +Cre12.g515850.t1.2,1.0 +Cre12.g516200.t1.2,0.8597176126185088 +Cre12.g516450.t1.2,1.0 +Cre12.g517100.t1.1,0.4972830561665652 +Cre12.g517150.t1.1,1.0 +Cre12.g517400.t1.2,1.0 +Cre12.g517900.t1.1;Cre12.g518000.t1.1;Cre12.g518000.t2.1,1.0 +Cre12.g519100.t1.2,1.0 +Cre12.g519180.t2.1;Cre12.g519180.t1.1;Cre12.g519180.t3.1;Cre12.g519180.t4.1,1.0 +Cre12.g519300.t1.2,1.0 +Cre12.g519350.t1.2,1.0 +Cre12.g519900.t1.2,1.0 +Cre12.g520500.t1.1,1.0 +Cre12.g520600.t1.2,1.0 +Cre12.g522350.t1.2,1.0 +Cre12.g522450.t1.2,1.0 +Cre12.g522600.t1.2,1.0 +Cre12.g523150.t1.2,1.0 +Cre12.g523300.t1.2,1.0 +Cre12.g523850.t1.2,1.0 +Cre12.g524400.t1.2,1.0 +Cre12.g525200.t1.2,1.0 +Cre12.g526800.t1.2,1.0 +Cre12.g527550.t1.2,1.0 +Cre12.g528000.t1.2,1.0 +Cre12.g528700.t1.2,1.0 +Cre12.g528750.t1.2,0.06317369299214892 +Cre12.g529400.t1.2,1.0 +Cre12.g529651.t1.1,1.0 +Cre12.g529950.t1.2,1.0 +Cre12.g530300.t1.2,1.0 +Cre12.g530650.t1.1;Cre12.g530650.t2.1;Cre12.g530600.t1.1,1.0 +Cre12.g531550.t1.2,1.0 +Cre12.g532550.t1.1,1.0 +Cre12.g533351.t1.1,1.0 +Cre12.g533550.t1.1,1.0 +Cre12.g534450.t1.1,0.9365082204661731 +Cre12.g534600.t1.2,1.0 +Cre12.g534700.t1.2,1.0 +Cre12.g534800.t1.1,1.0 +Cre12.g535851.t1.1,1.0 +Cre12.g535950.t1.2,1.0 +Cre12.g537100.t1.2,1.0 +Cre12.g537200.t1.2,1.0 +Cre12.g537450.t1.2,1.0 +Cre12.g537581.t1.1,1.0 +Cre12.g537800.t1.2,1.0 +Cre12.g549550.t1.2;Cre12.g542250.t1.1,0.270643939853364 +Cre12.g543350.t3.1;Cre12.g543350.t2.1;Cre12.g543350.t1.1;Cre12.g543400.t1.2,1.0 +Cre12.g544150.t1.2;Cre12.g544114.t1.1,1.0 +Cre12.g546050.t1.2,1.0 +Cre12.g546550.t1.1,1.0 +Cre12.g546600.t1.1,1.0 +Cre12.g548950.t1.2;Cre12.g548400.t1.2,0.0839067259874093 +Cre12.g549350.t1.2,1.0 +Cre12.g549852.t1.1,1.0 +Cre12.g550400.t1.2,1.0 +Cre12.g550850.t1.2,1.0 +Cre12.g551800.t1.2,1.0 +Cre12.g551900.t1.2,1.0 +Cre12.g551950.t1.2,1.0 +Cre12.g552200.t1.2,1.0 +Cre12.g553250.t1.2,1.0 +Cre12.g554800.t1.2,1.0 +Cre12.g555250.t1.2,1.0 +Cre12.g556050.t1.2,1.0 +Cre12.g556250.t1.2,1.0 +Cre12.g557600.t1.1,1.0 +Cre12.g558100.t1.2,1.0 +Cre12.g558900.t1.2,1.0 +Cre12.g559250.t1.2,1.0 +Cre12.g560150.t1.2,1.0 +Cre12.g560300.t3.1;Cre12.g560300.t2.1;Cre12.g560300.t1.2,1.0 +Cre12.g560950.t1.2,1.0 +Cre13.g562850.t1.2,1.0 +Cre13.g564250.t1.2,1.0 +Cre13.g565450.t1.2;Cre13.g565321.t1.1,1.0 +Cre13.g565800.t1.2,0.4842454023554576 +Cre13.g565850.t1.1,1.0 +Cre13.g566000.t1.2;REV__Cre01.g008500.t1.2,0.9811544970404044 +Cre13.g566050.t1.2,1.0 +Cre13.g566650.t2.1;Cre13.g566650.t1.2,0.913003746791322 +Cre13.g566700.t1.1,1.0 +Cre13.g567600.t1.2,1.0 +Cre13.g567700.t1.2,1.0 +Cre13.g567850.t1.2;REV__Cre03.g197900.t1.1,1.0 +Cre13.g567950.t1.2,1.0 +Cre13.g568650.t1.2,1.0 +Cre13.g568800.t1.2,1.0 +Cre13.g568900.t1.2,1.0 +Cre13.g571500.t1.2,1.0 +Cre13.g572900.t2.1;Cre13.g572900.t1.1,1.0 +Cre13.g573250.t1.2,1.0 +Cre13.g573351.t1.2,1.0 +Cre13.g573400.t1.2,1.0 +Cre13.g577100.t1.2,1.0 +Cre13.g578451.t1.1,1.0 +Cre13.g579550.t1.1,1.0 +Cre13.g581600.t1.2,1.0 +Cre13.g581650.t1.2,1.0 +Cre13.g583550.t1.2,1.0 +Cre13.g584850.t1.1,1.0 +Cre13.g585150.t1.2,1.0 +Cre13.g585900.t1.2,1.0 +Cre13.g586300.t1.2,1.0 +Cre13.g587050.t1.2,1.0 +Cre13.g588100.t1.2,1.0 +Cre13.g590650.t1.2,1.0 +Cre13.g592200.t1.2,0.0008354558919287935 +Cre13.g592450.t1.2,1.0 +Cre13.g602350.t1.2,1.0 +Cre13.g602450.t1.2,1.0 +Cre13.g602650.t1.2,0.8437959853692104 +Cre13.g603225.t1.1,1.0 +Cre13.g603500.t1.2,1.0 +Cre13.g603700.t1.2;Cre12.g542900.t1.1,1.0 +Cre13.g603900.t1.2,1.0 +Cre13.g604650.t2.1;Cre13.g604650.t1.2,1.0 +Cre13.g605150.t1.2,1.0 +Cre13.g605650.t1.2,1.0 +Cre13.g607050.t1.2,1.0 +Cre13.g608000.t1.2,1.0 +Cre14.g610950.t1.2,1.0 +Cre14.g612450.t1.2;REV__Cre05.g240650.t1.2,1.0 +Cre14.g612800.t1.2,0.1695315198548906 +Cre14.g614300.t1.2,1.0 +Cre14.g614900.t2.1;Cre14.g614900.t1.2,1.0 +Cre14.g615950.t1.1,0.5048762089854979 +Cre14.g616100.t1.1,1.0 +Cre14.g616600.t1.2,1.0 +Cre14.g617450.t1.2,1.0 +Cre14.g617826.t1.1,1.0 +Cre14.g617900.t1.2,0.6573237559719884 +Cre14.g619100.t1.2,1.0 +Cre14.g619133.t1.1,1.0 +Cre14.g619166.t1.1,1.0 +Cre14.g619550.t2.1;Cre14.g619550.t1.2,1.0 +Cre14.g620600.t1.2;Cre14.g620702.t1.1,1.0 +Cre14.g621450.t1.2,0.07609953892506027 +Cre14.g621650.t1.1,1.0 +Cre14.g621751.t1.1,1.0 +Cre14.g623000.t1.1,1.0 +Cre14.g624201.t1.1,1.0 +Cre14.g625400.t1.1,1.0 +Cre14.g625750.t2.1;Cre14.g625750.t1.2,1.0 +Cre14.g626900.t1.2,1.0 +Cre14.g627850.t1.2,1.0 +Cre14.g628100.t1.2,1.0 +Cre14.g629550.t1.2,1.0 +Cre14.g630100.t1.2,0.7089224919646874 +Cre14.g630400.t1.2,1.0 +Cre14.g630847.t1.1;Cre14.g630835.t1.1,1.0 +Cre14.g632775.t1.1,1.0 +Cre14.g632950.t1.2,1.0 +Cre14.g633750.t1.1,1.0 +Cre15.g635600.t1.2,1.0 +Cre15.g635650.t2.1;Cre15.g635650.t1.2,0.008680189752543477 +Cre15.g635850.t2.1;Cre15.g635850.t1.2,1.0 +Cre15.g636050.t1.2,1.0 +Cre15.g638400.t1.2,1.0 +Cre15.g638500.t1.2,1.0 +Cre15.g639150.t2.1;Cre15.g639150.t1.1,1.0 +Cre15.g643550.t1.2,1.0 +Cre15.g643600.t1.2,1.0 +Cre15.g644051.t1.1,1.0 +Cre16.g650550.t2.1;Cre16.g650550.t1.2,1.0 +Cre16.g651550.t1.2,1.0 +Cre16.g651750.t1.2,1.0 +Cre16.g651923.t1.2,1.0 +Cre16.g652550.t1.2,1.0 +Cre16.g654500.t1.1,1.0 +Cre16.g655150.t1.2,1.0 +Cre16.g656400.t1.2,1.0 +Cre16.g658650.t1.1,1.0 +Cre16.g659350.t1.2,1.0 +Cre16.g659950.t1.1,0.17023124458861918 +Cre16.g660150.t1.2,1.0 +Cre16.g661050.t1.2,1.0 +Cre16.g661350.t1.2,1.0 +Cre16.g661750.t1.2;Cre16.g661850.t1.1,1.0 +Cre16.g662600.t1.2,1.0 +Cre16.g662702.t1.1,1.0 +Cre16.g663500.t1.2,1.0 +Cre16.g663900.t1.2,1.0 +Cre16.g664550.t1.2,1.0 +Cre16.g665250.t1.2,1.0 +Cre16.g669650.t1.2,1.0 +Cre16.g670300.t2.1;Cre16.g670300.t1.2,1.0 +Cre16.g671900.t1.1,1.0 +Cre16.g672385.t1.1,1.0 +Cre16.g672650.t1.2,1.0 +Cre16.g672750.t1.2,1.0 +Cre16.g672800.t1.2,1.0 +Cre16.g673550.t1.1,1.0 +Cre16.g673650.t1.1,1.0 +Cre16.g673729.t1.1,1.0 +Cre16.g673852.t1.1;Cre11.g476325.t1.1;REV__Cre12.g522700.t1.2,1.0 +Cre16.g675550.t3.1;Cre16.g675550.t2.1;Cre16.g675550.t1.2,1.0 +Cre16.g675637.t1.1,1.0 +Cre16.g675650.t1.2,1.0 +Cre16.g676197.t1.1,1.0 +Cre16.g676314.t1.1,1.0 +Cre16.g677000.t1.2,1.0 +Cre16.g677026.t1.1,1.0 +Cre16.g677450.t1.2,1.0 +Cre16.g677500.t1.2,1.0 +Cre16.g679500.t1.2,1.0 +Cre16.g679600.t1.2,1.0 +Cre16.g679800.t1.2;Cre16.g679750.t1.2,1.0 +Cre16.g680000.t1.2,1.0 +Cre16.g680700.t1.2,0.4945732646962974 +Cre16.g682725.t1.1,1.0 +Cre16.g684150.t1.2,1.0 +Cre16.g684300.t1.2,1.0 +Cre16.g684350.t1.2;Cre16.g684550.t1.1,1.0 +Cre16.g685400.t1.2,1.0 +Cre16.g685550.t1.2,1.0 +Cre16.g685901.t1.1,1.0 +Cre16.g687300.t1.2,1.0 +Cre16.g687900.t1.2,1.0 +Cre16.g688050.t1.1,1.0 +Cre16.g688550.t1.2,1.0 +Cre16.g689087.t1.1,1.0 +Cre16.g689871.t1.1,1.0 +Cre16.g690431.t2.1;Cre16.g690431.t1.1,1.0 +Cre16.g691000.t1.2,0.04532394591050837 +Cre16.g691800.t1.1,1.0 +Cre16.g691850.t1.2,1.0 +Cre16.g692901.t1.1,1.0 +Cre16.g693600.t2.1;Cre16.g693600.t1.2,1.0 +Cre16.g694850.t1.2,1.0 +Cre16.g695050.t1.2,1.0 +Cre16.g695100.t1.1,1.0 +Cre16.g696000.t1.2,1.0 +Cre17.g696250.t1.1;Cre17.g696250.t2.1,1.0 +Cre17.g696850.t1.2,1.0 +Cre17.g697450.t1.2,1.0 +Cre17.g698000.t1.2,1.0 +Cre17.g698450.t1.2,1.0 +Cre17.g699000.t2.1;Cre17.g699000.t1.2,1.0 +Cre17.g701200.t2.1;Cre17.g701200.t1.2,1.0 +Cre17.g701500.t1.2,1.0 +Cre17.g701650.t1.2,1.0 +Cre17.g701700.t2.1;Cre17.g701700.t1.2,1.0 +Cre17.g702200.t1.2,0.036602420368794165 +Cre17.g702750.t1.2,1.0 +Cre17.g703700.t1.1,1.0 +Cre17.g704850.t1.2,1.0 +Cre17.g705000.t1.2,1.0 +Cre17.g705400.t1.2,1.0 +Cre17.g706600.t1.2,1.0 +Cre17.g707900.t1.2,1.0 +Cre17.g708300.t1.2,1.0 +Cre17.g708750.t1.2,1.0 +Cre17.g708800.t1.1,1.0 +Cre17.g710150.t1.2,1.0 +Cre17.g711650.t1.2,1.0 +Cre17.g712100.t1.2,1.0 +Cre17.g713200.t1.1;Cre17.g713350.t1.2,1.0 +Cre17.g713450.t1.2;Cre17.g714050.t1.2;Cre17.g714550.t1.2,0.06314009528492193 +Cre17.g715250.t1.2,1.0 +Cre17.g715500.t1.2,1.0 +Cre17.g719000.t1.2,1.0 +Cre17.g719900.t1.2,1.0 +Cre17.g720050.t1.2,1.0 +Cre17.g720250.t1.2,1.0 +Cre17.g720450.t1.1,1.0 +Cre17.g721300.t1.2,1.0 +Cre17.g721500.t1.2,1.0 +Cre17.g722150.t1.2,1.0 +Cre17.g722750.t1.2,1.0 +Cre17.g723250.t1.2,1.0 +Cre17.g723650.t1.2,1.0 +Cre17.g724200.t1.2,1.0 +Cre17.g724300.t1.2,1.0 +Cre17.g724350.t1.2,1.0 +Cre17.g725350.t1.1;Cre17.g725350.t2.1,1.0 +Cre17.g726750.t1.2,1.0 +Cre17.g727950.t1.1,1.0 +Cre17.g728800.t1.2,1.0 +Cre17.g729150.t1.2,1.0 +Cre17.g729800.t1.2,1.0 +Cre17.g732300.t1.2,1.0 +Cre17.g734100.t1.2,1.0 +Cre17.g734200.t1.2,1.0 +Cre17.g734300.t2.1;Cre17.g734300.t1.1,1.0 +Cre17.g734400.t1.1,1.0 +Cre17.g734450.t1.2,1.0 +Cre17.g734500.t1.2,1.0 +Cre17.g734516.t1.1,1.0 +Cre17.g734548.t1.1;Cre10.g424750.t1.2,1.0 +Cre17.g734612.t1.1,1.0 +Cre17.g734900.t2.1;Cre17.g734900.t1.2,1.0 +Cre17.g737250.t1.2,1.0 +Cre17.g738300.t1.2,1.0 +Cre17.g741000.t1.2,1.0 +Cre17.g741450.t1.2,0.3380903993460096 +Cre17.g741850.t1.2,1.0 +Cre17.g742200.t1.1,1.0 +Cre17.g742300.t1.1,1.0 +Cre17.g742450.t1.1,1.0 +Cre17.g743897.t1.1,1.0 +Cre17.g744147.t1.1,1.0 +Cre17.g746997.t1.1;Cre16.g669150.t1.2;Cre16.g669125.t1.1,0.6349108313510784 +Cre18.g749447.t2.1;Cre18.g749447.t1.1,1.0 +Cre18.g749497.t1.1;Cre18.g749647.t1.1,1.0 +Cre18.g749847.t2.1;Cre18.g749847.t1.1,1.0 +Cre18.g750047.t1.1,0.0036490885310087595 +Cre19.g750547.t4.1;Cre19.g750547.t3.1;Cre19.g750547.t2.1;Cre19.g750547.t1.1,1.0 +Cre19.g751247.t2.1;Cre19.g751247.t1.1,1.0 +Cre-2.g801495.t1.p1,1.0 +Cre26.g756797.t1.1,1.0 +Cre43.g760497.t1.1,1.0 +Cre48.g761197.t1.1;Cre01.g050316.t2.1;Cre01.g050316.t1.1,1.0 diff --git a/tests/FSharp.Stats.Tests/data/holmHochberg_Input_nan.csv b/tests/FSharp.Stats.Tests/data/holmHochberg_Input_nan.csv new file mode 100644 index 000000000..94ab5c5da --- /dev/null +++ b/tests/FSharp.Stats.Tests/data/holmHochberg_Input_nan.csv @@ -0,0 +1,1231 @@ +Key,pValues +CON__P00761,nan +CON__P07477,nan +CON__P15636,nan +"CON__P35908v2;CON__P35908;CON__Q6IFZ6;CON__Q7Z794;CON__Q6NXH9",nan +Cre01.g000350.t1.1,0.007976353107647166 +Cre01.g000900.t1.2,0.08708893455014244 +Cre01.g001100.t1.2,0.021384725673514682 +Cre01.g002300.t1.2,0.4334295200013165 +Cre01.g002451.t1.1,0.12843932766067517 +Cre01.g002500.t1.2,0.9728744502708255 +Cre01.g004300.t1.2,0.079885746334174 +Cre01.g004350.t1.2,0.09875831597209911 +Cre01.g004450.t1.2,0.00046620113488396 +Cre01.g004500.t1.2,0.11176046417912805 +Cre01.g004900.t1.2,0.048985617285594266 +Cre01.g004950.t1.1,0.0032865574608725513 +Cre01.g005050.t1.1,0.7767805597587136 +Cre01.g005150.t1.1,0.002061946531430326 +Cre01.g005850.t1.2,0.03090663438989938 +"Cre01.g006950.t2.1;Cre01.g006950.t1.1",0.0019717989392017375 +Cre01.g007700.t1.1,0.9785886725515051 +Cre01.g010400.t1.2,0.01053802810999982 +Cre01.g010900.t1.2,0.8031314537216668 +Cre01.g011000.t1.2,0.0005186810224546701 +Cre01.g012150.t1.2,0.2740538723294388 +"Cre01.g013700.t2.1;Cre01.g013700.t1.2",0.004480387431772253 +Cre01.g014000.t1.2,0.5931361198431784 +Cre01.g014050.t1.2,0.17255239943500295 +Cre01.g014350.t1.2,0.018513015707342453 +Cre01.g015000.t1.2,0.006812219692069941 +Cre01.g015350.t1.1,0.008328872467418473 +Cre01.g015600.t1.1,0.997121384734196 +Cre01.g016050.t1.2,0.16359992965255346 +Cre01.g016300.t1.1,0.008640406377347948 +Cre01.g016514.t1.1,0.05410742328688738 +Cre01.g016528.t1.1,0.9993188644999806 +Cre01.g016850.t1.2,0.02386089565470976 +Cre01.g016900.t1.2,0.0920201693449908 +Cre01.g017300.t1.2,0.03613431773568676 +Cre01.g019250.t1.2,0.3985443637757715 +Cre01.g020350.t1.2,0.7596670066859695 +Cre01.g020918.t1.1,0.10004836307489562 +Cre01.g021251.t1.1,0.03247871976012893 +Cre01.g021600.t1.2,0.20293446555065442 +Cre01.g023350.t1.1,4.1801964888873467E-05 +Cre01.g025250.t1.1,0.9689444126014948 +Cre01.g026450.t1.2,0.5442356522069554 +"Cre01.g026550.t1.1;REV__Cre13.g583972.t1.1",0.24801507633546538 +Cre01.g026600.t1.2,0.5307561445826439 +Cre01.g027000.t1.2,0.006417462603170998 +Cre01.g027550.t1.1,0.452090776726635 +Cre01.g027800.t1.2,0.5823061901777646 +Cre01.g028550.t1.2,0.8020552274162074 +Cre01.g029300.t1.2,0.12071422012897481 +Cre01.g029650.t1.1,0.4571674714380698 +Cre01.g029750.t1.1,0.6004901266439704 +Cre01.g030850.t1.2,0.2996478688504647 +Cre01.g031100.t1.2,0.1286379540186809 +Cre01.g032300.t1.2,0.012408374656534438 +"Cre01.g032650.t2.1;Cre01.g032650.t1.2",0.3813604905935233 +Cre01.g033550.t1.2,8.286025845497344E-06 +Cre01.g034000.t1.2,0.8175404786247276 +Cre01.g034400.t1.1,0.47908867063171134 +Cre01.g035350.t1.2,0.014950818401427642 +Cre01.g037850.t1.1,0.9305289230401661 +Cre01.g038400.t1.2,0.0005624711377480968 +Cre01.g038850.t1.1,0.022668982855486908 +"Cre01.g039250.t2.1;Cre01.g039250.t1.1",9.849830630836998E-05 +Cre01.g039300.t1.2,0.0015755485855541984 +Cre01.g040000.t1.2,0.009518563828662119 +Cre01.g042750.t1.2,0.007526937564241498 +Cre01.g042800.t1.2,0.2612747697776323 +Cre01.g044800.t1.2,0.00015427213634144898 +Cre01.g045550.t1.2,0.4931419602696294 +Cre01.g046652.t1.1,0.003811501011906574 +Cre01.g047700.t1.2,0.001810166467526034 +Cre01.g047750.t1.2,0.08349609208713793 +Cre01.g047800.t1.1,0.31778052720859185 +Cre01.g048950.t1.2,0.830714926590217 +Cre01.g049000.t1.2,0.0005629104137756864 +Cre01.g049500.t1.2,0.27272207909875046 +Cre01.g050100.t1.2,0.05864895577393877 +"Cre01.g050850.t2.1;Cre01.g050850.t1.2",0.9797323235035451 +Cre01.g050950.t1.2,0.464828352314107 +Cre01.g051500.t1.2,0.0029891326489663527 +Cre01.g051900.t1.2,0.06439954424568342 +Cre01.g052100.t1.2,0.04541716737003121 +Cre01.g052250.t1.2,0.006273096639010409 +Cre01.g054150.t1.2,0.0639244662343033 +Cre01.g054500.t1.2,0.00013471072942928609 +Cre01.g054850.t1.2,0.012173986771316425 +Cre01.g055408.t1.1,0.01800520972459352 +Cre01.g055453.t1.1,0.6751419644124569 +Cre01.g061077.t1.1,0.12287808524495401 +Cre01.g066917.t1.1,0.0025337471792682043 +Cre01.g071662.t1.1,0.038998613205088795 +Cre02.g073550.t1.2,0.564304555115607 +Cre02.g075700.t1.2,0.03623398848380033 +Cre02.g076250.t1.1,0.0349347593710737 +Cre02.g076300.t1.1,0.0022271150648052185 +Cre02.g076350.t1.2,0.18692950834495048 +Cre02.g077100.t1.2,0.02353997930816595 +Cre02.g077300.t1.2,0.0029343397276724303 +Cre02.g077350.t1.2,0.13609429469662085 +Cre02.g077800.t1.2,0.3577558858642935 +Cre02.g077850.t1.2,0.0042704609962112006 +Cre02.g078100.t1.1,0.24537908494273708 +Cre02.g078300.t1.1,0.04862955656845225 +Cre02.g079400.t1.2,0.8447974354196537 +Cre02.g079550.t1.2,0.17147523662138175 +Cre02.g079600.t1.2,0.19472876508466053 +Cre02.g079700.t1.2,0.6662714470405846 +Cre02.g079800.t1.2,0.8000995983037789 +Cre02.g080200.t1.2,0.2532094154536513 +Cre02.g080350.t1.1,0.8602388190110557 +Cre02.g080650.t1.2,3.705517686649237E-05 +Cre02.g080700.t1.2,1.6075606202673014E-05 +Cre02.g080900.t1.2,0.11032261427100053 +Cre02.g081050.t1.2,1.182097344676336E-06 +Cre02.g081250.t1.2,0.0017347686582932919 +"Cre02.g082250.t1.1;Cre02.g082150.t1.1",0.8832112406163457 +Cre02.g082500.t1.1,0.002028651361647387 +Cre02.g082550.t1.2,0.003746657003878072 +"Cre02.g082852.t1.1;Cre02.g082750.t1.2",0.24811211224899032 +"Cre02.g083800.t2.1;Cre02.g083800.t1.2",0.015275536062299729 +Cre02.g083950.t1.1,0.0012219517862479545 +Cre02.g084000.t1.2,0.004934558218351981 +Cre02.g085450.t1.2,0.009792628654235839 +Cre02.g085900.t1.2,0.26635549537022785 +Cre02.g085950.t1.2,0.7484444924160323 +Cre02.g087700.t1.2,0.3025301949950845 +Cre02.g087950.t1.2,0.522787836767858 +Cre02.g088000.t1.2,0.16917334618859847 +Cre02.g088200.t1.2,0.1557154153462836 +Cre02.g088600.t1.2,0.07339855381581825 +Cre02.g088850.t1.2,0.0014002338733951625 +"Cre02.g088900.t1.2;Cre06.g278090.t1.1",0.00441904239734936 +Cre02.g089100.t1.2,0.5164986893534194 +"Cre02.g090850.t1.1;REV__Cre12.g528450.t1.2",0.004009568772693602 +Cre02.g091050.t1.2,0.4194765444481099 +Cre02.g091100.t1.2,0.011140447539244702 +Cre02.g091550.t1.2,0.03745272948181754 +Cre02.g092400.t1.1,0.5155292093672428 +Cre02.g092900.t1.2,0.0784112012133189 +Cre02.g093450.t1.2,0.04847796523660516 +Cre02.g093650.t1.2,0.005167660653224809 +Cre02.g094100.t1.2,0.6077851349668639 +Cre02.g095146.t1.1,0.2681686136464885 +Cre02.g096150.t1.2,0.00019133808327344618 +Cre02.g097400.t1.2,0.13018787646309415 +Cre02.g097550.t1.2,0.3409650975937193 +Cre02.g097650.t1.2,0.13799609158908566 +Cre02.g097900.t1.2,0.037506717267689886 +Cre02.g098250.t1.2,0.01714116718514358 +Cre02.g098450.t1.2,0.10777203640059474 +Cre02.g099150.t1.2,0.0029879372601770296 +Cre02.g099850.t1.1,0.060194411516150154 +Cre02.g100200.t1.2,0.02631071993871958 +Cre02.g101350.t1.2,0.004690749759168611 +Cre02.g101400.t1.2,0.0047532817081447735 +Cre02.g102250.t1.2,0.0013553999810744788 +Cre02.g103550.t1.2,0.787757568673964 +Cre02.g104900.t1.2,0.00010160610743747966 +"Cre02.g106600.t1.2;Cre17.g733650.t1.1",0.00042712666010991107 +Cre02.g107300.t1.2,0.7998184166235545 +Cre02.g108450.t1.2,0.09656022587166425 +Cre02.g108850.t1.2,0.03370352163369761 +Cre02.g109550.t1.2,0.06404619936174342 +"Cre02.g110350.t1.2;Cre12.g485200.t1.1;Cre11.g467595.t1.1",0.3575732798877671 +Cre02.g111450.t1.2,0.00110365338337854 +Cre02.g111700.t1.2,0.7899549158760935 +Cre02.g113200.t1.1,0.10716827879452451 +Cre02.g114450.t1.2,0.9734640250485946 +Cre02.g114600.t1.2,0.02910036666457339 +Cre02.g115200.t1.2,0.020316004511075736 +"Cre02.g116750.t2.1;Cre02.g116750.t1.1",0.14892658234393905 +Cre02.g118500.t1.1,0.4312698874387929 +Cre02.g118850.t1.2,0.004341010745408962 +Cre02.g118950.t1.2,0.0008824400739420035 +Cre02.g119550.t1.2,0.036701570065454894 +Cre02.g120150.t1.2,0.05548402255447149 +"Cre02.g120250.t2.1;Cre02.g120250.t1.1;Cre02.g120200.t1.2",0.07688031975328728 +Cre02.g141400.t1.2,0.001488654270081602 +Cre02.g141500.t1.2,0.029923807567430287 +Cre02.g142146.t1.1,0.5851679569064601 +Cre02.g142206.t1.1,0.13319144663584 +Cre02.g142352.t1.1,0.01404428491424059 +"Cre12.g486250.t1.2;Cre02.g142687.t2.1;Cre02.g142687.t1.1",0.02054152149692214 +Cre02.g142800.t1.2,0.49580055249665256 +Cre02.g143000.t1.2,0.01195058930867443 +Cre02.g143050.t1.2,0.018333910754168903 +"Cre02.g143200.t1.1;Cre12.g547000.t1.2",0.3379912935806688 +Cre02.g143250.t1.2,0.016755176595897314 +Cre02.g143307.t1.1,0.10347873856068117 +Cre02.g143550.t1.2,0.03685275102997731 +Cre02.g145800.t1.2,0.08951739440605454 +Cre02.g146250.t1.2,0.4515974622373746 +Cre02.g147302.t1.1,0.0001614804519814399 +"Cre02.g147900.t4.1;Cre02.g147900.t2.1;Cre02.g147900.t1.1;Cre02.g147900.t3.1",0.01103420598318916 +Cre03.g143887.t1.1,0.7565345293972348 +Cre03.g144627.t1.1,0.4848234202675934 +"Cre03.g144807.t1.1;REV__Cre01.g020918.t1.1",0.010646816298710116 +Cre03.g144847.t1.1,0.015705966917273596 +Cre03.g144967.t1.1,0.023885963119395504 +Cre03.g145507.t1.1,0.08167208877231102 +Cre03.g145547.t1.1,0.41680391498409497 +Cre03.g145647.t1.1,0.0013875131877111764 +Cre03.g145727.t1.1,0.13605121259273487 +Cre03.g145747.t1.1,0.33070918124508353 +Cre03.g145967.t1.1,0.6378164990066886 +Cre03.g146167.t1.1,0.09780033428929488 +Cre03.g146187.t1.1,0.03158259869141568 +Cre03.g146247.t1.1,0.14371739624832136 +Cre03.g146487.t1.1,0.26904157997576517 +Cre03.g146527.t1.1,0.054863922305120515 +Cre03.g149100.t1.2,0.021089005251446302 +Cre03.g150300.t1.2,0.029003313742001532 +Cre03.g152150.t1.2,0.0009738379851673695 +Cre03.g153450.t1.2,0.06044905476996609 +Cre03.g154550.t1.1,0.006596918833917097 +Cre03.g156050.t1.2,0.8107055830068972 +Cre03.g156250.t1.2,0.2403158262800139 +Cre03.g156600.t1.2,0.15820563920450592 +Cre03.g156750.t1.2,0.43700459823532556 +Cre03.g156900.t1.2,0.01873851757310343 +Cre03.g156950.t1.1,0.7538684119744778 +Cre03.g157700.t1.2,0.017654327048267977 +Cre03.g158000.t1.2,0.0016376773864557408 +Cre03.g158750.t1.1,0.19774728374107936 +"Cre03.g158800.t3.1;Cre03.g158800.t2.1;Cre03.g158800.t1.1",0.0004555622468472114 +Cre03.g158900.t1.2,0.0048115731177557726 +Cre03.g160500.t1.2,0.13300475152166635 +Cre03.g161400.t1.2,0.06488676173989116 +Cre03.g164000.t1.2,0.00541904244017033 +"Cre03.g164600.t1.2;Cre03.g165050.t1.2",5.165290865005723E-05 +Cre03.g164700.t1.2,0.8522176456704966 +Cre03.g166050.t1.2,0.062086065995771246 +Cre03.g168450.t1.2,0.054993426140455 +Cre03.g168700.t1.2,0.0017374277768383976 +Cre03.g169400.t1.2,0.0014679668186980965 +Cre03.g169850.t1.2,0.01985133917180426 +Cre03.g169900.t1.2,0.09844166554709466 +Cre03.g171100.t1.1,0.08576422193294997 +Cre03.g171950.t1.1,0.025053129769957945 +Cre03.g172000.t1.2,0.1783318087590041 +Cre03.g172300.t1.2,0.9027209730149064 +Cre03.g172850.t1.2,0.8490540985591764 +Cre03.g172950.t1.2,0.01913417757544189 +"Cre03.g173350.t2.1;Cre03.g173350.t1.2",0.019449191844129743 +Cre03.g175200.t1.2,0.024612124701814952 +Cre03.g175400.t2.1,0.1485641650688363 +Cre03.g176100.t1.2,0.5304353240735808 +Cre03.g176250.t1.2,0.6956874636966992 +Cre03.g177053.t1.1,0.46070179598842 +Cre03.g177200.t1.2,0.10114710459442167 +Cre03.g178150.t1.1,0.036512583613781846 +Cre03.g178250.t1.2,0.026951706843445087 +Cre03.g178450.t1.2,1.3186510831179691E-05 +Cre03.g180750.t1.2,5.6464332764960545E-08 +Cre03.g180800.t1.1,0.2179803308911632 +Cre03.g181300.t1.2,0.7483628257778823 +Cre03.g181500.t1.2,0.028085494379006745 +Cre03.g182050.t1.2,0.016070979526531966 +Cre03.g182150.t1.2,0.00032265465741967053 +Cre03.g182450.t1.2,0.9480256960944624 +Cre03.g182500.t1.2,0.40351380629261646 +Cre03.g182551.t1.2,6.081885760988913E-05 +"Cre03.g182950.t1.2;Cre12.g520150.t1.1",0.9137406519431572 +Cre03.g183100.t1.2,0.9694911298681452 +Cre03.g183400.t1.1,0.733845851009157 +Cre03.g184550.t1.2,0.08064238004117268 +Cre03.g185550.t1.2,0.060673762121324026 +Cre03.g187450.t1.2,0.13435037010955142 +Cre03.g188250.t1.2,0.0035746977987691484 +Cre03.g189250.t1.2,0.8132130387539861 +Cre03.g189300.t1.1,0.0004633516715427224 +Cre03.g189400.t1.2,0.164607011072476 +Cre03.g189500.t1.2,0.13247380496241795 +Cre03.g189800.t1.2,0.029178195132510625 +Cre03.g189950.t1.2,0.0008777602224215063 +Cre03.g190100.t1.1,0.006071953297743793 +Cre03.g190500.t1.2,0.009865466313603603 +"Cre04.g216850.t1.2;Cre03.g190950.t1.2",0.0001532850220411497 +Cre03.g191050.t1.2,0.8576581071171834 +Cre03.g193750.t1.1,0.6354015908223831 +Cre03.g193800.t1.1,0.08122650904522369 +Cre03.g193850.t1.2,0.21001628777794798 +Cre03.g193950.t1.2,0.10712870847640432 +Cre03.g194200.t1.2,0.9059822510391216 +Cre03.g194350.t1.2,0.0249922401553202 +Cre03.g194400.t1.2,0.004438116560187444 +Cre03.g194850.t1.2,0.10696777299445137 +Cre03.g195650.t1.2,0.005270176067700971 +"Cre03.g197500.t2.1;Cre03.g197500.t1.2",0.5594569816210944 +"Cre03.g198850.t1.2;Cre03.g198863.t1.1",0.08209689257389881 +Cre03.g198950.t1.2,0.07734696009176001 +Cre03.g199000.t1.2,0.024315202853543147 +Cre03.g199423.t1.1,0.11179164896353584 +Cre03.g199535.t1.1,0.4130197977397727 +Cre03.g199647.t1.1,0.0822858054091844 +"Cre03.g199759.t2.1;Cre03.g199759.t1.1",0.0052117453437559025 +Cre03.g199900.t1.2,0.03829472325180672 +Cre03.g199983.t1.1,0.22441879003380083 +Cre03.g200250.t1.2,0.0030230410343384698 +"Cre03.g202950.t1.1;Cre10.g419400.t1.1",0.0041279429603077724 +Cre03.g203450.t1.2,0.07915621023241792 +Cre03.g203850.t1.2,0.9740109468971676 +Cre03.g204250.t1.2,0.0008399513508159373 +Cre03.g204350.t1.2,0.3273984670445408 +Cre03.g204601.t1.1,0.008109735768453419 +Cre03.g206600.t1.2,0.0644957190520662 +Cre03.g207700.t1.1,0.05970578276892202 +Cre03.g213537.t1.1,0.7737911123838979 +Cre04.g213250.t1.2,0.19376860862369083 +Cre04.g214150.t1.1,0.042528489239876954 +Cre04.g214500.t1.1,0.04217378723383769 +Cre04.g214501.t1.1,0.1384548931917089 +Cre04.g214502.t1.1,0.29649889105685656 +"Cre04.g215150.t2.1;Cre04.g215150.t1.2",0.0003162085390416332 +"Cre04.g215850.t1.2;REV__Cre13.g576600.t1.2",0.01627529581253722 +Cre04.g217550.t1.1,0.010421808370600916 +Cre04.g217921.t1.1,0.07396992660793072 +Cre04.g218100.t1.2,0.1503184788923186 +Cre04.g218250.t1.2,0.11194795380520639 +"Cre04.g220200.t3.1;Cre04.g220200.t2.1;Cre04.g220200.t1.2",0.4330249092047195 +"Cre04.g220350.t2.1;Cre04.g220350.t1.2",0.1070813765029137 +Cre04.g221400.t1.2,0.15451539077581405 +Cre04.g222700.t1.2,1.703597300095616E-05 +Cre04.g223100.t1.2,0.012776567366215663 +Cre04.g223850.t1.2,0.0026172886354323133 +Cre04.g226850.t1.2,0.0050630681812886625 +Cre04.g229300.t1.1,0.00016310909582392268 +Cre04.g229700.t1.2,0.0001934493094469288 +Cre04.g231026.t1.1,0.24528032337124372 +"Cre04.g231222.t2.1;Cre04.g231222.t1.1",2.4733001776767723E-05 +Cre04.g232104.t1.1,0.00013210131941577142 +"Cre05.g232002.t2.1;Cre05.g232002.t1.1",0.020592979261122624 +Cre05.g232200.t1.2,0.1759333501338046 +Cre05.g232750.t1.2,0.8287265732222926 +Cre05.g233050.t1.2,0.632115228123838 +"Cre05.g233303.t2.1;Cre05.g233303.t1.1",0.04036863261888021 +"Cre05.g233305.t2.1;Cre05.g233305.t1.1",0.25203147045006935 +Cre05.g233800.t1.2,0.08297552064441076 +Cre05.g233900.t1.2,0.09939466083151437 +Cre05.g233950.t1.2,0.05997686624153562 +"Cre05.g234550.t2.1;Cre05.g234550.t1.2",0.009270369458959121 +Cre05.g234637.t1.1,0.013935350372139332 +Cre05.g234638.t1.1,0.5794034219854389 +Cre05.g234639.t1.1,0.5305689594225986 +Cre05.g234652.t1.1,0.005109640460613049 +Cre05.g237400.t1.2,0.039221169679815926 +Cre05.g237450.t1.2,0.05922401265692901 +Cre05.g238322.t1.1,0.8293325385914659 +Cre05.g238332.t1.1,0.06242439939317918 +Cre05.g238687.t1.1,0.41219232220530255 +Cre05.g240800.t1.2,0.20767119985620686 +Cre05.g240850.t1.2,0.00042136009975379807 +Cre05.g241450.t1.2,0.13724665185739834 +Cre05.g241850.t1.2,0.06834987513298785 +Cre05.g241950.t1.2,0.010140055591592896 +Cre05.g242000.t1.2,0.23132278073914048 +Cre05.g242300.t1.2,0.01528008527641278 +Cre05.g242350.t1.2,0.26422394650381675 +Cre05.g243050.t1.2,0.013489829142516877 +Cre05.g243800.t1.2,0.8984925911383845 +"Cre05.g245158.t1.1;Cre24.g755097.t1.1",0.0012744504514825695 +Cre05.g245900.t1.2,0.0014004180691804735 +Cre05.g245950.t1.1,0.03266424353731406 +Cre05.g247450.t1.2,0.004249403547724967 +Cre05.g247600.t1.2,0.0466445491515286 +Cre05.g247950.t1.2,0.7302231379401276 +"Cre05.g248450.t1.2;Cre05.g248400.t1.2",0.0008899245710771759 +Cre06.g249250.t1.2,0.05411300348159176 +Cre06.g250100.t1.2,3.383969697870131E-05 +Cre06.g250200.t1.2,0.0034496118556039956 +Cre06.g250250.t1.2,0.022046414676883064 +"Cre06.g250800.t2.1;Cre06.g250800.t1.1",0.9182191261360303 +Cre06.g250902.t1.1,0.02773331272039381 +Cre06.g251400.t1.2,0.4616969580499255 +Cre06.g251500.t1.2,0.0021293869781764396 +Cre06.g252200.t1.2,0.41006036890989406 +Cre06.g252450.t1.1,0.0014057281796382437 +Cre06.g252550.t1.1,0.438688147221459 +Cre06.g252650.t1.2,0.5521369343071232 +Cre06.g253350.t1.2,0.027905827246482932 +Cre06.g254400.t1.1,0.47021379836520727 +Cre06.g255100.t1.1,0.019717539855377927 +Cre06.g256250.t1.2,0.24123872786938838 +Cre06.g257150.t1.2,0.11373104880176776 +Cre06.g257500.t1.2,0.2541839626137784 +Cre06.g257601.t1.2,0.00012543690362342937 +Cre06.g257850.t1.2,0.5061682733053338 +Cre06.g257950.t1.2,0.0010322906100770357 +Cre06.g258700.t1.1,0.004068837159057814 +"Cre06.g258733.t2.1;Cre06.g258733.t1.1",0.009571583578198232 +Cre06.g258800.t1.1,0.03961413357372523 +Cre06.g259100.t1.1,0.8174636325849631 +Cre06.g259150.t1.2,0.09997546501555306 +Cre06.g259401.t1.1,0.39439110160659563 +Cre06.g259450.t1.2,0.027756201686933605 +Cre06.g259850.t1.2,0.015459537674151314 +Cre06.g259900.t1.2,7.144135350634073E-06 +Cre06.g261000.t1.2,0.036504785834599485 +Cre06.g261450.t1.2,0.00044224210463439384 +Cre06.g261500.t1.2,0.0008512539111124819 +Cre06.g261650.t1.1,0.08900017966378404 +Cre06.g261800.t1.2,0.29158253642786125 +Cre06.g262100.t1.1,0.9321120222123566 +Cre06.g262700.t1.1,0.5543560797015389 +Cre06.g263250.t1.1,0.6450230270605679 +Cre06.g263300.t1.2,0.6336903921346864 +"Cre12.g498600.t1.2;Cre06.g263450.t1.2;Cre06.g263450.t2.1",0.061555026679134706 +Cre06.g264200.t1.2,0.19889452705055044 +Cre06.g264300.t1.2,0.0009411056161792164 +Cre06.g264350.t1.2,0.11428246463812664 +"Cre06.g264600.t1.2;Cre12.g504850.t1.2;Cre17.g714600.t1.2;Cre17.g714000.t1.2;Cre17.g713500.t1.2;Cre17.g711800.t1.2;Cre17.g710500.t1.2;Cre17.g709100.t1.2;Cre17.g708650.t1.2;Cre17.g708200.t1.2;Cre16.g650250.t1.2;Cre16.g649950.t1.2;Cre12.g506450.t1.2;Cre12.g506350.t1.2;Cre12.g505450.t1.2;Cre12.g504600.t1.2;Cre06.g276800.t1.2;Cre06.g276650.t1.2;Cre06.g275700.t1.2;Cre06.g274900.t1.2;Cre06.g274300.t1.2;Cre06.g274150.t1.2;Cre06.g273950.t1.2;Cre06.g271300.t1.2;Cre06.g268400.t1.2;Cre06.g268000.t1.2;Cre06.g266600.t1.2;Cre06.g265450.t1.2;Cre06.g265200.t1.2;Cre06.g265050.t1.2;Cre13.g570000.t1.2;Cre13.g570000.t2.1",0.0046310992024671815 +"Cre06.g264650.t1.2;Cre12.g505500.t1.2;Cre06.g265000.t1.2;Cre17.g713950.t1.2;Cre17.g713550.t1.2;Cre17.g711850.t1.2;Cre17.g710550.t1.2;Cre17.g709050.t1.2;Cre17.g708700.t1.2;Cre17.g708150.t1.2;Cre16.g650300.t1.2;Cre16.g649900.t1.1;Cre16.g648500.t1.2;Cre13.g569950.t1.2;Cre12.g506500.t1.2;Cre12.g506300.t1.2;Cre12.g504800.t1.2;Cre17.g714650.t1.2;Cre12.g504650.t1.2;Cre06.g276850.t1.2;Cre06.g276600.t1.2;Cre06.g275750.t1.2;Cre06.g274850.t1.2;Cre06.g274350.t1.2;Cre06.g274101.t1.1;Cre06.g274000.t1.2;Cre06.g271250.t1.2;Cre06.g268350.t1.2;Cre06.g267950.t1.2;Cre06.g266650.t1.2;Cre06.g265500.t1.2;Cre06.g265250.t1.2;Cre02.g104800.t1.1",0.15228960274554315 +"Cre06.g264750.t1.2;Cre17.g708550.t1.2;Cre06.g264950.t1.2;Cre06.g265350.t1.2;Cre06.g266700.t1.2;Cre06.g268050.t1.2;Cre13.g591150.t1.2;Cre13.g590800.t1.2;Cre12.g506250.t1.2;Cre12.g505550.t1.2;Cre12.g504750.t1.2;Cre12.g504500.t1.2;Cre06.g268300.t1.2;Cre06.g274800.t1.2;Cre06.g273900.t1.2;Cre06.g271350.t1.2;Cre06.g275850.t1.2;Cre17.g714100.t1.2;Cre17.g713400.t1.2;Cre17.g711700.t1.2;Cre17.g710400.t1.2;Cre17.g709200.t1.2;Cre06.g276500.t1.2;Cre13.g570100.t1.2;Cre06.g274200.t1.2;Cre17.g714500.t1.2;Cre06.g276950.t1.2;Cre06.g278088.t1.1",0.5475355826313304 +Cre06.g265800.t1.2,0.05041705834157373 +Cre06.g268600.t1.2,0.0026139394430217434 +Cre06.g269050.t1.2,0.0006543312699439142 +Cre06.g269450.t1.2,0.04042401512429028 +"Cre06.g269650.t1.2;Cre06.g269601.t1.1",0.003822058261168104 +Cre06.g269950.t1.2,0.006310830709051194 +Cre06.g272050.t1.2,0.0899886796860595 +Cre06.g272650.t1.2,0.0014070509033888665 +Cre06.g272800.t1.2,0.003797632722274402 +"Cre06.g272850.t1.2;Cre10.g449700.t1.1",0.005660444414466559 +Cre06.g272900.t1.2,0.002190188804990889 +Cre06.g272950.t1.1,3.2240964868535116E-05 +Cre06.g273000.t1.2,0.02408210354590552 +Cre06.g273300.t1.2,0.18151741213733483 +Cre06.g273550.t1.2,0.004053253593817639 +Cre06.g273700.t1.2,0.12107660525752206 +Cre06.g274650.t1.1,0.11519206382471005 +Cre06.g275100.t1.2,0.000509854882964289 +"Cre06.g278087.t1.1;Cre06.g278089.t1.1",0.5961000129276459 +Cre06.g278125.t1.1,0.09276132213219412 +Cre06.g278135.t1.1,0.009303095470308831 +Cre06.g278148.t1.1,0.24951592587216964 +Cre06.g278162.t1.1,0.9164911944848226 +Cre06.g278163.t1.1,0.06503010604589081 +Cre06.g278169.t1.1,0.05461466700728535 +Cre06.g278170.t1.1,0.011045260992145176 +Cre06.g278185.t1.1,0.00025534924355024685 +Cre06.g278195.t1.1,0.28212789898162194 +Cre06.g278210.t1.1,3.299701181535679E-05 +Cre06.g278211.t1.1,0.010009601806752245 +Cre06.g278213.t1.1,0.011764210902023538 +Cre06.g278221.t1.1,0.194649899484312 +Cre06.g278222.t1.1,0.007558454839370343 +"Cre06.g278239.t2.1;Cre06.g278239.t1.1",0.005195978932401646 +Cre06.g278255.t1.1,0.02311414624165555 +Cre06.g278256.t1.1,0.6293491853465549 +Cre06.g278750.t1.2,0.09414428217099191 +Cre06.g279150.t1.2,0.0003010578311946477 +Cre06.g279400.t1.2,0.27855394847820625 +Cre06.g280650.t1.2,0.039137021921283786 +Cre06.g280950.t1.2,0.4085302462945195 +"Cre06.g282000.t1.1;Cre06.g282000.t2.1",0.010799425969789478 +Cre06.g282500.t1.2,0.01793923263143138 +Cre06.g282800.t1.2,0.03100399861344627 +Cre06.g283050.t1.2,0.0034408020270289582 +Cre06.g283950.t1.2,0.000854368609517206 +Cre06.g284750.t1.2,0.4769251086687659 +"Cre06.g284900.t2.1;Cre06.g284900.t1.2",0.13421507647032963 +Cre06.g285250.t1.2,0.0027026857710335415 +Cre06.g285401.t1.1,0.0021174863411912437 +Cre06.g286250.t1.2,0.2999477610416301 +Cre06.g288700.t1.2,0.647462057295182 +Cre06.g289550.t1.2,0.0178246404073521 +Cre06.g290950.t1.2,0.2639315131347042 +Cre06.g292000.t1.1,0.0002537989243522236 +Cre06.g293150.t1.2,0.6998248122507387 +Cre06.g293582.t1.1,0.9011428414390905 +Cre06.g293850.t1.2,0.08455593103945859 +Cre06.g293950.t1.2,4.621421695993888E-06 +Cre06.g294650.t1.2,0.0002267510169151598 +Cre06.g294750.t1.2,0.14082696234152678 +Cre06.g294950.t1.1,0.4814816275975844 +Cre06.g295450.t1.2,0.0039317788626242745 +Cre06.g296500.t1.2,0.26553905390985444 +Cre06.g298100.t1.2,0.05250404097288186 +Cre06.g298350.t1.2,0.0013489975516964847 +Cre06.g298650.t1.2,0.011487271233956209 +Cre06.g299000.t1.2,0.00689450191755725 +Cre06.g299650.t1.2,0.510251655847269 +Cre06.g300550.t1.2,0.5920547813569325 +Cre06.g300700.t1.1,0.39365098040473123 +Cre06.g300800.t1.2,0.007116578740266499 +Cre06.g302700.t1.1,0.261965035653017 +Cre06.g304300.t1.2,0.2336132627038695 +Cre06.g304350.t1.2,0.008235276524637306 +Cre06.g304500.t1.2,0.26421905353721564 +Cre06.g306300.t1.2,0.061638125803457955 +Cre06.g306601.t1.1,0.24795422641678622 +Cre06.g307450.t1.2,0.6713912988507582 +Cre06.g307500.t1.1,0.00019274800870039345 +Cre06.g308250.t1.2,0.00012979534059742726 +Cre06.g308450.t1.2,0.06599724174478139 +Cre06.g308500.t1.2,0.8072434393465484 +Cre06.g308850.t1.2,0.13243212960009432 +Cre06.g308950.t1.2,0.05241645485291377 +Cre06.g309100.t1.2,0.0014016805790271706 +Cre06.g310750.t1.2,0.1934258183128971 +Cre06.g311900.t1.2,0.6679163665258028 +Cre07.g313700.t1.1,0.9274202245418017 +Cre07.g314150.t1.2,0.010525859182687114 +Cre07.g316000.t1.2,0.1144103548184113 +Cre07.g318450.t1.2,0.06989968838482263 +Cre07.g318750.t1.2,0.10350052977672643 +"Cre07.g324200.t1.2;REV__Cre13.g602800.t1.1",0.0003543836493498098 +Cre07.g325400.t1.2,0.01455271803531856 +Cre07.g325500.t1.1,0.0011470677002647367 +Cre07.g325734.t1.1,0.024692768177223323 +Cre07.g325736.t1.1,0.0005367868625519001 +Cre07.g325746.t1.1,0.11159036811728984 +Cre07.g325755.t1.1,6.221461513243563E-05 +Cre07.g326800.t1.1,0.001812957582937953 +Cre07.g326950.t1.1,0.5691322531835394 +Cre07.g327350.t1.2,0.5605243470815415 +Cre07.g327400.t1.1,0.01863841287931105 +"Cre07.g328150.t2.1;Cre07.g328150.t1.1",0.0025419258779562012 +Cre07.g328200.t1.2,0.35380814058641763 +Cre07.g328900.t1.2,0.8892134831056434 +Cre07.g329700.t1.2,0.4876582038326682 +Cre07.g330250.t1.2,0.03437715113537522 +Cre07.g331500.t1.1,0.21264458238840778 +Cre07.g331550.t1.2,0.09746348585055342 +Cre07.g331900.t1.2,0.007227627686845262 +Cre07.g332450.t1.2,0.0005800810070951154 +Cre07.g334900.t1.1,0.05368681447870112 +Cre07.g335400.t1.1,0.01888348521642147 +Cre07.g336450.t1.2,0.09067678235762111 +Cre07.g336950.t1.1,3.587161486837531E-05 +Cre07.g337650.t1.2,0.2218381603338733 +Cre07.g338050.t1.2,0.4096180921390151 +Cre07.g338451.t1.1,0.00028802271024153114 +Cre07.g339150.t1.1,0.00010636738855095472 +Cre07.g339700.t1.2,0.4341059749635121 +Cre07.g340200.t1.1,0.8938237831445304 +Cre07.g340350.t1.1,0.24506601617738877 +Cre07.g341550.t1.2,0.9965152885273 +Cre07.g341600.t2.1,1.3498280747653205E-05 +Cre07.g342150.t1.2,0.7351290592464969 +Cre07.g342250.t1.2,0.2805551902448955 +"Cre07.g343700.t1.2;Cre07.g343433.t1.1",0.011828749443847819 +Cre07.g344400.t1.2,0.004174277708958396 +Cre07.g344550.t1.2,0.05122144927871619 +Cre07.g344950.t1.2,0.011506839931630349 +"Cre07.g346050.t2.1;Cre07.g346050.t1.2",0.021240788416392542 +Cre07.g347150.t1.2,0.03151935620049562 +Cre07.g349350.t1.2,0.17843045464993185 +Cre07.g350500.t1.2,0.00014985940007838867 +Cre07.g352650.t1.2,0.830805931959097 +Cre07.g352850.t1.2,0.009224254575500135 +Cre07.g353450.t1.2,0.01321224515646291 +Cre07.g356350.t1.1,0.3241204452631079 +Cre07.g356400.t1.2,0.00970646055455271 +Cre07.g356600.t1.2,0.05829055615565215 +Cre07.g357200.t1.2,0.06896722886563386 +Cre07.g357350.t1.2,0.002036464845267126 +Cre07.g357850.t1.2,0.0040909392743682105 +Cre08.g358526.t1.1,0.00028786116166790165 +Cre08.g358562.t1.1,7.93795991374435E-05 +Cre08.g358580.t1.1,0.005260660873474432 +Cre08.g359350.t1.2,0.5369871661570895 +"Cre08.g359750.t2.1;Cre08.g359750.t1.2",0.0005279528956221302 +Cre08.g360900.t1.2,0.0009855530635323184 +Cre08.g361850.t1.2,0.029064094510805386 +Cre08.g362450.t1.2,0.34624626080921506 +Cre08.g364650.t1.1,0.1404414975722121 +Cre08.g364800.t1.2,0.0005663859226108237 +Cre08.g365400.t1.2,0.006044917440532371 +Cre08.g365632.t1.1,0.2821690703337283 +Cre08.g365692.t1.1,0.5351761278440619 +"Cre08.g366400.t2.1;Cre08.g366400.t1.2",0.4455052691141115 +"Cre08.g367500.t1.1;Cre08.g367400.t1.1",0.0006362683234911868 +Cre08.g368400.t1.2,0.1840416727045057 +"Cre08.g368900.t2.1;Cre08.g368900.t1.2",0.009370166874926473 +Cre08.g368950.t1.2,0.03164881456502834 +Cre08.g370450.t1.2,0.30858286356613507 +Cre08.g370650.t1.2,0.0008135350431452227 +Cre08.g372100.t1.2,1.0207685445433012E-05 +Cre08.g372450.t1.2,0.0034766306842007517 +Cre08.g372950.t1.2,0.0013722715895451705 +Cre08.g373100.t1.1,0.007580276481214049 +"Cre08.g375200.t2.1;Cre08.g375200.t1.2",0.033974930147534464 +Cre08.g376100.t1.2,0.19068680482672018 +Cre08.g378000.t1.2,0.6057862506627942 +Cre08.g378050.t1.2,0.7590637962669212 +Cre08.g378850.t1.2,0.27214576595038364 +"Cre08.g379200.t1.1;Cre08.g379175.t1.1",0.07410374755726101 +Cre08.g380201.t1.1,0.47346992933950294 +Cre08.g382500.t1.2,0.002122117068984908 +Cre08.g384000.t1.1,0.029158347955827148 +Cre09.g386200.t1.1,0.9840328367263986 +Cre09.g386400.t1.2,0.03988804714309206 +"Cre09.g386650.t2.1;Cre09.g386650.t1.2",0.7557118556850175 +Cre09.g386735.t1.1,0.0269206756215853 +Cre09.g386750.t1.2,0.0001332714725564922 +Cre09.g386758.t1.1,0.013895211250384145 +"Cre09.g387171.t2.1;Cre09.g387171.t1.1",0.007842561486912463 +Cre09.g387393.t1.1,0.0029046810318550695 +Cre09.g387726.t1.1,0.14608868692087285 +Cre09.g387800.t1.2,0.05005830682630874 +Cre09.g387875.t1.1,0.0028798041757815973 +Cre09.g388200.t1.1,0.00921114065748152 +Cre09.g388467.t1.1,0.05174932746613212 +"Cre09.g388726.t1.1;Cre09.g388726.t2.1;Cre09.g388726.t3.1;Cre09.g388726.t4.1",0.000127284295048824 +Cre09.g389430.t1.1,0.2490492608540662 +Cre09.g389689.t1.1,0.4164392293488648 +Cre09.g390050.t1.2,0.15937625587566173 +Cre09.g390763.t1.1,0.3186896632597377 +Cre09.g391023.t1.1,0.948821866563575 +"Cre09.g391097.t2.1;Cre09.g391097.t1.1",0.013013867387067224 +Cre09.g391900.t1.1,0.3591367592194338 +"Cre09.g392350.t2.1;Cre09.g392350.t1.2",6.472133574320083E-05 +Cre09.g392500.t1.2,0.10656776403201572 +Cre09.g393150.t1.2,0.00018497462984523594 +Cre09.g393173.t1.1,0.10017048515740812 +Cre09.g393200.t1.2,0.0008236837066335763 +Cre09.g393358.t1.1,0.055703917916849255 +Cre09.g393543.t1.1,0.0857648025639437 +Cre09.g393765.t1.1,0.03208939976833546 +Cre09.g394102.t1.1,0.018919969946317818 +Cre09.g394200.t1.1,0.540647081825702 +Cre09.g394436.t1.1,0.03995886227165416 +Cre09.g394450.t1.2,0.0007635137983485128 +Cre09.g394547.t1.1,0.8869084606878099 +Cre09.g394550.t1.2,0.5619304078483842 +Cre09.g394750.t1.2,0.0037406930339825006 +Cre09.g394850.t1.2,0.575153404924585 +Cre09.g395350.t1.1,0.11743759336317951 +Cre09.g396213.t1.1,0.012309475954806717 +Cre09.g396252.t1.1,0.05292991005513899 +Cre09.g396300.t1.2,0.8205507995307539 +"Cre09.g396400.t1.2;Cre01.g007051.t1.2;Cre11.g467567.t1.1",0.3901792803040265 +Cre09.g396650.t1.2,0.975889043483152 +Cre09.g397200.t1.2,0.7679508755304348 +Cre09.g397549.t1.1,0.914949022890124 +Cre09.g397697.t1.1,0.011104874655442298 +Cre09.g398067.t1.1,3.911419730757835E-05 +Cre09.g398900.t1.1,0.7529914640700236 +Cre09.g400050.t1.1,0.07567891393615578 +Cre09.g400650.t1.2,0.00792416264918594 +Cre09.g401515.t1.1,0.4957160850278002 +Cre09.g401886.t1.1,0.058587809537089974 +Cre09.g401900.t1.2,0.0055111775732188395 +Cre09.g402300.t1.2,0.5615628666054706 +Cre09.g402450.t1.2,0.2591170598156831 +Cre09.g402500.t1.2,0.9183019309666056 +Cre09.g402775.t1.1,0.9350927054882661 +Cre09.g402950.t1.1,0.7931070020017725 +Cre09.g403800.t1.2,0.6442432258945399 +Cre09.g403900.t1.2,0.45126294297573133 +Cre09.g404000.t1.1,0.19431288019302229 +Cre09.g405050.t1.2,0.46776375241796 +Cre09.g405800.t1.2,0.22200687859845925 +Cre09.g405850.t1.1,0.10021313558358894 +Cre09.g406200.t1.2,0.895914093910605 +Cre09.g406600.t1.1,6.111289497810166E-06 +Cre09.g406983.t1.1,0.5556838998264406 +Cre09.g407600.t1.2,0.09584663729452231 +Cre09.g408200.t1.2,0.02074589980681063 +Cre09.g409100.t1.2,0.23822693919940874 +Cre09.g409350.t1.2,0.04315214131603207 +Cre09.g409500.t1.2,0.017071706696216566 +"Cre09.g410650.t1.2;Cre09.g410650.t2.1;Cre09.g410650.t3.1",0.4166156666108083 +Cre09.g410700.t1.2,0.0020720021048666612 +"Cre09.g411100.t2.1;Cre09.g411100.t1.2",0.000149570006141575 +Cre09.g411200.t1.2,0.0018822581129906719 +Cre09.g411900.t1.1,0.29708060677031345 +Cre09.g412100.t1.2,0.008910115464664206 +Cre09.g414050.t1.2,0.3927766803609689 +Cre09.g415550.t1.2,0.4626747231288644 +Cre09.g415700.t1.2,0.0316591303563003 +Cre09.g415800.t1.2,0.08008348251939768 +Cre09.g415850.t1.2,0.9099904637542382 +Cre09.g415950.t1.2,0.012916343695372978 +Cre09.g416050.t1.2,0.3223499483356269 +Cre09.g416150.t1.2,0.10334450626764029 +Cre09.g416350.t1.2,0.23114496560063258 +Cre09.g416750.t1.2,0.07471155677197595 +Cre09.g416850.t1.2,0.048923530462333 +Cre09.g417150.t1.2,0.12446243126618839 +Cre09.g417200.t1.2,0.005124456904462615 +Cre-1.g000035.t1.p1,0.0010376528580440247 +Cre-1.g2716952.t1.p1,0.13501313293324957 +Cre-1.g2716955.t1.p1,0.0033236170711476998 +Cre-1.g2716958.t1.p1,0.012236521339167849 +Cre-1.g2716959.t1.p1,0.15325310518045754 +Cre-1.g2716961.t1.p1,0.0017940409201526247 +Cre-1.g2716963.t1.p1,0.0005665127196073991 +Cre-1.g2716972.t1.p1,0.020124937191462022 +Cre-1.g2716979.t1.p1,0.021056223591839895 +Cre-1.g2716983.t1.p1,3.478937972345442E-05 +Cre-1.g2716987.t1.p1,0.0074143026888285795 +Cre-1.g2716989.t1.p1,0.16560220361461098 +Cre-1.g2716990.t1.p1,0.06547354240518641 +Cre-1.g2716994.t1.p1,0.1023923959166962 +Cre-1.g2716997.t1.p1,0.0019821872498473336 +Cre-1.g2717000.t1.p1,0.048040696241444504 +Cre-1.g2717002.t1.p1,0.0010249961395681377 +"Cre-1.g2717005.t1.p1;REV__Cre24.g755297.t1.1;Cre01.g027764.t1.2;REV__Cre07.g352400.t1.2",0.03213197846673044 +Cre-1.g2717006.t1.p1,0.012298335324710141 +Cre-1.g2717008.t1.p1,0.05839512984933304 +Cre-1.g2717009.t1.p1,0.12185265891030927 +Cre-1.g2717010.t1.p1,0.007491717925522279 +Cre-1.g2717015.t1.p1,0.1812404973355004 +Cre-1.g2717017.t1.p1,0.038985933236230785 +Cre-1.g2717021.t1.p1,0.40716814035295124 +Cre-1.g2717030.t1.p1,0.22838741069016055 +Cre-1.g2717034.t1.p1,3.668590198135924E-05 +Cre-1.g2717038.t1.p1,0.0017750258335635588 +Cre-1.g2717040.t1.p1,0.06865858181135143 +Cre-1.g2717041.t1.p1,9.270149505868908E-05 +Cre-1.g2717044.t1.p1,0.03391367801232392 +Cre-1.g2717046.t1.p1,0.7852756505436813 +Cre-1.g2717054.t1.p1,0.11501977570982325 +Cre-1.g2717055.t1.p1,0.0012133084316812148 +Cre-1.g2717056.t1.p1,0.036551923764584604 +Cre-1.g2717057.t1.p1,0.046889967929596876 +Cre-1.g2717058.t1.p1,0.0007724327157399014 +Cre-1.g2717059.t1.p1,0.0004569360861972349 +Cre10.g417700.t1.2,0.002340614643991268 +Cre10.g418100.t1.1,0.7940755077204201 +Cre10.g418450.t1.2,0.9402852112449338 +Cre10.g419950.t1.1,0.03210048943760215 +Cre10.g420350.t1.2,0.621590795546251 +Cre10.g420750.t1.2,0.4783449421179271 +Cre10.g421600.t1.2,0.06849911887599044 +Cre10.g422300.t1.2,0.0005262398815879914 +Cre10.g422600.t1.1,0.02708446238188477 +Cre10.g423250.t1.2,0.21842037411107937 +Cre10.g423500.t1.2,0.03469285059726124 +Cre10.g423650.t1.2,0.00018225977412522631 +Cre10.g424100.t1.2,0.7184204529616516 +Cre10.g424450.t1.2,0.6508049754284253 +Cre10.g425900.t1.2,0.022628225271550326 +Cre10.g425950.t1.2,0.09427276930326299 +Cre10.g427250.t1.2,0.4392844137728069 +Cre10.g427700.t1.2,0.0002523509207676966 +Cre10.g428200.t1.2,0.16386182755516643 +Cre10.g428750.t1.1,0.09232195582132151 +Cre10.g429100.t1.2,0.05146013259263352 +Cre10.g430000.t1.1,0.04228801883338555 +Cre10.g430150.t1.2,0.0050321584008119905 +"Cre10.g430501.t1.1;Cre09.g388430.t1.1;Cre10.g449200.t1.1",0.0002916488453310606 +Cre10.g432800.t1.2,0.002038833771833559 +Cre10.g433000.t1.1,0.6448372663808857 +Cre10.g433600.t1.2,0.9887999828272505 +Cre10.g433950.t1.1,0.009343940386257242 +Cre10.g434200.t1.1,0.14734570568695413 +Cre10.g434450.t1.2,0.17757521528095682 +Cre10.g434750.t1.2,0.16214100068726012 +"Cre10.g435300.t2.1;Cre10.g435300.t1.2",0.13332429844782576 +Cre10.g435800.t1.2,0.010855707140846951 +Cre10.g435850.t1.2,0.12117794603750034 +Cre10.g436050.t1.2,0.0006328780606034012 +Cre10.g436350.t1.1,0.6510987832593205 +Cre10.g436500.t1.2,0.027446304923121057 +Cre10.g436550.t1.2,0.25343078882448244 +Cre10.g439100.t1.2,0.08677804939169885 +Cre10.g439150.t1.2,0.8025917440296424 +Cre10.g439400.t1.1,0.2080302346084195 +Cre10.g439850.t1.2,0.3588794025113 +"Cre10.g439900.t1.2;Cre18.g749547.t1.1",0.009333811688008026 +"Cre10.g440050.t1.2;REV__Cre10.g463700.t1.1",0.02572370547795052 +Cre10.g440450.t1.2,0.33317528396153695 +Cre10.g441200.t1.2,0.10019907260952521 +Cre10.g441400.t1.2,0.008700726987011187 +Cre10.g442700.t1.2,0.007763180781733387 +Cre10.g443250.t1.2,0.16947459447514704 +Cre10.g444700.t1.1,0.029116189269760596 +Cre10.g444800.t1.2,0.06367939425362118 +Cre10.g446550.t1.2,0.12414190978353168 +Cre10.g447100.t1.2,0.008448875207540823 +Cre10.g449550.t1.2,0.005226820740035413 +Cre10.g450400.t1.2,0.24171567475306965 +Cre10.g451900.t1.1,0.9403585296399961 +Cre10.g451950.t1.2,0.0020000476185728644 +Cre10.g452050.t1.2,0.06011766936543256 +Cre10.g452450.t1.2,0.0045469685930523696 +Cre10.g452800.t1.2,0.05804195440693767 +Cre10.g456000.t1.2,0.004907788634758603 +"Cre10.g456050.t2.1;Cre10.g456050.t1.2",0.003445710803521506 +Cre10.g456200.t1.2,0.10164067236958085 +Cre10.g456750.t1.2,0.004122708276966536 +Cre10.g457700.t1.2,0.5326827597041608 +Cre10.g458550.t1.2,0.5864105663013321 +Cre10.g459200.t1.2,0.6737204516474127 +Cre10.g459250.t1.2,0.0016873529062200188 +Cre10.g461050.t1.2,0.006014913373052488 +Cre10.g461250.t1.1,0.5025378991603513 +Cre10.g462250.t1.2,0.044820930861353414 +Cre10.g465550.t1.1,0.2500278555160831 +Cre11.g467350.t1.2,0.17328787482643368 +Cre11.g467400.t1.2,0.08969637565662175 +"Cre11.g467535.t1.1;Cre16.g658850.t1.1",0.5500656345079005 +Cre11.g467547.t1.1,0.9941019777579835 +Cre11.g467550.t1.2,0.39946802833992723 +Cre11.g467569.t1.1,0.008445607931099719 +Cre11.g467573.t1.1,0.03187495713934492 +Cre11.g467578.t1.1,0.0006715781251995789 +Cre11.g467617.t1.1,0.02239086924504816 +Cre11.g467640.t1.1,0.15872359329118804 +Cre11.g467668.t1.1,0.02892630457890653 +Cre11.g467689.t1.1,0.4222163931263183 +Cre11.g467699.t1.1,0.6100625214044604 +Cre11.g467700.t1.1,0.2710583442001373 +Cre11.g467707.t1.1,0.34642184348712035 +"Cre11.g467723.t2.1;Cre11.g467723.t1.1",0.35650963082954046 +Cre11.g467767.t1.1,0.035229887753613465 +Cre11.g467770.t1.1,0.0022925867212629162 +Cre11.g467773.t1.1,0.06217639302359443 +Cre11.g467778.t1.1,0.044979315617401275 +Cre11.g468300.t1.2,0.8711834674196663 +Cre11.g468359.t1.1,0.039023949590160534 +Cre11.g468450.t1.2,0.00105815313602875 +Cre11.g468550.t1.2,0.5184413798919543 +Cre11.g468750.t1.2,0.8628793352226181 +Cre11.g468950.t1.2,0.33972975755836676 +Cre11.g469150.t1.2,0.25434118196793687 +Cre11.g476550.t1.2,0.00036123883770479263 +Cre11.g476750.t1.2,0.02993300089598806 +Cre11.g477300.t1.1,0.13824383341697333 +Cre11.g477850.t1.1,0.0002971290167512741 +Cre11.g477950.t1.1,0.025951550819744748 +"Cre11.g478156.t2.1;Cre11.g478156.t1.1",0.43707280177660834 +Cre11.g478700.t1.2,0.2351190215645529 +Cre11.g479050.t1.2,0.025032524028657223 +Cre11.g479250.t1.2,0.21954635170026693 +Cre11.g479500.t1.2,0.0002609835718245801 +Cre11.g479750.t1.2,0.018702044285378954 +Cre11.g480150.t1.2,0.00017807249594636865 +Cre11.g481126.t1.1,0.6121267489455973 +Cre11.g481450.t1.2,0.006713436734455902 +Cre11.g481500.t1.2,0.08324661178633894 +Cre12.g483650.t1.2,0.47023993707273215 +"Cre12.g483700.t2.1;Cre12.g483700.t1.2",0.000631152300667015 +"Cre12.g483850.t1.2;REV__Cre12.g542100.t1.2;REV__Cre12.g541800.t1.2",0.04697431880526832 +Cre12.g483950.t1.2,0.001230260060137071 +Cre12.g484000.t1.2,0.7214265064872608 +Cre12.g484050.t1.2,0.0034545259204039613 +Cre12.g484200.t1.2,0.41301987032307397 +Cre12.g485150.t1.2,0.1615839827773995 +Cre12.g485800.t1.2,0.015416198560999978 +Cre12.g486100.t1.2,0.06656604188952686 +Cre12.g486300.t1.2,0.09628904397667064 +Cre12.g487100.t1.2,0.05728793145682906 +"Cre12.g488850.t2.1;Cre12.g488850.t1.1",0.4057772581028104 +Cre12.g489153.t1.1,0.0019116102421015135 +Cre12.g489700.t1.2,0.10308590537732655 +Cre12.g490000.t1.2,0.3436607463931989 +Cre12.g490350.t1.1,0.06778252004313594 +Cre12.g490500.t1.2,0.13375756854392026 +Cre12.g492300.t1.2,0.00323166539940751 +Cre12.g492600.t1.2,0.7528264756235731 +Cre12.g492650.t1.2,0.1676250274325138 +Cre12.g493250.t1.2,0.10355884041149777 +Cre12.g493950.t1.2,0.015479546596711025 +Cre12.g494050.t1.2,0.04545912837577615 +Cre12.g494100.t1.1,0.5795951550754568 +Cre12.g494450.t1.2,0.026416027790088004 +Cre12.g494750.t1.2,0.0022280138769867897 +Cre12.g494850.t1.2,0.26135954157098396 +Cre12.g495650.t1.2,0.8568995872444658 +Cre12.g495850.t1.2,0.1019694897204908 +"Cre12.g495951.t2.1;Cre12.g495951.t1.1",0.09774585152519566 +Cre12.g496750.t1.2,0.032494287439277 +"Cre12.g497300.t2.1;Cre12.g497300.t1.2",1.92231834024674E-05 +Cre12.g497700.t1.2,0.150510836275999 +Cre12.g498100.t1.2,0.01913129269699998 +Cre12.g498250.t1.2,0.003967264918828484 +Cre12.g498450.t1.2,0.8164114348144969 +Cre12.g498550.t1.1,7.609516921980308E-05 +Cre12.g498900.t1.2,0.009336064170511582 +Cre12.g498950.t1.2,0.011184005840803367 +Cre12.g499800.t1.2,0.8405814545801982 +Cre12.g500150.t1.1,0.0011777616023570913 +"Cre12.g500500.t2.1;Cre12.g500500.t1.1",0.0001661130209915651 +Cre12.g500950.t1.2,0.578192012631687 +Cre12.g501200.t1.2,0.01991827203928123 +Cre12.g503300.t1.2,0.7955928663160854 +Cre12.g503550.t1.2,0.03375929396337293 +Cre12.g504200.t1.2,0.09904846478443652 +Cre12.g505850.t1.2,3.784926469397036E-05 +Cre12.g507400.t1.2,0.8866041807990448 +"Cre12.g507650.t2.1;Cre12.g507650.t1.2",0.06762209710727234 +Cre12.g508000.t1.1,0.0020349185454946036 +Cre12.g508500.t1.2,0.4569832395979365 +Cre12.g508750.t1.2,0.12288588869243706 +Cre12.g509050.t1.1,0.0006737809099450609 +Cre12.g509650.t1.2,0.0032635603230399823 +Cre12.g509750.t1.2,0.6196449225719556 +Cre12.g510050.t1.2,0.2205475362170526 +Cre12.g510400.t1.1,0.007603947244392612 +Cre12.g510450.t1.2,0.002020357608489176 +Cre12.g510650.t1.2,0.6498410734992257 +Cre12.g510800.t1.2,0.525825901701245 +Cre12.g510850.t1.2,0.00015057759206871246 +Cre12.g511850.t1.2,0.009959966985585211 +Cre12.g511900.t1.2,0.020719750996041286 +Cre12.g512000.t1.1,0.9079128065618667 +Cre12.g512600.t1.2,0.18390224427545165 +"Cre12.g513150.t1.2;REV__Cre09.g395646.t1.2",0.005530494909578243 +Cre12.g513200.t1.2,0.5927162964948204 +Cre12.g513750.t1.1,0.44412562504371833 +Cre12.g513950.t1.2,0.25715555884297325 +Cre12.g514050.t1.2,0.28089145153061246 +Cre12.g514200.t1.2,0.7634092144010081 +Cre12.g514500.t1.2,0.06401802862702555 +Cre12.g514750.t1.2,0.36978955589527895 +Cre12.g514850.t1.2,3.188037498331348E-05 +Cre12.g515650.t1.2,0.019111245950917066 +Cre12.g515850.t1.2,0.00354573125099078 +Cre12.g516200.t1.2,0.0007728362072390027 +Cre12.g516450.t1.2,0.6469668567376539 +Cre12.g517100.t1.1,0.0004358308993572712 +Cre12.g517150.t1.1,0.05363580110923187 +Cre12.g517400.t1.2,0.22610418678949343 +"Cre12.g517900.t1.1;Cre12.g518000.t1.1;Cre12.g518000.t2.1",0.6974101695764652 +Cre12.g519100.t1.2,0.009587400884372205 +"Cre12.g519180.t2.1;Cre12.g519180.t1.1;Cre12.g519180.t3.1;Cre12.g519180.t4.1",0.0016715202121582173 +Cre12.g519300.t1.2,0.03808065971134556 +Cre12.g519350.t1.2,0.08074969803442936 +Cre12.g519900.t1.2,0.014959529972234709 +Cre12.g520500.t1.1,0.0020805114221698062 +Cre12.g520600.t1.2,0.20861136916503042 +Cre12.g522350.t1.2,0.018202406841135083 +Cre12.g522450.t1.2,0.07102645579384805 +Cre12.g522600.t1.2,0.05204660525848315 +Cre12.g523150.t1.2,0.31140940481810997 +Cre12.g523300.t1.2,0.3625417713525849 +Cre12.g523850.t1.2,0.5372562962407607 +Cre12.g524400.t1.2,0.15426001305696546 +Cre12.g525200.t1.2,0.0058607418957157265 +Cre12.g526800.t1.2,0.02427597223104908 +Cre12.g527550.t1.2,0.07598420607536394 +Cre12.g528000.t1.2,0.001660395704522033 +Cre12.g528700.t1.2,0.5146246718241925 +Cre12.g528750.t1.2,5.2865015056191567E-05 +Cre12.g529400.t1.2,0.005306089537126191 +Cre12.g529651.t1.1,0.03276640972973288 +Cre12.g529950.t1.2,0.02613067390390378 +Cre12.g530300.t1.2,0.06617812998241339 +"Cre12.g530650.t1.1;Cre12.g530650.t2.1;Cre12.g530600.t1.1",0.5274709142557916 +Cre12.g531550.t1.2,0.04927783257573792 +Cre12.g532550.t1.1,0.03948164117736508 +Cre12.g533351.t1.1,0.047343882206652754 +Cre12.g533550.t1.1,0.030453925368524315 +Cre12.g534450.t1.1,0.0008459875523633654 +Cre12.g534600.t1.2,0.024013587266166647 +Cre12.g534700.t1.2,0.38682279634211814 +Cre12.g534800.t1.1,0.16328744017731656 +Cre12.g535851.t1.1,0.003025555273781677 +Cre12.g535950.t1.2,0.01856494948936727 +Cre12.g537100.t1.2,0.3700777649916316 +Cre12.g537200.t1.2,0.014416477000240402 +Cre12.g537450.t1.2,0.11033103664475341 +Cre12.g537581.t1.1,0.0018621140460550745 +Cre12.g537800.t1.2,0.0013490725852793872 +"Cre12.g549550.t1.2;Cre12.g542250.t1.1",0.00023331374125290516 +"Cre12.g543350.t3.1;Cre12.g543350.t2.1;Cre12.g543350.t1.1;Cre12.g543400.t1.2",0.007833644145060475 +"Cre12.g544150.t1.2;Cre12.g544114.t1.1",0.029219243928443474 +Cre12.g546050.t1.2,0.006027223346934285 +Cre12.g546550.t1.1,0.03880057858565089 +Cre12.g546600.t1.1,0.016334288637111172 +"Cre12.g548950.t1.2;Cre12.g548400.t1.2",7.050985377093218E-05 +Cre12.g549350.t1.2,0.01583058130825628 +Cre12.g549852.t1.1,0.042808782532231415 +Cre12.g550400.t1.2,0.34167887658504004 +Cre12.g550850.t1.2,0.0009252391858694588 +Cre12.g551800.t1.2,0.7113152029185016 +Cre12.g551900.t1.2,0.4030647971777159 +Cre12.g551950.t1.2,0.024522806601011693 +Cre12.g552200.t1.2,0.14151669005461276 +Cre12.g553250.t1.2,0.20001776523465453 +Cre12.g554800.t1.2,0.10636146438417104 +Cre12.g555250.t1.2,0.22230966218133946 +Cre12.g556050.t1.2,0.06972168869581319 +Cre12.g556250.t1.2,0.008905773420884973 +Cre12.g557600.t1.1,0.008258494953708562 +Cre12.g558100.t1.2,0.02194653326091589 +Cre12.g558900.t1.2,0.4303454927349305 +Cre12.g559250.t1.2,0.09356861047430032 +Cre12.g560150.t1.2,0.013322822113849176 +"Cre12.g560300.t3.1;Cre12.g560300.t2.1;Cre12.g560300.t1.2",0.03437561314280502 +Cre12.g560950.t1.2,0.020826038250702648 +Cre13.g562850.t1.2,0.18214593346518515 +Cre13.g564250.t1.2,0.004277869226101405 +"Cre13.g565450.t1.2;Cre13.g565321.t1.1",0.3203923832911084 +Cre13.g565800.t1.2,0.00042329143562547245 +Cre13.g565850.t1.1,0.11438521308754183 +"Cre13.g566000.t1.2;REV__Cre01.g008500.t1.2",0.000891148498674361 +Cre13.g566050.t1.2,0.1381143343410003 +"Cre13.g566650.t2.1;Cre13.g566650.t1.2",0.0008225258980102374 +Cre13.g566700.t1.1,0.19855823234490888 +Cre13.g567600.t1.2,0.5568968319241736 +Cre13.g567700.t1.2,0.020015796307000677 +"Cre13.g567850.t1.2;REV__Cre03.g197900.t1.1",0.09183824406577878 +Cre13.g567950.t1.2,0.017991627926072753 +Cre13.g568650.t1.2,0.012398190376458285 +Cre13.g568800.t1.2,0.23097182358511925 +Cre13.g568900.t1.2,0.01476498474738519 +Cre13.g571500.t1.2,0.004892971872931647 +"Cre13.g572900.t2.1;Cre13.g572900.t1.1",0.2348181950487842 +Cre13.g573250.t1.2,0.015941208626709107 +Cre13.g573351.t1.2,0.015471619596421293 +Cre13.g573400.t1.2,0.32993914023229887 +Cre13.g577100.t1.2,0.44685128858785195 +Cre13.g578451.t1.1,0.07407682307862291 +Cre13.g579550.t1.1,0.37976469924578615 +Cre13.g581600.t1.2,0.3483357001764109 +Cre13.g581650.t1.2,0.0037634166628035537 +Cre13.g583550.t1.2,0.0009147767530594582 +Cre13.g584850.t1.1,0.10330287752011721 +Cre13.g585150.t1.2,0.48168877374168817 +Cre13.g585900.t1.2,0.3014936984662484 +Cre13.g586300.t1.2,0.10394108815147618 +Cre13.g587050.t1.2,0.001962572817605368 +Cre13.g588100.t1.2,0.12780454823068693 +Cre13.g590650.t1.2,0.0013790038541927482 +Cre13.g592200.t1.2,6.820048097377907E-07 +Cre13.g592450.t1.2,0.418068263303375 +Cre13.g602350.t1.2,0.01884176590235661 +Cre13.g602450.t1.2,0.11604578334699112 +Cre13.g602650.t1.2,0.000756767699882728 +Cre13.g603225.t1.1,0.08451481153836327 +Cre13.g603500.t1.2,0.008387317560386917 +"Cre13.g603700.t1.2;Cre12.g542900.t1.1",0.11098163580202258 +Cre13.g603900.t1.2,0.7690189047907425 +"Cre13.g604650.t2.1;Cre13.g604650.t1.2",0.011104624400556373 +Cre13.g605150.t1.2,0.005255398590922712 +Cre13.g605650.t1.2,0.016769747077441163 +Cre13.g607050.t1.2,0.09503257135731306 +Cre13.g608000.t1.2,0.13519248054790656 +Cre14.g610950.t1.2,0.0750952163567625 +"Cre14.g612450.t1.2;REV__Cre05.g240650.t1.2",0.011026109670251083 +Cre14.g612800.t1.2,0.00014403697523782756 +Cre14.g614300.t1.2,0.9042208271242598 +"Cre14.g614900.t2.1;Cre14.g614900.t1.2",0.9259636220972549 +Cre14.g615950.t1.1,0.00044326269445615907 +Cre14.g616100.t1.1,0.19527966894914833 +Cre14.g616600.t1.2,0.002388859530965566 +Cre14.g617450.t1.2,0.06149410731751717 +Cre14.g617826.t1.1,0.31839247434119144 +Cre14.g617900.t1.2,0.0005853283668495468 +Cre14.g619100.t1.2,0.8410889353134825 +Cre14.g619133.t1.1,0.0581838847713243 +Cre14.g619166.t1.1,0.0776959955421388 +"Cre14.g619550.t2.1;Cre14.g619550.t1.2",0.33580671457932654 +"Cre14.g620600.t1.2;Cre14.g620702.t1.1",0.07892600957927995 +Cre14.g621450.t1.2,6.384189507135929E-05 +Cre14.g621650.t1.1,0.02768681501114231 +Cre14.g621751.t1.1,0.061758665480105515 +Cre14.g623000.t1.1,0.43285279813419086 +Cre14.g624201.t1.1,0.07632612308079299 +Cre14.g625400.t1.1,0.38533069539150744 +"Cre14.g625750.t2.1;Cre14.g625750.t1.2",0.0268450565181666 +Cre14.g626900.t1.2,0.008377210898089515 +Cre14.g627850.t1.2,0.5362911547891034 +Cre14.g628100.t1.2,0.007077310243333024 +Cre14.g629550.t1.2,0.9976246376896087 +Cre14.g630100.t1.2,0.0006324018661594266 +Cre14.g630400.t1.2,0.024146991526278357 +"Cre14.g630847.t1.1;Cre14.g630835.t1.1",0.7875715565551928 +Cre14.g632775.t1.1,0.2674313356450533 +Cre14.g632950.t1.2,0.976553187730453 +Cre14.g633750.t1.1,0.005072831869314509 +Cre15.g635600.t1.2,0.0897774427531961 +"Cre15.g635650.t2.1;Cre15.g635650.t1.2",7.114909633232358E-06 +"Cre15.g635850.t2.1;Cre15.g635850.t1.2",0.31635816068790334 +Cre15.g636050.t1.2,0.4995380783377559 +Cre15.g638400.t1.2,0.04173897469995859 +Cre15.g638500.t1.2,0.7418546816202061 +"Cre15.g639150.t2.1;Cre15.g639150.t1.1",0.920885525026684 +Cre15.g643550.t1.2,0.9405819711037053 +Cre15.g643600.t1.2,0.6587673871578602 +Cre15.g644051.t1.1,0.06258481912590175 +"Cre16.g650550.t2.1;Cre16.g650550.t1.2",0.3736967861331407 +Cre16.g651550.t1.2,0.4316301291604183 +Cre16.g651750.t1.2,0.017189466519681895 +Cre16.g651923.t1.2,0.14509116655655196 +Cre16.g652550.t1.2,0.004509336775152084 +Cre16.g654500.t1.1,0.003974821724485267 +Cre16.g655150.t1.2,0.9582826803292921 +Cre16.g656400.t1.2,0.08154313214240845 +Cre16.g658650.t1.1,0.01018487576373458 +Cre16.g659350.t1.2,0.13418070409397875 +Cre16.g659950.t1.1,0.0001447544596842043 +Cre16.g660150.t1.2,0.003900512446847193 +Cre16.g661050.t1.2,0.08379804905141386 +Cre16.g661350.t1.2,0.04783496995034652 +"Cre16.g661750.t1.2;Cre16.g661850.t1.1",0.005979690449383521 +Cre16.g662600.t1.2,0.0059594468843833 +Cre16.g662702.t1.1,0.005981079659746813 +Cre16.g663500.t1.2,0.13928672836256972 +Cre16.g663900.t1.2,0.0012919737300156608 +Cre16.g664550.t1.2,0.934250979907556 +Cre16.g665250.t1.2,0.38946874974914836 +Cre16.g669650.t1.2,0.40327679068573596 +"Cre16.g670300.t2.1;Cre16.g670300.t1.2",0.0928110858565927 +Cre16.g671900.t1.1,0.750765301493468 +Cre16.g672385.t1.1,0.675670791507613 +Cre16.g672650.t1.2,0.061704867811822384 +Cre16.g672750.t1.2,0.03631953066939242 +Cre16.g672800.t1.2,0.7394022965644169 +Cre16.g673550.t1.1,0.06899798044005157 +Cre16.g673650.t1.1,0.014404756880763746 +Cre16.g673729.t1.1,0.0012017363262232456 +"Cre16.g673852.t1.1;Cre11.g476325.t1.1;REV__Cre12.g522700.t1.2",0.2571955050934118 +"Cre16.g675550.t3.1;Cre16.g675550.t2.1;Cre16.g675550.t1.2",0.9027958878431184 +Cre16.g675637.t1.1,0.9851519754884237 +Cre16.g675650.t1.2,0.4989942721037135 +Cre16.g676197.t1.1,0.5559126873031717 +Cre16.g676314.t1.1,0.5675759783948793 +Cre16.g677000.t1.2,0.02935702427167384 +Cre16.g677026.t1.1,0.9243095941927538 +Cre16.g677450.t1.2,0.39303202050885755 +Cre16.g677500.t1.2,0.3516567301000628 +Cre16.g679500.t1.2,0.10712512966420586 +Cre16.g679600.t1.2,0.5279303850469765 +"Cre16.g679800.t1.2;Cre16.g679750.t1.2",0.03735910638286718 +Cre16.g680000.t1.2,0.36750128858715236 +Cre16.g680700.t1.2,0.00043307641391976404 +Cre16.g682725.t1.1,0.0011218673692979916 +Cre16.g684150.t1.2,0.15339894671645604 +Cre16.g684300.t1.2,0.0047221440356279175 +"Cre16.g684350.t1.2;Cre16.g684550.t1.1",0.19529181691005124 +Cre16.g685400.t1.2,0.0624599651495912 +Cre16.g685550.t1.2,0.002634439143846044 +Cre16.g685901.t1.1,0.8668293685872175 +Cre16.g687300.t1.2,0.025865162960922224 +Cre16.g687900.t1.2,0.143381713964015 +Cre16.g688050.t1.1,0.7867429835181807 +Cre16.g688550.t1.2,0.4276658617928746 +Cre16.g689087.t1.1,0.002509049492389654 +Cre16.g689871.t1.1,0.2005709926415453 +"Cre16.g690431.t2.1;Cre16.g690431.t1.1",0.1024923768726258 +Cre16.g691000.t1.2,3.773850617028174E-05 +Cre16.g691800.t1.1,0.009829943326652291 +Cre16.g691850.t1.2,0.06349012493872357 +Cre16.g692901.t1.1,0.11018968089463843 +"Cre16.g693600.t2.1;Cre16.g693600.t1.2",0.003373138138073939 +Cre16.g694850.t1.2,0.27956717970777145 +Cre16.g695050.t1.2,0.9703439738274886 +Cre16.g695100.t1.1,0.08825440607493804 +Cre16.g696000.t1.2,0.022236116738741263 +"Cre17.g696250.t1.1;Cre17.g696250.t2.1",0.06002861079833455 +Cre17.g696850.t1.2,0.025129461428768197 +Cre17.g697450.t1.2,0.01294589811628133 +Cre17.g698000.t1.2,0.0925385901981662 +Cre17.g698450.t1.2,0.000991238663331683 +"Cre17.g699000.t2.1;Cre17.g699000.t1.2",0.12864541069112545 +"Cre17.g701200.t2.1;Cre17.g701200.t1.2",0.015294608579448754 +Cre17.g701500.t1.2,0.0049978514463583186 +Cre17.g701650.t1.2,0.005398706338425319 +"Cre17.g701700.t2.1;Cre17.g701700.t1.2",0.00214649126117314 +Cre17.g702200.t1.2,3.0249934189086088E-05 +Cre17.g702750.t1.2,0.8226276621520903 +Cre17.g703700.t1.1,0.14789128058636614 +Cre17.g704850.t1.2,0.024151092592696877 +Cre17.g705000.t1.2,0.18948202717879492 +Cre17.g705400.t1.2,0.7647572813919501 +Cre17.g706600.t1.2,0.20694693189829114 +Cre17.g707900.t1.2,0.032613698253015105 +Cre17.g708300.t1.2,0.133740857534436 +Cre17.g708750.t1.2,0.14155330326198357 +Cre17.g708800.t1.1,0.18506839101836992 +Cre17.g710150.t1.2,0.46924500043294426 +Cre17.g711650.t1.2,0.002773541981214688 +Cre17.g712100.t1.2,0.0227610722877436 +"Cre17.g713200.t1.1;Cre17.g713350.t1.2",0.4273656977352198 +"Cre17.g713450.t1.2;Cre17.g714050.t1.2;Cre17.g714550.t1.2",5.279272181013539E-05 +Cre17.g715250.t1.2,0.9960599293276831 +Cre17.g715500.t1.2,0.0009534738808988905 +Cre17.g719000.t1.2,0.0068087310255831035 +Cre17.g719900.t1.2,0.01311515322510659 +Cre17.g720050.t1.2,0.42025129497275104 +Cre17.g720250.t1.2,0.0021086230323250753 +Cre17.g720450.t1.1,0.18719182034889256 +Cre17.g721300.t1.2,0.8768617571770446 +Cre17.g721500.t1.2,0.052208501299876045 +Cre17.g722150.t1.2,0.027432520823684525 +Cre17.g722750.t1.2,0.07971517959551377 +Cre17.g723250.t1.2,0.4311458556263037 +Cre17.g723650.t1.2,0.7244788700635438 +Cre17.g724200.t1.2,0.6196507079143112 +Cre17.g724300.t1.2,0.004856397313798304 +Cre17.g724350.t1.2,0.1812071748669113 +"Cre17.g725350.t1.1;Cre17.g725350.t2.1",0.4315987148697873 +Cre17.g726750.t1.2,0.016613739066886016 +Cre17.g727950.t1.1,0.18729988394264838 +Cre17.g728800.t1.2,0.6932870512621161 +Cre17.g729150.t1.2,0.3339804871118093 +Cre17.g729800.t1.2,0.28662301758720465 +Cre17.g732300.t1.2,0.9168539303137834 +Cre17.g734100.t1.2,0.015598209113972139 +Cre17.g734200.t1.2,0.05929418611566451 +"Cre17.g734300.t2.1;Cre17.g734300.t1.1",0.620675376632533 +Cre17.g734400.t1.1,0.27888922187454845 +Cre17.g734450.t1.2,0.0038317053098204656 +Cre17.g734500.t1.2,0.3081990955644711 +Cre17.g734516.t1.1,0.9023884280196787 +"Cre17.g734548.t1.1;Cre10.g424750.t1.2",0.20206417265815083 +Cre17.g734612.t1.1,0.9477781855439821 +"Cre17.g734900.t2.1;Cre17.g734900.t1.2",0.005285433439048277 +Cre17.g737250.t1.2,0.23837124337167181 +Cre17.g738300.t1.2,0.08229748082251676 +Cre17.g741000.t1.2,0.06388618778124466 +Cre17.g741450.t1.2,0.00029348124943230647 +Cre17.g741850.t1.2,0.03715465954397912 +Cre17.g742200.t1.1,0.4171245754275714 +Cre17.g742300.t1.1,0.030043908419290024 +Cre17.g742450.t1.1,0.31880659335978434 +Cre17.g743897.t1.1,0.006072351396641692 +Cre17.g744147.t1.1,0.3488977369418298 +"Cre17.g746997.t1.1;Cre16.g669150.t1.2;Cre16.g669125.t1.1",0.0005623656610727092 +"Cre18.g749447.t2.1;Cre18.g749447.t1.1",0.8643417814882589 +"Cre18.g749497.t1.1;Cre18.g749647.t1.1",0.043730206994730715 +"Cre18.g749847.t2.1;Cre18.g749847.t1.1",0.011437326301298567 +Cre18.g750047.t1.1,2.983719158633491E-06 +"Cre19.g750547.t4.1;Cre19.g750547.t3.1;Cre19.g750547.t2.1;Cre19.g750547.t1.1",0.9110431963052381 +"Cre19.g751247.t2.1;Cre19.g751247.t1.1",0.13730507655605306 +Cre-2.g801495.t1.p1,0.9659703297160163 +Cre26.g756797.t1.1,0.34487460662600067 +Cre43.g760497.t1.1,0.42234799600983486 +"Cre48.g761197.t1.1;Cre01.g050316.t2.1;Cre01.g050316.t1.1",0.025144830438096122 From 908ce3f309fb77dd806770642cc894add21b43a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20M=C3=BChlhaus?= Date: Sun, 10 Aug 2025 11:31:38 +0200 Subject: [PATCH 098/121] Update Normalizaiton module towards using FsMath --- src/FSharp.Stats/FSharp.Stats.fsproj | 1 + src/FSharp.Stats/Signal/Normalization.fs | 241 ++++++++++++----------- src/FSharp.Stats/Vector.fs | 240 ++++++++++++++++++++++ 3 files changed, 368 insertions(+), 114 deletions(-) create mode 100644 src/FSharp.Stats/Vector.fs diff --git a/src/FSharp.Stats/FSharp.Stats.fsproj b/src/FSharp.Stats/FSharp.Stats.fsproj index bc175d2b9..c7dc2ee1f 100644 --- a/src/FSharp.Stats/FSharp.Stats.fsproj +++ b/src/FSharp.Stats/FSharp.Stats.fsproj @@ -40,6 +40,7 @@ + diff --git a/src/FSharp.Stats/Signal/Normalization.fs b/src/FSharp.Stats/Signal/Normalization.fs index de46e6568..bfa942699 100644 --- a/src/FSharp.Stats/Signal/Normalization.fs +++ b/src/FSharp.Stats/Signal/Normalization.fs @@ -46,122 +46,135 @@ module Normalization = NormFunction : Matrix -> Matrix } with static member Create cf nd f = {CorrFactors=cf;NormedData=nd;NormFunction=f} - ///// - ///// Median of ratios normalization As used by Deseq2, see: https://github.com/hbctraining/DGE_workshop/blob/master/lessons/02_DGE_count_normalization.md . - ///// Rows are genes, columns are samples - ///// - ///// The transformation function is applied on all values of the matrix before calculating the normalization factors. - ///// data matrix with columns as features (samples,time points) and rows as measured entities (genes,proteins). - ///// Normalized data matrix with correction factors and normalization function. - ///// - ///// - ///// // raw data with proteins as rows and samples as columns - ///// let myData = Matrix.init 500 5 (fun _ _ -> rnd.NextDouble()) - ///// let normedData = Normalization.medianOfRatiosBy (fun x -> ln (x+1)) myData - ///// - ///// - //let medianOfRatiosBy (f: float -> float) (data: Matrix) = - // let sampleWiseCorrectionFactors = - // data - // |> Matrix.mapiRows (fun _ v -> - // let v = Array.map f v - // let geometricMean = Seq.meanGeometric v - // Array.map (fun s -> s / geometricMean) v - // ) - // |> Matrix.mapiCols (fun _ (v:Vector) -> Seq.median v) - // let normData m = - // m - // |> Matrix.mapi (fun r c v -> - // v / sampleWiseCorrectionFactors.[c] - // ) - // MorResult.Create sampleWiseCorrectionFactors (normData data) normData + /// + /// Median of ratios normalization As used by Deseq2, see: https://github.com/hbctraining/DGE_workshop/blob/master/lessons/02_DGE_count_normalization.md . + /// Rows are genes, columns are samples + /// + /// The transformation function is applied on all values of the matrix before calculating the normalization factors. + /// data matrix with columns as features (samples,time points) and rows as measured entities (genes,proteins). + /// Normalized data matrix with correction factors and normalization function. + /// + /// + /// // raw data with proteins as rows and samples as columns + /// let myData = Matrix.init 500 5 (fun _ _ -> rnd.NextDouble()) + /// let normedData = Normalization.medianOfRatiosBy (fun x -> ln (x+1)) myData + /// + /// + let medianOfRatiosBy (f: float -> float) (data: Matrix) = + let sampleWiseCorrectionFactors = + data + |> Matrix.mapiRows (fun _ v -> + let v = Array.map f v + let geometricMean = Seq.meanGeometric v + Array.map (fun s -> s / geometricMean) v + ) + |> Matrix.getCols + |> Array.map (fun (v:Vector) -> Vector.median v) + + let normData m = + m + |> Matrix.mapi (fun r c v -> + v / sampleWiseCorrectionFactors.[c] + ) + MorResult.Create sampleWiseCorrectionFactors (normData data) normData - ///// - ///// Median of ratios normalization As used by Deseq2, see: https://github.com/hbctraining/DGE_workshop/blob/master/lessons/02_DGE_count_normalization.md . - ///// Rows are genes, columns are samples - ///// - ///// data matrix with columns as features (samples,time points) and rows as measured entities (genes,proteins). - ///// Normalized data matrix with correction factors and normalization function. - ///// - ///// - ///// // raw data with proteins as rows and samples as columns - ///// let myData = Matrix.init 500 5 (fun _ _ -> rnd.NextDouble()) - ///// let normedData = Normalization.medianOfRatios myData - ///// - ///// - //let medianOfRatios (data:Matrix) = - // medianOfRatiosBy id data + /// + /// Median of ratios normalization As used by Deseq2, see: https://github.com/hbctraining/DGE_workshop/blob/master/lessons/02_DGE_count_normalization.md . + /// Rows are genes, columns are samples + /// + /// data matrix with columns as features (samples,time points) and rows as measured entities (genes,proteins). + /// Normalized data matrix with correction factors and normalization function. + /// + /// + /// // raw data with proteins as rows and samples as columns + /// let myData = Matrix.init 500 5 (fun _ _ -> rnd.NextDouble()) + /// let normedData = Normalization.medianOfRatios myData + /// + /// + let medianOfRatios (data:Matrix) = + medianOfRatiosBy id data - ///// - ///// Median of ratios normalization As used by Deseq2, see: https://github.com/hbctraining/DGE_workshop/blob/master/lessons/02_DGE_count_normalization.md . - ///// Columns are genes, rows are samples - ///// - ///// The transformation function is applied on all values of the matrix before calculating the normalization factors. - ///// data matrix with columns as measured entities and rows as features (samples,time points) (genes,proteins). - ///// Normalized data matrix with correction factors and normalization function. - ///// - ///// - ///// // raw data with proteins as columns and samples as rows - ///// let myData = Matrix.init 5 500 (fun _ _ -> rnd.NextDouble()) - ///// let normedData = Normalization.medianOfRatiosWideBy (fun x -> ln (x+1)) myData - ///// - ///// - //let medianOfRatiosWideBy (f: float -> float) (data:Matrix) = - // let sampleWiseCorrectionFactors = - // data - // |> Matrix.mapiCols (fun _ v -> - // let v = Vector.map f v - // let geometricMean = Seq.meanGeometric v - // Vector.map (fun s -> s / geometricMean) v - // ) - // |> Matrix.ofCols - // |> Matrix.mapiRows (fun _ v -> Seq.median v) - // let normData m = - // m - // |> Matrix.mapi (fun r c v -> - // v / sampleWiseCorrectionFactors.[r] - // ) - // MorResult.Create sampleWiseCorrectionFactors (normData data) normData + /// + /// Median of ratios normalization As used by Deseq2, see: https://github.com/hbctraining/DGE_workshop/blob/master/lessons/02_DGE_count_normalization.md . + /// Columns are genes, rows are samples + /// + /// The transformation function is applied on all values of the matrix before calculating the normalization factors. + /// data matrix with columns as measured entities and rows as features (samples,time points) (genes,proteins). + /// Normalized data matrix with correction factors and normalization function. + /// + /// + /// // raw data with proteins as columns and samples as rows + /// let myData = Matrix.init 5 500 (fun _ _ -> rnd.NextDouble()) + /// let normedData = Normalization.medianOfRatiosWideBy (fun x -> ln (x+1)) myData + /// + /// + let medianOfRatiosWideBy (f: float -> float) (data:Matrix) = + let sampleWiseCorrectionFactors = + data + |> Matrix.mapiCols (fun _ v -> + let v = Array.map f v + let geometricMean = Seq.meanGeometric v + Array.map (fun s -> s / geometricMean) v + ) + |> Matrix.getCols + |> Array.map (fun v -> Vector.median v) + let normData m = + m + |> Matrix.mapi (fun r c v -> + v / sampleWiseCorrectionFactors.[r] + ) + MorResult.Create sampleWiseCorrectionFactors (normData data) normData - ///// - ///// Median of ratios normalization As used by Deseq2, see: https://github.com/hbctraining/DGE_workshop/blob/master/lessons/02_DGE_count_normalization.md . - ///// Columns are genes, rows are samples - ///// - ///// data matrix with columns as measured entities and rows as features (samples,time points) (genes,proteins). - ///// Normalized data matrix with correction factors and normalization function. - ///// - ///// - ///// // raw data with proteins as columns and samples as rows - ///// let myData = Matrix.init 5 500 (fun _ _ -> rnd.NextDouble()) - ///// let normedData = Normalization.medianOfRatiosWide myData - ///// - ///// - //let medianOfRatiosWide (data:Matrix) = - // medianOfRatiosWideBy id data + /// + /// Median of ratios normalization As used by Deseq2, see: https://github.com/hbctraining/DGE_workshop/blob/master/lessons/02_DGE_count_normalization.md . + /// Columns are genes, rows are samples + /// + /// data matrix with columns as measured entities and rows as features (samples,time points) (genes,proteins). + /// Normalized data matrix with correction factors and normalization function. + /// + /// + /// // raw data with proteins as columns and samples as rows + /// let myData = Matrix.init 5 500 (fun _ _ -> rnd.NextDouble()) + /// let normedData = Normalization.medianOfRatiosWide myData + /// + /// + let medianOfRatiosWide (data:Matrix) = + medianOfRatiosWideBy id data - ///// - ///// Quantile normalization with equal number of elements (rows) for each sample (column). - ///// Column mean and column standard deviation are qual after normalization. - ///// Rows are genes, columns are samples. - ///// - ///// data matrix with columns as measured entities and rows as features (samples,time points) (genes,proteins). - ///// Normalized data matrix. - ///// - ///// - ///// // raw data with proteins as rows and samples as columns - ///// let myData = Matrix.init 500 5 (fun _ _ -> rnd.NextDouble()) - ///// let normedData = Normalization.quantile myData - ///// - ///// - //let quantile (data:Matrix) = - // data - // |> Matrix.mapCols (Seq.indexed >> Seq.sortBy snd) - // |> Matrix.Generic.ofColSeq - // |> Matrix.Generic.mapRows (fun row -> - // let avg = Seq.meanBy snd row - // row |> RowVector.Generic.map (fun (i,_) -> i,avg) - // ) - // |> Matrix.Generic.ofSeq - // |> Matrix.Generic.mapCols (Seq.sortBy fst >> Seq.map snd >> vector) - // |> Matrix.ofCols + /// + /// Quantile normalization with equal number of elements (rows) for each sample (column). + /// Column mean and column standard deviation are qual after normalization. + /// Rows are genes, columns are samples. + /// + /// data matrix with columns as measured entities and rows as features (samples,time points) (genes,proteins). + /// Normalized data matrix. + /// + /// + /// // raw data with proteins as rows and samples as columns + /// let myData = Matrix.init 500 5 (fun _ _ -> rnd.NextDouble()) + /// let normedData = Normalization.quantile myData + /// + /// + let quantile (data:Matrix) = + data + |> Matrix.getCols + |> Array.map (fun v -> + v |> Seq.indexed |> Seq.sortBy snd |> Array.ofSeq + ) + |> JaggedArray.transpose + |> Array.map (fun row -> + + let avg = Seq.meanBy snd row + row |> Array.map (fun (i,_) -> i,avg) + ) + |> JaggedArray.transpose + |> Array.map (Seq.sortBy fst >> Seq.map snd >> Vector.ofSeq) + |> Matrix.ofCols + //|> Matrix.Generic.mapRows (fun row -> + // let avg = Seq.meanBy snd row + // row |> RowVector.Generic.map (fun (i,_) -> i,avg) + // ) + //|> Matrix.Generic.ofSeq + //|> Matrix.Generic.mapCols (Seq.sortBy fst >> Seq.map snd >> vector) + //|> Matrix.ofCols diff --git a/src/FSharp.Stats/Vector.fs b/src/FSharp.Stats/Vector.fs new file mode 100644 index 000000000..8026d1acc --- /dev/null +++ b/src/FSharp.Stats/Vector.fs @@ -0,0 +1,240 @@ +namespace FSharp.Stats + +open FsMath +open System + +[] +module Vector = + + + //---------------------------------------------------------------------------- + // Stats + //---------------------------------------------------------------------------- + + + /// Creates a vector from a sequence + let interval (items:Vector<'T>) = + let rec loop index (minimum) (maximum) = + if index < items.Length then + let current = items.[index] + loop (index+1) (min current minimum) (max current maximum) + else + Interval.CreateClosed<_> (minimum,maximum) + //Init by fist value + if items.Length > 1 then + loop 1 items.[0] items.[0] + else + Interval.Empty + + ///// Computes the population mean (Normalized by N) + ///// + ///// + ///// + ///// + ///// + ///// + ///// + //let inline mean (items:Vector<'T>) = + // Vector.mean items + + + /// Computes the sample median + /// + /// + /// + /// + /// + /// + /// + let inline median (items:Vector) = + items |> Array.median + + /// Median absolute deviation (MAD) + /// + /// + /// + /// + /// + /// + /// + let medianAbsoluteDev (items:Vector) = + items |> Array.medianAbsoluteDev + + + /// Returns SummaryStats of vector with N, mean, sum-of-squares, minimum and maximum + /// + /// + /// + /// + /// + /// + /// + let inline stats (items:Vector<'T>) = + let zero = LanguagePrimitives.GenericZero< 'T > + let one = LanguagePrimitives.GenericOne< 'T > + + let rec loop index n (minimum) (maximum) m1 m2 = + if index < items.Length then + let current = items.[index] + let delta = current - m1 + let deltaN = (delta / n) + //let delta_n2 = deltaN * deltaN + let m1' = m1 + deltaN + let m2' = m2 + delta * deltaN * (n-one) + loop (index+1) (n + one) (min current minimum) (max current maximum) m1' m2' + else + SummaryStats.createSummaryStats (n-one) m1 m2 minimum maximum + //Init by fist value + if items.Length > 1 then + loop 0 one items.[0] items.[0] zero zero + else + let uNan = zero / zero + SummaryStats.createSummaryStats zero uNan uNan uNan uNan + + + /// Returns an estimator of the population covariance of two random variables v1 and v2 + /// + /// + /// + /// + /// + /// + /// + /// + let covPopulation (v1:Vector) (v2:Vector) = + Seq.covPopulation v1 v2 + + /// Returns the sample covariance of two random variables v1 and v2. (Bessel's correction by N-1) + /// + /// + /// + /// + /// + /// + /// + /// + let cov (v1:Vector) (v2:Vector) = + Seq.cov v1 v2 + + /// calculates the sample means with a given number of replicates present in the sequence + /// + /// + /// + /// + /// + /// + /// + /// + let getMeanOfReplicates rep (data:Vector) = + Seq.getMeanOfReplicates rep data + |> Vector.ofSeq + + /// calculates the sample standard deviations with a given number of replicates present in the sequence + /// + /// + /// + /// + /// + /// + /// + /// + let getStDevOfReplicates rep (data:Vector) = + Seq.getStDevOfReplicates rep data + |> Vector.ofSeq + + /// calculates the coefficient of variation based on the sample standard deviations with a given number of replicates present in the sequence + /// + /// + /// + /// + /// + /// + /// + /// + let getCvOfReplicates rep (data:Vector) = + Seq.getCvOfReplicates rep data + |> Vector.ofSeq + + ///// Splits a vector according to given indices. Returns (vector including values according to indices, rest) + ///// + ///// + ///// + ///// + ///// + ///// + ///// + ///// + //let splitVector (indices:int[]) (v:Vector<_>) = + // let len = v.Length + // //let nv = Vector.Generic.zero (len-indices.Length) + // //let nvi = Vector.Generic.zero indices.Length + // let nv = VG.zeroCreate (len-indices.Length) + // let nvi = VG.zeroCreate indices.Length + // indices |> Array.sortInPlace + // let rec loop ni nii i = + // match i with + // | i when i < 0 -> nvi,nv + // | i when nii >= 0 && i = indices.[nii] -> + // nvi.[nii] <- v.[i] + // loop (ni) (nii-1) (i-1) + // | _ -> + // nv.[ni] <- v.[i] + // loop (ni-1) (nii) (i-1) + + // loop (len-1-indices.Length) (indices.Length-1) (len-1) + + + /// Module to compute common statistical measure on + module SummaryStats = + + /// Returns SummaryStats of vector with N, mean, sum-of-squares, minimum and maximum + /// + /// + /// + /// + /// + /// + /// + let ofVector (a:Vector<'a>) = stats a + + + + + + + + + +//[] +//module VectorExtension = + +// type Vector<'T when 'T :> Numerics.INumber<'T>> with +// member x.Norm = Vector.Generic.norm x +// member x.Copy () = Vector.Generic.copy x + +// /// +// /// Creates an vector with values between a given interval +// /// +// /// start value (is included) +// /// end value (by default is included) +// /// sets the number of elements in the vector. If not set, stepsize = 1. +// /// If false, the vector does not contain the stop value +// static member linspace(start:float,stop:float,num:int,?IncludeEndpoint:bool) : vector = + +// let includeEndpoint = defaultArg IncludeEndpoint true + +// Seq.linspace(start,stop,num,includeEndpoint) |> Vector.ofSeq + +// /// +// /// Creates a geometric vector of floats with values between a given interval. +// /// +// /// start value (is included) +// /// end value (by default is included) +// /// sets the number of elements in the vector. Defaults to 50. +// /// If false, the vector does not contain the stop value. Defaults to true. +// static member geomspace(start:float,stop:float,num:int,?IncludeEndpoint:bool) : vector = +// let includeEndpoint = defaultArg IncludeEndpoint true + +// Seq.geomspace (start, stop ,num, includeEndpoint) +// |> Vector.ofSeq + From bd10bfe2b286372f48dd232cc7914743799fe499 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20M=C3=BChlhaus?= Date: Sun, 10 Aug 2025 11:31:59 +0200 Subject: [PATCH 099/121] Update docs using FsMath --- FSharp.Stats.sln | 6 +- docs/ComparisonMetrics.fsx | 4 +- docs/Correlation.fsx | 9 +- docs/Covariance.fsx | 2 +- docs/CrossValidation.fsx | 34 ++-- docs/Distributions.fsx | 4 +- docs/Fitting.fsx | 7 +- docs/GeneralisedLinearModels.fsx | 312 ------------------------------- docs/GoodnessOfFit.fsx | 9 +- docs/GrowthCurve.fsx | 16 +- docs/Interpolation.fsx | 6 +- docs/Normalization.fsx | 15 +- docs/Optimization.fsx | 8 +- 13 files changed, 63 insertions(+), 369 deletions(-) delete mode 100644 docs/GeneralisedLinearModels.fsx diff --git a/FSharp.Stats.sln b/FSharp.Stats.sln index d1b9bdc5c..2c18d0e23 100644 --- a/FSharp.Stats.sln +++ b/FSharp.Stats.sln @@ -56,17 +56,19 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "docs", "docs", "{23F9FB2E-6 docs\Interpolation.fsx = docs\Interpolation.fsx docs\Intervals.fsx = docs\Intervals.fsx docs\Normalization.fsx = docs\Normalization.fsx + docs\NuGet.config = docs\NuGet.config docs\Optimization.fsx = docs\Optimization.fsx docs\Quantiles.fsx = docs\Quantiles.fsx docs\Rank.fsx = docs\Rank.fsx docs\Signal.fsx = docs\Signal.fsx docs\Testing.fsx = docs\Testing.fsx - docs\_head.html = docs\_head.html + docs\_template.html = docs\_template.html + docs\_template.ipynb = docs\_template.ipynb EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "content", "content", "{50E3E339-AA4D-4FD2-8791-DEBD2EBF0504}" ProjectSection(SolutionItems) = preProject - docs\content\fsdocs-theme.css = docs\content\fsdocs-theme.css + docs\content\fsdocs-custom.css = docs\content\fsdocs-custom.css EndProjectSection EndProject Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FSharp.Stats.Interactive", "src\FSharp.Stats.Interactive\FSharp.Stats.Interactive.fsproj", "{D7BCF5C0-9E2B-4170-9390-607B0B65A8CD}" diff --git a/docs/ComparisonMetrics.fsx b/docs/ComparisonMetrics.fsx index 8eac4a019..b4a141aeb 100644 --- a/docs/ComparisonMetrics.fsx +++ b/docs/ComparisonMetrics.fsx @@ -18,7 +18,7 @@ categoryindex: 0 #I "../src/FSharp.Stats/bin/Release/.net8.0/" #r "FSharp.Stats.dll" #r "nuget: Plotly.NET, 4.0.0" -open FsMath + Plotly.NET.Defaults.DefaultDisplayOptions <- Plotly.NET.DisplayOptions.init (PlotlyJSReference = Plotly.NET.PlotlyJSReference.NoReference) @@ -27,6 +27,7 @@ Plotly.NET.Defaults.DefaultDisplayOptions <- #if IPYNB #r "nuget: Plotly.NET, 4.0.0" #r "nuget: Plotly.NET.Interactive, 4.0.0" +#r "nuget: FsMath, 0.0.1" #r "nuget: FSharp.Stats" #endif // IPYNB @@ -91,6 +92,7 @@ A BinaryConfusionMatrix can be created in various ways : let actual = [1;1;1;1;0;0;0] let predicted = [1;1;1;0;1;0;0] +open FsMath open FSharp.Stats.Testing BinaryConfusionMatrix.ofPredictions(1,actual,predicted) diff --git a/docs/Correlation.fsx b/docs/Correlation.fsx index 3280468aa..22442c855 100644 --- a/docs/Correlation.fsx +++ b/docs/Correlation.fsx @@ -19,7 +19,7 @@ categoryindex: 0 #r "FSharp.Stats.dll" #r "nuget: Plotly.NET, 4.0.0" #r "nuget: FsMath, 0.0.1" -open FsMath + Plotly.NET.Defaults.DefaultDisplayOptions <- Plotly.NET.DisplayOptions.init (PlotlyJSReference = Plotly.NET.PlotlyJSReference.NoReference) @@ -29,7 +29,7 @@ Plotly.NET.Defaults.DefaultDisplayOptions <- #r "nuget: Plotly.NET, 4.0.0" #r "nuget: Plotly.NET.Interactive, 4.0.0" #r "nuget: FSharp.Stats" - +#r "nuget: FsMath, 0.0.1" #endif // IPYNB (** @@ -45,6 +45,7 @@ _Summary_: This tutorial demonstrates how to calculate correlation coefficients *) open Plotly.NET +open FsMath open FSharp.Stats open FSharp.Stats.Correlation @@ -175,7 +176,7 @@ let table2 = let proportion = int (255. * (value - min) / (max - min)) Color.fromARGB 1 (255 - proportion) 255 proportion pearsonCorrelationMatrix - |> Matrix.toJaggedArray + |> fun m -> m.toJaggedArray() |> JaggedArray.map (mapColor -1. 1.) |> JaggedArray.transpose |> Array.map Color.fromColors @@ -183,7 +184,7 @@ let table2 = let values = pearsonCorrelationMatrix - |> Matrix.toJaggedArray + |> fun m -> m.toJaggedArray() |> JaggedArray.map (sprintf "%.3f") Chart.Table(["colindex 0";"colindex 1";"colindex 2";"colindex 3"],values,CellsFillColor=cellcolors) diff --git a/docs/Covariance.fsx b/docs/Covariance.fsx index f80728d3d..7d14e30c8 100644 --- a/docs/Covariance.fsx +++ b/docs/Covariance.fsx @@ -51,7 +51,7 @@ let error() = rnd.Next(11) let sampleA = Vector.init 50 (fun x -> float x) let sampleB = Vector.init 50 (fun x -> float (x + error())) -let sampleBHigh = sampleB |> Vector.map (fun x -> 200. + x) +let sampleBHigh = sampleB |> Array.map (fun x -> 200. + x) let sampleC = Vector.init 50 (fun x -> 100. - float (x + 3 * error())) let sampleD = Vector.init 50 (fun x -> 100. + float (10 * error())) diff --git a/docs/CrossValidation.fsx b/docs/CrossValidation.fsx index 6b6001c7a..c97a5e2b5 100644 --- a/docs/CrossValidation.fsx +++ b/docs/CrossValidation.fsx @@ -66,8 +66,8 @@ let xV = vector [1. .. 10.] let yV = vector [1.;20.;51.;40.;37.;6.;-10.;-5.;0.;10.] // the fitting function fits a polynomial of order 'order' to the training data set (xTrain and yTrain) and applies it to xTest -let getFitFuncPolynomial xTrain yTrain (xTest:RowVector) order = - let xDat = xTrain |> Matrix.toVector +let getFitFuncPolynomial (xTrain:Matrix) yTrain (xTest:Vector) order = + let xDat = xTrain.Data // |> Matrix.toVector let coeffs = Polynomial.fit order xDat yTrain let predictFunction = Polynomial.predict coeffs (xTest.[0]) predictFunction @@ -113,8 +113,8 @@ let error (f1:float) f2 = pown (f1 - f2) 2 /// Leave-one-out cross validation. Returns the mean squared error of each leave-out at the /// specific polynomial order. Minimize for model selection. let loocvPolynomial (xData:Vector) (yData:Vector) order = - let xDataMat = Matrix.ofVector xData - let getFitFuncPol xTrain yTrain (xTest:RowVector) = + let xDataMat = Matrix.ofCols [|xData|] + let getFitFuncPol xTrain yTrain (xTest:Vector) = getFitFuncPolynomial xTrain yTrain xTest order let meanSquaredError = CrossValidation.loocv xDataMat yData getFitFuncPol error @@ -158,11 +158,11 @@ let's first create some smoothing splines to cross validate: *) // the fitting function fits a smoothing spline with smoothing factor lambda to the training data set (xTrain and yTrain) and applies it to xTest -let getFitFuncSpline xDat yDat (xDatTrain: RowVector) lambda = - let xDatVec = xDat |> Matrix.toVector +let getFitFuncSpline (xDat:Matrix) (yDat:Vector) (xDatTrain: Vector) lambda = + let xDatVec = xDat.Data // |> Matrix.toVector let zippedData = Seq.zip xDatVec yDat |> Array.ofSeq let xValTest = xDatTrain.[0] - Spline.smoothingSpline zippedData (xDat |> Array.ofSeq) lambda xValTest + Spline.smoothingSpline zippedData (xDat.Data) lambda xValTest /// in loocv the border points are chosen so that the support range of the training data set does not cover the test point. /// if splines are used, that are not defined outside the border points use the following: @@ -210,8 +210,8 @@ let errorSpl (f1:float) f2 = /// Leave-one-out cross validation. Returns the mean squared error of each leave-out at the /// specific regularization parameter (lambda). Minimize the (MSE) for model selection. let loocvSmoothingSpline (xData:Vector) (yData:Vector) lambda = - let xDataMat = Matrix.ofVector xData - let getFitFuncSpl xDat yDat (xDatTrain: RowVector) = + let xDataMat = Matrix.ofCols [|xData|] + let getFitFuncSpl xDat yDat (xDatTrain: Vector) = getFitFuncSpline xDat yDat xDatTrain lambda CrossValidation.loocv xDataMat yData getFitFuncSpl errorSpl @@ -260,9 +260,9 @@ The output contains the average error together with the standardDeviation comput //repeated k fold cross validation for polynomials let repeatedKFoldPolynomial k (xData: Vector) (yData: Vector) order = - let xDataMat = xData |> Matrix.Generic.ofVector + let xDataMat = [|xData|] |> Matrix.ofCols - let getFitFuncPol xTrain yTrain (xTest:RowVector) = + let getFitFuncPol xTrain yTrain (xTest:Vector) = getFitFuncPolynomial xTrain yTrain xTest order CrossValidation.repeatedKFold k 10 xDataMat yData getFitFuncPol error Seq.stDev @@ -272,9 +272,9 @@ let kfPolynomial order = repeatedKFoldPolynomial 5 xV yV order //repeated k fold cross validation for smoothing splines let repeatedKFoldSpline k (xData: Vector) (yData: Vector) lambda = - let xDataMat = xData |> Matrix.ofVector + let xDataMat = [|xData|] |> Matrix.ofCols - let getFitFuncSpl xDat yDat (xDatTrain: RowVector) = + let getFitFuncSpl xDat yDat (xDatTrain: Vector) = getFitFuncSpline xDat yDat xDatTrain lambda CrossValidation.repeatedKFold k 10 xDataMat yData getFitFuncSpl errorSpl Seq.stDev @@ -352,9 +352,9 @@ The output contains the average error together with the standardDeviation comput *) let shuffleAndSplitPolynomial p iterations (xData: Vector) (yData: Vector) order = - let xDataMat = xData |> Matrix.ofVector + let xDataMat = [|xData|] |> Matrix.ofCols - let getFitFuncPol xTrain yTrain (xTest:RowVector) = + let getFitFuncPol xTrain yTrain (xTest:Vector) = getFitFuncPolynomial xTrain yTrain xTest order CrossValidation.shuffelAndSplit p iterations xDataMat yData getFitFuncPol error Seq.stDev @@ -363,9 +363,9 @@ let shuffleAndSplitPolynomial p iterations (xData: Vector) (yData: Vector let sasPolynomial order = shuffleAndSplitPolynomial 0.2 5 xV yV order let shuffleAndSplitSpline p iterations (xData: Vector) (yData: Vector) lambda = - let xDataMat = xData |> Matrix.ofVector + let xDataMat = [|xData|] |> Matrix.ofCols - let getFitFuncSpl xDat yDat (xDatTrain: RowVector) = + let getFitFuncSpl xDat yDat (xDatTrain: Vector) = getFitFuncSpline xDat yDat xDatTrain lambda CrossValidation.shuffelAndSplit p iterations xDataMat yData getFitFuncSpl errorSpl Seq.stDev diff --git a/docs/Distributions.fsx b/docs/Distributions.fsx index b3282ced5..3f769378a 100644 --- a/docs/Distributions.fsx +++ b/docs/Distributions.fsx @@ -711,7 +711,7 @@ _1 from town B_, and _3 from town C_? The individual success probabilities can b let multiNomProb = vector [(3./30.); (7./30.); (20./30.)] // the success combination that is of interest -let multiNomKs = Vector.Generic.ofList [1; 1; 3] +let multiNomKs = vector [1; 1; 3] // gives the probability of obtaining exactly the pattern 1,1,3 let mNom = Discrete.Multinomial.PMF multiNomProb multiNomKs @@ -731,7 +731,7 @@ multinomial distribution you have to give the corresponding anto-probability: *) let mNom_bin_A = (Discrete.Binomial.PMF 0.123 200 20) -let mNom_bin_B = Discrete.Multinomial.PMF (vector [|0.123; 0.877|]) (Vector.Generic.ofArray [|20; 180|]) +let mNom_bin_B = Discrete.Multinomial.PMF ([|0.123; 0.877|]) ([|20; 180|]) mNom_bin_A //0.0556956956889893 mNom_bin_B //0.0556956956889898 diff --git a/docs/Fitting.fsx b/docs/Fitting.fsx index 9b2495417..fcf5c6bb2 100644 --- a/docs/Fitting.fsx +++ b/docs/Fitting.fsx @@ -203,12 +203,13 @@ let xVectorMulti = [5.; 4. ;18. ] [6.; 3. ;22. ] ] - |> Matrix.ofJaggedSeq + |> matrix let yVectorMulti = let transformX (x:Matrix) = x - |> Matrix.mapiRows (fun _ v -> 100. + (v.[0] * 2.5) + (v.[1] * 4.) + (v.[2] * 0.5)) + |> Matrix.getRows + |> Array.map (fun v -> 100. + (v.[0] * 2.5) + (v.[1] * 4.) + (v.[2] * 0.5)) xVectorMulti |> transformX |> vector @@ -249,7 +250,7 @@ let predictionFunctionPol x = let orderP = 3 //define the weighting vector -let weights = yDataP |> Vector.map (fun y -> 1. / y) +let weights = yDataP |> Array.map (fun y -> 1. / y) let coefficientsPolW = OLS.Polynomial.fitWithWeighting orderP weights xDataP yDataP let predictionFunctionPolW x = diff --git a/docs/GeneralisedLinearModels.fsx b/docs/GeneralisedLinearModels.fsx deleted file mode 100644 index b8955ceb5..000000000 --- a/docs/GeneralisedLinearModels.fsx +++ /dev/null @@ -1,312 +0,0 @@ - -(** ---- -title: GLM Documentation -index: 24 -category: Documentation -categoryindex: 0 ---- -*) - -(*** hide ***) - - -(*** condition: prepare ***) -#I "../src/FSharp.Stats/bin/Release/netstandard2.0/" -#r "nuget: Deedle" -#r "FSharp.Stats.dll" -#r "nuget: Plotly.NET, 4.0.0" - -Plotly.NET.Defaults.DefaultDisplayOptions <- - Plotly.NET.DisplayOptions.init (PlotlyJSReference = Plotly.NET.PlotlyJSReference.NoReference) - -(*** condition: ipynb ***) -#if IPYNB -#r "nuget: Plotly.NET, 4.0.0" -#r "nuget: Plotly.NET.Interactive, 4.0.0" -#r "nuget: FSharp.Stats" - -open Plotly.NET -open FSharp.Stats -open Deedle -#endif // IPYNB - - -(** -# General linear models (GLMs) - -_Summary:_ This document provides an overview of fitting a Generalized Linear Model (GLM) using FSharp.Stats. - -General linear models (GLMs) are a broad class of statistical models that are used to analyze the relationship between a dependent variable and one or more independent variables. GLMs are a flexible framework that encompasses various statistical techniques, including ANOVA (Analysis of Variance). - -Like ANOVA, GLMs are used to examine the effects of different factors or variables on an outcome of interest. They allow us to determine if there are significant differences between groups or if there is a relationship between the independent variables and the dependent variable. - -GLMs extend the concept of ANOVA by allowing for more complex modeling scenarios. While ANOVA is primarily used for comparing the means of different groups, GLMs can handle a wider range of data types and relationships. For example, GLMs can handle continuous, categorical, and count data, as well as non-linear relationships between variables. - -GLMs also provide a flexible framework for incorporating multiple independent variables, interactions between variables, and controlling for confounding factors. This allows for more nuanced relationships and better understand the factors that influence the outcome variable. - -In terms of similarities, both ANOVA and GLMs involve partitioning the total variation in the data into different components. ANOVA partitions the variation into between-group and within-group components, while GLMs partition the variation into systematic (explained) and residual (unexplained) components. Both ANOVA and GLMs also calculate statistics (such as F-statistic in ANOVA and t-statistic in GLMs) to assess the significance of the relationships or differences. - -Overall, GLMs provide a more flexible and powerful framework for analyzing data compared to ANOVA. They allow for more complex modeling scenarios and can handle a wider range of data types. However, ANOVA remains a useful and widely used technique, particularly when comparing the means of multiple groups. - -In this notebook we will discuss how to design your GLMs and how to use them in F#. - -# Designing a GLM -To design a General Linear Model (GLM), you need to consider the following components: - -1. Dependent Variable: This is the variable you want to predict or explain. It should be continuous or categorical. - -2. Independent Variables: These are the variables that you believe have an impact on the dependent variable. They can be continuous or categorical. - -3. Link Function: The link function relates the linear predictor to the expected value of the dependent variable. It transforms the linear combination of the independent variables into the appropriate scale for the dependent variable. The choice of link function depends on the distribution of the dependent variable. - -4. Distribution: The distribution of the dependent variable determines the appropriate probability distribution to model the data. The choice of distribution depends on the nature of the dependent variable (continuous, binary, count, etc.) and the assumptions about the data. - -The formula for a GLM is typically written as: - -``` -Y = β₀ + β₁X₁ + β₂X₂ + ... + βₚXₚ -``` -This model is used in statistics to predict the outcome of a dependent variable (Y) based on the values of multiple independent variables (X₁, X₂, ..., Xₚ). - -Let's break down the equation: - -- `Y` is the dependent variable, also known as the response or outcome variable. This is what we're trying to predict or estimate. -- `β₀` is the y-intercept of the model. It represents the predicted value of Y when all the independent variables (X's) are 0. -- `β₁, β₂, ..., βₚ` are the coefficients of the independent variables (X₁, X₂, ..., Xₚ). These values quantify the impact of each corresponding independent variable on the dependent variable. For example, `β₁` is the change in the predicted value of Y for a one-unit change in X₁, assuming all other variables are held constant. -- `X₁, X₂, ..., Xₚ` are the independent variables, also known as predictors or explanatory variables. These are the variables that we use to predict Y. - -In the context of programming, this equation could be implemented in a variety of ways depending on the language and libraries used. For instance, in Python, you might use the `statsmodels` or `scikit-learn` libraries to create a GLM, but in F# we can utilise `FSharp.Stats`. - - -## Loading the Dataset -First, let's read some data to learn how to utilize Generalized Linear Models (GLMs). Below is the code to read the cheeseDataset, which is sourced from David S. Moore and George P. McCabe's "Introduction to the Practice of Statistics" (1993), second edition, published by W. H. Freeman and Company, available on the [Statlib database](https://dasl.datadescription.com). It contains information on the taste and concentration of various chemical components in 30 matured cheddar cheeses from the LaTrobe Valley in Victoria, Australia. The final Taste score is an aggregate of the scores given by several tasters. -*) - -open Deedle -open Plotly.NET -open FSharp.Stats - -let cheeseDataset :Frame= - Frame.ReadCsv $"{__SOURCE_DIRECTORY__}/data/cheese.csv" - |> Frame.indexRows "Column1" - -(***include-value:cheeseDataset***) - -(** -## Creating Histograms - -Step two involves visualizing the data using histograms. Histograms are an effective way to understand the distribution and frequency of the data by dividing it into bins and displaying the count of data points in each bin. This visual representation can help identify patterns, trends, and potential outliers in the dataset
-*) - -let histograms = - let histogramTaste = - Chart.Histogram(cheeseDataset?Taste |> Series.values) - |> Chart.withXAxisStyle("Taste") - |> Chart.withYAxisStyle("Frequency") - |> Chart.withTitle "Histogram of Taste" - |> Chart.withTraceInfo("Taste") - let histogramAcetic = - Chart.Histogram(cheeseDataset?Acetic |> Series.values) - |> Chart.withXAxisStyle("Acetic") - |> Chart.withYAxisStyle("Frequency") - |> Chart.withTitle "Histogram of Acetic" - |> Chart.withTraceInfo("Acetic") - let histogramH2S = - Chart.Histogram(cheeseDataset?H2S |> Series.values) - |> Chart.withXAxisStyle("H2S") - |> Chart.withYAxisStyle("Frequency") - |> Chart.withTitle "Histogram of H2S" - |> Chart.withTraceInfo("H2S") - let histogramLactic = - Chart.Histogram(cheeseDataset?Lactic |> Series.values) - |> Chart.withXAxisStyle("Lactic") - |> Chart.withYAxisStyle("Frequency") - |> Chart.withTitle "Histogram of Lactic" - |> Chart.withTraceInfo("Lactic") - Chart.Grid(2,2) [histogramTaste; histogramAcetic; histogramH2S; histogramLactic] - -(***include-value:histograms***) - - -(** -## Preparing Data for GLM -Now we can try to predict the taste of a cheese by its Aciticity, its H2S content and its Lactic acid content: For this we utilise a GLM. To use this we need to get the dependent variable, the given taste from our dataframe, as a vector and the independent variables, Acetic, H2S and Lactic, into a Matrix. -*) - -let dependentVector = - cheeseDataset?Taste - |> Series.values - |> Vector.ofSeq - -let independentMatrix = - cheeseDataset - |> Frame.dropCol "Taste" - |> Frame.toJaggedArray - |> Matrix.ofJaggedArray - -(** -To include the y-intercept (also known as the intercept term) in the GLM, we must add a column of ones to our matrix of independent variables. This column represents the constant term in the model and allows the estimation of the y-intercept when fitting the model. -*) - -let updatedIndependentMatrix = - independentMatrix - |> Matrix.toJaggedArray - |> Array.map (fun row -> Array.append [|1.0|] row) - |> Matrix.ofJaggedArray - -(** -## Fitting the GLM -The next step we need to take is to determine which linker functions to use in our Model. -Generalized Linear Models extend linear models to allow for response variables that have error distribution models other than a normal distribution. The choice of distribution family in a GLM depends on the nature of the response variable (dependent variable). Here is a summary of when to use each GLM distribution family: - -**Normal (Gaussian) Distribution**:
- - **Use when**: The response variable is continuous and normally distributed.
- - **Common applications**: Linear regression, ANOVA, ANCOVA.
- - **Examples**: Heights, weights, test scores. - -**Binomial Distribution**:
- - **Use when**: The response variable is binary (0 or 1) or proportion data.
- - **Common applications**: Logistic regression, probit regression.
- - **Examples**: Yes/No outcomes, success/failure data. - -**Poisson Distribution**:
- - **Use when**: The response variable represents count data, especially counts of rare events.
- - **Common applications**: Poisson regression.
- - **Examples**: Number of customer complaints, number of accidents. - -**Negative Binomial Distribution**:
- - **Use when**: The response variable is count data with overdispersion (variance greater than the mean).
- - **Common applications**: Negative binomial regression.
- - **Examples**: Number of insurance claims, number of hospital visits. - -**Gamma Distribution**:
- - **Use when**: The response variable is continuous and positive, often for skewed distributions.
- - **Common applications**: Gamma regression.
- - **Examples**: Insurance claims costs, time until an event occurs. - -**Inverse Gaussian Distribution**:
- - **Use when**: The response variable is continuous and positive, and particularly when the data has a long right tail.
- - **Common applications**: Inverse Gaussian regression.
- - **Examples**: Reaction times, survival times. - - -**Multinomial Distribution**:
- - **Use when**: The response variable represents categorical data with more than two categories.
- - **Common applications**: Multinomial logistic regression.
- - **Examples**: Survey responses with multiple choices, type of disease diagnosis. - -Each distribution family has a corresponding link function that relates the linear predictor to the mean of the distribution. The choice of link function can also be tailored to better fit the specific characteristics of the data. Common link functions include the identity link, log link, logit link, and inverse link, among others. - -Understanding the characteristics of your data and the nature of the response variable is crucial in selecting the appropriate distribution family for a GLM. -*) - -// Matrix of independent variables -let A = updatedIndependentMatrix - -// Vector of dependent variable -let b = dependentVector - -// Maximum number of iterations -let maxIter = 100 - -// Distribution family of the dependent variable -let distributionFamily = FSharp.Stats.Fitting.GLM.GlmDistributionFamily.Poisson - -// Tolerance for the convergence of the algorithm, usually 1e-11 or 1e-6 -let mTol = 1e-6 - -// Fit the model -let glm = - FSharp.Stats.Fitting.GLM.SolveGLM.solveQR A b maxIter distributionFamily mTol - -glm -(***include-value:glm***) - -(** -## Getting GLM Predictions - -The results of the GLM are in the GLMReturn format, containing the coefficient vector *mX* and the mean response vector *mu*. The coefficients in the *mx* vector are in the same order as the matrix of independent variables we gave the model. In our case this order is: -1. intercept term -2. Acetic -3. H2S -4. Lactic - -This means we can build a predictor funtion using the result of the GLM that can predict Taste based on Acetic, H2S and Lactic. -Lets turn the predictions into a Map for easy access. For this we use the 'GLMParameterStatistics' for easy acess for each parameter of the predictions. -Using this map we can also access the zScore and Pearson scores of each of the predictors, which tell us how important they are to explain our model. -*) - -let glmPredictions = - FSharp.Stats.Fitting.GLM.GLMStatistics.getGLMParameterStatistics A b glm ["Intercept"; "Acetic"; "H2S"; "Lactic"] - |> Map.ofSeq - -(***include-value:glmPredictions***) - - -(** -## Cheese Taste Predictor Function - -This function returned a map of the name of the value we assigned to it and their coefficient, standard error, z score and pvalue. - -### Coefficient -The estimated effect size of the predictor variable. It indicates the expected change in the dependent variable for a one-unit change in the predictor variable, holding all other variables constant. - -### Standard Error -Measures the accuracy of the coefficient's estimate. It is the standard deviation of the sampling distribution of the coefficient. A smaller standard error indicates a more precise estimate. - -### Z Score -Calculated as the coefficient divided by its standard error. It tests the null hypothesis that the coefficient is zero. A larger absolute value indicates stronger evidence against the null hypothesis. - -### p-value -Indicates the probability of observing a test statistic as extreme as the observed value under the null hypothesis. A smaller p-value suggests stronger evidence against the null hypothesis. Typically, a p-value less than 0.05 is considered statistically significant. - -Lets use these values to create a function to predict the taste based of the coefficients. - -*) - -/// Predicts the taste of cheese based on the given input variables. -/// -/// Parameters: -/// acetic - The acetic acid level in the cheese. -/// h2s - The hydrogen sulfide level in the cheese. -/// lactic - The lactic acid level in the cheese. -/// -/// Returns: -/// The predicted taste of the cheese. -let cheeseTastePredictor acetic h2s lactic = - // Extract the intercept term from the GLM coefficients - let intercept = glmPredictions.Item "Intercept" |> fun x -> x.Coefficient - - // Extract the coefficient for the acetic acid predictor from the GLM coefficients - let aceticCoefficient = glmPredictions.Item "Acetic" |> fun x -> x.Coefficient - - // Extract the coefficient for the hydrogen sulfide (H2S) predictor from the GLM coefficients - let H2SCoefficient = glmPredictions.Item "H2S" |> fun x -> x.Coefficient - - // Extract the coefficient for the lactic acid predictor from the GLM coefficients - let LacticCoefficient = glmPredictions.Item "Lactic" |> fun x -> x.Coefficient - - // Calculate and return the predicted cheese taste - // The prediction is the sum of the intercept and the products of each coefficient with its corresponding predictor value - intercept + aceticCoefficient * acetic + H2SCoefficient * h2s + LacticCoefficient * lactic - -(** -## Getting GLM Model Statistics - -Lastly, let's examine how well our model fits the data overall. For this, we use the 'GLMModelStatistics', which provide key metrics such as LogLikelihood, Deviance, and PearsonChi2. - -### LogLikelihood -LogLikelihood measures the goodness of fit of the model. It is the logarithm of the likelihood function, which evaluates how likely it is that the observed data would occur under the model parameters. Higher values indicate a better fit of the model to the data. - -### Deviance -Deviance is a measure of the discrepancy between the observed data and the values predicted by the model. It compares the likelihood of the model to the likelihood of a perfect model that predicts the data exactly. Lower deviance indicates a better fit. - -### Pearson Chi-Square (PearsonChi2) -Pearson Chi-Square is another measure of goodness of fit. It assesses how well the observed data match the expected data predicted by the model. Lower values suggest a better fit. It is particularly useful for identifying overdispersion or underdispersion in the model. - -These statistics together give us a comprehensive view of the model's performance and its ability to explain the variability in the data. -*) - -let glmStats = FSharp.Stats.Fitting.GLM.GLMStatistics.getGLMStatisticsModel b glm distributionFamily -(***include-value:glmStats***) diff --git a/docs/GoodnessOfFit.fsx b/docs/GoodnessOfFit.fsx index bcfb23238..2668cbdf9 100644 --- a/docs/GoodnessOfFit.fsx +++ b/docs/GoodnessOfFit.fsx @@ -196,12 +196,11 @@ let fitValues = xData |> Seq.map (fun xi -> xi,(predictionFunction xi)) ///calculate confidence band errors for every x value let confidence = xData - |> Vector.map (calculateConfidenceBandError xData yData 0.95) + |> Array.map (calculateConfidenceBandError xData yData 0.95) ///lower and upper bounds of the 95% confidence band sorted according to x values let (lower,upper) = xData - |> Vector.toArray |> Array.mapi (fun i xi -> (predictionFunction xi) - confidence.[i],(predictionFunction xi) + confidence.[i]) |> Array.unzip @@ -241,12 +240,11 @@ let newXValues = ///calculate confidence band errors for every x value let newConfidence = newXValues - |> Vector.map (calculateConfidenceBandError xData yData 0.95) + |> Array.map (calculateConfidenceBandError xData yData 0.95) ///lower and upper bounds of the 95% confidence band sorted according to x values let (newLower,newUpper) = newXValues - |> Vector.toArray |> Array.mapi (fun i xi -> (predictionFunction xi) - newConfidence.[i],(predictionFunction xi) + newConfidence.[i]) |> Array.unzip @@ -280,12 +278,11 @@ let predictionXValues = vector [|1. .. 0.5 .. 15.|] ///calculate preditcion band errors for every x value let prediction = predictionXValues - |> Vector.map (calculatePredictionBandError xData yData 0.95) + |> Array.map (calculatePredictionBandError xData yData 0.95) ///lower and upper bounds of the 95% prediction band sorted according to x values let (pLower,pUpper) = predictionXValues - |> Vector.toArray |> Array.mapi (fun i xi -> (predictionFunction xi) - prediction.[i],(predictionFunction xi) + prediction.[i]) |> Array.unzip diff --git a/docs/GrowthCurve.fsx b/docs/GrowthCurve.fsx index a8a6d3cc5..e5ad0513a 100644 --- a/docs/GrowthCurve.fsx +++ b/docs/GrowthCurve.fsx @@ -265,10 +265,10 @@ The four parameter Gompertz model allows the determination of generation times f *) -let generationtime (parametervector:vector) (logTransform:float -> float) = +let generationtime (parametervector:Vector) (logTransform:float -> float) = logTransform 2. * Math.E / (parametervector.[1] * parametervector.[2]) -let lag (parametervector:vector) = +let lag (parametervector:Vector) = (parametervector.[3] - 1.) / parametervector.[1] let g = sprintf "The generation time (Gompertz) is: %.1f min" (60. * (generationtime gompertzParams log)) @@ -336,7 +336,7 @@ let fittingFunctionRichards = (**Here is a pre-evaluated version (to save time during the build process, as the solver takes quite some time.)*) -let generationtimeRichards (richardParameters:vector) = +let generationtimeRichards (richardParameters:Vector) = let l = richardParameters.[0] let k = richardParameters.[1] let y = richardParameters.[2] //x value of inflection point @@ -419,7 +419,7 @@ let fittingFunctionWeibull = (**Here is a pre-evaluated version (to save time during the build process, as the solver takes quite some time.)*) -let generationtimeWeibull (weibullParameters:vector) = +let generationtimeWeibull (weibullParameters:Vector) = let b = weibullParameters.[0] let l = weibullParameters.[1] let k = weibullParameters.[2] @@ -505,7 +505,7 @@ let fittingFunctionJanoschek = (**Here is a pre-evaluated version (to save time during the build process, as the solver takes quite some time.)*) -let generationtimeJanoschek (janoschekParameters:vector) = +let generationtimeJanoschek (janoschekParameters:Vector) = let b = janoschekParameters.[0] let l = janoschekParameters.[1] let k = janoschekParameters.[2] @@ -593,7 +593,7 @@ let fittingFunctionExponential = (**Here is a pre-evaluated version (to save time during the build process, as the solver takes quite some time.)*) -let generationtimeExponential (expParameters:vector) = +let generationtimeExponential (expParameters:Vector) = let b = expParameters.[0] let l = expParameters.[1] let k = expParameters.[2] @@ -684,7 +684,7 @@ let fittingFunctionVerhulst() = (**Here is a pre-evaluated version (to save time during the build process, as the solver takes quite some time.)*) -let generationtimeVerhulst (verhulstParameters:vector) = +let generationtimeVerhulst (verhulstParameters:Vector) = let lmax = verhulstParameters.[0] let k = verhulstParameters.[1] let d = verhulstParameters.[2] @@ -768,7 +768,7 @@ let fittingFunctionMMF() = (**Here is a pre-evaluated version (to save time during the build process, as the solver takes quite some time.)*) -let generationtimeMmf (mmfParameters:vector) = +let generationtimeMmf (mmfParameters:Vector) = let b = mmfParameters.[0] let l = mmfParameters.[1] let k = mmfParameters.[2] diff --git a/docs/Interpolation.fsx b/docs/Interpolation.fsx index 0431b2e49..54bedc997 100644 --- a/docs/Interpolation.fsx +++ b/docs/Interpolation.fsx @@ -388,7 +388,7 @@ let bezierInterpolation = let c2 = vector [|6.5;-1.5|] //control point 2 let c3 = vector [|13.5;4.|] //control point 3 let p1 = vector [|10.;5.|] //point 1 that should be traversed - let toPoint (v : vector) = v[0],v[1] + let toPoint (v : Vector) = v[0],v[1] let interpolate = Bezier.interpolate [|p0;c0;c1;c2;c3;p1|] >> toPoint [ @@ -424,7 +424,7 @@ let bezierInterpolation3d = let c0 = vector [|1.5;2.1;2.|] //control point 0 let c1 = vector [|5.8;1.6;1.4|] //control point 1 let p1 = vector [|3.;2.;0.|] //point 1 that should be traversed - let to3Dpoint (v : vector) = v[0],v[1],v[2] + let to3Dpoint (v : Vector) = v[0],v[1],v[2] let interpolate = Bezier.interpolate [|p0;c0;c1;p1|] >> to3Dpoint [ @@ -535,7 +535,7 @@ let xs_cheby = // to get the corresponding y values to the xs_cheby a linear spline is generated that approximates the new y values let ys_cheby = let ls = Interpolation.LinearSpline.interpolate xs ys - xs_cheby |> Vector.map (Interpolation.LinearSpline.predict ls) + xs_cheby |> Array.map (Interpolation.LinearSpline.predict ls) // again polynomial interpolation coefficients are determined, but here with the x and y data that correspond to the chebyshev spacing let coeffs_cheby = Interpolation.Polynomial.interpolate xs_cheby ys_cheby diff --git a/docs/Normalization.fsx b/docs/Normalization.fsx index fd38656ae..4a2229d1d 100644 --- a/docs/Normalization.fsx +++ b/docs/Normalization.fsx @@ -162,8 +162,9 @@ let rawData = // visualization of the raw data let rawDataChart = - rawData.Transpose - |> Matrix.toJaggedArray + rawData + |> Matrix.transpose + |> (fun m -> m.toJaggedArray()) |> Array.mapi (fun sampleID sample -> let sampleIntensities = sample @@ -220,8 +221,9 @@ corrFactors // visualization of the normed data let normedDataChart = - morNormedData.Transpose - |> Matrix.toJaggedArray + morNormedData + |> Matrix.transpose + |> (fun m -> m.toJaggedArray()) |> Array.mapi (fun sampleID sample -> let sampleIntensities = sample @@ -314,8 +316,9 @@ let quantileNorm = // visualization of the normed data let normedDataQuantileChart = - quantileNorm.Transpose - |> Matrix.toJaggedArray + quantileNorm + |> Matrix.transpose + |> (fun m -> m.toJaggedArray()) |> Array.mapi (fun sampleID sample -> let sampleIntensities = sample diff --git a/docs/Optimization.fsx b/docs/Optimization.fsx index 82539e69a..4d6589a29 100644 --- a/docs/Optimization.fsx +++ b/docs/Optimization.fsx @@ -65,7 +65,7 @@ open Plotly.NET open Plotly.NET.TraceObjects -let myFunction (xs: vector) = +let myFunction (xs: Vector) = let x = xs.[0] x**2. + 0.32*x + 0.13 @@ -121,7 +121,7 @@ Lets define the function, and a starting coordinate for the optimization task. // Rosenbrock's valley or Rosenbrock's banana function -let rosenbrock (xs: vector) = +let rosenbrock (xs: Vector) = let x, y = xs.[0], xs.[1] pown (1.0 - x) 2 + 100.0 * pown (y - pown x 2) 2 @@ -232,7 +232,7 @@ The Auckley function has many valleys, with one center and global minimum at $(0 // Auckley function -let auckley (xs: vector) = +let auckley (xs: Vector) = let x, y = xs.[0], xs.[1] -20.*exp(-0.2*sqrt(0.5*(x**2. + y**2))) - exp(0.5*(cos(2. * Math.PI * x) + cos(2. * Math.PI * y))) + @@ -299,7 +299,7 @@ The Nelder-Mead method is able to identiy a local minimum, but misses the global // Beale function function -let beale (xs: vector) = +let beale (xs: Vector) = let x, y = xs.[0], xs.[1] (1.5 - x + x*y)**2. + (2.25 - x + x*y**2)**2. + From 8054b5c29fb77add7e82f7977fdbd3a4ef61e0fd Mon Sep 17 00:00:00 2001 From: Kevin Schneider Date: Sun, 10 Aug 2025 14:52:33 +0200 Subject: [PATCH 100/121] - Fix xml doc errors - Fix typo (VCrossvalidation > shuffelAndSplit -> shuffleAndSplit) --- src/FSharp.Stats/Array.fs | 2 +- src/FSharp.Stats/Correlation.fs | 18 ++++----- src/FSharp.Stats/DistanceMetrics.fs | 16 ++++---- .../Distributions/Continuous/ChiSquared.fs | 2 +- .../Distributions/Discrete/Binomial.fs | 1 - .../Distributions/Discrete/Hypergeometric.fs | 15 +++++--- .../Discrete/NegativeBinomial.fs | 11 ++++-- .../Distributions/Discrete/Poisson.fs | 1 - src/FSharp.Stats/Distributions/Distance.fs | 4 +- src/FSharp.Stats/Distributions/Empirical.fs | 4 +- src/FSharp.Stats/Distributions/Frequency.fs | 4 +- src/FSharp.Stats/Fitting/CrossValidation.fs | 24 ++++++++++-- src/FSharp.Stats/Fitting/LinearRegression.fs | 11 ++---- .../Fitting/LogisticRegression.fs | 2 + .../Fitting/NonLinearRegression.fs | 3 ++ src/FSharp.Stats/Fitting/Spline.fs | 2 +- src/FSharp.Stats/Interpolation.fs | 14 ++----- src/FSharp.Stats/List.fs | 8 ++-- src/FSharp.Stats/Quantile.fs | 2 +- src/FSharp.Stats/Rank.fs | 3 -- src/FSharp.Stats/Signal/Normalization.fs | 16 ++++---- src/FSharp.Stats/Signal/Padding.fs | 1 + src/FSharp.Stats/Signal/PeakDetection.fs | 1 - src/FSharp.Stats/SpecialFunctions/Erf.fs | 2 - src/FSharp.Stats/Testing/TestStatistics.fs | 37 ++++++++----------- 25 files changed, 104 insertions(+), 100 deletions(-) diff --git a/src/FSharp.Stats/Array.fs b/src/FSharp.Stats/Array.fs index e7c7e1f1c..4221def69 100644 --- a/src/FSharp.Stats/Array.fs +++ b/src/FSharp.Stats/Array.fs @@ -645,7 +645,7 @@ module ArrayExtension = ///
/// start value (is included) /// end value (by default is included ) - /// sets the number of elements in the array. If not set, stepsize = 1. + /// sets the number of elements in the array. If not set, stepsize = 1. /// If false, the array does not contain the stop value static member linspace(start:float,stop:float,num:int,?IncludeEndpoint:bool) : float [] = diff --git a/src/FSharp.Stats/Correlation.fs b/src/FSharp.Stats/Correlation.fs index 805000d38..5182b213c 100644 --- a/src/FSharp.Stats/Correlation.fs +++ b/src/FSharp.Stats/Correlation.fs @@ -298,19 +298,19 @@ module Correlation = /// /// Tau A - Make no adjustments for ties /// - /// The first array of observations. - /// The second array of observations. + /// The first array of observations. + /// The second array of observations. /// Number of concordant minues the number of discordant pairs. /// n(n-1)/2 or (n choose 2), where n is the number of observations. - /// sum_i(t_i(t_i-1)/2) where t_is is t_i he number of pairs of observations with the same x value. - /// sum_i(u_i(u_i-1)/2) where u_is is u_i he number of pairs of observations with the same y value. + /// sum_i(t_i(t_i-1)/2) where t_is is t_i he number of pairs of observations with the same x value. + /// sum_i(u_i(u_i-1)/2) where u_is is u_i he number of pairs of observations with the same y value. /// The Kendall tau A statistic. let tauA _x _y pq n0 _n1 _n2 = pq / float n0 /// /// Tau B - Adjust for ties. tau_b = pq / sqrt((n0 - n1)(n0 - n2)) /// - /// The first array of observations. - /// The second array of observations. + /// The first array of observations. + /// The second array of observations. /// Number of concordant minues the number of discordant pairs. /// n(n-1)/2 or (n choose 2), where n is the number of observations. /// sum_i(t_i(t_i-1)/2) where t_is is t_i he number of pairs of observations with the same x value. @@ -325,9 +325,9 @@ module Correlation = /// The first array of observations. /// The second array of observations. /// Number of concordant minues the number of discordant pairs. - /// n(n-1)/2 or (n choose 2), where n is the number of observations. - /// sum_i(t_i(t_i-1)/2) where t_is is t_i he number of pairs of observations with the same x value. - /// sum_i(u_i(u_i-1)/2) where u_is is u_i he number of pairs of observations with the same y value. + /// n(n-1)/2 or (n choose 2), where n is the number of observations. + /// sum_i(t_i(t_i-1)/2) where t_is is t_i he number of pairs of observations with the same x value. + /// sum_i(u_i(u_i-1)/2) where u_is is u_i he number of pairs of observations with the same y value. /// The Kendall tau C statistic. let tauC (x : _[]) y pq _n0 _n1 _n2 = let n = x.Length diff --git a/src/FSharp.Stats/DistanceMetrics.fs b/src/FSharp.Stats/DistanceMetrics.fs index aa2f0ff20..5c173c529 100644 --- a/src/FSharp.Stats/DistanceMetrics.fs +++ b/src/FSharp.Stats/DistanceMetrics.fs @@ -124,8 +124,8 @@ module DistanceMetrics = /// The [Minkowski distance](https://en.wikipedia.org/wiki/Minkowski_distance) between two vectors of order `p`. /// The two vectors need not have equal lengths: when one vectors is exhausted any remaining elements in the other vectors are ignored. - /// first vector - /// second vector + /// first vector + /// second vector /// float constrained to `p > 0` /// Minkowski distance between elements of given vectors. Returns NaN if vectors contain NaN. /// @@ -163,8 +163,8 @@ module DistanceMetrics = /// The [Minkowski distance](https://en.wikipedia.org/wiki/Minkowski_distance) between two vectors (ignores NaN) of order `p`. /// Non-regular differences between the sequences are ignored. /// The two vectors need not have equal lengths: when one vectors is exhausted any remaining elements in the other vectors are ignored. - /// first vector - /// second vector + /// first vector + /// second vector /// float constrained to `p > 0` /// Minkowski distance between elements of given vectors. /// @@ -319,8 +319,8 @@ module DistanceMetrics = /// The [Minkowski distance](https://en.wikipedia.org/wiki/Minkowski_distance) between two arrays of order `p`. /// The two arrays need not have equal lengths: when one array is exhausted any remaining elements in the other array are ignored. - /// first array - /// second array + /// first array + /// second array /// float constrained to `p > 0` /// Minkowski distance between elements of given arrays. Returns NaN if arrays contain NaN. /// @@ -358,8 +358,8 @@ module DistanceMetrics = /// The [Minkowski distance](https://en.wikipedia.org/wiki/Minkowski_distance) between two arrays (ignores NaN) of order `p`. /// Non-regular differences between the sequences are ignored. /// The two arrays need not have equal lengths: when one array is exhausted any remaining elements in the other array are ignored. - /// first array - /// second array + /// first array + /// second array /// float constrained to `p > 0` /// Minkowski distance between elements of given arrays. /// diff --git a/src/FSharp.Stats/Distributions/Continuous/ChiSquared.fs b/src/FSharp.Stats/Distributions/Continuous/ChiSquared.fs index 393c70c5d..44aa14ac4 100644 --- a/src/FSharp.Stats/Distributions/Continuous/ChiSquared.fs +++ b/src/FSharp.Stats/Distributions/Continuous/ChiSquared.fs @@ -67,7 +67,7 @@ type ChiSquared = ChiSquared.CheckParam dof sqrt (dof * 2.) - /// Degrees of freedom (must be positive). + /// Degrees of freedom (must be positive). /// A sample from χ²(dof), interpreted as Gamma(dof/2, 2). static member SampleUnchecked (dof: float) : float = let alpha = dof / 2.0 diff --git a/src/FSharp.Stats/Distributions/Discrete/Binomial.fs b/src/FSharp.Stats/Distributions/Discrete/Binomial.fs index b4a292d08..a4f654c40 100644 --- a/src/FSharp.Stats/Distributions/Discrete/Binomial.fs +++ b/src/FSharp.Stats/Distributions/Discrete/Binomial.fs @@ -82,7 +82,6 @@ type Binomial = /// Produces a random sample using the current random number generator (from GetSampleGenerator()).
No parameter checking!
/// - /// /// /// /// diff --git a/src/FSharp.Stats/Distributions/Discrete/Hypergeometric.fs b/src/FSharp.Stats/Distributions/Discrete/Hypergeometric.fs index e71974105..c64319715 100644 --- a/src/FSharp.Stats/Distributions/Discrete/Hypergeometric.fs +++ b/src/FSharp.Stats/Distributions/Discrete/Hypergeometric.fs @@ -100,7 +100,6 @@ type Hypergeometric = /// Produces a random sample using the current random number generator (from GetSampleGenerator()).
No parameter checking!
/// - /// /// /// /// @@ -253,11 +252,17 @@ type Hypergeometric = /// Initializes a hypergeometric distribution. /// - /// The hypergeometric distribution is a discrete probability distribution
that describes the probability of `k` successes (random draws for which the object
drawn has a specified feature) in `n` draws, without replacement, from a finite
population of size `N` that contains exactly `K` objects with that feature,
wherein each draw is either a success (`1.0`) or a failure (`0.0`).

The population size
The number of success states in the population
The number of draws
+ /// + /// The hypergeometric distribution is a discrete probability distribution + /// that describes the probability of `k` successes (random draws for which the object + /// drawn has a specified feature) in `n` draws, without replacement, from a finite + /// population of size `N` that contains exactly `K` objects with that feature, + /// wherein each draw is either a success (`1.0`) or a failure (`0.0`). + /// + /// The population size + /// The number of success states in the population + /// The number of draws /// - /// - /// - /// /// /// /// diff --git a/src/FSharp.Stats/Distributions/Discrete/NegativeBinomial.fs b/src/FSharp.Stats/Distributions/Discrete/NegativeBinomial.fs index 44d1f0a3e..429f6217a 100644 --- a/src/FSharp.Stats/Distributions/Discrete/NegativeBinomial.fs +++ b/src/FSharp.Stats/Distributions/Discrete/NegativeBinomial.fs @@ -1,4 +1,4 @@ -namespace FSharp.Stats.Distributions.Discrete +Fkspace FSharp.Stats.Distributions.Discrete open System open FSharp.Stats @@ -154,10 +154,13 @@ type NegativeBinomial_trials = sprintf "NegativeBinomial_trials(r = %i, p = %f)" r p /// Initializes a negative binomial distribution. - /// The negative binomial distribution is a discrete probability distribution
that models the number of trials needed x to get the rth success in repeated
independent Bernoulli trials with probability p.

The number of success states
The probability of each independent bernoulli trial
The number of trials until the rth success
+ /// The negative binomial distribution is a discrete probability distribution + /// that models the number of trials needed x to get the rth success in repeated + /// independent Bernoulli trials with probability p. + ///
+ /// The number of success states + /// The probability of each independent bernoulli trial /// - /// - /// /// /// /// diff --git a/src/FSharp.Stats/Distributions/Discrete/Poisson.fs b/src/FSharp.Stats/Distributions/Discrete/Poisson.fs index 7ffd9d580..82c64a1cc 100644 --- a/src/FSharp.Stats/Distributions/Discrete/Poisson.fs +++ b/src/FSharp.Stats/Distributions/Discrete/Poisson.fs @@ -86,7 +86,6 @@ type Poisson = /// Produces a random sample using the current random number generator (from GetSampleGenerator()).
No parameter checking!
/// - /// /// /// /// diff --git a/src/FSharp.Stats/Distributions/Distance.fs b/src/FSharp.Stats/Distributions/Distance.fs index acc97b092..1d1c14f10 100644 --- a/src/FSharp.Stats/Distributions/Distance.fs +++ b/src/FSharp.Stats/Distributions/Distance.fs @@ -201,13 +201,13 @@ module Distance = /// /// /// - /// + /// /// /// /// /// /// - let cdfDistanceWeighted p (xs : float []) (ys : float []) xWeights yWeights = + let cdfDistanceWeighted p (xs : float []) (ys : float []) xWeights yWeights = if xs.Length = 0 then failwith "Given distribtuion xs is empty" if ys.Length = 0 then failwith "Given distribtuion ys is empty" diff --git a/src/FSharp.Stats/Distributions/Empirical.fs b/src/FSharp.Stats/Distributions/Empirical.fs index a37c6af6f..15f40b64e 100644 --- a/src/FSharp.Stats/Distributions/Empirical.fs +++ b/src/FSharp.Stats/Distributions/Empirical.fs @@ -327,8 +327,8 @@ module Empirical = /// Merges two maps into a single map. If a key exists in both maps, the value is determined by f with the first value being from mapA and the second originating from mapB. /// Is the binwidth equal for both distributions? For nominal data set to true. /// Function to transform values if key is present in both histograms. `histA-value → histB-value → newValue` - /// Empirical distribution A - /// Empirical distribution B + /// Empirical distribution A + /// Empirical distribution B /// When applied to continuous data the bandwidths must be equal! /// This function is not commutative! (mergeBy f a b) is not equal to (mergeBy f b a) /// New frequency map that results from merged maps mapA and mapB. Values from keys that are present in both maps are handled by f diff --git a/src/FSharp.Stats/Distributions/Frequency.fs b/src/FSharp.Stats/Distributions/Frequency.fs index 942c63939..086e81e68 100644 --- a/src/FSharp.Stats/Distributions/Frequency.fs +++ b/src/FSharp.Stats/Distributions/Frequency.fs @@ -141,8 +141,8 @@ module Frequency = /// Merges two histograms into a single histogram. If a key exists in both maps, the value is determined by f with the first value being from mapA and the second originating from mapB. /// Is the binwidth equal for both frequencies? For nominal data set to true. /// Function to transform values if key is present in both histograms. `mapA-value → mapB-value → newValue` - /// Frequency map A - /// Frequency map B + /// Frequency map A + /// Frequency map B /// When applied to continuous data the bandwidths must be equal! /// This function is not commutative! (mergeBy f a b) is not equal to (mergeBy f b a) /// New frequency map that results from merged maps mapA and mapB. Values from keys that are present in both maps are handled by f diff --git a/src/FSharp.Stats/Fitting/CrossValidation.fs b/src/FSharp.Stats/Fitting/CrossValidation.fs index 6e724ac76..b7c6a59a9 100644 --- a/src/FSharp.Stats/Fitting/CrossValidation.fs +++ b/src/FSharp.Stats/Fitting/CrossValidation.fs @@ -19,6 +19,7 @@ module CrossValidation = /// Computes sum of squared residuals (SSR) /// /// + /// /// /// /// @@ -31,6 +32,7 @@ module CrossValidation = /// Computes root mean square error (RMSE) /// /// + /// /// /// /// @@ -50,7 +52,13 @@ module CrossValidation = /// Computes a repeated k fold cross-validation,
k: training set size (and number of iterations),
iterations: number of random subset creation,
xData: rowwise x-coordinate matrix,
yData: yData vector
fit: x and y data lead to function that maps a xData row vector to a y-coordinate,
error: defines the error of the fitted y-coordinate and the actual y-coordinate,
getStDev: function that calculates the standard deviation from a seq<^T>. (Seq.stDev)
/// - /// + /// + /// + /// + /// + /// + /// + /// /// /// /// @@ -113,7 +121,10 @@ module CrossValidation = /// Computes a leave one out cross-validation
xData: rowwise x-coordinate matrix,
yData: yData vector
fit: x and y data lead to function that maps an xData row vector to a y-coordinate,
error: defines the error of the fitted y-coordinate and the actual y-coordinate
/// - /// + /// + /// + /// + /// /// /// /// @@ -141,13 +152,18 @@ module CrossValidation = /// Computes a repeated shuffel-and-split cross validation
p: percentage of training set size from original size,
iterations: number of random subset creation,
xData: rowwise x-coordinate matrix,
yData: yData vector
fit: x and y data lead to function that maps a xData row vector to a y-coordinate,
error: defines the error of the fitted y-coordinate and the actual y-coordinate,
getStDev: function that calculates the standard deviation from a seq<^T>. (Seq.stDev)
/// - /// + /// + /// + /// + /// + /// + /// /// /// /// /// /// - let inline shuffelAndSplit + let inline shuffleAndSplit p (iterations: int) (xData:Matrix< ^T >) (yData:Vector< ^T >) (fit: Matrix< ^T > -> Vector< ^T > -> Vector< ^T > -> ^T) (error: ^T -> ^T -> ^T) diff --git a/src/FSharp.Stats/Fitting/LinearRegression.fs b/src/FSharp.Stats/Fitting/LinearRegression.fs index 0d89702c5..27be4c5cc 100644 --- a/src/FSharp.Stats/Fitting/LinearRegression.fs +++ b/src/FSharp.Stats/Fitting/LinearRegression.fs @@ -161,7 +161,7 @@ module LinearRegression = /// /// let mySlope = 17.8 /// - /// // get the f�tting function that fits through the origin + /// // get the fitting function that fits through the origin /// let myF = /// LinearRegression.OLS.Linear.RTO.predictFunc mySlope /// @@ -451,7 +451,7 @@ module LinearRegression = /// Takes linear coefficients and x vector to predict the corresponding y value. ///
/// Coefficients from linear regression. - /// x vector for which the y value should be predicted + /// x vector for which the y value should be predicted /// predicted y value with given coefficients at X=x /// /// @@ -620,7 +620,6 @@ module LinearRegression = /// /// Takes polynomial coefficients and x value to predict the corresponding y value. /// - /// order of the polynomial (1 = linear, 2 = quadratic, ... ) /// vector of polynomial coefficients (e.g. determined by Polynomial.coefficients), sorted as [intercept;constant;quadratic;...] /// x value of which the corresponding y value should be predicted /// predicted y value with given polynomial coefficients at X=x @@ -858,14 +857,12 @@ module LinearRegression = /// /// Defines if regression function should pass any specific point. /// -/// float*float coordinate type Constraint<'a> = /// No constraints are given. | Unconstrained /// The regression line must go through the origin (0,0) | RegressionThroughOrigin /// The regression line must go through a specified point, defined as float*float tuple ('xCorrdinate*'yCoordinate) - /// float*float coordinate | RegressionThroughXY of 'a /// @@ -1022,7 +1019,7 @@ type LinearRegression() = /// Creates prediction function for linear regression. /// /// Linear regression coefficients (e.g. from LinearRegression.fit()) - /// x value of which the corresponding y value should be predicted + /// x value of which the corresponding y value should be predicted /// Prediction function that takes an x value and predicts its corresponding y value. /// /// @@ -1046,7 +1043,7 @@ type LinearRegression() = /// Creates prediction function for multivariate linear regression. ///
/// Multivariate linear regression coefficients (e.g. from LinearRegression.fit()) - /// x value of which the corresponding y value should be predicted + /// x value of which the corresponding y value should be predicted /// Prediction function that takes an x vector and predicts its corresponding y value. /// /// diff --git a/src/FSharp.Stats/Fitting/LogisticRegression.fs b/src/FSharp.Stats/Fitting/LogisticRegression.fs index 873c1a639..95bf061fc 100644 --- a/src/FSharp.Stats/Fitting/LogisticRegression.fs +++ b/src/FSharp.Stats/Fitting/LogisticRegression.fs @@ -127,6 +127,7 @@ module LogisticRegression = /// Returns the regression function /// /// + /// /// /// /// @@ -204,6 +205,7 @@ module LogisticRegression = /// Returns the regression function /// /// + /// /// /// /// diff --git a/src/FSharp.Stats/Fitting/NonLinearRegression.fs b/src/FSharp.Stats/Fitting/NonLinearRegression.fs index 54c5234ca..68197e269 100644 --- a/src/FSharp.Stats/Fitting/NonLinearRegression.fs +++ b/src/FSharp.Stats/Fitting/NonLinearRegression.fs @@ -376,6 +376,8 @@ module NonLinearRegression = /// Returns an estimate for an initial parameter for the linear least square estimator for a given dataset (xData, yData).
The initial estimation is intended for a logistic function.
The returned parameters are the max y value, the steepness of the curve and the x value in the middle of the slope.
/// /// + /// + /// /// /// /// @@ -535,6 +537,7 @@ module NonLinearRegression = /// Takes the result of the linearization as initialGuessParams /// /// + /// /// /// /// diff --git a/src/FSharp.Stats/Fitting/Spline.fs b/src/FSharp.Stats/Fitting/Spline.fs index 80eaa661c..d26ff3fca 100644 --- a/src/FSharp.Stats/Fitting/Spline.fs +++ b/src/FSharp.Stats/Fitting/Spline.fs @@ -9,7 +9,6 @@ module Spline = /// Some preprocessing of the input data /// - /// /// /// /// @@ -32,6 +31,7 @@ module Spline = /// Creates a smoothing spline through some data. Takes as spline points the x-values given by basispts.
The resulting function takes lambda (regularization parameter) and a x_Value as input.
/// /// + /// /// /// /// diff --git a/src/FSharp.Stats/Interpolation.fs b/src/FSharp.Stats/Interpolation.fs index dfbe59bbe..29f58812b 100644 --- a/src/FSharp.Stats/Interpolation.fs +++ b/src/FSharp.Stats/Interpolation.fs @@ -31,7 +31,6 @@ module Interpolation = /// /// takes x value to predict the corresponding interpolating y value /// - /// x value of which the corresponding y value should be predicted /// predicted y value with given polynomial coefficients at X=x /// /// @@ -355,7 +354,6 @@ module Interpolation = /// /// Predicts the y value at point x. A straight line is fitted between the neighboring x values given. /// - /// X value at which the corresponding y value should be predicted /// Y value corresponding to the given x value. /// /// @@ -598,7 +596,6 @@ module Interpolation = /// /// Predicts the y value at point x. A straight line is fitted between the neighboring x values given. /// - /// X value at which the corresponding y value should be predicted /// Y value corresponding to the given x value. /// /// @@ -772,7 +769,6 @@ module Interpolation = /// /// Returns function that takes x value and predicts the corresponding interpolating y value. /// - /// X value of which the y value should be predicted. /// Function that takes an x value and returns function value. /// /// @@ -1015,7 +1011,7 @@ module Interpolation = /// /// Returns integral from interpolating function from x=xVal1 to x=xVal2. /// - /// Interpolation functions coefficients. + /// Integration function. /// X value from where the integral should be calculated. /// X value up to which the integral should be calculated. /// Integral (area under the curve) from x=xVal1 to x=xVal2 @@ -1061,7 +1057,6 @@ module Interpolation = /// /// Returns function that takes x value (that lies within the range of input x values) and predicts the corresponding interpolating y value. /// - /// X value of which the y value should be predicted. /// Function that takes an x value and returns function value. /// /// @@ -1106,7 +1101,6 @@ module Interpolation = /// /// Returns function that takes x value and predicts the corresponding interpolating y value. /// - /// X value of which the y value should be predicted. /// Function that takes an x value and returns function value. /// /// @@ -1767,7 +1761,6 @@ module Interpolation = /// /// Returns function that takes x value and predicts the corresponding interpolating y value. /// - /// X value of which the y value should be predicted. /// Function that takes an x value and returns function value. /// /// @@ -1944,6 +1937,7 @@ module Interpolation = /// If the knots are monotone in/decreasing, the spline also is monotone (CJC Kruger method) /// The x data has to be sorted ascending ///
+ /// x values /// function value at x values /// Coefficients that define the interpolating function. /// @@ -2003,7 +1997,7 @@ module Interpolation = /// /// Returns function that takes x value and predicts the corresponding interpolating y value. /// - /// Interpolation functions coefficients. + /// Interpolation functions coefficients. /// X value of which the y value should be predicted. /// Function that takes an x value and returns function value. /// @@ -2366,7 +2360,6 @@ type InterpolationMethod = /// /// Creates a spline as piecewise cubic polynomials with continuous first and second derivative at the knots. /// - /// One of four conditions to manipulate the curvatures at the outer knots. | CubicSpline of CubicSpline.BoundaryCondition /// /// Creates a subspline as piecewise cubic polynomials with continuous first derivative but DIScontinuous second derivative at the knots. @@ -2375,7 +2368,6 @@ type InterpolationMethod = /// /// Creates a spline as piecewise cubic polynomials with given slope. /// - /// choose between cSpline, given slopes or monotonicity when appropriate | HermiteSpline of HermiteMethod diff --git a/src/FSharp.Stats/List.fs b/src/FSharp.Stats/List.fs index 88c4c02cb..43911e177 100644 --- a/src/FSharp.Stats/List.fs +++ b/src/FSharp.Stats/List.fs @@ -39,9 +39,9 @@ module List = /// let inline median (xs: 'T list) = let one = LanguagePrimitives.GenericOne<'T> + /// Partition list into three piles; less-than, equal and greater-than
x: Current pivot
xs: Sublist to partition
cont: Continuation function
/// - /// /// /// /// @@ -70,9 +70,9 @@ module List = // place item in greater-than pile partition x ys (fun lts n1 eqs n2 gts n3 -> cont lts n1 eqs n2 (y::gts) (n3+1)) + /// Partition input and recurse into the part than contains the median
before: Number of elements before this sublist.
xs: Current sublist.
after: Number of elements after this sublist.
/// - /// /// /// /// @@ -228,7 +228,7 @@ module ListExtension = ///
/// start value (is included) /// end value (by default is included ) - /// sets the number of elements in the list. If not set, stepsize = 1. + /// sets the number of elements in the list. If not set, stepsize = 1. /// If false, the list does not contain the stop value static member linspace(start:float,stop:float,num:int,?IncludeEndpoint:bool) : float list = @@ -241,7 +241,7 @@ module ListExtension = ///
/// start value (is included) /// end value (by default is included) - /// sets the number of elements in the list. Defaults to 50. + /// sets the number of elements in the list. Defaults to 50. /// If false, the list does not contain the stop value. Defaults to true. static member geomspace(start:float,stop:float,num:int,?IncludeEndpoint:bool) : float list = let includeEndpoint = defaultArg IncludeEndpoint true diff --git a/src/FSharp.Stats/Quantile.fs b/src/FSharp.Stats/Quantile.fs index f1a0bfc07..87abe0e86 100644 --- a/src/FSharp.Stats/Quantile.fs +++ b/src/FSharp.Stats/Quantile.fs @@ -542,7 +542,7 @@ module Quantile = /// Computes percentiles
percentiles: Each percentile must be between 0.0 and 1.0 (inclusive)
CalcMethod should be ofSorted array
/// - /// + /// /// /// /// diff --git a/src/FSharp.Stats/Rank.fs b/src/FSharp.Stats/Rank.fs index faae6fbb0..97cbf13ae 100644 --- a/src/FSharp.Stats/Rank.fs +++ b/src/FSharp.Stats/Rank.fs @@ -4,7 +4,6 @@ module Rank = /// Comparer that sorts nan at the end of a collection /// - /// /// /// /// @@ -25,7 +24,6 @@ module Rank = /// Comparer that sorts nan at the start of a collection /// - /// /// /// /// @@ -36,7 +34,6 @@ module Rank = /// Ranks each entry of the given unsorted data array. Use 'breakTies function to break ties /// - /// /// /// /// diff --git a/src/FSharp.Stats/Signal/Normalization.fs b/src/FSharp.Stats/Signal/Normalization.fs index bfa942699..c01ff54fa 100644 --- a/src/FSharp.Stats/Signal/Normalization.fs +++ b/src/FSharp.Stats/Signal/Normalization.fs @@ -17,10 +17,10 @@ module Normalization = /// /// /// Bortz J., Schuster C., Statistik für Human- und Sozialwissenschaftler, 7 (2010), p. 35 - let zScoreTransformPopulation (yVal:Vector) : Vector = - let yMean = Seq.mean yVal - let std = Seq.stDevPopulation yVal - yVal |> Array.map (fun x -> (x - yMean) / std) + let zScoreTransformPopulation (yData:Vector) : Vector = + let yMean = Seq.mean yData + let std = Seq.stDevPopulation yData + yData |> Array.map (fun x -> (x - yMean) / std) /// /// z score normalization/transformation using the sample standard deviation. Rarely used since variance is not equal to 1. @@ -34,10 +34,10 @@ module Normalization = /// /// /// Bortz J., Schuster C., Statistik für Human- und Sozialwissenschaftler, 7 (2010), p. 35 - let zScoreTransform (yVal:Vector) : Vector = - let yMean = Seq.mean yVal - let std = Seq.stDev yVal - yVal |> Array.map (fun x -> (x - yMean) / std) + let zScoreTransform (yData:Vector) : Vector = + let yMean = Seq.mean yData + let std = Seq.stDev yData + yData |> Array.map (fun x -> (x - yMean) / std) /// Summary of the median of ratios (mor) normalization with normed data, determined correctionfactors, and transformation function. type MorResult = { diff --git a/src/FSharp.Stats/Signal/Padding.fs b/src/FSharp.Stats/Signal/Padding.fs index 0be333ca0..5ff4f6c16 100644 --- a/src/FSharp.Stats/Signal/Padding.fs +++ b/src/FSharp.Stats/Signal/Padding.fs @@ -30,6 +30,7 @@ module Padding = /// median spacing of the data points /// /// + /// /// /// /// diff --git a/src/FSharp.Stats/Signal/PeakDetection.fs b/src/FSharp.Stats/Signal/PeakDetection.fs index a011d4865..4f15807bf 100644 --- a/src/FSharp.Stats/Signal/PeakDetection.fs +++ b/src/FSharp.Stats/Signal/PeakDetection.fs @@ -331,7 +331,6 @@ module PeakDetection = 0 /// Inspects the sourrounding of the peak. The function walks in the direction given by the step parameter. The function accumulates all
lift offs till till the next peak or the end of the signal trace is reached. Returns the last index, the number of lift offs and a bool
indicating if a flanking peak is present.
/// - /// /// /// /// diff --git a/src/FSharp.Stats/SpecialFunctions/Erf.fs b/src/FSharp.Stats/SpecialFunctions/Erf.fs index 6db65b96e..a545e2421 100644 --- a/src/FSharp.Stats/SpecialFunctions/Erf.fs +++ b/src/FSharp.Stats/SpecialFunctions/Erf.fs @@ -18,7 +18,6 @@ module Errorfunction = /// Computes the error function. Note that this implementation has only been verified to have a relative error of around 1e-5. /// - /// /// /// /// @@ -41,7 +40,6 @@ module Errorfunction = /// Computes the complement of the error function. Note that this implementation has only been verified to have a relative error of around 1e-4. /// - /// /// /// /// diff --git a/src/FSharp.Stats/Testing/TestStatistics.fs b/src/FSharp.Stats/Testing/TestStatistics.fs index e81a5279e..955c125ff 100644 --- a/src/FSharp.Stats/Testing/TestStatistics.fs +++ b/src/FSharp.Stats/Testing/TestStatistics.fs @@ -9,17 +9,16 @@ module TestStatistics = /// Creates a new T-Test for a given statistic /// with given degrees of freedom. ///
- /// - /// The test statistic. - /// The degrees of freedom for the numerator. - /// One Tailed/Sided. - /// One Tailed/Sided. - /// Two Tailed/Sided. type TTestStatistics = { + /// The test statistic. Statistic : float + /// The degrees of freedom for the numerator. DegreesOfFreedom : float + /// One Tailed/Sided. PValueLeft : float + /// One Tailed/Sided. PValueRight : float + /// Two Tailed/Sided. PValue : float } @@ -33,13 +32,12 @@ module TestStatistics = /// Creates a new F-Test for a given statistic /// with given degrees of freedom. ///
- /// - /// The test statistic. - /// The degrees of freedom for the numerator. - /// The degrees of freedom for the denominator. type FTestStatistics = { + /// The test statistic. Statistic : float + /// The degrees of freedom for the numerator. DegreesOfFreedom1 : float + /// The degrees of freedom for the denominator. DegreesOfFreedom2 : float PValue : float PValueTwoTailed : float @@ -56,20 +54,16 @@ module TestStatistics = /// Computes the Chi-Square test statistics for a given statistic /// with given degrees of freedom. ///
- /// - /// The test statistic. - /// The degrees of freedom for the numerator. - /// One Tailed/Sided. - /// One Tailed/Sided. - /// Two Tailed/Sided. type ChiSquareStatistics = { + /// The test statistic. Statistic : float + /// The degrees of freedom for the numerator. DegreesOfFreedom : float - /// one tailed/sided chiSquare pValue + /// One Tailed/Sided. PValueLeft : float - /// one tailed/sided chiSquare pValue (default) + /// One Tailed/Sided. PValueRight : float - /// two tailed/sided chiSquare pValue + /// Two Tailed/Sided. PValue : float } @@ -83,13 +77,12 @@ module TestStatistics = /// /// Computes the Wilcoxon test statistics for a given statistic. /// - /// The test statistic. - /// One Tailed/Sided. - /// Two Tailed/Sided. type WilcoxonTestStatistics = { + /// The test statistic. Statistic : float PValueLeft : float PValueRight : float + /// Two Tailed/Sided. PValueTwoTailed : float } let createWilcoxon statistic = From 3f626bc146dcabb5458936d666762ec4cc9998b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20M=C3=BChlhaus?= Date: Sun, 10 Aug 2025 17:23:47 +0200 Subject: [PATCH 101/121] Fixed Namespace --- src/FSharp.Stats/Distributions/Discrete/NegativeBinomial.fs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/FSharp.Stats/Distributions/Discrete/NegativeBinomial.fs b/src/FSharp.Stats/Distributions/Discrete/NegativeBinomial.fs index 429f6217a..9b69b855f 100644 --- a/src/FSharp.Stats/Distributions/Discrete/NegativeBinomial.fs +++ b/src/FSharp.Stats/Distributions/Discrete/NegativeBinomial.fs @@ -1,4 +1,4 @@ -Fkspace FSharp.Stats.Distributions.Discrete +namespace FSharp.Stats.Distributions.Discrete open System open FSharp.Stats From cbcd5c7cfc8ac25d229f8f70011dc8a3f05acbad Mon Sep 17 00:00:00 2001 From: David Zimmer Date: Thu, 14 Aug 2025 07:50:47 +0200 Subject: [PATCH 102/121] add tool references for holm and hochberg validation data --- tests/FSharp.Stats.Tests/Testing.fs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/FSharp.Stats.Tests/Testing.fs b/tests/FSharp.Stats.Tests/Testing.fs index 9a51a9679..e76ad3ecf 100644 --- a/tests/FSharp.Stats.Tests/Testing.fs +++ b/tests/FSharp.Stats.Tests/Testing.fs @@ -406,7 +406,6 @@ let pearsonTests = [] let holmTests = - let largeSetnan = Frame.ReadCsv(location = @"data/holmHochberg_Input_nan.csv",hasHeaders = true,separators = ",").GetColumn("pValues") |> Series.valuesAll @@ -415,7 +414,8 @@ let holmTests = let largeSet = largeSetnan |> Array.filter (fun x -> not (nan.Equals x)) - + + // calculated using stats "The R Stats Package" v.4.5.1, using the p.adjust with method parameter set to "holm" let largeSet_Expectednan = Frame.ReadCsv(location = @"data/fwer_holm_results.csv",hasHeaders = true,separators = ",").GetColumn("pValues") |> Series.valuesAll @@ -457,6 +457,7 @@ let hochbergTests = let largeSet = largeSetnan |> Array.filter (fun x -> not (nan.Equals x)) + // calculated using stats "The R Stats Package" v.4.5.1, using the p.adjust with method parameter set to "hochberg" let largeSet_Expectednan = Frame.ReadCsv(location = @"data/fwer_hochberg_results.csv",hasHeaders = true,separators = ",").GetColumn("pValues") |> Series.valuesAll From d5733649090c9892f57b17a4e4c8ba3f26440ac2 Mon Sep 17 00:00:00 2001 From: Kevin Schneider Date: Thu, 16 Oct 2025 09:28:02 +0200 Subject: [PATCH 103/121] #352: remove native lapack dlls --- lib/LICENSE | 48 ---------------------------------------- lib/README.md | 11 --------- lib/libblas.dll | Bin 447037 -> 0 bytes lib/libgcc_s_seh-1.dll | Bin 74240 -> 0 bytes lib/libgfortran-4.dll | Bin 1801728 -> 0 bytes lib/liblapack.dll | Bin 7457332 -> 0 bytes lib/libquadmath-0.dll | Bin 326656 -> 0 bytes lib/libwinpthread-1.dll | Bin 52224 -> 0 bytes 8 files changed, 59 deletions(-) delete mode 100644 lib/LICENSE delete mode 100644 lib/README.md delete mode 100644 lib/libblas.dll delete mode 100644 lib/libgcc_s_seh-1.dll delete mode 100644 lib/libgfortran-4.dll delete mode 100644 lib/liblapack.dll delete mode 100644 lib/libquadmath-0.dll delete mode 100644 lib/libwinpthread-1.dll diff --git a/lib/LICENSE b/lib/LICENSE deleted file mode 100644 index c9ae626c2..000000000 --- a/lib/LICENSE +++ /dev/null @@ -1,48 +0,0 @@ -Copyright (c) 1992-2013 The University of Tennessee and The University - of Tennessee Research Foundation. All rights - reserved. -Copyright (c) 2000-2013 The University of California Berkeley. All - rights reserved. -Copyright (c) 2006-2013 The University of Colorado Denver. All rights - reserved. - -$COPYRIGHT$ - -Additional copyrights may follow - -$HEADER$ - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - -- Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - -- Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer listed - in this license in the documentation and/or other materials - provided with the distribution. - -- Neither the name of the copyright holders nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - -The copyright holders provide no reassurances that the source code -provided does not infringe any patent, copyright, or any other -intellectual property rights of third parties. The copyright holders -disclaim any liability to any recipient for claims brought against -recipient by any third party for infringement of that parties -intellectual property rights. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/lib/README.md b/lib/README.md deleted file mode 100644 index 11cdd7a51..000000000 --- a/lib/README.md +++ /dev/null @@ -1,11 +0,0 @@ -This file is in the `lib` directory. - -Any **libraries** on which your project depends and which are **NOT managed via NuGet** should be kept **in this directory**. -This typically includes custom builds of third-party software, private (i.e. to a company) codebases, and native libraries. - ---- -NOTE: - -This file is a placeholder, used to preserve directory structure in Git. - -This file does not need to be edited. diff --git a/lib/libblas.dll b/lib/libblas.dll deleted file mode 100644 index 1d9faabb4a34f9b28ffba220f42b1bd5cee63c96..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 447037 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

vLa3<2^)a%8@d{pD8j*3N#Jfk(yqt)y z4|DaC`BSe&WoYN@LpYejj55J@eVt$GuClEu;q^9(%o?noG7wMa7JF3I`rG!J@IFBC ze)q9J@m8>-6z`AP$OI5tMlXFMqd_iViJe&T|1usrJ};)OAlWx=R74!Bu6dPaZ5uaU zlAZRPRc}>P#gDmDw29-LoF*GT8Egkl#K$6bRn@M}b1=2iL|k9jQ{%GJw%M&}V|WSn zPm{qGG~K?-4NH&LCbG4**Ij+@<;<51KTMzYkG_f1Ckm%ma=NN;n(V|MPr24k)RSdo zSSF7m>04s7HYhs>IhJxeqTpV*xkLmkRvN*Mi?bzMSE9dPF3q>q^nLNrqw&8`sOD8x zNT*lhYW(bP$QJ?SyS)lghDp2S(sI%1ihwmouU&J>dn!j0T|A(N57d1wE@3}I}r=!^;Vz9CHH6l22hpf&E7_KtP%y1S#jwE`w3UW@=?F*ya7iwbV3M zpy&nQ>6+CmqL!}-`f7yw5FhOG{LgU@>cM)+BC*Zg*ujmpEF|`d?Yh51_eJ0&3LBw% zgUbec8+}sW!vZDZ zFAN~*xa#L(fq}^S6)*utE=M$Qi+T^UsR4%q%4Iq*swto(oV{Xk0F;;Z1^CbZ33YJBj`W_1?z1!#-02&mIF;yq1VQOHV%+?RF zBBo{tN6&_|RrFr$Q!(d-`Wj~MF zHz#nA@>fnZ6Clu4WsRsRtEiHh6l;y`1Dpj0OOISYmDb-Zi^g3cQvzN&vBTG}Vt;2I z8?RaHwM-YOKM0Qn3BG0a$#3n=T@9f0(Y=F9Um zxgzzNOX4w2h9}zji>{h{2Qs{ws{d;2Cv9U&Hm;60zN1u#c;mG4QD%9HK+mlgNo_)n zIKIYrsi6_5`KdH7yClUEw&SOY_Uv+M283gj?$6+UGCPAkD;M=9(SPzhWf}bD8;+E~ z7j!nokrMyxvPfrikr@M=w~dmPPmzm)35%3DI*sYda?_h_Up$fJSZVynLbu~&5-{Sz z$rZ>(uEnM_-0>(Gv*0lj(mB0S0(#{GLrTo5^|y-X-M@vJ%zc!lVMD%n<5KjRC-+va zv7{-hT!tV^Ik%@Jz>g}}U$BN1$O&Bz&8h2k=MmZ9Vj*-=4dY6W~KPfz6WKaqc|XSRHFUKO(uvfSAp)y?Gzxo`6e;7y#|7m#Zm>7rW-hAB7kFQ5EXbFQ7y9KIhsf2H683gmr*q|Nlo1S%4%_ajglJYmn@$pS`pu7sFK&aaMz z)=RSn_M`7$TzfVN$s9v%5K4j7WsgU{G!cIjlWcy)OVLVSgmyd89&riNvjvBmcrU~M zvl626B7R<)>fj|m)9`Rbe4?F;M0_J*xePMdIcL9#!pc|kfXuY@PR!$~& zv&kAP*ssJgn+R!_P>;Dfx(4HQqxLn_*@QK3X@5VV0bRnU48$Qst3DkWioX8IwPOR2 zjMcoxgQB#rvH99lg2B!U0-q87YbWRbACmF4&s*6A;Pa)J!#@ndm}nQnO-cPt_7h+m zw{FzzvDx92U}I9L)wVd1X)Ex1x}H$=mqmfR&(O*w=1BvR$R|*g(x{!#ObrEBF_-uN zdH`|%GJ7bmgN`+$%0L~I$25XCbu3!G$pCV7092uW1v2P^)~8uDamTV3?R!k% z>O}q4`+a^qo-HifhV;g$C+=0fYm2u6`}=qE5TdhboI%W3Se;FVmZ?5H@M%WB=M$8i zOV5^AZ}rTm-g#6cL*b-HOeV;FSs>EOG;@1qrx~K6iw#2e_EQ`!4X&L>31)V%FV?=_2qp}+i#I|>=UDc*jX+j@jh2rC=C+?zNu zP9t9We+;!;@7U`4IdVKF61p(CG&`NGmCxMa>^EA;v089t6u!#;cSU?p1ws53UuY|C zMKmuIU!C-d9=Kc#_bHv4`C$u3saFLAD{0~l9c<@M>RQ>+%titcO}QmEzN}meUXa}+ z>Xqp+);wABtk?22o1978;*E;#cug?2R)4hR-!lwyOXmfF*9&r;lIQCt@#UMg=Pn0Q z`pNrinS{Sd-WR;dEZmBx;MuxN2c81o&0`=I&pd&F{Iy?LMPCyDB_OssvoNowg0nMw z9-h;;kb=v#e?YHx_WW?b&2_XpUpG5?W(>F~tNgdP8R6BhaJNOZ6PlV@wnng8duiDi z1empaT>=KDJi0jA`UzZCWp~vPLZIRAidqPHQGwWLDg@D(g$DlTE54~qTi~I^gfn(Gb(6*t-Zy8(T34V{p0Xb+KG)}xj-8BNahTE0!s)Fj;~=^dsc)S`as z+M4?q+df|X+tf9bGl6g)gb|IjLpHm;RLI6F(-TE;#LdtzfPWyT5gv{%b+`D`NNuR(- zujO@)r5wr&#FC|V@*8i2;ruU8DuU!?=lBuqX*uI9@8FBU$`$^aA6>u2yJrDXW>*@u zQ~Q~ERc{qt>EMc7Fp`LQY3O%;X4#asgEb+u!OLD186x*AhJ?Em}TFktI0MK7`X_ zphgf+h5TS{Q&GQdibsftc0_8HH@}eUWw!J26kuHQIhqBH#LbDC{;!`x!mEzTkGSb0 zUR7gh{?u#vr7c-4Vm*dawt|f}Hk6+kZ&{M?;$8T>_*si~o&I-PwJk0DA?YhoMCHhz zv<@!UL*J|6d%oTP!yow%oI;qxBTn`Yj^?4;D7#ffEx*T2$7bdhkAZ!6Vd+E(MV>SI=zhye_ zr}w&bxmZhqA0j+-Hdlfr(JLq4;6F0*S`Jv5#Vo}eTDWBPo48Rd3x}1$5?jTlYi^}< zn`2ulAK*Hc$j>e0}9B(2ygdc59j19m7gI{EhS-Ae|b8VmXVG`W>NJ%fO z4;p-*^-;#mBP>TE^jtjjbW|%ObuuxhV;F103f0xT=e1O8d6Lq5^7*5J9V8S=TA1id z2#A(?OKwJhe*@@*qYwS*LZGiW`Vf{-35+2*y9gHoE*LJdRUSrhHA*@PoH9m778lWx zM|1xnT}q%$)UM?hZ_GDJGcvb3Unjy7QyLW4@SQw1j77QMV_A@5mR3cPJ~VIBQDfad{6l$zcpYvW4&SyEJgy-*(m z=Zl0{03v)DPML{HKgvOd`2<9OKbx5vW)}YnX@pEU&RnF?C%Khc-uyer7S1(wvb0{!DSF?iuenz8^{!& z)2yqAX4zL*adc#A+~Oi^`MhRc;T^MFx)naT z`-iGow;@>Y!g_za-+DXbw);ivokB|tU#8W9RNBVAy)3oA%A{sbgekLtOk)oRR{pa; za{u0Bl8PmaUe;!nOtj70pYm6GwXHUAVc6ZUbkN2ApjKjRpT$0Fz+x-pG#4TTnujUW ztCSZGK1SzROjKetXOk}^nXKWK<#-DEMDra!%gxVs++w>avDFTc*5}m3Ut2wHXQsr0w__ss!F^zlZbnbDeL_G+ux6d6FQAqT#E1*V=J&%BqXS4H%B_^DJLA(Nv(e$YQ? zcaUQ3qR$9a&}XftPn*SPCn>x$Pn(|$XtSes%@5-}HuAiTsc}ecRQ*|h`N+VH!TB2& z_{16f%F}1v0$tD7q{^#V7Pqi`xom4Xyp}UrFA?ZO=xqgTRQLp1F>SfCi|UQ=dbkAK z4d`>d!(F=5mp%&)`_boN?yJ3b7A7cn8tn@=j_xPvIa!+-8v3&z^cC<%-oXXEGU9d) z0s)U%87SW!R1(*YGA8Er6Yr3~`-peq^1gWY3Wp}%{ak##pLpli`{F+G-6szqeY@xX zZt{0tzKamzUnJj2{5JVc+%Pwd`rPy>&=>j&cTf}P<;Qu>9?8?o`cORKOJDYOf+p9a*o08zW57Cm z&Bgvb4WqN#LdN67+RUU!D3bHA7|9du3qI8Q!#s*?$QfLoIgOJ4yKVHi*&BT+;XiaPm|kJWK->G2^WPeiYq^k@vV zuk`3+XNV6v!|^*6Ed$aX!N9r-{OVY1QkCA+!eEUi6Pe50>z)fK6|oo5LO zAh(cc9kxK|IlbRw*dl3i5|3d>?M#a&byin8{y%AfZ?qG0P@&+KvTtImLUxAh<&F}`pv zHpD-F-E4^dl>0FofMhV`1dW%_FjwxjWNHqADJS;BO?gEy<-~s2l;6Hc3)#o2=+nb~ z=1`{RT=nAZY0jT5yPiJ=8Ys!dfx_Zf+{7QPSK9qoIts7I25V_;1^wD@%v|6yAo}Ns zj3v2V&Nat^4$a`)v-l?GS|-_npWwb$Nkubd5_*f3wiZ!;3m#C#9a&;+?QFTq!EGdj()E!29x ze=5fG`=EpU34INjRH^HPXPS7ItKWJHae7HiAV82g?Y}0elI*j1g}DAXZOg7?Nx1K<)C(_ zw8yit5GMTV@_7fDborh77%w}7omoC3o=p)eS8C{v;SX%4+z{W4^YCmQmI%jv-+_`W z3CD3&OJ%LLy&@B&gzF$h-MdiijFlWtCC#r%5h0=^iR{d;mzaGyF=sK>{zok2F}Pco zZTi6R7N(**kMTM79SrMuzK;Di;@O$IhO->hQh2=lK5nRQzvfp_6XfU+Ow5Vd8!sFt zu@-7@;c(Ea3&rTV62VZHKuT6bTS7A$Nk|8i(tm~&A%xDlPSf&`T4x5-6(zK!NNh=l z*5vJ5{puCUKuqgw`XDDfes%r?cA^HdBF#vA8Ns&}HL3)g~#rqDg~jQZIrjHu>fiuCT;MYglqFV3^Wiz#BwH$iu)vX*ic9Gn>tPA0EP! z(j?f4&TL9I7mW0Z6QIjR6LHiVRw=)xVKFC`y{R**T3ODZbPC)1?X6_ZPOs%^z!kOb zoN47#z4SW-UuXig65{Au9;u-B@jEU%I;=$|`hQJ=9j8K_oJ_Cm(ZI=dIkVlzKO609 zyg;7_-`@+73YV5M;3rvB#-x#&xmDvf`Y7*DgImb|3j=O2{B&qhM`ji)G(#|II29t$ zFUcQrw%X#M1xX9r4!s+PCf34F*w8Q@ik7G1p_%3Nxy!`n<=?v4?4(EMWRjY%@iJ^d zFcVN(ZZ^nb*p)6=H00dzP*l^O{*(4J>jpfTwq$6f_$lqHo}?Jf8h`Btzc|pCNLUgk z9vxw+4&Tf&!yfR!@$jqS4&D4|FuTbPE~%=YGq}sHZT36)K;GaoN{g40rLI5?yPDIv z578wtbL|Qqh!fG)^W|)HLWN|BR6wDHYZZtYAfXc`6l^wKL=oUe9Qht8RZZnn#|Cmq zW}9BG*Xs^p8rf2EBYUl_if8V%1tGw1B!nVbK4WaQbSsV6Ni~;G*5({>RfUL30CDRX z&mMmok(R-JYbKvqD1@K6Qj0xA@HuaYBo_c(!bvQ9bx2*9t=3s^putgCW+N}EaH*f1 zlIMStR}@fa@=B~`qXd{~iw-2N%srORC;d4}G_K0?J9fM~LETcvQLRs)Dgj=ZC8c^+ zGla>0IXe+fSWz0w>?X>tF0?|SkF{)0Gdhrm2Z$-3o4a6|~733Q;4jxp#xumara}?h{GWkY+p}c%^OF_QrK)$&F04~TkohILO zBHs|XO{MwxX-dFAsHslYm>grdrh?4)QAnkbvbgrjtJkKbQ{#v`(-C*B^IDz)0dgBD zdzse%Cs0|v6DLM*rcc<|Ja88p0y?9JrBv^-yooi-ZE#jt` zL_r?kUK6_Y8ybYg=g5$z{A`O>$|(s9dNc6TU)QIH+NYaa^f=gFlH1MF2k}FutgFf$ z@9P0m*4MgoKs8ApTb6Jt$DlSl4RWxhlRJ@==oGDPHT_hLeEoV=)lQ~VB#sn)6ms@; zHZfC|{*g<1N5mTR9=hgxriyDrn{ZhAi9P96Esx*~<2Xv>P}4Dr>uLG2x>oh9g!!b~k|<{`oIa6F3~QRg2S!}uzBcqKe%af(V84JK z4T$w=$BRIIC)=B>Y+jjLBR-suCr|~N{9P~oCvNs@uTN}1H^k^A7sW1{BN_=piE~;@ zH<%)N=wgf(_ujAd5rCwR7XN5@#|G@9N_ONAz8e@71Y)T9J)^F4R<4hm`upRw0=!eO^;)8JSv=C|{_{&KM?n#g-NczCvtjGGr19^*uxmDV7KY1HGa>;v$J$$gEYnkhUSvb}RMjQOC4PX+ZNh zKbf7Ra;4HAut#jt)*2`fy`Rk9TIw%< zWv=&R0LSw4@bxxVxYZ+$YY!0?N!qE&(Tg}JmZMcF<}nMO z1V4ktGQ86w{fugfUX>~?Se&z$Ud1|lRnrTo*77L=lyZ;jGVhauoo*u`(3ZMsx-4i~ z168cV3h$tcc1N5~yK4U&eiPa64)f*hXwA}@r(~8#E4!?=+iCCZy`$$`AAD611qR4^veLolyNq3U^ zv7oslLO!R(YpqvDev$ha9f49v%ccM$Xr*X}d8J&9wB8CxYZ6{I)lkW7dPU@{P7v%%ok0)6A+CIfE4)ka zR2_6^zQn~E+Q6>hiBbD;F?o8!8%83Jmjo^=F`yGpE|-e8-sE+J^R@nN*#b)hZ9o&T z{5hb?;$nQ?>!X-!q~P)2j5^YfEH7(0C`;!i5wa4)x?~cNMaEq0%mliO08|5(l=&`D z%sRv3l@ya)S68#vYZ(LDqU6bJKnuuJfVA=G2YP**Yv}4N;Y#OxQYRChkT`6by|^i04hW%2K#$QfF--!)&{jTF8hozzt^$27Op*ESjZ?l& zOiy1<=>ls5+Kc(YXh5D(e*9Zjf0gaC5c>mesr4GU`{qFz<*Qsi97aieE#b93=@gU1 zCQj~0Eg*!YjZ~QaT+*u0XuogxBikr>Ev0~j&m!eGH5R!XcoFgOlMQ>x>4cTMkY|sl zialDGGwks{cv#9v={o&wSXWxiAZ5P_A7=~_Wx7Xa*JHR7Qp*I2+Haw{5bg$)y3~uk zA1;E&QuL^B!wQIjU&RZuIBB^vKI9{OMZSzfA|VYZ2^y(caqFYGae&Qyg7na_AUJg) z@=qE>8YJrGPQj!gc}naAFX{0D%CaO`kr)>uH4ARtoXbhFrSD=kK1Fa*;=Vk1fCx;- za9~}t7UX_GGetU8KYi*%=KlX!{j0}lT;lg^e)}t4^SRbf@%pFff#PLeSJ;;;q2>Ev zSF%%Nu{Pmcf#>m3UK4Ar?s5zQ_V|j}0~`)~aVRhL%;ITj6B!=STXf2lu|id? z?r-wgk9f?KvFZOes%jPY)oE)J)rpnkO4eLnAU z<>G?um>$g~0miTS1vQ4&)7yZDgi-0_HA0jhR8Kpb&+^FfK@_!-j6sI4htzyQQM-JY zo1a8BK1?p8@QAfvcVg%>{5t$?+n>0}UW6;41kKOo7MQF%n>nZCmjpon7D7IEuy7aX zKi@zm&c|*;p$=U?)7qE^wx;ks)7Lh$gvrM1%152i=EftiB3q^+a3zg=n^mrBc{%CD zyIrcx_MU6&oc8uzV8ujKX>Z2`+S@h)yKU7ZrzScVBk7pp7Ocx-G^nf$O{h4}$v@)) z`dV!?`^}K0k?ZO(hC8E_CGM)rUM`bvc;xqZ&M6Np)h@T1rXilfrY%)nFq=_MZL`~| zY_dQb-YMk+mgK99Jk=l;L;*A;K@O^oG4<8r%tdvl7Tnk3@CpaDs(LW0V(hH_5H~y2>4OmD_vI2Ok7)#=ulS^fJzR z@@G-by7Ome!6@oNFA_=?t?BjBAJx3UwtVf6N85Bd)s#VIz?WO@)5TAY&5|x9PQuA} zcB7pz6#t*>l5ZoGyvVdpdYKb(zD+#RpyFznc9emVo`>^&gdy#ngz0a z-7T(Q)Vo@vGi+AD{juHYr#Lix{SnP(pnj@)vgjtLg=^7I=i_H} z`YD(Pg1J3XrHkFd9YMKtzKGdO0B#W$!D}2ymI@U9hy#A#B^uzNfi#sEB*6>rd82_{ zUS<9NvA~TN$Cr-Fp81Nk2Q{hCL0$H1!#Ezr6Y$2FF8o)RtY(Dnd6g2-_#}&pj&KIk z=j4B3M{QkZz3_slDw4@m(ezPXy9A9g&Q^ln>s$H%vceW*z+?VS7OZucK3KKmgY!QaK+P#f{<$zYGnz-rll$aY|;*>lzwGyF*oFk zWFOhH`Xd2zr)e47RuIK2O{${UZKO>_fg8An%90WSxd_FZEff+-w@%sgJL;59B>svY zZd6Fo2=YXZGAxK!O2iLc$K-+(ic)C6^ej|JD(z!FZH7OH_{fGx6-GNQ)0~MESl6Fa z51GM+*Xe-#2Uvgbh`A2En(xrHrMa6xKH$0ka#@T5q$gN!)~7f>0K7%HT~>roK9hC0 zv&7*JWwHwPmUd@v0bjbDy+xJ<=dG|w!Xi{Gf8Hf-JBtD2)d4=PHIIrM?0KkFypeO`E1aiOGKd(V}NY`aU#tcs;*EKv!)f~7QzBiu!k>Kk+bWTt4O0Whu$L~{|KJu zZOP0Vvj1^PRkMmWs7nN(Q_(usxnh42EBj{Zq_r}9IJuQsMPx2 zkFtcNa`T0o7KoOFhf7flU)LrBSDq*89f%2@M(39{Dz%$WTk=Pq|FKJAf&blPOw#zD z0u_vXI{qh|%=15ONnUorTd0IyHqZZ5UPP|CG4kHQ|0an4U19w1O~Lo_BKQU$PwHd< zWfMA!l*0<&$7BD1} z&&6`cUp`}rst=ALKVJp4`B;Jd7~An#kOJZkjs3tyfQ5kl80%pf1GXd9qGj9~upTI` zV!p!BrDktW)^u^lLhO8Q=Hk8c?B{Ks-_@7>JVS&1*pEeE@A26WY|pVD96E&rmYn4i zrgo<3tQF^crAZYB9s7~z_$t1HNJ6y?Y*NG5>+f~zVL;d|0tOVV+30240U1Sthyx*Y zITl1ri20Sr#Nj-()Rz+wuEb9g;J+~Tr1g0QBm>!caUi)Vi~|`{4LA@SG)2->O8y5p zyz5hG(5KuD@Ss3W2o@~&JfAEWIQrQ)c0mLc2(Bx;1o_24l zAP4VEQM1{R_w$ZC$M2rs*R0_*{_k@av>DU$T)*4S>T#pHJ-X*F+$Q#RE?w3?t6)LC z^uOuYxP{MPGgM$7Siu2++YR&0(dCym8(#4?_@sq_Lrq z9+c^7INkHF(~pwe>6{Pz{1<7UXTJZ6FvfqyOgDSYT;Sw&|GMgU=U(P|-=G}F4 z%>GXQo#~p_mJRuEdwk04UC4bRv(c;iVq)hS7awnmTMMl@k3IsEm3qHLI-eMgh0bm| z3hFzehR#RX%fWDi3qwb9f$)pPa+(Ff?~0)f;I*Hw*515LzJbtscBE`xlY1U*(Vwwn zHQa|eSFOitGcf_*Zu+$TSF(cQI}B+nBk6$=#WSzR8AEy(mwVnkN9!rbH8@4(Tfrh& z6v2xab(o-e-=uX(8SuJze8DSZS3hFZL~x}SXK2E*=RVIzFv(cdyMkP6li9Bh(;{dt z{37qDe45_YvtU%t)S(9S0J-$Lva|MO2nDo^PXZ=~P;ipq_StGzYMlD=DLo2rt+$z! z*H&N0WN*8Hxnl93CF%<4doyN@c+JyfbMwArs8aJ-C%f_{dve2?5Q0c~kW2f;ITWV# zGtRU*V&hqKzcmv4Q}7C zlpOPAqcyxThG$!NDCtuv`L(9EDeaRm@<&0N+e?Oj~s`B<^_M`<=d+q(?{QO=t7@(U!V_}0-TdY~<@Jes>2X=uI`wzs;_@8e-ooL{Xe1rbUycrDsdI5$RK z=zyMK#h|yj-*BUq(Cl}>^Ed{1Q5d!k9KoYnK*1Sss~(R0*hFR3zl<(!5vaUSo38+R z@(6B9hOakTfeNNHMn426o{fIfY)y_Xxvkld&Dn|y&Hg*X1Rd2;0+3~;g$NOdC@N)7 z1FY=BaIra?4JcLVfG4H|bPUDW<=adEPqEwmSkMHD*2`Dc4O7<%>t)mf8v7`m&Q-G$ zb_!H1d4}D%Hklp?3G!OX^^hNrV;4Tm1y$LJ5;9Orx}F7y(>2PxBsv!`|0q!}iTGI` zfvM`T*>g*JKU^HIEiJK@a1V>oG{gYj(5WnFFdy0E=A*NPCb@D{|QBRlKHA zsAdcOCCTTXdDMl==Tl%zsR*!L!p^LJhu2{^fhr=gE_e7+s}U_(@_rc{KMW!JCy1nFwOJD0a=G^&;2IUB0J)a>7XcDDmoC1Aykz z*}HS|IW~rN5we1q$WJkw1WXLZmdI?4m}@|*A0?S!bYiD6g1+!0c4JMz@WA?~qCi1y z>v2KEkR@ydj6UAD&gEiVL8vt`Fb(C?p-LUe>^K0)m8qrX|Gqeg!Y8Hzpo?v9OA<(8 zA)Z`Ft3F+W{pqm)9<$L-{M#2FZ_vuSQ}A;qDi>crA99w0n$0^wl+(u?X_^44LTNdg zAzCxNfEErk%axoQp0>1<4Qp6fh=$`e7eWrD5`~Xtip8>ERTh#3hk?SN7&SPHeQGmo za@JMZ$otynfdusIxor%Z>Do^{1o)k+hp;YDV>Cu!A)BSKGOJZ1mT1OLSZ=DP`43j6 zb6GOfD^p{2ymFh5Ixf1RhgV;tKL7*PQdnN8##DBlG~8S$p#qy>fI<^dkKR}tl99-a zaXSb?j(aU_z(ejQSS&R9&uh?^1fxe-o3xHZX#rX{|4|CTfub1@&}jy|c@z0Y|5+&D z-@)d?o2b3g4|z%+$|){2k8)v1&%6x^-C=A~2v#rOrxG|JN>v~KEani4=Yd~s;TtX- zO6C^ElGEI4d6)8E4iDRVjM0`&-Nhe;TrO{3n43-0%tCuVyay&y%X1NK3X4)Qz4)Ra zSR{nG{!$ReNq_)r3aA||+)=+pULnF;WgZlUOu~y$%&&MCPqfb3{Zf)XVakY+`h~FV=Wv5v}(%dm}aLz3l72mSKu!t6u05 z4>4`x@l&v`q`a0N2xV?4vac{*hB-=lu<2s`4*_$6DZ7MKQi_xK7gGii`S9O9WqF)Z zp3lK&?V+4}8-nC{RCg$XWZcSvA^@~n04lD)-b_A$hVDjNzZ5`hA7D*pFCvp>Cn;NJ zX+s2@ys5pPcJgi@PRRX>J_KE?ls=TuuCk+eO;pe6LlX-6ki0_DhY0cQHXC+$ zoNQ*Bq?GUr?Q=A{MeH|V2eedHZmP$$uF|Hn)Ubd8rt!Rv1s6DY43$Jp5m0@n2Janj z??t;xQH>*%ub+FF!Nt8!7;9Xf$ewfp30c7;fJ&=MCCQIr!q%3uy9=Rl;&ruThN|w4 zwm@8sQ16TAA2Y+aK*0&<5{_Z)`wyUUA;!xbI#iqfBy^~j(K`huz&z#%6Rx5@g%O_# z9H@6%PXeq-dfDtYSJonH-SVXf-vHn2@!r?o_zc`L8YTnu9GSDl#^#r}NU-=xoUnLa~lz0?-G*qP-r9A?&!&yGHh z9abp7+}3*v?dSCw`B(ydCSJ26ug?%*K)rY;rlQaA*rDq)J?207d+0M=fj*O0UXr2r zL_^2qe!@Z*__?pY{4W>bKE$fP|9T5+A8&j%k$FMgOc-mf`I8&? zjb^V8Ie0)}k>;q)0KD)R$&5SK)}a+6_Dx|y1HBnx&S5{iW4rmp>e;@gh^Ev6D|sMF ziNKHoJ%$I`i--%l_AY6AMn9kuK0)yfHrxmc%&Il4Xw9qM+*9a5qH&P|v<-qYZ%|2H z`KGn8%9q4@r!z!0hG|Eiz;v}jbY})0uz2OtWMz9I)TK8~o605^um=F)2WKwsEq7Xm zTWXOcsU*8iB_U25xcCjEmf4UTaUA!#F>uU&a4@;3=yR%_PtDv7CN2%p;e3}F|haWH*kIq(vJM$H#V zgmt84y%d@IGL+{v>tr~_Fi`*K*>XxGa37^deYAc;{a%z5<@7&)HZF10+CMulGG`0= zYZHQ9*83~lf@jv_dfLswc8n(Q z9KwT`gTFy0yq;kPGGQ?5!Dw=y)tnUn>*o(S5tup>e~8uB+0Gnt@IZcp(}#p32lkNM zr$@3Q-@eHAkc{d1;Adp;G7rf{ZaUjl9}mfF_f9+S$V0O3)BR22GN}J2cZDuJf9iMJ z8Pvb;ZjbJ{hugl1mhR_0B=_rhfQMupZ}r^B8-P^H?L6YYIjEQ9GkSO?52F+xzLx~K z@_xUnQH4LFgY2+6zqpUiU-CeV&vtxDeQX}YUouy>e`&Y(=P&u19+~4mQliO*7HQJ^ z`b$J~`ua<>m>4Av>@Rty554Z+|2)+jxhd+FcTf3X%e$Dnw!9nq-FD0SYj=Be&*S}W z$20Pm{0q1H`Ahzl2eqp2<6ZDqmC=;sK1Fx?c2dxFF%9%g@n7lhFL{F|0(+X@l=(~6 zbG>g<@|WzpkfuiZP4)MeDE`xL!u%ya;#@`tVHUl0{*txy6B|?DFZmYFh~(X&Uqp{t zdZ)-wk}pd{vBZry7|aKtM(5LL9~X(2&eAlll)N9M={5;WzvjUrr%99%^l_SekqiBu zCcZo@-w6uMFemw$BAfS_s9ey-+|zh53jEw3ym?Q4!kuIz_P_z&lgBOyyeD;3jrHOf zS+^!L`^?|eaG zV}M*1p}N9w=S~cTY*ddORQtEde46kc>`YefN@(j`@4?-H;6dpQMOD0q8M1^euxM@y z;WyQ6L6GxWjwb8Y!Wq88h+-DV2Xj#ngw{{YH|3O)P(GFa0_li2xc*#03%@KNQ$EB_Aww%(&^x zV#Mr!%imM5Gh+UTcoRtMnvnCVa^4+7PLv^&%RO&;lg06+&nPfXZWUA%dH-d;pNwN= zGN~G6H}R#i56!{YlU5X(8GBYFL)}<8NypnxH^y2?L&-9ne2o7Q((-6Fd@14p%@uoX z2qEKwOkITdDWKMBqsp_SjaJKap)77rpkLaS16mT)4*WOQmB-HkI=z+|V);kolevC= z&pD%tAx~RWyrtz(_HQ@-V+p9w6DDS?Ml&w(lYBZgA0jq#%lW_@TCVbp3>rti$`ys9 z|CombcozCnOUzN#QWx~akpwgR4`)yT^5tXN11%=Vx43fxCP?6=UWljzHJNbsDVy$D0(OI8jg zp8Y0iWG9hNi>#W=EC7OgOtdxs3b@h+uCy2FBieg2Ee9?OQpx}Cl;(w09&38S$xb^;)bL0hoZt9;VJeZ$w-N3PKHs|Sb8tOW>8=YuB*1-3z{Fc z`b!RqDY36HI_F(|qLRAq8%?t}9aMIiF~l9Ch;9}z>`}s<);xKfTk{+jg5|cgPh_6c zvQOvJBi}s_a^|wNSlmwy`;v?OJNb34LwufRCdhlJP@MFEmR{YdCFtGM78bldARANS zjf){8-PBU6^B#PifbdfgWak>TGm=E;J-j(9l9@g6o$v@nU}cA|)<+ZBiMW@|T;~%C zRG0vy#%7Z_K#76#xFe9xLM|xPbrc`W7)S9r+t4u<3&#EpZ;8R!kFedEs5Wno??938 z2FG#EeL>C1kDO!j6YRiYJ-W}Ex-p`a8&PqsC@L!MD#z-i2uD#>Mk`i8a5|qFU&8LZw9xSNR&#h1S{6F8^(&cwkc!5M51c^)1zD7;Y2in;i(n-KIF;tq+3 zSR3;uyoiGO1aq?o9`c1uCLRqXVZwz~hfdLelbN%WI6e#iQqHBD zp-+p@3mK{z!-@Q_-AlA-MK2Rb^8~d|U}L>q&|K}wbH`Bo4qSY)oSO>>C2^%KF!HAq zSxFDrX5E{t&uuaS;LZCsUKEG`HI+))T*qnXwFP|DCrjZkj;&bu`7YYlI6(A(Bs6TK z^#z9X{Bho!j@(J|-n4#1KBDF3SeHRRJ3j9sny?ybkMY-~d;>=n-N9$nHoe9B2e7y4 z&l39nT>r1MQ!>AqrcDgI+*pp2{uDEdwFn^zIej647+}L}NTX<@>>wg>#ouD`ZA^w- z^r(NlyQ%{&%H0FG@u%(l!KTg8&ysw@T64NiG>(m<+l|9UG{|6MO$`r4$&Hh;jo_$|g0k&KS2f~Eb z_<-w6vBca)CS3B}d*-%qqMgs{H;9JTGub1(v!py-5ps&5$ll0dT++b-q&nm3u=Hw0 z?=(IOGhZ*}p2$3F>{b5QT3Gu|k!DHzW3$uNBB#GEWkJiVr^Y16^$D1Fku6f}+Swxg zm$i9DK;v0EvrndccrkUuYxyYeMA<%X?nW9{6p=)ah@2}NK5lYql0AqjWfWbNtXzi+ zG|tXd=os*^WT?&fx3fq4{F}g;B6~EP+n4`tWZJ_udHIjWise6weAKajE@4dtc>epy ze~PK;EB~b#s={cLz8z0gZb+Wyn*hgH98t@QV#=Xyd6amLa}y`lLPuN|O+FRA9SL#^ zAMT`0VM3kZ!&QR({s=J#-T5#OLK}n6`xLahPgnE)SSJ5S&|x{~u$;cOnn!#K9ti=I z#1e`V_z;P&Sx|rSM?Wva578Zg=b8C&vdQb8Bh&~A9bl~L^@B@qsd;`46sPgW`J3AS?mGQwT?dN-Dr&8->HtTKr z+7xvgVR32{Jt^{Mdz>ewxe4wu3G@l*V9FwjI+DcFBJbBJ5Rd&yE6QJv)NE&8az3V* zI(4kBal6W9YIK)mOV40v?bNwD{!94TR^zgMzAp53U1%Abg>M!8J_LEjZ0Ls~&%Es9 z8FYDo?1O{IGnb>o9+o`gtOI2??yalbt&|@4;VDWOAjm5>%r;B6y4t>*8>IyXkDGe} zq9w^JzMK0Nq1G=qW6QR=`u>s4m9HNjaK7@Q&!J5jqR-3ZCIJ$fFm0EE9ppfw&xeuK z4^Q;@Gh;8vAL1|no-62*;wv+J$GEWRQ%{_ZppSHjgjg+|F&~>Z@`v0JCdp}TDy3mx zD_0A;r_X|9J#Yab3XAfwBF{Sf*pDf?AsBV&=&N*Q-!kk9JX?YO{565Pg6FVWhz-Gtr2T-KnS%N>)2hS3Fj^SuA7_PZx%TzMd|J;en?M zb+JP0?}~frTYvPZ!kE0eC~sDg{b7K< zhzw;htdyM5u4_lEFV?2FdM(%CXHW;?rEN|$%+F&YE5*esvrLs;TdIa9XS?{78&>Z>`1V{tnj+}URWYiZ z&#mNf1!UBP_Tc$tv_ll9#P4O8-F$a1Pd6=chtt&rex|N+S z+)XrgoW&o7k10k@U;Qdacr$Zw|)N3LXjj^>4@73?-O@k#HF$u_@qY%*&#iMU`4oedqi1nvy8hha=W z)z*{RJK0p1;K|p#3i7%q`Kpo16d6*3+>^U=dx;{ue!l2S`rJ(cBHs1w|DU%rfseDU z^M9rXq+HKLS|}_l5u;`RORFq4QX~U2FatACu+Ri!DGWzZ)T)Vclv-`#GNe!G{>5E) zS6AE>S62{MSdU%Qq-R>L9vm&@2nFd(Lun|`rkwxx=lgq}$xNCapu2g!GV?soJkRg> z9pC%+J!rOgBIkJTnCp?L(#)pCOz@-;3=~nb&`XhCSFBf$mAik&dVWVYC(xB&nh;fa zbu*fG3(GJAlZQDH z|LX)I#6v3BQSp$yd|NzZu(ux;dx?d`USeUfm)MWZ3(xld8)=1udtK&4wIh*P*gKxh zxP27bQFdpxML+lvXsIi-)6c^$`<4&TrXmFU z4h~Kf0jF3>{ZNXf{1lxkTue92OTgxxSjt{*L2UeUitO-sFz?@7s%5Rn_*>HFoY^6C zuh_uE-}xar)G^xahRd5d=sitT6;BiIFdK$@#LfTL^~i<6BYzltgjuO79>gPq@@mi+ zTPIb;{=qvDIjV}ioNKBDB*WF)5u4UxsjQhcwpD+ptlkbxjaI4%p0j#8y}{b(+naC$ zIb4Fkzf!%OPnKPJUQc4Fuv$N*WTn5Vvt8e-#WjxgCTw;O3|nvKQ*_3g@XRpvcDAtY zN*%L_Z@nVQ@DP)%thcMTb0)8G^T~TgH*khkZbf;>VQIaF**_mzZ|7dbreK;0+o>w% zIWIl0dOM_f8ou7n-5=azy`9>^S4NiV?fe5H0b8uz&d<>cBs3AWs^G)U(*wV9b{&yR zCW`&lhIM#MNctQval1r_^8+kS7^yFL3i0RrHbJN{^_T{%t`2s9T0x)U_W3eGQqY4= zc}WjQF|Z31;DOoO7SmK^J4K~T1=V;o>$VA%@tdN9@JRRS)%~y@kDw*M2EE@vk<%locr2RFj!I<5tq>BLzST>u>< z1IRwFa+Fv$Y*&>Uxb=&bazJIyoh{eGKvt0h0oy)TwoBY(F4V&p+hx6O>bH74+jz{0 zqE?SbeETJGeAKx5H`j*scy_2H50YxfH^Dg!1+`X>r%{k*E}<4l$@a&@pdOF1`G)(` zN*OX%^?05~8D6Hdgw^A*d{<^jw-g)}av_04J2dR;HNnVDj;QQUMLnJ!#pgtjcEj)h zoQ7a@AfGyX{)^P(xeqr2>hWYj&6NqZTdBwMGi8GUWChiZr~$GcDjW+2f>bF(CRy27 zRO1=DuhsCrkX2ozV{|5 z{F)@s96ij!;)_r!*E17)uR~=@Q`}sE(rB@9|AI(ZV~5>*B@0ou53GF^6?_~Cz>3K8 zasNy?!jxC=xfC)05edBY**i-sYqQhYT;(sRY9c^GtM=$xscH}E*6>w(?8)-tJZz)) z1SNcKtGk^}rGgSZ0C@CzAUy%JAH2hQkXrI8f1mnzJggM?se{^GWv;;Y2ALw zH?F(Kt8~az^oPNGEae+CY@aW#ra_6L2(v_pf@D1)n4DM;{Az;gJQ@6}{y6^~++@0G z*FT&3Vz*i53v(J)b)Lym6UhjBr_BrWcd-dYJDCs-BBGDxQMNnTjP(EnC54;$>XXXG z5jTQyH_pAl73OjKJ;Yl>l0skq8}Ps=^%hmdB4LT@4Z~TP3{J|U3sslrx1`)<|KcgK zGiPx^?zj?w#qkDr8|v~bv9L=_wKi+FRn+An|8>21P%52YLtUP9q??o3u>lR4RO`V2 zU*JiNtwoh-7?>&sQJjX}LDZ*fv7Y9iDOISQ(Qq5)d4u(b{ujo0Ib#$M%+s(UPYDJn zzJjy2om*Nj{KUdiJh1gN5g3re$;7?OXCoq`xD2Po8{y5NKFq)@UOgD(QH%*XXK~Ri zp~5cQ_^b#m@D|QWFeS$3rbE4DwXzw}%#>!ODECQ)Z!c7pKf#yKgbbF{Y659z{^V@n6o@ewNyoPXn@Cd#I zz{5|_?L@i<3l#LUbrd6XNxc3$C|DI`dSnHi1xa$`g?X;khJmQrq4ymvX~iS~C%It? zwK(UJ%)zboqM?k_Bob)br309Stg*Br@fG9_SFoAzuO{^99X1}!?NW7nPO>sRqwq*@ zOUlk)9zE%&iANuLO;v!evEz5M&NHQhiZhhZgD44D6vu&tzAmM~p_` zStjp{3C%YF-H>v-M|lUiCaBL-DeuUtQz`FoC3*?+j*@pZ?^E7600QPD9us$HO~jxi z>NprI6LXkLh_7V|GjRt5F;Pcm5fgX5PHTa&_#}vO+6{;Je(0&LkIV{RNq!Z{=`zZTEk8xNrpz;9x&H zc!+MG#|%l6benFxksD35U&Jj^$#3Ty>h<2zBn|QRmn-`5dds7)sXMKgx#Z91#8J(l zbT=>LU9z8QnxGUmD^%*)m25b5&XxK>bBh1T`K#g$2jBG7U@-U%R~09)vheTV5(;0H zafI^eaH**78pr!DviG;m3vLJZtBNlQ8iEU^?{DNnaBlj(^mizTCLMLY<33K6s^MY2 z@mDu_RbYiezd_V?CVeHdkJ9=~m~_JdM5yr^M%n&ZDb|(cW(KRs67}YfJAgi>^RE_u z@#>q@jD188J!d*Bl{K!cB9Syotak1eep>H#JHSeyEpc&{%Q+wjypA4-oKJ*yoVIo> z8*5nFB`v9IBC+HClZ%p|8}TS{j^qEpm83sAl7ODK@?1S)YH7D^^i8^7%*Kcu2WXtI z0lkNe`9VZso#RVELdKbccU*_Pe@ThI%+gcyx0%>`or%3>|9weQwG4lE5+rW%Zh4*~ zuj6SxS0tHutX=d=T=8TsNycbY28CLuw4{S17MQPLVT6xyGf4%ZL8;i9IHDvJeu>*H zO!;Sw%6jKNqtVoBZ>`;05B-o=u)PqAV;~@nEm<6sY;m_Q9&L(6S{@ydFfkA}wp#83 zoEfHL&6ZI6*nD~vF^g(5W?sp-*m5P4$zI*Gz7GULyv&Y0qe zvrJS8Pv9Qx-6>0We1%Og8N}&{xHEob-~_Kxg2!<~vsg=T$I@(y zg6sn3p4Q#A9OwQF1yUmG`#Q^pH2UEh@^4eW=ayTv!O(sj?<;=8_8R7?KZ*~yN3wHd!eS`DD-pyH21eQo4u(N@^p1@6)<1 zyGUckZ(RqtF3$Kjj*_3Xf6SvI8hU))oo8xy99_Ju<@3k+gjYgr$A)-oADK*#Z^vus`c70GZTT7q5PJtG7y@(ccy2+ z*`Jgjeqn~E0sDh_{Z?0=r8K{EWt938#A`wrujikVXEq0rCONzPnI?m7%P!yv^Vi1Qw7a3fxhzj6c?hat2Qy>XeM4MonOU zGklx>`a1!-(XSG&eVFyiQ#u!aED)A;`4>KEC-S@YF zz9s{VA&@IN;K&1$d+6zh31Uf#5AuA1W0fF)-lJ*_hazP~1*kXh1soI0^g+^9;cd%6 zA+e&Zf+uNp@@E%yaApL=*0n6tGEKM5d3;n+iKG>iB;RCM*tL{_l>$mIfno%-C8|J( zi5c|tnbh+J)QT^otOG|Y`Ipe>;Hg+cL!Q|?>BiY1kn(=XpEluVzgbL4rSva?!L1*p zZ)C1@xWIuNYn4wr#*4(AS|u9efPzn!V_N=L)GRTG6hjU(z%{ZBTt4go{z}%9Af>aK zMvRXp-wYT5z2m$l`DXEV0D_4RV;Nj1H;{twg^`mC+$1*yJ~>X9_&pb(jZSbF^tL&4 z?jg?ebKEt-!RRI(NNNBM0-|$TifhOV%!3%QeM9y!#L)=YCYvG3^03VnkRWIr}Q3Tkt=6D*#c8oWPVJ zFgW{^?CT{16?A$q8^y4~f+?0JEC_cMELPJfyLsEaRy~CddkYT1!eFs_(4LfRG83!i zz1CQi#X8yWrnlfi=c!1x=8VMhCGyXn=O6O1SP`}Req#Jrrm2O?v(;tbk2l0#!GDlM zEf+Vqb(^%x_d{RBPmiN70zpB&sTbm!CIe>ulUps|2;dat8nikOnh-=8YV^=s#)yzP zi!9X?kaA`Lw`>I&yCgwF6FhSXdpseG6VN0%SuFF!fMw!h20;!J)UF_YqNo})nl=EaU-ue>fQ2Vopk(*+An9T@%c+h26qLy*Kd6_0Jo_r zC1%)V=}+i1ZqT5OLLosHsAeM8OE44Me@XZb%}O+scZ~m9K3YF|oZ;}RvxFWTJ4!;ppNE0`bT|zdp78zZ&+tVb2YoYDG;J!WD6LB`(<=oP| zMdO7FBk(pUB~?q;4d=CG#C5IiNKGu@x(JGCaozJIz%Vqdk~^p#u8o*_9Bk8(6`B+x zBh5GFrLz1)Li90;fZMtxZY}aPyFP3uu2e6e1CYbO!Qk4&$)CF^eK)+ysfZk46$dJD1xKI?JTzZ9AvOJ ze~B)4upmqueOq0xyYl@Ys2_icDxk;wC8F-&Ufbs6%6+y2BX}tAi`hI#Tk>Ewzf{+{ zxRx2LNvs(1i?PN9#5rg5el_<5b+P{YPeUyrih%zRPe9=Fg*1C{vVeSt+fdFGAE&>- z0`hwfUBgZxBnc)D7e}M=U(N$eRmVSZOYk5sMNYiU8YwwA{6ROjakE)LZs!(RLEJ=P z1?l1fR6U%i`f#G^!-*mdf}5!NJL}v;kxikNSMgLZQQusub*OM~2=S-9^DaNa@#@bV z&pUfbymM?FwT;t(vqxwz(G+7Z`K<<|%El#oiRP7)o30B+EdP$;7$7cuUvM1~TvdD- zu-g6oca7rxAF}tGy+kt(J*p}yfx7G^x?uJamB9+m#gU6Dk0qyD0fme%E83xGWA%Y3fD z9t07YRyPM=TDU>&NstcoCF%A2tff`+(ELUjj}T|BLDWI&PRCZJDY{EupT5(ubw6a$ z=qs=SUC5csA)vDaXHS=YJ4F!zIACWZpd3}Ma+(P!`1NnXb0j0at#9%$^Ep0zs`YjT zH4^THXW`~JLBpJWW|TMmqcbCtott|h6spS6jBY90kL3FTt-=N2Xx+NViLCEM8j&Kc zyNK9x8)4q`zdn+Ny!Ib4P7@mmbUu`Q4610^eysK@9>kj7&wEs~DjKs@l|DM(b~>dD zvjs~JUenK%zv6w?Bdc+x7}lnT_@((dT2Q2mDi~R9W!wp2)Uae(rYLH=Q>VJd{ceLx z;l$+k_Tz9@>OL_W7LCf~ z=t9YpDoC=6pV^M(gPhgi4>e9Cm{Gwt@D)OIi%xSTOt{`;)wXz+l0=l+k?Tztpl2nv z5?$2wtA9(VqV~22J8`H}Y^{|yX_6n}VAHc+#|&}WdaS~D5L>yE#mNTyRzX*b7Dj?K zA0zrk5OMp3o>JNq%AtLXj55#@qTW4@`lf}HS-OYHuYJJlXd#McAbiBkt}&v zIyR7v5d6HIqDCN#Vk=Xb80;D@0&H^TR1#}=9TuQ;2xb=Tq>fdC(JR)C zlD`$NmtD;23|YS1=NYjnuV81>CjPOLDbQI4*`}w|l~LBAmUXVk7RywzWW_!@RkDW| zflB!oj|%NO7&jAd0>`EZ)Lh5>Mo;?$7r=gLmy6q;Dvmc)ZWmx0K8MID>zL_usAo^v zkK}Tdbu69V9^xb8!3H_Jee4jVY1zkmPbA#H;O z=|Sal8488j$IK=j+Q(!*SAVfkH0_7^-255#W8^7iUyMxWoBMv^o?De5- z3bGT>ey{l~5%{y-EPfKIp*M)o-GE&pBy@5?4e6Qa6{v;7q)Iaf6i@C^Mvg)=m&&_%#Y&1tzznZIav@N{)2(q+) z4%-D?QjjOgvNXAKqJI`WA3NSfQm7WkiAE0bjh29O_ zGU})V6)ca;EFmcrb=-{%?h-+yq;rW31_X0^rXgs_+J#`q=fDi+a>tZ4)cjl4hxG7% z%fqeOn9cVm8q9xD3Vt)@T8TI2fQnetvdU|ZO5)?EN_wcA60*v_3wlU~TB>v#Jw)uA zY(&xMq0H?_rQ%%B!^VIfj)O)O-^3F^l(5d|At_>A$w8xsTQqkBDgfp5#l)Wdr-x!+ zr4=)JXp;K^-q+a%IJyX93Fu|sjZSX)qf{?loeaDnn*7)S4(^Bb0O_2B|HX)fYq6L} z?wDEu^jTpZo!OyG4yGaV1KKV&K9#q8z{c1^cVyk_gmP!NRdosBn-$)e88*ZP_Jo`m z?*;z9v>eFm2|7zh?80eZ+kv!o%gtQ!I=;o{ilm$?B#F-vsy`=$0PR!xH-Zh?6U->4 zFfhsSfeV~;G6@J%WwGu1)S{B8zPv(I*V&+`uCqW?@6Sf?CZHalO5L(_(d$e&uMR}@ z3+(JD6V-VNQJq^x)tRt9{iA<;jUm);*0q*8kj#nd4Y1ZwQg^necPXyVQnL&GmC3;I zocS%B^F%O-t=m* zUF^QJ|7H$<5i;gj8Ug@Pfo90=Q>#-E5l;?N)hVVFq2!m6+rLgMk_e?l`^n_hT5vyC z$w>QZ{s|+uF%mOOI~}io>P=!nj$oEsg@L#3IgE@)CQ)_AJ)FNA?!7f6{62Bq~WbRbF#aza?KS9?YB5 z=*Ys%$;B^Xu#>DOrV5X3>b_w_>tQ^Kp2Y0RlN+&$jiMEd4U@`Ih$!Lhjr+d+btI(< zb0FiHJFc3k*p7O76=@duPFG(=LK6O0ZRc%ED(|0u@uySsU!3U0TI*^%BeKA)n|p4& zv$|vD+{Aox^GqWp!KAgR+%8Dkj#T&NQLyQqFXxws{EA2>GCrjuZxp@-^pND5cl5Uv z`$G8EWAtOWSI-Ml^OsJi0pcOmmOVIAxBe&+5mj#q!}B5vc><}Uu( zkk(^OZ%J^8teQXYPHUE@-WNRd2OfGv4}JanJhYkz)^hXfeLwN)Pp(s^yn05&jMOjD z@1;h<8{6*L?p=U#adI73&@jTAE0=Fk{NngU@o5*8FXN;gZXxea%Iq}oX(|px??^Ug5(o5i;|PX-KmRYX zH_7RRI8+N*d-&hN|5E89 zg2ptP;2*gEifU2H+3J!y>-s1W01`aj)`Lq&(vt`H?}PqEIX@eJ{}miGt4{^j7xl^Y zhyGiC8u_Ir#aT^bLF&P;iwfOY)Hy~-{B5Qyn?u<{Kv2XIQ``DAI_D&X>klSlf6}{q zy{vJi*&P$>2_`q2+nD-ZnyE|+4)yIPBK?}=grAPsbYdMlnv_zFqKhMJ7Hf2P1~bWI z)u=QZleDs}*Cxlkw(T~`A0YH|yU2!vPaYaI0#UnWlvW}!qFTp^h;*{30t22ILSF;w z8W1q{QrKtfJi3FDXg%J-ZviIRT#XEsn7dwQ*hhQqPZ~t6wQgTOCPpTnyI0W#oY)Nl zxkP!=yVn6|socr{m=IRyj=pRwERl|C^_VDV%+{=*sO}eMovEqe3PyKY$(brUcH@7k4#;)Hf|Jr!EM~ngEY?U(Gs@%!Wyhdxy;BrfmADjA_wH5kp83zw?FykRTxI{JxyqY9?v>2~;pUw@ zwVCft+&{wrgA-s(w6kR?KmJKg>Wz=_gMjW?{zb}`af9XsLaPU6JVFaK7t!X7R~d_# z^5c3`x9(DBxCh2dhd}q5k^J8XHK_SIXd@s(o&<=X$^cQl0a3jH5!>AJ01z&QK*Top z?e0nlL~L_+afQ0c0!p{dy(G|QML-8$fDx@o@>`XN>c{y%P}d7wSEtWaN6xM;eg*6v z2464X=jd^*(+z3M5O$um2N0UP&v#1rs_`Oc*K0}o+|=w7UrV@p)gmTn7;II8g`h!6 zS7LG{0wW2;l)o`NZ*#PxJ1UUIE?eJjx>Tn&6$XH{I?g4cSj;KjloKAn!D1L(wme z$yeUY{mi2ikdUz@A@!JqG$?nIN6O@GiAW|IiugOeDxGuMK_(tr6DBMs{c|Ise0#K; z&kLEpXtij{b3g+K4Sx_`y`W2Lb@Ygiy7jSAr^|G-UPn&?GH>eO0cc2zhzUfe`6-<& z(Z^EVDGJd10<+lybb;v{Ji(=!D*f1{AHn!$s9n?joHRi+nvk<<4x#~sE%3VAn&PtP zX=$NNq-CMKj!B@`5DAQyZ7INYVZSX!Jxc)xy$%d!{UyBEw0IqNV%Uizn8~Ngrq4eE zg$4PN=|dTC`vXi%3VEz6gqKDG6$CPxe^wtW>1ydR!0e@n^UaT0t2T4NJc)|dqzX2N@-VYm z(@JoeF6-%jv=Xo5L?*2$uf{;^8{%Ij#NID1EX!@R06YI^CeLQm!`a-)bxw8*-9GNe z%6lU1A&rmw)3cGP!tGto??cv&AYkeTIy?f8picw<@15ThZ#bmRTkwJ&WaoN3FG+Nc zK?fzij%#YPn(w|tZ9R3$9=9a^x)V!2P}l2qU*>iAKajOTY=yOESl&cQ=7h^|LnQ*ROCRHs2v04o z+ueZnXU2|Qa|0DP}Gu8^qFyJ+%%JUsRbDhWMrF7}<-KDQrS4>l@Y+2M=31+BcHKrI6 zwFo>z?>>Lr2^xplI~W(GPWlTQe(y#UMggn8ou_m4Vo zm6NZd?rlbie_<4^9}0w{hAxp0kZOny`>L81t3se(jMV&qarEeBh5g~@)Ha`Qqm)Ny_ z?sT>xyi|TwCXb3~{Lw6Y&Ke^&Nw?2{te739hi@sICEEw>?q-YWNjI!*`yKi@g*G#h z?uJ*qj#YHd z+|9SlDU$$3MN?{y(z!>);o)h4Rp-$BQ{jry`O)(^BX8^Bh?b82cfoSuGF}bTK7vbM zPg`HHm(_B=Lzg-aD>jwRY2vgLO%&g8{ngSqlJx%0D7?gLe}hgLpZ_~d;cS1g)-1YK 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

s5BG zp;r$Z>-|^`g&m543zW*0D~-@8%9(383*}N#b+eywV@-{FGGN1^AZ-f~1wHVn?@VYA zko}D{O$)iHfqr<@{c7>WpT`U3XcOk!%@;&3!Xz!cyP>x=mRkFT_9N@ZlX(+ zQ1^gm5a1c8J_r}vaq_%KexD-~Kq$V`)6jBIQjFiCx@v#5_Q-cNmTWAl!SssulW)+3 zXd-@#I*f?W1RL%if9_rm{~bhT*-=Y^iIhWf>N39qc1`BDZe)LB zA!NS>L;hwZ{jU)pBqR|d0Au_1eEmlR~3We(=3$gTbR*yuzcGG`vWXQ7^mVVcEY7_i)A&UG{vW zpvunDh5z)jJK?O#PDxSPL+4!7YDg4);!UG5B=0ncwmn!=F4KbtsgB{*a8Ve_uj4}@ z)W4S(!!cl}c$l9;02q;HBg;}d9}k5ETd zpuVH|h$dr-hxmMX!ttp@o}=N@0iJ01*fF!AWNdsrw%fpm=W&Dqq@B9G_c}XNAxB?ch(r6Ad3<4EVfn;3JP_3I#|%tZ6tcIzEbr`1}nqhW}1< z9lRaUN0Xlc@I=F>KL&jGO_QOcHiaoE{WvO)=%eZ=$wPeFkS(mKg#1o4K6fB)g^xWX z6=l_R)KhpI4bas2?PD-7ob^PyXGU6+V>qG4!<4v(hCI1{6_r#$#D0z-K)rszLC zI);je81~@BPb`L=F<_Vm9)+Pzhb~BU3}=BS8is7+qG8ByQuRJ94z>)(P#twCaxh6B zO%4?gF-*Wr5a-H`--(vPz95De&_(=oU1yI0Lt6|O_Q!xBKhD-M93_Y9cv0cWijJY; zA%?3VhZBq8t{5=%1Th@HE}tI*hQl#n$n6_ChB$CELJs8-q+%DASfa_H;vt4Z(1#O? zVSfx5HU%-XMM$dArew!}p&i})XmuHf>gyQtNY!u*)gh~*FDE*Niia4U3jil*e4+JQ z27(x3@+#t|*X3J-7-mFp7#QZqfT1r24EKj%II1qIvuwqHD>{aXhZx#Xu!+TRFa``c z)1cav@iAn5kJhH}#(`*Z_+ki#qw2Cc0ay%|N5@d{5X1AK4<{DGLos0ZP!K~5R3m>#)`?^U&@H z4COK2!h@k%Gz=9FF?3FNT~3PuL*g7w4m)GOus;S2Pd6~c8KhwlYUk7ov1@B|3>6PC zT!t9&7xFvNeQX<|S8|AMRK!njmovblFdSn%sO_#{+a0Y<8IA$NB}hx}A8w7rP#(UI zolc*Pj-lcqhWDX(5XF$+iN??##4tP^CaGhX8N?7EMEvwN<&GFIeKk6Uiia3phCVhHfJ1&K8pF;QFuW&- z;rMm=*%&bN#em_rLNRQ;HWEW#0VAq*MaNL_5W_boTn;H?N;bxq!$)Gk@K6jG_Q!zX zkHRoq90sC(!I09 z5*+v2y*rKL!jx31TSk&kKc6 zzfn(AJsTZE#X}5>03fB`_?>7Bvtz(;ZVVVwXELY9`*vVB1`LxCi5f4<%LgMcRQulh zpNo#6;$eO!e&72gF<{8?@_6-Bm&4&8hUiL+@ss;xpb8YumyP1kzrQ%ez;M*QckK>G zVS6DuhKh$6PW-<2oFImy%dXeurN_aLV90$kG2nBafzPOY@9J_(%xfKtj*sFYJ`=z1 z-5CQuIWgeV9|Jxs4SYuJd)Myv6ge+N$4BuHpJRACh&1GPqV>A?r|~9RNNx=)WsEmdE1vP|U=bKJJvM6JySn^Rh@6*Wz)6PCocMk39YGAo zmoeXQFeF&Sr#}XKZVbUEQqgO7@QT4dM8`+*5TCz|dRHe}#;%V6pX+15XE+9YZVSOD z^1A@--eocPY7F>D9^y0c-vx9A@fp9LurmgH?5FB=aC{xU+rS4pJbd4~evx(OAEV== zc!ZF&NVL8L zuf`6?P+gWS`iG)psCby4iQjX3C|LF}=EJq|JMoD&zj5zzaMm##jse3LLNJWnAEjMo zFLH*XW2ktD;l%H`WhF(nk=FPaz7xdIMmWNLdVSv$1BUj~^t8s;hrD=3lSA&X4VOc0 z&+Xum=ol&(+9%4B0dv0@Lz|a}Q&=!H9A&0NTfZ=cq81f7o4Z~4;ZtJu?w{~lE z3>6PCya+-#v3tyTri#*sbb81BSjBFw6_Va8zB^_T28m)JL?staymw#P7NF#em@* zK@7*AE1-aZ4SDAGAe6T7pB(4fln>VE!#(k&&-Ye@U>LdQ7Ij(fxgEsOT+uL8Jj_qU zgx6)tShTu)ZxF-r>vBpA7!JpP;l>aQBlq0a`PH6V`?Ba5Djs4u@q2FjV!-f`7%=2I zBiN2BhxXI;_cgv8ZVkaOa?foYcj0=m4x1AlL&d}VxX`zm*fwQX3>dx=1BPeCfT1r2 z40{X=NA0<-g9{)ORnF)bDjs6E9GV(`A-@ydKkN@;7(V~XB=!BG9|SQRqaUud%k~&B zdB*Vw>CmO?nAco=TgkosMAVrN+ z#@B~ji$qk&^Z0Gba10pU7lL8ro?G;>l^o)l+h}b{mE>W5CVtQDU!|Mdvr}3F z0Tgh-e3b>9M4^ehIFchEhpe#;R&kPzt$>?CpH{moY4K|Hy1Q~Dkx&(qL*OK>2o0F8 zRup6ghO9#j2fyc*0v)%ngjgrnZK|4Kf{yG{styd> z4h;V*WN7WVMOzjOz3Fs@tV0Y3zvnjN!0;B$uyb3cXLcw)^4z&k$v$7zSLc5Dv9P7u z@=|QiEyY9HbDNt_XUIB~pTY0B%{ee!b6|Lj1H-_9;WG_}=AK*8rvPGhF`Xgn5W~Um zxt(-ic&`J)RR@MG2Zoo046Qx4wDv{Mq$b~(&X9G8;jIJTbGzce@Qee)_c}0aJ21Q| z$}qO)mew4IVS6>5A?pys&kcOfEwxh=AGQ+u3)!dq$bsQW2Zq_5%2wxic%5d5?Hf~# z7e;3)Eb+bdKTK!HI#jObpmbaC|M2SD_)zj0!W0kLhArw5%uB8Ff2<21^?Z3<*M&VF zq*TT86bFXID8t5rvH2SeA@RLU2ZpRe<+=;jw;BcOH^c1?4A&hPZa6S(IWSy^FpO{b zYZOW1dna zXD%e@FIs<;&WCl#*3AR=F?x48vJG3Eee9twd{nHXYGgik%v1~m2ZkRC8Cv_gi}HQu z*$<^NWF0Ek=gGWr_1nktnxS2G)lS=87*giMa}WnUp9uM2yI(Qd1id0j;A7s&bUv&@ zeEwwMJ~pBGbbe0slP-Lek5RwOK4$x>V%TS#t=Qg z`n6jdY&-CIJZ$kgQn3-=w=5*!v+}3ud{~F_^WOvKbIO6wm;;~e#mZN&vhytWr93mj z2Tjh5;q=08;)9oBq>V*chxq&v+Ms#$tqsZ;b+6{L(=>!{Du(ZO;1f9Txh&*k?WZlu z{j}MSrt@JP;`14tTgS^HBUj(}$QVUqQI1jBh!y^*V$`N)n4lwLRNjGM%Yorl5r*-- zPeppGEqtu~>2!vyLkz!$#pS^=3>+8^p{qgoMSeOne2oLcwgbcKLWZ;PeceTpfZ@j9 zq%&k4%JWTNh(G)jx%%ygYYq%^nqlX@lJ@E0f5>x}X9~mkUFdXs&e))C>hHVFi?}{+A+OphFyS8;}>bQk2Zo=HFpTe~MOzm8 z7~2;)Fcdn(@C5wuLZkKcyDhJ3h6&>qImVvU3=?$Z_>lJUrTJmYf#Kgq7{>S07Uh20 z)t96*WF2C7DK>%*mf^Ys!&L`{_c}0aJ23oqgkgL?ZBg#0T|b=8kadXRh4>2}gJsxu zV7TtU@U#QN>i-!ykqWv3oYQCQK5HvD-803|WU5-U*Y`Lc*)xZ8-xzT&_%L zM1E5Ja$7S@(2;HV0SAVG1H;FlPUU(Fh{e`~Ndkte$I=kz|-;T(fy7&tJTaA0`OfnoNS zRov(t4_^{tSdQ(dB|oJ7wAq`}8L|#B%mW~{KSi#7`yutYY4PwT%`g|q34c`c6xu%z zjL0+9Ii+Y`^qetpV0d+eVf;P7n|#(~DcGHf|8yw`!@kORY(14BP# zXzfX+HCWm|7TlH2kadXRevECNXH;mv{cuAwOc+1QG4@Y1!_I3CbOs^K58Dn5e=}rg z?MW`mJ<02ToX(JSh~Wi8o`+?J$klI#bX1+&@{WiV{;2wtk;kci`AS-46~Oi zTb<+Ko1zS3dy>IW>`C7IWI99EA%+LAeux*pMy`G{%s4O%G{ccdPWYpWhjfl3%?|?y zhIbhZ%{|G)a5wEqKAp~xb%^2D;fI4|m~&wGLCrANkzvk(VatKxheC$do@81-q= zjdX^rLk!Qu+t@EL^4)JgoYV{xd`!l}hcv^4m?_)xAqR$S2Zo=BGK}p>rga-)nE8)% zhO9#jfBYQJ8yzUaHO(-=$0Wn;7##o+^3%CbIqJYLdl}LY>2!{VUkVxG36!y&)}v=q zg5i_TOI?G_2p!7vb!f|2{)$}v_QOrhFu}(p!$X>3E|L@esN!MCfnngl@LN%a@jeA( zY&z$%^1O70tV0a%14F#zD020i;Sky>`$lJmw`+z8I?GrhZt^!6J{a=v9F+CdtlTvdIyI0YKA!@FZ4zE;Y|(<+YSurwPW(Um36+LBqY8! z`HFOgtV0ZGd~I&$>l;Hge%5?wWMW>5&uv}!sQr*M{$YPc(@D5!u9w}VbUMew3qpp= zbebT#nWiKp*w^jAkadXRdyyL$k6is`NJ|<(1Y3656~o`_!jQ5i=E4qqo*&^8KRZxb z=CcD?9H>s)Ys5N~=L-hD=XS_}&srBg%Ewl;k7Wp%brHjs1H;QT!^*OCc0foF>&DX= zvJNr41Psk}&wl$@Ml(#9$H~6no-Pat7V&92@HwFQEL&#>goOIjUrp!3I>hI92kv8I znos98c&ZB@`>ovc+s6)S zhMoI@FLYr@85D8MfzM3H$2vQ(EYA+K9r&;g@%bEl%*=P+_{i}_OZ!H~t_wBp)eOxs zINhN70y;;Qwhqv8V7O#3G@la@LwZiMeoeZMu?{hO_u$&8WVoRjCbUz@a8ff&(2=q3 zK?jCy2ZnEnFpO{hUY0NQp3J8+WF2C7pY0p{8uv;*f#zfSd(_9yI`GM6kzd@@Esnh> zIMRp#oZ`2rz999#X(bcU=$d42>QFxb8EE1F>fAL)lzYKEQH!>@E;*mhv} zln6u159RrSl{cg_WF2C7(-Q~Hu;sw8>A>)y1HuSXbKZCRc#$l_I>X>$kGA%-u$V9*Tn4h%;e7}7cVw6>hRT={(G zcsLhf7(ZWtwk*yU1b?5-kadXRCkMW-JJ1X}_sg%*3=?!@TfW7CVc@{X$Pyjd1Oq-kXuurvwfR|2kxd-4Vu;jEA|N*c-orKl+l^mRW}wz730_ zXl#+I-wd;wVJ2dQKPrY<&9L*>X5E2d%YorHA`Ii_3ouU+41$}n!vJNr)IGhl{D021N4+95=E1F?0k`w-@;^7$w zhFNSUOpAyA8(|nfUqF5+&KJBSo#BemA%@2X&T!R%;kpCEha4CN4h)}!6;rwPWt}ge zHCWom=p9UF$U4OE^B7}4*Qon``(aBn%o%p*i;9Qdkm^%9uYI*07`7Z3J~w1&oiA9H z=LZ9j2f*mhued6Z#nFDMv_y`b4z zIz!eWhQEMdIM}`M8Cc*L)tO;aGeoBlyHq^fhTbo2Y?IxiY;~S5A21l2dqIgI?FG%< zl+KWKh~ceR`x-36yaU6Nnqe+RFdQFlcVHMeFno2$&^lj0>xUE%H-0CbA?pyscL3le zM!x&qmRB^xgjgrr@>$I=YvhH#C_l_NFl;$6tV9{c&KJ$e}$ zJdWdG&agvYRKJ|p3=?!D!!ZYj*(;Q-&hhY$D8qQ4f-yFoFPMBVogwQG!y0lw*z*N> z2ZpPfVdu8I-+^J^!0^)s!&sj}^Ateb_;7Keun9;zX7si)-M(Zpto#koSI zW&-oBLy=pmq#+2MQn2eqyGKSbCBa2>h??gW@v*J$5|RZ-vR$b9J{kACNxUwBsnTtC z;w~y5MPbvJ^BlrlRwW4ll+HLd?j>Nr4C!U0g_DD zR=HU63s|zk-Q?HjdA<+HvghTs1Rp$X=R!kNHK_cV^Fy3JfS*l_%AYg%C9N*jRJ|vi zER*f@pstI~?X;!qBB7n`J3O)T=%M{%$d4##Eb>F_?P8sMy1xd+9oX7=!wok~ zLWgZpxy)-9>FnLRm!utaWc+!t_UB@yRzYAdhaRo`XGnNdhjuD=dS_rO&3{_je<)|> z#bw`j1C^#@*+pIK6XoizGk!xRHJ$OjL)~;FpK;A+u2P%1(Vs0>gL1v0A>E7?$9y`+ z=R2r%TdgvrYR+GgDZT$WgU{|%O^*}l$W}S2TV;Z`$oc65x>Y7bNJ*olX#|b(LTUc8 zdbv7Z)G)mFp`=+^(oWG2+o!xWr9+wY=x+nlNiObFnzLoUQ7$%4YYFLm6*?aNgk(4- zISa|Uq4Qsmw~mE^5UFO6#33 z>tc%*8z1g~&e{{A_4NTr=p0Zua`-b!2l)vl^zKah8cO~OlGP`wbQF2EPUNTXd-5K< z43bJ~JDVy$Th>U`xD?ejO*LcuPG1z&Av7z>`gvP+;@=omS%aSTC=@w%De`w{@(AJ0 z*?K8Loo@LSj0AWI7qx;;?dyM`vxfYH3?GkDt{9T1L$WE;;ezjh9r|XMi!7R#ngwhss!8d{{Jc-+htjy2IP2@thn53 zmdoos+aJ^U3Cf7YQ9L4FZ$l25PiH^8n@aH%xqrM$PTz4xH0 zfN#osOGt;kcM;Oqyh(b?eY$oqAo8b!7iL5E#n(Ejtm!>XmNdcZl#15Tvo@BH&r|3@GW`0f6m@XVEn|Y>hOQ?6c@Msw2`ZWHv?cFMM zXszhHE%tZ}V(;xz2OTkVUXOoGw92D~1bNcgO}80WzZg=Ye<1TC$cXbqc6Q zc_OZwI*Q@Lnqjpvg$1bHp+jlk$m?<$MG{~7SuUzCswJ+kF?8<9^+mPB_4ORHB4qZ6 z5BVzd$>5W%Ms-Rx$#sf9o*26npC4*IrE0ZYYu1+{fN;;JkPh=no&_l12pQsr*wrtF zD%xD>(7w((v@d#Hs(g=7wHjNQ++VF;P0NLoU80RDJL`}i4!-O;hqC|3q3lo6Wv3S= znRQMQs=~mb?5sm&CyzDVtl#y%-=XZ((Qz*$T8H6@%IBYLlzrMLJe7SKcda;-opq?} z7Y)4Z2X)y|xv@+2u;)9J{cc_M*`)wyoWr?~=LreYZaI{lb*Su@q0(dhSD!~0d55y^ z=vH<)PZ`ql6zVn1OSR?A9W=V25?S7>SM~LXNIxH(z{H2@ML#hd-2o(qWCVXS-jwX2 zIiu8(&mGS8WSyRS8n#Aaw5*de8Z<^0 zE$e?{S@$q;gxaI5cY11X*cv^DVTd6a2`uZhDk61cy>IKudd{*=&pAx%vzGP0u&fXD zWc^CZ`dQ2Rq-CAnon@ANM^Dyi&xuje(M`+xQOo)VE$f+{tdCgM&sf&;mi2dA)`xqt zp0%uRSk@0(*6*~eXM3_vJElzXcm=X48Od4JZ?mkA^<;h6vc7IvAG55#!Lpv~$@)&q z`YFqL*0O%wvVO29>lw>>%d$RfS$~~nJ>Qe{XIa)yTGlg`^-0V6(VndDu&mR%rs0Pp zJ1pymE$fp#S>JA1KVexPvaIj7tk3pjeaN!DYFXcAS*LYR$w#iPd_s@??Dd4%T4An? z{x3{tx;eX0JBGEU(3b420#ypwj9=EMDM?2@0oUWGBpu${vzz9^q7-870$qFLlDo4; z!aPgKXe7_F>;+7^d9G)dU5)*IhUFSLq3SE?sVkR#G^0i`opr7_s(fP$Ci1b%D%YbL z)6z)+qkWC8gr2}T961MzhR&XgLa&qFvZ%b}QCUA{SzolQw=L^fI#v0R)>nG6{v*qJ zU|BzFS*O2cBWXzMxAkP5&bb&=M`tbTo0j$OTGm&4vi^u=ebTai#^4 zAGNG+Sk}L4SzqhPI-Sxo$>%NWr!DLBw*}35KiQM@P0RX0%lf)y{k@j;R!`O+w5;bW z>!&R1Z?vqR>d88tF*M1KS=L*YbsR8KcgYsF-jnqQEbCdz`bo?BQOo-2o~&ItT!XY{geLvJTAeZFm3pS7%i(6YX*C+jWC`dQ2Rq-A~8vOd(4^?NMqo0j#Xmi0x; z`i`Eg)4MfH@@FjTdCU4_XkCuy=evyO)m$b_N6lp-wq$>iQKdjG;#a@tGL*h3dzZOP zm}fPYiR4+9{pK!ZS7ZL4VYx;;RfC=9DWkWk*wR_&3Qx~v=n1KLsb@EL>9QA>W@zK$ zW!U3VuIcSWUxa^g*)w=HVWvUfewKX5-nVpqu(rH~_N>~O`W|$Sc6r7@>HHWvJG(sN zAf3m8-DWFdJGByD*nizPIp6qP(1l1ZcN!=&S7B6qzE z5*Uw2egl$WNJy1)7~rFdb+V)-5Ysw7HV*n|>64IzRBy*!S%cvpLK4U^i7Y!L$a2Ki z=O9@#N_syeW`4c{30-V!t~^%^mhjam>Gz?NldXVlJpt;J4uNCIg(NX_UJ6Ox$a4vj zO`~>hhUBD?!?!|mPPW0V-dv#yzk?kkKOcaO8WDjZZKAq*0yV*T;rx6YI=2~o?t^62 zkUT)?;0nEkPH~yu@)#^QwT!!-MN3eIZ;X({D8(xv*)$}FA=xl!Ohb}0blwEXqG9V! zNYt)-F4y}ZIS6x9Z7lgHBpD-}uR@|m_*=cg6pkc8dsw8Lk#~I?I%=;qr}KEMn}#X- zK6c9ZIEsubY!}ajjwzuxT=EG=l`{R^4>iK)l&2w4qd1nlp3=c?Iyj8X&s$02MPtId zAjufSJ`9PPcXK+QqPvW`_&Z2wHI;tf>J_E`WQ?-^E2WIzsroscA40NXkf%32Pa6Kb z1Cn!4kN7+!rnl^aB&&6fRLkW6Hcl8RzZN=tjx{5#-v~)w=7sZf3nXWCI{3+Z8>MW- z`9FY!t}s8JARRac`!k|wh5DupbV6_WOXzIs`~>3Ai0ADvbnb_aT9M}bd>0a6mQ?Y< z+lq}aBneY~G9>FdWzx9_k~O0S_d~L&TQ}+WkkHdo&U2$OQ!7-#Sv)0Id|n3~G8DGc z-zEtQCBwHvqE^~D&+jLRw$*6XYsI<1S_l>8G( zf-7t(&xK^zNck#A)Sdy(;UP%cTE~|gQ}TkL%Hgk3%Fqc@u0o<#4>+CMA;}xQ`cX*E z79egV+?CgNk^B}&GDehm4M#a*X@!`sPjBXvPSLXAUSH(@+%?9;cjF} z(wK#0*2v*9Bx)v3dY*SXB#T-{a4y0YehKsZeo62i+xhc_~}(hGd%&Nm`Js8u{6PawR7WJ2KyupPa|I+P4Tjf3a?mL0A|#tShlpd?zzXX|gnTn} z=!A7h^&OC?wF@SH45!Q1;u1*IQ@pL-acp6))SA=04=n?7)AcfH9eFlv?ZaK<&tzw-cRjxCDwU@eX8c0E zP@5??)YnRFdR~1lOik6x$JMuLrB+s-r|b0e7yIk|qECk)_oe;OcgLCv(!YdpCm0L=+f-f)}`3z`*L$IhSx_p_qL|YIEIR}vDmMd z3yt}jmwF=~#ViDY-&_h%QgJSHeD7Wu#pZP+GgE0a@zztWFcy}|F|o|{^768`Sguc1 z3vh~hVafM6b=hvM!d2!1RnIV2n)hd_^HYVYUuw?R8-}DPBvu0ZCayi~9~wV0fgX&i zqEe_-S&lA3kvC+I?Ij z2d>$VTCu9E^9>2gmAS%9*`F#j%18>Y(-6moj~qDYi-M`+l=>IZ8q4yKrN}zoKU7B6 z_w3Gk<+%l)kHXL=KFsUS)E4}*sZMK}sd6Zt*7$9noD*esc>c>PwNn0otpC{8mn~gGv034MMY$>UUOr#nTPop56uB_hMfl^sdH7B&r2~s) zWDGj_13FipKi;@zzD6Edn5ve?Yx@@Jb+j;{pwlha7Uq0}2WoLRMpG};mwehU^eB6o zSl7fc3?cCV9Xk>2(K92NPl1M)Y%rtV0{?Mm? z8qgE5O&}o!iW+!#x4xgECNCuT#0JiWe~*>xwQ}|H-F^XX#nnf_ zjypTic>Mj5VCfTF+)fLL{P}RR`l<^0#X|M^+KuoI??}0MeT~~vNr$zUSE?vVq@0bW zkuN#PMuu$u#WaE!dc;U^L4zaW~w2w>>o$x zfN(5+^Xa%amR?PS`^(jGv%C*&rvlQd`G#Dg{h_SQ>lVuOC1isWti%%Z3v-PbL_iF{ zLKU77hBZj#A#aJ)A61=?!7u#0GUwq<4uukVq1G6oC98z{q_c!M?%Eb)keRQR5TgTq zd|su?lXT7;DqaSXiCGMNO5^B`wJ48qA)*#!6V(R92#5=1Z=zgB5JSY2KO2(Pi0=8LGVKvT1nvvl8& zHh$eA_|bd^M?8H|vBNN?2c1tS+sJe(p93QB}l4 z(MaT@8`WYF=FX9E51iB- zn-Gue1(;7Kpw*##r zsnN4oYDyj-GS#GxFuiNXFpgbEdRfRxjhZ4^pcO0?mz%mn)N>TorReAq^Ly|A0r7BI ANB{r; diff --git a/lib/libgcc_s_seh-1.dll b/lib/libgcc_s_seh-1.dll deleted file mode 100644 index 4ec945b8a371e97d4db054139adcf7131476deea..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 74240 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%0AgmuFlQR8 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
8$CNCek{RFNR4*cg42TSAn_#4pI3^uh$ma{ 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%0Dk&B;SKulr@;3}cH6_9 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

0Ee3?POLE_7?5J2~V&Y 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
AyCcFfV8uoe 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�NLLX}U1&sh@euV!wvwm8 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
EMa*xK^nVx#b~uN1ub`-8y4 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 diff --git a/lib/liblapack.dll b/lib/liblapack.dll deleted file mode 100644 index f9813bac43a883a9a9669106ace1b34830ea9cc4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7457332 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℞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�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%0AO*#~np_?q_K;A>m>T<6gS_!WQSUQFjz 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

07#Y{`7lQM+# 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 z zxoR^S4{}H^Fn*%62#Ji{z#}9Hb*&)>t&lXT(63l;f#p%nS1Ol0*N+~7n3FEEvBM0F zU4eT_=&FnCxR66MbHf$qYQZe2q<7@8%UXy;oYx@?C~^^+Xn=z-`;bl|(@qKmLK?gaE|{Jhpj(l)Xs!I< z^9fro*-071H*2WK44Nv23)yq%miPE2Q>Q|NA9<^U-Ug~My(jE2(mTd$ljsP-Q@A!# z6{VM}yx^Pp+3k|xPW5o)Ldceajaue@20zsAOdam0>z-dpo1EM_K&-&598!gT(dmgH z59o!6ZMSbhRa!XgT%L$_!7MS=)dPtrg8ga1zK!+ z$np6hIi3rLq^3m^0!o9)a`iW< PYrg`(@3h&F-d2a$)y+iRm>lE=h`NbuW&zz0 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≈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%0Dv<=vO>qW`y;&+wrGoCdm&aND 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

}Ts=bu|*Or%Qe$L$|+{k!i!57oc>d7E7u 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�M%C=&S~+YZ-GqQGyon6r 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࿴GqACfNU%aZ)q$MiBxQ0 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 z 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Ŝ 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

5h|5WGkJudU~#!UFb#OrxUv2}Y?F}p7-wonY# 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

+1^p|_jE^LO{>$?HKZ1mk3$Ql( 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%0DGF{!ygSDBVog+DCo98ya|+snz`sY5xAo33cMxX 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ʖ^CNdE*F%2S_vWuv=ijo(Nyiqsnob>hB!3-^ zjdf5l=KQby`K1yAHM#MLs$`ysa3`~Z@@S76I`eh!nMk*}Unf1gax{_7J;2n=i$3$l zLnok;Z&F0hETl>0C=c%6+B}w)M1PCO6}^)z+~ZHGdJ*47fnBJu$SY}KFJQ}M%3Dj` zu5|mBrDNErzdt#)emm_@nXN}ue~|qM^%m9^9i0=oVmgs&dkVRZTdPhVy;cPs=Tn1U zugJ|Y!>IM@;b7$<;*MRfc=D#WJZZgpMG>hS`lNc+za?AhbFC$&!yOA0F|b#s0+jWy z8&Eo45s#zC@FnjS_Z!4`eE{*`l2e@LKc}3dNP-83D%BMg&_gu{IxV0h^ zq+@iWrb{&wmgwqn5l(*tK?;y`85W{tj z=Q$Bz7|nB-_-#loFV|-eEAy6`m^#vil?xRH!Ohy15Tlaz6c zJ-`o%w%z&PLMZ-;6j6?-bp?HhX%#KGj>UC6Bx$YlED`J)FG6l527Yof4T%GGshrj@ z2sXA5I6%uv>$Y*pLSQamh9DKA%>zt*j)XT5qlYlf40Y5SlWSB>n-5e)`pKqyA$7Vi~;ftK>k||2JY}Gq8qV9TO;*Yz8(c zO#BK9Z!)#8%mx;^%A_UMe=4FXl(mcB3}yrC`5ju;6+?i*HG6x3=gW28?)(Q5-9%l4 zW2*?PW;7FOL9$+*0Faj5z-;gSzF<7i`z>cYpqBg?Fdq0i00}x;ZEnXH4=}rG=otHf zOslDpH4-sm9kpOTAUM!90aU;043*YEhoi^igqCUL|38iAZrhM2zoRe_7(&D+TLQ&eZ%%m{Au@*#UoX;h#bM4+TSi+Dy!RMb zn6ZG%N<+)3CAwft@u1^RX?3*8fc&|SdgCbn7-1d3ACMF!{kP_`i$V6$e%nX#Pmm5> zIER?t#9)Vuo6tyuaduP@qf89sAj!)Q*cY6qe9pe$;ZAQ~ARPT~*%yfAQ28kPf{&?k zXJ1gqCmWTX$)oKHemD*Lg0IE=S+0%VfqnZ zEo%AwSZs2r^5P^X0@jlXeRh1FGP7QgU026uYbv$|+eipLH0_rZh|W5$uHTTfR&|}s zK76=+Fo9gT!ZE8Te;{rd1WTU$B3ZwztX8G85B-G1Eur+*!WA*}0IaG!Pw|$ghQzQhFZ#M+D>C{tXBQT9SW1`HlXV=40^W z$SI8F>X+j=84dEMl=Pt!CT$@}b2a0HsXrt&o~y&dZmxFGkIpll2xy~Z4e25-5l>&R z`Vxknzg}aX8N-7mbfq%!ul+EOs}1s@^-9EH2oqenxi%53w3W1gu(CiG}C3@yUqB zj3v$;&y?*2UyNWN$zQ}i9?Q0Jhs zZ7|ix1t&`z;B4U7&bvEyC{j^%T+crYHIy}4)w%2FJskIoX8x7hqed!9b)KY*n0E~G z{1gSyY0UQ~SgSJFk7#~-m;`+Guq)VoML5Yl5D{Kgnv{hC*Qt1Tx6JUF#baFIY+1fi zWstz1G$+UXt-ldCWPp@xA4z!HStX};if`jLDf(gc;9dY9+El9HIkZSL@t*s#W09ni z%JKTuuhESxMwfE2T_v%~!?|zjYEZbaG##e8$}+i^1T68223?TA4bK70D&)wTiWJSN z^-mMcwI?3Mqv5PpttlTplEGmD&ROEljAi}8(QF2Jxbw7B=SMoW%lwO~f>pDL%e358 z*-gmiR2wXHS2H!OlXg-gyeu_?3|{u#D(&}Wf|OvQ zcY|}T5y`xYO7l2~cq&-3j*5mLS_7dtaH@03H;%AwwEh{BseWP?FsjdAm4ttXp+5e# zJ9f2lGtwQw@QiGK24B@}l*uIec?oH&7U=S3opqE?5308CDlr-~ls5A?A8#4}dDu)J z2yWYnp-C`vS8#hjAJREBp9F|Gtf&vB1Qedafp_+L^(~zL=EuU+{gWCK`y0Y*ORo$w z_fPfoOgWvmavZ$5jPEpi^lP!Wn4;s$Yq>!^Wex{p{jK{177f~VFGEvd){efcllnt{ zDGn-@(-*lLma=F{S|_7IQuYb+bbQ+~j*q5GC%jpLmRD z1?p5p+*N@ZrKm*(DxzO4f8G38Xg(R3E7ZVUKl)!c(pPtccxImaGyIyZPb2+Hw|Gy- zAa*wiY3{2AcRvh8qA;4qpQ(F;Rg%MWV^Dsw3RQzxPb;4H-%8^FdBReMY||!Yj*Pb0 zGR(v7nI2mq^CqBmR?KHU$+rDhIR=eUGktbrg9SfNF8vpMx*ZheI9F00#rFW zfqs7KbZ)pK#sautM2Fm6*66d}z}>AUo7WOIe<;&(Qg{_8Tgs8^W+-BBnK;!tTIjNx zJOh*+?UZr+o5Nx3Q+givH&7i;%!-7!`ZksnsZT`tncVAz#WDMSObdX71}>PTI#0s{ zLpQ3_Ot4Cp2l67Ob=H^+dG)KjrXrXVo^L$Un9iBN#yHOYah~H$B}N>li~Qm+0~GW= z#l$~UtzU4u`J5A8Y&>bGMgw*HBqe^*(>fFMR3~xITSH>bx4D$nX7`bzJVcwP`02*(BJmvUq{W)Vqv~Ky`&u8*@Roq;PoZ1q)79vhIF$`x zXmC|x==7N1Y0Upae#K?rRPC7eln`eN29(%}SmJ7dUXEtjc0 zy@d0oBslom8>~JJz(Q&5C63Z2-fWb%gy3iI zW;7t6b)JTdfdjwow|q*t(x%E=c5-Umkl1B&(U90}qtJ|IcoxAU6gCjM0qy*w_0{*< zw5A@#08VVu))Rj5upX1AE{#K;Pqlj@%Fi+pEd_p6J)HmNQSzF?HJE?I>r1>SupwH0 zv;q<7g=F=1Ip0xtM6QN#Fgy|!-9~i0dPuWUMp!(surk2OrjwU6(-#5#Q(Vv%3S}L; zJOG2Ck;cR`1qNJPD*&O;7MU$_Yg3=%uK>3#|};+BQU*S%T6HedYA(4nw4aErXqgv!=IO7b}BuaEDe zmyG*jN*j|W2bO{dfPt+S@e)Fp;?*z1q7hC$g94*g3;cae0C9EIU8`gDO=H&%pFFiM zUu_fGM&A+CoS&p*^)@7(wbpMPqiU|Yl`b#p{A!T;Wxs}7j4!^yRO^NV?pA1UDrQH0 z3~BdB^w=_%iZd-OA1_?hxYHX%j_}d~q}3N~`WmNotXACBrAio#kUdP59|e4g!4uI+ z=Sia%r|JQw0Y+`;)q)p6x57~t{;BofFI{(iy+}(Ex`S0eWW~WB=bKE(RvRr`(ZA4B5wGO~Ad0k|2ftJp-TqYvu|gj3 z%oWWfhU1KB8$2ZL;lbJGA79>AFc*G#XDeJcKC3D+3CJ>~yyj~$fdSCL8 zEi*qSsJ804#EuKb#KSmTJj4zN{&F0=wzE_h;1vsiPPokf?Du2URma|kSqf!HUsZ0u zn_}%$Hoo+-GQRY}6??LnzN(oIHDi((%dOon1+Wz`^G>D!137rBGUYfDpLRAwiIofw zI9&wkVqbAzO-Z%hM~qO=BGwTR{b+Eko`QoOs_Z{Zl_(=tlPay%S*$emvksbq zqw%m3e@BU^S(TlEpH+eP9@n~(8m#rcXvzsw-%Bdv z>sIeydQ$x(lqJOL*8=#`+I+Vu(b+e0KYp}h=!NKsKN>V{2KI^dzoZaM$EJ=o>2y5SBw*pr&6q4r!OQXP%>3Q5 zL9w}&`C=zl(ULKk$0&!+u*oUPkuI~kQ* z(D5xo+LUSwmh8N^GFe+2gt4Ab5bG-`XoQ9;MwEIGu{TZtH2PiQ!jFFY33poG`tp-&#w0$96}v;KBA(ZU0T@FcEQGtsm+u zv6mBYk5`iaGPz^a17mKQIXY)~U&*lgRj!;Fa+;nndjntCA54J3O9OOuHK?2DJpuf~n9qe#)5GD#LYSW)u# zc5V02YxlGf=Wj4%Dk~tzaim_N*x-tRFm<|Ccr}3R;;|{()O7ghMxsV3_Sm%}g-xIqTt>62B z`V3^(=odktf^*0WPx5giFys z*1buY+sf>S8^;1Nx_Jb%3anF0saq6{2z}`*6(tht5<}4$Utp1z@(F|QqpiE7-BSl- zx1)}U)np$j)j~jvn#}sn^DA)@?XDH0fRt_`SoJfqWSGhIglv9opM3@G=;NHL{m0~T zJ{miYqQk{}i~rrl6BAOT!6zp*By_RiL9XX4c=CAtpBd{G^nWrgHT_=$ zFJj&6^nZer={}Cp|M`*7t%ClKx4jl^9SwX z*J#b!T3-pO7{{%YwIce-7hgZxc@is{p8=k$qZ%Bfp>h~jg|Y{qijg#`)4ofU2F~13 z+0Cz6gIvb3K)ZKq9HUUsaS5thkwy>M8d?TKdJbb@LG+)E_im9o!jUNscLuAJ)3%4{ zcy(=$FyVAMJy_3+*u25S(<*?17Z8#5@p=1+rj`0c7 z?CAOoJ_ZYk4m9w6>VVNtQcnI8bj<05_18dE{=eMD(7+PhZSLeO)hie8W#-DQCoe}+ zKd-zFgz#CZ4W%;aQO#&O{5FM6;)r5^lqzB*120veZX95b0GgE(liFQ|LDXArMpQ-g zIt|9~cN@0ZL~Fwa|A0K4u5mqaf#d}$uZu6QjnOwANZ0nZ;y?O@gg@-hQiQIVj&ZF% zgX}p@$0&>uv^q}%ZUTw|rlV9o9)nT|Msp_qn z#H;CW(GW^VdS^;V0bc!AzaceKLjL|pJpV=gV$(72_Vd$z1|Fy2%}liAT8HjcWSbHp+^gPpqG8fSjeD>>*PkFI!Waf9WH?WC2It z3V#t%J*FSs4iY;NqTZZB)%<3T_Xing=i7bR$5`uUWjqsr8?0dTEa0Ueu_9>@F53W06^%FeX`(rEs+l zY-YD(?Q4;&0|lA#zo!2B#50X8Pot%kz@y3H+F-np$1>0{%eWSh!h+5EQcE=yiM6w5 z5^PL7R#?fyY40LNg~qPspu*7DwOn~@;SyQT2}=hHOVtWGrU3qtKF6wlnxDTI=Kxl` zy7#6y%Hn)Wt4#68FaK?)q67Z9{xnC?JyfXUFu^8O-4A`;WhA1N6>oGKiDv3-Np0zs z`c^$iCh%4r6U+riBa?B^bKS=!1>S^Ognlokt3<@!p_j+JqsKm5TwBT3d1hQi_2zUU za!OFO!x^6C-|*=%#Ov>Qi%6X^ltPToXmm7T9;*!H4zT;KyfQ`wDvPa znlI*3-L+j#wyHw2ZI$#zMbE6n2IiQ{@lOyEbYp!Y`dHQNJ+W? zWN2dy>ZN7MJ!eUGnZi|%%8gJo`t%LTg83pSkGLXtaHb|5P&X2Th0L?DY{>X8R z)p;XR6iXyJjo~S$9l`2mWQTe^YwScG6E91rI`!z}r+!yal1hlkCp^k0^ehxbxeWUJ zR&+d?rwpJ|KAqYey`uY1YXpXYx&HWUw7$AuBnDm-5gB+%Mr0}Ylp67}X$Hb^rwvYy z=CmOh&O2FByoNub5@eYTNBEM8Nx#cR+9dZ;VxvDxK(lVn7j)oY#}c@?Q7PFsLZGpn z8f_BbTik5Mm^Avpx;HuXi zIp| z;qZc=JY9kG+C~byMtA>=wa5;Z;ANZ)MgRC$Iz}-J&a*6&`mj!A5(66J8tb+R)^#J2 ztl3w`%eL8bj6NtSvVed7)VU?~wXe3W^u3GW0kS!Oo(c443;NOn37~>`h4v#gf&dW? z!d%mqKaK;{y>M4j1Sq5FB3zFLo8S~q-uYX!F-xyFh&IO6h$yWoRI4x&y*L3u?IT3y zJINfQiS3YL>@aMRnnNg2y~A-;k;0|n)bXGWaqRnr(L|ieDi8d6g)PcMZgp1M!FhW} z#E5JYC42#+>%PHNf$+V}Hq8&KOLkq0Z339~KjxXJ%7=1tGQ*g{kL+hFBg3?-R( zOqN?tdUcE{m3tO8_kW(M0Mnm`CLSZ3(ZBEkj`uRY*^6v4TJ@I&bl7i+d%1jEM1}@; z>Qgr&Ta5o6GThOO8|OD#yQEiA$Kp=M&}VuK3V!Ry%(_h~5bMPo?G6NxP3Gea; zxP9#SBQd5qAeQ*X7cjBN^`HxVZ{ALlj=7Ig#n5zqB>pdZ=RtnW-dVNs;WUYS+~Hqm zT5HxFg320-COc9%`fI4g*NV=Vhkg+I(Q{ve4cLLFdDk1y)u!+`*!e*tZb`d+Oe(K^-oP?v&)+#$lyt(^hB zc0N?Q^QKb{I?PD4p05?GTSNI!?Z~pyj-$7nuT9SYn;sQrB{*tl4*4WsiYY4RW%RGo z>s0!5+#Z#7?7HP_mHw75T~x%6SLx14m9jLxjZ`!-!K!j1@!^my{b}>N1 z5#~yevGsy{ZOTV@y?#kFIk?9HUI|R%1`9920~RH^2;_grANfn<+A4E*zPbc8RfN~# zH^kViav@Pv~0N~#K2@m3vPJ0^^Du?I0qw`8d%jfPNXU2bu-MgG?mF$I3~3O5Ek zAbz+X5%+U5;SF1XQR%7DJ6v4JCg&u5 zEs=*Dq#SOl?=e-%Y4GR?_Jtp=FtbM{1BhG>jHoc_25Y+w%?LpH{a}H)tF9;vINEnM zujY8#LQkwd(udCSG+k^;*6t3%MT4g*s#JxT1C#NB&3^^%)S~QHkI)BNP}@!UX*B5hnX?d(9BEiZJ?X+M z7iJb&`k4T=n`G9qwwfd*X`JQ&Dyd?iCSdhO2oBeyz zV8e^~$@LGt8s9-Vh9CD+PW-sSemTUN8!>NsSj2) zk-vb)9lGM!QccWN_Lhq1KYDb(Z>7~Y=6pV!wnA0pwnEu=P(E7Wb5>CDn4H&>6Qo%d z-9R4f13WVbvQy~*=(0?VFRgFKB^3NF!BpqxQCq*@d|YZh>@4T3Z^d?!)JF}8WOofT zxbl8353Ib?r>XzCOz`i786gta(T(W7OXTBn;+Qo>eJHFc3c#0s{0M8xpI1QJdIWHG*-paNIf=XVKw?FfQx-!K2A#P`%;W1dN+wlyft7= zF(TX&wlSf@Fdg@BC<&`KI}gt&-Z{f`mbHRyn&x@JJw?4D%oSv5Xn7#rv7P0b-I-r@ zdk4qs+m>Yd++>BCN8|zz*+Nzx7Xu4#zS?#p6t2YT{JYIjqPqTWPcf8(647Ia6e7 zk*yC6;j&81#E|;)Ugb2QVQ&Q)4o6?OTDlHL?6^w=kaH;t`*W;}uowqf9M2;x>Llza zNY%|QtXS50lN{(rMRdtL8Kc2RRUsMK{L8dx*TZTWT@1>D&3wyc=K->sI|Ck=#$)H4 z|B=VeWhM+SD;0;^VBFJuxNkzgDLa0NKxW6k8O{uUNt080j zc`g?S=rjI22do|W^At}(8W6tfKkv`;4ttZ!{CRSoe>=r6@zkDnjiHdtUg1p(J>p5^ zGKAam=XMWUm1&Lp9>0?2vpcETdGoyP7;l~qo{R)C{U7@CjH$>-0#d@1a}*UBRmD^j zQ&oYQ=)H-2#}Lr-bD;_xCmeB%ykMD?|5vszaeLahi6c{)HKL}Eqh3d?aeHq`wO?_K z0>D*S+U1ZCsTLn8pKu;Oi}ow>_i6Wu%-^RRJDLB}xAOOSovg*>R80Op-$m^X{^qNf z=9nhVxy5Tlib8w-;qEhA*+vqxH2Gh4L6%`^b2)+ksmITSV&HiET$~P%_xQQky0MOC zg=ve^38zdgYN7q{81d>`n*07e{01Fe>_YSJL?DuKN|Kw5^|CXVAgO;H?*TXWu=I-e zypydZtOO=MLS9YW0KZr;7MM=BWI4BLoc~X8Q>`hD;etwBTymI6;4@t~YvjE=!K#4I z^8cv|UuN(zSN=a2a-#W%{D1b4#HMGA|4Mx3y$vo@$`ygegl;xYnU7QC2Y9c`^)-JZ zf`w~O^1}OczRi#YRq@7{q5N_GpCjNk1qB*`Y9A00WKOl|aa=hSeoZfq#D1w_#*BRu zUO?|M7m`lemTA;d3hKaGEE~X?Z&1_45SBRKZNEM1)&5bi8l?ogE3^{aT~DWos0L;01RUwxxGvb z41rO^RsUcG0CLw3{x5Ow0v=aY_5XL;1X5`@DKt=l!l*$LZWa~o2uKEIWCD}6Xq5m} z>zj&I5G$ryq%F}V+F^3is;E^_tD;uLx4iFL-?s{A(p%DU>xI&^TnwN%LnxMOQf~Qu zzH6T|Gf4~T^ZcLZpXbS(bM|%Zwbx#I?X}ll+uR~<1Tp4BaAV1gwg`(quoPlwLXShx z%#h$Teb&E$gV1j0AQUV>TF-$9TJKbd8UY&gqt{&dVPkhU6=$fPvKvV|CjWcTf{F3t znspfwYDDY3(O`X~z(fsBBQJ*Xp>qUV*tlVDZ$0KO?)=WE?jp1Im7q0gbaN9{8NOWOOJB0~mU?n+`C3BMIik79XNMZUa}Mpgl_N|C zyKaRzj+aD+lhH!!(mz&Q|Cr%MI3rSqAO7ZfU zhU@JIcf7AJQYgV8Wty+fkmt*PEKWZgV|@kppO3>ip(NBxY);hfHus+!+4QfO#OL0^ z$dx-$x}krdx@aF!;<;1fb%giNuE6^z`$Dl^?;!7=3%VqjMh@iV1XRp2A7v&8)`xQX zDQRSS{z0_unO?LxFLEh!sL659QTiN>dnsc2d8)VPkzWjZnLRll#ZzZ4?&Z{ZV`d{u zh~I8ykQ+)1w~Vk75>4jjtQn~_H`%57dNO1-Jf?*2|3jtCSmRb zl5w_uM66#uO;HgQk1Xl5I#eo-i~uV=Dqv~`>--8OgN9ZGIa(gLs_^a9DF(X(?a?h1 z`z?! z?QtEeb%>T3PqHUkx1FKa1)P+o76|*d(G1qa8~NnA-hw+3MXh#Gy+qmRm1RoP_5sy- z!uX{xqc`8c6tIG$ZFX6b8eV#N6{ z*@F5FbKZ>2@{iF%&4Ozo;m-HPmkEh&UUDRx2*OSTC)+_9!5*8u_(<%f1op7k{l0QR!$eJ~)wFUlm88nn2Wn}D z(O`AO!Z1h{%{~5C*t;VYE#)=`WaIf_1)M`^r3_@?J88Mufd5tKLLG4{!L(Wr{b}L1 zji=NXt$LC~L`4!qDzDn;zF$!RoilNz$ff8MKE=8$$y!4UrjCu7C!8O>ROV@}?*v2@ zSMb~w(3QD;6&_lN1b*8~UM1Y(Od_dX*|fpUGf6v`-6|%b5I+VZjV07ZYna3(}((O<}p zdhAPCG(HN0`rsja4$wGWcDt~UJMioKhx4bS>6QEuR@wewv8FC7*}w=ZeVxh{eDmPy z?%5a}<0@J~MH)qYRC{o`Uyv^MIhUk8PsbIB@IldDhzrvgy5YrgS%g*4NgI`MSEfp8 zrX<_v>?Z}Am_s~9>X40}7K<%xIS%})7>MNPTt^Ok%dL+>pjwVpq7~{K3T{2mj%3Lj zC_SU0F3h&SxFn%eq6dFEI;OIRD+o^cGfi>YN^na0CuZ&Q3kE<^`!W0cdZFwW?0tJ~K_zrNQ`?J~!<}!McM+5WQgiH^5u<5fdn5WyTau&;Kw+eh;& z|ItnRet)W|t5k!KWV{6GG-e;vM9s#1gwZ+D^f5cjI0XxcvV3HoBrJ zzmAMWvMru=lTT!h!sdU+k^%v-j1+y`0pG(_N@ip3KZ%8^+kZ)U z$@af`ZRe6}a1T zm`h~(IiNhgXPJX9x0+1i^P+z4C+``@6Aj0bcL)lhp5<0b$A{rpiR@$)`1rr$DsO4k zIZ^*q2yA^@;5*f8`>Ki>!CKVJZ~qAp-%o8YT?r%*>lfME0 zz*h-Az0SYW-jFElz+c##`EOb3L}|wtr-}>V?xDO9V2*;uqJ5sGdgDCqmLIjEi zj`QBTnh+6c6BR6FccHzLgwoB4m^cO2Vj2rktXp<@ZD)|OfD{t}#stH#^*q8|O>Gqc zz}tkZs+0-BU}QM;77Q-}UjyT}XY0#wr_kLWO^xr)t)1>R?W$Fv63VV??uUeFHhGF*I4~C|RGoD@aawc8ywR)G-3rb!n0OSR6P+zx z?wjZAU@dw$6d>71#oF0_NiSY!QV4B!GCf6}+d`3~)Q~m+G8?pu8!VV^HetS@`Qdc) z(?MY9oed>!7kSdMkY|UV*Ngo3>@zXQ9r#>kL1pvgJw?6O;LqM%C5Lx?L@>{8W@pqb z(saxB0D)RZXznzwt;kh;47|S}p9S50I&dxxAO`7bBQq?@eKn9G6yPoY7{fvWiRf1;E-ObNLj={Y&jU{tzV>R_k3ROyz#_J~xR|Z|XWXUdE_^_CM92E)>x}G@q{JX~czhk; zn`GF>)AcvB8Hv-cJlVU7d$ZZ|<@ZP$M%cs#JdJIMqaxWYH)z&jEIId+9b(o)f9gYx zJ9vudYq}P!ZVMjey5b?c3a~(ySNPN)ox5C$ddaap7h0$!OucALt1*%nWv|e9mxTlv zuv4#e;4}XhwMMK`-b8TV)vrE4u<$k$eB|uC#Vs#WDq|&ywFsVO{bGCWLSAj|uJ<{w z*QzpTz-8dhyYbxwc?3=Rk< zZO*;-IKW@Mr(`kj;OL;IR35 zd;gc3fA@QFlC4eEqCV6ePK6*G)8kTRT^)#cx_&EH2X=cO+3J0?o4Z*BoB9u~*bk}9 zc_n`jYi=M+P`yMH?gym&D*}u%Lws!w11q{ z!aVxdsrI}h^oE0#8UdKdxg`uQ?7+B?n`>I#%PqE=6;dQBOX|(+;?9o7%)L&^3uM2{ zU16UhfL%ia64|Ii>dA!CLAQ6T{{CngS;E@+q=lVjiL|>rlxe0$23-KqZ7=d`)*f}h zgAmshS=#?9<)yr~ZxB^X4w9Uil%~B}5*OD0`Vco+3tF40$JYObirNqr*rYjB)P|_Q zCe5J&n>2@t+5iZjM^_>? z&hzgd(F7Jlfx+`M-bM z?TEa51S$cEdIkN5D;U}gY|C!3NGE?5(O#4vWlIpsj}p4X-$22P?Xja5ovZ-S0E*|>h_z>#7mBNtIj==wlP%C_S)V`YH9e6 zQ!c-9-+u=(l2<#JTSntUF=-bOnk{o*Bv1rXMVC@UTaEVd8Tu@UJM3K(nYccYYb}-3 z$GNNDEg=bqzzhVYcGu%+{N=(8mBWhYqu9$KYByHu$E#R@gt zHOhG?mW0@^IM6ftW-$r+U zu!XYr(}XLci(36|&p*|({&~TBYG^)wQ%x($^55d;N;uX%y8RX+$Z2t0$;Z4WAv@G|bxF}~T z{j#yh6i73=(HG?OO5Sh-WRfj!C7`!Xw#HibDFFQp(iVa*vuvYu6VH!gFed) zK+jpv5Z(%?DSy)B+!x8q;qEKFYxXgh13mo%aC{>f=b{Wc?wz})kN+-VuTMXyrY>W+ z%{G6kCkdArnDW>aL{^HOX>-$j6itjn?c(NidxRO&ry3 zI);BdsL(AnfWQX4j!<@3uk(TA(X^GJx8+(>fQY}br@KX+;LV;>iqTHl;I9E1QNB zDn;9s(v5jn{SLut1O5(P%Oy_XJlTL8oV!xRI&TX~Q>g`N6+kJf2Tal6nEYjcTD0%x z#^w~eF3vJRw2+FlKy{cc^jm3e|0oq%YwSY_a|$QX{P0|U`T2sIhzQFw9A~!Bam;*gG8+g2NoMmL8<);D`9M1 zd>8sxz`8xu^Nh*44pl8mn(*3rXj>oT=VlO$e@*v6t`r}^V%+<-Dy}l(?EIuZ=!S@ zZtWixgK44*1%!6|qPhB7$9Cq}=fA{uY=HQa_UB%CN62>m1_{G2{w=;^${08}Jf%_0 zLw9L5^K#i9$8;Qznk_C<^$~C@?lXHp*zF?G10Yq5=|W{?oX_@n%F#hb$aggOUH8E+ z*gEhE^5DJS&VL`do1s2qOa>#-L-)gWRX67_m*oM%Yb;=k)UKwd2*1Wo+Kh*fj3)0iZYT z!QFEw@~*%sFGU;-C13m|!ZXNPlh+_R{80O6m!Tt$s7_qKV zHN-NyCp^qMl{kB)6oZ4|e@TRL9!PP+WkIg0!~eAy6C-Cx8Suqs8F9ix;Uwg127Mc9|e5~KQ@m;ivdl>nJz_?*h{ZeN;?&h_v zHJsr4!L)Js;em05N}7O~i81C{-XgmM?MwS zBxc%R#5Ug#faeXo7;#{iVTS!HCb&iw=!ys@^2b# z%Apdw?CEMyi7NT^8Rc=bptyh2Z+V>-R95!;^^JtqswWEgAw40XIbPcpPs0Z_&>5cn z1m~YZ4G~{DjF47O6wI@2nv#UfQ>Pj`-)3@j>)k98dW4aJq zC6Sm%ga74W&QkBT#i&dHY^j`;RWfzDYl=%ZgOBlQN{@VTSjkQ=rDxz~OTzbQOTiOQb4(3?2-l`^rsmHPA~ z>|y9SvF4SA%%IoyENN{K`ZSAB&6Q&L2@Yasv4jYCSKPl8NtTgKS`7bLldfcjJ6x%S zD*7v2k)|UUolU|iefj29QKP=7h)Rr442-?)+*?l6CJFN)r`boXLTSC5y&WHQ>++C) z;u1q0659r61<-%OO`XY_1LyS_s^Izl6l17=m+|k_ufPXKiJJc=Pi+Ln2%HpFgHsrM zg|f`;x7)n~c~gsAlQZvyeeLCAw((Z2cEjbcq|T-z`2YW0>TEY2c}Rx(S)xWV)Fw;( z7o<)uv}QZgt#;~N^(*?9U6#T)7ppKdRGTBtlQz2z4RMrJ#Ft?l8(5X zxLuB?+{a1 zkQ9sSUBTN=dhtys(>XpTDRaNdt8)^9cvGvs1AgkYRpIbt1S|b1tkiZ5?#~r>4My41 z2t@4{tgxq(N7)^4f}G7fCLy47c}ksCL5w!iP8n$-yoKAoS7c4?PiLhXWF*#%pQj22EHT~eMJ(IYBVjbyC>U!Ochdb zK~F8k+A;;&jdkEdALwIG5CC(j!qorPvf8j^sQ+(Ms;_QT%SWj8-Tb8*ARV{CFmUq- z{knEx{pvezrua>*PB-uTm6Y5up1+dJrFd~IZ&#)jL8eJcLOrae0(JbEyan|KH-X=# z8KC{aKLRCeEVUPONfYbTtE_cz0Xs5Xcr!VX&27HoB2&$U<@Ho1X~6OJXSAT02mPHp zm2gqA|1rc+J56@hxfUb|&kxQ{XCC4rY;sbC!XqC;b)eD4(mmNYk#z3n?^oL^NveR5qVAF&GN` zYL6T!if0ll3Yp+OQxo_kxSr*iO$oKO!zv|ul)a!b zM3R5rDJNO&u2T{*J1F=uy5%qGmgE@kQbgF%-Qsob15I&%MkG-;6k@!9>daP#rSJ&o zI|((6vvqo;q?UOh>Iv8=d2njluU`25sCC8sLT^gX?g&w8^=a%!-)~29O~pQobqH6- z1(|9Yo;AGZI;-U$i%C@8RTfGhn~&tcge_PaIo%zw4tZkv4QU5X4drjqR~bd9`Pv8) zPbpBCxBO^^TSMI=>2X)n*GPh1+e-LR_ON^leQwP5O1{0?$DsEvXd5;0WlU-h@n9I} zioK>Oe^{wL)>NwL>*L+|SC|3bILp^ZXVE33wh=svpZ5vZ(7i}PQ&GL1nFrX%g>Ac? z)>7uwkhweE{BE$8q=MZ3>qjzecc|r5qHtc4+d(WoMBoNqTb61}fqEw|Tu;H7x-pC9 zuA?$k+cUaj<3bob|3SifMl$WYl`Lf1`k)JYz6StnsA2`YS*;k!n+x}?h6VSOaOvNc zHp%hZFRQpH#la)nKO`O*Af?21FF&8~(yXq%?^o8peZ^(fwGqXvMTUJA;Wqx|FFwTu5ZHZ8zy~r;^-I>@lX&r2r{i8SsR+&LD6IrhnOJjubfBq}p z4>`t~+}gIK1s*-N__aL*B$1hxUn-gk101bLd!i0%QQF=$Ds&H%g`g=r~=Z%{Ei?$K78hmhRi-Kam4Q9gM%n~IfKfw49SiVm}xw-zM;7XuCom; zyFbTQSDaFt*#Qs3w)qR9QUN>i1~U_gQJUsF=(C_}bA z+|G?WFiWhq{8Ply3}Cq4!C-(}*&)awxI6>D{3GB9LC76L)zFBUCCPs!P>2JOO$Y#d z6!E&qM;?-`Wwp64>Zo{N*Mw}VQ6ZUk70*Zy8URjpeGP)l?}MKPCzH(6~Upe@{o?wgsU-%H(H5wO*ijmnO9Sp!Bpmv zRA$4#XAt%@6_G4Jm0|Ct5Mi1~m080r8b>Xgtb4V9KJ13R6%DX>I$Oy?o7Kp|dKH=C z3}mnE_n0=@K||cB=C~FF*Xx{UpV5Qw*K(OZ_L5S5Yp)lFYu*vB>oQ|SxdKD@R=1`6 zvg6|L5GppxkT+`)9Hes!01#|s&C^Jlm*`1j5+7vN$yvq$c=H)@gDh246cBJ8+Op_!t|^UIK)?!zKZmko(1%X>AAFgH~%J; ze$^Lk5^Ym@)-Np|PTGA}3$GXQw79j&b6MV^w-^I9>496aG~$GMO)jyqp1+Ilo^eHE zp;-WI^KWU@$a`StuH{sHvQ@pHvu9jkF_+g|zM^Lw!d7svlgC?Weh0d*{C~UF&Hu?m zCb>#U)(1)6N|K&&bab$m`vb4V^?c8`qOI3Yi0K&zUkdE3mh+t*CkaJjn#m78CdfP- z-9m#U9SBtw#F~`QqeBfw*b4H_7$fl@6c%t*R1g*}r5G%**O3~1hARPaBxgbbQUd~n z*^4XsVV^x^IrSFX1cZENeg3^yeq!+6e7kE;yfFV;f3$5QDE})_Z`wckEQ2y^SLM6- zWZYQ0cv^#K%Q%8HS83K6y3xJYhUiZOLP+jMP27ceB<%?>?KSkp_IRDA8t`ryuts-= zL^}8)IU>s%Zp{u5-SIR^s6=chemK0w4HCqk14J&C!`(n;D|dl%O&kont8OpdZN0t? zOng5+_!0%I$JKTf0>+H(@w)A2?l|9{U4fx~cO=sXiR`DEL|t!u@YzJ{E;2vQx7Trv zs>|$1H9y#>o6FXk*fF@bVUYFft!A6sfU-8-EN9+BR*PTZ9p%1BX%f363~=0A zyCdlc@@?61jV6ILJ1C`pQ9GymHTUoUi?_Iqd{nmTP4e|{N67&)J;X_fC!`P-5zAqI zq_3g-@8dwGTF~gXY|`;^L9d(4wprMsT@}g9t^gxiK)JyY$U=N;@T7?EBDvyqGn2l> zt@SM#K;Qkrw>yg9w#)}AHCE=6f^NuG=sp0qmu#d^$9B|Bu3W9tkloy%jOFMixgS+k zxW|sy^@^jYLJ4&OP_x8seAo4ni!cG1d*^8{51TIt-AAJws#sMBwCv%kTV7`+R8)1q*6~)YN15UsxNT8t{}Qr z(YfFwnyb3+!0^&r-NluOI_~l7FghfS29xmI%Tu;)qAd9>TW!yK8zT4WmeTh93`bJ! zCp4LPl6*Ff*0>#34S5?GELx0U>bP&m4Wr05@St2|(c^qST{WCPh82U65%~Va*SY2q zzB;J2`bgGOazdo~29jw68eD#5mQP9+^trdq!U&t?I&S>MSQNH&XsnlBFSwN6W|yBK z9p&XJIGnae$;T1^UUz@O&NFnWD4k~zj(EA*h?AFK-KLOBnEkRr8lt|NLn?P-)m!#OMaKHPj?eN!3AR_k zys@3T=Dm(9gRGrTDr@ulL4z^y*@`>% z<3f3Wd8puO02h_r3!cUZK)$};+8D{}c|NYZUWz@pV6*wvl=({BzaSF7Q}_{+o5zdx zR~Pc6DJ|NYMj8rq@oK`BHb5qdG3S)O2K4_Cs+Yxa3wX0IAKcNgNzGkQzxD)T>T#^d!WRHOo1S*E;MT#1W$m08O<4d+I@>rKR{FPhK^r!Z{nNyKc99)V%rxX z9%Ivx@Ef$MPepdd>z*Om!^~cHvC)kZdgA*7dF0wx((dl49_*@mDiUWes%dHYKna=W zwLoEH@axt#5_$!2VRdMDVlU)t2))mK>Wy~XIB?*uI_D)EtF_@+tqsQNS2t?BkC2$D zp4x*GFN=610InDKNxsSj6qi(&6A-czdye8KLqIQnvdW&$3<6%^CSzXQK|@~L94A*^ zB6RKIYV5PgnH?_?BgIEL)2rLD86g_~-m)_x6s;)~m&hKG;3lw+HO2;r{H0#9j+-1q z!ld|1B`CS>7ve;GJjr^*mGlH5dRr%OH>Y*KrBZjDUg(KiD5Sz9I6Y_K7|$SAgtHKL zltoiRGp6|ecu^cg(}@tOCZzplZV!0aIK-o^2IaYVJ;e;Vf|ttMc}bx^8~h6cd;o>q z3uL7w=e(+CV+I>XSZPZ41kRd5_os2JYRwTCP}o6(L`C|Fd%pqPO#ZP1%xn`5%5w z7@i^sK>$cTMz4MvG-jT?as|nX_)2kY>eFd<@U&mp82L*&^LXl1+z+KQyVGaSl|9t& zs84c$(U$;S`V`9WhZ9g8p~4(+XUBWK6d-l78lHGeyp9t(jCl#y&QGb*+N8&L)%2od z)629_6T#?GI6ch_Y?d_dC9Xz_4DaTeRuXB?ZN5@W^DpL-9K33;!JIlZE>PV?IIV{D zj9*@H1Fa^RG07+__qiqTgh%!c*`|d6mp@A@5gs?+aGYgT1eT3qfp^cB*MbDIO`w`WjAog8j^=fobH!(xg$3$P1RnZgDPOJ%F0Vy&CR^z{(Rs> zIUTw%sYC~oM!*enT46k4L z4&j7|yHm!}la9X)=&Qio2EN8uk+Xflakf$XOz?PhEj9CXnN6!IVG^q_BEr63&*sVN z2!?ZEyTKW@`{L^e4b+DS#T|=5C0E*nNBN!aGq%cAP%TM&lzU9>{!g&`mwitSx=A9U zM6~ZqWKT+Ds}h<0?u4cUB`v7rg?`~X+V>^1XcHbHfb-YPdRz(4^kn-v{R9^L@4IUL zsCK(eJ@EV5qUe~xy#dx|)m+WEuDLq50vNFAP;0?OyAEK}eIg#@CB9y8gPm>$v zPeS6Rdc=uP()>J$MN2$3anVPUu}8$Hgw3Qk<2e+6Jf2R(PFcKA9x+?4Ez~Z}XU`b@ z<{t)+B%h+(Xp`=#rn^fzy3&F75)+V-hoxY_Ky2}ZvZ7aGe?*Q^EbUfWOAEWopg zU@aeZJwe-Vcw-w`#BqbtlG}f8xiXQxb1`pRRVzEZnGKnT?gUDtGpsJ1GwCs8ZWw$B zF7z_cR6p?*sJHvC*tEHMdvm)Kbv{-VuWNg1r1!Am5yvhe&!J4OX<3;>>p98xKusD*Te~!!cF9YSTnHTy1z8k?OD1B{l-gU7yL*l7Mzlj^(50Y{^y66v-ec-HPKn%;D}i+ zzOXK1$i>x2=6FOnXQ-KgkIfbB&(j-%Y`SKy-mXsjT15DXrm>pC>NWkb^bEESh`ZV( zQ-v5WAUYaC15$c&4@7OsOB7XZn|eNo++n~TmR|{36wcEJeVs?u$bEg#yVr4mgiE<` zwDV}_BkfPQ__`>qr3H57D8!g%&`lG6t)l$~EK`GP2`@AR$a%S1={T?I+$&h~tUby> z6TpNLM3q2@Z1g8=$X$PAanv%eopy#%Ki5sfUPyZBr$x25!!`2@VJP$;RY?s%QEW%+ z^n~HdFJHMZY9mwSO7BmwE#3vNu?dCPdfj1Ao71aK!q3Q3E76jSEb)VHP@?PAgG$Vw z0d<4FBgh)|{UJ~n5&`)g4e)Zc;d=!Bil}o9aO5!>e-ECBhFD5$SRDNiyITG++MLQd zqNQ64^y+m!0un>Q(UqVOzJ}fBzbqzDHRURvkmv5IB0nN?l}k3U$>}>Cp#BLDi@e*H-9{{@UO zx|V}_>ls&7^>~h+SU*Xc*1u}=QsaCg!mgf|l{H58K)?%rV|`d0Zs4I-adaWZxCfvKY?vvi&Sgq{Nw}FR`#`7p<6eX_6JMH)BV8*AjFx+ip0Cd3MJ7 zSofl`*!Cr#54QItI}B7AJqJ5+&^K7W$;7_FJ|{>ZSNy3ZDg~7ZgXdpbBEBI=s3{|s zoy~wYN;^87FniI{ggX7;Nx?v*G+#_(=s) zcc@3xDhNnYKthmd^BZ)2UZOMBYXlSfc0C|9XBC4!?g$HTN|s!2JxYBi+d5AZTM&&k zeWQFr@gDjfmME?SH8vS@#rXj!{kNIw*lkL$f)K^&>+Zu#fvUM3}o~bFms* z0Do_2-p=s~mPAbGAFOg~K1!XBH+)WvEP1au%{=ZGc(oz&7o9*S4l$Ml)BSUXj1Ad( zY;wS#W}^QX;_hrZbsE+|W8;~Bz<@S$mICjajs7_gu!oQ~E!^u!07DBNPsZ+AbRu%Y zgd#thSR0f-2maT~)NTi;ns=w`b~e^+LrOS%R?Td$T~62-3Bs+;v@GYzbgfVHZNrXF zUc@=S3PObDw_PjBn6=p$@NxPuWLJ)}@abBxmcRT3rMYT|%RpJfZxTV$yGy13;H2Vw zUey2Dew1-Zm?OF|)~^#UnUE5b99po6ws{@j4XVF|qT~J*5#36kk!G^`yM)loQcYGa zQN@^aE@UYdLR|hiCGZ#0k=s}#ZdS8WSblI2$Dj2;6<)9k0GX02u zqk*A-soV=;z&So)yA_B>o6)F9j}y!W+aaCMP{mfu%&5A7F|#$d{8&}iW(5LUIMVXJ zWb~J;Z`?qvDxWi7)8<5VXL*x*uP@7ASIS;T?^kOHC;oaH&C?REi>K+Uwz-!MTUnaE zYQGC{qLM_Wm4=EoQj)MLHG2W^ z(bYs17Qy;}N&WQmEP`LTB;cY3Avth;pMnqvAsknY8^v)oE5u`4 zxa4!obteOaIQu$5nEw)Qk_SqRRr3E~1ir-$7M4yBM%UtrBoX&r$4X*M{ydk&>ulmh z9DxfSw*>yZSCGK#{4>8Af&a%-w9=GdcgX4FL@dIZNc_*&sPn4IZ|8}I$(_=t?}PX$ zzq0UaG!CnOV((2u_{`tNh4j11rrA}}0b~(avD?b#3>EuLUhr-PRO>fT8;}sMb(8v z-ld$|LgjTUNdWa09%{rq@6!E*uQkAOcRq2V4%KOcRz)bmd^_`2*GK7Uf9~?l4%}8g z%zQqdf)#}Gn^i`)p;7!88blV#t_4OR0;<>m9d0PU=_({HXDQj3>9Z!e##?s>?Fz(i z2aywOv}dB#&B8jlZBLa0jI~Z6%2*G~+ImgHFC94$HW*g5$|ZF!9Zfq4p5_GtR^_vw zWk`_OmUdPlAJN=do1LQ45rl(KM>ZDbzeM8;((j7V{8`eF_;b{r!PMfPzC*RZg0~SY z%-m*Am?O{7V(K1La*gZ?HnYfO51*I@E;}*M{7T=zoW zo!cuE@d4hPnbVz^<(n$1ksxhHl#?^n{-PPvA#{7GXLZ(?Yik+?cP=?185{DJYpXZY zjp*b5jKZW|t7GHEZCTS#GE6`do(4l^w}D2SSIuOh9h8kE1!$bX2+)JvRI`q66FDr_ zS%m1cJkha0f#g z!3iU1F}*&DMbKLxo}cdJJJq})<gda0#32dM1_R4C+l^N+f8#G-jkjbr5XsYU$HJOmFawQ~cy((a2Qg7=q<2&jb zlLEy(F2s{D6WWrG%ag1D9CTPb(ucVXAh0%)-L(^bw^!KAMsJz~9FO%aIj+Gkn<#mJ zfiNvtKg?(Sfc(phmySG!#Jd|?5p^-!BQFQNE$3b8j)D&oEa}xJwsqd}`@xqORDPA|L!6b9W-{S9z`Xc!y{0DD_th({%D`U$ z!8RWJ%4Gxtm{}TWZh&c6Pfatvu5Mxzs)cTu`hu9cqX%}48psD;)IYTJd=*ZiL*&km z7YF90Zcp8Iw~gio@R2HVzJ6vJ8z)I%2c$~t_E7yoF(dMbRwP%8g#3#lxJiLEumg{T z&_xQB0VxG-1H5U06_G*jr|+|2KhG$S5{PUi*U>@FT2a10QZZ36h&f8>2HYgGq&MVf ze}lgI++5m5qI&wOh4=Nd%v(O|5o-3G?N2_+-qDf zm4D|CsE4tUU`cE?gTp$IalU`Tw4kO$4C99xePVB)C#jgInwx<6I(eUy9Vi3ZZdd*;tF+wfH24nl4{$Q@9XNl(!4(VV1&4*6!Q$ z&tsotR1d{G^B>qmF(?jY6BUjHkbf7+WPfQ41ltHc!x6$Hojc;4fn8KMNU(~Mfs~SC z9TkuDEUpn!^Vd=J;Dh=3Ol<0FAvinH7)SnM!Zf=o*)QHuKAA=?$tP9zyu+<&=`L|g z2`K7mS%r1+Ok^2B_m~m%Mj1ih8y@pcWZ$j5y}dvvOXx+5+IK8m$U+UFwL?r@Ye#MT zwRahKD931p*P;8QrH=mvWvg?Nh8UQu8_DuGIdM#&oHB}&Vz1Zhlp{o^qS{MN0in4) zerE;Y1FY`c!Rh#&G<-Nd_^{?*O$u&#nqX41iP^9G)+eF-*%t)TieUh0B}!7(oHL1zzJo6Qt03i?0Nm?7oei`$b%61=ggF3iI~6&YZjib2;R&xHmx$#dCkkeK2_PYI z3~kAdgW0fS8+4)9(NIp{%`OdK#$yk&R`D7)(OdpU$)D+!8oDm$C&mqbfAD2?8;P0G zjn+C|w;r2uRKhy3xL9bSiJHHX{^wcYR#jdIc%uFbcp~g8>k?97S_y;lW+3yN$ttAyj{#N*Jzc5~`qczI zfiOsX=9>sBbd5$YfzEK+q)?6P+{d3XQ$vKAyJxE;%<)tUw+8Sj(kDc~CbLJW`1y6c zddv))7U`2<)Z{0|4kHK$l8ovFeDyY+fyh$VE6V97IMN3U3(I&5gcY%1KQ#=+GFgWt zLwm%n0+D3`Ng!pXHB~bp?!%Cd&_txrt`}O^W$CJq0q}x6V@!{RnxN#!F0F$=9d5o7 z3N*ZO$_i$My~nOlezCd#{=<+hii8nEMUuzSk-oa#ajpj=dr|r{?@$je%@sSar0XxV4d2Sc&)aQA=99(j{rzD&{coIPRC_cy-|F2GN7t65}7@Ty6urY3I9FlHt$_> zoj74qEag5%KTCvoq$`D5T`u`Whz-r#l65^&Oar(m5@$gTn7)ZWu#@qsctSyb!H#f| z^!vva^@pYF2hN+=`r%0`Ua*q|#A?cm0GOVf7q!6^7?|54;UUEH{Jn@Cn*XFmjo+!? z{I{tUWGH>6@5~*DZ4wMi#%rf;|H|J)PLZ5e2`67}HstyEpq&E;6C&w=cQeHp(}saR zc^Rbamp{gXzEBOhCr%E8Bxf>?S49Ocu5xq8;p*P}pMXd&@cMi`5~5SmjM|^9rB=y5 z8jRAPOA26?*+E?re~jS3#tMQ%z0BPWnO#zBI=zg#vqUfR9c6@;qX7I>z5CVI^PpYz zBrItkD9A-=MLfIMd9l&Fh^&y=)IQ99W)GsTw+2^5r*w&;MMfpkkhBhBkj9RN7G2Rk zyztUEN8t~6%YQ>HlDB@wQxc>gC#ejIj`ljfPpAlZHKEy~O!e_?f^;die7Hl z&6MgNp=XFd*q*SY*;G#*hf^M^R&0SYsAC*wxDL*sxo`#39eu4%ZQo}~nr1@I+%fn< z`-7a;Wu3#PQ3ENYoLMONGx9Tg?j@JH$*z$nwyY*agp<8yy>+S@hzxqZRY|cG&LYv% z{u)<^&;B4)=HGigM@e zkl5&2B|eFw1iKekwSVzza7^@7Dl)P^>{IRg!YJ7t?v=YFgea$E3Dh*A?H3fZ+iuKp$gjTcBT>SF zxj$%hsNIliyIzf*2BW;3gm9381W?O|X*CM!m2DKC`{ZA>i2n$bS9zj}221KUIMJK= zR5u!#Qj-9vGnJe&X2)x?4<>TDP-IHt=Xn&URrFIT54e*^QillA`KI5XSA&+9=r;nv zKw1n_UMl%aIwlymv~ZpPRflVYrNV)zrbz|TO2!HN7i0iY9UD7rr9t7$=_uu~|^aR=nN;Im?e;z4v9Yv1GZSW&_^F8vCWL~^x#*{;&b$@ zL95QNR7f6DV?}e1oTwSZV|jt<3~gGhJG1$Q(?Tv6+u->>r*s5Zfvs7C#Q6b$DaZ#l zTmS=>sMXJY(s^rMMLX*9pz-ebEn%^zGdZtubF6pquQR=M@<;sr!B?4}{1e0zMNeqN zXY7H+axm(Kc8#`G1Zqp)>0oaAP}D3hg`?HHLjritm|)76;@HFmgyX|DGEcDO4a4<; zDy$TaWmF!$0^E*T-Le$Ql3DS1MTmpmcN*nWJMdkIax>zn{hRB+f; z=g~BE%8g(vPi(G(^JoufK_E&=gX#H7(wx+(knlvBHY-rOZ1*}_c^iEkXQjf{F^x)g z(g(CPji%gVuyZ(`cgn9vWGzli)?e}v=L`=&aHr_t@`ymQ(5ih zXST;PJK~wUl6CB4RaIUzlTK#8G+wtg0dJVe8D$aV`v^|fZQvkss%JALyX_@nro4q1 zp4C%$Cj9?kk5~+gU5#LlZS-dh8T$z557`k;kOTLLiEbGJN8+&!i=X6>^pX=}aK1&8 z0c#%Xtd-13N_9eyerNTR*^d1K4Uq$h*y9Us%>ty^MPCk)$vcZXJ}83&F+lCZmw$5x zjY-rjvX*L_eusijzJ_4ir~gdwQn`?qP_;l~&Q0*G$zSBa_gT{vkCJ|w&_;1b=V1WOKu@+plr~eR z^tgpZkDA^7hliQLRtR?ZtH4!(EG67TkeF^<)wYYJwwA-_qaA~06 z436mSji34v&f8tuRj8ehUOpW3?tq?yl|zBKFZXB{{TTCf1fozAkliJ+AqZY3{YrQ_ zhJE}kZc>6;tv=QOI>*NmYzU)?)38EvWJ9`n0~CUg)s@C4@tnrU#@OB&e%aqeJr(+? zFT+Pi^9B>lXtq)cJ@eC%E*K}SjLtWE5()wAY5dQ}Qc5Dzf~Vrl|8~MJHmhcl*Y@{d zN^`?_O#TS*x$tk)`e_=(_)lZK1^==6V8eVeU9GhNoc6nNIWNj&aw4DMv<;^{#(j=Zh`w~Oa!4T> zJ@$UKIPz}gw~_5&9Br(Z*AH(E7eAb0zJi4~GwOEWe0>4*8d4mcnN}I^-n&bNxiwFn%)d!@Oo=ph@18*$~IId%SLMBG!Aub(&|@ zSxNa6Z-!-5RX*Bab5;4nJe_!TLP5L|wPLjz?lv|AMwW5^3lVNya%yBQ?48`m%Ewqr z!%|H7#a1wa<;rCyGIYqX%?mis=LjI|__{r%dSp>a*xQFBiBTk=?HD5?(6ySp%46ES z)c~v|ea-?=@CA{k;FCnIl+oN`cGk6a-epuEwb?!Kx`*Rf(dv3_JAFrZNZ-&5@47Y6!*JdyWvD*uTAnGt zWiu)RH+Is2Tu_j&sXd-Ok?O%)MkS&t(4t|a9#{ozS~t~0pnte9N>~w(Q3%>L!8QA79r+Uy5Edwn zrGyjX3QaiF)NK@(d-DTDMX8%l)k93DZYWn?LNS6;i5WT#R;@DwiD!=pl}?FBK7Q&E z1sVteogb_s#rK1?VFj;#`b||m$qxBkWud_sO`eY+>&@odv zj8q)`m~y%LS04m$YN!`Nno0|gDkKGpzDJVWvY!XWUTSugn!19wMC8d+t5}{03t{t_ z(^X6_umqhVTYXTqnh@#IkvxzsTn7{y6R0p&kp>fy+#l?&7tG{T36-e=&P^8T&1_F_ z6ryem7)?ajI^DYH%PgvNFGv?9I1>_EQHvkc^(FnwBdpI-k=+8sNGa08dI}`zq}w?* z*o*XucseEZPxZquVPI@)y^fIJvyD9m2JqRs@2E9yc{_?AXPNIEp^p@+H+l`-3|4Ht++^ z=h+r~u!m^=%5T2_lCL(%z4iu@DI<>{qu%l#=LeEWxK=Y+1(ABo$6aI_5DJNtYP6|8 zv&^vAlJ?UzEf}4F(S_DpUKSxY&7xK}tbJm%4>pHxol0mp4f71WN{9kODio*7{-ldomTkbtK~-TqHpKF}<6_cI{m$N5=Cx^k z&xY{Wr9+V=)8qan<771?m9>;$iJcX~O4D?|>`ffGnITWv>=?5^MfPuc!}Fuxe&J98)@o9)kg)ev?j2p%bhtoC zc}%Km??ry%<%-700sKYiCdAS+fap{kBd?}d=*(;2K533&LK5?}#GI3Wg|?`wb17aQ z3-z<;x$|)Y&vlDc<#no-uf#x^@K7HPPBZXQh{>b^SRW=?Xa?0sZEpWV&~c$X#p4+r z49Kv()~TOT7U0A5|0B#%y_{K7*RHA;FS?*Y%r)rNaQ;su z6OdGe!e0{}fVvhuWwgZfAxk&x=FH2kL=N?s^^o-py_OoQ*--4rx{1bZC`^5>4}z)B z^?{kO(#yF|{}ncJEmS68KIDKgz%B{_%g-X#_(y(6z{%Z;bQC{V)BX+po3LRsBvddT zu-V#UmD-rOyXPr)ORDc z3hn$$39Jsu=c@Qmp{5m_w?P&?hw&3QSJhR&J%<(bg-!OY33eS5(wKb8zBL)HlLVTd z#v7_isoL82juq~_Ho3v1Q`$bDC%4(ZSI^+Yo!531spv|Ucr4ctRW;FjiDwgDa))fi z-^}#?%+lUSlC4~K@?j|}3DVH{pHfzY|JY`4`J=#`Zgwd`hw!Q9d*u@z)q4jSq{FNH z*g1?$UaIHvq8n%G=}{4gyvDP1naQW(%cl|FnAyPEJ)OCwrioxl2J?6_J3W%by9c*P zX!B)WLuB(s!39u*gz5o99r~%&WKB0?7$`?FQt-_qKncWPOIc2E%-gSC6%%edj6N_f z&8>LzXr`)5fvzVNzN)`SBv%4$^4c;2CHp?y6iZe+mD01vib<{|T=l8mY=zkBCjtn> zHWN74LjSV-Y~D58mzksn+=3rjaUBnuI(>gK_HM7^EWWgo73`Ef1H0RCp8rn1dd3ym z>C7uvgcX)HP^2oF2lzivi&FE{-0vrgU&+$l4)&HDQXDv<

AdcT2|tOSN?*?zJf< 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%0AfzB;=ok->Y3I>qZ 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


v6K(T(7NS`TC8H5 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ⅈRKTW2pDoiXoyiMTiW%-WWWk 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 z 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 HrZ@@SK9;4qa?1qm!Df3H;hZw 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%0DH9 z-gP|PD<8tx4UDlFg3yZuDOY2%=yMhhNm^X=Oz=61WSHE?~;l8TkF#3 zxD0)i@Z(5uBD%0}7^x&)D!l)ZT5awVV{Y98WrP zqp*0q92a*KmLEOXP8NnOeV&br9`h96Y{Nc!a4I*4sSoL7-AX#vE(BP1~E?7Ec538FeT54%x;Sp{% z9mT+-33!*K+kvRT=gTS+)t>J)_&kH+{lmvcF>3^e@qleeLxYmg?BhaGvBe*!6 zdwg6Sp2B;ZEf($V%gn^aCMr!PH0IKEImH58;5z5$nz{W7rEP9qhc%sUVk@T8=J)V@ z{lS()`g(Uzp4+}{Zgw$9f-4;`yZCG$v>9gO+w5-Jtl1r0Ji*pK%#?;IJrP;JjN1TQ zLYL$cK3UQlQ6_{gg-dCX{e4k5d$&6;VX9NrXYz)0ssA*b>b#EcB`OJr-^asfIYgte zp(yV)d(ia^yw%juXJc{Du#r^EYbt-2M`yPD)XSbtmFVg9;SN0s=-Ocdc(M}=b-q&b zhSg`#598G7Rv&(!FQP?vhwX^v&b91Ac4b<;31rY6FCJ#;7VDpjHb?xgP=JTivaY?E*Mmw99H+={PaC zJV^*162D+xRd8#^H!yorwDMs&3WA z=5BRLz5sTbcAeS@wk&zfo4m|52oe}3xU#u?c%j)7}2Oq~|8$Tq@OfZsT z1wJu!1?JX#UBuwZ83xw^E_A9#C&_6VHD>YWBtGPWL%6{*6KH&%zpcG15;X9ED6TrJ zxO>f(KXexzaS{vl!I$+zcidm`Kit^eL|eaC{8{}@GO@1T#{HGJSk>k_W&QTI^xKbs zez%p1&~Ndv@>HSU{yF`&vVI*o9=6zosms88CCgc}f0=mss8Q}Ti%!$0wAnseSyyi- zr#tJ$m|g|jO8w>^%;wjT1SQ#1RmVX3hZ@R1kZTza);;e#*x+> zLxUeudl11Pel;vK>ACOLU9_6AMB@@5DzC{F3A2)^9 zy0}58gK?i+lxb=^gWjP>T6{qWgwHD>25yj1V9v4Kd5t3$XTLBs_g;cp8^mL~nmUmG#0OvBf#n+) zUoxe#Y@f9Nz~=G45#@;|_X_iy8L9HEPaXHw#U}E))6g|frkya4ClYI5!7%mgPwOTX zjDJ2@ydKf4o|~(-G%X?y$f>DsgK#6qW9TW!6as>J1iX%bRw|2`yHI(_P8MGZVv4l< zUZ#X%jbb9z4@R6N~JAXt;%wCCh{foMU+V6 z9(}o?^HU;XvX!~NLnb<=DUnP|$A2T<>L?C@wa)K>3V1uCy1Bz3;-Zcc37;C=UZZi5x+o%Vz1q%PYLaFm zy6|K@nBn|YtiMhWHC1LCGjWQQ_90$%BsahB{d6FEZ`Jk;wV6E1f;4Zp2CZI8d@fHx z<67i+SgFQv6){zD>JJvzzt_kjvZ!bZwu|vFLD^1${!Js|8rW{#dY@GpB$*t_3*Qwi z;1Tu8k}bTg&Nv}E1C+eYOrtT0!uW|oOde06qdV2PvPwg^Em(Z(FxMsLZl&^0rP0k> zU=F*f3;N=;6ZY7uF>WP#X?eX}7-Rcrll#caq0|zc@O5EQ1#n?^?I{`!@+qrbla)P8 zQ|L1K4QacYe}T?RXv)VlUm=P59)efk>kOPJ32@a(%@-vtp7y=mJk5XR!9p=$;2r5S zB%5_i*xfSsmw}mSG?IzexhQEg)-xiE0o5fJ?M6yR2(hnIAMy4$dv!pfOVIe0Or2WaW57t)Xr6Wt z?!8~~C`aotOjH#tp6bgdT$f?exIqNN51|zFw7_|3Fp3PcREM!9e zYz*30YCYs1>ir#{ysl;vWwyW{0o%dFb0j#5^yz(wJ|z<#!1OII5l-0*+B!7W53Es` zPG>uhDqbP9MLb(cCQ689IXESfZXn6{M1@>(Xko04(wz&7zvXiq-%Xy=T^-44OkfV( z7G{Ux5ZXN#C4Bsv{RBgUhcbQpCb0O_QD3>vm>h2^GK)K0M~=?L){ClVT%dv-U}}s! z_%jDSMH#n65C+(%~;RskBZQ-=xHMGNK^;E%WhB#lAj68O^255ynJ<}Bv z*)@X>$shg~^A0|AF%deC5nAB`^z75`>)1jEjO$QTASt=lsUf&Wo%{#zLfLCQFSH&g z615I!3%)`+GEBuW*DO*^Lsxw=g=NYpw&=L%L$So(%0s*mf}kP$i!ZWI)M%LjVuX)k zeNjU%oLHl*e>1kH87^@E>!S)hZxYOO=F0+4i7SCqfkA}-gf&4Xf*=J+Mp;+J*PB(v zGh%OEchp>+rTn1`iukg_F(`KkEQ?dD2CXmWU#m(7Fet`Hyc2^Gz4Q!pn z42pXUgJQ)a24yRSna=He5Ldg1Y;feN;7|OB;3k-T<53P}PbM*&#-3=BHI6@@J(0nM zXHT4|G3-fuC%#9f9i4g09eb$gY- z0T{$ax{y%2HM?GQ%J7wQ1!HK|#V)JAAIn-SSf`AicKTwhCY+RtZa$#vWr7fOZz^wc zH!`4RCSq*h|HX7mRcZUb=bIJVKe!=--TQF7y@2= znW?p2cbArq77<;S>6j%+Q&29Ag)<8gOz60Tjbd}fVwc5>-F_0ukE{wxd&sXzczXu# zHW*hNmu(-|rn9YKyNe=kQu7YFR8}jN?3^#QtRmy634hGEq=)fQ22qOD|fJ7#cMhEUBjhidqtM9CIQcV~MW1 ztt3I%$-BruLV`$`6%MbWPw75F?x5W){L4Q*d9dU0s5$Vxi@*@H*J9@2jNOAS#hY>t zw8StXZsS1<#rQz0xW#Lw%5kppI$z+Vr!dEuhc&9bDI6^bFp41rZzxhuMiq42Fq&CC zv5kiYHj_-!{*?TTJKofcquyF4lZK@;k&yPD)-$MIO#K>4Bv)~gRwxqP0HH^}h6H%~ ziCzM1s|CreTP@hoPoNZCj#f*3v|8$;)lwg=milP5AOT+HzVfT(TX(B#10=wuMWlS) z^M|DJ6Quc1<@ZhQNu5@s0Tz#C3>E$Z=;eSiI>+iW=rfmdN~0i93fDLCkx2_>oFw_K z4Uq-frWekewYl)@f1=pL1t+XJGn;?V$~!jGc3`(QWMd7Raq2ovlPG?3w`OT|aKnF# zWz~dfudWWh^Uscj9p9t-KF!<7bQ$Dw_AkEb1c2RAED9T80r9sy12?EJl`WRmSTU%L z5zN1u%ReV;2|J7O&2qlM#N{S^N+BVLT>jxiZ_uu6>bCa6PsgzEk||)euDM~WH2m5# z5m0axQZkuFe5Z_%#dZ{mcS_Zmt!oTFIwsA^#jy-7{w@I`+ZVl|)3W%P zvO*1yq1)0J)LbK z=MAI858+45|E5r~0Py zYqCSA)WPd@ynRN!Hjj<3G)f$0q^O@qv`Xi-MRq@Vl;L!A0zPDo0#}sY?+fs6oRnZu z!1^w`-{mmTwO15)gf!KX`%T9c%98u7gI)WSr6N?jGRx;2f-qKy z{3X*w$|a}cu6CH7)eg<{Twt3f-GcFfAk&!blt%tk@L+;OD1hYR@T?)Yi6w%L7>4hq zN}M0v+k@G6Cs-9h$JcOLVKoVKec;PG-MJ8aH>GcDKJ{B-+M$%d7S^y1lRBu_!Kua; zCEKI^0b5j`c7<^REQY=IBN55-jfrN-%&mi`;)2|hOff%s-oQ>?XY{eg#c+jLhuXcGNL*(Fe}L^RU3rB29s<@ zoelA^fClseab=+W@yOLwFH1C{Rhvd4NB3;Q5HFNyM%W~AoJ}kLWfBHB*??21-$)=E z%aQ5n8592n{PoONPrJo!pz8TFz|DK2?K6C~J+NI>i!mmf$?v1zY9;67@+p@i?Vesd zPuN4H#AIxq3u(bh$<2^I6C?y>a`XO1?8dpMvw_DsEnDw3MF!ix9AkJ4nr&#dERrL2V z(OqOtuy)pl&2N@oi1XV_(C!R`3^S2C)SB~RBXO=?zV;p`uZbATL6!)kB=NxUSdhI!{D|2h*I8*Z`~az!zM>b#&em zMoAOo%5!hctSZM!*{a9MYa$Kh@^4GZMPD(CtonE+_F^(22a`CV6Wm?_p7KhX3J>%z z43&v_E%?qXyV}FfAKxP~J%#&B&-pgT`6sC&==uX}ky2()(Vimr94lIX8ddp+(n?2q zfU57-RZaady=>TCCrrWG8Fw@#Z2AvbKQbW7@3V2JaAC~9I$I^N>%?j5JxMFc z-{?|!QeL9-2j|B`@YVB(Pi+>(U@c7%$ipK+oL&N)^1ufo3Y($Ez+IUyx{fVKD;D4y zO|cMCiM4a&(sOq63P;{vI|$AOQhw_17RdB&Dp(gRCT9is)gg-% zNJC6b;z@nk*ZO&_t9g+6(`E7J_a6gj*a{x@LoTF&FU97hi0XrV16x4H7*agK#TBCQ z1n~)OI9layICw2YGm-6_U6<}uocNu}8{Y`qvoyxEkTqu<<0N`3{aqiiZFoS8(s*HZ zgYoNeiPOYRa_4Htx7{Cn`(z%57Y-&yh6t{#@H8;76p>6k)rna9YEWgCkdZ26yqS11 z@l%aW@+r9s$ik^jN!(;5g0ABXwZg856VpecCyW1zLu5EIDDT2#19?ujBo`G28yR!F z*k+l=36q!`KWkg~+4d_b5r>blv_hWjMEC`my=(q#bB1J>;?KxHOt^eSN>aQ8au@be z-MOMAW$x?GP%L6s4 zM(#Fkj4iPh{_Jc+Si#Z-+Gd_VGo^{!U)R<(i$D8~Vh#&qFUYqp*KV6r4B>i|rb$b% zft0^n%6n|*l>j`p!(bcRRakdh?VuPX@V1PeG19|wWi0uZgU_!^1s7oEP`|hM_i$U_ zcg>`jvino{w{tCfif_=i_~QgY#NEn~GEnmsv_B4(RHxFJ`~i3!ZEkixkEQ~F{O`4h z(K}FJiml}+B|s+sVCCwwrOgsdYOP;|_yD-h3A%3fl{aSLiRWl>HP~2-u<)dh%*8fq zHep+gg%qC(*+Dj zT$xf8bEEcHe$VAbtr8X@T5w!9)`aH`7K+o#6pg%*85Vg_m(!smD8}$>!sc0=YTFnv zRmfH}mDH^W6xu+MLxZdCNWMWgp6?SW7-1H*2lyu1kK76ASvGr&SvpZA8HYM zsZ85AYzDRLJpSHN*Tx8`>@og}&QerGeyo=J)31o*W0+>fvN0w3`wGgQHJOP7xLSr)D{tX@f9?KQ2L zk%t`r%v3c#w{D)6$vt|oMPEy*Lic9zK-R=m5Y#KyIJNP|@?~t}k(nnc`d-v?dA%a7 zH{wic3)E9|M}1RI%&O_xs5^Si8gZ|;2q8U;;$k{lCEU2^hjLob8Q*!0?QJ#Gr;=M- zN%cql?&aCE({|5drC?ukz?Fc5ctkH{oHK3Q1H3Gr0!Yi}&s_N780F)0hs*FMo;}-s zW}j^nHDkD)N6qr9PmyeaxjO(a%r!_c9l*Rd(2RZ9|2I7AUFfSKqAi^KY zvOlD`wJIImWRxR@a~NcIlsYjVL2 zhH~sDtgN|sUDGK|pUT!=ZX$Ns#non6k~|p+J*}#v1!5vNW3I%$praN%gj8ZXkE5fr zCdF;3;ts56*$--Lb#Vfw%Z{JU?<@Wd)&?bgJ7`FF%pb9#sK(J0e~ffKkp9ZkBfSte zGb>9t(Kc>GWxDD(>wv9&E;+F6bq?s;xre!(I}_&C zX9kD5j2l$=&X3C6wP=q%6rZCHK!L)BYNU7qjbF8lVB#X3%{uxEEtHP_mvHo#;>ww; zbJXXYLM?5SQ9tkCm*!vioTT+S^NpZcHKR(@>hO%3qjE;eDs zP{|Q;EJB>fBgqc@>H(Y>6~S_7m|^wbmRkJrKlC5yjkM$kxLu7tEc6*{m;*A9@j&?o;ME(SY$XdL`eKXuyrCDy&z;%HIDhF5^T=Bo< z^F>rfRi&dA!P`Zss(;2;6(=+GKO2s_gr}MOenxe7H0J1N=6u)SekMetV{?{9Q+)wn z+5_wJ7jLcQ=vN>`vaFk#QXSQzkr8pwv5*a0^ZU58FP8E}RFD}do`WZ5q;KGG46E^S zCXzmiktquq3ERyX9A*KAg9XPs&ugH@5c>$LVQhvm9%4E?zrh7zsM89Z5XEXb>l^}@mWW6THq06|=Z(eWJzg(+ZM zGg4TGfE`=1fUbD9#FW}rENCXQ)%kCymm{Q>IiwcA#dLaR!6c_3;>WNtJ4ZLOIC#$z zr?rX>(VpX3vJH5U?$5+t&&4*0F#ty!4|B!k3f*<>@EU}2pp;FR*Q)0#auHU;FcIP= zvWjL&sImMen;Z#a?z3WfBnaYekWvXD(hqS$j?JN)hv$LXD9QFY;gRXK;G8y<&y8Avu_rZ?@seA#@L+%%-IX(WOI1*9eh_08J4@b}9*^d}U;;V%`sdT*VBbjir#hg(n z4?^-blb)D3DY_|fG{zI~WV#vh%9=yWp0OyR@{VN?H=ySEW9hw62iw@WE%5~6Aj&+! z8kK)Uq|JQ9WdS6|eypdXVIU_lc4~$NF_FOxZvFgG))(Bj~Y*M{7Bu*9l2j?+zfim!X3s;Oi3Zm0(=)ti9G6^9q%UX2`YI-PfGj< z)j58IrT^#gBh*kktA==OLC1&TM>30wBpQ4Heq>t~QOP{pu4?j+awDuT6)c5)I1D>- z{6_#IY#8haDQMwFE{UgIv^3ILWE1xV9b?3Z*j9DyzvDty0O;afK9`1n>5EGFX|}H5kV=HsC@Hxydk&! zupKZ7EQR&OZ_pEB)D4JFC(II|JYgCMjB_mw;-|)PnaMwt%|GDNBj)cHHkNL9fU;!& zWhhHpVm$|wXx+iA(iWqB#v3YVUjnU3c2?C{>iPfRrmW1r?$bR(I5!>qwf>-k{w3A) zZS$Jxo9b?%Yob#6Ei_TPIVY{qQ&h?P3{WL|dhFYmKKc3)$wdbbwhr$Z0;_cJ*ZR}@ z1Esj1|J`gj>N7M4O~h*zQr1Y9VT9yS8jd=JH&Vmv9@**edhT^SR%BRubKT4;ytHc_ zu1Uk{oKapfzdD8DkeQkVl!Qi7!7n!8Op**P2KAgm{DPY-KL*S8%yiGWHIx{n&IBD& zDXFJHyL8xqXn!nN`lTTN4Zx9QWZ_U=scI?r+gs^##|EA(;YrXXl9vs= zDhaM+8Bb-mG)I0lnzd}W(u#^c&&tAvh$qR0w_9Vqa~*#y?dB}!;A_6en$LPZX6O=^ z!x}=|<(=ComJ734g1)K3iDn{IIPI%AHIIO)R-aCF0zHP<-oXG$eO)*!;f8VTcQH>@ zGtysRGesj>J9HZdU>A{!cqAlz5kR<;N}&ix&J*I|nibX-E2o*~S_!C&i7@k+awYVX(jQ@l*~ zt~=^z$A*PBX(+N!7PM-!c`hB8(=M3bEU}B47~_$2quJEWJl&Z3o0|m{ z=f{@E;N9};fu*gfhV_WU)+!zoNNyH!8g6|PsHnAE4AWmoJXYuIH2{mT5?J|+RrS8VbpARwoI3bme#)C1d#kcY zm)a-r3Go#=wp{;gs$mU>VqW&*&=K+5+K0AkUUp{zzhGEHg+Y(YSFqg6{6=4c>uoW| z43;_@bj@Wh^FwTk%kYlym(owH55oTgZu%i0GW-Cx=(FQTgaZH~7{X8k3u)gJ9aDx6 zzGMUoGZ|de4QlbIpm5J~>kir`R{s|59~|U1(G$&RaU4yQgNP2m&o?rY!p}Oe$nMH! zHfTVXqA3mlWLmJXskTa@}4xkHW(4QgjomSOV0odK8ZO9DOE3tV3an zK2qShTgegDcOftei{8)<$*&9Azfz^zoV$5ve9-{{e}3N{xvypAGbp%tO(GVAU0gaO zzlsuu&fny>WPPL?K=#ZfX54VK;62Vlvi4AWp?*LB9lsOZQ>Zf}vN?elO@Z6;4LHw=qA0 zsJI!dwKFZNoARW!+tZD1W^)u|6E4(5$%sjt&e)P`SdV*Vmp5y`Z|@kh4@q{me(TMS z*A||HrsdrI!Og3aLDNPO7LVZG=P%|q=uo zONHMc<;2_IFAB6~76=GsXj_4$m!d$O#bPo?TrO3PR`V+)JAESDf+WwlY%$#RLUXv3D;nXH9oMa9l zY&Q)y7v_lBeVK*qW&|&11tn~SW5hsR;=m#Ci8{SF#Jea=)x`k*^GWn(p%D$$PsDo^ zD&68*pSEbLxK%VYJe|$2$w_D~y{|dS{Uypd%Dsv@1{Ifa4?o>AM09(V_^0A^Ru#J_6JAuq z7S#rps7rgor6kW1blN`GsX36mtEn@!NZvgQPiBM0lEKa0O+nL|ruOdEV|ajvPx(pE z@hKWeg=8!jeU5ENtV!jET=zd>rZq02N$pMMA9h<9kbG6{% zSaKO8tSPZGXphk`$r@O{cPsdnj90NQnn#4eVCi3D#L^Tt*(z*GY!AZk&{MNfV+9h1 z+%H0kV?M_UYzni)3D+7Fx??>GF=%v|SdW$^OYjJm;PYC7pJE9DU*Pbr*PplaVg0Sc zB%>+6JCX-wW3Q35lPb@T*56eX>o16($g61;i_a<3E~se==hhK(j7(gL#T@+{U=lp%;V7tkj#H#?Zt(q8>3b!Yaq;5B&gTl+nmali?O- z{)9{h!5&CS{br&Sb5h=vi3D*SVXZ7a^Z4g0|oXj9(j-v5nOH*r_uIc6@ zEJtG8#t~vDE9-QrS}-U=ZeY=BCG(fm17}$d$C!{Pbc;E0b4syet~ndXMZ%O_1qr(N z23-IGdj@e_#vfjIfj_N$1jtdYGd{cc6fWcvWfA+|s|$&gW)fju2CEUBAV8K&@#o?ISM`f(8zny!zy|)PZ699F4Xp6QVyAx4lBfVk1i}aarNOiKkB-b8wG%F9 z;IkEe8vdZxv_`;@;~Xtv&gC^t`JG7uWG3DU+RswgMa*+8FL2Cy zRrGZp#Qb2eqyWNnTyj&xcB9DRZ8I&PIGCxdDLG^SIma778r99kddXBkpjB*MeZKUj zhPBufh`fLdgE5*O5$V$T=J5D%J)3ACJ?`e2qsI|G%*I~GNgFp;GFGF;BKOqT1TMy6 zZl`d`G=0}(XwlJXN15Nx?q&7xu1uKCaOHdzeJ}sH=ug4lPhq~Opx~WjlKCf+eNUtk zP7WKi*Q13?cg}U}QSgfw({yg$qBj8OdBnstuaJhv60ZkK^8mqiL$+l@!vh#7!wxuZ z%3!)JQ?|S@&>|x*aX3(u6UXF~nBGCvI$C2^bMzQ5wTP`bJQx{(aUfF=s&}U`_34(p z4SOUv2u1OY5y4*icp>!z!t2svM8L#sf@Y4?A6Zbufr}tXwa4m@8B_qk+Vg9Q@572R zdn(j68D6KXIV%{oRM2ebgf+e@;NSEKyN5<)0LHi`z^caU^TMl&QWHM*wYV#7CgQdU4j7SVnvhN}M zwu2>-eFy~!u{7n2a6xHw-x_(cZ!HEtHPC!Jzk4a-`pmQ6yUV*coVV@>gQGA9@x$)}pa&shd%F(au4OzWN7 zYp&&Se+ncu^+&{8s2?bKcYjK!KvbD*SvwKO`f~a0UcU=dNl*~Z-Gvj{FbM^iVf9)* z(Cf71{!p9Qi1L7>s*AWBNiG^`+_%UgNf_6Pq~-6_9Bd9pX~!32VhHVc} zh7m(FHlpc;#P#%n4U&JlOqIctLL4Jf4T@7_jL+=4da!{V^f}gUr(f#N*utfJF0A3v zR6jn4Z)->BG*kR5{4$%uD=T3rw6~sWaxKsL5#_?OJ}Ss=RplOV?pQJGQxPAItJSiz zOFW~Ys{Cr4P%Lvs;l70)o+m7#Py{&RPc&W?2iDVgr@7jsTY#)dHL1AG?6p`$yOX`v zl~975e1!~DPrU=VSW10r;G|~bj+{}YN{!Wa&7;t9v_KUJK85?Pv;M(pMcr}WHDH^> zTwMSct4kHV(8roWo3-0i)8nO@WINNQ_k1RJQdhr8@HJ}er5auO0JB^1T_d53&6avH zMt`P6oR>tfSJPTlKfqQKj=$96^-E5lkI}HyS(Wh7RhVYAU0%5GtSYMpw1D2{M#8-O zZj##r23bu`X#%Nr1@|^d(Zbcu1e-B2|9%=vBXj__8H?u0CZ;g?+Gq+QIIBXzlupG* zQ=xu8??!(}bppmLYS4<`>b|J}_UGYl+-Nnx(YErxWcECa?y*lQnf&@ z6q)YOhs)?gsbV!o)lvI2RM>fq8=8O}4MpJ7lomId=~X+I81in5Hl!blb%+-BB}OPS z>VPrPlTT_FwehLiSF>(xg|E`2nzANV0jxms196EsgXUt83tG@iD*rx}_ieEO_y&CI z2-}=0B*b#kDn3wnpC5}={6(;Nj`-N{2dYox+gAjvRKiyzL7plLt52aVqawZ~afpIg zVf8m1j8sRt+vM*yoWJ3P|^8N*E=g2Bl^8W37i!49NV%6ZRVocs2rzjV$PsF5lx$IO+VoQUz?)yKvNZCK4{!ICUisbDHmD z=f?|QeMW+}Wd5Gk3pF~`&^e~#@dZ~WJ4d7PyKyiNIv!ueU$g;h6H$J!Wa5Y*Jc6f{ z3BppP^G`n!U;Z)LKZ^DX)z;Yj@BeA}!K9yIy4Ldp&Aay#R8U0)|NqSocC_>nj|c6a zMOG8JTkw>;uAgl!>1*rrm3upMLwdqK#dB170C@Tu@8XMc#HiXh&tk^AMV{nw^@ zFF}NB;iOT#mq*A)6Wf#yY!~7fgx(gm;&s~>mI-B7;jOQ04bQHdwW!yMG$Nk=;m2tN zRA`lgTPLbBW3>jfV%QOLD4_Z#!23OCmU*(b&-0$(T#aN11#z0kj9UpBl7iPE$9M9PsbR zv|NTdF<4p)Pzmk5t@VRgEmn?KsbGW){FvWEwaL!Q_Jw4WG(HSw&33Gasc=f!!(*iu1!odpj=TQXH1#=aVs^-)qLxfCdL@jFGPVfc7GC`HT#IDu)P z79VQ8MyEkJ&Jy^%i>zWzohJiUOsQqdgnXagZs$KK-zn@o?iJzT(R^^Fqm zI;oh?1S58Y$#Q27YJI1qVlETRDp%T)iv78nV9tvhohh@y#P$$Col)$}rvRk|!%;>b zj8d_^!=@1%U5kRV7J$5SQnBrfL?JkDmeTJ-IKaaaz~70gO_`u`oWnw<`lcu(toIV= z7os`KInC!TpO`~LCaTN7p30M>D54t83hL4I zAmhw(GDj*XeW8#L*|HJ`S|^G8%@YmvZNpY1@XPH*X z%SPuU-UzztAyf@-MD#k-@~|Tg@Rvr{!m=V%7*vylu@q7Wy8aoJpJrDJ z$3zHyPbv?YW3^Wm%zCA*w zt*6L<8Mi!<8s3QJl(LUa-&#q0PEkP|r=kpGmssUiBZ%H&ZAVoKIsZX_WUFm9|0qbC z<-CGv@;wp3+>d@^*Wa-J_(~r^8i|T8^rW5V#Aw-9fRS+GB6f3VE(b0hW z5gl(NE@65F(P`5>EDqT)>Xt{=C8Fad4*GE$#nhn#K-r1)T{ZTNy`&4C=%`Ajy&M(J zedHehKS@8fSWx|oryn~dN^4YRQ@TbK-U2T3p!J5#vD63NpTGAyxpNcq59s* ziF<=3&j5$SgRKqNg*js5&QIxZ>cR$~V9AfFkVfbPL#t%$;p`-A3ZhNR zK+Rf4W>RXkkybmW?KeG#%T^`5R_PnV#+>%V?#skxS) z9CGDnQ{JB|r4wKLPq7jnCkXOi)yt}IePsk#WQcp6Hc#bF*GQ~WoFQH6Dg0!I2#8vBsqnL8GkaVatnzwc^FPJ_&zr@MLk3IohiGanRSo)u4 zbsupGM5SK{@IQP<=Vfman}m~Qm(rUNoG0k|ITxAyTdqL{F;6tg=QX>O<_X?oB544@ zP@7MNibuJ%+~`l^5md01!+r?{0Qd+VM_>fHM{(;_?f_CC9m~)s*r`^;w+s-Dfo=4u z@OOVDNbK^E=vfIQE_+iP2}}BPThiqq!~pv&t!VXMdTfrI!vw#luVQ)eEWb7a8m?kb z0L*mDdX)zP5=GC$(pCf@|Aq&HGh%THhyEGN&Y>Tv2qv-xw2?c4%c{xjT-qO zEsLq*a)yuP8lb#1PLGhcS3pM3Fp@sT_>L)+3&hr(1C=e62r_@msLGJ}x1Yv1sXMu* z>wYPF+4p#5$;p_(Qi~W2%%VqKG;7P-`on`O?EyoI24mw;yl~%XjU(m1ax;jW+5QF0kpWn8stNh-qAagr4u#w4SQ8cG@l)fFYMM zqG0O1ta(Ra$87M#+QG$xAkVV?E0cf4!AbZ+M@=V*NsVJ_EOd)4zt8+c_`-=DaZVc- zFNq|=;g{A4c9G1%pI5``ll0hO5Ck42vS})6%dlni#*W zkeo0&n;F1xl&t~j0qLuVVdeS|dNau_x#_4zO`VL&ji8}o1nOlp23E)i)f4qs2%`eq85Y&j zQlF9y+sdoV!%+yfJOqPZ;kzxB*l_I%hYfFm0P66u#0Z{Zhp(W{zDFeh^baG!IPY}g z$c7#%gM`^ChHPNf)yYP5kEa^N;AR4LqtlF3O56yp_H#td0`?d+x-CtZ<{*$+eQb6e9~&629HEt``H+Iog{UW z)wBACrG=fKB2!CFQYl@Y0ayC86||rkR*RiuidVS6vTjzzqW*bV z)Lusqfu5iq7cqDrC;XBWLw=Zw%TNwxEFBqask7lbd=|BTf5B=gOFw*{qAY5AsIXsV zH<-w7svVfxZI8>ww$ib;^hU;n*Z>lR3hq%6(4USvBa=bm4Zw@Si(6f0eYmFh0|y@m zH)HF>U@w%K{dkR}3ASGpcbP+(?65!S43YM&_SaWKnaHlRGG1 zTtvU|xu z|3CFX`X*H&frH#ia>VmRH8h4xQlI7W_mKL`t9?uj2L(JK)iA(3~ck!mgWrMD3>KQ6WKko=KwXW5Bfu!nM!EE1GMW3f4Q_@&>NEt@2 z`Z;m9d>%FQO#XSS9!!(R?+tD!^2D@G9iOu^=Mr<2>F7@P@PZMxYxk- zI4gbyFR#$?6(6*FzVs&iYwaHC;K5ah>jo8n$$h%>?60Wte4?n&g^O*z!pmwjolR$K z(A3z{y=ocu{NE|r^Oq)IwWeegLyG1|4}y-rQSFu~=;g%v>+UXoiH=yz?z4E|HdR0U z?V{at%*~1+3l#h5p*aWXH~%nxR=LQTw!fP5fmA1crlamS4oDogPLOELAX_7Q;Jl|Hv)%SW_OjjZ`bTl2IaFloKR^Wajdx!7t?q?SLhhINnQV$d#%Egul5-zj%T zZLwC5D4s}n-TviRb{ajgoHt_gtqEXw1P{42cVO2@IDC-0Z2SU$#uhgJd>tE14McSZ zzi47FoYLK~C7Hil4F&C|&{FYxtg9%#23wWQEN@spHcf1_pT%}=_aiZHC^syzrh-Sr`g(pQ1CfM&?ktIQUWJ$0jaw@#3 zZXQL<{-DiWz!kWQ+budguSkXGo{)-w3r)im(6f&huPBiKvUiMR1r_n)C-U5_*>b#i zMYb!%)@sEnUi=SgTx}L;a*$D*yY10kb^5yOVjeXaEV+T_oot<;<3n|P{Lb;>IfxIx zfgViW3=n5K9gw*Z)ir(RPooRVZ`sB2hv>f-=p?QeRYS4&&D4oA2 zlEx5k24iy>f4`u}@mdqjbg9WWto5{}kn^MIk_4ZGoWB+{Dq0Hevyk(1r3L9}0-DTj zexK?fp1Ec(Y&S=6!VsMOjnQtQFR&;#j@304vU+hFUkW^J_IszhN65r3i%V=Iu~qCv z*u%SFek|go2kf`o#u`AY>#3d)Jlb9~Ol2}?56`~u7@h2}?}xOI%CX(%+H4CIWmB6u z%}Hde`U(orlEIe1_NK!3=($az_!{)e`?wO=tdBNheY6>=$2Q})?%qn# zei&Tw87pQK=HYVs;ZJM6bN#1TO0X!*zIB}w+8vq*`9mR7C|n2d2(y1-SoJ|4W}gtI zVt<`pR#)#7X8$KuevyhtCd~f#bRWfJwJ`f}o@l#m9f{tCLfvvL5%Rhk3?bi z8$`+TE*(!Q|7s@x8XWFJDw=l*kI2&CBkR9uvqzNk%ET7-nTE_>|(0}!JhY6-B{&7EV zn0172I!lPaVO!ZpVum2|ZnyWZ0XZYh;ZYO56+ZU7N*o!XKWfA^HK-k2iq=s}(CuJp z1|XzcoN2#BxRrhAjX+Uh_NTZo`}4|S_74mfe2`8^;u+O_VH9Q`b8zT@d^z^`5LwRR zJm~l~HeuF9VN3$>54kg!)4_9Gvcik@4!}+43&+XS^iGeG2o1}ViTrP_ zq0gEgLd917*4$(B$A7>0Y4|jGgHDmCp%lPBt?6ALhHGE|e=V894=-iaxBRIA{4HPW z>Y`%i2;T@_iYX9nZk-x|$E5GYJK*z?F{zt6XZ!g6&7303@AA&Jv3}#sRX>}5cxII!v5I=JR)Ik4U4$>U@oUe`2^(5?(+%!=X*sSES~`0?P&W~ z+5?wQ;1cbdcgiOK{lcv;XZZvK)xqLxET2FRSGDFVBImDoDdMvp;{wkn>1njpCXfg# zb;g7Ci@^@b#3MoYJy`No15tt;F7cpO)bA+{3vlH&A_CwH*{btIf7`)O71*&vhxuAG zO2l_;Cf{8+JBN_o$-dy@uB450i{sb&AuW}kCsb6NXBfcs4*;D#V|c{erdwc=)+!=J zC7K~QfI}(p!BNp!Jb@ePYVwU^3oD|5ReDSVim0a__h&Hyb~#jsY4I>!!M z!>l~5tLVHWY?W(y&gBgtE?)2p^9!d`8>O75h(*I-;s7*bGU$kPl}4*MO|U&^Ev%n& zwPiz-HDJkWG!9Qp)_`m5s+=|8OWcbKGNtT1VfF=(1<*z`y+PM=_}<$K0a@KpupWX} zGlR50RtW~0OAN4_pJLciZ*rr1si^@xjuzJ^5-9L_CY(EbQ1I;uPz1iOt{LXoZ{#&a z3GHmg!#i!SD)8u7dgyrMhz(X`rHMQ(bI9_EfT#ZEQK|~>3Z{%`^fuIK)j!~=Juv*< zaG__9VWyFWxwRoyTg5GYq%d@7lK%d2TpCr_8Snjq$p@mn5#du$ zAENwF5x^s8m#1Rk2Pzk)YuK;Nh(lLnjyuPeHI@J9@|4(gQT0%gq+%DsQkxxk-H-$w2;amk~Xz5Lp?Zft{=Y4DF+dJhU zxU1T&JC+A|2!5`+i08FD1k$gHYp#CgJ&x%m>X>7C#kqrOrgv*E>o^xIp2w-8G82Iq zUI>P0R$pt27N=V}BgZRLeA!u%xnwlabpAI+i|jHYkDN6$N=Gn7h$&4}Oo3d(dgpWm z#(!y-61!Gurtk$!6XSeCw8PLb?<-C~gJUSD5 zAeGn_EZxY77*4U7j0LI+vnGre1T8HG1;o-*1?T%h4d>Hv*n9P^jc0NOox*O0jwKfr zEN?+2*Snn}7ORC0t1l{^Hp-QaJ?;I)hij=s{O`NZC-ou6xW%5=`jmqlvkK)B>qEVj zi3^aVi)IDso}`f|_RV`lw@MkMf~7l|1Zl0)Vlp&#L+n;Jn zCyq8=r!mP}pZMxBN1i056RtH(s~V*l**t~Hk_Cs$ydgO|v*;MpJJ)81urh4%3*XcK{T z+-Z0sqD^)VJQfxk3RnCY?0M<@A>6vUm@b_U{3L)~1{H4-b@9NhcrImA8}Aibd&w9WR%C9^zC^huL6C^Wbz#j!OUA{@j9_di_Iv99seMzSb`woVW~=67eovLhnzGTAPu?%8A8#e(G=cFR`SnpNQy)o!hVOK zH!%iI`bnFExzzqBj`sX?n?4bn9vwN0T^ItAUkjFB1Uu?S3CPZHLr%mTgghL$@kam; z?F@O&>P52T^Lr4R0wUMfBxrU1^S?~ z0Tj@VZZhPKIsp+JBT8uf;kn|JFZnb9(W3*D@fIffDSiYS0gYMMvol_N1XBmC;brvD z1S)*(1=Jy&Im?g-;94#U?O#)@a=*?I!lhyIloQ1*Ho7xfLT-&W7u(8tK^<3rWw@y$ z2>iZz8M(|TRv|2ON>{i7U-bs9xtBe-Xf20$4N;3rddZ$BbTXu&lNi;trAVKo9W>u>eue@ELMxdKD}g z&!T~sR8rFk0E-j&X&dL*#$cFYUELvk7h< z4vWE>TjCTgT4ptDRm^jlD_Y_d(rw*tdSQvv!pWt)DG#Lca!iSTkeD+V8SNz^KkT(* zDfQg)rdaIiKH+vn)55-6$P&10e)&8?W)HC_aEmVx#R zfX#ucnG$d6qkVeWCpRa>AD=;fFCI~&&6>5yiP*BYl)CnkD&0+I`$|=@gk0A#xv&%= zme7Tu=TvDS)ma}{rKlfj^kud8kVg0nBb+ua{T55c`a#PItp2v%$p&fKX&>fYaU5gv z^nn9=%z!#{zd>;*AI9rGp}*NrxX|P%=pG!#Emz7`hWjpZrIg%1 z4ilU_%9U~+xl&k$7mzCjxl=h;N;gdr*{b7Mqg-weK`gbov>$BmF|<343t;%8`G0Xu zaVeZibpFO<+>lomveCwO=}O$?k(eW@h2MR}C0t0uLcHaLfvl0rd<)z1WGWWDg8)Rk zKbuE}6dx@qk3eHPyPFHeC!Rw5H~If)OJ5vTy$4J!GejXm;RHj7*xCrd`csjcA&BRM z%*o6UG)s+k!AC@gc5Nd^`%OQ8LG;O8FI1pqzL2df{_bw@OGMJ@*lf6ytbNL z3svBq_28X|np_ypCB=fFDYwfu=fbA_hJ-Q=o3K7tkSU!#Ab`ryfTSmnFQ?1lF#f>N zj!VenV&bzg_ze$c0O^YJVD%k78-tJ%nDm6LuX_}&Y34JB%-no3*7&j6uxW38D>I{X z3>SwpoCHy?zGOKWG7WUGAh7uTY?w!FGjL@Zif2a{&T}hC2t$r1@wySJ(;fRX8rDSlqnkw*zy=H8Oq+~Dvu*pg(8H6MUq+~EG>Qge%u%(O=X4_1K4tdi* zmy*E}C-{^M9<3?;ky1)ce@3PDYPnk}CIP%x!o>aaGkkSFP!@6qEzD3hR5Dvpg+s?0 z{XXFf^Hen?ZeB^sChoH_oXPi=jUgA-+2Olxq+odbF#Vl7OddY*tk1@P)b-E6cXBJL z$iWbSVy_?=--5ME}{u6SBz!-U9M z!P-d^8kUy-cs_;^hU1k@<(<+)9j`^^@-a-V0mQYJ#xu@5F%vtOMU-y&7sD`&76{vbc}!*>6qi1WQ5WM_>E)pHPqJIthEHg(a_$~A#tchXDoSNwiL zo{SBhBS`Tn=o0GJQ-Wxjr4+6A1JE_pb4c=DFNl{(1Lh9w+&2}T9a9I#B$i~h;5(_5 z=$bQ001*rCij|9m{m62w|Ls+fhnYB!chOdXAt!H@d@MWQihLq}3z%YJ?FJy=I#fBo4f z4<2;N$dkB=m}hwVDj&dQp#2n8%J8Y1U#+=W%u`cm!c?$aW|U6@d)j-GJx!G8uO`go z@5df$68$I~^AGC|=6lp!GhcNe$3#_h2IdZ>R2s9nDcLyvtc5hX9Yow1PPzH(} zBm!jBxG@`^u!MH8T_Z>sQ`t!8Ij)mFn1RjajVz5U)Dku>Gr6}&OPX_aQ#W%8H{am1 zYUI0hc9N+J>)q{P-pk`=9+@>(M@o4x#VLDP9A~O0()k{g2!k%WoV|S80~0?zBYl zNb-hHc9!Qxq*n)R5ih;83E*Bhsc4nB{7A+OWzE=0Q_Z6BVt7owh*axFo@UTjepkT>GEP$xTW?z|+ZzP?I_HATwRoREJg&#a>i5Jv|Gd2JO z0jKy4>bhzf_9Y9i$&kCg>5ON!pU>@_`m;CB?M(gb&D94^JY!SCrt@$Q8kE@7dM=XO z^l||K#pYIwJ3hp`8dTvD=Qy<_EEO_ofmrOKc{LU$O+b6G#KxZ?zC|wa{QR3CNa{i| zkLuas8KnW*<-SB8{ z^|H*OJ+X5;vx^zS)WvVEe*MHVHa2Wb;a2roWqz>kH>_UN%}}E5<3AewLTDdJbQ@j3 zwr6o0=$fDJuE9N*iv1-;4E$fLb)p*X&xWb*SM`nzryg0(mx2-VZ&;Bo zU&>B{iqfU*DAR8@TrdH_lg9qS%cZ+LWaYZE2TUwoNQ;{eew_Oounn*0!v*yKHNB z-LBtNx3(WzaT`EL0DlCnh(FMXiZjF?@fQR{@_D|_eZOZWi2bqq`S0sPGVk|&-=F86 zd(OG%o_h{A511j5F;{({P&@^k2<>+SBgISU@%%ece3!;cffel8YkbPsKq;x`b{A_I zM)28}j*?;S#oYa!cplF*r-{ye|N2A4Owp(Oc{Foq`+H;7(hv@jFPV9?Df0jrtpAcO zepL^TrHg__b1$+Oe(~cC;PJ%mJO{R*{)8uZi90@=qnKIgS8gJaaWpV!6IZJEHBzfT z01{B=wl37l`Wr@d$u=&TFi`A@c6eO}$ZG*pPNDQF)j*&WJfd9_qmyFah1)T$@l~pr z+AzAGaG`n_r-$z}yN~;c<0GBx%Dvk;!gZFku}R*N=O}Df2)ynJ+A+iV7DAr7L{B(v@#K%#frvv`PYX=$IDL=B?2qyssvX2;O@^3&|ND%p1h5TEVf0oDWae3WN zD99hW5%6AeNj5Q%BD1$Ga&m|ZP-ZZjvJro|X=pTf`$TxO+yL2EI;*;4~c_!cGl6R+Qe zK!n)5kXI>NX7d|2NMxs_;TCiCZr4~`2njh|mSI~i_d@}XD+ONH{fLFCUsYyh8BaYo z0tRo%>-NRf5@4SDM4X-_yAf~fPDJ;jdY)YTF{pdj;gsSSFoLz`h`4X>={;$T91xMb zFIgYRga@4I#rDw_+nz^U^Ype7uY`R#nA%u^eJymQr z%Cw_07v4Dd(!Sz+33=0VY%x0q@Pg%ae{VhX$H9o+O02I|mXW7grv0$NKeA_pxC zp4LZyMwNpA@IXs?7&Mu@PqlYRcK$cVINGu6?IVg)Sf`*A z-KwqafZ#0HN{IF^#Q%ZQvdh3jYm=GoQ{^jw-nn0;BMK=pVIB|27aLNUH!Z}7-rd(q8D^*vIQT=_tSi_uSAY z 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 fx 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
|& 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
Ws|lzkj6M%1uo^n}yb5K{T}3BfJc>B@SZ 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

E4NC^YfYB?X_)s#Yey; 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 z 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�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

*(*F%y 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

B&{O5~|c}uB=wLf!pIlmmvC&TINT5!kJ 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

-s-5BjuMCo+vV15bsT#mZ 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

!5+``M%d`0 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

  • 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 /// Computes an approximation of the real value of the log gamma function using the Lanczos Coefficients described in Numerical Recipes (Press et al) @@ -40,16 +61,42 @@ module Gamma = /// The caller is responsible to handle edge cases such as nan, infinity, and -infinity in the input /// /// The function input for approximating ln(Γ(z)) - let _gammaLn z = - let lanczosCoefficients = [76.18009172947146;-86.50532032941677;24.01409824083091;-1.231739572450155;0.1208650973866179e-2;-0.5395239384953e-5] - let rec sumCoefficients acc i coefficients = - match coefficients with - | [] -> acc - | h::t -> sumCoefficients (acc + (h/i)) (i+1.0) t - let gamma = 5.0 - let x = z - 1.0 - let tmp = x + gamma + 0.5 - -(tmp - ((x + 0.5) * log(tmp))) + log(Math.Sqrt( 2.0 * Math.PI ) * sumCoefficients 1.000000000190015 (x + 1.0) lanczosCoefficients) + let inline _gammaLn<'T when 'T :> Numerics.IFloatingPoint<'T> + and Numerics.IExponentialFunctions<'T> + and Numerics.ILogarithmicFunctions<'T> + and Numerics.IRootFunctions<'T> + and Numerics.IPowerFunctions<'T> > (z: 'T) : 'T = + let coeffs = + [| + T 76.18009172947146 + T -86.50532032941677 + T 24.01409824083091 + T -1.231739572450155 + T 0.001208650973866179 + T -0.000005395239384953 + |] + + let pi = 'T.Pi + let x = z - one + let g = T 5.0 + let half = T 0.5 + let xg = x + g + half + + // let sum = + // coeffs + // |> Vector.foldi (fun i acc c -> + // acc + c / (x + T (float (i + 1)))) (T 1.000000000190015) + + // //(x + half) * log xg - xg + log (sqrt ('T.Pi * T<'T> 2.0) * sum) + // (x + half) * log xg - xg + T 0.5 * log (T (2.0 * System.Math.PI)) + log sum + let sum = + coeffs + |> Vector.foldi (fun i acc c -> acc + c / (z + T (float i))) (T 1.000000000190015) + + (x + half) * log xg + - xg + + half * log (T 2.0 * pi) + + log sum /// /// Computes an approximation of the real value of the gamma function using the Lanczos Coefficients described in Numerical Recipes (Press et al) @@ -59,12 +106,18 @@ module Gamma = /// This might be slower than the unchecked version `_gamma` but does not require input sanitation to get expected results for these cases. /// /// The function input for approximating Γ(z) - let gamma z = + let inline gamma<'T when 'T :> Numerics.IFloatingPoint<'T> + and Numerics.IExponentialFunctions<'T> + and Numerics.IRootFunctions<'T> + and Numerics.IPowerFunctions<'T> + and 'T : equality > (z: 'T) : 'T = //TODO: maybe rename in "complete" for consisteny match z with - | z when (infinity.Equals(z)) -> infinity - | z when ((-infinity).Equals(z)) -> nan - | _ -> _gamma z + | z when 'T.IsPositiveInfinity z -> z + | z_ when 'T.IsNegativeInfinity z -> T nan + | z when 'T.IsNaN z -> z + | z -> _gamma z + /// /// Computes an approximation of the real value of the log gamma function using the Lanczos Coefficients described in Numerical Recipes (Press et al) @@ -74,146 +127,193 @@ module Gamma = /// This might be slower than the unchecked version `_gamma` but does not require input sanitation to get expected results for these cases. /// /// The function input for approximating ln(Γ(z)) - let gammaLn z = + let inline gammaLn<'T when 'T :> Numerics.IFloatingPoint<'T> + and Numerics.IExponentialFunctions<'T> + and Numerics.ILogarithmicFunctions<'T> + and Numerics.IRootFunctions<'T> + and Numerics.IPowerFunctions<'T> + and 'T : equality > (z: 'T) : 'T = + match z with - | z when (infinity.Equals(z)) -> infinity - | z when ((-infinity).Equals(z)) -> nan - | _ -> _gammaLn z + | z when 'T.IsPositiveInfinity z -> z + | z when 'T.IsNegativeInfinity z -> T<'T> System.Double.NaN + | z when 'T.IsNaN z -> z + | z -> _gammaLn z let private FPMIN = 1.0e-30 //(System.Double.MinValue + System.Double.Epsilon) let private EPS = 3.0e-8 //System.Double.Epsilon - let private gser a x = - let gln = gammaLn a - let rec loop sum del ap = - let ap' = ap + 1. + let inline gser<'T when 'T :> Numerics.INumber<'T> + and Numerics.IFloatingPoint<'T> + and Numerics.IExponentialFunctions<'T> + and Numerics.ILogarithmicFunctions<'T> + and Numerics.IRootFunctions<'T> + and Numerics.IPowerFunctions<'T> + and 'T : comparison > (a: 'T) (x: 'T) : 'T = + + // Relative precision threshold used in convergence tests + let EPS = T<'T> 3.0e-8 + + let gln = _gammaLn a + let rec loop sum (del: 'T) (ap: 'T) = + let ap':'T = ap + 'T.One let del' = del * x / ap' - if (abs del < (abs sum) * EPS) then - sum * exp(-x + a * log(x) - gln) - else - loop (sum+del') (del') (ap') - - loop (1. / a) (1. / a) a + if abs del < abs sum * EPS then + sum * exp (-x + a * log x - gln) + else + loop (sum + del') del' ap' + + loop (T<'T> 1.0 / a) (T<'T> 1.0 / a) a // Page 286 // Returns the incomplete gamma function Q(a,x) evaluated by its continued fraction representation. Also sets ln // .a/ as gln. User should not call directly. - let private gcf a x = - - // let eps = 3.0e-7//System.Double.Epsilon - let gln = gammaLn a - let b = x + 1.0 - a - let c = 1. / FPMIN - let d = 1. / b - let h = d - - let rec loop i b c d h = + let inline gcf<'T when 'T :> Numerics.INumber<'T> + and Numerics.IFloatingPoint<'T> + and Numerics.IExponentialFunctions<'T> + and Numerics.ILogarithmicFunctions<'T> + and Numerics.IRootFunctions<'T> + and Numerics.IPowerFunctions<'T> + and 'T : comparison > (a: 'T) (x: 'T) : 'T = + + // Smallest positive number to avoid division underflow in continued fractions + let FPMIN = T<'T> 1.0e-30 + // Relative precision threshold used in convergence tests + let EPS = T<'T> 3.0e-8 + + let gln = _gammaLn a + let one = 'T.One + let b0 = x + one - a + let c0 = one / FPMIN + let d0 = one / b0 + let h0 = d0 + + let rec loop (i: 'T) (b: 'T) (c: 'T) (d: 'T) (h: 'T) = let an = -i * (i - a) - let b = b + 2. - let d = + let b = b + T<'T> 2.0 + let d = let tmp = an * d + b if abs tmp < FPMIN then FPMIN else tmp - let c = + let c = let tmp = b + an / c if abs tmp < FPMIN then FPMIN else tmp - let d = 1. / d + let d = one / d let del = d * c let h = h * del - if (abs (del - 1.) <= EPS) then - exp(-x + a * log(x) - gln) * h + if abs (del - one) <= EPS then + exp (-x + a * log x - gln) * h else - loop (i+1.) b c d h - - loop (1.) b c d h + loop (i + one) b c d h + + loop one b0 c0 d0 h0 // Incomplete gamma by quadrature. Returns P(a,x) or Q(a,x), when psig is 1 or 0, respectively. // User should not call directly. - let private gammpapprox a x (psig:bool) = + let inline gammpapprox<'T when 'T :> Numerics.IFloatingPoint<'T> + and Numerics.IExponentialFunctions<'T> + and Numerics.ILogarithmicFunctions<'T> + and Numerics.IRootFunctions<'T> + and Numerics.IPowerFunctions<'T> + and 'T : comparison > (a: 'T) (x: 'T) (psig:bool) : 'T = // Abscissas for Gauss-Legendre quadrature - let gaussLegQuadY = - [| - 0.0021695375159141994; 0.011413521097787704; 0.027972308950302116; 0.051727015600492421; 0.082502225484340941; 0.12007019910960293; - 0.16415283300752470; 0.21442376986779355; 0.27051082840644336; 0.33199876341447887; 0.39843234186401943; 0.46931971407375483; - 0.54413605556657973; 0.62232745288031077; 0.70331500465597174; 0.78649910768313447; 0.87126389619061517; 0.95698180152629142; - |] - // Weights for Gauss-Legendre quadrature - let gaussLegQuadWeights = - [| - 0.0055657196642445571; 0.012915947284065419; 0.020181515297735382; 0.027298621498568734; 0.034213810770299537; 0.040875750923643261; - 0.047235083490265582; 0.053244713977759692; 0.058860144245324798; 0.064039797355015485; 0.068745323835736408; 0.072941885005653087; - 0.076598410645870640; 0.079687828912071670; 0.082187266704339706; 0.084078218979661945; 0.085346685739338721; 0.085983275670394821; - |] - - let ngau = gaussLegQuadWeights.Length //18 + let gaussLegQuadY = [| + 0.0021695375159141994; 0.011413521097787704; 0.027972308950302116; + 0.051727015600492421; 0.082502225484340941; 0.12007019910960293; + 0.16415283300752470; 0.21442376986779355; 0.27051082840644336; + 0.33199876341447887; 0.39843234186401943; 0.46931971407375483; + 0.54413605556657973; 0.62232745288031077; 0.70331500465597174; + 0.78649910768313447; 0.87126389619061517; 0.95698180152629142 |] - let a1 = a - 1.0 + // Weights for Gauss-Legendre quadrature + let gaussLegQuadWeights = [| + 0.0055657196642445571; 0.012915947284065419; 0.020181515297735382; + 0.027298621498568734; 0.034213810770299537; 0.040875750923643261; + 0.047235083490265582; 0.053244713977759692; 0.058860144245324798; + 0.064039797355015485; 0.068745323835736408; 0.072941885005653087; + 0.076598410645870640; 0.079687828912071670; 0.082187266704339706; + 0.084078218979661945; 0.085346685739338721; 0.085983275670394821 |] + + let ngau = gaussLegQuadWeights.Length + let a1 = a - 'T.One let lna1 = log a1 let sqrta1 = sqrt a1 - let gln = gammaLn a + let gln = _gammaLn a + let xu = - if (x > a1) then - max (a1 + 11.5*sqrta1) (x + 6.0*sqrta1) - else - max 0. ( min (a1 - 7.5*sqrta1) (x - 5.0*sqrta1)) + if x > a1 then + max (a1 + T<'T> 11.5 * sqrta1) (x + T<'T> 6.0 * sqrta1) + else + max 'T.Zero (min (a1 - T<'T> 7.5 * sqrta1) (x - T<'T> 5.0 * sqrta1)) - let rec gaussLegendre j sum = + let rec gaussLegendre j (sum: 'T) = if j < ngau then - let t = x + (xu - x) * gaussLegQuadY.[j] - let sum' = sum + gaussLegQuadWeights.[j] * exp(-(t - a1) + a1 * (log(t) - lna1)) - gaussLegendre (j+1) sum' + let t: 'T = x + (xu - x) * T<'T> gaussLegQuadY.[j] + let w: 'T = T<'T> gaussLegQuadWeights.[j] + let f: 'T = exp (-(t - a1) + a1 * (log t - lna1)) + gaussLegendre (j + 1) (sum + w * f) else - let ans = sum * (xu - x) * exp(a1 * (lna1 - 1.) - gln) - if psig then - if (ans > 0.0) then 1.0 - ans else -ans + let ans = sum * (xu - x) * exp (a1 * (lna1 - 'T.One) - gln) + if psig then + if ans > 'T.Zero then 'T.One - ans else -ans else - if (ans>=0.0) then ans else 1.0 + ans + if ans >= 'T.Zero then ans else 'T.One + ans - gaussLegendre 0 0.0 + gaussLegendre 0 'T.Zero /// Returns the incomplete gamma function P(a,X) (regularized gamma) // gammp -> GammaLowerIncomplete - let lowerIncompleteRegularized a x = - let ASWITCH=100. - //if (x < 0.0 || a <= 0.0) then failwith ("bad args in gammp") + let inline lowerIncompleteRegularized<'T when 'T :> Numerics.IFloatingPoint<'T> + and Numerics.IExponentialFunctions<'T> + and Numerics.ILogarithmicFunctions<'T> + and Numerics.IRootFunctions<'T> + and Numerics.IPowerFunctions<'T> + and 'T : comparison > (a: 'T) (x: 'T) : 'T = + + let ASWITCH = T<'T> 100.0 match x with - | x when x = 0. -> 0. - | x when (x < 0.0 || a <= 0.0) -> nan - | x when (Ops.isPosInf x) -> 1. - | _ -> - if (x= 0.0) then 0.0 - elif (a >= ASWITCH) then + | _ when x = 'T.Zero -> 'T.Zero + | _ when x < 'T.Zero || a <= 'T.Zero -> T nan + | _ when 'T.IsPositiveInfinity x -> 'T.One + | _ -> + if a >= ASWITCH then gammpapprox a x true - - elif (x < a+1.0) then gser a x - else 1.0 - gcf a x + elif x < a + 'T.One then + gser a x + else + 'T.One - gcf a x /// Returns the incomplete gamma function Q(a,X) = 1 - P(a,X) (regularized gamma) // gammq -> GammaUpperIncomplete - let upperIncompleteRegularized a x = - let ASWITCH=100. - //if (x < 0.0 || a <= 0.0) then failwith ("bad args in gammp") + let inline upperIncompleteRegularized<'T when 'T :> Numerics.IFloatingPoint<'T> + and Numerics.IExponentialFunctions<'T> + and Numerics.ILogarithmicFunctions<'T> + and Numerics.IRootFunctions<'T> + and Numerics.IPowerFunctions<'T> + and 'T : comparison > (a: 'T) ( x: 'T) : 'T = + + let ASWITCH = T<'T> 100.0 match x with - | x when x = 0. -> 1. - | x when (x < 0.0 || a <= 0.0) -> nan - | x when (Ops.isPosInf x) -> 0. - | _ -> - if (x= 0.0) then 1.0 - elif (a >= ASWITCH) then - 1.0 - gammpapprox a x true - - elif (x < a+1.0) then 1.0 - gser a x - else gcf a x + | _ when x = 'T.Zero -> 'T.One + | _ when x < 'T.Zero || a <= 'T.Zero -> T nan + | _ when 'T.IsPositiveInfinity x -> 'T.Zero + | _ -> + if a >= ASWITCH then + 'T.One - gammpapprox a x true + elif x < a + 'T.One then + 'T.One - gser a x + else + gcf a x /// Returns the lower incomplete gamma function
    gamma(a,x) = int(exp(-t)t^(a-1),t=0..x) for real a > 0, x > 0.
    /// @@ -224,8 +324,14 @@ module Gamma = /// /// /// - let lowerIncomplete a x = - (lowerIncompleteRegularized a x) * gamma(a) + let inline lowerIncomplete<'T when 'T :> Numerics.IFloatingPoint<'T> + and Numerics.IExponentialFunctions<'T> + and Numerics.ILogarithmicFunctions<'T> + and Numerics.IRootFunctions<'T> + and Numerics.IPowerFunctions<'T> + and 'T : comparison > (a: 'T) (x: 'T) : 'T = + + (lowerIncompleteRegularized a x) * (exp (_gammaLn a)) /// Returns the upper incomplete gamma function
    Gamma(a,x) = int(exp(-t)t^(a-1),t=0..x) for real a > 0, x > 0.
    /// @@ -236,80 +342,121 @@ module Gamma = /// /// /// - let upperIncomplete a x = - (upperIncompleteRegularized a x) * gamma(a) + let inline upperIncomplete<'T when 'T :> Numerics.IFloatingPoint<'T> + and Numerics.IExponentialFunctions<'T> + and Numerics.ILogarithmicFunctions<'T> + and Numerics.IRootFunctions<'T> + and Numerics.IPowerFunctions<'T> + and 'T : comparison > (a: 'T) (x: 'T) : 'T = + + (upperIncompleteRegularized a x) * (exp (_gammaLn a)) /// - /// Digamma function. + /// Optimized digamma function for x > 1. Skips reflection and tan-based correction. + /// Use when x is guaranteed to be greater than 1. /// - let rec digamma (x:float) = - match x with - | x when (x = 0.) -> - Double.NegativeInfinity - | x when (x < 0.) -> - digamma(1. - x) + Math.PI / Math.Tan(-Math.PI * x) - | _ -> - let nz = - - let q = x - let p = floor q + /// The input value (must be > 1). + /// The value of the digamma function ψ(x). + let inline digammaPositive<'T when 'T :> Numerics.INumber<'T> + and Numerics.IFloatingPoint<'T> + and Numerics.IExponentialFunctions<'T> + and Numerics.ILogarithmicFunctions<'T> + and Numerics.IRootFunctions<'T> + and Numerics.IPowerFunctions<'T> + and 'T : comparison > (x: 'T) : 'T = + + let pi = 'T.Pi + let half = T<'T> 0.5 + let one = 'T.One + let zero = 'T.Zero + let ln = log<'T> + + let polyCoeffs = + [| + T 8.33333333333333333333E-2 + T -2.10927960927960927961E-2 + T 7.57575757575757575758E-3 + T -4.16666666666666666667E-3 + T 3.96825396825396825397E-3 + T -8.33333333333333333333E-3 + T 8.33333333333333333333E-2 + |] - if (p = q) then - raise (OverflowException("Function computation resulted in arithmetic overflow.")) + let ten = T<'T> 10.0 + let limit = T<'T> 1.0e17 - let nz = q - p - if (nz <> 0.5) then - if (nz > 0.5) then - let p = p + 1.0 - Math.PI / Math.Tan(System.Math.PI * (q - p)) - else - Math.PI / Math.Tan(System.Math.PI * nz) - else - 0.0 + let mutable s = x + let mutable w = zero - let x' = - if x <= 0 then - 1.0 - x - else - x + while s < ten do + w <- w + one / s + s <- s + one - let y = + if s < limit then + let z = one / (s * s) + let polv:'T = polyCoeffs |> Array.fold (fun acc c -> acc * z + c) zero + ln s - half / s - z * polv - w + else + ln s - half / s - w - if (x' <= 10.0 && x' = floor x') then - let n = floor x' - [1. .. (n-1.)] - |> Seq.fold (fun w y -> y + 1.0 / w) 0. - |> fun y -> y - 0.57721566490153286061 - else + /// + /// Full digamma function ψ(x), + /// + let inline digamma<'T when 'T :> Numerics.INumber<'T> + and Numerics.IFloatingPoint<'T> + and Numerics.IExponentialFunctions<'T> + and Numerics.ILogarithmicFunctions<'T> + and Numerics.IRootFunctions<'T> + and Numerics.IPowerFunctions<'T> + and Numerics.ITrigonometricFunctions<'T> + and 'T : comparison > (x: 'T) : 'T = + + let one = 'T.One + let zero = 'T.Zero + let half = T<'T> 0.5 + let ten = T<'T> 10.0 + let limit = T<'T> 1e17 + let pi = 'T.Pi + + let polyCoeffs = + [| + T 8.33333333333333333333E-2 + T -2.10927960927960927961E-2 + T 7.57575757575757575758E-3 + T -4.16666666666666666667E-3 + T 3.96825396825396825397E-3 + T -8.33333333333333333333E-3 + T 8.33333333333333333333E-2 + |] - let rec loop s w = - if (s < 10.0) then - let w = w + 1.0 / s - let s = s + 1.0 - loop s w - - else - if (s < 1.0E17) then - let z = 1.0 / (s * s) - let polv = - ((((((8.33333333333333333333E-2 - * z - 2.10927960927960927961E-2) - * z + 7.57575757575757575758E-3) - * z - 4.16666666666666666667E-3) - * z + 3.96825396825396825397E-3) - * z - 8.33333333333333333333E-3) - * z + 8.33333333333333333333E-2) - Math.Log(s) - 0.5 / s - (z * polv) - w - - else - Math.Log(s) - 0.5 / s - w - - loop x' 0. - - if (x < 0.) then - y - nz + let input = + if x < zero then + one - x // reflect else - y + x + + // Accumulate series if input is small + let mutable s = input + let mutable w = zero + while s < ten do + w <- w + one / s + s <- s + one + + // Asymptotic expansion + let result = + if s < limit then + let z = one / (s * s) + let polv: 'T = polyCoeffs |> Array.fold (fun acc c -> acc * z + c) zero + log<'T> s - half / s - z * polv - w + else + log<'T> s - half / s - w + + if x = zero then + T System.Double.NegativeInfinity + elif x < zero then + result + pi / 'T.Tan (-pi * x) + else + result /// @@ -322,7 +469,7 @@ module Gamma = /// made public under the GNU LGPL license. /// let rec trigamma (x:float) = - + //TODO: adapt to 'T match x with | x when (x < 0.) -> let v = Math.PI / Math.Sin(-Math.PI * x) From 1c82ab7d894ed76c2c8b78ebd4738764848a7bcd Mon Sep 17 00:00:00 2001 From: Christopher Lux <59606965+LibraChris@users.noreply.github.com> Date: Mon, 23 Jun 2025 16:50:47 +0200 Subject: [PATCH 110/121] Update Beta.fs Marked _betaLn, _beta, betaLn, and beta functions as 'inline' to enable generic numeric support. --- src/FSharp.Stats/SpecialFunctions/Beta.fs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/FSharp.Stats/SpecialFunctions/Beta.fs b/src/FSharp.Stats/SpecialFunctions/Beta.fs index ab83be604..42774a9b8 100644 --- a/src/FSharp.Stats/SpecialFunctions/Beta.fs +++ b/src/FSharp.Stats/SpecialFunctions/Beta.fs @@ -19,7 +19,7 @@ module Beta = /// /// The function input for approximating ln(B(z, w)) /// The function input for approximating ln(B(z, w)) - let _betaLn z w = (Gamma._gammaLn z) + (Gamma._gammaLn w) - (Gamma._gammaLn (z+w)) + let inline _betaLn (z: 'T) (w: 'T) = (Gamma._gammaLn z) + (Gamma._gammaLn w) - (Gamma._gammaLn (z+w)) /// /// Computes an approximation of the real value of the beta function using approximations for the gamma function using Lanczos Coefficients described in Numerical Recipes (Press et al) @@ -29,7 +29,7 @@ module Beta = /// /// The function input for approximating B(z, w) /// The function input for approximating B(z, w) - let _beta z w = exp (_betaLn z w) + let inline _beta (z: 'T) (w: 'T) = exp (_betaLn z w) /// /// Computes an approximation of the real value of the log beta function using approximations for the gamma function using Lanczos Coefficients described in Numerical Recipes (Press et al) @@ -40,7 +40,7 @@ module Beta = /// /// The function input for approximating ln(B(z, w)) /// The function input for approximating ln(B(z, w)) - let betaLn z w = (Gamma.gammaLn z) + (Gamma.gammaLn w) - (Gamma.gammaLn (z+w)) + let inline betaLn (z: 'T) (w: 'T) = (Gamma.gammaLn z) + (Gamma.gammaLn w) - (Gamma.gammaLn (z+w)) /// /// Computes an approximation of the real value of the beta function using approximations for the gamma function using Lanczos Coefficients described in Numerical Recipes (Press et al) @@ -51,7 +51,7 @@ module Beta = /// /// The function input for approximating B(z, w) /// The function input for approximating B(z, w) - let beta z w = exp (betaLn z w) + let inline beta (z: 'T) (w: 'T) = exp (betaLn z w) // incomplete beta function /// From dc849cce84c05bee0ff0c500c0b9b8c32b012489 Mon Sep 17 00:00:00 2001 From: Christopher Lux <59606965+LibraChris@users.noreply.github.com> Date: Tue, 24 Jun 2025 16:18:50 +0200 Subject: [PATCH 111/121] Start Update for Beta.lowerIncompleteRegularized<'T> --- src/FSharp.Stats/SpecialFunctions/Beta.fs | 188 ++++++++++++++++------ 1 file changed, 139 insertions(+), 49 deletions(-) diff --git a/src/FSharp.Stats/SpecialFunctions/Beta.fs b/src/FSharp.Stats/SpecialFunctions/Beta.fs index 42774a9b8..2195885b2 100644 --- a/src/FSharp.Stats/SpecialFunctions/Beta.fs +++ b/src/FSharp.Stats/SpecialFunctions/Beta.fs @@ -2,14 +2,15 @@ open System open FSharp.Stats +open FSharp.Stats.GenericMath /// The beta function B(p,q), or the beta integral (also called the Eulerian integral of the first kind) is defined by /// /// B(p, q) = (Γ(p) * Γ(q)) / Γ(p+q) module Beta = - let private EPS = 3.0e-8 // Precision.DoublePrecision; - let private FPMIN = 1.0e-30 // 0.0.Increment()/eps + let private EPS : 'T = T 3.0e-8 // Precision.DoublePrecision; + let private FPMIN : 'T = T 1.0e-30 // 0.0.Increment()/eps /// /// Computes an approximation of the real value of the log beta function using approximations for the gamma function using Lanczos Coefficients described in Numerical Recipes (Press et al) @@ -19,7 +20,19 @@ module Beta = /// /// The function input for approximating ln(B(z, w)) /// The function input for approximating ln(B(z, w)) - let inline _betaLn (z: 'T) (w: 'T) = (Gamma._gammaLn z) + (Gamma._gammaLn w) - (Gamma._gammaLn (z+w)) + let inline _betaLn<'T when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T : equality + and 'T :> ValueType + and 'T :> System.Numerics.IFloatingPoint<'T> + and 'T :> System.Numerics.IExponentialFunctions<'T> + and 'T :> System.Numerics.ILogarithmicFunctions<'T> + and 'T :> System.Numerics.IRootFunctions<'T> + and 'T :> System.Numerics.IPowerFunctions<'T> + and 'T : comparison> + (z: 'T) (w: 'T) = + (Gamma._gammaLn z) + (Gamma._gammaLn w) - (Gamma._gammaLn (z+w)) /// /// Computes an approximation of the real value of the beta function using approximations for the gamma function using Lanczos Coefficients described in Numerical Recipes (Press et al) @@ -29,7 +42,19 @@ module Beta = /// /// The function input for approximating B(z, w) /// The function input for approximating B(z, w) - let inline _beta (z: 'T) (w: 'T) = exp (_betaLn z w) + let inline _beta<'T when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T : equality + and 'T :> ValueType + and 'T :> System.Numerics.IFloatingPoint<'T> + and 'T :> System.Numerics.IExponentialFunctions<'T> + and 'T :> System.Numerics.ILogarithmicFunctions<'T> + and 'T :> System.Numerics.IRootFunctions<'T> + and 'T :> System.Numerics.IPowerFunctions<'T> + and 'T : comparison> + (z: 'T) (w: 'T) = + exp (_betaLn z w) /// /// Computes an approximation of the real value of the log beta function using approximations for the gamma function using Lanczos Coefficients described in Numerical Recipes (Press et al) @@ -40,7 +65,19 @@ module Beta = /// /// The function input for approximating ln(B(z, w)) /// The function input for approximating ln(B(z, w)) - let inline betaLn (z: 'T) (w: 'T) = (Gamma.gammaLn z) + (Gamma.gammaLn w) - (Gamma.gammaLn (z+w)) + let inline betaLn<'T when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T : equality + and 'T :> ValueType + and 'T :> System.Numerics.IFloatingPoint<'T> + and 'T :> System.Numerics.IExponentialFunctions<'T> + and 'T :> System.Numerics.ILogarithmicFunctions<'T> + and 'T :> System.Numerics.IRootFunctions<'T> + and 'T :> System.Numerics.IPowerFunctions<'T> + and 'T : comparison> + (z: 'T) (w: 'T) = + (Gamma.gammaLn z) + (Gamma.gammaLn w) - (Gamma.gammaLn (z+w)) /// /// Computes an approximation of the real value of the beta function using approximations for the gamma function using Lanczos Coefficients described in Numerical Recipes (Press et al) @@ -51,7 +88,19 @@ module Beta = /// /// The function input for approximating B(z, w) /// The function input for approximating B(z, w) - let inline beta (z: 'T) (w: 'T) = exp (betaLn z w) + let inline beta<'T when 'T :> Numerics.INumber<'T> + and 'T : (new: unit -> 'T) + and 'T : struct + and 'T : equality + and 'T :> ValueType + and 'T :> System.Numerics.IFloatingPoint<'T> + and 'T :> System.Numerics.IExponentialFunctions<'T> + and 'T :> System.Numerics.ILogarithmicFunctions<'T> + and 'T :> System.Numerics.IRootFunctions<'T> + and 'T :> System.Numerics.IPowerFunctions<'T> + and 'T : comparison> + (z: 'T) (w: 'T) = + exp (betaLn z w) // incomplete beta function /// @@ -60,59 +109,100 @@ module Beta = /// The first Beta parameter, a positive real number. /// The second Beta parameter, a positive real number. /// The upper limit of the integral. - let lowerIncompleteRegularized a b x = - if (a < 0.0) then invalidArg "a" "Argument must not be negative" - if (b < 0.0) then invalidArg "b" "Argument must not be negative" - if (x < 0.0 || x > 1.0) then invalidArg "x" "Argument XY interval is inclusive" - let bt = - if (x = 0.0 || x = 1.0) then - 0.0 + let inline lowerIncompleteRegularized + (a: ^T when ^T :> Numerics.INumber<^T> + and ^T : (new: unit -> ^T) + and ^T : struct + and ^T : equality + and ^T :> ValueType + and ^T :> System.Numerics.IFloatingPoint<^T> + and ^T :> System.Numerics.IExponentialFunctions<^T> + and ^T :> System.Numerics.ILogarithmicFunctions<^T> + and ^T :> System.Numerics.IRootFunctions<^T> + and ^T :> System.Numerics.IPowerFunctions<^T> + and ^T : comparison) + (b: ^T when ^T :> Numerics.INumber<^T> + and ^T : (new: unit -> ^T) + and ^T : struct + and ^T : equality + and ^T :> ValueType + and ^T :> System.Numerics.IFloatingPoint<^T> + and ^T :> System.Numerics.IExponentialFunctions<^T> + and ^T :> System.Numerics.ILogarithmicFunctions<^T> + and ^T :> System.Numerics.IRootFunctions<^T> + and ^T :> System.Numerics.IPowerFunctions<^T> + and ^T : comparison) + (x: ^T when ^T :> Numerics.INumber<^T> + and ^T : (new: unit -> ^T) + and ^T : struct + and ^T : equality + and ^T :> ValueType + and ^T :> System.Numerics.IFloatingPoint<^T> + and ^T :> System.Numerics.IExponentialFunctions<^T> + and ^T :> System.Numerics.ILogarithmicFunctions<^T> + and ^T :> System.Numerics.IRootFunctions<^T> + and ^T :> System.Numerics.IPowerFunctions<^T> + and ^T : comparison) = + if (a < T 0.0) then invalidArg "a" "Argument must not be negative" + if (b < T 0.0) then invalidArg "b" "Argument must not be negative" + if (x < T 0.0 || x > T 1.0) then invalidArg "x" "Argument XY interval is inclusive" + let bt: 'T = + if (x = T 0.0 || x = T 1.0) then + T 0.0 else - exp (Gamma._gammaLn (a + b) - Gamma._gammaLn a - Gamma._gammaLn b + (a*Math.Log(x)) + (b*Math.Log(1.0 - x))) + exp (Gamma._gammaLn (a + b) - Gamma._gammaLn a - Gamma._gammaLn b + (a*log(x)) + (b*log(T 1.0 - x))) - let isSymmetryTransformation = ( x >= (a + 1.0)/(a + b + 2.0)) + let isSymmetryTransformation = ( x >= (a + T 1.0)/(a + b + T 2.0)) - let symmetryTransformation a b x = + let inline symmetryTransformation + (a: 'T) (b: 'T) (x: 'T) = let qab = a + b - let qap = a + 1.0 - let qam = a - 1.0 - let c = 1.0 - let d = - let tmp = 1.0 - (qab * x / qap) - if (abs tmp < FPMIN) then 1. / FPMIN else 1. / tmp + let qap = a + T 1.0 + let qam = a - T 1.0 + let c = T 1.0 + let d: 'T = + let tmp = T 1.0 - (qab * x / qap) + if (abs tmp < FPMIN) then T 1. / FPMIN else T 1. / tmp let h = d - let rec loop m mm d h c = - let aa = float m * (b - float m)*x/((qam + mm)*(a + mm)) + let rec loop (m: 'T) (mm: 'T) (d: 'T) (h: 'T) (c: 'T) = + let aa = m * (b - m)*x/((qam + mm)*(a + mm)) let d' = - let tmp = 1.0 + (aa*d) - if (abs tmp < FPMIN) then 1. / FPMIN else 1. / tmp + let tmp = T 1.0 + (aa*d) + if (abs tmp < FPMIN) then T 1. / FPMIN else T 1. / tmp let c' = - let tmp = 1.0 + (aa/c) + let tmp = T 1.0 + (aa/c) if (abs tmp < FPMIN) then FPMIN else tmp - let h' = h * d' * c' - let aa' = -(a + float m)*(qab + float m)*x/((a + mm)*(qap + mm)) - let d'' = - let tmp = 1.0 + (aa' * d') - if (abs tmp < FPMIN) then 1. / FPMIN else 1. / tmp - let c'' = - let tmp = 1.0 + (aa'/c') + let h': 'T = h * d' * c' + let aa': 'T = -(a + m)*(qab + m)*x/((a + mm)*(qap + mm)) + let d'': 'T = + let tmp = T 1.0 + (aa' * d') + if (abs tmp < FPMIN) then T 1. / FPMIN else T 1. / tmp + let c'': 'T = + let tmp = T 1.0 + (aa'/c') if (abs tmp < FPMIN) then FPMIN else tmp - let del = d''*c'' - let h'' = h' * del + let del: 'T = d''*c'' + let h'': 'T = h' * del - if abs (del - 1.0) <= EPS then - if isSymmetryTransformation then 1.0 - (bt*h''/a) else bt*h''/a + let tepmI: 'T = + bt*h''/a + + if abs (del - T 1.0) <= EPS then + + if isSymmetryTransformation then + T 1.0 - tepmI + else + tepmI else - if m < 140 then - loop (m+1) (mm+2.) d'' h'' c'' + if m < T 140 then + loop (m+T 1) (mm+T 2.) d'' h'' c'' else - if isSymmetryTransformation then 1.0 - (bt*h''/a) else bt*h''/a + if isSymmetryTransformation then T 1.0 - tepmI else tepmI - loop 1 2. d h c + loop (T 1) (T 2.) d h c if isSymmetryTransformation then - symmetryTransformation b a (1.0-x) + symmetryTransformation b a (T 1.0-x) else symmetryTransformation a b x @@ -123,7 +213,7 @@ module Beta = /// The first Beta parameter, a positive real number. /// The second Beta parameter, a positive real number. /// The upper limit of the integral. - let lowerIncomplete(a, b, x) = + let inline lowerIncomplete(a, b, x) : 'T= (lowerIncompleteRegularized a b x) * (beta a b) @@ -131,11 +221,11 @@ module Beta = /// Power series for incomplete beta integral. Use when b*x /// is small and x not too close to 1. /// - let powerSeries a b x = - let ai = 1.0 / a - let ui = (1.0 - b) * x - let t1 = ui / (a + 1.0) - let z = Ops.epsilon * ai + let inline powerSeries a b x = + let ai = T 1.0 / a + let ui = (T 1.0 - b) * x + let t1 = ui / (a + T 1.0) + let z = Ops.epsilon * ai |> T let rec loop u t v s n = if (abs v > z) then From bc3f0b7423b5b701c8c54136987911d284973c5b Mon Sep 17 00:00:00 2001 From: Christopher Lux <59606965+LibraChris@users.noreply.github.com> Date: Tue, 24 Jun 2025 16:19:03 +0200 Subject: [PATCH 112/121] Start Update for TestStatistics for 'T --- .../Distributions/Continuous/StudentT.fs | 9 +++-- src/FSharp.Stats/Testing/TestStatistics.fs | 40 +++++++++++-------- 2 files changed, 29 insertions(+), 20 deletions(-) diff --git a/src/FSharp.Stats/Distributions/Continuous/StudentT.fs b/src/FSharp.Stats/Distributions/Continuous/StudentT.fs index d30537395..f6fa8b936 100644 --- a/src/FSharp.Stats/Distributions/Continuous/StudentT.fs +++ b/src/FSharp.Stats/Distributions/Continuous/StudentT.fs @@ -4,6 +4,7 @@ open System open FSharp.Stats open FSharp.Stats.Distributions open FSharp.Stats.Ops +open FSharp.Stats.GenericMath // ###### // Student's T-distribution @@ -17,10 +18,10 @@ open FSharp.Stats.Ops type StudentT = // Student's T-distribution helper functions. - static member CheckParam mu tau dof = - if System.Double.IsNaN(mu) || tau < 0.0 || System.Double.IsNaN(dof) || dof < 0. then + static member CheckParam (mu: 'T) (tau: 'T) (dof: 'T) = + if isNan(mu) || tau < T 0.0 || isNan(dof) || dof < T 0. then failwith "Student's T-distribution should be parametrized by mu, tau and dof > 0.0." - + /// Computes the mode. /// /// @@ -63,7 +64,7 @@ type StudentT = StudentT.CheckParam mu tau dof match dof with | df when System.Double.IsPositiveInfinity(df) -> tau*tau - | df when df > 2.0 -> dof*tau*tau/(dof-2.0) + | df when df > T 2.0 -> dof*tau*tau/(dof-T 2.0) | _ -> System.Double.PositiveInfinity /// Computes the standard deviation. diff --git a/src/FSharp.Stats/Testing/TestStatistics.fs b/src/FSharp.Stats/Testing/TestStatistics.fs index 955c125ff..b6e4fddd1 100644 --- a/src/FSharp.Stats/Testing/TestStatistics.fs +++ b/src/FSharp.Stats/Testing/TestStatistics.fs @@ -1,4 +1,6 @@ namespace FSharp.Stats.Testing +open System +open FSharp.Stats.GenericMath module TestStatistics = @@ -9,25 +11,31 @@ module TestStatistics = /// Creates a new T-Test for a given statistic /// with given degrees of freedom. /// - type TTestStatistics = { - /// The test statistic. - Statistic : float - /// The degrees of freedom for the numerator. - DegreesOfFreedom : float - /// One Tailed/Sided. - PValueLeft : float - /// One Tailed/Sided. - PValueRight : float - /// Two Tailed/Sided. - PValue : float - } + /// + /// The test statistic. + /// The degrees of freedom for the numerator. + /// One Tailed/Sided. + /// One Tailed/Sided. + /// Two Tailed/Sided. + type TTestStatistics<'T when 'T :> Numerics.INumber<'T> + and Numerics.IFloatingPoint<'T> + and Numerics.IExponentialFunctions<'T> + and Numerics.IRootFunctions<'T> + and Numerics.IPowerFunctions<'T>> = + { + Statistic : 'T + DegreesOfFreedom : 'T + PValueLeft : 'T + PValueRight : 'T + PValue : 'T + } - let createTTest statistic dof = - let cdf = Distributions.Continuous.StudentT.CDF 0. 1. dof statistic - let pvalue = if statistic > 0. then 1. - cdf else cdf + let createTTest (statistic: 'T) (dof: 'T) = + let cdf: 'T = Distributions.Continuous.StudentT.CDF 0. 1. ('T.One dof) statistic + let pvalue: 'T = if statistic > T 0. then T 1. - cdf else cdf + {Statistic=statistic; DegreesOfFreedom=dof; PValueLeft=1. - pvalue; PValueRight=pvalue; PValue=pvalue*2.;} - /// /// Creates a new F-Test for a given statistic /// with given degrees of freedom. From eb3b9d281637a47b5cdac5d9fa01e0105286d318 Mon Sep 17 00:00:00 2001 From: Christopher Lux <59606965+LibraChris@users.noreply.github.com> Date: Thu, 26 Jun 2025 16:14:51 +0200 Subject: [PATCH 113/121] Refactor to support generic numeric type 'T --- src/FSharp.Stats/SpecialFunctions/Beta.fs | 140 ++++++++-------------- 1 file changed, 52 insertions(+), 88 deletions(-) diff --git a/src/FSharp.Stats/SpecialFunctions/Beta.fs b/src/FSharp.Stats/SpecialFunctions/Beta.fs index 2195885b2..480a879ad 100644 --- a/src/FSharp.Stats/SpecialFunctions/Beta.fs +++ b/src/FSharp.Stats/SpecialFunctions/Beta.fs @@ -4,13 +4,18 @@ open System open FSharp.Stats open FSharp.Stats.GenericMath +// TODO: Generalize lowerIncompleteRegularized, lowerIncomplete, and powerSeries to support generic type 'T instead of using float + /// The beta function B(p,q), or the beta integral (also called the Eulerian integral of the first kind) is defined by /// /// B(p, q) = (Γ(p) * Γ(q)) / Γ(p+q) module Beta = - let private EPS : 'T = T 3.0e-8 // Precision.DoublePrecision; - let private FPMIN : 'T = T 1.0e-30 // 0.0.Increment()/eps + // let private EPS : 'T = T 3.0e-8 // Precision.DoublePrecision; + // let private FPMIN : 'T = T 1.0e-30 // 0.0.Increment()/eps + + let private f_EPS = T 3.0e-8 // Precision.DoublePrecision; + let private f_FPMIN = T 1.0e-30 // 0.0.Increment()/eps /// /// Computes an approximation of the real value of the log beta function using approximations for the gamma function using Lanczos Coefficients described in Numerical Recipes (Press et al) @@ -109,100 +114,59 @@ module Beta = /// The first Beta parameter, a positive real number. /// The second Beta parameter, a positive real number. /// The upper limit of the integral. - let inline lowerIncompleteRegularized - (a: ^T when ^T :> Numerics.INumber<^T> - and ^T : (new: unit -> ^T) - and ^T : struct - and ^T : equality - and ^T :> ValueType - and ^T :> System.Numerics.IFloatingPoint<^T> - and ^T :> System.Numerics.IExponentialFunctions<^T> - and ^T :> System.Numerics.ILogarithmicFunctions<^T> - and ^T :> System.Numerics.IRootFunctions<^T> - and ^T :> System.Numerics.IPowerFunctions<^T> - and ^T : comparison) - (b: ^T when ^T :> Numerics.INumber<^T> - and ^T : (new: unit -> ^T) - and ^T : struct - and ^T : equality - and ^T :> ValueType - and ^T :> System.Numerics.IFloatingPoint<^T> - and ^T :> System.Numerics.IExponentialFunctions<^T> - and ^T :> System.Numerics.ILogarithmicFunctions<^T> - and ^T :> System.Numerics.IRootFunctions<^T> - and ^T :> System.Numerics.IPowerFunctions<^T> - and ^T : comparison) - (x: ^T when ^T :> Numerics.INumber<^T> - and ^T : (new: unit -> ^T) - and ^T : struct - and ^T : equality - and ^T :> ValueType - and ^T :> System.Numerics.IFloatingPoint<^T> - and ^T :> System.Numerics.IExponentialFunctions<^T> - and ^T :> System.Numerics.ILogarithmicFunctions<^T> - and ^T :> System.Numerics.IRootFunctions<^T> - and ^T :> System.Numerics.IPowerFunctions<^T> - and ^T : comparison) = - if (a < T 0.0) then invalidArg "a" "Argument must not be negative" - if (b < T 0.0) then invalidArg "b" "Argument must not be negative" - if (x < T 0.0 || x > T 1.0) then invalidArg "x" "Argument XY interval is inclusive" - let bt: 'T = - if (x = T 0.0 || x = T 1.0) then - T 0.0 + let lowerIncompleteRegularized a b x = + if (a < 0.0) then invalidArg "a" "Argument must not be negative" + if (b < 0.0) then invalidArg "b" "Argument must not be negative" + if (x < 0.0 || x > 1.0) then invalidArg "x" "Argument XY interval is inclusive" + let bt = + if (x = 0.0 || x = 1.0) then + 0.0 else - exp (Gamma._gammaLn (a + b) - Gamma._gammaLn a - Gamma._gammaLn b + (a*log(x)) + (b*log(T 1.0 - x))) + exp (Gamma._gammaLn (a + b) - Gamma._gammaLn a - Gamma._gammaLn b + (a*Math.Log(x)) + (b*Math.Log(1.0 - x))) - let isSymmetryTransformation = ( x >= (a + T 1.0)/(a + b + T 2.0)) + let isSymmetryTransformation = ( x >= (a + 1.0)/(a + b + 2.0)) - let inline symmetryTransformation - (a: 'T) (b: 'T) (x: 'T) = + let symmetryTransformation a b x = let qab = a + b - let qap = a + T 1.0 - let qam = a - T 1.0 - let c = T 1.0 - let d: 'T = - let tmp = T 1.0 - (qab * x / qap) - if (abs tmp < FPMIN) then T 1. / FPMIN else T 1. / tmp + let qap = a + 1.0 + let qam = a - 1.0 + let c = 1.0 + let d = + let tmp = 1.0 - (qab * x / qap) + if (abs tmp < f_FPMIN) then 1. / f_FPMIN else 1. / tmp let h = d - let rec loop (m: 'T) (mm: 'T) (d: 'T) (h: 'T) (c: 'T) = - let aa = m * (b - m)*x/((qam + mm)*(a + mm)) + let rec loop m mm d h c = + let aa = float m * (b - float m)*x/((qam + mm)*(a + mm)) let d' = - let tmp = T 1.0 + (aa*d) - if (abs tmp < FPMIN) then T 1. / FPMIN else T 1. / tmp + let tmp = 1.0 + (aa*d) + if (abs tmp < f_FPMIN) then 1. / f_FPMIN else 1. / tmp let c' = - let tmp = T 1.0 + (aa/c) - if (abs tmp < FPMIN) then FPMIN else tmp - let h': 'T = h * d' * c' - let aa': 'T = -(a + m)*(qab + m)*x/((a + mm)*(qap + mm)) - let d'': 'T = - let tmp = T 1.0 + (aa' * d') - if (abs tmp < FPMIN) then T 1. / FPMIN else T 1. / tmp - let c'': 'T = - let tmp = T 1.0 + (aa'/c') - if (abs tmp < FPMIN) then FPMIN else tmp + let tmp = 1.0 + (aa/c) + if (abs tmp < f_FPMIN) then f_FPMIN else tmp + let h' = h * d' * c' + let aa' = -(a + float m)*(qab + float m)*x/((a + mm)*(qap + mm)) + let d'' = + let tmp = 1.0 + (aa' * d') + if (abs tmp < f_FPMIN) then 1. / f_FPMIN else 1. / tmp + let c'' = + let tmp = 1.0 + (aa'/c') + if (abs tmp < f_FPMIN) then f_FPMIN else tmp - let del: 'T = d''*c'' - let h'': 'T = h' * del + let del = d''*c'' + let h'' = h' * del - let tepmI: 'T = - bt*h''/a - - if abs (del - T 1.0) <= EPS then - - if isSymmetryTransformation then - T 1.0 - tepmI - else - tepmI + if abs (del - 1.0) <= f_EPS then + if isSymmetryTransformation then 1.0 - (bt*h''/a) else bt*h''/a else - if m < T 140 then - loop (m+T 1) (mm+T 2.) d'' h'' c'' + if m < 140 then + loop (m+1) (mm+2.) d'' h'' c'' else - if isSymmetryTransformation then T 1.0 - tepmI else tepmI + if isSymmetryTransformation then 1.0 - (bt*h''/a) else bt*h''/a - loop (T 1) (T 2.) d h c + loop 1 2. d h c if isSymmetryTransformation then - symmetryTransformation b a (T 1.0-x) + symmetryTransformation b a (1.0-x) else symmetryTransformation a b x @@ -213,7 +177,7 @@ module Beta = /// The first Beta parameter, a positive real number. /// The second Beta parameter, a positive real number. /// The upper limit of the integral. - let inline lowerIncomplete(a, b, x) : 'T= + let lowerIncomplete(a, b, x) = (lowerIncompleteRegularized a b x) * (beta a b) @@ -221,11 +185,11 @@ module Beta = /// Power series for incomplete beta integral. Use when b*x /// is small and x not too close to 1. /// - let inline powerSeries a b x = - let ai = T 1.0 / a - let ui = (T 1.0 - b) * x - let t1 = ui / (a + T 1.0) - let z = Ops.epsilon * ai |> T + let powerSeries a b x = + let ai = 1.0 / a + let ui = (1.0 - b) * x + let t1 = ui / (a + 1.0) + let z = Ops.epsilon * ai let rec loop u t v s n = if (abs v > z) then From 64ac64ae6fda326d23f04819ce2e596181fc3a1f Mon Sep 17 00:00:00 2001 From: Christopher Lux <59606965+LibraChris@users.noreply.github.com> Date: Thu, 26 Jun 2025 16:15:31 +0200 Subject: [PATCH 114/121] Partial update to support generic numeric type 'T in TestStatistics --- .../Distributions/Continuous/StudentT.fs | 7 +- src/FSharp.Stats/Testing/TestStatistics.fs | 184 +++++++++++++----- 2 files changed, 142 insertions(+), 49 deletions(-) diff --git a/src/FSharp.Stats/Distributions/Continuous/StudentT.fs b/src/FSharp.Stats/Distributions/Continuous/StudentT.fs index f6fa8b936..dd5df8fb1 100644 --- a/src/FSharp.Stats/Distributions/Continuous/StudentT.fs +++ b/src/FSharp.Stats/Distributions/Continuous/StudentT.fs @@ -4,7 +4,6 @@ open System open FSharp.Stats open FSharp.Stats.Distributions open FSharp.Stats.Ops -open FSharp.Stats.GenericMath // ###### // Student's T-distribution @@ -18,8 +17,8 @@ open FSharp.Stats.GenericMath type StudentT = // Student's T-distribution helper functions. - static member CheckParam (mu: 'T) (tau: 'T) (dof: 'T) = - if isNan(mu) || tau < T 0.0 || isNan(dof) || dof < T 0. then + static member CheckParam mu tau dof = + if isNan(mu) || tau < 0.0 || isNan(dof) || dof < 0. then failwith "Student's T-distribution should be parametrized by mu, tau and dof > 0.0." /// Computes the mode. @@ -64,7 +63,7 @@ type StudentT = StudentT.CheckParam mu tau dof match dof with | df when System.Double.IsPositiveInfinity(df) -> tau*tau - | df when df > T 2.0 -> dof*tau*tau/(dof-T 2.0) + | df when df > 2.0 -> dof*tau*tau/(dof-2.0) | _ -> System.Double.PositiveInfinity /// Computes the standard deviation. diff --git a/src/FSharp.Stats/Testing/TestStatistics.fs b/src/FSharp.Stats/Testing/TestStatistics.fs index b6e4fddd1..d620c2863 100644 --- a/src/FSharp.Stats/Testing/TestStatistics.fs +++ b/src/FSharp.Stats/Testing/TestStatistics.fs @@ -2,6 +2,7 @@ namespace FSharp.Stats.Testing open System open FSharp.Stats.GenericMath +// TODO: Update specific distributions to support generic type 'T to avoid explicit float casting module TestStatistics = @@ -21,7 +22,9 @@ module TestStatistics = and Numerics.IFloatingPoint<'T> and Numerics.IExponentialFunctions<'T> and Numerics.IRootFunctions<'T> - and Numerics.IPowerFunctions<'T>> = + and Numerics.IPowerFunctions<'T> + and 'T: (static member op_Explicit: ^T -> float) + and 'T : comparison > = { Statistic : 'T DegreesOfFreedom : 'T @@ -30,71 +33,162 @@ module TestStatistics = PValue : 'T } - let createTTest (statistic: 'T) (dof: 'T) = - let cdf: 'T = Distributions.Continuous.StudentT.CDF 0. 1. ('T.One dof) statistic - let pvalue: 'T = if statistic > T 0. then T 1. - cdf else cdf + let inline createTTest<'T when 'T :> Numerics.INumber<'T> + and Numerics.IFloatingPoint<'T> + and Numerics.IExponentialFunctions<'T> + and Numerics.ILogarithmicFunctions<'T> + and Numerics.IRootFunctions<'T> + and Numerics.IPowerFunctions<'T> + and 'T: (static member op_Explicit: ^T -> float) + and 'T : comparison > + (statistic: 'T) (dof: 'T) = + let fstatistic = toFloat statistic + let fdof = toFloat dof + + let cdf = Distributions.Continuous.StudentT.CDF 0. 1. fdof fstatistic |> T + let pvalue = if fstatistic > 0. then 1. - cdf else cdf - {Statistic=statistic; DegreesOfFreedom=dof; PValueLeft=1. - pvalue; PValueRight=pvalue; PValue=pvalue*2.;} + { + Statistic=statistic; + DegreesOfFreedom=dof; + PValueLeft= T(1. - pvalue); + PValueRight=T(pvalue); + PValue=T(pvalue*2.); + } /// /// Creates a new F-Test for a given statistic /// with given degrees of freedom. /// - type FTestStatistics = { - /// The test statistic. - Statistic : float - /// The degrees of freedom for the numerator. - DegreesOfFreedom1 : float - /// The degrees of freedom for the denominator. - DegreesOfFreedom2 : float - PValue : float - PValueTwoTailed : float - } + /// + /// The test statistic. + /// The degrees of freedom for the numerator. + /// The degrees of freedom for the denominator. + type FTestStatistics<'T when 'T :> Numerics.INumber<'T> + and Numerics.IFloatingPoint<'T> + and Numerics.IExponentialFunctions<'T> + and Numerics.IRootFunctions<'T> + and Numerics.IPowerFunctions<'T> + and 'T: (static member op_Explicit: ^T -> float) + and 'T : comparison > = + { + Statistic : 'T + DegreesOfFreedom1 : 'T + DegreesOfFreedom2 : 'T + PValue : 'T + PValueTwoTailed : 'T + } - let createFTest statistic dof1 dof2 = - let cdf = Distributions.Continuous.F.CDF dof1 dof2 statistic + let inline createFTest<'T when 'T :> Numerics.INumber<'T> + and Numerics.IFloatingPoint<'T> + and Numerics.IExponentialFunctions<'T> + and Numerics.IRootFunctions<'T> + and Numerics.IPowerFunctions<'T> + and 'T: (static member op_Explicit: ^T -> float) + and 'T : comparison > + (statistic: 'T) (dof1: 'T) (dof2: 'T) = + let fstatistic = toFloat statistic + let fdof1 = toFloat dof1 + let fdof2 = toFloat dof2 + let cdf = Distributions.Continuous.F.CDF fdof1 fdof2 fstatistic let pvalue = 1. - cdf let pvalueTwoTailed = pvalue * 2. - {Statistic=statistic; DegreesOfFreedom1=dof1; DegreesOfFreedom2=dof2; PValue=pvalue; PValueTwoTailed = pvalueTwoTailed} + { + Statistic=statistic; + DegreesOfFreedom1=dof1; + DegreesOfFreedom2=dof2; + PValue=T pvalue; + PValueTwoTailed = T pvalueTwoTailed + } /// /// Computes the Chi-Square test statistics for a given statistic /// with given degrees of freedom. /// - type ChiSquareStatistics = { - /// The test statistic. - Statistic : float - /// The degrees of freedom for the numerator. - DegreesOfFreedom : float - /// One Tailed/Sided. - PValueLeft : float - /// One Tailed/Sided. - PValueRight : float - /// Two Tailed/Sided. - PValue : float - } + /// + /// The test statistic. + /// The degrees of freedom for the numerator. + /// One Tailed/Sided. + /// One Tailed/Sided. + /// Two Tailed/Sided. + type ChiSquareStatistics<'T when 'T :> Numerics.INumber<'T> + and Numerics.IFloatingPoint<'T> + and Numerics.IExponentialFunctions<'T> + and Numerics.IRootFunctions<'T> + and Numerics.IPowerFunctions<'T> + and 'T: (static member op_Explicit: ^T -> float) + and 'T : comparison > = + { + Statistic : 'T + DegreesOfFreedom : 'T + /// one tailed/sided chiSquare pValue + PValueLeft : 'T + /// one tailed/sided chiSquare pValue (default) + PValueRight : 'T + /// two tailed/sided chiSquare pValue + PValue : 'T + } - let createChiSquare statistic dof = - let cdf = Distributions.Continuous.ChiSquared.CDF dof statistic - let pvalue = if statistic > 0. then 1. - cdf else cdf - {Statistic = statistic; DegreesOfFreedom = dof; PValueLeft = 1. - pvalue; PValueRight = pvalue; PValue = pvalue * 2.} + let inline createChiSquare<'T when 'T :> Numerics.INumber<'T> + and Numerics.IFloatingPoint<'T> + and Numerics.IExponentialFunctions<'T> + and Numerics.IRootFunctions<'T> + and Numerics.IPowerFunctions<'T> + and 'T: (static member op_Explicit: ^T -> float) + and 'T : comparison > + (statistic:'T) (dof:'T) = + let fstatistic = toFloat statistic + let fdof = toFloat dof + + + let cdf = Distributions.Continuous.ChiSquared.CDF fdof fstatistic + let pvalue = if fstatistic > 0. then 1. - cdf else cdf + { + Statistic = statistic; + DegreesOfFreedom = dof; + PValueLeft =T(1. - pvalue); + PValueRight = T pvalue; + PValue = T(pvalue * 2.) + } /// /// Computes the Wilcoxon test statistics for a given statistic. /// - type WilcoxonTestStatistics = { - /// The test statistic. - Statistic : float - PValueLeft : float - PValueRight : float - /// Two Tailed/Sided. - PValueTwoTailed : float - } - let createWilcoxon statistic = - let cdf = Distributions.Continuous.Normal.CDF 0. 1. statistic + /// The test statistic. + /// One Tailed/Sided. + /// Two Tailed/Sided. + type WilcoxonTestStatistics<'T when 'T :> Numerics.INumber<'T> + and Numerics.IFloatingPoint<'T> + and Numerics.IExponentialFunctions<'T> + and Numerics.IRootFunctions<'T> + and Numerics.IPowerFunctions<'T> + and 'T: (static member op_Explicit: ^T -> float) + and 'T : comparison > = + { + Statistic : 'T + PValueLeft : 'T + PValueRight : 'T + PValueTwoTailed : 'T + } + let inline createWilcoxon<'T when 'T :> Numerics.INumber<'T> + and Numerics.IFloatingPoint<'T> + and Numerics.IExponentialFunctions<'T> + and Numerics.IRootFunctions<'T> + and Numerics.IPowerFunctions<'T> + and 'T: (static member op_Explicit: ^T -> float) + and 'T : comparison > + (statistic:'T) = + let fstatistic = toFloat statistic + + let cdf = Distributions.Continuous.Normal.CDF 0. 1. fstatistic let pvalue = 1.- cdf let pvalueTwoTailed = pvalue * 2. - {Statistic=statistic; PValueLeft=pvalue;PValueRight = cdf; PValueTwoTailed = pvalueTwoTailed} \ No newline at end of file + { + Statistic=statistic; + PValueLeft=T pvalue; + PValueRight = T cdf; + PValueTwoTailed = T pvalueTwoTailed + } \ No newline at end of file From 8080cea2ec33b7eec5b3770617599cbb43448771 Mon Sep 17 00:00:00 2001 From: Christopher Lux <59606965+LibraChris@users.noreply.github.com> Date: Thu, 26 Jun 2025 16:15:43 +0200 Subject: [PATCH 115/121] Update SpecialFunctions.fs --- tests/FSharp.Stats.Tests/SpecialFunctions.fs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/FSharp.Stats.Tests/SpecialFunctions.fs b/tests/FSharp.Stats.Tests/SpecialFunctions.fs index 1e1bd132f..9f64f2d35 100644 --- a/tests/FSharp.Stats.Tests/SpecialFunctions.fs +++ b/tests/FSharp.Stats.Tests/SpecialFunctions.fs @@ -292,7 +292,7 @@ let factorialTests = Expect.floatClose Accuracy.high (Factorial._factorialLn 6942) 54467.727976695301612523565124699078303834231913072759124392135342 "factorialLn of large number failed" ) testCase "_ln(0!) = 0" (fun _ -> - Expect.equal (Factorial._factorialLn 0) 0. "Expected factorialLn of 0 to be 1." + Expect.floatClose Accuracy.high (Factorial._factorialLn 0) 0. "Expected factorialLn of 0 to be 1." ) testCase "_ln(69!)" (fun _ -> Expect.floatClose Accuracy.high 226.19054832372759333227016852232261788323276357495863628461257077 (Factorial._factorialLn 69) "Expected factorialLn of 69 to be 226.19054832372759333227016852232261788323276357495863628461257077" @@ -310,7 +310,7 @@ let factorialTests = Expect.floatClose Accuracy.high (Factorial.factorialLn 6942) 54467.727976695301612523565124699078303834231913072759124392135342 "factorialLn of large number failed" ) testCase "ln(0!) = 0" (fun _ -> - Expect.equal (Factorial.factorialLn 0) 0. "Expected factorialLn of 0 to be 1." + Expect.floatClose Accuracy.high (Factorial.factorialLn 0) 0. "Expected factorialLn of 0 to be 1." ) testCase "ln(69!)" (fun _ -> Expect.floatClose Accuracy.high 226.19054832372759333227016852232261788323276357495863628461257077 (Factorial.factorialLn 69) "Expected factorialLn of 69 to be 226.19054832372759333227016852232261788323276357495863628461257077" From 77ba43eec8d3c72dcda047b3c3e298a51be7f4af Mon Sep 17 00:00:00 2001 From: Christopher Lux <59606965+LibraChris@users.noreply.github.com> Date: Mon, 20 Oct 2025 11:18:40 +0200 Subject: [PATCH 116/121] Update FSharp.Stats.GenericMath to FsMath.GenericMath --- src/FSharp.Stats/SpecialFunctions/Beta.fs | 3 ++- src/FSharp.Stats/SpecialFunctions/Gamma.fs | 3 ++- src/FSharp.Stats/Testing/TestStatistics.fs | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/FSharp.Stats/SpecialFunctions/Beta.fs b/src/FSharp.Stats/SpecialFunctions/Beta.fs index 480a879ad..4f88f0f2b 100644 --- a/src/FSharp.Stats/SpecialFunctions/Beta.fs +++ b/src/FSharp.Stats/SpecialFunctions/Beta.fs @@ -2,7 +2,8 @@ open System open FSharp.Stats -open FSharp.Stats.GenericMath +open FsMath +open FsMath.GenericMath // TODO: Generalize lowerIncompleteRegularized, lowerIncomplete, and powerSeries to support generic type 'T instead of using float diff --git a/src/FSharp.Stats/SpecialFunctions/Gamma.fs b/src/FSharp.Stats/SpecialFunctions/Gamma.fs index 0e662773e..724c97386 100644 --- a/src/FSharp.Stats/SpecialFunctions/Gamma.fs +++ b/src/FSharp.Stats/SpecialFunctions/Gamma.fs @@ -1,7 +1,8 @@ namespace FSharp.Stats.SpecialFunctions open System -open FSharp.Stats.GenericMath +open FsMath +open FsMath.GenericMath /// Approximations for the gamma function and related functions. /// diff --git a/src/FSharp.Stats/Testing/TestStatistics.fs b/src/FSharp.Stats/Testing/TestStatistics.fs index d620c2863..2670a9fe0 100644 --- a/src/FSharp.Stats/Testing/TestStatistics.fs +++ b/src/FSharp.Stats/Testing/TestStatistics.fs @@ -1,6 +1,7 @@ namespace FSharp.Stats.Testing open System -open FSharp.Stats.GenericMath +open FsMath +open FsMath.GenericMath // TODO: Update specific distributions to support generic type 'T to avoid explicit float casting From b956775b17e4489fbdea57e2c29077714fec897b Mon Sep 17 00:00:00 2001 From: Christopher Lux <59606965+LibraChris@users.noreply.github.com> Date: Tue, 21 Oct 2025 09:57:30 +0200 Subject: [PATCH 117/121] Update FsMath Reference --- src/FSharp.Stats/FSharp.Stats.fsproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/FSharp.Stats/FSharp.Stats.fsproj b/src/FSharp.Stats/FSharp.Stats.fsproj index c7dc2ee1f..a994bcd49 100644 --- a/src/FSharp.Stats/FSharp.Stats.fsproj +++ b/src/FSharp.Stats/FSharp.Stats.fsproj @@ -172,7 +172,7 @@ - + From 47d93e90ab347ef85472b676e397a9e5f8092aec Mon Sep 17 00:00:00 2001 From: Christopher Lux <59606965+LibraChris@users.noreply.github.com> Date: Tue, 21 Oct 2025 10:06:50 +0200 Subject: [PATCH 118/121] Update FsMath Reference in Docs --- docs/BasicStats.fsx | 2 +- docs/Clustering.fsx | 2 +- docs/ComparisonMetrics.fsx | 4 ++-- docs/Correlation.fsx | 6 +++--- docs/Covariance.fsx | 2 +- docs/CrossValidation.fsx | 2 +- docs/Differentiation.fsx | 2 +- docs/Distributions.fsx | 2 +- docs/Fitting.fsx | 2 +- docs/GoodnessOfFit.fsx | 2 +- docs/GrowthCurve.fsx | 2 +- docs/Imputation.fsx | 4 ++-- docs/Integration.fsx | 2 +- docs/Interpolation.fsx | 2 +- docs/Intervals.fsx | 2 +- docs/Normalization.fsx | 2 +- docs/Optimization.fsx | 2 +- docs/Quantiles.fsx | 2 +- docs/Rank.fsx | 2 +- docs/Signal.fsx | 2 +- docs/Testing.fsx | 2 +- docs/index.fsx | 2 +- 22 files changed, 26 insertions(+), 26 deletions(-) diff --git a/docs/BasicStats.fsx b/docs/BasicStats.fsx index fe1a11be8..2f66fcca6 100644 --- a/docs/BasicStats.fsx +++ b/docs/BasicStats.fsx @@ -14,7 +14,7 @@ categoryindex: 0 #r "nuget: FSharpAux, 2.0.0" #r "nuget: FSharpAux.IO, 2.0.0" #r "nuget: OptimizedPriorityQueue, 5.1.0" -#r "nuget: FsMath, 0.0.1" +#r "nuget: FsMath, 0.0.2" #I "../src/FSharp.Stats/bin/Release/.net8.0/" #r "FSharp.Stats.dll" (*** condition: ipynb ***) diff --git a/docs/Clustering.fsx b/docs/Clustering.fsx index d846b6c65..e63ff8230 100644 --- a/docs/Clustering.fsx +++ b/docs/Clustering.fsx @@ -14,7 +14,7 @@ categoryindex: 0 #r "nuget: FSharpAux, 2.0.0" #r "nuget: FSharpAux.IO, 2.0.0" #r "nuget: OptimizedPriorityQueue, 5.1.0" -#r "nuget: FsMath, 0.0.1" +#r "nuget: FsMath, 0.0.2" #I "../src/FSharp.Stats/bin/Release/.net8.0/" #r "FSharp.Stats.dll" #r "nuget: Plotly.NET, 4.0.0" diff --git a/docs/ComparisonMetrics.fsx b/docs/ComparisonMetrics.fsx index b4a141aeb..056e79707 100644 --- a/docs/ComparisonMetrics.fsx +++ b/docs/ComparisonMetrics.fsx @@ -14,7 +14,7 @@ categoryindex: 0 #r "nuget: FSharpAux, 2.0.0" #r "nuget: FSharpAux.IO, 2.0.0" #r "nuget: OptimizedPriorityQueue, 5.1.0" -#r "nuget: FsMath, 0.0.1" +#r "nuget: FsMath, 0.0.2" #I "../src/FSharp.Stats/bin/Release/.net8.0/" #r "FSharp.Stats.dll" #r "nuget: Plotly.NET, 4.0.0" @@ -27,7 +27,7 @@ Plotly.NET.Defaults.DefaultDisplayOptions <- #if IPYNB #r "nuget: Plotly.NET, 4.0.0" #r "nuget: Plotly.NET.Interactive, 4.0.0" -#r "nuget: FsMath, 0.0.1" +#r "nuget: FsMath, 0.0.2" #r "nuget: FSharp.Stats" #endif // IPYNB diff --git a/docs/Correlation.fsx b/docs/Correlation.fsx index 22442c855..34a52d44c 100644 --- a/docs/Correlation.fsx +++ b/docs/Correlation.fsx @@ -14,11 +14,11 @@ categoryindex: 0 #r "nuget: FSharpAux, 2.0.0" #r "nuget: FSharpAux.IO, 2.0.0" #r "nuget: OptimizedPriorityQueue, 5.1.0" -#r "nuget: FsMath, 0.0.1" +#r "nuget: FsMath, 0.0.2" #I "../src/FSharp.Stats/bin/Release/.net8.0/" #r "FSharp.Stats.dll" #r "nuget: Plotly.NET, 4.0.0" -#r "nuget: FsMath, 0.0.1" +#r "nuget: FsMath, 0.0.2" Plotly.NET.Defaults.DefaultDisplayOptions <- @@ -29,7 +29,7 @@ Plotly.NET.Defaults.DefaultDisplayOptions <- #r "nuget: Plotly.NET, 4.0.0" #r "nuget: Plotly.NET.Interactive, 4.0.0" #r "nuget: FSharp.Stats" -#r "nuget: FsMath, 0.0.1" +#r "nuget: FsMath, 0.0.2" #endif // IPYNB (** diff --git a/docs/Covariance.fsx b/docs/Covariance.fsx index 7d14e30c8..74702d854 100644 --- a/docs/Covariance.fsx +++ b/docs/Covariance.fsx @@ -14,7 +14,7 @@ categoryindex: 0 #r "nuget: FSharpAux, 2.0.0" #r "nuget: FSharpAux.IO, 2.0.0" #r "nuget: OptimizedPriorityQueue, 5.1.0" -#r "nuget: FsMath, 0.0.1" +#r "nuget: FsMath, 0.0.2" #I "../src/FSharp.Stats/bin/Release/.net8.0/" #r "FSharp.Stats.dll" #r "nuget: Plotly.NET, 4.0.0" diff --git a/docs/CrossValidation.fsx b/docs/CrossValidation.fsx index c97a5e2b5..7202514bb 100644 --- a/docs/CrossValidation.fsx +++ b/docs/CrossValidation.fsx @@ -15,7 +15,7 @@ categoryindex: 0 #r "nuget: FSharpAux, 2.0.0" #r "nuget: FSharpAux.IO, 2.0.0" #r "nuget: OptimizedPriorityQueue, 5.1.0" -#r "nuget: FsMath, 0.0.1" +#r "nuget: FsMath, 0.0.2" #I "../src/FSharp.Stats/bin/Release/.net8.0/" #r "FSharp.Stats.dll" #r "nuget: Plotly.NET, 4.0.0" diff --git a/docs/Differentiation.fsx b/docs/Differentiation.fsx index 6484e9a45..2b98ff47e 100644 --- a/docs/Differentiation.fsx +++ b/docs/Differentiation.fsx @@ -14,7 +14,7 @@ categoryindex: 0 #r "nuget: FSharpAux, 2.0.0" #r "nuget: FSharpAux.IO, 2.0.0" #r "nuget: OptimizedPriorityQueue, 5.1.0" -#r "nuget: FsMath, 0.0.1" +#r "nuget: FsMath, 0.0.2" #I "../src/FSharp.Stats/bin/Release/.net8.0/" #r "FSharp.Stats.dll" #r "nuget: Plotly.NET, 4.0.0" diff --git a/docs/Distributions.fsx b/docs/Distributions.fsx index 3f769378a..120e9eddb 100644 --- a/docs/Distributions.fsx +++ b/docs/Distributions.fsx @@ -15,7 +15,7 @@ categoryindex: 0 #r "nuget: FSharpAux, 2.0.0" #r "nuget: FSharpAux.IO, 2.0.0" #r "nuget: OptimizedPriorityQueue, 5.1.0" -#r "nuget: FsMath, 0.0.1" +#r "nuget: FsMath, 0.0.2" #r "nuget: Plotly.NET, 4.0.0" #I "../src/FSharp.Stats/bin/Release/.net8.0/" #r "FSharp.Stats.dll" diff --git a/docs/Fitting.fsx b/docs/Fitting.fsx index fcf5c6bb2..cee5dc910 100644 --- a/docs/Fitting.fsx +++ b/docs/Fitting.fsx @@ -14,7 +14,7 @@ categoryindex: 0 #r "nuget: FSharpAux, 2.0.0" #r "nuget: FSharpAux.IO, 2.0.0" #r "nuget: OptimizedPriorityQueue, 5.1.0" -#r "nuget: FsMath, 0.0.1" +#r "nuget: FsMath, 0.0.2" #I "../src/FSharp.Stats/bin/Release/.net8.0/" #r "FSharp.Stats.dll" #r "nuget: Plotly.NET, 4.0.0" diff --git a/docs/GoodnessOfFit.fsx b/docs/GoodnessOfFit.fsx index 2668cbdf9..005715b07 100644 --- a/docs/GoodnessOfFit.fsx +++ b/docs/GoodnessOfFit.fsx @@ -14,7 +14,7 @@ categoryindex: 0 #r "nuget: FSharpAux, 2.0.0" #r "nuget: FSharpAux.IO, 2.0.0" #r "nuget: OptimizedPriorityQueue, 5.1.0" -#r "nuget: FsMath, 0.0.1" +#r "nuget: FsMath, 0.0.2" #I "../src/FSharp.Stats/bin/Release/.net8.0/" #r "FSharp.Stats.dll" #r "nuget: Plotly.NET, 4.0.0" diff --git a/docs/GrowthCurve.fsx b/docs/GrowthCurve.fsx index e5ad0513a..d1ecb4f80 100644 --- a/docs/GrowthCurve.fsx +++ b/docs/GrowthCurve.fsx @@ -14,7 +14,7 @@ categoryindex: 0 #r "nuget: FSharpAux, 2.0.0" #r "nuget: FSharpAux.IO, 2.0.0" #r "nuget: OptimizedPriorityQueue, 5.1.0" -#r "nuget: FsMath, 0.0.1" +#r "nuget: FsMath, 0.0.2" #I "../src/FSharp.Stats/bin/Release/.net8.0/" #r "FSharp.Stats.dll" #r "nuget: Plotly.NET, 4.0.0" diff --git a/docs/Imputation.fsx b/docs/Imputation.fsx index 528f065e8..3d28a74f0 100644 --- a/docs/Imputation.fsx +++ b/docs/Imputation.fsx @@ -14,7 +14,7 @@ categoryindex: 0 #r "nuget: FSharpAux, 2.0.0" #r "nuget: FSharpAux.IO, 2.0.0" #r "nuget: OptimizedPriorityQueue, 5.1.0" -#r "nuget: FsMath, 0.0.1" +#r "nuget: FsMath, 0.0.2" #I "../src/FSharp.Stats/bin/Release/.net8.0/" #r "FSharp.Stats.dll" #r "nuget: Plotly.NET, 4.0.0" @@ -28,7 +28,7 @@ Plotly.NET.Defaults.DefaultDisplayOptions <- #r "nuget: Plotly.NET, 4.0.0" #r "nuget: Plotly.NET.Interactive, 4.0.0" #r "nuget: FSharp.Stats" -#r "nuget: FsMath, 0.0.1" +#r "nuget: FsMath, 0.0.2" open FsMath open Plotly.NET diff --git a/docs/Integration.fsx b/docs/Integration.fsx index 78523e311..d8667a4c9 100644 --- a/docs/Integration.fsx +++ b/docs/Integration.fsx @@ -14,7 +14,7 @@ categoryindex: 0 #r "nuget: FSharpAux, 2.0.0" #r "nuget: FSharpAux.IO, 2.0.0" #r "nuget: OptimizedPriorityQueue, 5.1.0" -#r "nuget: FsMath, 0.0.1" +#r "nuget: FsMath, 0.0.2" #I "../src/FSharp.Stats/bin/Release/.net8.0/" #r "FSharp.Stats.dll" #r "nuget: Plotly.NET, 4.0.0" diff --git a/docs/Interpolation.fsx b/docs/Interpolation.fsx index 54bedc997..53f35af53 100644 --- a/docs/Interpolation.fsx +++ b/docs/Interpolation.fsx @@ -14,7 +14,7 @@ categoryindex: 0 #r "nuget: FSharpAux, 2.0.0" #r "nuget: FSharpAux.IO, 2.0.0" #r "nuget: OptimizedPriorityQueue, 5.1.0" -#r "nuget: FsMath, 0.0.1" +#r "nuget: FsMath, 0.0.2" #I "../src/FSharp.Stats/bin/Release/.net8.0/" #r "FSharp.Stats.dll" #r "nuget: Plotly.NET, 4.0.0" diff --git a/docs/Intervals.fsx b/docs/Intervals.fsx index 51c2b1ca5..217336a1a 100644 --- a/docs/Intervals.fsx +++ b/docs/Intervals.fsx @@ -14,7 +14,7 @@ categoryindex: 0 #r "nuget: FSharpAux, 2.0.0" #r "nuget: FSharpAux.IO, 2.0.0" #r "nuget: OptimizedPriorityQueue, 5.1.0" -#r "nuget: FsMath, 0.0.1" +#r "nuget: FsMath, 0.0.2" #I "../src/FSharp.Stats/bin/Release/.net8.0/" #r "FSharp.Stats.dll" #r "nuget: Plotly.NET, 4.0.0" diff --git a/docs/Normalization.fsx b/docs/Normalization.fsx index 4a2229d1d..4c68a45bc 100644 --- a/docs/Normalization.fsx +++ b/docs/Normalization.fsx @@ -14,7 +14,7 @@ categoryindex: 0 #r "nuget: FSharpAux, 2.0.0" #r "nuget: FSharpAux.IO, 2.0.0" #r "nuget: OptimizedPriorityQueue, 5.1.0" -#r "nuget: FsMath, 0.0.1" +#r "nuget: FsMath, 0.0.2" #I "../src/FSharp.Stats/bin/Release/.net8.0/" #r "FSharp.Stats.dll" #r "nuget: Plotly.NET, 4.0.0" diff --git a/docs/Optimization.fsx b/docs/Optimization.fsx index 4d6589a29..e0eeb3bf1 100644 --- a/docs/Optimization.fsx +++ b/docs/Optimization.fsx @@ -14,7 +14,7 @@ categoryindex: 0 #r "nuget: FSharpAux, 2.0.0" #r "nuget: FSharpAux.IO, 2.0.0" #r "nuget: OptimizedPriorityQueue, 5.1.0" -#r "nuget: FsMath, 0.0.1" +#r "nuget: FsMath, 0.0.2" #I "../src/FSharp.Stats/bin/Release/.net8.0/" #r "FSharp.Stats.dll" #r "nuget: Plotly.NET, 4.0.0" diff --git a/docs/Quantiles.fsx b/docs/Quantiles.fsx index a175be6d1..511d3fd0d 100644 --- a/docs/Quantiles.fsx +++ b/docs/Quantiles.fsx @@ -14,7 +14,7 @@ categoryindex: 0 #r "nuget: FSharpAux, 2.0.0" #r "nuget: FSharpAux.IO, 2.0.0" #r "nuget: OptimizedPriorityQueue, 5.1.0" -#r "nuget: FsMath, 0.0.1" +#r "nuget: FsMath, 0.0.2" #I "../src/FSharp.Stats/bin/Release/.net8.0/" #r "FSharp.Stats.dll" #r "nuget: Plotly.NET, 4.0.0" diff --git a/docs/Rank.fsx b/docs/Rank.fsx index 63ee06197..fdb1e7ae0 100644 --- a/docs/Rank.fsx +++ b/docs/Rank.fsx @@ -14,7 +14,7 @@ categoryindex: 0 #r "nuget: FSharpAux, 2.0.0" #r "nuget: FSharpAux.IO, 2.0.0" #r "nuget: OptimizedPriorityQueue, 5.1.0" -#r "nuget: FsMath, 0.0.1" +#r "nuget: FsMath, 0.0.2" #I "../src/FSharp.Stats/bin/Release/.net8.0/" #r "FSharp.Stats.dll" #r "nuget: Plotly.NET, 4.0.0" diff --git a/docs/Signal.fsx b/docs/Signal.fsx index ce3e7f2d5..9da9cff7e 100644 --- a/docs/Signal.fsx +++ b/docs/Signal.fsx @@ -14,7 +14,7 @@ categoryindex: 0 #r "nuget: FSharpAux, 2.0.0" #r "nuget: FSharpAux.IO, 2.0.0" #r "nuget: OptimizedPriorityQueue, 5.1.0" -#r "nuget: FsMath, 0.0.1" +#r "nuget: FsMath, 0.0.2" #I "../src/FSharp.Stats/bin/Release/.net8.0/" #r "FSharp.Stats.dll" #r "nuget: Plotly.NET, 4.0.0" diff --git a/docs/Testing.fsx b/docs/Testing.fsx index 2e33df7d0..ebd363e85 100644 --- a/docs/Testing.fsx +++ b/docs/Testing.fsx @@ -14,7 +14,7 @@ categoryindex: 0 #r "nuget: FSharpAux, 2.0.0" #r "nuget: FSharpAux.IO, 2.0.0" #r "nuget: OptimizedPriorityQueue, 5.1.0" -#r "nuget: FsMath, 0.0.1" +#r "nuget: FsMath, 0.0.2" #I "../src/FSharp.Stats/bin/Release/.net8.0/" #r "FSharp.Stats.dll" #r "nuget: Plotly.NET, 4.0.0" diff --git a/docs/index.fsx b/docs/index.fsx index 5b6146af2..c7ab85cd2 100644 --- a/docs/index.fsx +++ b/docs/index.fsx @@ -5,7 +5,7 @@ #r "nuget: FSharpAux, 2.0.0" #r "nuget: FSharpAux.IO, 2.0.0" #r "nuget: OptimizedPriorityQueue, 5.1.0" -#r "nuget: FsMath, 0.0.1" +#r "nuget: FsMath, 0.0.2" #I "../src/FSharp.Stats/bin/Release/.net8.0/" #r "FSharp.Stats.dll" #r "nuget: Plotly.NET, 4.0.0" From 00d3a4039dd9781eb9f0c575d79aac282c9b06bf Mon Sep 17 00:00:00 2001 From: Christopher Lux <59606965+LibraChris@users.noreply.github.com> Date: Tue, 21 Oct 2025 10:16:00 +0200 Subject: [PATCH 119/121] Fix incorrect function calls in docs --- docs/ComparisonMetrics.fsx | 2 +- docs/CrossValidation.fsx | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/ComparisonMetrics.fsx b/docs/ComparisonMetrics.fsx index 056e79707..67be4665c 100644 --- a/docs/ComparisonMetrics.fsx +++ b/docs/ComparisonMetrics.fsx @@ -154,7 +154,7 @@ let mlcm = [2; 0; 4] ] |> array2D - |> Matrix.Generic.ofArray2D + |> Matrix.ofArray2D ) ) (** diff --git a/docs/CrossValidation.fsx b/docs/CrossValidation.fsx index 7202514bb..64911c181 100644 --- a/docs/CrossValidation.fsx +++ b/docs/CrossValidation.fsx @@ -357,7 +357,7 @@ let shuffleAndSplitPolynomial p iterations (xData: Vector) (yData: Vector let getFitFuncPol xTrain yTrain (xTest:Vector) = getFitFuncPolynomial xTrain yTrain xTest order - CrossValidation.shuffelAndSplit p iterations xDataMat yData getFitFuncPol error Seq.stDev + CrossValidation.shuffleAndSplit p iterations xDataMat yData getFitFuncPol error Seq.stDev //creates an output for 5 iterations where random 20 % of the data set are taken as testing data set let sasPolynomial order = shuffleAndSplitPolynomial 0.2 5 xV yV order @@ -368,7 +368,7 @@ let shuffleAndSplitSpline p iterations (xData: Vector) (yData: Vector) = getFitFuncSpline xDat yDat xDatTrain lambda - CrossValidation.shuffelAndSplit p iterations xDataMat yData getFitFuncSpl errorSpl Seq.stDev + CrossValidation.shuffleAndSplit p iterations xDataMat yData getFitFuncSpl errorSpl Seq.stDev //creates an output for 5 iterations where random 20 % of the data set are taken as testing data set let sasSpline lambda = shuffleAndSplitSpline 0.2 5 xV yV lambda From 050e07a149c19dd86d3cea997ec4091ad1a86972 Mon Sep 17 00:00:00 2001 From: Christopher Lux <59606965+LibraChris@users.noreply.github.com> Date: Tue, 21 Oct 2025 11:18:01 +0200 Subject: [PATCH 120/121] Fix XML Comments --- .../Distributions/Discrete/Hypergeometric.fs | 5 +- .../Discrete/NegativeBinomial.fs | 7 +-- src/FSharp.Stats/Fitting/CrossValidation.fs | 1 + src/FSharp.Stats/Fitting/LinearRegression.fs | 1 + .../Fitting/LogisticRegression.fs | 1 + src/FSharp.Stats/ML/Imputation.fs | 5 ++ .../ML/Unsupervised/ClusterNumber.fs | 3 + src/FSharp.Stats/ML/Unsupervised/KNN.fs | 2 + src/FSharp.Stats/Testing/TestStatistics.fs | 62 ++++++++++++------- 9 files changed, 58 insertions(+), 29 deletions(-) diff --git a/src/FSharp.Stats/Distributions/Discrete/Hypergeometric.fs b/src/FSharp.Stats/Distributions/Discrete/Hypergeometric.fs index c64319715..cfda78d81 100644 --- a/src/FSharp.Stats/Distributions/Discrete/Hypergeometric.fs +++ b/src/FSharp.Stats/Distributions/Discrete/Hypergeometric.fs @@ -250,9 +250,8 @@ type Hypergeometric = static member ToString N K n = sprintf "Hypergeometric(N = %i, K = %i, n = %i)" N K n - /// Initializes a hypergeometric distribution. - /// - /// + /// + /// Initializes a hypergeometric distribution. /// The hypergeometric distribution is a discrete probability distribution /// that describes the probability of `k` successes (random draws for which the object /// drawn has a specified feature) in `n` draws, without replacement, from a finite diff --git a/src/FSharp.Stats/Distributions/Discrete/NegativeBinomial.fs b/src/FSharp.Stats/Distributions/Discrete/NegativeBinomial.fs index 9b69b855f..09986b468 100644 --- a/src/FSharp.Stats/Distributions/Discrete/NegativeBinomial.fs +++ b/src/FSharp.Stats/Distributions/Discrete/NegativeBinomial.fs @@ -374,11 +374,10 @@ type NegativeBinomial_failures = static member ToString r p = sprintf "NegativeBinomial_failures(r = %i, p = %f)" r p - /// Initializes a negative binomial distribution. - /// The negative binomial distribution is a discrete probability distribution
    that models the number of failures needed k to get the rth success in repeated
    independent Bernoulli trials with probability p.

    The number of success states
    The probability of each independent bernoulli trial
    The number of failures before the rth success
    + /// Initializes a negative binomial distribution.
    The negative binomial distribution is a discrete probability distribution
    that models the number of failures needed k to get the rth success in repeated
    independent Bernoulli trials with probability p.
    /// - /// - /// + /// The number of success states + /// The probability of each independent bernoulli trial /// /// /// diff --git a/src/FSharp.Stats/Fitting/CrossValidation.fs b/src/FSharp.Stats/Fitting/CrossValidation.fs index b7c6a59a9..c321e432c 100644 --- a/src/FSharp.Stats/Fitting/CrossValidation.fs +++ b/src/FSharp.Stats/Fitting/CrossValidation.fs @@ -153,6 +153,7 @@ module CrossValidation = /// Computes a repeated shuffel-and-split cross validation
    p: percentage of training set size from original size,
    iterations: number of random subset creation,
    xData: rowwise x-coordinate matrix,
    yData: yData vector
    fit: x and y data lead to function that maps a xData row vector to a y-coordinate,
    error: defines the error of the fitted y-coordinate and the actual y-coordinate,
    getStDev: function that calculates the standard deviation from a seq<^T>. (Seq.stDev)
    /// /// + /// /// /// /// diff --git a/src/FSharp.Stats/Fitting/LinearRegression.fs b/src/FSharp.Stats/Fitting/LinearRegression.fs index 27be4c5cc..66c50e4c4 100644 --- a/src/FSharp.Stats/Fitting/LinearRegression.fs +++ b/src/FSharp.Stats/Fitting/LinearRegression.fs @@ -156,6 +156,7 @@ module LinearRegression = /// Returns the regression function of a line through the origin ///
    /// The functions slope + /// x value of which the corresponding y value should be predicted /// Function that takes a x value and returns the predicted y value /// /// diff --git a/src/FSharp.Stats/Fitting/LogisticRegression.fs b/src/FSharp.Stats/Fitting/LogisticRegression.fs index 95bf061fc..296dabe88 100644 --- a/src/FSharp.Stats/Fitting/LogisticRegression.fs +++ b/src/FSharp.Stats/Fitting/LogisticRegression.fs @@ -190,6 +190,7 @@ module LogisticRegression = /// Returns the regression function /// /// + /// /// /// /// diff --git a/src/FSharp.Stats/ML/Imputation.fs b/src/FSharp.Stats/ML/Imputation.fs index 53ddae054..2ff7ea84c 100644 --- a/src/FSharp.Stats/ML/Imputation.fs +++ b/src/FSharp.Stats/ML/Imputation.fs @@ -34,6 +34,8 @@ module Imputation = /// Imputation by random sampling from the input vector /// /// + /// + /// /// /// /// @@ -71,6 +73,9 @@ module Imputation = /// Imputation by k-nearest neighbour /// /// + /// + /// + /// /// /// /// diff --git a/src/FSharp.Stats/ML/Unsupervised/ClusterNumber.fs b/src/FSharp.Stats/ML/Unsupervised/ClusterNumber.fs index e9fe0579b..e202526e8 100644 --- a/src/FSharp.Stats/ML/Unsupervised/ClusterNumber.fs +++ b/src/FSharp.Stats/ML/Unsupervised/ClusterNumber.fs @@ -28,6 +28,8 @@ module ClusterNumber = /// Akaike Information Criterion (AIC) /// /// + /// + /// /// /// /// @@ -299,6 +301,7 @@ https://www.datanovia.com/en/lessons/determining-the-optimal-number-of-clusters- /// Generate uniform points within the range of `data`. /// /// + /// /// /// /// diff --git a/src/FSharp.Stats/ML/Unsupervised/KNN.fs b/src/FSharp.Stats/ML/Unsupervised/KNN.fs index 3711ba4d2..83f39372c 100644 --- a/src/FSharp.Stats/ML/Unsupervised/KNN.fs +++ b/src/FSharp.Stats/ML/Unsupervised/KNN.fs @@ -207,6 +207,7 @@ module KNN = /// Predict (or classify) the given point. ///
    /// the point to be classified. + /// /// /// /// // .. construct and fit the knnClassifier before .. @@ -221,6 +222,7 @@ module KNN = /// Predict (or classify) the given collection of points. ///
    /// the array of points to be classified. + /// /// /// /// // .. construct and fit the knnClassifier before .. diff --git a/src/FSharp.Stats/Testing/TestStatistics.fs b/src/FSharp.Stats/Testing/TestStatistics.fs index 2670a9fe0..4c174f3d0 100644 --- a/src/FSharp.Stats/Testing/TestStatistics.fs +++ b/src/FSharp.Stats/Testing/TestStatistics.fs @@ -10,15 +10,12 @@ module TestStatistics = open FSharp.Stats /// - /// Creates a new T-Test for a given statistic - /// with given degrees of freedom. + /// Represents the result of a T-Test with statistic, degrees of freedom, + /// and one-/two-tailed p-values. /// - /// - /// The test statistic. - /// The degrees of freedom for the numerator. - /// One Tailed/Sided. - /// One Tailed/Sided. - /// Two Tailed/Sided. + /// + /// Numeric type used for the test statistics. + /// type TTestStatistics<'T when 'T :> Numerics.INumber<'T> and Numerics.IFloatingPoint<'T> and Numerics.IExponentialFunctions<'T> @@ -27,10 +24,19 @@ module TestStatistics = and 'T: (static member op_Explicit: ^T -> float) and 'T : comparison > = { + /// The test statistic. Statistic : 'T + + /// The degrees of freedom for the numerator. DegreesOfFreedom : 'T + + /// One Tailed/Sided PValue. PValueLeft : 'T + + /// One Tailed/Sided PValue. PValueRight : 'T + + /// Two Tailed/Sided PValue. PValue : 'T } @@ -61,10 +67,10 @@ module TestStatistics = /// Creates a new F-Test for a given statistic /// with given degrees of freedom. ///
    - /// - /// The test statistic. - /// The degrees of freedom for the numerator. - /// The degrees of freedom for the denominator. + // /// + // /// The test statistic. + // /// The degrees of freedom for the numerator. + // /// The degrees of freedom for the denominator. type FTestStatistics<'T when 'T :> Numerics.INumber<'T> and Numerics.IFloatingPoint<'T> and Numerics.IExponentialFunctions<'T> @@ -73,9 +79,15 @@ module TestStatistics = and 'T: (static member op_Explicit: ^T -> float) and 'T : comparison > = { + /// The test statistic. Statistic : 'T + + /// The degrees of freedom for the numerator. DegreesOfFreedom1 : 'T + + /// The degrees of freedom for the denominator. DegreesOfFreedom2 : 'T + PValue : 'T PValueTwoTailed : 'T } @@ -107,12 +119,12 @@ module TestStatistics = /// Computes the Chi-Square test statistics for a given statistic /// with given degrees of freedom. ///
    - /// - /// The test statistic. - /// The degrees of freedom for the numerator. - /// One Tailed/Sided. - /// One Tailed/Sided. - /// Two Tailed/Sided. + // /// + // /// The test statistic. + // /// The degrees of freedom for the numerator. + // /// One Tailed/Sided. + // /// One Tailed/Sided. + // /// Two Tailed/Sided. type ChiSquareStatistics<'T when 'T :> Numerics.INumber<'T> and Numerics.IFloatingPoint<'T> and Numerics.IExponentialFunctions<'T> @@ -121,7 +133,9 @@ module TestStatistics = and 'T: (static member op_Explicit: ^T -> float) and 'T : comparison > = { + /// The test statistic. Statistic : 'T + /// The degrees of freedom for the numerator. DegreesOfFreedom : 'T /// one tailed/sided chiSquare pValue PValueLeft : 'T @@ -158,9 +172,9 @@ module TestStatistics = /// /// Computes the Wilcoxon test statistics for a given statistic. /// - /// The test statistic. - /// One Tailed/Sided. - /// Two Tailed/Sided. + // /// The test statistic. + // /// One Tailed/Sided. + // /// Two Tailed/Sided. type WilcoxonTestStatistics<'T when 'T :> Numerics.INumber<'T> and Numerics.IFloatingPoint<'T> and Numerics.IExponentialFunctions<'T> @@ -169,9 +183,13 @@ module TestStatistics = and 'T: (static member op_Explicit: ^T -> float) and 'T : comparison > = { + /// The test statistic. Statistic : 'T + /// One Tailed/Sided PValue. PValueLeft : 'T - PValueRight : 'T + /// One Tailed/Sided PValue. + PValueRight : 'T + /// Two Tailed/Sided PValue. PValueTwoTailed : 'T } let inline createWilcoxon<'T when 'T :> Numerics.INumber<'T> From 1889d5c000856ac920ae9cf8a2abcec366ef8783 Mon Sep 17 00:00:00 2001 From: Kevin Schneider Date: Tue, 21 Oct 2025 12:01:17 +0200 Subject: [PATCH 121/121] add release notes --- RELEASE_NOTES.md | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index e930eede2..c9e8d25c3 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,3 +1,32 @@ +### 1.0.0 (Released TBD) + +This version marks the journey to our first stable release and introduces significant architectural changes, which obviously are backward incompatible. + +* Decoupled vector and matrix representations from *FSharp.Stats*. +* Integrated `FsMath` as the new lightweight, array-centric math backend. +* Updated internal references in *FSharp.Stats* to use `FsMath` primitives for zero-friction integration. +* Improved performance in core operations by leveraging `FsMath`’s optimized routines. + +**Description** +This PR introduces a separation of concerns between statistical algorithms and low-level numerical primitives. +Vector and matrix types have been moved to the new `FsMath` library under FsLab.org, which is optimized for performance and designed for seamless interoperability. +This change keeps *FSharp.Stats* focused on statistical functionality while making it easier to maintain and integrate into other F# workflows that rely on common libraries. + +**Migration note** +If your project uses `Vector` or `Matrix` types from *FSharp.Stats*, you will now need to reference `FsMath` and update your `open` statements accordingly: + +```fsharp +open FsMath +``` + +All existing APIs are preserved with minimal changes, so most code will require slight modifications from `vector` to `Vector` explicitly, along with namespace adjustments. +Previously, arrays needed to be explicitly converted to vectors - now, `Array` and `Vector` can be used synonymously, removing the need for manual conversions in most cases. + +Other Changes: + +- [Fix incorrect F-test denominator assignments in TwoWayAnovaModel](https://github.com/fslaborg/FSharp.Stats/pull/350) +- [Update test statistics to support generic type 'T data](https://github.com/fslaborg/FSharp.Stats/pull/348) + ### 0.6.0 (Released 2025-1-7) * Additions: * latest commit #529c2c01

    CJCzF`?duQmbsFsauk(zv}YDV9AG~D72oqTxg!U>!YFzVzGORcCII#FS(OF#}XRwgz+raJ6Jdc9v!kAP?^_TJ*V z&EssZq%b|FPe43`DS5hNxgS?_dr-w15|9Aiu25RhFrptUykxtK2?%==<(TwgezBIq zsHg`f1Vqh1&U)}^Ps`(MWkn)W0#do}hJ-TLzKe%B;!IAO;e1*2g{r1_r)wv5B=4CM z5Yb&hm;2E0Dz$!+?n(;+Vpb&-WJY!_{7t02u+o=nATOupsD)tApo+Tje2X|>dd1gad*6=ns$CiLd1;>x%PqGVh0mcaPB$( zkz=M#&ICkZRhgTMrs>0)jK>7!IRY}a@cGz&PRBW=)#Lh!I3JSO74O9@?aWRRRVU#> zK$0R+iz`O<5~_D=V)Aib{IU!)hdtH4>y#gd)m;h5cW3^y&#vbQ98%6(s=)aHc9MpR z5-D4g?`AG(xe<^mAIGivwmg(C6EfJ#aQ>l#(`V6OdpSb%Xn>MC0l5|a^oAj^?8S`l ze5YUF{2|+mGj9dA?mwb_tBc=*fKb*`u86yjMp6Dix8K2eK1Nl}>>aZ{29)B8YdD|F z@Qk+~Vb|Vy@~oAOCjk+Yajn@i<$p3C70#~0`CAOZ7e)6Wd6yfg6~w#IdgqrRBRJ2&l)HEIE>Kw_^bvSbm2GoR&ZT_7M&?GM#VJQmwWW>M4-hx2@qvJK2S z(OXl=DGw!I=o^XV_~9QAYRBr_7N=+arL&`*ikM@a5W-BrA&4_EWb6A%un8Bn5$2UrurQ}n#(kPGm5S+soaDF z)lpNHGNz09%qe30!;Op_L|e9Eu)Y5zTIm1MdCOGx){>( zCfZT%Qe0sAM=~PvP2~YFrb%vf%GwsuSE9|7r!s+vY|Ui-~fGix+1@Wvb>`#yeL zeR0+b=u10uU~KyOL$9!au3#INN@JX@+S+*1qe z);&)ASN_PHKSkaP#oi2U3GWcTG>Qbyh7Tkqq%8&7r+A6xPa%XP-j2(Q#Ro>-zpD+k zokzmhwVD-r=bg@xoftb#x{S~>KMi91lCGMS5&zZGeid;jBGo>Y5i(`NYU;%_yoN){ z7iL2r1n_$44w5MCB_PR7iE{n?TSYDE2c8$ot|3{~A6W$1_IjV4;yLuebs357!M)~1 z3|_8I+`nGEbp~PiLh8m5Q*ohIcusR~%ul4ZaIEicxZT&l0cL-H;TgnDH9ynip_Z^6 z+lz$=xkaSi!D^QF?Qv(3PloCXVyj4HPgSPdOk3BgWUl|n9zYE*R%&X~drNOK0it6v z#HjV_)^D9F!r^QR$176RNzf9VEjuEo39PK++Z^aMNKipuhv+MkW@9DhG~DX+f7joq zw$8gu3(Q$AV@qAeT|>x8EiWo>+DvtFkuhHdoe89@QS^K8^pm_M^}!9Zv= zUQ4#-yTuwp`APGkJ5~3J=MB@f_NrBc-dMkQ;Xbc)Ck1J>men$Hlj2Q1ji!9t#d1fU zJf9gvoj;vt;#xM}<<ntj?%Q-%ZO=*ah82jq~T*luFq$7^drk1^9NYO<0;MZh4P}VjUWSdy(Dj# z2`73Ujrhjim_+FNxI9u^t{$>|ev-NM1cry{I`!-68(-+JGLs*4(*0?mmyJmAs?JXChRDh+5(0*4wk`#l>$& zm5I@+v6qExOK#~OQf{5nyg-CzEDEwz)}*UMeW>4AdAtWn*=8s;_4alA6qj_WW#Ira zz1wMI7j>PxgiCpn>${)G(UynZSGMY3Q{C-3rk^&2j0b|%?UIHOYgtOa9qDsOdK-x> z8P&K$y4*>!h_XfG>Lr@?>P%TJI!$xiOrjOUm7~z_wFxHpwv9DwWXCE(s;og$8Ji`q zsZu_e%Djpw97wu^KxW|5?S#kh5uC712eb0}uXhiPoK>AO7-;!X~L{+NljC8X= z0`D|(OIeIhagyzJQkwkzS5M~=9>39E+99b(OSa;pem2X3LjoW zrdkWo=)Un5X09WV4)p?KajHaUG{Z|dv&e)zNzBaHkA?{S7E2fO z{rOt+!Vb<`DV&{Wz%~>)_wciZ)Abi}r zu3(NSlT6X0WItF35r#)=rTpJvOgqi zQZE2%T{s)7@RaZDiNkjjV}B5#<#mbsgg#z-ey?`Ua@3yaulY$&y1eFt7`^kOJ3?ZGev#;T%E}H0Nh!QE?lm>p!A_xsUK@%mG}D7P=^T^3{WHk%D)IY+H^sIbXrHJJnVm=YtZF&3 zDpIc)R?^qY%4l2gxnJ?V9H1otD8SZwR$Rf z9AVnCcKP5~t<6PCamw$xxNq2@9o}w+x`VW=!Necw77-0<)j*w6h0A@O7Et56f=o&6 z99k5}J*O8aag791BvJi_A~onJGM8dzxvhZ5v0D3fg9VYdr-v~S^V;4 z0=Z##?hRikXZ`e3Ud=bmv&f~yQl_Vr+WzWiHAt-N77+DUH#v&=%!z8*v+Nf;mku_)3B#5d#=y&Ac^jZ*f9i<}Cx$QS$BjGHwl--lLfTYtQ@ zh;-aJX1GLL{A?snsz_{f1*tifcE&76`=yk_-k^!^Ysg^1=hruE%TJzE)I+`+l^~Y& zBlR=U1>KURO{7SL*v9pN3wkg58F^B&^(df1<9~O{QrS`cn+KQ*eJa3FEl$VeW%Pewt<_{g7)UB^5 z9TxuT-viqV;;i=e>Z&>osK|NFBCOl+FEp3T$~Fjb4P>5QM)I}BFp6m|Sy~-3CUbH? zJ=m{CK2_J+Ln5F{PIZU`?NDI0o|4>8e$!7nmij&!+AsB$*|@5<>AT6Z?FozIs8UVW z7k8&O_ueRv9+BHafhy56<>9VWpF^%?jZjIGqvfX2-ecl1_PlrKh~9o6`AdETSx4jx zptL7m@9$&pN}0s?Dj0@zZvD78bt>+%;DdRrM{B!WvYq)MiKb62CCn?>^?vO))(XzS zC7nAHKdTY2mwAN397455(AIjXPCKH)u%Gkz-gx#LYpYq^cizN>+40kitXDsgeLLFA z$7V)cC^F1WMcaRoCp9*VL8}uAzg(BuCe%xnanTbGc`qkfYkuE88rbi|4mAFLsv z1zei>r;D;@Ecad`cO*jXY)sOW>56=Pp2*ya$Lp71BK|$d?&67CXtCN(2~w0SC@Lo6 zI3Yp)kwKyvDJj~YTBVjuqiC?leK&8oCGlVN=RV)w;Rgat+S=+~Zxz?iO# zFOGVv*tYN=GI#4~!_KrHJZi~I!1}%R(dQ&^3+Oy}q+ygyz!z0CB8-Tu#azagz{t!w%)>H_OhJNg>b~F@|C-Y%^6`Oe zD5YP(>5B8DiY-FZ$Waydw5!8M_=O1z$}y)F5CMashl-p>YI8WFCkHOCAmh!S-x;2! z=<+^zIoCD|x34|o@+YDT2h_qf+E0uTp^m3AD#z328ov}57{A8-XE{h~Y3mmsd{VvL z;nZ}11npAwuw@%RGVa5pKbOJscm2_?(5+QI&4_e)#W0i~H;6@aoKy+p_^AF2>rI`| z8plSOxGuJ$R5a?xIRvyW%wQqZ22+$oEpHsWBJ1^TEMRhjtu|vWb1pksE*#nwzl?Fe z4_ z$9e1S;t9lI#KT+HKUv|#?&SjF%X7#{!@K+4(tjKdli69xEVGOd%^N(8C_b<6l1srE zOhG`l7PIar&7cetD0K~%?k7Tze}5&y7l-_Gx|&Wc(Mp0+7QeGPbl`bfz_eUKM=dGJ z=yIp-TICD9c-2nb^n0YJv6M{MJ$@r>@WPDfMIb?+|JY??bJC`~Qiccl{NXz`>Of2# zTy%os(dfvD&vT=gg@deX$U!~*n{}^SZIh<3yNCCR>3z^WMEABke4pk#_N{KY=w61U zgj>UsyBp0i7DU}1s9zJjgOY|-F}7kA`&tPtyl<>kV^ZWFox4fEq}2Cy2Ah@E*3t2l zA5eorUr7$8kBcM;H?ddQ#Bl^H-?+0{mm!AKL+pgqB+)7+G^b^meq5%dXRQ0;rLKNN zS@X2qN8jbIUXOdprd>vn#wJUTxOe$ya^iKQ;~z~SV(k3&`isO>kDuqit!|%3m^+u% zZ`^geD3k2id4hcf=}B$7F_KP_yzPjIO&E^Hac%4EXgf#I>T%hT_S!fRnnW63uYUak zPdxFqExYweP!GXGO$cz-mtsyogFGTZ87Z|WoWgVXPAR5`#d;E>Lh7X5j-xW(@wMUo z{B*sTck=m%g9nS^UA1FsUg7<*|J=%;d?Q-=?8Y)z{FgCo=F6_-+#h$XxLiGheh{WH z7iC-J8Hq++uj3vXLc12QR=)2E%!K@^x$8nckIpP(?N@fbq;4-M@+&6Mds489^{cnt z)D+rv#I;Q5i#a6$BX50nUTdvREh9aDl;!6dcBxD=Eoe!I_f^qXn>{rv*mB#-_u<_T zKVw@0CU$W)VfMqkj^kokKGUY9+Fk@7~Bwr#gxgmzFS zmd%HnyFDY7bAH-R=V6nQZ_{^<8z3&!nOv;;X>_)8NYwHVd? z>YDZ}m(}@>V#C)1tM8s`ZQAkb-sMdHN$i#Dpd!cki2-9SJI&kdlX8U}= z_hoF_@$3;g0)F_>DcU$~{)NBh7x9%fox5!{58dVRW_IprK*Tk1*gK3#jf1#J@rQ8- zvgIgi!OUa&d95$>jywu|Nc*aQocN1zf8wga`q#X}$Zq~OK2v7*mq>@3hDU`akmHQ~ z@2H=bUoFU+Yw0teMJSzhyT>duOC9uHc&)WBA`?c1y_PNaRbrn{MKxNkBCo>a$84Qw zTY?4&M}E@du1U2cF1j+M7C(>8thjj*p;UUh%zJlIl}ZPe5KY+qt^Z#<##3{2bc)rg zK-)d!crE5*IvH<05Jx*o8lNb8tp&6AKv_*1p_O(;|AYRrSvS`F;7Q)=d?F3vkcs+4 zI*4#b7o@<`6|pmf>B-QT-40; za__tMY2SzX35-*Vh@p0+GkG%4npQPn7TaR5H#pm0{2O79ZqjAxMJ#lfyUd!&o!@MY zL5KPJGG;hr7Ix%~u&0~K^lfX>6^#7muxhe>!zAtHe*SOv&}Mt?-_`>*uW!H~*QWhsxX;%AJih;Jy=nO`dAZqs z-#mY9#!vpp9*)0k)-N{WUz_!}&3NRW@omaKitmrxq(5)Qi#OXVoALNR;>Y(xZnh6M zuZL{5zyD>u$#<<~jU}^>qyCi;sb?qdkMu`+K)CuRUxwHZr#w5lper2m;4AsG`aj`A z28r??*c}nujJN$?`-}LxW<4dy6}VM0E84u4*}8&=ePR_bDw-C3{3L1YfyNs0Ks=u@ zVC`#r{NCMi@md7LUfbd=Ps(YTIN|6Z)5`=TniM5eKkt)^(P=*ucane*d0k)jzu!>O ze8*=k*Y}_H;(IFC5+i;c_kZ|ZUXf3I&AP+pcQ^C@l=q+TYlz+-*D6w?b8M+a#rWqe z1y`|B*#x5I6H!lnZ+HTgrP$HWIFBqjk*e`MpiDXY<-jTD`elS);!JzdT-SbCL| z^-*5`Mb@2?WIE>l0;DK+yTMN3JPURakLCsnS7P+f_5-lIy2=tI7v`!%K0Fg_=Y&G6S1I!~`A*v_ zbefv?cHnrzC!d=UwN`hPIMYhM8?0dRE+()X!nX!s_u0tikqc`lGt&4mH73^po&cx#sxa(LqlRq(fQ;l{+kT3XBu1IH!VJHbIC;7t0 z%bJ!j8u60h<0TUG$b)&yc&`=Jo+}2lwgP|GpWh3=PLb$f=1VR3>PXEn7V@QCL4UtQ z%QuCQE=tu&%=uYuPWiX9LiG*~l@IpMVYQMkU0PTLvD^wBiMp*zn5O=rCfPG4fqKuy z2T6KYu>8~;A!`GKOH3Cnf*tRzVFzRNn9Gbk&dE>Qq}ZcEz|73&jD}{%16as>?S>z& zVJth&I8fNy#7v)CqnK7*!S1$OAYNM2?NL>WZ{x;iv3I3Iy22~Qc-A! zvMq~}p;yRSOb9dQ&zDI&p06z@MVW<5QWkm^%^OMOwGQC;L003SZbe+CC>i%7S$4NU z47scWB7x6!>xFu=-kFVKkGT`d?zIIdDLX0KNO#X*I#r*!V1@U)r^dJ?Cuz8RF?%OO^~}}W_vH-@*GxcT_*RMzX1$Lj1W#UkRYi=(DlAE) z@g?2;=%d224fhZD6m>;@Rr*NonxUBAO9FmAz{oi|IyQqQe?7k`VLxJ2DM)(zu3`yf zS);ij!?Pb#WH?7IB`RLv7ykIplhP4P#n>x9W8k}#BAHq3YUCu=olkkmpDEt`Q=?%Q z`N=t~!Qd-h4o|MSg`3;nI)Nq3@l;)DKN}gzQt(O3!*r|IX^xuMN26QBk4F!ooRe$V z^;V|Wed==$O*%(ke#;_YBhg)457#_JRk!l+FKj1ZM|hguF3D{3insUa)^cCLxWb2X zzO>tPlc1MAxV-E}_+!eQ55FC#cXmTF5u`KRVv&~nGo9%+Z%Ey3Dl|Gu{o@hVzCFhD<1eaI_ogBJm{d5?UsW)SJ zbTzT!jJ#NOKgR?nMd?_G-BEqMc$!`Rc^KY5ZyOH|4p^P!^d@3v6kovj)BG3SS<+)) zEC$c+A6vo};?7V%2}-&b*Xfwm5V?ZgD`G4~7;~um%U3CDxmGducWaCTIgI;upSrKO zgJ=c2YH7~zdg7w7r{>%z{_XSFX8E0Yca{0|DG^EHFOz=hFATZ|+!=xg& zLoaeaYxH!1YTo;uQ6&La?hPUejRlG9*XY(>O&N71)r}$X)b8%)xq77Us&+OSWlORU@cy`$jcyD-C*jotrr&#?^a z)33fdk6^|$vAN{(YSAe#`Hc)pCa{lmx@;_g*8=?mGPUItXR(#G5rcqzE3V2^Des~u z7BKH^vNjj($c$;XJmRQMUdH&6|Lnp>k6k-){46M^JV|F1}uFt=iQcWA=&Ekxj9>gM$cl zFuMK5npO0sbgf)RZ~ZhlslSL_RXuN^8nZoK<VNukojVn%poKlOHRX9rf;VcKqu&suBFQNo*_Fwlfb(C?;<53M`T^nOl59 zD(c8}%u_kvXEQWaE(SFqN4h5O@B1|AVcoH;-gmqMkz=m9yca#m23M>~2Kf7svrlvV zG--Nvv?-@u|IRjy97c`dVaY?kFeMMUDv=3fx=QJIT89lKQ^Kr}yv;094i-IOCbwfd zg}ts;6yfWKG}`IqXFJA<12MI2^s9)Q+wL;ui*7p}=kvZOC&Jfn^EAwVpuy}`D&;G5 zyrtNau+VFCZ(^H?Js)e$B6XP8cwtG1p`Ci;@lA$v$TY@agUF8Jn-c% z=@6!yR#^N?zG$1>nG&8U-afruE(QK-BGzH;zxpVim&G_Txjn!h?jfnqdk4<;L{B&~ux?JDBVp;jJ;N^04E#<&A`v6^jFomAuRr&vw1Aaq~)7jNFXIbJ;*UprZpznQ5I6;Lc;O|Tt| zGv)vR^eeY@Y)NA=CN6$=u12kAPpnW`OB6lmuWNIG+2Nz?qu@`&%^Wkg~=x1j+ws-p@)iRY7{o;fxQk@)@1aI z%#gduqqzxAArulpBZe-v%Z?ugnd(9+_TFnIx78xqvma+j349;Hj1v4sSr zq{T(Z3Yil7mqjY&)=>7xeNLgTqIz2HH}H4$W?cgG*~VIxT`NDR^4-H{>JUIVr2><7 zk$1Id8UxJn-6^oN*;gwbOpq{7ts{^az7E7pJ{lZn&U&1Lt#_>}{S+k3roIz0e5yk;atUaLH+%dbUTlzpR_&q^;j;_rRE%gNpL(= zCaULk1GPUOaddkJi23w-7K<6ihm!Y3v2Hyg#I9=;Tors@E9xBU*nz# zVuC(;qa&gA#1QmAz_U3R2{=AI+)NWwws36Iv&5>N2V$wpJVY~P%${C!d#-z|0k+>C zJ=^{sD#L_gx!c=!0Kl<&c;4Wb!^&FjrA;E822G2+3wLD2sjsu)2Gt-9UQ5m-Dm^RH-J~Z1`<}q6>SVryv?7;#Q^*O;byxCX+L3+o4eBU!y zB#{^2*`k$-)z~lKQHYHEo_h3ro4Uhhxcdd*L3%|nmCQ}FJ7@iyH#HIvs;?Iep%R{x z!}(l&5rhO3WN|ByV8X$mghNcQ{UrMxn_Bp&#$oH>(oc~5g3=I2si**}H zM)A_GpJ5|QCxN@wcyB-HQezmLI0G`QOTaQk$PBZ!zisTBo7cAZHvkgX>AK9Mj!%&b zr?`1CdqA;t__Z#wSGKs*s!pQr#{kAo*3CDe-qG}riXLW-p8>!)z_254+?*A8uv~-k z?-uZ3$|CB5zUavWjlfv zUc19pNd1HQC!oqibb6~l>YO|L;DnHM8?a%#Qk!+ATQ{!i#G|HhfWrG%_Mv8oZ4P&Z z%l$VefD}vYYXlJ4J zo4mBey{&K>Z%!7O|9a>BC1CP1C0Ji{)PD&TE_#yw&-uy!N)e4o35z3l|MMjx-(FzH zly=`EIabp2U0wWE?BZTL7H^+nKV|j@iiKJ@WPV%Mp*6Q`Jz0$+8=$cfEX$!Llcjea3JuSUm)&td*-)kf0)U29#X2shk2X z4tfn;F-#xyJFsb&)h_}nnzt-}3g9MCKeRT$KUo7@X@!dp*0iD&jZ^A9jdp+#$4()i z;QniUyb2SvxQ9TS9zJ=e9;4gshZzMj9VdXq`>GwH#&F2?p$20^-Wi~nz2g*hVB!!~ z`YV3c`T{WZ<2>X3b@N9OQKsQ)+653=dFAuHX~t_GqsWFC)_(z%CR&qA_>!HwO{4EM z75jhyVd;U)aFe#5Nwd%UILCoES81N@FGqc7#`2zW&zuJm%&K=E7((mPw};lG7}o%c z8qXk)*8;sdYHkUHxjO)2ucTzeaKY@`C4N^LO2W*XbHz|UG1{uXTMrMXJ_A%dO`pVJ zrHXMkT-iH8@yEUrbAy)C%IyjdhYLofFu=O=DMkGy+@lPVxM?+%zCe5ZNs8NOUb8Y_ zrFfse2Z%Kf9T&B{e@0%0$FbY5o~@SgJOi%eeK2YkK_bJ{yHjSr8>Pc>~H18;k7 zN-Y#NFk~M0lwHK00R{(HbSF{avUq+(O(KgIKqt8clefVXG48;UYN8ARxc_>3>VrG$ zTExSATJs`#aM}LJ(N?>?;Lc;pgsUP_py$Swk0Dbb9`BS42*11&22*}~`El8xC=xw3 zZ!!3U8$6%h7Cph^dsa1Cegq?90n6ztFZXdXE@q=_@*sR_P)`hV7TKL!NfPHgf8p@w z`s37Z_m_c)+3JMKF7)+;f$x^MFU7&28SeI|l6jah${qcDx)3CWEZRFU!n`wIGq!&B z0XOLQKq%0ggQA#%<)-<=OcsdUF^Z?%LQo?-FZ;*W25PW4;nX5PqfsFe`N?td0pVY- zqu2j$?T7yU|E3?H>pOqz-{|A{Z~7d%zWO&jL&xjC>F?>A#^_fxAIZ*3%dS^zMg`v-=nWr{l8m}OhI3dg#Vw{C;wf` zzwM9z_b>nZ>@Vx1fAk;lf9FrK4O4fP1%LN9Oaj8^^z_1Ns(NMhZVqO1>ni{6-~ac? zW%Q1?eccNgWp>{-A`}?1#17Y ziu1s2#lvIzsoI*{Bml-Ro!UA<7q8M&47UA30(?n2@eUU0k;KDt+h(W90I*auo_&+8 z{?kq;{WJBf0khnY-d*suamlIBf ziJuIQwI{Q5RS>ALI}lT}75TPgu%zb9SW(X?XOw>|$k=oASU zTRs?eRgtIN`Ek>3avlaGJ-*_1eMd#mm+I_7&F%vD7=XB)nyvLPy}}N-A(#Ygt=;gC zH=9>nKnf_&aqli z_QsXI`&iHJ7?SvPhwCc{CjiN`?SLib$Y4e6#*XSSN*|x;?yO{f0;Cl-SoNqSz^|24 z>buiNDm*RQkqAk-08DxxuXQ4fPkTse`2$`g!8NWZ%>Bq;^bbGo(+WRA0y8)tTMSn` zLUffkX7@*uff8R%x~h0NF7Zv0t2{Xuz&CX^V|AJZR_kPckt***`1j$r-U^Y1Pm31^ zx{D4`{s^wE55{FZD4vM0p}GDf8D6czi<@!Us~3`=S@XT(0%*1d3j#@vhlee%F`JSn zz&|zEjGEZY%+M(*MD`pY0l{cu4wfqNlNb>Y^F%xu-YVFZYvt+pjPdJMoNx05@H*wH zrz^wOK?MoxhH5-DM{*BGWH??@FA2Oi;W35&~_sT#6aagYHm{fZg1E)4}O1y7~8*aTly8r}tjC&2NwT*lv z#m&{OCBgl;biXNun_KS>Vo=lUp!_#m1-KVY6_#ul1Y~y)Cd0W5UdCAVr8k-zA9vHD z_@*_##YHMizWVP*`NWY!FhFUK0^v`b2B#!%W+UE4?Wf(53by}QL|igD@38eC89r}< zKN+cX@20BE4oN==0$6#bigH7DJ7=&7#(V3H$g&`SmqU&CGx2$<{<$0jYQ6FB zE=!Fy(<{PzhfU0QpHcgTv(%joPezr>&LqqA%7~JIpVvU)gV{E#gEC5vWiAxnfA7%B zs^=ypPN?khseu7ZU#rNj-3}2Ni(@81aGI8I0s+?{9ehMETpeT6~Xx@!Tiqk#DKF zL^8lgOoCl`^?vB7Hn=7(i2w!?u-^LP2>Gr48k)Jo1_N%~(R(Xl>wEU&3Ff-wDiRo^ z@Dfa%!e02{6@|M%mIQonRgEoUC5TbV2@x2OM*tkhA}MAiE>R6f(GW#@60j<=Pkh*R zhMVJ~s(Xam4-|1%o71Ly0A?a|Ec1QfA;AAU^}1lHl85KE=Us0V1aRy5q@hbToh)qc zW`c4S43Ix?wLKiQY0`dEL-P*B537DuyfjTpC2D(6VPx5p4Cg54+RWZ2z#BZM>cr4N z0E@)2)SoGJtJ}nfpkpN%oT+gbo$r#n8lZHU?bma2mhIA`>5ZuRD>mOT zxA|TansmIGW{d!K{b}TVyg50EzsP2_;=tfa&ik@{c-$VegapSY6lb7|+dB^GZMqqI9(GS#enwN9UO8KcplPM742fSenW!2Lv$H;ozHC;h2^qX>*T+A`wnw zDB*(#V8BDd|M^=N(MU2wtS)|b3CF`3gkFE5P)%xiKfN{ z6LI7~{a|kp44@lQZwWY{w@cw9AD)>;`FF?Or_Hu@pgsb}e>(h1h8x@uX)@g z49M{&jxZK-Dsi~n;Gqab0IW4vNcD_vj+SA}ZbrO@!QJIEN0ayxWqu}nXxN=V0+w%$ z=(?ZMvVHX1N-0oD0uogPj5;a!#)lp%&fUF>08W7Y#M4doUE>yvl0JDD+}(pwfX=7>_m?+LcC{4iHee- z{7M+SomaW?BH>GJ9sS+4B@_xfNt&05fXhSPI-7j~4`J|-&gVHzF;qv7wL^7uQ1&iQ z1l|YDW~{cP!v|~V&69wu`#4v91NhFcmjZW9M^N}hT|soyM3e79y2{%y6n;_&?z&cW zSnAv|%llOH6aknw8jZ{fKBA$!opdgbdOrOz=lN-o@A$cnEV&A!rwen`EZP5MCLADAW-|~ES^~!;7PqHwtpp%4}%xnxkg#U+~W+5j-4|9 zK>6Fjw*z&!cSMyeN3J&*Bmt7t2RbY}Hn}}UJ?VM{sQTm9sG7J!MwY>(&YDv&;1-u> zRfmo=j^Q{Te((Sipp2}%qjVA~!$P6(f&mi-{CpHWCNL&{n~zYwA)^cdglU0>Zqf}s ztQw`vE@d#d{QWL2v)fmX#{~=fzV;!3_AYSaJHE+ug&Q00P&8`(Y>Z{p_to@tI#z2!LKxjSky;koNNzFSRC37!X@}zsYIdU_L-VsLZSf2`D~rO!FjM z*nVea`r*I&XaC`kcfA*q5=1n2su0_wdXhvu$TpPMxE zLNXBH7H#uET>4F?fNAT{6bgT8D_)FXRgyDNvEFddgTX1%4D91nh6%=|F*mNYApzv0 zUHjSmxN4d0m0=ul7@REB;dti#QEE{v?XBfS1W?=z+3*fKlf==#(&kQ10*;T=6+YgX z{5AC6HO8bB2|SEg)_6r^S0z-Wr#~#243`@-lxcQ}N7_}X#c!{p{5d?k&?}bMG{V+x z>UZOX!HqoxliH7F+)P*RQMka7K!(wpfKmPDTQVQ+x7!iJfXin?0-xe+>M{+Rk9YPE zz`L^vv(%C&8IgN@u%ziE_zUV-%B)al6GH)t0-qMtdV+sr?^0ul?*|_F{L#H+xD-+U zK2b)Fe`k3}?%F8=SYQukn9oyc_6j|1bjpSqq|eZNyL4+ zg!wKn>5gE4`fcJt9@Djg8=@&rla~k}aXlBNM*LD)F2-PgF9!x-`9>+O47{EL6OOih z8j(P&{R1Cco|z5dQbK2DSTei}c(wPcM_V_;^W_sKY$V{h@S@#a=tj9`?uA{2PBL6# zTs*vQOMpSoPxph%dn9nDhrJT!R9^MmSkjf`Jq(!m3K*n&BkGnlJUxEkq2iegQ%eW2 z=oh3x4MT_XFnC2jwOrSE#~e;8#T(OlBp~c|_uF!-a-P1W?iDnuCb zYaAfaf9W@$rO#O~)Gw-j{<`Cs3|AJM)YL33jeq(ru}Ps838UZ;u~buOLdmTr+!^43}mIn{6voaMBZ`!?{w8(tot?>|_g3?dQPD?&jq3zRgpYgp?8qq|5UwGcD;A4=f!0^1YP|41>b^894<2DTvpfF8ojo$i5L(8L_ zq$UajC~GT&3ns2x%y{~mbXOpOnvIhFlcDFMk776GNKpFA9jyf{|7B^+$?g5+Z}doD zT@^x9he&?aq7-M(`V50FmXq8iV*4eUPH^Ajc^ML*Z%c)ZZLu^V5kp5hKav3wqu1dt zW%2tESlv48%t&CZ<#beRLU2sw_77og#(01^eDi_x+=~IM>#{?3B}jmiyvw8eVz^rG z$LT|TF&Lm#en0n6Q~h(0E0<~@%3sb6MWH`>D^yEu5Qp)p*p$KlA!G9Z_= z2nitim?^*iv?L0T=28@Yk_gJ!K&e&X{j}N-7rau#N}b zx@M26rQ57e2}$>l7NGjitA~Bh`lqf2*XiCHybXhQXPqSBL=4q_Opt9P=0O4uCK>+x zDcO%te9NuqzrcWZcw;L%%@Rgx+t~q0uaLkdhLtRxQ?cz^{}S@nj$}9?cVTAY{Znte zh;$ZXek5@Ba~c~#eqQH;dsl29MZf^ZyG^fpqhY$IRO6{Kc}Rc|{5jvRBPEJ4aX)-# zI0>LJE0j&-q95akE15|bLfMZEPX*@h8qk#5<>IbKz~BjEhDB;F$S=!0fXEbTKW~Th zR8BR^X;f_5mm}McNx*~I(`%>Z`g{Zh;rri3kbn!rT8A|IldoC(Cs?;{Bmo@jYkUW_ z-_(tZWUTIFqvZekBe{M;;o#}S%$opq63{miXA#>!aqi=AdoR~;WeDQe|7MkZs!1u#An+x62NwuNvJr$OCI1V|^yH&ngf0?-#ld{q% z{e~(;=HW&amqw`rvVkla{ym5_EEDYSX6wedTata2Q?O*R$P|KclWwf7>h#F+%BFW#c?Q|bKGAr}K~c#*EbfHD#|scH;~k(OFM zP_67k+QR@vu`7k-rwn*$Q-!$IFeK2Z|FS0iZB3`U7kwnw8zeIr2@f^orhU&zB>;WTpA`;laTcP6=)V(KG{WXOVNCfbk zaaNrwudUsrR7C}eKmuIByv!@K649j3cVoi}5`fnVh#MDd?oPKNMhVg%qVU!B<6fS_ z1V5fZapeG%47_Yl4#b_Hpa?1V`a-UY1cLV8F1x78G}711X}fzT!|j*SqCVF(U3Oxw zPM_RI@dsm`<=pK|%~RAH^cc-Bcqk9q<12NyOO3b8444d1_`;bM$MK#tZ!~TuC_mFGOiuXV>3nqMDK@d z8Rd<>vP0mh%wjV9tU{RQ>PCNz)~j`=+Pg^L@HKA-;tYRJG0)dI@qQAVD}d>Zk)?)8 zz{lwdHZzp{M-;JRO2KK{X+cghW_vOa&1jtR_%n)Y%H8E7h(rRvVlh7Xe4v;?nq5`j zdz=jam>lIX!LcOvV%W`-=>`%Y#)=h`E&I%jeVjVL)gBMu(pXDUcQO?)J088T2uA{Y zT>0bA15G3}z$A0M<7B|n@r1}kGmqgFbwVe(6$-zS)9Yt&9z`e=2Qs(uBm=d9*YFEs zqqZqcTsQMVQ2jG*TgS&>X_fuaIkABP47j&2EI%b|J+gc1-Fj(*1fG@Vl`e{Ma8X~E zS5V>pFZsBhm!~;1=Nn_s}y9c7GIph?2Zhi^{*4dC(|8fJg@7euX?< z&(cchV0x_GhgzS;%WueaGO|_Nr6Od_ok<1~1P&YCzlvEl@5A_Z!v}>=TE?U$m0Ncm zbmn|5m6PEY2Fg=bpR~<_uRr_z))fgzy8B>tGrwHGPQHKpI*K2ZewI7FYbi8Xzf<}s z(HjY*I9#C)Y>#R0*K#6xR+|jZc-ZB`No=xSBQ^gf!2=19U#x^GJA`-tC^Lr8_#$5?et43I@!4oaiWr4W~oB@mbUVu(u)uG#d6+9LWU=C&H12z)NSTfX>#7MYUPz;gUE7bosDzYf6c^EaCb`lk_kW$T>=St)SUl zBiT&YESLfx`lnw19GP&wgZxO%dvb0w5lz*U;3BE?Q0kAZCPu4%@;(`AP%i(Y=YSls zsMwZ+rtBmYXzQK1;U#`|^3C#bw9+OeWNEOG&9IuKGw8Fp%fLqseM!uoFFEh)8Zi{| z$MB|tgq6bH{8*BoctwQ6>y|+Qy-|;hO8C_0B@yt;Wjc)%I&Vt1 zAN6xQ(evntN{eM+esyk5MhZ44_dA4WK|)T}+F0**iIy>KFU zeuuYOtg6?Q5R6?L(bK;9ikZ8GMb}mu74OS!`o1>9!l#unl{+kQB#;bcM5%*BD*Mq&0=654KU8&mOQ+)Hc*oC} z6s!(Bxd1d|Z5lI?WjHsVn?>cQGy%d)_7HIZ|z#BbwmhkslkoPWsCBQ zh$7&|9WJc8X@rH{XdK zT=1WM_0JJvKrndjPT=IgZ_U;^l0);~1>vGB1cq3dV_#HE$sxIdTvlQ(3`79JAzXoy z5{z-ScueD%yY%K+Ay(2=D$q%LkK2)3JKpe%V%gv?N^l;h*`t@9qyGtg)ez|i3Q$*X z^%NK@oFv{nB`3`z13fM~W5%rOh>g`9)Oj8ggKcHszbP|FDDIkUzDP2`2bEM(ai>?r zovD#(t&H-R;N18=tH``8FUz-;_9#ng&`8Dp7B_a|>1uealr-^C6DH+gt zE%^x`-tYFzTb&y0BcAJ97c!0~_$H6X2T_8%4J?w1j+zcfn}IjVt;xY4*{W~;1F%;l zzJyKNOeEldI#$qkO!LF*BD)e68Tg=aXP42_+Cc)f36c6Nl|TDmu=Pt{!geRF9`{^Z z_s2|-B1?@5R<@sZcl$Pn`5ZG8MDND0nkFH&OgW1T8)Jq*r3#ye97;zaAL3OvwwNHP zL7S#(w(oI`M7lNGyo?YQ{Vaw+C7ywO0`bC7Ivvy=DH~}rGS7;#gfMEv2lR*NqMc*0VsopnaUBbE~37~)4?Vsb-$ULC?r+eC#eAtwEDg#7I`p(GE z75nzlx-4x(JQFk}PR4S2@^aby(Y5hRMrO$7e)>)qpZ$mC*}EIH&zPWd8qchfaFWmG2`A1f$nO@y{YNbfjknd!` z#grXdx84^U{m5!>G!TXtUCa(~2fTHWwd~dMSLYe?VP=O)%?pCF6`GcoC6?~Cd}4(X z1}7Y+@(-4_s<2Sp6ARR@0&~sb&EN@pdqYiho)JQdz2`jaKe~2cNA%#G2px3TxsG#V z=ls&Il<;Sk4<$rXuTkv7%#b^q>Mc?sNDOhdbZUI6F0~8EeS6`N%m%%a(eYQM8E%m& zmZ5m7$qtDxkhJN3F7@g)V0eLSVS~%bq8PN=6^0kkLG*IbxUBY&*(D-k|gc|u>j_HohQPdYN+Qxmb$dLdOQ}J(6BnoHy)!b$B%ilb#*2wJp=P z&36vk8OG?S>_Wv)c934lFT%46TdVfj=b@7OXA^jsw6Ad&sCN9j57fOs%3bc?JZbzHii3j37D-gkiq zYI)HR8YWB5n*3o$aN zzp7wFBxDdm)Z8B_>mFLsuU*-u`-gk3CRw3TT*+Qhb*{W;E2UP4( ze1jjSOf3k}x=brvMm5+B zHOvTvkqSV^^qa1^au{;h+-p&a?0k?U<&er%FjN6n|HA&dFE<1o*$A;8G+*hp<$k=) z%mFzI>pFBD&dzmxkWp{Oz5->vxXR)eE~@2c>3OFDhXJ}l-6(p$k|v5$4D5+np@hWG zrf}n}LRf#Y`vDYGL{J!`)ig7gYFjmR_N}jif{=?$dbMU`qF#rU1fyc4Ae2xe_WDCr z^jRCdr^oGV0Tc~BcBrpf_#s!b$%%W74|-|hG?UJ}`C@>U_sOgs52VszB>-Y)-DQ3E(B(z+IN3C_TUVv1$d6uX z$Y!Yg2}qaz^je#J<4->lXnu(Abh1~ed(>7c*L9Bz71YR0meEr|TWprL*R`GtbTYV^ zchRbOGDZKm?iAz%Lz9gxgI?7Q>s2Sv$2Uhm4ESbv#{Dth*QJMWgX`d@&N=pAM}mbo)1NNfpl8;VPdeKAx2uh_ z^C?-mz^*xI-(u#h7k1VSEW?NF;6_f=h})M7top&LBA3{#AnoC3eaT=3Z#*?JLtUK- z^yMd>t9wEm;V!Sr`f`#Mgs(AOto&)enBC!n@SRzc8v-f*@rahk+N0>AZN$`05M8hjKzEn`lm`aQ{n&wX90PG~V-S zEg@E@@1c2kDqLG#7k@>y=a2ykkJEptB^KN>+xmEMDw+!FGoW zt!XFTwD37C^g{3lRS>2y^hLJSv{>%x1x$ zTfL`PpsD}Hgd`v2eJg;IImWN|wY9{e&j=TEs6w$@MWdz-wFYGns{5CW$zR3Cw(}0P!bq^TB31&$G;tgKWkb{(4 z65UOaEEwg=G^c#z1Yr8(JHH~>T(r|QWx5MuxWUB|$2}f=_ky$K3`vSkF3{UGE0JrS zPa|W;-a6zH2PnR?YLk!*!=uf)TTt_z75rw5XNaHT?j?0#>53#{22X9p#0v%JxYi2{ zJ|o=dz{%_>vvZd`MV12QiTnc!(4enHKOj&_t}qwsrH~*31!hiuZd1$^<#-M$1n2xI z-vuaremqYfWT3k{(0U=p1Cqqg9C(F3&jUNgUcct$27@P-DBWbAMtBIFhbi`PfQrIo zcqI8UZBdx&25%x+!A3#B*%Puc3=UWVu8b`cNFX-&bv#b;D|?5RLVzPJ*f(J5(a*}S zp1FL;5$R11M%>IgHh@d>eZ_^;#$^aV{POpHYeX#C?-;Nh>?L`@lbIVYqyY+{xE#52 zB_$rPXupK|OzgwRm=V}YM#=>`Vvb@9kxdET!Ygb1wZI1E62>R8uyL!LKVb}>*GfMFMC8f{Fy)OelU7|?udlG>dn|R83 zZ#xj7+ye7b|A+mdEl+(;(wm%d5{(L5S%cK)&J zp6`u^wq|^g4A;_5M9b#ekT35i-#2nW#v=K}P%Tp&T^+CTjwBnDy%|nzzbJ#}H|Dhr zG&4d9i(jHMr!;&t*$FOv*{GpcO)|Q-B3hrh_ddEW+(-neDVux&Kz~tzBgwLGmd1kT_<@-l-DD@E&HK?gu9fJ~3LT^R{RN*{d@R ze9r{=iRfD)xtI2238@6Sd=tq!bWZ@E*`cA zYVkwu@eX{?>wXw@6DNE*yUPuYer?X)tu2t$xce0(oMVG1&4w{2+gIu9hxb-=WtpG> z+k{YO=7O#~JIcF~UewTV_Q+C60ESDKnsmAb&Nisro2LF^%3ia zFDc|DJ>pw%;(S1xC#v@HJ{KsHWW3BvXm7)O4X>kij04QMQ-mcO`qSw8=||-s?W|yH z6}Kq%YIfGMS-sVJHB4ZKyZ3OFQ{}9jPd7t-6)mWf{EaUWGwVIQPjCTuF*!(Dkp4}H z<;qBUaNRRGV}d{Cr{PWSaCSyA+l0{s!EYVhU}REFr^MzW-EDkYLR)?=u(T~MMcm3a zZu1kIgF})X9B|++ds6SL-E+u4@>GQdBw;*gG^oinx1-teb@iYJ3r?z(=%1QRPvR?N zjz6aaB{-CML@eePY!%JLjnas~bMGLEYhq&y0zYysUX-Ku`&F^TJzKo3@-=Nkkk_3X zjJN1!S&kuJTppXUrb*`n2jiBn{~~%2nr)G1l32nGsRyHqL`NA_-%iOvqIcBnyCDu$`L1y}rhb1uzlRbJiRH*w zzU#+Cy#)3tY(B}v&WLJ4n<5YRB_{6r`i{i#0#yXAtOgedmd(2{ z$R~(w`CMj%5U_){L*+`Wm37QrlgH{_lrw{L&sn!Fo=47T{P_Ak#hnhMGOe$TAH;qv ztmWi0#ZLkHA^h+PG1J@;F+q5tkN$jqt_=8k`9i$p`#Ldqsx)2@TPtoPlG40PREdbz zqMjS{p*vi|kyahVOn2*WyU*AK(jIne*NRCSK99W)&J0}jy#PGN<|8%o|)mY{5axf(Iq?YSLB9A)?8jIJMswBm67>hRzrMjbB3N%l^i%pz}lM`~kZD zi_SNo^CN%bThaMqbbS$BpG4Px|E3?I>vw+x&?>zyEE%L7xx*hR^8p$=~n{9e@8e{?YO3Z{zD9z3P9CF~6tL_b;HwKf?gq zNYrr~nLaa=Uufb57pw&SmcI%M{4I@f0ig5wzg>?(+h2fz0MPkt+q-oKl&hI|^ii)? zERD8-|IDBE7|nke_`7|5-53IJ`J6-3OpAGLq|KktVD{a!vs3=%-&Kfz$bm)PoD$#-(OboWdgey=Zd^Bh3q_dvAuA@H~R zv7@~YRJ^g@u7kg)uZH}d#>huY&!MFuv@~k}%Wvh2p`}3#5RGpGH9gkv)_u4ZbFK*d zz&ZT=d1FxazQ2{{fL2}%28hNtfrnnAK+H9T+~({PmZ<2B-|{b^)<1tM4+9fK<6FS4 z6&tDvl=+&P28Nn?^zZel>Oy;75c3cIA-yHVd>EGZl ziyBhrqC`H$LhW9zh4ufeFX$$Lrr$xBf9Rv~Byy@COJMHvxuqEQoZs#bQWc`*$H4kS zU;EnQ`)Ee{C5*RQwCC!3#T>ugKc*xLEx!ZSpYrv1@gS=kxgflpMn5C%xBTFZ zMYQ}eSbxZ;0{DHhT&@V5Mz>t=pyXe}3|@{*do7-qk5*QV}JXXUotS z-Ttlr<#z+v;IR_>?YC;{qvx0OS!Mov(Gm$*?BN2QIvctVS)x()v;Pzyvl%o(*DMeI zlm6H75{OC97R0LQjW{j0qNK>^1zZov@QB@-JH&RZl%n5`0JQ!Y%GpV#F*Nt&9l0H6 z05fuj#WK_+r%a)GzZiOWx9q%!s>XSEi0o^@XdUjC&_erm(jEyNDei7+ZMBt?(cD_z2)Ky7nJM zoc-_j_pkT$@Avu7`}_TUB7vee`VBmeKknH&$9!CKA_4!O_H`Imo`|NC`}7%}?r?yxg#7EaqCim*ItFbor`b}2n~yIptA-&CC%YGL6h z9I@VfD{`W=_w^wq7{&Whg5rX2gQY!kl&O^r+9VoWGlp}f5zKN=_8$;|&cef$k>7)P zoM9AFunAlUQD-D^UWDb*`g5WFjD`XfY{UC0Z<{K|MHcq7!j2sJrYtx$Bu2Hq^`*9( z9V7*-u2Smag-WSpAka*$D{?67S0)g~j2_mLfw;v#q=uf$@4K3>OO9V5 z0ez3cIu=CFb1m+M(f}O{5rzkTPL?%*ztVv!jr$R55imj_eig_qODWh_Ke_gHD zH~8|Jy67mu({~*Av{W}U{P(oI80{%Qm%~=I1{`Bb@M>&&F+VxDx$QF1wd?8JXM}6` zT8|VIJbN!k`nBDT>TPW}>kJX-fQuNW%``pZf9YHj_yQkXeO&0YuBzw$3>jwZ7>Et# zizYLz)xQ+!(WG7&McD&iI6T1M)K<-i-5NoKCfES}_P)^j%iqdFZ@=IB?|8L^u-`_VnKA`tUG<*Tk@dpi`Ky>^8T4X+`I2r;j z(aNVlnr$wuy=&TC0su0ir7wV2sGu9ua{EJ~zLxT&Iw*ff7mGioZc1d1+(_IFNW=uy zrf$}N!8*wFrVqB|Cs-hRVxk_MeoOL$h^Wd1Ic)Gw3P*8##n7x)R7xS6C>Hqdn*Hmn zcoU1la+2vf?gNZcuG=ecoL~>L7tbVcS?}HFY4g~EM|j#_?!~j4-npXtZJP7|-hwtQwq0FoZsU&#SBz@A#~paVq!(rEbHA3Ex*J((&^X-P88lBESGpZdB=2Nz&UvW zTn5v@m|TB08?P~Xl@MJ3!-;l|(FHl1Cp97mW{#J@cU`v4^4dq-zcOn|imqURu~W98 z3gujOQb_{q?-+4Fl7S>H@{#3hJ#py|Z)oF!kF}oql$+yfcM*x|h*jc(XF-Jt)r7w^ z&RZ2=5G^jakMYrBm00z8;LO!KEG%gH8LEk`PK`|tW^JV0i!zWuk(NAX57~#GIz~Uf*V+Dwj8r(B?b-<(;dHbRQQ*0p$Ze5+ zRs0+tx#YJ9?N0)EbG|dno=EsJ+N7Y`)s=%^U%rLt;A2AkIU`T=Of(|qRp~?bda$6E z?<+r%*2b^kHO1Yt{*Dbr@YzAvJ9dN{&M%viX0RdEy>F)q9t2`k&)HSzORykPMf&rG z$duBjdXmDh$Cq&5;nW@cAlDY1Cxq>!d8l~3i*XN*#v-g#8-xs)@09RRw#(8#Y z-*CaL7wOaP#wrOdIH55`;`ktk`+NHCGl%IroDMH&XYfG+y!jL2{F2s;py`$8+4x}R z;YYft_efe7`1##_OFU4Q1^>;W0?SM6fxwyM&wsZ6muwp-7q-0Jin)a##@mE9Klq&0 z8HoLEDxqR@?$bV8C#gJAW&hqI@!;=lcc@O`&o<~>n)XCN-JZxyB9jYvg+SZv=8E>p zAg^`XG}eaoe+5jq zLbwo*vT?)+7Hs{Ea_Uh!Cms})gE61NJk%MutrqWb2N#lWnWoI#F!8B|t(K!g2Se5T zQRV8)9KNY#0!&SvmvD{b)H;z83r^OltOX?#1e}ibL4YzeJo99Dp;4+D3%ZGwM>|}W zz9{8O-F&SP56W!uV}H8%E@71vk_#Llgm&%s_{HR}x_{4Ja{fk30vXQ|MU62Q@31M! zJk-5M3LR9fmugH!Rd;@58*`B)gZKu8(-?YkgKah+!L~@rpzSBy9_9?xO&JA~?=_}K zpeh4z5-f7dnp7q38^-oTP)xyX>R*BdEk5=B;+-UT(7#aS-~Znr1TOGh`W)CQ-tsV& z9|Od`%a!IE>=oM&vgT*S5kR!;ruSjsQnu2%Xn6rW7U=Puam>MkR%JR}@z%luF8Cft z?NM-!#3Xk#J2cly0Gb4S{*uYOmO$d+-3v_+fnHI{9HXD7ynYg2dDY260=8P;j-ta% z9l}JA&f&h{_F={q9x# zot^%XDrYy`(h+}RV(>Y=*O^maBzbLG!wf$Y5lEbf^f70WIltx1M)#180OSj9vd_?v zwF*w-CUkg#11?y;nCY$XQm8}9lYOZ>hBG{8F&nz_F88DB_c;+71l-2njBW+6`TM!|cymhQZ~Z z2%vKVSr3mlm>ZYz`2eOFA#|DAEEi|~v*O8Dy^${@gwWzu`y$oZYfmr9Zc{a<<3sON zUcR$J@RZ%AmQs5$gahprY^JYU<9lW~`##?%#Q39sjCL#6e(=!GY%x8!xu%B)jcoxb zHthqJ_&8U1F(-*2xyvT2yM;HyBeZU$;b4$KT&cMV3&Skqk#dT^x=AUZ$SJP>McA3Z zL-oCnf9(67eGS>OMHITXED>eNQdvWVC`)B6`@TzAlS;^zB_isMoe&jK$dZJVbu2T3 z|25NR=9lm5^>04CUiJPw^PKaX=RD^*=bpLu9{6rGOY1aGcitTt79{UZk=QFc9)AI= zh|U}E{fqSVp1-*+9dF?|uPtcQ$c&tFOs=|$a<o)RBQ&x9Omcc4$65~@_OI-#vV zN{=L8Sa#kQ+r*5e?JIO$r$pL9cXhUpI;wau?MHZ+e6^c_lA^lkSCS*s28M%)+tGh!} zI_+D&IH%5g`1yq}9;pSl#s-GblKls5sgQAL@Aw^AIC;dkjy&sPAOl~i=~DxR^qoVP zpEe0%@beM_m(QJfZeiwMhM}loV*nNU?4LK~pZ_jpK|65$2@}Z2Wxc9bw4Me9c9AbB zuz-gLDdeW*>N$)G9>DkYv4B4H@?IIOO|5lI`LWdcEa0ceH?F=@N2#88ZmDFyWdhw_ zmY#&)vse;oaW>YDi~(HvTyw!M?c#82z)xBVLuwF`GjDgRYu;~oz7_i%3%~yuyf0ch zEkl>l_yQnXpa#uk>8GM7!p?_E>x`7y(Sgyov(Nta<_uY^(|u$(LJt~AlaxoBa5^iT zOqA0*#Q=`xin8Ay7xd&l(#%daN)Kjw3q@29o-fj7Hdwf4Ne4>r`$9Fl>~5yOmRnFY zKn*^B;L85_`vHyhBJQ=Opa1**=chs%(=INrY?v_5NOlCsK?Y+#Q%13S&*s7o?ieys zgJT7{Z$TPLr$%*|Jm+h)AlsBLZxBs~(y3TcmenpgP!fBt*t2*dLe=-^@hCxhP&Jm3 zoZ{xqwmar$#4WGTfy(_9M_!Ukd)YV~x|>-{0}A?{{`KI8$0lD!My6O9CAeyObED&Q z`;op|dQ;VKem>s9CbGYXwd(Rl7{V_R4HOJ>Fx8Lq8*uR{AVr zgJyGRKr`cg`6uXx?{}VY_%`{B1}vR^3$b0lKiZ*SW>o@Eg8{Ukx>O4aiz!aE7p~}%(;A#0zAB#v20U&a`}Ps)7O$HGSKb><<+t>iMITzRh>v)5^y5_ zjGdHP3>AWxGXL=;HFCVqQ}zhWo4EBnDX%YZzNB1E@ka1M*mhb+_(oMKWKy`byj3Vl zst?0;LM<0QuVd|w$=UV#6S~adQKZW7`bhDVSXI_}sp|(lw-W;~5K@fX;M?IFzlKl6 zcdHa2koKS7KS?^2JjE%#?a&TCuXu0~YwR$73n?=_>RuU**|Q&nK=@tRFg&{aiN!8v zsG7!t7QEm+cg;ww`a#yYRqG6O8nB*CZ+bL9-;y6;e)jn_8Zh8C>JUfOt6BA$^sTSc zRN$kcqEB*Qb6owvPMS#*D+OpCLY0aQ^l>4r$t~4Dl7UuS zugGG1_3R@RZtB_eAV3k3a3to_!3?82w^F#z#`@m5fmwOjDeFH1!+{lov;i4p0sjlCn zRd<;D{&fc!CF>u&6zHdxfNff|q$5EZOQkTs85tujT~~H^4L^_R;g0I@W{yWlezA}C zzxcoYIp2|WG`yqg_cOs;cgq1<@X#@V&dVE0!|HX-8!>b=pm5_L_DXKd{=;26i^@hc zAT|6fXQS1C2d~Nv1O8kp&|tj!iMMd{0d+TPl=VI;(CumhX5Rhh?*SW>?3Xce@SD5v zSsuZQqWW%33Tn^DKocqU<<>IYW0}GfqB^+<@Wf44#rSB4HLkjn~2tM!!%PN(=M5$6^(t!%Dg#Twt-{w&E88GGN zj9w)}YFx{SHWwALJ@Wp;bpu{E%{;pu&p; z`8DhE3eQQWLkBn>1kQND=ZXE&qzc$EmArg(wEO#yJ^P>VGIQ-qqT1IITDp#IP2)>J zwBRM(P7z5VJeq^1GLD7x00b=?#lMELE|X5BxA9=o`-sD6up{Gz8leJ4gj&K)pe zcZ1_gUh{Mtf32!=gp0$6G7_ZhVo_p_!*G_|g$%EllB||G)2_ zKCKd6`z$$x*X>RXkIqe6(EhlQ`nzPEklZw8t3L+9bg zV<*(F+y96n1KpG`cDHrRqm1a%JJ5DJ!1VfY7V0+#92|y)x+!&OkuMG#3)UpIcyo~_ zkX95>gLzNcU+D^c6eq38xM4_5jg+u#)yTeFea*=%EaRC9InpQ5%PL%o<$Z3=Oft(N zIkF+4b*%M>Zt;a)FIKrvq+r&)QS>_L?+=5_;iD0+Ns#7_(}DufLbZ;^>aU~5>p<2@ z+o$pB_|*1uGkWYg|LY%y^`zfVCPB$psX;s6RcOIb#`I!?;TKC8?&s^PS1G}nL)|s# zxs=3fTO$XW_S1l0NQBNYA7Cq_mmMNQ`cr_Njkcu5B2Io@B4?G3wNrwJ5X*1Z!$r+D zlYh29t0o0c-fYG6%t~=44-a}6!|&hcay@;YLi)qJF=;?lQsg$kTQO-Q6diOw*YqLK zsz8fOtBz!D8|QU9^mdAN5ni7p3A{XC(^04WJNjdzo#6F-tI0nDb_d=Q|!22fmj?p z#6iDiSxN~$OET->mwikF{@gF?b(s`gW!8y!>~}t_vR_oD`63w@pvoQ@bK|B(&P7pH z0DfNpqe6+e!8~pn(BLZyElvq zNq;SVaM2bii9G55y4#ct`JPGdRFmAB*w;f{_2k+VNMy6-3uOlm+B$=P+n>ov!D{c9 z?7e~(9*FVaOyLtG$Sti40q8>r<_eAK1%E3vR41VskWhHV?JY?%Nv;0>&R;iaN0?*^ zRZ>}<-!b~a&lf8N^SfT|VgJnl9#5t8qX*A47GDT388_UyyF}6LLJvO3$b-%qTdgqm zj@F18(}C8uEr^$qUO$rkN(+Bj(Sl>uLgCk5@m}IB;+gP=xfi za%BD`uh>p8$&1IhW#1S$)i@n99rw=L64{jZqWnXFivr!}X)#_vh>}579o=%WS>Yypeq?UH?1h0c3)$NajI7 zB~OMJhA4?u5v09jqeGm8IP+D9+hqL@_9Hz-g1!ge=i`-TDO)=IPyksW4nNE$IT3Wl zD3(W>ofmmYsi3+0pwq9{-)njkH#m@{wb}a8+SjU*T}DVy@~p^TZMx&Bk|CU*C!rXw-zboK?NhCXf=xfhjrkjwn%oi;MtV*cN>W`gx}qCTmCKBCfHZY2jFK~KBNa(%3)ayrATzo>oXT3mX#7p3_9TJ3VZYs+rZxSP{1eJ`s}X8?GvNI9>-|^)<^u@^LswH4eVWS z-sh-kx(#XE?!5AO;*#iJ_qQRsgZJpe_jm4H&#T#2&M}_WTsca^BbV>=cl|Bmd-Rdp zz~1X6srxOH`lnxN<>Zl_EUWojU;Y&q*n9nXf&TNd7U{xv%31G)*zmuCZU{Z7o@`Q(3o@7nwO%--J%_UvE(&;IJ3{XlTf{?@YfiC}GRL$xAg+D3xjt?yGw;T)Xng9NO>j{pM z^1bnmKqxgJUR}GX$Uv)nM$oYp4ehH>aJn{X@iFar$->tnH1s&){!If8>K{Liv&k%y z(a_LnX?lpWU?{_+>O`9l8Y=XfoKr4;`lT^FLrwA`8lpbwqcq=RGUQP#but9QC(QdcOUq30uR!~XjQuDw+*t>_j+L&vWl+0Jd{UeH)(JKj!*hE^xEj#gW` zdfA^lZKt}l3Gr%@tn}n|ziIe<{%}I~Ce$g!g%&DjqoIjf35Vq2U-peId?VL5eO^9B@4@1>@A{h$uzjpB8 zCZw<>KckReH#+{luyUMb6MB3mKXN@iBD>z@W-Kdw9-}N}2zEXt1XH15dKH8=ppg6g zIc|X2SG(#%p&H2>kn#CwPkoU>IgTXua_prIsP96|Pk*#W9!Zm)l!pfV{jZ+bnxSgW1TPu@q%@zyYWTa0aDZ$uVra` zhs!!dbD(Gbi4A{Ql-_x3n?vhR*zIKJ1p~L$apWBBN5neRYs1mx@W`{fb`g<9M8+pgieeL`n*CfLD4%#N8d@=S>987Hh!0P1)})GFj3CL*S&p6u8n}P@?ia$>!>{d!f&?-p zh56kmHL8w|2Il-kK`JlKhrK_kCU=asPB=vw_Sff2V{Dt*8J{kqAL58Eb(sJL* z4+i(H1TS^2L6F`wtIlO!#}}zQHxDwcL$6I)GY9m~(vCU4lYFJV4yjtUIt(0K&CHgn zZcTAphoaBq++m)PoNG|cb1#0h4*k4HB7pE==ip%&NZuG)hbD(ElN}nIDSAxHdgUd} z2IOh10fi?xW#oIvg$7G(K#g3Nc+xPNpKR0nqy}_1pfn1a?F12Y)d=l4RjJDcarayBKT zjHNwQ{srfcsm=BkIdUDN1eLY~I4YqqkNopRa^+t4zDSTA)j&f@2>~bBvlX^CWTc9W z4bV_j)HmDKTD}m{L;4S^EYXmYjj_zd*I#8%YjTm=UPVKO-`0a~*E}^UYhYe8@kc}U z%l@xDvt}!<+lEBekG&G_fOm10qKIOTlmU7=X8d8sxN;ka7>px58 ztp02n4au)&1e`YcJm>gK_NYB62AUHH5(&s2xf;JEnUq9_fo{YHnyW~NzTinP)*Rcn z_j-2w@9{>uXa2zM&Hp>VzwQ^Cl&j|W)DpKOO52k!$btd7xTi)676Rl^ZV&o$MKORP zt-AYM#DRNb?BnHZY8XH&$1nK3L4%ZNKM8zaGY0s5;e0Il?E-At2W?L48yH{=@j`K2 z+wDs@E;6Nb&t85?rP>X{(fx?05HGOr9G7*s)zdnpC55# zx}%?P$21nmx}&yR(4P+$cMt>Zk5h*bc{$CY*2`s1(sr!iQ{>IpKGEoF(_gZGtuu3g&1utB=~vSf z;vKJA<-FhmZTx6uN(5xcZ_L)7e#ylPb_q0b&xz`lXsxZTbJ|gW$K0!}qH-%+`;)$n zAAUy*mRY{N!KZ3$<35_ipXJR2dc8-RNUdKud#kyK?rSC+D4F!I>*qw%g7~dhGY6G8 zK?x?EmT58CBkUFCLBPdtZ_+g!SFS zhgP4NkmKa%wxAC5{56{+`eYhRqPJsB(;$S=mjLmby7>A{x1fp3YFepQOQ&_Sgu(plCIEbamJ>A6U_d^@V8OPoeemgn=A-TS`VVbEEq5xn zSFG5A=F+Rx51PSpX40pDx%qgx+!mA-PR`{CSzn(MQ^*hv>Rb9YD6Wp%)E1Y1sT zb`@S9z8{2X|1*_~j~%Vv&i5+H&B5(QN*`ScQpKt7Fl|9oHbSqxzhQ)vEuDU=l-&am zh<@K-#}$10=(nKB7c05lPuOpQ0w1rCYwX%@DIWaL1K)qtThQk8koX7BUONTrlX244 zaQQ*Oay5B*c>BnS8@CINZ$=Phy8jt6ipI!#+ z6HJ2rUoQ4FhEW7>{{|MKb&8ws^9AIwE3Jqt8n8a1-iJr#4L)%$VxgyKaMR%TV&qKv z5y4{8WC*dS$&~s*A7B3uEJVs*Nnx)Uz1-|vOtx?xE?f7H+IMO&ma~m_Gwfc?wR&u-W;SAq=w~-8Z^wkZ}17d7YhY^Qa#2U z(biIcu2>93-Ukqi+<-_-C*FS@Sm?8mz};ew0;*p&K$3Dn3LM|x3>pvSZQ=}ou#jEb zoCV9wN7J`*mI-en;qsAh6GAiuC~*#`#X@8hsvaS?@+O|Rcw1Es!SW!MIVm}IynWBH z(ECy0g{;#wM?~q$4>>Bra&UIs#+iW%r(cMLzS2nr)x*j3sdBQXSTfwdi#)9u$w&D3 z&c#A8(-mFXrBCkEJ^zQR!+7jeA44;Bh!aUmN^8f&`tA*FcX39R2I zE;-B*f%pG)EYzbpAjt*r2#|CBin7gy^QZhAn_=gl{B;Ejy=xHX3qv(wf80`PyD1H~ zFIS=UD$`kf{Mlk5rbDE3pQm>U%UE;KZZ2^Bxl)G7KfUnfTVNsR)exJji}rw^xu^En z1-O6Z6W6A){>z_OXm#Kg`+ft`wMth~=dJ+QzT7a*WsOJp$H-1%p@BiMhgFkH@>w#= zi6~xJKgj5ZcIh{K{Q%s5H_K`TX86}1=PBR71 z9dmPU*gj;{MbgSI`0*!?h1RgM_s9(6+>b7VSmr`-{pCNLx&2Xp@)H(9sRO6VCk#J^ zvjn_6!w=UFT4}glal(%;AuJTU!Pv_t`QqOCmjf-d*Y3jkF~dywR^*@jf`vNA*B{=l zdH1qwHd$0C46Z*(CGXp5F?{?mW1;K_BZ0KW&Tsk?@#H4iupH4* zy4N`gU6GWH?l*VqZ?8|^FO0Vjfrb1Al3hLSem~g(J+ZE%hwIPXLcQneXTlk{h=IbS zxJ$%jB^~o3O0~~#!TvD{bKZFM>d*MaKyH2fvPXKe9&ieu_4+al_kU9Hk5|rgbU6J! z4AflgAtg|JU9e<;?hf5=SYKX-zoF#&%gb%Q1F0cyReaC(bmIr~!K^f}n zxC)+QpjPb3k)M&~WxTn}-v+P3Kn6czMQNC*5*XA)n}exfD?)@OPx_Ldeu{^9#gZp*w~=p}Wlu4`pCGQ9-% z-+0%zN7;RN|G8tJ3hFHd``15zB>nmze;b_wAjWSULN3hX^=&Z_dnb)LX&+j6Fl*N4 ziYjbBLI`|)5WwdTBMkIQBDzo`vn3?m{&L#tYgivqz`J3t#(=XQ#6aH|ZrwJI$x+4> z7g0@J+HJpT^=u6nzJKL0(1&xMV%!SH^#`&0S!XL@IZ{eP`)mS!dWqpC=LcPOYVPk*d0|U*vJJj5le|=VN_;tzoOjvGr=uC3;Q~dZwV4x=l=7K98 zoTA4%FWyU;PKNXIdFJA>e4Kd*_e2#1?Lh@ z9*Bmz5=z28r|MrZw~X6p-+;?U(0|LSz|iB$w?ji2(j-4a8O?4L9-@BuaegaNCvks9D-f4dL#QXYvVb_;>9~0s6#hySP!gK^*{yNk%>=oj4 zx|8QZ(^2coOfj&3|M3AMJ2P+T9{i&ZNaF;a;^i?kd9?kQs$X(R-#Mr>`Bjjl-{`%xFPA-TBvZ4fH75IibIXz z0cuI`{FrlcpoRlKKLw%zv(5mnr@8l^R##U|N!RV_cMU}JSq|XJe~1P+Qja4TI+9=9 zB;jRI3y0;*`8Uw9Z2dSnga)FmbH^M8%u=e7X94u9-T01`v!xA|!ufw34H!gl%y&?5 zCW2D|i}wc-;Q47%Tj-nrpZt#jiX-|CnN&U+N~O{oJY)mshraD6s+m;y^$ioeKcIW! znO5;aKwXa-$C@9UAB}R~#q2ko!qqQ`0fH#*AU&@ANOgN$Dzy&n+Bb6Fk>kQDPA-Q5 zl>1is9tga<8|!~wRGbbj->9L~q=6aVegFf!rY%+K%{V8jZW%py#|Ms&q{55&=jl0d z_8VbXFz1*G+cYwp%{mWA%- zFV{ekw^w;_@+1s^(R{+~JC$A~ts$$tRt&dq@zH1cW;I5fJQo8Pv447=XiD{9G$&Y% z7rEQMbnhOeX}o`)V*upCu}6C9{TeGq(=Pg6u)O?7d>_vPy#J9H;8R?LcHe|{4EJPq z)f6dgzmfC48G(-?b73_m|fV1c{b!WTBtM)@&=mNZv|VSV}S4W_fc zf96Ll(B+gy>XKyf%*#en?*RnYzv%IhxorpMK7=Y3IL3bW@+F&heUHRg!#ys*6H)|I1G8H%Jm-Vu%!snzq-Oa3kHi8G2Bqr6 zrBv=-q1hyp3xxd-9tkobslxj&5ewv^Gn|d@?vM;v4%`0Tl^f9<@tu~(&)@0r`K=d! zt9X%2CpXsw43n-VAP-`%MaylGrRasY`46iRlE_X--3b{Wae!H1{ zf#rSGBNY9g@%F7_fw5+T%SB;PG-aDJw;~(h_Q}_?8ccTL#}8r)xc$P_RoH1B>BE8y zh@gY}Cy1kpqU_K04LSV0(8j5|p>$_|41RflTDX}8_wR$!*vNK#|4?lK<)Q2(O&+q~ z@yFSh#7toMV(#5`10{TX!sn0Pw>%T8b%TQh{n+;V&Jno$#o0&5Mb$s^%N8*6igFC% z+1U1+Ny)T$4)<^Q?N8Ltwjz3oLdF>^}Wy* zAhQ$COH2PX_jHo6T73n|Pqqzpl3@XE%R8Xtx_m z`IEo40L8?+`Jd8;U6*F=7)R^C@!7|D^v75NUaqtSAmi68t~y4$KEfVjOtOIMx2wvy zKHq?kPn9h|uTL}n&e3MO2<`9gBKcu4112P+39J88w>%Qwh z$_6H_VSN4qw*Z#f8J!}`khFbuY&xV5%fVpN=$vW1f3@KEYiYEfGf9gO@I%*e8fEQ{ zZ^~?T$3Onph5dhc0;;t=QX}5hX)HuB zw?O^uPE-PAm{t{tOD5ef@d;%tx;#3sIL7rys)lx!0xn;+9fy z<&U8tpTM9_ovBxckq2J{861s=^H<)Bkhuq!aq>YF^xFB8QMmUrH4BW$e!m^KeD`4u zt7L8gT>JV^(40o(MWq~_-V(I?g+QYiI6nP1uZ_IKuTMHq(Ao0dZ#_RR+*3MsD99%V zULV`l<;TnfZQ%j{LP6a>__^O*dsyvTpkS9!9S`RpHogzn$I5Z#*P@^pIYHJbG;ff? zfKGA42yCB`1$*?nE+bs~%2CjHUw50+SJc)SBS!mw-htaEG}DZT%+bR6rw|2w3ZHm8 zejfZ`OFL;BHoNQp4?RxP8IrgTeu#ot_2Vk3c(rAZq}7+9o8bEG4lv|>mYKtqpN@je z6j6dDoZmV)%#3_<4@ATI&R2n$;wL!!l2DLob*FNfgGOof=hXNgjIe*?Z&>i!FV*1^ zKoklZ7y8**jv-HxP&9a7P`B&<7ZXW*uX}I_BoOXD6$fQ5y2!FdeNQ>L-Ss!Z;wgG# ztO@5IZxpm7zd9Qy5EsGjY$1Ab5Z3RrX)EHQdyTXIItntR&?RH7WTF2q!bo3)-t8ZY z@+HI;AFli>@cjTU4d>GB^G@isXNpjN-PJ#9T`r##iqp46L7g9mDwH>#iR(LAY49A2 zh3yw`zINBSA1Aj!L6~IG&pR9z`|@5oxFu%8*N=Vsi_4=g;RlEz3W~g6zmwWTY5c9C zo_dA~E+6^9WodvCgY%y*3aWhGnt$CzHHK5<6Q|`QtPfIwE#^-?;NlBFLE4lUt}E{? z1u~>|hLY6c;QU!Q8eZL;iEFzP5z9~U){3JQlF$5uR;mVgsK`+(S z3mfJ6h3wRHV_Xg3^4;0kz3vFM;^Y!2DBn!_W5VUfWf|7G0x~IZ|K>`+>+D~~Zx9Ni zp!fS&I~w1RIY@u5l5f4U8=qRtOsX$~asA7Mf<%5?y*i%sLq3*7L!na;)@NqalV@4P z?@utHpt|criz{zgr+Thmtz*%I^_eMtbUz>bf@>cY3i=f`TcAZHU%`4H1DvMWEq^RV zkbUSCK0&QQqD=Bi*a&@!nTU+!%o@1=gnU063SFqiEua=wp}`e?KMSUS~xaN#Tr+YWm)`X+`OtT!fUmgt zy}k-D4p*c$YNl|JCbiJ_AA#jayI5cTPBPpCYPSkiA47bJm97d;afw+(?t}fqd~-G| z`Mxx6{2Q%8`G5waYUkn4qW;BKR~&ZzXY=h)OM4owd|(w?j6H`Px_wH7ZYjcN@-S@Q zqI9p@4jX>|QGOLVLG5c&EOi{ggSd0W@d(_$a*p;R7EO(~1&H7(wEt1~#%fuHx=i|z z#H<}0zee7NcVzNIa2G(#tI*}Xf;$a7Jr{4^+_*(A2iL#IpqLWz5OyY9$OF8a}4!C~1 z_V-0gFAQ-TxZnzec0O6d!c1|9j<0@hymQyTatBJxg)DIcL~sSFpgo~Ht;NtWxbd)B zt|J_de}{rkA@%t1-&uydGmBFA{2kx;u$7z5`oQtISf9VG%;AEY;gQP_|Hm$ciF28( z7hNu17X)Hq{~QUSe@(yrbGHKnm!XqClYfX`R5Skk?CmR4l}OnC8QsekT}Xl51OP5W z(O;)B7F#0AUG5z1Ta$&$2cIZEd{KXP02csD(4wWDo=8upAeCKqT?s$z|Deg9Ydv5P zZUZ)G3EG#L+rA{6JTN4RaW#R@mqsMH1Rkub-+qqMUxXCMpsE2k)x6c5MeDay(Qtlj zL`Qu!D>lO=phZafGG+bIe5IM(Cl7@+g5dK1^-0o`W3Gc=T8A4T3jnjh>5zTFsAeg0 zG>@`bBwW6jf#10GGZS1nO902^PvDur!P&RTho46BMd9q1>IQ?BasF8Xa*WD5<6q7{ zZfk45d^ZP{%U7RmoF4siX6D*=jnp^80|}SnAGpKqlm8GtX|8_{cYy&c1JgQQ zP5!sPa(v~tyZ@0A_P@JYNZbhhHrsCfLCb*1&*aH@xj@5HX4_e>I(Pf;$^NhQ92z+P zAz^*a&XRZKMGB{O$g@Zt1?Za-x_Wga1}T>U_UN_2`2h|+ zuvOVGe}H#O>`>35|L zxP9d=y{9s*BXJAtT=;!3qgpbLJmS`$E&ZM=AcOT0;lGDFYgH83g@Yz`bjA#5F zb3VSp@I;dPB^M7oewf3b{x&o6#&ti_Do|RYc=y4%m~zJmSd9vrVYb`pO9Dz^%Z2`0U{MREUH&e7Wk)w|&Q#w;FZ zh_au@wGUhc5^Ud7B&cthf1pyBPrjc=n>pvLOw-DrMlVd@`=Rwcu5 z{YZ*oFG*huoW9*EP)wdgKBT(Ps^_e^Z$HbfenqX!7|%ys{&imkE--P#9!+pe5L{2_ z-r3Dxxg7(sdZ_>MKaeifSb#}_ek5)4yTJJ$LIj=CpyB0V#wFmSRiL8VC67wmc`fze z>p4Sl*#5=(8^t4=A93^7!&SgW{>#d!?9{Ww1)Kb79awHxX;y@hx{dSS^HtysA9z{& ziDS*{I~0J!b6B4AJ>y$LQ8zw5SAj2UK~?V=bwffTsD&Y8*U$I`^FEx+LZ)2-~)tjB)ddu|Us9Ek6x}_L+{u<=fraxwl9di;c}ftCT@ObMgev_NYlzk8>;nQ*vPZd ziE#Ngwp9aIKV1BAp@3U)JMO%Rifd{l^2dda!T#;L+ScYBg#Uq12nE;#ZyGOkn}QKz z38|kzSid}Yd&rvU4X*zrP{7N1)6j;gk?34m&i!8IyY&m~^r{Jn;QTL#0xH5c`zM_Y zMWe;R+r2FC{D^2;+gRzr|G=z@0{o1zq`J0-Di?;_4_WWp4{8gV3sVK+{0pD}(y#$c z>-K5UTRYrltlqGk*;y#+!BhMV4!S77NHA+cEHT@>c{9Q?aT~TT>4BzWfsrC^{xw7a zdI#Qa4XZ1v_A=CxMD4B*g+8_I%RA76i_dc?V0H-^YR$iq_nM#m)REV)JZYf!M0v72 z&VE}I(3*^~wSP8@o)2Wud;0*cf3X|I>ZN`SXWtbRU`R#!B3;-J9JIWy=kOBNXI7PZ zxHx$QH$PuT0nuzml2Jt=&wh^W^i6HR@}QXK9{kx5u6%D4kXdW->?2b_X$zms&`tB* z{(0eXi*FSF`%EAT=ssjU3LK0m+y~prF>b2TR%jh083Ij*YWQqNzK>G zygk)neWaQ`^JM0!Ki3}s`{X;R3Dx>!$y-V->-4bxxS6JqOpY?H|I$&wql)ed+lhNc zaYG)G1~TyY6$ zyvjTujxg8wS1f76awGFKA+*UU-1@5=1uVZyuF(6v?}eVJLDIMfTz@%pC+qC9JY4;? zD4-`!$GM*~pXH`NNq5U`el#MvQ-q;;go|G!3K%|oH=cFo)rp_;%7wO~F|Zur=MW!Y zkJIl!0Tyy1av91$4q)E!Wkno-uP=hsqH4m_TXFvFMFEt)5*0Mi@D~kE{yL5h*gpu( z!qp5e8(jYlq5xmk)zep=o(@ObC+>?b+@1fgys{Vg5QX#aI6QvLKD@hm-{U7qS)G+# z30(eov|G%il{?PAGbkWgT9c1KJyGV)`~lKK>2UdraXsx@&a*iGET8~-(&WG~$0=rX z_U)5GX|R5--YF)P$>_d=1F!?6Ti}Xnc=6_4AcWzjxb*`;4#|G%Ot^or zFZ$=fb*8HXmj9eT+u-j?;BgO){R=a01fF^}aXiuDI)Po0hhF8hyA$|^fhJnu2=V!w zp^_vomJ;|p;y?BG`7&mB3*98}_`2|z$$j{|<3DoUxM%fw3_b+zS6qF1EdoAI`Hx&4 z)y+|f@Fy_R!8^)5Ab`MqOqI8aH*XWzk*e0l(I=3|CMTfmjUWQsc|>!W`-Kn~IjS?C zyam4x;!k~Xu{E!aL&6E1>YC1yMh!pj`$w*YQn==j6h+{n$A*@*+%W`J4b`zv%Znwj z)*BQ9sX{z~%Y{1THs2%=*r%{MBIpc!{`jBrhgh{e(#Dbr+(d*x;Vt>A0{b1WsT4JTWQpl)wQx?hn7d%O`MyH?>Ug ztwI8;Drw7g3ld6HzC_P0w-10L|Adx6IiHbuM1DIN#LROJTKYRw*-!Qk949&b`#j(8J)oM_;&c-8&LBezcj1Qzo1(v>S6B(OXW`Gbz|&jjY`3G-I78z%60s#9gO`Y3_< z`nM#jdBzB=F6G_;p~ngQ!uYLT@yH~B$q^e>zQ`#8m$$cnmC2tbFcvfaye)o)z~%Qz znDo5oh%6ZOz1n`B!0z{d2{0M`Ca{lnY@s=@NZ>;8XC4Xi%LGpPap!8S$SQ%ek%yx{ zajg+p7yTQWW7;6FDyp7xof=JGBjFbAauC?4ndNXMGZ%q}=+988NOBXnqicxd*9jg1 zi?TWaudR6rOt0MirO=m;z^OkL7s~JR6FA%aYu2Y10tBAXeud@f7bLK*Y^Ortst|$u ztgc&8j|rWwU`XIT^+pHJU?T#{caa!oe=sJnPcNFD>%dt8_lZa>PWzY=xS{==0qr|8 z0uLQ3zZEKKL16Od1+8ZT&JlP#k107|;5>m-x0n@oqy|1cHZ9e%9jbe zs&^sqMD`T|%V=(PrI0%lm`gy9-{6`Hfy-a_Zyd)G^L12_ISN4R5c0QOdjF;dIgw@3 z&QPjT6M4R-h36w`0 zipP1Zi0l-7X^YE_$jm42H*z`>dEdR3cn&8b-w0j2$nHvH8DXAd``n2vAADSx?FNy< z$}cmr`Vd(N8BNL(Kx726XqzdB$U?|YQl>B>`}9pSGDZ=Zo`h6{A&$sH7kL5tBqH~b z9&(^dCGy6KZX#_uk#)7Ln`yF%jHGnmq0S|;m2R*mbsmwqc#;#T3W>ZL`|ulO36bYZ zO90ApB4ZP4pHRFYvgnCsCW=}jTlIH`k~a{!#C%|f3`u0_&m*B^EkwR?^&1me2a)Ib zXP=OE6WJB<8zAi?@`mv8HVooXB==*k;5Ok*See ziHI2@msD;$Am)jDZa0-J5*bmuBZ62Za>?8d6JmqNrdvB?2rQBJuGdUS5Tx*bgnUs# zi=al36B!|jU`0?8`J5R-2>u4~`}qh(1TB%tg-CP}^hCDmB(X;@68S|DX%KuX6+xf5 zo9r=M1A*O@DLN4Qh}`#^av8xvWK{%>5D6ENb3N!xNO*|Mtj`!l!bjw=RF)?A!DT}E z2y=D>sSuIF(zs8M3KN<6qCga>D3J?aiF_axBeFq>q!5_|k+B-`o@7!)uJu;wAd?|- z*hN5?T$adoWV%7*@>z9vA7l=G1jEQEpBC^pUpB9S^k;xB(q^x#CMqnLVSnY|dbt*Q7&5_7M z5>=-AE)%)o;fOH16OmVIs8H-KM2@_{k$$csI)^_UHp)u{#biumHs7qC1RcP&06+Ef{3uN@a_?q&UuW*t;i`Tbpd&W;kiJLE^sw#maHi}j|UMJYVil3@At?^V=I?Mv!^7e6p-*Z2635l9-QCa2d=JL*PMCwJ1t*B{Gk5= z7s%r_aA9`e$+hEh^Qjlec)-8h^*_&>?`=OKs7R8M>XIHk3z`s2f_}}&U zpZ^`W$6v(qO4q%Vf~2>B*}_eAy&FFt2Zywf&iv^7TR({SeSCp?{lB+A5kd5h-_jhf z=i7)x6=qD;&R_o9K6fxoURjkR8uLEG;ZR#fc`CoC5r?!Dpgz%lKnFb7+Y7JQ=97^m%C`mE^ul zn{AuuS5olFTHzaj)%o~sQ}a_E`zgQ<2K%-;cfNP5UKHfL@|2)OcvL}@R7=fSLrR$| z!jzzmq+M~ zF{TuOA36ZHFDZH7w$4xC$8RUl%}d>_JSlbK`TuM0OW>*e*0$HS&9h{lHc}eMJQSJ7 zB(tJ2ZnJIJ+fX8vqEaN$9HIz?QYoQQXhaf4DUl(iQYq7SKWzQkb=P ze%HS4wVpNH>t4gNthJuKm32>;E##Rxw}#N*bpM?_9*pad=No+1J^%F+{?LWay8IfQ zx2ZL4SGcQ=8Mf}f`EcQ|&M4;`R8?#|Zl)rU&NevWxM5Wna-1Klg{+H<3d^x(*6;>x=blNZuBt{hR#7r|mIqCf&(> zglQM_M;iBEcP6C}-Ps=4e#OiySa+rip;uIQEY(|s>ZUr87)^ZI?`xoKuL#kO7qi_H zI_7!}2No_^EiI<>xh7o>>CV3YvprB1nAkG4&;Ik1#!WlE(OL&jQy$v>MBD#p$Gcze zPg`c1XX{V<`?wQ2KQ*5c{z?65^Pku~DW|!|5ef~lFptUzVab{ot z&>sI>{h%U;Oj?i~nE!{$ii$_OCia?K>(v z%v-H*)Aq+-`_IhYgwQ{_Pp3OOJdVaqJ08&X|Jkvz`S9%FiFSPW`_G#e_`O$}6k}(* zY4!PKyq+B#(cb^J>qqmv{&zorCn{&#bByNsHF?TuMw#LFZ5bR33Y+BCSleF{xi)|D z6vmAEwDud*@o{pozwEcD(~4wMe7T&~P5b{5ZTWtl$C%0^mNxx;I^X%%T$m%F_~GO? z7F9iXUuT9glj7{>6K(pm?T6O=_uCV+$A8*>v-P7b&oBDx&JO>N?Lj-Ao*kdoMLR$I zW&W^bcKi6}?DNm}w_o(5sn3at*&%54p>_ZL`upegqqWyRKVPENf3}-;{G;uE<2tkJ zW0a=9()LH1)c?itv)-LecV>$9zl^7}<2y}zof&yj{@2FKe?=e6QuH(QnYJ9p*x9-1 zdz0tbz>WE1FP%@lxPZ{q3%*nS*vsluUpN5Yo&hp;Ve!=fN|*yK?kR#bZiM^+-c&a~ zm9g}m02--o2`Xdp&ceSXxsO?@#1LfH9zTTsf1s<;I;yasR%WRgWyJdWxg2yD)Q zkO=_0K28yO3Y-dGN0dzcN}^h7J_W!FR1um7z%B|kAA4X+KS&FJU3Jua&Hx{6Lg*0S zzj9665ew@%BLeq=8ID(9CXYc*`P>Nlv{QPR@jxR$=5NWc5?=rMB}ef6`V2jxOrluzU5 zOY~aOcEw+l`RRk(EPu#3{&7X<$<~(mrF?VlSiSHMCYe9tYB~6X6jCz3$m>qwJT*Qs zr^otQoOTl)Rb>170w2B;KgpKcf2(PWZ5tpBJ^aw-^38Te@qecN-xF}d0i)ibpCa0f z4<-err>#%lz3fV>u=p)rhH7II$L`b{;k#-#mWCNFClAY3W{RDae7qvK?~#nS)KcLR z`4Q{#^{Zc{6%3rJJm+{!$u?y4?Lo%TTl0kSc5Lu)`QEWFx#Ue@{((hgFWz+#W~rRc z6}|=M4ai%|4;LAWoiQ>^_sznSixPPy*mkGy&QEOBXuQ$Hr{W>{-z&=hNG#l-(8AEg z&R?7*Hg8a8mgSMl0467VWo;;Vsp^!A4* zk1ZCHuCZSs{nWLMxJS}@NTp$&=+3nsbtkVaPEkzlIm5K*a zE4DQ@C+B+XHd(?EFRp&YWQn9vZe_ppm?*#3yVZPNUdiaxdg!jdFU$H=Sly+ffbC&x z4Rwg6in}`mpt10+Dy_!{+(TC{QI~t#!J_B?@`;I*_C4-_(Yx@v29Gh!K$xh?`7)~ zOH>Y(KeMX+*i70vXNihXyxGQ-o4&)1=JNZ!lE!L6B zY8Lj&={wEx$0e_Gh?$LRd1cETI%CmyFN&S##BTrF8%;89yU264#2F6d32PC!$oa*N zey6|LJaun76F*^OlTgZ+AI*%~y#J|?)?k!g zzq0fGZ+wm}=K_+(n38E6;VQ`=64k=>`ZK=n7?>p+g5s^XL?rgAJ!56sQYiX z0Ite=(O%2Yrnj5M_a%!T85YoE{$OX_VP}1}6#$cZFVO5a@5LSCA5L7#kkHiK?&BuFTh743HlcSc z-)>$BZ@8s`sBjej_;M3DQNv?>0jsyV4Mtu$N$l4&2W~fg+pI9v`Z`!k45m-j-2f zX~a^d5uesu&CPSabus&cbR~s%F2rIPrgJ@wqVWSkiJJbOjx4vzPOUQ#P$?}* zKOJ_X%&H*8`JNVod&h)Zx>BybP2bDscenR{D?I+z_dP*Nz=u_QQ<-G&4~haM{7itr z*WDu#{YNw3z4&-FWzJ=f^LuJlUnC~=XZJo)f0f~RQMczoL;UsSDf$!cNe@0J&zI+K z+rT1nvUctIv0Mr5Fb(U4i&-@Vm-5BRw6@5tXo>qyk&oYWUgE?JIlEN@^`+n6h4s0o zzGT(9t&(|;U9%}meYgCN+8Cv+k_)axkqFH5}Vj?1kP zOP8tE5__}RJ(l%I>E8TW^}Z7kBdooTgzhFUQSCfoRm-cktvPbsij)*d&%)@O-5_#V zrSzQ+yU~&hjvBWJ&mQ%jemJB_7aw9~dhq#?%-sVi7jsV+9Bd7Eu*ynWXIkrx=Kieyp#0R$%cX;2 zUFVpQk3{X;pPabz@b^QFrD{E@6E6bu6p!+xmA7*E@71|~XT(cJ_U*PSq03K(H*2d< zP9L=zMY|#@+jRWqH;?J1ofEO!Wyz#+kOzMD*4F7M$37$F(yl_GB<}KEd${fDvh_R` zFYnl*9c8d@pddZitNGqdX8R?+<($Mp`PJ(xzphSxnYH8aiT1*invE?Rl-8_~DHHAL zZ2CCFbwsYpfqvLBk#~2-jau9oZ%BA!_mIlXGxx)B$3JO5t>5)y&#DL9tL;iU1QtiH zW4&xPzH>}ZNB!lsgNBl0jy-WtcpsyR(KLEPldIX=>hAWCPTV}F5&SM*C=Y8M_{6&4*m1cprUQ%nUxijKyE##9&aC<< zX4?^*l+&iQ8d_0)6{HF4BkFODS;s3_+57IC*gO$`sOE63^_qHur@_`IeIK^im4=o! z79SpN*~H{r*}iUo!C-lf@XpS$&k1rB2L9S-2}+s_^EA2+5}HNR*fZT;HDtuE&pCLv zTe;5X^|p=^*LKB5^q$byYihYP!eO=Wc8J}h`3oz`d~}QJnw>l-UO&Q9N529+wu4GLHx0TE+CT8CzbpUt z<*DwXJ#{Kc(c#C6B^fR?oL>}H!5`ft`}Eau_C3416f|&mgl=Rlb=bdJt5)}@b<*e> zE0N&He3N6h3+-~~ZU@O;;IbGr@ggx@JYIV+dqeRL%CS9MgBP_nZQga~VoJR(euZqV z#Al`Z%$MK4*1qJuM=NUe;;O|TIxFWst1>)LU9qG5?1}E`OQ&}~l;`Kp^jLNEkx=U! zzfgU)IxeQSe(%kTlJ#%rA6do8w0PtJquFQHm0u)S((l^5s?=u-<}=_ASKvByjcD(0 zZjsm@uGM`kq~=YTtwomh4==hPFD=f}jjKDu(^g)?t$1X5cwS}&*POzNoo$vsGDVZc z8@@-C-NJK{L-ysctMjE7o4)q;Oh~6lKc5#9s?~U(Uy}6Hd*7pT$B$3Gb(=D3+~rzt2vPr2h3c}O3J11(RrCKoX&oFV7u2*Q!!6itd7WlAGmj@ zVF9b9((V;k)~m=E$o5EACReExueeHmDzxE)Xu$C0-jubM_jh5$)QdKTd4*eHzr))yjRfo}i9)hFl2**|? zU$?DsnnNl(HhenK;O14`Bd=A&x;y;5%FVesN8(kpDCv&Ry4GIssy^y;UGsAwUB03B zSm`yo(DcQh>UOB1wl4e$RlDG#N18Uw5}8Nc!=#7fcgh@V=Po^!R9R#5s9yZS#ttK; z$HONlYBb(ob+?cHSayN#o5v1|`|B6nz1Psn&{6PQpocZ(4ue(aL-(paF|IPR4k60P zwQKn|WtBLI?H}YAd>HN3j#smmvR7AC-1s*))V}SUaX6jII0gm^Q3=#c5h|zH$lfOF(+1Vy?vD3HE({< z%{NX*6L$>tyzJce<0}iF`JF!Vk^(}>JcX)7MeXh5585fWRa$QCw9q)*LEjpZW7_VL zVP!;FcOfFgrDtnkTmRYOqN7}PRS%kWyd2teey3wxyhc~o-TjMR@@&ibT77Dl1K-)N ziOUW#oUvJ2d2(?4?GktM9#f+2a&r@5+2K&;-A!NHq~lf`OBpn?GN%_|de^IV|Al}E zdnbWccGSpENMHH;<@3hsoj5N|!!U)0)Yy-6^!7Y%;LvkZ^WWIgvMRcjt-RM{zjbWv zv)6HaH#FWn_&9I1H#$ZDL6o zHJHEWhSHB56GK~`1?SuD3aB*>R!!ytbmz z?pz0MQCZSZ=Zm~5X;&NBb6=N-D`%a!r>f{j^Vke~0LpipK@;#A396# z3YWTgG_1HII?;Tx%89kPb>EAi8g170mYeHeh#gihDRBPIODc?g&!E76x@Nd3wn0XT znJYYd6`F8~7hZfcd`I6~FSh!1HgP8JI9k@rYR=;!WM04-)Sir=NW66K$Ca;s=i^>( zDgM~Xd^7x@=}_@d-)yBuss@8OUXL)HGQa6awJ7O zeODDeXX0X#&i751Y&%1xMHF+-*LiKboAySmi2wO>YqlTFA9D5|-lgDhovR{|zcbU0 z#V94pRyw`jR&If}Y+0iH&iRAe*|^u&{;*!?FnsX&dhuExwZfFBM$_)g3U!BfmkM=K zUYruhdyw~Dm2{8Puxitj-dGDArnptP&UuuoM-#{Tcf>V@dTiu-&@15hGIt=tQp+U& z6|t;vt#9GPT8ApUbee5q!>LNi~g)px=nuHvLH?J+~I+ouad%V zw1icw**&*ehLJavolO(jR^u_Wbm;64{hP!B)Xq6ShWX2Z1_4=o1xKBSd0ZM-!}s?6 zXLr0?@bT)kXO~!Wx_3NW-S|bA->>wokW;{elTRBQWfzaGA8cIpF4J>d&`&aSZv;Wg zh1vXLD9_QNmVAxD<%SZE?rdH^zxr)a@v|j+HI04R9z{Q9czdb4;k@~Fo+WBbJi#rO z4;6fkS;bR0FV(Zzx|Fs0&7FpJF1%7^ZCqpBA}@*O?|pT*txR^*E4*M_dv|NxV}ZnZ ztP-ffXqD7tRS2Dc^=ALPde4-+}h+|7d62GdLf1knT zuB{H+&h#jW)xP3?`xvq9Ttn1uJ)M4xZ~IbdUYxJgoaT&MlH|`Reie`NEbiunzi#lb z?y73$TU&G^a#K_``#G+aFHgA#y~}6j;lT6mRyJ<>RNLnIq=CWZ>-SeO@7c2Hc|#Jn zRK*M>9Qkr`jhkAcLZ**ZUlN>Ln27FS)O)*@uPwi+=}k%pZgVpK`|ijnr+fL!-gaE} zpSw#|z3{ey|7x*Ov$0)Y7IN99kRLlZQL1l_7QC*xx9;f!{`!Fq52u31_qTl@nb};Z zu6(u_N3ZR?MW_g;71&#-Ez`R2>h%gC5&zp{nWzmi;#(F=#2ESIsMQ{JkG$`(?hfT{ z)`9UI>-t0--@D1|v#S4CDwo$iR(v?>N}f7v*=i=P`QOHFubD`XdGBESqwMO#@7?<3 zpskVKjo~7)H6>%mti6o(whNqd$@^NCsr*E=kAvU4V5RNc@53#lV#%LAvr6m{YUZN&B-I1g)Hs)Tm$EeMYVlikCnnTO;ecb)B~71v&25Y_@*gBNaa5>YveuWf z|H@#0eUNj%k1XEvlKzr{5xzq_%@QWZ)GfCjS80iU=A4ynab@SBh39? zQ`%C$^L)~W?cvV;mtJz2tRWwLlC~?s&H5X=ZrdHMeWSr@zULkGWw3NdllQ;c_LZWO zg69mpy?aa3BSbm!hGCypU%!PXkEKSU_M4Io9jv9TE7-WC-B7lA2(PD#&=E_dr_0bS z;@)bXweY~T7?pJ*{rAHBRpPqs-*d&;ru$v}s-`g%-_gOCC#9HqMnFWD)KvD^5x|mmt>pL-Mk=@cj0$xZ|e2 zj!e}}n+AK$SZl*xt88D-q;1aQA;#yK7i!Xb$lry{N=&Vd>&Xr)@ws7h!s1ml;@+N! zjg)$Cv#z+YZ&NB=)bnw}%jwp+M>{-E*PA8mI9nmjTlS8}yE%r-)b!B$K1Gj{y~*3w zGgr{QQ6{WadWp-ypANpcK;xVCwP2^sT3Xwa^@hH$j6T}Z6`SfdddB0@haYB( zyWAfXUV1!goEE$6+Y*V@1H{WCE5&U;F+4~)-7x3;XNC7t6z*pl*GxPIm>oieA4`2Y zZx^Js$>GSE@;Q4sqi(wzi;gs_kWLDl1|6$AKECaF!f?h3)0Q7q7vr{Oy{Ov0V^ey3 zkHWck<)VrAOijhq8#*{gi+JkI#!6G0qW7A-{p77(=$>D&sQV)8m*`P3TO;|#Fiy63 zT+wB-z)G^n*p}Ei>P#owY}Tv@vikJ8%3QwtfKyJ|svWQDZ#n~*_$ zmo@E|WRmLo+zF=z0!$)5x!&83H=#OT|F-NY+v}J(%lhNxdUYD*UUwi@4P{lt8~^|39Gapo@04j zG}3ou^}!7mChez>ku<&wJ?l8#{(7Hc+abFRM$go)cTA*aXSZ&(#eDO#@=5Ps53h}Gz8u-w zdobpLdMaCCMA#OJezkrD(|DsxVBY#fi|Ct499&P9a!I>BV%K4CaK4V?Sso28ju+h9!?Pmc9Fy@@|1rS zwe6Wo$cp~gjNz-Rp7OM8yim@$e6jLqYGS_ao-Ew@fT~3XsP*ptzAel}3W3Znah_(j zK^voe-i&#VCk#6T(04>gnx5micj%!p``S2U*e`K3ON7M3zjWf*3Y~9>ch@Qku8mVM z9vE~`VsE&N^UG}Af5KUJ-ir5Hr{8GCUrf8OC?rxuXKej;mXoHN63s8C@NM1vl0jW( zFDLnv#A&It5+C))$7D{&O&IhhJ=(gxh2(H&i@vFBYK`jJk;X@R5@YgO&as9`-)&d= zz`XVB_lc3Tvzqmp311#`qL{ZP&vpDC#2#7n)<)9i$aeRP0d5C@51EgGPgi%JRDStP*`l}9t+()a*d_D_?-P&Wy1mOs~Q_W5hGWwc3b{ow^p*1OM$s^qH2i%Msi@b0Lsr25Bx7OIEyWrja( z=yhUw!1E$<^^=%$xQu(pw_Ug{c-`s5v3^1N+ouWx>^nQpZnS&sQn25;KvGcZace`Z zb>cF`TAf5@&n)8`1NnBvx1GaM4pf~`alC5&Js{zUUP+4+>&m=*wKd+$5>84L<{e@5 zT)$Mnn1TP97e0Gm>@EB}0XEgF!C)`a)*lP5JY3!P$mR4ChbaD%lZ(e6_}?0@v#`kJ zQc8Oew`0zVE4c$KGCA+|N4=_vX{#_QA5zl2ab{Qd(JHnQ`BCwg6E537%v~FhcBf@; z#DnEr{VseFP13dTE1Ruyq#O?^Cb;hrc2evX*yp+Fc+5&!?d-*Ickg;1!b?!r;=D+C zulQFOX}!=s=ddE@18aZHiqD!lWU;Ww;lQm%--5l}_cjXL8;U=XeAO@afb8eC8?PRw8j4Z@T7bx$~>i_5@vhnVU_*^nyzoLV0s8`d%&3 zkv%Mxc9ZA9=jJvU>6dl|8*)y~6C=HfaMpWpp=!tRvYHQ3W}S9Cy?Y)I$!C#uY5(DF z&eIE6Mqf}aeBjQzyIY&{;&w))^K4f}@{TZ(hj$1QU+q4B%NqN-CciOod3Zga%=rL0 zcOe-^-H=;J9v+8QUqgMX%==gZdyjX!jN|-s+;C~{lup?6vd$mwi#dghU-JGO*0_$8vbUQp)U05Anne05{ z*wz%m`@Sn?pHx|D7OTqb)903s7uoMtluHS{%>40dyYol7^h+--cN;wLdj2Xo^Nq!t zdtdiC9CzvRy&8Thkmbhdb*ZmwjCwCb)UgLRKRRsaD|RmaB2R(l_D7`q7s@+iuULg} z`_pp_;2n+Ex-H@6=LoHT&YY)Qv6%8Yyh_T;FU>Uj1H0JCtuMqXZFpTZ+11O;@9)S- z-Lj*fF?6ZZ8vk=T5?l|=v`4xk!<%-AICu9_oKv?AZ1=Rh+*+--@ct&|m^Q(64qcyE zgtZ@7R7UjDKNj9-(3)#}R$ zbH4{|!S5A+cQ|)JM40KEOE|q~^+#8HEOT;v85}QWWZYgfc1)X*Vqvw}A|dCaz0gtC z%KdD6m+t)9f38p=srzJ9Pez`I`HnU(z%WJMxGuKy;x$H z-gS{5p%-K%^XQjW$BlPcwl7JMS!U~FnAWkp&@50bR(4!CPE;tl>fG%q{jtz>VG))B3+Q~L_{*VjDMExUd==}U}Bjk4M9y?fS{d^=A3A}U_+ z$Ta?>a=v-SYn>vgSL#9KMhgAobs1;Fj#&z5-B`aSgY)9GHEmAU)0Sbp}q$K=Grjg_MxC3ccF zS6n@FdM)3V;JvnU!&7D6(EFE6_{7T$<%lxHozRKn@m%iUo#c{}Q|wNVEO+pE*3}^R zaAKMw6kwffw0UP8Twb()N;l%z0<_xqx+Q`+1436^49V#>Jw~r z8?0NAT+mb9oFFj5>72w;6xqTeu;IcSt;??hbnGTBWL}F-+U>X3Regm+4_TK%`IH$` zhiBQ{%KqAiUV3fg%M8UN+mBK4?@#3Z>O(N`}-SGqr*UtKsn(0}~y>K9V$BEPAq`3rXbI9NJd z;Buz&DgR?F^i^y8n$H(nTi1O!&fSut;r)6{ z>s6@I*(Q~($EutQcU6iAF2L7_TeB!#l03Up^6k^o9fEI;>4X^XTA*z<|MpJab&DFG zRKFa1C@Q=5(diZGDPIjLEDP`4?u*_v6p*pas&$dW!)@1lyJVjaw#aTJ4YqsXqJojm zxoE$zFC($WPIx*!p4G}LufBabo@|{O=ErST{;|uuu=A|fnarmly`1!Ovk3bs7x;$y z;@iZvE}j*L_9(n_W6hd`8a%$0?Q&BkXaA5+!Vz;7g+B2XW4n}t?*?Buz5P;}f2-vh z;o*{-H{A78yQQBO+?Ld(i&ed&B(;_OLaJ#v9D+FF5UJUhmL^-;yh>MOh3Ey_H7_=* zE!o|2rj&Ff_qs#c;ISm51Hty$5aFRnZthM9<0_BZ73pY zD{dW(F?5_Se(B6-ob)$750-1U&zv$^nT^j&SZaXcg_woBL@fKSdqrIfv7Q(BWt-j$ zw(Gk%0$vQoyYA-r=DZ{Rh#4h|nKiV=TtGLisi3{JDADx7D#K{aac4?Yebl{Zp=gKW zq&duGogc>y_7~7~lm&iw;lW9Y9y4t^Q=Tfx-~J?^zyGH|a}j7R`N=xP>fV>+OW8Ox>z^|A3L*Bo90u%l zp_#y5)%$yZ+cU4&+3&lKZ=rF|wnOYM@8i$DPkmn>d-o7~=dcG9!`?T{*oi~B`dlbB z?GSwB4!m=C_sH^@O3aiAd|v`Ew=VY-&%B4p+#a7N@6-DKbX!fuW2W+bYI+K~zfbRH zJgTtDm*gEG7ony?2n{1qd;^IDFE`(Suu$T%sW&S1JUv5+WHLb}nBe0^CXj*%zJYGu zL^(3igW?-RLIi??Zzv_qExkgc1XSJlwFn3BeFG$Rj9# z5KaswV;(Y|^3(5u{=Inaz7zu4cN1}D_-Vc5gFW3SZqqJc_!e+HT=dk7f#zcT2N%=7 zcrpJkU*wQb$_#77PRYa6elWOY$~~wv9R>?O)nH?(_pm!y_$mNGdZFH7fkYC8;29L? z=1U?FLqnmh$QrI*rDtZj@UPosXqRCDZlN$H5M*u5OyJ(+wHoT$D5b8$qCQe6R z?O1YpBc~N9NMxuOT%1z5~7@l1oL^F;t)3~{5+yokTJ#{>sYCSNX(&#ts|A+q{wE%qK0sG{aB`_dv z;0YdVz5wsR&p~K0{3xCv$O^z)0J0#*0w)0!Ku!kE1gL;q1bhjg1#%Uz_gn-sOa>GT zoG*aT8Y~R(0AMr7gTQw1LV6s?uE1vr2<2j7fHPoVl@I0~tIRn@krpl2Zy8>74gzrZHxe8c30ijxu3BX>72z7uQ3|tNv#KHh8 zCBaAxvM#Xe0k8`lqywA_Pyx9J_|risBgiNX@;?Fjf{d|x8RQGHE^x#Xgo;3p1-|(d z<~<zK$Qi)ip*WNcaxidlI1bf=Tm^hP0`vj79(Y|e4h@6s3XIy{Aq9{Lz@O*PAq|ibFC8KP zEHHmyNj^Gc1+oILDnA|a0a+LLtsor=26+%zWf>hx!2E%WR@0$ckTHH|MTbVQFu;{- z=@2tB*csT?3GxEj6}aD(4w-^H2%O+fhay2v1}^uZL#bGJVCi7c8)OAwEx;(qy1?rI zhy~IC77C$5^dJ*}7Xt)ARsg zfm{zfRtRZ=jLyOR%XH`>$O^#UZqT7OnEy?%+dVoomko3S-p~kj0kSLb-4?J9$o0TM zt#l{@msToV9!gIo{1ED(=6K-LAW1Pp>)1?))y1*L%+?YRbC}1wg zvB1>;L6GZ#*9YT~C>92|2_Oq{2e5bu9w~rK08RpEfSe3m1JDJz9@s4uYz1;KFh3cO ztg!IF(ttIX3}5IoAFvK&1zpgkO{z%fNabkxDZePauIMl;0nkc!1p$REkLe{ z!lN!g8_0veS2ly4F@NBt(O_qg6@XU*MnNXTK-mHGT%bSjW&k_Lv6#FCYz}fV@OMBW z)DeosBUXSc`2V^7_bq^}9pTuS5W7CJ0+TCaFoP9+6Y+sz}9He?k8S+trd=w!c1<1$u*L)c9i19U@0?rlE@fSz_!&=C_XE|EivJ6?( zY9f;>8fZnXI;5orX{kb5Dv*{kq!smRTGE_wp9Ai*|GrFV za%Opje=V;GKj^g_^jZdbX+nA$ke)iErv~Y5{53s37R2Ynj5u)cyBLh}dv^ zh+YBjN*9dP8Pp?YbIhJ4zq2PNmc#Noq;m|st)4(U#oUkuU^1${+8 zUt!Q!``0u!2%`->yvV*~4zj4_K?Ya2(Xw1FqdLm zbe(LYGwW%=uX=imBJbh3|3zIF|9f=B`WQD0;=W1SW59p1{mzB<%M0yy4zyn$XeZpz zPPm|*(AM4JU&}MuemS9DIG|pBQ@0Fsh#>_B|60+oFbfifI++7?!V164GS$mLA1qu6 zgrCcb=E4}j1!Dkf$zLrH2Xix4Xp=v~Pq!USUZk1Jh7=C5q6G;oNIa4m@%u1A-xvI~ zFRYjg$ z4{vq^oRw=gRs#9r^So3a@mpcAvPGVSYf8Gsh~) zU-MMvfwFKwS=ga0Y)}@~-;cdkg3!(uKs%cc^&kWFFb~p}1|6h82T9Pu`q#8&Y5TF* z?7lIn<6=l>5u~#a(vgL9*8ZB#bbSe7`mun1bAPq&4Ko7lFMO zg1u$I-V4Cq^Fdb`&~+Z@Dh;|i|ElX`9SK7mA&4UgaReX^Kg8jKICFnrKBgJZ>&fR0 zFT};3sXP#u8{%?7TuzAlo97od%=w`{n4vy!3Q#U1K4f$S>mPHVP4PgR;)XWG1$D*= zbte03ok_DH=>#?yQ&?e4VSzD1@UJmqQWqZ3g&TCCZO1admVK=-*o+r!HV4Z8x8nV# z3|M_l))^Dxj)do=55r&c1k8Uvj17mFkyru~%%>SaPljKgufLo7{LT-ne|N0@nZa&M z@J#0U>zO>+4{67g-;9I5iz~ni&q)?|PV)WLzhK7nUz&fJ&PArRoJi*i2U3G^O%BGj zc`&Ytz_`W>;~E=0AEuw|xPK<>WLw~bw!i^xfgRcc8?*&hYX24gwJrR!;Z69ENi7Fj zafKbJ!ZTzEJVT@tu;&vq)Dg@{VE*{m69{Z>&WFsQoO)1B4JhYQDCc}Arx=uTYR)7+ zJN#sO;)3?X3GE5;fjFuVX9>iShBzW%8(!RR##4j2FpuGac?>7aV>nIY`nxMg$xMmUMt;b1LlR$1uacipgO(ezmJyEy`^rLagbDA2p&gD2U=)e!cyposo_cp=i-tL&jkPoJ_2-^-3JTLC& zOzUR~a1YBf>o;TPWZDA1_WPOT_+7cCZS}Xxg3W=IWoB^FBy3hxLvt| zIjuOV*y>qk{=b6tWqr^WE1Uj|vSI%-+5A;oF!y0#ZDhnx&V8&P{NIX)*#*N)TVZLX z%t&j>?(S6U{IuH7G->}|!{%j5FfW5OKW6>uUJQBAx~IcU^RzA)W6uYrshQi)e5T9r zk9cM}tS~2pdEu;iB@Q?B+`#g+0X?zwq^Ne7nRXWVO^2CjpP9DD>R10a?FQ3K{iQ2*zJApg%@X^rP$7X_h*^B5*=5CJj5b>By%?u5aik_li1(;l2Qx+y}z;d9ZyPY|jSUlfm{}ussiK zT^w5v$M!j}wQy_=99#Rw*1WNO7Hmx!+v~vgP_TUwY+V^!1IN~sv9)Au4IJC&!1gh) zeF|)k1X~No*1)kfWo(TZTTjN;jpY!3O{S$0|1l#|>*3Pl@e{639 zTRX@0FR=XyY|jB(KgaeJuzdq;O&Htj!q(BTy)A6-3fr5)_M5OhBy2wi+l#^WTClwl zZ0#4@|G@S%ussWGPXgPg!uFo9{iF`4_fG&083rT;&;-~5`~X`3>439<`+(N~G@k(p z1GE9Q053okU_anApaSq1&<{Whu(rd1WC6EJ0^!7C5DG>iC=`(q1%;t-6yWO~66WTKoh6Y|koOD-KrSxR9xk3iF2Qb| zGkv^*ec^l*iA-?`4vJ7zn0d<=4%m3PkjNo3J^hKHBw~PzN6>G*A;#anGb^3IV3G?Q z`Enu6Oq}W&7#857NbBzr82pPDrgvzV2gL=B`?ygQl{9EWc>0Ei5(8;{iIJ30x5-$) zi{p!FfvNC|YJc5vad(5$Z2;P&1IRwUUKCniNbNUXzm_rdx3S4#?!W2+p1+tWIMkO! z@pAE+WvHK?KE%kGN`PHlpzf7s)e413BF_wjxm|ooE&;xQ?lb)(l{P8`Dq>NoHSR)j za}OXQH>iD|kV%41xQ97_;FID;g1j)o{D4A`hnqXJA`fb$NyeO^-q`0<Oyd<8U zP6iL~b_>MP3kbmKev*U2NRS-0&=`R_Kw$i-G~p9OYVgph(4YZiGnomA=oad}aWXLy zbQCu)3K5i^G|kUpgiM-hRR|gpoY3>cLVy?&76d#Qm6|Tu!!5u)0MwlnFb1Q;*-A{9 z8Y!miJ89l2>q3vF1bGEa_RJ|mPuiJ6EhzMN5*U0Vm|`QCVk4yauU=LP*fV14I;08v zf=b|4{L7Di89WP>;dwH{FA@9%RsISy9Uo(E)hT~bD$7z?h02ChwxhBul>?}}naYV& zK1StSDqo~>6_xK(xrNGas60sJQ7W^mQT3wow9ZSYZbK@sqjE5ncT)Knl?$kRhsw=V z{zPR~^{IU3QF$4aEvf87<;_$+Lgg$fU!rm~l{={XiOSP@(`iiQ!%gLRR92$07L`q@ zY)9pFRQ94WiOP{w-bUp_DyLHU1eJ5CTtek?D%VoEnaUkh?xXS$l}D*e4{Z&*IH@d1 zWhp8zp|Tp4r_24Pef?=)SX=m?YG3^DScj<@#Y-8%JlDkqCQ*|zHaR4QP`t3;m%^rJ z@N^)OJUzWIALXC!$VoRg6Z7(oq`(sp-nOC2WM5>2$=GDg)0YDO)*|C+H+jl!G3^c` zP5Rh?+nYF*r!6K^rer&i1E~HEm`wF|0vYB-6c5ndnJQ!D@B*1c4IczDOrIvpgw1v) zA1Rw}j6S%`jL7`v`tk|%wYDk29i3V`$98Qb}*izqdP{bL*3GYx^ZzM=( zLZldkg@(cbaCnWu1KyKBLcjW%c_OhHzIHw^`|t!$Z$Wem|HT^_(@(yl zVFlBfpwK|oHin&FxUlZLWXN;sL_R`M$i*#?>v5tYwq5jQ)|75*AJY2|789s7~ zlmE)1xsb>I1Xdc^SQ=Rwb{W{{{ld;U1xsX)Q3r{<;3wEWkbcJ(p=crr)>g zaHn|>Wjeqg{$qhZ7WmJxKrEcs1#Ja0;3FB%MPr(0DP(D6>1J7Ff!sk4Yq+qdk)4}e zmEDoulRcO{oL!&Wkvo`+^0@N|c?x;Dc~*I@dBJ(HdC7Shc}00udG&c6d4qZAEcaQY W3+w+7Uob-c-kC3bl4b58~BBAIe{s=Q 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 DD=>*O From d34fe13c1cc9ea5865756a7897a732f338460a04 Mon Sep 17 00:00:00 2001 From: Christopher Lux <59606965+LibraChris@users.noreply.github.com> Date: Thu, 7 Aug 2025 23:13:05 +0200 Subject: [PATCH 104/121] Fix incorrect use of anovaType in twoWayANOVA - 'Fixed' case was incorrectly using Random logic - 'Random' case was using Mixed logic - 'Mixed' case was using Fixed logic Corrected F-test denominator assignments for each TwoWayAnovaModel type. --- src/FSharp.Stats/Testing/Anova.fs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/FSharp.Stats/Testing/Anova.fs b/src/FSharp.Stats/Testing/Anova.fs index d56e31c48..6c68b925d 100644 --- a/src/FSharp.Stats/Testing/Anova.fs +++ b/src/FSharp.Stats/Testing/Anova.fs @@ -246,20 +246,20 @@ module Anova = // Create the F-Statistics let fstFactorSig,sndFactorSig,factorSig = match anovaType with - | Fixed -> - // Model 1: Factors A and B fixed + | Random -> + // Model 1: Factors A and B random ( (Testing.TestStatistics.createFTest (fstFactorMeanSquares / factorMeanSquares) fstFactorDf factorDf), (Testing.TestStatistics.createFTest (sndFactorMeanSquares / factorMeanSquares) sndFactorDf factorDf), (Testing.TestStatistics.createFTest (factorMeanSquares / errorMeanSquares) factorDf errorDf)) - | Mixed -> - // Model 2: Factors A and B random + | Fixed-> + // Model 2: Factors A and B fixed ( (Testing.TestStatistics.createFTest (fstFactorMeanSquares / errorMeanSquares) fstFactorDf errorDf), (Testing.TestStatistics.createFTest (sndFactorMeanSquares / errorMeanSquares) sndFactorDf errorDf), (Testing.TestStatistics.createFTest (factorMeanSquares / errorMeanSquares) factorDf errorDf) ) - | Random -> + | Mixed -> // Model 3: Factor A fixed, factor B random ( (Testing.TestStatistics.createFTest(fstFactorMeanSquares / factorMeanSquares) fstFactorDf factorDf), From d7005e9a11d091e691967cff2809decc731bd53b Mon Sep 17 00:00:00 2001 From: Christopher Lux <59606965+LibraChris@users.noreply.github.com> Date: Fri, 8 Aug 2025 01:02:42 +0200 Subject: [PATCH 105/121] Init ANOVA tests for oneway and twoway models --- tests/FSharp.Stats.Tests/Testing.fs | 287 ++++++++++++++++++++++++++++ 1 file changed, 287 insertions(+) diff --git a/tests/FSharp.Stats.Tests/Testing.fs b/tests/FSharp.Stats.Tests/Testing.fs index e76ad3ecf..df2518853 100644 --- a/tests/FSharp.Stats.Tests/Testing.fs +++ b/tests/FSharp.Stats.Tests/Testing.fs @@ -1326,3 +1326,290 @@ let SAMTests = Expect.isTrue (SAMResult.areSame result1 result1NonStringId (=)) "the ID type being other than string shouldn't affect the results" ] + + +[] +let anovaTests = + // tested against R Python + let a0 = [|9.105820655954515; 9.03375793269564; 8.915088867146936|] + let b0 = [|9.218533797307847; 9.374165278011928; 9.09902059371791|] + let a1 = [|9.054802062519045; 8.980015323427445; 9.066383039929153|] + let b1 = [|8.819119236212753; 8.96115712165076; 9.042933513927682|] + let a2 = [|8.80043362511518; 8.938413526335156; 8.886644395458491|] + let b2 = [|8.614386401606065; 8.53829813235829; 8.611071068887409|] + + let oneWaySetup = [|a0;a1;a2|] + let twoWaySetup = [|[|a0;b0|];[|a1;b1|];[|a2;b2|]|] + + let oneWayAnova = Testing.Anova.oneWayAnova oneWaySetup + let twoWayANOVAFixed = twoWaySetup|>Anova.twoWayANOVA Anova.TwoWayAnovaModel.Fixed + let twoWayANOVAMixed = twoWaySetup|>Anova.twoWayANOVA Anova.TwoWayAnovaModel.Mixed + let twoWayANOVARandom = twoWaySetup|>Anova.twoWayANOVA Anova.TwoWayAnovaModel.Random + + + let oneWayAnova_Factor_DegreesOfFreedom = 0. + let oneWayAnova_Factor_MeanSquares = 0. + let oneWayAnova_Factor_Significance = 0. + let oneWayAnova_Factor_Source = 0. + let oneWayAnova_Factor_Statistic = 0. + let oneWayAnova_Factor_SumOfSquares = 0. + let oneWayAnova_Error_DegreesOfFreedom = 0. + let oneWayAnova_Error_MeanSquares = 0. + let oneWayAnova_Error_Significance = 0. + let oneWayAnova_Error_Source = 0. + let oneWayAnova_Error_Statistic = 0. + let oneWayAnova_Error_SumOfSquares = 0. + let oneWayAnova_Total_DegreesOfFreedom = 0. + let oneWayAnova_Total_MeanSquares = 0. + let oneWayAnova_Total_Significance = 0. + let oneWayAnova_Total_Source = 0. + let oneWayAnova_Total_Statistic = 0. + let oneWayAnova_Total_SumOfSquares = 0. + + let twoWayANOVAFixed_FactorFst_DegreesOfFreedom = 0. + let twoWayANOVAFixed_FactorFst_MeanSquares = 0. + let twoWayANOVAFixed_FactorFst_Significance = 0. + let twoWayANOVAFixed_FactorFst_Source = 0. + let twoWayANOVAFixed_FactorFst_Statistic = 0. + let twoWayANOVAFixed_FactorFst_SumOfSquares = 0. + let twoWayANOVAFixed_FactorSnd_DegreesOfFreedom = 0. + let twoWayANOVAFixed_FactorSnd_MeanSquares = 0. + let twoWayANOVAFixed_FactorSnd_Significance = 0. + let twoWayANOVAFixed_FactorSnd_Source = 0. + let twoWayANOVAFixed_FactorSnd_Statistic = 0. + let twoWayANOVAFixed_FactorSnd_SumOfSquares = 0. + let twoWayANOVAFixed_Interaction_DegreesOfFreedom = 0. + let twoWayANOVAFixed_Interaction_MeanSquares = 0. + let twoWayANOVAFixed_Interaction_Significance = 0. + let twoWayANOVAFixed_Interaction_Source = 0. + let twoWayANOVAFixed_Interaction_Statistic = 0. + let twoWayANOVAFixed_Interaction_SumOfSquares = 0. + let twoWayANOVAFixed_Cells_DegreesOfFreedom = 0. + let twoWayANOVAFixed_Cells_MeanSquares = 0. + let twoWayANOVAFixed_Cells_Significance = 0. + let twoWayANOVAFixed_Cells_Source = 0. + let twoWayANOVAFixed_Cells_Statistic = 0. + let twoWayANOVAFixed_Cells_SumOfSquares = 0. + let twoWayANOVAFixed_Error_DegreesOfFreedom = 0. + let twoWayANOVAFixed_Error_MeanSquares = 0. + let twoWayANOVAFixed_Error_Significance = 0. + let twoWayANOVAFixed_Error_Source = 0. + let twoWayANOVAFixed_Error_Statistic = 0. + let twoWayANOVAFixed_Error_SumOfSquares = 0. + let twoWayANOVAFixed_Total_DegreesOfFreedom = 0. + let twoWayANOVAFixed_Total_MeanSquares = 0. + let twoWayANOVAFixed_Total_Significance = 0. + let twoWayANOVAFixed_Total_Source = 0. + let twoWayANOVAFixed_Total_Statistic = 0. + let twoWayANOVAFixed_Total_SumOfSquares = 0. + + let twoWayANOVAMixed_FactorFst_DegreesOfFreedom = 0. + let twoWayANOVAMixed_FactorFst_MeanSquares = 0. + let twoWayANOVAMixed_FactorFst_Significance = 0. + let twoWayANOVAMixed_FactorFst_Source = 0. + let twoWayANOVAMixed_FactorFst_Statistic = 0. + let twoWayANOVAMixed_FactorFst_SumOfSquares = 0. + let twoWayANOVAMixed_FactorSnd_DegreesOfFreedom = 0. + let twoWayANOVAMixed_FactorSnd_MeanSquares = 0. + let twoWayANOVAMixed_FactorSnd_Significance = 0. + let twoWayANOVAMixed_FactorSnd_Source = 0. + let twoWayANOVAMixed_FactorSnd_Statistic = 0. + let twoWayANOVAMixed_FactorSnd_SumOfSquares = 0. + let twoWayANOVAMixed_Interaction_DegreesOfFreedom = 0. + let twoWayANOVAMixed_Interaction_MeanSquares = 0. + let twoWayANOVAMixed_Interaction_Significance = 0. + let twoWayANOVAMixed_Interaction_Source = 0. + let twoWayANOVAMixed_Interaction_Statistic = 0. + let twoWayANOVAMixed_Interaction_SumOfSquares = 0. + let twoWayANOVAMixed_Cells_DegreesOfFreedom = 0. + let twoWayANOVAMixed_Cells_MeanSquares = 0. + let twoWayANOVAMixed_Cells_Significance = 0. + let twoWayANOVAMixed_Cells_Source = 0. + let twoWayANOVAMixed_Cells_Statistic = 0. + let twoWayANOVAMixed_Cells_SumOfSquares = 0. + let twoWayANOVAMixed_Error_DegreesOfFreedom = 0. + let twoWayANOVAMixed_Error_MeanSquares = 0. + let twoWayANOVAMixed_Error_Significance = 0. + let twoWayANOVAMixed_Error_Source = 0. + let twoWayANOVAMixed_Error_Statistic = 0. + let twoWayANOVAMixed_Error_SumOfSquares = 0. + let twoWayANOVAMixed_Total_DegreesOfFreedom = 0. + let twoWayANOVAMixed_Total_MeanSquares = 0. + let twoWayANOVAMixed_Total_Significance = 0. + let twoWayANOVAMixed_Total_Source = 0. + let twoWayANOVAMixed_Total_Statistic = 0. + let twoWayANOVAMixed_Total_SumOfSquares = 0. + + let twoWayANOVARandom_FactorFst_DegreesOfFreedom = 0. + let twoWayANOVARandom_FactorFst_MeanSquares = 0. + let twoWayANOVARandom_FactorFst_Significance = 0. + let twoWayANOVARandom_FactorFst_Source = 0. + let twoWayANOVARandom_FactorFst_Statistic = 0. + let twoWayANOVARandom_FactorFst_SumOfSquares = 0. + let twoWayANOVARandom_FactorSnd_DegreesOfFreedom = 0. + let twoWayANOVARandom_FactorSnd_MeanSquares = 0. + let twoWayANOVARandom_FactorSnd_Significance = 0. + let twoWayANOVARandom_FactorSnd_Source = 0. + let twoWayANOVARandom_FactorSnd_Statistic = 0. + let twoWayANOVARandom_FactorSnd_SumOfSquares = 0. + let twoWayANOVARandom_Interaction_DegreesOfFreedom = 0. + let twoWayANOVARandom_Interaction_MeanSquares = 0. + let twoWayANOVARandom_Interaction_Significance = 0. + let twoWayANOVARandom_Interaction_Source = 0. + let twoWayANOVARandom_Interaction_Statistic = 0. + let twoWayANOVARandom_Interaction_SumOfSquares = 0. + let twoWayANOVARandom_Cells_DegreesOfFreedom = 0. + let twoWayANOVARandom_Cells_MeanSquares = 0. + let twoWayANOVARandom_Cells_Significance = 0. + let twoWayANOVARandom_Cells_Source = 0. + let twoWayANOVARandom_Cells_Statistic = 0. + let twoWayANOVARandom_Cells_SumOfSquares = 0. + let twoWayANOVARandom_Error_DegreesOfFreedom = 0. + let twoWayANOVARandom_Error_MeanSquares = 0. + let twoWayANOVARandom_Error_Significance = 0. + let twoWayANOVARandom_Error_Source = 0. + let twoWayANOVARandom_Error_Statistic = 0. + let twoWayANOVARandom_Error_SumOfSquares = 0. + let twoWayANOVARandom_Total_DegreesOfFreedom = 0. + let twoWayANOVARandom_Total_MeanSquares = 0. + let twoWayANOVARandom_Total_Significance = 0. + let twoWayANOVARandom_Total_Source = 0. + let twoWayANOVARandom_Total_Statistic = 0. + let twoWayANOVARandom_Total_SumOfSquares = 0. + + testList "Testing.Anova" [ + testCase "onewayAnova" <| fun () -> + Expect.floatClose Accuracy.high oneWayAnova_Factor_DegreesOfFreedom oneWayAnova.Factor.DegreesOfFreedom "Factor.DegreesOfFreedom deviates from expected value" + Expect.floatClose Accuracy.high oneWayAnova_Factor_MeanSquares oneWayAnova.Factor.MeanSquares "Factor.MeanSquares deviates from expected value" + Expect.floatClose Accuracy.high oneWayAnova_Factor_Significance oneWayAnova.Factor.Significance "Factor.Significance deviates from expected value" + Expect.floatClose Accuracy.high oneWayAnova_Factor_Source oneWayAnova.Factor.Source "Factor.Source deviates from expected value" + Expect.floatClose Accuracy.high oneWayAnova_Factor_Statistic oneWayAnova.Factor.Statistic "Factor.Statistic deviates from expected value" + Expect.floatClose Accuracy.high oneWayAnova_Factor_SumOfSquares oneWayAnova.Factor.SumOfSquares "Factor.SumOfSquares deviates from expected value" + Expect.floatClose Accuracy.high oneWayAnova_Error_DegreesOfFreedom oneWayAnova.Error.DegreesOfFreedom "Error.DegreesOfFreedom deviates from expected value" + Expect.floatClose Accuracy.high oneWayAnova_Error_MeanSquares oneWayAnova.Error.MeanSquares "Error.MeanSquares deviates from expected value" + Expect.floatClose Accuracy.high oneWayAnova_Error_Significance oneWayAnova.Error.Significance "Error.Significance deviates from expected value" + Expect.floatClose Accuracy.high oneWayAnova_Error_Source oneWayAnova.Error.Source "Error.Source deviates from expected value" + Expect.floatClose Accuracy.high oneWayAnova_Error_Statistic oneWayAnova.Error.Statistic "Error.Statistic deviates from expected value" + Expect.floatClose Accuracy.high oneWayAnova_Error_SumOfSquares oneWayAnova.Error.SumOfSquares "Error.SumOfSquares deviates from expected value" + Expect.floatClose Accuracy.high oneWayAnova_Total_DegreesOfFreedom oneWayAnova.Total.DegreesOfFreedom "Total.DegreesOfFreedom deviates from expected value" + Expect.floatClose Accuracy.high oneWayAnova_Total_MeanSquares oneWayAnova.Total.MeanSquares "Total.MeanSquares deviates from expected value" + Expect.floatClose Accuracy.high oneWayAnova_Total_Significance oneWayAnova.Total.Significance "Total.Significance deviates from expected value" + Expect.floatClose Accuracy.high oneWayAnova_Total_Source oneWayAnova.Total.Source "Total.Source deviates from expected value" + Expect.floatClose Accuracy.high oneWayAnova_Total_Statistic oneWayAnova.Total.Statistic "Total.Statistic deviates from expected value" + Expect.floatClose Accuracy.high oneWayAnova_Total_SumOfSquares oneWayAnova.Total.SumOfSquares "Total.SumOfSquares deviates from expected value" + + testCase "twoWayANOVAFixed" <| fun () -> + Expect.floatClose Accuracy.high twoWayANOVAFixed_FactorFst_DegreesOfFreed twoWayANOVAFixed.FactorFst.DegreesOfFreed "FactorFst.DegreesOfFreed deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAFixed_FactorFst_MeanSquares twoWayANOVAFixed.FactorFst.MeanSquares "FactorFst.MeanSquares deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAFixed_FactorFst_Significance twoWayANOVAFixed.FactorFst.Significance "FactorFst.Significance deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAFixed_FactorFst_Source twoWayANOVAFixed.FactorFst.Source "FactorFst.Source deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAFixed_FactorFst_Statistic twoWayANOVAFixed.FactorFst.Statistic "FactorFst.Statistic deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAFixed_FactorFst_SumOfSquares twoWayANOVAFixed.FactorFst.SumOfSquares "FactorFst.SumOfSquares deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAFixed_FactorSnd_DegreesOfFreed twoWayANOVAFixed.FactorSnd.DegreesOfFreed "FactorSnd.DegreesOfFreed deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAFixed_FactorSnd_MeanSquares twoWayANOVAFixed.FactorSnd.MeanSquares "FactorSnd.MeanSquares deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAFixed_FactorSnd_Significance twoWayANOVAFixed.FactorSnd.Significance "FactorSnd.Significance deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAFixed_FactorSnd_Source twoWayANOVAFixed.FactorSnd.Source "FactorSnd.Source deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAFixed_FactorSnd_Statistic twoWayANOVAFixed.FactorSnd.Statistic "FactorSnd.Statistic deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAFixed_FactorSnd_SumOfSquares twoWayANOVAFixed.FactorSnd.SumOfSquares "FactorSnd.SumOfSquares deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAFixed_Interaction_DegreesOfFre twoWayANOVAFixed.Interaction.DegreesOfFre "Interaction.DegreesOfFre deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAFixed_Interaction_MeanSquares twoWayANOVAFixed.Interaction.MeanSquares "Interaction.MeanSquares deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAFixed_Interaction_Significance twoWayANOVAFixed.Interaction.Significance "Interaction.Significance deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAFixed_Interaction_Source twoWayANOVAFixed.Interaction.Source "Interaction.Source deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAFixed_Interaction_Statistic twoWayANOVAFixed.Interaction.Statistic "Interaction.Statistic deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAFixed_Interaction_SumOfSquares twoWayANOVAFixed.Interaction.SumOfSquares "Interaction.SumOfSquares deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAFixed_Cells_DegreesOfFreedom twoWayANOVAFixed.Cells.DegreesOfFreedom "Cells.DegreesOfFreedom deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAFixed_Cells_MeanSquares twoWayANOVAFixed.Cells.MeanSquares "Cells.MeanSquares deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAFixed_Cells_Significance twoWayANOVAFixed.Cells.Significance "Cells.Significance deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAFixed_Cells_Source twoWayANOVAFixed.Cells.Source "Cells.Source deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAFixed_Cells_Statistic twoWayANOVAFixed.Cells.Statistic "Cells.Statistic deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAFixed_Cells_SumOfSquares twoWayANOVAFixed.Cells.SumOfSquares "Cells.SumOfSquares deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAFixed_Error_DegreesOfFreedom twoWayANOVAFixed.Error.DegreesOfFreedom "Error.DegreesOfFreedom deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAFixed_Error_MeanSquares twoWayANOVAFixed.Error.MeanSquares "Error.MeanSquares deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAFixed_Error_Significance twoWayANOVAFixed.Error.Significance "Error.Significance deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAFixed_Error_Source twoWayANOVAFixed.Error.Source "Error.Source deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAFixed_Error_Statistic twoWayANOVAFixed.Error.Statistic "Error.Statistic deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAFixed_Error_SumOfSquares twoWayANOVAFixed.Error.SumOfSquares "Error.SumOfSquares deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAFixed_Total_DegreesOfFreedom twoWayANOVAFixed.Total.DegreesOfFreedom "Total.DegreesOfFreedom deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAFixed_Total_MeanSquares twoWayANOVAFixed.Total.MeanSquares "Total.MeanSquares deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAFixed_Total_Significance twoWayANOVAFixed.Total.Significance "Total.Significance deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAFixed_Total_Source twoWayANOVAFixed.Total.Source "Total.Source deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAFixed_Total_Statistic twoWayANOVAFixed.Total.Statistic "Total.Statistic deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAFixed_Total_SumOfSquares twoWayANOVAFixed.Total.SumOfSquares "Total.SumOfSquares deviated from expected value" + + testCase "twoWayANOVAMixed" <| fun () -> + Expect.floatClose Accuracy.high twoWayANOVAMixed_FactorFst_DegreesOfFreed twoWayANOVAMixed.FactorFst.DegreesOfFreed "FactorFst.DegreesOfFreed deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAMixed_FactorFst_MeanSquares twoWayANOVAMixed.FactorFst.MeanSquares "FactorFst.MeanSquares deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAMixed_FactorFst_Significance twoWayANOVAMixed.FactorFst.Significance "FactorFst.Significance deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAMixed_FactorFst_Source twoWayANOVAMixed.FactorFst.Source "FactorFst.Source deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAMixed_FactorFst_Statistic twoWayANOVAMixed.FactorFst.Statistic "FactorFst.Statistic deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAMixed_FactorFst_SumOfSquares twoWayANOVAMixed.FactorFst.SumOfSquares "FactorFst.SumOfSquares deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAMixed_FactorSnd_DegreesOfFreed twoWayANOVAMixed.FactorSnd.DegreesOfFreed "FactorSnd.DegreesOfFreed deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAMixed_FactorSnd_MeanSquares twoWayANOVAMixed.FactorSnd.MeanSquares "FactorSnd.MeanSquares deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAMixed_FactorSnd_Significance twoWayANOVAMixed.FactorSnd.Significance "FactorSnd.Significance deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAMixed_FactorSnd_Source twoWayANOVAMixed.FactorSnd.Source "FactorSnd.Source deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAMixed_FactorSnd_Statistic twoWayANOVAMixed.FactorSnd.Statistic "FactorSnd.Statistic deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAMixed_FactorSnd_SumOfSquares twoWayANOVAMixed.FactorSnd.SumOfSquares "FactorSnd.SumOfSquares deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAMixed_Interaction_DegreesOfFre twoWayANOVAMixed.Interaction.DegreesOfFre "Interaction.DegreesOfFre deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAMixed_Interaction_MeanSquares twoWayANOVAMixed.Interaction.MeanSquares "Interaction.MeanSquares deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAMixed_Interaction_Significance twoWayANOVAMixed.Interaction.Significance "Interaction.Significance deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAMixed_Interaction_Source twoWayANOVAMixed.Interaction.Source "Interaction.Source deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAMixed_Interaction_Statistic twoWayANOVAMixed.Interaction.Statistic "Interaction.Statistic deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAMixed_Interaction_SumOfSquares twoWayANOVAMixed.Interaction.SumOfSquares "Interaction.SumOfSquares deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAMixed_Cells_DegreesOfFreedom twoWayANOVAMixed.Cells.DegreesOfFreedom "Cells.DegreesOfFreedom deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAMixed_Cells_MeanSquares twoWayANOVAMixed.Cells.MeanSquares "Cells.MeanSquares deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAMixed_Cells_Significance twoWayANOVAMixed.Cells.Significance "Cells.Significance deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAMixed_Cells_Source twoWayANOVAMixed.Cells.Source "Cells.Source deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAMixed_Cells_Statistic twoWayANOVAMixed.Cells.Statistic "Cells.Statistic deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAMixed_Cells_SumOfSquares twoWayANOVAMixed.Cells.SumOfSquares "Cells.SumOfSquares deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAMixed_Error_DegreesOfFreedom twoWayANOVAMixed.Error.DegreesOfFreedom "Error.DegreesOfFreedom deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAMixed_Error_MeanSquares twoWayANOVAMixed.Error.MeanSquares "Error.MeanSquares deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAMixed_Error_Significance twoWayANOVAMixed.Error.Significance "Error.Significance deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAMixed_Error_Source twoWayANOVAMixed.Error.Source "Error.Source deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAMixed_Error_Statistic twoWayANOVAMixed.Error.Statistic "Error.Statistic deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAMixed_Error_SumOfSquares twoWayANOVAMixed.Error.SumOfSquares "Error.SumOfSquares deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAMixed_Total_DegreesOfFreedom twoWayANOVAMixed.Total.DegreesOfFreedom "Total.DegreesOfFreedom deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAMixed_Total_MeanSquares twoWayANOVAMixed.Total.MeanSquares "Total.MeanSquares deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAMixed_Total_Significance twoWayANOVAMixed.Total.Significance "Total.Significance deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAMixed_Total_Source twoWayANOVAMixed.Total.Source "Total.Source deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAMixed_Total_Statistic twoWayANOVAMixed.Total.Statistic "Total.Statistic deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAMixed_Total_SumOfSquares twoWayANOVAMixed.Total.SumOfSquares "Total.SumOfSquares deviated from expected value" + + testCase "twoWayANOVARandom" <| fun () -> + Expect.floatClose Accuracy.high twoWayANOVARandom_FactorFst_DegreesOfFreed twoWayANOVARandom.FactorFst.DegreesOfFreed "FactorFst.DegreesOfFreed deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVARandom_FactorFst_MeanSquares twoWayANOVARandom.FactorFst.MeanSquares "FactorFst.MeanSquares deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVARandom_FactorFst_Significance twoWayANOVARandom.FactorFst.Significance "FactorFst.Significance deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVARandom_FactorFst_Source twoWayANOVARandom.FactorFst.Source "FactorFst.Source deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVARandom_FactorFst_Statistic twoWayANOVARandom.FactorFst.Statistic "FactorFst.Statistic deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVARandom_FactorFst_SumOfSquares twoWayANOVARandom.FactorFst.SumOfSquares "FactorFst.SumOfSquares deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVARandom_FactorSnd_DegreesOfFreed twoWayANOVARandom.FactorSnd.DegreesOfFreed "FactorSnd.DegreesOfFreed deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVARandom_FactorSnd_MeanSquares twoWayANOVARandom.FactorSnd.MeanSquares "FactorSnd.MeanSquares deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVARandom_FactorSnd_Significance twoWayANOVARandom.FactorSnd.Significance "FactorSnd.Significance deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVARandom_FactorSnd_Source twoWayANOVARandom.FactorSnd.Source "FactorSnd.Source deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVARandom_FactorSnd_Statistic twoWayANOVARandom.FactorSnd.Statistic "FactorSnd.Statistic deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVARandom_FactorSnd_SumOfSquares twoWayANOVARandom.FactorSnd.SumOfSquares "FactorSnd.SumOfSquares deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVARandom_Interaction_DegreesOfFre twoWayANOVARandom.Interaction.DegreesOfFre "Interaction.DegreesOfFre deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVARandom_Interaction_MeanSquares twoWayANOVARandom.Interaction.MeanSquares "Interaction.MeanSquares deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVARandom_Interaction_Significance twoWayANOVARandom.Interaction.Significance "Interaction.Significance deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVARandom_Interaction_Source twoWayANOVARandom.Interaction.Source "Interaction.Source deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVARandom_Interaction_Statistic twoWayANOVARandom.Interaction.Statistic "Interaction.Statistic deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVARandom_Interaction_SumOfSquares twoWayANOVARandom.Interaction.SumOfSquares "Interaction.SumOfSquares deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVARandom_Cells_DegreesOfFreedom twoWayANOVARandom.Cells.DegreesOfFreedom "Cells.DegreesOfFreedom deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVARandom_Cells_MeanSquares twoWayANOVARandom.Cells.MeanSquares "Cells.MeanSquares deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVARandom_Cells_Significance twoWayANOVARandom.Cells.Significance "Cells.Significance deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVARandom_Cells_Source twoWayANOVARandom.Cells.Source "Cells.Source deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVARandom_Cells_Statistic twoWayANOVARandom.Cells.Statistic "Cells.Statistic deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVARandom_Cells_SumOfSquares twoWayANOVARandom.Cells.SumOfSquares "Cells.SumOfSquares deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVARandom_Error_DegreesOfFreedom twoWayANOVARandom.Error.DegreesOfFreedom "Error.DegreesOfFreedom deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVARandom_Error_MeanSquares twoWayANOVARandom.Error.MeanSquares "Error.MeanSquares deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVARandom_Error_Significance twoWayANOVARandom.Error.Significance "Error.Significance deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVARandom_Error_Source twoWayANOVARandom.Error.Source "Error.Source deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVARandom_Error_Statistic twoWayANOVARandom.Error.Statistic "Error.Statistic deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVARandom_Error_SumOfSquares twoWayANOVARandom.Error.SumOfSquares "Error.SumOfSquares deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVARandom_Total_DegreesOfFreedom twoWayANOVARandom.Total.DegreesOfFreedom "Total.DegreesOfFreedom deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVARandom_Total_MeanSquares twoWayANOVARandom.Total.MeanSquares "Total.MeanSquares deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVARandom_Total_Significance twoWayANOVARandom.Total.Significance "Total.Significance deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVARandom_Total_Source twoWayANOVARandom.Total.Source "Total.Source deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVARandom_Total_Statistic twoWayANOVARandom.Total.Statistic "Total.Statistic deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVARandom_Total_SumOfSquares twoWayANOVARandom.Total.SumOfSquares "Total.SumOfSquares deviated from expected value" + + ] \ No newline at end of file From 1e45147c83a0d05cb68c2481d9156a8a5b9b1588 Mon Sep 17 00:00:00 2001 From: Christopher Lux <59606965+LibraChris@users.noreply.github.com> Date: Fri, 8 Aug 2025 11:58:45 +0200 Subject: [PATCH 106/121] Update Anova oneway tests --- tests/FSharp.Stats.Tests/Testing.fs | 142 ++++++++++++---------------- 1 file changed, 61 insertions(+), 81 deletions(-) diff --git a/tests/FSharp.Stats.Tests/Testing.fs b/tests/FSharp.Stats.Tests/Testing.fs index df2518853..675d569ab 100644 --- a/tests/FSharp.Stats.Tests/Testing.fs +++ b/tests/FSharp.Stats.Tests/Testing.fs @@ -1330,7 +1330,7 @@ let SAMTests = [] let anovaTests = - // tested against R Python + // tested against R and Python.statsmodels let a0 = [|9.105820655954515; 9.03375793269564; 8.915088867146936|] let b0 = [|9.218533797307847; 9.374165278011928; 9.09902059371791|] let a1 = [|9.054802062519045; 8.980015323427445; 9.066383039929153|] @@ -1346,26 +1346,6 @@ let anovaTests = let twoWayANOVAMixed = twoWaySetup|>Anova.twoWayANOVA Anova.TwoWayAnovaModel.Mixed let twoWayANOVARandom = twoWaySetup|>Anova.twoWayANOVA Anova.TwoWayAnovaModel.Random - - let oneWayAnova_Factor_DegreesOfFreedom = 0. - let oneWayAnova_Factor_MeanSquares = 0. - let oneWayAnova_Factor_Significance = 0. - let oneWayAnova_Factor_Source = 0. - let oneWayAnova_Factor_Statistic = 0. - let oneWayAnova_Factor_SumOfSquares = 0. - let oneWayAnova_Error_DegreesOfFreedom = 0. - let oneWayAnova_Error_MeanSquares = 0. - let oneWayAnova_Error_Significance = 0. - let oneWayAnova_Error_Source = 0. - let oneWayAnova_Error_Statistic = 0. - let oneWayAnova_Error_SumOfSquares = 0. - let oneWayAnova_Total_DegreesOfFreedom = 0. - let oneWayAnova_Total_MeanSquares = 0. - let oneWayAnova_Total_Significance = 0. - let oneWayAnova_Total_Source = 0. - let oneWayAnova_Total_Statistic = 0. - let oneWayAnova_Total_SumOfSquares = 0. - let twoWayANOVAFixed_FactorFst_DegreesOfFreedom = 0. let twoWayANOVAFixed_FactorFst_MeanSquares = 0. let twoWayANOVAFixed_FactorFst_Significance = 0. @@ -1479,77 +1459,77 @@ let anovaTests = testList "Testing.Anova" [ testCase "onewayAnova" <| fun () -> - Expect.floatClose Accuracy.high oneWayAnova_Factor_DegreesOfFreedom oneWayAnova.Factor.DegreesOfFreedom "Factor.DegreesOfFreedom deviates from expected value" - Expect.floatClose Accuracy.high oneWayAnova_Factor_MeanSquares oneWayAnova.Factor.MeanSquares "Factor.MeanSquares deviates from expected value" - Expect.floatClose Accuracy.high oneWayAnova_Factor_Significance oneWayAnova.Factor.Significance "Factor.Significance deviates from expected value" - Expect.floatClose Accuracy.high oneWayAnova_Factor_Source oneWayAnova.Factor.Source "Factor.Source deviates from expected value" - Expect.floatClose Accuracy.high oneWayAnova_Factor_Statistic oneWayAnova.Factor.Statistic "Factor.Statistic deviates from expected value" - Expect.floatClose Accuracy.high oneWayAnova_Factor_SumOfSquares oneWayAnova.Factor.SumOfSquares "Factor.SumOfSquares deviates from expected value" - Expect.floatClose Accuracy.high oneWayAnova_Error_DegreesOfFreedom oneWayAnova.Error.DegreesOfFreedom "Error.DegreesOfFreedom deviates from expected value" - Expect.floatClose Accuracy.high oneWayAnova_Error_MeanSquares oneWayAnova.Error.MeanSquares "Error.MeanSquares deviates from expected value" - Expect.floatClose Accuracy.high oneWayAnova_Error_Significance oneWayAnova.Error.Significance "Error.Significance deviates from expected value" - Expect.floatClose Accuracy.high oneWayAnova_Error_Source oneWayAnova.Error.Source "Error.Source deviates from expected value" - Expect.floatClose Accuracy.high oneWayAnova_Error_Statistic oneWayAnova.Error.Statistic "Error.Statistic deviates from expected value" - Expect.floatClose Accuracy.high oneWayAnova_Error_SumOfSquares oneWayAnova.Error.SumOfSquares "Error.SumOfSquares deviates from expected value" - Expect.floatClose Accuracy.high oneWayAnova_Total_DegreesOfFreedom oneWayAnova.Total.DegreesOfFreedom "Total.DegreesOfFreedom deviates from expected value" - Expect.floatClose Accuracy.high oneWayAnova_Total_MeanSquares oneWayAnova.Total.MeanSquares "Total.MeanSquares deviates from expected value" - Expect.floatClose Accuracy.high oneWayAnova_Total_Significance oneWayAnova.Total.Significance "Total.Significance deviates from expected value" - Expect.floatClose Accuracy.high oneWayAnova_Total_Source oneWayAnova.Total.Source "Total.Source deviates from expected value" - Expect.floatClose Accuracy.high oneWayAnova_Total_Statistic oneWayAnova.Total.Statistic "Total.Statistic deviates from expected value" - Expect.floatClose Accuracy.high oneWayAnova_Total_SumOfSquares oneWayAnova.Total.SumOfSquares "Total.SumOfSquares deviates from expected value" + Expect.equal oneWayAnova.Factor.DegreesOfFreedom 2 "Factor.DegreesOfFreedom deviates from expected value" + Expect.floatClose Accuracy.high oneWayAnova.Factor.MeanSquares 0.022925 "Factor.MeanSquares deviates from expected value" + Expect.floatClose Accuracy.high oneWayAnova.Factor.Significance 0.072 "Factor.Significance deviates from expected value" + Expect.equal oneWayAnova.Factor.Source Anova.BetweenGroups "Factor.Source deviates from expected value" + Expect.floatClose Accuracy.high oneWayAnova.Factor.Statistic 4.211 "Factor.Statistic deviates from expected value" + Expect.floatClose Accuracy.high oneWayAnova.Factor.SumOfSquares 0.04585 "Factor.SumOfSquares deviates from expected value" + Expect.equal oneWayAnova.Error.DegreesOfFreedom 6 "Error.DegreesOfFreedom deviates from expected value" + Expect.floatClose Accuracy.high oneWayAnova.Error.MeanSquares 0.005444 "Error.MeanSquares deviates from expected value" + Expect.equal oneWayAnova.Error.Source Anova.WithinGroups "Error.Source deviates from expected value" + Expect.floatClose Accuracy.high oneWayAnova.Error.SumOfSquares 0.03266 "Error.SumOfSquares deviates from expected value" + Expect.equal oneWayAnova.Total.DegreesOfFreedom 8 "Total.DegreesOfFreedom deviates from expected value" + Expect.floatClose Accuracy.high oneWayAnova.Total.MeanSquares 0.009814 "Total.MeanSquares deviates from expected value" + Expect.floatClose Accuracy.high oneWayAnova.Total.SumOfSquares 0.07851 "Total.SumOfSquares deviates from expected value" + // Expect.floatClose Accuracy.high 0. oneWayAnova.Error.Significance "Error.Significance deviates from expected value" + // Expect.floatClose Accuracy.high 0. oneWayAnova.Error.Statistic "Error.Statistic deviates from expected value" + // Expect.floatClose Accuracy.high 0. oneWayAnova.Total.Significance "Total.Significance deviates from expected value" + // Expect.floatClose Accuracy.high 0. oneWayAnova.Total.Source "Total.Source deviates from expected value" + // Expect.floatClose Accuracy.high 0. oneWayAnova.Total.Statistic "Total.Statistic deviates from expected value" testCase "twoWayANOVAFixed" <| fun () -> - Expect.floatClose Accuracy.high twoWayANOVAFixed_FactorFst_DegreesOfFreed twoWayANOVAFixed.FactorFst.DegreesOfFreed "FactorFst.DegreesOfFreed deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAFixed_FactorFst_MeanSquares twoWayANOVAFixed.FactorFst.MeanSquares "FactorFst.MeanSquares deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAFixed_FactorFst_Significance twoWayANOVAFixed.FactorFst.Significance "FactorFst.Significance deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAFixed_FactorFst_Source twoWayANOVAFixed.FactorFst.Source "FactorFst.Source deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAFixed_FactorFst_Statistic twoWayANOVAFixed.FactorFst.Statistic "FactorFst.Statistic deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAFixed_FactorFst_SumOfSquares twoWayANOVAFixed.FactorFst.SumOfSquares "FactorFst.SumOfSquares deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAFixed_FactorSnd_DegreesOfFreed twoWayANOVAFixed.FactorSnd.DegreesOfFreed "FactorSnd.DegreesOfFreed deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAFixed_FactorSnd_MeanSquares twoWayANOVAFixed.FactorSnd.MeanSquares "FactorSnd.MeanSquares deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAFixed_FactorSnd_Significance twoWayANOVAFixed.FactorSnd.Significance "FactorSnd.Significance deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAFixed_FactorSnd_Source twoWayANOVAFixed.FactorSnd.Source "FactorSnd.Source deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAFixed_FactorSnd_Statistic twoWayANOVAFixed.FactorSnd.Statistic "FactorSnd.Statistic deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAFixed_FactorSnd_SumOfSquares twoWayANOVAFixed.FactorSnd.SumOfSquares "FactorSnd.SumOfSquares deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAFixed_Interaction_DegreesOfFre twoWayANOVAFixed.Interaction.DegreesOfFre "Interaction.DegreesOfFre deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAFixed_Interaction_MeanSquares twoWayANOVAFixed.Interaction.MeanSquares "Interaction.MeanSquares deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAFixed_Interaction_Significance twoWayANOVAFixed.Interaction.Significance "Interaction.Significance deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAFixed_Interaction_Source twoWayANOVAFixed.Interaction.Source "Interaction.Source deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAFixed_Interaction_Statistic twoWayANOVAFixed.Interaction.Statistic "Interaction.Statistic deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAFixed_Interaction_SumOfSquares twoWayANOVAFixed.Interaction.SumOfSquares "Interaction.SumOfSquares deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAFixed_Cells_DegreesOfFreedom twoWayANOVAFixed.Cells.DegreesOfFreedom "Cells.DegreesOfFreedom deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAFixed_Cells_MeanSquares twoWayANOVAFixed.Cells.MeanSquares "Cells.MeanSquares deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAFixed_Cells_Significance twoWayANOVAFixed.Cells.Significance "Cells.Significance deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAFixed_Cells_Source twoWayANOVAFixed.Cells.Source "Cells.Source deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAFixed_Cells_Statistic twoWayANOVAFixed.Cells.Statistic "Cells.Statistic deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAFixed_Cells_SumOfSquares twoWayANOVAFixed.Cells.SumOfSquares "Cells.SumOfSquares deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAFixed_Error_DegreesOfFreedom twoWayANOVAFixed.Error.DegreesOfFreedom "Error.DegreesOfFreedom deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAFixed_Error_MeanSquares twoWayANOVAFixed.Error.MeanSquares "Error.MeanSquares deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAFixed_Error_Significance twoWayANOVAFixed.Error.Significance "Error.Significance deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAFixed_Error_Source twoWayANOVAFixed.Error.Source "Error.Source deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAFixed_Error_Statistic twoWayANOVAFixed.Error.Statistic "Error.Statistic deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAFixed_Error_SumOfSquares twoWayANOVAFixed.Error.SumOfSquares "Error.SumOfSquares deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAFixed_Total_DegreesOfFreedom twoWayANOVAFixed.Total.DegreesOfFreedom "Total.DegreesOfFreedom deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAFixed_Total_MeanSquares twoWayANOVAFixed.Total.MeanSquares "Total.MeanSquares deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAFixed_Total_Significance twoWayANOVAFixed.Total.Significance "Total.Significance deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAFixed_Total_Source twoWayANOVAFixed.Total.Source "Total.Source deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAFixed_Total_Statistic twoWayANOVAFixed.Total.Statistic "Total.Statistic deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAFixed_Total_SumOfSquares twoWayANOVAFixed.Total.SumOfSquares "Total.SumOfSquares deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAFixed.FactorFst.DegreesOfFreedom twoWayANOVAFixed_FactorFst_DegreesOfFreedom "FactorFst.DegreesOfFreed deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAFixed.FactorFst.MeanSquares twoWayANOVAFixed_FactorFst_MeanSquares "FactorFst.MeanSquares deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAFixed.FactorFst.Significance twoWayANOVAFixed_FactorFst_Significance "FactorFst.Significance deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAFixed.FactorFst.Source twoWayANOVAFixed_FactorFst_Source "FactorFst.Source deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAFixed.FactorFst.Statistic twoWayANOVAFixed_FactorFst_Statistic "FactorFst.Statistic deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAFixed.FactorFst.SumOfSquares twoWayANOVAFixed_FactorFst_SumOfSquares "FactorFst.SumOfSquares deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAFixed.FactorSnd.DegreesOfFreedom twoWayANOVAFixed_FactorSnd_DegreesOfFreedom "FactorSnd.DegreesOfFreed deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAFixed.FactorSnd.MeanSquares twoWayANOVAFixed_FactorSnd_MeanSquares "FactorSnd.MeanSquares deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAFixed.FactorSnd.Significance twoWayANOVAFixed_FactorSnd_Significance "FactorSnd.Significance deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAFixed.FactorSnd.Source twoWayANOVAFixed_FactorSnd_Source "FactorSnd.Source deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAFixed.FactorSnd.Statistic twoWayANOVAFixed_FactorSnd_Statistic "FactorSnd.Statistic deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAFixed.FactorSnd.SumOfSquares twoWayANOVAFixed_FactorSnd_SumOfSquares "FactorSnd.SumOfSquares deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAFixed.Interaction.DegreesOfFreedom twoWayANOVAFixed_Interaction_DegreesOfFreedom "Interaction.DegreesOfFre deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAFixed.Interaction.MeanSquares twoWayANOVAFixed_Interaction_MeanSquares "Interaction.MeanSquares deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAFixed.Interaction.Significance twoWayANOVAFixed_Interaction_Significance "Interaction.Significance deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAFixed.Interaction.Source twoWayANOVAFixed_Interaction_Source "Interaction.Source deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAFixed.Interaction.Statistic twoWayANOVAFixed_Interaction_Statistic "Interaction.Statistic deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAFixed.Interaction.SumOfSquares twoWayANOVAFixed_Interaction_SumOfSquares "Interaction.SumOfSquares deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAFixed.Cells.DegreesOfFreedom twoWayANOVAFixed_Cells_DegreesOfFreedom "Cells.DegreesOfFreedom deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAFixed.Cells.MeanSquares twoWayANOVAFixed_Cells_MeanSquares "Cells.MeanSquares deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAFixed.Cells.Significance twoWayANOVAFixed_Cells_Significance "Cells.Significance deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAFixed.Cells.Source twoWayANOVAFixed_Cells_Source "Cells.Source deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAFixed.Cells.Statistic twoWayANOVAFixed_Cells_Statistic "Cells.Statistic deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAFixed.Cells.SumOfSquares twoWayANOVAFixed_Cells_SumOfSquares "Cells.SumOfSquares deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAFixed.Error.DegreesOfFreedom twoWayANOVAFixed_Error_DegreesOfFreedom "Error.DegreesOfFreedom deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAFixed.Error.MeanSquares twoWayANOVAFixed_Error_MeanSquares "Error.MeanSquares deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAFixed.Error.Significance twoWayANOVAFixed_Error_Significance "Error.Significance deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAFixed.Error.Source twoWayANOVAFixed_Error_Source "Error.Source deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAFixed.Error.Statistic twoWayANOVAFixed_Error_Statistic "Error.Statistic deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAFixed.Error.SumOfSquares twoWayANOVAFixed_Error_SumOfSquares "Error.SumOfSquares deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAFixed.Total.DegreesOfFreedom twoWayANOVAFixed_Total_DegreesOfFreedom "Total.DegreesOfFreedom deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAFixed.Total.MeanSquares twoWayANOVAFixed_Total_MeanSquares "Total.MeanSquares deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAFixed.Total.Significance twoWayANOVAFixed_Total_Significance "Total.Significance deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAFixed.Total.Source twoWayANOVAFixed_Total_Source "Total.Source deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAFixed.Total.Statistic twoWayANOVAFixed_Total_Statistic "Total.Statistic deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAFixed.Total.SumOfSquares twoWayANOVAFixed_Total_SumOfSquares "Total.SumOfSquares deviated from expected value" testCase "twoWayANOVAMixed" <| fun () -> - Expect.floatClose Accuracy.high twoWayANOVAMixed_FactorFst_DegreesOfFreed twoWayANOVAMixed.FactorFst.DegreesOfFreed "FactorFst.DegreesOfFreed deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAMixed_FactorFst_DegreesOfFreedom twoWayANOVAMixed.FactorFst.DegreesOfFreedom "FactorFst.DegreesOfFreed deviated from expected value" Expect.floatClose Accuracy.high twoWayANOVAMixed_FactorFst_MeanSquares twoWayANOVAMixed.FactorFst.MeanSquares "FactorFst.MeanSquares deviated from expected value" Expect.floatClose Accuracy.high twoWayANOVAMixed_FactorFst_Significance twoWayANOVAMixed.FactorFst.Significance "FactorFst.Significance deviated from expected value" Expect.floatClose Accuracy.high twoWayANOVAMixed_FactorFst_Source twoWayANOVAMixed.FactorFst.Source "FactorFst.Source deviated from expected value" Expect.floatClose Accuracy.high twoWayANOVAMixed_FactorFst_Statistic twoWayANOVAMixed.FactorFst.Statistic "FactorFst.Statistic deviated from expected value" Expect.floatClose Accuracy.high twoWayANOVAMixed_FactorFst_SumOfSquares twoWayANOVAMixed.FactorFst.SumOfSquares "FactorFst.SumOfSquares deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAMixed_FactorSnd_DegreesOfFreed twoWayANOVAMixed.FactorSnd.DegreesOfFreed "FactorSnd.DegreesOfFreed deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAMixed_FactorSnd_DegreesOfFreedom twoWayANOVAMixed.FactorSnd.DegreesOfFreedom "FactorSnd.DegreesOfFreed deviated from expected value" Expect.floatClose Accuracy.high twoWayANOVAMixed_FactorSnd_MeanSquares twoWayANOVAMixed.FactorSnd.MeanSquares "FactorSnd.MeanSquares deviated from expected value" Expect.floatClose Accuracy.high twoWayANOVAMixed_FactorSnd_Significance twoWayANOVAMixed.FactorSnd.Significance "FactorSnd.Significance deviated from expected value" Expect.floatClose Accuracy.high twoWayANOVAMixed_FactorSnd_Source twoWayANOVAMixed.FactorSnd.Source "FactorSnd.Source deviated from expected value" Expect.floatClose Accuracy.high twoWayANOVAMixed_FactorSnd_Statistic twoWayANOVAMixed.FactorSnd.Statistic "FactorSnd.Statistic deviated from expected value" Expect.floatClose Accuracy.high twoWayANOVAMixed_FactorSnd_SumOfSquares twoWayANOVAMixed.FactorSnd.SumOfSquares "FactorSnd.SumOfSquares deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAMixed_Interaction_DegreesOfFre twoWayANOVAMixed.Interaction.DegreesOfFre "Interaction.DegreesOfFre deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVAMixed_Interaction_DegreesOfFreedom twoWayANOVAMixed.Interaction.DegreesOfFreedom "Interaction.DegreesOfFre deviated from expected value" Expect.floatClose Accuracy.high twoWayANOVAMixed_Interaction_MeanSquares twoWayANOVAMixed.Interaction.MeanSquares "Interaction.MeanSquares deviated from expected value" Expect.floatClose Accuracy.high twoWayANOVAMixed_Interaction_Significance twoWayANOVAMixed.Interaction.Significance "Interaction.Significance deviated from expected value" Expect.floatClose Accuracy.high twoWayANOVAMixed_Interaction_Source twoWayANOVAMixed.Interaction.Source "Interaction.Source deviated from expected value" @@ -1575,19 +1555,19 @@ let anovaTests = Expect.floatClose Accuracy.high twoWayANOVAMixed_Total_SumOfSquares twoWayANOVAMixed.Total.SumOfSquares "Total.SumOfSquares deviated from expected value" testCase "twoWayANOVARandom" <| fun () -> - Expect.floatClose Accuracy.high twoWayANOVARandom_FactorFst_DegreesOfFreed twoWayANOVARandom.FactorFst.DegreesOfFreed "FactorFst.DegreesOfFreed deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVARandom_FactorFst_DegreesOfFreedom twoWayANOVARandom.FactorFst.DegreesOfFreedom "FactorFst.DegreesOfFreed deviated from expected value" Expect.floatClose Accuracy.high twoWayANOVARandom_FactorFst_MeanSquares twoWayANOVARandom.FactorFst.MeanSquares "FactorFst.MeanSquares deviated from expected value" Expect.floatClose Accuracy.high twoWayANOVARandom_FactorFst_Significance twoWayANOVARandom.FactorFst.Significance "FactorFst.Significance deviated from expected value" Expect.floatClose Accuracy.high twoWayANOVARandom_FactorFst_Source twoWayANOVARandom.FactorFst.Source "FactorFst.Source deviated from expected value" Expect.floatClose Accuracy.high twoWayANOVARandom_FactorFst_Statistic twoWayANOVARandom.FactorFst.Statistic "FactorFst.Statistic deviated from expected value" Expect.floatClose Accuracy.high twoWayANOVARandom_FactorFst_SumOfSquares twoWayANOVARandom.FactorFst.SumOfSquares "FactorFst.SumOfSquares deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVARandom_FactorSnd_DegreesOfFreed twoWayANOVARandom.FactorSnd.DegreesOfFreed "FactorSnd.DegreesOfFreed deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVARandom_FactorSnd_DegreesOfFreedom twoWayANOVARandom.FactorSnd.DegreesOfFreedom "FactorSnd.DegreesOfFreed deviated from expected value" Expect.floatClose Accuracy.high twoWayANOVARandom_FactorSnd_MeanSquares twoWayANOVARandom.FactorSnd.MeanSquares "FactorSnd.MeanSquares deviated from expected value" Expect.floatClose Accuracy.high twoWayANOVARandom_FactorSnd_Significance twoWayANOVARandom.FactorSnd.Significance "FactorSnd.Significance deviated from expected value" Expect.floatClose Accuracy.high twoWayANOVARandom_FactorSnd_Source twoWayANOVARandom.FactorSnd.Source "FactorSnd.Source deviated from expected value" Expect.floatClose Accuracy.high twoWayANOVARandom_FactorSnd_Statistic twoWayANOVARandom.FactorSnd.Statistic "FactorSnd.Statistic deviated from expected value" Expect.floatClose Accuracy.high twoWayANOVARandom_FactorSnd_SumOfSquares twoWayANOVARandom.FactorSnd.SumOfSquares "FactorSnd.SumOfSquares deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVARandom_Interaction_DegreesOfFre twoWayANOVARandom.Interaction.DegreesOfFre "Interaction.DegreesOfFre deviated from expected value" + Expect.floatClose Accuracy.high twoWayANOVARandom_Interaction_DegreesOfFreedom twoWayANOVARandom.Interaction.DegreesOfFreedom "Interaction.DegreesOfFre deviated from expected value" Expect.floatClose Accuracy.high twoWayANOVARandom_Interaction_MeanSquares twoWayANOVARandom.Interaction.MeanSquares "Interaction.MeanSquares deviated from expected value" Expect.floatClose Accuracy.high twoWayANOVARandom_Interaction_Significance twoWayANOVARandom.Interaction.Significance "Interaction.Significance deviated from expected value" Expect.floatClose Accuracy.high twoWayANOVARandom_Interaction_Source twoWayANOVARandom.Interaction.Source "Interaction.Source deviated from expected value" From d442db1f2b913970840b473b6c8d60a81f3039dd Mon Sep 17 00:00:00 2001 From: Christopher Lux <59606965+LibraChris@users.noreply.github.com> Date: Sat, 9 Aug 2025 01:52:10 +0200 Subject: [PATCH 107/121] Fix m F-test statistics in ANOVA mixed model --- src/FSharp.Stats/Testing/Anova.fs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/FSharp.Stats/Testing/Anova.fs b/src/FSharp.Stats/Testing/Anova.fs index 6c68b925d..b18ab2c67 100644 --- a/src/FSharp.Stats/Testing/Anova.fs +++ b/src/FSharp.Stats/Testing/Anova.fs @@ -262,8 +262,8 @@ module Anova = | Mixed -> // Model 3: Factor A fixed, factor B random ( - (Testing.TestStatistics.createFTest(fstFactorMeanSquares / factorMeanSquares) fstFactorDf factorDf), - (Testing.TestStatistics.createFTest(sndFactorMeanSquares / errorMeanSquares) sndFactorDf errorDf), + (Testing.TestStatistics.createFTest(fstFactorMeanSquares / errorMeanSquares) fstFactorDf errorDf), + (Testing.TestStatistics.createFTest(sndFactorMeanSquares / factorMeanSquares) sndFactorDf factorDf), (Testing.TestStatistics.createFTest(factorMeanSquares / errorMeanSquares) factorDf errorDf) ) From e7cf1fefe4456cb0237647b8b1b4f3fae3765f92 Mon Sep 17 00:00:00 2001 From: Christopher Lux <59606965+LibraChris@users.noreply.github.com> Date: Sat, 9 Aug 2025 01:52:36 +0200 Subject: [PATCH 108/121] Finish twowayAnova tests --- tests/FSharp.Stats.Tests/Testing.fs | 322 ++++++++-------------------- 1 file changed, 87 insertions(+), 235 deletions(-) diff --git a/tests/FSharp.Stats.Tests/Testing.fs b/tests/FSharp.Stats.Tests/Testing.fs index 675d569ab..cf867dd50 100644 --- a/tests/FSharp.Stats.Tests/Testing.fs +++ b/tests/FSharp.Stats.Tests/Testing.fs @@ -1346,132 +1346,21 @@ let anovaTests = let twoWayANOVAMixed = twoWaySetup|>Anova.twoWayANOVA Anova.TwoWayAnovaModel.Mixed let twoWayANOVARandom = twoWaySetup|>Anova.twoWayANOVA Anova.TwoWayAnovaModel.Random - let twoWayANOVAFixed_FactorFst_DegreesOfFreedom = 0. - let twoWayANOVAFixed_FactorFst_MeanSquares = 0. - let twoWayANOVAFixed_FactorFst_Significance = 0. - let twoWayANOVAFixed_FactorFst_Source = 0. - let twoWayANOVAFixed_FactorFst_Statistic = 0. - let twoWayANOVAFixed_FactorFst_SumOfSquares = 0. - let twoWayANOVAFixed_FactorSnd_DegreesOfFreedom = 0. - let twoWayANOVAFixed_FactorSnd_MeanSquares = 0. - let twoWayANOVAFixed_FactorSnd_Significance = 0. - let twoWayANOVAFixed_FactorSnd_Source = 0. - let twoWayANOVAFixed_FactorSnd_Statistic = 0. - let twoWayANOVAFixed_FactorSnd_SumOfSquares = 0. - let twoWayANOVAFixed_Interaction_DegreesOfFreedom = 0. - let twoWayANOVAFixed_Interaction_MeanSquares = 0. - let twoWayANOVAFixed_Interaction_Significance = 0. - let twoWayANOVAFixed_Interaction_Source = 0. - let twoWayANOVAFixed_Interaction_Statistic = 0. - let twoWayANOVAFixed_Interaction_SumOfSquares = 0. - let twoWayANOVAFixed_Cells_DegreesOfFreedom = 0. - let twoWayANOVAFixed_Cells_MeanSquares = 0. - let twoWayANOVAFixed_Cells_Significance = 0. - let twoWayANOVAFixed_Cells_Source = 0. - let twoWayANOVAFixed_Cells_Statistic = 0. - let twoWayANOVAFixed_Cells_SumOfSquares = 0. - let twoWayANOVAFixed_Error_DegreesOfFreedom = 0. - let twoWayANOVAFixed_Error_MeanSquares = 0. - let twoWayANOVAFixed_Error_Significance = 0. - let twoWayANOVAFixed_Error_Source = 0. - let twoWayANOVAFixed_Error_Statistic = 0. - let twoWayANOVAFixed_Error_SumOfSquares = 0. - let twoWayANOVAFixed_Total_DegreesOfFreedom = 0. - let twoWayANOVAFixed_Total_MeanSquares = 0. - let twoWayANOVAFixed_Total_Significance = 0. - let twoWayANOVAFixed_Total_Source = 0. - let twoWayANOVAFixed_Total_Statistic = 0. - let twoWayANOVAFixed_Total_SumOfSquares = 0. - - let twoWayANOVAMixed_FactorFst_DegreesOfFreedom = 0. - let twoWayANOVAMixed_FactorFst_MeanSquares = 0. - let twoWayANOVAMixed_FactorFst_Significance = 0. - let twoWayANOVAMixed_FactorFst_Source = 0. - let twoWayANOVAMixed_FactorFst_Statistic = 0. - let twoWayANOVAMixed_FactorFst_SumOfSquares = 0. - let twoWayANOVAMixed_FactorSnd_DegreesOfFreedom = 0. - let twoWayANOVAMixed_FactorSnd_MeanSquares = 0. - let twoWayANOVAMixed_FactorSnd_Significance = 0. - let twoWayANOVAMixed_FactorSnd_Source = 0. - let twoWayANOVAMixed_FactorSnd_Statistic = 0. - let twoWayANOVAMixed_FactorSnd_SumOfSquares = 0. - let twoWayANOVAMixed_Interaction_DegreesOfFreedom = 0. - let twoWayANOVAMixed_Interaction_MeanSquares = 0. - let twoWayANOVAMixed_Interaction_Significance = 0. - let twoWayANOVAMixed_Interaction_Source = 0. - let twoWayANOVAMixed_Interaction_Statistic = 0. - let twoWayANOVAMixed_Interaction_SumOfSquares = 0. - let twoWayANOVAMixed_Cells_DegreesOfFreedom = 0. - let twoWayANOVAMixed_Cells_MeanSquares = 0. - let twoWayANOVAMixed_Cells_Significance = 0. - let twoWayANOVAMixed_Cells_Source = 0. - let twoWayANOVAMixed_Cells_Statistic = 0. - let twoWayANOVAMixed_Cells_SumOfSquares = 0. - let twoWayANOVAMixed_Error_DegreesOfFreedom = 0. - let twoWayANOVAMixed_Error_MeanSquares = 0. - let twoWayANOVAMixed_Error_Significance = 0. - let twoWayANOVAMixed_Error_Source = 0. - let twoWayANOVAMixed_Error_Statistic = 0. - let twoWayANOVAMixed_Error_SumOfSquares = 0. - let twoWayANOVAMixed_Total_DegreesOfFreedom = 0. - let twoWayANOVAMixed_Total_MeanSquares = 0. - let twoWayANOVAMixed_Total_Significance = 0. - let twoWayANOVAMixed_Total_Source = 0. - let twoWayANOVAMixed_Total_Statistic = 0. - let twoWayANOVAMixed_Total_SumOfSquares = 0. - - let twoWayANOVARandom_FactorFst_DegreesOfFreedom = 0. - let twoWayANOVARandom_FactorFst_MeanSquares = 0. - let twoWayANOVARandom_FactorFst_Significance = 0. - let twoWayANOVARandom_FactorFst_Source = 0. - let twoWayANOVARandom_FactorFst_Statistic = 0. - let twoWayANOVARandom_FactorFst_SumOfSquares = 0. - let twoWayANOVARandom_FactorSnd_DegreesOfFreedom = 0. - let twoWayANOVARandom_FactorSnd_MeanSquares = 0. - let twoWayANOVARandom_FactorSnd_Significance = 0. - let twoWayANOVARandom_FactorSnd_Source = 0. - let twoWayANOVARandom_FactorSnd_Statistic = 0. - let twoWayANOVARandom_FactorSnd_SumOfSquares = 0. - let twoWayANOVARandom_Interaction_DegreesOfFreedom = 0. - let twoWayANOVARandom_Interaction_MeanSquares = 0. - let twoWayANOVARandom_Interaction_Significance = 0. - let twoWayANOVARandom_Interaction_Source = 0. - let twoWayANOVARandom_Interaction_Statistic = 0. - let twoWayANOVARandom_Interaction_SumOfSquares = 0. - let twoWayANOVARandom_Cells_DegreesOfFreedom = 0. - let twoWayANOVARandom_Cells_MeanSquares = 0. - let twoWayANOVARandom_Cells_Significance = 0. - let twoWayANOVARandom_Cells_Source = 0. - let twoWayANOVARandom_Cells_Statistic = 0. - let twoWayANOVARandom_Cells_SumOfSquares = 0. - let twoWayANOVARandom_Error_DegreesOfFreedom = 0. - let twoWayANOVARandom_Error_MeanSquares = 0. - let twoWayANOVARandom_Error_Significance = 0. - let twoWayANOVARandom_Error_Source = 0. - let twoWayANOVARandom_Error_Statistic = 0. - let twoWayANOVARandom_Error_SumOfSquares = 0. - let twoWayANOVARandom_Total_DegreesOfFreedom = 0. - let twoWayANOVARandom_Total_MeanSquares = 0. - let twoWayANOVARandom_Total_Significance = 0. - let twoWayANOVARandom_Total_Source = 0. - let twoWayANOVARandom_Total_Statistic = 0. - let twoWayANOVARandom_Total_SumOfSquares = 0. - testList "Testing.Anova" [ testCase "onewayAnova" <| fun () -> - Expect.equal oneWayAnova.Factor.DegreesOfFreedom 2 "Factor.DegreesOfFreedom deviates from expected value" - Expect.floatClose Accuracy.high oneWayAnova.Factor.MeanSquares 0.022925 "Factor.MeanSquares deviates from expected value" - Expect.floatClose Accuracy.high oneWayAnova.Factor.Significance 0.072 "Factor.Significance deviates from expected value" - Expect.equal oneWayAnova.Factor.Source Anova.BetweenGroups "Factor.Source deviates from expected value" - Expect.floatClose Accuracy.high oneWayAnova.Factor.Statistic 4.211 "Factor.Statistic deviates from expected value" - Expect.floatClose Accuracy.high oneWayAnova.Factor.SumOfSquares 0.04585 "Factor.SumOfSquares deviates from expected value" - Expect.equal oneWayAnova.Error.DegreesOfFreedom 6 "Error.DegreesOfFreedom deviates from expected value" - Expect.floatClose Accuracy.high oneWayAnova.Error.MeanSquares 0.005444 "Error.MeanSquares deviates from expected value" - Expect.equal oneWayAnova.Error.Source Anova.WithinGroups "Error.Source deviates from expected value" - Expect.floatClose Accuracy.high oneWayAnova.Error.SumOfSquares 0.03266 "Error.SumOfSquares deviates from expected value" - Expect.equal oneWayAnova.Total.DegreesOfFreedom 8 "Total.DegreesOfFreedom deviates from expected value" - Expect.floatClose Accuracy.high oneWayAnova.Total.MeanSquares 0.009814 "Total.MeanSquares deviates from expected value" - Expect.floatClose Accuracy.high oneWayAnova.Total.SumOfSquares 0.07851 "Total.SumOfSquares deviates from expected value" + Expect.equal oneWayAnova.Factor.DegreesOfFreedom 2 "Factor.DegreesOfFreedom deviates from expected value" + Expect.floatClose Accuracy.low (Math.Round (oneWayAnova.Factor.MeanSquares,8)) 0.022925 "Factor.MeanSquares deviates from expected value" + Expect.floatClose Accuracy.low (Math.Round (oneWayAnova.Factor.Significance,8)) 0.072 "Factor.Significance deviates from expected value" + Expect.equal oneWayAnova.Factor.Source Anova.BetweenGroups "Factor.Source deviates from expected value" + Expect.floatClose Accuracy.low (Math.Round (oneWayAnova.Factor.Statistic,8)) 4.211 "Factor.Statistic deviates from expected value" + Expect.floatClose Accuracy.low (Math.Round (oneWayAnova.Factor.SumOfSquares,8)) 0.04585 "Factor.SumOfSquares deviates from expected value" + Expect.equal oneWayAnova.Error.DegreesOfFreedom 6 "Error.DegreesOfFreedom deviates from expected value" + Expect.floatClose Accuracy.low (Math.Round (oneWayAnova.Error.MeanSquares,8)) 0.005444 "Error.MeanSquares deviates from expected value" + Expect.equal oneWayAnova.Error.Source Anova.WithinGroups "Error.Source deviates from expected value" + Expect.floatClose Accuracy.low (Math.Round (oneWayAnova.Error.SumOfSquares,8)) 0.03266 "Error.SumOfSquares deviates from expected value" + Expect.equal oneWayAnova.Total.DegreesOfFreedom 8 "Total.DegreesOfFreedom deviates from expected value" + Expect.floatClose Accuracy.low (Math.Round (oneWayAnova.Total.MeanSquares,8)) 0.009814 "Total.MeanSquares deviates from expected value" + Expect.floatClose Accuracy.low (Math.Round (oneWayAnova.Total.SumOfSquares,8)) 0.07851 "Total.SumOfSquares deviates from expected value" // Expect.floatClose Accuracy.high 0. oneWayAnova.Error.Significance "Error.Significance deviates from expected value" // Expect.floatClose Accuracy.high 0. oneWayAnova.Error.Statistic "Error.Statistic deviates from expected value" // Expect.floatClose Accuracy.high 0. oneWayAnova.Total.Significance "Total.Significance deviates from expected value" @@ -1479,117 +1368,80 @@ let anovaTests = // Expect.floatClose Accuracy.high 0. oneWayAnova.Total.Statistic "Total.Statistic deviates from expected value" testCase "twoWayANOVAFixed" <| fun () -> - Expect.floatClose Accuracy.high twoWayANOVAFixed.FactorFst.DegreesOfFreedom twoWayANOVAFixed_FactorFst_DegreesOfFreedom "FactorFst.DegreesOfFreed deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAFixed.FactorFst.MeanSquares twoWayANOVAFixed_FactorFst_MeanSquares "FactorFst.MeanSquares deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAFixed.FactorFst.Significance twoWayANOVAFixed_FactorFst_Significance "FactorFst.Significance deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAFixed.FactorFst.Source twoWayANOVAFixed_FactorFst_Source "FactorFst.Source deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAFixed.FactorFst.Statistic twoWayANOVAFixed_FactorFst_Statistic "FactorFst.Statistic deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAFixed.FactorFst.SumOfSquares twoWayANOVAFixed_FactorFst_SumOfSquares "FactorFst.SumOfSquares deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAFixed.FactorSnd.DegreesOfFreedom twoWayANOVAFixed_FactorSnd_DegreesOfFreedom "FactorSnd.DegreesOfFreed deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAFixed.FactorSnd.MeanSquares twoWayANOVAFixed_FactorSnd_MeanSquares "FactorSnd.MeanSquares deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAFixed.FactorSnd.Significance twoWayANOVAFixed_FactorSnd_Significance "FactorSnd.Significance deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAFixed.FactorSnd.Source twoWayANOVAFixed_FactorSnd_Source "FactorSnd.Source deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAFixed.FactorSnd.Statistic twoWayANOVAFixed_FactorSnd_Statistic "FactorSnd.Statistic deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAFixed.FactorSnd.SumOfSquares twoWayANOVAFixed_FactorSnd_SumOfSquares "FactorSnd.SumOfSquares deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAFixed.Interaction.DegreesOfFreedom twoWayANOVAFixed_Interaction_DegreesOfFreedom "Interaction.DegreesOfFre deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAFixed.Interaction.MeanSquares twoWayANOVAFixed_Interaction_MeanSquares "Interaction.MeanSquares deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAFixed.Interaction.Significance twoWayANOVAFixed_Interaction_Significance "Interaction.Significance deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAFixed.Interaction.Source twoWayANOVAFixed_Interaction_Source "Interaction.Source deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAFixed.Interaction.Statistic twoWayANOVAFixed_Interaction_Statistic "Interaction.Statistic deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAFixed.Interaction.SumOfSquares twoWayANOVAFixed_Interaction_SumOfSquares "Interaction.SumOfSquares deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAFixed.Cells.DegreesOfFreedom twoWayANOVAFixed_Cells_DegreesOfFreedom "Cells.DegreesOfFreedom deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAFixed.Cells.MeanSquares twoWayANOVAFixed_Cells_MeanSquares "Cells.MeanSquares deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAFixed.Cells.Significance twoWayANOVAFixed_Cells_Significance "Cells.Significance deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAFixed.Cells.Source twoWayANOVAFixed_Cells_Source "Cells.Source deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAFixed.Cells.Statistic twoWayANOVAFixed_Cells_Statistic "Cells.Statistic deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAFixed.Cells.SumOfSquares twoWayANOVAFixed_Cells_SumOfSquares "Cells.SumOfSquares deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAFixed.Error.DegreesOfFreedom twoWayANOVAFixed_Error_DegreesOfFreedom "Error.DegreesOfFreedom deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAFixed.Error.MeanSquares twoWayANOVAFixed_Error_MeanSquares "Error.MeanSquares deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAFixed.Error.Significance twoWayANOVAFixed_Error_Significance "Error.Significance deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAFixed.Error.Source twoWayANOVAFixed_Error_Source "Error.Source deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAFixed.Error.Statistic twoWayANOVAFixed_Error_Statistic "Error.Statistic deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAFixed.Error.SumOfSquares twoWayANOVAFixed_Error_SumOfSquares "Error.SumOfSquares deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAFixed.Total.DegreesOfFreedom twoWayANOVAFixed_Total_DegreesOfFreedom "Total.DegreesOfFreedom deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAFixed.Total.MeanSquares twoWayANOVAFixed_Total_MeanSquares "Total.MeanSquares deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAFixed.Total.Significance twoWayANOVAFixed_Total_Significance "Total.Significance deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAFixed.Total.Source twoWayANOVAFixed_Total_Source "Total.Source deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAFixed.Total.Statistic twoWayANOVAFixed_Total_Statistic "Total.Statistic deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAFixed.Total.SumOfSquares twoWayANOVAFixed_Total_SumOfSquares "Total.SumOfSquares deviated from expected value" - + Expect.equal twoWayANOVAFixed.FactorFst.DegreesOfFreedom 2 "FactorFst.DegreesOfFreed deviated from expected value" + Expect.floatClose Accuracy.low (Math.Round (twoWayANOVAFixed.FactorFst.MeanSquares,8)) 0.2386 "FactorFst.MeanSquares deviated from expected value" + Expect.floatClose Accuracy.low (Math.Round (twoWayANOVAFixed.FactorFst.Significance,8)) 0.00002717 "FactorFst.Significance deviated from expected value" + Expect.equal twoWayANOVAFixed.FactorFst.Source Anova.Residual "FactorFst.Source deviated from expected value" + Expect.floatClose Accuracy.low (Math.Round (twoWayANOVAFixed.FactorFst.Statistic,8)) 28.6043 "FactorFst.Statistic deviated from expected value" + Expect.floatClose Accuracy.low (Math.Round (twoWayANOVAFixed.FactorFst.SumOfSquares,8)) 0.4771 "FactorFst.SumOfSquares deviated from expected value" + Expect.equal twoWayANOVAFixed.FactorSnd.DegreesOfFreedom 1 "FactorSnd.DegreesOfFreed deviated from expected value" + Expect.floatClose Accuracy.low (Math.Round (twoWayANOVAFixed.FactorSnd.MeanSquares,8)) 0.01404 "FactorSnd.MeanSquares deviated from expected value" + Expect.floatClose Accuracy.low (Math.Round (twoWayANOVAFixed.FactorSnd.Significance,8)) 0.21898 "FactorSnd.Significance deviated from expected value" + Expect.equal twoWayANOVAFixed.FactorSnd.Source Anova.Residual "FactorSnd.Source deviated from expected value" + Expect.floatClose Accuracy.low (Math.Round (twoWayANOVAFixed.FactorSnd.Statistic,8)) 1.6831 "FactorSnd.Statistic deviated from expected value" + Expect.floatClose Accuracy.low (Math.Round (twoWayANOVAFixed.FactorSnd.SumOfSquares,8)) 0.01404 "FactorSnd.SumOfSquares deviated from expected value" + Expect.equal twoWayANOVAFixed.Interaction.DegreesOfFreedom 2 "Interaction.DegreesOfFre deviated from expected value" + Expect.floatClose Accuracy.low (Math.Round (twoWayANOVAFixed.Interaction.MeanSquares,8)) 0.09512 "Interaction.MeanSquares deviated from expected value" + Expect.floatClose Accuracy.low (Math.Round (twoWayANOVAFixed.Interaction.Significance,8)) 0.001678 "Interaction.Significance deviated from expected value" + Expect.equal twoWayANOVAFixed.Interaction.Source Anova.BetweenGroups "Interaction.Source deviated from expected value" + Expect.floatClose Accuracy.low (Math.Round (twoWayANOVAFixed.Interaction.Statistic,8)) 11.4052 "Interaction.Statistic deviated from expected value" + Expect.floatClose Accuracy.low (Math.Round (twoWayANOVAFixed.Interaction.SumOfSquares,8)) 0.1902 "Interaction.SumOfSquares deviated from expected value" + Expect.equal twoWayANOVAFixed.Error.DegreesOfFreedom 12 "Error.DegreesOfFreedom deviated from expected value" + Expect.floatClose Accuracy.low (Math.Round (twoWayANOVAFixed.Error.MeanSquares,8)) 0.00834 "Error.MeanSquares deviated from expected value" + Expect.equal twoWayANOVAFixed.Total.DegreesOfFreedom 17 "Total.DegreesOfFreedom deviated from expected value" + // Expect.floatClose Accuracy.low (Math.Round (twoWayANOVAFixed.Total.SumOfSquares,8)) 0.7815 "Total.SumOfSquares deviated from expected value" + // Expect.floatClose Accuracy.low (Math.Round (twoWayANOVAFixed.Total.MeanSquares,8)) 0.04597 "Total.MeanSquares deviated from expected value" + testCase "twoWayANOVAMixed" <| fun () -> - Expect.floatClose Accuracy.high twoWayANOVAMixed_FactorFst_DegreesOfFreedom twoWayANOVAMixed.FactorFst.DegreesOfFreedom "FactorFst.DegreesOfFreed deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAMixed_FactorFst_MeanSquares twoWayANOVAMixed.FactorFst.MeanSquares "FactorFst.MeanSquares deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAMixed_FactorFst_Significance twoWayANOVAMixed.FactorFst.Significance "FactorFst.Significance deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAMixed_FactorFst_Source twoWayANOVAMixed.FactorFst.Source "FactorFst.Source deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAMixed_FactorFst_Statistic twoWayANOVAMixed.FactorFst.Statistic "FactorFst.Statistic deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAMixed_FactorFst_SumOfSquares twoWayANOVAMixed.FactorFst.SumOfSquares "FactorFst.SumOfSquares deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAMixed_FactorSnd_DegreesOfFreedom twoWayANOVAMixed.FactorSnd.DegreesOfFreedom "FactorSnd.DegreesOfFreed deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAMixed_FactorSnd_MeanSquares twoWayANOVAMixed.FactorSnd.MeanSquares "FactorSnd.MeanSquares deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAMixed_FactorSnd_Significance twoWayANOVAMixed.FactorSnd.Significance "FactorSnd.Significance deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAMixed_FactorSnd_Source twoWayANOVAMixed.FactorSnd.Source "FactorSnd.Source deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAMixed_FactorSnd_Statistic twoWayANOVAMixed.FactorSnd.Statistic "FactorSnd.Statistic deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAMixed_FactorSnd_SumOfSquares twoWayANOVAMixed.FactorSnd.SumOfSquares "FactorSnd.SumOfSquares deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAMixed_Interaction_DegreesOfFreedom twoWayANOVAMixed.Interaction.DegreesOfFreedom "Interaction.DegreesOfFre deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAMixed_Interaction_MeanSquares twoWayANOVAMixed.Interaction.MeanSquares "Interaction.MeanSquares deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAMixed_Interaction_Significance twoWayANOVAMixed.Interaction.Significance "Interaction.Significance deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAMixed_Interaction_Source twoWayANOVAMixed.Interaction.Source "Interaction.Source deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAMixed_Interaction_Statistic twoWayANOVAMixed.Interaction.Statistic "Interaction.Statistic deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAMixed_Interaction_SumOfSquares twoWayANOVAMixed.Interaction.SumOfSquares "Interaction.SumOfSquares deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAMixed_Cells_DegreesOfFreedom twoWayANOVAMixed.Cells.DegreesOfFreedom "Cells.DegreesOfFreedom deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAMixed_Cells_MeanSquares twoWayANOVAMixed.Cells.MeanSquares "Cells.MeanSquares deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAMixed_Cells_Significance twoWayANOVAMixed.Cells.Significance "Cells.Significance deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAMixed_Cells_Source twoWayANOVAMixed.Cells.Source "Cells.Source deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAMixed_Cells_Statistic twoWayANOVAMixed.Cells.Statistic "Cells.Statistic deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAMixed_Cells_SumOfSquares twoWayANOVAMixed.Cells.SumOfSquares "Cells.SumOfSquares deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAMixed_Error_DegreesOfFreedom twoWayANOVAMixed.Error.DegreesOfFreedom "Error.DegreesOfFreedom deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAMixed_Error_MeanSquares twoWayANOVAMixed.Error.MeanSquares "Error.MeanSquares deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAMixed_Error_Significance twoWayANOVAMixed.Error.Significance "Error.Significance deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAMixed_Error_Source twoWayANOVAMixed.Error.Source "Error.Source deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAMixed_Error_Statistic twoWayANOVAMixed.Error.Statistic "Error.Statistic deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAMixed_Error_SumOfSquares twoWayANOVAMixed.Error.SumOfSquares "Error.SumOfSquares deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAMixed_Total_DegreesOfFreedom twoWayANOVAMixed.Total.DegreesOfFreedom "Total.DegreesOfFreedom deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAMixed_Total_MeanSquares twoWayANOVAMixed.Total.MeanSquares "Total.MeanSquares deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAMixed_Total_Significance twoWayANOVAMixed.Total.Significance "Total.Significance deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAMixed_Total_Source twoWayANOVAMixed.Total.Source "Total.Source deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAMixed_Total_Statistic twoWayANOVAMixed.Total.Statistic "Total.Statistic deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVAMixed_Total_SumOfSquares twoWayANOVAMixed.Total.SumOfSquares "Total.SumOfSquares deviated from expected value" - + Expect.equal twoWayANOVAMixed.FactorFst.DegreesOfFreedom 2 "FactorFst.DegreesOfFreed deviated from expected value" + Expect.floatClose Accuracy.low (Math.Round (twoWayANOVAMixed.FactorFst.MeanSquares,8)) 0.2386 "FactorFst.MeanSquares deviated from expected value" + Expect.floatClose Accuracy.low (Math.Round (twoWayANOVAMixed.FactorFst.Significance,8)) 0.00002717 "FactorFst.Significance deviated from expected value" + Expect.equal twoWayANOVAMixed.FactorFst.Source Anova.Residual "FactorFst.Source deviated from expected value" + Expect.floatClose Accuracy.low (Math.Round (twoWayANOVAMixed.FactorFst.Statistic,8)) 28.6043 "FactorFst.Statistic deviated from expected value" + Expect.floatClose Accuracy.low (Math.Round (twoWayANOVAMixed.FactorFst.SumOfSquares,8)) 0.4771 "FactorFst.SumOfSquares deviated from expected value" + Expect.equal twoWayANOVAMixed.FactorSnd.DegreesOfFreedom 1 "FactorSnd.DegreesOfFreed deviated from expected value" + Expect.floatClose Accuracy.low (Math.Round (twoWayANOVAMixed.FactorSnd.MeanSquares,8)) 0.01404 "FactorSnd.MeanSquares deviated from expected value" + Expect.floatClose Accuracy.low (Math.Round (twoWayANOVAMixed.FactorSnd.Significance,8)) 0.7379 "FactorSnd.Significance deviated from expected value" + Expect.equal twoWayANOVAMixed.FactorSnd.Source Anova.Residual "FactorSnd.Source deviated from expected value" + Expect.floatClose Accuracy.low (Math.Round (twoWayANOVAMixed.FactorSnd.Statistic,8)) 0.1476 "FactorSnd.Statistic deviated from expected value" + Expect.floatClose Accuracy.low (Math.Round (twoWayANOVAMixed.FactorSnd.SumOfSquares,8)) 0.01404 "FactorSnd.SumOfSquares deviated from expected value" + Expect.equal twoWayANOVAMixed.Interaction.DegreesOfFreedom 2 "Interaction.DegreesOfFre deviated from expected value" + Expect.floatClose Accuracy.low (Math.Round (twoWayANOVAMixed.Interaction.MeanSquares,8)) 0.09512 "Interaction.MeanSquares deviated from expected value" + Expect.floatClose Accuracy.low (Math.Round (twoWayANOVAMixed.Interaction.Significance,8)) 0.001678 "Interaction.Significance deviated from expected value" + Expect.equal twoWayANOVAMixed.Interaction.Source Anova.BetweenGroups "Interaction.Source deviated from expected value" + Expect.floatClose Accuracy.low (Math.Round (twoWayANOVAMixed.Interaction.Statistic,8)) 11.4052 "Interaction.Statistic deviated from expected value" + Expect.floatClose Accuracy.low (Math.Round (twoWayANOVAMixed.Interaction.SumOfSquares,8)) 0.1902 "Interaction.SumOfSquares deviated from expected value" + Expect.equal twoWayANOVAMixed.Error.DegreesOfFreedom 12 "Error.DegreesOfFreedom deviated from expected value" + Expect.floatClose Accuracy.low (Math.Round (twoWayANOVAMixed.Error.MeanSquares,8)) 0.00834 "Error.MeanSquares deviated from expected value" + Expect.floatClose Accuracy.low (Math.Round (twoWayANOVAMixed.Error.SumOfSquares,8)) 0.1001 "Error.MeanSquares deviated from expected value" + Expect.equal twoWayANOVAMixed.Total.DegreesOfFreedom 17 "Total.DegreesOfFreedom deviated from expected value" + // Expect.floatClose Accuracy.low (Math.Round (twoWayANOVAMixed.Total.SumOfSquares,8)) 0.7815 "Total.SumOfSquares deviated from expected value" + // Expect.floatClose Accuracy.low (Math.Round (twoWayANOVAMixed.Total.MeanSquares,8)) 0.04597 "Total.MeanSquares deviated from expected value" + testCase "twoWayANOVARandom" <| fun () -> - Expect.floatClose Accuracy.high twoWayANOVARandom_FactorFst_DegreesOfFreedom twoWayANOVARandom.FactorFst.DegreesOfFreedom "FactorFst.DegreesOfFreed deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVARandom_FactorFst_MeanSquares twoWayANOVARandom.FactorFst.MeanSquares "FactorFst.MeanSquares deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVARandom_FactorFst_Significance twoWayANOVARandom.FactorFst.Significance "FactorFst.Significance deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVARandom_FactorFst_Source twoWayANOVARandom.FactorFst.Source "FactorFst.Source deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVARandom_FactorFst_Statistic twoWayANOVARandom.FactorFst.Statistic "FactorFst.Statistic deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVARandom_FactorFst_SumOfSquares twoWayANOVARandom.FactorFst.SumOfSquares "FactorFst.SumOfSquares deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVARandom_FactorSnd_DegreesOfFreedom twoWayANOVARandom.FactorSnd.DegreesOfFreedom "FactorSnd.DegreesOfFreed deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVARandom_FactorSnd_MeanSquares twoWayANOVARandom.FactorSnd.MeanSquares "FactorSnd.MeanSquares deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVARandom_FactorSnd_Significance twoWayANOVARandom.FactorSnd.Significance "FactorSnd.Significance deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVARandom_FactorSnd_Source twoWayANOVARandom.FactorSnd.Source "FactorSnd.Source deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVARandom_FactorSnd_Statistic twoWayANOVARandom.FactorSnd.Statistic "FactorSnd.Statistic deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVARandom_FactorSnd_SumOfSquares twoWayANOVARandom.FactorSnd.SumOfSquares "FactorSnd.SumOfSquares deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVARandom_Interaction_DegreesOfFreedom twoWayANOVARandom.Interaction.DegreesOfFreedom "Interaction.DegreesOfFre deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVARandom_Interaction_MeanSquares twoWayANOVARandom.Interaction.MeanSquares "Interaction.MeanSquares deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVARandom_Interaction_Significance twoWayANOVARandom.Interaction.Significance "Interaction.Significance deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVARandom_Interaction_Source twoWayANOVARandom.Interaction.Source "Interaction.Source deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVARandom_Interaction_Statistic twoWayANOVARandom.Interaction.Statistic "Interaction.Statistic deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVARandom_Interaction_SumOfSquares twoWayANOVARandom.Interaction.SumOfSquares "Interaction.SumOfSquares deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVARandom_Cells_DegreesOfFreedom twoWayANOVARandom.Cells.DegreesOfFreedom "Cells.DegreesOfFreedom deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVARandom_Cells_MeanSquares twoWayANOVARandom.Cells.MeanSquares "Cells.MeanSquares deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVARandom_Cells_Significance twoWayANOVARandom.Cells.Significance "Cells.Significance deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVARandom_Cells_Source twoWayANOVARandom.Cells.Source "Cells.Source deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVARandom_Cells_Statistic twoWayANOVARandom.Cells.Statistic "Cells.Statistic deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVARandom_Cells_SumOfSquares twoWayANOVARandom.Cells.SumOfSquares "Cells.SumOfSquares deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVARandom_Error_DegreesOfFreedom twoWayANOVARandom.Error.DegreesOfFreedom "Error.DegreesOfFreedom deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVARandom_Error_MeanSquares twoWayANOVARandom.Error.MeanSquares "Error.MeanSquares deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVARandom_Error_Significance twoWayANOVARandom.Error.Significance "Error.Significance deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVARandom_Error_Source twoWayANOVARandom.Error.Source "Error.Source deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVARandom_Error_Statistic twoWayANOVARandom.Error.Statistic "Error.Statistic deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVARandom_Error_SumOfSquares twoWayANOVARandom.Error.SumOfSquares "Error.SumOfSquares deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVARandom_Total_DegreesOfFreedom twoWayANOVARandom.Total.DegreesOfFreedom "Total.DegreesOfFreedom deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVARandom_Total_MeanSquares twoWayANOVARandom.Total.MeanSquares "Total.MeanSquares deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVARandom_Total_Significance twoWayANOVARandom.Total.Significance "Total.Significance deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVARandom_Total_Source twoWayANOVARandom.Total.Source "Total.Source deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVARandom_Total_Statistic twoWayANOVARandom.Total.Statistic "Total.Statistic deviated from expected value" - Expect.floatClose Accuracy.high twoWayANOVARandom_Total_SumOfSquares twoWayANOVARandom.Total.SumOfSquares "Total.SumOfSquares deviated from expected value" - + Expect.equal twoWayANOVARandom.FactorFst.DegreesOfFreedom 2 "FactorFst.DegreesOfFreed deviated from expected value" + Expect.floatClose Accuracy.low (Math.Round (twoWayANOVARandom.FactorFst.MeanSquares,8)) 0.2386 "FactorFst.MeanSquares deviated from expected value" + Expect.floatClose Accuracy.low (Math.Round (twoWayANOVARandom.FactorFst.Significance,8)) 0.2851 "FactorFst.Significance deviated from expected value" + Expect.equal twoWayANOVARandom.FactorFst.Source Anova.Residual "FactorFst.Source deviated from expected value" + Expect.floatClose Accuracy.low (Math.Round (twoWayANOVARandom.FactorFst.Statistic,8)) 2.508 "FactorFst.Statistic deviated from expected value" + Expect.floatClose Accuracy.low (Math.Round (twoWayANOVARandom.FactorFst.SumOfSquares,8)) 0.4771 "FactorFst.SumOfSquares deviated from expected value" + Expect.equal twoWayANOVARandom.FactorSnd.DegreesOfFreedom 1 "FactorSnd.DegreesOfFreed deviated from expected value" + Expect.floatClose Accuracy.low (Math.Round (twoWayANOVARandom.FactorSnd.MeanSquares,8)) 0.01404 "FactorSnd.MeanSquares deviated from expected value" + Expect.floatClose Accuracy.low (Math.Round (twoWayANOVARandom.FactorSnd.Significance,8)) 0.7379 "FactorSnd.Significance deviated from expected value" + Expect.equal twoWayANOVARandom.FactorSnd.Source Anova.Residual "FactorSnd.Source deviated from expected value" + Expect.floatClose Accuracy.low (Math.Round (twoWayANOVARandom.FactorSnd.Statistic,8)) 0.1476 "FactorSnd.Statistic deviated from expected value" + Expect.floatClose Accuracy.low (Math.Round (twoWayANOVARandom.FactorSnd.SumOfSquares,8)) 0.01404 "FactorSnd.SumOfSquares deviated from expected value" + Expect.equal twoWayANOVARandom.Interaction.DegreesOfFreedom 2 "Interaction.DegreesOfFre deviated from expected value" + Expect.floatClose Accuracy.low (Math.Round (twoWayANOVARandom.Interaction.MeanSquares,8)) 0.09512 "Interaction.MeanSquares deviated from expected value" + Expect.floatClose Accuracy.low (Math.Round (twoWayANOVARandom.Interaction.Significance,8)) 0.001678 "Interaction.Significance deviated from expected value" + Expect.equal twoWayANOVARandom.Interaction.Source Anova.BetweenGroups "Interaction.Source deviated from expected value" + Expect.floatClose Accuracy.low (Math.Round (twoWayANOVARandom.Interaction.Statistic,8)) 11.4052 "Interaction.Statistic deviated from expected value" + Expect.floatClose Accuracy.low (Math.Round (twoWayANOVARandom.Interaction.SumOfSquares,8)) 0.1902 "Interaction.SumOfSquares deviated from expected value" + Expect.equal twoWayANOVARandom.Error.DegreesOfFreedom 12 "Error.DegreesOfFreedom deviated from expected value" + Expect.floatClose Accuracy.low (Math.Round (twoWayANOVARandom.Error.MeanSquares,8)) 0.00834 "Error.MeanSquares deviated from expected value" + Expect.floatClose Accuracy.low (Math.Round (twoWayANOVARandom.Error.SumOfSquares,8)) 0.1001 "Error.SumOfSquares deviated from expected value" + Expect.equal twoWayANOVARandom.Total.DegreesOfFreedom 17 "Total.DegreesOfFreedom deviated from expected value" + // Expect.floatClose Accuracy.low (Math.Round (twoWayANOVARandom.Total.SumOfSquares,8)) 0.7815 "Total.SumOfSquares deviated from expected value" + // Expect.floatClose Accuracy.low (Math.Round (twoWayANOVARandom.Total.MeanSquares,8)) 0.04597 "Total.MeanSquares deviated from expected value" + ] \ No newline at end of file From 55f8f1e44098dbe65d496208a05ef6df5945ed85 Mon Sep 17 00:00:00 2001 From: Christopher Lux <59606965+LibraChris@users.noreply.github.com> Date: Wed, 28 May 2025 15:08:53 +0200 Subject: [PATCH 109/121] Update SpecialFunctions/Gamma.fs to support generic type 'T as implemented in FsMath. --- src/FSharp.Stats/SpecialFunctions/Gamma.fs | 505 +++++++++++++-------- 1 file changed, 326 insertions(+), 179 deletions(-) diff --git a/src/FSharp.Stats/SpecialFunctions/Gamma.fs b/src/FSharp.Stats/SpecialFunctions/Gamma.fs index 189af2aa9..0e662773e 100644 --- a/src/FSharp.Stats/SpecialFunctions/Gamma.fs +++ b/src/FSharp.Stats/SpecialFunctions/Gamma.fs @@ -1,6 +1,7 @@ namespace FSharp.Stats.SpecialFunctions open System +open FSharp.Stats.GenericMath /// Approximations for the gamma function and related functions. /// @@ -23,15 +24,35 @@ module Gamma = /// The caller is responsible to handle edge cases such as nan, infinity, and -infinity in the input /// /// The function input for approximating Γ(z) - let _gamma z = - let lanczosCoefficients = [76.18009172947146;-86.50532032941677;24.01409824083091;-1.231739572450155;0.1208650973866179e-2;-0.5395239384953e-5] - let rec sumCoefficients acc i coefficients = - match coefficients with - | [] -> acc - | h::t -> sumCoefficients (acc + (h/i)) (i+1.0) t - let gamma = 5.0 - let x = z - 1.0 - Math.Pow(x + gamma + 0.5, x + 0.5) * Math.Exp( -(x + gamma + 0.5) ) * Math.Sqrt( 2.0 * Math.PI ) * sumCoefficients 1.000000000190015 (x + 1.0) lanczosCoefficients + let inline _gamma<'T when 'T :> Numerics.INumber<'T> + and Numerics.IFloatingPoint<'T> + and Numerics.IExponentialFunctions<'T> + and Numerics.IRootFunctions<'T> + and Numerics.IPowerFunctions<'T> > (z: 'T) : 'T = + let coeffs : Vector<'T> = + [| + T 76.18009172947146 + T -86.50532032941677 + T 24.01409824083091 + T -1.231739572450155 + T 0.001208650973866179 + T -0.000005395239384953 + |] + + let x = z - one + let g = T 5.0 + let half = T 0.5 + let xg = x + g + half + + let sum = + coeffs + |> Vector.foldi (fun i acc c -> + acc + c / (x + T (float (i + 1)))) (T 1.000000000190015) + + pow xg (x + half) + * exp (-xg) + * sqrt ('T.Pi * T 2.0) + * sum ///

  • If45&)w|?=G?ckUF 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

    rIQ^H2Ir~@yDB{xO4J2*GE6Y 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 z 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