public class CMAESSpecies extends FloatVectorSpecies
CMAESSpecies must be used in combination with CMAESBreeder, which will call it at appropriate times to revise the distribution and to generate a new subpopulation of individuals. It must also be used in combination with CMAESInitializer, which will use it to generate the initial population.
Note importantly that CMAESSpecies ignores the subpopulation size. Instead the first thing it will do is revise the subpopulation size to reflect the "lambda" parameter. This is a consequence of another feature of CMAESSpecies: many of its parameters do not have fixed default values, but rather values which are computed on the fly if the user does not provide them. For this reason, it also prints out these values when running so the user may see what values it used for that given run. The computed default values use equations which are common in the CMA-ES literature and are described below.
CMAESSpecies also has an "alternative termination" option. Normally ECJ terminates when the optimal individual is discovered or when the generations or maximum number of evaluations has been exceeded. CMA-ES can optionally terminate when the eigenvalues of the covariance matrix of its gaussian distribution are too small. Among other things, this will generally prevent CMA-ES from terminating abnormally because an eigenvalue has gone negative (due to floating point underflows). But by default this alternative termination is turned off, and CMA-ES will simply terminate in that case.
CMAESSpecies needs initial values of sigma (the scaling parameter for its covariance matrix) and the mean of the gaussian distribution. By default sigma's initial value is 1.0. The mean must be set to one of "zero" (meaning the origin), "center" (meaning the center of the genome space defined by the min and max gene values for each gene), or "random" (meaning a randomly- chosen point in the space". If it is not set to any of these, you may alternatively set the initial mean values by hand. But you must do one of the two.
Initializing the covariance matrix can be a problem in in CMA-ES, particularly if it is large relative to the gene bounds. If CMA-ES generates a random individual under its current distribution and that individual violates the bounds of just a single gene, it is invalid and must be regenerated. If you have a lot of genes, and the covariance matrix is large relative to their bounds, then the probability that this will occur rapidly approaches 1.0, so CMA-ES will be trapped in an effectively infinite loop endlessly producing invalid individuals.
This can be remedied in a few ways. First there is an option available to force the initial covariance matrix to NOT be the identity matrix (the default) but instead be scaled according to the gene bounds. That may help. You can also of course reduce sigma. Last, you can turn on an alternative individual generation mechanism; here, if a specific gene bound is violated, then *for that gene only* the value is chosen at random uniformly from within the gene bounds.
CMAESSpecies relies on the EJML matrix library, available at http://ejml.org/
Parameters
base.mean String, one of center, zero, or random |
(the initial mean for the distribution) If not provided, base.mean.0 and so on must be given |
base.mean.i Floating-point value |
(the value of dimension i of the initial mean vector) These values will override those set as a result of base.mean |
base.sigma Floating-point value > 0.0 |
(the sigma scaling parameter) If not provided, this defaults to 1.0. |
base.lambda Integer > base.mu |
(lambda population size) If not provided, this defaults to 4 + Math.floor(3 * Math.log(n)). |
base.lambda Integer > 1 |
(mu truncated population size) If not provided, this defaults to Math.floor(lambda / 2.0). |
base.weight.i Float >= 0 |
(weight for individual i (i from 0 to mu-1)) If not provided, this defaults to Math.log((lambda + 1.0) / (2.0 * (i + 1))). |
base.cc 0 <= Float < 1 |
(c_c parameter) If not provided, this defaults to (4.0+mueff/n) / (n+4.0 + 2.0*mueff/n) Where mueff is defined in the variables below, and n is the genome size |
base.cs 0 <= Float < 1 |
(c_sigma parameter) If not provided, this defaults to (mueff+2.0)/(n+mueff+5.0) Where mueff is defined in the variables below, and n is the genome size |
base.c1 0 <= Float < 1 (and c1 > (1-cmu)) |
(c_1 parameter) If not provided, this defaults to 2.0 / ((n+1.3)*(n+1.3)+mueff) Where mueff is defined in the variables below, and n is the genome size |
base.cmu 0 <= Float < 1 (and cmu > (1-c1)) |
(c_mu parameter) If not provided, this defaults to Math.min(1.0-c1, 2.0*(mueff-2.0+1.0/mueff) / ((n+2.0)*(n+2.0)+mueff)) Where mueff is defined in the variables below, and n is the genome size |
base.damps 0 <= Float < 1 |
(d_sigma dampening parameter) If not provided, this defaults to 1.0 + 2.0*Math.max(0.0, Math.sqrt((mueff-1.0)/(n+1.0))-1.0) + cs Where mueff is defined in the variables below, and n is the genome size |
base.covariance String, either "identity" (default) or "scaled" |
Covariance matrix initialization procedure. If "identity", then the covariance matrix is initialized to the identity matrix. If "scaled", then the covariance matrix is initialized to a diagonal matrix whose values are squares of each gene range (max - min). |
base.alternative-generator true or false (default) |
Whether or not to use the alternative indivdiual-generation procedure. If "true", then if, in the process of generating an individual, we have failed alternative-generator-tries times to create an individual which falls within the min and max gene values for each gene, then whenever a gene value violates those constraints we will simply randomize it to something uniformly chosen between the min and max. If "false", then whenever an individual violates constraints, we will try again as necessary. |
base.alternative-generator-tries Integer > 1 (default is 100) |
How many times we try to generate a valid individual before possibly using the alternative-generator approach. |
Default Base
eda.cma-es.species
Modifier and Type | Field and Description |
---|---|
int |
altGeneratorTries
How many times should we try to generate a valid individual before we give up and use the useAltGenerator approach?
|
SimpleMatrix |
b
The "B" matrix, eigendecomposed from the "C" covariance matrix of the distribution.
|
DenseMatrix64F |
bd
b x d
|
SimpleMatrix |
c
The "C" covariance matrix of the distribution.
|
double |
c1
The c_1 rank-1 update learning rate.
|
double |
cc
The c_c rank-one evolution path cumulation parameter.
|
double |
chiN
An estimate of the expected size of the standard multivariate gaussian N(0,I).
|
double |
cmu
The c_{\mu} rank-mu update learning rate.
|
double |
cs
The c_{\sigma} mutation rate evolution path learning rate.
|
SimpleMatrix |
d
The "C" matrix, eigendecomposed from the "C" covariance matrix of the distribution.
|
double |
damps
The d_{\sigma} dampening for the mutation rate update.
|
static int |
DEFAULT_ALT_GENERATOR_TRIES
Default value (100) for altGeneratorTries.
|
SimpleMatrix |
invsqrtC
C^{-1/2}.
|
int |
lambda
The individuals generated from the distribution.
|
int |
lastEigenDecompositionGeneration
The most recent generation where an eigendecomposition on C was performed into B and D
|
static int |
MAX_TRIES_BEFORE_WARNING |
int |
mu
The truncated individuals used to update the distribution.
|
double |
mueff
The "mu_{eff}" constant in CMA-ES.
|
static java.lang.String |
P_ALTERNATIVE_GENERATOR |
static java.lang.String |
P_ALTERNATIVE_GENERATOR_TRIES |
static java.lang.String |
P_ALTERNATIVE_TERMINATION |
static java.lang.String |
P_C1 |
static java.lang.String |
P_CC |
static java.lang.String |
P_CMAES_SPECIES |
static java.lang.String |
P_CMU |
static java.lang.String |
P_COVARIANCE |
static java.lang.String |
P_CS |
static java.lang.String |
P_DAMPS |
static java.lang.String |
P_LAMBDA |
static java.lang.String |
P_MEAN |
static java.lang.String |
P_MU |
static java.lang.String |
P_SIGMA |
static java.lang.String |
P_WEIGHTS |
SimpleMatrix |
pc
The p_c evolution path vector.
|
SimpleMatrix |
ps
The p_{\sigma} evolution path vector.
|
DenseMatrix64F |
sbd
bd x sigma
|
double |
sigma
The "sigma" scaling factor for the covariance matrix.
|
boolean |
useAltGenerator
If, after trying altGeneratorTries to build an indiviual, we are still building one which violates min/max gene constraints, should
we instead fill those violated genes with uniformly-selected values between the min and max?
|
boolean |
useAltTermination
Should we terminate when the eigenvalues get too small? If we don't, they might go negative and the eigendecomposition will fail.
|
static java.lang.String |
V_CENTER |
static java.lang.String |
V_IDENTITY |
static java.lang.String |
V_RANDOM |
static java.lang.String |
V_SCALED |
static java.lang.String |
V_ZERO |
double[] |
weights
The ranked fitness weights for the mu individuals.
|
SimpleMatrix |
xmean
The mean of the distribution.
|
C_GAUSS_MUTATION, C_INTEGER_RANDOM_WALK_MUTATION, C_INTEGER_RESET_MUTATION, C_POLYNOMIAL_MUTATION, C_RESET_MUTATION, DEFAULT_OUT_OF_BOUNDS_RETRIES, gaussMutationStdev, maxGene, minGene, mutationDistributionIndex, mutationIsBounded, mutationType, outOfBoundsRetries, P_MAXGENE, P_MINGENE, P_MUTATION_BOUNDED, P_MUTATION_DISTRIBUTION_INDEX, P_MUTATIONTYPE, P_OUTOFBOUNDS_RETRIES, P_POLYNOMIAL_ALTERNATIVE, P_RANDOM_WALK_PROBABILITY, P_STDEV, polynomialIsAlternative, randomWalkProbability, V_GAUSS_MUTATION, V_INTEGER_RANDOM_WALK_MUTATION, V_INTEGER_RESET_MUTATION, V_POLYNOMIAL_MUTATION, V_RESET_MUTATION
C_ANY_POINT, C_GEOMETRIC, C_INTERMED_RECOMB, C_LINE_RECOMB, C_NONE, C_ONE_POINT, C_ONE_POINT_NO_NOP, C_SIMULATED_BINARY, C_TWO_POINT, C_TWO_POINT_NO_NOP, C_UNIFORM, chunksize, crossoverDistributionIndex, crossoverProbability, crossoverType, duplicateRetries, dynamicInitialSize, genomeIncreaseProbability, genomeResizeAlgorithm, genomeSize, lineDistance, maxInitialSize, minInitialSize, mutationProbability, P_CHUNKSIZE, P_CROSSOVER_DISTRIBUTION_INDEX, P_CROSSOVERPROB, P_CROSSOVERTYPE, P_DUPLICATE_RETRIES, P_GENOMESIZE, P_GEOMETRIC_PROBABILITY, P_LINEDISTANCE, P_MUTATIONPROB, P_NUM_SEGMENTS, P_SEGMENT, P_SEGMENT_END, P_SEGMENT_START, P_SEGMENT_TYPE, P_UNIFORM_MAX, P_UNIFORM_MIN, P_VECTORSPECIES, V_ANY_POINT, V_GEOMETRIC, V_INTERMED_RECOMB, V_LINE_RECOMB, V_ONE_POINT, V_ONE_POINT_NO_NOP, V_SIMULATED_BINARY, V_TWO_POINT, V_TWO_POINT_NO_NOP, V_UNIFORM
f_prototype, i_prototype, P_FITNESS, P_INDIVIDUAL, P_PIPE, pipe_prototype
Constructor and Description |
---|
CMAESSpecies() |
Modifier and Type | Method and Description |
---|---|
java.lang.Object |
clone()
Creates a new individual cloned from a prototype,
and suitable to begin use in its own evolutionary
context.
|
Parameter |
defaultBase()
Returns the default base for this prototype.
|
Individual |
newIndividual(EvolutionState state,
int thread)
Provides a brand-new individual to fill in a population.
|
void |
setup(EvolutionState state,
Parameter base)
The default version of setup(...) loads requested pipelines and calls setup(...) on them and normalizes their probabilities.
|
void |
updateDistribution(EvolutionState state,
Subpopulation subpop)
Revises the CMA-ES distribution to reflect the current fitness results in the provided subpopulation.
|
gaussMutationStdev, inNumericalTypeRange, loadParametersForGene, maxGene, minGene, mutationDistributionIndex, mutationIsBounded, mutationType, outOfRangeRetryLimitReached, polynomialIsAlternative, randomWalkProbability
contains, contains, contains, contains, duplicateRetries, fill, fill, fill, fill, initializeGenomeSegmentsByEndIndices, initializeGenomeSegmentsByStartIndices, mutationProbability, setupGenome
newIndividual, newIndividual
public static final java.lang.String P_CMAES_SPECIES
public static final java.lang.String P_LAMBDA
public static final java.lang.String P_MU
public static final java.lang.String P_SIGMA
public static final java.lang.String P_MEAN
public static final java.lang.String P_WEIGHTS
public static final java.lang.String P_CC
public static final java.lang.String P_CS
public static final java.lang.String P_C1
public static final java.lang.String P_CMU
public static final java.lang.String P_DAMPS
public static final java.lang.String V_CENTER
public static final java.lang.String V_ZERO
public static final java.lang.String V_RANDOM
public static final java.lang.String P_COVARIANCE
public static final java.lang.String V_IDENTITY
public static final java.lang.String V_SCALED
public static final java.lang.String P_ALTERNATIVE_TERMINATION
public static final java.lang.String P_ALTERNATIVE_GENERATOR
public static final java.lang.String P_ALTERNATIVE_GENERATOR_TRIES
public int lambda
public int mu
public double[] weights
public double mueff
public double cmu
public double c1
public double cc
public double cs
public double damps
public double sigma
public SimpleMatrix xmean
public SimpleMatrix c
public SimpleMatrix b
public SimpleMatrix d
public DenseMatrix64F bd
public DenseMatrix64F sbd
public SimpleMatrix invsqrtC
public SimpleMatrix ps
public SimpleMatrix pc
public double chiN
public int lastEigenDecompositionGeneration
public boolean useAltTermination
public boolean useAltGenerator
public int altGeneratorTries
public static final int DEFAULT_ALT_GENERATOR_TRIES
public static final int MAX_TRIES_BEFORE_WARNING
public Parameter defaultBase()
Prototype
defaultBase
in interface Prototype
defaultBase
in class VectorSpecies
public void setup(EvolutionState state, Parameter base)
Species
setup
in interface Prototype
setup
in interface Setup
setup
in class FloatVectorSpecies
Prototype.setup(EvolutionState,Parameter)
public java.lang.Object clone()
Prototype
Typically this should be a full "deep" clone. However, you may share certain elements with other objects rather than clone hem, depending on the situation:
Implementations.
public Object clone()
{
try
{
return super.clone();
}
catch ((CloneNotSupportedException e)
{ throw new InternalError(); } // never happens
}
public Object clone()
{
try
{
MyObject myobj = (MyObject) (super.clone());
// put your deep-cloning code here...
}
catch ((CloneNotSupportedException e)
{ throw new InternalError(); } // never happens
return myobj;
}
public Object clone()
{
MyObject myobj = (MyObject) (super.clone());
// put your deep-cloning code here...
return myobj;
}
public Individual newIndividual(EvolutionState state, int thread)
Species
newIndividual
in class VectorSpecies
public void updateDistribution(EvolutionState state, Subpopulation subpop)