MATH-394, MATH-397, MATH-404
Overhaul of the "optimization" package. Removed lots of duplicate code. Removed methods referring to the concept of "iteration". Removed interface methods to access the number of evaluations of the gradient and Jacobian. Removed all references to "OptimizationException" (replaced by "ConvergenceException"). Javadoc comments updated. git-svn-id: https://svn.apache.org/repos/asf/commons/proper/math/trunk@990792 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
320194b3cb
commit
a21faeae6e
|
@ -26,6 +26,8 @@ package org.apache.commons.math;
|
||||||
* @see ConvergenceException
|
* @see ConvergenceException
|
||||||
* @version $Revision$ $Date$
|
* @version $Revision$ $Date$
|
||||||
* @since 2.0
|
* @since 2.0
|
||||||
|
* @deprecated in 2.2 (to be removed in 3.0). Please use
|
||||||
|
* {@link IterativeAlgorithm} instead.
|
||||||
*/
|
*/
|
||||||
public interface ConvergingAlgorithm {
|
public interface ConvergingAlgorithm {
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@ package org.apache.commons.math;
|
||||||
*
|
*
|
||||||
* @version $Revision$ $Date$
|
* @version $Revision$ $Date$
|
||||||
* @since 2.0
|
* @since 2.0
|
||||||
|
* @deprecated in 2.2 (to be removed in 3.0).
|
||||||
*/
|
*/
|
||||||
public abstract class ConvergingAlgorithmImpl implements ConvergingAlgorithm {
|
public abstract class ConvergingAlgorithmImpl implements ConvergingAlgorithm {
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,85 @@
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base class for all convergence checker implementations.
|
||||||
|
*
|
||||||
|
* @version $Revision$ $Date$
|
||||||
|
* @since 3.0
|
||||||
|
*/
|
||||||
|
public abstract class AbstractConvergenceChecker<T>
|
||||||
|
implements ConvergenceChecker<T> {
|
||||||
|
/**
|
||||||
|
* 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 thresholds.
|
||||||
|
*/
|
||||||
|
public AbstractConvergenceChecker() {
|
||||||
|
this.relativeThreshold = DEFAULT_RELATIVE_THRESHOLD;
|
||||||
|
this.absoluteThreshold = DEFAULT_ABSOLUTE_THRESHOLD;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build an instance with a specified thresholds.
|
||||||
|
*
|
||||||
|
* @param relativeThreshold relative tolerance threshold
|
||||||
|
* @param absoluteThreshold absolute tolerance threshold
|
||||||
|
*/
|
||||||
|
public AbstractConvergenceChecker(final double relativeThreshold,
|
||||||
|
final double absoluteThreshold) {
|
||||||
|
this.relativeThreshold = relativeThreshold;
|
||||||
|
this.absoluteThreshold = absoluteThreshold;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public double getRelativeThreshold() {
|
||||||
|
return relativeThreshold;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public double getAbsoluteThreshold() {
|
||||||
|
return absoluteThreshold;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public abstract boolean converged(int iteration, T ... points);
|
||||||
|
}
|
|
@ -0,0 +1,195 @@
|
||||||
|
/*
|
||||||
|
* 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.util.Arrays;
|
||||||
|
import java.util.Comparator;
|
||||||
|
|
||||||
|
import org.apache.commons.math.FunctionEvaluationException;
|
||||||
|
import org.apache.commons.math.exception.MathIllegalStateException;
|
||||||
|
import org.apache.commons.math.exception.ConvergenceException;
|
||||||
|
import org.apache.commons.math.analysis.MultivariateRealFunction;
|
||||||
|
import org.apache.commons.math.exception.util.LocalizedFormats;
|
||||||
|
import org.apache.commons.math.random.RandomVectorGenerator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base class for all implementations of a multi-start optimizer.
|
||||||
|
*
|
||||||
|
* This interface is mainly intended to enforce the internal coherence of
|
||||||
|
* Commons-Math. Users of the API are advised to base their code on
|
||||||
|
* {@link MultiStartMultivariateRealOptimizer} or on
|
||||||
|
* {@link MultiStartDifferentiableMultivariateRealOptimizer}.
|
||||||
|
*
|
||||||
|
* @param <FUNC> Type of the objective function to be optimized.
|
||||||
|
*
|
||||||
|
* @version $Revision$ $Date$
|
||||||
|
* @since 3.0
|
||||||
|
*/
|
||||||
|
public class BaseMultiStartMultivariateRealOptimizer<FUNC extends MultivariateRealFunction>
|
||||||
|
implements BaseMultivariateRealOptimizer<FUNC> {
|
||||||
|
/** Underlying classical optimizer. */
|
||||||
|
private final BaseMultivariateRealOptimizer<FUNC> optimizer;
|
||||||
|
/** Maximal number of evaluations allowed. */
|
||||||
|
private int maxEvaluations;
|
||||||
|
/** Number of evaluations already performed for all starts. */
|
||||||
|
private int totalEvaluations;
|
||||||
|
/** Number of starts to go. */
|
||||||
|
private int starts;
|
||||||
|
/** Random generator for multi-start. */
|
||||||
|
private RandomVectorGenerator generator;
|
||||||
|
/** Found optima. */
|
||||||
|
private RealPointValuePair[] optima;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a multi-start optimizer from a single-start optimizer.
|
||||||
|
*
|
||||||
|
* @param optimizer Single-start optimizer to wrap.
|
||||||
|
* @param starts Number of starts to perform (including the
|
||||||
|
* first one), multi-start is disabled if value is less than or
|
||||||
|
* equal to 1.
|
||||||
|
* @param generator Random vector generator to use for restarts.
|
||||||
|
*/
|
||||||
|
protected BaseMultiStartMultivariateRealOptimizer(final BaseMultivariateRealOptimizer<FUNC> optimizer,
|
||||||
|
final int starts,
|
||||||
|
final RandomVectorGenerator generator) {
|
||||||
|
this.optimizer = optimizer;
|
||||||
|
this.starts = starts;
|
||||||
|
this.generator = generator;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all the optima found during the last call to {@link
|
||||||
|
* #optimize(FUNC,GoalType,double[]) optimize}.
|
||||||
|
* The optimizer stores all the optima found during a set of
|
||||||
|
* restarts. The {@link #optimize(FUNC,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(FUNC,GoalType,double[]) optimize} method.
|
||||||
|
* <br/>
|
||||||
|
* The returned array as one element for each start as specified
|
||||||
|
* in the constructor. It is ordered with the results from the
|
||||||
|
* runs that did converge first, sorted from best to worst
|
||||||
|
* 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(FUNC,GoalType,double[])
|
||||||
|
* optimize} method did throw a {@link ConvergenceException}).
|
||||||
|
* This also means that if the first element is not {@code null}, it
|
||||||
|
* is the best point found across all starts.
|
||||||
|
*
|
||||||
|
* @return an array containing the optima.
|
||||||
|
* @throws MathIllegalStateException if {@link
|
||||||
|
* #optimize(FUNC,GoalType,double[]) optimize} has not been called.
|
||||||
|
*/
|
||||||
|
public RealPointValuePair[] getOptima() {
|
||||||
|
if (optima == null) {
|
||||||
|
throw new MathIllegalStateException(LocalizedFormats.NO_OPTIMUM_COMPUTED_YET);
|
||||||
|
}
|
||||||
|
return optima.clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** {@inheritDoc} */
|
||||||
|
public int getMaxEvaluations() {
|
||||||
|
return maxEvaluations;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** {@inheritDoc} */
|
||||||
|
public int getEvaluations() {
|
||||||
|
return totalEvaluations;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** {@inheritDoc} */
|
||||||
|
public void setMaxEvaluations(int maxEvaluations) {
|
||||||
|
this.maxEvaluations = maxEvaluations;
|
||||||
|
optimizer.setMaxEvaluations(maxEvaluations);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** {@inheritDoc} */
|
||||||
|
public void setConvergenceChecker(ConvergenceChecker<RealPointValuePair> checker) {
|
||||||
|
optimizer.setConvergenceChecker(checker);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** {@inheritDoc} */
|
||||||
|
public ConvergenceChecker<RealPointValuePair> getConvergenceChecker() {
|
||||||
|
return optimizer.getConvergenceChecker();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param f Function to optimize.
|
||||||
|
* @param goal Goal type ({@link GoalType#MINIMIZE} or
|
||||||
|
* {@link GoalType#MAXIMIZE}).
|
||||||
|
* @param startPoint Start point.
|
||||||
|
*/
|
||||||
|
public RealPointValuePair optimize(final FUNC f,
|
||||||
|
final GoalType goal,
|
||||||
|
double[] startPoint)
|
||||||
|
throws FunctionEvaluationException {
|
||||||
|
optima = new RealPointValuePair[starts];
|
||||||
|
|
||||||
|
// Multi-start loop.
|
||||||
|
for (int i = 0; i < starts; ++i) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
optima[i] = optimizer.optimize(f, goal,
|
||||||
|
(i == 0 ? startPoint :
|
||||||
|
generator.nextVector()));
|
||||||
|
} catch (FunctionEvaluationException fee) {
|
||||||
|
optima[i] = null;
|
||||||
|
} catch (ConvergenceException oe) {
|
||||||
|
optima[i] = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
final int usedEvaluations = optimizer.getEvaluations();
|
||||||
|
optimizer.setMaxEvaluations(optimizer.getMaxEvaluations() - usedEvaluations);
|
||||||
|
totalEvaluations += usedEvaluations;
|
||||||
|
}
|
||||||
|
|
||||||
|
sortPairs(goal);
|
||||||
|
|
||||||
|
if (optima[0] == null) {
|
||||||
|
throw new ConvergenceException(LocalizedFormats.NO_CONVERGENCE_WITH_ANY_START_POINT,
|
||||||
|
starts);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the found point given the best objective function value.
|
||||||
|
return optima[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sort the optima from best to worst, followed by {@code null} elements.
|
||||||
|
*
|
||||||
|
* @param goal Goal type.
|
||||||
|
*/
|
||||||
|
private void sortPairs(final GoalType goal) {
|
||||||
|
Arrays.sort(optima, new Comparator<RealPointValuePair>() {
|
||||||
|
public int compare(final RealPointValuePair o1,
|
||||||
|
final RealPointValuePair o2) {
|
||||||
|
if (o1 == null) {
|
||||||
|
return (o2 == null) ? 0 : 1;
|
||||||
|
} else if (o2 == null) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
final double v1 = o1.getValue();
|
||||||
|
final double v2 = o2.getValue();
|
||||||
|
return (goal == GoalType.MINIMIZE) ?
|
||||||
|
Double.compare(v1, v2) : Double.compare(v2, v1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,202 @@
|
||||||
|
/*
|
||||||
|
* 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.util.Arrays;
|
||||||
|
import java.util.Comparator;
|
||||||
|
|
||||||
|
import org.apache.commons.math.FunctionEvaluationException;
|
||||||
|
import org.apache.commons.math.exception.MathIllegalStateException;
|
||||||
|
import org.apache.commons.math.exception.ConvergenceException;
|
||||||
|
import org.apache.commons.math.analysis.MultivariateVectorialFunction;
|
||||||
|
import org.apache.commons.math.exception.util.LocalizedFormats;
|
||||||
|
import org.apache.commons.math.random.RandomVectorGenerator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base class for all implementations of a multi-start optimizer.
|
||||||
|
*
|
||||||
|
* This interface is mainly intended to enforce the internal coherence of
|
||||||
|
* Commons-Math. Users of the API are advised to base their code on
|
||||||
|
* {@link MultiStartDifferentiableMultivariateVectorialOptimizer}.
|
||||||
|
*
|
||||||
|
* @param <FUNC> Type of the objective function to be optimized.
|
||||||
|
*
|
||||||
|
* @version $Revision$ $Date$
|
||||||
|
* @since 3.0
|
||||||
|
*/
|
||||||
|
public class BaseMultiStartMultivariateVectorialOptimizer<FUNC extends MultivariateVectorialFunction>
|
||||||
|
implements BaseMultivariateVectorialOptimizer<FUNC> {
|
||||||
|
/** Underlying classical optimizer. */
|
||||||
|
private final BaseMultivariateVectorialOptimizer<FUNC> optimizer;
|
||||||
|
/** Maximal number of evaluations allowed. */
|
||||||
|
private int maxEvaluations;
|
||||||
|
/** Number of evaluations already performed for all starts. */
|
||||||
|
private int totalEvaluations;
|
||||||
|
/** Number of starts to go. */
|
||||||
|
private int starts;
|
||||||
|
/** Random generator for multi-start. */
|
||||||
|
private RandomVectorGenerator generator;
|
||||||
|
/** Found optima. */
|
||||||
|
private VectorialPointValuePair[] optima;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a multi-start optimizer from a single-start optimizer.
|
||||||
|
*
|
||||||
|
* @param optimizer Single-start optimizer to wrap.
|
||||||
|
* @param starts Number of starts to perform (including the
|
||||||
|
* first one), multi-start is disabled if value is less than or
|
||||||
|
* equal to 1.
|
||||||
|
* @param generator Random vector generator to use for restarts.
|
||||||
|
*/
|
||||||
|
protected BaseMultiStartMultivariateVectorialOptimizer(final BaseMultivariateVectorialOptimizer<FUNC> optimizer,
|
||||||
|
final int starts,
|
||||||
|
final RandomVectorGenerator generator) {
|
||||||
|
this.optimizer = optimizer;
|
||||||
|
this.starts = starts;
|
||||||
|
this.generator = generator;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all the optima found during the last call to {@link
|
||||||
|
* #optimize(FUNC,double[],double[],double[]) optimize}.
|
||||||
|
* The optimizer stores all the optima found during a set of
|
||||||
|
* restarts. The {@link #optimize(FUNC,double[],double[],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(FUNC,double[],double[],double[]) optimize} method.
|
||||||
|
* <br/>
|
||||||
|
* The returned array as one element for each start as specified
|
||||||
|
* in the constructor. It is ordered with the results from the
|
||||||
|
* runs that did converge first, sorted from best to worst
|
||||||
|
* 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(FUNC,double[],double[],double[]) optimize} method did
|
||||||
|
* throw a {@link ConvergenceException}). This also means that if
|
||||||
|
* the first element is not {@code null}, it is the best point found
|
||||||
|
* across all starts.
|
||||||
|
*
|
||||||
|
* @return array containing the optima
|
||||||
|
* @throws MathIllegalStateException if {@link
|
||||||
|
* #optimize(FUNC,double[],double[],double[]) optimize} has not been
|
||||||
|
* called.
|
||||||
|
*/
|
||||||
|
public VectorialPointValuePair[] getOptima() {
|
||||||
|
if (optima == null) {
|
||||||
|
throw new MathIllegalStateException(LocalizedFormats.NO_OPTIMUM_COMPUTED_YET);
|
||||||
|
}
|
||||||
|
return optima.clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** {@inheritDoc} */
|
||||||
|
public int getMaxEvaluations() {
|
||||||
|
return maxEvaluations;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** {@inheritDoc} */
|
||||||
|
public int getEvaluations() {
|
||||||
|
return totalEvaluations;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** {@inheritDoc} */
|
||||||
|
public void setMaxEvaluations(int maxEvaluations) {
|
||||||
|
this.maxEvaluations = maxEvaluations;
|
||||||
|
optimizer.setMaxEvaluations(maxEvaluations);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** {@inheritDoc} */
|
||||||
|
public void setConvergenceChecker(ConvergenceChecker<VectorialPointValuePair> checker) {
|
||||||
|
optimizer.setConvergenceChecker(checker);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** {@inheritDoc} */
|
||||||
|
public ConvergenceChecker<VectorialPointValuePair> getConvergenceChecker() {
|
||||||
|
return optimizer.getConvergenceChecker();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public VectorialPointValuePair optimize(final FUNC f,
|
||||||
|
double[] target, double[] weights,
|
||||||
|
double[] startPoint)
|
||||||
|
throws FunctionEvaluationException {
|
||||||
|
|
||||||
|
optima = new VectorialPointValuePair[starts];
|
||||||
|
|
||||||
|
// Multi-start loop.
|
||||||
|
for (int i = 0; i < starts; ++i) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
optima[i] = optimizer.optimize(f, target, weights,
|
||||||
|
(i == 0 ? startPoint :
|
||||||
|
generator.nextVector()));
|
||||||
|
} catch (FunctionEvaluationException fee) {
|
||||||
|
optima[i] = null;
|
||||||
|
} catch (ConvergenceException oe) {
|
||||||
|
optima[i] = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
final int usedEvaluations = optimizer.getEvaluations();
|
||||||
|
optimizer.setMaxEvaluations(optimizer.getMaxEvaluations() - usedEvaluations);
|
||||||
|
totalEvaluations += usedEvaluations;
|
||||||
|
}
|
||||||
|
|
||||||
|
sortPairs(target, weights);
|
||||||
|
|
||||||
|
if (optima[0] == null) {
|
||||||
|
throw new ConvergenceException(LocalizedFormats.NO_CONVERGENCE_WITH_ANY_START_POINT,
|
||||||
|
starts);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the found point given the best objective function value.
|
||||||
|
return optima[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sort the optima from best to worst, followed by {@code null} elements.
|
||||||
|
*
|
||||||
|
* @param target Target value for the objective functions at optimum.
|
||||||
|
* @param weights Weights for the least-squares cost computation.
|
||||||
|
*/
|
||||||
|
private void sortPairs(final double[] target,
|
||||||
|
final double[] weights) {
|
||||||
|
Arrays.sort(optima, new Comparator<VectorialPointValuePair>() {
|
||||||
|
public int compare(final VectorialPointValuePair o1,
|
||||||
|
final VectorialPointValuePair o2) {
|
||||||
|
if (o1 == null) {
|
||||||
|
return (o2 == null) ? 0 : 1;
|
||||||
|
} else if (o2 == null) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return Double.compare(weightedResidual(o1), weightedResidual(o2));
|
||||||
|
}
|
||||||
|
private double weightedResidual(final VectorialPointValuePair pv) {
|
||||||
|
final double[] value = pv.getValueRef();
|
||||||
|
double sum = 0;
|
||||||
|
for (int i = 0; i < value.length; ++i) {
|
||||||
|
final double ri = value[i] - target[i];
|
||||||
|
sum += weights[i] * ri * ri;
|
||||||
|
}
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -21,95 +21,36 @@ import org.apache.commons.math.FunctionEvaluationException;
|
||||||
import org.apache.commons.math.analysis.MultivariateRealFunction;
|
import org.apache.commons.math.analysis.MultivariateRealFunction;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Optimization algorithms find the input point set that either {@link GoalType
|
|
||||||
* maximize or minimize} an objective function.
|
|
||||||
* This interface is mainly intended to enforce the internal coherence of
|
* This interface is mainly intended to enforce the internal coherence of
|
||||||
* Commons-FastMath. Users of the API are advised to base their code on
|
* Commons-FastMath. Users of the API are advised to base their code on
|
||||||
* {@link MultivariateRealOptimizer} or on
|
* the following interfaces:
|
||||||
* {@link DifferentiableMultivariateRealOptimizer}.
|
* <ul>
|
||||||
* @param <T> the type of the objective function to be optimized
|
* <li>{@link org.apache.commons.math.optimization.MultivariateRealOptimizer}</li>
|
||||||
|
* <li>{@link org.apache.commons.math.optimization.DifferentiableMultivariateRealOptimizer}</li>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* @param <FUNC> Type of the objective function to be optimized.
|
||||||
*
|
*
|
||||||
* @see MultivariateRealOptimizer
|
|
||||||
* @see DifferentiableMultivariateRealOptimizer
|
|
||||||
* @version $Revision$ $Date$
|
* @version $Revision$ $Date$
|
||||||
* @since 2.2
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
public interface BaseMultivariateRealOptimizer<T extends MultivariateRealFunction> {
|
public interface BaseMultivariateRealOptimizer<FUNC extends MultivariateRealFunction>
|
||||||
/**
|
extends BaseOptimizer<RealPointValuePair> {
|
||||||
* Set the maximal number of iterations of the algorithm.
|
|
||||||
*
|
|
||||||
* @param maxIterations Maximal number of algorithm iterations.
|
|
||||||
*/
|
|
||||||
void setMaxIterations(int maxIterations);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the maximal number of iterations of the algorithm.
|
|
||||||
*
|
|
||||||
* @return the maximal number of iterations.
|
|
||||||
*/
|
|
||||||
int getMaxIterations();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the maximal number of functions evaluations.
|
|
||||||
*
|
|
||||||
* @param maxEvaluations Maximal number of function evaluations.
|
|
||||||
*/
|
|
||||||
void setMaxEvaluations(int maxEvaluations);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the maximal number of functions evaluations.
|
|
||||||
*
|
|
||||||
* @return the maximal number of functions evaluations.
|
|
||||||
*/
|
|
||||||
int getMaxEvaluations();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the number of iterations realized by the algorithm.
|
|
||||||
* The number of iterations corresponds to the last call to the
|
|
||||||
* {@code optimize} method. It is 0 if the method has not been
|
|
||||||
* called yet.
|
|
||||||
*
|
|
||||||
* @return the number of iterations.
|
|
||||||
*/
|
|
||||||
int getIterations();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the number of evaluations of the objective function.
|
|
||||||
* The number of evaluations corresponds to the last call to the
|
|
||||||
* {@code optimize} method. It is 0 if the method has not been
|
|
||||||
* called yet.
|
|
||||||
*
|
|
||||||
* @return the number of evaluations of the objective function.
|
|
||||||
*/
|
|
||||||
int getEvaluations();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the convergence checker.
|
|
||||||
*
|
|
||||||
* @param checker Object to use to check for convergence.
|
|
||||||
*/
|
|
||||||
void setConvergenceChecker(RealConvergenceChecker checker);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the convergence checker.
|
|
||||||
*
|
|
||||||
* @return the object used to check for convergence.
|
|
||||||
*/
|
|
||||||
RealConvergenceChecker getConvergenceChecker();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Optimize an objective function.
|
* Optimize an objective function.
|
||||||
*
|
*
|
||||||
* @param f Objective function.
|
* @param f Objective function.
|
||||||
* @param goalType Type of optimization goal: either {@link GoalType#MAXIMIZE}
|
* @param goalType Type of optimization goal: either
|
||||||
* or {@link GoalType#MINIMIZE}.
|
* {@link GoalType#MAXIMIZE} or {@link GoalType#MINIMIZE}.
|
||||||
* @param startPoint Start point for optimization.
|
* @param startPoint Start point for optimization.
|
||||||
* @return the point/value pair giving the optimal value for objective function.
|
* @return the point/value pair giving the optimal value for objective
|
||||||
* @throws FunctionEvaluationException if the objective function throws one during
|
* function.
|
||||||
* the search.
|
* @throws FunctionEvaluationException if the objective function throws one
|
||||||
* @throws OptimizationException if the algorithm failed to converge.
|
* during the search.
|
||||||
* @throws IllegalArgumentException if the start point dimension is wrong.
|
* @throws DimensionMismatchException if the start point dimension is wrong.
|
||||||
|
* @throws TooManyEvaluationsException if the maximal number of evaluations is
|
||||||
|
* exceeded.
|
||||||
*/
|
*/
|
||||||
RealPointValuePair optimize(T f, GoalType goalType, double[] startPoint)
|
RealPointValuePair optimize(FUNC f, GoalType goalType, double[] startPoint)
|
||||||
throws FunctionEvaluationException, OptimizationException;
|
throws FunctionEvaluationException;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,59 @@
|
||||||
|
/*
|
||||||
|
* 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.FunctionEvaluationException;
|
||||||
|
import org.apache.commons.math.analysis.MultivariateVectorialFunction;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This interface is mainly intended to enforce the internal coherence of
|
||||||
|
* Commons-Math. Users of the API are advised to base their code on
|
||||||
|
* the following interfaces:
|
||||||
|
* <ul>
|
||||||
|
* <li>{@link org.apache.commons.math.optimization.DifferentiableMultivariateVectorialOptimizer}</li>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* @param <FUNC> Type of the objective function to be optimized.
|
||||||
|
*
|
||||||
|
* @version $Revision$ $Date$
|
||||||
|
* @since 3.0
|
||||||
|
*/
|
||||||
|
public interface BaseMultivariateVectorialOptimizer<FUNC extends MultivariateVectorialFunction>
|
||||||
|
extends BaseOptimizer<VectorialPointValuePair> {
|
||||||
|
/**
|
||||||
|
* Optimize an objective function.
|
||||||
|
* Optimization is considered to be a weighted least-squares minimization.
|
||||||
|
* The cost function to be minimized is
|
||||||
|
* <code>∑weight<sub>i</sub>(objective<sub>i</sub> - target<sub>i</sub>)<sup>2</sup></code>
|
||||||
|
*
|
||||||
|
* @param f Objective function.
|
||||||
|
* @param target Target value for the objective functions at optimum.
|
||||||
|
* @param weight Weights for the least squares cost computation.
|
||||||
|
* @param startPoint Start point for optimization.
|
||||||
|
* @return the point/value pair giving the optimal value for objective
|
||||||
|
* function.
|
||||||
|
* @throws FunctionEvaluationException if the objective function throws one
|
||||||
|
* during the search.
|
||||||
|
* @throws DimensionMismatchException if the start point dimension is wrong.
|
||||||
|
* @throws TooManyEvaluationsException if the maximal number of evaluations is
|
||||||
|
* exceeded.
|
||||||
|
*/
|
||||||
|
VectorialPointValuePair optimize(FUNC f, double[] target, double[] weight,
|
||||||
|
double[] startPoint)
|
||||||
|
throws FunctionEvaluationException;
|
||||||
|
}
|
|
@ -0,0 +1,77 @@
|
||||||
|
/*
|
||||||
|
* 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.FunctionEvaluationException;
|
||||||
|
import org.apache.commons.math.analysis.MultivariateRealFunction;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This interface is mainly intended to enforce the internal coherence of
|
||||||
|
* Commons-Math. Users of the API are advised to base their code on
|
||||||
|
* the following interfaces:
|
||||||
|
* <ul>
|
||||||
|
* <li>{@link org.apache.commons.math.optimization.MultivariateRealOptimizer}</li>
|
||||||
|
* <li>{@link org.apache.commons.math.optimization.DifferentiableMultivariateRealOptimizer}</li>
|
||||||
|
* <li>{@link org.apache.commons.math.optimization.DifferentiableMultivariateVectorialOptimizer}</li>
|
||||||
|
* <li>{@link org.apache.commons.math.optimization.univariate.UnivariateRealOptimizer}</li>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* @param <PAIR> Type of the point/objective pair.
|
||||||
|
*
|
||||||
|
* @version $Revision$ $Date$
|
||||||
|
* @since 3.0
|
||||||
|
*/
|
||||||
|
public interface BaseOptimizer<PAIR> {
|
||||||
|
/**
|
||||||
|
* Set the maximal number of function evaluations.
|
||||||
|
*
|
||||||
|
* @param maxEvaluations Maximal number of function evaluations.
|
||||||
|
*/
|
||||||
|
void setMaxEvaluations(int maxEvaluations);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the maximal number of function evaluations.
|
||||||
|
*
|
||||||
|
* @return the maximal number of function evaluations.
|
||||||
|
*/
|
||||||
|
int getMaxEvaluations();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the number of evaluations of the objective function.
|
||||||
|
* The number of evaluations corresponds to the last call to the
|
||||||
|
* {@code optimize} method. It is 0 if the method has not been
|
||||||
|
* called yet.
|
||||||
|
*
|
||||||
|
* @return the number of evaluations of the objective function.
|
||||||
|
*/
|
||||||
|
int getEvaluations();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the convergence checker.
|
||||||
|
*
|
||||||
|
* @param checker Object to use to check for convergence.
|
||||||
|
*/
|
||||||
|
void setConvergenceChecker(ConvergenceChecker<PAIR> checker);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the convergence checker.
|
||||||
|
*
|
||||||
|
* @return the object used to check for convergence.
|
||||||
|
*/
|
||||||
|
ConvergenceChecker<PAIR> getConvergenceChecker();
|
||||||
|
}
|
|
@ -0,0 +1,58 @@
|
||||||
|
/*
|
||||||
|
* 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 specifies how to check if an optimization algorithm has
|
||||||
|
* converged.
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* @param <PAIR> Type of the (point, objective value) pair.
|
||||||
|
*
|
||||||
|
* @see org.apache.commons.math.optimization.SimpleScalarValueChecker
|
||||||
|
* @see org.apache.commons.math.optimization.SimpleRealPointChecker
|
||||||
|
*
|
||||||
|
* @version $Revision$ $Date$
|
||||||
|
* @since 3.0
|
||||||
|
*/
|
||||||
|
public interface ConvergenceChecker<PAIR> {
|
||||||
|
/**
|
||||||
|
* Check if the optimization algorithm has converged.
|
||||||
|
*
|
||||||
|
* @param iteration Current iteration.
|
||||||
|
* @param points Data used for checking the convergence.
|
||||||
|
* @return {@code true} if the algorithm is considered to have converged.
|
||||||
|
*/
|
||||||
|
boolean converged(int iteration, PAIR ... points);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the relative tolerance.
|
||||||
|
*
|
||||||
|
* @return the relative threshold.
|
||||||
|
*/
|
||||||
|
double getRelativeThreshold();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the absolute tolerance.
|
||||||
|
*
|
||||||
|
* @return the absolute threshold.
|
||||||
|
*/
|
||||||
|
double getAbsoluteThreshold();
|
||||||
|
}
|
|
@ -28,18 +28,9 @@ import org.apache.commons.math.analysis.DifferentiableMultivariateRealFunction;
|
||||||
*
|
*
|
||||||
* @see MultivariateRealOptimizer
|
* @see MultivariateRealOptimizer
|
||||||
* @see DifferentiableMultivariateVectorialOptimizer
|
* @see DifferentiableMultivariateVectorialOptimizer
|
||||||
|
*
|
||||||
* @version $Revision$ $Date$
|
* @version $Revision$ $Date$
|
||||||
* @since 2.0
|
* @since 2.0
|
||||||
*/
|
*/
|
||||||
public interface DifferentiableMultivariateRealOptimizer
|
public interface DifferentiableMultivariateRealOptimizer
|
||||||
extends BaseMultivariateRealOptimizer<DifferentiableMultivariateRealFunction> {
|
extends BaseMultivariateRealOptimizer<DifferentiableMultivariateRealFunction> {}
|
||||||
/**
|
|
||||||
* Get the number of evaluations of the objective function gradient.
|
|
||||||
* The number of evaluations corresponds to the last call to the
|
|
||||||
* {@code optimize} method (see {@link BaseMultivariateRealOptimizer}).
|
|
||||||
* It is 0 if the method has not been called yet.
|
|
||||||
*
|
|
||||||
* @return the number of evaluations of the objective function gradient.
|
|
||||||
*/
|
|
||||||
int getGradientEvaluations();
|
|
||||||
}
|
|
||||||
|
|
|
@ -21,94 +21,12 @@ import org.apache.commons.math.FunctionEvaluationException;
|
||||||
import org.apache.commons.math.analysis.DifferentiableMultivariateVectorialFunction;
|
import org.apache.commons.math.analysis.DifferentiableMultivariateVectorialFunction;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This interface represents an optimization algorithm for {@link DifferentiableMultivariateVectorialFunction
|
* This interface represents an optimization algorithm for
|
||||||
* vectorial differentiable objective functions}.
|
* {@link DifferentiableMultivariateVectorialFunction vectorial differentiable
|
||||||
* <p>Optimization algorithms find the input point set that either {@link GoalType
|
* objective functions}.
|
||||||
* maximize or minimize} an objective function.</p>
|
*
|
||||||
* @see MultivariateRealOptimizer
|
|
||||||
* @see DifferentiableMultivariateRealOptimizer
|
|
||||||
* @version $Revision$ $Date$
|
* @version $Revision$ $Date$
|
||||||
* @since 2.0
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
public interface DifferentiableMultivariateVectorialOptimizer {
|
public interface DifferentiableMultivariateVectorialOptimizer
|
||||||
|
extends BaseMultivariateVectorialOptimizer<DifferentiableMultivariateVectorialFunction> {}
|
||||||
/** Set the maximal number of iterations of the algorithm.
|
|
||||||
* @param maxIterations maximal number of function calls
|
|
||||||
* .
|
|
||||||
*/
|
|
||||||
void setMaxIterations(int maxIterations);
|
|
||||||
|
|
||||||
/** Get the maximal number of iterations of the algorithm.
|
|
||||||
* @return maximal number of iterations
|
|
||||||
*/
|
|
||||||
int getMaxIterations();
|
|
||||||
|
|
||||||
/** Get the number of iterations realized by the algorithm.
|
|
||||||
* @return number of iterations
|
|
||||||
*/
|
|
||||||
int getIterations();
|
|
||||||
|
|
||||||
/** Set the maximal number of functions evaluations.
|
|
||||||
* @param maxEvaluations maximal number of function evaluations
|
|
||||||
*/
|
|
||||||
void setMaxEvaluations(int maxEvaluations);
|
|
||||||
|
|
||||||
/** Get the maximal number of functions evaluations.
|
|
||||||
* @return maximal number of functions evaluations
|
|
||||||
*/
|
|
||||||
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(DifferentiableMultivariateVectorialFunction,
|
|
||||||
* double[], double[], 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();
|
|
||||||
|
|
||||||
/** Get the number of evaluations of the objective function jacobian .
|
|
||||||
* <p>
|
|
||||||
* The number of evaluation correspond to the last call to the
|
|
||||||
* {@link #optimize(DifferentiableMultivariateVectorialFunction,
|
|
||||||
* double[], double[], double[]) optimize} method. It is 0 if
|
|
||||||
* the method has not been called yet.
|
|
||||||
* </p>
|
|
||||||
* @return number of evaluations of the objective function jacobian
|
|
||||||
*/
|
|
||||||
int getJacobianEvaluations();
|
|
||||||
|
|
||||||
/** Set the convergence checker.
|
|
||||||
* @param checker object to use to check for convergence
|
|
||||||
*/
|
|
||||||
void setConvergenceChecker(VectorialConvergenceChecker checker);
|
|
||||||
|
|
||||||
/** Get the convergence checker.
|
|
||||||
* @return object used 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
|
|
||||||
* ∑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 FunctionEvaluationException if the objective function throws one during
|
|
||||||
* the search
|
|
||||||
* @exception OptimizationException if the algorithm failed to converge
|
|
||||||
* @exception IllegalArgumentException if the start point dimension is wrong
|
|
||||||
*/
|
|
||||||
VectorialPointValuePair optimize(DifferentiableMultivariateVectorialFunction f,
|
|
||||||
double[] target, double[] weights,
|
|
||||||
double[] startPoint)
|
|
||||||
throws FunctionEvaluationException, OptimizationException, IllegalArgumentException;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
|
@ -21,208 +21,38 @@ import java.util.Arrays;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
|
|
||||||
import org.apache.commons.math.FunctionEvaluationException;
|
import org.apache.commons.math.FunctionEvaluationException;
|
||||||
import org.apache.commons.math.MathRuntimeException;
|
import org.apache.commons.math.exception.MathIllegalStateException;
|
||||||
|
import org.apache.commons.math.exception.ConvergenceException;
|
||||||
import org.apache.commons.math.analysis.DifferentiableMultivariateRealFunction;
|
import org.apache.commons.math.analysis.DifferentiableMultivariateRealFunction;
|
||||||
import org.apache.commons.math.exception.util.LocalizedFormats;
|
import org.apache.commons.math.exception.util.LocalizedFormats;
|
||||||
import org.apache.commons.math.random.RandomVectorGenerator;
|
import org.apache.commons.math.random.RandomVectorGenerator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Special implementation of the {@link DifferentiableMultivariateRealOptimizer} interface adding
|
* Special implementation of the {@link DifferentiableMultivariateRealOptimizer}
|
||||||
* multi-start features to an existing optimizer.
|
* interface adding multi-start features to an existing optimizer.
|
||||||
* <p>
|
*
|
||||||
* This class wraps a classical optimizer to use it several times in
|
* This class wraps a classical optimizer to use it several times in
|
||||||
* turn with different starting points in order to avoid being trapped
|
* turn with different starting points in order to avoid being trapped
|
||||||
* into a local extremum when looking for a global one.
|
* into a local extremum when looking for a global one.
|
||||||
* </p>
|
*
|
||||||
* @version $Revision$ $Date$
|
* @version $Revision$ $Date$
|
||||||
* @since 2.0
|
* @since 2.0
|
||||||
*/
|
*/
|
||||||
public class MultiStartDifferentiableMultivariateRealOptimizer
|
public class MultiStartDifferentiableMultivariateRealOptimizer
|
||||||
|
extends BaseMultiStartMultivariateRealOptimizer<DifferentiableMultivariateRealFunction>
|
||||||
implements DifferentiableMultivariateRealOptimizer {
|
implements DifferentiableMultivariateRealOptimizer {
|
||||||
|
|
||||||
/** Underlying classical optimizer. */
|
|
||||||
private final DifferentiableMultivariateRealOptimizer optimizer;
|
|
||||||
|
|
||||||
/** Maximal number of iterations allowed. */
|
|
||||||
private int maxIterations;
|
|
||||||
|
|
||||||
/** Number of iterations already performed for all starts. */
|
|
||||||
private int totalIterations;
|
|
||||||
|
|
||||||
/** Maximal number of evaluations allowed. */
|
|
||||||
private int maxEvaluations;
|
|
||||||
|
|
||||||
/** Number of evaluations already performed for all starts. */
|
|
||||||
private int totalEvaluations;
|
|
||||||
|
|
||||||
/** Number of gradient evaluations already performed for all starts. */
|
|
||||||
private int totalGradientEvaluations;
|
|
||||||
|
|
||||||
/** Number of starts to go. */
|
|
||||||
private int starts;
|
|
||||||
|
|
||||||
/** Random generator for multi-start. */
|
|
||||||
private RandomVectorGenerator generator;
|
|
||||||
|
|
||||||
/** Found optima. */
|
|
||||||
private RealPointValuePair[] optima;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a multi-start optimizer from a single-start optimizer
|
* Create a multi-start optimizer from a single-start optimizer.
|
||||||
* @param optimizer single-start optimizer to wrap
|
*
|
||||||
* @param starts number of starts to perform (including the
|
* @param optimizer Single-start optimizer to wrap.
|
||||||
|
* @param starts Number of starts to perform (including the
|
||||||
* first one), multi-start is disabled if value is less than or
|
* first one), multi-start is disabled if value is less than or
|
||||||
* equal to 1
|
* equal to 1.
|
||||||
* @param generator random vector generator to use for restarts
|
* @param generator Random vector generator to use for restarts.
|
||||||
*/
|
*/
|
||||||
public MultiStartDifferentiableMultivariateRealOptimizer(final DifferentiableMultivariateRealOptimizer optimizer,
|
public MultiStartDifferentiableMultivariateRealOptimizer(final DifferentiableMultivariateRealOptimizer optimizer,
|
||||||
final int starts,
|
final int starts,
|
||||||
final RandomVectorGenerator generator) {
|
final RandomVectorGenerator generator) {
|
||||||
this.optimizer = optimizer;
|
super(optimizer, starts, generator);
|
||||||
this.totalIterations = 0;
|
|
||||||
this.totalEvaluations = 0;
|
|
||||||
this.totalGradientEvaluations = 0;
|
|
||||||
this.starts = starts;
|
|
||||||
this.generator = generator;
|
|
||||||
this.optima = null;
|
|
||||||
setMaxIterations(Integer.MAX_VALUE);
|
|
||||||
setMaxEvaluations(Integer.MAX_VALUE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Get all the optima found during the last call to {@link
|
|
||||||
* #optimize(DifferentiableMultivariateRealFunction, GoalType, double[])
|
|
||||||
* optimize}.
|
|
||||||
* <p>The optimizer stores all the optima found during a set of
|
|
||||||
* restarts. The {@link #optimize(DifferentiableMultivariateRealFunction,
|
|
||||||
* 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(DifferentiableMultivariateRealFunction, GoalType, double[])
|
|
||||||
* optimize} method.
|
|
||||||
* </p>
|
|
||||||
* <p>
|
|
||||||
* The returned array as one element for each start as specified
|
|
||||||
* in the constructor. It is ordered with the results from the
|
|
||||||
* runs that did converge first, sorted from best to worst
|
|
||||||
* 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(DifferentiableMultivariateRealFunction,
|
|
||||||
* GoalType, double[]) optimize} method did throw a {@link
|
|
||||||
* org.apache.commons.math.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(DifferentiableMultivariateRealFunction,
|
|
||||||
* GoalType, double[]) optimize} has not been called
|
|
||||||
*/
|
|
||||||
public RealPointValuePair[] getOptima() throws IllegalStateException {
|
|
||||||
if (optima == null) {
|
|
||||||
throw MathRuntimeException.createIllegalStateException(LocalizedFormats.NO_OPTIMUM_COMPUTED_YET);
|
|
||||||
}
|
|
||||||
return optima.clone();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
public void setMaxIterations(int maxIterations) {
|
|
||||||
this.maxIterations = maxIterations;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
public int getMaxIterations() {
|
|
||||||
return maxIterations;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
public int getIterations() {
|
|
||||||
return totalIterations;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
public void setMaxEvaluations(int maxEvaluations) {
|
|
||||||
this.maxEvaluations = maxEvaluations;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
public int getMaxEvaluations() {
|
|
||||||
return maxEvaluations;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
public int getEvaluations() {
|
|
||||||
return totalEvaluations;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
public int getGradientEvaluations() {
|
|
||||||
return totalGradientEvaluations;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
public void setConvergenceChecker(RealConvergenceChecker checker) {
|
|
||||||
optimizer.setConvergenceChecker(checker);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
public RealConvergenceChecker getConvergenceChecker() {
|
|
||||||
return optimizer.getConvergenceChecker();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
public RealPointValuePair optimize(final DifferentiableMultivariateRealFunction f,
|
|
||||||
final GoalType goalType,
|
|
||||||
double[] startPoint)
|
|
||||||
throws FunctionEvaluationException, OptimizationException {
|
|
||||||
|
|
||||||
optima = new RealPointValuePair[starts];
|
|
||||||
totalIterations = 0;
|
|
||||||
totalEvaluations = 0;
|
|
||||||
totalGradientEvaluations = 0;
|
|
||||||
|
|
||||||
// multi-start loop
|
|
||||||
for (int i = 0; i < starts; ++i) {
|
|
||||||
|
|
||||||
try {
|
|
||||||
optimizer.setMaxIterations(maxIterations - totalIterations);
|
|
||||||
optimizer.setMaxEvaluations(maxEvaluations - totalEvaluations);
|
|
||||||
optima[i] = optimizer.optimize(f, goalType,
|
|
||||||
(i == 0) ? startPoint : generator.nextVector());
|
|
||||||
} catch (FunctionEvaluationException fee) {
|
|
||||||
optima[i] = null;
|
|
||||||
} catch (OptimizationException oe) {
|
|
||||||
optima[i] = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
totalIterations += optimizer.getIterations();
|
|
||||||
totalEvaluations += optimizer.getEvaluations();
|
|
||||||
totalGradientEvaluations += optimizer.getGradientEvaluations();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// sort the optima from best to worst, followed by null elements
|
|
||||||
Arrays.sort(optima, new Comparator<RealPointValuePair>() {
|
|
||||||
public int compare(final RealPointValuePair o1, final RealPointValuePair o2) {
|
|
||||||
if (o1 == null) {
|
|
||||||
return (o2 == null) ? 0 : +1;
|
|
||||||
} else if (o2 == null) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
final double v1 = o1.getValue();
|
|
||||||
final double v2 = o2.getValue();
|
|
||||||
return (goalType == GoalType.MINIMIZE) ?
|
|
||||||
Double.compare(v1, v2) : Double.compare(v2, v1);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (optima[0] == null) {
|
|
||||||
throw new OptimizationException(
|
|
||||||
LocalizedFormats.NO_CONVERGENCE_WITH_ANY_START_POINT,
|
|
||||||
starts);
|
|
||||||
}
|
|
||||||
|
|
||||||
// return the found point given the best objective function value
|
|
||||||
return optima[0];
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,222 +17,36 @@
|
||||||
|
|
||||||
package org.apache.commons.math.optimization;
|
package org.apache.commons.math.optimization;
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Comparator;
|
|
||||||
|
|
||||||
import org.apache.commons.math.FunctionEvaluationException;
|
|
||||||
import org.apache.commons.math.MathRuntimeException;
|
|
||||||
import org.apache.commons.math.analysis.DifferentiableMultivariateVectorialFunction;
|
import org.apache.commons.math.analysis.DifferentiableMultivariateVectorialFunction;
|
||||||
import org.apache.commons.math.exception.util.LocalizedFormats;
|
|
||||||
import org.apache.commons.math.random.RandomVectorGenerator;
|
import org.apache.commons.math.random.RandomVectorGenerator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Special implementation of the {@link DifferentiableMultivariateVectorialOptimizer} interface adding
|
* Special implementation of the {@link DifferentiableMultivariateVectorialOptimizer}
|
||||||
* multi-start features to an existing optimizer.
|
* interface addind multi-start features to an existing optimizer.
|
||||||
* <p>
|
*
|
||||||
* This class wraps a classical optimizer to use it several times in
|
* This class wraps a classical optimizer to use it several times in
|
||||||
* turn with different starting points in order to avoid being trapped
|
* turn with different starting points in order to avoid being trapped
|
||||||
* into a local extremum when looking for a global one.
|
* into a local extremum when looking for a global one.
|
||||||
* </p>
|
*
|
||||||
* @version $Revision$ $Date$
|
* @version $Revision$ $Date$
|
||||||
* @since 2.0
|
* @since 2.0
|
||||||
*/
|
*/
|
||||||
public class MultiStartDifferentiableMultivariateVectorialOptimizer
|
public class MultiStartDifferentiableMultivariateVectorialOptimizer
|
||||||
|
extends BaseMultiStartMultivariateVectorialOptimizer<DifferentiableMultivariateVectorialFunction>
|
||||||
implements DifferentiableMultivariateVectorialOptimizer {
|
implements DifferentiableMultivariateVectorialOptimizer {
|
||||||
|
|
||||||
/** Serializable version identifier. */
|
|
||||||
private static final long serialVersionUID = 9206382258980561530L;
|
|
||||||
|
|
||||||
/** Underlying classical optimizer. */
|
|
||||||
private final DifferentiableMultivariateVectorialOptimizer optimizer;
|
|
||||||
|
|
||||||
/** Maximal number of iterations allowed. */
|
|
||||||
private int maxIterations;
|
|
||||||
|
|
||||||
/** Number of iterations already performed for all starts. */
|
|
||||||
private int totalIterations;
|
|
||||||
|
|
||||||
/** Maximal number of evaluations allowed. */
|
|
||||||
private int maxEvaluations;
|
|
||||||
|
|
||||||
/** Number of evaluations already performed for all starts. */
|
|
||||||
private int totalEvaluations;
|
|
||||||
|
|
||||||
/** Number of jacobian evaluations already performed for all starts. */
|
|
||||||
private int totalJacobianEvaluations;
|
|
||||||
|
|
||||||
/** Number of starts to go. */
|
|
||||||
private int starts;
|
|
||||||
|
|
||||||
/** Random generator for multi-start. */
|
|
||||||
private RandomVectorGenerator generator;
|
|
||||||
|
|
||||||
/** Found optima. */
|
|
||||||
private VectorialPointValuePair[] optima;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a multi-start optimizer from a single-start optimizer
|
* Create a multi-start optimizer from a single-start optimizer.
|
||||||
* @param optimizer single-start optimizer to wrap
|
*
|
||||||
* @param starts number of starts to perform (including the
|
* @param optimizer Single-start optimizer to wrap.
|
||||||
|
* @param starts Number of starts to perform (including the
|
||||||
* first one), multi-start is disabled if value is less than or
|
* first one), multi-start is disabled if value is less than or
|
||||||
* equal to 1
|
* equal to 1.
|
||||||
* @param generator random vector generator to use for restarts
|
* @param generator Random vector generator to use for restarts.
|
||||||
*/
|
*/
|
||||||
public MultiStartDifferentiableMultivariateVectorialOptimizer(
|
public MultiStartDifferentiableMultivariateVectorialOptimizer(
|
||||||
final DifferentiableMultivariateVectorialOptimizer optimizer,
|
final DifferentiableMultivariateVectorialOptimizer optimizer,
|
||||||
final int starts,
|
final int starts,
|
||||||
final RandomVectorGenerator generator) {
|
final RandomVectorGenerator generator) {
|
||||||
this.optimizer = optimizer;
|
super(optimizer, starts, generator);
|
||||||
this.totalIterations = 0;
|
|
||||||
this.totalEvaluations = 0;
|
|
||||||
this.totalJacobianEvaluations = 0;
|
|
||||||
this.starts = starts;
|
|
||||||
this.generator = generator;
|
|
||||||
this.optima = null;
|
|
||||||
setMaxIterations(Integer.MAX_VALUE);
|
|
||||||
setMaxEvaluations(Integer.MAX_VALUE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Get all the optima found during the last call to {@link
|
|
||||||
* #optimize(DifferentiableMultivariateVectorialFunction,
|
|
||||||
* double[], double[], double[]) optimize}.
|
|
||||||
* <p>The optimizer stores all the optima found during a set of
|
|
||||||
* restarts. The {@link #optimize(DifferentiableMultivariateVectorialFunction,
|
|
||||||
* double[], double[], 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(DifferentiableMultivariateVectorialFunction, double[],
|
|
||||||
* double[], double[]) optimize} method.
|
|
||||||
* </p>
|
|
||||||
* <p>
|
|
||||||
* The returned array as one element for each start as specified
|
|
||||||
* in the constructor. It is ordered with the results from the
|
|
||||||
* runs that did converge first, sorted from best to worst
|
|
||||||
* 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(DifferentiableMultivariateVectorialFunction,
|
|
||||||
* double[], double[], double[]) optimize} method did throw a {@link
|
|
||||||
* org.apache.commons.math.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(DifferentiableMultivariateVectorialFunction,
|
|
||||||
* double[], double[], double[]) optimize} has not been called
|
|
||||||
*/
|
|
||||||
public VectorialPointValuePair[] getOptima() throws IllegalStateException {
|
|
||||||
if (optima == null) {
|
|
||||||
throw MathRuntimeException.createIllegalStateException(LocalizedFormats.NO_OPTIMUM_COMPUTED_YET);
|
|
||||||
}
|
|
||||||
return optima.clone();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
public void setMaxIterations(int maxIterations) {
|
|
||||||
this.maxIterations = maxIterations;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
public int getMaxIterations() {
|
|
||||||
return maxIterations;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
public int getIterations() {
|
|
||||||
return totalIterations;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
public void setMaxEvaluations(int maxEvaluations) {
|
|
||||||
this.maxEvaluations = maxEvaluations;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
public int getMaxEvaluations() {
|
|
||||||
return maxEvaluations;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
public int getEvaluations() {
|
|
||||||
return totalEvaluations;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
public int getJacobianEvaluations() {
|
|
||||||
return totalJacobianEvaluations;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
public void setConvergenceChecker(VectorialConvergenceChecker checker) {
|
|
||||||
optimizer.setConvergenceChecker(checker);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
public VectorialConvergenceChecker getConvergenceChecker() {
|
|
||||||
return optimizer.getConvergenceChecker();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
public VectorialPointValuePair optimize(final DifferentiableMultivariateVectorialFunction f,
|
|
||||||
final double[] target, final double[] weights,
|
|
||||||
final double[] startPoint)
|
|
||||||
throws FunctionEvaluationException, OptimizationException, IllegalArgumentException {
|
|
||||||
|
|
||||||
optima = new VectorialPointValuePair[starts];
|
|
||||||
totalIterations = 0;
|
|
||||||
totalEvaluations = 0;
|
|
||||||
totalJacobianEvaluations = 0;
|
|
||||||
|
|
||||||
// multi-start loop
|
|
||||||
for (int i = 0; i < starts; ++i) {
|
|
||||||
|
|
||||||
try {
|
|
||||||
optimizer.setMaxIterations(maxIterations - totalIterations);
|
|
||||||
optimizer.setMaxEvaluations(maxEvaluations - totalEvaluations);
|
|
||||||
optima[i] = optimizer.optimize(f, target, weights,
|
|
||||||
(i == 0) ? startPoint : generator.nextVector());
|
|
||||||
} catch (FunctionEvaluationException fee) {
|
|
||||||
optima[i] = null;
|
|
||||||
} catch (OptimizationException oe) {
|
|
||||||
optima[i] = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
totalIterations += optimizer.getIterations();
|
|
||||||
totalEvaluations += optimizer.getEvaluations();
|
|
||||||
totalJacobianEvaluations += optimizer.getJacobianEvaluations();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// sort the optima from best to worst, followed by null elements
|
|
||||||
Arrays.sort(optima, new Comparator<VectorialPointValuePair>() {
|
|
||||||
public int compare(final VectorialPointValuePair o1, final VectorialPointValuePair o2) {
|
|
||||||
if (o1 == null) {
|
|
||||||
return (o2 == null) ? 0 : +1;
|
|
||||||
} else if (o2 == null) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return Double.compare(weightedResidual(o1), weightedResidual(o2));
|
|
||||||
}
|
|
||||||
private double weightedResidual(final VectorialPointValuePair pv) {
|
|
||||||
final double[] value = pv.getValueRef();
|
|
||||||
double sum = 0;
|
|
||||||
for (int i = 0; i < value.length; ++i) {
|
|
||||||
final double ri = value[i] - target[i];
|
|
||||||
sum += weights[i] * ri * ri;
|
|
||||||
}
|
|
||||||
return sum;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (optima[0] == null) {
|
|
||||||
throw new OptimizationException(
|
|
||||||
LocalizedFormats.NO_CONVERGENCE_WITH_ANY_START_POINT,
|
|
||||||
starts);
|
|
||||||
}
|
|
||||||
|
|
||||||
// return the found point given the best objective function value
|
|
||||||
return optima[0];
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,200 +17,35 @@
|
||||||
|
|
||||||
package org.apache.commons.math.optimization;
|
package org.apache.commons.math.optimization;
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Comparator;
|
|
||||||
|
|
||||||
import org.apache.commons.math.FunctionEvaluationException;
|
|
||||||
import org.apache.commons.math.MathRuntimeException;
|
|
||||||
import org.apache.commons.math.analysis.MultivariateRealFunction;
|
import org.apache.commons.math.analysis.MultivariateRealFunction;
|
||||||
import org.apache.commons.math.exception.util.LocalizedFormats;
|
|
||||||
import org.apache.commons.math.random.RandomVectorGenerator;
|
import org.apache.commons.math.random.RandomVectorGenerator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Special implementation of the {@link MultivariateRealOptimizer} interface adding
|
* Special implementation of the {@link MultivariateRealOptimizer} interface adding
|
||||||
* multi-start features to an existing optimizer.
|
* multi-start features to an existing optimizer.
|
||||||
* <p>
|
*
|
||||||
* This class wraps a classical optimizer to use it several times in
|
* This class wraps a classical optimizer to use it several times in
|
||||||
* turn with different starting points in order to avoid being trapped
|
* turn with different starting points in order to avoid being trapped
|
||||||
* into a local extremum when looking for a global one.
|
* into a local extremum when looking for a global one.
|
||||||
* </p>
|
*
|
||||||
* @version $Revision$ $Date$
|
* @version $Revision$ $Date$
|
||||||
* @since 2.0
|
* @since 2.0
|
||||||
*/
|
*/
|
||||||
public class MultiStartMultivariateRealOptimizer
|
public class MultiStartMultivariateRealOptimizer
|
||||||
|
extends BaseMultiStartMultivariateRealOptimizer<MultivariateRealFunction>
|
||||||
implements MultivariateRealOptimizer {
|
implements MultivariateRealOptimizer {
|
||||||
|
|
||||||
/** Underlying classical optimizer. */
|
|
||||||
private final MultivariateRealOptimizer optimizer;
|
|
||||||
|
|
||||||
/** Maximal number of iterations allowed. */
|
|
||||||
private int maxIterations;
|
|
||||||
|
|
||||||
/** Maximal number of evaluations allowed. */
|
|
||||||
private int maxEvaluations;
|
|
||||||
|
|
||||||
/** Number of iterations already performed for all starts. */
|
|
||||||
private int totalIterations;
|
|
||||||
|
|
||||||
/** Number of evaluations already performed for all starts. */
|
|
||||||
private int totalEvaluations;
|
|
||||||
|
|
||||||
/** Number of starts to go. */
|
|
||||||
private int starts;
|
|
||||||
|
|
||||||
/** Random generator for multi-start. */
|
|
||||||
private RandomVectorGenerator generator;
|
|
||||||
|
|
||||||
/** Found optima. */
|
|
||||||
private RealPointValuePair[] optima;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a multi-start optimizer from a single-start optimizer
|
* Create a multi-start optimizer from a single-start optimizer.
|
||||||
* @param optimizer single-start optimizer to wrap
|
*
|
||||||
* @param starts number of starts to perform (including the
|
* @param optimizer Single-start optimizer to wrap.
|
||||||
|
* @param starts Number of starts to perform (including the
|
||||||
* first one), multi-start is disabled if value is less than or
|
* first one), multi-start is disabled if value is less than or
|
||||||
* equal to 1
|
* equal to 1.
|
||||||
* @param generator random vector generator to use for restarts
|
* @param generator Random vector generator to use for restarts.
|
||||||
*/
|
*/
|
||||||
public MultiStartMultivariateRealOptimizer(final MultivariateRealOptimizer optimizer,
|
public MultiStartMultivariateRealOptimizer(final MultivariateRealOptimizer optimizer,
|
||||||
final int starts,
|
final int starts,
|
||||||
final RandomVectorGenerator generator) {
|
final RandomVectorGenerator generator) {
|
||||||
this.optimizer = optimizer;
|
super(optimizer, starts, generator);
|
||||||
this.totalIterations = 0;
|
|
||||||
this.totalEvaluations = 0;
|
|
||||||
this.starts = starts;
|
|
||||||
this.generator = generator;
|
|
||||||
this.optima = null;
|
|
||||||
setMaxIterations(Integer.MAX_VALUE);
|
|
||||||
setMaxEvaluations(Integer.MAX_VALUE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Get all the optima found during the last call to {@link
|
|
||||||
* #optimize(MultivariateRealFunction, GoalType, double[]) optimize}.
|
|
||||||
* <p>The optimizer stores all the optima found during a set of
|
|
||||||
* restarts. The {@link #optimize(MultivariateRealFunction, 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(MultivariateRealFunction, GoalType, double[]) optimize}
|
|
||||||
* method.
|
|
||||||
* </p>
|
|
||||||
* <p>
|
|
||||||
* The returned array as one element for each start as specified
|
|
||||||
* in the constructor. It is ordered with the results from the
|
|
||||||
* runs that did converge first, sorted from best to worst
|
|
||||||
* 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(MultivariateRealFunction,
|
|
||||||
* GoalType, double[]) optimize} method did throw a {@link
|
|
||||||
* org.apache.commons.math.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(MultivariateRealFunction,
|
|
||||||
* GoalType, double[]) optimize} has not been called
|
|
||||||
*/
|
|
||||||
public RealPointValuePair[] getOptima() throws IllegalStateException {
|
|
||||||
if (optima == null) {
|
|
||||||
throw MathRuntimeException.createIllegalStateException(LocalizedFormats.NO_OPTIMUM_COMPUTED_YET);
|
|
||||||
}
|
|
||||||
return optima.clone();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
public void setMaxIterations(int maxIterations) {
|
|
||||||
this.maxIterations = maxIterations;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
public int getMaxIterations() {
|
|
||||||
return maxIterations;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
public void setMaxEvaluations(int maxEvaluations) {
|
|
||||||
this.maxEvaluations = maxEvaluations;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
public int getMaxEvaluations() {
|
|
||||||
return maxEvaluations;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
public int getIterations() {
|
|
||||||
return totalIterations;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
public int getEvaluations() {
|
|
||||||
return totalEvaluations;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
public void setConvergenceChecker(RealConvergenceChecker checker) {
|
|
||||||
optimizer.setConvergenceChecker(checker);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
public RealConvergenceChecker getConvergenceChecker() {
|
|
||||||
return optimizer.getConvergenceChecker();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
public RealPointValuePair optimize(final MultivariateRealFunction f,
|
|
||||||
final GoalType goalType,
|
|
||||||
double[] startPoint)
|
|
||||||
throws FunctionEvaluationException, OptimizationException {
|
|
||||||
|
|
||||||
optima = new RealPointValuePair[starts];
|
|
||||||
totalIterations = 0;
|
|
||||||
totalEvaluations = 0;
|
|
||||||
|
|
||||||
// multi-start loop
|
|
||||||
for (int i = 0; i < starts; ++i) {
|
|
||||||
|
|
||||||
try {
|
|
||||||
optimizer.setMaxIterations(maxIterations - totalIterations);
|
|
||||||
optimizer.setMaxEvaluations(maxEvaluations - totalEvaluations);
|
|
||||||
optima[i] = optimizer.optimize(f, goalType,
|
|
||||||
(i == 0) ? startPoint : generator.nextVector());
|
|
||||||
} catch (FunctionEvaluationException fee) {
|
|
||||||
optima[i] = null;
|
|
||||||
} catch (OptimizationException oe) {
|
|
||||||
optima[i] = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
totalIterations += optimizer.getIterations();
|
|
||||||
totalEvaluations += optimizer.getEvaluations();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// sort the optima from best to worst, followed by null elements
|
|
||||||
Arrays.sort(optima, new Comparator<RealPointValuePair>() {
|
|
||||||
public int compare(final RealPointValuePair o1, final RealPointValuePair o2) {
|
|
||||||
if (o1 == null) {
|
|
||||||
return (o2 == null) ? 0 : +1;
|
|
||||||
} else if (o2 == null) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
final double v1 = o1.getValue();
|
|
||||||
final double v2 = o2.getValue();
|
|
||||||
return (goalType == GoalType.MINIMIZE) ?
|
|
||||||
Double.compare(v1, v2) : Double.compare(v2, v1);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (optima[0] == null) {
|
|
||||||
throw new OptimizationException(
|
|
||||||
LocalizedFormats.NO_CONVERGENCE_WITH_ANY_START_POINT,
|
|
||||||
starts);
|
|
||||||
}
|
|
||||||
|
|
||||||
// return the found point given the best objective function value
|
|
||||||
return optima[0];
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,319 +0,0 @@
|
||||||
/*
|
|
||||||
* 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.ConvergenceException;
|
|
||||||
import org.apache.commons.math.FunctionEvaluationException;
|
|
||||||
import org.apache.commons.math.MathRuntimeException;
|
|
||||||
import org.apache.commons.math.analysis.UnivariateRealFunction;
|
|
||||||
import org.apache.commons.math.exception.util.LocalizedFormats;
|
|
||||||
import org.apache.commons.math.random.RandomGenerator;
|
|
||||||
import org.apache.commons.math.util.FastMath;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Special implementation of the {@link UnivariateRealOptimizer} interface adding
|
|
||||||
* multi-start features to an existing optimizer.
|
|
||||||
* <p>
|
|
||||||
* This class wraps a classical optimizer to use it several times in
|
|
||||||
* turn with different starting points in order to avoid being trapped
|
|
||||||
* into a local extremum when looking for a global one.
|
|
||||||
* </p>
|
|
||||||
* @version $Revision$ $Date$
|
|
||||||
* @since 2.0
|
|
||||||
*/
|
|
||||||
public class MultiStartUnivariateRealOptimizer implements UnivariateRealOptimizer {
|
|
||||||
|
|
||||||
/** Serializable version identifier. */
|
|
||||||
private static final long serialVersionUID = 5983375963110961019L;
|
|
||||||
|
|
||||||
/** Underlying classical optimizer. */
|
|
||||||
private final UnivariateRealOptimizer optimizer;
|
|
||||||
|
|
||||||
/** Maximal number of iterations allowed. */
|
|
||||||
private int maxIterations;
|
|
||||||
|
|
||||||
/** Maximal number of evaluations allowed. */
|
|
||||||
private int maxEvaluations;
|
|
||||||
|
|
||||||
/** Number of iterations already performed for all starts. */
|
|
||||||
private int totalIterations;
|
|
||||||
|
|
||||||
/** Number of evaluations already performed for all starts. */
|
|
||||||
private int totalEvaluations;
|
|
||||||
|
|
||||||
/** Number of starts to go. */
|
|
||||||
private int starts;
|
|
||||||
|
|
||||||
/** Random generator for multi-start. */
|
|
||||||
private RandomGenerator generator;
|
|
||||||
|
|
||||||
/** Found optima. */
|
|
||||||
private double[] optima;
|
|
||||||
|
|
||||||
/** Found function values at optima. */
|
|
||||||
private double[] optimaValues;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a multi-start optimizer from a single-start optimizer
|
|
||||||
* @param optimizer single-start optimizer to wrap
|
|
||||||
* @param starts number of starts to perform (including the
|
|
||||||
* first one), multi-start is disabled if value is less than or
|
|
||||||
* equal to 1
|
|
||||||
* @param generator random generator to use for restarts
|
|
||||||
*/
|
|
||||||
public MultiStartUnivariateRealOptimizer(final UnivariateRealOptimizer optimizer,
|
|
||||||
final int starts,
|
|
||||||
final RandomGenerator generator) {
|
|
||||||
this.optimizer = optimizer;
|
|
||||||
this.totalIterations = 0;
|
|
||||||
this.starts = starts;
|
|
||||||
this.generator = generator;
|
|
||||||
this.optima = null;
|
|
||||||
setMaximalIterationCount(Integer.MAX_VALUE);
|
|
||||||
setMaxEvaluations(Integer.MAX_VALUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
public double getFunctionValue() {
|
|
||||||
return optimaValues[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
public double getResult() {
|
|
||||||
return optima[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
public double getAbsoluteAccuracy() {
|
|
||||||
return optimizer.getAbsoluteAccuracy();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
public int getIterationCount() {
|
|
||||||
return totalIterations;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
public int getMaximalIterationCount() {
|
|
||||||
return maxIterations;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
public int getMaxEvaluations() {
|
|
||||||
return maxEvaluations;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
public int getEvaluations() {
|
|
||||||
return totalEvaluations;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
public double getRelativeAccuracy() {
|
|
||||||
return optimizer.getRelativeAccuracy();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
public void resetAbsoluteAccuracy() {
|
|
||||||
optimizer.resetAbsoluteAccuracy();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
public void resetMaximalIterationCount() {
|
|
||||||
optimizer.resetMaximalIterationCount();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
public void resetRelativeAccuracy() {
|
|
||||||
optimizer.resetRelativeAccuracy();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
public void setAbsoluteAccuracy(double accuracy) {
|
|
||||||
optimizer.setAbsoluteAccuracy(accuracy);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
public void setMaximalIterationCount(int count) {
|
|
||||||
this.maxIterations = count;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
public void setMaxEvaluations(int maxEvaluations) {
|
|
||||||
this.maxEvaluations = maxEvaluations;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
public void setRelativeAccuracy(double accuracy) {
|
|
||||||
optimizer.setRelativeAccuracy(accuracy);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Get all the optima found during the last call to {@link
|
|
||||||
* #optimize(UnivariateRealFunction, GoalType, double, double) optimize}.
|
|
||||||
* <p>The optimizer stores all the optima found during a set of
|
|
||||||
* restarts. The {@link #optimize(UnivariateRealFunction, GoalType,
|
|
||||||
* double, 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(UnivariateRealFunction, GoalType, double, double) optimize}
|
|
||||||
* method.
|
|
||||||
* </p>
|
|
||||||
* <p>
|
|
||||||
* The returned array as one element for each start as specified
|
|
||||||
* in the constructor. It is ordered with the results from the
|
|
||||||
* runs that did converge first, sorted from best to worst
|
|
||||||
* objective value (i.e in ascending order if minimizing and in
|
|
||||||
* descending order if maximizing), followed by Double.NaN elements
|
|
||||||
* corresponding to the runs that did not converge. This means all
|
|
||||||
* elements will be NaN if the {@link #optimize(UnivariateRealFunction,
|
|
||||||
* GoalType, double, double) optimize} method did throw a {@link
|
|
||||||
* ConvergenceException ConvergenceException}). This also means that
|
|
||||||
* if the first element is not NaN, it is the best point found across
|
|
||||||
* all starts.</p>
|
|
||||||
* @return array containing the optima
|
|
||||||
* @exception IllegalStateException if {@link #optimize(UnivariateRealFunction,
|
|
||||||
* GoalType, double, double) optimize} has not been called
|
|
||||||
* @see #getOptimaValues()
|
|
||||||
*/
|
|
||||||
public double[] getOptima() throws IllegalStateException {
|
|
||||||
if (optima == null) {
|
|
||||||
throw MathRuntimeException.createIllegalStateException(LocalizedFormats.NO_OPTIMUM_COMPUTED_YET);
|
|
||||||
}
|
|
||||||
return optima.clone();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Get all the function values at optima found during the last call to {@link
|
|
||||||
* #optimize(UnivariateRealFunction, GoalType, double, double) optimize}.
|
|
||||||
* <p>
|
|
||||||
* The returned array as one element for each start as specified
|
|
||||||
* in the constructor. It is ordered with the results from the
|
|
||||||
* runs that did converge first, sorted from best to worst
|
|
||||||
* objective value (i.e in ascending order if minimizing and in
|
|
||||||
* descending order if maximizing), followed by Double.NaN elements
|
|
||||||
* corresponding to the runs that did not converge. This means all
|
|
||||||
* elements will be NaN if the {@link #optimize(UnivariateRealFunction,
|
|
||||||
* GoalType, double, double) optimize} method did throw a {@link
|
|
||||||
* ConvergenceException ConvergenceException}). This also means that
|
|
||||||
* if the first element is not NaN, it is the best point found across
|
|
||||||
* all starts.</p>
|
|
||||||
* @return array containing the optima
|
|
||||||
* @exception IllegalStateException if {@link #optimize(UnivariateRealFunction,
|
|
||||||
* GoalType, double, double) optimize} has not been called
|
|
||||||
* @see #getOptima()
|
|
||||||
*/
|
|
||||||
public double[] getOptimaValues() throws IllegalStateException {
|
|
||||||
if (optimaValues == null) {
|
|
||||||
throw MathRuntimeException.createIllegalStateException(LocalizedFormats.NO_OPTIMUM_COMPUTED_YET);
|
|
||||||
}
|
|
||||||
return optimaValues.clone();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
public double optimize(final UnivariateRealFunction f, final GoalType goalType,
|
|
||||||
final double min, final double max)
|
|
||||||
throws ConvergenceException,
|
|
||||||
FunctionEvaluationException {
|
|
||||||
|
|
||||||
optima = new double[starts];
|
|
||||||
optimaValues = new double[starts];
|
|
||||||
totalIterations = 0;
|
|
||||||
totalEvaluations = 0;
|
|
||||||
|
|
||||||
// multi-start loop
|
|
||||||
for (int i = 0; i < starts; ++i) {
|
|
||||||
|
|
||||||
try {
|
|
||||||
optimizer.setMaximalIterationCount(maxIterations - totalIterations);
|
|
||||||
optimizer.setMaxEvaluations(maxEvaluations - totalEvaluations);
|
|
||||||
final double bound1 = (i == 0) ? min : min + generator.nextDouble() * (max - min);
|
|
||||||
final double bound2 = (i == 0) ? max : min + generator.nextDouble() * (max - min);
|
|
||||||
optima[i] = optimizer.optimize(f, goalType,
|
|
||||||
FastMath.min(bound1, bound2),
|
|
||||||
FastMath.max(bound1, bound2));
|
|
||||||
optimaValues[i] = optimizer.getFunctionValue();
|
|
||||||
} catch (FunctionEvaluationException fee) {
|
|
||||||
optima[i] = Double.NaN;
|
|
||||||
optimaValues[i] = Double.NaN;
|
|
||||||
} catch (ConvergenceException ce) {
|
|
||||||
optima[i] = Double.NaN;
|
|
||||||
optimaValues[i] = Double.NaN;
|
|
||||||
}
|
|
||||||
|
|
||||||
totalIterations += optimizer.getIterationCount();
|
|
||||||
totalEvaluations += optimizer.getEvaluations();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// sort the optima from best to worst, followed by NaN elements
|
|
||||||
int lastNaN = optima.length;
|
|
||||||
for (int i = 0; i < lastNaN; ++i) {
|
|
||||||
if (Double.isNaN(optima[i])) {
|
|
||||||
optima[i] = optima[--lastNaN];
|
|
||||||
optima[lastNaN + 1] = Double.NaN;
|
|
||||||
optimaValues[i] = optimaValues[--lastNaN];
|
|
||||||
optimaValues[lastNaN + 1] = Double.NaN;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
double currX = optima[0];
|
|
||||||
double currY = optimaValues[0];
|
|
||||||
for (int j = 1; j < lastNaN; ++j) {
|
|
||||||
final double prevY = currY;
|
|
||||||
currX = optima[j];
|
|
||||||
currY = optimaValues[j];
|
|
||||||
if ((goalType == GoalType.MAXIMIZE) ^ (currY < prevY)) {
|
|
||||||
// the current element should be inserted closer to the beginning
|
|
||||||
int i = j - 1;
|
|
||||||
double mIX = optima[i];
|
|
||||||
double mIY = optimaValues[i];
|
|
||||||
while ((i >= 0) && ((goalType == GoalType.MAXIMIZE) ^ (currY < mIY))) {
|
|
||||||
optima[i + 1] = mIX;
|
|
||||||
optimaValues[i + 1] = mIY;
|
|
||||||
if (i-- != 0) {
|
|
||||||
mIX = optima[i];
|
|
||||||
mIY = optimaValues[i];
|
|
||||||
} else {
|
|
||||||
mIX = Double.NaN;
|
|
||||||
mIY = Double.NaN;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
optima[i + 1] = currX;
|
|
||||||
optimaValues[i + 1] = currY;
|
|
||||||
currX = optima[j];
|
|
||||||
currY = optimaValues[j];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Double.isNaN(optima[0])) {
|
|
||||||
throw new OptimizationException(
|
|
||||||
LocalizedFormats.NO_CONVERGENCE_WITH_ANY_START_POINT,
|
|
||||||
starts);
|
|
||||||
}
|
|
||||||
|
|
||||||
// return the found point given the best objective function value
|
|
||||||
return optima[0];
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
public double optimize(final UnivariateRealFunction f, final GoalType goalType,
|
|
||||||
final double min, final double max, final double startValue)
|
|
||||||
throws ConvergenceException, FunctionEvaluationException {
|
|
||||||
return optimize(f, goalType, min, max);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -24,6 +24,7 @@ import org.apache.commons.math.analysis.MultivariateRealFunction;
|
||||||
* scalar objective functions}.
|
* scalar objective functions}.
|
||||||
* <p>Optimization algorithms find the input point set that either {@link GoalType
|
* <p>Optimization algorithms find the input point set that either {@link GoalType
|
||||||
* maximize or minimize} an objective function.</p>
|
* maximize or minimize} an objective function.</p>
|
||||||
|
*
|
||||||
* @see DifferentiableMultivariateRealOptimizer
|
* @see DifferentiableMultivariateRealOptimizer
|
||||||
* @see DifferentiableMultivariateVectorialOptimizer
|
* @see DifferentiableMultivariateVectorialOptimizer
|
||||||
* @version $Revision$ $Date$
|
* @version $Revision$ $Date$
|
||||||
|
|
|
@ -32,8 +32,8 @@ package org.apache.commons.math.optimization;
|
||||||
*
|
*
|
||||||
* @version $Revision$ $Date$
|
* @version $Revision$ $Date$
|
||||||
* @since 2.0
|
* @since 2.0
|
||||||
|
* @deprecated To be removed in 3.0.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public interface RealConvergenceChecker {
|
public interface RealConvergenceChecker {
|
||||||
|
|
||||||
/** Check if the optimization algorithm has converged considering the last points.
|
/** Check if the optimization algorithm has converged considering the last points.
|
||||||
|
|
|
@ -17,71 +17,81 @@
|
||||||
|
|
||||||
package org.apache.commons.math.optimization;
|
package org.apache.commons.math.optimization;
|
||||||
|
|
||||||
import org.apache.commons.math.util.FastMath;
|
|
||||||
import org.apache.commons.math.util.MathUtils;
|
import org.apache.commons.math.util.MathUtils;
|
||||||
|
import org.apache.commons.math.util.FastMath;
|
||||||
|
import org.apache.commons.math.exception.DimensionMismatchException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Simple implementation of the {@link RealConvergenceChecker} interface using
|
* Simple implementation of the {@link ConvergenceChecker} interface using
|
||||||
* only point coordinates.
|
* only point coordinates.
|
||||||
* <p>
|
*
|
||||||
* Convergence is considered to have been reached if either the relative
|
* Convergence is considered to have been reached if either the relative
|
||||||
* difference between each point coordinate are smaller than a threshold
|
* difference between each point coordinate are smaller than a threshold
|
||||||
* or if either the absolute difference between the point coordinates are
|
* or if either the absolute difference between the point coordinates are
|
||||||
* smaller than another threshold.
|
* smaller than another threshold.
|
||||||
* </p>
|
*
|
||||||
* @version $Revision$ $Date$
|
* @version $Revision$ $Date$
|
||||||
* @since 2.0
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
public class SimpleRealPointChecker implements RealConvergenceChecker {
|
public class SimpleRealPointChecker
|
||||||
|
extends AbstractConvergenceChecker<RealPointValuePair> {
|
||||||
/** Default relative threshold. */
|
/**
|
||||||
private static final double DEFAULT_RELATIVE_THRESHOLD = 100 * MathUtils.EPSILON;
|
* Build an instance with default threshold.
|
||||||
|
|
||||||
/** 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 SimpleRealPointChecker() {
|
public SimpleRealPointChecker() {}
|
||||||
this.relativeThreshold = DEFAULT_RELATIVE_THRESHOLD;
|
|
||||||
this.absoluteThreshold = DEFAULT_ABSOLUTE_THRESHOLD;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Build an instance with a specified threshold.
|
/**
|
||||||
* <p>
|
* Build an instance with specified thresholds.
|
||||||
* In order to perform only relative checks, the absolute tolerance
|
* In order to perform only relative checks, the absolute tolerance
|
||||||
* must be set to a negative value. In order to perform only absolute
|
* must be set to a negative value. In order to perform only absolute
|
||||||
* checks, the relative tolerance must be set to a negative value.
|
* checks, the relative tolerance must be set to a negative value.
|
||||||
* </p>
|
*
|
||||||
* @param relativeThreshold relative tolerance threshold
|
* @param relativeThreshold relative tolerance threshold
|
||||||
* @param absoluteThreshold absolute tolerance threshold
|
* @param absoluteThreshold absolute tolerance threshold
|
||||||
*/
|
*/
|
||||||
public SimpleRealPointChecker(final double relativeThreshold,
|
public SimpleRealPointChecker(final double relativeThreshold,
|
||||||
final double absoluteThreshold) {
|
final double absoluteThreshold) {
|
||||||
this.relativeThreshold = relativeThreshold;
|
super(relativeThreshold, absoluteThreshold);
|
||||||
this.absoluteThreshold = absoluteThreshold;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
/**
|
||||||
|
* Check if the optimization algorithm has converged considering the
|
||||||
|
* last two points.
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* @param iteration Index of current iteration
|
||||||
|
* @param points Points used for checking convergence. The list must
|
||||||
|
* contain two elements:
|
||||||
|
* <ul>
|
||||||
|
* <li>the previous best point,</li>
|
||||||
|
* <li>the current best point.</li>
|
||||||
|
* </ul>
|
||||||
|
* @return {@code true} if the algorithm has converged.
|
||||||
|
* @throws DimensionMismatchException if the length of the {@code points}
|
||||||
|
* list is not equal to 2.
|
||||||
|
*/
|
||||||
public boolean converged(final int iteration,
|
public boolean converged(final int iteration,
|
||||||
final RealPointValuePair previous,
|
final RealPointValuePair ... points) {
|
||||||
final RealPointValuePair current) {
|
if (points.length != 2) {
|
||||||
final double[] p = previous.getPoint();
|
throw new DimensionMismatchException(points.length, 2);
|
||||||
final double[] c = current.getPoint();
|
}
|
||||||
|
|
||||||
|
final double[] p = points[0].getPoint();
|
||||||
|
final double[] c = points[1].getPoint();
|
||||||
for (int i = 0; i < p.length; ++i) {
|
for (int i = 0; i < p.length; ++i) {
|
||||||
final double difference = FastMath.abs(p[i] - c[i]);
|
final double difference = FastMath.abs(p[i] - c[i]);
|
||||||
final double size = FastMath.max(FastMath.abs(p[i]), FastMath.abs(c[i]));
|
final double size = FastMath.max(FastMath.abs(p[i]), FastMath.abs(c[i]));
|
||||||
if ((difference > (size * relativeThreshold)) && (difference > absoluteThreshold)) {
|
if (difference > size * getRelativeThreshold() &&
|
||||||
|
difference > getAbsoluteThreshold()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,65 +17,76 @@
|
||||||
|
|
||||||
package org.apache.commons.math.optimization;
|
package org.apache.commons.math.optimization;
|
||||||
|
|
||||||
import org.apache.commons.math.util.FastMath;
|
|
||||||
import org.apache.commons.math.util.MathUtils;
|
import org.apache.commons.math.util.MathUtils;
|
||||||
|
import org.apache.commons.math.util.FastMath;
|
||||||
|
import org.apache.commons.math.exception.DimensionMismatchException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Simple implementation of the {@link RealConvergenceChecker} interface using
|
* Simple implementation of the {@link ConvergenceChecker} interface using
|
||||||
* only objective function values.
|
* only objective function values.
|
||||||
* <p>
|
*
|
||||||
* Convergence is considered to have been reached if either the relative
|
* Convergence is considered to have been reached if either the relative
|
||||||
* difference between the objective function values is smaller than a
|
* difference between the objective function values is smaller than a
|
||||||
* threshold or if either the absolute difference between the objective
|
* threshold or if either the absolute difference between the objective
|
||||||
* function values is smaller than another threshold.
|
* function values is smaller than another threshold.
|
||||||
* </p>
|
*
|
||||||
* @version $Revision$ $Date$
|
* @version $Revision$ $Date$
|
||||||
* @since 2.0
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
public class SimpleScalarValueChecker implements RealConvergenceChecker {
|
public class SimpleScalarValueChecker
|
||||||
|
extends AbstractConvergenceChecker<RealPointValuePair> {
|
||||||
/** Default relative threshold. */
|
/**
|
||||||
private static final double DEFAULT_RELATIVE_THRESHOLD = 100 * MathUtils.EPSILON;
|
* Build an instance with default thresholds.
|
||||||
|
|
||||||
/** 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 SimpleScalarValueChecker() {
|
public SimpleScalarValueChecker() {}
|
||||||
this.relativeThreshold = DEFAULT_RELATIVE_THRESHOLD;
|
|
||||||
this.absoluteThreshold = DEFAULT_ABSOLUTE_THRESHOLD;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Build an instance with a specified threshold.
|
/** Build an instance with specified thresholds.
|
||||||
* <p>
|
*
|
||||||
* In order to perform only relative checks, the absolute tolerance
|
* In order to perform only relative checks, the absolute tolerance
|
||||||
* must be set to a negative value. In order to perform only absolute
|
* must be set to a negative value. In order to perform only absolute
|
||||||
* checks, the relative tolerance must be set to a negative value.
|
* checks, the relative tolerance must be set to a negative value.
|
||||||
* </p>
|
*
|
||||||
* @param relativeThreshold relative tolerance threshold
|
* @param relativeThreshold relative tolerance threshold
|
||||||
* @param absoluteThreshold absolute tolerance threshold
|
* @param absoluteThreshold absolute tolerance threshold
|
||||||
*/
|
*/
|
||||||
public SimpleScalarValueChecker(final double relativeThreshold,
|
public SimpleScalarValueChecker(final double relativeThreshold,
|
||||||
final double absoluteThreshold) {
|
final double absoluteThreshold) {
|
||||||
this.relativeThreshold = relativeThreshold;
|
super(relativeThreshold, absoluteThreshold);
|
||||||
this.absoluteThreshold = absoluteThreshold;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
/**
|
||||||
|
* Check if the optimization algorithm has converged considering the
|
||||||
|
* last two points.
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* @param iteration Index of current iteration
|
||||||
|
* @param points Points used for checking convergence. The list must
|
||||||
|
* contain two elements:
|
||||||
|
* <ul>
|
||||||
|
* <li>the previous best point,</li>
|
||||||
|
* <li>the current best point.</li>
|
||||||
|
* </ul>
|
||||||
|
* @return {@code true} if the algorithm has converged.
|
||||||
|
* @throws DimensionMismatchException if the length of the {@code points}
|
||||||
|
* list is not equal to 2.
|
||||||
|
*/
|
||||||
public boolean converged(final int iteration,
|
public boolean converged(final int iteration,
|
||||||
final RealPointValuePair previous,
|
final RealPointValuePair ... points) {
|
||||||
final RealPointValuePair current) {
|
if (points.length != 2) {
|
||||||
final double p = previous.getValue();
|
throw new DimensionMismatchException(points.length, 2);
|
||||||
final double c = current.getValue();
|
}
|
||||||
|
|
||||||
|
final double p = points[0].getValue();
|
||||||
|
final double c = points[1].getValue();
|
||||||
final double difference = FastMath.abs(p - c);
|
final double difference = FastMath.abs(p - c);
|
||||||
final double size = FastMath.max(FastMath.abs(p), FastMath.abs(c));
|
final double size = FastMath.max(FastMath.abs(p), FastMath.abs(c));
|
||||||
return (difference <= (size * relativeThreshold)) || (difference <= absoluteThreshold);
|
return (difference <= size * getRelativeThreshold() ||
|
||||||
|
difference <= getAbsoluteThreshold());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,74 +17,83 @@
|
||||||
|
|
||||||
package org.apache.commons.math.optimization;
|
package org.apache.commons.math.optimization;
|
||||||
|
|
||||||
import org.apache.commons.math.util.FastMath;
|
|
||||||
import org.apache.commons.math.util.MathUtils;
|
import org.apache.commons.math.util.MathUtils;
|
||||||
|
import org.apache.commons.math.exception.DimensionMismatchException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Simple implementation of the {@link VectorialConvergenceChecker} interface using
|
* Simple implementation of the {@link ConvergenceChecker} interface using
|
||||||
* only point coordinates.
|
* only point coordinates.
|
||||||
* <p>
|
*
|
||||||
* Convergence is considered to have been reached if either the relative
|
* Convergence is considered to have been reached if either the relative
|
||||||
* difference between each point coordinate are smaller than a threshold
|
* difference between each point coordinate are smaller than a threshold
|
||||||
* or if either the absolute difference between the point coordinates are
|
* or if either the absolute difference between the point coordinates are
|
||||||
* smaller than another threshold.
|
* smaller than another threshold.
|
||||||
* </p>
|
*
|
||||||
* @version $Revision$ $Date$
|
* @version $Revision$ $Date$
|
||||||
* @since 2.0
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
public class SimpleVectorialPointChecker implements VectorialConvergenceChecker {
|
public class SimpleVectorialPointChecker
|
||||||
|
extends AbstractConvergenceChecker<VectorialPointValuePair> {
|
||||||
/** Default relative threshold. */
|
/**
|
||||||
private static final double DEFAULT_RELATIVE_THRESHOLD = 100 * MathUtils.EPSILON;
|
* Build an instance with default threshold.
|
||||||
|
|
||||||
/** 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 SimpleVectorialPointChecker() {
|
public SimpleVectorialPointChecker() {}
|
||||||
this.relativeThreshold = DEFAULT_RELATIVE_THRESHOLD;
|
|
||||||
this.absoluteThreshold = DEFAULT_ABSOLUTE_THRESHOLD;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Build an instance with a specified threshold.
|
/**
|
||||||
* <p>
|
* Build an instance with a specified threshold.
|
||||||
|
*
|
||||||
* In order to perform only relative checks, the absolute tolerance
|
* In order to perform only relative checks, the absolute tolerance
|
||||||
* must be set to a negative value. In order to perform only absolute
|
* must be set to a negative value. In order to perform only absolute
|
||||||
* checks, the relative tolerance must be set to a negative value.
|
* checks, the relative tolerance must be set to a negative value.
|
||||||
* </p>
|
*
|
||||||
* @param relativeThreshold relative tolerance threshold
|
* @param relativeThreshold relative tolerance threshold
|
||||||
* @param absoluteThreshold absolute tolerance threshold
|
* @param absoluteThreshold absolute tolerance threshold
|
||||||
*/
|
*/
|
||||||
public SimpleVectorialPointChecker(final double relativeThreshold,
|
public SimpleVectorialPointChecker(final double relativeThreshold,
|
||||||
final double absoluteThreshold) {
|
final double absoluteThreshold) {
|
||||||
this.relativeThreshold = relativeThreshold;
|
super(relativeThreshold, absoluteThreshold);
|
||||||
this.absoluteThreshold = absoluteThreshold;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
/**
|
||||||
|
* Check if the optimization algorithm has converged considering the
|
||||||
|
* last two points.
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* @param iteration Index of current iteration
|
||||||
|
* @param points Points used for checking convergence. The list must
|
||||||
|
* contain two elements:
|
||||||
|
* <ul>
|
||||||
|
* <li>the previous best point,</li>
|
||||||
|
* <li>the current best point.</li>
|
||||||
|
* </ul>
|
||||||
|
* @return {@code true} if the algorithm has converged.
|
||||||
|
* @throws DimensionMismatchException if the length of the {@code points}
|
||||||
|
* list is not equal to 2.
|
||||||
|
*/
|
||||||
public boolean converged(final int iteration,
|
public boolean converged(final int iteration,
|
||||||
final VectorialPointValuePair previous,
|
final VectorialPointValuePair ... points) {
|
||||||
final VectorialPointValuePair current) {
|
if (points.length != 2) {
|
||||||
final double[] p = previous.getPointRef();
|
throw new DimensionMismatchException(points.length, 2);
|
||||||
final double[] c = current.getPointRef();
|
}
|
||||||
|
|
||||||
|
final double[] p = points[0].getPointRef();
|
||||||
|
final double[] c = points[1].getPointRef();
|
||||||
for (int i = 0; i < p.length; ++i) {
|
for (int i = 0; i < p.length; ++i) {
|
||||||
final double pi = p[i];
|
final double pi = p[i];
|
||||||
final double ci = c[i];
|
final double ci = c[i];
|
||||||
final double difference = FastMath.abs(pi - ci);
|
final double difference = Math.abs(pi - ci);
|
||||||
final double size = FastMath.max(FastMath.abs(pi), FastMath.abs(ci));
|
final double size = Math.max(Math.abs(pi), Math.abs(ci));
|
||||||
if ((difference > (size * relativeThreshold)) &&
|
if (difference > size * getRelativeThreshold() &&
|
||||||
(difference > absoluteThreshold)) {
|
difference > getAbsoluteThreshold()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,72 +19,82 @@ package org.apache.commons.math.optimization;
|
||||||
|
|
||||||
import org.apache.commons.math.util.FastMath;
|
import org.apache.commons.math.util.FastMath;
|
||||||
import org.apache.commons.math.util.MathUtils;
|
import org.apache.commons.math.util.MathUtils;
|
||||||
|
import org.apache.commons.math.exception.DimensionMismatchException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Simple implementation of the {@link VectorialConvergenceChecker} interface using
|
* Simple implementation of the {@link ConvergenceChecker} interface using
|
||||||
* only objective function values.
|
* only objective function values.
|
||||||
* <p>
|
*
|
||||||
* Convergence is considered to have been reached if either the relative
|
* Convergence is considered to have been reached if either the relative
|
||||||
* difference between the objective function values is smaller than a
|
* difference between the objective function values is smaller than a
|
||||||
* threshold or if either the absolute difference between the objective
|
* threshold or if either the absolute difference between the objective
|
||||||
* function values is smaller than another threshold for all vectors elements.
|
* function values is smaller than another threshold for all vectors elements.
|
||||||
* </p>
|
*
|
||||||
* @version $Revision$ $Date$
|
* @version $Revision$ $Date$
|
||||||
* @since 2.0
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
public class SimpleVectorialValueChecker implements VectorialConvergenceChecker {
|
public class SimpleVectorialValueChecker
|
||||||
|
extends AbstractConvergenceChecker<VectorialPointValuePair> {
|
||||||
/** Default relative threshold. */
|
/**
|
||||||
private static final double DEFAULT_RELATIVE_THRESHOLD = 100 * MathUtils.EPSILON;
|
* Build an instance with default thresholds.
|
||||||
|
|
||||||
/** 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() {
|
public SimpleVectorialValueChecker() {}
|
||||||
this.relativeThreshold = DEFAULT_RELATIVE_THRESHOLD;
|
|
||||||
this.absoluteThreshold = DEFAULT_ABSOLUTE_THRESHOLD;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Build an instance with a specified threshold.
|
/**
|
||||||
* <p>
|
* Build an instance with specified thresholds.
|
||||||
|
*
|
||||||
* In order to perform only relative checks, the absolute tolerance
|
* In order to perform only relative checks, the absolute tolerance
|
||||||
* must be set to a negative value. In order to perform only absolute
|
* must be set to a negative value. In order to perform only absolute
|
||||||
* checks, the relative tolerance must be set to a negative value.
|
* checks, the relative tolerance must be set to a negative value.
|
||||||
* </p>
|
*
|
||||||
* @param relativeThreshold relative tolerance threshold
|
* @param relativeThreshold relative tolerance threshold
|
||||||
* @param absoluteThreshold absolute tolerance threshold
|
* @param absoluteThreshold absolute tolerance threshold
|
||||||
*/
|
*/
|
||||||
public SimpleVectorialValueChecker(final double relativeThreshold,
|
public SimpleVectorialValueChecker(final double relativeThreshold,
|
||||||
final double absoluteThreshold) {
|
final double absoluteThreshold) {
|
||||||
this.relativeThreshold = relativeThreshold;
|
super(relativeThreshold, absoluteThreshold);
|
||||||
this.absoluteThreshold = absoluteThreshold;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
/**
|
||||||
|
* Check if the optimization algorithm has converged considering the
|
||||||
|
* last two points.
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* @param iteration Index of current iteration
|
||||||
|
* @param points Points used for checking convergence. The list must
|
||||||
|
* contain two elements:
|
||||||
|
* <ul>
|
||||||
|
* <li>the previous best point,</li>
|
||||||
|
* <li>the current best point.</li>
|
||||||
|
* </ul>
|
||||||
|
* @return {@code true} if the algorithm has converged.
|
||||||
|
* @throws DimensionMismatchException if the length of the {@code points}
|
||||||
|
* list is not equal to 2.
|
||||||
|
*/
|
||||||
public boolean converged(final int iteration,
|
public boolean converged(final int iteration,
|
||||||
final VectorialPointValuePair previous,
|
final VectorialPointValuePair ... points) {
|
||||||
final VectorialPointValuePair current) {
|
if (points.length != 2) {
|
||||||
final double[] p = previous.getValueRef();
|
throw new DimensionMismatchException(points.length, 2);
|
||||||
final double[] c = current.getValueRef();
|
}
|
||||||
|
|
||||||
|
final double[] p = points[0].getValueRef();
|
||||||
|
final double[] c = points[1].getValueRef();
|
||||||
for (int i = 0; i < p.length; ++i) {
|
for (int i = 0; i < p.length; ++i) {
|
||||||
final double pi = p[i];
|
final double pi = p[i];
|
||||||
final double ci = c[i];
|
final double ci = c[i];
|
||||||
final double difference = FastMath.abs(pi - ci);
|
final double difference = FastMath.abs(pi - ci);
|
||||||
final double size = FastMath.max(FastMath.abs(pi), FastMath.abs(ci));
|
final double size = FastMath.max(FastMath.abs(pi), FastMath.abs(ci));
|
||||||
if ((difference > (size * relativeThreshold)) &&
|
if (difference > size * getRelativeThreshold() &&
|
||||||
(difference > absoluteThreshold)) {
|
difference > getAbsoluteThreshold()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,115 +0,0 @@
|
||||||
/*
|
|
||||||
* 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.ConvergenceException;
|
|
||||||
import org.apache.commons.math.ConvergingAlgorithm;
|
|
||||||
import org.apache.commons.math.FunctionEvaluationException;
|
|
||||||
import org.apache.commons.math.analysis.UnivariateRealFunction;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Interface for (univariate real) optimization algorithms.
|
|
||||||
*
|
|
||||||
* @version $Revision$ $Date$
|
|
||||||
* @since 2.0
|
|
||||||
*/
|
|
||||||
public interface UnivariateRealOptimizer extends ConvergingAlgorithm {
|
|
||||||
|
|
||||||
/** Set the maximal number of functions evaluations.
|
|
||||||
* @param maxEvaluations maximal number of function evaluations
|
|
||||||
*/
|
|
||||||
void setMaxEvaluations(int maxEvaluations);
|
|
||||||
|
|
||||||
/** Get the maximal number of functions evaluations.
|
|
||||||
* @return the maximal number of functions evaluations.
|
|
||||||
*/
|
|
||||||
int getMaxEvaluations();
|
|
||||||
|
|
||||||
/** Get the number of evaluations of the objective function.
|
|
||||||
* <p>
|
|
||||||
* The number of evaluations corresponds to the last call to the
|
|
||||||
* {@link #optimize(UnivariateRealFunction, GoalType, double, double) optimize}
|
|
||||||
* method. It is 0 if the method has not been called yet.
|
|
||||||
* </p>
|
|
||||||
* @return the number of evaluations of the objective function.
|
|
||||||
*/
|
|
||||||
int getEvaluations();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Find an optimum in the given interval.
|
|
||||||
* <p>
|
|
||||||
* An optimizer may require that the interval brackets a single optimum.
|
|
||||||
* </p>
|
|
||||||
* @param f the function to optimize.
|
|
||||||
* @param goalType type of optimization goal: either {@link GoalType#MAXIMIZE}
|
|
||||||
* or {@link GoalType#MINIMIZE}.
|
|
||||||
* @param min the lower bound for the interval.
|
|
||||||
* @param max the upper bound for the interval.
|
|
||||||
* @return a value where the function is optimum.
|
|
||||||
* @throws ConvergenceException if the maximum iteration count is exceeded
|
|
||||||
* or the optimizer detects convergence problems otherwise.
|
|
||||||
* @throws FunctionEvaluationException if an error occurs evaluating the
|
|
||||||
* function.
|
|
||||||
* @throws IllegalArgumentException if min > max or the endpoints do not
|
|
||||||
* satisfy the requirements specified by the optimizer.
|
|
||||||
*/
|
|
||||||
double optimize(UnivariateRealFunction f, GoalType goalType,
|
|
||||||
double min, double max)
|
|
||||||
throws ConvergenceException, FunctionEvaluationException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Find an optimum in the given interval, start at startValue.
|
|
||||||
* <p>
|
|
||||||
* An optimizer may require that the interval brackets a single optimum.
|
|
||||||
* </p>
|
|
||||||
* @param f the function to optimize.
|
|
||||||
* @param goalType type of optimization goal: either {@link GoalType#MAXIMIZE}
|
|
||||||
* or {@link GoalType#MINIMIZE}.
|
|
||||||
* @param min the lower bound for the interval.
|
|
||||||
* @param max the upper bound for the interval.
|
|
||||||
* @param startValue the start value to use.
|
|
||||||
* @return a value where the function is optimum.
|
|
||||||
* @throws ConvergenceException if the maximum iteration count is exceeded
|
|
||||||
* or the optimizer detects convergence problems otherwise.
|
|
||||||
* @throws FunctionEvaluationException if an error occurs evaluating the
|
|
||||||
* function.
|
|
||||||
* @throws IllegalArgumentException if min > max or the arguments do not
|
|
||||||
* satisfy the requirements specified by the optimizer.
|
|
||||||
*/
|
|
||||||
double optimize(UnivariateRealFunction f, GoalType goalType,
|
|
||||||
double min, double max, double startValue)
|
|
||||||
throws ConvergenceException, FunctionEvaluationException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the result of the last run of the optimizer.
|
|
||||||
*
|
|
||||||
* @return the optimum.
|
|
||||||
* @throws IllegalStateException if there is no result available, either
|
|
||||||
* because no result was yet computed or the last attempt failed.
|
|
||||||
*/
|
|
||||||
double getResult();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the result of the last run of the optimizer.
|
|
||||||
*
|
|
||||||
* @return the value of the function at the optimum.
|
|
||||||
* @throws IllegalStateException if there is no result available, either
|
|
||||||
* because no result was yet computed or the last attempt failed.
|
|
||||||
*/
|
|
||||||
double getFunctionValue();
|
|
||||||
}
|
|
|
@ -22,16 +22,19 @@ import java.util.Comparator;
|
||||||
|
|
||||||
import org.apache.commons.math.FunctionEvaluationException;
|
import org.apache.commons.math.FunctionEvaluationException;
|
||||||
import org.apache.commons.math.MathRuntimeException;
|
import org.apache.commons.math.MathRuntimeException;
|
||||||
import org.apache.commons.math.MaxEvaluationsExceededException;
|
import org.apache.commons.math.util.Incrementor;
|
||||||
import org.apache.commons.math.MaxIterationsExceededException;
|
|
||||||
import org.apache.commons.math.analysis.MultivariateRealFunction;
|
import org.apache.commons.math.analysis.MultivariateRealFunction;
|
||||||
|
import org.apache.commons.math.exception.MaxCountExceededException;
|
||||||
|
import org.apache.commons.math.exception.TooManyEvaluationsException;
|
||||||
|
import org.apache.commons.math.exception.DimensionMismatchException;
|
||||||
import org.apache.commons.math.exception.util.LocalizedFormats;
|
import org.apache.commons.math.exception.util.LocalizedFormats;
|
||||||
import org.apache.commons.math.optimization.GoalType;
|
import org.apache.commons.math.optimization.GoalType;
|
||||||
import org.apache.commons.math.optimization.MultivariateRealOptimizer;
|
import org.apache.commons.math.optimization.MultivariateRealOptimizer;
|
||||||
import org.apache.commons.math.optimization.OptimizationException;
|
import org.apache.commons.math.optimization.OptimizationException;
|
||||||
import org.apache.commons.math.optimization.RealConvergenceChecker;
|
import org.apache.commons.math.optimization.ConvergenceChecker;
|
||||||
import org.apache.commons.math.optimization.RealPointValuePair;
|
import org.apache.commons.math.optimization.RealPointValuePair;
|
||||||
import org.apache.commons.math.optimization.SimpleScalarValueChecker;
|
import org.apache.commons.math.optimization.SimpleScalarValueChecker;
|
||||||
|
import org.apache.commons.math.optimization.general.AbstractScalarOptimizer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class implements simplex-based direct search optimization
|
* This class implements simplex-based direct search optimization
|
||||||
|
@ -67,7 +70,7 @@ import org.apache.commons.math.optimization.SimpleScalarValueChecker;
|
||||||
* change, the start configuration will be reset to a default one with the
|
* change, the start configuration will be reset to a default one with the
|
||||||
* appropriate dimensions.</p>
|
* appropriate dimensions.</p>
|
||||||
*
|
*
|
||||||
* <p>If {@link #setConvergenceChecker(RealConvergenceChecker)} is not called,
|
* <p>If {@link #setConvergenceChecker(ConvergenceChecker)} is not called,
|
||||||
* a default {@link SimpleScalarValueChecker} is used.</p>
|
* a default {@link SimpleScalarValueChecker} is used.</p>
|
||||||
*
|
*
|
||||||
* <p>Convergence is checked by providing the <em>worst</em> points of
|
* <p>Convergence is checked by providing the <em>worst</em> points of
|
||||||
|
@ -86,41 +89,24 @@ import org.apache.commons.math.optimization.SimpleScalarValueChecker;
|
||||||
* @version $Revision$ $Date$
|
* @version $Revision$ $Date$
|
||||||
* @since 1.2
|
* @since 1.2
|
||||||
*/
|
*/
|
||||||
public abstract class DirectSearchOptimizer implements MultivariateRealOptimizer {
|
public abstract class DirectSearchOptimizer
|
||||||
|
extends AbstractScalarOptimizer
|
||||||
|
implements MultivariateRealOptimizer {
|
||||||
/** Simplex. */
|
/** Simplex. */
|
||||||
protected RealPointValuePair[] simplex;
|
protected RealPointValuePair[] simplex;
|
||||||
|
|
||||||
/** Objective function. */
|
|
||||||
private MultivariateRealFunction f;
|
|
||||||
|
|
||||||
/** Convergence checker. */
|
|
||||||
private RealConvergenceChecker checker;
|
|
||||||
|
|
||||||
/** Maximal number of iterations allowed. */
|
|
||||||
private int maxIterations;
|
|
||||||
|
|
||||||
/** Number of iterations already performed. */
|
|
||||||
private int iterations;
|
|
||||||
|
|
||||||
/** Maximal number of evaluations allowed. */
|
|
||||||
private int maxEvaluations;
|
|
||||||
|
|
||||||
/** Number of evaluations already performed. */
|
|
||||||
private int evaluations;
|
|
||||||
|
|
||||||
/** Start simplex configuration. */
|
/** Start simplex configuration. */
|
||||||
private double[][] startConfiguration;
|
private double[][] startConfiguration;
|
||||||
|
|
||||||
/** Simple constructor.
|
/**
|
||||||
|
* Default constructor.
|
||||||
*/
|
*/
|
||||||
protected DirectSearchOptimizer() {
|
protected DirectSearchOptimizer() {
|
||||||
setConvergenceChecker(new SimpleScalarValueChecker());
|
setConvergenceChecker(new SimpleScalarValueChecker());
|
||||||
setMaxIterations(Integer.MAX_VALUE);
|
|
||||||
setMaxEvaluations(Integer.MAX_VALUE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Set start configuration for simplex.
|
/**
|
||||||
|
* Set start configuration for simplex.
|
||||||
|
*
|
||||||
* <p>The start configuration for simplex is built from a box parallel to
|
* <p>The start configuration for simplex is built from a box parallel to
|
||||||
* the canonical axes of the space. The simplex is the subset of vertices
|
* the canonical axes of the space. The simplex is the subset of vertices
|
||||||
* of a box parallel to the canonical axes. It is built as the path followed
|
* of a box parallel to the canonical axes. It is built as the path followed
|
||||||
|
@ -132,9 +118,10 @@ public abstract class DirectSearchOptimizer implements MultivariateRealOptimizer
|
||||||
* start simplex would be: { (1, 1, 1), (2, 1, 1), (2, 11, 1), (2, 11, 3) }.
|
* start simplex would be: { (1, 1, 1), (2, 1, 1), (2, 11, 1), (2, 11, 3) }.
|
||||||
* The first vertex would be set to the start point at (1, 1, 1) and the
|
* The first vertex would be set to the start point at (1, 1, 1) and the
|
||||||
* last vertex would be set to the diagonally opposite vertex at (2, 11, 3).</p>
|
* last vertex would be set to the diagonally opposite vertex at (2, 11, 3).</p>
|
||||||
* @param steps steps along the canonical axes representing box edges,
|
*
|
||||||
* they may be negative but not null
|
* @param steps Steps along the canonical axes representing box edges. They
|
||||||
* @exception IllegalArgumentException if one step is null
|
* may be negative but not zero.
|
||||||
|
* @throws IllegalArgumentException if one step is zero.
|
||||||
*/
|
*/
|
||||||
public void setStartConfiguration(final double[] steps)
|
public void setStartConfiguration(final double[] steps)
|
||||||
throws IllegalArgumentException {
|
throws IllegalArgumentException {
|
||||||
|
@ -154,14 +141,16 @@ public abstract class DirectSearchOptimizer implements MultivariateRealOptimizer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Set start configuration for simplex.
|
/**
|
||||||
* <p>The real initial simplex will be set up by moving the reference
|
* Set start configuration for simplex.
|
||||||
|
* The real initial simplex will be set up by moving the reference
|
||||||
* simplex such that its first point is located at the start point of the
|
* simplex such that its first point is located at the start point of the
|
||||||
* optimization.</p>
|
* optimization.
|
||||||
* @param referenceSimplex reference simplex
|
*
|
||||||
* @exception IllegalArgumentException if the reference simplex does not
|
* @param referenceSimplex Reference simplex.
|
||||||
|
* @throws IllegalArgumentException if the reference simplex does not
|
||||||
* contain at least one point, or if there is a dimension mismatch
|
* contain at least one point, or if there is a dimension mismatch
|
||||||
* in the reference simplex or if one of its vertices is duplicated
|
* in the reference simplex or if one of its vertices is duplicated.
|
||||||
*/
|
*/
|
||||||
public void setStartConfiguration(final double[][] referenceSimplex)
|
public void setStartConfiguration(final double[][] referenceSimplex)
|
||||||
throws IllegalArgumentException {
|
throws IllegalArgumentException {
|
||||||
|
@ -183,8 +172,7 @@ public abstract class DirectSearchOptimizer implements MultivariateRealOptimizer
|
||||||
|
|
||||||
// safety checks
|
// safety checks
|
||||||
if (refI.length != n) {
|
if (refI.length != n) {
|
||||||
throw MathRuntimeException.createIllegalArgumentException(
|
throw new DimensionMismatchException(refI.length, n);
|
||||||
LocalizedFormats.DIMENSIONS_MISMATCH_SIMPLE, refI.length, n);
|
|
||||||
}
|
}
|
||||||
for (int j = 0; j < i; ++j) {
|
for (int j = 0; j < i; ++j) {
|
||||||
final double[] refJ = referenceSimplex[j];
|
final double[] refJ = referenceSimplex[j];
|
||||||
|
@ -208,92 +196,46 @@ public abstract class DirectSearchOptimizer implements MultivariateRealOptimizer
|
||||||
confI[k] = refI[k] - ref0[k];
|
confI[k] = refI[k] - ref0[k];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
/** {@inheritDoc} */
|
||||||
public void setMaxIterations(int maxIterations) {
|
protected RealPointValuePair doOptimize()
|
||||||
this.maxIterations = maxIterations;
|
throws FunctionEvaluationException {
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
public int getMaxIterations() {
|
|
||||||
return maxIterations;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
public void setMaxEvaluations(int maxEvaluations) {
|
|
||||||
this.maxEvaluations = maxEvaluations;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
public int getMaxEvaluations() {
|
|
||||||
return maxEvaluations;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
public int getIterations() {
|
|
||||||
return iterations;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
public int getEvaluations() {
|
|
||||||
return evaluations;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
public void setConvergenceChecker(RealConvergenceChecker convergenceChecker) {
|
|
||||||
this.checker = convergenceChecker;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
public RealConvergenceChecker getConvergenceChecker() {
|
|
||||||
return checker;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
public RealPointValuePair optimize(final MultivariateRealFunction function,
|
|
||||||
final GoalType goalType,
|
|
||||||
final double[] startPoint)
|
|
||||||
throws FunctionEvaluationException, OptimizationException,
|
|
||||||
IllegalArgumentException {
|
|
||||||
|
|
||||||
|
final double[] startPoint = getStartPoint();
|
||||||
if ((startConfiguration == null) ||
|
if ((startConfiguration == null) ||
|
||||||
(startConfiguration.length != startPoint.length)) {
|
(startConfiguration.length != startPoint.length)) {
|
||||||
// no initial configuration has been set up for simplex
|
// No initial configuration has been set up for simplex
|
||||||
// build a default one from a unit hypercube
|
// build a default one from a unit hypercube.
|
||||||
final double[] unit = new double[startPoint.length];
|
final double[] unit = new double[startPoint.length];
|
||||||
Arrays.fill(unit, 1.0);
|
Arrays.fill(unit, 1.0);
|
||||||
setStartConfiguration(unit);
|
setStartConfiguration(unit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final boolean isMinim = (getGoalType() == GoalType.MINIMIZE);
|
||||||
|
final Comparator<RealPointValuePair> comparator
|
||||||
|
= new Comparator<RealPointValuePair>() {
|
||||||
|
public int compare(final RealPointValuePair o1,
|
||||||
|
final RealPointValuePair o2) {
|
||||||
|
final double v1 = o1.getValue();
|
||||||
|
final double v2 = o2.getValue();
|
||||||
|
return isMinim ? Double.compare(v1, v2) : Double.compare(v2, v1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
this.f = function;
|
// Initialize search.
|
||||||
final Comparator<RealPointValuePair> comparator =
|
|
||||||
new Comparator<RealPointValuePair>() {
|
|
||||||
public int compare(final RealPointValuePair o1,
|
|
||||||
final RealPointValuePair o2) {
|
|
||||||
final double v1 = o1.getValue();
|
|
||||||
final double v2 = o2.getValue();
|
|
||||||
return (goalType == GoalType.MINIMIZE) ?
|
|
||||||
Double.compare(v1, v2) : Double.compare(v2, v1);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// initialize search
|
|
||||||
iterations = 0;
|
|
||||||
evaluations = 0;
|
|
||||||
buildSimplex(startPoint);
|
buildSimplex(startPoint);
|
||||||
evaluateSimplex(comparator);
|
evaluateSimplex(comparator);
|
||||||
|
|
||||||
RealPointValuePair[] previous = new RealPointValuePair[simplex.length];
|
RealPointValuePair[] previous = new RealPointValuePair[simplex.length];
|
||||||
|
int iteration = 0;
|
||||||
|
final ConvergenceChecker<RealPointValuePair> checker = getConvergenceChecker();
|
||||||
while (true) {
|
while (true) {
|
||||||
|
if (iteration > 0) {
|
||||||
if (iterations > 0) {
|
|
||||||
boolean converged = true;
|
boolean converged = true;
|
||||||
for (int i = 0; i < simplex.length; ++i) {
|
for (int i = 0; i < simplex.length; ++i) {
|
||||||
converged &= checker.converged(iterations, previous[i], simplex[i]);
|
converged &= checker.converged(iteration, previous[i], simplex[i]);
|
||||||
}
|
}
|
||||||
if (converged) {
|
if (converged) {
|
||||||
// we have found an optimum
|
// we have found an optimum
|
||||||
|
@ -301,65 +243,37 @@ public abstract class DirectSearchOptimizer implements MultivariateRealOptimizer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// we still need to search
|
// We still need to search.
|
||||||
System.arraycopy(simplex, 0, previous, 0, simplex.length);
|
System.arraycopy(simplex, 0, previous, 0, simplex.length);
|
||||||
iterateSimplex(comparator);
|
iterateSimplex(comparator);
|
||||||
|
++iteration;
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Increment the iterations counter by 1.
|
|
||||||
* @exception OptimizationException if the maximal number
|
|
||||||
* of iterations is exceeded
|
|
||||||
*/
|
|
||||||
protected void incrementIterationsCounter()
|
|
||||||
throws OptimizationException {
|
|
||||||
if (++iterations > maxIterations) {
|
|
||||||
throw new OptimizationException(new MaxIterationsExceededException(maxIterations));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Compute the next simplex of the algorithm.
|
/**
|
||||||
* @param comparator comparator to use to sort simplex vertices from best to worst
|
* Compute the next simplex of the algorithm.
|
||||||
* @exception FunctionEvaluationException if the function cannot be evaluated at
|
*
|
||||||
* some point
|
* @param comparator Comparator to use to sort simplex vertices from best to worst.
|
||||||
* @exception OptimizationException if the algorithm fails to converge
|
* @throws FunctionEvaluationException if the function cannot be evaluated at
|
||||||
* @exception IllegalArgumentException if the start point dimension is wrong
|
* some point.
|
||||||
|
* @throws TooManyEvaluationsException if the algorithm fails to converge.
|
||||||
|
* @throws DimensionMismatchException if the start point dimension is wrong.
|
||||||
*/
|
*/
|
||||||
protected abstract void iterateSimplex(final Comparator<RealPointValuePair> comparator)
|
protected abstract void iterateSimplex(final Comparator<RealPointValuePair> comparator)
|
||||||
throws FunctionEvaluationException, OptimizationException, IllegalArgumentException;
|
throws FunctionEvaluationException;
|
||||||
|
|
||||||
/** Evaluate the objective function on one point.
|
/**
|
||||||
* <p>A side effect of this method is to count the number of
|
* Build an initial simplex.
|
||||||
* function evaluations</p>
|
*
|
||||||
* @param x point on which the objective function should be evaluated
|
* @param startPoint Start point for optimization.
|
||||||
* @return objective function value at the given point
|
* @throws DimensionMismatchException if the start point does not match
|
||||||
* @exception FunctionEvaluationException if no value can be computed for the
|
* simplex dimension.
|
||||||
* parameters or if the maximal number of evaluations is exceeded
|
|
||||||
* @exception IllegalArgumentException if the start point dimension is wrong
|
|
||||||
*/
|
*/
|
||||||
protected double evaluate(final double[] x)
|
private void buildSimplex(final double[] startPoint) {
|
||||||
throws FunctionEvaluationException, IllegalArgumentException {
|
|
||||||
if (++evaluations > maxEvaluations) {
|
|
||||||
throw new FunctionEvaluationException(new MaxEvaluationsExceededException(maxEvaluations),
|
|
||||||
x);
|
|
||||||
}
|
|
||||||
return f.value(x);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Build an initial simplex.
|
|
||||||
* @param startPoint the start point for optimization
|
|
||||||
* @exception IllegalArgumentException if the start point does not match
|
|
||||||
* simplex dimension
|
|
||||||
*/
|
|
||||||
private void buildSimplex(final double[] startPoint)
|
|
||||||
throws IllegalArgumentException {
|
|
||||||
|
|
||||||
final int n = startPoint.length;
|
final int n = startPoint.length;
|
||||||
if (n != startConfiguration.length) {
|
if (n != startConfiguration.length) {
|
||||||
throw MathRuntimeException.createIllegalArgumentException(
|
throw new DimensionMismatchException(n, startConfiguration.length);
|
||||||
LocalizedFormats.DIMENSIONS_MISMATCH_SIMPLE, n, startConfiguration.length);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// set first vertex
|
// set first vertex
|
||||||
|
@ -368,41 +282,43 @@ public abstract class DirectSearchOptimizer implements MultivariateRealOptimizer
|
||||||
|
|
||||||
// set remaining vertices
|
// set remaining vertices
|
||||||
for (int i = 0; i < n; ++i) {
|
for (int i = 0; i < n; ++i) {
|
||||||
final double[] confI = startConfiguration[i];
|
final double[] confI = startConfiguration[i];
|
||||||
final double[] vertexI = new double[n];
|
final double[] vertexI = new double[n];
|
||||||
for (int k = 0; k < n; ++k) {
|
for (int k = 0; k < n; ++k) {
|
||||||
vertexI[k] = startPoint[k] + confI[k];
|
vertexI[k] = startPoint[k] + confI[k];
|
||||||
}
|
}
|
||||||
simplex[i + 1] = new RealPointValuePair(vertexI, Double.NaN);
|
simplex[i + 1] = new RealPointValuePair(vertexI, Double.NaN);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Evaluate all the non-evaluated points of the simplex.
|
/**
|
||||||
* @param comparator comparator to use to sort simplex vertices from best to worst
|
* Evaluate all the non-evaluated points of the simplex.
|
||||||
* @exception FunctionEvaluationException if no value can be computed for the parameters
|
*
|
||||||
* @exception OptimizationException if the maximal number of evaluations is exceeded
|
* @param comparator Comparator to use to sort simplex vertices from best to worst.
|
||||||
|
* @throws FunctionEvaluationException if no value can be computed for the parameters.
|
||||||
|
* @throws TooManyEvaluationsException if the maximal number of evaluations is exceeded.
|
||||||
*/
|
*/
|
||||||
protected void evaluateSimplex(final Comparator<RealPointValuePair> comparator)
|
protected void evaluateSimplex(final Comparator<RealPointValuePair> comparator)
|
||||||
throws FunctionEvaluationException, OptimizationException {
|
throws FunctionEvaluationException {
|
||||||
|
|
||||||
// evaluate the objective function at all non-evaluated simplex points
|
// Evaluate the objective function at all non-evaluated simplex points.
|
||||||
for (int i = 0; i < simplex.length; ++i) {
|
for (int i = 0; i < simplex.length; ++i) {
|
||||||
final RealPointValuePair vertex = simplex[i];
|
final RealPointValuePair vertex = simplex[i];
|
||||||
final double[] point = vertex.getPointRef();
|
final double[] point = vertex.getPointRef();
|
||||||
if (Double.isNaN(vertex.getValue())) {
|
if (Double.isNaN(vertex.getValue())) {
|
||||||
simplex[i] = new RealPointValuePair(point, evaluate(point), false);
|
simplex[i] = new RealPointValuePair(point, computeObjectiveValue(point), false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// sort the simplex from best to worst
|
// Sort the simplex from best to worst.
|
||||||
Arrays.sort(simplex, comparator);
|
Arrays.sort(simplex, comparator);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Replace the worst point of the simplex by a new point.
|
/**
|
||||||
* @param pointValuePair point to insert
|
* Replace the worst point of the simplex by a new point.
|
||||||
* @param comparator comparator to use to sort simplex vertices from best to worst
|
*
|
||||||
|
* @param pointValuePair Point to insert.
|
||||||
|
* @param comparator Comparator to use to sort simplex vertices from best to worst.
|
||||||
*/
|
*/
|
||||||
protected void replaceWorstPoint(RealPointValuePair pointValuePair,
|
protected void replaceWorstPoint(RealPointValuePair pointValuePair,
|
||||||
final Comparator<RealPointValuePair> comparator) {
|
final Comparator<RealPointValuePair> comparator) {
|
||||||
|
@ -410,11 +326,10 @@ public abstract class DirectSearchOptimizer implements MultivariateRealOptimizer
|
||||||
for (int i = 0; i < n; ++i) {
|
for (int i = 0; i < n; ++i) {
|
||||||
if (comparator.compare(simplex[i], pointValuePair) > 0) {
|
if (comparator.compare(simplex[i], pointValuePair) > 0) {
|
||||||
RealPointValuePair tmp = simplex[i];
|
RealPointValuePair tmp = simplex[i];
|
||||||
simplex[i] = pointValuePair;
|
simplex[i] = pointValuePair;
|
||||||
pointValuePair = tmp;
|
pointValuePair = tmp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
simplex[n] = pointValuePair;
|
simplex[n] = pointValuePair;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,8 +20,7 @@ package org.apache.commons.math.optimization.direct;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
|
|
||||||
import org.apache.commons.math.FunctionEvaluationException;
|
import org.apache.commons.math.FunctionEvaluationException;
|
||||||
import org.apache.commons.math.optimization.OptimizationException;
|
import org.apache.commons.math.optimization.ConvergenceChecker;
|
||||||
import org.apache.commons.math.optimization.RealConvergenceChecker;
|
|
||||||
import org.apache.commons.math.optimization.RealPointValuePair;
|
import org.apache.commons.math.optimization.RealPointValuePair;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -59,72 +58,72 @@ public class MultiDirectional extends DirectSearchOptimizer {
|
||||||
/** {@inheritDoc} */
|
/** {@inheritDoc} */
|
||||||
@Override
|
@Override
|
||||||
protected void iterateSimplex(final Comparator<RealPointValuePair> comparator)
|
protected void iterateSimplex(final Comparator<RealPointValuePair> comparator)
|
||||||
throws FunctionEvaluationException, OptimizationException, IllegalArgumentException {
|
throws FunctionEvaluationException {
|
||||||
|
|
||||||
final RealConvergenceChecker checker = getConvergenceChecker();
|
final ConvergenceChecker<RealPointValuePair> checker = getConvergenceChecker();
|
||||||
|
int iteration = 0;
|
||||||
while (true) {
|
while (true) {
|
||||||
|
++iteration;
|
||||||
|
|
||||||
incrementIterationsCounter();
|
// Save the original vertex.
|
||||||
|
|
||||||
// save the original vertex
|
|
||||||
final RealPointValuePair[] original = simplex;
|
final RealPointValuePair[] original = simplex;
|
||||||
final RealPointValuePair best = original[0];
|
final RealPointValuePair best = original[0];
|
||||||
|
|
||||||
// perform a reflection step
|
// Perform a reflection step.
|
||||||
final RealPointValuePair reflected = evaluateNewSimplex(original, 1.0, comparator);
|
final RealPointValuePair reflected = evaluateNewSimplex(original, 1.0, comparator);
|
||||||
if (comparator.compare(reflected, best) < 0) {
|
if (comparator.compare(reflected, best) < 0) {
|
||||||
|
|
||||||
// compute the expanded simplex
|
// Compute the expanded simplex.
|
||||||
final RealPointValuePair[] reflectedSimplex = simplex;
|
final RealPointValuePair[] reflectedSimplex = simplex;
|
||||||
final RealPointValuePair expanded = evaluateNewSimplex(original, khi, comparator);
|
final RealPointValuePair expanded = evaluateNewSimplex(original, khi, comparator);
|
||||||
if (comparator.compare(reflected, expanded) <= 0) {
|
if (comparator.compare(reflected, expanded) <= 0) {
|
||||||
// accept the reflected simplex
|
// Accept the reflected simplex.
|
||||||
simplex = reflectedSimplex;
|
simplex = reflectedSimplex;
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// compute the contracted simplex
|
// Compute the contracted simplex.
|
||||||
final RealPointValuePair contracted = evaluateNewSimplex(original, gamma, comparator);
|
final RealPointValuePair contracted = evaluateNewSimplex(original, gamma, comparator);
|
||||||
if (comparator.compare(contracted, best) < 0) {
|
if (comparator.compare(contracted, best) < 0) {
|
||||||
// accept the contracted simplex
|
// Accept the contracted simplex.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// check convergence
|
// Check convergence.
|
||||||
final int iter = getIterations();
|
|
||||||
boolean converged = true;
|
boolean converged = true;
|
||||||
for (int i = 0; i < simplex.length; ++i) {
|
for (int i = 0; i < simplex.length; ++i) {
|
||||||
converged &= checker.converged(iter, original[i], simplex[i]);
|
converged &= checker.converged(iteration, original[i], simplex[i]);
|
||||||
}
|
}
|
||||||
if (converged) {
|
if (converged) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Compute and evaluate a new simplex.
|
/**
|
||||||
* @param original original simplex (to be preserved)
|
* Compute and evaluate a new simplex.
|
||||||
* @param coeff linear coefficient
|
*
|
||||||
* @param comparator comparator to use to sort simplex vertices from best to poorest
|
* @param original Original simplex (to be preserved).
|
||||||
* @return best point in the transformed simplex
|
* @param coeff Linear coefficient.
|
||||||
* @exception FunctionEvaluationException if the function cannot be evaluated at
|
* @param comparator Comparator to use to sort simplex vertices from best
|
||||||
* some point
|
* to poorest.
|
||||||
* @exception OptimizationException if the maximal number of evaluations is exceeded
|
* @return the best point in the transformed simplex.
|
||||||
|
* @exception FunctionEvaluationException if the function cannot be
|
||||||
|
* evaluated at some point.
|
||||||
|
* @exception TooManyEvaluationsException if the maximal number of
|
||||||
|
* evaluations is exceeded.
|
||||||
*/
|
*/
|
||||||
private RealPointValuePair evaluateNewSimplex(final RealPointValuePair[] original,
|
private RealPointValuePair evaluateNewSimplex(final RealPointValuePair[] original,
|
||||||
final double coeff,
|
final double coeff,
|
||||||
final Comparator<RealPointValuePair> comparator)
|
final Comparator<RealPointValuePair> comparator)
|
||||||
throws FunctionEvaluationException, OptimizationException {
|
throws FunctionEvaluationException {
|
||||||
|
|
||||||
final double[] xSmallest = original[0].getPointRef();
|
final double[] xSmallest = original[0].getPointRef();
|
||||||
final int n = xSmallest.length;
|
final int n = xSmallest.length;
|
||||||
|
|
||||||
// create the linearly transformed simplex
|
// Create the linearly transformed simplex.
|
||||||
simplex = new RealPointValuePair[n + 1];
|
simplex = new RealPointValuePair[n + 1];
|
||||||
simplex[0] = original[0];
|
simplex[0] = original[0];
|
||||||
for (int i = 1; i <= n; ++i) {
|
for (int i = 1; i <= n; ++i) {
|
||||||
|
@ -136,10 +135,8 @@ public class MultiDirectional extends DirectSearchOptimizer {
|
||||||
simplex[i] = new RealPointValuePair(xTransformed, Double.NaN, false);
|
simplex[i] = new RealPointValuePair(xTransformed, Double.NaN, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// evaluate it
|
// Evaluate the simplex.
|
||||||
evaluateSimplex(comparator);
|
evaluateSimplex(comparator);
|
||||||
return simplex[0];
|
return simplex[0];
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,6 @@ package org.apache.commons.math.optimization.direct;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
|
|
||||||
import org.apache.commons.math.FunctionEvaluationException;
|
import org.apache.commons.math.FunctionEvaluationException;
|
||||||
import org.apache.commons.math.optimization.OptimizationException;
|
|
||||||
import org.apache.commons.math.optimization.RealPointValuePair;
|
import org.apache.commons.math.optimization.RealPointValuePair;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -72,9 +71,7 @@ public class NelderMead extends DirectSearchOptimizer {
|
||||||
/** {@inheritDoc} */
|
/** {@inheritDoc} */
|
||||||
@Override
|
@Override
|
||||||
protected void iterateSimplex(final Comparator<RealPointValuePair> comparator)
|
protected void iterateSimplex(final Comparator<RealPointValuePair> comparator)
|
||||||
throws FunctionEvaluationException, OptimizationException {
|
throws FunctionEvaluationException {
|
||||||
|
|
||||||
incrementIterationsCounter();
|
|
||||||
|
|
||||||
// the simplex has n+1 point if dimension is n
|
// the simplex has n+1 point if dimension is n
|
||||||
final int n = simplex.length - 1;
|
final int n = simplex.length - 1;
|
||||||
|
@ -104,7 +101,8 @@ public class NelderMead extends DirectSearchOptimizer {
|
||||||
for (int j = 0; j < n; ++j) {
|
for (int j = 0; j < n; ++j) {
|
||||||
xR[j] = centroid[j] + rho * (centroid[j] - xWorst[j]);
|
xR[j] = centroid[j] + rho * (centroid[j] - xWorst[j]);
|
||||||
}
|
}
|
||||||
final RealPointValuePair reflected = new RealPointValuePair(xR, evaluate(xR), false);
|
final RealPointValuePair reflected
|
||||||
|
= new RealPointValuePair(xR, computeObjectiveValue(xR), false);
|
||||||
|
|
||||||
if ((comparator.compare(best, reflected) <= 0) &&
|
if ((comparator.compare(best, reflected) <= 0) &&
|
||||||
(comparator.compare(reflected, secondBest) < 0)) {
|
(comparator.compare(reflected, secondBest) < 0)) {
|
||||||
|
@ -119,7 +117,8 @@ public class NelderMead extends DirectSearchOptimizer {
|
||||||
for (int j = 0; j < n; ++j) {
|
for (int j = 0; j < n; ++j) {
|
||||||
xE[j] = centroid[j] + khi * (xR[j] - centroid[j]);
|
xE[j] = centroid[j] + khi * (xR[j] - centroid[j]);
|
||||||
}
|
}
|
||||||
final RealPointValuePair expanded = new RealPointValuePair(xE, evaluate(xE), false);
|
final RealPointValuePair expanded
|
||||||
|
= new RealPointValuePair(xE, computeObjectiveValue(xE), false);
|
||||||
|
|
||||||
if (comparator.compare(expanded, reflected) < 0) {
|
if (comparator.compare(expanded, reflected) < 0) {
|
||||||
// accept the expansion point
|
// accept the expansion point
|
||||||
|
@ -138,7 +137,8 @@ public class NelderMead extends DirectSearchOptimizer {
|
||||||
for (int j = 0; j < n; ++j) {
|
for (int j = 0; j < n; ++j) {
|
||||||
xC[j] = centroid[j] + gamma * (xR[j] - centroid[j]);
|
xC[j] = centroid[j] + gamma * (xR[j] - centroid[j]);
|
||||||
}
|
}
|
||||||
final RealPointValuePair outContracted = new RealPointValuePair(xC, evaluate(xC), false);
|
final RealPointValuePair outContracted
|
||||||
|
= new RealPointValuePair(xC, computeObjectiveValue(xC), false);
|
||||||
|
|
||||||
if (comparator.compare(outContracted, reflected) <= 0) {
|
if (comparator.compare(outContracted, reflected) <= 0) {
|
||||||
// accept the contraction point
|
// accept the contraction point
|
||||||
|
@ -153,7 +153,8 @@ public class NelderMead extends DirectSearchOptimizer {
|
||||||
for (int j = 0; j < n; ++j) {
|
for (int j = 0; j < n; ++j) {
|
||||||
xC[j] = centroid[j] - gamma * (centroid[j] - xWorst[j]);
|
xC[j] = centroid[j] - gamma * (centroid[j] - xWorst[j]);
|
||||||
}
|
}
|
||||||
final RealPointValuePair inContracted = new RealPointValuePair(xC, evaluate(xC), false);
|
final RealPointValuePair inContracted
|
||||||
|
= new RealPointValuePair(xC, computeObjectiveValue(xC), false);
|
||||||
|
|
||||||
if (comparator.compare(inContracted, worst) < 0) {
|
if (comparator.compare(inContracted, worst) < 0) {
|
||||||
// accept the contraction point
|
// accept the contraction point
|
||||||
|
@ -173,9 +174,6 @@ public class NelderMead extends DirectSearchOptimizer {
|
||||||
simplex[i] = new RealPointValuePair(x, Double.NaN, false);
|
simplex[i] = new RealPointValuePair(x, Double.NaN, false);
|
||||||
}
|
}
|
||||||
evaluateSimplex(comparator);
|
evaluateSimplex(comparator);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,6 @@ import org.apache.commons.math.FunctionEvaluationException;
|
||||||
import org.apache.commons.math.analysis.DifferentiableMultivariateVectorialFunction;
|
import org.apache.commons.math.analysis.DifferentiableMultivariateVectorialFunction;
|
||||||
import org.apache.commons.math.analysis.MultivariateMatrixFunction;
|
import org.apache.commons.math.analysis.MultivariateMatrixFunction;
|
||||||
import org.apache.commons.math.optimization.DifferentiableMultivariateVectorialOptimizer;
|
import org.apache.commons.math.optimization.DifferentiableMultivariateVectorialOptimizer;
|
||||||
import org.apache.commons.math.optimization.OptimizationException;
|
|
||||||
import org.apache.commons.math.optimization.VectorialPointValuePair;
|
import org.apache.commons.math.optimization.VectorialPointValuePair;
|
||||||
|
|
||||||
/** Fitter for parametric univariate real functions y = f(x).
|
/** Fitter for parametric univariate real functions y = f(x).
|
||||||
|
@ -120,12 +119,12 @@ public class CurveFitter {
|
||||||
* @return fitted parameters
|
* @return fitted parameters
|
||||||
* @exception FunctionEvaluationException 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 ConvergenceException if the algorithm failed to converge
|
||||||
* @exception IllegalArgumentException if the start point dimension is wrong
|
* @exception IllegalArgumentException if the start point dimension is wrong.
|
||||||
*/
|
*/
|
||||||
public double[] fit(final ParametricRealFunction f,
|
public double[] fit(final ParametricRealFunction f,
|
||||||
final double[] initialGuess)
|
final double[] initialGuess)
|
||||||
throws FunctionEvaluationException, OptimizationException, IllegalArgumentException {
|
throws FunctionEvaluationException {
|
||||||
|
|
||||||
// prepare least squares problem
|
// prepare least squares problem
|
||||||
double[] target = new double[observations.size()];
|
double[] target = new double[observations.size()];
|
||||||
|
@ -143,7 +142,6 @@ public class CurveFitter {
|
||||||
|
|
||||||
// extract the coefficients
|
// extract the coefficients
|
||||||
return optimum.getPointRef();
|
return optimum.getPointRef();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Vectorial function computing function theoretical values. */
|
/** Vectorial function computing function theoretical values. */
|
||||||
|
|
|
@ -21,7 +21,7 @@ import org.apache.commons.math.FunctionEvaluationException;
|
||||||
import org.apache.commons.math.MathRuntimeException;
|
import org.apache.commons.math.MathRuntimeException;
|
||||||
import org.apache.commons.math.analysis.polynomials.PolynomialFunction;
|
import org.apache.commons.math.analysis.polynomials.PolynomialFunction;
|
||||||
import org.apache.commons.math.optimization.DifferentiableMultivariateVectorialOptimizer;
|
import org.apache.commons.math.optimization.DifferentiableMultivariateVectorialOptimizer;
|
||||||
import org.apache.commons.math.optimization.OptimizationException;
|
import org.apache.commons.math.exception.ConvergenceException;
|
||||||
|
|
||||||
/** This class implements a curve fitting specialized for polynomials.
|
/** This class implements a curve fitting specialized for polynomials.
|
||||||
* <p>Polynomial fitting is a very simple case of curve fitting. The
|
* <p>Polynomial fitting is a very simple case of curve fitting. The
|
||||||
|
@ -69,10 +69,9 @@ public class PolynomialFitter {
|
||||||
|
|
||||||
/** Get the polynomial fitting the weighted (x, y) points.
|
/** Get the polynomial fitting the weighted (x, y) points.
|
||||||
* @return polynomial function best fitting the observed points
|
* @return polynomial function best fitting the observed points
|
||||||
* @exception OptimizationException if the algorithm failed to converge
|
* @exception ConvergenceException if the algorithm failed to converge
|
||||||
*/
|
*/
|
||||||
public PolynomialFunction fit()
|
public PolynomialFunction fit() {
|
||||||
throws OptimizationException {
|
|
||||||
try {
|
try {
|
||||||
return new PolynomialFunction(fitter.fit(new ParametricPolynomial(), new double[degree + 1]));
|
return new PolynomialFunction(fitter.fit(new ParametricPolynomial(), new double[degree + 1]));
|
||||||
} catch (FunctionEvaluationException fee) {
|
} catch (FunctionEvaluationException fee) {
|
||||||
|
|
|
@ -18,8 +18,7 @@
|
||||||
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.FunctionEvaluationException;
|
||||||
import org.apache.commons.math.MaxEvaluationsExceededException;
|
import org.apache.commons.math.exception.ConvergenceException;
|
||||||
import org.apache.commons.math.MaxIterationsExceededException;
|
|
||||||
import org.apache.commons.math.analysis.DifferentiableMultivariateVectorialFunction;
|
import org.apache.commons.math.analysis.DifferentiableMultivariateVectorialFunction;
|
||||||
import org.apache.commons.math.analysis.MultivariateMatrixFunction;
|
import org.apache.commons.math.analysis.MultivariateMatrixFunction;
|
||||||
import org.apache.commons.math.exception.util.LocalizedFormats;
|
import org.apache.commons.math.exception.util.LocalizedFormats;
|
||||||
|
@ -27,155 +26,72 @@ import org.apache.commons.math.linear.InvalidMatrixException;
|
||||||
import org.apache.commons.math.linear.LUDecompositionImpl;
|
import org.apache.commons.math.linear.LUDecompositionImpl;
|
||||||
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.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.ConvergenceChecker;
|
||||||
import org.apache.commons.math.optimization.DifferentiableMultivariateVectorialOptimizer;
|
import org.apache.commons.math.optimization.DifferentiableMultivariateVectorialOptimizer;
|
||||||
import org.apache.commons.math.optimization.VectorialPointValuePair;
|
import org.apache.commons.math.optimization.VectorialPointValuePair;
|
||||||
import org.apache.commons.math.util.FastMath;
|
import org.apache.commons.math.util.FastMath;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class for implementing least squares optimizers.
|
* Base class for implementing least squares optimizers.
|
||||||
* <p>This base class handles the boilerplate methods associated to thresholds
|
* It handles the boilerplate methods associated to thresholds settings,
|
||||||
* settings, jacobian and error estimation.</p>
|
* jacobian and error estimation.
|
||||||
|
*
|
||||||
* @version $Revision$ $Date$
|
* @version $Revision$ $Date$
|
||||||
* @since 1.2
|
* @since 1.2
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public abstract class AbstractLeastSquaresOptimizer implements DifferentiableMultivariateVectorialOptimizer {
|
public abstract class AbstractLeastSquaresOptimizer
|
||||||
|
extends BaseAbstractVectorialOptimizer<DifferentiableMultivariateVectorialFunction>
|
||||||
/** Default maximal number of iterations allowed. */
|
implements DifferentiableMultivariateVectorialOptimizer {
|
||||||
public static final int DEFAULT_MAX_ITERATIONS = 100;
|
|
||||||
|
|
||||||
/** Convergence checker. */
|
|
||||||
protected VectorialConvergenceChecker checker;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Jacobian matrix of the weighted residuals.
|
* Jacobian matrix of the weighted residuals.
|
||||||
* <p>This matrix is in canonical form just after the calls to
|
* This matrix is in canonical form just after the calls to
|
||||||
* {@link #updateJacobian()}, but may be modified by the solver
|
* {@link #updateJacobian()}, but may be modified by the solver
|
||||||
* in the derived class (the {@link LevenbergMarquardtOptimizer
|
* in the derived class (the {@link LevenbergMarquardtOptimizer
|
||||||
* Levenberg-Marquardt optimizer} does this).</p>
|
* Levenberg-Marquardt optimizer} does this).
|
||||||
*/
|
*/
|
||||||
protected double[][] weightedResidualJacobian;
|
protected double[][] weightedResidualJacobian;
|
||||||
|
|
||||||
/** Number of columns of the jacobian matrix. */
|
/** Number of columns of the jacobian matrix. */
|
||||||
protected int cols;
|
protected int cols;
|
||||||
|
|
||||||
/** Number of rows of the jacobian matrix. */
|
/** Number of rows of the jacobian matrix. */
|
||||||
protected int rows;
|
protected int rows;
|
||||||
|
|
||||||
/**
|
|
||||||
* Target value for the objective functions at optimum.
|
|
||||||
* @since 2.1
|
|
||||||
*/
|
|
||||||
protected double[] targetValues;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Weight for the least squares cost computation.
|
|
||||||
* @since 2.1
|
|
||||||
*/
|
|
||||||
protected double[] residualsWeights;
|
|
||||||
|
|
||||||
/** Current point. */
|
/** Current point. */
|
||||||
protected double[] point;
|
protected double[] point;
|
||||||
|
|
||||||
/** Current objective function value. */
|
/** Current objective function value. */
|
||||||
protected double[] objective;
|
protected double[] objective;
|
||||||
|
/** Current residuals. */
|
||||||
|
protected double[] residuals;
|
||||||
/** Weighted residuals */
|
/** Weighted residuals */
|
||||||
protected double[] weightedResiduals;
|
protected double[] weightedResiduals;
|
||||||
|
|
||||||
/** Cost value (square root of the sum of the residuals). */
|
/** Cost value (square root of the sum of the residuals). */
|
||||||
protected double cost;
|
protected double cost;
|
||||||
|
|
||||||
/** Maximal number of iterations allowed. */
|
|
||||||
private int maxIterations;
|
|
||||||
|
|
||||||
/** Number of iterations already performed. */
|
|
||||||
private int iterations;
|
|
||||||
|
|
||||||
/** Maximal number of evaluations allowed. */
|
|
||||||
private int maxEvaluations;
|
|
||||||
|
|
||||||
/** Number of evaluations already performed. */
|
|
||||||
private int objectiveEvaluations;
|
|
||||||
|
|
||||||
/** Number of jacobian evaluations. */
|
|
||||||
private int jacobianEvaluations;
|
|
||||||
|
|
||||||
/** Objective function. */
|
|
||||||
private DifferentiableMultivariateVectorialFunction function;
|
|
||||||
|
|
||||||
/** Objective function derivatives. */
|
/** Objective function derivatives. */
|
||||||
private MultivariateMatrixFunction jF;
|
private MultivariateMatrixFunction jF;
|
||||||
|
/** Number of evaluations of the Jacobian. */
|
||||||
|
private int jacobianEvaluations;
|
||||||
|
|
||||||
/** Simple constructor with default settings.
|
/**
|
||||||
* <p>The convergence check is set to a {@link SimpleVectorialValueChecker}
|
* Simple constructor with default settings.
|
||||||
* and the maximal number of evaluation is set to its default value.</p>
|
* The convergence check is set to a {@link SimpleVectorialValueChecker}.
|
||||||
*/
|
*/
|
||||||
protected AbstractLeastSquaresOptimizer() {
|
protected AbstractLeastSquaresOptimizer() {}
|
||||||
setConvergenceChecker(new SimpleVectorialValueChecker());
|
/**
|
||||||
setMaxIterations(DEFAULT_MAX_ITERATIONS);
|
* @param checker Convergence checker.
|
||||||
setMaxEvaluations(Integer.MAX_VALUE);
|
* @param maxEvaluations Maximal number of function evaluations.
|
||||||
|
*/
|
||||||
|
protected AbstractLeastSquaresOptimizer(ConvergenceChecker<VectorialPointValuePair> checker,
|
||||||
|
int maxEvaluations) {
|
||||||
|
super(checker, maxEvaluations);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
/**
|
||||||
public void setMaxIterations(int maxIterations) {
|
* @return the number of evaluations of the Jacobian function.
|
||||||
this.maxIterations = maxIterations;
|
*/
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
public int getMaxIterations() {
|
|
||||||
return maxIterations;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
public int getIterations() {
|
|
||||||
return iterations;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
public void setMaxEvaluations(int maxEvaluations) {
|
|
||||||
this.maxEvaluations = maxEvaluations;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
public int getMaxEvaluations() {
|
|
||||||
return maxEvaluations;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
public int getEvaluations() {
|
|
||||||
return objectiveEvaluations;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
public int getJacobianEvaluations() {
|
public int getJacobianEvaluations() {
|
||||||
return jacobianEvaluations;
|
return jacobianEvaluations;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
public void setConvergenceChecker(VectorialConvergenceChecker convergenceChecker) {
|
|
||||||
this.checker = convergenceChecker;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
public VectorialConvergenceChecker getConvergenceChecker() {
|
|
||||||
return checker;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Increment the iterations counter by 1.
|
|
||||||
* @exception OptimizationException if the maximal number
|
|
||||||
* of iterations is exceeded
|
|
||||||
*/
|
|
||||||
protected void incrementIterationsCounter()
|
|
||||||
throws OptimizationException {
|
|
||||||
if (++iterations > maxIterations) {
|
|
||||||
throw new OptimizationException(new MaxIterationsExceededException(maxIterations));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update the jacobian matrix.
|
* Update the jacobian matrix.
|
||||||
* @exception FunctionEvaluationException if the function jacobian
|
* @exception FunctionEvaluationException if the function jacobian
|
||||||
|
@ -188,6 +104,9 @@ public abstract class AbstractLeastSquaresOptimizer implements DifferentiableMul
|
||||||
throw new FunctionEvaluationException(point, LocalizedFormats.DIMENSIONS_MISMATCH_SIMPLE,
|
throw new FunctionEvaluationException(point, LocalizedFormats.DIMENSIONS_MISMATCH_SIMPLE,
|
||||||
weightedResidualJacobian.length, rows);
|
weightedResidualJacobian.length, rows);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final double[] residualsWeights = getWeightRef();
|
||||||
|
|
||||||
for (int i = 0; i < rows; i++) {
|
for (int i = 0; i < rows; i++) {
|
||||||
final double[] ji = weightedResidualJacobian[i];
|
final double[] ji = weightedResidualJacobian[i];
|
||||||
double wi = FastMath.sqrt(residualsWeights[i]);
|
double wi = FastMath.sqrt(residualsWeights[i]);
|
||||||
|
@ -204,18 +123,16 @@ public abstract class AbstractLeastSquaresOptimizer implements DifferentiableMul
|
||||||
* or its dimension doesn't match problem dimension or maximal number of
|
* or its dimension doesn't match problem dimension or maximal number of
|
||||||
* of evaluations is exceeded
|
* of evaluations is exceeded
|
||||||
*/
|
*/
|
||||||
protected void updateResidualsAndCost()
|
protected void updateResidualsAndCost() throws FunctionEvaluationException {
|
||||||
throws FunctionEvaluationException {
|
objective = computeObjectiveValue(point);
|
||||||
|
|
||||||
if (++objectiveEvaluations > maxEvaluations) {
|
|
||||||
throw new FunctionEvaluationException(new MaxEvaluationsExceededException(maxEvaluations),
|
|
||||||
point);
|
|
||||||
}
|
|
||||||
objective = function.value(point);
|
|
||||||
if (objective.length != rows) {
|
if (objective.length != rows) {
|
||||||
throw new FunctionEvaluationException(point, LocalizedFormats.DIMENSIONS_MISMATCH_SIMPLE,
|
throw new FunctionEvaluationException(point, LocalizedFormats.DIMENSIONS_MISMATCH_SIMPLE,
|
||||||
objective.length, rows);
|
objective.length, rows);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final double[] targetValues = getTargetRef();
|
||||||
|
final double[] residualsWeights = getWeightRef();
|
||||||
|
|
||||||
cost = 0;
|
cost = 0;
|
||||||
int index = 0;
|
int index = 0;
|
||||||
for (int i = 0; i < rows; i++) {
|
for (int i = 0; i < rows; i++) {
|
||||||
|
@ -225,7 +142,6 @@ public abstract class AbstractLeastSquaresOptimizer implements DifferentiableMul
|
||||||
index += cols;
|
index += cols;
|
||||||
}
|
}
|
||||||
cost = FastMath.sqrt(cost);
|
cost = FastMath.sqrt(cost);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -249,7 +165,7 @@ public abstract class AbstractLeastSquaresOptimizer implements DifferentiableMul
|
||||||
* @return chi-square value
|
* @return chi-square value
|
||||||
*/
|
*/
|
||||||
public double getChiSquare() {
|
public double getChiSquare() {
|
||||||
return cost*cost;
|
return cost * cost;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -257,11 +173,11 @@ public abstract class AbstractLeastSquaresOptimizer implements DifferentiableMul
|
||||||
* @return covariance matrix
|
* @return covariance matrix
|
||||||
* @exception FunctionEvaluationException if the function jacobian cannot
|
* @exception FunctionEvaluationException if the function jacobian cannot
|
||||||
* be evaluated
|
* be evaluated
|
||||||
* @exception OptimizationException if the covariance matrix
|
* @exception ConvergenceException if the covariance matrix
|
||||||
* cannot be computed (singular problem)
|
* cannot be computed (singular problem)
|
||||||
*/
|
*/
|
||||||
public double[][] getCovariances()
|
public double[][] getCovariances()
|
||||||
throws FunctionEvaluationException, OptimizationException {
|
throws FunctionEvaluationException {
|
||||||
|
|
||||||
// set up the jacobian
|
// set up the jacobian
|
||||||
updateJacobian();
|
updateJacobian();
|
||||||
|
@ -285,7 +201,7 @@ public abstract class AbstractLeastSquaresOptimizer implements DifferentiableMul
|
||||||
new LUDecompositionImpl(MatrixUtils.createRealMatrix(jTj)).getSolver().getInverse();
|
new LUDecompositionImpl(MatrixUtils.createRealMatrix(jTj)).getSolver().getInverse();
|
||||||
return inverse.getData();
|
return inverse.getData();
|
||||||
} catch (InvalidMatrixException ime) {
|
} catch (InvalidMatrixException ime) {
|
||||||
throw new OptimizationException(LocalizedFormats.UNABLE_TO_COMPUTE_COVARIANCE_SINGULAR_PROBLEM);
|
throw new ConvergenceException(LocalizedFormats.UNABLE_TO_COMPUTE_COVARIANCE_SINGULAR_PROBLEM);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -295,16 +211,15 @@ public abstract class AbstractLeastSquaresOptimizer implements DifferentiableMul
|
||||||
* <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 FunctionEvaluationException 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 ConvergenceException 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 FunctionEvaluationException, OptimizationException {
|
throws FunctionEvaluationException {
|
||||||
if (rows <= cols) {
|
if (rows <= cols) {
|
||||||
throw new OptimizationException(
|
throw new ConvergenceException(LocalizedFormats.NO_DEGREES_OF_FREEDOM,
|
||||||
LocalizedFormats.NO_DEGREES_OF_FREEDOM,
|
rows, cols);
|
||||||
rows, cols);
|
|
||||||
}
|
}
|
||||||
double[] errors = new double[cols];
|
double[] errors = new double[cols];
|
||||||
final double c = FastMath.sqrt(getChiSquare() / (rows - cols));
|
final double c = FastMath.sqrt(getChiSquare() / (rows - cols));
|
||||||
|
@ -319,46 +234,24 @@ public abstract class AbstractLeastSquaresOptimizer implements DifferentiableMul
|
||||||
public VectorialPointValuePair optimize(final DifferentiableMultivariateVectorialFunction 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 FunctionEvaluationException, OptimizationException, IllegalArgumentException {
|
throws FunctionEvaluationException {
|
||||||
|
// Reset counter.
|
||||||
|
jacobianEvaluations = 0;
|
||||||
|
|
||||||
if (target.length != weights.length) {
|
// Store least squares problem characteristics.
|
||||||
throw new OptimizationException(LocalizedFormats.DIMENSIONS_MISMATCH_SIMPLE,
|
jF = f.jacobian();
|
||||||
target.length, weights.length);
|
this.residuals = new double[target.length];
|
||||||
}
|
|
||||||
|
|
||||||
// reset counters
|
// Arrays shared with the other private methods.
|
||||||
iterations = 0;
|
point = startPoint.clone();
|
||||||
objectiveEvaluations = 0;
|
rows = target.length;
|
||||||
jacobianEvaluations = 0;
|
cols = point.length;
|
||||||
|
|
||||||
// store least squares problem characteristics
|
|
||||||
function = f;
|
|
||||||
jF = f.jacobian();
|
|
||||||
targetValues = target.clone();
|
|
||||||
residualsWeights = weights.clone();
|
|
||||||
this.point = startPoint.clone();
|
|
||||||
|
|
||||||
// arrays shared with the other private methods
|
|
||||||
rows = target.length;
|
|
||||||
cols = point.length;
|
|
||||||
|
|
||||||
weightedResidualJacobian = new double[rows][cols];
|
weightedResidualJacobian = new double[rows][cols];
|
||||||
this.weightedResiduals = new double[rows];
|
this.weightedResiduals = new double[rows];
|
||||||
|
|
||||||
cost = Double.POSITIVE_INFINITY;
|
cost = Double.POSITIVE_INFINITY;
|
||||||
|
|
||||||
return doOptimize();
|
return super.optimize(f, target, weights, startPoint);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Perform the bulk of optimization algorithm.
|
|
||||||
* @return the point/value pair giving the optimal value for objective function
|
|
||||||
* @exception FunctionEvaluationException if the objective function throws one during
|
|
||||||
* the search
|
|
||||||
* @exception OptimizationException if the algorithm failed to converge
|
|
||||||
* @exception IllegalArgumentException if the start point dimension is wrong
|
|
||||||
*/
|
|
||||||
protected abstract VectorialPointValuePair doOptimize()
|
|
||||||
throws FunctionEvaluationException, OptimizationException, IllegalArgumentException;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,8 +22,7 @@ import org.apache.commons.math.analysis.DifferentiableMultivariateRealFunction;
|
||||||
import org.apache.commons.math.analysis.MultivariateVectorialFunction;
|
import org.apache.commons.math.analysis.MultivariateVectorialFunction;
|
||||||
import org.apache.commons.math.optimization.DifferentiableMultivariateRealOptimizer;
|
import org.apache.commons.math.optimization.DifferentiableMultivariateRealOptimizer;
|
||||||
import org.apache.commons.math.optimization.GoalType;
|
import org.apache.commons.math.optimization.GoalType;
|
||||||
import org.apache.commons.math.optimization.OptimizationException;
|
import org.apache.commons.math.optimization.ConvergenceChecker;
|
||||||
import org.apache.commons.math.optimization.RealConvergenceChecker;
|
|
||||||
import org.apache.commons.math.optimization.RealPointValuePair;
|
import org.apache.commons.math.optimization.RealPointValuePair;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -37,63 +36,39 @@ import org.apache.commons.math.optimization.RealPointValuePair;
|
||||||
public abstract class AbstractScalarDifferentiableOptimizer
|
public abstract class AbstractScalarDifferentiableOptimizer
|
||||||
extends BaseAbstractScalarOptimizer<DifferentiableMultivariateRealFunction>
|
extends BaseAbstractScalarOptimizer<DifferentiableMultivariateRealFunction>
|
||||||
implements DifferentiableMultivariateRealOptimizer {
|
implements DifferentiableMultivariateRealOptimizer {
|
||||||
|
|
||||||
/** Convergence checker.
|
|
||||||
* @deprecated in 2.2 (to be removed in 3.0). Please use the accessor
|
|
||||||
* {@link BaseAbstractScalarOptimizer#getConvergenceChecker()} instead.
|
|
||||||
*/
|
|
||||||
protected RealConvergenceChecker checker;
|
|
||||||
/**
|
/**
|
||||||
* Type of optimization.
|
* Objective function gradient.
|
||||||
* @since 2.1
|
|
||||||
* @deprecated in 2.2 (to be removed in 3.0). Please use the accessor
|
|
||||||
* {@link BaseAbstractScalarOptimizer#getGoalType()} instead.
|
|
||||||
*/
|
*/
|
||||||
protected GoalType goal;
|
|
||||||
/** Current point set.
|
|
||||||
* @deprecated in 2.2 (to be removed in 3.0).
|
|
||||||
*/
|
|
||||||
protected double[] point;
|
|
||||||
|
|
||||||
/** Number of gradient evaluations. */
|
|
||||||
private int gradientEvaluations;
|
|
||||||
|
|
||||||
/** Objective function gradient. */
|
|
||||||
private MultivariateVectorialFunction gradient;
|
private MultivariateVectorialFunction gradient;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Simple constructor with default settings.
|
* Simple constructor with default settings.
|
||||||
* The convergence check is set to a {@link org.apache.commons.math.optimization.SimpleScalarValueChecker},
|
* The convergence check is set to a
|
||||||
* the allowed number of iterations and evaluations are set to their
|
* {@link org.apache.commons.math.optimization.SimpleScalarValueChecker
|
||||||
* default values.
|
* SimpleScalarValueChecker}.
|
||||||
*/
|
*/
|
||||||
protected AbstractScalarDifferentiableOptimizer() {}
|
protected AbstractScalarDifferentiableOptimizer() {}
|
||||||
/**
|
/**
|
||||||
* @param checker Convergence checker.
|
* @param checker Convergence checker.
|
||||||
* @param maxIterations Maximum number of iterations.
|
* @param maxEvaluations Maximum number of function evaluations.
|
||||||
* @param maxEvaluations Maximum number of evaluations.
|
|
||||||
*/
|
*/
|
||||||
protected AbstractScalarDifferentiableOptimizer(RealConvergenceChecker checker,
|
protected AbstractScalarDifferentiableOptimizer(ConvergenceChecker<RealPointValuePair> checker,
|
||||||
int maxIterations,
|
|
||||||
int maxEvaluations) {
|
int maxEvaluations) {
|
||||||
super(checker, maxIterations, maxEvaluations);
|
super(checker, maxEvaluations);
|
||||||
this.checker = checker; // Do not use (deprecated).
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
public int getGradientEvaluations() {
|
|
||||||
return gradientEvaluations;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compute the gradient vector.
|
* Compute the gradient vector.
|
||||||
* @param evaluationPoint point at which the gradient must be evaluated
|
*
|
||||||
* @return gradient at the specified point
|
* @param evaluationPoint Point at which the gradient must be evaluated.
|
||||||
* @exception FunctionEvaluationException if the function gradient
|
* @return the gradient at the specified point.
|
||||||
|
* @throws FunctionEvaluationException if the function gradient cannot be
|
||||||
|
* evaluated.
|
||||||
|
* @throws TooManyEvaluationsException if the allowed number of evaluations
|
||||||
|
* is exceeded.
|
||||||
*/
|
*/
|
||||||
protected double[] computeObjectiveGradient(final double[] evaluationPoint)
|
protected double[] computeObjectiveGradient(final double[] evaluationPoint)
|
||||||
throws FunctionEvaluationException {
|
throws FunctionEvaluationException {
|
||||||
++gradientEvaluations;
|
|
||||||
return gradient.value(evaluationPoint);
|
return gradient.value(evaluationPoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,17 +76,10 @@ public abstract class AbstractScalarDifferentiableOptimizer
|
||||||
public RealPointValuePair optimize(final DifferentiableMultivariateRealFunction f,
|
public RealPointValuePair optimize(final DifferentiableMultivariateRealFunction f,
|
||||||
final GoalType goalType,
|
final GoalType goalType,
|
||||||
final double[] startPoint)
|
final double[] startPoint)
|
||||||
throws FunctionEvaluationException,
|
throws FunctionEvaluationException {
|
||||||
OptimizationException {
|
// Store optimization problem characteristics.
|
||||||
// reset counters
|
|
||||||
gradientEvaluations = 0;
|
|
||||||
|
|
||||||
// store optimization problem characteristics
|
|
||||||
gradient = f.gradient();
|
gradient = f.gradient();
|
||||||
|
|
||||||
goal = goalType; // Do not use (deprecated).
|
|
||||||
point = startPoint.clone(); // Do not use (deprecated).
|
|
||||||
|
|
||||||
return super.optimize(f, goalType, startPoint);
|
return super.optimize(f, goalType, startPoint);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,8 @@ package org.apache.commons.math.optimization.general;
|
||||||
|
|
||||||
import org.apache.commons.math.analysis.MultivariateRealFunction;
|
import org.apache.commons.math.analysis.MultivariateRealFunction;
|
||||||
import org.apache.commons.math.optimization.MultivariateRealOptimizer;
|
import org.apache.commons.math.optimization.MultivariateRealOptimizer;
|
||||||
import org.apache.commons.math.optimization.RealConvergenceChecker;
|
import org.apache.commons.math.optimization.ConvergenceChecker;
|
||||||
|
import org.apache.commons.math.optimization.RealPointValuePair;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class for implementing optimizers for multivariate (not necessarily
|
* Base class for implementing optimizers for multivariate (not necessarily
|
||||||
|
@ -33,19 +34,16 @@ public abstract class AbstractScalarOptimizer
|
||||||
implements MultivariateRealOptimizer {
|
implements MultivariateRealOptimizer {
|
||||||
/**
|
/**
|
||||||
* Simple constructor with default settings.
|
* Simple constructor with default settings.
|
||||||
* The convergence check is set to a {@link org.apache.commons.math.optimization.SimpleScalarValueChecker},
|
* The convergence check is set to a
|
||||||
* the allowed number of iterations and evaluations are set to their
|
* {@link org.apache.commons.math.optimization.SimpleScalarValueChecker}.
|
||||||
* default values.
|
|
||||||
*/
|
*/
|
||||||
protected AbstractScalarOptimizer() {}
|
protected AbstractScalarOptimizer() {}
|
||||||
/**
|
/**
|
||||||
* @param checker Convergence checker.
|
* @param checker Convergence checker.
|
||||||
* @param maxIterations Maximum number of iterations.
|
* @param maxEvaluations Maximum number of function evaluations.
|
||||||
* @param maxEvaluations Maximum number of evaluations.
|
|
||||||
*/
|
*/
|
||||||
protected AbstractScalarOptimizer(RealConvergenceChecker checker,
|
protected AbstractScalarOptimizer(ConvergenceChecker<RealPointValuePair> checker,
|
||||||
int maxIterations,
|
|
||||||
int maxEvaluations) {
|
int maxEvaluations) {
|
||||||
super(checker, maxIterations, maxEvaluations);
|
super(checker, maxEvaluations);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,13 +18,14 @@
|
||||||
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.FunctionEvaluationException;
|
||||||
import org.apache.commons.math.MaxEvaluationsExceededException;
|
import org.apache.commons.math.util.Incrementor;
|
||||||
import org.apache.commons.math.MaxIterationsExceededException;
|
import org.apache.commons.math.exception.MaxCountExceededException;
|
||||||
|
import org.apache.commons.math.exception.TooManyEvaluationsException;
|
||||||
import org.apache.commons.math.analysis.MultivariateRealFunction;
|
import org.apache.commons.math.analysis.MultivariateRealFunction;
|
||||||
import org.apache.commons.math.optimization.BaseMultivariateRealOptimizer;
|
import org.apache.commons.math.optimization.BaseMultivariateRealOptimizer;
|
||||||
import org.apache.commons.math.optimization.GoalType;
|
import org.apache.commons.math.optimization.GoalType;
|
||||||
import org.apache.commons.math.optimization.OptimizationException;
|
import org.apache.commons.math.optimization.OptimizationException;
|
||||||
import org.apache.commons.math.optimization.RealConvergenceChecker;
|
import org.apache.commons.math.optimization.ConvergenceChecker;
|
||||||
import org.apache.commons.math.optimization.RealPointValuePair;
|
import org.apache.commons.math.optimization.RealPointValuePair;
|
||||||
import org.apache.commons.math.optimization.SimpleScalarValueChecker;
|
import org.apache.commons.math.optimization.SimpleScalarValueChecker;
|
||||||
|
|
||||||
|
@ -37,6 +38,7 @@ import org.apache.commons.math.optimization.SimpleScalarValueChecker;
|
||||||
* A class that implements an optimization algorithm should inherit from
|
* A class that implements an optimization algorithm should inherit from
|
||||||
* {@link AbstractScalarOptimizer} or from
|
* {@link AbstractScalarOptimizer} or from
|
||||||
* {@link AbstractScalarDifferentiableOptimizer}.
|
* {@link AbstractScalarDifferentiableOptimizer}.
|
||||||
|
*
|
||||||
* @param <T> the type of the objective function to be optimized
|
* @param <T> the type of the objective function to be optimized
|
||||||
*
|
*
|
||||||
* @version $Revision$ $Date$
|
* @version $Revision$ $Date$
|
||||||
|
@ -44,136 +46,93 @@ import org.apache.commons.math.optimization.SimpleScalarValueChecker;
|
||||||
*/
|
*/
|
||||||
public abstract class BaseAbstractScalarOptimizer<T extends MultivariateRealFunction>
|
public abstract class BaseAbstractScalarOptimizer<T extends MultivariateRealFunction>
|
||||||
implements BaseMultivariateRealOptimizer<T> {
|
implements BaseMultivariateRealOptimizer<T> {
|
||||||
/** Default maximal number of iterations allowed ({@value}). */
|
/** Evaluations counter. */
|
||||||
public static final int DEFAULT_MAX_ITERATIONS = 1000;
|
protected final Incrementor evaluations = new Incrementor();
|
||||||
/** Default maximal number of iterations allowed ({@value}). */
|
|
||||||
public static final int DEFAULT_MAX_EVALUATIONS = 10000;
|
|
||||||
|
|
||||||
/** Convergence checker. */
|
/** Convergence checker. */
|
||||||
private RealConvergenceChecker checker;
|
private ConvergenceChecker<RealPointValuePair> checker;
|
||||||
/** Type of optimization. */
|
/** Type of optimization. */
|
||||||
private GoalType goal;
|
private GoalType goal;
|
||||||
/** Initial guess. */
|
/** Initial guess. */
|
||||||
private double[] start;
|
private double[] start;
|
||||||
/** Maximal number of iterations allowed. */
|
|
||||||
private int maxIterations;
|
|
||||||
/** Number of iterations already performed. */
|
|
||||||
private int iterations;
|
|
||||||
/** Maximal number of evaluations allowed. */
|
|
||||||
private int maxEvaluations;
|
|
||||||
/** Number of evaluations already performed. */
|
|
||||||
private int evaluations;
|
|
||||||
/** Objective function. */
|
/** Objective function. */
|
||||||
private MultivariateRealFunction function;
|
private MultivariateRealFunction function;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Simple constructor with default settings.
|
* Simple constructor with default settings.
|
||||||
* The convergence check is set to a {@link SimpleScalarValueChecker},
|
* The convergence check is set to a {@link SimpleScalarValueChecker} and
|
||||||
* the allowed number of iterations and evaluations are set to their
|
* the allowed number of evaluations is set to {@link Integer#MAX_VALUE}.
|
||||||
* default values.
|
|
||||||
*/
|
*/
|
||||||
protected BaseAbstractScalarOptimizer() {
|
protected BaseAbstractScalarOptimizer() {
|
||||||
this(new SimpleScalarValueChecker(),
|
this(new SimpleScalarValueChecker(), Integer.MAX_VALUE);
|
||||||
DEFAULT_MAX_ITERATIONS,
|
|
||||||
DEFAULT_MAX_EVALUATIONS);
|
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* @param checker Convergence checker.
|
* @param checker Convergence checker.
|
||||||
* @param maxIterations Maximum number of iterations.
|
* @param maxEvaluations Maximum number of function evaluations.
|
||||||
* @param maxEvaluations Maximum number of evaluations.
|
|
||||||
*/
|
*/
|
||||||
protected BaseAbstractScalarOptimizer(RealConvergenceChecker checker,
|
protected BaseAbstractScalarOptimizer(ConvergenceChecker<RealPointValuePair> checker,
|
||||||
int maxIterations,
|
|
||||||
int maxEvaluations) {
|
int maxEvaluations) {
|
||||||
this.checker = checker;
|
this.checker = checker;
|
||||||
this.maxIterations = maxIterations;
|
evaluations.setMaximalCount(maxEvaluations);
|
||||||
this.maxEvaluations = maxEvaluations;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
public void setMaxIterations(int maxIterations) {
|
|
||||||
this.maxIterations = maxIterations;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
public int getMaxIterations() {
|
|
||||||
return maxIterations;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
public int getIterations() {
|
|
||||||
return iterations;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
/** {@inheritDoc} */
|
||||||
public void setMaxEvaluations(int maxEvaluations) {
|
public void setMaxEvaluations(int maxEvaluations) {
|
||||||
this.maxEvaluations = maxEvaluations;
|
evaluations.setMaximalCount(maxEvaluations);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
/** {@inheritDoc} */
|
||||||
public int getMaxEvaluations() {
|
public int getMaxEvaluations() {
|
||||||
return maxEvaluations;
|
return evaluations.getMaximalCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
/** {@inheritDoc} */
|
||||||
public int getEvaluations() {
|
public int getEvaluations() {
|
||||||
return evaluations;
|
return evaluations.getCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
/** {@inheritDoc} */
|
||||||
public void setConvergenceChecker(RealConvergenceChecker convergenceChecker) {
|
public void setConvergenceChecker(ConvergenceChecker<RealPointValuePair> convergenceChecker) {
|
||||||
this.checker = convergenceChecker;
|
this.checker = convergenceChecker;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
/** {@inheritDoc} */
|
||||||
public RealConvergenceChecker getConvergenceChecker() {
|
public ConvergenceChecker<RealPointValuePair> getConvergenceChecker() {
|
||||||
return checker;
|
return checker;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Increment the iterations counter by 1.
|
|
||||||
* @throws OptimizationException if the maximal number
|
|
||||||
* of iterations is exceeded
|
|
||||||
*/
|
|
||||||
protected void incrementIterationsCounter()
|
|
||||||
throws OptimizationException {
|
|
||||||
if (++iterations > maxIterations) {
|
|
||||||
throw new OptimizationException(new MaxIterationsExceededException(maxIterations));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compute the objective function value.
|
* Compute the objective function value.
|
||||||
* @param evaluationPoint point at which the objective function must be evaluated
|
*
|
||||||
* @return objective function value at specified point
|
* @param point Point at which the objective function must be evaluated.
|
||||||
* @throws FunctionEvaluationException if the function cannot be evaluated
|
* @return the objective function value at the specified point.
|
||||||
* or its dimension doesn't match problem dimension or the maximal number
|
* @throws FunctionEvaluationException if the function cannot be evaluated.
|
||||||
* of iterations is exceeded
|
* @throws TooManyEvaluationsException if the maximal number of evaluations is
|
||||||
|
* exceeded.
|
||||||
*/
|
*/
|
||||||
protected double computeObjectiveValue(double[] evaluationPoint)
|
protected double computeObjectiveValue(double[] point)
|
||||||
throws FunctionEvaluationException {
|
throws FunctionEvaluationException {
|
||||||
if (++evaluations > maxEvaluations) {
|
try {
|
||||||
throw new FunctionEvaluationException(new MaxEvaluationsExceededException(maxEvaluations),
|
evaluations.incrementCount();
|
||||||
evaluationPoint);
|
} catch (MaxCountExceededException e) {
|
||||||
|
throw new TooManyEvaluationsException(e.getMax());
|
||||||
}
|
}
|
||||||
return function.value(evaluationPoint);
|
return function.value(point);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
/** {@inheritDoc} */
|
||||||
public RealPointValuePair optimize(T f,
|
public RealPointValuePair optimize(T f,
|
||||||
GoalType goalType,
|
GoalType goalType,
|
||||||
double[] startPoint)
|
double[] startPoint)
|
||||||
throws FunctionEvaluationException, OptimizationException {
|
throws FunctionEvaluationException {
|
||||||
|
// Reset.
|
||||||
|
evaluations.resetCount();
|
||||||
|
|
||||||
// reset counters
|
// Store optimization problem characteristics.
|
||||||
iterations = 0;
|
|
||||||
evaluations = 0;
|
|
||||||
|
|
||||||
// store optimization problem characteristics
|
|
||||||
function = f;
|
function = f;
|
||||||
goal = goalType;
|
goal = goalType;
|
||||||
start = startPoint.clone();
|
start = startPoint.clone();
|
||||||
|
|
||||||
|
// Perform computation.
|
||||||
return doOptimize();
|
return doOptimize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -192,13 +151,12 @@ public abstract class BaseAbstractScalarOptimizer<T extends MultivariateRealFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Perform the bulk of optimization algorithm.
|
* Perform the bulk of the 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
|
||||||
* @throws FunctionEvaluationException if the objective function throws one during
|
* @throws FunctionEvaluationException if the objective function throws one during
|
||||||
* the search
|
* the search
|
||||||
* @throws OptimizationException if the algorithm failed to converge
|
|
||||||
* @throws IllegalArgumentException if the start point dimension is wrong
|
|
||||||
*/
|
*/
|
||||||
protected abstract RealPointValuePair doOptimize()
|
protected abstract RealPointValuePair doOptimize()
|
||||||
throws FunctionEvaluationException, OptimizationException;
|
throws FunctionEvaluationException;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,172 @@
|
||||||
|
/*
|
||||||
|
* 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.general;
|
||||||
|
|
||||||
|
import org.apache.commons.math.FunctionEvaluationException;
|
||||||
|
import org.apache.commons.math.util.Incrementor;
|
||||||
|
import org.apache.commons.math.exception.MaxCountExceededException;
|
||||||
|
import org.apache.commons.math.exception.TooManyEvaluationsException;
|
||||||
|
import org.apache.commons.math.exception.DimensionMismatchException;
|
||||||
|
import org.apache.commons.math.analysis.MultivariateVectorialFunction;
|
||||||
|
import org.apache.commons.math.optimization.BaseMultivariateVectorialOptimizer;
|
||||||
|
import org.apache.commons.math.optimization.GoalType;
|
||||||
|
import org.apache.commons.math.optimization.OptimizationException;
|
||||||
|
import org.apache.commons.math.optimization.ConvergenceChecker;
|
||||||
|
import org.apache.commons.math.optimization.VectorialPointValuePair;
|
||||||
|
import org.apache.commons.math.optimization.SimpleVectorialValueChecker;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base class for implementing optimizers for multivariate scalar functions.
|
||||||
|
* This base class handles the boiler-plate methods associated to thresholds
|
||||||
|
* settings, iterations and evaluations counting.
|
||||||
|
*
|
||||||
|
* @param <FUNC> the type of the objective function to be optimized
|
||||||
|
*
|
||||||
|
* @version $Revision$ $Date$
|
||||||
|
* @since 3.0
|
||||||
|
*/
|
||||||
|
public abstract class BaseAbstractVectorialOptimizer<FUNC extends MultivariateVectorialFunction>
|
||||||
|
implements BaseMultivariateVectorialOptimizer<FUNC> {
|
||||||
|
/** Evaluations counter. */
|
||||||
|
protected final Incrementor evaluations = new Incrementor();
|
||||||
|
/** Convergence checker. */
|
||||||
|
private ConvergenceChecker<VectorialPointValuePair> checker;
|
||||||
|
/** Target value for the objective functions at optimum. */
|
||||||
|
private double[] target;
|
||||||
|
/** Weight for the least squares cost computation. */
|
||||||
|
private double[] weight;
|
||||||
|
/** Initial guess. */
|
||||||
|
private double[] start;
|
||||||
|
/** Objective function. */
|
||||||
|
private MultivariateVectorialFunction function;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple constructor with default settings.
|
||||||
|
* The convergence check is set to a {@link SimpleVectorialValueChecker} and
|
||||||
|
* the allowed number of evaluations is set to {@link Integer#MAX_VALUE}.
|
||||||
|
*/
|
||||||
|
protected BaseAbstractVectorialOptimizer() {
|
||||||
|
this(new SimpleVectorialValueChecker(), Integer.MAX_VALUE);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @param checker Convergence checker.
|
||||||
|
* @param maxEvaluations Maximum number of function evaluations.
|
||||||
|
*/
|
||||||
|
protected BaseAbstractVectorialOptimizer(ConvergenceChecker<VectorialPointValuePair> checker,
|
||||||
|
int maxEvaluations) {
|
||||||
|
this.checker = checker;
|
||||||
|
evaluations.setMaximalCount(maxEvaluations);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** {@inheritDoc} */
|
||||||
|
public void setMaxEvaluations(int maxEvaluations) {
|
||||||
|
evaluations.setMaximalCount(maxEvaluations);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** {@inheritDoc} */
|
||||||
|
public int getMaxEvaluations() {
|
||||||
|
return evaluations.getMaximalCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** {@inheritDoc} */
|
||||||
|
public int getEvaluations() {
|
||||||
|
return evaluations.getCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** {@inheritDoc} */
|
||||||
|
public void setConvergenceChecker(ConvergenceChecker<VectorialPointValuePair> convergenceChecker) {
|
||||||
|
this.checker = convergenceChecker;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** {@inheritDoc} */
|
||||||
|
public ConvergenceChecker<VectorialPointValuePair> getConvergenceChecker() {
|
||||||
|
return checker;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compute the objective function value.
|
||||||
|
*
|
||||||
|
* @param point Point at which the objective function must be evaluated.
|
||||||
|
* @return the objective function value at the specified point.
|
||||||
|
* @throws FunctionEvaluationException if the function cannot be evaluated.
|
||||||
|
* @throws TooManyEvaluationsException if the maximal number of evaluations is
|
||||||
|
* exceeded.
|
||||||
|
*/
|
||||||
|
protected double[] computeObjectiveValue(double[] point)
|
||||||
|
throws FunctionEvaluationException {
|
||||||
|
try {
|
||||||
|
evaluations.incrementCount();
|
||||||
|
} catch (MaxCountExceededException e) {
|
||||||
|
throw new TooManyEvaluationsException(e.getMax());
|
||||||
|
}
|
||||||
|
return function.value(point);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** {@inheritDoc} */
|
||||||
|
public VectorialPointValuePair optimize(FUNC f,
|
||||||
|
double[] target, double[] weight,
|
||||||
|
double[] startPoint)
|
||||||
|
throws FunctionEvaluationException {
|
||||||
|
|
||||||
|
if (target.length != weight.length) {
|
||||||
|
throw new DimensionMismatchException(target.length, weight.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset.
|
||||||
|
evaluations.resetCount();
|
||||||
|
|
||||||
|
// Store optimization problem characteristics.
|
||||||
|
function = f;
|
||||||
|
this.target = target.clone();
|
||||||
|
this.weight = weight.clone();
|
||||||
|
start = startPoint.clone();
|
||||||
|
|
||||||
|
// Perform computation.
|
||||||
|
return doOptimize();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the initial guess.
|
||||||
|
*/
|
||||||
|
public double[] getStartPoint() {
|
||||||
|
return start.clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Perform the bulk of the optimization algorithm.
|
||||||
|
*
|
||||||
|
* @return the point/value pair giving the optimal value for objective function
|
||||||
|
* @throws FunctionEvaluationException if the objective function throws one during
|
||||||
|
* the search
|
||||||
|
*/
|
||||||
|
protected abstract VectorialPointValuePair doOptimize()
|
||||||
|
throws FunctionEvaluationException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return a reference to the {@link #target array}.
|
||||||
|
*/
|
||||||
|
protected double[] getTargetRef() {
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @return a reference to the {@link #weight array}.
|
||||||
|
*/
|
||||||
|
protected double[] getWeightRef() {
|
||||||
|
return weight;
|
||||||
|
}
|
||||||
|
}
|
|
@ -25,7 +25,7 @@ import org.apache.commons.math.linear.InvalidMatrixException;
|
||||||
import org.apache.commons.math.linear.LUDecompositionImpl;
|
import org.apache.commons.math.linear.LUDecompositionImpl;
|
||||||
import org.apache.commons.math.linear.QRDecompositionImpl;
|
import org.apache.commons.math.linear.QRDecompositionImpl;
|
||||||
import org.apache.commons.math.linear.RealMatrix;
|
import org.apache.commons.math.linear.RealMatrix;
|
||||||
import org.apache.commons.math.optimization.OptimizationException;
|
import org.apache.commons.math.exception.ConvergenceException;
|
||||||
import org.apache.commons.math.optimization.VectorialPointValuePair;
|
import org.apache.commons.math.optimization.VectorialPointValuePair;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -43,17 +43,17 @@ import org.apache.commons.math.optimization.VectorialPointValuePair;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class GaussNewtonOptimizer extends AbstractLeastSquaresOptimizer {
|
public class GaussNewtonOptimizer extends AbstractLeastSquaresOptimizer {
|
||||||
|
|
||||||
/** Indicator for using LU decomposition. */
|
/** Indicator for using LU decomposition. */
|
||||||
private final boolean useLU;
|
private final boolean useLU;
|
||||||
|
|
||||||
/** Simple constructor with default settings.
|
/**
|
||||||
* <p>The convergence check is set to a {@link
|
* Simple constructor with default settings.
|
||||||
* org.apache.commons.math.optimization.SimpleVectorialValueChecker}
|
* The convergence check is set to a {@link
|
||||||
* and the maximal number of evaluation is set to
|
* org.apache.commons.math.optimization.SimpleVectorialValueChecker}.
|
||||||
* {@link AbstractLeastSquaresOptimizer#DEFAULT_MAX_ITERATIONS}.
|
*
|
||||||
* @param useLU if true, the normal equations will be solved using LU
|
* @param useLU if {@code true}, the normal equations will be solved
|
||||||
* decomposition, otherwise they will be solved using QR decomposition
|
* using LU decomposition, otherwise they will be solved using QR
|
||||||
|
* decomposition.
|
||||||
*/
|
*/
|
||||||
public GaussNewtonOptimizer(final boolean useLU) {
|
public GaussNewtonOptimizer(final boolean useLU) {
|
||||||
this.useLU = useLU;
|
this.useLU = useLU;
|
||||||
|
@ -62,13 +62,13 @@ public class GaussNewtonOptimizer extends AbstractLeastSquaresOptimizer {
|
||||||
/** {@inheritDoc} */
|
/** {@inheritDoc} */
|
||||||
@Override
|
@Override
|
||||||
public VectorialPointValuePair doOptimize()
|
public VectorialPointValuePair doOptimize()
|
||||||
throws FunctionEvaluationException, OptimizationException, IllegalArgumentException {
|
throws FunctionEvaluationException {
|
||||||
|
|
||||||
// iterate until convergence is reached
|
// iterate until convergence is reached
|
||||||
VectorialPointValuePair current = null;
|
VectorialPointValuePair current = null;
|
||||||
|
int iter = 0;
|
||||||
for (boolean converged = false; !converged;) {
|
for (boolean converged = false; !converged;) {
|
||||||
|
++iter;
|
||||||
incrementIterationsCounter();
|
|
||||||
|
|
||||||
// evaluate the objective function and its jacobian
|
// evaluate the objective function and its jacobian
|
||||||
VectorialPointValuePair previous = current;
|
VectorialPointValuePair previous = current;
|
||||||
|
@ -76,6 +76,9 @@ public class GaussNewtonOptimizer extends AbstractLeastSquaresOptimizer {
|
||||||
updateJacobian();
|
updateJacobian();
|
||||||
current = new VectorialPointValuePair(point, objective);
|
current = new VectorialPointValuePair(point, objective);
|
||||||
|
|
||||||
|
final double[] targetValues = getTargetRef();
|
||||||
|
final double[] residualsWeights = getWeightRef();
|
||||||
|
|
||||||
// build the linear problem
|
// build the linear problem
|
||||||
final double[] b = new double[cols];
|
final double[] b = new double[cols];
|
||||||
final double[][] a = new double[cols][cols];
|
final double[][] a = new double[cols][cols];
|
||||||
|
@ -99,11 +102,9 @@ public class GaussNewtonOptimizer extends AbstractLeastSquaresOptimizer {
|
||||||
ak[l] += wgk * grad[l];
|
ak[l] += wgk * grad[l];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
// solve the linearized least squares problem
|
// solve the linearized least squares problem
|
||||||
RealMatrix mA = new BlockRealMatrix(a);
|
RealMatrix mA = new BlockRealMatrix(a);
|
||||||
DecompositionSolver solver = useLU ?
|
DecompositionSolver solver = useLU ?
|
||||||
|
@ -115,21 +116,16 @@ public class GaussNewtonOptimizer extends AbstractLeastSquaresOptimizer {
|
||||||
for (int i = 0; i < cols; ++i) {
|
for (int i = 0; i < cols; ++i) {
|
||||||
point[i] += dX[i];
|
point[i] += dX[i];
|
||||||
}
|
}
|
||||||
|
} catch (InvalidMatrixException e) {
|
||||||
} catch(InvalidMatrixException e) {
|
throw new ConvergenceException(LocalizedFormats.UNABLE_TO_SOLVE_SINGULAR_PROBLEM);
|
||||||
throw new OptimizationException(LocalizedFormats.UNABLE_TO_SOLVE_SINGULAR_PROBLEM);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// check convergence
|
// check convergence
|
||||||
if (previous != null) {
|
if (previous != null) {
|
||||||
converged = checker.converged(getIterations(), previous, current);
|
converged = getConvergenceChecker().converged(iter, previous, current);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// we have converged
|
// we have converged
|
||||||
return current;
|
return current;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,9 +19,10 @@ package org.apache.commons.math.optimization.general;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
import org.apache.commons.math.FunctionEvaluationException;
|
import org.apache.commons.math.FunctionEvaluationException;
|
||||||
|
import org.apache.commons.math.exception.ConvergenceException;
|
||||||
import org.apache.commons.math.exception.util.LocalizedFormats;
|
import org.apache.commons.math.exception.util.LocalizedFormats;
|
||||||
import org.apache.commons.math.optimization.OptimizationException;
|
|
||||||
import org.apache.commons.math.optimization.VectorialPointValuePair;
|
import org.apache.commons.math.optimization.VectorialPointValuePair;
|
||||||
|
import org.apache.commons.math.optimization.ConvergenceChecker;
|
||||||
import org.apache.commons.math.util.MathUtils;
|
import org.apache.commons.math.util.MathUtils;
|
||||||
import org.apache.commons.math.util.FastMath;
|
import org.apache.commons.math.util.FastMath;
|
||||||
|
|
||||||
|
@ -150,9 +151,8 @@ public class LevenbergMarquardtOptimizer extends AbstractLeastSquaresOptimizer {
|
||||||
* Build an optimizer for least squares problems.
|
* Build an optimizer for least squares problems.
|
||||||
* <p>The default values for the algorithm settings are:
|
* <p>The default values for the algorithm settings are:
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>{@link #setConvergenceChecker(VectorialConvergenceChecker) vectorial convergence checker}: null</li>
|
* <li>{@link #setConvergenceChecker(ConvergenceChecker) vectorial convergence checker}: null</li>
|
||||||
* <li>{@link #setInitialStepBoundFactor(double) initial step bound factor}: 100.0</li>
|
* <li>{@link #setInitialStepBoundFactor(double) initial step bound factor}: 100.0</li>
|
||||||
* <li>{@link #setMaxIterations(int) maximal iterations}: 1000</li>
|
|
||||||
* <li>{@link #setCostRelativeTolerance(double) cost relative tolerance}: 1.0e-10</li>
|
* <li>{@link #setCostRelativeTolerance(double) cost relative tolerance}: 1.0e-10</li>
|
||||||
* <li>{@link #setParRelativeTolerance(double) parameters relative tolerance}: 1.0e-10</li>
|
* <li>{@link #setParRelativeTolerance(double) parameters relative tolerance}: 1.0e-10</li>
|
||||||
* <li>{@link #setOrthoTolerance(double) orthogonality tolerance}: 1.0e-10</li>
|
* <li>{@link #setOrthoTolerance(double) orthogonality tolerance}: 1.0e-10</li>
|
||||||
|
@ -165,10 +165,6 @@ public class LevenbergMarquardtOptimizer extends AbstractLeastSquaresOptimizer {
|
||||||
* and {@link #setParRelativeTolerance parameters relative tolerance} settings.
|
* and {@link #setParRelativeTolerance parameters relative tolerance} settings.
|
||||||
*/
|
*/
|
||||||
public LevenbergMarquardtOptimizer() {
|
public LevenbergMarquardtOptimizer() {
|
||||||
|
|
||||||
// set up the superclass with a default max cost evaluations setting
|
|
||||||
setMaxIterations(1000);
|
|
||||||
|
|
||||||
// default values for the tuning parameters
|
// default values for the tuning parameters
|
||||||
setConvergenceChecker(null);
|
setConvergenceChecker(null);
|
||||||
setInitialStepBoundFactor(100.0);
|
setInitialStepBoundFactor(100.0);
|
||||||
|
@ -176,7 +172,6 @@ public class LevenbergMarquardtOptimizer extends AbstractLeastSquaresOptimizer {
|
||||||
setParRelativeTolerance(1.0e-10);
|
setParRelativeTolerance(1.0e-10);
|
||||||
setOrthoTolerance(1.0e-10);
|
setOrthoTolerance(1.0e-10);
|
||||||
setQRRankingThreshold(MathUtils.SAFE_MIN);
|
setQRRankingThreshold(MathUtils.SAFE_MIN);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -239,8 +234,7 @@ public class LevenbergMarquardtOptimizer extends AbstractLeastSquaresOptimizer {
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
/** {@inheritDoc} */
|
||||||
@Override
|
@Override
|
||||||
protected VectorialPointValuePair doOptimize()
|
protected VectorialPointValuePair doOptimize() throws FunctionEvaluationException {
|
||||||
throws FunctionEvaluationException, OptimizationException, IllegalArgumentException {
|
|
||||||
|
|
||||||
// arrays shared with the other private methods
|
// arrays shared with the other private methods
|
||||||
solvedCols = FastMath.min(rows, cols);
|
solvedCols = FastMath.min(rows, cols);
|
||||||
|
@ -269,11 +263,14 @@ public class LevenbergMarquardtOptimizer extends AbstractLeastSquaresOptimizer {
|
||||||
lmPar = 0;
|
lmPar = 0;
|
||||||
boolean firstIteration = true;
|
boolean firstIteration = true;
|
||||||
VectorialPointValuePair current = new VectorialPointValuePair(point, objective);
|
VectorialPointValuePair current = new VectorialPointValuePair(point, objective);
|
||||||
|
int iter = 0;
|
||||||
|
final ConvergenceChecker<VectorialPointValuePair> checker = getConvergenceChecker();
|
||||||
while (true) {
|
while (true) {
|
||||||
|
++iter;
|
||||||
|
|
||||||
for (int i=0;i<rows;i++) {
|
for (int i=0;i<rows;i++) {
|
||||||
qtf[i]=weightedResiduals[i];
|
qtf[i]=weightedResiduals[i];
|
||||||
}
|
}
|
||||||
incrementIterationsCounter();
|
|
||||||
|
|
||||||
// compute the Q.R. decomposition of the jacobian matrix
|
// compute the Q.R. decomposition of the jacobian matrix
|
||||||
VectorialPointValuePair previous = current;
|
VectorialPointValuePair previous = current;
|
||||||
|
@ -290,7 +287,6 @@ public class LevenbergMarquardtOptimizer extends AbstractLeastSquaresOptimizer {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (firstIteration) {
|
if (firstIteration) {
|
||||||
|
|
||||||
// scale the point 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;
|
||||||
|
@ -307,7 +303,6 @@ public class LevenbergMarquardtOptimizer extends AbstractLeastSquaresOptimizer {
|
||||||
|
|
||||||
// initialize the step bound delta
|
// initialize the step bound delta
|
||||||
delta = (xNorm == 0) ? initialStepBoundFactor : (initialStepBoundFactor * xNorm);
|
delta = (xNorm == 0) ? initialStepBoundFactor : (initialStepBoundFactor * xNorm);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// check orthogonality between function vector and jacobian columns
|
// check orthogonality between function vector and jacobian columns
|
||||||
|
@ -425,17 +420,17 @@ public class LevenbergMarquardtOptimizer extends AbstractLeastSquaresOptimizer {
|
||||||
xNorm = 0;
|
xNorm = 0;
|
||||||
for (int k = 0; k < cols; ++k) {
|
for (int k = 0; k < cols; ++k) {
|
||||||
double xK = diag[k] * point[k];
|
double xK = diag[k] * point[k];
|
||||||
xNorm += xK * xK;
|
xNorm += xK * xK;
|
||||||
}
|
}
|
||||||
xNorm = FastMath.sqrt(xNorm);
|
xNorm = FastMath.sqrt(xNorm);
|
||||||
current = new VectorialPointValuePair(point, objective);
|
current = new VectorialPointValuePair(point, objective);
|
||||||
|
|
||||||
// tests for convergence.
|
// tests for convergence.
|
||||||
if (checker != null) {
|
if (checker != null) {
|
||||||
// we use the vectorial convergence checker
|
// we use the vectorial convergence checker
|
||||||
if (checker.converged(getIterations(), previous, current)) {
|
if (checker.converged(iter, previous, current)) {
|
||||||
return current;
|
return current;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// failed iteration, reset the previous values
|
// failed iteration, reset the previous values
|
||||||
|
@ -462,20 +457,17 @@ public class LevenbergMarquardtOptimizer extends AbstractLeastSquaresOptimizer {
|
||||||
// tests for termination and stringent tolerances
|
// tests for termination and stringent tolerances
|
||||||
// (2.2204e-16 is the machine epsilon for IEEE754)
|
// (2.2204e-16 is the machine epsilon for IEEE754)
|
||||||
if ((FastMath.abs(actRed) <= 2.2204e-16) && (preRed <= 2.2204e-16) && (ratio <= 2.0)) {
|
if ((FastMath.abs(actRed) <= 2.2204e-16) && (preRed <= 2.2204e-16) && (ratio <= 2.0)) {
|
||||||
throw new OptimizationException(LocalizedFormats.TOO_SMALL_COST_RELATIVE_TOLERANCE,
|
throw new ConvergenceException(LocalizedFormats.TOO_SMALL_COST_RELATIVE_TOLERANCE,
|
||||||
costRelativeTolerance);
|
costRelativeTolerance);
|
||||||
} else if (delta <= 2.2204e-16 * xNorm) {
|
} else if (delta <= 2.2204e-16 * xNorm) {
|
||||||
throw new OptimizationException(LocalizedFormats.TOO_SMALL_PARAMETERS_RELATIVE_TOLERANCE,
|
throw new ConvergenceException(LocalizedFormats.TOO_SMALL_PARAMETERS_RELATIVE_TOLERANCE,
|
||||||
parRelativeTolerance);
|
parRelativeTolerance);
|
||||||
} else if (maxCosine <= 2.2204e-16) {
|
} else if (maxCosine <= 2.2204e-16) {
|
||||||
throw new OptimizationException(LocalizedFormats.TOO_SMALL_ORTHOGONALITY_TOLERANCE,
|
throw new ConvergenceException(LocalizedFormats.TOO_SMALL_ORTHOGONALITY_TOLERANCE,
|
||||||
orthoTolerance);
|
orthoTolerance);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -733,7 +725,6 @@ public class LevenbergMarquardtOptimizer extends AbstractLeastSquaresOptimizer {
|
||||||
lmDiag[i] = -sin * rik + cos * lmDiag[i];
|
lmDiag[i] = -sin * rik + cos * lmDiag[i];
|
||||||
weightedResidualJacobian[i][pk] = temp2;
|
weightedResidualJacobian[i][pk] = temp2;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -741,7 +732,6 @@ public class LevenbergMarquardtOptimizer extends AbstractLeastSquaresOptimizer {
|
||||||
// the corresponding diagonal element of R
|
// the corresponding diagonal element of R
|
||||||
lmDiag[j] = weightedResidualJacobian[j][permutation[j]];
|
lmDiag[j] = weightedResidualJacobian[j][permutation[j]];
|
||||||
weightedResidualJacobian[j][permutation[j]] = lmDir[j];
|
weightedResidualJacobian[j][permutation[j]] = lmDir[j];
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// solve the triangular system for z, if the system is
|
// solve the triangular system for z, if the system is
|
||||||
|
@ -770,7 +760,6 @@ public class LevenbergMarquardtOptimizer extends AbstractLeastSquaresOptimizer {
|
||||||
for (int j = 0; j < lmDir.length; ++j) {
|
for (int j = 0; j < lmDir.length; ++j) {
|
||||||
lmDir[permutation[j]] = work[j];
|
lmDir[permutation[j]] = work[j];
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -793,9 +782,9 @@ public class LevenbergMarquardtOptimizer extends AbstractLeastSquaresOptimizer {
|
||||||
* are performed in non-increasing columns norms order thanks to columns
|
* are performed in non-increasing columns norms order thanks to columns
|
||||||
* pivoting. The diagonal elements of the R matrix are therefore also in
|
* pivoting. The diagonal elements of the R matrix are therefore also in
|
||||||
* non-increasing absolute values order.</p>
|
* non-increasing absolute values order.</p>
|
||||||
* @exception OptimizationException if the decomposition cannot be performed
|
* @exception ConvergenceException if the decomposition cannot be performed
|
||||||
*/
|
*/
|
||||||
private void qrDecomposition() throws OptimizationException {
|
private void qrDecomposition() throws ConvergenceException {
|
||||||
|
|
||||||
// initializations
|
// initializations
|
||||||
for (int k = 0; k < cols; ++k) {
|
for (int k = 0; k < cols; ++k) {
|
||||||
|
@ -821,7 +810,7 @@ public class LevenbergMarquardtOptimizer extends AbstractLeastSquaresOptimizer {
|
||||||
norm2 += aki * aki;
|
norm2 += aki * aki;
|
||||||
}
|
}
|
||||||
if (Double.isInfinite(norm2) || Double.isNaN(norm2)) {
|
if (Double.isInfinite(norm2) || Double.isNaN(norm2)) {
|
||||||
throw new OptimizationException(LocalizedFormats.UNABLE_TO_PERFORM_QR_DECOMPOSITION_ON_JACOBIAN,
|
throw new ConvergenceException(LocalizedFormats.UNABLE_TO_PERFORM_QR_DECOMPOSITION_ON_JACOBIAN,
|
||||||
rows, cols);
|
rows, cols);
|
||||||
}
|
}
|
||||||
if (norm2 > ak2) {
|
if (norm2 > ak2) {
|
||||||
|
@ -858,11 +847,8 @@ public class LevenbergMarquardtOptimizer extends AbstractLeastSquaresOptimizer {
|
||||||
weightedResidualJacobian[j][permutation[k + dk]] -= gamma * weightedResidualJacobian[j][pk];
|
weightedResidualJacobian[j][permutation[k + dk]] -= gamma * weightedResidualJacobian[j][pk];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rank = solvedCols;
|
rank = solvedCols;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -883,5 +869,4 @@ public class LevenbergMarquardtOptimizer extends AbstractLeastSquaresOptimizer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,14 +17,14 @@
|
||||||
|
|
||||||
package org.apache.commons.math.optimization.general;
|
package org.apache.commons.math.optimization.general;
|
||||||
|
|
||||||
import org.apache.commons.math.ConvergenceException;
|
|
||||||
import org.apache.commons.math.FunctionEvaluationException;
|
import org.apache.commons.math.FunctionEvaluationException;
|
||||||
|
import org.apache.commons.math.exception.MathIllegalStateException;
|
||||||
|
import org.apache.commons.math.exception.ConvergenceException;
|
||||||
import org.apache.commons.math.analysis.UnivariateRealFunction;
|
import org.apache.commons.math.analysis.UnivariateRealFunction;
|
||||||
import org.apache.commons.math.analysis.solvers.BrentSolver;
|
import org.apache.commons.math.analysis.solvers.BrentSolver;
|
||||||
import org.apache.commons.math.analysis.solvers.UnivariateRealSolver;
|
import org.apache.commons.math.analysis.solvers.UnivariateRealSolver;
|
||||||
import org.apache.commons.math.exception.util.LocalizedFormats;
|
import org.apache.commons.math.exception.util.LocalizedFormats;
|
||||||
import org.apache.commons.math.optimization.GoalType;
|
import org.apache.commons.math.optimization.GoalType;
|
||||||
import org.apache.commons.math.optimization.OptimizationException;
|
|
||||||
import org.apache.commons.math.optimization.RealPointValuePair;
|
import org.apache.commons.math.optimization.RealPointValuePair;
|
||||||
import org.apache.commons.math.util.FastMath;
|
import org.apache.commons.math.util.FastMath;
|
||||||
|
|
||||||
|
@ -54,11 +54,11 @@ public class NonLinearConjugateGradientOptimizer
|
||||||
/** Current point. */
|
/** Current point. */
|
||||||
private double[] point;
|
private double[] point;
|
||||||
|
|
||||||
/** Simple constructor with default settings.
|
/**
|
||||||
* <p>The convergence check is set to a {@link
|
* Simple constructor with default settings.
|
||||||
* org.apache.commons.math.optimization.SimpleVectorialValueChecker}
|
* The convergence check is set to a {@link
|
||||||
* and the maximal number of iterations is set to
|
* org.apache.commons.math.optimization.SimpleVectorialValueChecker}.
|
||||||
* {@link AbstractScalarDifferentiableOptimizer#DEFAULT_MAX_ITERATIONS}.
|
*
|
||||||
* @param updateFormula formula to use for updating the β parameter,
|
* @param updateFormula formula to use for updating the β parameter,
|
||||||
* must be one of {@link ConjugateGradientFormula#FLETCHER_REEVES} or {@link
|
* must be one of {@link ConjugateGradientFormula#FLETCHER_REEVES} or {@link
|
||||||
* ConjugateGradientFormula#POLAK_RIBIERE}
|
* ConjugateGradientFormula#POLAK_RIBIERE}
|
||||||
|
@ -110,104 +110,104 @@ public class NonLinearConjugateGradientOptimizer
|
||||||
/** {@inheritDoc} */
|
/** {@inheritDoc} */
|
||||||
@Override
|
@Override
|
||||||
protected RealPointValuePair doOptimize()
|
protected RealPointValuePair doOptimize()
|
||||||
throws FunctionEvaluationException, OptimizationException, IllegalArgumentException {
|
throws FunctionEvaluationException {
|
||||||
try {
|
// Initialization.
|
||||||
// initialization
|
if (preconditioner == null) {
|
||||||
if (preconditioner == null) {
|
preconditioner = new IdentityPreconditioner();
|
||||||
preconditioner = new IdentityPreconditioner();
|
}
|
||||||
|
if (solver == null) {
|
||||||
|
solver = new BrentSolver();
|
||||||
|
}
|
||||||
|
point = getStartPoint();
|
||||||
|
final GoalType goal = getGoalType();
|
||||||
|
final int n = point.length;
|
||||||
|
double[] r = computeObjectiveGradient(point);
|
||||||
|
if (goal == GoalType.MINIMIZE) {
|
||||||
|
for (int i = 0; i < n; ++i) {
|
||||||
|
r[i] = -r[i];
|
||||||
}
|
}
|
||||||
if (solver == null) {
|
}
|
||||||
solver = new BrentSolver();
|
|
||||||
|
// Initial search direction.
|
||||||
|
double[] steepestDescent = preconditioner.precondition(point, r);
|
||||||
|
double[] searchDirection = steepestDescent.clone();
|
||||||
|
|
||||||
|
double delta = 0;
|
||||||
|
for (int i = 0; i < n; ++i) {
|
||||||
|
delta += r[i] * searchDirection[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
RealPointValuePair current = null;
|
||||||
|
int iter = 0;
|
||||||
|
while (true) {
|
||||||
|
++iter;
|
||||||
|
|
||||||
|
final double objective = computeObjectiveValue(point);
|
||||||
|
RealPointValuePair previous = current;
|
||||||
|
current = new RealPointValuePair(point, objective);
|
||||||
|
if (previous != null) {
|
||||||
|
if (getConvergenceChecker().converged(iter, previous, current)) {
|
||||||
|
// We have found an optimum.
|
||||||
|
return current;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
point = getStartPoint();
|
|
||||||
final GoalType goal = getGoalType();
|
double dTd = 0;
|
||||||
final int n = point.length;
|
for (final double di : searchDirection) {
|
||||||
double[] r = computeObjectiveGradient(point);
|
dTd += di * di;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find the optimal step in the search direction.
|
||||||
|
final UnivariateRealFunction lsf = new LineSearchFunction(searchDirection);
|
||||||
|
try {
|
||||||
|
final double step = solver.solve(lsf, 0, findUpperBound(lsf, 0, initialStep));
|
||||||
|
|
||||||
|
// Validate new point.
|
||||||
|
for (int i = 0; i < point.length; ++i) {
|
||||||
|
point[i] += step * searchDirection[i];
|
||||||
|
}
|
||||||
|
} catch (org.apache.commons.math.ConvergenceException e) {
|
||||||
|
throw new ConvergenceException(); // XXX ugly workaround.
|
||||||
|
}
|
||||||
|
|
||||||
|
r = computeObjectiveGradient(point);
|
||||||
if (goal == GoalType.MINIMIZE) {
|
if (goal == GoalType.MINIMIZE) {
|
||||||
for (int i = 0; i < n; ++i) {
|
for (int i = 0; i < n; ++i) {
|
||||||
r[i] = -r[i];
|
r[i] = -r[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// initial search direction
|
// Compute beta.
|
||||||
double[] steepestDescent = preconditioner.precondition(point, r);
|
final double deltaOld = delta;
|
||||||
double[] searchDirection = steepestDescent.clone();
|
final double[] newSteepestDescent = preconditioner.precondition(point, r);
|
||||||
|
delta = 0;
|
||||||
double delta = 0;
|
|
||||||
for (int i = 0; i < n; ++i) {
|
for (int i = 0; i < n; ++i) {
|
||||||
delta += r[i] * searchDirection[i];
|
delta += r[i] * newSteepestDescent[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
RealPointValuePair current = null;
|
final double beta;
|
||||||
while (true) {
|
if (updateFormula == ConjugateGradientFormula.FLETCHER_REEVES) {
|
||||||
|
beta = delta / deltaOld;
|
||||||
final double objective = computeObjectiveValue(point);
|
} else {
|
||||||
RealPointValuePair previous = current;
|
double deltaMid = 0;
|
||||||
current = new RealPointValuePair(point, objective);
|
for (int i = 0; i < r.length; ++i) {
|
||||||
if (previous != null) {
|
deltaMid += r[i] * steepestDescent[i];
|
||||||
if (getConvergenceChecker().converged(getIterations(), previous, current)) {
|
|
||||||
// we have found an optimum
|
|
||||||
return current;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
beta = (delta - deltaMid) / deltaOld;
|
||||||
|
}
|
||||||
|
steepestDescent = newSteepestDescent;
|
||||||
|
|
||||||
incrementIterationsCounter();
|
// Compute conjugate search direction.
|
||||||
|
if (iter % n == 0 ||
|
||||||
double dTd = 0;
|
beta < 0) {
|
||||||
for (final double di : searchDirection) {
|
// Break conjugation: reset search direction.
|
||||||
dTd += di * di;
|
searchDirection = steepestDescent.clone();
|
||||||
}
|
} else {
|
||||||
|
// Compute new conjugate search direction.
|
||||||
// find the optimal step in the search direction
|
|
||||||
final UnivariateRealFunction lsf = new LineSearchFunction(searchDirection);
|
|
||||||
final double step = solver.solve(lsf, 0, findUpperBound(lsf, 0, initialStep));
|
|
||||||
|
|
||||||
// validate new point
|
|
||||||
for (int i = 0; i < point.length; ++i) {
|
|
||||||
point[i] += step * searchDirection[i];
|
|
||||||
}
|
|
||||||
r = computeObjectiveGradient(point);
|
|
||||||
if (goal == GoalType.MINIMIZE) {
|
|
||||||
for (int i = 0; i < n; ++i) {
|
|
||||||
r[i] = -r[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// compute beta
|
|
||||||
final double deltaOld = delta;
|
|
||||||
final double[] newSteepestDescent = preconditioner.precondition(point, r);
|
|
||||||
delta = 0;
|
|
||||||
for (int i = 0; i < n; ++i) {
|
for (int i = 0; i < n; ++i) {
|
||||||
delta += r[i] * newSteepestDescent[i];
|
searchDirection[i] = steepestDescent[i] + beta * searchDirection[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
final double beta;
|
|
||||||
if (updateFormula == ConjugateGradientFormula.FLETCHER_REEVES) {
|
|
||||||
beta = delta / deltaOld;
|
|
||||||
} else {
|
|
||||||
double deltaMid = 0;
|
|
||||||
for (int i = 0; i < r.length; ++i) {
|
|
||||||
deltaMid += r[i] * steepestDescent[i];
|
|
||||||
}
|
|
||||||
beta = (delta - deltaMid) / deltaOld;
|
|
||||||
}
|
|
||||||
steepestDescent = newSteepestDescent;
|
|
||||||
|
|
||||||
// compute conjugate search direction
|
|
||||||
if ((getIterations() % n == 0) || (beta < 0)) {
|
|
||||||
// break conjugation: reset search direction
|
|
||||||
searchDirection = steepestDescent.clone();
|
|
||||||
} else {
|
|
||||||
// compute new conjugate search direction
|
|
||||||
for (int i = 0; i < n; ++i) {
|
|
||||||
searchDirection[i] = steepestDescent[i] + beta * searchDirection[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (ConvergenceException ce) {
|
|
||||||
throw new OptimizationException(ce);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -218,11 +218,12 @@ public class NonLinearConjugateGradientOptimizer
|
||||||
* @param h initial step to try
|
* @param h initial step to try
|
||||||
* @return b such that f(a) and f(b) have opposite signs
|
* @return b such that f(a) and f(b) have opposite signs
|
||||||
* @exception FunctionEvaluationException if the function cannot be computed
|
* @exception FunctionEvaluationException if the function cannot be computed
|
||||||
* @exception OptimizationException if no bracket can be found
|
* @exception MathIllegalStateException if no bracket can be found
|
||||||
|
* @deprecated in 2.2 (must be replaced with "BracketFinder").
|
||||||
*/
|
*/
|
||||||
private double findUpperBound(final UnivariateRealFunction f,
|
private double findUpperBound(final UnivariateRealFunction f,
|
||||||
final double a, final double h)
|
final double a, final double h)
|
||||||
throws FunctionEvaluationException, OptimizationException {
|
throws FunctionEvaluationException {
|
||||||
final double yA = f.value(a);
|
final double yA = f.value(a);
|
||||||
double yB = yA;
|
double yB = yA;
|
||||||
for (double step = h; step < Double.MAX_VALUE; step *= FastMath.max(2, yA / yB)) {
|
for (double step = h; step < Double.MAX_VALUE; step *= FastMath.max(2, yA / yB)) {
|
||||||
|
@ -232,7 +233,7 @@ public class NonLinearConjugateGradientOptimizer
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
throw new OptimizationException(LocalizedFormats.UNABLE_TO_BRACKET_OPTIMUM_IN_LINE_SEARCH);
|
throw new MathIllegalStateException(LocalizedFormats.UNABLE_TO_BRACKET_OPTIMUM_IN_LINE_SEARCH);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Default identity preconditioner. */
|
/** Default identity preconditioner. */
|
||||||
|
|
|
@ -20,77 +20,69 @@ package org.apache.commons.math.optimization.general;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
import org.apache.commons.math.FunctionEvaluationException;
|
import org.apache.commons.math.FunctionEvaluationException;
|
||||||
import org.apache.commons.math.MaxIterationsExceededException;
|
|
||||||
import org.apache.commons.math.analysis.UnivariateRealFunction;
|
import org.apache.commons.math.analysis.UnivariateRealFunction;
|
||||||
import org.apache.commons.math.optimization.GoalType;
|
import org.apache.commons.math.optimization.GoalType;
|
||||||
import org.apache.commons.math.optimization.OptimizationException;
|
|
||||||
import org.apache.commons.math.optimization.RealPointValuePair;
|
import org.apache.commons.math.optimization.RealPointValuePair;
|
||||||
|
import org.apache.commons.math.optimization.ConvergenceChecker;
|
||||||
import org.apache.commons.math.optimization.univariate.AbstractUnivariateRealOptimizer;
|
import org.apache.commons.math.optimization.univariate.AbstractUnivariateRealOptimizer;
|
||||||
import org.apache.commons.math.optimization.univariate.BracketFinder;
|
import org.apache.commons.math.optimization.univariate.BracketFinder;
|
||||||
import org.apache.commons.math.optimization.univariate.BrentOptimizer;
|
import org.apache.commons.math.optimization.univariate.BrentOptimizer;
|
||||||
|
import org.apache.commons.math.optimization.univariate.UnivariateRealPointValuePair;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Powell algorithm.
|
* Powell algorithm.
|
||||||
* This code is translated and adapted from the Python version of this
|
* This code is translated and adapted from the Python version of this
|
||||||
* algorithm (as implemented in module {@code optimize.py} v0.5 of
|
* algorithm (as implemented in module {@code optimize.py} v0.5 of
|
||||||
* <em>SciPy</em>).
|
* <em>SciPy</em>).
|
||||||
|
* <br/>
|
||||||
|
* The user is responsible for calling {@link
|
||||||
|
* #setConvergenceChecker(ConvergenceChecker) ConvergenceChecker}
|
||||||
|
* prior to using the optimizer.
|
||||||
*
|
*
|
||||||
* @version $Revision$ $Date$
|
* @version $Revision$ $Date$
|
||||||
* @since 2.2
|
* @since 2.2
|
||||||
*/
|
*/
|
||||||
public class PowellOptimizer
|
public class PowellOptimizer
|
||||||
extends AbstractScalarOptimizer {
|
extends AbstractScalarOptimizer {
|
||||||
/**
|
|
||||||
* Default relative tolerance for line search ({@value}).
|
|
||||||
*/
|
|
||||||
public static final double DEFAULT_LS_RELATIVE_TOLERANCE = 1e-7;
|
|
||||||
/**
|
|
||||||
* Default absolute tolerance for line search ({@value}).
|
|
||||||
*/
|
|
||||||
public static final double DEFAULT_LS_ABSOLUTE_TOLERANCE = 1e-11;
|
|
||||||
/**
|
/**
|
||||||
* Line search.
|
* Line search.
|
||||||
*/
|
*/
|
||||||
private final LineSearch line;
|
private LineSearch line = new LineSearch();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor with default line search tolerances (see the
|
* Set the convergence checker.
|
||||||
* {@link #PowellOptimizer(double,double) other constructor}).
|
* It also indirectly sets the line search tolerances to the square-root
|
||||||
*/
|
* of the correponding tolerances in the checker.
|
||||||
public PowellOptimizer() {
|
|
||||||
this(DEFAULT_LS_RELATIVE_TOLERANCE,
|
|
||||||
DEFAULT_LS_ABSOLUTE_TOLERANCE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor with default absolute line search tolerances (see
|
|
||||||
* the {@link #PowellOptimizer(double,double) other constructor}).
|
|
||||||
*
|
*
|
||||||
* @param lsRelativeTolerance Relative error tolerance for
|
* @param checker Convergence checker.
|
||||||
* the line search algorithm ({@link BrentOptimizer}).
|
|
||||||
*/
|
*/
|
||||||
public PowellOptimizer(double lsRelativeTolerance) {
|
public void setConvergenceChecker(ConvergenceChecker<RealPointValuePair> checker) {
|
||||||
this(lsRelativeTolerance,
|
super.setConvergenceChecker(checker);
|
||||||
DEFAULT_LS_ABSOLUTE_TOLERANCE);
|
|
||||||
|
// Line search tolerances can be much lower than the tolerances
|
||||||
|
// required for the optimizer itself.
|
||||||
|
final double minTol = 1e-4;
|
||||||
|
final double rel = Math.min(Math.sqrt(checker.getRelativeThreshold()), minTol);
|
||||||
|
final double abs = Math.min(Math.sqrt(checker.getAbsoluteThreshold()), minTol);
|
||||||
|
line.setConvergenceChecker(new BrentOptimizer.BrentConvergenceChecker(rel, abs));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** {@inheritDoc} */
|
||||||
* @param lsRelativeTolerance Relative error tolerance for
|
@Override
|
||||||
* the line search algorithm ({@link BrentOptimizer}).
|
public void setMaxEvaluations(int maxEvaluations) {
|
||||||
* @param lsAbsoluteTolerance Relative error tolerance for
|
super.setMaxEvaluations(maxEvaluations);
|
||||||
* the line search algorithm ({@link BrentOptimizer}).
|
|
||||||
*/
|
// We must allow at least as many iterations to the underlying line
|
||||||
public PowellOptimizer(double lsRelativeTolerance,
|
// search optimizer. Because the line search inner class will call
|
||||||
double lsAbsoluteTolerance) {
|
// "computeObjectiveValue" in this class, we ensure that this class
|
||||||
line = new LineSearch(lsRelativeTolerance,
|
// will be the first to eventually throw "TooManyEvaluationsException".
|
||||||
lsAbsoluteTolerance);
|
line.setMaxEvaluations(maxEvaluations);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
/** {@inheritDoc} */
|
||||||
@Override
|
@Override
|
||||||
protected RealPointValuePair doOptimize()
|
protected RealPointValuePair doOptimize()
|
||||||
throws FunctionEvaluationException,
|
throws FunctionEvaluationException {
|
||||||
OptimizationException {
|
|
||||||
final GoalType goal = getGoalType();
|
final GoalType goal = getGoalType();
|
||||||
final double[] guess = getStartPoint();
|
final double[] guess = getStartPoint();
|
||||||
final int n = guess.length;
|
final int n = guess.length;
|
||||||
|
@ -103,8 +95,9 @@ public class PowellOptimizer
|
||||||
double[] x = guess;
|
double[] x = guess;
|
||||||
double fVal = computeObjectiveValue(x);
|
double fVal = computeObjectiveValue(x);
|
||||||
double[] x1 = x.clone();
|
double[] x1 = x.clone();
|
||||||
|
int iter = 0;
|
||||||
while (true) {
|
while (true) {
|
||||||
incrementIterationsCounter();
|
++iter;
|
||||||
|
|
||||||
double fX = fVal;
|
double fX = fVal;
|
||||||
double fX2 = 0;
|
double fX2 = 0;
|
||||||
|
@ -117,9 +110,9 @@ public class PowellOptimizer
|
||||||
|
|
||||||
fX2 = fVal;
|
fX2 = fVal;
|
||||||
|
|
||||||
line.search(x, d);
|
final UnivariateRealPointValuePair optimum = line.search(x, d);
|
||||||
fVal = line.getValueAtOptimum();
|
fVal = optimum.getValue();
|
||||||
alphaMin = line.getOptimum();
|
alphaMin = optimum.getPoint();
|
||||||
final double[][] result = newPointAndDirection(x, d, alphaMin);
|
final double[][] result = newPointAndDirection(x, d, alphaMin);
|
||||||
x = result[0];
|
x = result[0];
|
||||||
|
|
||||||
|
@ -131,7 +124,7 @@ public class PowellOptimizer
|
||||||
|
|
||||||
final RealPointValuePair previous = new RealPointValuePair(x1, fX);
|
final RealPointValuePair previous = new RealPointValuePair(x1, fX);
|
||||||
final RealPointValuePair current = new RealPointValuePair(x, fVal);
|
final RealPointValuePair current = new RealPointValuePair(x, fVal);
|
||||||
if (getConvergenceChecker().converged(getIterations(), previous, current)) {
|
if (getConvergenceChecker().converged(iter, previous, current)) {
|
||||||
if (goal == GoalType.MINIMIZE) {
|
if (goal == GoalType.MINIMIZE) {
|
||||||
return (fVal < fX) ? current : previous;
|
return (fVal < fX) ? current : previous;
|
||||||
} else {
|
} else {
|
||||||
|
@ -157,9 +150,9 @@ public class PowellOptimizer
|
||||||
t -= delta * temp * temp;
|
t -= delta * temp * temp;
|
||||||
|
|
||||||
if (t < 0.0) {
|
if (t < 0.0) {
|
||||||
line.search(x, d);
|
final UnivariateRealPointValuePair optimum = line.search(x, d);
|
||||||
fVal = line.getValueAtOptimum();
|
fVal = optimum.getValue();
|
||||||
alphaMin = line.getOptimum();
|
alphaMin = optimum.getPoint();
|
||||||
final double[][] result = newPointAndDirection(x, d, alphaMin);
|
final double[][] result = newPointAndDirection(x, d, alphaMin);
|
||||||
x = result[0];
|
x = result[0];
|
||||||
|
|
||||||
|
@ -200,11 +193,7 @@ public class PowellOptimizer
|
||||||
* Class for finding the minimum of the objective function along a given
|
* Class for finding the minimum of the objective function along a given
|
||||||
* direction.
|
* direction.
|
||||||
*/
|
*/
|
||||||
private class LineSearch {
|
private class LineSearch extends BrentOptimizer {
|
||||||
/**
|
|
||||||
* Optimizer.
|
|
||||||
*/
|
|
||||||
private final AbstractUnivariateRealOptimizer optim = new BrentOptimizer();
|
|
||||||
/**
|
/**
|
||||||
* Automatic bracketing.
|
* Automatic bracketing.
|
||||||
*/
|
*/
|
||||||
|
@ -212,78 +201,41 @@ public class PowellOptimizer
|
||||||
/**
|
/**
|
||||||
* Value of the optimum.
|
* Value of the optimum.
|
||||||
*/
|
*/
|
||||||
private double optimum = Double.NaN;
|
private UnivariateRealPointValuePair optimum;
|
||||||
/**
|
|
||||||
* Value of the objective function at the optimum.
|
|
||||||
*/
|
|
||||||
private double valueAtOptimum = Double.NaN;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param relativeTolerance Relative tolerance.
|
|
||||||
* @param absoluteTolerance Absolute tolerance.
|
|
||||||
*/
|
|
||||||
public LineSearch(double relativeTolerance,
|
|
||||||
double absoluteTolerance) {
|
|
||||||
optim.setRelativeAccuracy(relativeTolerance);
|
|
||||||
optim.setAbsoluteAccuracy(absoluteTolerance);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find the minimum of the function {@code f(p + alpha * d)}.
|
* Find the minimum of the function {@code f(p + alpha * d)}.
|
||||||
*
|
*
|
||||||
* @param p Starting point.
|
* @param p Starting point.
|
||||||
* @param d Search direction.
|
* @param d Search direction.
|
||||||
* @throws OptimizationException if function cannot be evaluated at some test point
|
|
||||||
* or algorithm fails to converge
|
|
||||||
*/
|
|
||||||
public void search(final double[] p,
|
|
||||||
final double[] d)
|
|
||||||
throws OptimizationException {
|
|
||||||
|
|
||||||
// Reset.
|
|
||||||
optimum = Double.NaN;
|
|
||||||
valueAtOptimum = Double.NaN;
|
|
||||||
|
|
||||||
try {
|
|
||||||
final int n = p.length;
|
|
||||||
final UnivariateRealFunction f = new UnivariateRealFunction() {
|
|
||||||
public double value(double alpha)
|
|
||||||
throws FunctionEvaluationException {
|
|
||||||
|
|
||||||
final double[] x = new double[n];
|
|
||||||
for (int i = 0; i < n; i++) {
|
|
||||||
x[i] = p[i] + alpha * d[i];
|
|
||||||
}
|
|
||||||
final double obj = computeObjectiveValue(x);
|
|
||||||
return obj;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
final GoalType goal = getGoalType();
|
|
||||||
bracket.search(f, goal, 0, 1);
|
|
||||||
optimum = optim.optimize(f, goal,
|
|
||||||
bracket.getLo(),
|
|
||||||
bracket.getHi(),
|
|
||||||
bracket.getMid());
|
|
||||||
valueAtOptimum = optim.getFunctionValue();
|
|
||||||
} catch (FunctionEvaluationException e) {
|
|
||||||
throw new OptimizationException(e);
|
|
||||||
} catch (MaxIterationsExceededException e) {
|
|
||||||
throw new OptimizationException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the optimum.
|
* @return the optimum.
|
||||||
|
* @throws FunctionEvaluationException if the function evaluation
|
||||||
|
* fails.
|
||||||
|
* @throws TooManyEvaluationsException if the number of evaluations is
|
||||||
|
* exceeded.
|
||||||
*/
|
*/
|
||||||
public double getOptimum() {
|
public UnivariateRealPointValuePair search(final double[] p,
|
||||||
return optimum;
|
final double[] d)
|
||||||
}
|
throws FunctionEvaluationException {
|
||||||
/**
|
|
||||||
* @return the value of the function at the optimum.
|
final int n = p.length;
|
||||||
*/
|
final UnivariateRealFunction f = new UnivariateRealFunction() {
|
||||||
public double getValueAtOptimum() {
|
public double value(double alpha)
|
||||||
return valueAtOptimum;
|
throws FunctionEvaluationException {
|
||||||
|
|
||||||
|
final double[] x = new double[n];
|
||||||
|
for (int i = 0; i < n; i++) {
|
||||||
|
x[i] = p[i] + alpha * d[i];
|
||||||
|
}
|
||||||
|
final double obj = PowellOptimizer.this.computeObjectiveValue(x);
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
final GoalType goal = PowellOptimizer.this.getGoalType();
|
||||||
|
bracket.search(f, goal, 0, 1);
|
||||||
|
return optimize(f, goal, bracket.getLo(), bracket.getHi(),
|
||||||
|
bracket.getMid());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,7 +33,7 @@ by changing its input variables set until an optimal set is found. There are onl
|
||||||
interfaces defining the common behavior of optimizers, one for each supported type of objective
|
interfaces defining the common behavior of optimizers, one for each supported type of objective
|
||||||
function:
|
function:
|
||||||
<ul>
|
<ul>
|
||||||
<li>{@link org.apache.commons.math.optimization.UnivariateRealOptimizer
|
<li>{@link org.apache.commons.math.optimization.univariate.UnivariateRealOptimizer
|
||||||
UnivariateRealOptimizer} for {@link org.apache.commons.math.analysis.UnivariateRealFunction
|
UnivariateRealOptimizer} for {@link org.apache.commons.math.analysis.UnivariateRealFunction
|
||||||
univariate real functions}</li>
|
univariate real functions}</li>
|
||||||
<li>{@link org.apache.commons.math.optimization.MultivariateRealOptimizer
|
<li>{@link org.apache.commons.math.optimization.MultivariateRealOptimizer
|
||||||
|
|
|
@ -17,14 +17,13 @@
|
||||||
|
|
||||||
package org.apache.commons.math.optimization.univariate;
|
package org.apache.commons.math.optimization.univariate;
|
||||||
|
|
||||||
import org.apache.commons.math.ConvergingAlgorithmImpl;
|
|
||||||
import org.apache.commons.math.FunctionEvaluationException;
|
import org.apache.commons.math.FunctionEvaluationException;
|
||||||
import org.apache.commons.math.MaxEvaluationsExceededException;
|
import org.apache.commons.math.util.Incrementor;
|
||||||
import org.apache.commons.math.MaxIterationsExceededException;
|
import org.apache.commons.math.exception.MaxCountExceededException;
|
||||||
|
import org.apache.commons.math.exception.TooManyEvaluationsException;
|
||||||
import org.apache.commons.math.analysis.UnivariateRealFunction;
|
import org.apache.commons.math.analysis.UnivariateRealFunction;
|
||||||
import org.apache.commons.math.exception.NoDataException;
|
|
||||||
import org.apache.commons.math.optimization.GoalType;
|
import org.apache.commons.math.optimization.GoalType;
|
||||||
import org.apache.commons.math.optimization.UnivariateRealOptimizer;
|
import org.apache.commons.math.optimization.ConvergenceChecker;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provide a default implementation for several functions useful to generic
|
* Provide a default implementation for several functions useful to generic
|
||||||
|
@ -34,19 +33,13 @@ import org.apache.commons.math.optimization.UnivariateRealOptimizer;
|
||||||
* @since 2.0
|
* @since 2.0
|
||||||
*/
|
*/
|
||||||
public abstract class AbstractUnivariateRealOptimizer
|
public abstract class AbstractUnivariateRealOptimizer
|
||||||
extends ConvergingAlgorithmImpl implements UnivariateRealOptimizer {
|
implements UnivariateRealOptimizer {
|
||||||
/** Indicates where a root has been computed. */
|
/** Convergence checker. */
|
||||||
private boolean resultComputed;
|
private ConvergenceChecker<UnivariateRealPointValuePair> checker;
|
||||||
/** The last computed root. */
|
/** Evaluations counter. */
|
||||||
private double result;
|
private final Incrementor evaluations = new Incrementor();
|
||||||
/** Value of the function at the last computed result. */
|
|
||||||
private double functionValue;
|
|
||||||
/** Maximal number of evaluations allowed. */
|
|
||||||
private int maxEvaluations;
|
|
||||||
/** Number of evaluations already performed. */
|
|
||||||
private int evaluations;
|
|
||||||
/** Optimization type */
|
/** Optimization type */
|
||||||
private GoalType optimizationGoal;
|
private GoalType goal;
|
||||||
/** Lower end of search interval. */
|
/** Lower end of search interval. */
|
||||||
private double searchMin;
|
private double searchMin;
|
||||||
/** Higher end of search interval. */
|
/** Higher end of search interval. */
|
||||||
|
@ -56,115 +49,35 @@ public abstract class AbstractUnivariateRealOptimizer
|
||||||
/** Function to optimize. */
|
/** Function to optimize. */
|
||||||
private UnivariateRealFunction function;
|
private UnivariateRealFunction function;
|
||||||
|
|
||||||
/**
|
|
||||||
* Construct a solver with given iteration count and accuracy.
|
|
||||||
* FunctionEvaluationExceptionFunctionEvaluationException
|
|
||||||
* @param defaultAbsoluteAccuracy maximum absolute error
|
|
||||||
* @param defaultMaximalIterationCount maximum number of iterations
|
|
||||||
* @throws IllegalArgumentException if f is null or the
|
|
||||||
* defaultAbsoluteAccuracy is not valid
|
|
||||||
* @deprecated in 2.2. Please use the "setter" methods to assign meaningful
|
|
||||||
* values to the maximum numbers of iterations and evaluations, and to the
|
|
||||||
* absolute and relative accuracy thresholds.
|
|
||||||
*/
|
|
||||||
protected AbstractUnivariateRealOptimizer(final int defaultMaximalIterationCount,
|
|
||||||
final double defaultAbsoluteAccuracy) {
|
|
||||||
super(defaultMaximalIterationCount, defaultAbsoluteAccuracy);
|
|
||||||
resultComputed = false;
|
|
||||||
setMaxEvaluations(Integer.MAX_VALUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Default constructor.
|
|
||||||
* To be removed once the single non-default one has been removed.
|
|
||||||
*/
|
|
||||||
protected AbstractUnivariateRealOptimizer() {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check whether a result has been computed.
|
|
||||||
* @throws NoDataException if no result has been computed
|
|
||||||
* @deprecated in 2.2 (no alternative).
|
|
||||||
*/
|
|
||||||
protected void checkResultComputed() {
|
|
||||||
if (!resultComputed) {
|
|
||||||
throw new NoDataException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
public double getResult() {
|
|
||||||
if (!resultComputed) {
|
|
||||||
throw new NoDataException();
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
public double getFunctionValue() {
|
|
||||||
if (functionValue == Double.NaN) {
|
|
||||||
final double opt = getResult();
|
|
||||||
try {
|
|
||||||
functionValue = function.value(opt);
|
|
||||||
} catch (FunctionEvaluationException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return functionValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convenience function for implementations.
|
|
||||||
*
|
|
||||||
* @param x the result to set
|
|
||||||
* @param fx the result to set
|
|
||||||
* @param iterationCount the iteration count to set
|
|
||||||
* @deprecated in 2.2 (no alternative).
|
|
||||||
*/
|
|
||||||
protected final void setResult(final double x, final double fx,
|
|
||||||
final int iterationCount) {
|
|
||||||
this.result = x;
|
|
||||||
this.functionValue = fx;
|
|
||||||
this.iterationCount = iterationCount;
|
|
||||||
this.resultComputed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convenience function for implementations.
|
|
||||||
* @deprecated in 2.2 (no alternative).
|
|
||||||
*/
|
|
||||||
protected final void clearResult() {
|
|
||||||
this.resultComputed = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
/** {@inheritDoc} */
|
||||||
public void setMaxEvaluations(int maxEvaluations) {
|
public void setMaxEvaluations(int maxEvaluations) {
|
||||||
this.maxEvaluations = maxEvaluations;
|
evaluations.setMaximalCount(maxEvaluations);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
/** {@inheritDoc} */
|
||||||
public int getMaxEvaluations() {
|
public int getMaxEvaluations() {
|
||||||
return maxEvaluations;
|
return evaluations.getMaximalCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
/** {@inheritDoc} */
|
||||||
public int getEvaluations() {
|
public int getEvaluations() {
|
||||||
return evaluations;
|
return evaluations.getCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the optimization type.
|
* @return the optimization type.
|
||||||
*/
|
*/
|
||||||
public GoalType getGoalType() {
|
public GoalType getGoalType() {
|
||||||
return optimizationGoal;
|
return goal;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* @return the lower of the search interval.
|
* @return the lower end of the search interval.
|
||||||
*/
|
*/
|
||||||
public double getMin() {
|
public double getMin() {
|
||||||
return searchMin;
|
return searchMin;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* @return the higher of the search interval.
|
* @return the higher end of the search interval.
|
||||||
*/
|
*/
|
||||||
public double getMax() {
|
public double getMax() {
|
||||||
return searchMax;
|
return searchMax;
|
||||||
|
@ -176,93 +89,76 @@ public abstract class AbstractUnivariateRealOptimizer
|
||||||
return searchStart;
|
return searchStart;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Compute the objective function value.
|
|
||||||
* @param f objective function
|
|
||||||
* @param point point at which the objective function must be evaluated
|
|
||||||
* @return objective function value at specified point
|
|
||||||
* @exception FunctionEvaluationException if the function cannot be evaluated
|
|
||||||
* or the maximal number of iterations is exceeded
|
|
||||||
* @deprecated in 2.2. Use this {@link #computeObjectiveValue(double)
|
|
||||||
* replacement} instead.
|
|
||||||
*/
|
|
||||||
protected double computeObjectiveValue(final UnivariateRealFunction f,
|
|
||||||
final double point)
|
|
||||||
throws FunctionEvaluationException {
|
|
||||||
if (++evaluations > maxEvaluations) {
|
|
||||||
throw new FunctionEvaluationException(new MaxEvaluationsExceededException(maxEvaluations),
|
|
||||||
point);
|
|
||||||
}
|
|
||||||
return f.value(point);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compute the objective function value.
|
* Compute the objective function value.
|
||||||
*
|
*
|
||||||
* @param point Point at which the objective function must be evaluated.
|
* @param point Point at which the objective function must be evaluated.
|
||||||
* @return the objective function value at specified point.
|
* @return the objective function value at specified point.
|
||||||
* @exception FunctionEvaluationException if the function cannot be evaluated
|
* @throws FunctionEvaluationException if the function cannot be
|
||||||
* or the maximal number of iterations is exceeded.
|
* evaluated.
|
||||||
|
* @throws TooManyEvaluationsException if the maximal number of evaluations
|
||||||
|
* is exceeded.
|
||||||
*/
|
*/
|
||||||
protected double computeObjectiveValue(double point)
|
protected double computeObjectiveValue(double point)
|
||||||
throws FunctionEvaluationException {
|
throws FunctionEvaluationException {
|
||||||
if (++evaluations > maxEvaluations) {
|
try {
|
||||||
resultComputed = false;
|
evaluations.incrementCount();
|
||||||
throw new FunctionEvaluationException(new MaxEvaluationsExceededException(maxEvaluations),
|
} catch (MaxCountExceededException e) {
|
||||||
point);
|
throw new TooManyEvaluationsException(e.getMax());
|
||||||
}
|
}
|
||||||
return function.value(point);
|
return function.value(point);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
/** {@inheritDoc} */
|
||||||
public double optimize(UnivariateRealFunction f, GoalType goal,
|
public UnivariateRealPointValuePair optimize(UnivariateRealFunction f,
|
||||||
double min, double max, double startValue)
|
GoalType goalType,
|
||||||
throws MaxIterationsExceededException, FunctionEvaluationException {
|
double min, double max,
|
||||||
// Initialize.
|
double startValue)
|
||||||
this.searchMin = min;
|
throws FunctionEvaluationException {
|
||||||
this.searchMax = max;
|
|
||||||
this.searchStart = startValue;
|
|
||||||
this.optimizationGoal = goal;
|
|
||||||
this.function = f;
|
|
||||||
|
|
||||||
// Reset.
|
// Reset.
|
||||||
functionValue = Double.NaN;
|
searchMin = min;
|
||||||
evaluations = 0;
|
searchMax = max;
|
||||||
resetIterationsCounter();
|
searchStart = startValue;
|
||||||
|
goal = goalType;
|
||||||
|
function = f;
|
||||||
|
evaluations.resetCount();
|
||||||
|
|
||||||
// Perform computation.
|
// Perform computation.
|
||||||
result = doOptimize();
|
return doOptimize();
|
||||||
resultComputed = true;
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the value at the optimum.
|
|
||||||
*
|
|
||||||
* @param functionValue Value of the objective function at the optimum.
|
|
||||||
*/
|
|
||||||
protected void setFunctionValue(double functionValue) {
|
|
||||||
this.functionValue = functionValue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
/** {@inheritDoc} */
|
||||||
public double optimize(UnivariateRealFunction f, GoalType goal,
|
public UnivariateRealPointValuePair optimize(UnivariateRealFunction f,
|
||||||
double min, double max)
|
GoalType goal,
|
||||||
throws MaxIterationsExceededException, FunctionEvaluationException {
|
double min, double max)
|
||||||
|
throws FunctionEvaluationException {
|
||||||
return optimize(f, goal, min, max, min + 0.5 * (max - min));
|
return optimize(f, goal, min, max, min + 0.5 * (max - min));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public void setConvergenceChecker(ConvergenceChecker<UnivariateRealPointValuePair> checker) {
|
||||||
|
this.checker = checker;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public ConvergenceChecker<UnivariateRealPointValuePair> getConvergenceChecker() {
|
||||||
|
return checker;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method for implementing actual optimization algorithms in derived
|
* Method for implementing actual optimization algorithms in derived
|
||||||
* classes.
|
* classes.
|
||||||
*
|
*
|
||||||
* @return the optimum.
|
* @return the optimum and its corresponding function value.
|
||||||
* @throws MaxIterationsExceededException if the maximum iteration count
|
* @throws TooManyEvaluationsException if the maximal number of evaluations
|
||||||
* is exceeded.
|
* is exceeded.
|
||||||
* @throws FunctionEvaluationException if an error occurs evaluating
|
* @throws FunctionEvaluationException if an error occurs evaluating
|
||||||
* the function.
|
* the function.
|
||||||
*/
|
*/
|
||||||
protected abstract double doOptimize()
|
protected abstract UnivariateRealPointValuePair doOptimize()
|
||||||
throws MaxIterationsExceededException, FunctionEvaluationException;
|
throws FunctionEvaluationException;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,88 @@
|
||||||
|
/*
|
||||||
|
* 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.univariate;
|
||||||
|
|
||||||
|
import org.apache.commons.math.FunctionEvaluationException;
|
||||||
|
import org.apache.commons.math.analysis.UnivariateRealFunction;
|
||||||
|
import org.apache.commons.math.optimization.BaseOptimizer;
|
||||||
|
import org.apache.commons.math.optimization.GoalType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This interface is mainly intended to enforce the internal coherence of
|
||||||
|
* Commons-Math. Users of the API are advised to base their code on
|
||||||
|
* the following interfaces:
|
||||||
|
* <ul>
|
||||||
|
* <li>{@link org.apache.commons.math.optimization.univariate.UnivariateRealOptimizer}</li>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* @param <FUNC> Type of the objective function to be optimized.
|
||||||
|
*
|
||||||
|
* @version $Revision$ $Date$
|
||||||
|
* @since 3.0
|
||||||
|
*/
|
||||||
|
public interface BaseUnivariateRealOptimizer<FUNC extends UnivariateRealFunction>
|
||||||
|
extends BaseOptimizer<UnivariateRealPointValuePair> {
|
||||||
|
/**
|
||||||
|
* Find an optimum in the given interval.
|
||||||
|
*
|
||||||
|
* An optimizer may require that the interval brackets a single optimum.
|
||||||
|
*
|
||||||
|
* @param f Function to optimize.
|
||||||
|
* @param goalType Type of optimization goal: either
|
||||||
|
* {@link GoalType#MAXIMIZE} or {@link GoalType#MINIMIZE}.
|
||||||
|
* @param min Lower bound for the interval.
|
||||||
|
* @param max Upper bound for the interval.
|
||||||
|
* @return a (point, value) pair where the function is optimum.
|
||||||
|
* @throws {@link org.apache.commons.math.exception.TooManyEvaluationsException}
|
||||||
|
* if the maximum evaluation count is exceeded.
|
||||||
|
* @throws {@link org.apache.commons.math.exception.ConvergenceException}
|
||||||
|
* if the optimizer detects a convergence problem.
|
||||||
|
* @throws FunctionEvaluationException if an error occurs evaluating the
|
||||||
|
* function.
|
||||||
|
* @throws IllegalArgumentException if {@code min > max} or the endpoints
|
||||||
|
* do not satisfy the requirements specified by the optimizer.
|
||||||
|
*/
|
||||||
|
UnivariateRealPointValuePair optimize(FUNC f, GoalType goalType,
|
||||||
|
double min, double max)
|
||||||
|
throws FunctionEvaluationException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find an optimum in the given interval, start at startValue.
|
||||||
|
* An optimizer may require that the interval brackets a single optimum.
|
||||||
|
*
|
||||||
|
* @param f Function to optimize.
|
||||||
|
* @param goalType Type of optimization goal: either
|
||||||
|
* {@link GoalType#MAXIMIZE} or {@link GoalType#MINIMIZE}.
|
||||||
|
* @param min Lower bound for the interval.
|
||||||
|
* @param max Upper bound for the interval.
|
||||||
|
* @param startValue Start value to use.
|
||||||
|
* @return a (point, value) pair where the function is optimum.
|
||||||
|
* @throws {@link org.apache.commons.math.exception.TooManyEvaluationsException}
|
||||||
|
* if the maximum evaluation count is exceeded.
|
||||||
|
* @throws {@link org.apache.commons.math.exception.ConvergenceException}
|
||||||
|
* if the optimizer detects a convergence problem.
|
||||||
|
* @throws FunctionEvaluationException if an error occurs evaluating the
|
||||||
|
* function.
|
||||||
|
* @throws IllegalArgumentException if {@code min > max} or the endpoints
|
||||||
|
* do not satisfy the requirements specified by the optimizer.
|
||||||
|
*/
|
||||||
|
UnivariateRealPointValuePair optimize(FUNC f, GoalType goalType,
|
||||||
|
double min, double max,
|
||||||
|
double startValue)
|
||||||
|
throws FunctionEvaluationException;
|
||||||
|
}
|
|
@ -16,9 +16,11 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.commons.math.optimization.univariate;
|
package org.apache.commons.math.optimization.univariate;
|
||||||
|
|
||||||
|
import org.apache.commons.math.util.Incrementor;
|
||||||
import org.apache.commons.math.exception.NotStrictlyPositiveException;
|
import org.apache.commons.math.exception.NotStrictlyPositiveException;
|
||||||
|
import org.apache.commons.math.exception.TooManyEvaluationsException;
|
||||||
|
import org.apache.commons.math.exception.MaxCountExceededException;
|
||||||
import org.apache.commons.math.FunctionEvaluationException;
|
import org.apache.commons.math.FunctionEvaluationException;
|
||||||
import org.apache.commons.math.MaxIterationsExceededException;
|
|
||||||
import org.apache.commons.math.analysis.UnivariateRealFunction;
|
import org.apache.commons.math.analysis.UnivariateRealFunction;
|
||||||
import org.apache.commons.math.optimization.GoalType;
|
import org.apache.commons.math.optimization.GoalType;
|
||||||
|
|
||||||
|
@ -26,6 +28,7 @@ import org.apache.commons.math.optimization.GoalType;
|
||||||
* Provide an interval that brackets a local optimum of a function.
|
* Provide an interval that brackets a local optimum of a function.
|
||||||
* This code is based on a Python implementation (from <em>SciPy</em>,
|
* This code is based on a Python implementation (from <em>SciPy</em>,
|
||||||
* module {@code optimize.py} v0.5).
|
* module {@code optimize.py} v0.5).
|
||||||
|
*
|
||||||
* @version $Revision$ $Date$
|
* @version $Revision$ $Date$
|
||||||
* @since 2.2
|
* @since 2.2
|
||||||
*/
|
*/
|
||||||
|
@ -41,17 +44,9 @@ public class BracketFinder {
|
||||||
*/
|
*/
|
||||||
private final double growLimit;
|
private final double growLimit;
|
||||||
/**
|
/**
|
||||||
* Maximum number of iterations.
|
* Counter for function evaluations.
|
||||||
*/
|
*/
|
||||||
private final int maxIterations;
|
private final Incrementor evaluations = new Incrementor();
|
||||||
/**
|
|
||||||
* Number of iterations.
|
|
||||||
*/
|
|
||||||
private int iterations;
|
|
||||||
/**
|
|
||||||
* Number of function evaluations.
|
|
||||||
*/
|
|
||||||
private int evaluations;
|
|
||||||
/**
|
/**
|
||||||
* Lower bound of the bracket.
|
* Lower bound of the bracket.
|
||||||
*/
|
*/
|
||||||
|
@ -89,20 +84,20 @@ public class BracketFinder {
|
||||||
* Create a bracketing interval finder.
|
* Create a bracketing interval finder.
|
||||||
*
|
*
|
||||||
* @param growLimit Expanding factor.
|
* @param growLimit Expanding factor.
|
||||||
* @param maxIterations Maximum number of iterations allowed for finding
|
* @param maxEvaluations Maximum number of evaluations allowed for finding
|
||||||
* a bracketing interval.
|
* a bracketing interval.
|
||||||
*/
|
*/
|
||||||
public BracketFinder(double growLimit,
|
public BracketFinder(double growLimit,
|
||||||
int maxIterations) {
|
int maxEvaluations) {
|
||||||
if (growLimit <= 0) {
|
if (growLimit <= 0) {
|
||||||
throw new NotStrictlyPositiveException(growLimit);
|
throw new NotStrictlyPositiveException(growLimit);
|
||||||
}
|
}
|
||||||
if (maxIterations <= 0) {
|
if (maxEvaluations <= 0) {
|
||||||
throw new NotStrictlyPositiveException(maxIterations);
|
throw new NotStrictlyPositiveException(maxEvaluations);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.growLimit = growLimit;
|
this.growLimit = growLimit;
|
||||||
this.maxIterations = maxIterations;
|
evaluations.setMaximalCount(maxEvaluations);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -112,7 +107,7 @@ public class BracketFinder {
|
||||||
* @param goal {@link GoalType Goal type}.
|
* @param goal {@link GoalType Goal type}.
|
||||||
* @param xA Initial point.
|
* @param xA Initial point.
|
||||||
* @param xB Initial point.
|
* @param xB Initial point.
|
||||||
* @throws MaxIterationsExceededException if the maximum iteration count
|
* @throws TooManyEvaluationsException if the maximum number of evaluations
|
||||||
* is exceeded.
|
* is exceeded.
|
||||||
* @throws FunctionEvaluationException if an error occurs evaluating
|
* @throws FunctionEvaluationException if an error occurs evaluating
|
||||||
* the function.
|
* the function.
|
||||||
|
@ -121,9 +116,8 @@ public class BracketFinder {
|
||||||
GoalType goal,
|
GoalType goal,
|
||||||
double xA,
|
double xA,
|
||||||
double xB)
|
double xB)
|
||||||
throws MaxIterationsExceededException,
|
throws FunctionEvaluationException {
|
||||||
FunctionEvaluationException {
|
evaluations.resetCount();
|
||||||
reset();
|
|
||||||
final boolean isMinim = goal == GoalType.MINIMIZE;
|
final boolean isMinim = goal == GoalType.MINIMIZE;
|
||||||
|
|
||||||
double fA = eval(func, xA);
|
double fA = eval(func, xA);
|
||||||
|
@ -131,6 +125,7 @@ public class BracketFinder {
|
||||||
if (isMinim ?
|
if (isMinim ?
|
||||||
fA < fB :
|
fA < fB :
|
||||||
fA > fB) {
|
fA > fB) {
|
||||||
|
|
||||||
double tmp = xA;
|
double tmp = xA;
|
||||||
xA = xB;
|
xA = xB;
|
||||||
xB = tmp;
|
xB = tmp;
|
||||||
|
@ -144,10 +139,6 @@ public class BracketFinder {
|
||||||
double fC = eval(func, xC);
|
double fC = eval(func, xC);
|
||||||
|
|
||||||
while (isMinim ? fC < fB : fC > fB) {
|
while (isMinim ? fC < fB : fC > fB) {
|
||||||
if (++iterations > maxIterations) {
|
|
||||||
throw new MaxIterationsExceededException(maxIterations);
|
|
||||||
}
|
|
||||||
|
|
||||||
double tmp1 = (xB - xA) * (fB - fC);
|
double tmp1 = (xB - xA) * (fB - fC);
|
||||||
double tmp2 = (xB - xC) * (fB - fA);
|
double tmp2 = (xB - xC) * (fB - fA);
|
||||||
|
|
||||||
|
@ -187,7 +178,7 @@ public class BracketFinder {
|
||||||
fW > fC) {
|
fW > fC) {
|
||||||
xB = xC;
|
xB = xC;
|
||||||
xC = w;
|
xC = w;
|
||||||
w = xC + GOLD * (xC -xB);
|
w = xC + GOLD * (xC - xB);
|
||||||
fB = fC;
|
fB = fC;
|
||||||
fC =fW;
|
fC =fW;
|
||||||
fW = eval(func, w);
|
fW = eval(func, w);
|
||||||
|
@ -198,37 +189,48 @@ public class BracketFinder {
|
||||||
}
|
}
|
||||||
|
|
||||||
xA = xB;
|
xA = xB;
|
||||||
xB = xC;
|
|
||||||
xC = w;
|
|
||||||
fA = fB;
|
fA = fB;
|
||||||
|
xB = xC;
|
||||||
fB = fC;
|
fB = fC;
|
||||||
|
xC = w;
|
||||||
fC = fW;
|
fC = fW;
|
||||||
}
|
}
|
||||||
|
|
||||||
lo = xA;
|
lo = xA;
|
||||||
mid = xB;
|
|
||||||
hi = xC;
|
|
||||||
fLo = fA;
|
fLo = fA;
|
||||||
|
mid = xB;
|
||||||
fMid = fB;
|
fMid = fB;
|
||||||
|
hi = xC;
|
||||||
fHi = fC;
|
fHi = fC;
|
||||||
|
|
||||||
|
if (lo > hi) {
|
||||||
|
double tmp = lo;
|
||||||
|
lo = hi;
|
||||||
|
hi = tmp;
|
||||||
|
|
||||||
|
tmp = fLo;
|
||||||
|
fLo = fHi;
|
||||||
|
fHi = tmp;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the number of iterations.
|
* @return the number of evalutations.
|
||||||
*/
|
*/
|
||||||
public int getIterations() {
|
public int getMaxEvaluations() {
|
||||||
return iterations;
|
return evaluations.getMaximalCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the number of evalutations.
|
* @return the number of evalutations.
|
||||||
*/
|
*/
|
||||||
public int getEvaluations() {
|
public int getEvaluations() {
|
||||||
return evaluations;
|
return evaluations.getCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the lower bound of the bracket.
|
* @return the lower bound of the bracket.
|
||||||
* @see #getFLow()
|
* @see #getFLo()
|
||||||
*/
|
*/
|
||||||
public double getLo() {
|
public double getLo() {
|
||||||
return lo;
|
return lo;
|
||||||
|
@ -238,7 +240,7 @@ public class BracketFinder {
|
||||||
* Get function value at {@link #getLo()}.
|
* Get function value at {@link #getLo()}.
|
||||||
* @return function value at {@link #getLo()}
|
* @return function value at {@link #getLo()}
|
||||||
*/
|
*/
|
||||||
public double getFLow() {
|
public double getFLo() {
|
||||||
return fLo;
|
return fLo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -278,21 +280,18 @@ public class BracketFinder {
|
||||||
* @param f Function.
|
* @param f Function.
|
||||||
* @param x Argument.
|
* @param x Argument.
|
||||||
* @return {@code f(x)}
|
* @return {@code f(x)}
|
||||||
* @throws FunctionEvaluationException if function cannot be evaluated at x
|
* @throws FunctionEvaluationException if function cannot be evaluated.
|
||||||
|
* @throws TooManyEvaluationsException if the maximal number of evaluations is
|
||||||
|
* exceeded.
|
||||||
*/
|
*/
|
||||||
private double eval(UnivariateRealFunction f,
|
private double eval(UnivariateRealFunction f,
|
||||||
double x)
|
double x)
|
||||||
throws FunctionEvaluationException {
|
throws FunctionEvaluationException {
|
||||||
|
try {
|
||||||
++evaluations;
|
evaluations.incrementCount();
|
||||||
|
} catch (MaxCountExceededException e) {
|
||||||
|
throw new TooManyEvaluationsException(e.getMax());
|
||||||
|
}
|
||||||
return f.value(x);
|
return f.value(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Reset internal state.
|
|
||||||
*/
|
|
||||||
private void reset() {
|
|
||||||
iterations = 0;
|
|
||||||
evaluations = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,16 +17,28 @@
|
||||||
package org.apache.commons.math.optimization.univariate;
|
package org.apache.commons.math.optimization.univariate;
|
||||||
|
|
||||||
import org.apache.commons.math.FunctionEvaluationException;
|
import org.apache.commons.math.FunctionEvaluationException;
|
||||||
import org.apache.commons.math.MaxIterationsExceededException;
|
import org.apache.commons.math.util.MathUtils;
|
||||||
import org.apache.commons.math.exception.NotStrictlyPositiveException;
|
|
||||||
import org.apache.commons.math.optimization.GoalType;
|
|
||||||
import org.apache.commons.math.util.FastMath;
|
import org.apache.commons.math.util.FastMath;
|
||||||
|
import org.apache.commons.math.exception.DimensionMismatchException;
|
||||||
|
import org.apache.commons.math.exception.NumberIsTooSmallException;
|
||||||
|
import org.apache.commons.math.exception.NotStrictlyPositiveException;
|
||||||
|
import org.apache.commons.math.exception.MathUnsupportedOperationException;
|
||||||
|
import org.apache.commons.math.optimization.ConvergenceChecker;
|
||||||
|
import org.apache.commons.math.optimization.AbstractConvergenceChecker;
|
||||||
|
import org.apache.commons.math.optimization.GoalType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implements Richard Brent's algorithm (from his book "Algorithms for
|
* Implements Richard Brent's algorithm (from his book "Algorithms for
|
||||||
* Minimization without Derivatives", p. 79) for finding minima of real
|
* Minimization without Derivatives", p. 79) for finding minima of real
|
||||||
* univariate functions. This implementation is an adaptation partly
|
* univariate functions. This implementation is an adaptation partly
|
||||||
* based on the Python code from SciPy (module "optimize.py" v0.5).
|
* based on the Python code from SciPy (module "optimize.py" v0.5).
|
||||||
|
* If the function is defined on some interval {@code (lo, hi)}, then
|
||||||
|
* this method finds an approximation {@code x} to the point at which
|
||||||
|
* the function attains its minimum.
|
||||||
|
* <br/>
|
||||||
|
* The user is responsible for calling {@link
|
||||||
|
* #setConvergenceChecker(ConvergenceChecker) ConvergenceChecker}
|
||||||
|
* prior to using the optimizer.
|
||||||
*
|
*
|
||||||
* @version $Revision$ $Date$
|
* @version $Revision$ $Date$
|
||||||
* @since 2.0
|
* @since 2.0
|
||||||
|
@ -38,57 +50,105 @@ public class BrentOptimizer extends AbstractUnivariateRealOptimizer {
|
||||||
private static final double GOLDEN_SECTION = 0.5 * (3 - FastMath.sqrt(5));
|
private static final double GOLDEN_SECTION = 0.5 * (3 - FastMath.sqrt(5));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a solver.
|
* Convergence checker that implements the original stopping criterion
|
||||||
|
* of Brent's algorithm.
|
||||||
|
* {@code abs} and {@code rel} define a tolerance
|
||||||
|
* {@code tol = rel |x| + abs}. {@code rel} should be no smaller than
|
||||||
|
* <em>2 macheps</em> and preferably not much less than <em>sqrt(macheps)</em>,
|
||||||
|
* where <em>macheps</em> is the relative machine precision. {@code abs} must
|
||||||
|
* be positive.
|
||||||
|
*
|
||||||
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
public BrentOptimizer() {
|
public static class BrentConvergenceChecker
|
||||||
setMaxEvaluations(1000);
|
extends AbstractConvergenceChecker<UnivariateRealPointValuePair> {
|
||||||
setMaximalIterationCount(100);
|
/**
|
||||||
setAbsoluteAccuracy(1e-11);
|
* Minimum relative tolerance.
|
||||||
setRelativeAccuracy(1e-9);
|
*/
|
||||||
}
|
private static final double MIN_RELATIVE_TOLERANCE = 2 * FastMath.ulp(1d);
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
/**
|
||||||
protected double doOptimize()
|
* Build an instance with specified thresholds.
|
||||||
throws MaxIterationsExceededException, FunctionEvaluationException {
|
*
|
||||||
return localMin(getGoalType() == GoalType.MINIMIZE,
|
* @param rel Relative tolerance threshold
|
||||||
getMin(), getStartValue(), getMax(),
|
* @param abs Absolute tolerance threshold
|
||||||
getRelativeAccuracy(), getAbsoluteAccuracy());
|
*/
|
||||||
|
public BrentConvergenceChecker(final double rel,
|
||||||
|
final double abs) {
|
||||||
|
super(rel, abs);
|
||||||
|
|
||||||
|
if (rel < MIN_RELATIVE_TOLERANCE) {
|
||||||
|
throw new NumberIsTooSmallException(rel, MIN_RELATIVE_TOLERANCE, true);
|
||||||
|
}
|
||||||
|
if (abs <= 0) {
|
||||||
|
throw new NotStrictlyPositiveException(abs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convergence criterion.
|
||||||
|
*
|
||||||
|
* @param iteration Current iteration.
|
||||||
|
* @param points Points used for checking the stopping criterion. The list
|
||||||
|
* must contain 3 points (in the following order):
|
||||||
|
* <ul>
|
||||||
|
* <li>the lower end of the current interval</li>
|
||||||
|
* <li>the current best point</li>
|
||||||
|
* <li>the higher end of the current interval</li>
|
||||||
|
* </ul>
|
||||||
|
* @return {@code true} if the stopping criterion is satisfied.
|
||||||
|
* @throws DimensionMismatchException if the length of the {@code points}
|
||||||
|
* list is not equal to 3.
|
||||||
|
*/
|
||||||
|
public boolean converged(final int iteration,
|
||||||
|
final UnivariateRealPointValuePair ... points) {
|
||||||
|
if (points.length != 3) {
|
||||||
|
throw new DimensionMismatchException(points.length, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
final double a = points[0].getPoint();
|
||||||
|
final double x = points[1].getPoint();
|
||||||
|
final double b = points[2].getPoint();
|
||||||
|
|
||||||
|
final double tol1 = getRelativeThreshold() * FastMath.abs(x) + getAbsoluteThreshold();
|
||||||
|
final double tol2 = 2 * tol1;
|
||||||
|
|
||||||
|
final double m = 0.5 * (a + b);
|
||||||
|
return FastMath.abs(x - m) <= tol2 - 0.5 * (b - a);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find the minimum of the function within the interval {@code (lo, hi)}.
|
* Set the convergence checker.
|
||||||
|
* Since this algorithm requires a specific checker, this method will throw
|
||||||
|
* an {@code UnsupportedOperationexception} if the argument type is not
|
||||||
|
* {@link BrentConvergenceChecker}.
|
||||||
*
|
*
|
||||||
* If the function is defined on the interval {@code (lo, hi)}, then
|
* @throws MathUnsupportedOperationexception if the checker is not an
|
||||||
* this method finds an approximation {@code x} to the point at which
|
* instance of {@link BrentConvergenceChecker}.
|
||||||
* the function attains its minimum.<br/>
|
|
||||||
* {@code t} and {@code eps} define a tolerance {@code tol = eps |x| + t}
|
|
||||||
* and the function is never evaluated at two points closer together than
|
|
||||||
* {@code tol}. {@code eps} should be no smaller than <em>2 macheps</em> and
|
|
||||||
* preferable not much less than <em>sqrt(macheps)</em>, where
|
|
||||||
* <em>macheps</em> is the relative machine precision. {@code t} should be
|
|
||||||
* positive.
|
|
||||||
* @param isMinim {@code true} when minimizing the function.
|
|
||||||
* @param lo Lower bound of the interval.
|
|
||||||
* @param mid Point inside the interval {@code [lo, hi]}.
|
|
||||||
* @param hi Higher bound of the interval.
|
|
||||||
* @param eps Relative accuracy.
|
|
||||||
* @param t Absolute accuracy.
|
|
||||||
* @return the optimum point.
|
|
||||||
* @throws MaxIterationsExceededException if the maximum iteration count
|
|
||||||
* is exceeded.
|
|
||||||
* @throws FunctionEvaluationException if an error occurs evaluating
|
|
||||||
* the function.
|
|
||||||
*/
|
*/
|
||||||
private double localMin(boolean isMinim,
|
@Override
|
||||||
double lo, double mid, double hi,
|
public void setConvergenceChecker(ConvergenceChecker<UnivariateRealPointValuePair> checker) {
|
||||||
double eps, double t)
|
if (checker instanceof BrentConvergenceChecker) {
|
||||||
throws MaxIterationsExceededException, FunctionEvaluationException {
|
super.setConvergenceChecker(checker);
|
||||||
if (eps <= 0) {
|
} else {
|
||||||
throw new NotStrictlyPositiveException(eps);
|
throw new MathUnsupportedOperationException();
|
||||||
}
|
|
||||||
if (t <= 0) {
|
|
||||||
throw new NotStrictlyPositiveException(t);
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** {@inheritDoc} */
|
||||||
|
protected UnivariateRealPointValuePair doOptimize()
|
||||||
|
throws FunctionEvaluationException {
|
||||||
|
final boolean isMinim = (getGoalType() == GoalType.MINIMIZE);
|
||||||
|
final double lo = getMin();
|
||||||
|
final double mid = getStartValue();
|
||||||
|
final double hi = getMax();
|
||||||
|
|
||||||
|
final ConvergenceChecker<UnivariateRealPointValuePair> checker
|
||||||
|
= getConvergenceChecker();
|
||||||
|
final double eps = checker.getRelativeThreshold();
|
||||||
|
final double t = checker.getAbsoluteThreshold();
|
||||||
|
|
||||||
double a;
|
double a;
|
||||||
double b;
|
double b;
|
||||||
if (lo < hi) {
|
if (lo < hi) {
|
||||||
|
@ -111,13 +171,19 @@ public class BrentOptimizer extends AbstractUnivariateRealOptimizer {
|
||||||
double fv = fx;
|
double fv = fx;
|
||||||
double fw = fx;
|
double fw = fx;
|
||||||
|
|
||||||
|
int iter = 0;
|
||||||
while (true) {
|
while (true) {
|
||||||
double m = 0.5 * (a + b);
|
double m = 0.5 * (a + b);
|
||||||
final double tol1 = eps * FastMath.abs(x) + t;
|
final double tol1 = eps * FastMath.abs(x) + t;
|
||||||
final double tol2 = 2 * tol1;
|
final double tol2 = 2 * tol1;
|
||||||
|
|
||||||
// Check stopping criterion.
|
// Check stopping criterion.
|
||||||
if (FastMath.abs(x - m) > tol2 - 0.5 * (b - a)) {
|
// This test will work only if the "checker" is an instance of
|
||||||
|
// "BrentOptimizer.BrentConvergenceChecker".
|
||||||
|
if (!getConvergenceChecker().converged(iter,
|
||||||
|
new UnivariateRealPointValuePair(a, Double.NaN),
|
||||||
|
new UnivariateRealPointValuePair(x, Double.NaN),
|
||||||
|
new UnivariateRealPointValuePair(b, Double.NaN))) {
|
||||||
double p = 0;
|
double p = 0;
|
||||||
double q = 0;
|
double q = 0;
|
||||||
double r = 0;
|
double r = 0;
|
||||||
|
@ -217,11 +283,10 @@ public class BrentOptimizer extends AbstractUnivariateRealOptimizer {
|
||||||
fv = fu;
|
fv = fu;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else { // termination
|
} else { // Termination.
|
||||||
setFunctionValue(isMinim ? fx : -fx);
|
return new UnivariateRealPointValuePair(x, (isMinim ? fx : -fx));
|
||||||
return x;
|
|
||||||
}
|
}
|
||||||
incrementIterationsCounter();
|
++iter;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,211 @@
|
||||||
|
/*
|
||||||
|
* 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.univariate;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Comparator;
|
||||||
|
|
||||||
|
import org.apache.commons.math.FunctionEvaluationException;
|
||||||
|
import org.apache.commons.math.analysis.UnivariateRealFunction;
|
||||||
|
import org.apache.commons.math.exception.MathIllegalStateException;
|
||||||
|
import org.apache.commons.math.exception.ConvergenceException;
|
||||||
|
import org.apache.commons.math.exception.util.LocalizedFormats;
|
||||||
|
import org.apache.commons.math.random.RandomGenerator;
|
||||||
|
import org.apache.commons.math.optimization.GoalType;
|
||||||
|
import org.apache.commons.math.optimization.ConvergenceChecker;
|
||||||
|
import org.apache.commons.math.util.FastMath;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Special implementation of the {@link UnivariateRealOptimizer} interface
|
||||||
|
* adding multi-start features to an existing optimizer.
|
||||||
|
*
|
||||||
|
* This class wraps a classical optimizer to use it several times in
|
||||||
|
* turn with different starting points in order to avoid being trapped
|
||||||
|
* into a local extremum when looking for a global one.
|
||||||
|
*
|
||||||
|
* @param <FUNC> Type of the objective function to be optimized.
|
||||||
|
*
|
||||||
|
* @version $Revision$ $Date$
|
||||||
|
* @since 3.0
|
||||||
|
*/
|
||||||
|
public class MultiStartUnivariateRealOptimizer<FUNC extends UnivariateRealFunction>
|
||||||
|
implements BaseUnivariateRealOptimizer<FUNC> {
|
||||||
|
/** Underlying classical optimizer. */
|
||||||
|
private final BaseUnivariateRealOptimizer<FUNC> optimizer;
|
||||||
|
/** Maximal number of evaluations allowed. */
|
||||||
|
private int maxEvaluations;
|
||||||
|
/** Number of evaluations already performed for all starts. */
|
||||||
|
private int totalEvaluations;
|
||||||
|
/** Number of starts to go. */
|
||||||
|
private int starts;
|
||||||
|
/** Random generator for multi-start. */
|
||||||
|
private RandomGenerator generator;
|
||||||
|
/** Found optima. */
|
||||||
|
private UnivariateRealPointValuePair[] optima;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a multi-start optimizer from a single-start optimizer.
|
||||||
|
*
|
||||||
|
* @param optimizer Single-start optimizer to wrap.
|
||||||
|
* @param starts Number of starts to perform (including the
|
||||||
|
* first one), multi-start is disabled if value is less than or
|
||||||
|
* equal to 1.
|
||||||
|
* @param generator Random generator to use for restarts.
|
||||||
|
*/
|
||||||
|
public MultiStartUnivariateRealOptimizer(final BaseUnivariateRealOptimizer<FUNC> optimizer,
|
||||||
|
final int starts,
|
||||||
|
final RandomGenerator generator) {
|
||||||
|
this.optimizer = optimizer;
|
||||||
|
this.starts = starts;
|
||||||
|
this.generator = generator;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public void setConvergenceChecker(ConvergenceChecker<UnivariateRealPointValuePair> checker) {
|
||||||
|
optimizer.setConvergenceChecker(checker);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public ConvergenceChecker<UnivariateRealPointValuePair> getConvergenceChecker() {
|
||||||
|
return optimizer.getConvergenceChecker();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** {@inheritDoc} */
|
||||||
|
public int getMaxEvaluations() {
|
||||||
|
return maxEvaluations;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** {@inheritDoc} */
|
||||||
|
public int getEvaluations() {
|
||||||
|
return totalEvaluations;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** {@inheritDoc} */
|
||||||
|
public void setMaxEvaluations(int maxEvaluations) {
|
||||||
|
this.maxEvaluations = maxEvaluations;
|
||||||
|
optimizer.setMaxEvaluations(maxEvaluations);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all the optima found during the last call to {@link
|
||||||
|
* #optimize(FUNC,GoalType,double,double) optimize}.
|
||||||
|
* The optimizer stores all the optima found during a set of
|
||||||
|
* restarts. The {@link #optimize(FUNC,GoalType,double,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(FUNC,GoalType,double,double) optimize}
|
||||||
|
* method.
|
||||||
|
* <br/>
|
||||||
|
* The returned array as one element for each start as specified
|
||||||
|
* in the constructor. It is ordered with the results from the
|
||||||
|
* runs that did converge first, sorted from best to worst
|
||||||
|
* objective value (i.e in ascending order if minimizing and in
|
||||||
|
* descending order if maximizing), followed by {@code null} elements
|
||||||
|
* corresponding to the runs that did not converge. This means all
|
||||||
|
* elements will be {@code null} if the {@link
|
||||||
|
* #optimize(FUNC,GoalType,double,double) optimize} method did throw a
|
||||||
|
* {@link ConvergenceException}). This also means that if the first
|
||||||
|
* element is not {@code null}, it is the best point found across all
|
||||||
|
* starts.
|
||||||
|
*
|
||||||
|
* @return an array containing the optima.
|
||||||
|
* @throws MathIllegalStateException if {@link
|
||||||
|
* #optimize(FUNC,GoalType,double,double) optimize} has not been called.
|
||||||
|
*/
|
||||||
|
public UnivariateRealPointValuePair[] getOptima() {
|
||||||
|
if (optima == null) {
|
||||||
|
throw new MathIllegalStateException(LocalizedFormats.NO_OPTIMUM_COMPUTED_YET);
|
||||||
|
}
|
||||||
|
return optima.clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** {@inheritDoc} */
|
||||||
|
public UnivariateRealPointValuePair optimize(final FUNC f,
|
||||||
|
final GoalType goal,
|
||||||
|
final double min, final double max)
|
||||||
|
throws FunctionEvaluationException {
|
||||||
|
|
||||||
|
optima = new UnivariateRealPointValuePair[starts];
|
||||||
|
totalEvaluations = 0;
|
||||||
|
|
||||||
|
// Multi-start loop.
|
||||||
|
for (int i = 0; i < starts; ++i) {
|
||||||
|
try {
|
||||||
|
final double bound1 = (i == 0) ? min : min + generator.nextDouble() * (max - min);
|
||||||
|
final double bound2 = (i == 0) ? max : min + generator.nextDouble() * (max - min);
|
||||||
|
optima[i] = optimizer.optimize(f, goal,
|
||||||
|
FastMath.min(bound1, bound2),
|
||||||
|
FastMath.max(bound1, bound2));
|
||||||
|
} catch (FunctionEvaluationException fee) {
|
||||||
|
optima[i] = null;
|
||||||
|
} catch (ConvergenceException ce) {
|
||||||
|
optima[i] = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
final int usedEvaluations = optimizer.getEvaluations();
|
||||||
|
optimizer.setMaxEvaluations(optimizer.getMaxEvaluations() - usedEvaluations);
|
||||||
|
totalEvaluations += usedEvaluations;
|
||||||
|
}
|
||||||
|
|
||||||
|
sortPairs(goal);
|
||||||
|
|
||||||
|
if (optima[0] == null) {
|
||||||
|
throw new ConvergenceException(LocalizedFormats.NO_CONVERGENCE_WITH_ANY_START_POINT,
|
||||||
|
starts);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the point with the best objective function value.
|
||||||
|
return optima[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** {@inheritDoc} */
|
||||||
|
public UnivariateRealPointValuePair optimize(final FUNC f, final GoalType goalType,
|
||||||
|
final double min, final double max,
|
||||||
|
final double startValue)
|
||||||
|
throws FunctionEvaluationException {
|
||||||
|
// XXX Main code should be here, using "startValue" for the first start.
|
||||||
|
// XXX This method should set "startValue" to min + 0.5 * (max - min)
|
||||||
|
return optimize(f, goalType, min, max);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sort the optima from best to worst, followed by {@code null} elements.
|
||||||
|
*
|
||||||
|
* @param goal Goal type.
|
||||||
|
*/
|
||||||
|
private void sortPairs(final GoalType goal) {
|
||||||
|
Arrays.sort(optima, new Comparator<UnivariateRealPointValuePair>() {
|
||||||
|
public int compare(final UnivariateRealPointValuePair o1,
|
||||||
|
final UnivariateRealPointValuePair o2) {
|
||||||
|
if (o1 == null) {
|
||||||
|
return (o2 == null) ? 0 : 1;
|
||||||
|
} else if (o2 == null) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
final double v1 = o1.getValue();
|
||||||
|
final double v2 = o2.getValue();
|
||||||
|
return (goal == GoalType.MINIMIZE) ?
|
||||||
|
Double.compare(v1, v2) : Double.compare(v2, v1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
/*
|
||||||
|
* 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.univariate;
|
||||||
|
|
||||||
|
import org.apache.commons.math.analysis.UnivariateRealFunction;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface for univariate optimization algorithms.
|
||||||
|
*
|
||||||
|
* @version $Revision$ $Date$
|
||||||
|
* @since 3.0
|
||||||
|
*/
|
||||||
|
public interface UnivariateRealOptimizer
|
||||||
|
extends BaseUnivariateRealOptimizer<UnivariateRealFunction> {}
|
|
@ -0,0 +1,67 @@
|
||||||
|
/*
|
||||||
|
* 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.univariate;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class holds a point and the value of an objective function at this
|
||||||
|
* point.
|
||||||
|
* This is a simple immutable container.
|
||||||
|
*
|
||||||
|
* @version $Revision$ $Date$
|
||||||
|
* @since 3.0
|
||||||
|
*/
|
||||||
|
public class UnivariateRealPointValuePair implements Serializable {
|
||||||
|
/** Serializable version identifier. */
|
||||||
|
private static final long serialVersionUID = 1003888396256744753L;
|
||||||
|
/** Point. */
|
||||||
|
private final double point;
|
||||||
|
/** Value of the objective function at the point. */
|
||||||
|
private final double value;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build a point/objective function value pair.
|
||||||
|
*
|
||||||
|
* @param point Point.
|
||||||
|
* @param value Value of an objective function at the point
|
||||||
|
*/
|
||||||
|
public UnivariateRealPointValuePair(final double point,
|
||||||
|
final double value) {
|
||||||
|
this.point = point;
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the point.
|
||||||
|
*
|
||||||
|
* @return the point.
|
||||||
|
*/
|
||||||
|
public double getPoint() {
|
||||||
|
return point;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the value of the objective function.
|
||||||
|
*
|
||||||
|
* @return the stored value of the objective function.
|
||||||
|
*/
|
||||||
|
public double getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
|
@ -51,6 +51,17 @@ The <action> type attribute can be add,update,fix,remove.
|
||||||
with a new-line in the release notes. (These spaces are ignored when displaying HTML).
|
with a new-line in the release notes. (These spaces are ignored when displaying HTML).
|
||||||
If the output is not quite correct, check for invisible trailing spaces!
|
If the output is not quite correct, check for invisible trailing spaces!
|
||||||
-->
|
-->
|
||||||
|
<release version="3.0" date="TBD" description="TBD">
|
||||||
|
<action dev="erans" type="update" issue="MATH-397">
|
||||||
|
Removed methods referring to the concept of "iteration".
|
||||||
|
Removed interface methods to access the number of evaluations of the
|
||||||
|
gradient and Jacobian.
|
||||||
|
Added new "Incrementor" utility to be used as a bounded counter for
|
||||||
|
objective function evaluations.
|
||||||
|
Removed all references to "OptimizationException" (replaced by
|
||||||
|
"ConvergenceException").
|
||||||
|
</action>
|
||||||
|
</release>
|
||||||
<release version="2.2" date="TBD" description="TBD">
|
<release version="2.2" date="TBD" description="TBD">
|
||||||
<action dev="luc" type="fix" issue="MATH-375" due-to="Bill Rossi">
|
<action dev="luc" type="fix" issue="MATH-375" due-to="Bill Rossi">
|
||||||
Added faster and more accurate version of traditional mathematical functions in a FastMath
|
Added faster and more accurate version of traditional mathematical functions in a FastMath
|
||||||
|
|
|
@ -39,7 +39,7 @@ import org.junit.Test;
|
||||||
public class MultiStartDifferentiableMultivariateRealOptimizerTest {
|
public class MultiStartDifferentiableMultivariateRealOptimizerTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCircleFitting() throws FunctionEvaluationException, OptimizationException {
|
public void testCircleFitting() throws FunctionEvaluationException {
|
||||||
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);
|
||||||
|
@ -55,14 +55,10 @@ public class MultiStartDifferentiableMultivariateRealOptimizerTest {
|
||||||
new GaussianRandomGenerator(g));
|
new GaussianRandomGenerator(g));
|
||||||
MultiStartDifferentiableMultivariateRealOptimizer optimizer =
|
MultiStartDifferentiableMultivariateRealOptimizer optimizer =
|
||||||
new MultiStartDifferentiableMultivariateRealOptimizer(underlying, 10, generator);
|
new MultiStartDifferentiableMultivariateRealOptimizer(underlying, 10, generator);
|
||||||
optimizer.setMaxIterations(100);
|
|
||||||
assertEquals(100, optimizer.getMaxIterations());
|
|
||||||
optimizer.setMaxEvaluations(100);
|
optimizer.setMaxEvaluations(100);
|
||||||
assertEquals(100, optimizer.getMaxEvaluations());
|
assertEquals(100, optimizer.getMaxEvaluations());
|
||||||
optimizer.setConvergenceChecker(new SimpleScalarValueChecker(1.0e-10, 1.0e-10));
|
optimizer.setConvergenceChecker(new SimpleScalarValueChecker(1.0e-10, 1.0e-10));
|
||||||
BrentSolver solver = new BrentSolver();
|
BrentSolver solver = new BrentSolver();
|
||||||
solver.setAbsoluteAccuracy(1.0e-13);
|
|
||||||
solver.setRelativeAccuracy(1.0e-15);
|
|
||||||
RealPointValuePair optimum =
|
RealPointValuePair optimum =
|
||||||
optimizer.optimize(circle, GoalType.MINIMIZE, new double[] { 98.680, 47.345 });
|
optimizer.optimize(circle, GoalType.MINIMIZE, new double[] { 98.680, 47.345 });
|
||||||
RealPointValuePair[] optima = optimizer.getOptima();
|
RealPointValuePair[] optima = optimizer.getOptima();
|
||||||
|
@ -72,12 +68,8 @@ public class MultiStartDifferentiableMultivariateRealOptimizerTest {
|
||||||
assertEquals(96.075902096, center.x, 1.0e-8);
|
assertEquals(96.075902096, center.x, 1.0e-8);
|
||||||
assertEquals(48.135167894, center.y, 1.0e-8);
|
assertEquals(48.135167894, center.y, 1.0e-8);
|
||||||
}
|
}
|
||||||
assertTrue(optimizer.getGradientEvaluations() > 650);
|
|
||||||
assertTrue(optimizer.getGradientEvaluations() < 700);
|
|
||||||
assertTrue(optimizer.getEvaluations() > 70);
|
assertTrue(optimizer.getEvaluations() > 70);
|
||||||
assertTrue(optimizer.getEvaluations() < 90);
|
assertTrue(optimizer.getEvaluations() < 90);
|
||||||
assertTrue(optimizer.getIterations() > 70);
|
|
||||||
assertTrue(optimizer.getIterations() < 90);
|
|
||||||
assertEquals(3.1267527, optimum.getValue(), 1.0e-8);
|
assertEquals(3.1267527, optimum.getValue(), 1.0e-8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,7 +111,6 @@ public class MultiStartDifferentiableMultivariateRealOptimizerTest {
|
||||||
dJdY *= 2;
|
dJdY *= 2;
|
||||||
|
|
||||||
return new double[] { dJdX, dJdY };
|
return new double[] { dJdX, dJdY };
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public double value(double[] variables)
|
public double value(double[] variables)
|
||||||
|
@ -133,9 +124,7 @@ public class MultiStartDifferentiableMultivariateRealOptimizerTest {
|
||||||
double di = point.distance(center) - radius;
|
double di = point.distance(center) - radius;
|
||||||
sum += di * di;
|
sum += di * di;
|
||||||
}
|
}
|
||||||
|
|
||||||
return sum;
|
return sum;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public MultivariateVectorialFunction gradient() {
|
public MultivariateVectorialFunction gradient() {
|
||||||
|
@ -153,7 +142,5 @@ public class MultiStartDifferentiableMultivariateRealOptimizerTest {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@ import static org.junit.Assert.fail;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
||||||
import org.apache.commons.math.FunctionEvaluationException;
|
import org.apache.commons.math.FunctionEvaluationException;
|
||||||
|
import org.apache.commons.math.exception.ConvergenceException;
|
||||||
import org.apache.commons.math.analysis.DifferentiableMultivariateVectorialFunction;
|
import org.apache.commons.math.analysis.DifferentiableMultivariateVectorialFunction;
|
||||||
import org.apache.commons.math.analysis.MultivariateMatrixFunction;
|
import org.apache.commons.math.analysis.MultivariateMatrixFunction;
|
||||||
import org.apache.commons.math.linear.BlockRealMatrix;
|
import org.apache.commons.math.linear.BlockRealMatrix;
|
||||||
|
@ -112,7 +113,7 @@ public class MultiStartDifferentiableMultivariateVectorialOptimizerTest {
|
||||||
MultiStartDifferentiableMultivariateVectorialOptimizer optimizer =
|
MultiStartDifferentiableMultivariateVectorialOptimizer optimizer =
|
||||||
new MultiStartDifferentiableMultivariateVectorialOptimizer(underlyingOptimizer,
|
new MultiStartDifferentiableMultivariateVectorialOptimizer(underlyingOptimizer,
|
||||||
10, generator);
|
10, generator);
|
||||||
optimizer.setMaxIterations(100);
|
optimizer.setMaxEvaluations(100);
|
||||||
optimizer.setConvergenceChecker(new SimpleVectorialValueChecker(1.0e-6, 1.0e-6));
|
optimizer.setConvergenceChecker(new SimpleVectorialValueChecker(1.0e-6, 1.0e-6));
|
||||||
|
|
||||||
// no optima before first optimization attempt
|
// no optima before first optimization attempt
|
||||||
|
@ -134,14 +135,10 @@ public class MultiStartDifferentiableMultivariateVectorialOptimizerTest {
|
||||||
}
|
}
|
||||||
assertTrue(optimizer.getEvaluations() > 20);
|
assertTrue(optimizer.getEvaluations() > 20);
|
||||||
assertTrue(optimizer.getEvaluations() < 50);
|
assertTrue(optimizer.getEvaluations() < 50);
|
||||||
assertTrue(optimizer.getIterations() > 20);
|
assertEquals(100, optimizer.getMaxEvaluations());
|
||||||
assertTrue(optimizer.getIterations() < 50);
|
|
||||||
assertTrue(optimizer.getJacobianEvaluations() > 20);
|
|
||||||
assertTrue(optimizer.getJacobianEvaluations() < 50);
|
|
||||||
assertEquals(100, optimizer.getMaxIterations());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = OptimizationException.class)
|
@Test(expected = ConvergenceException.class)
|
||||||
public void testNoOptimum() throws FunctionEvaluationException, OptimizationException {
|
public void testNoOptimum() throws FunctionEvaluationException, OptimizationException {
|
||||||
DifferentiableMultivariateVectorialOptimizer underlyingOptimizer =
|
DifferentiableMultivariateVectorialOptimizer underlyingOptimizer =
|
||||||
new GaussNewtonOptimizer(true);
|
new GaussNewtonOptimizer(true);
|
||||||
|
@ -152,7 +149,7 @@ public class MultiStartDifferentiableMultivariateVectorialOptimizerTest {
|
||||||
MultiStartDifferentiableMultivariateVectorialOptimizer optimizer =
|
MultiStartDifferentiableMultivariateVectorialOptimizer optimizer =
|
||||||
new MultiStartDifferentiableMultivariateVectorialOptimizer(underlyingOptimizer,
|
new MultiStartDifferentiableMultivariateVectorialOptimizer(underlyingOptimizer,
|
||||||
10, generator);
|
10, generator);
|
||||||
optimizer.setMaxIterations(100);
|
optimizer.setMaxEvaluations(100);
|
||||||
optimizer.setConvergenceChecker(new SimpleVectorialValueChecker(1.0e-6, 1.0e-6));
|
optimizer.setConvergenceChecker(new SimpleVectorialValueChecker(1.0e-6, 1.0e-6));
|
||||||
optimizer.optimize(new DifferentiableMultivariateVectorialFunction() {
|
optimizer.optimize(new DifferentiableMultivariateVectorialFunction() {
|
||||||
public MultivariateMatrixFunction jacobian() {
|
public MultivariateMatrixFunction jacobian() {
|
||||||
|
|
|
@ -48,13 +48,13 @@ public class MultiStartMultivariateRealOptimizerTest {
|
||||||
MultiStartMultivariateRealOptimizer optimizer =
|
MultiStartMultivariateRealOptimizer optimizer =
|
||||||
new MultiStartMultivariateRealOptimizer(underlying, 10, generator);
|
new MultiStartMultivariateRealOptimizer(underlying, 10, generator);
|
||||||
optimizer.setConvergenceChecker(new SimpleScalarValueChecker(-1, 1.0e-3));
|
optimizer.setConvergenceChecker(new SimpleScalarValueChecker(-1, 1.0e-3));
|
||||||
optimizer.setMaxIterations(100);
|
optimizer.setMaxEvaluations(1100);
|
||||||
RealPointValuePair optimum =
|
RealPointValuePair optimum =
|
||||||
optimizer.optimize(rosenbrock, GoalType.MINIMIZE, new double[] { -1.2, 1.0 });
|
optimizer.optimize(rosenbrock, GoalType.MINIMIZE, new double[] { -1.2, 1.0 });
|
||||||
|
|
||||||
assertEquals(rosenbrock.getCount(), optimizer.getEvaluations());
|
assertEquals(rosenbrock.getCount(), optimizer.getEvaluations());
|
||||||
assertTrue(optimizer.getEvaluations() > 20);
|
assertTrue(optimizer.getEvaluations() > 900);
|
||||||
assertTrue(optimizer.getEvaluations() < 250);
|
assertTrue(optimizer.getEvaluations() < 1200);
|
||||||
assertTrue(optimum.getValue() < 8.0e-4);
|
assertTrue(optimum.getValue() < 8.0e-4);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -91,7 +91,7 @@ public class MultiDirectionalTest {
|
||||||
|
|
||||||
MultiDirectional optimizer = new MultiDirectional();
|
MultiDirectional optimizer = new MultiDirectional();
|
||||||
optimizer.setConvergenceChecker(new SimpleScalarValueChecker(1.0e-11, 1.0e-30));
|
optimizer.setConvergenceChecker(new SimpleScalarValueChecker(1.0e-11, 1.0e-30));
|
||||||
optimizer.setMaxIterations(200);
|
optimizer.setMaxEvaluations(200);
|
||||||
optimizer.setStartConfiguration(new double[] { 0.2, 0.2 });
|
optimizer.setStartConfiguration(new double[] { 0.2, 0.2 });
|
||||||
RealPointValuePair optimum;
|
RealPointValuePair optimum;
|
||||||
|
|
||||||
|
@ -146,7 +146,7 @@ public class MultiDirectionalTest {
|
||||||
count = 0;
|
count = 0;
|
||||||
MultiDirectional optimizer = new MultiDirectional();
|
MultiDirectional optimizer = new MultiDirectional();
|
||||||
optimizer.setConvergenceChecker(new SimpleScalarValueChecker(-1, 1.0e-3));
|
optimizer.setConvergenceChecker(new SimpleScalarValueChecker(-1, 1.0e-3));
|
||||||
optimizer.setMaxIterations(100);
|
optimizer.setMaxEvaluations(100);
|
||||||
optimizer.setStartConfiguration(new double[][] {
|
optimizer.setStartConfiguration(new double[][] {
|
||||||
{ -1.2, 1.0 }, { 0.9, 1.2 } , { 3.5, -2.3 }
|
{ -1.2, 1.0 }, { 0.9, 1.2 } , { 3.5, -2.3 }
|
||||||
});
|
});
|
||||||
|
@ -180,7 +180,7 @@ public class MultiDirectionalTest {
|
||||||
count = 0;
|
count = 0;
|
||||||
MultiDirectional optimizer = new MultiDirectional();
|
MultiDirectional optimizer = new MultiDirectional();
|
||||||
optimizer.setConvergenceChecker(new SimpleScalarValueChecker(-1.0, 1.0e-3));
|
optimizer.setConvergenceChecker(new SimpleScalarValueChecker(-1.0, 1.0e-3));
|
||||||
optimizer.setMaxIterations(1000);
|
optimizer.setMaxEvaluations(1000);
|
||||||
RealPointValuePair optimum =
|
RealPointValuePair optimum =
|
||||||
optimizer.optimize(powell, GoalType.MINIMIZE, new double[] { 3.0, -1.0, 0.0, 1.0 });
|
optimizer.optimize(powell, GoalType.MINIMIZE, new double[] { 3.0, -1.0, 0.0, 1.0 });
|
||||||
Assert.assertEquals(count, optimizer.getEvaluations());
|
Assert.assertEquals(count, optimizer.getEvaluations());
|
||||||
|
@ -196,7 +196,6 @@ public class MultiDirectionalTest {
|
||||||
// fails because MultiDirectional.iterateSimplex is looping forever
|
// fails because MultiDirectional.iterateSimplex is looping forever
|
||||||
// the while(true) should be replaced with a convergence check
|
// the while(true) should be replaced with a convergence check
|
||||||
MultiDirectional multiDirectional = new MultiDirectional();
|
MultiDirectional multiDirectional = new MultiDirectional();
|
||||||
multiDirectional.setMaxIterations(100);
|
|
||||||
multiDirectional.setMaxEvaluations(1000);
|
multiDirectional.setMaxEvaluations(1000);
|
||||||
|
|
||||||
final Gaussian2D function = new Gaussian2D(0.0, 0.0, 1.0);
|
final Gaussian2D function = new Gaussian2D(0.0, 0.0, 1.0);
|
||||||
|
|
|
@ -23,315 +23,278 @@ import static org.junit.Assert.assertNull;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
import static org.junit.Assert.fail;
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
import org.apache.commons.math.ConvergenceException;
|
|
||||||
import org.apache.commons.math.FunctionEvaluationException;
|
import org.apache.commons.math.FunctionEvaluationException;
|
||||||
import org.apache.commons.math.MathException;
|
import org.apache.commons.math.exception.TooManyEvaluationsException;
|
||||||
import org.apache.commons.math.MaxEvaluationsExceededException;
|
|
||||||
import org.apache.commons.math.MaxIterationsExceededException;
|
|
||||||
import org.apache.commons.math.analysis.MultivariateRealFunction;
|
import org.apache.commons.math.analysis.MultivariateRealFunction;
|
||||||
import org.apache.commons.math.analysis.MultivariateVectorialFunction;
|
import org.apache.commons.math.analysis.MultivariateVectorialFunction;
|
||||||
import org.apache.commons.math.linear.Array2DRowRealMatrix;
|
import org.apache.commons.math.linear.Array2DRowRealMatrix;
|
||||||
import org.apache.commons.math.linear.RealMatrix;
|
import org.apache.commons.math.linear.RealMatrix;
|
||||||
import org.apache.commons.math.optimization.GoalType;
|
import org.apache.commons.math.optimization.GoalType;
|
||||||
import org.apache.commons.math.optimization.LeastSquaresConverter;
|
import org.apache.commons.math.optimization.LeastSquaresConverter;
|
||||||
import org.apache.commons.math.optimization.OptimizationException;
|
|
||||||
import org.apache.commons.math.optimization.RealPointValuePair;
|
import org.apache.commons.math.optimization.RealPointValuePair;
|
||||||
import org.apache.commons.math.optimization.SimpleRealPointChecker;
|
import org.apache.commons.math.optimization.SimpleRealPointChecker;
|
||||||
import org.apache.commons.math.optimization.SimpleScalarValueChecker;
|
import org.apache.commons.math.optimization.SimpleScalarValueChecker;
|
||||||
import org.apache.commons.math.util.FastMath;
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
public class NelderMeadTest {
|
public class NelderMeadTest {
|
||||||
|
@Test
|
||||||
@Test
|
public void testFunctionEvaluationExceptions() {
|
||||||
public void testFunctionEvaluationExceptions() {
|
MultivariateRealFunction wrong =
|
||||||
MultivariateRealFunction wrong =
|
new MultivariateRealFunction() {
|
||||||
new MultivariateRealFunction() {
|
private static final long serialVersionUID = 4751314470965489371L;
|
||||||
private static final long serialVersionUID = 4751314470965489371L;
|
public double value(double[] x) throws FunctionEvaluationException {
|
||||||
public double value(double[] x) throws FunctionEvaluationException {
|
if (x[0] < 0) {
|
||||||
if (x[0] < 0) {
|
throw new FunctionEvaluationException(x, "{0}", "oops");
|
||||||
throw new FunctionEvaluationException(x, "{0}", "oops");
|
} else if (x[0] > 1) {
|
||||||
} else if (x[0] > 1) {
|
throw new FunctionEvaluationException(new RuntimeException("oops"), x);
|
||||||
throw new FunctionEvaluationException(new RuntimeException("oops"), x);
|
} else {
|
||||||
} else {
|
return x[0] * (1 - x[0]);
|
||||||
return x[0] * (1 - x[0]);
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
};
|
try {
|
||||||
try {
|
NelderMead optimizer = new NelderMead(0.9, 1.9, 0.4, 0.6);
|
||||||
NelderMead optimizer = new NelderMead(0.9, 1.9, 0.4, 0.6);
|
optimizer.optimize(wrong, GoalType.MINIMIZE, new double[] { -1.0 });
|
||||||
optimizer.optimize(wrong, GoalType.MINIMIZE, new double[] { -1.0 });
|
fail("an exception should have been thrown");
|
||||||
fail("an exception should have been thrown");
|
} catch (FunctionEvaluationException ce) {
|
||||||
} catch (FunctionEvaluationException ce) {
|
// expected behavior
|
||||||
// expected behavior
|
assertNull(ce.getCause());
|
||||||
assertNull(ce.getCause());
|
} catch (Exception e) {
|
||||||
} catch (Exception e) {
|
fail("wrong exception caught: " + e.getMessage());
|
||||||
fail("wrong exception caught: " + e.getMessage());
|
}
|
||||||
}
|
try {
|
||||||
try {
|
NelderMead optimizer = new NelderMead(0.9, 1.9, 0.4, 0.6);
|
||||||
NelderMead optimizer = new NelderMead(0.9, 1.9, 0.4, 0.6);
|
optimizer.optimize(wrong, GoalType.MINIMIZE, new double[] { +2.0 });
|
||||||
optimizer.optimize(wrong, GoalType.MINIMIZE, new double[] { +2.0 });
|
fail("an exception should have been thrown");
|
||||||
fail("an exception should have been thrown");
|
} catch (FunctionEvaluationException ce) {
|
||||||
} catch (FunctionEvaluationException ce) {
|
// expected behavior
|
||||||
// expected behavior
|
assertNotNull(ce.getCause());
|
||||||
assertNotNull(ce.getCause());
|
} catch (Exception e) {
|
||||||
} catch (Exception e) {
|
fail("wrong exception caught: " + e.getMessage());
|
||||||
fail("wrong exception caught: " + e.getMessage());
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testMinimizeMaximize()
|
public void testMinimizeMaximize()
|
||||||
throws FunctionEvaluationException, ConvergenceException {
|
throws FunctionEvaluationException {
|
||||||
|
|
||||||
// the following function has 4 local extrema:
|
// the following function has 4 local extrema:
|
||||||
final double xM = -3.841947088256863675365;
|
final double xM = -3.841947088256863675365;
|
||||||
final double yM = -1.391745200270734924416;
|
final double yM = -1.391745200270734924416;
|
||||||
final double xP = 0.2286682237349059125691;
|
final double xP = 0.2286682237349059125691;
|
||||||
final double yP = -yM;
|
final double yP = -yM;
|
||||||
final double valueXmYm = 0.2373295333134216789769; // local maximum
|
final double valueXmYm = 0.2373295333134216789769; // local maximum
|
||||||
final double valueXmYp = -valueXmYm; // local minimum
|
final double valueXmYp = -valueXmYm; // local minimum
|
||||||
final double valueXpYm = -0.7290400707055187115322; // global minimum
|
final double valueXpYm = -0.7290400707055187115322; // global minimum
|
||||||
final double valueXpYp = -valueXpYm; // global maximum
|
final double valueXpYp = -valueXpYm; // global maximum
|
||||||
MultivariateRealFunction fourExtrema = new MultivariateRealFunction() {
|
MultivariateRealFunction fourExtrema = new MultivariateRealFunction() {
|
||||||
private static final long serialVersionUID = -7039124064449091152L;
|
private static final long serialVersionUID = -7039124064449091152L;
|
||||||
public double value(double[] variables) throws FunctionEvaluationException {
|
public double value(double[] variables) throws FunctionEvaluationException {
|
||||||
final double x = variables[0];
|
final double x = variables[0];
|
||||||
final double y = variables[1];
|
final double y = variables[1];
|
||||||
return ((x == 0) || (y == 0)) ? 0 : (FastMath.atan(x) * FastMath.atan(x + 2) * FastMath.atan(y) * FastMath.atan(y) / (x * y));
|
return ((x == 0) || (y == 0)) ? 0 : (Math.atan(x) * Math.atan(x + 2) * Math.atan(y) * Math.atan(y) / (x * y));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
NelderMead optimizer = new NelderMead();
|
NelderMead optimizer = new NelderMead();
|
||||||
optimizer.setConvergenceChecker(new SimpleScalarValueChecker(1.0e-10, 1.0e-30));
|
optimizer.setConvergenceChecker(new SimpleScalarValueChecker(1.0e-10, 1.0e-30));
|
||||||
optimizer.setMaxIterations(100);
|
optimizer.setMaxEvaluations(100);
|
||||||
optimizer.setStartConfiguration(new double[] { 0.2, 0.2 });
|
optimizer.setStartConfiguration(new double[] { 0.2, 0.2 });
|
||||||
RealPointValuePair optimum;
|
RealPointValuePair optimum;
|
||||||
|
|
||||||
// minimization
|
// minimization
|
||||||
optimum = optimizer.optimize(fourExtrema, GoalType.MINIMIZE, new double[] { -3.0, 0 });
|
optimum = optimizer.optimize(fourExtrema, GoalType.MINIMIZE, new double[] { -3.0, 0 });
|
||||||
assertEquals(xM, optimum.getPoint()[0], 2.0e-7);
|
assertEquals(xM, optimum.getPoint()[0], 2.0e-7);
|
||||||
assertEquals(yP, optimum.getPoint()[1], 2.0e-5);
|
assertEquals(yP, optimum.getPoint()[1], 2.0e-5);
|
||||||
assertEquals(valueXmYp, optimum.getValue(), 6.0e-12);
|
assertEquals(valueXmYp, optimum.getValue(), 6.0e-12);
|
||||||
assertTrue(optimizer.getEvaluations() > 60);
|
assertTrue(optimizer.getEvaluations() > 60);
|
||||||
assertTrue(optimizer.getEvaluations() < 90);
|
assertTrue(optimizer.getEvaluations() < 90);
|
||||||
|
|
||||||
optimum = optimizer.optimize(fourExtrema, GoalType.MINIMIZE, new double[] { +1, 0 });
|
optimum = optimizer.optimize(fourExtrema, GoalType.MINIMIZE, new double[] { +1, 0 });
|
||||||
assertEquals(xP, optimum.getPoint()[0], 5.0e-6);
|
assertEquals(xP, optimum.getPoint()[0], 5.0e-6);
|
||||||
assertEquals(yM, optimum.getPoint()[1], 6.0e-6);
|
assertEquals(yM, optimum.getPoint()[1], 6.0e-6);
|
||||||
assertEquals(valueXpYm, optimum.getValue(), 1.0e-11);
|
assertEquals(valueXpYm, optimum.getValue(), 1.0e-11);
|
||||||
assertTrue(optimizer.getEvaluations() > 60);
|
assertTrue(optimizer.getEvaluations() > 60);
|
||||||
assertTrue(optimizer.getEvaluations() < 90);
|
assertTrue(optimizer.getEvaluations() < 90);
|
||||||
|
|
||||||
// maximization
|
// maximization
|
||||||
optimum = optimizer.optimize(fourExtrema, GoalType.MAXIMIZE, new double[] { -3.0, 0.0 });
|
optimum = optimizer.optimize(fourExtrema, GoalType.MAXIMIZE, new double[] { -3.0, 0.0 });
|
||||||
assertEquals(xM, optimum.getPoint()[0], 1.0e-5);
|
assertEquals(xM, optimum.getPoint()[0], 1.0e-5);
|
||||||
assertEquals(yM, optimum.getPoint()[1], 3.0e-6);
|
assertEquals(yM, optimum.getPoint()[1], 3.0e-6);
|
||||||
assertEquals(valueXmYm, optimum.getValue(), 3.0e-12);
|
assertEquals(valueXmYm, optimum.getValue(), 3.0e-12);
|
||||||
assertTrue(optimizer.getEvaluations() > 60);
|
assertTrue(optimizer.getEvaluations() > 60);
|
||||||
assertTrue(optimizer.getEvaluations() < 90);
|
assertTrue(optimizer.getEvaluations() < 90);
|
||||||
|
|
||||||
optimum = optimizer.optimize(fourExtrema, GoalType.MAXIMIZE, new double[] { +1, 0 });
|
optimum = optimizer.optimize(fourExtrema, GoalType.MAXIMIZE, new double[] { +1, 0 });
|
||||||
assertEquals(xP, optimum.getPoint()[0], 4.0e-6);
|
assertEquals(xP, optimum.getPoint()[0], 4.0e-6);
|
||||||
assertEquals(yP, optimum.getPoint()[1], 5.0e-6);
|
assertEquals(yP, optimum.getPoint()[1], 5.0e-6);
|
||||||
assertEquals(valueXpYp, optimum.getValue(), 7.0e-12);
|
assertEquals(valueXpYp, optimum.getValue(), 7.0e-12);
|
||||||
assertTrue(optimizer.getEvaluations() > 60);
|
assertTrue(optimizer.getEvaluations() > 60);
|
||||||
assertTrue(optimizer.getEvaluations() < 90);
|
assertTrue(optimizer.getEvaluations() < 90);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
@Test
|
||||||
|
public void testRosenbrock()
|
||||||
|
throws FunctionEvaluationException {
|
||||||
|
|
||||||
@Test
|
Rosenbrock rosenbrock = new Rosenbrock();
|
||||||
public void testRosenbrock()
|
NelderMead optimizer = new NelderMead();
|
||||||
throws FunctionEvaluationException, ConvergenceException {
|
optimizer.setConvergenceChecker(new SimpleScalarValueChecker(-1, 1.0e-3));
|
||||||
|
optimizer.setMaxEvaluations(100);
|
||||||
|
optimizer.setStartConfiguration(new double[][] {
|
||||||
|
{ -1.2, 1.0 }, { 0.9, 1.2 } , { 3.5, -2.3 }
|
||||||
|
});
|
||||||
|
RealPointValuePair optimum =
|
||||||
|
optimizer.optimize(rosenbrock, GoalType.MINIMIZE, new double[] { -1.2, 1.0 });
|
||||||
|
|
||||||
Rosenbrock rosenbrock = new Rosenbrock();
|
assertEquals(rosenbrock.getCount(), optimizer.getEvaluations());
|
||||||
NelderMead optimizer = new NelderMead();
|
assertTrue(optimizer.getEvaluations() > 40);
|
||||||
optimizer.setConvergenceChecker(new SimpleScalarValueChecker(-1, 1.0e-3));
|
assertTrue(optimizer.getEvaluations() < 50);
|
||||||
optimizer.setMaxIterations(100);
|
assertTrue(optimum.getValue() < 8.0e-4);
|
||||||
optimizer.setStartConfiguration(new double[][] {
|
}
|
||||||
{ -1.2, 1.0 }, { 0.9, 1.2 } , { 3.5, -2.3 }
|
|
||||||
});
|
|
||||||
RealPointValuePair optimum =
|
|
||||||
optimizer.optimize(rosenbrock, GoalType.MINIMIZE, new double[] { -1.2, 1.0 });
|
|
||||||
|
|
||||||
assertEquals(rosenbrock.getCount(), optimizer.getEvaluations());
|
@Test
|
||||||
assertTrue(optimizer.getEvaluations() > 40);
|
public void testPowell()
|
||||||
assertTrue(optimizer.getEvaluations() < 50);
|
throws FunctionEvaluationException {
|
||||||
assertTrue(optimum.getValue() < 8.0e-4);
|
|
||||||
|
|
||||||
}
|
Powell powell = new Powell();
|
||||||
|
NelderMead optimizer = new NelderMead();
|
||||||
|
optimizer.setConvergenceChecker(new SimpleScalarValueChecker(-1.0, 1.0e-3));
|
||||||
|
optimizer.setMaxEvaluations(200);
|
||||||
|
RealPointValuePair optimum =
|
||||||
|
optimizer.optimize(powell, GoalType.MINIMIZE, new double[] { 3.0, -1.0, 0.0, 1.0 });
|
||||||
|
assertEquals(powell.getCount(), optimizer.getEvaluations());
|
||||||
|
assertTrue(optimizer.getEvaluations() > 110);
|
||||||
|
assertTrue(optimizer.getEvaluations() < 130);
|
||||||
|
assertTrue(optimum.getValue() < 2.0e-3);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testPowell()
|
public void testLeastSquares1()
|
||||||
throws FunctionEvaluationException, ConvergenceException {
|
throws FunctionEvaluationException {
|
||||||
|
|
||||||
Powell powell = new Powell();
|
final RealMatrix factors =
|
||||||
NelderMead optimizer = new NelderMead();
|
new Array2DRowRealMatrix(new double[][] {
|
||||||
optimizer.setConvergenceChecker(new SimpleScalarValueChecker(-1.0, 1.0e-3));
|
{ 1.0, 0.0 },
|
||||||
optimizer.setMaxIterations(200);
|
{ 0.0, 1.0 }
|
||||||
RealPointValuePair optimum =
|
}, false);
|
||||||
optimizer.optimize(powell, GoalType.MINIMIZE, new double[] { 3.0, -1.0, 0.0, 1.0 });
|
LeastSquaresConverter ls = new LeastSquaresConverter(new MultivariateVectorialFunction() {
|
||||||
assertEquals(powell.getCount(), optimizer.getEvaluations());
|
public double[] value(double[] variables) {
|
||||||
assertTrue(optimizer.getEvaluations() > 110);
|
return factors.operate(variables);
|
||||||
assertTrue(optimizer.getEvaluations() < 130);
|
}
|
||||||
assertTrue(optimum.getValue() < 2.0e-3);
|
}, new double[] { 2.0, -3.0 });
|
||||||
|
NelderMead optimizer = new NelderMead();
|
||||||
|
optimizer.setConvergenceChecker(new SimpleScalarValueChecker(-1.0, 1.0e-6));
|
||||||
|
optimizer.setMaxEvaluations(200);
|
||||||
|
RealPointValuePair optimum =
|
||||||
|
optimizer.optimize(ls, GoalType.MINIMIZE, new double[] { 10.0, 10.0 });
|
||||||
|
assertEquals( 2.0, optimum.getPointRef()[0], 3.0e-5);
|
||||||
|
assertEquals(-3.0, optimum.getPointRef()[1], 4.0e-4);
|
||||||
|
assertTrue(optimizer.getEvaluations() > 60);
|
||||||
|
assertTrue(optimizer.getEvaluations() < 80);
|
||||||
|
assertTrue(optimum.getValue() < 1.0e-6);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
@Test
|
||||||
|
public void testLeastSquares2()
|
||||||
|
throws FunctionEvaluationException {
|
||||||
|
|
||||||
@Test
|
final RealMatrix factors =
|
||||||
public void testLeastSquares1()
|
new Array2DRowRealMatrix(new double[][] {
|
||||||
throws FunctionEvaluationException, ConvergenceException {
|
{ 1.0, 0.0 },
|
||||||
|
{ 0.0, 1.0 }
|
||||||
|
}, false);
|
||||||
|
LeastSquaresConverter ls = new LeastSquaresConverter(new MultivariateVectorialFunction() {
|
||||||
|
public double[] value(double[] variables) {
|
||||||
|
return factors.operate(variables);
|
||||||
|
}
|
||||||
|
}, new double[] { 2.0, -3.0 }, new double[] { 10.0, 0.1 });
|
||||||
|
NelderMead optimizer = new NelderMead();
|
||||||
|
optimizer.setConvergenceChecker(new SimpleScalarValueChecker(-1.0, 1.0e-6));
|
||||||
|
optimizer.setMaxEvaluations(200);
|
||||||
|
RealPointValuePair optimum =
|
||||||
|
optimizer.optimize(ls, GoalType.MINIMIZE, new double[] { 10.0, 10.0 });
|
||||||
|
assertEquals( 2.0, optimum.getPointRef()[0], 5.0e-5);
|
||||||
|
assertEquals(-3.0, optimum.getPointRef()[1], 8.0e-4);
|
||||||
|
assertTrue(optimizer.getEvaluations() > 60);
|
||||||
|
assertTrue(optimizer.getEvaluations() < 80);
|
||||||
|
assertTrue(optimum.getValue() < 1.0e-6);
|
||||||
|
}
|
||||||
|
|
||||||
final RealMatrix factors =
|
@Test
|
||||||
new Array2DRowRealMatrix(new double[][] {
|
public void testLeastSquares3()
|
||||||
{ 1.0, 0.0 },
|
throws FunctionEvaluationException {
|
||||||
{ 0.0, 1.0 }
|
|
||||||
}, false);
|
|
||||||
LeastSquaresConverter ls = new LeastSquaresConverter(new MultivariateVectorialFunction() {
|
|
||||||
public double[] value(double[] variables) {
|
|
||||||
return factors.operate(variables);
|
|
||||||
}
|
|
||||||
}, new double[] { 2.0, -3.0 });
|
|
||||||
NelderMead optimizer = new NelderMead();
|
|
||||||
optimizer.setConvergenceChecker(new SimpleScalarValueChecker(-1.0, 1.0e-6));
|
|
||||||
optimizer.setMaxIterations(200);
|
|
||||||
RealPointValuePair optimum =
|
|
||||||
optimizer.optimize(ls, GoalType.MINIMIZE, new double[] { 10.0, 10.0 });
|
|
||||||
assertEquals( 2.0, optimum.getPointRef()[0], 3.0e-5);
|
|
||||||
assertEquals(-3.0, optimum.getPointRef()[1], 4.0e-4);
|
|
||||||
assertTrue(optimizer.getEvaluations() > 60);
|
|
||||||
assertTrue(optimizer.getEvaluations() < 80);
|
|
||||||
assertTrue(optimum.getValue() < 1.0e-6);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
final RealMatrix factors =
|
||||||
public void testLeastSquares2()
|
new Array2DRowRealMatrix(new double[][] {
|
||||||
throws FunctionEvaluationException, ConvergenceException {
|
{ 1.0, 0.0 },
|
||||||
|
{ 0.0, 1.0 }
|
||||||
|
}, false);
|
||||||
|
LeastSquaresConverter ls = new LeastSquaresConverter(new MultivariateVectorialFunction() {
|
||||||
|
public double[] value(double[] variables) {
|
||||||
|
return factors.operate(variables);
|
||||||
|
}
|
||||||
|
}, new double[] { 2.0, -3.0 }, new Array2DRowRealMatrix(new double [][] {
|
||||||
|
{ 1.0, 1.2 }, { 1.2, 2.0 }
|
||||||
|
}));
|
||||||
|
NelderMead optimizer = new NelderMead();
|
||||||
|
optimizer.setConvergenceChecker(new SimpleScalarValueChecker(-1.0, 1.0e-6));
|
||||||
|
optimizer.setMaxEvaluations(200);
|
||||||
|
RealPointValuePair optimum =
|
||||||
|
optimizer.optimize(ls, GoalType.MINIMIZE, new double[] { 10.0, 10.0 });
|
||||||
|
assertEquals( 2.0, optimum.getPointRef()[0], 2.0e-3);
|
||||||
|
assertEquals(-3.0, optimum.getPointRef()[1], 8.0e-4);
|
||||||
|
assertTrue(optimizer.getEvaluations() > 60);
|
||||||
|
assertTrue(optimizer.getEvaluations() < 80);
|
||||||
|
assertTrue(optimum.getValue() < 1.0e-6);
|
||||||
|
}
|
||||||
|
|
||||||
final RealMatrix factors =
|
@Test(expected = TooManyEvaluationsException.class)
|
||||||
new Array2DRowRealMatrix(new double[][] {
|
public void testMaxIterations() throws FunctionEvaluationException {
|
||||||
{ 1.0, 0.0 },
|
Powell powell = new Powell();
|
||||||
{ 0.0, 1.0 }
|
NelderMead optimizer = new NelderMead();
|
||||||
}, false);
|
optimizer.setConvergenceChecker(new SimpleScalarValueChecker(-1.0, 1.0e-3));
|
||||||
LeastSquaresConverter ls = new LeastSquaresConverter(new MultivariateVectorialFunction() {
|
optimizer.setMaxEvaluations(20);
|
||||||
public double[] value(double[] variables) {
|
optimizer.optimize(powell, GoalType.MINIMIZE, new double[] { 3.0, -1.0, 0.0, 1.0 });
|
||||||
return factors.operate(variables);
|
}
|
||||||
}
|
|
||||||
}, new double[] { 2.0, -3.0 }, new double[] { 10.0, 0.1 });
|
|
||||||
NelderMead optimizer = new NelderMead();
|
|
||||||
optimizer.setConvergenceChecker(new SimpleScalarValueChecker(-1.0, 1.0e-6));
|
|
||||||
optimizer.setMaxIterations(200);
|
|
||||||
RealPointValuePair optimum =
|
|
||||||
optimizer.optimize(ls, GoalType.MINIMIZE, new double[] { 10.0, 10.0 });
|
|
||||||
assertEquals( 2.0, optimum.getPointRef()[0], 5.0e-5);
|
|
||||||
assertEquals(-3.0, optimum.getPointRef()[1], 8.0e-4);
|
|
||||||
assertTrue(optimizer.getEvaluations() > 60);
|
|
||||||
assertTrue(optimizer.getEvaluations() < 80);
|
|
||||||
assertTrue(optimum.getValue() < 1.0e-6);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
private static class Rosenbrock implements MultivariateRealFunction {
|
||||||
public void testLeastSquares3()
|
private int count;
|
||||||
throws FunctionEvaluationException, ConvergenceException {
|
|
||||||
|
|
||||||
final RealMatrix factors =
|
public Rosenbrock() {
|
||||||
new Array2DRowRealMatrix(new double[][] {
|
count = 0;
|
||||||
{ 1.0, 0.0 },
|
}
|
||||||
{ 0.0, 1.0 }
|
|
||||||
}, false);
|
|
||||||
LeastSquaresConverter ls = new LeastSquaresConverter(new MultivariateVectorialFunction() {
|
|
||||||
public double[] value(double[] variables) {
|
|
||||||
return factors.operate(variables);
|
|
||||||
}
|
|
||||||
}, new double[] { 2.0, -3.0 }, new Array2DRowRealMatrix(new double [][] {
|
|
||||||
{ 1.0, 1.2 }, { 1.2, 2.0 }
|
|
||||||
}));
|
|
||||||
NelderMead optimizer = new NelderMead();
|
|
||||||
optimizer.setConvergenceChecker(new SimpleScalarValueChecker(-1.0, 1.0e-6));
|
|
||||||
optimizer.setMaxIterations(200);
|
|
||||||
RealPointValuePair optimum =
|
|
||||||
optimizer.optimize(ls, GoalType.MINIMIZE, new double[] { 10.0, 10.0 });
|
|
||||||
assertEquals( 2.0, optimum.getPointRef()[0], 2.0e-3);
|
|
||||||
assertEquals(-3.0, optimum.getPointRef()[1], 8.0e-4);
|
|
||||||
assertTrue(optimizer.getEvaluations() > 60);
|
|
||||||
assertTrue(optimizer.getEvaluations() < 80);
|
|
||||||
assertTrue(optimum.getValue() < 1.0e-6);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(expected = MaxIterationsExceededException.class)
|
public double value(double[] x) throws FunctionEvaluationException {
|
||||||
public void testMaxIterations() throws MathException {
|
++count;
|
||||||
try {
|
double a = x[1] - x[0] * x[0];
|
||||||
Powell powell = new Powell();
|
double b = 1.0 - x[0];
|
||||||
NelderMead optimizer = new NelderMead();
|
return 100 * a * a + b * b;
|
||||||
optimizer.setConvergenceChecker(new SimpleScalarValueChecker(-1.0, 1.0e-3));
|
}
|
||||||
optimizer.setMaxIterations(20);
|
|
||||||
optimizer.optimize(powell, GoalType.MINIMIZE, new double[] { 3.0, -1.0, 0.0, 1.0 });
|
|
||||||
} catch (OptimizationException oe) {
|
|
||||||
if (oe.getCause() instanceof ConvergenceException) {
|
|
||||||
throw (ConvergenceException) oe.getCause();
|
|
||||||
}
|
|
||||||
throw oe;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(expected = MaxEvaluationsExceededException.class)
|
public int getCount() {
|
||||||
public void testMaxEvaluations() throws MathException {
|
return count;
|
||||||
try {
|
}
|
||||||
Powell powell = new Powell();
|
}
|
||||||
NelderMead optimizer = new NelderMead();
|
|
||||||
optimizer.setConvergenceChecker(new SimpleRealPointChecker(-1.0, 1.0e-3));
|
|
||||||
optimizer.setMaxEvaluations(20);
|
|
||||||
optimizer.optimize(powell, GoalType.MINIMIZE, new double[] { 3.0, -1.0, 0.0, 1.0 });
|
|
||||||
} catch (FunctionEvaluationException fee) {
|
|
||||||
if (fee.getCause() instanceof ConvergenceException) {
|
|
||||||
throw (ConvergenceException) fee.getCause();
|
|
||||||
}
|
|
||||||
throw fee;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class Rosenbrock implements MultivariateRealFunction {
|
private static class Powell implements MultivariateRealFunction {
|
||||||
|
private int count;
|
||||||
|
|
||||||
private int count;
|
public Powell() {
|
||||||
|
count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
public Rosenbrock() {
|
public double value(double[] x) throws FunctionEvaluationException {
|
||||||
count = 0;
|
++count;
|
||||||
}
|
double a = x[0] + 10 * x[1];
|
||||||
|
double b = x[2] - x[3];
|
||||||
public double value(double[] x) throws FunctionEvaluationException {
|
double c = x[1] - 2 * x[2];
|
||||||
++count;
|
double d = x[0] - x[3];
|
||||||
double a = x[1] - x[0] * x[0];
|
return a * a + 5 * b * b + c * c * c * c + 10 * d * d * d * d;
|
||||||
double b = 1.0 - x[0];
|
}
|
||||||
return 100 * a * a + b * b;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getCount() {
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class Powell implements MultivariateRealFunction {
|
|
||||||
|
|
||||||
private int count;
|
|
||||||
|
|
||||||
public Powell() {
|
|
||||||
count = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public double value(double[] x) throws FunctionEvaluationException {
|
|
||||||
++count;
|
|
||||||
double a = x[0] + 10 * x[1];
|
|
||||||
double b = x[2] - x[3];
|
|
||||||
double c = x[1] - 2 * x[2];
|
|
||||||
double d = x[0] - x[3];
|
|
||||||
return a * a + 5 * b * b + c * c * c * c + 10 * d * d * d * d;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getCount() {
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
public int getCount() {
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,8 +23,8 @@ import static org.junit.Assert.assertTrue;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
import org.apache.commons.math.analysis.polynomials.PolynomialFunction;
|
import org.apache.commons.math.analysis.polynomials.PolynomialFunction;
|
||||||
|
import org.apache.commons.math.exception.ConvergenceException;
|
||||||
import org.apache.commons.math.optimization.DifferentiableMultivariateVectorialOptimizer;
|
import org.apache.commons.math.optimization.DifferentiableMultivariateVectorialOptimizer;
|
||||||
import org.apache.commons.math.optimization.OptimizationException;
|
|
||||||
import org.apache.commons.math.optimization.general.GaussNewtonOptimizer;
|
import org.apache.commons.math.optimization.general.GaussNewtonOptimizer;
|
||||||
import org.apache.commons.math.optimization.general.LevenbergMarquardtOptimizer;
|
import org.apache.commons.math.optimization.general.LevenbergMarquardtOptimizer;
|
||||||
import org.apache.commons.math.util.FastMath;
|
import org.apache.commons.math.util.FastMath;
|
||||||
|
@ -33,7 +33,7 @@ import org.junit.Test;
|
||||||
public class PolynomialFitterTest {
|
public class PolynomialFitterTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testNoError() throws OptimizationException {
|
public void testNoError() {
|
||||||
Random randomizer = new Random(64925784252l);
|
Random randomizer = new Random(64925784252l);
|
||||||
for (int degree = 1; degree < 10; ++degree) {
|
for (int degree = 1; degree < 10; ++degree) {
|
||||||
PolynomialFunction p = buildRandomPolynomial(degree, randomizer);
|
PolynomialFunction p = buildRandomPolynomial(degree, randomizer);
|
||||||
|
@ -57,7 +57,7 @@ public class PolynomialFitterTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSmallError() throws OptimizationException {
|
public void testSmallError() {
|
||||||
Random randomizer = new Random(53882150042l);
|
Random randomizer = new Random(53882150042l);
|
||||||
double maxError = 0;
|
double maxError = 0;
|
||||||
for (int degree = 0; degree < 10; ++degree) {
|
for (int degree = 0; degree < 10; ++degree) {
|
||||||
|
@ -116,7 +116,7 @@ public class PolynomialFitterTest {
|
||||||
try {
|
try {
|
||||||
fitter.fit();
|
fitter.fit();
|
||||||
assertTrue(solvable || (degree == 0));
|
assertTrue(solvable || (degree == 0));
|
||||||
} catch(OptimizationException e) {
|
} catch(ConvergenceException e) {
|
||||||
assertTrue((! solvable) && (degree > 0));
|
assertTrue((! solvable) && (degree > 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,11 +25,13 @@ import java.util.Arrays;
|
||||||
import junit.framework.TestCase;
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
import org.apache.commons.math.FunctionEvaluationException;
|
import org.apache.commons.math.FunctionEvaluationException;
|
||||||
|
import org.apache.commons.math.exception.ConvergenceException;
|
||||||
|
import org.apache.commons.math.exception.TooManyEvaluationsException;
|
||||||
|
import org.apache.commons.math.exception.DimensionMismatchException;
|
||||||
import org.apache.commons.math.analysis.DifferentiableMultivariateVectorialFunction;
|
import org.apache.commons.math.analysis.DifferentiableMultivariateVectorialFunction;
|
||||||
import org.apache.commons.math.analysis.MultivariateMatrixFunction;
|
import org.apache.commons.math.analysis.MultivariateMatrixFunction;
|
||||||
import org.apache.commons.math.linear.BlockRealMatrix;
|
import org.apache.commons.math.linear.BlockRealMatrix;
|
||||||
import org.apache.commons.math.linear.RealMatrix;
|
import org.apache.commons.math.linear.RealMatrix;
|
||||||
import org.apache.commons.math.optimization.OptimizationException;
|
|
||||||
import org.apache.commons.math.optimization.SimpleVectorialPointChecker;
|
import org.apache.commons.math.optimization.SimpleVectorialPointChecker;
|
||||||
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;
|
||||||
|
@ -104,11 +106,11 @@ extends TestCase {
|
||||||
super(name);
|
super(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testTrivial() throws FunctionEvaluationException, OptimizationException {
|
public void testTrivial() throws FunctionEvaluationException {
|
||||||
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);
|
||||||
optimizer.setMaxIterations(100);
|
optimizer.setMaxEvaluations(100);
|
||||||
optimizer.setConvergenceChecker(new SimpleVectorialValueChecker(1.0e-6, 1.0e-6));
|
optimizer.setConvergenceChecker(new SimpleVectorialValueChecker(1.0e-6, 1.0e-6));
|
||||||
VectorialPointValuePair optimum =
|
VectorialPointValuePair optimum =
|
||||||
optimizer.optimize(problem, problem.target, new double[] { 1 }, new double[] { 0 });
|
optimizer.optimize(problem, problem.target, new double[] { 1 }, new double[] { 0 });
|
||||||
|
@ -117,14 +119,14 @@ extends TestCase {
|
||||||
assertEquals(3.0, optimum.getValue()[0], 1.0e-10);
|
assertEquals(3.0, optimum.getValue()[0], 1.0e-10);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testColumnsPermutation() throws FunctionEvaluationException, OptimizationException {
|
public void testColumnsPermutation() throws FunctionEvaluationException {
|
||||||
|
|
||||||
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 } },
|
||||||
new double[] { 4.0, 6.0, 1.0 });
|
new double[] { 4.0, 6.0, 1.0 });
|
||||||
|
|
||||||
GaussNewtonOptimizer optimizer = new GaussNewtonOptimizer(true);
|
GaussNewtonOptimizer optimizer = new GaussNewtonOptimizer(true);
|
||||||
optimizer.setMaxIterations(100);
|
optimizer.setMaxEvaluations(100);
|
||||||
optimizer.setConvergenceChecker(new SimpleVectorialValueChecker(1.0e-6, 1.0e-6));
|
optimizer.setConvergenceChecker(new SimpleVectorialValueChecker(1.0e-6, 1.0e-6));
|
||||||
VectorialPointValuePair optimum =
|
VectorialPointValuePair optimum =
|
||||||
optimizer.optimize(problem, problem.target, new double[] { 1, 1, 1 }, new double[] { 0, 0 });
|
optimizer.optimize(problem, problem.target, new double[] { 1, 1, 1 }, new double[] { 0, 0 });
|
||||||
|
@ -137,7 +139,7 @@ extends TestCase {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testNoDependency() throws FunctionEvaluationException, OptimizationException {
|
public void testNoDependency() throws FunctionEvaluationException {
|
||||||
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 },
|
||||||
|
@ -147,7 +149,7 @@ extends TestCase {
|
||||||
{ 0, 0, 0, 0, 0, 2 }
|
{ 0, 0, 0, 0, 0, 2 }
|
||||||
}, new double[] { 0.0, 1.1, 2.2, 3.3, 4.4, 5.5 });
|
}, new double[] { 0.0, 1.1, 2.2, 3.3, 4.4, 5.5 });
|
||||||
GaussNewtonOptimizer optimizer = new GaussNewtonOptimizer(true);
|
GaussNewtonOptimizer optimizer = new GaussNewtonOptimizer(true);
|
||||||
optimizer.setMaxIterations(100);
|
optimizer.setMaxEvaluations(100);
|
||||||
optimizer.setConvergenceChecker(new SimpleVectorialValueChecker(1.0e-6, 1.0e-6));
|
optimizer.setConvergenceChecker(new SimpleVectorialValueChecker(1.0e-6, 1.0e-6));
|
||||||
VectorialPointValuePair optimum =
|
VectorialPointValuePair optimum =
|
||||||
optimizer.optimize(problem, problem.target, new double[] { 1, 1, 1, 1, 1, 1 },
|
optimizer.optimize(problem, problem.target, new double[] { 1, 1, 1, 1, 1, 1 },
|
||||||
|
@ -158,7 +160,7 @@ extends TestCase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testOneSet() throws FunctionEvaluationException, OptimizationException {
|
public void testOneSet() throws FunctionEvaluationException {
|
||||||
|
|
||||||
LinearProblem problem = new LinearProblem(new double[][] {
|
LinearProblem problem = new LinearProblem(new double[][] {
|
||||||
{ 1, 0, 0 },
|
{ 1, 0, 0 },
|
||||||
|
@ -166,7 +168,7 @@ extends TestCase {
|
||||||
{ 0, -1, 1 }
|
{ 0, -1, 1 }
|
||||||
}, new double[] { 1, 1, 1});
|
}, new double[] { 1, 1, 1});
|
||||||
GaussNewtonOptimizer optimizer = new GaussNewtonOptimizer(true);
|
GaussNewtonOptimizer optimizer = new GaussNewtonOptimizer(true);
|
||||||
optimizer.setMaxIterations(100);
|
optimizer.setMaxEvaluations(100);
|
||||||
optimizer.setConvergenceChecker(new SimpleVectorialValueChecker(1.0e-6, 1.0e-6));
|
optimizer.setConvergenceChecker(new SimpleVectorialValueChecker(1.0e-6, 1.0e-6));
|
||||||
VectorialPointValuePair optimum =
|
VectorialPointValuePair optimum =
|
||||||
optimizer.optimize(problem, problem.target, new double[] { 1, 1, 1 }, new double[] { 0, 0, 0 });
|
optimizer.optimize(problem, problem.target, new double[] { 1, 1, 1 }, new double[] { 0, 0, 0 });
|
||||||
|
@ -177,7 +179,7 @@ extends TestCase {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testTwoSets() throws FunctionEvaluationException, OptimizationException {
|
public void testTwoSets() throws FunctionEvaluationException {
|
||||||
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 },
|
||||||
|
@ -189,7 +191,7 @@ extends TestCase {
|
||||||
}, new double[] { 2, -9, 2, 2, 1 + epsilon * epsilon, 2});
|
}, new double[] { 2, -9, 2, 2, 1 + epsilon * epsilon, 2});
|
||||||
|
|
||||||
GaussNewtonOptimizer optimizer = new GaussNewtonOptimizer(true);
|
GaussNewtonOptimizer optimizer = new GaussNewtonOptimizer(true);
|
||||||
optimizer.setMaxIterations(100);
|
optimizer.setMaxEvaluations(100);
|
||||||
optimizer.setConvergenceChecker(new SimpleVectorialValueChecker(1.0e-6, 1.0e-6));
|
optimizer.setConvergenceChecker(new SimpleVectorialValueChecker(1.0e-6, 1.0e-6));
|
||||||
VectorialPointValuePair optimum =
|
VectorialPointValuePair optimum =
|
||||||
optimizer.optimize(problem, problem.target, new double[] { 1, 1, 1, 1, 1, 1 },
|
optimizer.optimize(problem, problem.target, new double[] { 1, 1, 1, 1, 1, 1 },
|
||||||
|
@ -212,19 +214,19 @@ extends TestCase {
|
||||||
{ -3, 0, -9 }
|
{ -3, 0, -9 }
|
||||||
}, new double[] { 1, 1, 1 });
|
}, new double[] { 1, 1, 1 });
|
||||||
GaussNewtonOptimizer optimizer = new GaussNewtonOptimizer(true);
|
GaussNewtonOptimizer optimizer = new GaussNewtonOptimizer(true);
|
||||||
optimizer.setMaxIterations(100);
|
optimizer.setMaxEvaluations(100);
|
||||||
optimizer.setConvergenceChecker(new SimpleVectorialValueChecker(1.0e-6, 1.0e-6));
|
optimizer.setConvergenceChecker(new SimpleVectorialValueChecker(1.0e-6, 1.0e-6));
|
||||||
try {
|
try {
|
||||||
optimizer.optimize(problem, problem.target, new double[] { 1, 1, 1 }, new double[] { 0, 0, 0 });
|
optimizer.optimize(problem, problem.target, new double[] { 1, 1, 1 }, new double[] { 0, 0, 0 });
|
||||||
fail("an exception should have been caught");
|
fail("an exception should have been caught");
|
||||||
} catch (OptimizationException ee) {
|
} catch (ConvergenceException ee) {
|
||||||
// expected behavior
|
// expected behavior
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
fail("wrong exception type caught");
|
fail("wrong exception type caught");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testIllConditioned() throws FunctionEvaluationException, OptimizationException {
|
public void testIllConditioned() throws FunctionEvaluationException {
|
||||||
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 },
|
||||||
|
@ -232,7 +234,7 @@ extends TestCase {
|
||||||
{ 7.0, 5.0, 9.0, 10.0 }
|
{ 7.0, 5.0, 9.0, 10.0 }
|
||||||
}, new double[] { 32, 23, 33, 31 });
|
}, new double[] { 32, 23, 33, 31 });
|
||||||
GaussNewtonOptimizer optimizer = new GaussNewtonOptimizer(true);
|
GaussNewtonOptimizer optimizer = new GaussNewtonOptimizer(true);
|
||||||
optimizer.setMaxIterations(100);
|
optimizer.setMaxEvaluations(100);
|
||||||
optimizer.setConvergenceChecker(new SimpleVectorialValueChecker(1.0e-6, 1.0e-6));
|
optimizer.setConvergenceChecker(new SimpleVectorialValueChecker(1.0e-6, 1.0e-6));
|
||||||
VectorialPointValuePair optimum1 =
|
VectorialPointValuePair optimum1 =
|
||||||
optimizer.optimize(problem1, problem1.target, new double[] { 1, 1, 1, 1 },
|
optimizer.optimize(problem1, problem1.target, new double[] { 1, 1, 1, 1 },
|
||||||
|
@ -269,13 +271,13 @@ extends TestCase {
|
||||||
}, new double[] { 7.0, 3.0, 5.0 });
|
}, new double[] { 7.0, 3.0, 5.0 });
|
||||||
|
|
||||||
GaussNewtonOptimizer optimizer = new GaussNewtonOptimizer(true);
|
GaussNewtonOptimizer optimizer = new GaussNewtonOptimizer(true);
|
||||||
optimizer.setMaxIterations(100);
|
optimizer.setMaxEvaluations(100);
|
||||||
optimizer.setConvergenceChecker(new SimpleVectorialValueChecker(1.0e-6, 1.0e-6));
|
optimizer.setConvergenceChecker(new SimpleVectorialValueChecker(1.0e-6, 1.0e-6));
|
||||||
try {
|
try {
|
||||||
optimizer.optimize(problem, problem.target, new double[] { 1, 1, 1 },
|
optimizer.optimize(problem, problem.target, new double[] { 1, 1, 1 },
|
||||||
new double[] { 7, 6, 5, 4 });
|
new double[] { 7, 6, 5, 4 });
|
||||||
fail("an exception should have been caught");
|
fail("an exception should have been caught");
|
||||||
} catch (OptimizationException ee) {
|
} catch (ConvergenceException ee) {
|
||||||
// expected behavior
|
// expected behavior
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
fail("wrong exception type caught");
|
fail("wrong exception type caught");
|
||||||
|
@ -292,20 +294,20 @@ extends TestCase {
|
||||||
{ 0.0, 0.0, 0.0, -1.0, 1.0, 0.0 }
|
{ 0.0, 0.0, 0.0, -1.0, 1.0, 0.0 }
|
||||||
}, new double[] { 3.0, 12.0, -1.0, 7.0, 1.0 });
|
}, new double[] { 3.0, 12.0, -1.0, 7.0, 1.0 });
|
||||||
GaussNewtonOptimizer optimizer = new GaussNewtonOptimizer(true);
|
GaussNewtonOptimizer optimizer = new GaussNewtonOptimizer(true);
|
||||||
optimizer.setMaxIterations(100);
|
optimizer.setMaxEvaluations(100);
|
||||||
optimizer.setConvergenceChecker(new SimpleVectorialValueChecker(1.0e-6, 1.0e-6));
|
optimizer.setConvergenceChecker(new SimpleVectorialValueChecker(1.0e-6, 1.0e-6));
|
||||||
try {
|
try {
|
||||||
optimizer.optimize(problem, problem.target, new double[] { 1, 1, 1, 1, 1 },
|
optimizer.optimize(problem, problem.target, new double[] { 1, 1, 1, 1, 1 },
|
||||||
new double[] { 2, 2, 2, 2, 2, 2 });
|
new double[] { 2, 2, 2, 2, 2, 2 });
|
||||||
fail("an exception should have been caught");
|
fail("an exception should have been caught");
|
||||||
} catch (OptimizationException ee) {
|
} catch (ConvergenceException ee) {
|
||||||
// expected behavior
|
// expected behavior
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
fail("wrong exception type caught");
|
fail("wrong exception type caught");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testRedundantEquations() throws FunctionEvaluationException, OptimizationException {
|
public void testRedundantEquations() throws FunctionEvaluationException {
|
||||||
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 },
|
||||||
|
@ -313,7 +315,7 @@ extends TestCase {
|
||||||
}, new double[] { 3.0, 1.0, 5.0 });
|
}, new double[] { 3.0, 1.0, 5.0 });
|
||||||
|
|
||||||
GaussNewtonOptimizer optimizer = new GaussNewtonOptimizer(true);
|
GaussNewtonOptimizer optimizer = new GaussNewtonOptimizer(true);
|
||||||
optimizer.setMaxIterations(100);
|
optimizer.setMaxEvaluations(100);
|
||||||
optimizer.setConvergenceChecker(new SimpleVectorialValueChecker(1.0e-6, 1.0e-6));
|
optimizer.setConvergenceChecker(new SimpleVectorialValueChecker(1.0e-6, 1.0e-6));
|
||||||
VectorialPointValuePair optimum =
|
VectorialPointValuePair optimum =
|
||||||
optimizer.optimize(problem, problem.target, new double[] { 1, 1, 1 },
|
optimizer.optimize(problem, problem.target, new double[] { 1, 1, 1 },
|
||||||
|
@ -324,7 +326,7 @@ extends TestCase {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testInconsistentEquations() throws FunctionEvaluationException, OptimizationException {
|
public void testInconsistentEquations() throws FunctionEvaluationException {
|
||||||
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 },
|
||||||
|
@ -332,18 +334,18 @@ extends TestCase {
|
||||||
}, new double[] { 3.0, 1.0, 4.0 });
|
}, new double[] { 3.0, 1.0, 4.0 });
|
||||||
|
|
||||||
GaussNewtonOptimizer optimizer = new GaussNewtonOptimizer(true);
|
GaussNewtonOptimizer optimizer = new GaussNewtonOptimizer(true);
|
||||||
optimizer.setMaxIterations(100);
|
optimizer.setMaxEvaluations(100);
|
||||||
optimizer.setConvergenceChecker(new SimpleVectorialValueChecker(1.0e-6, 1.0e-6));
|
optimizer.setConvergenceChecker(new SimpleVectorialValueChecker(1.0e-6, 1.0e-6));
|
||||||
optimizer.optimize(problem, problem.target, new double[] { 1, 1, 1 }, new double[] { 1, 1 });
|
optimizer.optimize(problem, problem.target, new double[] { 1, 1, 1 }, new double[] { 1, 1 });
|
||||||
assertTrue(optimizer.getRMS() > 0.1);
|
assertTrue(optimizer.getRMS() > 0.1);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testInconsistentSizes() throws FunctionEvaluationException, OptimizationException {
|
public void testInconsistentSizes() throws FunctionEvaluationException {
|
||||||
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);
|
||||||
optimizer.setMaxIterations(100);
|
optimizer.setMaxEvaluations(100);
|
||||||
optimizer.setConvergenceChecker(new SimpleVectorialValueChecker(1.0e-6, 1.0e-6));
|
optimizer.setConvergenceChecker(new SimpleVectorialValueChecker(1.0e-6, 1.0e-6));
|
||||||
|
|
||||||
VectorialPointValuePair optimum =
|
VectorialPointValuePair optimum =
|
||||||
|
@ -357,7 +359,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 (OptimizationException oe) {
|
} catch (DimensionMismatchException oe) {
|
||||||
// expected behavior
|
// expected behavior
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
fail("wrong exception caught");
|
fail("wrong exception caught");
|
||||||
|
@ -376,7 +378,7 @@ extends TestCase {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testMaxIterations() {
|
public void testMaxEvaluations() {
|
||||||
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);
|
||||||
|
@ -384,21 +386,21 @@ extends TestCase {
|
||||||
circle.addPoint( 35.0, 15.0);
|
circle.addPoint( 35.0, 15.0);
|
||||||
circle.addPoint( 45.0, 97.0);
|
circle.addPoint( 45.0, 97.0);
|
||||||
GaussNewtonOptimizer optimizer = new GaussNewtonOptimizer(true);
|
GaussNewtonOptimizer optimizer = new GaussNewtonOptimizer(true);
|
||||||
optimizer.setMaxIterations(100);
|
optimizer.setMaxEvaluations(100);
|
||||||
optimizer.setConvergenceChecker(new SimpleVectorialPointChecker(1.0e-30, 1.0e-30));
|
optimizer.setConvergenceChecker(new SimpleVectorialPointChecker(1.0e-30, 1.0e-30));
|
||||||
try {
|
try {
|
||||||
optimizer.optimize(circle, new double[] { 0, 0, 0, 0, 0 },
|
optimizer.optimize(circle, new double[] { 0, 0, 0, 0, 0 },
|
||||||
new double[] { 1, 1, 1, 1, 1 },
|
new double[] { 1, 1, 1, 1, 1 },
|
||||||
new double[] { 98.680, 47.345 });
|
new double[] { 98.680, 47.345 });
|
||||||
fail("an exception should have been caught");
|
fail("an exception should have been caught");
|
||||||
} catch (OptimizationException ee) {
|
} catch (TooManyEvaluationsException ee) {
|
||||||
// expected behavior
|
// expected behavior
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
fail("wrong exception type caught");
|
fail("wrong exception type caught");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testCircleFitting() throws FunctionEvaluationException, OptimizationException {
|
public void testCircleFitting() throws FunctionEvaluationException {
|
||||||
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);
|
||||||
|
@ -406,7 +408,7 @@ extends TestCase {
|
||||||
circle.addPoint( 35.0, 15.0);
|
circle.addPoint( 35.0, 15.0);
|
||||||
circle.addPoint( 45.0, 97.0);
|
circle.addPoint( 45.0, 97.0);
|
||||||
GaussNewtonOptimizer optimizer = new GaussNewtonOptimizer(true);
|
GaussNewtonOptimizer optimizer = new GaussNewtonOptimizer(true);
|
||||||
optimizer.setMaxIterations(100);
|
optimizer.setMaxEvaluations(100);
|
||||||
optimizer.setConvergenceChecker(new SimpleVectorialValueChecker(1.0e-13, 1.0e-13));
|
optimizer.setConvergenceChecker(new SimpleVectorialValueChecker(1.0e-13, 1.0e-13));
|
||||||
VectorialPointValuePair optimum =
|
VectorialPointValuePair optimum =
|
||||||
optimizer.optimize(circle, new double[] { 0, 0, 0, 0, 0 },
|
optimizer.optimize(circle, new double[] { 0, 0, 0, 0, 0 },
|
||||||
|
@ -419,7 +421,7 @@ extends TestCase {
|
||||||
assertEquals(48.135167894714, center.y, 1.0e-10);
|
assertEquals(48.135167894714, center.y, 1.0e-10);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testCircleFittingBadInit() throws FunctionEvaluationException, OptimizationException {
|
public void testCircleFittingBadInit() throws FunctionEvaluationException {
|
||||||
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},
|
||||||
|
@ -460,12 +462,12 @@ extends TestCase {
|
||||||
circle.addPoint(points[i][0], points[i][1]);
|
circle.addPoint(points[i][0], points[i][1]);
|
||||||
}
|
}
|
||||||
GaussNewtonOptimizer optimizer = new GaussNewtonOptimizer(true);
|
GaussNewtonOptimizer optimizer = new GaussNewtonOptimizer(true);
|
||||||
optimizer.setMaxIterations(100);
|
optimizer.setMaxEvaluations(100);
|
||||||
optimizer.setConvergenceChecker(new SimpleVectorialValueChecker(1.0e-6, 1.0e-6));
|
optimizer.setConvergenceChecker(new SimpleVectorialValueChecker(1.0e-6, 1.0e-6));
|
||||||
try {
|
try {
|
||||||
optimizer.optimize(circle, target, weights, new double[] { -12, -12 });
|
optimizer.optimize(circle, target, weights, new double[] { -12, -12 });
|
||||||
fail("an exception should have been caught");
|
fail("an exception should have been caught");
|
||||||
} catch (OptimizationException ee) {
|
} catch (ConvergenceException ee) {
|
||||||
// expected behavior
|
// expected behavior
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
fail("wrong exception type caught");
|
fail("wrong exception type caught");
|
||||||
|
|
|
@ -26,11 +26,13 @@ import java.util.List;
|
||||||
import junit.framework.TestCase;
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
import org.apache.commons.math.FunctionEvaluationException;
|
import org.apache.commons.math.FunctionEvaluationException;
|
||||||
|
import org.apache.commons.math.exception.ConvergenceException;
|
||||||
|
import org.apache.commons.math.exception.DimensionMismatchException;
|
||||||
|
import org.apache.commons.math.exception.TooManyEvaluationsException;
|
||||||
import org.apache.commons.math.analysis.DifferentiableMultivariateVectorialFunction;
|
import org.apache.commons.math.analysis.DifferentiableMultivariateVectorialFunction;
|
||||||
import org.apache.commons.math.analysis.MultivariateMatrixFunction;
|
import org.apache.commons.math.analysis.MultivariateMatrixFunction;
|
||||||
import org.apache.commons.math.linear.BlockRealMatrix;
|
import org.apache.commons.math.linear.BlockRealMatrix;
|
||||||
import org.apache.commons.math.linear.RealMatrix;
|
import org.apache.commons.math.linear.RealMatrix;
|
||||||
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;
|
||||||
import org.apache.commons.math.util.FastMath;
|
import org.apache.commons.math.util.FastMath;
|
||||||
|
@ -104,7 +106,7 @@ public class LevenbergMarquardtOptimizerTest
|
||||||
super(name);
|
super(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testTrivial() throws FunctionEvaluationException, OptimizationException {
|
public void testTrivial() throws FunctionEvaluationException {
|
||||||
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();
|
||||||
|
@ -114,7 +116,7 @@ public class LevenbergMarquardtOptimizerTest
|
||||||
try {
|
try {
|
||||||
optimizer.guessParametersErrors();
|
optimizer.guessParametersErrors();
|
||||||
fail("an exception should have been thrown");
|
fail("an exception should have been thrown");
|
||||||
} catch (OptimizationException ee) {
|
} catch (ConvergenceException ee) {
|
||||||
// expected behavior
|
// expected behavior
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
fail("wrong exception caught");
|
fail("wrong exception caught");
|
||||||
|
@ -123,7 +125,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 FunctionEvaluationException, OptimizationException {
|
public void testQRColumnsPermutation() throws FunctionEvaluationException {
|
||||||
|
|
||||||
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 } },
|
||||||
|
@ -141,7 +143,7 @@ public class LevenbergMarquardtOptimizerTest
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testNoDependency() throws FunctionEvaluationException, OptimizationException {
|
public void testNoDependency() throws FunctionEvaluationException {
|
||||||
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 },
|
||||||
|
@ -160,7 +162,7 @@ public class LevenbergMarquardtOptimizerTest
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testOneSet() throws FunctionEvaluationException, OptimizationException {
|
public void testOneSet() throws FunctionEvaluationException {
|
||||||
|
|
||||||
LinearProblem problem = new LinearProblem(new double[][] {
|
LinearProblem problem = new LinearProblem(new double[][] {
|
||||||
{ 1, 0, 0 },
|
{ 1, 0, 0 },
|
||||||
|
@ -177,7 +179,7 @@ public class LevenbergMarquardtOptimizerTest
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testTwoSets() throws FunctionEvaluationException, OptimizationException {
|
public void testTwoSets() throws FunctionEvaluationException {
|
||||||
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 },
|
||||||
|
@ -202,7 +204,7 @@ public class LevenbergMarquardtOptimizerTest
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testNonInversible() throws FunctionEvaluationException, OptimizationException {
|
public void testNonInversible() throws FunctionEvaluationException {
|
||||||
|
|
||||||
LinearProblem problem = new LinearProblem(new double[][] {
|
LinearProblem problem = new LinearProblem(new double[][] {
|
||||||
{ 1, 2, -3 },
|
{ 1, 2, -3 },
|
||||||
|
@ -216,7 +218,7 @@ public class LevenbergMarquardtOptimizerTest
|
||||||
try {
|
try {
|
||||||
optimizer.getCovariances();
|
optimizer.getCovariances();
|
||||||
fail("an exception should have been thrown");
|
fail("an exception should have been thrown");
|
||||||
} catch (OptimizationException ee) {
|
} catch (ConvergenceException ee) {
|
||||||
// expected behavior
|
// expected behavior
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
fail("wrong exception caught");
|
fail("wrong exception caught");
|
||||||
|
@ -224,7 +226,7 @@ public class LevenbergMarquardtOptimizerTest
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testIllConditioned() throws FunctionEvaluationException, OptimizationException {
|
public void testIllConditioned() throws FunctionEvaluationException {
|
||||||
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 },
|
||||||
|
@ -258,7 +260,7 @@ public class LevenbergMarquardtOptimizerTest
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testMoreEstimatedParametersSimple() throws FunctionEvaluationException, OptimizationException {
|
public void testMoreEstimatedParametersSimple() throws FunctionEvaluationException {
|
||||||
|
|
||||||
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 },
|
||||||
|
@ -273,7 +275,7 @@ public class LevenbergMarquardtOptimizerTest
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testMoreEstimatedParametersUnsorted() throws FunctionEvaluationException, OptimizationException {
|
public void testMoreEstimatedParametersUnsorted() throws FunctionEvaluationException {
|
||||||
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 },
|
||||||
|
@ -294,7 +296,7 @@ public class LevenbergMarquardtOptimizerTest
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testRedundantEquations() throws FunctionEvaluationException, OptimizationException {
|
public void testRedundantEquations() throws FunctionEvaluationException {
|
||||||
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 },
|
||||||
|
@ -311,7 +313,7 @@ public class LevenbergMarquardtOptimizerTest
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testInconsistentEquations() throws FunctionEvaluationException, OptimizationException {
|
public void testInconsistentEquations() throws FunctionEvaluationException {
|
||||||
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 },
|
||||||
|
@ -324,7 +326,7 @@ public class LevenbergMarquardtOptimizerTest
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testInconsistentSizes() throws FunctionEvaluationException, OptimizationException {
|
public void testInconsistentSizes() throws FunctionEvaluationException {
|
||||||
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();
|
||||||
|
@ -340,7 +342,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 (OptimizationException oe) {
|
} catch (DimensionMismatchException oe) {
|
||||||
// expected behavior
|
// expected behavior
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
fail("wrong exception caught");
|
fail("wrong exception caught");
|
||||||
|
@ -380,23 +382,23 @@ public class LevenbergMarquardtOptimizerTest
|
||||||
try {
|
try {
|
||||||
LevenbergMarquardtOptimizer optimizer = new LevenbergMarquardtOptimizer();
|
LevenbergMarquardtOptimizer optimizer = new LevenbergMarquardtOptimizer();
|
||||||
optimizer.setInitialStepBoundFactor(initialStepBoundFactor);
|
optimizer.setInitialStepBoundFactor(initialStepBoundFactor);
|
||||||
optimizer.setMaxIterations(maxCostEval);
|
optimizer.setMaxEvaluations(maxCostEval);
|
||||||
optimizer.setCostRelativeTolerance(costRelativeTolerance);
|
optimizer.setCostRelativeTolerance(costRelativeTolerance);
|
||||||
optimizer.setParRelativeTolerance(parRelativeTolerance);
|
optimizer.setParRelativeTolerance(parRelativeTolerance);
|
||||||
optimizer.setOrthoTolerance(orthoTolerance);
|
optimizer.setOrthoTolerance(orthoTolerance);
|
||||||
optimizer.optimize(problem, new double[] { 0, 0, 0, 0, 0 }, new double[] { 1, 1, 1, 1, 1 },
|
optimizer.optimize(problem, new double[] { 0, 0, 0, 0, 0 }, new double[] { 1, 1, 1, 1, 1 },
|
||||||
new double[] { 98.680, 47.345 });
|
new double[] { 98.680, 47.345 });
|
||||||
assertTrue(! shouldFail);
|
assertTrue(!shouldFail);
|
||||||
} catch (OptimizationException ee) {
|
|
||||||
assertTrue(shouldFail);
|
|
||||||
} catch (FunctionEvaluationException ee) {
|
} catch (FunctionEvaluationException ee) {
|
||||||
assertTrue(shouldFail);
|
assertTrue(shouldFail);
|
||||||
|
} catch (TooManyEvaluationsException ee) {
|
||||||
|
assertTrue(shouldFail);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
fail("wrong exception type caught");
|
fail("wrong exception type caught");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testCircleFitting() throws FunctionEvaluationException, OptimizationException {
|
public void testCircleFitting() throws FunctionEvaluationException {
|
||||||
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 FunctionEvaluationException, OptimizationException {
|
public void testCircleFittingBadInit() throws FunctionEvaluationException {
|
||||||
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},
|
||||||
|
@ -513,7 +515,7 @@ public class LevenbergMarquardtOptimizerTest
|
||||||
new double[] { 0.0, 4.4e-323, 1.0, 4.4e-323, 0.0 },
|
new double[] { 0.0, 4.4e-323, 1.0, 4.4e-323, 0.0 },
|
||||||
new double[] { 0, 0, 0 });
|
new double[] { 0, 0, 0 });
|
||||||
fail("an exception should have been thrown");
|
fail("an exception should have been thrown");
|
||||||
} catch (OptimizationException ee) {
|
} catch (ConvergenceException ee) {
|
||||||
// expected behavior
|
// expected behavior
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,9 +23,9 @@ import java.util.Arrays;
|
||||||
import junit.framework.TestCase;
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
import org.apache.commons.math.FunctionEvaluationException;
|
import org.apache.commons.math.FunctionEvaluationException;
|
||||||
|
import org.apache.commons.math.exception.TooManyEvaluationsException;
|
||||||
import org.apache.commons.math.analysis.DifferentiableMultivariateVectorialFunction;
|
import org.apache.commons.math.analysis.DifferentiableMultivariateVectorialFunction;
|
||||||
import org.apache.commons.math.analysis.MultivariateMatrixFunction;
|
import org.apache.commons.math.analysis.MultivariateMatrixFunction;
|
||||||
import org.apache.commons.math.optimization.OptimizationException;
|
|
||||||
import org.apache.commons.math.optimization.VectorialPointValuePair;
|
import org.apache.commons.math.optimization.VectorialPointValuePair;
|
||||||
import org.apache.commons.math.util.FastMath;
|
import org.apache.commons.math.util.FastMath;
|
||||||
|
|
||||||
|
@ -490,7 +490,7 @@ public class MinpackTest extends TestCase {
|
||||||
|
|
||||||
private void minpackTest(MinpackFunction function, boolean exceptionExpected) {
|
private void minpackTest(MinpackFunction function, boolean exceptionExpected) {
|
||||||
LevenbergMarquardtOptimizer optimizer = new LevenbergMarquardtOptimizer();
|
LevenbergMarquardtOptimizer optimizer = new LevenbergMarquardtOptimizer();
|
||||||
optimizer.setMaxIterations(100 * (function.getN() + 1));
|
optimizer.setMaxEvaluations(400 * (function.getN() + 1));
|
||||||
optimizer.setCostRelativeTolerance(FastMath.sqrt(2.22044604926e-16));
|
optimizer.setCostRelativeTolerance(FastMath.sqrt(2.22044604926e-16));
|
||||||
optimizer.setParRelativeTolerance(FastMath.sqrt(2.22044604926e-16));
|
optimizer.setParRelativeTolerance(FastMath.sqrt(2.22044604926e-16));
|
||||||
optimizer.setOrthoTolerance(2.22044604926e-16);
|
optimizer.setOrthoTolerance(2.22044604926e-16);
|
||||||
|
@ -503,7 +503,7 @@ public class MinpackTest extends TestCase {
|
||||||
assertFalse(exceptionExpected);
|
assertFalse(exceptionExpected);
|
||||||
function.checkTheoreticalMinCost(optimizer.getRMS());
|
function.checkTheoreticalMinCost(optimizer.getRMS());
|
||||||
function.checkTheoreticalMinParams(optimum);
|
function.checkTheoreticalMinParams(optimum);
|
||||||
} catch (OptimizationException lsse) {
|
} catch (TooManyEvaluationsException e) {
|
||||||
assertTrue(exceptionExpected);
|
assertTrue(exceptionExpected);
|
||||||
} catch (FunctionEvaluationException fe) {
|
} catch (FunctionEvaluationException fe) {
|
||||||
assertTrue(exceptionExpected);
|
assertTrue(exceptionExpected);
|
||||||
|
|
|
@ -109,7 +109,7 @@ extends TestCase {
|
||||||
new LinearProblem(new double[][] { { 2 } }, new double[] { 3 });
|
new LinearProblem(new double[][] { { 2 } }, new double[] { 3 });
|
||||||
NonLinearConjugateGradientOptimizer optimizer =
|
NonLinearConjugateGradientOptimizer optimizer =
|
||||||
new NonLinearConjugateGradientOptimizer(ConjugateGradientFormula.POLAK_RIBIERE);
|
new NonLinearConjugateGradientOptimizer(ConjugateGradientFormula.POLAK_RIBIERE);
|
||||||
optimizer.setMaxIterations(100);
|
optimizer.setMaxEvaluations(100);
|
||||||
optimizer.setConvergenceChecker(new SimpleScalarValueChecker(1.0e-6, 1.0e-6));
|
optimizer.setConvergenceChecker(new SimpleScalarValueChecker(1.0e-6, 1.0e-6));
|
||||||
RealPointValuePair optimum =
|
RealPointValuePair optimum =
|
||||||
optimizer.optimize(problem, GoalType.MINIMIZE, new double[] { 0 });
|
optimizer.optimize(problem, GoalType.MINIMIZE, new double[] { 0 });
|
||||||
|
@ -125,7 +125,7 @@ extends TestCase {
|
||||||
|
|
||||||
NonLinearConjugateGradientOptimizer optimizer =
|
NonLinearConjugateGradientOptimizer optimizer =
|
||||||
new NonLinearConjugateGradientOptimizer(ConjugateGradientFormula.POLAK_RIBIERE);
|
new NonLinearConjugateGradientOptimizer(ConjugateGradientFormula.POLAK_RIBIERE);
|
||||||
optimizer.setMaxIterations(100);
|
optimizer.setMaxEvaluations(100);
|
||||||
optimizer.setConvergenceChecker(new SimpleScalarValueChecker(1.0e-6, 1.0e-6));
|
optimizer.setConvergenceChecker(new SimpleScalarValueChecker(1.0e-6, 1.0e-6));
|
||||||
RealPointValuePair optimum =
|
RealPointValuePair optimum =
|
||||||
optimizer.optimize(problem, GoalType.MINIMIZE, new double[] { 0, 0 });
|
optimizer.optimize(problem, GoalType.MINIMIZE, new double[] { 0, 0 });
|
||||||
|
@ -146,7 +146,7 @@ extends TestCase {
|
||||||
}, new double[] { 0.0, 1.1, 2.2, 3.3, 4.4, 5.5 });
|
}, new double[] { 0.0, 1.1, 2.2, 3.3, 4.4, 5.5 });
|
||||||
NonLinearConjugateGradientOptimizer optimizer =
|
NonLinearConjugateGradientOptimizer optimizer =
|
||||||
new NonLinearConjugateGradientOptimizer(ConjugateGradientFormula.POLAK_RIBIERE);
|
new NonLinearConjugateGradientOptimizer(ConjugateGradientFormula.POLAK_RIBIERE);
|
||||||
optimizer.setMaxIterations(100);
|
optimizer.setMaxEvaluations(100);
|
||||||
optimizer.setConvergenceChecker(new SimpleScalarValueChecker(1.0e-6, 1.0e-6));
|
optimizer.setConvergenceChecker(new SimpleScalarValueChecker(1.0e-6, 1.0e-6));
|
||||||
RealPointValuePair optimum =
|
RealPointValuePair optimum =
|
||||||
optimizer.optimize(problem, GoalType.MINIMIZE, new double[] { 0, 0, 0, 0, 0, 0 });
|
optimizer.optimize(problem, GoalType.MINIMIZE, new double[] { 0, 0, 0, 0, 0, 0 });
|
||||||
|
@ -164,7 +164,7 @@ extends TestCase {
|
||||||
}, new double[] { 1, 1, 1});
|
}, new double[] { 1, 1, 1});
|
||||||
NonLinearConjugateGradientOptimizer optimizer =
|
NonLinearConjugateGradientOptimizer optimizer =
|
||||||
new NonLinearConjugateGradientOptimizer(ConjugateGradientFormula.POLAK_RIBIERE);
|
new NonLinearConjugateGradientOptimizer(ConjugateGradientFormula.POLAK_RIBIERE);
|
||||||
optimizer.setMaxIterations(100);
|
optimizer.setMaxEvaluations(100);
|
||||||
optimizer.setConvergenceChecker(new SimpleScalarValueChecker(1.0e-6, 1.0e-6));
|
optimizer.setConvergenceChecker(new SimpleScalarValueChecker(1.0e-6, 1.0e-6));
|
||||||
RealPointValuePair optimum =
|
RealPointValuePair optimum =
|
||||||
optimizer.optimize(problem, GoalType.MINIMIZE, new double[] { 0, 0, 0 });
|
optimizer.optimize(problem, GoalType.MINIMIZE, new double[] { 0, 0, 0 });
|
||||||
|
@ -187,7 +187,7 @@ extends TestCase {
|
||||||
|
|
||||||
NonLinearConjugateGradientOptimizer optimizer =
|
NonLinearConjugateGradientOptimizer optimizer =
|
||||||
new NonLinearConjugateGradientOptimizer(ConjugateGradientFormula.POLAK_RIBIERE);
|
new NonLinearConjugateGradientOptimizer(ConjugateGradientFormula.POLAK_RIBIERE);
|
||||||
optimizer.setMaxIterations(100);
|
optimizer.setMaxEvaluations(100);
|
||||||
optimizer.setPreconditioner(new Preconditioner() {
|
optimizer.setPreconditioner(new Preconditioner() {
|
||||||
public double[] precondition(double[] point, double[] r) {
|
public double[] precondition(double[] point, double[] r) {
|
||||||
double[] d = r.clone();
|
double[] d = r.clone();
|
||||||
|
@ -222,7 +222,7 @@ extends TestCase {
|
||||||
}, new double[] { 1, 1, 1 });
|
}, new double[] { 1, 1, 1 });
|
||||||
NonLinearConjugateGradientOptimizer optimizer =
|
NonLinearConjugateGradientOptimizer optimizer =
|
||||||
new NonLinearConjugateGradientOptimizer(ConjugateGradientFormula.POLAK_RIBIERE);
|
new NonLinearConjugateGradientOptimizer(ConjugateGradientFormula.POLAK_RIBIERE);
|
||||||
optimizer.setMaxIterations(100);
|
optimizer.setMaxEvaluations(100);
|
||||||
optimizer.setConvergenceChecker(new SimpleScalarValueChecker(1.0e-6, 1.0e-6));
|
optimizer.setConvergenceChecker(new SimpleScalarValueChecker(1.0e-6, 1.0e-6));
|
||||||
RealPointValuePair optimum =
|
RealPointValuePair optimum =
|
||||||
optimizer.optimize(problem, GoalType.MINIMIZE, new double[] { 0, 0, 0 });
|
optimizer.optimize(problem, GoalType.MINIMIZE, new double[] { 0, 0, 0 });
|
||||||
|
@ -238,7 +238,7 @@ extends TestCase {
|
||||||
}, new double[] { 32, 23, 33, 31 });
|
}, new double[] { 32, 23, 33, 31 });
|
||||||
NonLinearConjugateGradientOptimizer optimizer =
|
NonLinearConjugateGradientOptimizer optimizer =
|
||||||
new NonLinearConjugateGradientOptimizer(ConjugateGradientFormula.POLAK_RIBIERE);
|
new NonLinearConjugateGradientOptimizer(ConjugateGradientFormula.POLAK_RIBIERE);
|
||||||
optimizer.setMaxIterations(100);
|
optimizer.setMaxEvaluations(100);
|
||||||
optimizer.setConvergenceChecker(new SimpleScalarValueChecker(1.0e-13, 1.0e-13));
|
optimizer.setConvergenceChecker(new SimpleScalarValueChecker(1.0e-13, 1.0e-13));
|
||||||
BrentSolver solver = new BrentSolver();
|
BrentSolver solver = new BrentSolver();
|
||||||
solver.setAbsoluteAccuracy(1.0e-15);
|
solver.setAbsoluteAccuracy(1.0e-15);
|
||||||
|
@ -277,7 +277,7 @@ extends TestCase {
|
||||||
|
|
||||||
NonLinearConjugateGradientOptimizer optimizer =
|
NonLinearConjugateGradientOptimizer optimizer =
|
||||||
new NonLinearConjugateGradientOptimizer(ConjugateGradientFormula.POLAK_RIBIERE);
|
new NonLinearConjugateGradientOptimizer(ConjugateGradientFormula.POLAK_RIBIERE);
|
||||||
optimizer.setMaxIterations(100);
|
optimizer.setMaxEvaluations(100);
|
||||||
optimizer.setConvergenceChecker(new SimpleScalarValueChecker(1.0e-6, 1.0e-6));
|
optimizer.setConvergenceChecker(new SimpleScalarValueChecker(1.0e-6, 1.0e-6));
|
||||||
RealPointValuePair optimum =
|
RealPointValuePair optimum =
|
||||||
optimizer.optimize(problem, GoalType.MINIMIZE, new double[] { 7, 6, 5, 4 });
|
optimizer.optimize(problem, GoalType.MINIMIZE, new double[] { 7, 6, 5, 4 });
|
||||||
|
@ -296,7 +296,7 @@ extends TestCase {
|
||||||
}, new double[] { 3.0, 12.0, -1.0, 7.0, 1.0 });
|
}, new double[] { 3.0, 12.0, -1.0, 7.0, 1.0 });
|
||||||
NonLinearConjugateGradientOptimizer optimizer =
|
NonLinearConjugateGradientOptimizer optimizer =
|
||||||
new NonLinearConjugateGradientOptimizer(ConjugateGradientFormula.POLAK_RIBIERE);
|
new NonLinearConjugateGradientOptimizer(ConjugateGradientFormula.POLAK_RIBIERE);
|
||||||
optimizer.setMaxIterations(100);
|
optimizer.setMaxEvaluations(100);
|
||||||
optimizer.setConvergenceChecker(new SimpleScalarValueChecker(1.0e-6, 1.0e-6));
|
optimizer.setConvergenceChecker(new SimpleScalarValueChecker(1.0e-6, 1.0e-6));
|
||||||
RealPointValuePair optimum =
|
RealPointValuePair optimum =
|
||||||
optimizer.optimize(problem, GoalType.MINIMIZE, new double[] { 2, 2, 2, 2, 2, 2 });
|
optimizer.optimize(problem, GoalType.MINIMIZE, new double[] { 2, 2, 2, 2, 2, 2 });
|
||||||
|
@ -312,7 +312,7 @@ extends TestCase {
|
||||||
|
|
||||||
NonLinearConjugateGradientOptimizer optimizer =
|
NonLinearConjugateGradientOptimizer optimizer =
|
||||||
new NonLinearConjugateGradientOptimizer(ConjugateGradientFormula.POLAK_RIBIERE);
|
new NonLinearConjugateGradientOptimizer(ConjugateGradientFormula.POLAK_RIBIERE);
|
||||||
optimizer.setMaxIterations(100);
|
optimizer.setMaxEvaluations(100);
|
||||||
optimizer.setConvergenceChecker(new SimpleScalarValueChecker(1.0e-6, 1.0e-6));
|
optimizer.setConvergenceChecker(new SimpleScalarValueChecker(1.0e-6, 1.0e-6));
|
||||||
RealPointValuePair optimum =
|
RealPointValuePair optimum =
|
||||||
optimizer.optimize(problem, GoalType.MINIMIZE, new double[] { 1, 1 });
|
optimizer.optimize(problem, GoalType.MINIMIZE, new double[] { 1, 1 });
|
||||||
|
@ -330,7 +330,7 @@ extends TestCase {
|
||||||
|
|
||||||
NonLinearConjugateGradientOptimizer optimizer =
|
NonLinearConjugateGradientOptimizer optimizer =
|
||||||
new NonLinearConjugateGradientOptimizer(ConjugateGradientFormula.POLAK_RIBIERE);
|
new NonLinearConjugateGradientOptimizer(ConjugateGradientFormula.POLAK_RIBIERE);
|
||||||
optimizer.setMaxIterations(100);
|
optimizer.setMaxEvaluations(100);
|
||||||
optimizer.setConvergenceChecker(new SimpleScalarValueChecker(1.0e-6, 1.0e-6));
|
optimizer.setConvergenceChecker(new SimpleScalarValueChecker(1.0e-6, 1.0e-6));
|
||||||
RealPointValuePair optimum =
|
RealPointValuePair optimum =
|
||||||
optimizer.optimize(problem, GoalType.MINIMIZE, new double[] { 1, 1 });
|
optimizer.optimize(problem, GoalType.MINIMIZE, new double[] { 1, 1 });
|
||||||
|
@ -347,7 +347,7 @@ extends TestCase {
|
||||||
circle.addPoint( 45.0, 97.0);
|
circle.addPoint( 45.0, 97.0);
|
||||||
NonLinearConjugateGradientOptimizer optimizer =
|
NonLinearConjugateGradientOptimizer optimizer =
|
||||||
new NonLinearConjugateGradientOptimizer(ConjugateGradientFormula.POLAK_RIBIERE);
|
new NonLinearConjugateGradientOptimizer(ConjugateGradientFormula.POLAK_RIBIERE);
|
||||||
optimizer.setMaxIterations(100);
|
optimizer.setMaxEvaluations(100);
|
||||||
optimizer.setConvergenceChecker(new SimpleScalarValueChecker(1.0e-30, 1.0e-30));
|
optimizer.setConvergenceChecker(new SimpleScalarValueChecker(1.0e-30, 1.0e-30));
|
||||||
BrentSolver solver = new BrentSolver();
|
BrentSolver solver = new BrentSolver();
|
||||||
solver.setAbsoluteAccuracy(1.0e-13);
|
solver.setAbsoluteAccuracy(1.0e-13);
|
||||||
|
|
|
@ -48,13 +48,13 @@ public class PowellOptimizerTest {
|
||||||
for (int i = 0; i < dim; i++) {
|
for (int i = 0; i < dim; i++) {
|
||||||
init[i] = minPoint[i];
|
init[i] = minPoint[i];
|
||||||
}
|
}
|
||||||
// doTest(func, minPoint, init, GoalType.MINIMIZE, 1e-5, 1e-9, 1e-7);
|
doTest(func, minPoint, init, GoalType.MINIMIZE, 1e-9, 1e-7);
|
||||||
|
|
||||||
// Initial is far from minimum.
|
// Initial is far from minimum.
|
||||||
for (int i = 0; i < dim; i++) {
|
for (int i = 0; i < dim; i++) {
|
||||||
init[i] = minPoint[i] + 3;
|
init[i] = minPoint[i] + 3;
|
||||||
}
|
}
|
||||||
doTest(func, minPoint, init, GoalType.MINIMIZE, 1e-5, 1e-9, 1e-7);
|
doTest(func, minPoint, init, GoalType.MINIMIZE, 1e-9, 1e-7);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -80,13 +80,13 @@ public class PowellOptimizerTest {
|
||||||
for (int i = 0; i < dim; i++) {
|
for (int i = 0; i < dim; i++) {
|
||||||
init[i] = minPoint[i];
|
init[i] = minPoint[i];
|
||||||
}
|
}
|
||||||
doTest(func, minPoint, init, GoalType.MINIMIZE, 1e-5, 1e-9, 1e-8);
|
doTest(func, minPoint, init, GoalType.MINIMIZE, 1e-9, 1e-8);
|
||||||
|
|
||||||
// Initial is far from minimum.
|
// Initial is far from minimum.
|
||||||
for (int i = 0; i < dim; i++) {
|
for (int i = 0; i < dim; i++) {
|
||||||
init[i] = minPoint[i] - 20;
|
init[i] = minPoint[i] - 20;
|
||||||
}
|
}
|
||||||
doTest(func, minPoint, init, GoalType.MINIMIZE, 1e-5, 1e-9, 1e-8);
|
doTest(func, minPoint, init, GoalType.MINIMIZE, 1e-9, 1e-8);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -112,13 +112,13 @@ public class PowellOptimizerTest {
|
||||||
for (int i = 0; i < dim; i++) {
|
for (int i = 0; i < dim; i++) {
|
||||||
init[i] = maxPoint[i];
|
init[i] = maxPoint[i];
|
||||||
}
|
}
|
||||||
doTest(func, maxPoint, init, GoalType.MAXIMIZE, 1e-5, 1e-9, 1e-8);
|
doTest(func, maxPoint, init, GoalType.MAXIMIZE, 1e-9, 1e-8);
|
||||||
|
|
||||||
// Initial is far from minimum.
|
// Initial is far from minimum.
|
||||||
for (int i = 0; i < dim; i++) {
|
for (int i = 0; i < dim; i++) {
|
||||||
init[i] = maxPoint[i] - 20;
|
init[i] = maxPoint[i] - 20;
|
||||||
}
|
}
|
||||||
doTest(func, maxPoint, init, GoalType.MAXIMIZE, 1e-5, 1e-9, 1e-8);
|
doTest(func, maxPoint, init, GoalType.MAXIMIZE, 1e-9, 1e-8);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -126,8 +126,6 @@ public class PowellOptimizerTest {
|
||||||
* @param optimum Expected optimum.
|
* @param optimum Expected optimum.
|
||||||
* @param init Starting point.
|
* @param init Starting point.
|
||||||
* @param goal Minimization or maximization.
|
* @param goal Minimization or maximization.
|
||||||
* @param xTol Tolerance (relative error on the objective function) for
|
|
||||||
* "Brent" line search algorithm used by "Powell".
|
|
||||||
* @param fTol Tolerance (relative error on the objective function) for
|
* @param fTol Tolerance (relative error on the objective function) for
|
||||||
* "Powell" algorithm.
|
* "Powell" algorithm.
|
||||||
* @param pointTol Tolerance for checking that the optimum is correct.
|
* @param pointTol Tolerance for checking that the optimum is correct.
|
||||||
|
@ -136,12 +134,12 @@ public class PowellOptimizerTest {
|
||||||
double[] optimum,
|
double[] optimum,
|
||||||
double[] init,
|
double[] init,
|
||||||
GoalType goal,
|
GoalType goal,
|
||||||
double xTol,
|
|
||||||
double fTol,
|
double fTol,
|
||||||
double pointTol)
|
double pointTol)
|
||||||
throws MathException {
|
throws MathException {
|
||||||
final MultivariateRealOptimizer optim = new PowellOptimizer(xTol);
|
final MultivariateRealOptimizer optim = new PowellOptimizer();
|
||||||
optim.setConvergenceChecker(new SimpleScalarValueChecker(fTol, -1));
|
optim.setMaxEvaluations(1000);
|
||||||
|
optim.setConvergenceChecker(new SimpleScalarValueChecker(fTol, Math.ulp(1d)));
|
||||||
|
|
||||||
final RealPointValuePair result = optim.optimize(func, goal, init);
|
final RealPointValuePair result = optim.optimize(func, goal, init);
|
||||||
final double[] found = result.getPoint();
|
final double[] found = result.getPoint();
|
||||||
|
|
|
@ -24,6 +24,9 @@ import org.apache.commons.math.optimization.GoalType;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test for {@link BracketFinder}.
|
||||||
|
*/
|
||||||
public class BracketFinderTest {
|
public class BracketFinderTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -70,4 +73,52 @@ public class BracketFinderTest {
|
||||||
Assert.assertEquals(-1, bFind.getMid(), tol);
|
Assert.assertEquals(-1, bFind.getMid(), tol);
|
||||||
Assert.assertEquals(0.61803399999999997, bFind.getHi(), tol);
|
Assert.assertEquals(0.61803399999999997, bFind.getHi(), tol);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMinimumIsOnIntervalBoundary() throws MathException {
|
||||||
|
final UnivariateRealFunction func = new UnivariateRealFunction() {
|
||||||
|
public double value(double x)
|
||||||
|
throws FunctionEvaluationException {
|
||||||
|
return x * x;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
final BracketFinder bFind = new BracketFinder();
|
||||||
|
|
||||||
|
bFind.search(func, GoalType.MINIMIZE, 0, 1);
|
||||||
|
Assert.assertTrue(bFind.getLo() <= 0);
|
||||||
|
Assert.assertTrue(0 <= bFind.getHi());
|
||||||
|
|
||||||
|
bFind.search(func, GoalType.MINIMIZE, -1, 0);
|
||||||
|
Assert.assertTrue(bFind.getLo() <= 0);
|
||||||
|
Assert.assertTrue(0 <= bFind.getHi());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testIntervalBoundsOrdering() throws MathException {
|
||||||
|
final UnivariateRealFunction func = new UnivariateRealFunction() {
|
||||||
|
public double value(double x)
|
||||||
|
throws FunctionEvaluationException {
|
||||||
|
return x * x;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
final BracketFinder bFind = new BracketFinder();
|
||||||
|
|
||||||
|
bFind.search(func, GoalType.MINIMIZE, -1, 1);
|
||||||
|
Assert.assertTrue(bFind.getLo() <= 0);
|
||||||
|
Assert.assertTrue(0 <= bFind.getHi());
|
||||||
|
|
||||||
|
bFind.search(func, GoalType.MINIMIZE, 1, -1);
|
||||||
|
Assert.assertTrue(bFind.getLo() <= 0);
|
||||||
|
Assert.assertTrue(0 <= bFind.getHi());
|
||||||
|
|
||||||
|
bFind.search(func, GoalType.MINIMIZE, 1, 2);
|
||||||
|
Assert.assertTrue(bFind.getLo() <= 0);
|
||||||
|
Assert.assertTrue(0 <= bFind.getHi());
|
||||||
|
|
||||||
|
bFind.search(func, GoalType.MINIMIZE, 2, 1);
|
||||||
|
Assert.assertTrue(bFind.getLo() <= 0);
|
||||||
|
Assert.assertTrue(0 <= bFind.getHi());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,17 +20,14 @@ import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
import static org.junit.Assert.fail;
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
import org.apache.commons.math.FunctionEvaluationException;
|
|
||||||
import org.apache.commons.math.MathException;
|
import org.apache.commons.math.MathException;
|
||||||
import org.apache.commons.math.MaxIterationsExceededException;
|
import org.apache.commons.math.FunctionEvaluationException;
|
||||||
import org.apache.commons.math.exception.NoDataException;
|
import org.apache.commons.math.exception.TooManyEvaluationsException;
|
||||||
import org.apache.commons.math.analysis.QuinticFunction;
|
import org.apache.commons.math.analysis.QuinticFunction;
|
||||||
import org.apache.commons.math.analysis.SinFunction;
|
import org.apache.commons.math.analysis.SinFunction;
|
||||||
import org.apache.commons.math.analysis.UnivariateRealFunction;
|
import org.apache.commons.math.analysis.UnivariateRealFunction;
|
||||||
import org.apache.commons.math.optimization.GoalType;
|
import org.apache.commons.math.optimization.GoalType;
|
||||||
import org.apache.commons.math.optimization.UnivariateRealOptimizer;
|
|
||||||
import org.apache.commons.math.stat.descriptive.DescriptiveStatistics;
|
import org.apache.commons.math.stat.descriptive.DescriptiveStatistics;
|
||||||
import org.apache.commons.math.util.FastMath;
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -41,28 +38,22 @@ public final class BrentOptimizerTest {
|
||||||
@Test
|
@Test
|
||||||
public void testSinMin() throws MathException {
|
public void testSinMin() throws MathException {
|
||||||
UnivariateRealFunction f = new SinFunction();
|
UnivariateRealFunction f = new SinFunction();
|
||||||
UnivariateRealOptimizer minimizer = new BrentOptimizer();
|
UnivariateRealOptimizer optimizer = new BrentOptimizer();
|
||||||
minimizer.setMaxEvaluations(200);
|
optimizer.setConvergenceChecker(new BrentOptimizer.BrentConvergenceChecker(1e-10, 1e-14));
|
||||||
assertEquals(200, minimizer.getMaxEvaluations());
|
optimizer.setMaxEvaluations(200);
|
||||||
|
assertEquals(200, optimizer.getMaxEvaluations());
|
||||||
|
assertEquals(3 * Math.PI / 2, optimizer.optimize(f, GoalType.MINIMIZE, 4, 5).getPoint(),
|
||||||
|
100 * optimizer.getConvergenceChecker().getRelativeThreshold());
|
||||||
|
assertTrue(optimizer.getEvaluations() <= 50);
|
||||||
|
assertEquals(3 * Math.PI / 2, optimizer.optimize(f, GoalType.MINIMIZE, 1, 5).getPoint(),
|
||||||
|
100 * optimizer.getConvergenceChecker().getRelativeThreshold());
|
||||||
|
assertTrue(optimizer.getEvaluations() <= 100);
|
||||||
|
assertTrue(optimizer.getEvaluations() >= 15);
|
||||||
|
optimizer.setMaxEvaluations(10);
|
||||||
try {
|
try {
|
||||||
minimizer.getResult();
|
optimizer.optimize(f, GoalType.MINIMIZE, 4, 5);
|
||||||
fail("an exception should have been thrown");
|
fail("an exception should have been thrown");
|
||||||
} catch (NoDataException ise) {
|
} catch (TooManyEvaluationsException fee) {
|
||||||
// expected
|
|
||||||
} catch (Exception e) {
|
|
||||||
fail("wrong exception caught");
|
|
||||||
}
|
|
||||||
assertEquals(3 * FastMath.PI / 2, minimizer.optimize(f, GoalType.MINIMIZE, 4, 5), 10 * minimizer.getRelativeAccuracy());
|
|
||||||
assertTrue(minimizer.getIterationCount() <= 50);
|
|
||||||
assertEquals(3 * FastMath.PI / 2, minimizer.optimize(f, GoalType.MINIMIZE, 1, 5), 10 * minimizer.getRelativeAccuracy());
|
|
||||||
assertTrue(minimizer.getIterationCount() <= 50);
|
|
||||||
assertTrue(minimizer.getEvaluations() <= 100);
|
|
||||||
assertTrue(minimizer.getEvaluations() >= 15);
|
|
||||||
minimizer.setMaxEvaluations(10);
|
|
||||||
try {
|
|
||||||
minimizer.optimize(f, GoalType.MINIMIZE, 4, 5);
|
|
||||||
fail("an exception should have been thrown");
|
|
||||||
} catch (FunctionEvaluationException fee) {
|
|
||||||
// expected
|
// expected
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
fail("wrong exception caught");
|
fail("wrong exception caught");
|
||||||
|
@ -73,25 +64,27 @@ public final class BrentOptimizerTest {
|
||||||
public void testQuinticMin() throws MathException {
|
public void testQuinticMin() throws MathException {
|
||||||
// The function has local minima at -0.27195613 and 0.82221643.
|
// The function has local minima at -0.27195613 and 0.82221643.
|
||||||
UnivariateRealFunction f = new QuinticFunction();
|
UnivariateRealFunction f = new QuinticFunction();
|
||||||
UnivariateRealOptimizer minimizer = new BrentOptimizer();
|
UnivariateRealOptimizer optimizer = new BrentOptimizer();
|
||||||
assertEquals(-0.27195613, minimizer.optimize(f, GoalType.MINIMIZE, -0.3, -0.2), 1.0e-8);
|
optimizer.setConvergenceChecker(new BrentOptimizer.BrentConvergenceChecker(1e-10, 1e-14));
|
||||||
assertEquals( 0.82221643, minimizer.optimize(f, GoalType.MINIMIZE, 0.3, 0.9), 1.0e-8);
|
optimizer.setMaxEvaluations(200);
|
||||||
assertTrue(minimizer.getIterationCount() <= 50);
|
assertEquals(-0.27195613, optimizer.optimize(f, GoalType.MINIMIZE, -0.3, -0.2).getPoint(), 1.0e-8);
|
||||||
|
assertEquals( 0.82221643, optimizer.optimize(f, GoalType.MINIMIZE, 0.3, 0.9).getPoint(), 1.0e-8);
|
||||||
|
assertTrue(optimizer.getEvaluations() <= 50);
|
||||||
|
|
||||||
// search in a large interval
|
// search in a large interval
|
||||||
assertEquals(-0.27195613, minimizer.optimize(f, GoalType.MINIMIZE, -1.0, 0.2), 1.0e-8);
|
assertEquals(-0.27195613, optimizer.optimize(f, GoalType.MINIMIZE, -1.0, 0.2).getPoint(), 1.0e-8);
|
||||||
assertTrue(minimizer.getIterationCount() <= 50);
|
assertTrue(optimizer.getEvaluations() <= 50);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testQuinticMinStatistics() throws MathException {
|
public void testQuinticMinStatistics() throws MathException {
|
||||||
// The function has local minima at -0.27195613 and 0.82221643.
|
// The function has local minima at -0.27195613 and 0.82221643.
|
||||||
UnivariateRealFunction f = new QuinticFunction();
|
UnivariateRealFunction f = new QuinticFunction();
|
||||||
UnivariateRealOptimizer minimizer = new BrentOptimizer();
|
UnivariateRealOptimizer optimizer = new BrentOptimizer();
|
||||||
minimizer.setRelativeAccuracy(1e-10);
|
optimizer.setConvergenceChecker(new BrentOptimizer.BrentConvergenceChecker(1e-12, 1e-14));
|
||||||
minimizer.setAbsoluteAccuracy(1e-11);
|
optimizer.setMaxEvaluations(40);
|
||||||
|
|
||||||
final DescriptiveStatistics[] stat = new DescriptiveStatistics[3];
|
final DescriptiveStatistics[] stat = new DescriptiveStatistics[2];
|
||||||
for (int i = 0; i < stat.length; i++) {
|
for (int i = 0; i < stat.length; i++) {
|
||||||
stat[i] = new DescriptiveStatistics();
|
stat[i] = new DescriptiveStatistics();
|
||||||
}
|
}
|
||||||
|
@ -102,31 +95,29 @@ public final class BrentOptimizerTest {
|
||||||
final double delta = (max - min) / nSamples;
|
final double delta = (max - min) / nSamples;
|
||||||
for (int i = 0; i < nSamples; i++) {
|
for (int i = 0; i < nSamples; i++) {
|
||||||
final double start = min + i * delta;
|
final double start = min + i * delta;
|
||||||
stat[0].addValue(minimizer.optimize(f, GoalType.MINIMIZE, min, max, start));
|
stat[0].addValue(optimizer.optimize(f, GoalType.MINIMIZE, min, max, start).getPoint());
|
||||||
stat[1].addValue(minimizer.getIterationCount());
|
stat[1].addValue(optimizer.getEvaluations());
|
||||||
stat[2].addValue(minimizer.getEvaluations());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
final double meanOptValue = stat[0].getMean();
|
final double meanOptValue = stat[0].getMean();
|
||||||
final double medianIter = stat[1].getPercentile(50);
|
final double medianEval = stat[1].getPercentile(50);
|
||||||
final double medianEval = stat[2].getPercentile(50);
|
assertTrue(meanOptValue > -0.2719561281 && meanOptValue < -0.2719561280);
|
||||||
assertTrue(meanOptValue > -0.27195612812 && meanOptValue < -0.27195612811);
|
assertEquals((int) medianEval, 27);
|
||||||
assertEquals(medianIter, 17, FastMath.ulp(1d));
|
|
||||||
assertEquals(medianEval, 18, FastMath.ulp(1d));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test(expected = TooManyEvaluationsException.class)
|
||||||
public void testQuinticMax() throws MathException {
|
public void testQuinticMax() throws MathException {
|
||||||
// The quintic function has zeros at 0, +-0.5 and +-1.
|
// The quintic function has zeros at 0, +-0.5 and +-1.
|
||||||
// The function has a local maximum at 0.27195613.
|
// The function has a local maximum at 0.27195613.
|
||||||
UnivariateRealFunction f = new QuinticFunction();
|
UnivariateRealFunction f = new QuinticFunction();
|
||||||
UnivariateRealOptimizer minimizer = new BrentOptimizer();
|
UnivariateRealOptimizer optimizer = new BrentOptimizer();
|
||||||
assertEquals(0.27195613, minimizer.optimize(f, GoalType.MAXIMIZE, 0.2, 0.3), 1.0e-8);
|
optimizer.setConvergenceChecker(new BrentOptimizer.BrentConvergenceChecker(1e-12, 1e-14));
|
||||||
minimizer.setMaximalIterationCount(5);
|
assertEquals(0.27195613, optimizer.optimize(f, GoalType.MAXIMIZE, 0.2, 0.3).getPoint(), 1e-8);
|
||||||
|
optimizer.setMaxEvaluations(5);
|
||||||
try {
|
try {
|
||||||
minimizer.optimize(f, GoalType.MAXIMIZE, 0.2, 0.3);
|
optimizer.optimize(f, GoalType.MAXIMIZE, 0.2, 0.3);
|
||||||
fail("an exception should have been thrown");
|
fail("an exception should have been thrown");
|
||||||
} catch (MaxIterationsExceededException miee) {
|
} catch (TooManyEvaluationsException miee) {
|
||||||
// expected
|
// expected
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
fail("wrong exception caught");
|
fail("wrong exception caught");
|
||||||
|
@ -136,15 +127,15 @@ public final class BrentOptimizerTest {
|
||||||
@Test
|
@Test
|
||||||
public void testMinEndpoints() throws Exception {
|
public void testMinEndpoints() throws Exception {
|
||||||
UnivariateRealFunction f = new SinFunction();
|
UnivariateRealFunction f = new SinFunction();
|
||||||
UnivariateRealOptimizer solver = new BrentOptimizer();
|
UnivariateRealOptimizer optimizer = new BrentOptimizer();
|
||||||
|
optimizer.setConvergenceChecker(new BrentOptimizer.BrentConvergenceChecker(1e-8, 1e-14));
|
||||||
solver.setRelativeAccuracy(1e-8);
|
optimizer.setMaxEvaluations(50);
|
||||||
|
|
||||||
// endpoint is minimum
|
// endpoint is minimum
|
||||||
double result = solver.optimize(f, GoalType.MINIMIZE, 3 * FastMath.PI / 2, 5);
|
double result = optimizer.optimize(f, GoalType.MINIMIZE, 3 * Math.PI / 2, 5).getPoint();
|
||||||
assertEquals(3 * FastMath.PI / 2, result, 10 * solver.getRelativeAccuracy());
|
assertEquals(3 * Math.PI / 2, result, 100 * optimizer.getConvergenceChecker().getRelativeThreshold());
|
||||||
|
|
||||||
result = solver.optimize(f, GoalType.MINIMIZE, 4, 3 * FastMath.PI / 2);
|
result = optimizer.optimize(f, GoalType.MINIMIZE, 4, 3 * Math.PI / 2).getPoint();
|
||||||
assertEquals(3 * FastMath.PI / 2, result, 10 * solver.getRelativeAccuracy());
|
assertEquals(3 * Math.PI / 2, result, 100 * optimizer.getConvergenceChecker().getRelativeThreshold());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.apache.commons.math.optimization;
|
package org.apache.commons.math.optimization.univariate;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
@ -26,6 +26,7 @@ import org.apache.commons.math.analysis.QuinticFunction;
|
||||||
import org.apache.commons.math.analysis.SinFunction;
|
import org.apache.commons.math.analysis.SinFunction;
|
||||||
import org.apache.commons.math.analysis.UnivariateRealFunction;
|
import org.apache.commons.math.analysis.UnivariateRealFunction;
|
||||||
import org.apache.commons.math.optimization.univariate.BrentOptimizer;
|
import org.apache.commons.math.optimization.univariate.BrentOptimizer;
|
||||||
|
import org.apache.commons.math.optimization.GoalType;
|
||||||
import org.apache.commons.math.random.JDKRandomGenerator;
|
import org.apache.commons.math.random.JDKRandomGenerator;
|
||||||
import org.apache.commons.math.util.FastMath;
|
import org.apache.commons.math.util.FastMath;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
@ -36,21 +37,22 @@ public class MultiStartUnivariateRealOptimizerTest {
|
||||||
public void testSinMin() throws MathException {
|
public void testSinMin() throws MathException {
|
||||||
UnivariateRealFunction f = new SinFunction();
|
UnivariateRealFunction f = new SinFunction();
|
||||||
UnivariateRealOptimizer underlying = new BrentOptimizer();
|
UnivariateRealOptimizer underlying = new BrentOptimizer();
|
||||||
|
underlying.setConvergenceChecker(new BrentOptimizer.BrentConvergenceChecker(1e-10, 1e-14));
|
||||||
|
underlying.setMaxEvaluations(300);
|
||||||
JDKRandomGenerator g = new JDKRandomGenerator();
|
JDKRandomGenerator g = new JDKRandomGenerator();
|
||||||
g.setSeed(44428400075l);
|
g.setSeed(44428400075l);
|
||||||
MultiStartUnivariateRealOptimizer minimizer =
|
MultiStartUnivariateRealOptimizer optimizer =
|
||||||
new MultiStartUnivariateRealOptimizer(underlying, 10, g);
|
new MultiStartUnivariateRealOptimizer(underlying, 10, g);
|
||||||
minimizer.optimize(f, GoalType.MINIMIZE, -100.0, 100.0);
|
optimizer.optimize(f, GoalType.MINIMIZE, -100.0, 100.0);
|
||||||
double[] optima = minimizer.getOptima();
|
UnivariateRealPointValuePair[] optima = optimizer.getOptima();
|
||||||
double[] optimaValues = minimizer.getOptimaValues();
|
|
||||||
for (int i = 1; i < optima.length; ++i) {
|
for (int i = 1; i < optima.length; ++i) {
|
||||||
double d = (optima[i] - optima[i-1]) / (2 * FastMath.PI);
|
double d = (optima[i].getPoint() - optima[i-1].getPoint()) / (2 * FastMath.PI);
|
||||||
assertTrue (FastMath.abs(d - FastMath.rint(d)) < 1.0e-8);
|
assertTrue (FastMath.abs(d - FastMath.rint(d)) < 1.0e-8);
|
||||||
assertEquals(-1.0, f.value(optima[i]), 1.0e-10);
|
assertEquals(-1.0, f.value(optima[i].getPoint()), 1.0e-10);
|
||||||
assertEquals(f.value(optima[i]), optimaValues[i], 1.0e-10);
|
assertEquals(f.value(optima[i].getPoint()), optima[i].getValue(), 1.0e-10);
|
||||||
}
|
}
|
||||||
assertTrue(minimizer.getEvaluations() > 150);
|
assertTrue(optimizer.getEvaluations() > 150);
|
||||||
assertTrue(minimizer.getEvaluations() < 250);
|
assertTrue(optimizer.getEvaluations() < 250);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -59,44 +61,23 @@ public class MultiStartUnivariateRealOptimizerTest {
|
||||||
// The function has extrema (first derivative is zero) at 0.27195613 and 0.82221643,
|
// The function has extrema (first derivative is zero) at 0.27195613 and 0.82221643,
|
||||||
UnivariateRealFunction f = new QuinticFunction();
|
UnivariateRealFunction f = new QuinticFunction();
|
||||||
UnivariateRealOptimizer underlying = new BrentOptimizer();
|
UnivariateRealOptimizer underlying = new BrentOptimizer();
|
||||||
underlying.setRelativeAccuracy(1e-15);
|
underlying.setConvergenceChecker(new BrentOptimizer.BrentConvergenceChecker(1e-9, 1e-14));
|
||||||
|
underlying.setMaxEvaluations(300);
|
||||||
JDKRandomGenerator g = new JDKRandomGenerator();
|
JDKRandomGenerator g = new JDKRandomGenerator();
|
||||||
g.setSeed(4312000053L);
|
g.setSeed(4312000053L);
|
||||||
MultiStartUnivariateRealOptimizer minimizer =
|
MultiStartUnivariateRealOptimizer optimizer =
|
||||||
new MultiStartUnivariateRealOptimizer(underlying, 5, g);
|
new MultiStartUnivariateRealOptimizer(underlying, 5, g);
|
||||||
minimizer.setAbsoluteAccuracy(10 * minimizer.getAbsoluteAccuracy());
|
|
||||||
minimizer.setRelativeAccuracy(10 * minimizer.getRelativeAccuracy());
|
|
||||||
|
|
||||||
try {
|
UnivariateRealPointValuePair optimum
|
||||||
minimizer.getOptima();
|
= optimizer.optimize(f, GoalType.MINIMIZE, -0.3, -0.2);
|
||||||
fail("an exception should have been thrown");
|
assertEquals(-0.2719561271, optimum.getPoint(), 1e-9);
|
||||||
} catch (IllegalStateException ise) {
|
assertEquals(-0.0443342695, optimum.getValue(), 1e-9);
|
||||||
// expected
|
|
||||||
} catch (Exception e) {
|
|
||||||
fail("wrong exception caught");
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
minimizer.getOptimaValues();
|
|
||||||
fail("an exception should have been thrown");
|
|
||||||
} catch (IllegalStateException ise) {
|
|
||||||
// expected
|
|
||||||
} catch (Exception e) {
|
|
||||||
fail("wrong exception caught");
|
|
||||||
}
|
|
||||||
|
|
||||||
double result = minimizer.optimize(f, GoalType.MINIMIZE, -0.3, -0.2);
|
UnivariateRealPointValuePair[] optima = optimizer.getOptima();
|
||||||
assertEquals(-0.2719561270319131, result, 1.0e-13);
|
|
||||||
assertEquals(-0.2719561270319131, minimizer.getResult(), 1.0e-13);
|
|
||||||
assertEquals(-0.04433426954946637, minimizer.getFunctionValue(), 1.0e-13);
|
|
||||||
|
|
||||||
double[] optima = minimizer.getOptima();
|
|
||||||
double[] optimaValues = minimizer.getOptimaValues();
|
|
||||||
for (int i = 0; i < optima.length; ++i) {
|
for (int i = 0; i < optima.length; ++i) {
|
||||||
assertEquals(f.value(optima[i]), optimaValues[i], 1.0e-10);
|
assertEquals(f.value(optima[i].getPoint()), optima[i].getValue(), 1e-9);
|
||||||
}
|
}
|
||||||
assertTrue(minimizer.getEvaluations() >= 120);
|
assertTrue(optimizer.getEvaluations() >= 110);
|
||||||
assertTrue(minimizer.getEvaluations() <= 170);
|
assertTrue(optimizer.getEvaluations() <= 150);
|
||||||
assertTrue(minimizer.getIterationCount() >= 120);
|
|
||||||
assertTrue(minimizer.getIterationCount() <= 170);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue