New interface and abstract base class for separate support of unconstrained
and simple bounds constraints optimizers.


git-svn-id: https://svn.apache.org/repos/asf/commons/proper/math/trunk@1202140 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Gilles Sadowski 2011-11-15 11:47:25 +00:00
parent 3ad3a1fa41
commit 754434a4c0
9 changed files with 197 additions and 126 deletions

View File

@ -137,16 +137,6 @@ public class BaseMultiStartMultivariateRealOptimizer<FUNC extends MultivariateRe
public RealPointValuePair optimize(int maxEval, final FUNC f,
final GoalType goal,
double[] startPoint) {
return optimize(maxEval, f, goal, startPoint, null, null);
}
/**
* {@inheritDoc}
*/
public RealPointValuePair optimize(int maxEval, final FUNC f,
final GoalType goal,
double[] startPoint,
double[] lowerBound, double[] upperBound) {
maxEvaluations = maxEval;
RuntimeException lastException = null;
optima = new RealPointValuePair[starts];
@ -157,8 +147,7 @@ public class BaseMultiStartMultivariateRealOptimizer<FUNC extends MultivariateRe
// CHECKSTYLE: stop IllegalCatch
try {
optima[i] = optimizer.optimize(maxEval - totalEvaluations, f, goal,
i == 0 ? startPoint : generator.nextVector(),
lowerBound, upperBound);
i == 0 ? startPoint : generator.nextVector());
} catch (RuntimeException mue) {
lastException = mue;
optima[i] = null;

View File

@ -54,31 +54,4 @@ public interface BaseMultivariateRealOptimizer<FUNC extends MultivariateRealFunc
*/
RealPointValuePair optimize(int maxEval, FUNC f, GoalType goalType,
double[] startPoint);
/**
* Optimize an objective function.
*
* @param f Objective function.
* @param goalType Type of optimization goal: either
* {@link GoalType#MAXIMIZE} or {@link GoalType#MINIMIZE}.
* @param startPoint Start point for optimization.
* @param maxEval Maximum number of function evaluations.
* @param lowerBound Lower bound for each of the parameters.
* @param upperBound Upper bound for each of the parameters.
* @return the point/value pair giving the optimal value for objective
* function.
* @throws org.apache.commons.math.exception.DimensionMismatchException
* if the array sizes are wrong.
* @throws org.apache.commons.math.exception.TooManyEvaluationsException
* if the maximal number of evaluations is exceeded.
* @throws org.apache.commons.math.exception.NullArgumentException if
* {@code f}, {@code goalType} or {@code startPoint} is {@code null}.
* @throws org.apache.commons.math.exception.NumberIsTooSmallException if any
* of the initial values is less than its lower bound.
* @throws org.apache.commons.math.exception.NumberIsTooLargeException if any
* of the initial values is greater than its upper bound.
*/
RealPointValuePair optimize(int maxEval, FUNC f, GoalType goalType,
double[] startPoint,
double[] lowerBound, double[] upperBound);
}

View File

@ -0,0 +1,64 @@
/*
* 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.analysis.MultivariateRealFunction;
/**
* This interface is mainly intended to enforce the internal coherence of
* Commons-FastMath. 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>
* </ul>
*
* @param <FUNC> Type of the objective function to be optimized.
*
* @version $Id$
* @since 3.0
*/
public interface BaseSimpleBoundsMultivariateRealOptimizer<FUNC extends MultivariateRealFunction>
extends BaseMultivariateRealOptimizer<FUNC> {
/**
* Optimize an objective function.
*
* @param f Objective function.
* @param goalType Type of optimization goal: either
* {@link GoalType#MAXIMIZE} or {@link GoalType#MINIMIZE}.
* @param startPoint Start point for optimization.
* @param maxEval Maximum number of function evaluations.
* @param lowerBound Lower bound for each of the parameters.
* @param upperBound Upper bound for each of the parameters.
* @return the point/value pair giving the optimal value for objective
* function.
* @throws org.apache.commons.math.exception.DimensionMismatchException
* if the array sizes are wrong.
* @throws org.apache.commons.math.exception.TooManyEvaluationsException
* if the maximal number of evaluations is exceeded.
* @throws org.apache.commons.math.exception.NullArgumentException if
* {@code f}, {@code goalType} or {@code startPoint} is {@code null}.
* @throws org.apache.commons.math.exception.NumberIsTooSmallException if any
* of the initial values is less than its lower bound.
* @throws org.apache.commons.math.exception.NumberIsTooLargeException if any
* of the initial values is greater than its upper bound.
*/
RealPointValuePair optimize(int maxEval, FUNC f, GoalType goalType,
double[] startPoint,
double[] lowerBound, double[] upperBound);
}

View File

