You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by er...@apache.org on 2011/02/23 16:52:38 UTC

svn commit: r1073796 - in /commons/proper/math/trunk/src: main/java/org/apache/commons/math/optimization/fitting/HarmonicFitter.java test/java/org/apache/commons/math/optimization/fitting/HarmonicFitterTest.java

Author: erans
Date: Wed Feb 23 15:52:38 2011
New Revision: 1073796

URL: http://svn.apache.org/viewvc?rev=1073796&view=rev
Log:
MATH-521
Changed initial guess default values.
Added test.

Modified:
    commons/proper/math/trunk/src/main/java/org/apache/commons/math/optimization/fitting/HarmonicFitter.java
    commons/proper/math/trunk/src/test/java/org/apache/commons/math/optimization/fitting/HarmonicFitterTest.java

Modified: commons/proper/math/trunk/src/main/java/org/apache/commons/math/optimization/fitting/HarmonicFitter.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math/optimization/fitting/HarmonicFitter.java?rev=1073796&r1=1073795&r2=1073796&view=diff
==============================================================================
--- commons/proper/math/trunk/src/main/java/org/apache/commons/math/optimization/fitting/HarmonicFitter.java (original)
+++ commons/proper/math/trunk/src/main/java/org/apache/commons/math/optimization/fitting/HarmonicFitter.java Wed Feb 23 15:52:38 2011
@@ -295,17 +295,27 @@ public class HarmonicFitter extends Curv
             double c2 = sxy * sxz - sx2 * syz;
             double c3 = sx2 * sy2 - sxy * sxy;
             if ((c1 / c2 < 0) || (c2 / c3 < 0)) {
-                a = 0;
-
+                final int last = observations.length - 1;
                 // Range of the observations, assuming that the
                 // observations are sorted.
-                final double range = observations[observations.length - 1].getX() -
-                    observations[0].getX();
-
-                if (range == 0) {
+                final double xRange = observations[last].getX() - observations[0].getX();
+                if (xRange == 0) {
                     throw new ZeroException();
                 }
-                omega = 2 * Math.PI / range;
+                omega = 2 * Math.PI / xRange;
+
+                double yMin = Double.POSITIVE_INFINITY;
+                double yMax = Double.NEGATIVE_INFINITY;
+                for (int i = 1; i < observations.length; ++i) {
+                    final double y = observations[i].getY();
+                    if (y < yMin) {
+                        yMin = y;
+                    }
+                    if (y > yMax) {
+                        yMax = y;
+                    }
+                }
+                a = 0.5 * (yMax - yMin);
             } else {
                 a = FastMath.sqrt(c1 / c2);
                 omega = FastMath.sqrt(c2 / c3);

Modified: commons/proper/math/trunk/src/test/java/org/apache/commons/math/optimization/fitting/HarmonicFitterTest.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/test/java/org/apache/commons/math/optimization/fitting/HarmonicFitterTest.java?rev=1073796&r1=1073795&r2=1073796&view=diff
==============================================================================
--- commons/proper/math/trunk/src/test/java/org/apache/commons/math/optimization/fitting/HarmonicFitterTest.java (original)
+++ commons/proper/math/trunk/src/test/java/org/apache/commons/math/optimization/fitting/HarmonicFitterTest.java Wed Feb 23 15:52:38 2011
@@ -17,18 +17,41 @@
 
 package org.apache.commons.math.optimization.fitting;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
 import java.util.Random;
 
 import org.apache.commons.math.analysis.function.HarmonicOscillator;
 import org.apache.commons.math.optimization.general.LevenbergMarquardtOptimizer;
+import org.apache.commons.math.exception.NumberIsTooSmallException;
+import org.apache.commons.math.exception.ZeroException;
 import org.apache.commons.math.util.FastMath;
 import org.apache.commons.math.util.MathUtils;
+
 import org.junit.Test;
+import org.junit.Assert;
 
 public class HarmonicFitterTest {
+    @Test(expected=NumberIsTooSmallException.class)
+    public void testPreconditions1() {
+        HarmonicFitter fitter =
+            new HarmonicFitter(new LevenbergMarquardtOptimizer());
+
+        final double[] fitted = fitter.fit();
+    }
+
+    // This test fails (throwing "ConvergenceException" instead).
+//     @Test(expected=ZeroException.class)
+//     public void testPreconditions2() {
+//         HarmonicFitter fitter =
+//             new HarmonicFitter(new LevenbergMarquardtOptimizer());
+
+//         final double x = 1.2;
+//         fitter.addObservedPoint(1, x, 1);
+//         fitter.addObservedPoint(1, x, -1);
+//         fitter.addObservedPoint(1, x, 0.5);
+//         fitter.addObservedPoint(1, x, 0);
+
+//         final double[] fitted = fitter.fit();
+//     }
 
     @Test
     public void testNoError() {
@@ -44,14 +67,14 @@ public class HarmonicFitterTest {
         }
 
         final double[] fitted = fitter.fit();
-        assertEquals(a, fitted[0], 1.0e-13);
-        assertEquals(w, fitted[1], 1.0e-13);
-        assertEquals(p, MathUtils.normalizeAngle(fitted[2], p), 1e-13);
+        Assert.assertEquals(a, fitted[0], 1.0e-13);
+        Assert.assertEquals(w, fitted[1], 1.0e-13);
+        Assert.assertEquals(p, MathUtils.normalizeAngle(fitted[2], p), 1e-13);
 
         HarmonicOscillator ff = new HarmonicOscillator(fitted[0], fitted[1], fitted[2]);
 
         for (double x = -1.0; x < 1.0; x += 0.01) {
-            assertTrue(FastMath.abs(f.value(x) - ff.value(x)) < 1e-13);
+            Assert.assertTrue(FastMath.abs(f.value(x) - ff.value(x)) < 1e-13);
         }
     }
 
@@ -67,14 +90,28 @@ public class HarmonicFitterTest {
             new HarmonicFitter(new LevenbergMarquardtOptimizer());
         for (double x = 0.0; x < 10.0; x += 0.1) {
             fitter.addObservedPoint(1, x,
-                                   f.value(x) + 0.01 * randomizer.nextGaussian());
+                                    f.value(x) + 0.01 * randomizer.nextGaussian());
         }
 
         final double[] fitted = fitter.fit();
-        assertEquals(a, fitted[0], 7.6e-4);
-        assertEquals(w, fitted[1], 2.7e-3);
-        assertEquals(p, MathUtils.normalizeAngle(fitted[2], p), 1.3e-2);
+        Assert.assertEquals(a, fitted[0], 7.6e-4);
+        Assert.assertEquals(w, fitted[1], 2.7e-3);
+        Assert.assertEquals(p, MathUtils.normalizeAngle(fitted[2], p), 1.3e-2);
+    }
 
+    @Test
+    public void testTinyVariationsData() {
+        Random randomizer = new Random(64925784252l);
+
+        HarmonicFitter fitter =
+            new HarmonicFitter(new LevenbergMarquardtOptimizer());
+        for (double x = 0.0; x < 10.0; x += 0.1) {
+            fitter.addObservedPoint(1, x, 1e-7 * randomizer.nextGaussian());
+        }
+
+        final double[] fitted = fitter.fit();
+        // This test serves to cover the part of the code of "guessAOmega"
+        // when the algorithm using integrals fails.
     }
 
     @Test
@@ -89,13 +126,13 @@ public class HarmonicFitterTest {
             new HarmonicFitter(new LevenbergMarquardtOptimizer());
         for (double x = 0.0; x < 10.0; x += 0.1) {
             fitter.addObservedPoint(1, x,
-                                   f.value(x) + 0.01 * randomizer.nextGaussian());
+                                    f.value(x) + 0.01 * randomizer.nextGaussian());
         }
 
         final double[] fitted = fitter.fit(new double[] { 0.15, 3.6, 4.5 });
-        assertEquals(a, fitted[0], 1.2e-3);
-        assertEquals(w, fitted[1], 3.3e-3);
-        assertEquals(p, MathUtils.normalizeAngle(fitted[2], p), 1.7e-2);
+        Assert.assertEquals(a, fitted[0], 1.2e-3);
+        Assert.assertEquals(w, fitted[1], 3.3e-3);
+        Assert.assertEquals(p, MathUtils.normalizeAngle(fitted[2], p), 1.7e-2);
     }
 
     @Test
@@ -136,8 +173,8 @@ public class HarmonicFitterTest {
         }
 
         final double[] fitted = fitter.fit();
-        assertEquals(a, fitted[0], 7.6e-4);
-        assertEquals(w, fitted[1], 3.5e-3);
-        assertEquals(p, MathUtils.normalizeAngle(fitted[2], p), 1.5e-2);
+        Assert.assertEquals(a, fitted[0], 7.6e-4);
+        Assert.assertEquals(w, fitted[1], 3.5e-3);
+        Assert.assertEquals(p, MathUtils.normalizeAngle(fitted[2], p), 1.5e-2);
     }
 }