From dcade5cb90ab3f9406e2ee0b2f155986f3ec4768 Mon Sep 17 00:00:00 2001 From: Christoph Ruegg Date: Wed, 26 Jun 2013 13:30:38 +0200 Subject: [PATCH] Fitting: New Least Squares Linear Curve Fitting --- .../FSharpPortableUnitTests.fsproj | 3 + src/FSharpUnitTests/CurveFittingTests.fs | 37 ++++ src/FSharpUnitTests/FSharpUnitTests.fsproj | 1 + src/Numerics/LeastSquares.cs | 110 ++++++++++++ src/Numerics/Numerics.csproj | 1 + src/Portable/Portable.csproj | 3 + src/UnitTests/LeastSquaresTests.cs | 160 ++++++++++++++++++ src/UnitTests/UnitTests.csproj | 1 + 8 files changed, 316 insertions(+) create mode 100644 src/FSharpUnitTests/CurveFittingTests.fs create mode 100644 src/Numerics/LeastSquares.cs create mode 100644 src/UnitTests/LeastSquaresTests.cs diff --git a/src/FSharpPortableUnitTests/FSharpPortableUnitTests.fsproj b/src/FSharpPortableUnitTests/FSharpPortableUnitTests.fsproj index 6d4ad457..f106b5d3 100644 --- a/src/FSharpPortableUnitTests/FSharpPortableUnitTests.fsproj +++ b/src/FSharpPortableUnitTests/FSharpPortableUnitTests.fsproj @@ -91,6 +91,9 @@ PokerTests.fs + + CurveFittingTests.fs + diff --git a/src/FSharpUnitTests/CurveFittingTests.fs b/src/FSharpUnitTests/CurveFittingTests.fs new file mode 100644 index 00000000..3e5c2a6e --- /dev/null +++ b/src/FSharpUnitTests/CurveFittingTests.fs @@ -0,0 +1,37 @@ +namespace MathNet.Numerics.Tests + +open System +open MathNet.Numerics +open NUnit.Framework +open FsUnit + +module CurveFittingTests = + + let tofs (f:Func<_,_>) = fun a -> f.Invoke(a) + + [] + let ``When fitting to an exact line should return exact parameters``() = + let f z = 4.0 - 1.5*z + let x = Array.append [| 1.0 .. 2.0 .. 10.0 |] [| -1.0 .. -1.0 .. -5.0 |] + let y = x |> Array.map f + + LeastSquares.FitToLine(x,y) + |> should (equalWithin 1.0e-12) [| 4.0; -1.5 |] + + let fres = LeastSquares.FitToLineFunc(x,y) |> tofs + in x |> Array.iter (fun x -> fres x |> should (equalWithin 1.0e-12) (f x)) + + [] + let ``Can fit to arbitrary linear combination``() = + + // Mathematica: Fit[{{1,4.986},{2,2.347},{3,2.061},{4,-2.995},{5,-2.352},{6,-5.782}}, {1, sin(x), cos(x)}, x] + // -> 4.02159 sin(x) - 1.46962 cos(x) - 0.287476 + + let x = [| 1.0 .. 6.0 |] + let y = [| 4.986; 2.347; 2.061; -2.995; -2.352; -5.782 |] + + LeastSquares.FitToLinearCombination(x, y, (fun z -> 1.0), (fun z -> Math.Sin(z)), (fun z -> Math.Cos(z))) + |> should (equalWithin 1.0e-4) [| -0.287476; 4.02159; -1.46962 |] + + let fres = LeastSquares.FitToLinearCombinationFunc(x, y, (fun z -> 1.0), (fun z -> Math.Sin(z)), (fun z -> Math.Cos(z))) |> tofs + in x |> Array.iter (fun x -> fres x |> should (equalWithin 1.0e-4) (4.02159*Math.Sin(x) - 1.46962*Math.Cos(x) - 0.287476)) diff --git a/src/FSharpUnitTests/FSharpUnitTests.fsproj b/src/FSharpUnitTests/FSharpUnitTests.fsproj index 75885c55..b10a7f7b 100644 --- a/src/FSharpUnitTests/FSharpUnitTests.fsproj +++ b/src/FSharpUnitTests/FSharpUnitTests.fsproj @@ -76,6 +76,7 @@ +