@ -28,8 +28,9 @@ import org.apache.commons.math.linear.Array2DRowRealMatrix;
import org.apache.commons.math.linear.ArrayRealVector;
import org.apache.commons.math.linear.RealVector;
import org.apache.commons.math.optimization.GoalType;
import org.apache.commons.math.optimization.MultivariateRealOptimizer;
import org.apache.commons.math.optimization.BaseSimpleBoundsMultivariateRealOptimizer;
import org.apache.commons.math.optimization.RealPointValuePair;
import org.apache.commons.math.optimization.MultivariateRealOptimizer;
/**
* Powell's BOBYQA algorithm. This implementation is translated and
@ -50,7 +51,7 @@ import org.apache.commons.math.optimization.RealPointValuePair;
* @since 3.0
*/
public class BOBYQAOptimizer
extends BaseAbstractScalarOptimizer<MultivariateRealFunction>
extends BaseAbstractSimpleBoundsScalarOptimizer<MultivariateRealFunction>
implements MultivariateRealOptimizer {
/** Minimum dimension of the problem: {@value} */
public static final int MINIMUM_PROBLEM_DIMENSION = 2;

View File

@ -21,9 +21,6 @@ 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.NullArgumentException;
import org.apache.commons.math.exception.DimensionMismatchException;
import org.apache.commons.math.exception.NumberIsTooSmallException;
import org.apache.commons.math.exception.NumberIsTooLargeException;
import org.apache.commons.math.analysis.MultivariateRealFunction;
import org.apache.commons.math.optimization.BaseMultivariateRealOptimizer;
import org.apache.commons.math.optimization.GoalType;
@ -36,7 +33,7 @@ import org.apache.commons.math.optimization.SimpleScalarValueChecker;
* This base class handles the boiler-plate methods associated to thresholds
* settings, iterations and evaluations counting.
*
* @param <FUNC> Type of the objective function to be optimized
* @param <FUNC> Type of the objective function to be optimized.
*
* @version $Id$
* @since 2.2
@ -51,10 +48,6 @@ public abstract class BaseAbstractScalarOptimizer<FUNC extends MultivariateRealF
private GoalType goal;
/** Initial guess. */
private double[] start;
/** Lower bounds. */
private double[] lowerBound;
/** Upper bounds. */
private double[] upperBound;
/** Objective function. */
private MultivariateRealFunction function;
@ -108,13 +101,6 @@ public abstract class BaseAbstractScalarOptimizer<FUNC extends MultivariateRealF
/** {@inheritDoc} */
public RealPointValuePair optimize(int maxEval, FUNC f, GoalType goalType,
double[] startPoint) {
return optimize(maxEval, f, goalType, startPoint, null, null);
}
/** {@inheritDoc} */
public RealPointValuePair optimize(int maxEval, FUNC f, GoalType goalType,
double[] startPoint,
double[] lower, double[] upper) {
// Checks.
if (f == null) {
throw new NullArgumentException();
@ -125,31 +111,6 @@ public abstract class BaseAbstractScalarOptimizer<FUNC extends MultivariateRealF
if (startPoint == null) {
throw new NullArgumentException();
}
final int dim = startPoint.length;
if (lower != null) {
if (lower.length != dim) {
throw new DimensionMismatchException(lower.length, dim);
}
for (int i = 0; i < dim; i++) {
final double v = startPoint[i];
final double lo = lower[i];
if (v < lo) {
throw new NumberIsTooSmallException(v, lo, true);
}
}
}
if (upper != null) {
if (upper.length != dim) {
throw new DimensionMismatchException(upper.length, dim);
}
for (int i = 0; i < dim; i++) {
final double v = startPoint[i];
final double hi = upper[i];
if (v > hi) {
throw new NumberIsTooLargeException(v, hi, true);
}
}
}
// Reset.
evaluations.setMaximalCount(maxEval);
@ -160,23 +121,6 @@ public abstract class BaseAbstractScalarOptimizer<FUNC extends MultivariateRealF
goal = goalType;
start = startPoint.clone();
if (lower == null) {
lowerBound = new double[dim];
for (int i = 0; i < dim; i++) {
lowerBound[i] = Double.NEGATIVE_INFINITY;
}
} else {
lowerBound = lower.clone();
}
if (upper == null) {
upperBound = new double[dim];
for (int i = 0; i < dim; i++) {
upperBound[i] = Double.POSITIVE_INFINITY;
}
} else {
upperBound = upper.clone();
}
// Perform computation.
return doOptimize();
}
@ -195,20 +139,6 @@ public abstract class BaseAbstractScalarOptimizer<FUNC extends MultivariateRealF
return start.clone();
}
/**
* @return the lower bounds.
*/
public double[] getLowerBound() {
return lowerBound.clone();
}
/**
* @return the upper bounds.
*/
public double[] getUpperBound() {
return upperBound.clone();
}
/**
* Perform the bulk of the optimization algorithm.
*

View File

@ -0,0 +1,122 @@
/*
* 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.direct;
import org.apache.commons.math.analysis.MultivariateRealFunction;
import org.apache.commons.math.optimization.BaseMultivariateRealOptimizer;
import org.apache.commons.math.optimization.BaseSimpleBoundsMultivariateRealOptimizer;
import org.apache.commons.math.optimization.GoalType;
import org.apache.commons.math.optimization.RealPointValuePair;
import org.apache.commons.math.exception.DimensionMismatchException;
import org.apache.commons.math.exception.NumberIsTooSmallException;
import org.apache.commons.math.exception.NumberIsTooLargeException;
/**
* Base class for implementing optimizers for multivariate scalar functions,
* subject to simple bounds: The valid range of the parameters is an interval.
* The interval can possibly be infinite (in one or both directions).
* This base class handles the boiler-plate methods associated to thresholds
* settings, iterations and evaluations counting.
*
* @param <FUNC> Type of the objective function to be optimized.
*
* @version $Id$
* @since 3.0
*/
public abstract class BaseAbstractSimpleBoundsScalarOptimizer<FUNC extends MultivariateRealFunction>
extends BaseAbstractScalarOptimizer<FUNC>
implements BaseMultivariateRealOptimizer<FUNC>,
BaseSimpleBoundsMultivariateRealOptimizer<FUNC> {
/** Lower bounds. */
private double[] lowerBound;
/** Upper bounds. */
private double[] upperBound;
/**
* @return the lower bounds.
*/
public double[] getLowerBound() {
return lowerBound.clone();
}
/**
* @return the upper bounds.
*/
public double[] getUpperBound() {
return upperBound.clone();
}
/** {@inheritDoc} */
public RealPointValuePair optimize(int maxEval, FUNC f, GoalType goalType,
double[] startPoint) {
return optimize(maxEval, f, goalType, startPoint, null, null);
}
/** {@inheritDoc} */
public RealPointValuePair optimize(int maxEval, FUNC f, GoalType goalType,
double[] startPoint,
double[] lower, double[] upper) {
// Checks.
final int dim = startPoint.length;
if (lower != null) {
if (lower.length != dim) {
throw new DimensionMismatchException(lower.length, dim);
}
for (int i = 0; i < dim; i++) {
final double v = startPoint[i];
final double lo = lower[i];
if (v < lo) {
throw new NumberIsTooSmallException(v, lo, true);
}
}
}
if (upper != null) {
if (upper.length != dim) {
throw new DimensionMismatchException(upper.length, dim);
}
for (int i = 0; i < dim; i++) {
final double v = startPoint[i];
final double hi = upper[i];
if (v > hi) {
throw new NumberIsTooLargeException(v, hi, true);
}
}
}
// Initialization.
if (lower == null) {
lowerBound = new double[dim];
for (int i = 0; i < dim; i++) {
lowerBound[i] = Double.NEGATIVE_INFINITY;
}
} else {
lowerBound = lower.clone();
}
if (upper == null) {
upperBound = new double[dim];
for (int i = 0; i < dim; i++) {
upperBound[i] = Double.POSITIVE_INFINITY;
}
} else {
upperBound = upper.clone();
}
// Base class method performs the non bound-specific initializations.
return super.optimize(maxEval, f, goalType, startPoint);
}
}

View File

@ -73,21 +73,9 @@ public abstract class AbstractScalarDifferentiableOptimizer
final DifferentiableMultivariateRealFunction f,
final GoalType goalType,
final double[] startPoint) {
return optimize(maxEval, f, goalType, startPoint, null, null);
}
/** {@inheritDoc} */
@Override
public RealPointValuePair optimize(int maxEval,
final DifferentiableMultivariateRealFunction f,
final GoalType goalType,
final double[] startPoint,
double[] lowerBound, double[] upperBound) {
// Store optimization problem characteristics.
gradient = f.gradient();
return super.optimize(maxEval, f, goalType,
startPoint,
lowerBound, upperBound);
return super.optimize(maxEval, f, goalType, startPoint);
}
}

View File

@ -52,6 +52,10 @@ The <action> type attribute can be add,update,fix,remove.
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-697">
Added interface and abstract class for supporting optimizers classes
that can take simple constraints into account.
</action>
<action dev="luc" type="fix" due-to="MATH-706" >
Fixed a bad interaction between step handlers and event handlers in
ODE integrators.

View File

@ -259,7 +259,7 @@ public class BOBYQAOptimizerTest {
// RealPointValuePair result = optim.optimize(100000, func, goal, startPoint);
final double[] lB = boundaries == null ? null : boundaries[0];
final double[] uB = boundaries == null ? null : boundaries[1];
MultivariateRealOptimizer optim = new BOBYQAOptimizer(2 * dim + 1);
BOBYQAOptimizer optim = new BOBYQAOptimizer(2 * dim + 1);
RealPointValuePair result = optim.optimize(maxEvaluations, func, goal, startPoint, lB, uB);
// System.out.println(func.getClass().getName() + " = "
// + optim.getEvaluations() + " f(");