diff --git a/src/Numerics/Fit.cs b/src/Numerics/Fit.cs index 2a829c5e..9960e87a 100644 --- a/src/Numerics/Fit.cs +++ b/src/Numerics/Fit.cs @@ -3,9 +3,9 @@ // http://numerics.mathdotnet.com // http://github.com/mathnet/mathnet-numerics // http://mathnetnumerics.codeplex.com -// -// Copyright (c) 2009-2013 Math.NET -// +// +// Copyright (c) 2009-2015 Math.NET +// // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation // files (the "Software"), to deal in the Software without @@ -14,10 +14,10 @@ // copies of the Software, and to permit persons to whom the // Software is furnished to do so, subject to the following // conditions: -// +// // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. -// +// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND @@ -94,6 +94,7 @@ namespace MathNet.Numerics /// /// Least-Squares fitting the points (x,y) 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. + /// A polynomial with order/degree k has (k+1) coefficients and thus requires at least (k+1) samples. /// public static double[] Polynomial(double[] x, double[] y, int order, DirectRegressionMethod method = DirectRegressionMethod.QR) { @@ -104,6 +105,7 @@ namespace MathNet.Numerics /// /// 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. + /// A polynomial with order/degree k has (k+1) coefficients and thus requires at least (k+1) samples. /// public static Func PolynomialFunc(double[] x, double[] y, int order, DirectRegressionMethod method = DirectRegressionMethod.QR) { @@ -114,6 +116,7 @@ namespace MathNet.Numerics /// /// 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. + /// A polynomial with order/degree k has (k+1) coefficients and thus requires at least (k+1) samples. /// public static double[] PolynomialWeighted(double[] x, double[] y, double[] w, int order) { diff --git a/src/Numerics/LinearRegression/MultipleRegression.cs b/src/Numerics/LinearRegression/MultipleRegression.cs index 42e1a705..d925c65e 100644 --- a/src/Numerics/LinearRegression/MultipleRegression.cs +++ b/src/Numerics/LinearRegression/MultipleRegression.cs @@ -3,9 +3,9 @@ // http://numerics.mathdotnet.com // http://github.com/mathnet/mathnet-numerics // http://mathnetnumerics.codeplex.com -// -// Copyright (c) 2009-2014 Math.NET -// +// +// Copyright (c) 2009-2015 Math.NET +// // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation // files (the "Software"), to deal in the Software without @@ -14,10 +14,10 @@ // copies of the Software, and to permit persons to whom the // Software is furnished to do so, subject to the following // conditions: -// +// // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. -// +// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND @@ -31,6 +31,7 @@ using System; using System.Collections.Generic; using MathNet.Numerics.LinearAlgebra; +using MathNet.Numerics.Properties; namespace MathNet.Numerics.LinearRegression { @@ -135,6 +136,16 @@ namespace MathNet.Numerics.LinearRegression /// Best fitting vector for model parameters β public static Vector NormalEquations(Matrix x, Vector y) where T : struct, IEquatable, IFormattable { + if (x.RowCount != y.Count) + { + throw new ArgumentException(string.Format(Resources.SampleVectorsSameLength, x.RowCount, y.Count)); + } + + if (x.ColumnCount > y.Count) + { + throw new ArgumentException(string.Format(Resources.RegressionNotEnoughSamples, x.ColumnCount, y.Count)); + } + return x.TransposeThisAndMultiply(x).Cholesky().Solve(x.TransposeThisAndMultiply(y)); } @@ -147,6 +158,16 @@ namespace MathNet.Numerics.LinearRegression /// Best fitting vector for model parameters β public static Matrix NormalEquations(Matrix x, Matrix y) where T : struct, IEquatable, IFormattable { + if (x.RowCount != y.RowCount) + { + throw new ArgumentException(string.Format(Resources.SampleVectorsSameLength, x.RowCount, y.RowCount)); + } + + if (x.ColumnCount > y.RowCount) + { + throw new ArgumentException(string.Format(Resources.RegressionNotEnoughSamples, x.ColumnCount, y.RowCount)); + } + return x.TransposeThisAndMultiply(x).Cholesky().Solve(x.TransposeThisAndMultiply(y)); } @@ -166,6 +187,16 @@ namespace MathNet.Numerics.LinearRegression predictor = predictor.InsertColumn(0, Vector.Build.Dense(predictor.RowCount, Vector.One)); } + if (predictor.RowCount != y.Length) + { + throw new ArgumentException(string.Format(Resources.SampleVectorsSameLength, predictor.RowCount, y.Length)); + } + + if (predictor.ColumnCount > y.Length) + { + throw new ArgumentException(string.Format(Resources.RegressionNotEnoughSamples, predictor.ColumnCount, y.Length)); + } + var response = Vector.Build.Dense(y); return predictor.TransposeThisAndMultiply(predictor).Cholesky().Solve(predictor.TransposeThisAndMultiply(response)).ToArray(); } @@ -192,6 +223,16 @@ namespace MathNet.Numerics.LinearRegression /// Best fitting vector for model parameters β public static Vector QR(Matrix x, Vector y) where T : struct, IEquatable, IFormattable { + if (x.RowCount != y.Count) + { + throw new ArgumentException(string.Format(Resources.SampleVectorsSameLength, x.RowCount, y.Count)); + } + + if (x.ColumnCount > y.Count) + { + throw new ArgumentException(string.Format(Resources.RegressionNotEnoughSamples, x.ColumnCount, y.Count)); + } + return x.QR().Solve(y); } @@ -204,6 +245,16 @@ namespace MathNet.Numerics.LinearRegression /// Best fitting vector for model parameters β public static Matrix QR(Matrix x, Matrix y) where T : struct, IEquatable, IFormattable { + if (x.RowCount != y.RowCount) + { + throw new ArgumentException(string.Format(Resources.SampleVectorsSameLength, x.RowCount, y.RowCount)); + } + + if (x.ColumnCount > y.RowCount) + { + throw new ArgumentException(string.Format(Resources.RegressionNotEnoughSamples, x.ColumnCount, y.RowCount)); + } + return x.QR().Solve(y); } @@ -223,6 +274,16 @@ namespace MathNet.Numerics.LinearRegression predictor = predictor.InsertColumn(0, Vector.Build.Dense(predictor.RowCount, Vector.One)); } + if (predictor.RowCount != y.Length) + { + throw new ArgumentException(string.Format(Resources.SampleVectorsSameLength, predictor.RowCount, y.Length)); + } + + if (predictor.ColumnCount > y.Length) + { + throw new ArgumentException(string.Format(Resources.RegressionNotEnoughSamples, predictor.ColumnCount, y.Length)); + } + return predictor.QR().Solve(Vector.Build.Dense(y)).ToArray(); } @@ -248,6 +309,16 @@ namespace MathNet.Numerics.LinearRegression /// Best fitting vector for model parameters β public static Vector Svd(Matrix x, Vector y) where T : struct, IEquatable, IFormattable { + if (x.RowCount != y.Count) + { + throw new ArgumentException(string.Format(Resources.SampleVectorsSameLength, x.RowCount, y.Count)); + } + + if (x.ColumnCount > y.Count) + { + throw new ArgumentException(string.Format(Resources.RegressionNotEnoughSamples, x.ColumnCount, y.Count)); + } + return x.Svd().Solve(y); } @@ -260,6 +331,16 @@ namespace MathNet.Numerics.LinearRegression /// Best fitting vector for model parameters β public static Matrix Svd(Matrix x, Matrix y) where T : struct, IEquatable, IFormattable { + if (x.RowCount != y.RowCount) + { + throw new ArgumentException(string.Format(Resources.SampleVectorsSameLength, x.RowCount, y.RowCount)); + } + + if (x.ColumnCount > y.RowCount) + { + throw new ArgumentException(string.Format(Resources.RegressionNotEnoughSamples, x.ColumnCount, y.RowCount)); + } + return x.Svd().Solve(y); } @@ -279,6 +360,16 @@ namespace MathNet.Numerics.LinearRegression predictor = predictor.InsertColumn(0, Vector.Build.Dense(predictor.RowCount, Vector.One)); } + if (predictor.RowCount != y.Length) + { + throw new ArgumentException(string.Format(Resources.SampleVectorsSameLength, predictor.RowCount, y.Length)); + } + + if (predictor.ColumnCount > y.Length) + { + throw new ArgumentException(string.Format(Resources.RegressionNotEnoughSamples, predictor.ColumnCount, y.Length)); + } + return predictor.Svd().Solve(Vector.Build.Dense(y)).ToArray(); } diff --git a/src/Numerics/LinearRegression/SimpleRegression.cs b/src/Numerics/LinearRegression/SimpleRegression.cs index 1b2cbc1a..41332cdd 100644 --- a/src/Numerics/LinearRegression/SimpleRegression.cs +++ b/src/Numerics/LinearRegression/SimpleRegression.cs @@ -3,9 +3,9 @@ // http://numerics.mathdotnet.com // http://github.com/mathnet/mathnet-numerics // http://mathnetnumerics.codeplex.com -// +// // Copyright (c) 2009-2013 Math.NET -// +// // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation // files (the "Software"), to deal in the Software without @@ -14,10 +14,10 @@ // copies of the Software, and to permit persons to whom the // Software is furnished to do so, subject to the following // conditions: -// +// // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. -// +// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND @@ -47,12 +47,12 @@ namespace MathNet.Numerics.LinearRegression { if (x.Length != y.Length) { - throw new ArgumentException(Resources.ArgumentVectorsSameLength); + throw new ArgumentException(string.Format(Resources.SampleVectorsSameLength, x.Length, y.Length)); } if (x.Length <= 1) { - throw new ArgumentException(string.Format(Resources.ArrayTooSmall, 2)); + throw new ArgumentException(string.Format(Resources.RegressionNotEnoughSamples, 2, x.Length)); } // First Pass: Mean (Less robust but faster than ArrayStatistics.Mean) diff --git a/src/Numerics/Properties/Resources.Designer.cs b/src/Numerics/Properties/Resources.Designer.cs index a8569c78..b4650370 100644 --- a/src/Numerics/Properties/Resources.Designer.cs +++ b/src/Numerics/Properties/Resources.Designer.cs @@ -1,7 +1,7 @@ //------------------------------------------------------------------------------ // // This code was generated by a tool. -// Runtime Version:4.0.30319.34209 +// Runtime Version:4.0.30319.42000 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -12,8 +12,8 @@ using System.Reflection; namespace MathNet.Numerics.Properties { using System; - - + + /// /// A strongly-typed resource class, for looking up localized strings, etc. /// @@ -25,15 +25,15 @@ namespace MathNet.Numerics.Properties { [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] public class Resources { - + private static global::System.Resources.ResourceManager resourceMan; - + private static global::System.Globalization.CultureInfo resourceCulture; - + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] internal Resources() { } - + /// /// Returns the cached ResourceManager instance used by this class. /// @@ -56,7 +56,7 @@ namespace MathNet.Numerics.Properties { return resourceMan; } } - + /// /// Overrides the current thread's CurrentUICulture property for all /// resource lookups using this strongly typed resource class. @@ -394,7 +394,7 @@ namespace MathNet.Numerics.Properties { return ResourceManager.GetString("ArgumentOutOfRangeSmaller", resourceCulture); } } - + /// /// Looks up a localized string similar to {0} must be smaller than or equal to {1}.. /// @@ -403,7 +403,7 @@ namespace MathNet.Numerics.Properties { return ResourceManager.GetString("ArgumentOutOfRangeSmallerEqual", resourceCulture); } } - + /// /// Looks up a localized string similar to The chosen parameter set is invalid (probably some value is out of range).. /// @@ -864,6 +864,15 @@ namespace MathNet.Numerics.Properties { } } + /// + /// Looks up a localized string similar to A regression of the requested order requires at least {0} samples. Only {1} samples have been provided. . + /// + public static string RegressionNotEnoughSamples { + get { + return ResourceManager.GetString("RegressionNotEnoughSamples", resourceCulture); + } + } + /// /// Looks up a localized string similar to The algorithm has failed, exceeded the number of iterations allowed or there is no root within the provided bounds.. /// @@ -909,6 +918,15 @@ namespace MathNet.Numerics.Properties { } } + /// + /// Looks up a localized string similar to All sample vectors must have the same length. However, vectors with disagreeing length {0} and {1} have been provided. A sample with index i is given by the value at index i of each provided vector.. + /// + public static string SampleVectorsSameLength { + get { + return ResourceManager.GetString("SampleVectorsSameLength", resourceCulture); + } + } + /// /// Looks up a localized string similar to U is singular, and the inversion could not be completed.. /// diff --git a/src/Numerics/Properties/Resources.resx b/src/Numerics/Properties/Resources.resx index d87f9a72..e3c53791 100644 --- a/src/Numerics/Properties/Resources.resx +++ b/src/Numerics/Properties/Resources.resx @@ -436,4 +436,10 @@ U is singular, and the inversion could not be completed. The {0}-th diagonal element of the factor U is zero. + + A regression of the requested order requires at least {0} samples. Only {1} samples have been provided. + + + All sample vectors must have the same length. However, vectors with disagreeing length {0} and {1} have been provided. A sample with index i is given by the value at index i of each provided vector. + \ No newline at end of file