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 2013/08/10 01:21:15 UTC

svn commit: r1512530 - in /commons/proper/math/trunk/src: main/java/org/apache/commons/math3/fitting/leastsquares/ main/java/org/apache/commons/math3/optim/ test/java/org/apache/commons/math3/fitting/leastsquares/

Author: erans
Date: Fri Aug  9 23:21:14 2013
New Revision: 1512530

URL: http://svn.apache.org/r1512530
Log:
MATH-1008
Simplification of the code introduced in revision 1508481. The changes
only focus on the "fluent API" aspect (rather than also try to achieve
thread-safety through immutability).
Class "AbstractOptimizer" introduced to serve as the base class for all
optimizers (i.e. replace the current "BaseOptimizer").

Added:
    commons/proper/math/trunk/src/main/java/org/apache/commons/math3/optim/AbstractOptimizer.java   (with props)
Modified:
    commons/proper/math/trunk/src/main/java/org/apache/commons/math3/fitting/leastsquares/AbstractLeastSquaresOptimizer.java
    commons/proper/math/trunk/src/main/java/org/apache/commons/math3/fitting/leastsquares/GaussNewtonOptimizer.java
    commons/proper/math/trunk/src/main/java/org/apache/commons/math3/fitting/leastsquares/LevenbergMarquardtOptimizer.java
    commons/proper/math/trunk/src/main/java/org/apache/commons/math3/fitting/leastsquares/WithConvergenceChecker.java
    commons/proper/math/trunk/src/test/java/org/apache/commons/math3/fitting/leastsquares/AbstractLeastSquaresOptimizerAbstractTest.java
    commons/proper/math/trunk/src/test/java/org/apache/commons/math3/fitting/leastsquares/LevenbergMarquardtOptimizerTest.java
    commons/proper/math/trunk/src/test/java/org/apache/commons/math3/fitting/leastsquares/MinpackTest.java

Modified: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/fitting/leastsquares/AbstractLeastSquaresOptimizer.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math3/fitting/leastsquares/AbstractLeastSquaresOptimizer.java?rev=1512530&r1=1512529&r2=1512530&view=diff
==============================================================================
--- commons/proper/math/trunk/src/main/java/org/apache/commons/math3/fitting/leastsquares/AbstractLeastSquaresOptimizer.java (original)
+++ commons/proper/math/trunk/src/main/java/org/apache/commons/math3/fitting/leastsquares/AbstractLeastSquaresOptimizer.java Fri Aug  9 23:21:14 2013
@@ -17,7 +17,6 @@
 package org.apache.commons.math3.fitting.leastsquares;
 
 import org.apache.commons.math3.exception.DimensionMismatchException;
-import org.apache.commons.math3.exception.MathUnsupportedOperationException;
 import org.apache.commons.math3.analysis.MultivariateVectorFunction;
 import org.apache.commons.math3.analysis.MultivariateMatrixFunction;
 import org.apache.commons.math3.linear.ArrayRealVector;
@@ -27,71 +26,82 @@ import org.apache.commons.math3.linear.D
 import org.apache.commons.math3.linear.MatrixUtils;
 import org.apache.commons.math3.linear.QRDecomposition;
 import org.apache.commons.math3.linear.EigenDecomposition;
-import org.apache.commons.math3.optim.ConvergenceChecker;
-import org.apache.commons.math3.optim.BaseOptimizer;
+import org.apache.commons.math3.optim.AbstractOptimizer;
 import org.apache.commons.math3.optim.PointVectorValuePair;
-import org.apache.commons.math3.optim.OptimizationData;
 import org.apache.commons.math3.util.FastMath;
 
 /**
  * Base class for implementing least-squares optimizers.
  * It provides methods for error estimation.
  *
+ * @param <OPTIM> Concrete optimizer.
+ *
  * @version $Id$
  * @since 3.3
  */
