Author: erans Date: Wed Jul 4 18:00:02 2012 New Revision: 1357353 URL: http://svn.apache.org/viewvc?rev=1357353&view=rev Log: MATH-798 Added overridden "fit" method where one can specify the maximum number of function evaluations.
Modified: commons/proper/math/trunk/src/changes/changes.xml commons/proper/math/trunk/src/main/java/org/apache/commons/math3/optimization/fitting/PolynomialFitter.java commons/proper/math/trunk/src/test/java/org/apache/commons/math3/optimization/fitting/CurveFitterTest.java commons/proper/math/trunk/src/test/java/org/apache/commons/math3/optimization/fitting/PolynomialFitterTest.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=1357353&r1=1357352&r2=1357353&view=diff ============================================================================== --- commons/proper/math/trunk/src/changes/changes.xml (original) +++ commons/proper/math/trunk/src/changes/changes.xml Wed Jul 4 18:00:02 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-798"> + Added overridden method in "PolynomialFitter" (package + "o.a.c.m.optimization.fitting") to limit the number of evaluations. + </action> <action dev="celestin" type="add" issue="MATH-807"> Added a new constructor to o.a.c.m.utils.IterationManager, allowing for the specification of a callback function in case the maximum Modified: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/optimization/fitting/PolynomialFitter.java URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math3/optimization/fitting/PolynomialFitter.java?rev=1357353&r1=1357352&r2=1357353&view=diff ============================================================================== --- commons/proper/math/trunk/src/main/java/org/apache/commons/math3/optimization/fitting/PolynomialFitter.java (original) +++ commons/proper/math/trunk/src/main/java/org/apache/commons/math3/optimization/fitting/PolynomialFitter.java Wed Jul 4 18:00:02 2012 @@ -77,6 +77,23 @@ public class PolynomialFitter extends Cu * * @param guess First guess for the coefficients. They must be sorted in * increasing order of the polynomial's degree. + * @param maxEval Maximum number of evaluations of the polynomial. + * @return the coefficients of the polynomial that best fits the observed points. + * @throws org.apache.commons.math3.exception.TooManyEvaluationsException if + * the number of evaluations exceeds {@code maxEval}. + * @throws org.apache.commons.math3.exception.ConvergenceException + * if the algorithm failed to converge. + */ + public double[] fit(int maxEval, double[] guess) { + return fit(maxEval, new PolynomialFunction.Parametric(), guess); + } + + /** + * Get the coefficients of the polynomial fitting the weighted data points. + * The degree of the fitting polynomial is {@code guess.length - 1}. + * + * @param guess First guess for the coefficients. They must be sorted in + * increasing order of the polynomial's degree. * @return the coefficients of the polynomial that best fits the observed points. * @throws org.apache.commons.math3.exception.ConvergenceException * if the algorithm failed to converge. Modified: commons/proper/math/trunk/src/test/java/org/apache/commons/math3/optimization/fitting/CurveFitterTest.java URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/test/java/org/apache/commons/math3/optimization/fitting/CurveFitterTest.java?rev=1357353&r1=1357352&r2=1357353&view=diff ============================================================================== --- commons/proper/math/trunk/src/test/java/org/apache/commons/math3/optimization/fitting/CurveFitterTest.java (original) +++ commons/proper/math/trunk/src/test/java/org/apache/commons/math3/optimization/fitting/CurveFitterTest.java Wed Jul 4 18:00:02 2012 @@ -138,69 +138,6 @@ public class CurveFitterTest { } - @Test - public void testMath798() { - final double tol = 1e-14; - final SimpleVectorValueChecker checker = new SimpleVectorValueChecker(tol, tol); - final double[] init = new double[] { 0, 0 }; - final int maxEval = 3; - - final double[] lm = doMath798(new LevenbergMarquardtOptimizer(checker), maxEval, init); - final double[] gn = doMath798(new GaussNewtonOptimizer(checker), maxEval, init); - - for (int i = 0; i <= 1; i++) { - Assert.assertEquals(lm[i], gn[i], tol); - } - } - - /** - * @param optimizer Optimizer. - * @param maxEval Maximum number of function evaluations. - * @param init First guess. - * @return the solution found by the given optimizer. - */ - private double[] doMath798(DifferentiableMultivariateVectorOptimizer optimizer, - int maxEval, - double[] init) { - final CurveFitter fitter = new CurveFitter(optimizer); - - fitter.addObservedPoint(-0.2, -7.12442E-13); - fitter.addObservedPoint(-0.199, -4.33397E-13); - fitter.addObservedPoint(-0.198, -2.823E-13); - fitter.addObservedPoint(-0.197, -1.40405E-13); - fitter.addObservedPoint(-0.196, -7.80821E-15); - fitter.addObservedPoint(-0.195, 6.20484E-14); - fitter.addObservedPoint(-0.194, 7.24673E-14); - fitter.addObservedPoint(-0.193, 1.47152E-13); - fitter.addObservedPoint(-0.192, 1.9629E-13); - fitter.addObservedPoint(-0.191, 2.12038E-13); - fitter.addObservedPoint(-0.19, 2.46906E-13); - fitter.addObservedPoint(-0.189, 2.77495E-13); - fitter.addObservedPoint(-0.188, 2.51281E-13); - fitter.addObservedPoint(-0.187, 2.64001E-13); - fitter.addObservedPoint(-0.186, 2.8882E-13); - fitter.addObservedPoint(-0.185, 3.13604E-13); - fitter.addObservedPoint(-0.184, 3.14248E-13); - fitter.addObservedPoint(-0.183, 3.1172E-13); - fitter.addObservedPoint(-0.182, 3.12912E-13); - fitter.addObservedPoint(-0.181, 3.06761E-13); - fitter.addObservedPoint(-0.18, 2.8559E-13); - fitter.addObservedPoint(-0.179, 2.86806E-13); - fitter.addObservedPoint(-0.178, 2.985E-13); - fitter.addObservedPoint(-0.177, 2.67148E-13); - fitter.addObservedPoint(-0.176, 2.94173E-13); - fitter.addObservedPoint(-0.175, 3.27528E-13); - fitter.addObservedPoint(-0.174, 3.33858E-13); - fitter.addObservedPoint(-0.173, 2.97511E-13); - fitter.addObservedPoint(-0.172, 2.8615E-13); - fitter.addObservedPoint(-0.171, 2.84624E-13); - - final double[] coeff = fitter.fit(maxEval, - new PolynomialFunction.Parametric(), - init); - return coeff; - } - private static class SimpleInverseFunction implements ParametricUnivariateFunction { public double value(double x, double ... parameters) { Modified: commons/proper/math/trunk/src/test/java/org/apache/commons/math3/optimization/fitting/PolynomialFitterTest.java URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/test/java/org/apache/commons/math3/optimization/fitting/PolynomialFitterTest.java?rev=1357353&r1=1357352&r2=1357353&view=diff ============================================================================== --- commons/proper/math/trunk/src/test/java/org/apache/commons/math3/optimization/fitting/PolynomialFitterTest.java (original) +++ commons/proper/math/trunk/src/test/java/org/apache/commons/math3/optimization/fitting/PolynomialFitterTest.java Wed Jul 4 18:00:02 2012 @@ -21,6 +21,7 @@ import java.util.Random; import org.apache.commons.math3.analysis.polynomials.PolynomialFunction; import org.apache.commons.math3.exception.ConvergenceException; +import org.apache.commons.math3.exception.TooManyEvaluationsException; import org.apache.commons.math3.optimization.DifferentiableMultivariateVectorOptimizer; import org.apache.commons.math3.optimization.general.GaussNewtonOptimizer; import org.apache.commons.math3.optimization.general.LevenbergMarquardtOptimizer; @@ -108,6 +109,90 @@ public class PolynomialFitterTest { } @Test + public void testMath798() { + final double tol = 1e-14; + final SimpleVectorValueChecker checker = new SimpleVectorValueChecker(tol, tol); + final double[] init = new double[] { 0, 0 }; + final int maxEval = 3; + + final double[] lm = doMath798(new LevenbergMarquardtOptimizer(checker), maxEval, init); + final double[] gn = doMath798(new GaussNewtonOptimizer(checker), maxEval, init); + + for (int i = 0; i <= 1; i++) { + Assert.assertEquals(lm[i], gn[i], tol); + } + } + + /** + * This test shows that the user can set the maximum number of iterations + * to avoid running for too long. + * But in the test case, the real problem is that the tolerance is way too + * stringent. + */ + @Test(expected=TooManyEvaluationsException.class) + public void testMath798WithToleranceTooLow() { + final double tol = 1e-100; + final SimpleVectorValueChecker checker = new SimpleVectorValueChecker(tol, tol); + final double[] init = new double[] { 0, 0 }; + final int maxEval = 10000; // Trying hard to fit. + + final double[] lm = doMath798(new LevenbergMarquardtOptimizer(checker), maxEval, init); + final double[] gn = doMath798(new GaussNewtonOptimizer(checker), maxEval, init); + + for (int i = 0; i <= 1; i++) { + Assert.assertEquals(lm[i], gn[i], tol); + } + } + + /** + * @param optimizer Optimizer. + * @param maxEval Maximum number of function evaluations. + * @param init First guess. + * @return the solution found by the given optimizer. + */ + private double[] doMath798(DifferentiableMultivariateVectorOptimizer optimizer, + int maxEval, + double[] init) { + final CurveFitter fitter = new CurveFitter(optimizer); + + fitter.addObservedPoint(-0.2, -7.12442E-13); + fitter.addObservedPoint(-0.199, -4.33397E-13); + fitter.addObservedPoint(-0.198, -2.823E-13); + fitter.addObservedPoint(-0.197, -1.40405E-13); + fitter.addObservedPoint(-0.196, -7.80821E-15); + fitter.addObservedPoint(-0.195, 6.20484E-14); + fitter.addObservedPoint(-0.194, 7.24673E-14); + fitter.addObservedPoint(-0.193, 1.47152E-13); + fitter.addObservedPoint(-0.192, 1.9629E-13); + fitter.addObservedPoint(-0.191, 2.12038E-13); + fitter.addObservedPoint(-0.19, 2.46906E-13); + fitter.addObservedPoint(-0.189, 2.77495E-13); + fitter.addObservedPoint(-0.188, 2.51281E-13); + fitter.addObservedPoint(-0.187, 2.64001E-13); + fitter.addObservedPoint(-0.186, 2.8882E-13); + fitter.addObservedPoint(-0.185, 3.13604E-13); + fitter.addObservedPoint(-0.184, 3.14248E-13); + fitter.addObservedPoint(-0.183, 3.1172E-13); + fitter.addObservedPoint(-0.182, 3.12912E-13); + fitter.addObservedPoint(-0.181, 3.06761E-13); + fitter.addObservedPoint(-0.18, 2.8559E-13); + fitter.addObservedPoint(-0.179, 2.86806E-13); + fitter.addObservedPoint(-0.178, 2.985E-13); + fitter.addObservedPoint(-0.177, 2.67148E-13); + fitter.addObservedPoint(-0.176, 2.94173E-13); + fitter.addObservedPoint(-0.175, 3.27528E-13); + fitter.addObservedPoint(-0.174, 3.33858E-13); + fitter.addObservedPoint(-0.173, 2.97511E-13); + fitter.addObservedPoint(-0.172, 2.8615E-13); + fitter.addObservedPoint(-0.171, 2.84624E-13); + + final double[] coeff = fitter.fit(maxEval, + new PolynomialFunction.Parametric(), + init); + return coeff; + } + + @Test public void testRedundantSolvable() { // Levenberg-Marquardt should handle redundant information gracefully checkUnsolvableProblem(new LevenbergMarquardtOptimizer(), true);