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(),