Author: erans
Date: Thu Aug 16 20:43:59 2012
New Revision: 1374046
URL: http://svn.apache.org/viewvc?rev=1374046&view=rev
Log:
MATH-844
Generate an exception when the parameter guessing procedure cannot perform
correctly (in rare ill-conditioned cases).
Modified:
commons/proper/math/trunk/src/changes/changes.xml
commons/proper/math/trunk/src/main/java/org/apache/commons/math3/exception/util/LocalizedFormats.java
commons/proper/math/trunk/src/main/java/org/apache/commons/math3/optimization/fitting/HarmonicFitter.java
commons/proper/math/trunk/src/test/java/org/apache/commons/math3/optimization/fitting/HarmonicFitterTest.java
Modified: commons/proper/math/trunk/src/changes/changes.xml
URL:
http://svn.apache.org/viewvc/commons/proper/math/trunk/src/changes/changes.xml?rev=1374046&r1=1374045&r2=1374046&view=diff
==============================================================================
--- commons/proper/math/trunk/src/changes/changes.xml (original)
+++ commons/proper/math/trunk/src/changes/changes.xml Thu Aug 16 20:43:59 2012
@@ -52,6 +52,10 @@ If the output is not quite correct, chec
<body>
<release version="3.1" date="TBD" description="
">
+ <action dev="erans" type="fix" issue="MATH-844">
+ Generate an exception for rare ill-conditioned cases in
"HarmonicFitter"
+ guessing procedure (package "o.a.c.m.optimization.fitting").
+ </action>
<action dev="erans" type="add" issue="MATH-815" due-to="Jared Becksfort">
New interface for multivariate distributions.
Added multivariate normal distribution.
Modified:
commons/proper/math/trunk/src/main/java/org/apache/commons/math3/exception/util/LocalizedFormats.java
URL:
http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math3/exception/util/LocalizedFormats.java?rev=1374046&r1=1374045&r2=1374046&view=diff
==============================================================================
---
commons/proper/math/trunk/src/main/java/org/apache/commons/math3/exception/util/LocalizedFormats.java
(original)
+++
commons/proper/math/trunk/src/main/java/org/apache/commons/math3/exception/util/LocalizedFormats.java
Thu Aug 16 20:43:59 2012
@@ -344,7 +344,7 @@ public enum LocalizedFormats implements
WRONG_BLOCK_LENGTH("wrong array shape (block length = {0}, expected {1})"),
WRONG_NUMBER_OF_POINTS("{0} points are required, got only {1}"),
NUMBER_OF_POINTS("number of points ({0})"), /* keep */
- ZERO_DENOMINATOR("denominator must be different from 0"),
+ ZERO_DENOMINATOR("denominator must be different from 0"), /* keep */
ZERO_DENOMINATOR_IN_FRACTION("zero denominator in fraction {0}/{1}"),
ZERO_FRACTION_TO_DIVIDE_BY("the fraction to divide by must not be zero:
{0}/{1}"),
ZERO_NORM("zero norm"),
Modified:
commons/proper/math/trunk/src/main/java/org/apache/commons/math3/optimization/fitting/HarmonicFitter.java
URL:
http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math3/optimization/fitting/HarmonicFitter.java?rev=1374046&r1=1374045&r2=1374046&view=diff
==============================================================================
---
commons/proper/math/trunk/src/main/java/org/apache/commons/math3/optimization/fitting/HarmonicFitter.java
(original)
+++
commons/proper/math/trunk/src/main/java/org/apache/commons/math3/optimization/fitting/HarmonicFitter.java
Thu Aug 16 20:43:59 2012
@@ -21,6 +21,7 @@ import org.apache.commons.math3.optimiza
import org.apache.commons.math3.analysis.function.HarmonicOscillator;
import org.apache.commons.math3.exception.ZeroException;
import org.apache.commons.math3.exception.NumberIsTooSmallException;
+import org.apache.commons.math3.exception.MathIllegalStateException;
import org.apache.commons.math3.exception.util.LocalizedFormats;
import org.apache.commons.math3.util.FastMath;
@@ -250,6 +251,8 @@ public class HarmonicFitter extends Curv
* has been called previously.
*
* @throws ZeroException if the abscissa range is zero.
+ * @throws MathIllegalStateException when the guessing procedure cannot
+ * produce sensible results.
*/
private void guessAOmega() {
// initialize the sums for the linear model between the two
integrals
@@ -317,6 +320,12 @@ public class HarmonicFitter extends Curv
}
a = 0.5 * (yMax - yMin);
} else {
+ if (c2 == 0) {
+ // In some ill-conditioned cases (cf. MATH-844), the
guesser
+ // procedure cannot produce sensible results.
+ throw new
MathIllegalStateException(LocalizedFormats.ZERO_DENOMINATOR);
+ }
+
a = FastMath.sqrt(c1 / c2);
omega = FastMath.sqrt(c2 / c3);
}
Modified:
commons/proper/math/trunk/src/test/java/org/apache/commons/math3/optimization/fitting/HarmonicFitterTest.java
URL:
http://svn.apache.org/viewvc/commons/proper/math/trunk/src/test/java/org/apache/commons/math3/optimization/fitting/HarmonicFitterTest.java?rev=1374046&r1=1374045&r2=1374046&view=diff
==============================================================================
---
commons/proper/math/trunk/src/test/java/org/apache/commons/math3/optimization/fitting/HarmonicFitterTest.java
(original)
+++
commons/proper/math/trunk/src/test/java/org/apache/commons/math3/optimization/fitting/HarmonicFitterTest.java
Thu Aug 16 20:43:59 2012
@@ -22,6 +22,7 @@ import java.util.Random;
import org.apache.commons.math3.analysis.function.HarmonicOscillator;
import
org.apache.commons.math3.optimization.general.LevenbergMarquardtOptimizer;
import org.apache.commons.math3.exception.NumberIsTooSmallException;
+import org.apache.commons.math3.exception.MathIllegalStateException;
import org.apache.commons.math3.util.FastMath;
import org.apache.commons.math3.util.MathUtils;
@@ -176,4 +177,28 @@ public class HarmonicFitterTest {
Assert.assertEquals(w, fitted[1], 3.5e-3);
Assert.assertEquals(p, MathUtils.normalizeAngle(fitted[2], p), 1.5e-2);
}
+
+ @Test(expected=MathIllegalStateException.class)
+ public void testMath844() {
+ final double[] y = { 0, 1, 2, 3, 2, 1,
+ 0, -1, -2, -3, -2, -1,
+ 0, 1, 2, 3, 2, 1,
+ 0, -1, -2, -3, -2, -1,
+ 0, 1, 2, 3, 2, 1, 0 };
+ final int len = y.length;
+ final WeightedObservedPoint[] points = new WeightedObservedPoint[len];
+ for (int i = 0; i < len; i++) {
+ points[i] = new WeightedObservedPoint(1, i, y[i]);
+ }
+
+ final HarmonicFitter.ParameterGuesser guesser
+ = new HarmonicFitter.ParameterGuesser(points);
+
+ // The guesser fails because the function is far from an harmonic
+ // function: It is a triangular periodic function with amplitude 3
+ // and period 12, and all sample points are taken at integer abscissae
+ // so function values all belong to the integer subset {-3, -2, -1, 0,
+ // 1, 2, 3}.
+ guesser.guess();
+ }
}