updated general algorithms with latest interfaces definitions

git-svn-id: https://svn.apache.org/repos/asf/commons/proper/math/trunk@758058 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Luc Maisonobe 2009-03-24 22:15:08 +00:00
parent d99003bc0f
commit ed8fc4a03a
6 changed files with 334 additions and 152 deletions

View File

@ -17,17 +17,18 @@
package org.apache.commons.math.optimization.general;
import org.apache.commons.math.FunctionEvaluationException;
import org.apache.commons.math.MaxIterationsExceededException;
import org.apache.commons.math.analysis.DifferentiableMultivariateVectorialFunction;
import org.apache.commons.math.analysis.MultivariateMatrixFunction;
import org.apache.commons.math.linear.InvalidMatrixException;
import org.apache.commons.math.linear.MatrixUtils;
import org.apache.commons.math.linear.RealMatrix;
import org.apache.commons.math.linear.decomposition.LUDecompositionImpl;
import org.apache.commons.math.optimization.ObjectiveException;
import org.apache.commons.math.optimization.OptimizationException;
import org.apache.commons.math.optimization.SimpleVectorialValueChecker;
import org.apache.commons.math.optimization.VectorialConvergenceChecker;
import org.apache.commons.math.optimization.VectorialDifferentiableObjectiveFunction;
import org.apache.commons.math.optimization.VectorialDifferentiableOptimizer;
import org.apache.commons.math.optimization.DifferentiableMultivariateVectorialOptimizer;
import org.apache.commons.math.optimization.VectorialPointValuePair;
/**
@ -38,7 +39,7 @@ import org.apache.commons.math.optimization.VectorialPointValuePair;
* @since 1.2
*
*/
public abstract class AbstractLeastSquaresOptimizer implements VectorialDifferentiableOptimizer {
public abstract class AbstractLeastSquaresOptimizer implements DifferentiableMultivariateVectorialOptimizer {
/** Serializable version identifier */
private static final long serialVersionUID = 5413193243329026789L;
@ -77,7 +78,10 @@ public abstract class AbstractLeastSquaresOptimizer implements VectorialDifferen
protected int rows;
/** Objective function. */
private VectorialDifferentiableObjectiveFunction f;
private DifferentiableMultivariateVectorialFunction f;
/** Objective function derivatives. */
private MultivariateMatrixFunction jF;
/** Target value for the objective functions at optimum. */
protected double[] target;
@ -85,8 +89,8 @@ public abstract class AbstractLeastSquaresOptimizer implements VectorialDifferen
/** Weight for the least squares cost computation. */
protected double[] weights;
/** Current variables set. */
protected double[] variables;
/** Current point. */
protected double[] point;
/** Current objective function value. */
protected double[] objective;
@ -156,15 +160,15 @@ public abstract class AbstractLeastSquaresOptimizer implements VectorialDifferen
/**
* Update the jacobian matrix.
* @exception ObjectiveException if the function jacobian
* @exception FunctionEvaluationException if the function jacobian
* cannot be evaluated or its dimension doesn't match problem dimension
*/
protected void updateJacobian() throws ObjectiveException {
protected void updateJacobian() throws FunctionEvaluationException {
++jacobianEvaluations;
jacobian = f.jacobian(variables, objective);
jacobian = jF.value(point);
if (jacobian.length != rows) {
throw new ObjectiveException("dimension mismatch {0} != {1}",
jacobian.length, rows);
throw new FunctionEvaluationException(point, "dimension mismatch {0} != {1}",
jacobian.length, rows);
}
for (int i = 0; i < rows; i++) {
final double[] ji = jacobian[i];
@ -177,17 +181,17 @@ public abstract class AbstractLeastSquaresOptimizer implements VectorialDifferen
/**
* Update the residuals array and cost function value.
* @exception ObjectiveException if the function cannot be evaluated
* @exception FunctionEvaluationException if the function cannot be evaluated
* or its dimension doesn't match problem dimension
*/
protected void updateResidualsAndCost()
throws ObjectiveException {
throws FunctionEvaluationException {
++objectiveEvaluations;
objective = f.objective(variables);
objective = f.value(point);
if (objective.length != rows) {
throw new ObjectiveException("dimension mismatch {0} != {1}",
objective.length, rows);
throw new FunctionEvaluationException(point, "dimension mismatch {0} != {1}",
objective.length, rows);
}
cost = 0;
for (int i = 0, index = 0; i < rows; i++, index += cols) {
@ -234,13 +238,13 @@ public abstract class AbstractLeastSquaresOptimizer implements VectorialDifferen
/**
* Get the covariance matrix of optimized parameters.
* @return covariance matrix
* @exception ObjectiveException if the function jacobian cannot
* @exception FunctionEvaluationException if the function jacobian cannot
* be evaluated
* @exception OptimizationException if the covariance matrix
* cannot be computed (singular problem)
*/
public double[][] getCovariances()
throws ObjectiveException, OptimizationException {
throws FunctionEvaluationException, OptimizationException {
// set up the jacobian
updateJacobian();
@ -273,13 +277,13 @@ public abstract class AbstractLeastSquaresOptimizer implements VectorialDifferen
* Guess the errors in optimized parameters.
* <p>Guessing is covariance-based, it only gives rough order of magnitude.</p>
* @return errors in optimized parameters
* @exception ObjectiveException if the function jacobian cannot b evaluated
* @exception FunctionEvaluationException if the function jacobian cannot b evaluated
* @exception OptimizationException if the covariances matrix cannot be computed
* or the number of degrees of freedom is not positive (number of measurements
* lesser or equal to number of parameters)
*/
public double[] guessParametersErrors()
throws ObjectiveException, OptimizationException {
throws FunctionEvaluationException, OptimizationException {
if (rows <= cols) {
throw new OptimizationException(
"no degrees of freedom ({0} measurements, {1} parameters)",
@ -295,10 +299,10 @@ public abstract class AbstractLeastSquaresOptimizer implements VectorialDifferen
}
/** {@inheritDoc} */
public VectorialPointValuePair optimize(final VectorialDifferentiableObjectiveFunction f,
public VectorialPointValuePair optimize(final DifferentiableMultivariateVectorialFunction f,
final double[] target, final double[] weights,
final double[] startPoint)
throws ObjectiveException, OptimizationException, IllegalArgumentException {
throws FunctionEvaluationException, OptimizationException, IllegalArgumentException {
if (target.length != weights.length) {
throw new OptimizationException("dimension mismatch {0} != {1}",
@ -312,14 +316,15 @@ public abstract class AbstractLeastSquaresOptimizer implements VectorialDifferen
// store least squares problem characteristics
this.f = f;
jF = f.jacobian();
this.target = target.clone();
this.weights = weights.clone();
this.variables = startPoint.clone();
this.point = startPoint.clone();
this.residuals = new double[target.length];
// arrays shared with the other private methods
rows = target.length;
cols = variables.length;
cols = point.length;
jacobian = new double[rows][cols];
cost = Double.POSITIVE_INFINITY;
@ -330,12 +335,12 @@ public abstract class AbstractLeastSquaresOptimizer implements VectorialDifferen
/** Perform the bulk of optimization algorithm.
* @return the point/value pair giving the optimal value for objective function
* @exception ObjectiveException if the objective function throws one during
* @exception FunctionEvaluationException if the objective function throws one during
* the search
* @exception OptimizationException if the algorithm failed to converge
* @exception IllegalArgumentException if the start point dimension is wrong
*/
abstract protected VectorialPointValuePair doOptimize()
throws ObjectiveException, OptimizationException, IllegalArgumentException;
throws FunctionEvaluationException, OptimizationException, IllegalArgumentException;
}

View File

@ -17,13 +17,13 @@
package org.apache.commons.math.optimization.general;
import org.apache.commons.math.FunctionEvaluationException;
import org.apache.commons.math.linear.DenseRealMatrix;
import org.apache.commons.math.linear.InvalidMatrixException;
import org.apache.commons.math.linear.RealMatrix;
import org.apache.commons.math.linear.decomposition.DecompositionSolver;
import org.apache.commons.math.linear.decomposition.LUDecompositionImpl;
import org.apache.commons.math.linear.decomposition.QRDecompositionImpl;
import org.apache.commons.math.optimization.ObjectiveException;
import org.apache.commons.math.optimization.OptimizationException;
import org.apache.commons.math.optimization.SimpleVectorialValueChecker;
import org.apache.commons.math.optimization.VectorialPointValuePair;
@ -63,7 +63,7 @@ public class GaussNewtonOptimizer extends AbstractLeastSquaresOptimizer {
/** {@inheritDoc} */
public VectorialPointValuePair doOptimize()
throws ObjectiveException, OptimizationException, IllegalArgumentException {
throws FunctionEvaluationException, OptimizationException, IllegalArgumentException {
// iterate until convergence is reached
VectorialPointValuePair current = null;
@ -75,7 +75,7 @@ public class GaussNewtonOptimizer extends AbstractLeastSquaresOptimizer {
VectorialPointValuePair previous = current;
updateResidualsAndCost();
updateJacobian();
current = new VectorialPointValuePair(variables, objective);
current = new VectorialPointValuePair(point, objective);
// build the linear problem
final double[] b = new double[cols];
@ -114,7 +114,7 @@ public class GaussNewtonOptimizer extends AbstractLeastSquaresOptimizer {
// update the estimated parameters
for (int i = 0; i < cols; ++i) {
variables[i] += dX[i];
point[i] += dX[i];
}
} catch(InvalidMatrixException e) {

View File

@ -18,7 +18,7 @@ package org.apache.commons.math.optimization.general;
import java.util.Arrays;
import org.apache.commons.math.optimization.ObjectiveException;
import org.apache.commons.math.FunctionEvaluationException;
import org.apache.commons.math.optimization.OptimizationException;
import org.apache.commons.math.optimization.VectorialPointValuePair;
@ -27,8 +27,8 @@ import org.apache.commons.math.optimization.VectorialPointValuePair;
* This class solves a least squares problem using the Levenberg-Marquardt algorithm.
*
* <p>This implementation <em>should</em> work even for over-determined systems
* (i.e. systems having more variables than equations). Over-determined systems
* are solved by ignoring the variables which have the smallest impact according
* (i.e. systems having more point than equations). Over-determined systems
* are solved by ignoring the point which have the smallest impact according
* to their jacobian column norm. Only the rank of the matrix and some loop bounds
* are changed to implement this.</p>
*
@ -104,7 +104,7 @@ public class LevenbergMarquardtOptimizer extends AbstractLeastSquaresOptimizer {
/** Serializable version identifier */
private static final long serialVersionUID = 8851282236194244323L;
/** Number of solved variables. */
/** Number of solved point. */
private int solvedCols;
/** Diagonal elements of the R matrix in the Q.R. decomposition. */
@ -210,7 +210,7 @@ public class LevenbergMarquardtOptimizer extends AbstractLeastSquaresOptimizer {
/** {@inheritDoc} */
protected VectorialPointValuePair doOptimize()
throws ObjectiveException, OptimizationException, IllegalArgumentException {
throws FunctionEvaluationException, OptimizationException, IllegalArgumentException {
// arrays shared with the other private methods
solvedCols = Math.min(rows, cols);
@ -220,7 +220,7 @@ public class LevenbergMarquardtOptimizer extends AbstractLeastSquaresOptimizer {
permutation = new int[cols];
lmDir = new double[cols];
// local variables
// local point
double delta = 0, xNorm = 0;
double[] diag = new double[cols];
double[] oldX = new double[cols];
@ -255,7 +255,7 @@ public class LevenbergMarquardtOptimizer extends AbstractLeastSquaresOptimizer {
if (firstIteration) {
// scale the variables according to the norms of the columns
// scale the point according to the norms of the columns
// of the initial jacobian
xNorm = 0;
for (int k = 0; k < cols; ++k) {
@ -263,7 +263,7 @@ public class LevenbergMarquardtOptimizer extends AbstractLeastSquaresOptimizer {
if (dk == 0) {
dk = 1.0;
}
double xk = dk * variables[k];
double xk = dk * point[k];
xNorm += xk * xk;
diag[k] = dk;
}
@ -291,7 +291,7 @@ public class LevenbergMarquardtOptimizer extends AbstractLeastSquaresOptimizer {
}
if (maxCosine <= orthoTolerance) {
// convergence has been reached
return new VectorialPointValuePair(variables, objective);
return new VectorialPointValuePair(point, objective);
}
// rescale if necessary
@ -305,7 +305,7 @@ public class LevenbergMarquardtOptimizer extends AbstractLeastSquaresOptimizer {
// save the state
for (int j = 0; j < solvedCols; ++j) {
int pj = permutation[j];
oldX[pj] = variables[pj];
oldX[pj] = point[pj];
}
double previousCost = cost;
double[] tmpVec = residuals;
@ -320,7 +320,7 @@ public class LevenbergMarquardtOptimizer extends AbstractLeastSquaresOptimizer {
for (int j = 0; j < solvedCols; ++j) {
int pj = permutation[j];
lmDir[pj] = -lmDir[pj];
variables[pj] = oldX[pj] + lmDir[pj];
point[pj] = oldX[pj] + lmDir[pj];
double s = diag[pj] * lmDir[pj];
lmNorm += s * s;
}
@ -384,7 +384,7 @@ public class LevenbergMarquardtOptimizer extends AbstractLeastSquaresOptimizer {
firstIteration = false;
xNorm = 0;
for (int k = 0; k < cols; ++k) {
double xK = diag[k] * variables[k];
double xK = diag[k] * point[k];
xNorm += xK * xK;
}
xNorm = Math.sqrt(xNorm);
@ -393,7 +393,7 @@ public class LevenbergMarquardtOptimizer extends AbstractLeastSquaresOptimizer {
cost = previousCost;
for (int j = 0; j < solvedCols; ++j) {
int pj = permutation[j];
variables[pj] = oldX[pj];
point[pj] = oldX[pj];
}
tmpVec = residuals;
residuals = oldRes;
@ -405,7 +405,7 @@ public class LevenbergMarquardtOptimizer extends AbstractLeastSquaresOptimizer {
(preRed <= costRelativeTolerance) &&
(ratio <= 2.0)) ||
(delta <= parRelativeTolerance * xNorm)) {
return new VectorialPointValuePair(variables, objective);
return new VectorialPointValuePair(point, objective);
}
// tests for termination and stringent tolerances

View File

@ -25,12 +25,14 @@ import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
import org.apache.commons.math.FunctionEvaluationException;
import org.apache.commons.math.analysis.DifferentiableMultivariateVectorialFunction;
import org.apache.commons.math.analysis.MultivariateMatrixFunction;
import org.apache.commons.math.analysis.MultivariateVectorialFunction;
import org.apache.commons.math.linear.DenseRealMatrix;
import org.apache.commons.math.linear.RealMatrix;
import org.apache.commons.math.optimization.ObjectiveException;
import org.apache.commons.math.optimization.OptimizationException;
import org.apache.commons.math.optimization.SimpleVectorialValueChecker;
import org.apache.commons.math.optimization.VectorialDifferentiableObjectiveFunction;
import org.apache.commons.math.optimization.VectorialPointValuePair;
/**
@ -102,7 +104,7 @@ extends TestCase {
super(name);
}
public void testTrivial() throws ObjectiveException, OptimizationException {
public void testTrivial() throws FunctionEvaluationException, OptimizationException {
LinearProblem problem =
new LinearProblem(new double[][] { { 2 } }, new double[] { 3 });
GaussNewtonOptimizer optimizer = new GaussNewtonOptimizer(true);
@ -115,7 +117,7 @@ extends TestCase {
assertEquals(3.0, optimum.getValue()[0], 1.0e-10);
}
public void testColumnsPermutation() throws ObjectiveException, OptimizationException {
public void testColumnsPermutation() throws FunctionEvaluationException, OptimizationException {
LinearProblem problem =
new LinearProblem(new double[][] { { 1.0, -1.0 }, { 0.0, 2.0 }, { 1.0, -2.0 } },
@ -135,7 +137,7 @@ extends TestCase {
}
public void testNoDependency() throws ObjectiveException, OptimizationException {
public void testNoDependency() throws FunctionEvaluationException, OptimizationException {
LinearProblem problem = new LinearProblem(new double[][] {
{ 2, 0, 0, 0, 0, 0 },
{ 0, 2, 0, 0, 0, 0 },
@ -156,7 +158,7 @@ extends TestCase {
}
}
public void testOneSet() throws ObjectiveException, OptimizationException {
public void testOneSet() throws FunctionEvaluationException, OptimizationException {
LinearProblem problem = new LinearProblem(new double[][] {
{ 1, 0, 0 },
@ -175,7 +177,7 @@ extends TestCase {
}
public void testTwoSets() throws ObjectiveException, OptimizationException {
public void testTwoSets() throws FunctionEvaluationException, OptimizationException {
double epsilon = 1.0e-7;
LinearProblem problem = new LinearProblem(new double[][] {
{ 2, 1, 0, 4, 0, 0 },
@ -222,7 +224,7 @@ extends TestCase {
}
}
public void testIllConditioned() throws ObjectiveException, OptimizationException {
public void testIllConditioned() throws FunctionEvaluationException, OptimizationException {
LinearProblem problem1 = new LinearProblem(new double[][] {
{ 10.0, 7.0, 8.0, 7.0 },
{ 7.0, 5.0, 6.0, 5.0 },
@ -303,7 +305,7 @@ extends TestCase {
}
}
public void testRedundantEquations() throws ObjectiveException, OptimizationException {
public void testRedundantEquations() throws FunctionEvaluationException, OptimizationException {
LinearProblem problem = new LinearProblem(new double[][] {
{ 1.0, 1.0 },
{ 1.0, -1.0 },
@ -322,7 +324,7 @@ extends TestCase {
}
public void testInconsistentEquations() throws ObjectiveException, OptimizationException {
public void testInconsistentEquations() throws FunctionEvaluationException, OptimizationException {
LinearProblem problem = new LinearProblem(new double[][] {
{ 1.0, 1.0 },
{ 1.0, -1.0 },
@ -337,7 +339,7 @@ extends TestCase {
}
public void testInconsistentSizes() throws ObjectiveException, OptimizationException {
public void testInconsistentSizes() throws FunctionEvaluationException, OptimizationException {
LinearProblem problem =
new LinearProblem(new double[][] { { 1, 0 }, { 0, 1 } }, new double[] { -1, 1 });
GaussNewtonOptimizer optimizer = new GaussNewtonOptimizer(true);
@ -366,7 +368,7 @@ extends TestCase {
new double[] { 1 },
new double[] { 0, 0 });
fail("an exception should have been thrown");
} catch (ObjectiveException oe) {
} catch (FunctionEvaluationException oe) {
// expected behavior
} catch (Exception e) {
fail("wrong exception caught");
@ -396,7 +398,7 @@ extends TestCase {
}
}
public void testCircleFitting() throws ObjectiveException, OptimizationException {
public void testCircleFitting() throws FunctionEvaluationException, OptimizationException {
Circle circle = new Circle();
circle.addPoint( 30.0, 68.0);
circle.addPoint( 50.0, -6.0);
@ -417,7 +419,7 @@ extends TestCase {
assertEquals(48.135167894714, center.y, 1.0e-10);
}
public void testCircleFittingBadInit() throws ObjectiveException, OptimizationException {
public void testCircleFittingBadInit() throws FunctionEvaluationException, OptimizationException {
Circle circle = new Circle();
double[][] points = new double[][] {
{-0.312967, 0.072366}, {-0.339248, 0.132965}, {-0.379780, 0.202724},
@ -477,9 +479,9 @@ extends TestCase {
}
private static class LinearProblem implements VectorialDifferentiableObjectiveFunction {
private static class LinearProblem implements DifferentiableMultivariateVectorialFunction {
private static final long serialVersionUID = 703247177355019415L;
private static final long serialVersionUID = -8804268799379350190L;
final RealMatrix factors;
final double[] target;
public LinearProblem(double[][] factors, double[] target) {
@ -487,20 +489,42 @@ extends TestCase {
this.target = target;
}
public double[][] jacobian(double[] variables, double[] value) {
return factors.getData();
public double[] value(double[] variables) {
return factors.operate(variables);
}
public double[] objective(double[] variables) {
return factors.operate(variables);
public MultivariateVectorialFunction partialDerivative(final int i) {
return new MultivariateVectorialFunction() {
private static final long serialVersionUID = 1037082026387842358L;
public double[] value(double[] point) {
return factors.getColumn(i);
}
};
}
public MultivariateVectorialFunction gradient(final int i) {
return new MultivariateVectorialFunction() {
private static final long serialVersionUID = -3268626996728727146L;
public double[] value(double[] point) {
return factors.getRow(i);
}
};
}
public MultivariateMatrixFunction jacobian() {
return new MultivariateMatrixFunction() {
private static final long serialVersionUID = -8387467946663627585L;
public double[][] value(double[] point) {
return factors.getData();
}
};
}
}
private static class Circle implements VectorialDifferentiableObjectiveFunction {
private static final long serialVersionUID = -4711170319243817874L;
private static class Circle implements DifferentiableMultivariateVectorialFunction {
private static final long serialVersionUID = -7165774454925027042L;
private ArrayList<Point2D.Double> points;
public Circle() {
@ -523,8 +547,7 @@ extends TestCase {
return r / points.size();
}
public double[][] jacobian(double[] variables, double[] value)
throws ObjectiveException, IllegalArgumentException {
private double[][] jacobian(double[] variables) {
int n = points.size();
Point2D.Double center = new Point2D.Double(variables[0], variables[1]);
@ -553,8 +576,7 @@ extends TestCase {
}
public double[] objective(double[] variables)
throws ObjectiveException, IllegalArgumentException {
public double[] value(double[] variables) {
Point2D.Double center = new Point2D.Double(variables[0], variables[1]);
double radius = getRadius(center);
@ -568,6 +590,38 @@ extends TestCase {
}
public MultivariateVectorialFunction partialDerivative(final int i) {
return new MultivariateVectorialFunction() {
private static final long serialVersionUID = -2884159755283203273L;
public double[] value(double[] point) {
double[][] m = jacobian(point);
double[] partial = new double[m.length];
for (int j = 0; j < partial.length; ++j) {
partial[i] = m[i][j];
}
return partial;
}
};
}
public MultivariateVectorialFunction gradient(final int i) {
return new MultivariateVectorialFunction() {
private static final long serialVersionUID = -43357217231860547L;
public double[] value(double[] point) {
return jacobian(point)[i];
}
};
}
public MultivariateMatrixFunction jacobian() {
return new MultivariateMatrixFunction() {
private static final long serialVersionUID = -4340046230875165095L;
public double[][] value(double[] point) {
return jacobian(point);
}
};
}
}
public static Test suite() {

View File

@ -26,12 +26,14 @@ import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
import org.apache.commons.math.FunctionEvaluationException;
import org.apache.commons.math.analysis.DifferentiableMultivariateVectorialFunction;
import org.apache.commons.math.analysis.MultivariateMatrixFunction;
import org.apache.commons.math.analysis.MultivariateVectorialFunction;
import org.apache.commons.math.linear.DenseRealMatrix;
import org.apache.commons.math.linear.RealMatrix;
import org.apache.commons.math.optimization.ObjectiveException;
import org.apache.commons.math.optimization.OptimizationException;
import org.apache.commons.math.optimization.SimpleVectorialValueChecker;
import org.apache.commons.math.optimization.VectorialDifferentiableObjectiveFunction;
import org.apache.commons.math.optimization.VectorialPointValuePair;
/**
@ -103,7 +105,7 @@ public class LevenbergMarquardtOptimizerTest
super(name);
}
public void testTrivial() throws ObjectiveException, OptimizationException {
public void testTrivial() throws FunctionEvaluationException, OptimizationException {
LinearProblem problem =
new LinearProblem(new double[][] { { 2 } }, new double[] { 3 });
LevenbergMarquardtOptimizer optimizer = new LevenbergMarquardtOptimizer();
@ -122,7 +124,7 @@ public class LevenbergMarquardtOptimizerTest
assertEquals(3.0, optimum.getValue()[0], 1.0e-10);
}
public void testQRColumnsPermutation() throws ObjectiveException, OptimizationException {
public void testQRColumnsPermutation() throws FunctionEvaluationException, OptimizationException {
LinearProblem problem =
new LinearProblem(new double[][] { { 1.0, -1.0 }, { 0.0, 2.0 }, { 1.0, -2.0 } },
@ -140,7 +142,7 @@ public class LevenbergMarquardtOptimizerTest
}
public void testNoDependency() throws ObjectiveException, OptimizationException {
public void testNoDependency() throws FunctionEvaluationException, OptimizationException {
LinearProblem problem = new LinearProblem(new double[][] {
{ 2, 0, 0, 0, 0, 0 },
{ 0, 2, 0, 0, 0, 0 },
@ -159,7 +161,7 @@ public class LevenbergMarquardtOptimizerTest
}
}
public void testOneSet() throws ObjectiveException, OptimizationException {
public void testOneSet() throws FunctionEvaluationException, OptimizationException {
LinearProblem problem = new LinearProblem(new double[][] {
{ 1, 0, 0 },
@ -176,7 +178,7 @@ public class LevenbergMarquardtOptimizerTest
}
public void testTwoSets() throws ObjectiveException, OptimizationException {
public void testTwoSets() throws FunctionEvaluationException, OptimizationException {
double epsilon = 1.0e-7;
LinearProblem problem = new LinearProblem(new double[][] {
{ 2, 1, 0, 4, 0, 0 },
@ -201,7 +203,7 @@ public class LevenbergMarquardtOptimizerTest
}
public void testNonInversible() throws ObjectiveException, OptimizationException {
public void testNonInversible() throws FunctionEvaluationException, OptimizationException {
LinearProblem problem = new LinearProblem(new double[][] {
{ 1, 2, -3 },
@ -223,7 +225,7 @@ public class LevenbergMarquardtOptimizerTest
}
public void testIllConditioned() throws ObjectiveException, OptimizationException {
public void testIllConditioned() throws FunctionEvaluationException, OptimizationException {
LinearProblem problem1 = new LinearProblem(new double[][] {
{ 10.0, 7.0, 8.0, 7.0 },
{ 7.0, 5.0, 6.0, 5.0 },
@ -257,7 +259,7 @@ public class LevenbergMarquardtOptimizerTest
}
public void testMoreEstimatedParametersSimple() throws ObjectiveException, OptimizationException {
public void testMoreEstimatedParametersSimple() throws FunctionEvaluationException, OptimizationException {
LinearProblem problem = new LinearProblem(new double[][] {
{ 3.0, 2.0, 0.0, 0.0 },
@ -272,7 +274,7 @@ public class LevenbergMarquardtOptimizerTest
}
public void testMoreEstimatedParametersUnsorted() throws ObjectiveException, OptimizationException {
public void testMoreEstimatedParametersUnsorted() throws FunctionEvaluationException, OptimizationException {
LinearProblem problem = new LinearProblem(new double[][] {
{ 1.0, 1.0, 0.0, 0.0, 0.0, 0.0 },
{ 0.0, 0.0, 1.0, 1.0, 1.0, 0.0 },
@ -293,7 +295,7 @@ public class LevenbergMarquardtOptimizerTest
}
public void testRedundantEquations() throws ObjectiveException, OptimizationException {
public void testRedundantEquations() throws FunctionEvaluationException, OptimizationException {
LinearProblem problem = new LinearProblem(new double[][] {
{ 1.0, 1.0 },
{ 1.0, -1.0 },
@ -310,7 +312,7 @@ public class LevenbergMarquardtOptimizerTest
}
public void testInconsistentEquations() throws ObjectiveException, OptimizationException {
public void testInconsistentEquations() throws FunctionEvaluationException, OptimizationException {
LinearProblem problem = new LinearProblem(new double[][] {
{ 1.0, 1.0 },
{ 1.0, -1.0 },
@ -323,7 +325,7 @@ public class LevenbergMarquardtOptimizerTest
}
public void testInconsistentSizes() throws ObjectiveException, OptimizationException {
public void testInconsistentSizes() throws FunctionEvaluationException, OptimizationException {
LinearProblem problem =
new LinearProblem(new double[][] { { 1, 0 }, { 0, 1 } }, new double[] { -1, 1 });
LevenbergMarquardtOptimizer optimizer = new LevenbergMarquardtOptimizer();
@ -350,7 +352,7 @@ public class LevenbergMarquardtOptimizerTest
new double[] { 1 },
new double[] { 0, 0 });
fail("an exception should have been thrown");
} catch (ObjectiveException oe) {
} catch (FunctionEvaluationException oe) {
// expected behavior
} catch (Exception e) {
fail("wrong exception caught");
@ -372,7 +374,7 @@ public class LevenbergMarquardtOptimizerTest
checkEstimate(circle, 0.1, 20, 1.0e-18, 1.0e-16, 1.0e-10, true);
}
private void checkEstimate(VectorialDifferentiableObjectiveFunction problem,
private void checkEstimate(DifferentiableMultivariateVectorialFunction problem,
double initialStepBoundFactor, int maxCostEval,
double costRelativeTolerance, double parRelativeTolerance,
double orthoTolerance, boolean shouldFail) {
@ -388,14 +390,14 @@ public class LevenbergMarquardtOptimizerTest
assertTrue(! shouldFail);
} catch (OptimizationException ee) {
assertTrue(shouldFail);
} catch (ObjectiveException ee) {
} catch (FunctionEvaluationException ee) {
assertTrue(shouldFail);
} catch (Exception e) {
fail("wrong exception type caught");
}
}
public void testCircleFitting() throws ObjectiveException, OptimizationException {
public void testCircleFitting() throws FunctionEvaluationException, OptimizationException {
Circle circle = new Circle();
circle.addPoint( 30.0, 68.0);
circle.addPoint( 50.0, -6.0);
@ -445,7 +447,7 @@ public class LevenbergMarquardtOptimizerTest
}
public void testCircleFittingBadInit() throws ObjectiveException, OptimizationException {
public void testCircleFittingBadInit() throws FunctionEvaluationException, OptimizationException {
Circle circle = new Circle();
double[][] points = new double[][] {
{-0.312967, 0.072366}, {-0.339248, 0.132965}, {-0.379780, 0.202724},
@ -498,7 +500,7 @@ public class LevenbergMarquardtOptimizerTest
assertEquals( 0.2075001, center.y, 1.0e-6);
}
public void testMath199() throws ObjectiveException, OptimizationException {
public void testMath199() throws FunctionEvaluationException, OptimizationException {
try {
QuadraticProblem problem = new QuadraticProblem();
problem.addPoint (0, -3.182591015485607);
@ -517,7 +519,7 @@ public class LevenbergMarquardtOptimizerTest
}
private static class LinearProblem implements VectorialDifferentiableObjectiveFunction {
private static class LinearProblem implements DifferentiableMultivariateVectorialFunction {
private static final long serialVersionUID = 703247177355019415L;
final RealMatrix factors;
@ -527,17 +529,40 @@ public class LevenbergMarquardtOptimizerTest
this.target = target;
}
public double[][] jacobian(double[] variables, double[] value) {
return factors.getData();
public double[] value(double[] variables) {
return factors.operate(variables);
}
public double[] objective(double[] variables) {
return factors.operate(variables);
public MultivariateVectorialFunction partialDerivative(final int i) {
return new MultivariateVectorialFunction() {
private static final long serialVersionUID = 4868131119285501303L;
public double[] value(double[] point) {
return factors.getColumn(i);
}
};
}
public MultivariateVectorialFunction gradient(final int i) {
return new MultivariateVectorialFunction() {
private static final long serialVersionUID = 6280336674474631774L;
public double[] value(double[] point) {
return factors.getRow(i);
}
};
}
public MultivariateMatrixFunction jacobian() {
return new MultivariateMatrixFunction() {
private static final long serialVersionUID = 556396458721526234L;
public double[][] value(double[] point) {
return factors.getData();
}
};
}
}
private static class Circle implements VectorialDifferentiableObjectiveFunction {
private static class Circle implements DifferentiableMultivariateVectorialFunction {
private static final long serialVersionUID = -4711170319243817874L;
@ -563,11 +588,10 @@ public class LevenbergMarquardtOptimizerTest
return r / points.size();
}
public double[][] jacobian(double[] variables, double[] value)
throws ObjectiveException, IllegalArgumentException {
private double[][] jacobian(double[] point) {
int n = points.size();
Point2D.Double center = new Point2D.Double(variables[0], variables[1]);
Point2D.Double center = new Point2D.Double(point[0], point[1]);
// gradient of the optimal radius
double dRdX = 0;
@ -593,8 +617,8 @@ public class LevenbergMarquardtOptimizerTest
}
public double[] objective(double[] variables)
throws ObjectiveException, IllegalArgumentException {
public double[] value(double[] variables)
throws FunctionEvaluationException, IllegalArgumentException {
Point2D.Double center = new Point2D.Double(variables[0], variables[1]);
double radius = getRadius(center);
@ -608,11 +632,43 @@ public class LevenbergMarquardtOptimizerTest
}
public MultivariateVectorialFunction partialDerivative(final int i) {
return new MultivariateVectorialFunction() {
private static final long serialVersionUID = -2884159755283203273L;
public double[] value(double[] point) {
double[][] m = jacobian(point);
double[] partial = new double[m.length];
for (int j = 0; j < partial.length; ++j) {
partial[i] = m[i][j];
}
return partial;
}
};
}
public MultivariateVectorialFunction gradient(final int i) {
return new MultivariateVectorialFunction() {
private static final long serialVersionUID = -43357217231860547L;
public double[] value(double[] point) {
return jacobian(point)[i];
}
};
}
public MultivariateMatrixFunction jacobian() {
return new MultivariateMatrixFunction() {
private static final long serialVersionUID = -4340046230875165095L;
public double[][] value(double[] point) {
return jacobian(point);
}
};
}
}
private static class QuadraticProblem implements VectorialDifferentiableObjectiveFunction {
private static class QuadraticProblem implements DifferentiableMultivariateVectorialFunction {
private static final long serialVersionUID = -247096133023967957L;
private static final long serialVersionUID = 7072187082052755854L;
private List<Double> x;
private List<Double> y;
@ -626,7 +682,7 @@ public class LevenbergMarquardtOptimizerTest
this.y.add(y);
}
public double[][] jacobian(double[] variables, double[] value) {
private double[][] jacobian(double[] variables) {
double[][] jacobian = new double[x.size()][3];
for (int i = 0; i < jacobian.length; ++i) {
jacobian[i][0] = x.get(i) * x.get(i);
@ -636,7 +692,7 @@ public class LevenbergMarquardtOptimizerTest
return jacobian;
}
public double[] objective(double[] variables) {
public double[] value(double[] variables) {
double[] values = new double[x.size()];
for (int i = 0; i < values.length; ++i) {
values[i] = (variables[0] * x.get(i) + variables[1]) * x.get(i) + variables[2];
@ -644,6 +700,38 @@ public class LevenbergMarquardtOptimizerTest
return values;
}
public MultivariateVectorialFunction partialDerivative(final int i) {
return new MultivariateVectorialFunction() {
private static final long serialVersionUID = 2371658898687841192L;
public double[] value(double[] point) {
double[][] m = jacobian(point);
double[] partial = new double[m.length];
for (int j = 0; j < partial.length; ++j) {
partial[i] = m[i][j];
}
return partial;
}
};
}
public MultivariateVectorialFunction gradient(final int i) {
return new MultivariateVectorialFunction() {
private static final long serialVersionUID = 6863958501785879369L;
public double[] value(double[] point) {
return jacobian(point)[i];
}
};
}
public MultivariateMatrixFunction jacobian() {
return new MultivariateMatrixFunction() {
private static final long serialVersionUID = -8673650298627399464L;
public double[][] value(double[] point) {
return jacobian(point);
}
};
}
}
public static Test suite() {

View File

@ -19,14 +19,17 @@ package org.apache.commons.math.optimization.general;
import java.util.Arrays;
import org.apache.commons.math.optimization.ObjectiveException;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
import org.apache.commons.math.FunctionEvaluationException;
import org.apache.commons.math.analysis.DifferentiableMultivariateVectorialFunction;
import org.apache.commons.math.analysis.MultivariateMatrixFunction;
import org.apache.commons.math.analysis.MultivariateVectorialFunction;
import org.apache.commons.math.optimization.OptimizationException;
import org.apache.commons.math.optimization.VectorialDifferentiableObjectiveFunction;
import org.apache.commons.math.optimization.VectorialPointValuePair;
import junit.framework.*;
/**
* <p>Some of the unit tests are re-implementations of the MINPACK <a
* href="http://www.netlib.org/minpack/ex/file17">file17</a> and <a
@ -520,13 +523,13 @@ public class MinpackTest extends TestCase {
assertTrue(function.checkTheoreticalMinParams(optimum));
} catch (OptimizationException lsse) {
assertTrue(exceptionExpected);
} catch (ObjectiveException oe) {
} catch (FunctionEvaluationException fe) {
assertTrue(exceptionExpected);
}
}
private static abstract class MinpackFunction
implements VectorialDifferentiableObjectiveFunction {
implements DifferentiableMultivariateVectorialFunction {
private static final long serialVersionUID = -6209760235478794233L;
protected int n;
@ -597,9 +600,41 @@ public class MinpackTest extends TestCase {
return true;
}
public abstract double[][] jacobian(double[] variables, double[] value);
public MultivariateVectorialFunction partialDerivative(final int i) {
return new MultivariateVectorialFunction() {
private static final long serialVersionUID = 2192585229396907068L;
public double[] value(double[] point) {
double[][] m = jacobian(point);
double[] partial = new double[m.length];
for (int j = 0; j < partial.length; ++j) {
partial[i] = m[i][j];
}
return partial;
}
};
}
public abstract double[] objective(double[] variables);
public MultivariateVectorialFunction gradient(final int i) {
return new MultivariateVectorialFunction() {
private static final long serialVersionUID = -5562016064510078300L;
public double[] value(double[] point) {
return jacobian(point)[i];
}
};
}
public MultivariateMatrixFunction jacobian() {
return new MultivariateMatrixFunction() {
private static final long serialVersionUID = -2435076097232923678L;
public double[][] value(double[] point) {
return jacobian(point);
}
};
}
public abstract double[][] jacobian(double[] variables);
public abstract double[] value(double[] variables);
}
@ -614,7 +649,7 @@ public class MinpackTest extends TestCase {
buildArray(n, -1.0));
}
public double[][] jacobian(double[] variables, double[] value) {
public double[][] jacobian(double[] variables) {
double t = 2.0 / m;
double[][] jacobian = new double[m][];
for (int i = 0; i < m; ++i) {
@ -626,7 +661,7 @@ public class MinpackTest extends TestCase {
return jacobian;
}
public double[] objective(double[] variables) {
public double[] value(double[] variables) {
double sum = 0;
for (int i = 0; i < n; ++i) {
sum += variables[i];
@ -652,7 +687,7 @@ public class MinpackTest extends TestCase {
super(m, buildArray(n, x0), theoreticalMinCost, null);
}
public double[][] jacobian(double[] variables, double[] value) {
public double[][] jacobian(double[] variables) {
double[][] jacobian = new double[m][];
for (int i = 0; i < m; ++i) {
jacobian[i] = new double[n];
@ -663,7 +698,7 @@ public class MinpackTest extends TestCase {
return jacobian;
}
public double[] objective(double[] variables) {
public double[] value(double[] variables) {
double[] f = new double[m];
double sum = 0;
for (int i = 0; i < n; ++i) {
@ -687,7 +722,7 @@ public class MinpackTest extends TestCase {
null);
}
public double[][] jacobian(double[] variables, double[] value) {
public double[][] jacobian(double[] variables) {
double[][] jacobian = new double[m][];
for (int i = 0; i < m; ++i) {
jacobian[i] = new double[n];
@ -706,7 +741,7 @@ public class MinpackTest extends TestCase {
return jacobian;
}
public double[] objective(double[] variables) {
public double[] value(double[] variables) {
double[] f = new double[m];
double sum = 0;
for (int i = 1; i < (n - 1); ++i) {
@ -729,12 +764,12 @@ public class MinpackTest extends TestCase {
super(2, startParams, 0.0, buildArray(2, 1.0));
}
public double[][] jacobian(double[] variables, double[] value) {
public double[][] jacobian(double[] variables) {
double x1 = variables[0];
return new double[][] { { -20 * x1, 10 }, { -1, 0 } };
}
public double[] objective(double[] variables) {
public double[] value(double[] variables) {
double x1 = variables[0];
double x2 = variables[1];
return new double[] { 10 * (x2 - x1 * x1), 1 - x1 };
@ -751,7 +786,7 @@ public class MinpackTest extends TestCase {
super(3, startParams, 0.0, new double[] { 1.0, 0.0, 0.0 });
}
public double[][] jacobian(double[] variables, double[] value) {
public double[][] jacobian(double[] variables) {
double x1 = variables[0];
double x2 = variables[1];
double tmpSquare = x1 * x1 + x2 * x2;
@ -764,7 +799,7 @@ public class MinpackTest extends TestCase {
};
}
public double[] objective(double[] variables) {
public double[] value(double[] variables) {
double x1 = variables[0];
double x2 = variables[1];
double x3 = variables[2];
@ -798,7 +833,7 @@ public class MinpackTest extends TestCase {
super(4, startParams, 0.0, buildArray(4, 0.0));
}
public double[][] jacobian(double[] variables, double[] value) {
public double[][] jacobian(double[] variables) {
double x1 = variables[0];
double x2 = variables[1];
double x3 = variables[2];
@ -811,7 +846,7 @@ public class MinpackTest extends TestCase {
};
}
public double[] objective(double[] variables) {
public double[] value(double[] variables) {
double x1 = variables[0];
double x2 = variables[1];
double x3 = variables[2];
@ -841,7 +876,7 @@ public class MinpackTest extends TestCase {
theoreticalMinParams);
}
public double[][] jacobian(double[] variables, double[] value) {
public double[][] jacobian(double[] variables) {
double x2 = variables[1];
return new double[][] {
{ 1, x2 * (10 - 3 * x2) - 2 },
@ -849,7 +884,7 @@ public class MinpackTest extends TestCase {
};
}
public double[] objective(double[] variables) {
public double[] value(double[] variables) {
double x1 = variables[0];
double x2 = variables[1];
return new double[] {
@ -872,7 +907,7 @@ public class MinpackTest extends TestCase {
theoreticalMinParams);
}
public double[][] jacobian(double[] variables, double[] value) {
public double[][] jacobian(double[] variables) {
double x2 = variables[1];
double x3 = variables[2];
double[][] jacobian = new double[m][];
@ -887,7 +922,7 @@ public class MinpackTest extends TestCase {
return jacobian;
}
public double[] objective(double[] variables) {
public double[] value(double[] variables) {
double x1 = variables[0];
double x2 = variables[1];
double x3 = variables[2];
@ -925,7 +960,7 @@ public class MinpackTest extends TestCase {
}
}
public double[][] jacobian(double[] variables, double[] value) {
public double[][] jacobian(double[] variables) {
double x1 = variables[0];
double x2 = variables[1];
double x3 = variables[2];
@ -942,7 +977,7 @@ public class MinpackTest extends TestCase {
return jacobian;
}
public double[] objective(double[] variables) {
public double[] value(double[] variables) {
double x1 = variables[0];
double x2 = variables[1];
double x3 = variables[2];
@ -981,7 +1016,7 @@ public class MinpackTest extends TestCase {
}
}
public double[][] jacobian(double[] variables, double[] value) {
public double[][] jacobian(double[] variables) {
double x1 = variables[0];
double x2 = variables[1];
double x3 = variables[2];
@ -996,7 +1031,7 @@ public class MinpackTest extends TestCase {
return jacobian;
}
public double[] objective(double[] variables) {
public double[] value(double[] variables) {
double x1 = variables[0];
double x2 = variables[1];
double x3 = variables[2];
@ -1028,7 +1063,7 @@ public class MinpackTest extends TestCase {
theoreticalMinParams);
}
public double[][] jacobian(double[] variables, double[] value) {
public double[][] jacobian(double[] variables) {
double[][] jacobian = new double[m][];
@ -1060,7 +1095,7 @@ public class MinpackTest extends TestCase {
}
public double[] objective(double[] variables) {
public double[] value(double[] variables) {
double[] f = new double[m];
for (int i = 0; i < (m - 2); ++i) {
double div = (i + 1) / 29.0;
@ -1100,7 +1135,7 @@ public class MinpackTest extends TestCase {
new double[] { 1.0, 10.0, 1.0 });
}
public double[][] jacobian(double[] variables, double[] value) {
public double[][] jacobian(double[] variables) {
double x1 = variables[0];
double x2 = variables[1];
double[][] jacobian = new double[m][];
@ -1115,7 +1150,7 @@ public class MinpackTest extends TestCase {
return jacobian;
}
public double[] objective(double[] variables) {
public double[] value(double[] variables) {
double x1 = variables[0];
double x2 = variables[1];
double x3 = variables[2];
@ -1142,7 +1177,7 @@ public class MinpackTest extends TestCase {
theoreticalMinParams);
}
public double[][] jacobian(double[] variables, double[] value) {
public double[][] jacobian(double[] variables) {
double x1 = variables[0];
double x2 = variables[1];
double[][] jacobian = new double[m][];
@ -1153,7 +1188,7 @@ public class MinpackTest extends TestCase {
return jacobian;
}
public double[] objective(double[] variables) {
public double[] value(double[] variables) {
double x1 = variables[0];
double x2 = variables[1];
double[] f = new double[m];
@ -1178,7 +1213,7 @@ public class MinpackTest extends TestCase {
theoreticalMinParams);
}
public double[][] jacobian(double[] variables, double[] value) {
public double[][] jacobian(double[] variables) {
double x1 = variables[0];
double x2 = variables[1];
double x3 = variables[2];
@ -1196,7 +1231,7 @@ public class MinpackTest extends TestCase {
return jacobian;
}
public double[] objective(double[] variables) {
public double[] value(double[] variables) {
double x1 = variables[0];
double x2 = variables[1];
double x3 = variables[2];
@ -1234,7 +1269,7 @@ public class MinpackTest extends TestCase {
theoreticalMinParams);
}
public double[][] jacobian(double[] variables, double[] value) {
public double[][] jacobian(double[] variables) {
double[][] jacobian = new double[m][];
for (int i = 0; i < m; ++i) {
@ -1263,7 +1298,7 @@ public class MinpackTest extends TestCase {
}
public double[] objective(double[] variables) {
public double[] value(double[] variables) {
double[] f = new double[m];
@ -1307,7 +1342,7 @@ public class MinpackTest extends TestCase {
theoreticalMinParams);
}
public double[][] jacobian(double[] variables, double[] value) {
public double[][] jacobian(double[] variables) {
double[][] jacobian = new double[m][];
for (int i = 0; i < m; ++i) {
jacobian[i] = new double[n];
@ -1340,7 +1375,7 @@ public class MinpackTest extends TestCase {
}
public double[] objective(double[] variables) {
public double[] value(double[] variables) {
double[] f = new double[m];
double sum = -(n + 1);
double prod = 1;
@ -1369,7 +1404,7 @@ public class MinpackTest extends TestCase {
theoreticalMinParams);
}
public double[][] jacobian(double[] variables, double[] value) {
public double[][] jacobian(double[] variables) {
double x2 = variables[1];
double x3 = variables[2];
double x4 = variables[3];
@ -1386,7 +1421,7 @@ public class MinpackTest extends TestCase {
return jacobian;
}
public double[] objective(double[] variables) {
public double[] value(double[] variables) {
double x1 = variables[0];
double x2 = variables[1];
double x3 = variables[2];
@ -1422,7 +1457,7 @@ public class MinpackTest extends TestCase {
theoreticalMinParams);
}
public double[][] jacobian(double[] variables, double[] value) {
public double[][] jacobian(double[] variables) {
double x01 = variables[0];
double x02 = variables[1];
double x03 = variables[2];
@ -1458,7 +1493,7 @@ public class MinpackTest extends TestCase {
return jacobian;
}
public double[] objective(double[] variables) {
public double[] value(double[] variables) {
double x01 = variables[0];
double x02 = variables[1];
double x03 = variables[2];