Skip to content

Commit 80c1d43

Browse files
committed
Documentation and throw DivideByZeroException to fits with indeterminate parameters.
1 parent 70c2833 commit 80c1d43

File tree

4 files changed

+27
-14
lines changed

4 files changed

+27
-14
lines changed

Numerics/Matrices/SymmetricMatrix.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ public SymmetricMatrix Inverse () {
139139
}
140140

141141
/// <summary>
142-
/// Returns the Cholesky decomposition of the matrix.
142+
/// Computes the Cholesky decomposition of the matrix.
143143
/// </summary>
144144
/// <returns>The Cholesky decomposition of the matrix, or null if the matrix is not positive definite.</returns>
145145
/// <remarks>

Numerics/Meta.Numerics.nuspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<package>
33
<metadata>
44
<id>Meta.Numerics</id>
5-
<version>3.0.0</version>
5+
<version>3.1.0</version>
66
<authors>David Wright</authors>
77
<description>A library for numeric computing with support for statistics, matrix algebra, and advanced functions.</description>
88
<projectUrl>http://www.meta-numerics.net</projectUrl>

Numerics/Statistics/MultivariateSample.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -500,6 +500,8 @@ private FitResult LinearRegression_Internal (int outputIndex) {
500500
/// </remarks>
501501
/// <exception cref="ArgumentOutOfRangeException"><paramref name="outputIndex"/> is outside the range of allowed indexes.</exception>
502502
/// <exception cref="InsufficientDataException">There are fewer entries than the dimension of the multivariate sample.</exception>
503+
/// <exception cref="DivideByZeroException">The curvature matrix is singular, indicating that the data is independent of
504+
/// one or more parameters, or that two or more parameters are linearly dependent.</exception>
503505
/// <seealso cref="LinearRegression(int)"/>
504506
/// <seealso href="http://en.wikipedia.org/wiki/Linear_regression"/>
505507
public FitResult LinearRegression (int outputIndex) {
@@ -524,6 +526,8 @@ public FitResult LinearRegression (int outputIndex) {
524526
/// for the output variable.</remarks>
525527
/// <exception cref="InvalidOperationException">The column to be predicted contains values other than 0 and 1.</exception>
526528
/// <exception cref="InsufficientDataException">There are not more rows in the sample than columns.</exception>
529+
/// <exception cref="DivideByZeroException">The curvature matrix is singular, indicating that the data is independent of
530+
/// one or more parameters, or that two or more parameters are linearly dependent.</exception>
527531
public FitResult LogisticLinearRegression (int outputIndex) {
528532

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

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

566-
FitResult result = new FitResult(maximum.Location, maximum.HessianMatrix.CholeskyDecomposition().Inverse(), null);
572+
FitResult result = new FitResult(maximum.Location, CD.Inverse(), null);
567573

568574
return (result);
569575

Numerics/Statistics/UncertainMeasurementSample.cs

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ public UncertainMeasurementSample () {
2929
/// </summary>
3030
/// <param name="datum">The data point.</param>
3131
public void Add (UncertainMeasurement<T> datum) {
32-
if (datum == null) throw new ArgumentNullException("datum");
32+
if (datum == null) throw new ArgumentNullException(nameof(datum));
3333
data.Add(datum);
3434
}
3535

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

103-
if (functions == null) throw new ArgumentNullException("functions");
103+
if (functions == null) throw new ArgumentNullException(nameof(functions));
104104
if (functions.Length > data.Count) throw new InsufficientDataException();
105105

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

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

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

230233
void ICollection<UncertainMeasurement<T>>.CopyTo (UncertainMeasurement<T>[] array, int offset) {
231-
if (array == null) throw new ArgumentNullException("array");
234+
if (array == null) throw new ArgumentNullException(nameof(array));
232235
data.CopyTo(array, offset);
233236
}
234237

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

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

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

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

410-
if (order < 0) throw new ArgumentOutOfRangeException("order");
411-
if (Count < order) throw new InvalidOperationException();
417+
if (order < 0) throw new ArgumentOutOfRangeException(nameof(order));
418+
if (Count < order) throw new InsufficientDataException();
412419

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

0 commit comments

Comments
 (0)