fixed an error in multistart univariate optimizer:
the optima found were sorted according to the independant variable x, not according to the function value y git-svn-id: https://svn.apache.org/repos/asf/commons/proper/math/trunk@797785 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
48d014dac1
commit
4e2dd4df1f
|
@ -17,8 +17,6 @@
|
||||||
|
|
||||||
package org.apache.commons.math.optimization;
|
package org.apache.commons.math.optimization;
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
|
|
||||||
import org.apache.commons.math.ConvergenceException;
|
import org.apache.commons.math.ConvergenceException;
|
||||||
import org.apache.commons.math.FunctionEvaluationException;
|
import org.apache.commons.math.FunctionEvaluationException;
|
||||||
import org.apache.commons.math.MathRuntimeException;
|
import org.apache.commons.math.MathRuntimeException;
|
||||||
|
@ -65,6 +63,9 @@ public class MultiStartUnivariateRealOptimizer implements UnivariateRealOptimize
|
||||||
/** Found optima. */
|
/** Found optima. */
|
||||||
private double[] optima;
|
private double[] optima;
|
||||||
|
|
||||||
|
/** Found function values at optima. */
|
||||||
|
private double[] optimaValues;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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 optimizer single-start optimizer to wrap
|
||||||
|
@ -175,16 +176,17 @@ public class MultiStartUnivariateRealOptimizer implements UnivariateRealOptimize
|
||||||
* in the constructor. It is ordered with the results from the
|
* in the constructor. It is ordered with the results from the
|
||||||
* runs that did converge first, sorted from best to worst
|
* runs that did converge first, sorted from best to worst
|
||||||
* objective value (i.e in ascending order if minimizing and in
|
* objective value (i.e in ascending order if minimizing and in
|
||||||
* descending order if maximizing), followed by and null elements
|
* descending order if maximizing), followed by Double.NaN elements
|
||||||
* corresponding to the runs that did not converge. This means all
|
* corresponding to the runs that did not converge. This means all
|
||||||
* elements will be null if the {@link #optimize(UnivariateRealFunction,
|
* elements will be NaN if the {@link #optimize(UnivariateRealFunction,
|
||||||
* GoalType, double, double) optimize} method did throw a {@link
|
* GoalType, double, double) optimize} method did throw a {@link
|
||||||
* ConvergenceException ConvergenceException}). This also means that
|
* ConvergenceException ConvergenceException}). This also means that
|
||||||
* if the first element is non null, it is the best point found across
|
* if the first element is not NaN, it is the best point found across
|
||||||
* all starts.</p>
|
* all starts.</p>
|
||||||
* @return array containing the optima
|
* @return array containing the optima
|
||||||
* @exception IllegalStateException if {@link #optimize(UnivariateRealFunction,
|
* @exception IllegalStateException if {@link #optimize(UnivariateRealFunction,
|
||||||
* GoalType, double, double) optimize} has not been called
|
* GoalType, double, double) optimize} has not been called
|
||||||
|
* @see #getOptimaValues()
|
||||||
*/
|
*/
|
||||||
public double[] getOptima() throws IllegalStateException {
|
public double[] getOptima() throws IllegalStateException {
|
||||||
if (optima == null) {
|
if (optima == null) {
|
||||||
|
@ -193,6 +195,32 @@ public class MultiStartUnivariateRealOptimizer implements UnivariateRealOptimize
|
||||||
return optima.clone();
|
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("no optimum computed yet");
|
||||||
|
}
|
||||||
|
return optimaValues.clone();
|
||||||
|
}
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
/** {@inheritDoc} */
|
||||||
public double optimize(final UnivariateRealFunction f, final GoalType goalType,
|
public double optimize(final UnivariateRealFunction f, final GoalType goalType,
|
||||||
final double min, final double max)
|
final double min, final double max)
|
||||||
|
@ -200,6 +228,7 @@ public class MultiStartUnivariateRealOptimizer implements UnivariateRealOptimize
|
||||||
FunctionEvaluationException {
|
FunctionEvaluationException {
|
||||||
|
|
||||||
optima = new double[starts];
|
optima = new double[starts];
|
||||||
|
optimaValues = new double[starts];
|
||||||
totalIterations = 0;
|
totalIterations = 0;
|
||||||
totalEvaluations = 0;
|
totalEvaluations = 0;
|
||||||
|
|
||||||
|
@ -211,13 +240,16 @@ public class MultiStartUnivariateRealOptimizer implements UnivariateRealOptimize
|
||||||
optimizer.setMaxEvaluations(maxEvaluations - totalEvaluations);
|
optimizer.setMaxEvaluations(maxEvaluations - totalEvaluations);
|
||||||
final double bound1 = min + generator.nextDouble() * (max - min);
|
final double bound1 = min + generator.nextDouble() * (max - min);
|
||||||
final double bound2 = min + generator.nextDouble() * (max - min);
|
final double bound2 = min + generator.nextDouble() * (max - min);
|
||||||
optima[i] = optimizer.optimize(f, goalType,
|
optima[i] = optimizer.optimize(f, goalType,
|
||||||
Math.min(bound1, bound2),
|
Math.min(bound1, bound2),
|
||||||
Math.max(bound1, bound2));
|
Math.max(bound1, bound2));
|
||||||
|
optimaValues[i] = optimizer.getFunctionValue();
|
||||||
} catch (FunctionEvaluationException fee) {
|
} catch (FunctionEvaluationException fee) {
|
||||||
optima[i] = Double.NaN;
|
optima[i] = Double.NaN;
|
||||||
|
optimaValues[i] = Double.NaN;
|
||||||
} catch (ConvergenceException ce) {
|
} catch (ConvergenceException ce) {
|
||||||
optima[i] = Double.NaN;
|
optima[i] = Double.NaN;
|
||||||
|
optimaValues[i] = Double.NaN;
|
||||||
}
|
}
|
||||||
|
|
||||||
totalIterations += optimizer.getIterationCount();
|
totalIterations += optimizer.getIterationCount();
|
||||||
|
@ -231,14 +263,37 @@ public class MultiStartUnivariateRealOptimizer implements UnivariateRealOptimize
|
||||||
if (Double.isNaN(optima[i])) {
|
if (Double.isNaN(optima[i])) {
|
||||||
optima[i] = optima[--lastNaN];
|
optima[i] = optima[--lastNaN];
|
||||||
optima[lastNaN + 1] = Double.NaN;
|
optima[lastNaN + 1] = Double.NaN;
|
||||||
|
optimaValues[i] = optimaValues[--lastNaN];
|
||||||
|
optimaValues[lastNaN + 1] = Double.NaN;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Arrays.sort(optima, 0, lastNaN);
|
|
||||||
if (goalType == GoalType.MAXIMIZE) {
|
double currX = optima[0];
|
||||||
for (int i = 0, j = lastNaN - 1; i < j; ++i, --j) {
|
double currY = optimaValues[0];
|
||||||
double tmp = optima[i];
|
for (int j = 1; j < lastNaN; ++j) {
|
||||||
optima[i] = optima[j];
|
final double prevY = currY;
|
||||||
optima[j] = tmp;
|
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];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue