Author: erans
Date: Sat Aug 6 22:26:55 2011
New Revision: 1154614
URL: http://svn.apache.org/viewvc?rev=1154614&view=rev
Log:
MATH-631
Work around infinite loop.
Modified:
commons/proper/math/trunk/src/main/java/org/apache/commons/math/analysis/solvers/BaseSecantSolver.java
commons/proper/math/trunk/src/test/java/org/apache/commons/math/analysis/solvers/RegulaFalsiSolverTest.java
Modified: commons/proper/math/trunk/src/main/java/org/apache/commons/math/analysis/solvers/BaseSecantSolver.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math/analysis/solvers/BaseSecantSolver.java?rev=1154614&r1=1154613&r2=1154614&view=diff
==============================================================================
--- commons/proper/math/trunk/src/main/java/org/apache/commons/math/analysis/solvers/BaseSecantSolver.java
(original)
+++ commons/proper/math/trunk/src/main/java/org/apache/commons/math/analysis/solvers/BaseSecantSolver.java
Sat Aug 6 22:26:55 2011
@@ -169,25 +169,37 @@ public abstract class BaseSecantSolver
// Update the bounds with the new approximation.
if (f1 * fx < 0) {
- // We had [x0..x1]. We update it to [x1, x]. Note that the
- // value of x1 has switched to the other bound, thus inverting
+ // The value of x1 has switched to the other bound, thus inverting
// the interval.
x0 = x1;
f0 = f1;
- x1 = x;
- f1 = fx;
inverted = !inverted;
} else {
- // We had [x0..x1]. We update it to [x0, x].
- if (method == Method.ILLINOIS) {
+ switch (method) {
+ case ILLINOIS:
f0 *= 0.5;
- }
- if (method == Method.PEGASUS) {
+ break;
+ case PEGASUS:
f0 *= f1 / (f1 + fx);
+ break;
+ case REGULA_FALSI:
+ if (x == x1) {
+ final double delta = FastMath.max(rtol * FastMath.abs(x1),
+ atol);
+ // Update formula cannot make any progress: Update the
+ // search interval.
+ x0 = 0.5 * (x0 + x1 - delta);
+ f0 = computeObjectiveValue(x0);
+ }
+ break;
+ default:
+ // Should never happen.
+ throw new MathInternalError();
}
- x1 = x;
- f1 = fx;
}
+ // Update from [x0, x1] to [x0, x].
+ x1 = x;
+ f1 = fx;
// If the function value of the last approximation is too small,
// given the function value accuracy, then we can't get closer to
Modified: commons/proper/math/trunk/src/test/java/org/apache/commons/math/analysis/solvers/RegulaFalsiSolverTest.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/test/java/org/apache/commons/math/analysis/solvers/RegulaFalsiSolverTest.java?rev=1154614&r1=1154613&r2=1154614&view=diff
==============================================================================
--- commons/proper/math/trunk/src/test/java/org/apache/commons/math/analysis/solvers/RegulaFalsiSolverTest.java
(original)
+++ commons/proper/math/trunk/src/test/java/org/apache/commons/math/analysis/solvers/RegulaFalsiSolverTest.java
Sat Aug 6 22:26:55 2011
@@ -17,6 +17,10 @@
package org.apache.commons.math.analysis.solvers;
+import org.apache.commons.math.analysis.UnivariateRealFunction;
+import org.junit.Test;
+import org.junit.Assert;
+
/**
* Test case for {@link RegulaFalsiSolver Regula Falsi} solver.
*
@@ -35,4 +39,18 @@ public final class RegulaFalsiSolverTest
// even a million iterations. As such, it was disabled.
return new int[] {3, 7, 8, 19, 18, 11, 67, 55, 288, 151, -1};
}
+
+ @Test
+ public void testIssue631() {
+ final UnivariateRealFunction f = new UnivariateRealFunction() {
+ @Override
+ public double value(double x) {
+ return Math.exp(x) - Math.pow(Math.PI, 3.0);
+ }
+ };
+
+ final UnivariateRealSolver solver = new RegulaFalsiSolver();
+ final double root = solver.solve(3624, f, 1, 10);
+ Assert.assertEquals(3.4341896575482003, root, 1e-15);
+ }
}
|