updated optimization main interfaces to handle scalar and vectorial functions

and to handle functions with or without explicit derivatives

git-svn-id: https://svn.apache.org/repos/asf/commons/proper/math/trunk@754499 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Luc Maisonobe 2009-03-14 17:35:49 +00:00
parent 4f206ca3ee
commit 27c1eb726a
23 changed files with 763 additions and 183 deletions

View File

@ -54,6 +54,29 @@
<!-- the following expositions of internal representation are intentional and documented -->
<Match>
<Class name="org.apache.commons.math.optimization.PointValuePair"/>
<Method name="getPointRef" params="" returns="double[]" />
<Bug pattern="EI_EXPOSE_REP" />
</Match>
<Match>
<Class name="org.apache.commons.math.optimization.PointValuePair"/>
<Method name="&lt;init>" params="double[],double,boolean" returns="void" />
<Bug pattern="EI_EXPOSE_REP2" />
</Match>
<Match>
<Class name="org.apache.commons.math.optimization.VectorialPointValuePair"/>
<Or>
<Method name="getPointRef" params="" returns="double[]" />
<Method name="getValueRef" params="" returns="double[]" />
</Or>
<Bug pattern="EI_EXPOSE_REP" />
</Match>
<Match>
<Class name="org.apache.commons.math.optimization.VectorialPointValuePair"/>
<Method name="&lt;init>" params="double[],double[][],boolean" returns="void" />
<Bug pattern="EI_EXPOSE_REP2" />
</Match>
<Match>
<Class name="org.apache.commons.math.ode.sampling.AbstractStepInterpolator"/>
<Or>

View File

@ -71,6 +71,7 @@ public class MessagesResources_fr
// org.apache.commons.math.DimensionMismatchException
// org.apache.commons.math.optimization.LeastSquaresConverter
// org.apache.commons.math.optimization.direct.DirectSearchOptimizer
// org.apache.commons.math.optimization.general.AbstractLeastSquaresOptimizer
{ "dimension mismatch {0} != {1}",
"dimensions incompatibles {0} != {1}" },
@ -116,16 +117,19 @@ public class MessagesResources_fr
"le simplex doit contenir au moins un point" },
{ "equals vertices {0} and {1} in simplex configuration",
"sommets {0} et {1} \u00e9gaux dans la configuration du simplex" },
// org.apache.commons.math.optimization.direct.DirectSearchOptimizer
// org.apache.commons.math.optimization.general.AbstractLeastSquaresOptimizer
{ "maximal number of evaluations exceeded ({0})",
"nombre maximal d''\u00e9valuations d\u00e9pass\u00e9 ({0})" },
// org.apache.commons.math.optimization.general.AbstractEstimator
// org.apache.commons.math.optimization.general.AbstractLeastSquaresOptimizer
{ "unable to compute covariances: singular problem",
"impossible de calculer les covariances : probl\u00e8me singulier"},
{ "no degrees of freedom ({0} measurements, {1} parameters)",
"aucun degr\u00e9 de libert\u00e9 ({0} mesures, {1} param\u00e8tres)" },
// org.apache.commons.math.optimization.general.GaussNewtonEstimator
// org.apache.commons.math.optimization.general.GaussNewtonOptimizer
{ "unable to solve: singular problem",
"r\u00e9solution impossible : probl\u00e8me singulier" },

View File