-public abstract class AbstractLeastSquaresOptimizer
-    extends BaseOptimizer<PointVectorValuePair> {
+public abstract class AbstractLeastSquaresOptimizer<OPTIM extends AbstractLeastSquaresOptimizer<OPTIM>>
+    extends AbstractOptimizer<PointVectorValuePair, OPTIM>
+    implements WithTarget<OPTIM>,
+               WithWeight<OPTIM>,
+               WithModelAndJacobian<OPTIM>,
+               WithStartPoint<OPTIM> {
     /** Target values for the model function at optimum. */
-    private final double[] target;
+    private double[] target;
     /** Weight matrix. */
-    private final RealMatrix weight;
+    private RealMatrix weight;
     /** Model function. */
-    private final MultivariateVectorFunction model;
+    private MultivariateVectorFunction model;
     /** Jacobian of the model function. */
-    private final MultivariateMatrixFunction jacobian;
+    private MultivariateMatrixFunction jacobian;
     /** Square-root of the weight matrix. */
-    private final RealMatrix weightSqrt;
+    private RealMatrix weightSqrt;
     /** Initial guess. */
-    private final double[] start;
+    private double[] start;
 
     /**
-     * @param target Observations.
-     * @param weight Weight of the observations.
-     * For performance, no defensive copy is performed.
-     * @param weightSqrt Square-root of the {@code weight} matrix.
-     * If {@code null}, it will be computed; otherwise it is the caller's
-     * responsibility that {@code weight} and {@code weightSqrt} are
-     * consistent.
-     * No defensive copy is performed.
-     * @param model ModelFunction.
-     * @param jacobian Jacobian of the model function.
-     * @param checker Convergence checker.
-     * @param start Initial guess.
-     * @param maxEval Maximum number of evaluations of the model
-     * function.
-     * @param maxIter Maximum number of iterations.
+     * Default constructor.
      */
-    protected AbstractLeastSquaresOptimizer(double[] target,
-                                            RealMatrix weight,
-                                            RealMatrix weightSqrt,
-                                            MultivariateVectorFunction model,
-                                            MultivariateMatrixFunction jacobian,
-                                            ConvergenceChecker<PointVectorValuePair> checker,
-                                            double[] start,
-                                            int maxEval,
-                                            int maxIter) {
-        super(checker, maxEval, maxIter);
-
-        this.target = target;
-        this.weight = weight;
-        this.model = model;
-        this.jacobian = jacobian;
-        this.start = start;
-
-        this.weightSqrt = weightSqrt == null ?
-            (weight == null ?
-             null : squareRoot(weight)) : weightSqrt;
+    protected AbstractLeastSquaresOptimizer() {}
+
+    /**
+     * Copy constructor.
+     *
+     * @param other Instance to copy.
+     */
+    protected AbstractLeastSquaresOptimizer(AbstractLeastSquaresOptimizer other) {
+        target = other.target == null ? null : other.target.clone();
+        start = other.start == null ? null : other.start.clone();
+        weight = other.weight == null ? null : other.weight.copy();
+        weightSqrt = other.weightSqrt == null ? null : other.weightSqrt.copy();
+        model = other.model; // XXX Not thread-safe
+        jacobian = other.jacobian; // XXX Not thread-safe
+    }
+
+    /** {@inheritDoc} */
+    public OPTIM withTarget(double[] target) {
+        this.target = target.clone();
+        return self();
+    }
+
+    /** {@inheritDoc} */
+    public OPTIM withWeight(RealMatrix weight) {
+        this.weight = weight; // XXX Not thread-safe
+        weightSqrt = squareRoot(weight);
+        return self();
+    }
+
+    /** {@inheritDoc} */
+    public OPTIM withModelAndJacobian(MultivariateVectorFunction model,
+                                      MultivariateMatrixFunction jacobian) {
+        this.model = model; // XXX Not thread-safe
+        this.jacobian = jacobian; // XXX Not thread-safe
+        return self();
+    }
+
+    /** {@inheritDoc} */
+    public OPTIM withStartPoint(double[] start) {
+        this.start = start.clone();
+        return self();
     }
 
     /**
@@ -217,51 +227,6 @@ public abstract class AbstractLeastSquar
     }
 
     /**
-     * Calling this method will raise an exception.
-     *
-     * @param optData Obsolete.
-     * @return nothing.
-     * @throws MathUnsupportedOperationException if called.
-     * @deprecated Do not use this method.
-     */
-    @Deprecated
-    @Override
-    public PointVectorValuePair optimize(OptimizationData... optData)
-        throws MathUnsupportedOperationException {
-        throw new MathUnsupportedOperationException();
-    }
-
-    /**
-     * Gets a reference to the corresponding field.
-     * Altering it could jeopardize the consistency of this class.
-     *
-     * @return the reference.
-     */
-    protected double[] getTargetInternal() {
-        return target;
-    }
-
-    /**
-     * Gets a reference to the corresponding field.
-     * Altering it could jeopardize the consistency of this class.
-     *
-     * @return the reference.
-     */
-    protected RealMatrix getWeightInternal() {
-        return weight;
-    }
-
-    /**
-     * Gets a reference to the corresponding field.
-     * Altering it could jeopardize the consistency of this class.
-     *
-     * @return the reference.
-     */
-    protected RealMatrix getWeightSquareRootInternal() {
-        return weightSqrt;
-    }
-
-    /**
      * Computes the objective function value.
      * This method <em>must</em> be called by subclasses to enforce the
      * evaluation counter limit.

Modified: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/fitting/leastsquares/GaussNewtonOptimizer.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math3/fitting/leastsquares/GaussNewtonOptimizer.java?rev=1512530&r1=1512529&r2=1512530&view=diff
==============================================================================
--- commons/proper/math/trunk/src/main/java/org/apache/commons/math3/fitting/leastsquares/GaussNewtonOptimizer.java (original)
+++ commons/proper/math/trunk/src/main/java/org/apache/commons/math3/fitting/leastsquares/GaussNewtonOptimizer.java Fri Aug  9 23:21:14 2013
@@ -16,8 +16,6 @@
  */
 package org.apache.commons.math3.fitting.leastsquares;
 
-import org.apache.commons.math3.analysis.MultivariateVectorFunction;
-import org.apache.commons.math3.analysis.MultivariateMatrixFunction;
 import org.apache.commons.math3.exception.DimensionMismatchException;
 import org.apache.commons.math3.exception.ConvergenceException;
 import org.apache.commons.math3.exception.NullArgumentException;
@@ -45,53 +43,10 @@ import org.apache.commons.math3.optim.Po
  *
  * @version $Id$
  * @since 3.3
- *
  */
-public class GaussNewtonOptimizer extends AbstractLeastSquaresOptimizer
-    implements WithTarget<GaussNewtonOptimizer>,
-               WithWeight<GaussNewtonOptimizer>,
-               WithModelAndJacobian<GaussNewtonOptimizer>,
-               WithConvergenceChecker<GaussNewtonOptimizer>,
-               WithStartPoint<GaussNewtonOptimizer>,
-               WithMaxIterations<GaussNewtonOptimizer>,
-               WithMaxEvaluations<GaussNewtonOptimizer> {
+public class GaussNewtonOptimizer extends AbstractLeastSquaresOptimizer<GaussNewtonOptimizer> {
     /** Indicator for using LU decomposition. */
-    private final boolean useLU;
-
-    /**
-     * Constructor called by the various {@code withXxx} methods.
-     *
-     * @param target Observations.
-     * @param weight Weight of the observations.
-     * For performance, no defensive copy is performed.
-     * @param weightSqrt Square-root of the {@code weight} matrix.
-     * If {@code null}, it will be computed; otherwise it is the caller's
-     * responsibility that {@code weight} and {@code weightSqrt} are
-     * consistent.
-     * No defensive copy is performed.
-     * @param model ModelFunction.
-     * @param jacobian Jacobian of the model function.
-     * @param checker Convergence checker.
-     * @param start Initial guess.
-     * @param maxEval Maximum number of evaluations of the model
-     * function.
-     * @param maxIter Maximum number of iterations.
-     * @param useLU Whether to use LU decomposition.
-     */
-    private GaussNewtonOptimizer(double[] target,
-                                 RealMatrix weight,
-                                 RealMatrix weightSqrt,
-                                 MultivariateVectorFunction model,
-                                 MultivariateMatrixFunction jacobian,
-                                 ConvergenceChecker<PointVectorValuePair> checker,
-                                 double[] start,
-                                 int maxEval,
-                                 int maxIter,
-                                 boolean useLU) {
-        super(target, weight, weightSqrt, model, jacobian, checker, start, maxEval, maxIter);
-
-        this.useLU = useLU;
-    }
+    private boolean useLU = true;
 
     /**
      * Creates a bare-bones instance.
@@ -104,127 +59,16 @@ public class GaussNewtonOptimizer extend
      * @return an instance of this class.
      */
     public static GaussNewtonOptimizer create() {
-        return new GaussNewtonOptimizer(null, null, null, null, null, null, null,
-                                        0, 0, true);
-    }
-
-    /** {@inheritDoc} */
-    public GaussNewtonOptimizer withTarget(double[] target) {
-        return new GaussNewtonOptimizer(target,
-                                        getWeightInternal(),
-                                        getWeightSquareRootInternal(),
-                                        getModel(),
-                                        getJacobian(),
-                                        getConvergenceChecker(),
-                                        getStart(),
-                                        getMaxEvaluations(),
-                                        getMaxIterations(),
-                                        useLU);
-    }
-
-    /** {@inheritDoc} */
-    public GaussNewtonOptimizer withWeight(RealMatrix weight) {
-        return new GaussNewtonOptimizer(getTargetInternal(),
-                                        weight,
-                                        null,
-                                        getModel(),
-                                        getJacobian(),
-                                        getConvergenceChecker(),
-                                        getStart(),
-                                        getMaxEvaluations(),
-                                        getMaxIterations(),
-                                        useLU);
-    }
-
-    /** {@inheritDoc} */
-    public GaussNewtonOptimizer withModelAndJacobian(MultivariateVectorFunction model,
-                                                     MultivariateMatrixFunction jacobian) {
-        return new GaussNewtonOptimizer(getTargetInternal(),
-                                        getWeightInternal(),
-                                        getWeightSquareRootInternal(),
-                                        model,
-                                        jacobian,
-                                        getConvergenceChecker(),
-                                        getStart(),
-                                        getMaxEvaluations(),
-                                        getMaxIterations(),
-                                        useLU);
-    }
-
-    /** {@inheritDoc} */
-    public GaussNewtonOptimizer withConvergenceChecker(ConvergenceChecker<PointVectorValuePair> checker) {
-        return new GaussNewtonOptimizer(getTarget(),
-                                        getWeightInternal(),
-                                        getWeightSquareRootInternal(),
-                                        getModel(),
-                                        getJacobian(),
-                                        checker,
-                                        getStart(),
-                                        getMaxEvaluations(),
-                                        getMaxIterations(),
-                                        useLU);
-    }
-
-    /** {@inheritDoc} */
-    public GaussNewtonOptimizer withStartPoint(double[] start) {
-        return new GaussNewtonOptimizer(getTarget(),
-                                        getWeightInternal(),
-                                        getWeightSquareRootInternal(),
-                                        getModel(),
-                                        getJacobian(),
-                                        getConvergenceChecker(),
-                                        start,
-                                        getMaxEvaluations(),
-                                        getMaxIterations(),
-                                        useLU);
-    }
-
-    /** {@inheritDoc} */
-    public GaussNewtonOptimizer withMaxIterations(int maxIter) {
-        return new GaussNewtonOptimizer(getTarget(),
-                                        getWeightInternal(),
-                                        getWeightSquareRootInternal(),
-                                        getModel(),
-                                        getJacobian(),
-                                        getConvergenceChecker(),
-                                        getStart(),
-                                        getMaxEvaluations(),
-                                        maxIter,
-                                        useLU);
-    }
-
-    /** {@inheritDoc} */
-    public GaussNewtonOptimizer withMaxEvaluations(int maxEval) {
-        return new GaussNewtonOptimizer(getTarget(),
-                                        getWeightInternal(),
-                                        getWeightSquareRootInternal(),
-                                        getModel(),
-                                        getJacobian(),
-                                        getConvergenceChecker(),
-                                        getStart(),
-                                        maxEval,
-                                        getMaxIterations(),
-                                        useLU);
+        return new GaussNewtonOptimizer();
     }
 
     /**
-     * Creates a new instance.
-     *
-     * @param withLU Whether to use LU decomposition.
-     * @return a new instance with all fields identical to this instance except
-     * for the givens arguments.
+     * @param useLU Whether to use LU decomposition.
+     * @return this instance.
      */
-    public GaussNewtonOptimizer withLU(boolean withLU) {
-        return new GaussNewtonOptimizer(getTarget(),
-                                        getWeightInternal(),
-                                        getWeightSquareRootInternal(),
-                                        getModel(),
-                                        getJacobian(),
-                                        getConvergenceChecker(),
-                                        getStart(),
-                                        getMaxEvaluations(),
-                                        getMaxIterations(),
-                                        withLU);
+    public GaussNewtonOptimizer withLU(boolean useLU) {
+        this.useLU = useLU;
+        return self();
     }
 
     /** {@inheritDoc} */

Modified: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/fitting/leastsquares/LevenbergMarquardtOptimizer.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math3/fitting/leastsquares/LevenbergMarquardtOptimizer.java?rev=1512530&r1=1512529&r2=1512530&view=diff
==============================================================================
--- commons/proper/math/trunk/src/main/java/org/apache/commons/math3/fitting/leastsquares/LevenbergMarquardtOptimizer.java (original)
+++ commons/proper/math/trunk/src/main/java/org/apache/commons/math3/fitting/leastsquares/LevenbergMarquardtOptimizer.java Fri Aug  9 23:21:14 2013
@@ -17,8 +17,6 @@
 package org.apache.commons.math3.fitting.leastsquares;
 
 import java.util.Arrays;
-import org.apache.commons.math3.analysis.MultivariateVectorFunction;
-import org.apache.commons.math3.analysis.MultivariateMatrixFunction;
 import org.apache.commons.math3.linear.RealMatrix;
 import org.apache.commons.math3.exception.ConvergenceException;
 import org.apache.commons.math3.exception.util.LocalizedFormats;
@@ -107,91 +105,26 @@ import org.apache.commons.math3.util.Fas
  * @version $Id$
  * @since 2.0
  */
-public class LevenbergMarquardtOptimizer extends AbstractLeastSquaresOptimizer
-    implements WithTarget<LevenbergMarquardtOptimizer>,
-               WithWeight<LevenbergMarquardtOptimizer>,
-               WithModelAndJacobian<LevenbergMarquardtOptimizer>,
-               WithConvergenceChecker<LevenbergMarquardtOptimizer>,
-               WithStartPoint<LevenbergMarquardtOptimizer>,
-               WithMaxIterations<LevenbergMarquardtOptimizer>,
-               WithMaxEvaluations<LevenbergMarquardtOptimizer> {
+public class LevenbergMarquardtOptimizer extends AbstractLeastSquaresOptimizer<LevenbergMarquardtOptimizer> {
     /** Twice the "epsilon machine". */
     private static final double TWO_EPS = 2 * Precision.EPSILON;
     /** Positive input variable used in determining the initial step bound. */
-    private final double initialStepBoundFactor;
+    private double initialStepBoundFactor = 100;
     /** Desired relative error in the sum of squares. */
-    private final double costRelativeTolerance;
+    private double costRelativeTolerance = 1e-10;
     /**  Desired relative error in the approximate solution parameters. */
-    private final double parRelativeTolerance;
+    private double parRelativeTolerance = 1e-10;
     /** Desired max cosine on the orthogonality between the function vector
      * and the columns of the jacobian. */
-    private final double orthoTolerance;
+    private double orthoTolerance = 1e-10;
     /** Threshold for QR ranking. */
-    private final double qrRankingThreshold;
+    private double qrRankingThreshold = Precision.SAFE_MIN;
     /** Levenberg-Marquardt parameter. */
     private double lmPar;
     /** Parameters evolution direction associated with lmPar. */
     private double[] lmDir;
 
     /**
-     * Constructor called by the various {@code withXxx} methods.
-     *
-     * @param target Observations.
-     * @param weight Weight of the observations.
-     * For performance, no defensive copy is performed.
-     * @param weightSqrt Square-root of the {@code weight} matrix.
-     * If {@code null}, it will be computed; otherwise it is the caller's
-     * responsibility that {@code weight} and {@code weightSqrt} are
-     * consistent.
-     * No defensive copy is performed.
-     * @param model ModelFunction.
-     * @param jacobian Jacobian of the model function.
-     * @param checker Convergence checker.
-     * @param start Initial guess.
-     * @param maxEval Maximum number of evaluations of the model
-     * function.
-     * @param maxIter Maximum number of iterations.
-     * @param initialStepBoundFactor Positive input variable used in
-     * determining the initial step bound. This bound is set to the
-     * product of initialStepBoundFactor and the euclidean norm of
-     * {@code diag * x} if non-zero, or else to {@code initialStepBoundFactor}
-     * itself. In most cases factor should lie in the interval
-     * {@code (0.1, 100.0)}. {@code 100} is a generally recommended value.
-     * @param costRelativeTolerance Desired relative error in the sum of
-     * squares.
-     * @param parRelativeTolerance Desired relative error in the approximate
-     * solution parameters.
-     * @param orthoTolerance Desired max cosine on the orthogonality between
-     * the function vector and the columns of the Jacobian.
-     * @param threshold Desired threshold for QR ranking. If the squared norm
-     * of a column vector is smaller or equal to this threshold during QR
-     * decomposition, it is considered to be a zero vector and hence the rank
-     * of the matrix is reduced.
-     */
-    private LevenbergMarquardtOptimizer(double[] target,
-                                        RealMatrix weight,
-                                        RealMatrix weightSqrt,
-                                        MultivariateVectorFunction model,
-                                        MultivariateMatrixFunction jacobian,
-                                        ConvergenceChecker<PointVectorValuePair> checker,
-                                        double[] start,
-                                        int maxEval,
-                                        int maxIter,
-                                        double initialStepBoundFactor,
-                                        double costRelativeTolerance,
-                                        double parRelativeTolerance,
-                                        double orthoTolerance,
-                                        double threshold) {
-        super(target, weight, weightSqrt, model, jacobian, checker, start, maxEval, maxIter);
-
-        this.initialStepBoundFactor = initialStepBoundFactor;
-        this.costRelativeTolerance = costRelativeTolerance;
-        this.parRelativeTolerance = parRelativeTolerance;
-        this.orthoTolerance = orthoTolerance;
-        this.qrRankingThreshold = threshold;
-    }
-
-    /**
      * Creates a bare-bones instance.
      * Several calls to {@code withXxx} methods are necessary to obtain
      * an object with all necessary fields set to sensible values.
@@ -208,183 +141,68 @@ public class LevenbergMarquardtOptimizer
      * @return an instance of this class.
      */
     public static LevenbergMarquardtOptimizer create() {
-        return new LevenbergMarquardtOptimizer(null, null, null, null, null, null, null,
-                                               0, 0, 100, 1e-10, 1e-10, 1e-10,
-                                               Precision.SAFE_MIN);
-    }
-
-    /** {@inheritDoc} */
-    public LevenbergMarquardtOptimizer withTarget(double[] target) {
-        return new LevenbergMarquardtOptimizer(target,
-                                               getWeightInternal(),
-                                               getWeightSquareRootInternal(),
-                                               getModel(),
-                                               getJacobian(),
-                                               getConvergenceChecker(),
-                                               getStart(),
-                                               getMaxEvaluations(),
-                                               getMaxIterations(),
-                                               initialStepBoundFactor,
-                                               costRelativeTolerance,
-                                               parRelativeTolerance,
-                                               orthoTolerance,
-                                               qrRankingThreshold);
-    }
-
-    /** {@inheritDoc} */
-    public LevenbergMarquardtOptimizer withWeight(RealMatrix weight) {
-        return new LevenbergMarquardtOptimizer(getTargetInternal(),
-                                               weight,
-                                               null,
-                                               getModel(),
-                                               getJacobian(),
-                                               getConvergenceChecker(),
-                                               getStart(),
-                                               getMaxEvaluations(),
-                                               getMaxIterations(),
-                                               initialStepBoundFactor,
-                                               costRelativeTolerance,
-                                               parRelativeTolerance,
-                                               orthoTolerance,
-                                               qrRankingThreshold);
+        return new LevenbergMarquardtOptimizer();
     }
 
-    /** {@inheritDoc} */
-    public LevenbergMarquardtOptimizer withModelAndJacobian(MultivariateVectorFunction model,
-                                                            MultivariateMatrixFunction jacobian) {
-        return new LevenbergMarquardtOptimizer(getTargetInternal(),
-                                               getWeightInternal(),
-                                               getWeightSquareRootInternal(),
-                                               model,
-                                               jacobian,
-                                               getConvergenceChecker(),
-                                               getStart(),
-                                               getMaxEvaluations(),
-                                               getMaxIterations(),
-                                               initialStepBoundFactor,
-                                               costRelativeTolerance,
-                                               parRelativeTolerance,
-                                               orthoTolerance,
-                                               qrRankingThreshold);
-    }
-
-    /** {@inheritDoc} */
-    public LevenbergMarquardtOptimizer withConvergenceChecker(ConvergenceChecker<PointVectorValuePair> checker) {
-        return new LevenbergMarquardtOptimizer(getTarget(),
-                                               getWeightInternal(),
-                                               getWeightSquareRootInternal(),
-                                               getModel(),
-                                               getJacobian(),
-                                               checker,
-                                               getStart(),
-                                               getMaxEvaluations(),
-                                               getMaxIterations(),
-                                               initialStepBoundFactor,
-                                               costRelativeTolerance,
-                                               parRelativeTolerance,
-                                               orthoTolerance,
-                                               qrRankingThreshold);
+    /**
+     * @param initialStepBoundFactor Positive input variable used in
+     * determining the initial step bound. This bound is set to the
+     * product of initialStepBoundFactor and the euclidean norm of
+     * {@code diag * x} if non-zero, or else to {@code initialStepBoundFactor}
+     * itself. In most cases factor should lie in the interval
+     * {@code (0.1, 100.0)}. {@code 100} is a generally recommended value.
+     * of the matrix is reduced.
+     * @return this instance.
+     */
+    public LevenbergMarquardtOptimizer withInitialStepBoundFactor(double initialStepBoundFactor) {
+        this.initialStepBoundFactor = initialStepBoundFactor;
+        return self();
     }
 
-    /** {@inheritDoc} */
-    public LevenbergMarquardtOptimizer withStartPoint(double[] start) {
-        return new LevenbergMarquardtOptimizer(getTarget(),
-                                               getWeightInternal(),
-                                               getWeightSquareRootInternal(),
-                                               getModel(),
-                                               getJacobian(),
-                                               getConvergenceChecker(),
-                                               start,
-                                               getMaxEvaluations(),
-                                               getMaxIterations(),
-                                               initialStepBoundFactor,
-                                               costRelativeTolerance,
-                                               parRelativeTolerance,
-                                               orthoTolerance,
-                                               qrRankingThreshold);
+    /**
+     * @param costRelativeTolerance Desired relative error in the sum of squares.
+     * @return this instance.
+     */
+    public LevenbergMarquardtOptimizer withCostRelativeTolerance(double costRelativeTolerance) {
+        this.costRelativeTolerance = costRelativeTolerance;
+        return self();
     }
 
-    /** {@inheritDoc} */
-    public LevenbergMarquardtOptimizer withMaxIterations(int maxIter) {
-        return new LevenbergMarquardtOptimizer(getTarget(),
-                                               getWeightInternal(),
-                                               getWeightSquareRootInternal(),
-                                               getModel(),
-                                               getJacobian(),
-                                               getConvergenceChecker(),
-                                               getStart(),
-                                               getMaxEvaluations(),
-                                               maxIter,
-                                               initialStepBoundFactor,
-                                               costRelativeTolerance,
-                                               parRelativeTolerance,
-                                               orthoTolerance,
-                                               qrRankingThreshold);
+    /**
+     * @param parameterRelativeTolerance Desired relative error in the approximate solution
+     * parameters.
+     * @return this instance.
+     */
+    public LevenbergMarquardtOptimizer withParameterRelativeTolerance(double parameterRelativeTolerance) {
+        this.parRelativeTolerance = parameterRelativeTolerance;
+        return self();
     }
 
-    /** {@inheritDoc} */
-    public LevenbergMarquardtOptimizer withMaxEvaluations(int maxEval) {
-        return new LevenbergMarquardtOptimizer(getTarget(),
-                                               getWeightInternal(),
-                                               getWeightSquareRootInternal(),
-                                               getModel(),
-                                               getJacobian(),
-                                               getConvergenceChecker(),
-                                               getStart(),
-                                               maxEval,
-                                               getMaxIterations(),
-                                               initialStepBoundFactor,
-                                               costRelativeTolerance,
-                                               parRelativeTolerance,
-                                               orthoTolerance,
-                                               qrRankingThreshold);
+    /**
+     * @param orthoTolerance Desired max cosine on the orthogonality between
+     * the function vector and the columns of the Jacobian.
+     * @return this instance.
+     */
+    public LevenbergMarquardtOptimizer withOrthoTolerance(double orthoTolerance) {
+        this.orthoTolerance = orthoTolerance;
+        return self();
     }
 
     /**
-     * Creates a new instance.
-     *
-     * @param initStepBoundFactor Positive input variable used in
-     * determining the initial step bound. This bound is set to the
-     * product of initialStepBoundFactor and the euclidean norm of
-     * {@code diag * x} if non-zero, or else to {@code initialStepBoundFactor}
-     * itself. In most cases factor should lie in the interval
-     * {@code (0.1, 100.0)}. {@code 100} is a generally recommended value.
-     * @param costRelTol Desired relative error in the sum of squares.
-     * @param parRelTol Desired relative error in the approximate solution
-     * parameters.
-     * @param orthoTol Desired max cosine on the orthogonality between
-     * the function vector and the columns of the Jacobian.
-     * @param threshold Desired threshold for QR ranking. If the squared norm
-     * of a column vector is smaller or equal to this threshold during QR
-     * decomposition, it is considered to be a zero vector and hence the rank
-     * of the matrix is reduced.
-     * @return a new instance with all fields identical to this instance except
-     * for the givens arguments.
+     * @param rankingThreshold Desired threshold for QR ranking.
+     * If the squared norm of a column vector is smaller or equal to this
+     * threshold during QR decomposition, it is considered to be a zero vector
+     * and hence the rank of the matrix is reduced.
+     * @return this instance.
      */
-    public LevenbergMarquardtOptimizer withTuningParameters(double initStepBoundFactor,
-                                                            double costRelTol,
-                                                            double parRelTol,
-                                                            double orthoTol,
-                                                            double threshold) {
-        return new LevenbergMarquardtOptimizer(getTarget(),
-                                               getWeightInternal(),
-                                               getWeightSquareRootInternal(),
-                                               getModel(),
-                                               getJacobian(),
-                                               getConvergenceChecker(),
-                                               getStart(),
-                                               getMaxEvaluations(),
-                                               getMaxIterations(),
-                                               initStepBoundFactor,
-                                               costRelTol,
-                                               parRelTol,
-                                               orthoTol,
-                                               threshold);
+    public LevenbergMarquardtOptimizer withRankingThreshold(double rankingThreshold) {
+        this.qrRankingThreshold = rankingThreshold;
+        return self();
     }
 
     /**
      * Gets the value of a tuning parameter.
-     * @see #withTuningParameters(double,double,double,double,double)
+     * @see #withInitialStepBoundFactor(double)
      *
      * @return the parameter's value.
      */
@@ -394,7 +212,7 @@ public class LevenbergMarquardtOptimizer
 
     /**
      * Gets the value of a tuning parameter.
-     * @see #withTuningParameters(double,double,double,double,double)
+     * @see #withCostRelativeTolerance(double)
      *
      * @return the parameter's value.
      */
@@ -404,17 +222,17 @@ public class LevenbergMarquardtOptimizer
 
     /**
      * Gets the value of a tuning parameter.
-     * @see #withTuningParameters(double,double,double,double,double)
+     * @see #withParameterRelativeTolerance(double)
      *
      * @return the parameter's value.
      */
-    public double getParRelativeTolerance() {
+    public double getParameterRelativeTolerance() {
         return parRelativeTolerance;
     }
 
     /**
      * Gets the value of a tuning parameter.
-     * @see #withTuningParameters(double,double,double,double,double)
+     * @see #withOrthoTolerance(double)
      *
      * @return the parameter's value.
      */
@@ -424,7 +242,7 @@ public class LevenbergMarquardtOptimizer
 
     /**
      * Gets the value of a tuning parameter.
-     * @see #withTuningParameters(double,double,double,double,double)
+     * @see #withRankingThreshold(double)
      *
      * @return the parameter's value.
      */

Modified: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/fitting/leastsquares/WithConvergenceChecker.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math3/fitting/leastsquares/WithConvergenceChecker.java?rev=1512530&r1=1512529&r2=1512530&view=diff
==============================================================================
--- commons/proper/math/trunk/src/main/java/org/apache/commons/math3/fitting/leastsquares/WithConvergenceChecker.java (original)
+++ commons/proper/math/trunk/src/main/java/org/apache/commons/math3/fitting/leastsquares/WithConvergenceChecker.java Fri Aug  9 23:21:14 2013
@@ -17,17 +17,17 @@
 package org.apache.commons.math3.fitting.leastsquares;
 
 import org.apache.commons.math3.optim.ConvergenceChecker;
-import org.apache.commons.math3.optim.PointVectorValuePair;
 
 /**
  * Interface for "fluent-API" that advertizes a capability of the optimizer.
  *
  * @param <T> Concrete optimizer implementation.
+ * @param <PAIR> Parametric type for the {@link ConvergenceChecker}.
  *
  * @version $Id$
  * @since 3.3
  */
-public interface WithConvergenceChecker<T> {
+public interface WithConvergenceChecker<PAIR, T> {
     /**
      * Creates a new instance with the specified parameter.
      *
@@ -35,5 +35,5 @@ public interface WithConvergenceChecker<
      * @return a new optimizer instance with all fields identical to this
      * instance except for the given argument.
      */
-    T withConvergenceChecker(ConvergenceChecker<PointVectorValuePair> checker);
+    T withConvergenceChecker(ConvergenceChecker<PAIR> checker);
 }

Added: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/optim/AbstractOptimizer.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math3/optim/AbstractOptimizer.java?rev=1512530&view=auto
==============================================================================
--- commons/proper/math/trunk/src/main/java/org/apache/commons/math3/optim/AbstractOptimizer.java (added)
+++ commons/proper/math/trunk/src/main/java/org/apache/commons/math3/optim/AbstractOptimizer.java Fri Aug  9 23:21:14 2013
@@ -0,0 +1,226 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.math3.optim;
+
+import org.apache.commons.math3.util.Incrementor;
+import org.apache.commons.math3.exception.TooManyEvaluationsException;
+import org.apache.commons.math3.exception.TooManyIterationsException;
+import org.apache.commons.math3.fitting.leastsquares.WithMaxEvaluations;
+import org.apache.commons.math3.fitting.leastsquares.WithMaxIterations;
+import org.apache.commons.math3.fitting.leastsquares.WithConvergenceChecker;
+
+/**
+ * Base class for implementing optimizers.
+ * It contains the boiler-plate code for counting the number of evaluations
+ * of the objective function and the number of iterations of the algorithm,
+ * and storing the convergence checker.
+ *
+ * @param <PAIR> Type of the point/value pair returned by the optimization
+ * algorithm.
+ * @param <OPTIM> Type of a subclass of this class.
+ * This parameter allows to implement fluent API methods at upper levels
+ * of the class hierarchy (since the fluent API requires that the actual
+ * type of the subclass is returned).
+ *
+ * @version $Id$
+ * @since 3.3
+ */
+public abstract class AbstractOptimizer<PAIR, OPTIM extends AbstractOptimizer<PAIR, OPTIM>>
+    implements WithMaxEvaluations<OPTIM>,
+               WithMaxIterations<OPTIM>,
+               WithConvergenceChecker<PAIR, OPTIM> {
+    /** Evaluations counter. */
+    private Incrementor evaluations = new Incrementor(Integer.MAX_VALUE, new MaxEvalCallback());
+    /** Iterations counter. */
+    private Incrementor iterations = new Incrementor(Integer.MAX_VALUE, new MaxIterCallback());
+    /** Convergence checker. */
+    private ConvergenceChecker<PAIR> checker = null;
+
+    /**
+     * Default constructor.
+     */
+    protected AbstractOptimizer() {}
+
+    /**
+     * Copy constructor.
+     *
+     * @param other Instance to copy.
+     */
+    protected AbstractOptimizer(AbstractOptimizer other) {
+        checker = other.checker; // XXX Not thread-safe.
+        evaluations.setMaximalCount(other.getMaxEvaluations());
+        iterations.setMaximalCount(other.getMaxIterations());
+    }
+
+    /**
+     * Returns this instance, cast to the type of its actual subclass.
+     *
+     * @return the "self-type" instance.
+     */
+    protected OPTIM self() {
+        final OPTIM optim = (OPTIM) this;
+        return optim;
+    }
+
+    /** {@inheritDoc} */
+    public OPTIM withConvergenceChecker(ConvergenceChecker<PAIR> checker) {
+        this.checker = checker;
+        return self();
+    }
+
+    /** {@inheritDoc} */
+    public OPTIM withMaxEvaluations(int max) {
+        evaluations.setMaximalCount(max);
+        return self();
+    }
+
+    /** {@inheritDoc} */
+    public OPTIM withMaxIterations(int max) {
+        iterations.setMaximalCount(max);
+        return self();
+    }
+
+    /**
+     * Gets the maximal number of function evaluations.
+     *
+     * @return the maximal number of function evaluations.
+     */
+    public int getMaxEvaluations() {
+        return evaluations.getMaximalCount();
+    }
+
+    /**
+     * Gets the number of evaluations of the objective function.
+     * The number of evaluations corresponds to the last call to the
+     * {@code optimize} method. It is 0 if the method has not been
+     * called yet.
+     *
+     * @return the number of evaluations of the objective function.
+     */
+    public int getEvaluations() {
+        return evaluations.getCount();
+    }
+
+    /**
+     * Gets the maximal number of iterations.
+     *
+     * @return the maximal number of iterations.
+     */
+    public int getMaxIterations() {
+        return iterations.getMaximalCount();
+    }
+
+    /**
+     * Gets the number of iterations performed by the algorithm.
+     * The number iterations corresponds to the last call to the
+     * {@code optimize} method. It is 0 if the method has not been
+     * called yet.
+     *
+     * @return the number of evaluations of the objective function.
+     */
+    public int getIterations() {
+        return iterations.getCount();
+    }
+
+    /**
+     * Gets the convergence checker.
+     *
+     * @return the object used to check for convergence.
+     */
+    public ConvergenceChecker<PAIR> getConvergenceChecker() {
+        return checker;
+    }
+
+    /**
+     * Performs the optimization.
+     *
+     * @return a point/value pair that satifies the convergence criteria.
+     * @throws TooManyEvaluationsException if the maximal number of
+     * evaluations is exceeded.
+     * @throws TooManyIterationsException if the maximal number of
+     * iterations is exceeded.
+     */
+    public PAIR optimize()
+        throws TooManyEvaluationsException,
+               TooManyIterationsException {
+        // Reset counters.
+        evaluations.resetCount();
+        iterations.resetCount();
+        // Perform optimization.
+        return doOptimize();
+    }
+
+    /**
+     * Performs the bulk of the optimization algorithm.
+     *
+     * @return the point/value pair giving the optimal value of the
+     * objective function.
+     */
+    protected abstract PAIR doOptimize();
+
+    /**
+     * Increment the evaluation count.
+     *
+     * @throws TooManyEvaluationsException if the allowed evaluations
+     * have been exhausted.
+     */
+    protected void incrementEvaluationCount()
+        throws TooManyEvaluationsException {
+        evaluations.incrementCount();
+    }
+
+    /**
+     * Increment the iteration count.
+     *
+     * @throws TooManyIterationsException if the allowed iterations
+     * have been exhausted.
+     */
+    protected void incrementIterationCount()
+        throws TooManyIterationsException {
+        iterations.incrementCount();
+    }
+
+    /**
+     * Defines the action to perform when reaching the maximum number
+     * of evaluations.
+     */
+    private static class MaxEvalCallback
+        implements  Incrementor.MaxCountExceededCallback {
+        /**
+         * {@inheritDoc}
+         * @throws TooManyEvaluationsException
+         */
+        public void trigger(int max) {
+            throw new TooManyEvaluationsException(max);
+        }
+    }
+
+    /**
+     * Defines the action to perform when reaching the maximum number
+     * of evaluations.
+     */
+    private static class MaxIterCallback
+        implements Incrementor.MaxCountExceededCallback {
+        /**
+         * {@inheritDoc}
+         * @throws TooManyIterationsException
+         */
+        public void trigger(int max) {
+            throw new TooManyIterationsException(max);
+        }
+    }
+}

Propchange: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/optim/AbstractOptimizer.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/optim/AbstractOptimizer.java
------------------------------------------------------------------------------
    svn:keywords = Id Revision

Modified: commons/proper/math/trunk/src/test/java/org/apache/commons/math3/fitting/leastsquares/AbstractLeastSquaresOptimizerAbstractTest.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/test/java/org/apache/commons/math3/fitting/leastsquares/AbstractLeastSquaresOptimizerAbstractTest.java?rev=1512530&r1=1512529&r2=1512530&view=diff
==============================================================================
--- commons/proper/math/trunk/src/test/java/org/apache/commons/math3/fitting/leastsquares/AbstractLeastSquaresOptimizerAbstractTest.java (original)
+++ commons/proper/math/trunk/src/test/java/org/apache/commons/math3/fitting/leastsquares/AbstractLeastSquaresOptimizerAbstractTest.java Fri Aug  9 23:21:14 2013
@@ -44,14 +44,7 @@ import org.junit.Test;
  *
  * @version $Id$
  */
-public abstract class AbstractLeastSquaresOptimizerAbstractTest<T extends AbstractLeastSquaresOptimizer &
-                                                                          WithTarget<T> &
-                                                                          WithWeight<T> &
-                                                                          WithModelAndJacobian<T> &
-                                                                          WithConvergenceChecker<T> &
-                                                                          WithStartPoint<T> &
-                                                                          WithMaxIterations<T> &
-                                                                          WithMaxEvaluations<T>> {
+public abstract class AbstractLeastSquaresOptimizerAbstractTest<T extends AbstractLeastSquaresOptimizer<T>> {
     /**
      * @return a concrete optimizer.
      */

Modified: commons/proper/math/trunk/src/test/java/org/apache/commons/math3/fitting/leastsquares/LevenbergMarquardtOptimizerTest.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/test/java/org/apache/commons/math3/fitting/leastsquares/LevenbergMarquardtOptimizerTest.java?rev=1512530&r1=1512529&r2=1512530&view=diff
==============================================================================
--- commons/proper/math/trunk/src/test/java/org/apache/commons/math3/fitting/leastsquares/LevenbergMarquardtOptimizerTest.java (original)
+++ commons/proper/math/trunk/src/test/java/org/apache/commons/math3/fitting/leastsquares/LevenbergMarquardtOptimizerTest.java Fri Aug  9 23:21:14 2013
@@ -115,11 +115,11 @@ public class LevenbergMarquardtOptimizer
                                double orthoTolerance, boolean shouldFail) {
         try {
             final LevenbergMarquardtOptimizer optimizer = LevenbergMarquardtOptimizer.create()
-                .withTuningParameters(initialStepBoundFactor,
-                                      costRelativeTolerance,
-                                      parRelativeTolerance,
-                                      orthoTolerance,
-                                      Precision.SAFE_MIN)
+                .withInitialStepBoundFactor(initialStepBoundFactor)
+                .withCostRelativeTolerance(costRelativeTolerance)
+                .withParameterRelativeTolerance(parRelativeTolerance)
+                .withOrthoTolerance(orthoTolerance)
+                .withRankingThreshold(Precision.SAFE_MIN)
                 .withMaxEvaluations(maxCostEval)
                 .withMaxIterations(100)
                 .withModelAndJacobian(problem, problemJacobian)

Modified: commons/proper/math/trunk/src/test/java/org/apache/commons/math3/fitting/leastsquares/MinpackTest.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/test/java/org/apache/commons/math3/fitting/leastsquares/MinpackTest.java?rev=1512530&r1=1512529&r2=1512530&view=diff
==============================================================================
--- commons/proper/math/trunk/src/test/java/org/apache/commons/math3/fitting/leastsquares/MinpackTest.java (original)
+++ commons/proper/math/trunk/src/test/java/org/apache/commons/math3/fitting/leastsquares/MinpackTest.java Fri Aug  9 23:21:14 2013
@@ -498,13 +498,14 @@ public class MinpackTest {
 
     private void minpackTest(MinpackFunction function, boolean exceptionExpected) {
         final double tol = 2.22044604926e-16;
+        final double sqrtTol = FastMath.sqrt(tol);
         LevenbergMarquardtOptimizer optimizer = LevenbergMarquardtOptimizer.create();
         optimizer = optimizer
-            .withTuningParameters(optimizer.getInitialStepBoundFactor(),
-                                  FastMath.sqrt(tol),
-                                  FastMath.sqrt(tol),
-                                  tol,
-                                  optimizer.getRankingThreshold())
+            .withInitialStepBoundFactor(optimizer.getInitialStepBoundFactor())
+            .withCostRelativeTolerance(sqrtTol)
+            .withParameterRelativeTolerance(sqrtTol)
+            .withOrthoTolerance(tol)
+            .withRankingThreshold(optimizer.getRankingThreshold())
             .withMaxEvaluations(400 * (function.getN() + 1))
             .withMaxIterations(2000)
             .withModelAndJacobian(function.getModelFunction(),