MATH-868
MATH-879 "lambda" and "inputSigma" should be passed to "optimize" as arguments of type "OptimizationData". Deprecated constructors. Updated unit tests. git-svn-id: https://svn.apache.org/repos/asf/commons/proper/math/trunk@1400108 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
ea138c2da2
commit
0912bac520
|
@ -24,6 +24,7 @@ import java.util.List;
|
|||
import org.apache.commons.math3.analysis.MultivariateFunction;
|
||||
import org.apache.commons.math3.exception.DimensionMismatchException;
|
||||
import org.apache.commons.math3.exception.NotPositiveException;
|
||||
import org.apache.commons.math3.exception.NotStrictlyPositiveException;
|
||||
import org.apache.commons.math3.exception.OutOfRangeException;
|
||||
import org.apache.commons.math3.exception.TooManyEvaluationsException;
|
||||
import org.apache.commons.math3.linear.Array2DRowRealMatrix;
|
||||
|
@ -225,6 +226,10 @@ public class CMAESOptimizer
|
|||
|
||||
/**
|
||||
* Default constructor, uses default parameters
|
||||
*
|
||||
* @deprecated As of version 3.1: Parameter {@code lambda} must be
|
||||
* passed with the call to {@link #optimize(int,MultivariateFunction,GoalType,OptimizationData[])
|
||||
* optimize} (whereas in the current code it is set to an undocumented value).
|
||||
*/
|
||||
public CMAESOptimizer() {
|
||||
this(0);
|
||||
|
@ -232,9 +237,12 @@ public class CMAESOptimizer
|
|||
|
||||
/**
|
||||
* @param lambda Population size.
|
||||
* @deprecated As of version 3.1: Parameter {@code lambda} must be
|
||||
* passed with the call to {@link #optimize(int,MultivariateFunction,GoalType,OptimizationData[])
|
||||
* optimize} (whereas in the current code it is set to an undocumented value)..
|
||||
*/
|
||||
public CMAESOptimizer(int lambda) {
|
||||
this(lambda, DEFAULT_MAXITERATIONS, DEFAULT_STOPFITNESS,
|
||||
this(lambda, null, DEFAULT_MAXITERATIONS, DEFAULT_STOPFITNESS,
|
||||
DEFAULT_ISACTIVECMA, DEFAULT_DIAGONALONLY,
|
||||
DEFAULT_CHECKFEASABLECOUNT, DEFAULT_RANDOMGENERATOR,
|
||||
false, null);
|
||||
|
@ -244,7 +252,7 @@ public class CMAESOptimizer
|
|||
* @param lambda Population size.
|
||||
* @param inputSigma Initial standard deviations to sample new points
|
||||
* around the initial guess.
|
||||
* @deprecated As of version 3.1: Parameter {@code inputSigma} must be
|
||||
* @deprecated As of version 3.1: Parameters {@code lambda} and {@code inputSigma} must be
|
||||
* passed with the call to {@link #optimize(int,MultivariateFunction,GoalType,OptimizationData[])
|
||||
* optimize}.
|
||||
*/
|
||||
|
@ -296,7 +304,7 @@ public class CMAESOptimizer
|
|||
* @param random Random generator.
|
||||
* @param generateStatistics Whether statistic data is collected.
|
||||
* @param checker Convergence checker.
|
||||
* @deprecated As of version 3.1: Parameter {@code inputSigma} must be
|
||||
* @deprecated As of version 3.1: Parameters {@code lambda} and {@code inputSigma} must be
|
||||
* passed with the call to {@link #optimize(int,MultivariateFunction,GoalType,OptimizationData[])
|
||||
* optimize}.
|
||||
*/
|
||||
|
@ -319,7 +327,6 @@ public class CMAESOptimizer
|
|||
}
|
||||
|
||||
/**
|
||||
* @param lambda Population size.
|
||||
* @param maxIterations Maximal number of iterations.
|
||||
* @param stopFitness Whether to stop if objective function value is smaller than
|
||||
* {@code stopFitness}.
|
||||
|
@ -331,9 +338,10 @@ public class CMAESOptimizer
|
|||
* @param random Random generator.
|
||||
* @param generateStatistics Whether statistic data is collected.
|
||||
* @param checker Convergence checker.
|
||||
*
|
||||
* @since 3.1
|
||||
*/
|
||||
public CMAESOptimizer(int lambda,
|
||||
int maxIterations,
|
||||
public CMAESOptimizer(int maxIterations,
|
||||
double stopFitness,
|
||||
boolean isActiveCMA,
|
||||
int diagonalOnly,
|
||||
|
@ -342,7 +350,6 @@ public class CMAESOptimizer
|
|||
boolean generateStatistics,
|
||||
ConvergenceChecker<PointValuePair> checker) {
|
||||
super(checker);
|
||||
this.lambda = lambda;
|
||||
this.maxIterations = maxIterations;
|
||||
this.stopFitness = stopFitness;
|
||||
this.isActiveCMA = isActiveCMA;
|
||||
|
@ -397,8 +404,17 @@ public class CMAESOptimizer
|
|||
|
||||
/**
|
||||
* @param s Sigma values.
|
||||
* @throws NotPositiveException if any of the array entries is smaller
|
||||
* than zero.
|
||||
*/
|
||||
public Sigma(double[] s) {
|
||||
public Sigma(double[] s)
|
||||
throws NotPositiveException {
|
||||
for (int i = 0; i < s.length; i++) {
|
||||
if (s[i] < 0) {
|
||||
throw new NotPositiveException(s[i]);
|
||||
}
|
||||
}
|
||||
|
||||
sigma = s.clone();
|
||||
}
|
||||
|
||||
|
@ -410,6 +426,40 @@ public class CMAESOptimizer
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Population size.
|
||||
* The number of offspring is the primary strategy parameter.
|
||||
* In the absence of better clues, a good default could be an
|
||||
* integer close to {@code 4 + 3 ln(n)}, where {@code n} is the
|
||||
* number of optimized parameters.
|
||||
* Increasing the population size improves global search properties
|
||||
* at the expense of speed (which in general decreases at most
|
||||
* linearly with increasing population size).
|
||||
*/
|
||||
public static class PopulationSize implements OptimizationData {
|
||||
/** Population size. */
|
||||
private final int lambda;
|
||||
|
||||
/**
|
||||
* @param size Population size.
|
||||
* @throws NotStrictlyPositiveException if {@code size <= 0}.
|
||||
*/
|
||||
public PopulationSize(int size)
|
||||
throws NotStrictlyPositiveException {
|
||||
if (size <= 0) {
|
||||
throw new NotStrictlyPositiveException(size);
|
||||
}
|
||||
lambda = size;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the population size.
|
||||
*/
|
||||
public int getPopulationSize() {
|
||||
return lambda;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Optimize an objective function.
|
||||
*
|
||||
|
@ -420,6 +470,7 @@ public class CMAESOptimizer
|
|||
* <ul>
|
||||
* <li>{@link org.apache.commons.math3.optimization.InitialGuess InitialGuess}</li>
|
||||
* <li>{@link Sigma}</li>
|
||||
* <li>{@link PopulationSize}</li>
|
||||
* </ul>
|
||||
* @return the point/value pair giving the optimal value for objective
|
||||
* function.
|
||||
|
@ -593,6 +644,7 @@ public class CMAESOptimizer
|
|||
* @param optData Optimization data. The following data will be looked for:
|
||||
* <ul>
|
||||
* <li>{@link Sigma}</li>
|
||||
* <li>{@link PopulationSize}</li>
|
||||
* </ul>
|
||||
*/
|
||||
private void parseOptimizationData(OptimizationData... optData) {
|
||||
|
@ -603,6 +655,10 @@ public class CMAESOptimizer
|
|||
inputSigma = ((Sigma) data).getSigma();
|
||||
continue;
|
||||
}
|
||||
if (data instanceof PopulationSize) {
|
||||
lambda = ((PopulationSize) data).getPopulationSize();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -620,6 +676,7 @@ public class CMAESOptimizer
|
|||
}
|
||||
for (int i = 0; i < init.length; i++) {
|
||||
if (inputSigma[i] < 0) {
|
||||
// XXX Remove this block in 4.0 (check performed in "Sigma" class).
|
||||
throw new NotPositiveException(inputSigma[i]);
|
||||
}
|
||||
if (inputSigma[i] > uB[i] - lB[i]) {
|
||||
|
@ -636,11 +693,15 @@ public class CMAESOptimizer
|
|||
*/
|
||||
private void initializeCMA(double[] guess) {
|
||||
if (lambda <= 0) {
|
||||
// XXX Line below to replace the current one in 4.0 (MATH-879).
|
||||
// throw new NotStrictlyPositiveException(lambda);
|
||||
lambda = 4 + (int) (3 * Math.log(dimension));
|
||||
}
|
||||
// initialize sigma
|
||||
final double[][] sigmaArray = new double[guess.length][1];
|
||||
for (int i = 0; i < guess.length; i++) {
|
||||
// XXX Line below to replace the current one in 4.0 (MATH-868).
|
||||
// sigmaArray[i][0] = inputSigma[i];
|
||||
sigmaArray[i][0] = inputSigma == null ? 0.3 : inputSigma[i];
|
||||
}
|
||||
final RealMatrix insigma = new Array2DRowRealMatrix(sigmaArray, false);
|
||||
|
|
|
@ -52,7 +52,7 @@ public class CMAESOptimizerTest {
|
|||
@Test(expected = NumberIsTooLargeException.class)
|
||||
public void testInitOutofbounds1() {
|
||||
double[] startPoint = point(DIM,3);
|
||||
double[] insigma = null;
|
||||
double[] insigma = point(DIM, 0.3);
|
||||
double[][] boundaries = boundaries(DIM,-1,2);
|
||||
PointValuePair expected =
|
||||
new PointValuePair(point(DIM,1.0),0.0);
|
||||
|
@ -63,7 +63,7 @@ public class CMAESOptimizerTest {
|
|||
@Test(expected = NumberIsTooSmallException.class)
|
||||
public void testInitOutofbounds2() {
|
||||
double[] startPoint = point(DIM, -2);
|
||||
double[] insigma = null;
|
||||
double[] insigma = point(DIM, 0.3);
|
||||
double[][] boundaries = boundaries(DIM,-1,2);
|
||||
PointValuePair expected =
|
||||
new PointValuePair(point(DIM,1.0),0.0);
|
||||
|
@ -75,7 +75,7 @@ public class CMAESOptimizerTest {
|
|||
@Test(expected = DimensionMismatchException.class)
|
||||
public void testBoundariesDimensionMismatch() {
|
||||
double[] startPoint = point(DIM,0.5);
|
||||
double[] insigma = null;
|
||||
double[] insigma = point(DIM, 0.3);
|
||||
double[][] boundaries = boundaries(DIM+1,-1,2);
|
||||
PointValuePair expected =
|
||||
new PointValuePair(point(DIM,1.0),0.0);
|
||||
|
@ -111,7 +111,7 @@ public class CMAESOptimizerTest {
|
|||
@Test(expected = DimensionMismatchException.class)
|
||||
public void testInputSigmaDimensionMismatch() {
|
||||
double[] startPoint = point(DIM,0.5);
|
||||
double[] insigma = point(DIM+1,-0.5);
|
||||
double[] insigma = point(DIM + 1, 0.5);
|
||||
double[][] boundaries = null;
|
||||
PointValuePair expected =
|
||||
new PointValuePair(point(DIM,1.0),0.0);
|
||||
|
@ -459,17 +459,20 @@ public class CMAESOptimizerTest {
|
|||
PointValuePair expected) {
|
||||
int dim = startPoint.length;
|
||||
// test diagonalOnly = 0 - slow but normally fewer feval#
|
||||
CMAESOptimizer optim = new CMAESOptimizer(lambda, inSigma, 30000,
|
||||
stopValue, isActive, diagonalOnly,
|
||||
0, new MersenneTwister(), false);
|
||||
CMAESOptimizer optim = new CMAESOptimizer(30000, stopValue, isActive, diagonalOnly,
|
||||
0, new MersenneTwister(), false, null);
|
||||
final double[] lB = boundaries == null ? null : boundaries[0];
|
||||
final double[] uB = boundaries == null ? null : boundaries[1];
|
||||
PointValuePair result = boundaries == null ?
|
||||
optim.optimize(maxEvaluations, func, goal,
|
||||
new InitialGuess(startPoint)) :
|
||||
new InitialGuess(startPoint),
|
||||
new CMAESOptimizer.Sigma(inSigma),
|
||||
new CMAESOptimizer.PopulationSize(lambda)) :
|
||||
optim.optimize(maxEvaluations, func, goal,
|
||||
new InitialGuess(startPoint),
|
||||
new SimpleBounds(lB, uB));
|
||||
new SimpleBounds(lB, uB),
|
||||
new CMAESOptimizer.Sigma(inSigma),
|
||||
new CMAESOptimizer.PopulationSize(lambda));
|
||||
// System.out.println("sol=" + Arrays.toString(result.getPoint()));
|
||||
Assert.assertEquals(expected.getValue(), result.getValue(), fTol);
|
||||
for (int i = 0; i < dim; i++) {
|
||||
|
|
Loading…
Reference in New Issue