Skip to content

Commit

Permalink
Documentation and throw DivideByZeroException to fits with indetermin…
Browse files Browse the repository at this point in the history
…ate parameters.
  • Loading branch information
dcwuser committed Dec 27, 2016
1 parent 70c2833 commit 80c1d43
Show file tree
Hide file tree
Showing 4 changed files with 27 additions and 14 deletions.
2 changes: 1 addition & 1 deletion Numerics/Matrices/SymmetricMatrix.cs
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ public SymmetricMatrix Inverse () {
}

/// <summary>
/// Returns the Cholesky decomposition of the matrix.
/// Computes the Cholesky decomposition of the matrix.
/// </summary>
/// <returns>The Cholesky decomposition of the matrix, or null if the matrix is not positive definite.</returns>
/// <remarks>
Expand Down
2 changes: 1 addition & 1 deletion Numerics/Meta.Numerics.nuspec
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<package>
<metadata>
<id>Meta.Numerics</id>
<version>3.0.0</version>
<version>3.1.0</version>
<authors>David Wright</authors>
<description>A library for numeric computing with support for statistics, matrix algebra, and advanced functions.</description>
<projectUrl>http://www.meta-numerics.net</projectUrl>
Expand Down
8 changes: 7 additions & 1 deletion Numerics/Statistics/MultivariateSample.cs
Original file line number Diff line number Diff line change
Expand Up @@ -500,6 +500,8 @@ private FitResult LinearRegression_Internal (int outputIndex) {
/// </remarks>
/// <exception cref="ArgumentOutOfRangeException"><paramref name="outputIndex"/> is outside the range of allowed indexes.</exception>
/// <exception cref="InsufficientDataException">There are fewer entries than the dimension of the multivariate sample.</exception>
/// <exception cref="DivideByZeroException">The curvature matrix is singular, indicating that the data is independent of
/// one or more parameters, or that two or more parameters are linearly dependent.</exception>
/// <seealso cref="LinearRegression(int)"/>
/// <seealso href="http://en.wikipedia.org/wiki/Linear_regression"/>
public FitResult LinearRegression (int outputIndex) {
Expand All @@ -524,6 +526,8 @@ public FitResult LinearRegression (int outputIndex) {
/// for the output variable.</remarks>
/// <exception cref="InvalidOperationException">The column to be predicted contains values other than 0 and 1.</exception>
/// <exception cref="InsufficientDataException">There are not more rows in the sample than columns.</exception>
/// <exception cref="DivideByZeroException">The curvature matrix is singular, indicating that the data is independent of
/// one or more parameters, or that two or more parameters are linearly dependent.</exception>
public FitResult LogisticLinearRegression (int outputIndex) {

if ((outputIndex < 0) || (outputIndex >= this.Dimension)) throw new ArgumentOutOfRangeException(nameof(outputIndex));
Expand Down Expand Up @@ -562,8 +566,10 @@ public FitResult LogisticLinearRegression (int outputIndex) {
//}

MultiExtremum maximum = MultiFunctionMath.FindLocalMaximum(logLikelihood, start);
CholeskyDecomposition CD = maximum.HessianMatrix.CholeskyDecomposition();
if (CD == null) throw new DivideByZeroException();

FitResult result = new FitResult(maximum.Location, maximum.HessianMatrix.CholeskyDecomposition().Inverse(), null);
FitResult result = new FitResult(maximum.Location, CD.Inverse(), null);

return (result);

Expand Down
29 changes: 18 additions & 11 deletions Numerics/Statistics/UncertainMeasurementSample.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public UncertainMeasurementSample () {
/// </summary>
/// <param name="datum">The data point.</param>
public void Add (UncertainMeasurement<T> datum) {
if (datum == null) throw new ArgumentNullException("datum");
if (datum == null) throw new ArgumentNullException(nameof(datum));
data.Add(datum);
}

Expand All @@ -48,7 +48,7 @@ public void Add (T x, double y, double dy) {
/// </summary>
/// <param name="data">The data points.</param>
public void Add (IEnumerable<UncertainMeasurement<T>> data) {
if (data == null) throw new ArgumentNullException("data");
if (data == null) throw new ArgumentNullException(nameof(data));
foreach (UncertainMeasurement<T> datum in data) {
this.data.Add(datum);
}
Expand Down Expand Up @@ -100,7 +100,7 @@ public int Count {
/// <exception cref="InsufficientDataException">There are fewer data points than fit parameters.</exception>
public FitResult FitToLinearFunction (Func<T, double>[] functions) {

if (functions == null) throw new ArgumentNullException("functions");
if (functions == null) throw new ArgumentNullException(nameof(functions));
if (functions.Length > data.Count) throw new InsufficientDataException();

// construct the design matrix
Expand Down Expand Up @@ -176,11 +176,13 @@ public FitResult FitToLinearFunction (Func<T, double>[] functions) {
/// <param name="start">An initial guess at the parameters.</param>
/// <returns>A fit result containing the best-fitting function parameters
/// and a &#x3C7;<sup>2</sup> test of the quality of the fit.</returns>
/// <exception cref="ArgumentNullException"><paramref name="function"/> or <paramref name="start"/> are null.</exception>
/// <exception cref="ArgumentNullException"><paramref name="function"/> or <paramref name="start"/> are <see langword="null"/>.</exception>
/// <exception cref="InsufficientDataException">There are fewer data points than fit parameters.</exception>
/// <exception cref="DivideByZeroException">The curvature matrix is singular, indicating that the data is independent of
/// one or more parameters, or that two or more parameters are linearly dependent.</exception>
public FitResult FitToFunction (Func<double[], T, double> function, double[] start) {
if (function == null) throw new ArgumentNullException("function");
if (start == null) throw new ArgumentNullException("start");
if (function == null) throw new ArgumentNullException(nameof(function));
if (start == null) throw new ArgumentNullException(nameof(start));

// you can't do a fit with less data than parameters
if (this.Count < start.Length) throw new InsufficientDataException();
Expand All @@ -201,6 +203,7 @@ public FitResult FitToFunction (Func<double[], T, double> function, double[] sta
// compute the covariance (Hessian) matrix by inverting the curvature matrix
SymmetricMatrix A = 0.5 * minimum.Curvature();
CholeskyDecomposition CD = A.CholeskyDecomposition(); // should not return null if we were at a minimum
if (CD == null) throw new DivideByZeroException();
SymmetricMatrix C = CD.Inverse();

// package up the results and return them
Expand Down Expand Up @@ -228,7 +231,7 @@ bool ICollection<UncertainMeasurement<T>>.IsReadOnly {
}

void ICollection<UncertainMeasurement<T>>.CopyTo (UncertainMeasurement<T>[] array, int offset) {
if (array == null) throw new ArgumentNullException("array");
if (array == null) throw new ArgumentNullException(nameof(array));
data.CopyTo(array, offset);
}

Expand Down Expand Up @@ -262,7 +265,7 @@ public UncertainMeasurementSample ()
/// <param name="data">An enumerator over the <see cref="UncertainMeasurement{Double}" />s to place in the set.</param>
public UncertainMeasurementSample (IEnumerable<UncertainMeasurement<double>> data)
: base() {
if (data == null) throw new ArgumentNullException("data");
if (data == null) throw new ArgumentNullException(nameof(data));
foreach (UncertainMeasurement<double> datum in data) {
Add(datum);
}
Expand All @@ -273,6 +276,7 @@ public UncertainMeasurementSample (IEnumerable<UncertainMeasurement<double>> dat
/// </summary>
/// <returns>A fit result containing the best combined value and a &#x3C7;<sup>2</sup> test of the quality of the fit.</returns>
/// <remarks><para>This method provides a simple way to </para></remarks>
/// <exception cref="InsufficientDataException">There are fewer than one data points.</exception>
public FitResult FitToConstant () {

if (Count < 1) throw new InsufficientDataException();
Expand Down Expand Up @@ -310,6 +314,7 @@ public FitResult FitToConstant () {
/// </summary>
/// <returns>A fit result containing the best-fit proportionality constant parameter and a &#x3C7;<sup>2</sup> test of the
/// quality of the fit.</returns>
/// <exception cref="InsufficientDataException">There are fewer than one data points.</exception>
public FitResult FitToProportionality () {

if (Count < 1) throw new InsufficientDataException();
Expand Down Expand Up @@ -350,6 +355,7 @@ public FitResult FitToProportionality () {
/// </summary>
/// <returns>A fit result containing the best-fit intercept and slope parameters and a &#x3C7;<sup>2</sup> test of
/// the quality of the fit.</returns>
/// <exception cref="InsufficientDataException">There are fewer than two data points.</exception>
public FitResult FitToLine () {

if (Count < 2) throw new InsufficientDataException();
Expand Down Expand Up @@ -404,11 +410,12 @@ public FitResult FitToLine () {
/// <param name="order">The order of the polynomial to fit.</param>
/// <returns>A fit result containg the best-fit polynomial coefficients, in order of ascending power from 0 to <paramref name="order"/>,
/// and a &#x3C7;<sup>2</sup> test of the quality of the fit.</returns>
/// <exception cref="InvalidOperationException">There are more polynomial coefficients than data points.</exception>
/// <exception cref="ArgumentOutOfRangeException"><paramref name="order"/> is negative.</exception>
/// <exception cref="InsufficientDataException">There are more polynomial coefficients than data points.</exception>
public FitResult FitToPolynomial (int order) {

if (order < 0) throw new ArgumentOutOfRangeException("order");
if (Count < order) throw new InvalidOperationException();
if (order < 0) throw new ArgumentOutOfRangeException(nameof(order));
if (Count < order) throw new InsufficientDataException();

// create the functions
Func<double, double>[] functions = new Func<double, double>[order + 1];
Expand Down

0 comments on commit 80c1d43

Please sign in to comment.