diff --git a/MathNet.Numerics.sln.DotSettings b/MathNet.Numerics.sln.DotSettings index a97eba6c..5787163f 100644 --- a/MathNet.Numerics.sln.DotSettings +++ b/MathNet.Numerics.sln.DotSettings @@ -15,6 +15,8 @@ True False False + False + True True False <copyright file="$FILENAME$" company="Math.NET"> @@ -66,5 +68,6 @@ OTHER DEALINGS IN THE SOFTWARE. SVD TFQMR WH + True <data /> <data><IncludeFilters /><ExcludeFilters /></data> \ No newline at end of file diff --git a/src/Numerics/Fit.cs b/src/Numerics/Fit.cs index 48a08efc..b16026cd 100644 --- a/src/Numerics/Fit.cs +++ b/src/Numerics/Fit.cs @@ -70,6 +70,15 @@ namespace MathNet.Numerics return MultipleRegression.NormalEquations(x, y); } + /// + /// Weighted Least-Squares fitting the points (X,y) = ((x0,x1,..,xk),y) and weights w to a linear surface y : X -> p0*x0 + p1*x1 + ... + pk*xk, + /// returning its best fitting parameters as [p0, p1, p2, ..., pk] array. + /// + public static double[] MultiDimWeighted(double[][] x, double[] y, double[] w) + { + return WeightedRegression.Weighted(x, y, w); + } + /// /// Least-Squares fitting the points (X,y) = ((x0,x1,..,xk),y) to a linear surface y : X -> p0*x0 + p1*x1 + ... + pk*xk, /// returning a function y' for the best fitting combination. @@ -90,6 +99,16 @@ namespace MathNet.Numerics return MultipleRegression.QR(design, Vector.Build.Dense(y)).ToArray(); } + /// + /// Weighted Least-Squares fitting the points (x,y) and weights w to a k-order polynomial y : x -> p0 + p1*x + p2*x^2 + ... + pk*x^k, + /// returning its best fitting parameters as [p0, p1, p2, ..., pk] array, compatible with Evaluate.Polynomial. + /// + public static double[] PolynomialWeighted(double[] x, double[] y, double[] w, int order) + { + var design = Matrix.Build.Dense(x.Length, order + 1, (i, j) => Math.Pow(x[i], j)); + return WeightedRegression.Weighted(design, Vector.Build.Dense(y), Matrix.Build.DenseOfDiagonalArray(w)).ToArray(); + } + /// /// Least-Squares fitting the points (x,y) to a k-order polynomial y : x -> p0 + p1*x + p2*x^2 + ... + pk*x^k, /// returning a function y' for the best fitting polynomial. diff --git a/src/UnitTests/FitTests.cs b/src/UnitTests/FitTests.cs index c2444ff6..542c0eda 100644 --- a/src/UnitTests/FitTests.cs +++ b/src/UnitTests/FitTests.cs @@ -133,6 +133,28 @@ namespace MathNet.Numerics.UnitTests } } + [Test] + public void FitsToOrder2PolynomialWeighted() + { + // Mathematica: LinearModelFit[{{1,4.986},{2,2.347},{3,2.061},{4,-2.995},{5,-2.352},{6,-5.782}}, {1, x, x^2}, x, Weights -> {0.5, 1.0, 1.0, 1.0, 1.0, 0.5}] + // -> 7.01451 - 2.12819 x + 0.0115 x^2 + + var x = Enumerable.Range(1, 6).Select(Convert.ToDouble).ToArray(); + var y = new[] { 4.986, 2.347, 2.061, -2.995, -2.352, -5.782 }; + + var respUnweighted = Fit.PolynomialWeighted(x, y, new[] { 1.0, 1.0, 1.0, 1.0, 1.0, 1.0 }, 2); + Assert.AreEqual(3, respUnweighted.Length); + Assert.AreEqual(6.9703, respUnweighted[0], 1e-4); + Assert.AreEqual(-2.05564, respUnweighted[1], 1e-4); + Assert.AreEqual(-0.00426786, respUnweighted[2], 1e-6); + + var resp = Fit.PolynomialWeighted(x, y, new[] { 0.5, 1.0, 1.0, 1.0, 1.0, 0.5 }, 2); + Assert.AreEqual(3, resp.Length); + Assert.AreEqual(7.01451, resp[0], 1e-4); + Assert.AreEqual(-2.12819, resp[1], 1e-4); + Assert.AreEqual(0.0115, resp[2], 1e-6); + } + [Test] public void FitsToTrigonometricLinearCombination() {