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/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml index 1e03eb3f9..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 6 - uses: actions/setup-dotnet@v1 + - name: Setup .NET 8 + uses: actions/setup-dotnet@v4 with: - dotnet-version: '6.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 6 - uses: actions/setup-dotnet@v1 + - uses: actions/checkout@v4 + - name: Setup .NET 8 + uses: actions/setup-dotnet@v4 with: - dotnet-version: '6.x.x' + dotnet-version: '8.x.x' - name: Restore local tools run: dotnet tool restore - name: Build and test diff --git a/FSharp.Stats.sln b/FSharp.Stats.sln index bc6834aac..2c18d0e23 100644 --- a/FSharp.Stats.sln +++ b/FSharp.Stats.sln @@ -55,15 +55,12 @@ 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\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 +73,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 +101,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 +117,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/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 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..6760521d6 --- /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** | **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 new file mode 100644 index 000000000..27e1571ed --- /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,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 new file mode 100644 index 000000000..bcfdb6957 --- /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-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 SizeMean Error StdDev Gen0Gen1Gen2Allocated
Add1040.06 ns0.550 ns0.488 ns0.06820.0002-856 B
MatMultiply10442.83 ns2.841 ns2.373 ns0.1364--1712 B
MultiplyVector1033.28 ns0.425 ns0.397 ns0.0083--104 B
MultiplyRowVector1050.55 ns0.500 ns0.468 ns0.0083--104 B
Add500280,736.93 ns5,376.045 ns5,279.995 ns212.4023212.4023212.40232000164 B
MatMultiply50017,572,322.92 ns318,470.458 ns297,897.464 ns375.0000375.0000375.00004000242 B
MultiplyVector50031,726.43 ns202.403 ns189.328 ns0.3052--4024 B
MultiplyRowVector500127,918.10 ns996.783 ns832.359 ns0.2441--4024 B
Add10001,377,902.79 ns20,816.673 ns18,453.438 ns148.4375148.4375148.43758000105 B
MatMultiply1000143,300,325.00 ns1,445,291.857 ns1,606,438.070 ns250.0000250.0000250.000016000296 B
MultiplyVector1000135,247.34 ns1,334.685 ns1,248.465 ns0.4883--8024 B
MultiplyRowVector1000677,195.35 ns6,896.007 ns6,450.529 ns---8024 B
+ + diff --git a/benchmarks/FSharp.Stats.Benchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.Benchmarks.TriangularBenchmark-report-github.md b/benchmarks/FSharp.Stats.Benchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.Benchmarks.TriangularBenchmark-report-github.md new file mode 100644 index 000000000..ad6a0f913 --- /dev/null +++ b/benchmarks/FSharp.Stats.Benchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.Benchmarks.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 | Allocated | +|--------------------------- |----- |---------------:|-------------:|-------------:|-------:|----------:| +| **SolveTriangularSystemLower** | **10** | **186.3 ns** | **1.23 ns** | **1.09 ns** | **0.0172** | **216 B** | +| SolveTriangularSystemUpper | 10 | 185.9 ns | 1.33 ns | 1.18 ns | 0.0172 | 216 B | +| **SolveTriangularSystemLower** | **500** | **372,737.0 ns** | **2,926.50 ns** | **2,737.45 ns** | **0.4883** | **8056 B** | +| SolveTriangularSystemUpper | 500 | 357,818.8 ns | 1,729.90 ns | 1,618.15 ns | 0.4883 | 8056 B | +| **SolveTriangularSystemLower** | **1000** | **1,510,031.5 ns** | **7,131.73 ns** | **6,671.03 ns** | **-** | **16057 B** | +| SolveTriangularSystemUpper | 1000 | 1,422,197.8 ns | 8,642.37 ns | 8,084.08 ns | - | 16057 B | +| **SolveTriangularSystemLower** | **2000** | **6,119,478.8 ns** | **40,341.69 ns** | **37,735.64 ns** | **-** | **32059 B** | +| SolveTriangularSystemUpper | 2000 | 5,776,260.6 ns | 30,122.54 ns | 28,176.64 ns | - | 32059 B | diff --git a/benchmarks/FSharp.Stats.Benchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.Benchmarks.TriangularBenchmark-report.csv b/benchmarks/FSharp.Stats.Benchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.Benchmarks.TriangularBenchmark-report.csv new file mode 100644 index 000000000..87000c6b1 --- /dev/null +++ b/benchmarks/FSharp.Stats.Benchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.Benchmarks.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,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,186.3 ns,1.23 ns,1.09 ns,0.0172,216 B +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,185.9 ns,1.33 ns,1.18 ns,0.0172,216 B +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,"372,737.0 ns","2,926.50 ns","2,737.45 ns",0.4883,8056 B +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,"357,818.8 ns","1,729.90 ns","1,618.15 ns",0.4883,8056 B +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,"1,510,031.5 ns","7,131.73 ns","6,671.03 ns",0.0000,16057 B +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,"1,422,197.8 ns","8,642.37 ns","8,084.08 ns",0.0000,16057 B +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,"6,119,478.8 ns","40,341.69 ns","37,735.64 ns",0.0000,32059 B +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,"5,776,260.6 ns","30,122.54 ns","28,176.64 ns",0.0000,32059 B diff --git a/benchmarks/FSharp.Stats.Benchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.Benchmarks.TriangularBenchmark-report.html b/benchmarks/FSharp.Stats.Benchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.Benchmarks.TriangularBenchmark-report.html new file mode 100644 index 000000000..96438b3da --- /dev/null +++ b/benchmarks/FSharp.Stats.Benchmarks/BenchmarkDotNet.Artifacts/results/FSharp.Stats.Benchmarks.TriangularBenchmark-report.html @@ -0,0 +1,37 @@ + + + + +FSharp.Stats.Benchmarks.TriangularBenchmark-20250412-194429 + + + + +