@ -20,8 +20,8 @@ package org.apache.commons.math.optimization;
import org.apache.commons.math.MathRuntimeException;
import org.apache.commons.math.linear.RealMatrix;
/** This class converts {@link MultiObjectiveFunction vectorial
* objective functions} to {@link ObjectiveFunction scalar objective functions}
/** This class converts {@link VectorialObjectiveFunction vectorial
* objective functions} to {@link ScalarObjectiveFunction scalar objective functions}
* when the goal is to minimize them.
* <p>
* This class is mostly used when the vectorial objective function represents
@ -35,7 +35,7 @@ import org.apache.commons.math.linear.RealMatrix;
* This class computes a possibly weighted squared sum of the residuals, which is
* a scalar value. The residuals are the difference between the theoretical model
* (i.e. the output of the vectorial objective function) and the observations. The
* class implements the {@link ObjectiveFunction} interface and can therefore be
* class implements the {@link ScalarObjectiveFunction} interface and can therefore be
* minimized by any optimizer supporting scalar objectives functions.This is one way
* to perform a least square estimation. There are other ways to do this without using
* this converter, as some optimization algorithms directly support vectorial objective
@ -45,19 +45,19 @@ import org.apache.commons.math.linear.RealMatrix;
* This class support combination of residuals with or without weights and correlations.
* </p>
*
* @see ObjectiveFunction
* @see MultiObjectiveFunction
* @see ScalarObjectiveFunction
* @see VectorialObjectiveFunction
* @version $Revision$ $Date$
* @since 2.0
*/
public class LeastSquaresConverter implements ObjectiveFunction {
public class LeastSquaresConverter implements ScalarObjectiveFunction {
/** Serializable version identifier. */
private static final long serialVersionUID = 2424320989874772110L;
private static final long serialVersionUID = -4369653306135732243L;
/** Underlying vectorial function. */
private final MultiObjectiveFunction function;
private final VectorialObjectiveFunction function;
/** Observations to be compared to objective function to compute residuals. */
private final double[] observations;
@ -72,8 +72,8 @@ public class LeastSquaresConverter implements ObjectiveFunction {
* @param function vectorial residuals function to wrap
* @param observations observations to be compared to objective function to compute residuals
*/
public LeastSquaresConverter (final MultiObjectiveFunction function,
final double[] observations) {
public LeastSquaresConverter(final VectorialObjectiveFunction function,
final double[] observations) {
this.function = function;
this.observations = observations.clone();
this.weights = null;
@ -108,8 +108,8 @@ public class LeastSquaresConverter implements ObjectiveFunction {
* vector dimensions don't match (objective function dimension is checked only when
* the {@link #objective} method is called)
*/
public LeastSquaresConverter (final MultiObjectiveFunction function,
final double[] observations, final double[] weights)
public LeastSquaresConverter(final VectorialObjectiveFunction function,
final double[] observations, final double[] weights)
throws IllegalArgumentException {
if (observations.length != weights.length) {
throw MathRuntimeException.createIllegalArgumentException(
@ -141,8 +141,8 @@ public class LeastSquaresConverter implements ObjectiveFunction {
* matrix dimensions don't match (objective function dimension is checked only when
* the {@link #objective} method is called)
*/
public LeastSquaresConverter (final MultiObjectiveFunction function,
final double[] observations, final RealMatrix scale)
public LeastSquaresConverter(final VectorialObjectiveFunction function,
final double[] observations, final RealMatrix scale)
throws IllegalArgumentException {
if (observations.length != scale.getColumnDimension()) {
throw MathRuntimeException.createIllegalArgumentException(

View File

@ -25,7 +25,7 @@ import org.apache.commons.math.MathRuntimeException;
import org.apache.commons.math.random.RandomVectorGenerator;
/**
* Special implementation of the {@link Optimizer} interface adding
* Special implementation of the {@link ScalarOptimizer} interface adding
* multi-start features to an existing optimizer.
* <p>
* This class wraps a classical optimizer to use it several times in
@ -35,13 +35,13 @@ import org.apache.commons.math.random.RandomVectorGenerator;
* @version $Revision$ $Date$
* @since 2.0
*/
public class MultiStartOptimizer implements Optimizer {
public class MultiStartOptimizer implements ScalarOptimizer {
/** Serializable version identifier. */
private static final long serialVersionUID = 6648351778723282863L;
/** Underlying classical optimizer. */
private final Optimizer optimizer;
private final ScalarOptimizer optimizer;
/** Number of evaluations already performed for all starts. */
private int totalEvaluations;
@ -56,7 +56,7 @@ public class MultiStartOptimizer implements Optimizer {
private RandomVectorGenerator generator;
/** Found optima. */
private PointValuePair[] optima;
private ScalarPointValuePair[] optima;
/**
* Create a multi-start optimizer from a single-start optimizer
@ -66,7 +66,7 @@ public class MultiStartOptimizer implements Optimizer {
* equal to 1
* @param generator random vector generator to use for restarts
*/
public MultiStartOptimizer(final Optimizer optimizer, final int starts,
public MultiStartOptimizer(final ScalarOptimizer optimizer, final int starts,
final RandomVectorGenerator generator) {
this.optimizer = optimizer;
this.totalEvaluations = 0;
@ -77,13 +77,13 @@ public class MultiStartOptimizer implements Optimizer {
}
/** Get all the optima found during the last call to {@link
* #optimize(ObjectiveFunction, GoalType, double[]) optimize}.
* #optimize(ScalarObjectiveFunction, GoalType, double[]) optimize}.
* <p>The optimizer stores all the optima found during a set of
* restarts. The {@link #optimize(ObjectiveFunction, GoalType,
* restarts. The {@link #optimize(ScalarObjectiveFunction, GoalType,
* double[]) optimize} method returns the best point only. This
* method returns all the points found at the end of each starts,
* including the best one already returned by the {@link
* #optimize(ObjectiveFunction, GoalType, double[]) optimize}
* #optimize(ScalarObjectiveFunction, GoalType, double[]) optimize}
* method.
* </p>
* <p>
@ -93,20 +93,20 @@ public class MultiStartOptimizer implements Optimizer {
* objective value (i.e in ascending order if minimizing and in
* descending order if maximizing), followed by and null elements
* corresponding to the runs that did not converge. This means all
* elements will be null if the {@link #optimize(ObjectiveFunction,
* elements will be null if the {@link #optimize(ScalarObjectiveFunction,
* GoalType, double[]) optimize} method did throw a {@link
* ConvergenceException ConvergenceException}). This also means that
* if the first element is non null, it is the best point found across
* all starts.</p>
* @return array containing the optima
* @exception IllegalStateException if {@link #optimize(ObjectiveFunction,
* @exception IllegalStateException if {@link #optimize(ScalarObjectiveFunction,
* GoalType, double[]) optimize} has not been called
*/
public PointValuePair[] getOptima() throws IllegalStateException {
public ScalarPointValuePair[] getOptima() throws IllegalStateException {
if (optima == null) {
throw MathRuntimeException.createIllegalStateException("no optimum computed yet");
}
return (PointValuePair[]) optima.clone();
return (ScalarPointValuePair[]) optima.clone();
}
/** {@inheritDoc} */
@ -125,22 +125,22 @@ public class MultiStartOptimizer implements Optimizer {
}
/** {@inheritDoc} */
public void setConvergenceChecker(ConvergenceChecker checker) {
public void setConvergenceChecker(ScalarConvergenceChecker checker) {
optimizer.setConvergenceChecker(checker);
}
/** {@inheritDoc} */
public ConvergenceChecker getConvergenceChecker() {
public ScalarConvergenceChecker getConvergenceChecker() {
return optimizer.getConvergenceChecker();
}
/** {@inheritDoc} */
public PointValuePair optimize(final ObjectiveFunction f,
public ScalarPointValuePair optimize(final ScalarObjectiveFunction f,
final GoalType goalType,
double[] startPoint)
throws ObjectiveException, OptimizationException {
optima = new PointValuePair[starts];
optima = new ScalarPointValuePair[starts];
totalEvaluations = 0;
// multi-start loop
@ -161,8 +161,8 @@ public class MultiStartOptimizer implements Optimizer {
}
// sort the optima from best to worst, followed by null elements
Arrays.sort(optima, new Comparator<PointValuePair>() {
public int compare(final PointValuePair o1, final PointValuePair o2) {
Arrays.sort(optima, new Comparator<ScalarPointValuePair>() {
public int compare(final ScalarPointValuePair o1, final ScalarPointValuePair o2) {
if (o1 == null) {
return (o2 == null) ? 0 : +1;
} else if (o2 == null) {

View File

@ -19,7 +19,7 @@ package org.apache.commons.math.optimization;
import java.io.Serializable;
/** This interface specifies how to check if an {@link Optimizer optimization
/** This interface specifies how to check if an {@link ScalarOptimizer optimization
* algorithm} has converged.
*
* <p>Deciding if convergence has been reached is a problem-dependent
@ -31,7 +31,7 @@ import java.io.Serializable;
* @since 2.0
*/
public interface ConvergenceChecker extends Serializable {
public interface ScalarConvergenceChecker extends Serializable {
/** Check if the optimization algorithm has converged considering the last points.
* <p>
@ -47,6 +47,6 @@ public interface ConvergenceChecker extends Serializable {
* @param current point from current iteration
* @return true if the algorithm is considered to have converged
*/
boolean converged(int iteration, PointValuePair previous, PointValuePair current);
boolean converged(int iteration, ScalarPointValuePair previous, ScalarPointValuePair current);
}

View File

@ -0,0 +1,37 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math.optimization;
/**
* This interface represents a scalar objective function that can be differentiated.
* @version $Revision$ $Date$
* @since 2.0
*/
public interface ScalarDifferentiableObjectiveFunction extends ScalarObjectiveFunction {
/**
* Compute the partial derivatives of the objective function.
* @param variables variables set
* @return partial derivatives of the objective function
* @exception ObjectiveException if no value can be computed for the parameters
* @exception IllegalArgumentException if variables dimension is wrong
*/
double[] partials(double[] variables)
throws ObjectiveException, IllegalArgumentException;
}

View File

@ -0,0 +1,91 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math.optimization;
import java.io.Serializable;
/**
* This interface represents an optimization algorithm for {@link ScalarDifferentiableObjectiveFunction
* scalar differentiable objective functions}.
* @see ScalarOptimizer
* @see VectorialDifferentiableOptimizer
* @version $Revision$ $Date$
* @since 2.0
*/
public interface ScalarDifferentiableOptimizer extends Serializable {
/** Set the maximal number of objective function calls.
* <p>
* The number of objective function calls may be checked <em>after</em> a few
* related calls have been made. This implies that in some cases this number may
* be exceeded by a few units, depending on the dimension of the problem and kind
* of optimizer.
* </p>
* @param maxEvaluations maximal number of function calls
* .
*/
void setMaxEvaluations(int maxEvaluations);
/** Get the maximal number of objective function calls.
* <p>
* The number of objective function calls may be checked <em>after</em> a few
* related calls have been made. This implies that in some cases this number may
* be exceeded by a few units, depending on the dimension of the problem and kind
* of optimizer.
* </p>
* @return maximal number of function calls
*/
int getMaxEvaluations();
/** Get the number of evaluations of the objective function.
* <p>
* The number of evaluation correspond to the last call to the
* {@link #optimize(ScalarObjectiveFunction, GoalType, double[]) optimize}
* method. It is 0 if the method has not been called yet.
* </p>
* @return number of evaluations of the objective function
*/
int getEvaluations();
/** Set the convergence checker.
* @param checker object to use to check for convergence
*/
void setConvergenceChecker(ScalarConvergenceChecker checker);
/** Get the convergence checker.
* @param checker object to use to check for convergence
*/
ScalarConvergenceChecker getConvergenceChecker();
/** Optimizes an objective function.
* @param f objective function
* @param goalType type of optimization goal: either {@link GoalType#MAXIMIZE}
* or {@link GoalType#MINIMIZE}
* @param startPoint the start point for optimization
* @return the point/value pair giving the optimal value for objective function
* @exception ObjectiveException 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
*/
ScalarPointValuePair optimize(ScalarDifferentiableObjectiveFunction f,
GoalType goalType,
double[] startPoint)
throws ObjectiveException, OptimizationException, IllegalArgumentException;
}

View File

@ -22,9 +22,9 @@ import java.io.Serializable;
/**
* This interface represents a scalar objective function to be either minimized or maximized.
* @version $Revision$ $Date$
* @since 1.2
* @since 2.0
*/
public interface ObjectiveFunction extends Serializable {
public interface ScalarObjectiveFunction extends Serializable {
/**
* Compute the function value for the given variables set.

View File

@ -20,11 +20,14 @@ package org.apache.commons.math.optimization;
import java.io.Serializable;
/**
* This interface represents an optimization algorithm.
* This interface represents an optimization algorithm for {@link ScalarObjectiveFunction
* scalar objective functions}.
* @see ScalarDifferentiableOptimizer
* @see VectorialDifferentiableOptimizer
* @version $Revision$ $Date$
* @since 2.0
*/
public interface Optimizer extends Serializable {
public interface ScalarOptimizer extends Serializable {
/** Set the maximal number of objective function calls.
* <p>
@ -49,15 +52,25 @@ public interface Optimizer extends Serializable {
*/
int getMaxEvaluations();
/** Get the number of evaluations of the objective function.
* <p>
* The number of evaluation correspond to the last call to the
* {@link #optimize(ScalarObjectiveFunction, GoalType, double[]) optimize}
* method. It is 0 if the method has not been called yet.
* </p>
* @return number of evaluations of the objective function
*/
int getEvaluations();
/** Set the convergence checker.
* @param checker object to use to check for convergence
*/
void setConvergenceChecker(ConvergenceChecker checker);
void setConvergenceChecker(ScalarConvergenceChecker checker);
/** Get the convergence checker.
* @param checker object to use to check for convergence
*/
ConvergenceChecker getConvergenceChecker();
ScalarConvergenceChecker getConvergenceChecker();
/** Optimizes an objective function.
* @param f objective function
@ -70,18 +83,9 @@ public interface Optimizer extends Serializable {
* @exception OptimizationException if the algorithm failed to converge
* @exception IllegalArgumentException if the start point dimension is wrong
*/
PointValuePair optimize(ObjectiveFunction f, GoalType goalType,
double[] startPoint)
ScalarPointValuePair optimize(ScalarObjectiveFunction f,
GoalType goalType,
double[] startPoint)
throws ObjectiveException, OptimizationException, IllegalArgumentException;
/** Get the number of evaluations of the objective function.
* <p>
* The number of evaluation correspond to the last call to the
* {@link #optimize(ObjectiveFunction, GoalType, double[]) optimize}
* method. It is 0 if the method has not been called yet.
* </p>
* @return number of evaluations of the objective function
*/
int getEvaluations();
}

View File

@ -22,11 +22,12 @@ import java.io.Serializable;
/**
* This class holds a point and the value of an objective function at this point.
* <p>This is a simple immutable container.</p>
* @see VectorialPointValuePair
* @see ScalarObjectiveFunction
* @version $Revision$ $Date$
* @see ObjectiveFunction
* @since 2.0
*/
public class PointValuePair implements Serializable {
public class ScalarPointValuePair implements Serializable {
/** Serializable version identifier. */
private static final long serialVersionUID = 1003888396256744753L;
@ -42,11 +43,24 @@ public class PointValuePair implements Serializable {
* a copy of the array, not the array passed as argument)
* @param value value of an objective function at the point
*/
public PointValuePair(final double[] point, final double value) {
public ScalarPointValuePair(final double[] point, final double value) {
this.point = point.clone();
this.value = value;
}
/** Build a point/objective function value pair.
* @param point point coordinates (the built instance will store
* a copy of the array, not the array passed as argument)
* @param value value of an objective function at the point
* @param copyArray if true, the input array will be copied, otherwise
* it will be referenced
*/
public ScalarPointValuePair(final double[] point, final double value,
final boolean copyArray) {
this.point = copyArray ? point.clone() : point;
this.value = value;
}
/** Get the point.
* @return a copy of the stored point
*/
@ -54,6 +68,15 @@ public class PointValuePair implements Serializable {
return point.clone();
}
/** Get a reference to the point.
* <p>This method is provided as a convenience to avoid copying
* the array, the elements of the array should <em>not</em> be modified.</p>
* @return a reference to the internal array storing the point
*/
public double[] getPointRef() {
return point;
}
/** Get the value of the objective function.
* @return the stored value of the objective function
*/

View File

@ -20,7 +20,7 @@ package org.apache.commons.math.optimization;
import org.apache.commons.math.util.MathUtils;
/**
* Special implementation of the {@link ConvergenceChecker} interface using
* Simple implementation of the {@link ScalarConvergenceChecker} interface using
* only objective function values.
* <p>
* Convergence is considered to have been reached if either the relative
@ -31,7 +31,7 @@ import org.apache.commons.math.util.MathUtils;
* @version $Revision$ $Date$
* @since 2.0
*/
public class ObjectiveValueChecker implements ConvergenceChecker {
public class SimpleValueChecker implements ScalarConvergenceChecker {
/** Serializable version identifier. */
private static final long serialVersionUID = 2490271385513842607L;
@ -50,7 +50,7 @@ public class ObjectiveValueChecker implements ConvergenceChecker {
/** Build an instance with default threshold.
*/
public ObjectiveValueChecker() {
public SimpleValueChecker() {
this.relativeThreshold = DEFAULT_RELATIVE_THRESHOLD;
this.absoluteThreshold = DEFAULT_ABSOLUTE_THRESHOLD;
}
@ -64,7 +64,7 @@ public class ObjectiveValueChecker implements ConvergenceChecker {
* @param relativeThreshold relative tolerance threshold
* @param absoluteThreshold absolute tolerance threshold
*/
public ObjectiveValueChecker(final double relativeThreshold,
public SimpleValueChecker(final double relativeThreshold,
final double absoluteThreshold) {
this.relativeThreshold = relativeThreshold;
this.absoluteThreshold = absoluteThreshold;
@ -72,8 +72,8 @@ public class ObjectiveValueChecker implements ConvergenceChecker {
/** {@inheritDoc} */
public boolean converged(final int iteration,
final PointValuePair previous,
final PointValuePair current) {
final ScalarPointValuePair previous,
final ScalarPointValuePair current) {
final double p = previous.getValue();
final double c = current.getValue();
final double difference = Math.abs(p - c);

View File

@ -0,0 +1,92 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math.optimization;
import org.apache.commons.math.util.MathUtils;
/**
* Simple implementation of the {@link VectorialConvergenceChecker} interface using
* only objective function values.
* <p>
* Convergence is considered to have been reached if either the relative
* difference between the objective function values is smaller than a
* threshold or if either the absolute difference between the objective
* function values is smaller than another threshold for all vectors elements.
* </p>
* @version $Revision$ $Date$
* @since 2.0
*/
public class SimpleVectorialValueChecker implements VectorialConvergenceChecker {
/** Serializable version identifier. */
private static final long serialVersionUID = -3892196630780700808L;
/** Default relative threshold. */
private static final double DEFAULT_RELATIVE_THRESHOLD = 100 * MathUtils.EPSILON;
/** Default absolute threshold. */
private static final double DEFAULT_ABSOLUTE_THRESHOLD = 100 * MathUtils.SAFE_MIN;
/** Relative tolerance threshold. */
private final double relativeThreshold;
/** Absolute tolerance threshold. */
private final double absoluteThreshold;
/** Build an instance with default threshold.
*/
public SimpleVectorialValueChecker() {
this.relativeThreshold = DEFAULT_RELATIVE_THRESHOLD;
this.absoluteThreshold = DEFAULT_ABSOLUTE_THRESHOLD;
}
/** Build an instance with a specified threshold.
* <p>
* In order to perform only relative checks, the absolute tolerance
* must be set to a negative value. In order to perform only absolute
* checks, the relative tolerance must be set to a negative value.
* </p>
* @param relativeThreshold relative tolerance threshold
* @param absoluteThreshold absolute tolerance threshold
*/
public SimpleVectorialValueChecker(final double relativeThreshold,
final double absoluteThreshold) {
this.relativeThreshold = relativeThreshold;
this.absoluteThreshold = absoluteThreshold;
}
/** {@inheritDoc} */
public boolean converged(final int iteration,
final VectorialPointValuePair previous,
final VectorialPointValuePair current) {
final double[] p = previous.getValueRef();
final double[] c = current.getValueRef();
for (int i = 0; i < p.length; ++i) {
final double pi = p[i];
final double ci = c[i];
final double difference = Math.abs(pi - ci);
final double size = Math.max(Math.abs(pi), Math.abs(ci));
if ((difference > (size * relativeThreshold)) &&
(difference > absoluteThreshold)) {
return false;
}
}
return true;
}
}

View File

@ -0,0 +1,52 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math.optimization;
import java.io.Serializable;
/** This interface specifies how to check if an {@link VectorialOptimizer optimization
* algorithm} has converged.
*
* <p>Deciding if convergence has been reached is a problem-dependent
* issue. The user should provide a class implementing this interface
* to allow the optimization algorithm to stop its search according to
* the problem at hand.</p>
*
* @version $Revision$ $Date$
* @since 2.0
*/
public interface VectorialConvergenceChecker extends Serializable {
/** Check if the optimization algorithm has converged considering the last points.
* <p>
* This method may be called several time from the same algorithm iteration with
* different points. This can be detected by checking the iteration number at each
* call if needed. Each time this method is called, the previous and current point
* correspond to points with the same role at each iteration, so they can be
* compared. As an example, simplex-based algorithms call this method for all
* points of the simplex, not only for the best or worst ones.
* </p>
* @param iteration index of current iteration
* @param previous point from previous iteration
* @param current point from current iteration
* @return true if the algorithm is considered to have converged
*/
boolean converged(int iteration, VectorialPointValuePair previous, VectorialPointValuePair current);
}

View File

@ -0,0 +1,38 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math.optimization;
/**
* This interface represents a vectorial objective function that can be differentiated.
* @version $Revision$ $Date$
* @since 2.0
*/
public interface VectorialDifferentiableObjectiveFunction extends VectorialObjectiveFunction {
/**
* Compute the jacobian of the objective function.
* @param variables variables set
* @param value value of the objective function (already computed)
* @return jacobian of the objective function
* @exception ObjectiveException if no cost can be computed for the parameters
* @exception IllegalArgumentException if variables dimension is wrong
*/
double[][] jacobian(double[] variables, double[] value)
throws ObjectiveException, IllegalArgumentException;
}

View File

@ -0,0 +1,96 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math.optimization;
import java.io.Serializable;
/**
* This interface represents an optimization algorithm for {@link VectorialDifferentiableObjectiveFunction
* vectorial differentiable objective functions}.
* @see ScalarOptimizer
* @see ScalarDifferentiableOptimizer
* @version $Revision$ $Date$
* @since 2.0
*/
public interface VectorialDifferentiableOptimizer extends Serializable {
/** Set the maximal number of objective function calls.
* <p>
* The number of objective function calls may be checked <em>after</em> a few
* related calls have been made. This implies that in some cases this number may
* be exceeded by a few units, depending on the dimension of the problem and kind
* of optimizer.
* </p>
* @param maxEvaluations maximal number of function calls
* .
*/
void setMaxEvaluations(int maxEvaluations);
/** Get the maximal number of objective function calls.
* <p>
* The number of objective function calls may be checked <em>after</em> a few
* related calls have been made. This implies that in some cases this number may
* be exceeded by a few units, depending on the dimension of the problem and kind
* of optimizer.
* </p>
* @return maximal number of function calls
*/
int getMaxEvaluations();
/** Get the number of evaluations of the objective function.
* <p>
* The number of evaluation correspond to the last call to the
* {@link #optimize(ObjectiveFunction, GoalType, double[]) optimize}
* method. It is 0 if the method has not been called yet.
* </p>
* @return number of evaluations of the objective function
*/
int getEvaluations();
/** Set the convergence checker.
* @param checker object to use to check for convergence
*/
void setConvergenceChecker(VectorialConvergenceChecker checker);
/** Get the convergence checker.
* @param checker object to use to check for convergence
*/
VectorialConvergenceChecker getConvergenceChecker();
/** Optimizes an objective function.
* <p>
* Optimization is considered to be a weighted least-squares minimization.
* The cost function to be minimized is
* &sum;weight<sub>i</sub>(objective<sub>i</sub>-target<sub>i</sub>)<sup>2</sup>
* </p>
* @param f objective function
* @param target target value for the objective functions at optimum
* @param weights weight for the least squares cost computation
* @param startPoint the start point for optimization
* @return the point/value pair giving the optimal value for objective function
* @exception ObjectiveException 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
*/
VectorialPointValuePair optimize(VectorialDifferentiableObjectiveFunction f,
double[] target, double[] weights,
double[] startPoint)
throws ObjectiveException, OptimizationException, IllegalArgumentException;
}

View File

@ -25,7 +25,7 @@ import java.io.Serializable;
* @version $Revision$ $Date$
* @since 2.0
*/
public interface MultiObjectiveFunction extends Serializable {
public interface VectorialObjectiveFunction extends Serializable {
/**
* Compute the function value for the given variables set.

View File

@ -0,0 +1,96 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math.optimization;
import java.io.Serializable;
/**
* This class holds a point and the vectorial value of an objective function at this point.
* <p>This is a simple immutable container.</p>
* @see ScalarPointValuePair
* @see VectorialObjectiveFunction
* @version $Revision$ $Date$
* @since 2.0
*/
public class VectorialPointValuePair implements Serializable {
/** Serializable version identifier. */
private static final long serialVersionUID = 1003888396256744753L;
/** Point coordinates. */
private final double[] point;
/** Vectorial value of the objective function at the point. */
private final double[] value;
/** Build a point/objective function value pair.
* @param point point coordinates (the built instance will store
* a copy of the array, not the array passed as argument)
* @param value value of an objective function at the point
*/
public VectorialPointValuePair(final double[] point, final double[] value) {
this.point = point.clone();
this.value = value.clone();
}
/** Build a point/objective function value pair.
* @param point point coordinates (the built instance will store
* a copy of the array, not the array passed as argument)
* @param value value of an objective function at the point
* @param copyArray if true, the input arrays will be copied, otherwise
* they will be referenced
*/
public VectorialPointValuePair(final double[] point, final double[] value,
final boolean copyArray) {
this.point = copyArray ? point.clone() : point;
this.value = copyArray ? value.clone() : value;
}
/** Get the point.
* @return a copy of the stored point
*/
public double[] getPoint() {
return point.clone();
}
/** Get a reference to the point.
* <p>This method is provided as a convenience to avoid copying
* the array, the elements of the array should <em>not</em> be modified.</p>
* @return a reference to the internal array storing the point
*/
public double[] getPointRef() {
return point;
}
/** Get the value of the objective function.
* @return a copy of the stored value of the objective function
*/
public double[] getValue() {
return value.clone();
}
/** Get a reference to the value of the objective function.
* <p>This method is provided as a convenience to avoid copying
* the array, the elements of the array should <em>not</em> be modified.</p>
* @return a reference to the internal array storing the value of the objective function
*/
public double[] getValueRef() {
return value;
}
}

View File

@ -21,14 +21,14 @@ import java.util.Arrays;
import java.util.Comparator;
import org.apache.commons.math.MathRuntimeException;
import org.apache.commons.math.optimization.ConvergenceChecker;
import org.apache.commons.math.optimization.ScalarConvergenceChecker;
import org.apache.commons.math.optimization.GoalType;
import org.apache.commons.math.optimization.ObjectiveException;
import org.apache.commons.math.optimization.ObjectiveFunction;
import org.apache.commons.math.optimization.ScalarObjectiveFunction;
import org.apache.commons.math.optimization.OptimizationException;
import org.apache.commons.math.optimization.Optimizer;
import org.apache.commons.math.optimization.PointValuePair;
import org.apache.commons.math.optimization.ObjectiveValueChecker;
import org.apache.commons.math.optimization.ScalarOptimizer;
import org.apache.commons.math.optimization.ScalarPointValuePair;
import org.apache.commons.math.optimization.SimpleValueChecker;
/**
* This class implements simplex-based direct search optimization
@ -57,15 +57,15 @@ import org.apache.commons.math.optimization.ObjectiveValueChecker;
* before optimization is attempted, an explicit call to the first method
* with all steps set to +1 is triggered, thus building a default
* configuration from a unit hypercube. Each call to {@link
* #optimize(ObjectiveFunction, GoalType, double[]) optimize} will reuse
* #optimize(ScalarObjectiveFunction, GoalType, double[]) optimize} will reuse
* the current start configuration and move it such that its first vertex
* is at the provided start point of the optimization. If the same optimizer
* is used to solve different problems and the number of parameters change,
* the start configuration <em>must</em> be reset or a dimension mismatch
* will occur.</p>
*
* <p>If {@link #setConvergenceChecker(ConvergenceChecker)} is not called,
* a default {@link ObjectiveValueChecker} is used.</p>
* <p>If {@link #setConvergenceChecker(ScalarConvergenceChecker)} is not called,
* a default {@link SimpleValueChecker} is used.</p>
*
* <p>Convergence is checked by providing the <em>worst</em> points of
* previous and current simplex to the convergence checker, not the best ones.</p>
@ -75,25 +75,25 @@ import org.apache.commons.math.optimization.ObjectiveValueChecker;
* performed by the derived classes according to the implemented
* algorithms.</p>
*
* @see ObjectiveFunction
* @see ScalarObjectiveFunction
* @see NelderMead
* @see MultiDirectional
* @version $Revision$ $Date$
* @since 1.2
*/
public abstract class DirectSearchOptimizer implements Optimizer {
public abstract class DirectSearchOptimizer implements ScalarOptimizer {
/** Serializable version identifier. */
private static final long serialVersionUID = 4299910390345933369L;
/** Simplex. */
protected PointValuePair[] simplex;
protected ScalarPointValuePair[] simplex;
/** Objective function. */
private ObjectiveFunction f;
private ScalarObjectiveFunction f;
/** Convergence checker. */
private ConvergenceChecker checker;
private ScalarConvergenceChecker checker;
/** Number of evaluations already performed for the current start. */
private int evaluations;
@ -107,7 +107,8 @@ public abstract class DirectSearchOptimizer implements Optimizer {
/** Simple constructor.
*/
protected DirectSearchOptimizer() {
setConvergenceChecker(new ObjectiveValueChecker());
setConvergenceChecker(new SimpleValueChecker());
setMaxEvaluations(Integer.MAX_VALUE);
}
/** Set start configuration for simplex.
@ -217,17 +218,17 @@ public abstract class DirectSearchOptimizer implements Optimizer {
}
/** {@inheritDoc} */
public void setConvergenceChecker(ConvergenceChecker checker) {
public void setConvergenceChecker(ScalarConvergenceChecker checker) {
this.checker = checker;
}
/** {@inheritDoc} */
public ConvergenceChecker getConvergenceChecker() {
public ScalarConvergenceChecker getConvergenceChecker() {
return checker;
}
/** {@inheritDoc} */
public PointValuePair optimize(final ObjectiveFunction f, final GoalType goalType,
public ScalarPointValuePair optimize(final ScalarObjectiveFunction f, final GoalType goalType,
final double[] startPoint)
throws ObjectiveException, OptimizationException, IllegalArgumentException {
@ -240,8 +241,8 @@ public abstract class DirectSearchOptimizer implements Optimizer {
}
this.f = f;
final Comparator<PointValuePair> comparator = new Comparator<PointValuePair>() {
public int compare(final PointValuePair o1, final PointValuePair o2) {
final Comparator<ScalarPointValuePair> comparator = new Comparator<ScalarPointValuePair>() {
public int compare(final ScalarPointValuePair o1, final ScalarPointValuePair o2) {
final double v1 = o1.getValue();
final double v2 = o2.getValue();
return (goalType == GoalType.MINIMIZE) ?
@ -254,7 +255,7 @@ public abstract class DirectSearchOptimizer implements Optimizer {
buildSimplex(startPoint);
evaluateSimplex(comparator);
PointValuePair[] previous = new PointValuePair[simplex.length];
ScalarPointValuePair[] previous = new ScalarPointValuePair[simplex.length];
int iterations = 0;
while (evaluations <= maxEvaluations) {
@ -293,7 +294,7 @@ public abstract class DirectSearchOptimizer implements Optimizer {
* @exception OptimizationException if the algorithm failed to converge
* @exception IllegalArgumentException if the start point dimension is wrong
*/
protected abstract void iterateSimplex(final Comparator<PointValuePair> comparator)
protected abstract void iterateSimplex(final Comparator<ScalarPointValuePair> comparator)
throws ObjectiveException, OptimizationException, IllegalArgumentException;
/** Evaluate the objective function on one point.
@ -325,8 +326,8 @@ public abstract class DirectSearchOptimizer implements Optimizer {
}
// set first vertex
simplex = new PointValuePair[n + 1];
simplex[0] = new PointValuePair(startPoint, Double.NaN);
simplex = new ScalarPointValuePair[n + 1];
simplex[0] = new ScalarPointValuePair(startPoint, Double.NaN);
// set remaining vertices
for (int i = 0; i < n; ++i) {
@ -335,7 +336,7 @@ public abstract class DirectSearchOptimizer implements Optimizer {
for (int k = 0; k < n; ++k) {
vertexI[k] = startPoint[k] + confI[k];
}
simplex[i + 1] = new PointValuePair(vertexI, Double.NaN);
simplex[i + 1] = new ScalarPointValuePair(vertexI, Double.NaN);
}
}
@ -344,15 +345,15 @@ public abstract class DirectSearchOptimizer implements Optimizer {
* @param comparator comparator to use to sort simplex vertices from best to worst
* @exception ObjectiveException if no value can be computed for the parameters
*/
protected void evaluateSimplex(final Comparator<PointValuePair> comparator)
protected void evaluateSimplex(final Comparator<ScalarPointValuePair> comparator)
throws ObjectiveException {
// evaluate the objective function at all non-evaluated simplex points
for (int i = 0; i < simplex.length; ++i) {
final PointValuePair vertex = simplex[i];
final double[] point = vertex.getPoint();
final ScalarPointValuePair vertex = simplex[i];
final double[] point = vertex.getPointRef();
if (Double.isNaN(vertex.getValue())) {
simplex[i] = new PointValuePair(point, evaluate(point));
simplex[i] = new ScalarPointValuePair(point, evaluate(point), false);
}
}
@ -365,12 +366,12 @@ public abstract class DirectSearchOptimizer implements Optimizer {
* @param pointValuePair point to insert
* @param comparator comparator to use to sort simplex vertices from best to worst
*/
protected void replaceWorstPoint(PointValuePair pointValuePair,
final Comparator<PointValuePair> comparator) {
protected void replaceWorstPoint(ScalarPointValuePair pointValuePair,
final Comparator<ScalarPointValuePair> comparator) {
int n = simplex.length - 1;
for (int i = 0; i < n; ++i) {
if (comparator.compare(simplex[i], pointValuePair) > 0) {
PointValuePair tmp = simplex[i];
ScalarPointValuePair tmp = simplex[i];
simplex[i] = pointValuePair;
pointValuePair = tmp;
}

View File

@ -21,7 +21,7 @@ import java.util.Comparator;
import org.apache.commons.math.optimization.ObjectiveException;
import org.apache.commons.math.optimization.OptimizationException;
import org.apache.commons.math.optimization.PointValuePair;
import org.apache.commons.math.optimization.ScalarPointValuePair;
/**
* This class implements the multi-directional direct search method.
@ -59,23 +59,23 @@ public class MultiDirectional extends DirectSearchOptimizer {
}
/** {@inheritDoc} */
protected void iterateSimplex(final Comparator<PointValuePair> comparator)
protected void iterateSimplex(final Comparator<ScalarPointValuePair> comparator)
throws ObjectiveException, OptimizationException, IllegalArgumentException {
final int max = getMaxEvaluations();
while (getEvaluations() < max) {
// save the original vertex
final PointValuePair[] original = simplex;
final PointValuePair best = original[0];
final ScalarPointValuePair[] original = simplex;
final ScalarPointValuePair best = original[0];
// perform a reflection step
final PointValuePair reflected = evaluateNewSimplex(original, 1.0, comparator);
final ScalarPointValuePair reflected = evaluateNewSimplex(original, 1.0, comparator);
if (comparator.compare(reflected, best) < 0) {
// compute the expanded simplex
final PointValuePair[] reflectedSimplex = simplex;
final PointValuePair expanded = evaluateNewSimplex(original, khi, comparator);
final ScalarPointValuePair[] reflectedSimplex = simplex;
final ScalarPointValuePair expanded = evaluateNewSimplex(original, khi, comparator);
if (comparator.compare(reflected, expanded) <= 0) {
// accept the reflected simplex
simplex = reflectedSimplex;
@ -86,7 +86,7 @@ public class MultiDirectional extends DirectSearchOptimizer {
}
// compute the contracted simplex
final PointValuePair contracted = evaluateNewSimplex(original, gamma, comparator);
final ScalarPointValuePair contracted = evaluateNewSimplex(original, gamma, comparator);
if (comparator.compare(contracted, best) < 0) {
// accept the contracted simplex
return;
@ -108,24 +108,24 @@ public class MultiDirectional extends DirectSearchOptimizer {
* @exception ObjectiveException if the function cannot be evaluated at
* some point
*/
private PointValuePair evaluateNewSimplex(final PointValuePair[] original,
private ScalarPointValuePair evaluateNewSimplex(final ScalarPointValuePair[] original,
final double coeff,
final Comparator<PointValuePair> comparator)
final Comparator<ScalarPointValuePair> comparator)
throws ObjectiveException {
final double[] xSmallest = original[0].getPoint();
final double[] xSmallest = original[0].getPointRef();
final int n = xSmallest.length;
// create the linearly transformed simplex
simplex = new PointValuePair[n + 1];
simplex = new ScalarPointValuePair[n + 1];
simplex[0] = original[0];
for (int i = 1; i <= n; ++i) {
final double[] xOriginal = original[i].getPoint();
final double[] xOriginal = original[i].getPointRef();
final double[] xTransformed = new double[n];
for (int j = 0; j < n; ++j) {
xTransformed[j] = xSmallest[j] + coeff * (xSmallest[j] - xOriginal[j]);
}
simplex[i] = new PointValuePair(xTransformed, Double.NaN);
simplex[i] = new ScalarPointValuePair(xTransformed, Double.NaN, false);
}
// evaluate it

View File

@ -20,7 +20,7 @@ package org.apache.commons.math.optimization.direct;
import java.util.Comparator;
import org.apache.commons.math.optimization.ObjectiveException;
import org.apache.commons.math.optimization.PointValuePair;
import org.apache.commons.math.optimization.ScalarPointValuePair;
/**
* This class implements the Nelder-Mead direct search method.
@ -72,23 +72,23 @@ public class NelderMead extends DirectSearchOptimizer {
}
/** {@inheritDoc} */
protected void iterateSimplex(final Comparator<PointValuePair> comparator)
protected void iterateSimplex(final Comparator<ScalarPointValuePair> comparator)
throws ObjectiveException {
// the simplex has n+1 point if dimension is n
final int n = simplex.length - 1;
// interesting values
final PointValuePair best = simplex[0];
final PointValuePair secondBest = simplex[n-1];
final PointValuePair worst = simplex[n];
final double[] xWorst = worst.getPoint();
final ScalarPointValuePair best = simplex[0];
final ScalarPointValuePair secondBest = simplex[n-1];
final ScalarPointValuePair worst = simplex[n];
final double[] xWorst = worst.getPointRef();
// compute the centroid of the best vertices
// (dismissing the worst point at index n)
final double[] centroid = new double[n];
for (int i = 0; i < n; ++i) {
final double[] x = simplex[i].getPoint();
final double[] x = simplex[i].getPointRef();
for (int j = 0; j < n; ++j) {
centroid[j] += x[j];
}
@ -103,7 +103,7 @@ public class NelderMead extends DirectSearchOptimizer {
for (int j = 0; j < n; ++j) {
xR[j] = centroid[j] + rho * (centroid[j] - xWorst[j]);
}
final PointValuePair reflected = new PointValuePair(xR, evaluate(xR));
final ScalarPointValuePair reflected = new ScalarPointValuePair(xR, evaluate(xR), false);
if ((comparator.compare(best, reflected) <= 0) &&
(comparator.compare(reflected, secondBest) < 0)) {
@ -118,7 +118,7 @@ public class NelderMead extends DirectSearchOptimizer {
for (int j = 0; j < n; ++j) {
xE[j] = centroid[j] + khi * (xR[j] - centroid[j]);
}
final PointValuePair expanded = new PointValuePair(xE, evaluate(xE));
final ScalarPointValuePair expanded = new ScalarPointValuePair(xE, evaluate(xE), false);
if (comparator.compare(expanded, reflected) < 0) {
// accept the expansion point
@ -137,7 +137,7 @@ public class NelderMead extends DirectSearchOptimizer {
for (int j = 0; j < n; ++j) {
xC[j] = centroid[j] + gamma * (xR[j] - centroid[j]);
}
final PointValuePair outContracted = new PointValuePair(xC, evaluate(xC));
final ScalarPointValuePair outContracted = new ScalarPointValuePair(xC, evaluate(xC), false);
if (comparator.compare(outContracted, reflected) <= 0) {
// accept the contraction point
@ -152,7 +152,7 @@ public class NelderMead extends DirectSearchOptimizer {
for (int j = 0; j < n; ++j) {
xC[j] = centroid[j] - gamma * (centroid[j] - xWorst[j]);
}
final PointValuePair inContracted = new PointValuePair(xC, evaluate(xC));
final ScalarPointValuePair inContracted = new ScalarPointValuePair(xC, evaluate(xC), false);
if (comparator.compare(inContracted, worst) < 0) {
// accept the contraction point
@ -163,13 +163,13 @@ public class NelderMead extends DirectSearchOptimizer {
}
// perform a shrink
final double[] xSmallest = simplex[0].getPoint();
final double[] xSmallest = simplex[0].getPointRef();
for (int i = 1; i < simplex.length; ++i) {
final double[] x = simplex[i].getPoint();
for (int j = 0; j < n; ++j) {
x[j] = xSmallest[j] + sigma * (x[j] - xSmallest[j]);
}
simplex[i] = new PointValuePair(x, Double.NaN);
simplex[i] = new ScalarPointValuePair(x, Double.NaN, false);
}
evaluateSimplex(comparator);

View File

@ -19,45 +19,68 @@
<body>
<p>
This package provides common interfaces for the optimization algorithms
provided in sub-packages. The main interfaces are {@link
org.apache.commons.math.optimization.ObjectiveFunction ObjectiveFunction}
and {@link org.apache.commons.math.optimization.MultiObjectiveFunction
MultiObjectiveFunction}. Both interfaces are intended to be implemented by
user code to represent the problem they want to optimize.
provided in sub-packages. The main interfaces defines objective functions
and optimzers.
</p>
<p>
The {@link org.apache.commons.math.optimization.ObjectiveFunction ObjectiveFunction}
interface represent a scalar function that should be either minimized or maximized,
by changing its input variables set until an optimal set is found. This function is
often called a cost function when the goal is to minimize it.
Objective functions interfaces are intended to be implemented by
user code to represent the problem to minimize or maximize. When the goal is to
minimize, the objective function is often called a cost function. Objective
functions can be either scalar or vectorial and can be either differentiable or
not. There are four different interfaces, one for each case:
<ul>
<li>{@link org.apache.commons.math.optimization.ScalarObjectiveFunction
ScalarObjectiveFunction}</li>
<li>{@link org.apache.commons.math.optimization.ScalarDifferentiableObjectiveFunction
ScalarDifferentiableObjectiveFunction}</li>
<li>{@link org.apache.commons.math.optimization.VectorialObjectiveFunction
VectorialObjectiveFunction}</li>
<li>{@link org.apache.commons.math.optimization.VectorialDifferentiableObjectiveFunction
VectorialDifferentiableObjectiveFunction}</li>
</ul>
</p>
<p>
The {@link org.apache.commons.math.optimization.MultiObjectiveFunction
MultiObjectiveFunction} interface represent a vectorial function that should be either
minimized or maximized, by changing its input variables set until an optimal set is
found.
</p>
<p>
The {@link org.apache.commons.math.optimization.LeastSquaresConverter
LeastSquaresConverter} class can be used to convert vectorial objective functions to
scalar objective functions when the goal is to minimize them. This class is mostly used
when the vectorial objective function represents theoretical results computed from a
variables set applied to a model that should be fit against observations. Subtracting the
observations from the theoretical results give residuals. Residuals are intended to be
minimized in order to get the variables set that best fit the model to the observations.
The observations may be obtained for example from physical measurements whether the model
is built from theoretical considerations.
Optimizers are the algorithms that will either minimize or maximize, the objective function
by changing its input variables set until an optimal set is found. There are only three
interfaces defining the common behavior of optimizers, one for each type of objective
function except {@link org.apache.commons.math.optimization.VectorialObjectiveFunction
VectorialObjectiveFunction}:
<ul>
<li>{@link org.apache.commons.math.optimization.ScalarOptimizer
ScalarOptimizer}</li>
<li>{@link org.apache.commons.math.optimization.ScalarDifferentiableOptimizer
ScalarDifferentiableOptimizer}</li>
<li>{@link org.apache.commons.math.optimization.VectorialDifferentiableOptimizer
VectorialDifferentiableOptimizer}</li>
</ul>
</p>
<p>
The {@link org.apache.commons.math.optimization.Optimizer Optimizer} interface represents
the optimization algorithm by itself. Several implementations of this interface are
available for different kind of problems. There is also one special implementations, the
{@link org.apache.commons.math.optimization.MultiStartOptimizer MultiStartOptimizer} which
wraps a classical optimizer to use it several times in row with different starting points
in order to avoid being trapped into a local extremum when looking for a global one.
Despite there are only three types of supported optimizers, it is possible to optimize a
transform a non-differentiable {@link
org.apache.commons.math.optimization.VectorialObjectiveFunction VectorialObjectiveFunction}
by transforming into a {@link org.apache.commons.math.optimization.ScalarObjectiveFunction
ScalarObjectiveFunction} thanks to the {@link
org.apache.commons.math.optimization.LeastSquaresConverter LeastSquaresConverter} helper class.
The transformed function can be optimized using any implementation of the {@link
org.apache.commons.math.optimization.ScalarOptimizer ScalarOptimizer} interface.
</p>
<p>
There are also three special implementations which wrap classical optimizers in order to
add them a multi-start feature. This feature call the underlying optimizer several times
in sequence with different starting points and returns the best optimum found or all optima
if desired. This is a classical way to prevent being trapped into a local extremum when
looking for a global one. The multi-start wrappers are {@link
org.apache.commons.math.optimization.MultiStartScalarOptimizer MultiStartScalarOptimizer},
{@link org.apache.commons.math.optimization.MultiStartScalarDifferentiableOptimizer
MultiStartScalarDifferentiableOptimizer} and {@link
org.apache.commons.math.optimization.MultiStartMultiStartVectorialOptimizer
MultiStartVectorialOptimizer}.
</p>
</body>
</html>

View File

@ -25,9 +25,9 @@ import org.apache.commons.math.ConvergenceException;
import org.apache.commons.math.linear.decomposition.NotPositiveDefiniteMatrixException;
import org.apache.commons.math.optimization.GoalType;
import org.apache.commons.math.optimization.ObjectiveException;
import org.apache.commons.math.optimization.ObjectiveFunction;
import org.apache.commons.math.optimization.PointValuePair;
import org.apache.commons.math.optimization.ObjectiveValueChecker;
import org.apache.commons.math.optimization.ScalarObjectiveFunction;
import org.apache.commons.math.optimization.ScalarPointValuePair;
import org.apache.commons.math.optimization.SimpleValueChecker;
public class MultiDirectionalTest
extends TestCase {
@ -37,8 +37,8 @@ public class MultiDirectionalTest
}
public void testObjectiveExceptions() throws ConvergenceException {
ObjectiveFunction wrong =
new ObjectiveFunction() {
ScalarObjectiveFunction wrong =
new ScalarObjectiveFunction() {
private static final long serialVersionUID = 4751314470965489371L;
public double objective(double[] x) throws ObjectiveException {
if (x[0] < 0) {
@ -84,7 +84,7 @@ public class MultiDirectionalTest
final double valueXmYp = -valueXmYm; // local minimum
final double valueXpYm = -0.7290400707055187115322; // global minimum
final double valueXpYp = -valueXpYm; // global maximum
ObjectiveFunction fourExtrema = new ObjectiveFunction() {
ScalarObjectiveFunction fourExtrema = new ScalarObjectiveFunction() {
private static final long serialVersionUID = -7039124064449091152L;
public double objective(double[] variables) {
final double x = variables[0];
@ -94,10 +94,10 @@ public class MultiDirectionalTest
};
MultiDirectional optimizer = new MultiDirectional();
optimizer.setConvergenceChecker(new ObjectiveValueChecker(1.0e-10, 1.0e-30));
optimizer.setConvergenceChecker(new SimpleValueChecker(1.0e-10, 1.0e-30));
optimizer.setMaxEvaluations(200);
optimizer.setStartConfiguration(new double[] { 0.2, 0.2 });
PointValuePair optimum;
ScalarPointValuePair optimum;
// minimization
optimum = optimizer.optimize(fourExtrema, GoalType.MINIMIZE, new double[] { -3.0, 0 });
@ -134,8 +134,8 @@ public class MultiDirectionalTest
public void testRosenbrock()
throws ObjectiveException, ConvergenceException {
ObjectiveFunction rosenbrock =
new ObjectiveFunction() {
ScalarObjectiveFunction rosenbrock =
new ScalarObjectiveFunction() {
private static final long serialVersionUID = -9044950469615237490L;
public double objective(double[] x) {
++count;
@ -147,12 +147,12 @@ public class MultiDirectionalTest
count = 0;
MultiDirectional optimizer = new MultiDirectional();
optimizer.setConvergenceChecker(new ObjectiveValueChecker(-1, 1.0e-3));
optimizer.setConvergenceChecker(new SimpleValueChecker(-1, 1.0e-3));
optimizer.setMaxEvaluations(100);
optimizer.setStartConfiguration(new double[][] {
{ -1.2, 1.0 }, { 0.9, 1.2 } , { 3.5, -2.3 }
});
PointValuePair optimum =
ScalarPointValuePair optimum =
optimizer.optimize(rosenbrock, GoalType.MINIMIZE, new double[] { -1.2, 1.0 });
assertEquals(count, optimizer.getEvaluations());
@ -165,8 +165,8 @@ public class MultiDirectionalTest
public void testPowell()
throws ObjectiveException, ConvergenceException {
ObjectiveFunction powell =
new ObjectiveFunction() {
ScalarObjectiveFunction powell =
new ScalarObjectiveFunction() {
private static final long serialVersionUID = -832162886102041840L;
public double objective(double[] x) {
++count;
@ -180,9 +180,9 @@ public class MultiDirectionalTest
count = 0;
MultiDirectional optimizer = new MultiDirectional();
optimizer.setConvergenceChecker(new ObjectiveValueChecker(-1.0, 1.0e-3));
optimizer.setConvergenceChecker(new SimpleValueChecker(-1.0, 1.0e-3));
optimizer.setMaxEvaluations(1000);
PointValuePair optimum =
ScalarPointValuePair optimum =
optimizer.optimize(powell, GoalType.MINIMIZE, new double[] { 3.0, -1.0, 0.0, 1.0 });
assertEquals(count, optimizer.getEvaluations());
assertTrue(optimizer.getEvaluations() > 800);

View File

@ -25,9 +25,9 @@ import org.apache.commons.math.ConvergenceException;
import org.apache.commons.math.linear.decomposition.NotPositiveDefiniteMatrixException;
import org.apache.commons.math.optimization.GoalType;
import org.apache.commons.math.optimization.ObjectiveException;
import org.apache.commons.math.optimization.ObjectiveFunction;
import org.apache.commons.math.optimization.PointValuePair;
import org.apache.commons.math.optimization.ObjectiveValueChecker;
import org.apache.commons.math.optimization.ScalarObjectiveFunction;
import org.apache.commons.math.optimization.ScalarPointValuePair;
import org.apache.commons.math.optimization.SimpleValueChecker;
public class NelderMeadTest
extends TestCase {
@ -37,8 +37,8 @@ public class NelderMeadTest
}
public void testObjectiveExceptions() throws ConvergenceException {
ObjectiveFunction wrong =
new ObjectiveFunction() {
ScalarObjectiveFunction wrong =
new ScalarObjectiveFunction() {
private static final long serialVersionUID = 4751314470965489371L;
public double objective(double[] x) throws ObjectiveException {
if (x[0] < 0) {
@ -84,7 +84,7 @@ public class NelderMeadTest
final double valueXmYp = -valueXmYm; // local minimum
final double valueXpYm = -0.7290400707055187115322; // global minimum
final double valueXpYp = -valueXpYm; // global maximum
ObjectiveFunction fourExtrema = new ObjectiveFunction() {
ScalarObjectiveFunction fourExtrema = new ScalarObjectiveFunction() {
private static final long serialVersionUID = -7039124064449091152L;
public double objective(double[] variables) {
final double x = variables[0];
@ -94,10 +94,10 @@ public class NelderMeadTest
};
NelderMead optimizer = new NelderMead();
optimizer.setConvergenceChecker(new ObjectiveValueChecker(1.0e-10, 1.0e-30));
optimizer.setConvergenceChecker(new SimpleValueChecker(1.0e-10, 1.0e-30));
optimizer.setMaxEvaluations(100);
optimizer.setStartConfiguration(new double[] { 0.2, 0.2 });
PointValuePair optimum;
ScalarPointValuePair optimum;
// minimization
optimum = optimizer.optimize(fourExtrema, GoalType.MINIMIZE, new double[] { -3.0, 0 });
@ -134,8 +134,8 @@ public class NelderMeadTest
public void testRosenbrock()
throws ObjectiveException, ConvergenceException {
ObjectiveFunction rosenbrock =
new ObjectiveFunction() {
ScalarObjectiveFunction rosenbrock =
new ScalarObjectiveFunction() {
private static final long serialVersionUID = -9044950469615237490L;
public double objective(double[] x) {
++count;
@ -147,12 +147,12 @@ public class NelderMeadTest
count = 0;
NelderMead optimizer = new NelderMead();
optimizer.setConvergenceChecker(new ObjectiveValueChecker(-1, 1.0e-3));
optimizer.setConvergenceChecker(new SimpleValueChecker(-1, 1.0e-3));
optimizer.setMaxEvaluations(100);
optimizer.setStartConfiguration(new double[][] {
{ -1.2, 1.0 }, { 0.9, 1.2 } , { 3.5, -2.3 }
});
PointValuePair optimum =
ScalarPointValuePair optimum =
optimizer.optimize(rosenbrock, GoalType.MINIMIZE, new double[] { -1.2, 1.0 });
assertEquals(count, optimizer.getEvaluations());
@ -165,8 +165,8 @@ public class NelderMeadTest
public void testPowell()
throws ObjectiveException, ConvergenceException {
ObjectiveFunction powell =
new ObjectiveFunction() {
ScalarObjectiveFunction powell =
new ScalarObjectiveFunction() {
private static final long serialVersionUID = -832162886102041840L;
public double objective(double[] x) {
++count;
@ -180,9 +180,9 @@ public class NelderMeadTest
count = 0;
NelderMead optimizer = new NelderMead();
optimizer.setConvergenceChecker(new ObjectiveValueChecker(-1.0, 1.0e-3));
optimizer.setConvergenceChecker(new SimpleValueChecker(-1.0, 1.0e-3));
optimizer.setMaxEvaluations(200);
PointValuePair optimum =
ScalarPointValuePair optimum =
optimizer.optimize(powell, GoalType.MINIMIZE, new double[] { 3.0, -1.0, 0.0, 1.0 });
assertEquals(count, optimizer.getEvaluations());
assertTrue(optimizer.getEvaluations() > 110);