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

View File

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

View File

@ -25,12 +25,14 @@ import junit.framework.Test;
import junit.framework.TestCase; import junit.framework.TestCase;
import junit.framework.TestSuite; 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.DenseRealMatrix;
import org.apache.commons.math.linear.RealMatrix; 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.OptimizationException;
import org.apache.commons.math.optimization.SimpleVectorialValueChecker; import org.apache.commons.math.optimization.SimpleVectorialValueChecker;
import org.apache.commons.math.optimization.VectorialDifferentiableObjectiveFunction;
import org.apache.commons.math.optimization.VectorialPointValuePair; import org.apache.commons.math.optimization.VectorialPointValuePair;
/** /**
@ -102,7 +104,7 @@ extends TestCase {
super(name); super(name);
} }
public void testTrivial() throws ObjectiveException, OptimizationException { public void testTrivial() throws FunctionEvaluationException, OptimizationException {
LinearProblem problem = LinearProblem problem =
new LinearProblem(new double[][] { { 2 } }, new double[] { 3 }); new LinearProblem(new double[][] { { 2 } }, new double[] { 3 });
GaussNewtonOptimizer optimizer = new GaussNewtonOptimizer(true); GaussNewtonOptimizer optimizer = new GaussNewtonOptimizer(true);
@ -115,7 +117,7 @@ extends TestCase {
assertEquals(3.0, optimum.getValue()[0], 1.0e-10); assertEquals(3.0, optimum.getValue()[0], 1.0e-10);
} }
public void testColumnsPermutation() throws ObjectiveException, OptimizationException { public void testColumnsPermutation() throws FunctionEvaluationException, OptimizationException {
LinearProblem problem = LinearProblem problem =
new LinearProblem(new double[][] { { 1.0, -1.0 }, { 0.0, 2.0 }, { 1.0, -2.0 } }, 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[][] { LinearProblem problem = new LinearProblem(new double[][] {
{ 2, 0, 0, 0, 0, 0 }, { 2, 0, 0, 0, 0, 0 },
{ 0, 2, 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[][] { LinearProblem problem = new LinearProblem(new double[][] {
{ 1, 0, 0 }, { 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; double epsilon = 1.0e-7;
LinearProblem problem = new LinearProblem(new double[][] { LinearProblem problem = new LinearProblem(new double[][] {
{ 2, 1, 0, 4, 0, 0 }, { 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[][] { LinearProblem problem1 = new LinearProblem(new double[][] {
{ 10.0, 7.0, 8.0, 7.0 }, { 10.0, 7.0, 8.0, 7.0 },
{ 7.0, 5.0, 6.0, 5.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[][] { LinearProblem problem = new LinearProblem(new double[][] {
{ 1.0, 1.0 }, { 1.0, 1.0 },
{ 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[][] { LinearProblem problem = new LinearProblem(new double[][] {
{ 1.0, 1.0 }, { 1.0, 1.0 },
{ 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 = LinearProblem problem =
new LinearProblem(new double[][] { { 1, 0 }, { 0, 1 } }, new double[] { -1, 1 }); new LinearProblem(new double[][] { { 1, 0 }, { 0, 1 } }, new double[] { -1, 1 });
GaussNewtonOptimizer optimizer = new GaussNewtonOptimizer(true); GaussNewtonOptimizer optimizer = new GaussNewtonOptimizer(true);
@ -366,7 +368,7 @@ extends TestCase {
new double[] { 1 }, new double[] { 1 },
new double[] { 0, 0 }); new double[] { 0, 0 });
fail("an exception should have been thrown"); fail("an exception should have been thrown");
} catch (ObjectiveException oe) { } catch (FunctionEvaluationException oe) {
// expected behavior // expected behavior
} catch (Exception e) { } catch (Exception e) {
fail("wrong exception caught"); 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 circle = new Circle();
circle.addPoint( 30.0, 68.0); circle.addPoint( 30.0, 68.0);
circle.addPoint( 50.0, -6.0); circle.addPoint( 50.0, -6.0);
@ -417,7 +419,7 @@ extends TestCase {
assertEquals(48.135167894714, center.y, 1.0e-10); assertEquals(48.135167894714, center.y, 1.0e-10);
} }
public void testCircleFittingBadInit() throws ObjectiveException, OptimizationException { public void testCircleFittingBadInit() throws FunctionEvaluationException, OptimizationException {
Circle circle = new Circle(); Circle circle = new Circle();
double[][] points = new double[][] { double[][] points = new double[][] {
{-0.312967, 0.072366}, {-0.339248, 0.132965}, {-0.379780, 0.202724}, {-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 RealMatrix factors;
final double[] target; final double[] target;
public LinearProblem(double[][] factors, double[] target) { public LinearProblem(double[][] factors, double[] target) {
@ -487,20 +489,42 @@ extends TestCase {
this.target = target; this.target = target;
} }
public double[][] jacobian(double[] variables, double[] value) { public double[] value(double[] variables) {
return factors.getData();
}
public double[] objective(double[] variables) {
return factors.operate(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);
}
};
} }
private static class Circle implements VectorialDifferentiableObjectiveFunction { public MultivariateVectorialFunction gradient(final int i) {
return new MultivariateVectorialFunction() {
private static final long serialVersionUID = -3268626996728727146L;
public double[] value(double[] point) {
return factors.getRow(i);
}
};
}
private static final long serialVersionUID = -4711170319243817874L; 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 DifferentiableMultivariateVectorialFunction {
private static final long serialVersionUID = -7165774454925027042L;
private ArrayList<Point2D.Double> points; private ArrayList<Point2D.Double> points;
public Circle() { public Circle() {
@ -523,8 +547,7 @@ extends TestCase {
return r / points.size(); return r / points.size();
} }
public double[][] jacobian(double[] variables, double[] value) private double[][] jacobian(double[] variables) {
throws ObjectiveException, IllegalArgumentException {
int n = points.size(); int n = points.size();
Point2D.Double center = new Point2D.Double(variables[0], variables[1]); Point2D.Double center = new Point2D.Double(variables[0], variables[1]);
@ -553,8 +576,7 @@ extends TestCase {
} }
public double[] objective(double[] variables) public double[] value(double[] variables) {
throws ObjectiveException, IllegalArgumentException {
Point2D.Double center = new Point2D.Double(variables[0], variables[1]); Point2D.Double center = new Point2D.Double(variables[0], variables[1]);
double radius = getRadius(center); 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() { public static Test suite() {

View File

@ -26,12 +26,14 @@ import junit.framework.Test;
import junit.framework.TestCase; import junit.framework.TestCase;
import junit.framework.TestSuite; 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.DenseRealMatrix;
import org.apache.commons.math.linear.RealMatrix; 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.OptimizationException;
import org.apache.commons.math.optimization.SimpleVectorialValueChecker; import org.apache.commons.math.optimization.SimpleVectorialValueChecker;
import org.apache.commons.math.optimization.VectorialDifferentiableObjectiveFunction;
import org.apache.commons.math.optimization.VectorialPointValuePair; import org.apache.commons.math.optimization.VectorialPointValuePair;
/** /**
@ -103,7 +105,7 @@ public class LevenbergMarquardtOptimizerTest
super(name); super(name);
} }
public void testTrivial() throws ObjectiveException, OptimizationException { public void testTrivial() throws FunctionEvaluationException, OptimizationException {
LinearProblem problem = LinearProblem problem =
new LinearProblem(new double[][] { { 2 } }, new double[] { 3 }); new LinearProblem(new double[][] { { 2 } }, new double[] { 3 });
LevenbergMarquardtOptimizer optimizer = new LevenbergMarquardtOptimizer(); LevenbergMarquardtOptimizer optimizer = new LevenbergMarquardtOptimizer();
@ -122,7 +124,7 @@ public class LevenbergMarquardtOptimizerTest
assertEquals(3.0, optimum.getValue()[0], 1.0e-10); assertEquals(3.0, optimum.getValue()[0], 1.0e-10);
} }
public void testQRColumnsPermutation() throws ObjectiveException, OptimizationException { public void testQRColumnsPermutation() throws FunctionEvaluationException, OptimizationException {
LinearProblem problem = LinearProblem problem =
new LinearProblem(new double[][] { { 1.0, -1.0 }, { 0.0, 2.0 }, { 1.0, -2.0 } }, 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[][] { LinearProblem problem = new LinearProblem(new double[][] {
{ 2, 0, 0, 0, 0, 0 }, { 2, 0, 0, 0, 0, 0 },
{ 0, 2, 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[][] { LinearProblem problem = new LinearProblem(new double[][] {
{ 1, 0, 0 }, { 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; double epsilon = 1.0e-7;
LinearProblem problem = new LinearProblem(new double[][] { LinearProblem problem = new LinearProblem(new double[][] {
{ 2, 1, 0, 4, 0, 0 }, { 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[][] { LinearProblem problem = new LinearProblem(new double[][] {
{ 1, 2, -3 }, { 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[][] { LinearProblem problem1 = new LinearProblem(new double[][] {
{ 10.0, 7.0, 8.0, 7.0 }, { 10.0, 7.0, 8.0, 7.0 },
{ 7.0, 5.0, 6.0, 5.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[][] { LinearProblem problem = new LinearProblem(new double[][] {
{ 3.0, 2.0, 0.0, 0.0 }, { 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[][] { LinearProblem problem = new LinearProblem(new double[][] {
{ 1.0, 1.0, 0.0, 0.0, 0.0, 0.0 }, { 1.0, 1.0, 0.0, 0.0, 0.0, 0.0 },
{ 0.0, 0.0, 1.0, 1.0, 1.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[][] { LinearProblem problem = new LinearProblem(new double[][] {
{ 1.0, 1.0 }, { 1.0, 1.0 },
{ 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[][] { LinearProblem problem = new LinearProblem(new double[][] {
{ 1.0, 1.0 }, { 1.0, 1.0 },
{ 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 = LinearProblem problem =
new LinearProblem(new double[][] { { 1, 0 }, { 0, 1 } }, new double[] { -1, 1 }); new LinearProblem(new double[][] { { 1, 0 }, { 0, 1 } }, new double[] { -1, 1 });
LevenbergMarquardtOptimizer optimizer = new LevenbergMarquardtOptimizer(); LevenbergMarquardtOptimizer optimizer = new LevenbergMarquardtOptimizer();
@ -350,7 +352,7 @@ public class LevenbergMarquardtOptimizerTest
new double[] { 1 }, new double[] { 1 },
new double[] { 0, 0 }); new double[] { 0, 0 });
fail("an exception should have been thrown"); fail("an exception should have been thrown");
} catch (ObjectiveException oe) { } catch (FunctionEvaluationException oe) {
// expected behavior // expected behavior
} catch (Exception e) { } catch (Exception e) {
fail("wrong exception caught"); 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); 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 initialStepBoundFactor, int maxCostEval,
double costRelativeTolerance, double parRelativeTolerance, double costRelativeTolerance, double parRelativeTolerance,
double orthoTolerance, boolean shouldFail) { double orthoTolerance, boolean shouldFail) {
@ -388,14 +390,14 @@ public class LevenbergMarquardtOptimizerTest
assertTrue(! shouldFail); assertTrue(! shouldFail);
} catch (OptimizationException ee) { } catch (OptimizationException ee) {
assertTrue(shouldFail); assertTrue(shouldFail);
} catch (ObjectiveException ee) { } catch (FunctionEvaluationException ee) {
assertTrue(shouldFail); assertTrue(shouldFail);
} catch (Exception e) { } catch (Exception e) {
fail("wrong exception type caught"); fail("wrong exception type caught");
} }
} }
public void testCircleFitting() throws ObjectiveException, OptimizationException { public void testCircleFitting() throws FunctionEvaluationException, OptimizationException {
Circle circle = new Circle(); Circle circle = new Circle();
circle.addPoint( 30.0, 68.0); circle.addPoint( 30.0, 68.0);
circle.addPoint( 50.0, -6.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(); Circle circle = new Circle();
double[][] points = new double[][] { double[][] points = new double[][] {
{-0.312967, 0.072366}, {-0.339248, 0.132965}, {-0.379780, 0.202724}, {-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); assertEquals( 0.2075001, center.y, 1.0e-6);
} }
public void testMath199() throws ObjectiveException, OptimizationException { public void testMath199() throws FunctionEvaluationException, OptimizationException {
try { try {
QuadraticProblem problem = new QuadraticProblem(); QuadraticProblem problem = new QuadraticProblem();
problem.addPoint (0, -3.182591015485607); 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; private static final long serialVersionUID = 703247177355019415L;
final RealMatrix factors; final RealMatrix factors;
@ -527,17 +529,40 @@ public class LevenbergMarquardtOptimizerTest
this.target = target; this.target = target;
} }
public double[][] jacobian(double[] variables, double[] value) { public double[] value(double[] variables) {
return factors.getData();
}
public double[] objective(double[] variables) {
return factors.operate(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);
}
};
} }
private static class Circle implements VectorialDifferentiableObjectiveFunction { 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 DifferentiableMultivariateVectorialFunction {
private static final long serialVersionUID = -4711170319243817874L; private static final long serialVersionUID = -4711170319243817874L;
@ -563,11 +588,10 @@ public class LevenbergMarquardtOptimizerTest
return r / points.size(); return r / points.size();
} }
public double[][] jacobian(double[] variables, double[] value) private double[][] jacobian(double[] point) {
throws ObjectiveException, IllegalArgumentException {
int n = points.size(); 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 // gradient of the optimal radius
double dRdX = 0; double dRdX = 0;
@ -593,8 +617,8 @@ public class LevenbergMarquardtOptimizerTest
} }
public double[] objective(double[] variables) public double[] value(double[] variables)
throws ObjectiveException, IllegalArgumentException { throws FunctionEvaluationException, IllegalArgumentException {
Point2D.Double center = new Point2D.Double(variables[0], variables[1]); Point2D.Double center = new Point2D.Double(variables[0], variables[1]);
double radius = getRadius(center); 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;
}
};
} }
private static class QuadraticProblem implements VectorialDifferentiableObjectiveFunction { public MultivariateVectorialFunction gradient(final int i) {
return new MultivariateVectorialFunction() {
private static final long serialVersionUID = -43357217231860547L;
public double[] value(double[] point) {
return jacobian(point)[i];
}
};
}
private static final long serialVersionUID = -247096133023967957L; 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 DifferentiableMultivariateVectorialFunction {
private static final long serialVersionUID = 7072187082052755854L;
private List<Double> x; private List<Double> x;
private List<Double> y; private List<Double> y;
@ -626,7 +682,7 @@ public class LevenbergMarquardtOptimizerTest
this.y.add(y); this.y.add(y);
} }
public double[][] jacobian(double[] variables, double[] value) { private double[][] jacobian(double[] variables) {
double[][] jacobian = new double[x.size()][3]; double[][] jacobian = new double[x.size()][3];
for (int i = 0; i < jacobian.length; ++i) { for (int i = 0; i < jacobian.length; ++i) {
jacobian[i][0] = x.get(i) * x.get(i); jacobian[i][0] = x.get(i) * x.get(i);
@ -636,7 +692,7 @@ public class LevenbergMarquardtOptimizerTest
return jacobian; return jacobian;
} }
public double[] objective(double[] variables) { public double[] value(double[] variables) {
double[] values = new double[x.size()]; double[] values = new double[x.size()];
for (int i = 0; i < values.length; ++i) { for (int i = 0; i < values.length; ++i) {
values[i] = (variables[0] * x.get(i) + variables[1]) * x.get(i) + variables[2]; values[i] = (variables[0] * x.get(i) + variables[1]) * x.get(i) + variables[2];
@ -644,6 +700,38 @@ public class LevenbergMarquardtOptimizerTest
return values; 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() { public static Test suite() {

View File

@ -19,14 +19,17 @@ package org.apache.commons.math.optimization.general;
import java.util.Arrays; 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.OptimizationException;
import org.apache.commons.math.optimization.VectorialDifferentiableObjectiveFunction;
import org.apache.commons.math.optimization.VectorialPointValuePair; import org.apache.commons.math.optimization.VectorialPointValuePair;
import junit.framework.*;
/** /**
* <p>Some of the unit tests are re-implementations of the MINPACK <a * <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 * 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)); assertTrue(function.checkTheoreticalMinParams(optimum));
} catch (OptimizationException lsse) { } catch (OptimizationException lsse) {
assertTrue(exceptionExpected); assertTrue(exceptionExpected);
} catch (ObjectiveException oe) { } catch (FunctionEvaluationException fe) {
assertTrue(exceptionExpected); assertTrue(exceptionExpected);
} }
} }
private static abstract class MinpackFunction private static abstract class MinpackFunction
implements VectorialDifferentiableObjectiveFunction { implements DifferentiableMultivariateVectorialFunction {
private static final long serialVersionUID = -6209760235478794233L; private static final long serialVersionUID = -6209760235478794233L;
protected int n; protected int n;
@ -597,9 +600,41 @@ public class MinpackTest extends TestCase {
return true; 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)); buildArray(n, -1.0));
} }
public double[][] jacobian(double[] variables, double[] value) { public double[][] jacobian(double[] variables) {
double t = 2.0 / m; double t = 2.0 / m;
double[][] jacobian = new double[m][]; double[][] jacobian = new double[m][];
for (int i = 0; i < m; ++i) { for (int i = 0; i < m; ++i) {
@ -626,7 +661,7 @@ public class MinpackTest extends TestCase {
return jacobian; return jacobian;
} }
public double[] objective(double[] variables) { public double[] value(double[] variables) {
double sum = 0; double sum = 0;
for (int i = 0; i < n; ++i) { for (int i = 0; i < n; ++i) {
sum += variables[i]; sum += variables[i];
@ -652,7 +687,7 @@ public class MinpackTest extends TestCase {
super(m, buildArray(n, x0), theoreticalMinCost, null); super(m, buildArray(n, x0), theoreticalMinCost, null);
} }
public double[][] jacobian(double[] variables, double[] value) { public double[][] jacobian(double[] variables) {
double[][] jacobian = new double[m][]; double[][] jacobian = new double[m][];
for (int i = 0; i < m; ++i) { for (int i = 0; i < m; ++i) {
jacobian[i] = new double[n]; jacobian[i] = new double[n];
@ -663,7 +698,7 @@ public class MinpackTest extends TestCase {
return jacobian; return jacobian;
} }
public double[] objective(double[] variables) { public double[] value(double[] variables) {
double[] f = new double[m]; double[] f = new double[m];
double sum = 0; double sum = 0;
for (int i = 0; i < n; ++i) { for (int i = 0; i < n; ++i) {
@ -687,7 +722,7 @@ public class MinpackTest extends TestCase {
null); null);
} }
public double[][] jacobian(double[] variables, double[] value) { public double[][] jacobian(double[] variables) {
double[][] jacobian = new double[m][]; double[][] jacobian = new double[m][];
for (int i = 0; i < m; ++i) { for (int i = 0; i < m; ++i) {
jacobian[i] = new double[n]; jacobian[i] = new double[n];
@ -706,7 +741,7 @@ public class MinpackTest extends TestCase {
return jacobian; return jacobian;
} }
public double[] objective(double[] variables) { public double[] value(double[] variables) {
double[] f = new double[m]; double[] f = new double[m];
double sum = 0; double sum = 0;
for (int i = 1; i < (n - 1); ++i) { 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)); 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]; double x1 = variables[0];
return new double[][] { { -20 * x1, 10 }, { -1, 0 } }; return new double[][] { { -20 * x1, 10 }, { -1, 0 } };
} }
public double[] objective(double[] variables) { public double[] value(double[] variables) {
double x1 = variables[0]; double x1 = variables[0];
double x2 = variables[1]; double x2 = variables[1];
return new double[] { 10 * (x2 - x1 * x1), 1 - x1 }; 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 }); 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 x1 = variables[0];
double x2 = variables[1]; double x2 = variables[1];
double tmpSquare = x1 * x1 + x2 * x2; 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 x1 = variables[0];
double x2 = variables[1]; double x2 = variables[1];
double x3 = variables[2]; double x3 = variables[2];
@ -798,7 +833,7 @@ public class MinpackTest extends TestCase {
super(4, startParams, 0.0, buildArray(4, 0.0)); 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 x1 = variables[0];
double x2 = variables[1]; double x2 = variables[1];
double x3 = variables[2]; 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 x1 = variables[0];
double x2 = variables[1]; double x2 = variables[1];
double x3 = variables[2]; double x3 = variables[2];
@ -841,7 +876,7 @@ public class MinpackTest extends TestCase {
theoreticalMinParams); theoreticalMinParams);
} }
public double[][] jacobian(double[] variables, double[] value) { public double[][] jacobian(double[] variables) {
double x2 = variables[1]; double x2 = variables[1];
return new double[][] { return new double[][] {
{ 1, x2 * (10 - 3 * x2) - 2 }, { 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 x1 = variables[0];
double x2 = variables[1]; double x2 = variables[1];
return new double[] { return new double[] {
@ -872,7 +907,7 @@ public class MinpackTest extends TestCase {
theoreticalMinParams); theoreticalMinParams);
} }
public double[][] jacobian(double[] variables, double[] value) { public double[][] jacobian(double[] variables) {
double x2 = variables[1]; double x2 = variables[1];
double x3 = variables[2]; double x3 = variables[2];
double[][] jacobian = new double[m][]; double[][] jacobian = new double[m][];
@ -887,7 +922,7 @@ public class MinpackTest extends TestCase {
return jacobian; return jacobian;
} }
public double[] objective(double[] variables) { public double[] value(double[] variables) {
double x1 = variables[0]; double x1 = variables[0];
double x2 = variables[1]; double x2 = variables[1];
double x3 = variables[2]; 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 x1 = variables[0];
double x2 = variables[1]; double x2 = variables[1];
double x3 = variables[2]; double x3 = variables[2];
@ -942,7 +977,7 @@ public class MinpackTest extends TestCase {
return jacobian; return jacobian;
} }
public double[] objective(double[] variables) { public double[] value(double[] variables) {
double x1 = variables[0]; double x1 = variables[0];
double x2 = variables[1]; double x2 = variables[1];
double x3 = variables[2]; 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 x1 = variables[0];
double x2 = variables[1]; double x2 = variables[1];
double x3 = variables[2]; double x3 = variables[2];
@ -996,7 +1031,7 @@ public class MinpackTest extends TestCase {
return jacobian; return jacobian;
} }
public double[] objective(double[] variables) { public double[] value(double[] variables) {
double x1 = variables[0]; double x1 = variables[0];
double x2 = variables[1]; double x2 = variables[1];
double x3 = variables[2]; double x3 = variables[2];
@ -1028,7 +1063,7 @@ public class MinpackTest extends TestCase {
theoreticalMinParams); theoreticalMinParams);
} }
public double[][] jacobian(double[] variables, double[] value) { public double[][] jacobian(double[] variables) {
double[][] jacobian = new double[m][]; 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]; double[] f = new double[m];
for (int i = 0; i < (m - 2); ++i) { for (int i = 0; i < (m - 2); ++i) {
double div = (i + 1) / 29.0; double div = (i + 1) / 29.0;
@ -1100,7 +1135,7 @@ public class MinpackTest extends TestCase {
new double[] { 1.0, 10.0, 1.0 }); 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 x1 = variables[0];
double x2 = variables[1]; double x2 = variables[1];
double[][] jacobian = new double[m][]; double[][] jacobian = new double[m][];
@ -1115,7 +1150,7 @@ public class MinpackTest extends TestCase {
return jacobian; return jacobian;
} }
public double[] objective(double[] variables) { public double[] value(double[] variables) {
double x1 = variables[0]; double x1 = variables[0];
double x2 = variables[1]; double x2 = variables[1];
double x3 = variables[2]; double x3 = variables[2];
@ -1142,7 +1177,7 @@ public class MinpackTest extends TestCase {
theoreticalMinParams); theoreticalMinParams);
} }
public double[][] jacobian(double[] variables, double[] value) { public double[][] jacobian(double[] variables) {
double x1 = variables[0]; double x1 = variables[0];
double x2 = variables[1]; double x2 = variables[1];
double[][] jacobian = new double[m][]; double[][] jacobian = new double[m][];
@ -1153,7 +1188,7 @@ public class MinpackTest extends TestCase {
return jacobian; return jacobian;
} }
public double[] objective(double[] variables) { public double[] value(double[] variables) {
double x1 = variables[0]; double x1 = variables[0];
double x2 = variables[1]; double x2 = variables[1];
double[] f = new double[m]; double[] f = new double[m];
@ -1178,7 +1213,7 @@ public class MinpackTest extends TestCase {
theoreticalMinParams); theoreticalMinParams);
} }
public double[][] jacobian(double[] variables, double[] value) { public double[][] jacobian(double[] variables) {
double x1 = variables[0]; double x1 = variables[0];
double x2 = variables[1]; double x2 = variables[1];
double x3 = variables[2]; double x3 = variables[2];
@ -1196,7 +1231,7 @@ public class MinpackTest extends TestCase {
return jacobian; return jacobian;
} }
public double[] objective(double[] variables) { public double[] value(double[] variables) {
double x1 = variables[0]; double x1 = variables[0];
double x2 = variables[1]; double x2 = variables[1];
double x3 = variables[2]; double x3 = variables[2];
@ -1234,7 +1269,7 @@ public class MinpackTest extends TestCase {
theoreticalMinParams); theoreticalMinParams);
} }
public double[][] jacobian(double[] variables, double[] value) { public double[][] jacobian(double[] variables) {
double[][] jacobian = new double[m][]; double[][] jacobian = new double[m][];
for (int i = 0; i < m; ++i) { 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]; double[] f = new double[m];
@ -1307,7 +1342,7 @@ public class MinpackTest extends TestCase {
theoreticalMinParams); theoreticalMinParams);
} }
public double[][] jacobian(double[] variables, double[] value) { public double[][] jacobian(double[] variables) {
double[][] jacobian = new double[m][]; double[][] jacobian = new double[m][];
for (int i = 0; i < m; ++i) { for (int i = 0; i < m; ++i) {
jacobian[i] = new double[n]; 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[] f = new double[m];
double sum = -(n + 1); double sum = -(n + 1);
double prod = 1; double prod = 1;
@ -1369,7 +1404,7 @@ public class MinpackTest extends TestCase {
theoreticalMinParams); theoreticalMinParams);
} }
public double[][] jacobian(double[] variables, double[] value) { public double[][] jacobian(double[] variables) {
double x2 = variables[1]; double x2 = variables[1];
double x3 = variables[2]; double x3 = variables[2];
double x4 = variables[3]; double x4 = variables[3];
@ -1386,7 +1421,7 @@ public class MinpackTest extends TestCase {
return jacobian; return jacobian;
} }
public double[] objective(double[] variables) { public double[] value(double[] variables) {
double x1 = variables[0]; double x1 = variables[0];
double x2 = variables[1]; double x2 = variables[1];
double x3 = variables[2]; double x3 = variables[2];
@ -1422,7 +1457,7 @@ public class MinpackTest extends TestCase {
theoreticalMinParams); theoreticalMinParams);
} }
public double[][] jacobian(double[] variables, double[] value) { public double[][] jacobian(double[] variables) {
double x01 = variables[0]; double x01 = variables[0];
double x02 = variables[1]; double x02 = variables[1];
double x03 = variables[2]; double x03 = variables[2];
@ -1458,7 +1493,7 @@ public class MinpackTest extends TestCase {
return jacobian; return jacobian;
} }
public double[] objective(double[] variables) { public double[] value(double[] variables) {
double x01 = variables[0]; double x01 = variables[0];
double x02 = variables[1]; double x02 = variables[1];
double x03 = variables[2]; double x03 = variables[2];