+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/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..28d22c175 --- /dev/null +++ b/benchmarks/FSharp.Stats.Benchmarks/FSharp.Stats.Benchmarks.fsproj @@ -0,0 +1,23 @@ + + + + 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..cab6c1a95 --- /dev/null +++ b/benchmarks/FSharp.Stats.Benchmarks/Matrix.fs @@ -0,0 +1,46 @@ +namespace FSharp.Stats.Benchmarks + +open System +open BenchmarkDotNet.Attributes +open BenchmarkDotNet.Running +open FSharp.Stats +open FsMath +open FsMath.Algebra + +[] +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..ee69be2d0 --- /dev/null +++ b/benchmarks/FSharp.Stats.Benchmarks/Program.fs @@ -0,0 +1,14 @@ +open System +open BenchmarkDotNet.Running +open FSharp.Stats.Benchmarks + +[] +let Main args = + // Register multiple benchmark classes + 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..e71072935 --- /dev/null +++ b/benchmarks/FSharp.Stats.Benchmarks/TriangularSolver.fs @@ -0,0 +1,49 @@ +namespace FSharp.Stats.Benchmarks + +open System +open BenchmarkDotNet.Attributes +open BenchmarkDotNet.Running +open FSharp.Stats +open FsMath +open FsMath.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.Benchmarks/Vector.fs b/benchmarks/FSharp.Stats.Benchmarks/Vector.fs new file mode 100644 index 000000000..6276b5dd5 --- /dev/null +++ b/benchmarks/FSharp.Stats.Benchmarks/Vector.fs @@ -0,0 +1,45 @@ +namespace FSharp.Stats.Benchmarks + + +open System +open BenchmarkDotNet.Attributes +open BenchmarkDotNet.Running +open FSharp.Stats +open FsMath + + +[] +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 _.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.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/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..78b884d9d --- /dev/null +++ b/benchmarks/FSharp.Stats.LegacyBenchmarks/FSharp.Stats.LegacyBenchmarks.fsproj @@ -0,0 +1,20 @@ + + + + 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..829e670f5 --- /dev/null +++ b/benchmarks/FSharp.Stats.LegacyBenchmarks/Program.fs @@ -0,0 +1,16 @@ + +open System +open BenchmarkDotNet.Attributes +open BenchmarkDotNet.Running +open FSharp.Stats.LegacyBenchmarks + +[] +let Main args = + // Register multiple benchmark classes + 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 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/build/BasicTasks.fs b/build/BasicTasks.fs index 713217b79..c1d6c05f0 100644 --- a/build/BasicTasks.fs +++ b/build/BasicTasks.fs @@ -26,6 +26,19 @@ let clean = BuildTask.create "Clean" [] { } let build = BuildTask.create "Build" [clean] { - solutionFile - |> DotNet.build id + solutionFile + |> DotNet.build (fun p -> + 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 d51d99a4c..db16ad2c6 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] { @@ -17,17 +18,19 @@ 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 Properties = ([ "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" } @@ -44,6 +47,7 @@ let packPrerelease = BuildTask.create "PackPrerelease" [setPrereleaseTag; clean; "Version", prereleaseTag "PackageReleaseNotes", (release.Notes |> String.toLines ) ] @ p.MSBuildParams.Properties) + DisableInternalBinLog = true } { p with @@ -51,6 +55,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/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..4ddb58cd4 100644 --- a/build/TestTasks.fs +++ b/build/TestTasks.fs @@ -13,7 +13,9 @@ let runTests = BuildTask.create "RunTests" [clean; build] { Logger = Some "console;verbosity=detailed" Configuration = DotNet.BuildConfiguration.fromString configuration NoBuild = true + MSBuildParams = { testParams.MSBuildParams with DisableInternalBinLog = true } } + |> DotNet.Options.withCustomParams (Some "-tl") ) testProject } @@ -30,6 +32,7 @@ let runTestsWithCodeCov = BuildTask.create "RunTestsWithCodeCov" [clean; build] "AltCoverCobertura","../../codeCov.xml" "AltCoverForce","true" ] + DisableInternalBinLog = true }; Logger = Some "console;verbosity=detailed" } 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/docs/BasicStats.fsx b/docs/BasicStats.fsx index 34cacd0c2..2f66fcca6 100644 --- a/docs/BasicStats.fsx +++ b/docs/BasicStats.fsx @@ -10,8 +10,13 @@ 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: FsMath, 0.0.2" +#I "../src/FSharp.Stats/bin/Release/.net8.0/" +#r "FSharp.Stats.dll" (*** condition: ipynb ***) #if IPYNB #r "nuget: FSharp.Stats" @@ -26,19 +31,6 @@ categoryindex: 0 _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 d20ebea16..e63ff8230 100644 --- a/docs/Clustering.fsx +++ b/docs/Clustering.fsx @@ -10,12 +10,15 @@ categoryindex: 0 (*** hide ***) (*** condition: prepare ***) -#I "../src/FSharp.Stats/bin/Release/netstandard2.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" +#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: FSharpAux, 1.0.0" #r "nuget: Cyjs.NET" -#r "nuget: OptimizedPriorityQueue, 5.1.0" Plotly.NET.Defaults.DefaultDisplayOptions <- @@ -23,11 +26,8 @@ Plotly.NET.Defaults.DefaultDisplayOptions <- (*** 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 @@ -39,22 +39,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 a95d0b8b9..67be4665c 100644 --- a/docs/ComparisonMetrics.fsx +++ b/docs/ComparisonMetrics.fsx @@ -10,10 +10,16 @@ categoryindex: 0 (***hide***) (*** condition: prepare ***) -#I "../src/FSharp.Stats/bin/Release/netstandard2.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" +#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" + Plotly.NET.Defaults.DefaultDisplayOptions <- Plotly.NET.DisplayOptions.init (PlotlyJSReference = Plotly.NET.PlotlyJSReference.NoReference) @@ -21,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.2" #r "nuget: FSharp.Stats" #endif // IPYNB @@ -30,20 +37,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.` @@ -70,11 +63,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: @@ -83,11 +76,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`. @@ -98,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) @@ -136,12 +131,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 @@ -159,7 +154,7 @@ let mlcm = [2; 0; 4] ] |> array2D - |> Matrix.Generic.ofArray2D + |> Matrix.ofArray2D ) ) (** @@ -184,11 +179,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` *) @@ -212,29 +207,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 3b22549dd..34a52d44c 100644 --- a/docs/Correlation.fsx +++ b/docs/Correlation.fsx @@ -10,9 +10,16 @@ categoryindex: 0 (*** hide ***) (*** condition: prepare ***) -#I "../src/FSharp.Stats/bin/Release/netstandard2.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" +#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.2" + Plotly.NET.Defaults.DefaultDisplayOptions <- Plotly.NET.DisplayOptions.init (PlotlyJSReference = Plotly.NET.PlotlyJSReference.NoReference) @@ -22,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.2" #endif // IPYNB (** @@ -34,16 +41,11 @@ 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 *) open Plotly.NET +open FsMath open FSharp.Stats open FSharp.Stats.Correlation @@ -174,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 @@ -182,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 18007f55f..74702d854 100644 --- a/docs/Covariance.fsx +++ b/docs/Covariance.fsx @@ -10,9 +10,15 @@ categoryindex: 0 (*** hide ***) (*** condition: prepare ***) -#I "../src/FSharp.Stats/bin/Release/netstandard2.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" +#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" +open FsMath Plotly.NET.Defaults.DefaultDisplayOptions <- Plotly.NET.DisplayOptions.init (PlotlyJSReference = Plotly.NET.PlotlyJSReference.NoReference) @@ -45,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 566b7dd8c..64911c181 100644 --- a/docs/CrossValidation.fsx +++ b/docs/CrossValidation.fsx @@ -11,9 +11,15 @@ categoryindex: 0 (*** hide ***) (*** condition: prepare ***) -#I "../src/FSharp.Stats/bin/Release/netstandard2.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" +#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" +open FsMath Plotly.NET.Defaults.DefaultDisplayOptions <- Plotly.NET.DisplayOptions.init (PlotlyJSReference = Plotly.NET.PlotlyJSReference.NoReference) @@ -33,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). @@ -69,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 @@ -116,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 @@ -161,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: @@ -213,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 @@ -263,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 @@ -275,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 @@ -355,23 +352,23 @@ 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 + 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 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 + 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 diff --git a/docs/Differentiation.fsx b/docs/Differentiation.fsx index e393ee430..2b98ff47e 100644 --- a/docs/Differentiation.fsx +++ b/docs/Differentiation.fsx @@ -10,9 +10,15 @@ categoryindex: 0 (*** hide ***) (*** condition: prepare ***) -#I "../src/FSharp.Stats/bin/Release/netstandard2.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" +#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" +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..120e9eddb 100644 --- a/docs/Distributions.fsx +++ b/docs/Distributions.fsx @@ -11,9 +11,15 @@ categoryindex: 0 (*** hide ***) (*** condition: prepare ***) -#I "../src/FSharp.Stats/bin/Release/netstandard2.0/" -#r "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: FsMath, 0.0.2" #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 <- Plotly.NET.DisplayOptions.init (PlotlyJSReference = Plotly.NET.PlotlyJSReference.NoReference) @@ -34,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. @@ -723,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 @@ -743,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 7e79432d5..cee5dc910 100644 --- a/docs/Fitting.fsx +++ b/docs/Fitting.fsx @@ -10,11 +10,15 @@ 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" +#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" +open FsMath Plotly.NET.Defaults.DefaultDisplayOptions <- Plotly.NET.DisplayOptions.init (PlotlyJSReference = Plotly.NET.PlotlyJSReference.NoReference) @@ -38,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 @@ -210,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 @@ -256,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 6331c49d0..005715b07 100644 --- a/docs/GoodnessOfFit.fsx +++ b/docs/GoodnessOfFit.fsx @@ -10,9 +10,15 @@ categoryindex: 0 (*** hide ***) (*** condition: prepare ***) -#I "../src/FSharp.Stats/bin/Release/netstandard2.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" +#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" +open FsMath Plotly.NET.Defaults.DefaultDisplayOptions <- Plotly.NET.DisplayOptions.init (PlotlyJSReference = Plotly.NET.PlotlyJSReference.NoReference) @@ -37,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: @@ -197,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 @@ -242,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 @@ -281,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 fe22176ca..d1ecb4f80 100644 --- a/docs/GrowthCurve.fsx +++ b/docs/GrowthCurve.fsx @@ -10,9 +10,15 @@ categoryindex: 0 (*** hide ***) (*** condition: prepare ***) -#I "../src/FSharp.Stats/bin/Release/netstandard2.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" +#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" +open FsMath Plotly.NET.Defaults.DefaultDisplayOptions <- Plotly.NET.DisplayOptions.init (PlotlyJSReference = Plotly.NET.PlotlyJSReference.NoReference) @@ -35,25 +41,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. @@ -278,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)) @@ -349,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 @@ -432,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] @@ -518,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] @@ -606,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] @@ -697,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] @@ -781,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/Imputation.fsx b/docs/Imputation.fsx index a33c29386..3d28a74f0 100644 --- a/docs/Imputation.fsx +++ b/docs/Imputation.fsx @@ -10,9 +10,15 @@ categoryindex: 0 (*** hide ***) (*** condition: prepare ***) -#I "../src/FSharp.Stats/bin/Release/netstandard2.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" +#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" +open FsMath Plotly.NET.Defaults.DefaultDisplayOptions <- Plotly.NET.DisplayOptions.init (PlotlyJSReference = Plotly.NET.PlotlyJSReference.NoReference) @@ -22,6 +28,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.2" +open FsMath open Plotly.NET #endif // IPYNB diff --git a/docs/Integration.fsx b/docs/Integration.fsx index 4615e5b53..d8667a4c9 100644 --- a/docs/Integration.fsx +++ b/docs/Integration.fsx @@ -10,9 +10,15 @@ categoryindex: 0 (*** hide ***) (*** condition: prepare ***) -#I "../src/FSharp.Stats/bin/Release/netstandard2.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" +#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" +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..53f35af53 100644 --- a/docs/Interpolation.fsx +++ b/docs/Interpolation.fsx @@ -10,9 +10,15 @@ categoryindex: 0 (*** hide ***) (*** condition: prepare ***) -#I "../src/FSharp.Stats/bin/Release/netstandard2.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" +#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" +open FsMath Plotly.NET.Defaults.DefaultDisplayOptions <- Plotly.NET.DisplayOptions.init (PlotlyJSReference = Plotly.NET.PlotlyJSReference.NoReference) @@ -35,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 @@ -393,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 [ @@ -429,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 [ @@ -540,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/Intervals.fsx b/docs/Intervals.fsx index ec50b1e16..217336a1a 100644 --- a/docs/Intervals.fsx +++ b/docs/Intervals.fsx @@ -10,9 +10,15 @@ categoryindex: 0 (*** hide ***) (*** condition: prepare ***) -#I "../src/FSharp.Stats/bin/Release/netstandard2.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" +#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" +open FsMath Plotly.NET.Defaults.DefaultDisplayOptions <- Plotly.NET.DisplayOptions.init (PlotlyJSReference = Plotly.NET.PlotlyJSReference.NoReference) @@ -48,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/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..4c68a45bc 100644 --- a/docs/Normalization.fsx +++ b/docs/Normalization.fsx @@ -10,9 +10,15 @@ categoryindex: 0 (*** hide ***) (*** condition: prepare ***) -#I "../src/FSharp.Stats/bin/Release/netstandard2.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" +#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" +open FsMath Plotly.NET.Defaults.DefaultDisplayOptions <- Plotly.NET.DisplayOptions.init (PlotlyJSReference = Plotly.NET.PlotlyJSReference.NoReference) @@ -41,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 @@ -161,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 @@ -219,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 @@ -313,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/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 0509eb3bf..e0eeb3bf1 100644 --- a/docs/Optimization.fsx +++ b/docs/Optimization.fsx @@ -10,9 +10,15 @@ categoryindex: 0 (*** hide ***) (*** condition: prepare ***) -#I "../src/FSharp.Stats/bin/Release/netstandard2.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" +#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" +open FsMath Plotly.NET.Defaults.DefaultDisplayOptions <- Plotly.NET.DisplayOptions.init (PlotlyJSReference = Plotly.NET.PlotlyJSReference.NoReference) @@ -37,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/). @@ -64,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 @@ -120,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 @@ -231,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))) + @@ -298,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. + diff --git a/docs/Quantiles.fsx b/docs/Quantiles.fsx index 605313385..511d3fd0d 100644 --- a/docs/Quantiles.fsx +++ b/docs/Quantiles.fsx @@ -10,9 +10,15 @@ categoryindex: 0 (*** hide ***) (*** condition: prepare ***) -#I "../src/FSharp.Stats/bin/Release/netstandard2.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" +#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" +open FsMath Plotly.NET.Defaults.DefaultDisplayOptions <- Plotly.NET.DisplayOptions.init (PlotlyJSReference = Plotly.NET.PlotlyJSReference.NoReference) @@ -35,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 cbeefbc94..fdb1e7ae0 100644 --- a/docs/Rank.fsx +++ b/docs/Rank.fsx @@ -10,9 +10,15 @@ categoryindex: 0 (*** hide ***) (*** condition: prepare ***) -#I "../src/FSharp.Stats/bin/Release/netstandard2.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" +#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" +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..9da9cff7e 100644 --- a/docs/Signal.fsx +++ b/docs/Signal.fsx @@ -10,9 +10,15 @@ categoryindex: 0 (*** hide ***) (*** condition: prepare ***) -#I "../src/FSharp.Stats/bin/Release/netstandard2.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" +#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" +open FsMath Plotly.NET.Defaults.DefaultDisplayOptions <- Plotly.NET.DisplayOptions.init (PlotlyJSReference = Plotly.NET.PlotlyJSReference.NoReference) @@ -41,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 ed9a456c2..ebd363e85 100644 --- a/docs/Testing.fsx +++ b/docs/Testing.fsx @@ -10,11 +10,16 @@ categoryindex: 0 (*** hide ***) (*** condition: prepare ***) -#I "../src/FSharp.Stats/bin/Release/netstandard2.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" +#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: FSharpAux, 1.1.0" #r "nuget: Deedle, 3.0.0" +open FsMath Plotly.NET.Defaults.DefaultDisplayOptions <- Plotly.NET.DisplayOptions.init (PlotlyJSReference = Plotly.NET.PlotlyJSReference.NoReference) @@ -24,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 @@ -45,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 770a8887d..c7ab85cd2 100644 --- a/docs/index.fsx +++ b/docs/index.fsx @@ -1,9 +1,15 @@ (*** hide ***) (*** condition: prepare ***) -#I "../src/FSharp.Stats/bin/Release/netstandard2.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" +#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" +open FsMath Plotly.NET.Defaults.DefaultDisplayOptions <- Plotly.NET.DisplayOptions.init (PlotlyJSReference = Plotly.NET.PlotlyJSReference.NoReference) @@ -105,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 ***) (** 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 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/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 1d9faabb4..000000000 Binary files a/lib/libblas.dll and /dev/null differ diff --git a/lib/libgcc_s_seh-1.dll b/lib/libgcc_s_seh-1.dll deleted file mode 100644 index 4ec945b8a..000000000 Binary files a/lib/libgcc_s_seh-1.dll and /dev/null differ diff --git a/lib/libgfortran-4.dll b/lib/libgfortran-4.dll deleted file mode 100644 index 41cae21bc..000000000 Binary files a/lib/libgfortran-4.dll and /dev/null differ diff --git a/lib/liblapack.dll b/lib/liblapack.dll deleted file mode 100644 index f9813bac4..000000000 Binary files a/lib/liblapack.dll and /dev/null differ diff --git a/lib/libquadmath-0.dll b/lib/libquadmath-0.dll deleted file mode 100644 index 5918aa1ca..000000000 Binary files a/lib/libquadmath-0.dll and /dev/null differ diff --git a/lib/libwinpthread-1.dll b/lib/libwinpthread-1.dll deleted file mode 100644 index d9f4e1a73..000000000 Binary files a/lib/libwinpthread-1.dll and /dev/null differ 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/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/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/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/LinearAlgebra.fs b/src/FSharp.Stats/Algebra/LinearAlgebra.fs deleted file mode 100644 index 28e25f071..000000000 --- a/src/FSharp.Stats/Algebra/LinearAlgebra.fs +++ /dev/null @@ -1,487 +0,0 @@ -namespace FSharp.Stats.Algebra - -open FSharp.Stats -open System - - -module LinearAlgebra = - - type Factorization = matrix -> (matrix*matrix*matrix) - - //let private LinearAlgebraService = - // let tmp = new ServiceLocator.ServiceProvider([ProviderService.MKLProvider]) - // tmp.Start() - // tmp - let private MKLService = new ServiceLocator.ServiceProvider([ProviderService.LAPACKProvider;(*ProviderService.MKLProvider*)]) - - - 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 - - - /// 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 - - - /// 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 - - /// - /// 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. - /// - /// - /// 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 - - /// - /// Solves a linear system of equations using QR decomposition. - /// - /// 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 - - - ///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" - - 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 - -type LinearAlgebra() = - - /// 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 - - - 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/Algebra/SVD.fs b/src/FSharp.Stats/Algebra/SVD.fs deleted file mode 100644 index cbe44bcbd..000000000 --- a/src/FSharp.Stats/Algebra/SVD.fs +++ /dev/null @@ -1,415 +0,0 @@ -namespace FSharp.Stats.Algebra - -open FSharp.Stats - -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/Array.fs b/src/FSharp.Stats/Array.fs index ebaed80db..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 [] = @@ -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/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/Correlation.fs b/src/FSharp.Stats/Correlation.fs index 40c122c5a..5182b213c 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 = @@ -295,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. @@ -322,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 @@ -665,7 +668,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 +697,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 +734,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 +767,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 +784,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 +804,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 +839,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 +869,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 +879,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/DistanceMetrics.fs b/src/FSharp.Stats/DistanceMetrics.fs index 85c94a613..5c173c529 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 = @@ -122,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. /// @@ -161,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. /// @@ -317,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. /// @@ -356,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 da9f09ef3..44aa14ac4 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/Distributions/Continuous/Gamma.fs b/src/FSharp.Stats/Distributions/Continuous/Gamma.fs index 852f8d8ce..b7770795f 100644 --- a/src/FSharp.Stats/Distributions/Continuous/Gamma.fs +++ b/src/FSharp.Stats/Distributions/Continuous/Gamma.fs @@ -189,19 +189,97 @@ 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 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 = Gamma.CheckParam alpha beta - failwithf "not implemented yet" + + if p < 0.0 || p > 1.0 then failwith "p must be in [0, 1]" + if p = 0. then 0. + elif p = 1. then Double.PositiveInfinity + else + // 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 + 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 + + + + + + + /// Fits the underlying distribution to a given set of observations. static member Fit(observations:float[],?maxIter,?tolerance) = diff --git a/src/FSharp.Stats/Distributions/Continuous/MultivariateNormal.fs b/src/FSharp.Stats/Distributions/Continuous/MultivariateNormal.fs index 2076d1d03..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 @@ -14,50 +18,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/Continuous/StudentT.fs b/src/FSharp.Stats/Distributions/Continuous/StudentT.fs index d30537395..dd5df8fb1 100644 --- a/src/FSharp.Stats/Distributions/Continuous/StudentT.fs +++ b/src/FSharp.Stats/Distributions/Continuous/StudentT.fs @@ -18,9 +18,9 @@ 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 + 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. /// /// 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/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/Geometric.fs b/src/FSharp.Stats/Distributions/Discrete/Geometric.fs new file mode 100644 index 000000000..b43b4678c --- /dev/null +++ b/src/FSharp.Stats/Distributions/Discrete/Geometric.fs @@ -0,0 +1,155 @@ +namespace FSharp.Stats.Distributions.Discrete + +open System +open System.Numerics +open FSharp.Stats +open FSharp.Stats.Distributions +open FsMath +open FsMath.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 + // } + + diff --git a/src/FSharp.Stats/Distributions/Discrete/Hypergeometric.fs b/src/FSharp.Stats/Distributions/Discrete/Hypergeometric.fs index e71974105..cfda78d81 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!
/// - /// /// /// /// @@ -251,13 +250,18 @@ type Hypergeometric = static member ToString N K n = sprintf "Hypergeometric(N = %i, K = %i, n = %i)" N K n - /// 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
+ /// + /// 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 /// - /// - /// - /// /// /// /// 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/Distributions/Discrete/Multinomial.fs b/src/FSharp.Stats/Distributions/Discrete/Multinomial.fs index 6dbf92cdc..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 @@ -12,7 +14,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 +30,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,21 +46,35 @@ 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) + + /// + /// 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 p + ret[idx] <- ret[idx] + 1 + ret + /// Produces a random sample using the current random number generator (from GetSampleGenerator()). /// @@ -88,7 +104,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 +112,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 +134,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/Discrete/NegativeBinomial.fs b/src/FSharp.Stats/Distributions/Discrete/NegativeBinomial.fs index 44d1f0a3e..09986b468 100644 --- a/src/FSharp.Stats/Distributions/Discrete/NegativeBinomial.fs +++ b/src/FSharp.Stats/Distributions/Discrete/NegativeBinomial.fs @@ -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 /// - /// - /// /// /// /// @@ -371,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/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/Distribution.fs b/src/FSharp.Stats/Distributions/Distribution.fs index 71b55aa49..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 = @@ -37,8 +39,8 @@ module Parameters = StandardDeviation : float} type MultivariateNormal = { - Mean : vector - StandardDeviation : matrix} + Mean : Vector + StandardDeviation : Matrix} type Exponential = { Lambda : float} @@ -92,6 +94,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/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/FSIPrinters.fs b/src/FSharp.Stats/FSIPrinters.fs index 16fbc0788..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! @@ -34,7 +35,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/FSharp.Stats.fsproj b/src/FSharp.Stats/FSharp.Stats.fsproj index 12bc4e587..a994bcd49 100644 --- a/src/FSharp.Stats/FSharp.Stats.fsproj +++ b/src/FSharp.Stats/FSharp.Stats.fsproj @@ -1,7 +1,7 @@  - netstandard2.0 + .net8.0 true @@ -28,35 +28,28 @@ + - - - - - - - + + - - - - + @@ -65,15 +58,6 @@ - - - - - - - - - @@ -115,6 +99,9 @@ + + + @@ -127,6 +114,7 @@ + @@ -152,15 +140,12 @@ - - - @@ -175,10 +160,19 @@ + + + + + + + + + diff --git a/src/FSharp.Stats/Fitting/CrossValidation.fs b/src/FSharp.Stats/Fitting/CrossValidation.fs index 34c87fe5a..c321e432c 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 + (* @@ -17,18 +19,20 @@ module CrossValidation = /// Computes sum of squared residuals (SSR) /// /// + /// /// /// /// /// /// let ssr (y:Vector) (p:Vector)= - let residuals = y-p - residuals.Transpose * residuals + let residuals = y .- p + Vector.dot residuals residuals /// Computes root mean square error (RMSE) /// /// + /// /// /// /// @@ -45,54 +49,24 @@ 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)
/// - /// + /// + /// + /// + /// + /// + /// + /// /// /// /// /// /// - 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 +87,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,23 +114,24 @@ 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 /// 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
/// - /// + /// + /// + /// + /// /// /// /// /// /// - 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 +140,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 @@ -176,17 +152,21 @@ 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< ^T when ^T : (static member ( + ) : ^T * ^T -> ^T) - and ^T : (static member DivideByInt : ^T*int -> ^T) - and ^T : (static member Zero : ^T)> + let inline shuffleAndSplit 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 +185,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 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) - diff --git a/src/FSharp.Stats/Fitting/GoodnessOfFit.fs b/src/FSharp.Stats/Fitting/GoodnessOfFit.fs index 45829778f..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.) @@ -359,38 +362,55 @@ module GoodnessOfFit = [] 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 +465,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) diff --git a/src/FSharp.Stats/Fitting/LinearRegression.fs b/src/FSharp.Stats/Fitting/LinearRegression.fs index bf1aef5ec..66c50e4c4 100644 --- a/src/FSharp.Stats/Fitting/LinearRegression.fs +++ b/src/FSharp.Stats/Fitting/LinearRegression.fs @@ -3,6 +3,8 @@ namespace FSharp.Stats.Fitting open System open FSharp.Stats +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. @@ -21,7 +23,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,12 +57,12 @@ 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) = + member this.Predict (x: 'T) = 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) = - let tmp = Vector.init (x.Length + 1) (fun i -> if i = 0 then 1. else x.[i-1]) + 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.dot tmp coefficients /// Prints the polynomial function in a human readable form. @@ -78,7 +80,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 +121,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 +145,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) = @@ -154,12 +156,13 @@ 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 /// /// /// 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 /// @@ -215,7 +218,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 +244,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 +277,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 +337,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 +396,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 +442,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) = @@ -446,7 +452,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 /// /// @@ -491,10 +497,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) @@ -548,9 +554,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 +585,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) = @@ -614,7 +621,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 @@ -697,10 +703,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 +750,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 +778,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 +818,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 @@ -850,14 +858,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 /// @@ -931,7 +937,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 +951,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 +1003,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 @@ -1014,7 +1020,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. /// /// @@ -1038,7 +1044,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. /// /// @@ -1070,6 +1076,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 diff --git a/src/FSharp.Stats/Fitting/LogisticRegression.fs b/src/FSharp.Stats/Fitting/LogisticRegression.fs index 92637b974..296dabe88 100644 --- a/src/FSharp.Stats/Fitting/LogisticRegression.fs +++ b/src/FSharp.Stats/Fitting/LogisticRegression.fs @@ -9,23 +9,50 @@ open FSharp.Stats module LogisticRegression = open System + open FsMath - // 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.dot 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 +62,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 +73,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 +108,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 @@ -100,13 +127,14 @@ module LogisticRegression = /// Returns the regression function /// /// + /// /// /// /// /// /// 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 +171,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 @@ -162,6 +190,7 @@ module LogisticRegression = /// Returns the regression function /// /// + /// /// /// /// @@ -177,6 +206,7 @@ module LogisticRegression = /// Returns the regression function /// /// + /// /// /// /// diff --git a/src/FSharp.Stats/Fitting/NonLinearRegression.fs b/src/FSharp.Stats/Fitting/NonLinearRegression.fs index d741528d6..68197e269 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 []) = @@ -71,7 +72,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 +109,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 +132,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,19 +184,19 @@ 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 diagonal = Matrix.initDiagonal (Vector.map (fun x -> ((lambda)*x)) hessian.Diagonal) + let hessian = jacobian'.Transpose() * jacobian' + let diagonal = Matrix.diagonal (Array.map (fun x -> ((lambda)*x)) (Matrix.getDiagonal hessian)) let modHessian = (hessian + diagonal) - let step = FSharp.Stats.Algebra.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 @@ -234,9 +235,9 @@ 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 + 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 () @@ -244,31 +245,31 @@ module NonLinearRegression = | _ -> failwith "vector lengths differ" /// - let private toInternalParameters (lowerBound: vector) (upperBound: vector) (extParameters: vector) = - Vector.map3 (fun l u x -> + let private toInternalParameters (lowerBound: Vector) (upperBound: Vector) (extParameters: Vector) = + 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 -> + let private toExternalParameters (lowerBound: Vector) (upperBound: Vector) (intParameters: Vector) = + 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 -> + let private calculateJacScaleFactors (lowerBound: Vector) (upperBound: Vector) (intParameters: Vector) = + Array.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.
/// @@ -285,24 +286,24 @@ 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 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 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 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 = LinearAlgebra.solveLinearSystem modHessian gradient + let newParamGuessInt = currentParamGuessInt .- step let newParamGuessExt = toExternalParameters lowerBound upperBound newParamGuessInt let newValueRSS = getRSS model xData yData newParamGuessExt paramsAtIteration.Add(newParamGuessExt) @@ -331,8 +332,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 +351,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 -> @@ -375,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.
/// /// + /// + /// /// /// /// @@ -534,6 +537,7 @@ module NonLinearRegression = /// Takes the result of the linearization as initialGuessParams /// /// + /// /// /// /// @@ -542,8 +546,8 @@ 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 linearReg = LinearRegression.OLS.Linear.Univariable.fit (vector xData) yLn + let yLn : Vector = yData |> Array.map (fun x -> Math.Log(x)) + 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/Fitting/Spline.fs b/src/FSharp.Stats/Fitting/Spline.fs index 58f95cf98..d26ff3fca 100644 --- a/src/FSharp.Stats/Fitting/Spline.fs +++ b/src/FSharp.Stats/Fitting/Spline.fs @@ -4,11 +4,11 @@ namespace FSharp.Stats.Fitting module Spline = open FSharp.Stats - open FSharp.Stats.Algebra + open FsMath + open FsMath.Algebra /// Some preprocessing of the input data /// - /// /// /// /// @@ -31,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.
/// /// + /// /// /// /// @@ -41,7 +42,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 +60,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 +74,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 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/Interpolation.fs b/src/FSharp.Stats/Interpolation.fs index 536e89612..29f58812b 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. @@ -30,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 /// /// @@ -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 @@ -354,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. /// /// @@ -597,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. /// /// @@ -771,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. /// /// @@ -1014,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 @@ -1050,17 +1047,16 @@ 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} /// /// 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. /// /// @@ -1105,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. /// /// @@ -1160,11 +1155,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 +1189,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 +1227,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 +1262,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 +1298,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 +1326,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 +1561,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 +1748,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 @@ -1766,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. /// /// @@ -1822,7 +1816,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 @@ -1943,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. /// @@ -1965,11 +1960,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,14 +1990,14 @@ 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 /// /// 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. /// @@ -2069,7 +2064,7 @@ module Interpolation = slope let slopes = loop 1 [slopeAtFstKnot] - slopes |> vector + slopes |> Array.ofList [] module Simple = @@ -2138,15 +2133,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 +2214,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 +2242,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 +2265,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 +2332,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. @@ -2365,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. @@ -2374,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 @@ -2452,14 +2445,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 /// 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/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/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/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 diff --git a/src/FSharp.Stats/ML/Unsupervised/ClusterNumber.fs b/src/FSharp.Stats/ML/Unsupervised/ClusterNumber.fs index 927af7367..e202526e8 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 = @@ -26,6 +28,8 @@ module ClusterNumber = /// Akaike Information Criterion (AIC) /// /// + /// + /// /// /// /// @@ -176,21 +180,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 @@ -296,6 +301,7 @@ https://www.datanovia.com/en/lessons/determining-the-optimal-number-of-clusters- /// Generate uniform points within the range of `data`. /// /// + /// /// /// /// @@ -303,8 +309,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 +351,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 +366,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..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 @@ -62,7 +63,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 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/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 - } 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/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/Optimization/NelderMead.fs b/src/FSharp.Stats/Optimization/NelderMead.fs index 98848e2de..e0a39b90e 100644 --- a/src/FSharp.Stats/Optimization/NelderMead.fs +++ b/src/FSharp.Stats/Optimization/NelderMead.fs @@ -3,8 +3,8 @@ module NelderMead = open FSharp.Stats - open FSharp.Stats.Algebra - open FSharp.Stats.Algebra.LinearAlgebra + open FsMath + open FsMath.Algebra type NmConfig = { /// Delta used to generate initial simplex for non-zero value elements @@ -51,12 +51,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 +64,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 +79,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 +87,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 +96,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 +110,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 +136,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 +147,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 +155,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 +169,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 +205,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 +235,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 +266,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 3e726d09d..5067b2992 100644 --- a/src/FSharp.Stats/Permutation.fs +++ b/src/FSharp.Stats/Permutation.fs @@ -1,41 +1,92 @@ -// (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 + + // 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] + + /// + /// 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 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]) + /// 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 ofArray (arr:_[]) = arr |> Array.copy |> ofFreshArray - [] - 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) diff --git a/src/FSharp.Stats/Playground.fsx b/src/FSharp.Stats/Playground.fsx index a6b066450..7eb5fbae0 100644 --- a/src/FSharp.Stats/Playground.fsx +++ b/src/FSharp.Stats/Playground.fsx @@ -1,55 +1,619 @@ -#I "bin/Debug/netstandard2.0" +#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 +open FSharp.Stats.Algebra +open FSharp.Stats.Distributions.Continuous +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 -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; |] +// 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 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 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 alpha', beta' = Continuous.Gamma.Fit samplesHisto -let d = Continuous.Gamma.Estimate pdfs -d.Mean +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 + +// // 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 R1 = Matrix.matmul H A + +//let (n, m) = (A.NumRows, A.NumCols) + +//let Q : Matrix = Matrix.identity n +//let R = Matrix.copy A +//UpdateQ_Debug Q v +//applyHouseholderLeft R v 0 + + + + + + +//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 [| +// [| 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 = +// 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.|] +// [|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 @@ -62,36 +626,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/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/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/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 1853cfe1d..3cf9dc50f 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> @@ -1174,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. /// @@ -1183,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/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/Signal/Baseline.fs b/src/FSharp.Stats/Signal/Baseline.fs index 627cb8e49..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 = @@ -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..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 = @@ -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/Filtering.fs b/src/FSharp.Stats/Signal/Filtering.fs index ca337e139..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 FsMath +open FsMath.Algebra module Filtering = @@ -38,67 +39,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.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.dot 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 +151,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 ) diff --git a/src/FSharp.Stats/Signal/Normalization.fs b/src/FSharp.Stats/Signal/Normalization.fs index 5712150ba..c01ff54fa 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 = @@ -16,10 +17,10 @@ module Normalization = /// /// /// Bortz J., Schuster C., Statistik für Human- und Sozialwissenschaftler, 7 (2010), p. 35 - let zScoreTransformPopulation (yVal:Vector) = - let yMean = Seq.mean yVal - let std = Seq.stDevPopulation yVal - yVal |> Vector.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. @@ -33,16 +34,16 @@ module Normalization = /// /// /// Bortz J., Schuster C., Statistik für Human- und Sozialwissenschaftler, 7 (2010), p. 35 - let zScoreTransform (yVal:Vector) = - let yMean = Seq.mean yVal - let std = Seq.stDev yVal - yVal |> Vector.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 = { CorrFactors : seq NormedData : Matrix - NormFunction : matrix -> matrix + NormFunction : Matrix -> Matrix } with static member Create cf nd f = {CorrFactors=cf;NormedData=nd;NormFunction=f} /// @@ -63,12 +64,13 @@ module Normalization = let sampleWiseCorrectionFactors = data |> Matrix.mapiRows (fun _ v -> - let v = RowVector.map f v + let v = Array.map f v let geometricMean = Seq.meanGeometric v - RowVector.map (fun s -> s / geometricMean) v + Array.map (fun s -> s / geometricMean) v ) - |> Matrix.ofRows - |> Matrix.mapiCols (fun _ v -> Vector.median v) + |> Matrix.getCols + |> Array.map (fun (v:Vector) -> Vector.median v) + let normData m = m |> Matrix.mapi (fun r c v -> @@ -111,12 +113,12 @@ module Normalization = let sampleWiseCorrectionFactors = data |> Matrix.mapiCols (fun _ v -> - let v = Vector.map f v + let v = Array.map f v let geometricMean = Seq.meanGeometric v - Vector.map (fun s -> s / geometricMean) v + Array.map (fun s -> s / geometricMean) v ) - |> Matrix.ofCols - |> Matrix.mapiRows (fun _ v -> Seq.median v) + |> Matrix.getCols + |> Array.map (fun v -> Vector.median v) let normData m = m |> Matrix.mapi (fun r c v -> @@ -156,12 +158,23 @@ module Normalization = /// let quantile (data:Matrix) = data - |> Matrix.mapCols (Seq.indexed >> Seq.sortBy snd) - |> Matrix.Generic.ofColSeq - |> Matrix.Generic.mapRows (fun row -> + |> 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 |> RowVector.Generic.map (fun (i,_) -> i,avg) + row |> Array.map (fun (i,_) -> i,avg) ) - |> Matrix.Generic.ofSeq - |> Matrix.Generic.mapCols (Seq.sortBy fst >> Seq.map snd >> vector) + |> 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/Signal/Outliers.fs b/src/FSharp.Stats/Signal/Outliers.fs index a209ceed5..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).
/// @@ -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/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 d6a42ef76..4f15807bf 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 = @@ -330,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/Signal/QQPlot.fs b/src/FSharp.Stats/Signal/QQPlot.fs index 679f59809..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 = @@ -70,16 +72,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 +110,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 +176,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 +186,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. diff --git a/src/FSharp.Stats/SpecialFunctions/Beta.fs b/src/FSharp.Stats/SpecialFunctions/Beta.fs index ab83be604..4f88f0f2b 100644 --- a/src/FSharp.Stats/SpecialFunctions/Beta.fs +++ b/src/FSharp.Stats/SpecialFunctions/Beta.fs @@ -2,14 +2,21 @@ open System open FSharp.Stats +open FsMath +open FsMath.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 = 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 + + 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) @@ -19,7 +26,19 @@ 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<'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 +48,19 @@ 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<'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 +71,19 @@ 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<'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 +94,19 @@ 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<'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 /// @@ -79,29 +134,29 @@ module Beta = let c = 1.0 let d = let tmp = 1.0 - (qab * x / qap) - if (abs tmp < FPMIN) then 1. / FPMIN else 1. / tmp + if (abs tmp < f_FPMIN) then 1. / f_FPMIN else 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 d' = let tmp = 1.0 + (aa*d) - if (abs tmp < FPMIN) then 1. / FPMIN else 1. / tmp + if (abs tmp < f_FPMIN) then 1. / f_FPMIN else 1. / tmp let c' = let tmp = 1.0 + (aa/c) - if (abs tmp < FPMIN) then FPMIN else tmp + 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 < FPMIN) then 1. / FPMIN else 1. / tmp + if (abs tmp < f_FPMIN) then 1. / f_FPMIN else 1. / tmp let c'' = let tmp = 1.0 + (aa'/c') - if (abs tmp < FPMIN) then FPMIN else tmp + if (abs tmp < f_FPMIN) then f_FPMIN else tmp let del = d''*c'' let h'' = h' * del - if abs (del - 1.0) <= EPS then + if abs (del - 1.0) <= f_EPS then if isSymmetryTransformation then 1.0 - (bt*h''/a) else bt*h''/a else if m < 140 then 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/SpecialFunctions/Gamma.fs b/src/FSharp.Stats/SpecialFunctions/Gamma.fs index 91a7dd8ce..724c97386 100644 --- a/src/FSharp.Stats/SpecialFunctions/Gamma.fs +++ b/src/FSharp.Stats/SpecialFunctions/Gamma.fs @@ -1,6 +1,8 @@ namespace FSharp.Stats.SpecialFunctions open System +open FsMath +open FsMath.GenericMath /// Approximations for the gamma function and related functions. /// @@ -23,15 +25,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 /// /// 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 +62,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,11 +107,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) @@ -73,146 +128,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.
/// @@ -223,8 +325,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.
/// @@ -235,80 +343,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 /// @@ -321,7 +470,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) diff --git a/src/FSharp.Stats/SummaryStats.fs b/src/FSharp.Stats/SummaryStats.fs new file mode 100644 index 000000000..e82183c08 --- /dev/null +++ b/src/FSharp.Stats/SummaryStats.fs @@ -0,0 +1,304 @@ +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/src/FSharp.Stats/Table.fs b/src/FSharp.Stats/Table.fs new file mode 100644 index 000000000..3212a0b55 --- /dev/null +++ b/src/FSharp.Stats/Table.fs @@ -0,0 +1,159 @@ +namespace FSharp.Stats + + +open System +open FSharp.Stats +open FsMath +open FsMath.Algebra + +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 : comparison + 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/Anova.fs b/src/FSharp.Stats/Testing/Anova.fs index d56e31c48..b18ab2c67 100644 --- a/src/FSharp.Stats/Testing/Anova.fs +++ b/src/FSharp.Stats/Testing/Anova.fs @@ -246,24 +246,24 @@ 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), - (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) ) 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/ConfusionMatrix.fs b/src/FSharp.Stats/Testing/ConfusionMatrix.fs index bf25b4bc8..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 = { @@ -114,7 +116,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 +133,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/ContingencyTable.fs b/src/FSharp.Stats/Testing/ContingencyTable.fs new file mode 100644 index 000000000..c92083d70 --- /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 +open FsMath + +/// 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/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/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/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 19ee135a5..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: @@ -34,7 +36,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..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) @@ -40,8 +41,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 +65,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..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 = @@ -10,53 +12,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 ;|] + |] diff --git a/src/FSharp.Stats/Testing/TestStatistics.fs b/src/FSharp.Stats/Testing/TestStatistics.fs index e81a5279e..4c174f3d0 100644 --- a/src/FSharp.Stats/Testing/TestStatistics.fs +++ b/src/FSharp.Stats/Testing/TestStatistics.fs @@ -1,99 +1,213 @@ namespace FSharp.Stats.Testing +open System +open FsMath +open FsMath.GenericMath +// TODO: Update specific distributions to support generic type 'T to avoid explicit float casting 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. - type TTestStatistics = { - Statistic : float - DegreesOfFreedom : float - PValueLeft : float - PValueRight : float - PValue : float - } - - let createTTest statistic dof = - let cdf = Distributions.Continuous.StudentT.CDF 0. 1. dof statistic - let pvalue = if statistic > 0. then 1. - cdf else cdf - {Statistic=statistic; DegreesOfFreedom=dof; PValueLeft=1. - pvalue; PValueRight=pvalue; PValue=pvalue*2.;} + /// + /// Numeric type used for the test statistics. + /// + type TTestStatistics<'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 > = + { + /// 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 + } + + 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= T(1. - pvalue); + PValueRight=T(pvalue); + PValue=T(pvalue*2.); + } /// /// 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 = { - Statistic : float - DegreesOfFreedom1 : float - DegreesOfFreedom2 : float - PValue : float - PValueTwoTailed : float - } - - let createFTest statistic dof1 dof2 = - let cdf = Distributions.Continuous.F.CDF dof1 dof2 statistic + // /// + // /// 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 > = + { + /// 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 + } + + 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. /// - /// - /// The test statistic. - /// The degrees of freedom for the numerator. - /// One Tailed/Sided. - /// One Tailed/Sided. - /// Two Tailed/Sided. - type ChiSquareStatistics = { - Statistic : float - DegreesOfFreedom : float - /// one tailed/sided chiSquare pValue - PValueLeft : float - /// one tailed/sided chiSquare pValue (default) - PValueRight : float - /// two tailed/sided chiSquare pValue - PValue : float - } - - - 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.} + // /// + // /// 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 > = + { + /// The test statistic. + Statistic : 'T + /// The degrees of freedom for the numerator. + 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 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. /// - /// The test statistic. - /// One Tailed/Sided. - /// Two Tailed/Sided. - type WilcoxonTestStatistics = { - Statistic : float - PValueLeft : float - PValueRight : float - 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 > = + { + /// The test statistic. + Statistic : 'T + /// One Tailed/Sided PValue. + PValueLeft : 'T + /// One Tailed/Sided PValue. + PValueRight : 'T + /// Two Tailed/Sided PValue. + 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 diff --git a/src/FSharp.Stats/Vector.fs b/src/FSharp.Stats/Vector.fs index b2a2cfbce..8026d1acc 100644 --- a/src/FSharp.Stats/Vector.fs +++ b/src/FSharp.Stats/Vector.fs @@ -1,649 +1,18 @@ -namespace FSharp.Stats - -#nowarn "60" // implementations in augmentations -#nowarn "69" // implementations in augmentations +namespace FSharp.Stats +open FsMath 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) +module Vector = - 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 - - // + + /// Creates a vector from a sequence let interval (items:Vector<'T>) = let rec loop index (minimum) (maximum) = if index < items.Length then @@ -657,25 +26,17 @@ module Vector = 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 population mean (Normalized by N) + ///// + ///// + ///// + ///// + ///// + ///// + ///// + //let inline mean (items:Vector<'T>) = + // Vector.mean items + /// Computes the sample median /// @@ -685,8 +46,8 @@ module Vector = /// /// /// - let inline median (items:Vector<'T>) = - items.Values |> Array.median + let inline median (items:Vector) = + items |> Array.median /// Median absolute deviation (MAD) /// @@ -696,8 +57,8 @@ module Vector = /// /// /// - let medianAbsoluteDev (items : vector) = - items.Values |> Array.medianAbsoluteDev + let medianAbsoluteDev (items:Vector) = + items |> Array.medianAbsoluteDev /// Returns SummaryStats of vector with N, mean, sum-of-squares, minimum and maximum @@ -740,7 +101,7 @@ module Vector = /// /// /// - let covPopulation (v1:vector) (v2:vector) = + 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) @@ -752,7 +113,7 @@ module Vector = /// /// /// - let cov (v1:vector) (v2:vector) = + let cov (v1:Vector) (v2:Vector) = Seq.cov v1 v2 /// calculates the sample means with a given number of replicates present in the sequence @@ -764,9 +125,9 @@ module Vector = /// /// /// - let getMeanOfReplicates rep (data:vector) = + let getMeanOfReplicates rep (data:Vector) = Seq.getMeanOfReplicates rep data - |> ofSeq + |> Vector.ofSeq /// calculates the sample standard deviations with a given number of replicates present in the sequence /// @@ -777,9 +138,9 @@ module Vector = /// /// /// - let getStDevOfReplicates rep (data:vector) = + let getStDevOfReplicates rep (data:Vector) = Seq.getStDevOfReplicates rep data - |> ofSeq + |> Vector.ofSeq /// calculates the coefficient of variation based on the sample standard deviations with a given number of replicates present in the sequence /// @@ -790,37 +151,37 @@ module Vector = /// /// /// - let getCvOfReplicates rep (data:vector) = + 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) + |> 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) + // loop (len-1-indices.Length) (indices.Length-1) (len-1) /// Module to compute common statistical measure on @@ -844,37 +205,36 @@ module Vector = -[] -module VectorExtension = +//[] +//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 +// 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 = +// /// +// /// 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 +// 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 +// 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 + 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/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 2a6b19c63..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 @@ -118,6 +119,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" + } + ] + ] @@ -644,15 +692,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 +713,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..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} @@ -379,19 +379,139 @@ 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 = // 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 +519,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 +540,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 +549,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 +558,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,28 +568,43 @@ 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" + + test "Sample proportions should be close to the expected probabilities" { + let probabilities = [| 0.2; 0.3; 0.5 |] + 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.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/FSharp.Stats.Tests.fsproj b/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj index af6b5eb2d..dfcdb5fdc 100644 --- a/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj +++ b/tests/FSharp.Stats.Tests/FSharp.Stats.Tests.fsproj @@ -1,41 +1,34 @@  Exe - net6.0 + net8.0 false - - - + + - - + + + - - - - - - - - + - - - + - - - - + + + + + + @@ -69,6 +62,9 @@ + + + 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 486acb157..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 @@ -21,7 +22,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 +44,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 +102,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 +113,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 +127,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/LinearAlgebra.fs b/tests/FSharp.Stats.Tests/LinearAlgebra.fs deleted file mode 100644 index 989ea81f0..000000000 --- a/tests/FSharp.Stats.Tests/LinearAlgebra.fs +++ /dev/null @@ -1,1307 +0,0 @@ -module LinearAlgebraTests - -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 sM = - let tmp= Matrix.create A.NumRows A.NumCols 0. - 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 |> Matrix.toJaggedArray |> Array.concat - let m' = mEqualNRecov |> 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: 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 - 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 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 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>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: 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." - ] - - -[] -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 () -> - 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 concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| - [|-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." - testCase "3x3 diagonal Matrix (Values = 1) with 3x3 Matrix (Values = 1)" <| fun () -> - SolveTriangularLinearSystems KDiagonal1 B1 false - |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| - [|1.;1.;1.|]; - [|1.;1.;1.|]; - [|1.;1.;1.|] - |] - |> Array.concat - TestExtensions.sequenceEqual Accuracy.high concatRes concatExpected "Should be 3x3 Matrix of 1" - testCase "3x3 Upper Triangular Matrix (Values = 1) with 3x3 Matrix (Values = 1)" <| fun () -> - SolveTriangularLinearSystems KUpper1 B1 false - |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| - [|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" - testCase "3x3 Upper Triangular Matrix (Values = -1) with 3x3 Matrix (Values = 1)" <| fun () -> - SolveTriangularLinearSystems KUpperNeg1 B1 false - |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| - [|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" - testCase "3x3 Upper Triangular Matrix (Values = Inf) with 3x3 Matrix (Values = 1)" <| fun () -> - SolveTriangularLinearSystems KUpperInf B1 false - |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| - [|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" - testCase "3x3 Upper Triangular Matrix (Values = -Inf) with 3x3 Matrix (Values = 1)" <| fun () -> - SolveTriangularLinearSystems KUpperNegInf B1 false - |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| - [|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" - testCase "3x3 Upper Triangular Matrix (Values = NaN) with 3x3 Matrix (Values = 1)" <| fun () -> - SolveTriangularLinearSystems KUpperNaN B1 false - |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| - [|nan;nan;nan|]; - [|nan;nan;nan|]; - [|nan;nan;nan|] - |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix of NaN" - testCase "3x3 diagonal Matrix (Values = 1) with 3x3 Matrix (Values = Inf)" <| fun () -> - SolveTriangularLinearSystems KDiagonal1 BInf false - |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| - [|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" - testCase "3x3 Upper Triangular Matrix (Values = 1) with 3x3 Matrix (Values = Inf)" <| fun () -> - SolveTriangularLinearSystems KUpper1 BInf false - |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| - [|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" - testCase "3x3 Upper Triangular Matrix (Values = -1) with 3x3 Matrix (Values = Inf)" <| fun () -> - SolveTriangularLinearSystems KUpperNeg1 BInf false - |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| - [|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" - testCase "3x3 Upper Triangular Matrix (Values = Inf) with 3x3 Matrix (Values = Inf)" <| fun () -> - SolveTriangularLinearSystems KUpperInf BInf false - |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| - [|nan;nan;nan|]; - [|nan;nan;nan|]; - [|nan;nan;nan|] - |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix of NaN" - testCase "3x3 Upper Triangular Matrix (Values = -Inf) with 3x3 Matrix (Values = Inf)" <| fun () -> - SolveTriangularLinearSystems KUpperNegInf BInf false - |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| - [|nan;nan;nan|]; - [|nan;nan;nan|]; - [|nan;nan;nan|] - |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix of NaN" - testCase "3x3 Upper Triangular Matrix (Values = NaN) with 3x3 Matrix (Values = Inf)" <| fun () -> - SolveTriangularLinearSystems KUpperNaN BInf false - |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| - [|nan;nan;nan|]; - [|nan;nan;nan|]; - [|nan;nan;nan|] - |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix of NaN" - testCase "3x3 diagonal Matrix (Values = 1) with 3x3 Matrix (Values = -Inf)" <| fun () -> - SolveTriangularLinearSystems KDiagonal1 BNegInf false - |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| - [|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" - testCase "3x3 Upper Triangular Matrix (Values = 1) with 3x3 Matrix (Values = -Inf)" <| fun () -> - SolveTriangularLinearSystems KUpper1 BNegInf false - |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| - [|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" - testCase "3x3 Upper Triangular Matrix (Values = Inf) with 3x3 Matrix (Values = -Inf)" <| fun () -> - SolveTriangularLinearSystems KUpperInf BNegInf false - |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| - [|nan;nan;nan|]; - [|nan;nan;nan|]; - [|nan;nan;nan|] - |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix of NaN" - testCase "3x3 Upper Triangular Matrix (Values = -Inf) with 3x3 Matrix (Values = -Inf)" <| fun () -> - SolveTriangularLinearSystems KUpperNegInf BNegInf false - |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| - [|nan;nan;nan|]; - [|nan;nan;nan|]; - [|nan;nan;nan|] - |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix of NaN" - testCase "3x3 Upper Triangular Matrix (Values = NaN) with 3x3 Matrix (Values = -Inf)" <| fun () -> - SolveTriangularLinearSystems KUpperNaN BNegInf false - |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| - [|nan;nan;nan|]; - [|nan;nan;nan|]; - [|nan;nan;nan|] - |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix of NaN" - testCase "3x3 diagonal Matrix (Values = 1) with 3x3 Matrix (Values = NaN)" <| fun () -> - SolveTriangularLinearSystems KDiagonal1 BNaN false - |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| - [|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" - testCase "3x3 Upper Triangular Matrix (Values = 1) with 3x3 Matrix (Values = NaN)" <| fun () -> - SolveTriangularLinearSystems KUpper1 BNaN false - |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| - [|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" - testCase "3x3 Upper Triangular Matrix (Values = Inf) with 3x3 Matrix (Values = NaN)" <| fun () -> - SolveTriangularLinearSystems KUpperInf BNaN false - |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| - [|nan;nan;nan|]; - [|nan;nan;nan|]; - [|nan;nan;nan|] - |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix of NaN" - testCase "3x3 Upper Triangular Matrix (Values = -Inf) with 3x3 Matrix (Values = NaN)" <| fun () -> - SolveTriangularLinearSystems KUpperNegInf BNaN false - |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| - [|nan;nan;nan|]; - [|nan;nan;nan|]; - [|nan;nan;nan|] - |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix of NaN" - testCase "3x3 Upper Triangular Matrix (Values = NaN) with 3x3 Matrix (Values = NaN)" <| fun () -> - SolveTriangularLinearSystems KUpperNaN BNaN false - |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| - [|nan;nan;nan|]; - [|nan;nan;nan|]; - [|nan;nan;nan|] - |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix of NaN" - testCase "3x3 diagonal Matrix (Values = 1) with 3x3 Matrix (Values = -1)" <| fun () -> - SolveTriangularLinearSystems KDiagonal1 BNeg1 false - |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| - [|-1.;-1.;-1.|]; - [|-1.;-1.;-1.|]; - [|-1.;-1.;-1.|] - |] - |> Array.concat - TestExtensions.sequenceEqual Accuracy.high concatRes concatExpected "Should be 3x3 Matrix of -1" - testCase "3x3 Upper Triangular Matrix (Values = 1) with 3x3 Matrix (Values = -1)" <| fun () -> - SolveTriangularLinearSystems KUpper1 BNeg1 false - |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| - [|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" - testCase "3x3 Upper Triangular Matrix (Values = -1) with 3x3 Matrix (Values = -1)" <| fun () -> - SolveTriangularLinearSystems KUpperNeg1 BNeg1 false - |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| - [|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" - testCase "3x3 Upper Triangular Matrix (Values = Inf) with 3x3 Matrix (Values = -1)" <| fun () -> - SolveTriangularLinearSystems KUpperInf BNeg1 false - |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| - [|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" - testCase "3x3 Upper Triangular Matrix (Values = -Inf) with 3x3 Matrix (Values = -1)" <| fun () -> - SolveTriangularLinearSystems KUpperNegInf BNeg1 false - |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| - [|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" - testCase "3x3 Upper Triangular Matrix (Values = NaN) with 3x3 Matrix (Values = -1)" <| fun () -> - SolveTriangularLinearSystems KUpperNaN BNeg1 false - |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| - [|nan;nan;nan|]; - [|nan;nan;nan|]; - [|nan;nan;nan|] - |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "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 - ( - [| - [|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 concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| - [|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" - testCase "3x3 diagonal Matrix (Values = 1) with 3x3 Matrix (Values = 1) (lower)" <| fun () -> - SolveTriangularLinearSystems KDiagonal1 B1 true - |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| - [|1.;1.;1.|]; - [|1.;1.;1.|]; - [|1.;1.;1.|] - |] - |> Array.concat - TestExtensions.sequenceEqual Accuracy.high concatRes concatExpected "Should be 3x3 Matrix of 1" - testCase "3x3 Lower Triangular Matrix (Values = 1) with 3x3 Matrix (Values = 1)" <| fun () -> - SolveTriangularLinearSystems KLower1 B1 true - |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| - [|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" - testCase "3x3 Lower Triangular Matrix (Values = -1) with 3x3 Matrix (Values = 1)" <| fun () -> - SolveTriangularLinearSystems KLowerNeg1 B1 true - |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| - [|-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" - testCase "3x3 Lower Triangular Matrix (Values = Inf) with 3x3 Matrix (Values = 1)" <| fun () -> - SolveTriangularLinearSystems KLowerInf B1 true - |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| - [|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" - testCase "3x3 Lower Triangular Matrix (Values = -Inf) with 3x3 Matrix (Values = 1)" <| fun () -> - SolveTriangularLinearSystems KLowerNegInf B1 true - |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| - [|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" - testCase "3x3 Lower Triangular Matrix (Values = NaN) with 3x3 Matrix (Values = 1)" <| fun () -> - SolveTriangularLinearSystems KLowerNaN B1 true - |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| - [|nan;nan;nan|]; - [|nan;nan;nan|]; - [|nan;nan;nan|] - |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix of NaN" - testCase "3x3 diagonal Matrix (Values = 1) with 3x3 Matrix (Values = Inf) (lower)" <| fun () -> - SolveTriangularLinearSystems KDiagonal1 BInf true - |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| - [|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" - testCase "3x3 Upper Triangular Matrix (Values = 1) with 3x3 Matrix (Values = Inf)" <| fun () -> - SolveTriangularLinearSystems KLower1 BInf true - |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| - [|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" - testCase "3x3 Lower Triangular Matrix (Values = -1) with 3x3 Matrix (Values = Inf)" <| fun () -> - SolveTriangularLinearSystems KLowerNeg1 BInf true - |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| - [|-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" - testCase "3x3 Lower Triangular Matrix (Values = Inf) with 3x3 Matrix (Values = Inf)" <| fun () -> - SolveTriangularLinearSystems KLowerInf BInf true - |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| - [|nan;nan;nan|]; - [|nan;nan;nan|]; - [|nan;nan;nan|] - |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix of NaN" - testCase "3x3 Lower Triangular Matrix (Values = -Inf) with 3x3 Matrix (Values = Inf)" <| fun () -> - SolveTriangularLinearSystems KLowerNegInf BInf true - |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| - [|nan;nan;nan|]; - [|nan;nan;nan|]; - [|nan;nan;nan|] - |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix of NaN" - testCase "3x3 Lower Triangular Matrix (Values = NaN) with 3x3 Matrix (Values = Inf)" <| fun () -> - SolveTriangularLinearSystems KLowerNaN BInf true - |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| - [|nan;nan;nan|]; - [|nan;nan;nan|]; - [|nan;nan;nan|] - |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix of NaN" - testCase "3x3 diagonal Matrix (Values = 1) with 3x3 Matrix (Values = -Inf)" <| fun () -> - SolveTriangularLinearSystems KDiagonal1 BNegInf true - |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| - [|-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" - testCase "3x3 Lower Triangular Matrix (Values = 1) with 3x3 Matrix (Values = -Inf)" <| fun () -> - SolveTriangularLinearSystems KLower1 BNegInf true - |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| - [|-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" - testCase "3x3 Lower Triangular Matrix (Values = Inf) with 3x3 Matrix (Values = -Inf)" <| fun () -> - SolveTriangularLinearSystems KLowerInf BNegInf true - |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| - [|nan;nan;nan|]; - [|nan;nan;nan|]; - [|nan;nan;nan|] - |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix of NaN" - testCase "3x3 Lower Triangular Matrix (Values = -Inf) with 3x3 Matrix (Values = -Inf)" <| fun () -> - SolveTriangularLinearSystems KLowerNegInf BNegInf true - |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| - [|nan;nan;nan|]; - [|nan;nan;nan|]; - [|nan;nan;nan|] - |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix of NaN" - testCase "3x3 Lower Triangular Matrix (Values = NaN) with 3x3 Matrix (Values = -Inf)" <| fun () -> - SolveTriangularLinearSystems KLowerNaN BNegInf true - |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| - [|nan;nan;nan|]; - [|nan;nan;nan|]; - [|nan;nan;nan|] - |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix of NaN" - testCase "3x3 diagonal Matrix (Values = 1) with 3x3 Matrix (Values = NaN) (lower)" <| fun () -> - SolveTriangularLinearSystems KDiagonal1 BNaN true - |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| - [|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" - testCase "3x3 Lower Triangular Matrix (Values = 1) with 3x3 Matrix (Values = NaN)" <| fun () -> - SolveTriangularLinearSystems KLower1 BNaN true - |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| - [|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" - testCase "3x3 Lower Triangular Matrix (Values = Inf) with 3x3 Matrix (Values = NaN)" <| fun () -> - SolveTriangularLinearSystems KLowerInf BNaN true - |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| - [|nan;nan;nan|]; - [|nan;nan;nan|]; - [|nan;nan;nan|] - |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix of NaN" - testCase "3x3 Lower Triangular Matrix (Values = -Inf) with 3x3 Matrix (Values = NaN)" <| fun () -> - SolveTriangularLinearSystems KLowerNegInf BNaN true - |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| - [|nan;nan;nan|]; - [|nan;nan;nan|]; - [|nan;nan;nan|] - |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix of NaN" - testCase "3x3 Lower Triangular Matrix (Values = NaN) with 3x3 Matrix (Values = NaN)" <| fun () -> - SolveTriangularLinearSystems KLowerNaN BNaN true - |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| - [|nan;nan;nan|]; - [|nan;nan;nan|]; - [|nan;nan;nan|] - |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix of NaN" - testCase "3x3 diagonal Matrix (Values = 1) with 3x3 Matrix (Values = -1) (lower)" <| fun () -> - SolveTriangularLinearSystems KDiagonal1 BNeg1 true - |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| - [|-1.;-1.;-1.|]; - [|-1.;-1.;-1.|]; - [|-1.;-1.;-1.|] - |] - |> Array.concat - TestExtensions.sequenceEqual Accuracy.high concatRes concatExpected "Should be 3x3 Matrix of -1" - testCase "3x3 Lower Triangular Matrix (Values = 1) with 3x3 Matrix (Values = -1)" <| fun () -> - SolveTriangularLinearSystems KLower1 BNeg1 true - |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| - [|-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" - testCase "3x3 Lower Triangular Matrix (Values = -1) with 3x3 Matrix (Values = -1)" <| fun () -> - SolveTriangularLinearSystems KLowerNeg1 BNeg1 true - |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| - [|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" - testCase "3x3 Lower Triangular Matrix (Values = Inf) with 3x3 Matrix (Values = -1)" <| fun () -> - SolveTriangularLinearSystems KLowerInf BNeg1 true - |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| - [|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" - testCase "3x3 Lower Triangular Matrix (Values = -Inf) with 3x3 Matrix (Values = -1)" <| fun () -> - SolveTriangularLinearSystems KLowerNegInf BNeg1 true - |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| - [|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" - testCase "3x3 Lower Triangular Matrix (Values = NaN) with 3x3 Matrix (Values = -1)" <| fun () -> - SolveTriangularLinearSystems KLowerNaN BNeg1 true - |> fun res -> - let concatRes = - res - |> Matrix.toJaggedArray - |> Array.concat - let concatExpected = - [| - [|nan;nan;nan|]; - [|nan;nan;nan|]; - [|nan;nan;nan|] - |] - |> Array.concat - TestExtensions.sequenceEqualRoundedNaN 9 concatRes concatExpected "Should be 3x3 Matrix of NaN" - ] - testList "SolveTriangularLinearSystem (Upper)" [ - testCase "3x3 Upper Triangular Matrix with Vector (realistic example)" <| fun () -> - SolveTriangularLinearSystem - ( - [| - [|1.;2.;3.|]; - [|0.;1.;1.|]; - [|0.;0.;2.|] - |] - |> Matrix.ofJaggedArray - ) - ( - [|8.;4.;2.|] - |> vector - ) - false - |> fun res -> - let concatRes = - res - |> Vector.toArray - let concatExpected = - [|-1.;3.;1.|] - TestExtensions.sequenceEqual Accuracy.high concatRes concatExpected "Should be Vector of -1.;3.;1." - testCase "3x3 diagonal Matrix (Values = 1) with Vector (Values = 1)" <| fun () -> - 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" - testCase "3x3 Upper Triangular Matrix (Values = 1) with Vector (Values = 1)" <| fun () -> - 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" - testCase "3x3 Upper Triangular Matrix (Values = -1) with Vector (Values = 1)" <| fun () -> - 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" - testCase "3x3 Upper Triangular Matrix (Values = Inf) with Vector (Values = 1)" <| fun () -> - 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" - testCase "3x3 Upper Triangular Matrix (Values = -Inf) with Vector (Values = 1)" <| fun () -> - 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" - testCase "3x3 Upper Triangular Matrix (Values = NaN) with Vector (Values = 1)" <| fun () -> - 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" - ] - testList "SolveTriangularLinearSystem (Lower)" [ - testCase "3x3 Upper Triangular Matrix with Vector (realistic example)" <| fun () -> - SolveTriangularLinearSystem - ( - [| - [|1.;0.;0.|]; - [|2.;1.;0.|]; - [|3.;1.;2.|] - |] - |> Matrix.ofJaggedArray - ) - ( - [|8.;4.;2.|] - |> vector - ) - true - |> fun res -> - let concatRes = - res - |> Vector.toArray - let concatExpected = - [|8.;-12.;-5.|] - TestExtensions.sequenceEqual Accuracy.high concatRes concatExpected "Should be Vector of 8.;-12.;-5." - testCase "3x3 diagonal Matrix (Values = 1) with Vector (Values = 1)" <| fun () -> - 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" - testCase "3x3 Lower Triangular Matrix (Values = 1) with Vector (Values = 1)" <| fun () -> - 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" - testCase "3x3 Lower Triangular Matrix (Values = -1) with Vector (Values = 1)" <| fun () -> - 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" - testCase "3x3 Lower Triangular Matrix (Values = Inf) with Vector (Values = 1)" <| fun () -> - 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" - testCase "3x3 Lower Triangular Matrix (Values = -Inf) with Vector (Values = 1)" <| fun () -> - 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" - testCase "3x3 Lower Triangular Matrix (Values = NaN) with Vector (Values = 1)" <| fun () -> - 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" - ] - ] - diff --git a/tests/FSharp.Stats.Tests/Matrix.fs b/tests/FSharp.Stats.Tests/Matrix.fs deleted file mode 100644 index 754f450ef..000000000 --- a/tests/FSharp.Stats.Tests/Matrix.fs +++ /dev/null @@ -1,1337 +0,0 @@ -module MatrixTests -open Expecto - -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)) - -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 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 () -> - () - ] - - ] - ] - diff --git a/tests/FSharp.Stats.Tests/Optimization.fs b/tests/FSharp.Stats.Tests/Optimization.fs index 2c4f2feae..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 @@ -13,21 +14,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. 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/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/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" 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 diff --git a/tests/FSharp.Stats.Tests/TestExtensions.fs b/tests/FSharp.Stats.Tests/TestExtensions.fs index 09c1b8a0c..3c7ce678d 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 @@ -8,6 +9,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) @@ -32,6 +38,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) = @@ -53,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 41edb81d3..cf867dd50 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 @@ -182,10 +185,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 +274,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 +283,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 +325,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 @@ -400,6 +403,89 @@ 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)) + + // 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 + |> 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)) + + // 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 + |> 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 = @@ -672,7 +758,7 @@ let multiLabelConfusionMatrixTests = [2; 0; 4] ] |> array2D - |> Matrix.Generic.ofArray2D + |> Matrix.ofArray2D let expectedMLCM = { @@ -684,7 +770,7 @@ let multiLabelConfusionMatrixTests = [2; 0; 4] ] |> array2D - |> Matrix.Generic.ofArray2D + |> Matrix.ofArray2D } let multiLabelCM = MultiLabelConfusionMatrix.create([|"A";"B";"C"|], c) @@ -816,7 +902,7 @@ let comparisonMetricsTests = [2; 0; 4] ] |> array2D - |> Matrix.Generic.ofArray2D + |> Matrix.ofArray2D let multiLabelCM = MultiLabelConfusionMatrix.create([|"A";"B";"C"|], c) @@ -1240,3 +1326,122 @@ 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 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|] + 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 + + testList "Testing.Anova" [ + testCase "onewayAnova" <| fun () -> + 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" + // 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.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.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.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 diff --git a/tests/FSharp.Stats.Tests/Vector.fs b/tests/FSharp.Stats.Tests/Vector.fs deleted file mode 100644 index 42009b896..000000000 --- a/tests/FSharp.Stats.Tests/Vector.fs +++ /dev/null @@ -1,23 +0,0 @@ -module VectorTests -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)" - ] 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