Larger commit, adding IPOP-ES and RankMuCMA mutator. Revs. 130-174 from MK-branch should be merged with this.

This commit is contained in:
Marcel Kronfeld 2008-08-29 14:04:32 +00:00
parent c2a3f06498
commit 68241a0dc0
39 changed files with 1593 additions and 404 deletions

View File

@ -3,19 +3,23 @@
<title>Evolution Strategy - ES</title>
</head>
<body>
 
<h1 align="center">Evolution Strategy - ES</h1>
<center>
</center><br>
An ES works on a population of real valued solutions
by repeated use of evolutionary operators like reproduction,
recombination and mutation (see pseudocode in figures.
lambda offspring individuals are generated from mu parents
by recombination and mutation. After evaluating the fitness of the lambda
offspring individuals, mu individuals with the best fitness are
selected by a comma-strategy to build the parent population for the next generation.
On the other hand, a plus-strategy selects the best mu individuals
from the aggregation of parents and offspring individuals.
The properties of ES are given in the population sub frame.
recombination and mutation.
&lambda; offspring individuals are generated from &mu; parents
by recombination and mutation (with &mu; &lt; &lambda;).
<br>
After evaluating the fitness of the &lambda;
offspring individuals, the comma-strategy selects the &mu; individuals
with the best fitness as parent population for the next generation.
On the other hand, a plus-strategy selects the best &mu; individuals
from the aggregation of parents and offspring individuals, so in this
case the best individual is guaranteed to survive.
In general, however, the comma-strategy is more robust and can easier
escape from local optima, which is why it is usually the standard selection.
<br>
</body>
</html>

View File

@ -0,0 +1,30 @@
<html>
<head>
<title>Increasing Population Size ES - IPOP-ES</title>
</head>
<body>
<h1 align="center">Increasing Population Size ES - IPOP-ES</h1>
<center>
</center><br>
<p>
This class implements the IPOP (increased population size) restart strategy ES, which increases
the ES population size (i.e., lambda) after phases of stagnation and then restarts the optimization
by reinitializing the individuals and operators.<br>
Stagnation is for this implementation defined by a FitnessConvergenceTerminator instance
which terminates if the absolute change in fitness is below a threshold (default 10e-12) for a
certain number of generations (default: 10+floor(30*n/lambda) for problem dimension n).
</p>
<p>
If the MutateESRankMuCMA mutation operator is employed, additional criteria are used for restarts,
such as numeric conditions of the covariance matrix.
Lambda is increased multiplicatively for every restart, and typical initial values are
mu=5, lambda=10, incFact=2.
The IPOP-CMA-ES won the CEC 2005 benchmark challenge.
Refer to Auger&Hansen 05 for more details.
</p>
<br>
A.Auger & N.Hansen. <i>A Restart CMA Evolution Strategy With Increasing Population Size</i>. CEC 2005.
</body>
</html>

View File

@ -0,0 +1,33 @@
<html>
<head>
<title>Covariance Matrix Adaptation with Rank-Mu-Update</title>
</head>
<body>
<h1 align="center">Covariance Matrix Adaptation with rank-mu update after Hansen & Kern 2004</h1>
Implementing CMA ES with rank-mu-update and weighted recombination. This operator won the CEC 2005
challenge employed with a restart scheme with increasing population size.
Basically, in each generation the population is resampled around the weighted center of the
last population using the adapted covariance matrix C. In contrast to earlier CMA versions,
this implementation only holds one single covariance matrix for the whole population, making
it much more memory efficient and useful for high dimensional problems as well.
<br>
While C is adapted based on a cumulated evolution path, the step size sigma is adapted based
on path length control.
Due to the repeated resampling starting from a single "center", the CMA version can
be interpreted as a sophisticated local search, if the initial solution set is sampled
close to an initial guess. In this case, a small initial sigma is favourable.
<br>
For multimodal problems, the initial population can be sampled randomly in the search space
and the initial sigma must be rather high.
To meet both conditions, the initial sigma may be set to half the average problem range
or to the average distance in the initial population.
<br>
<p>
* N.Hansen & S.Kern 2004: <i>Evaluating the CMA Evolution Strategy on Multimodal Test Functions.</i>
Parallel Problem Solving from Nature 2004.
</body>
</html>

View File

@ -35,8 +35,8 @@ import eva2.server.go.individuals.GAIndividualDoubleData;
import eva2.server.go.individuals.InterfaceDataTypeDouble;
import eva2.server.go.operators.crossover.CrossoverGANPoint;
import eva2.server.go.operators.mutation.InterfaceMutation;
import eva2.server.go.operators.mutation.MutateESFixedStepSize;
import eva2.server.go.operators.mutation.MutateESLocal;
import eva2.server.go.operators.mutation.MutateESStandard;
import eva2.server.go.operators.selection.SelectTournament;
import eva2.server.go.operators.terminators.EvaluationTerminator;
import eva2.server.go.populations.Population;
@ -304,7 +304,7 @@ public class GOStandaloneVersion implements InterfaceGOStandalone, InterfacePopu
this.m_OutputPath = "results/";
// These are some tmp Variables
InterfaceDataTypeDouble tmpIndy = new ESIndividualDoubleData();
InterfaceMutation tmpMut = new MutateESStandard();
InterfaceMutation tmpMut = new MutateESFixedStepSize();
switch (experimentType) {
case 0 : {

View File

@ -2,6 +2,19 @@ package eva2.server.go.individuals;
import java.util.Comparator;
/**
* Comparator implementation which compares two individuals based on their fitness.
* The default version calls isDominatingDebConstraints() of the AbstractEAIndividual
* class and assigns -1 if first is dominant, 1 if second is dominant, 0 if the two ind.s
* are not comparable.
* As an alternative, a data key String may be set which is then used to request a data
* object from the individuals. The objects are interpreted as fitness vectors (double[]) and
* the comparison is based on those. This may be used to access alternative (e.g. older or
* best-so-far fitness values) for individual comparison.
*
* @author mkron
*
*/
public class AbstractEAIndividualComparator implements Comparator<Object> {
// flag whether a data field should be used.
@ -31,9 +44,21 @@ public class AbstractEAIndividualComparator implements Comparator<Object> {
this.indyDataKey = indyDataKey;
}
public AbstractEAIndividualComparator(AbstractEAIndividualComparator other) {
indyDataKey = other.indyDataKey;
}
public Object clone() {
return new AbstractEAIndividualComparator(this);
}
/**
* Compare two individuals, return -1 if first is dominant, 1 if second is dominant, 0 if they
* Compare two individuals, return -1 if the first is dominant, 1 if the second is dominant, 0 if they
* are not comparable.
*
* @param o1 the first AbstractEAIndividual to compare
* @param o2 the second AbstractEAIndividual to compare
* @return -1 if the first is dominant, 1 if the second is dominant, else 0
*/
public int compare(Object o1, Object o2) {
boolean o1domO2, o2domO1;

View File

@ -0,0 +1,15 @@
package eva2.server.go.operators.mutation;
import eva2.server.go.populations.Population;
/**
* An interface for a mutation operator which is updated on a generational basis, such as
* the 1/5-success rule.
*
* @author mkron
*
*/
public interface InterfaceMutationGenerational extends InterfaceMutation {
public void adaptAfterSelection(Population oldGen, Population selected);
public void adaptGenerational(Population selectedPop, Population parentPop, Population newPop, boolean updateSelected);
}

View File

@ -18,8 +18,8 @@ public class MutateESCorrolated implements InterfaceMutation, java.io.Serializab
protected double m_Tau1 = 0.15;
protected double m_LowerLimitStepSize = 0.0000005;
private static final long serialVersionUID = 1L;
private double[] m_Sigmas;
private double[] m_Alphas;
private double[] m_Sigmas = null;
private double[] m_Alphas = null;
protected double m_Tau2 = 0.15;
public MutateESCorrolated() {
@ -56,7 +56,7 @@ public class MutateESCorrolated implements InterfaceMutation, java.io.Serializab
return new MutateESCorrolated(this);
}
/** This method allows you to evaluate wether two mutation operators
/** This method allows you to evaluate whether two mutation operators
* are actually the same.
* @param mutator The other mutation operator
*/
@ -85,7 +85,19 @@ public class MutateESCorrolated implements InterfaceMutation, java.io.Serializab
* @param opt The optimization problem.
*/
public void init(AbstractEAIndividual individual, InterfaceOptimizationProblem opt) {
if (individual instanceof InterfaceESIndividual) {
double[] x = ((InterfaceESIndividual)individual).getDGenotype();
if (this.m_Sigmas == null) {
// init the Sigmas
this.m_Sigmas = new double[x.length];
for (int i = 0; i < this.m_Sigmas.length; i++) this.m_Sigmas[i] = this.m_MutationStepSize;
}
if (this.m_Alphas == null) {
// init the Alphas
this.m_Alphas = new double[(x.length*(x.length-1))/2];
for (int i = 0; i < this.m_Alphas.length; i++) this.m_Alphas[i] = 0.0;
}
}
}
/** This method will mutate a given AbstractEAIndividual. If the individual
@ -158,22 +170,12 @@ public class MutateESCorrolated implements InterfaceMutation, java.io.Serializab
double[][] range = ((InterfaceESIndividual)individual).getDoubleRange();
double tmpR = RNG.gaussianDouble(1);
if (this.m_Sigmas == null) {
// init the Sigmas
this.m_Sigmas = new double[x.length];
for (int i = 0; i < this.m_Sigmas.length; i++) this.m_Sigmas[i] = this.m_MutationStepSize;
}
//Mutate Sigmas
for (int i = 0; i < x.length; i++) {
this.m_Sigmas[i] = this.m_Sigmas[i] * Math.exp(this.m_Tau1 * tmpR + this.m_Tau2 * RNG.gaussianDouble(1));
if (this.m_Sigmas[i] < this.m_LowerLimitStepSize) this.m_Sigmas[i] = this.m_LowerLimitStepSize;
}
if (this.m_Alphas == null) {
// init the Alphas
this.m_Alphas = new double[(x.length*(x.length-1))/2];
for (int i = 0; i < this.m_Alphas.length; i++) this.m_Alphas[i] = 0.0;
}
//Mutate Alphas
for (int i = 0; i < this.m_Alphas.length; i++) {
this.m_Alphas[i] = this.m_Alphas[i] + RNG.gaussianDouble(0.2);
@ -230,7 +232,7 @@ public class MutateESCorrolated implements InterfaceMutation, java.io.Serializab
sum+=j-i; sum--;
return this.m_Alphas[sum];
}else{
System.out.println("Falscher Zugriff auf Alphaliste!");
System.err.println("Falscher Zugriff auf Alphaliste!");
return 0.0;
}
}
@ -240,7 +242,7 @@ public class MutateESCorrolated implements InterfaceMutation, java.io.Serializab
* @return A descriptive string.
*/
public String getStringRepresentation() {
return "ES local mutation";
return "ES local correlated mutation";
}
/**********************************************************************************************************************

View File

@ -160,6 +160,7 @@ public class MutateESCovarianceMatrixAdaption implements InterfaceMutation, java
double pathLen = 0.0;
for (int i = 0; i < this.m_D; i++)
this.s_N[i] = (1.0 - this.m_c) * this.s_N[i] + this.m_c * this.cu * this.Bz[i];
// System.out.println("C bef:\n" + m_C.toString());
// ADAPT COVARIANCE
for (int i = 0; i <this. m_D; i++) {
for (int j = i; j < this.m_D; j++) {
@ -168,6 +169,7 @@ public class MutateESCovarianceMatrixAdaption implements InterfaceMutation, java
this.m_C.set(j, i, Cij);
}
}
// System.out.println("C aft:\n" + m_C.toString());
// ADAPT GLOBAL STEPSIZE
for (int i = 0; i < this.m_D; i++) {
Bz_d = 0.0;

View File

@ -14,8 +14,7 @@ import wsi.ra.math.RNG;
* To change this template use File | Settings | File Templates.
*/
public class MutateESFixedStepSize implements InterfaceMutation, java.io.Serializable {
private double m_Sigma = 0.005;
protected double m_Sigma = 0.005;
public MutateESFixedStepSize() {
}

View File

@ -1,36 +1,43 @@
package eva2.server.go.operators.mutation;
import wsi.ra.math.RNG;
import eva2.server.go.individuals.AbstractEAIndividual;
import eva2.server.go.individuals.InterfaceESIndividual;
import eva2.server.go.populations.Population;
import eva2.server.go.problems.InterfaceOptimizationProblem;
import wsi.ra.math.RNG;
import eva2.tools.Mathematics;
/**
* Created by IntelliJ IDEA.
* User: streiche
* Date: 31.05.2005
* Time: 14:22:13
* To change this template use File | Settings | File Templates.
* ES mutation with path length control. The step size (single sigma) is
* adapted using the evolution path length by adapting the real path length
* to the expected path length in for uncorrelated single steps.
* See Hansen&Ostermeier 2001, Eqs. 16,17.
*
*/
public class MutateESDerandomized implements InterfaceMutation, java.io.Serializable {
public class MutateESPathLengthAdaption implements InterfaceMutation, java.io.Serializable {
private int m_D;
private double[] m_Z;
private int m_dim;
private double[] m_randZ;
private double[] m_Path;
private double m_SigmaGlobal = 1.0;
private double m_c;
private boolean m_UsePath = true;
private double dampening = 1;
private double expectedPathLen = -1;
private double m_cu;
public MutateESDerandomized() {
public MutateESPathLengthAdaption() {
}
public MutateESDerandomized(MutateESDerandomized mutator) {
public MutateESPathLengthAdaption(MutateESPathLengthAdaption mutator) {
this.m_UsePath = true;
this.m_D = mutator.m_D;
this.m_dim = mutator.m_dim;
this.m_SigmaGlobal = mutator.m_SigmaGlobal;
this.m_c = mutator.m_c;
if (mutator.m_Z != null) this.m_Z = (double[]) mutator.m_Z.clone();
this.dampening = mutator.dampening;
this.expectedPathLen = mutator.expectedPathLen;
this.m_cu = mutator.m_cu;
if (mutator.m_randZ != null) this.m_randZ = (double[]) mutator.m_randZ.clone();
if (mutator.m_Path != null) this.m_Path = (double[]) mutator.m_Path.clone();
}
@ -38,7 +45,7 @@ public class MutateESDerandomized implements InterfaceMutation, java.io.Serializ
* @return The clone
*/
public Object clone() {
return new MutateESDerandomized(this);
return new MutateESPathLengthAdaption(this);
}
/** This method allows you to evaluate wether two mutation operators
@ -46,14 +53,14 @@ public class MutateESDerandomized implements InterfaceMutation, java.io.Serializ
* @param mutator The other mutation operator
*/
public boolean equals(Object mutator) {
if (mutator instanceof MutateESDerandomized) {
MutateESDerandomized mut = (MutateESDerandomized)mutator;
if (mutator instanceof MutateESPathLengthAdaption) {
MutateESPathLengthAdaption mut = (MutateESPathLengthAdaption)mutator;
// i assume if the C Matrix is equal then the mutation operators are equal
if (this.m_D != mut.m_D) return false;
if (this.m_dim != mut.m_dim) return false;
if (this.m_SigmaGlobal != mut.m_SigmaGlobal) return false;
if (this.m_c != mut.m_c) return false;
if ((this.m_Z != null) && (mut.m_Z != null))
for (int i = 0; i < this.m_Z.length; i++) if (this.m_Z[i] != mut.m_Z[i]) return false;
if ((this.m_randZ != null) && (mut.m_randZ != null))
for (int i = 0; i < this.m_randZ.length; i++) if (this.m_randZ[i] != mut.m_randZ[i]) return false;
if ((this.m_Path != null) && (mut.m_Path != null))
for (int i = 0; i < this.m_Path.length; i++) if (this.m_Path[i] != mut.m_Path[i]) return false;
return true;
@ -69,13 +76,24 @@ public class MutateESDerandomized implements InterfaceMutation, java.io.Serializ
if (!(individual instanceof InterfaceESIndividual)) return;
double[] x = ((InterfaceESIndividual)individual).getDGenotype();
double[][] ranges = ((InterfaceESIndividual)individual).getDoubleRange();
this.m_D = x.length;
if (this.m_UsePath == true) this.m_c = Math.sqrt(1.0 / (double) this.m_D);
this.m_dim = x.length;
// if (this.m_UsePath) this.m_c = Math.sqrt(1.0 / (double) this.m_dim);
this.m_randZ = new double[this.m_dim];
this.m_Path = new double[this.m_dim];
for (int i = 0; i < this.m_dim; i++) {
this.m_randZ[i] = RNG.gaussianDouble(1.0);
// this.m_Path[i]=1;
}
if (this.m_UsePath) this.m_c = 4./(m_dim+4);
else this.m_c = 1.0;
this.m_Z = new double[this.m_D];
this.m_Path = new double[this.m_D];
for (int i = 0; i < this.m_D; i++) this.m_Z[i] = RNG.gaussianDouble(1.0);
evaluateNewObjectX(x, ranges);
expectedPathLen = Math.sqrt(m_dim)*(1-(1./(4*m_dim))+(1./(21*m_dim*m_dim)));
dampening = (1./m_c)+1;
m_cu = Math.sqrt(m_c*(2.0-m_c));
mutateX(x, ranges, true);
}
/** This method will mutate a given AbstractEAIndividual. If the individual
@ -87,19 +105,30 @@ public class MutateESDerandomized implements InterfaceMutation, java.io.Serializ
if (individual instanceof InterfaceESIndividual) {
double[] x = ((InterfaceESIndividual)individual).getDGenotype();
double[][] ranges = ((InterfaceESIndividual)individual).getDoubleRange();
this.adaptStrategy();
for (int i = 0; i < m_D; i++) m_Z[i] = RNG.gaussianDouble(1.0);
this.evaluateNewObjectX(x, ranges);
for (int i = 0; i < x.length; i++) {
if (x[i] < ranges[i][0]) x[i] = ranges[i][0];
if (x[i] > ranges[i][1]) x[i] = ranges[i][1];
}
this.adaptStrategy(); // this updates the path using the old step and adapts sigma
this.calculateNewStep();
this.mutateX(x, ranges, true); // this performs new mutation
((InterfaceESIndividual)individual).SetDGenotype(x);
}
//System.out.println("After Mutate: " +((GAIndividual)individual).getSolutionRepresentationFor());
}
private void checkRange(double[] x, double[][] ranges) {
for (int i = 0; i < x.length; i++) {
if (x[i] < ranges[i][0]) x[i] = ranges[i][0];
if (x[i] > ranges[i][1]) x[i] = ranges[i][1];
}
}
/** This method allows you to perform either crossover on the strategy parameters
private void calculateNewStep() {
for (int i = 0; i < m_dim; i++) m_randZ[i] = RNG.gaussianDouble(1.0);
}
/** This method allows you to perform either crossover on the strategy parameters
* or to deal in some other way with the crossover event.
* @param indy1 The original mother
* @param partners The original partners
@ -109,21 +138,23 @@ public class MutateESDerandomized implements InterfaceMutation, java.io.Serializ
}
private void adaptStrategy() {
double length_of_Z = 0;
for (int i = 0; i < m_D; i++) {
m_Path [i] = (1.0 -m_c) * m_Path[i] + Math.sqrt(m_c*(2.0-m_c))*m_Z[i];
length_of_Z = length_of_Z + m_Path[i] * m_Path[i];
// remember the path taken. m_randZ is at this time the last step before selection.
for (int i = 0; i < m_dim; i++) {
m_Path [i] = (1.0 -m_c) * m_Path[i] + m_cu*m_randZ[i];
}
length_of_Z = Math.sqrt(length_of_Z);
double E_of_length_of_Z = Math.sqrt(((double)m_D)+0.5);
double kappa_d = ((double)m_D)/4.0+1.0;
double Exponent = (length_of_Z - E_of_length_of_Z)/(kappa_d*E_of_length_of_Z);
m_SigmaGlobal = m_SigmaGlobal * Math.exp(Exponent);
double pathLen = Mathematics.norm(m_Path);
// double expectedPathLen = Math.sqrt(((double)m_dim)+0.5);
// double kappa_d = ((double)m_dim)/4.0+1.0;
double exp = (pathLen - expectedPathLen)/(dampening*expectedPathLen);
m_SigmaGlobal = m_SigmaGlobal * Math.exp(exp);
}
private void evaluateNewObjectX(double[] x,double[][] range) {
private void mutateX(double[] x,double[][] range, boolean checkRange) {
for (int i = 0; i < x.length; i++)
x[i] = x[i] + m_SigmaGlobal * m_Z[i];
x[i] = x[i] + m_SigmaGlobal * m_randZ[i];
if (checkRange) checkRange(x, range);
}
/** This method allows you to get a string representation of the mutation
@ -131,7 +162,7 @@ public class MutateESDerandomized implements InterfaceMutation, java.io.Serializ
* @return A descriptive string.
*/
public String getStringRepresentation() {
return "CMA mutation";
return "Mutation/Path-Length-Control";
}
/**********************************************************************************************************************
* These are for GUI
@ -141,27 +172,27 @@ public class MutateESDerandomized implements InterfaceMutation, java.io.Serializ
* @return The name.
*/
public String getName() {
return "CMA mutation";
return "Mutation/Path-Length-Control";
}
/** This method returns a global info string
* @return description
*/
public String globalInfo() {
return "This is the most sophisticated CMA mutation.";
return "The single step size is controlled using the evolution path.";
}
/** Use only positive numbers this limits the freedom of effect.
* @param bit The new representation for the inner constants.
*/
public void setUsePath(boolean bit) {
this.m_UsePath = bit;
}
public boolean getUsePath() {
return this.m_UsePath;
}
public String usePathTipText() {
return "Use path.";
}
// /** Use only positive numbers this limits the freedom of effect.
// * @param bit The new representation for the inner constants.
// */
// public void setUsePath(boolean bit) {
// this.m_UsePath = bit;
// }
// public boolean getUsePath() {
// return this.m_UsePath;
// }
// public String usePathTipText() {
// return "Use path.";
// }
/** This method allows you to set the initial sigma value.
* @param d The initial sigma value.
@ -173,6 +204,6 @@ public class MutateESDerandomized implements InterfaceMutation, java.io.Serializ
return this.m_SigmaGlobal;
}
public String initSigmaGlobalTipText() {
return "Set the initial global sigma value.";
return "Set the initial global step size.";
}
}

View File

@ -0,0 +1,648 @@
package eva2.server.go.operators.mutation;
import java.io.Serializable;
import java.util.Arrays;
import wsi.ra.math.RNG;
import wsi.ra.math.Jama.EigenvalueDecomposition;
import wsi.ra.math.Jama.Matrix;
import eva2.gui.BeanInspector;
import eva2.server.go.individuals.AbstractEAIndividual;
import eva2.server.go.individuals.InterfaceDataTypeDouble;
import eva2.server.go.populations.Population;
import eva2.server.go.problems.InterfaceOptimizationProblem;
import eva2.tools.EVAERROR;
import eva2.tools.Mathematics;
import eva2.tools.Pair;
/**
* Implementing CMA ES with rank-mu-update and weighted recombination. This is partly based on the
* java implementation provided on http://www.bionik.tu-berlin.de/user/niko/cmaes_inmatlab.html.
*
* N.Hansen & S.Kern 2004: Evaluating the CMA Evolution Strategy on Multimodal Test Functions.
* Parallel Problem Solving from Nature 2004.
*
* @author mkron
*
*/
public class MutateESRankMuCMA implements InterfaceMutationGenerational, Serializable {
int dim;
private double c_c, expRandStepLen;
private double[] z, zCor;
private InitialSigmaEnum initialSig = InitialSigmaEnum.avgInitialDistance;
private static double firstSigma = -1.;
private static double sigma;
private static double d_sig, c_sig;
private static double[] meanX, pathC, pathS, eigenvalues;
private static double[] weights = null;
private static double[][] range = null;
private static Matrix mC;
private static Matrix mB;
// private static double[] mBD;
private static boolean firstAdaptionDone = false;
private static boolean TRACE_1 = false;
private static boolean TRACE_2 = false;
private static boolean TRACE_TEST = false;
// private Matrix BD;
public MutateESRankMuCMA() {
firstAdaptionDone = false;
}
public MutateESRankMuCMA(MutateESRankMuCMA mutator) {
this.c_c = mutator.c_c;
// this.c_sig = mutator.c_sig;
// this.c_u_sig = mutator.c_u_sig;
// this.d_sig = mutator.d_sig;
this.expRandStepLen = mutator.expRandStepLen;
this.dim = mutator.dim;
this.initialSig = mutator.initialSig;
// if (mutator.meanX != null) this.meanX = (double[]) mutator.meanX.clone();
// if (mutator.pathC != null) this.pathC = (double[]) mutator.pathC.clone();
// if (mutator.pathS != null) this.pathS = (double[]) mutator.pathS.clone();
if (mutator.z != null) this.z = (double[]) mutator.z.clone();
if (mutator.zCor != null) this.zCor = (double[]) mutator.zCor.clone();
// if (mutator.eigenvalues != null) this.eigenvalues = (double[]) mutator.eigenvalues.clone();
// if (mutator.mC != null) this.mC = (Matrix) mutator.mC.clone();
// if (mutator.mB != null) this.mB = (Matrix) mutator.mB.clone();
}
public Object clone() {
// if (TRACE) System.out.println("WCMA clone");
return new MutateESRankMuCMA(this);
}
/**
* Retrieve the initial sigma for the given population and the user defined method.
* @param initGen
* @return
*/
private double getInitSigma(Population initGen) {
switch (initialSig) {
case avgInitialDistance: return initGen.getPopulationMeasures()[0];
case halfRange: return getAvgRange()/2.;
default: return 0.2;
}
}
public void adaptAfterSelection(Population oldGen, Population selectedP) {
Population selectedSorted = selectedP.getSortedBestFirst();
int mu,lambda;
mu = selectedP.size();
lambda = oldGen.size();
if (mu>= lambda) {
EVAERROR.errorMsgOnce("Warning: invalid mu/lambda ratio! Setting mu to lambda/2.");
mu = lambda/2;
}
if (!firstAdaptionDone) {
initWeights(mu, lambda);
double muEff = getMuEff(mu);
c_sig = (muEff+2)/(muEff+dim+3);
// c_u_sig = Math.sqrt(c_sig * (2.-c_sig));
d_sig = c_sig+1+2*Math.max(0, Math.sqrt((muEff-1)/(dim+1)) - 1);
sigma = getInitSigma(oldGen);
firstSigma = sigma;
meanX = oldGen.getCenter(); // this might be ok?
}
int generation = oldGen.getGeneration();
if (TRACE_1) {
System.out.println("WCMA adaptGenerational");
// System.out.println("newPop measures: " + BeanInspector.toString(newPop.getPopulationMeasures()));
System.out.println("mu_eff: " + getMuEff(mu));
System.out.println("meanX: " + BeanInspector.toString(meanX));
System.out.println("pathC: " + BeanInspector.toString(pathC));
System.out.println("pathS: " + BeanInspector.toString(pathS));
}
double[] newMeanX = calcMeanX(selectedSorted);
if (TRACE_1) System.out.println("newMeanX: " + BeanInspector.toString(newMeanX));
double[] BDz = new double[dim];
for (int i=0; i<dim; i++) { /* calculate xmean and BDz~N(0,C) */
// Eq. 4 from HK04, most right term
BDz[i] = Math.sqrt(getMuEff(mu)) * (newMeanX[i] - meanX[i]) / getSigma(i);
}
// if (TRACE_2) System.out.println("BDz is " + BeanInspector.toString(BDz));
double[] newPathS = pathS.clone();
double[] newPathC = pathC.clone();
double[] zVect = new double[dim];
/* calculate z := D^(-1) * B^(-1) * BDz into artmp, we could have stored z instead */
for (int i = 0; i < dim; ++i) {
double sum=0.;
for (int j = 0; j < dim; ++j) {
sum += mB.get(j,i) * BDz[j]; // times B transposed, (Eq 4) in HK04
}
zVect[i] = sum / Math.sqrt(eigenvalues[i]);
}
/* cumulation for sigma (ps) using B*z */
for (int i = 0; i < dim; ++i) {
double sum = 0.;
for (int j = 0; j < dim; ++j) sum += mB.get(i,j) * zVect[j];
newPathS[i] = (1. - getCs()) * pathS[i]
+ Math.sqrt(getCs() * (2. - getCs())) * sum;
}
// System.out.println("pathS diff: " + BeanInspector.toString(Mathematics.vvSub(newPathS, pathS)));
// System.out.println("newPathS is " + BeanInspector.toString(newPathS));
double psNorm = Mathematics.norm(newPathS);
double hsig = 0;
if (psNorm / Math.sqrt(1. - Math.pow(1. - getCs(), 2. * generation))
/ expRandStepLen < 1.4 + 2. / (dim + 1.)) {
hsig = 1;
}
for (int i = 0; i < dim; ++i) {
newPathC[i] = (1. - getCc()) * pathC[i] + hsig
* Math.sqrt(getCc() * (2. - getCc())) * BDz[i];
}
// TODO missing: "remove momentum in ps"
if (TRACE_1) {
System.out.println("newPathC: " + BeanInspector.toString(newPathC));
System.out.println("newPathS: " + BeanInspector.toString(newPathS));
}
if (TRACE_1) System.out.println("Bef: C is \n" + mC.toString());
if (meanX == null) meanX = newMeanX;
updateCov(newPathC, newMeanX, hsig, mu, selectedSorted);
updateBD();
if (TRACE_2) System.out.println("Aft: C is \n" + mC.toString());
/* update of sigma */
sigma *= Math.exp(((psNorm / expRandStepLen) - 1) * getCs()
/ getDamps());
if (Double.isInfinite(sigma) || Double.isNaN(sigma)) {
System.err.println("Error, unstable sigma!");
}
testAndCorrectNumerics(generation, selectedSorted);
// System.out.println("sigma=" + sigma + " psLen=" + (psNorm) + " chiN="+expRandStepLen + " cs="+getCs()+ " damps="+getDamps() + " diag " + BeanInspector.toString(eigenvalues));
if (TRACE_1) {
System.out.print("psLen=" + (psNorm) + " ");
outputParams(mu);
}
// take over data
meanX = newMeanX;
pathC = newPathC;
pathS = newPathS;
firstAdaptionDone = true;
// if (TRACE_2) System.out.println("sampling around " + BeanInspector.toString(meanX));
}
/**
* Expects newPop to have correct number of generations set.
*/
public void adaptGenerational(Population oldPop, Population selectedPop,
Population newPop, boolean updateSelected) {
// nothing to do?
}
/**
* Requires selected population to be sorted by fitness.
*
* @param iterations
* @param selected
*/
void testAndCorrectNumerics(int iterations, Population selected) { // not much left here
/* Flat Fitness, Test if function values are identical */
if (iterations > 1) {
// selected pop is sorted
if (nearlySame(selected.getEAIndividual(0).getFitness(),selected.getEAIndividual(selected.size()-1).getFitness())) {
if (TRACE_1) System.err.println("flat fitness landscape, consider reformulation of fitness, step-size increased");
sigma *= Math.exp(0.2+getCs()/getDamps());
// sigma=0.1;
}
}
/* Align (renormalize) scale C (and consequently sigma) */
/* e.g. for infinite stationary state simulations (noise
* handling needs to be introduced for that) */
double fac = 1.;
double minEig = 1e-12;
double maxEig = 1e8;
if (Mathematics.max(eigenvalues) < minEig)
fac = 1./Math.sqrt(Mathematics.max(eigenvalues));
else if (Mathematics.min(eigenvalues) > maxEig)
fac = 1./Math.sqrt(Mathematics.min(eigenvalues));
if (fac != 1.) {
System.err.println("Scaling by " + fac);
sigma /= fac;
for(int i = 0; i < dim; ++i) {
pathC[i] *= fac;
eigenvalues[i] *= fac*fac;
for (int j = 0; j <= i; ++j) {
mC.set(i, j, mC.get(i,j)*fac*fac);
if (i!=j) mC.set(j, i, mC.get(i,j));
}
}
}
} // Test...
private boolean nearlySame(double[] bestFitness, double[] worstFitness) {
double epsilon = 1e-14;
for (int i=0; i<bestFitness.length; i++) if (Math.abs(bestFitness[i]-worstFitness[i])>epsilon) return false;
return true;
}
/**
* Return the range scaled sigma parameter for dimension i.
*
* @param i
* @return
*/
private double getSigma(int i) {
return sigma;
}
private double getDamps() {
return d_sig;
}
private double getCc() {
return c_c;
}
private double getCs() {
return c_sig;
}
private double calcExpRandStepLen() {
// scale by avg range?
return Math.sqrt(dim)*(1.-(1./(4*dim))+(1./(21*dim*dim)));
}
private double getAvgRange() {
double sum = 0.;
for (int i=0; i<dim; i++) sum+=(range[i][1]-range[i][0]);
return sum/dim;
}
/* update C */
private void updateCov(double[] newPathC, double[] newMeanX, double hsig, int mu, Population selected) {
double newVal = 0;
if (getCCov(mu) > 0) {
/* (only upper triangle!) */
/* update covariance matrix */
//System.out.println("CCov " + getCCov(selected) + " Cc " + getCc() + " muCov " + getMuCov(selected));
for (int i = 0; i < dim; ++i)
for (int j = 0; j <= i; ++j) {
// oldVal = mC.get(i,j);
newVal = (1 - getCCov(mu)) * mC.get(i,j)
+ getCCov(mu)
* (1. / getMuCov(mu))
* (newPathC[i] * newPathC[j] + (1 - hsig) * getCc()
* (2. - getCc()) * mC.get(i,j));
mC.set(i,j,newVal);
for (int k = 0; k < mu; ++k) { /*
* additional rank mu
* update
*/
double[] x_k = ((InterfaceDataTypeDouble)selected.getEAIndividual(k)).getDoubleData();
newVal = mC.get(i,j)+ getCCov(mu) * (1 - 1. / getMuCov(mu))
* getWeight(k) * (x_k[i] - meanX[i])
* (x_k[j] - meanX[j]) / (getSigma(i) * getSigma(j)); // TODO right sigmas?
mC.set(i,j, newVal);
}
}
// fill rest of C
for (int i = 0; i < dim; ++i) {
for (int j = i+1; j < dim; ++j) {
mC.set(i, j, mC.get(j,i));
}
}
if (mC.get(0,1) != mC.get(1,0)) {
System.err.println("WARNING");
}
// maxsqrtdiagC = Math.sqrt(math.max(math.diag(C)));
// minsqrtdiagC = Math.sqrt(math.min(math.diag(C)));
} // update of C
}
private double getMuCov(int mu) {
// default parameter value ( HK03, sec. 2)
return getMuEff(mu);
}
private double getCCov(int mu) {
// ( HK03, sec. 2)
//return Math.min(1., 2*getMuEff(selected)/(dim*dim));
double ccov = (2./(getMuCov(mu)*Math.pow(dim+Math.sqrt(2.), 2)))+(1.-(1./getMuCov(mu)))*Math.min(1., (2*getMuEff(mu)-1.)/(dim*dim+2*dim+4+getMuEff(mu)));
return ccov;
}
private double getMuEff(int mu) {
double res = 0, u;
for (int i=0; i<mu;i++) {
u = getWeight(i);
res += u*u;
}
return 1./res;
}
private void outputParams(int mu) {
System.out.println("sigma=" + sigma + " chiN="+expRandStepLen + " cs="+getCs()+ " damps="+getDamps() + " Cc=" + getCc() + " Ccov=" + getCCov(mu) + " mueff=" + getMuEff(mu) + " mucov="+getMuCov(mu));
}
private void updateBD() {
// C=triu(C)+transpose(triu(C,1)); % enforce symmetry
// [B,D] = eig(C);
// % limit condition of C to 1e14 + 1
// if max(diag(D)) > 1e14*min(diag(D))
// tmp = max(diag(D))/1e14 - min(diag(D));
// C = C + tmp*eye(N);
// D = D + tmp*eye(N);
// end
// D = diag(sqrt(diag(D))); % D contains standard deviations now
// BD = B*D; % for speed up only
////////////////////////////////////////////7
mC = (mC.plus(mC.transpose()).times(0.5)); // MAKE C SYMMETRIC
EigenvalueDecomposition helper;
// this.m_Counter = 0;
helper = new EigenvalueDecomposition(mC);
mB = helper.getV(); // Return the eigenvector matrix
eigenvalues = helper.getRealEigenvalues();
// double[] sqrtEig = eigenvalues.clone();
// for (int i = 0; i < sqrtEig.length; i++) {
// sqrtEig[i] = Math.sqrt(eigenvalues[i]);
// }
// mB.times(sqrtEig, mBD);
// Matrix test = (Matrix)mB.clone();
// System.out.println(test);
// System.out.println(test.transpose());
// System.out.println(test.times(test.transpose()));
// test = (Matrix)mB.clone();
// double[] mult = new double[dim];
// int spalte=3;
// for (int i=0; i<dim; i++) {
// System.out.println(test.get(i,spalte));
// for (int j=0; j<dim; j++) mult[i] += mC.get(i,j)*test.get(j, spalte);
// }
// System.out.println("eigenv: " + eigenvalues[spalte]);
// System.out.println(BeanInspector.toString(mult));
// System.exit(1);
}
/**
* calculate weighted mean of the selected population
* @param selectedPop
* @return
*/
private double[] calcMeanX(Population selectedPop) {
return selectedPop.getCenterWeighted(weights);
}
private double getWeight(int i) {
return weights[i];
}
private void initWeights(int mu, int lambda) {
weights = new double[mu];
double sum = 0;
int type = 0; // zero is default log scale
for (int i=0; i<mu; i++) {
if (type == 0) {
weights[i] = (Math.log((lambda+1)/2.)-Math.log(i+1));
} else weights[i] = 1.;
sum+=weights[i];
}
for (int i=0; i<mu; i++) weights[i] /= sum;
}
public void crossoverOnStrategyParameters(AbstractEAIndividual indy1,
Population partners) {
// nothing to do
}
public String getName() {
return "Rank-Mu-CMA-Mutator";
}
public String getStringRepresentation() {
return "Rank-Mu-CMA-Mutator";
}
public String globalInfo() {
return "The CMA mutator scheme with static cov. matrix, rank-mu update and weighted recombination.";
}
public void init(AbstractEAIndividual individual,
InterfaceOptimizationProblem opt) {
// TODO recheck all this; some is handled in adaptGeneration on the first call
firstAdaptionDone = false;
range = ((InterfaceDataTypeDouble)individual).getDoubleRange();
dim = range.length;
if (TRACE_1) System.out.println("WCMA init " + dim);
c_c = (4./(dim+4));
c_sig = Double.NaN; // mark as not yet initialized
// c_u_sig = Double.NaN;
d_sig = Double.NaN; // init in first adaption step!
if (TRACE_1) System.out.println("WCMA static init " + dim);
eigenvalues = new double[dim];
Arrays.fill(eigenvalues, 1.);
meanX = new double[dim];
pathC = new double[dim];
pathS = new double[dim];
// mBD = new double[dim];
mC = Matrix.identity(dim, dim);
mB = Matrix.identity(dim, dim);
sigma = 0.2;
z = new double[dim];
zCor = new double[dim];
expRandStepLen = calcExpRandStepLen();
}
public void mutate(AbstractEAIndividual individual) {
// if (!firstAdaptionDone) {
// if (TRACE) System.out.println("No mutation before first adaptions step");
// return;
// }
if (individual instanceof InterfaceDataTypeDouble) {
double[] x = ((InterfaceDataTypeDouble)individual).getDoubleData();
// if (TRACE) System.out.println("WCMA mutate, bef: " + BeanInspector.toString(x));
double[][] range = ((InterfaceDataTypeDouble)individual).getDoubleRange();
((InterfaceDataTypeDouble)individual).SetDoubleGenotype(mutate(x, range, 0));
// if (TRACE) System.out.println("WCMA mutate, aft: " + BeanInspector.toString(x));
} else System.err.println("Error, expecting InterfaceDataTypeDouble");
}
private double[] mutate(double[] x, double[][] range, int count) {
if (firstAdaptionDone) {
double[] artmp = new double[x.length];
for (int i = 0; i < dim; ++i) {
artmp[i] = Math.sqrt(eigenvalues[i]) * RNG.gaussianDouble(1.);
}
// System.out.println("Sampling around " + BeanInspector.toString(meanX));
/* add mutation (sigma * B * (D*z)) */
for (int i = 0; i < dim; ++i) {
double sum = 0.;
for (int j = 0; j < dim; ++j)
sum += mB.get(i,j) * artmp[j];
x[i] = meanX[i]+getSigma(i)*sum;
}
} else {
// no valid meanX yet, so just do a gaussian jump with sigma
for (int i = 0; i < dim; ++i) {
x[i] += RNG.gaussianDouble(getSigma(i));
}
}
if (isInRange(x, range)) return x;
else {
if (count > 5) return repairMutation(x, range); // allow some nice tries before using brute force
else return mutate(x, range, count+1); // for really bad initial deviations this might be a quasi infinite loop
}
}
private double[] repairMutation(double[] x, double[][] range) {
// TODO % You may handle constraints here. You may either resample
// % arz(:,k) and/or multiply it with a factor between -1 and 1
// % (the latter will decrease the overall step size) and
// % recalculate arx accordingly. Do not change arx or arz in any
// % other way.
for (int i=0; i<x.length; i++) {
if (x[i]<range[i][0]) x[i]=range[i][0];
else if (x[i]>range[i][1]) x[i]=range[i][1];
}
return x;
}
private boolean isInRange(double[] x, double[][] range) {
for (int i=0; i<x.length; i++) {
if (x[i]<range[i][0] || (x[i]>range[i][1])) return false;
}
return true;
}
/**
* After optimization start, this returns the initial sigma value
* actually employed.
*
* @return the initial sigma value actually employed
*/
public double getFirstSigma() {
return firstSigma;
}
/**
* @return the initialSig
*/
public InitialSigmaEnum getInitialSigma() {
return initialSig;
}
/**
* @param initialSig the initialSig to set
*/
public void setInitialSigma(InitialSigmaEnum initialSig) {
this.initialSig = initialSig;
}
public String initialSigmaTipText() {
return "Method to use for setting the initial step size.";
}
/**
* From Auger&Hansen, CEC '05, stopping criterion TolX.
*
* @param tolX
* @return
*/
public boolean testAllDistBelow(double tolX) {
// if all(sigma*(max(abs(pc), sqrt(diag(C)))) < stopTolX)
boolean res = true;
int i=0;
while (res && i<dim) {
res = res && (getSigma(i)*Math.max(Math.abs(pathC[i]), Math.sqrt(mC.get(i,i))) < tolX);
i++;
}
if (TRACE_TEST) if (res) System.out.println("testAllDistBelow hit");
return res;
}
/**
* From Auger&Hansen, CEC '05, stopping criterion noeffectaxis.
* @param d
* @param gen
* @return
*/
public boolean testNoChangeAddingDevAxis(double d, int gen) {
// if all(xmean == xmean + 0.1*sigma*BD(:,1+floor(mod(countiter,N))))
// i = 1+floor(mod(countiter,N));
// stopflag(end+1) = {'warnnoeffectaxis'};
int k = gen%dim;
double[] ev_k = mB.getColumn(k);
Mathematics.svMult(Math.sqrt(eigenvalues[k]), ev_k, ev_k); // this is now e_k*v_k = BD(:,...)
int i=0;
boolean res = true;
while (res && (i<dim)) {
res = res && (meanX[i] == (meanX[i] + d*getSigma(i)*ev_k[i]));
i++;
}
if (TRACE_TEST) if (res) System.out.println("testNoChangeAddingDevAxis hit");
return res;
}
/**
* From Auger&Hansen, CEC '05, stopping criterion noeffectcoord.
* @param d
* @return
*/
public boolean testNoEffectCoord(double d) {
// if any(xmean == xmean + 0.2*sigma*sqrt(diag(C)))
// stopflag(end+1) = {'warnnoeffectcoord'};
boolean ret = false;
int i=0;
while ((i<dim) && !ret) {
ret = ret || (meanX[i]==(meanX[i] + d*getSigma(i)*Math.sqrt(mC.get(i, i))));
i++;
}
if (TRACE_TEST) if (ret) System.out.println("testNoEffectCoord hit");
return ret;
}
/**
* Test condition of C (Auger&Hansen, CEC '05, stopping criterion conditioncov).
* Return true, if a diagonal entry is <= 0 or >= d.
*
* @param d
* @return true, if a diagonal entry is <= 0 or >= d, else false
*/
public boolean testCCondition(double d) {
// if (min(diag(D)) <= 0) || (max(diag(D)) > 1e14*min(diag(D)))
// stopflag(end+1) = {'warnconditioncov'};
Pair<Double,Double> minMax = mC.getMinMaxDiag();
if ((minMax.head <= 0) || (minMax.tail >= d)) {
if (TRACE_TEST) System.out.println("testCCondition hit");
return true;
} else return false;
}
}
enum InitialSigmaEnum {
halfRange, avgInitialDistance;
}

View File

@ -1,121 +1,120 @@
package eva2.server.go.operators.mutation;
import eva2.server.go.individuals.AbstractEAIndividual;
import eva2.server.go.individuals.InterfaceDataTypeDouble;
import eva2.server.go.individuals.InterfaceESIndividual;
import eva2.server.go.populations.Population;
import eva2.server.go.problems.InterfaceOptimizationProblem;
import wsi.ra.math.RNG;
/**
* Created by IntelliJ IDEA.
* User: streiche
* Date: 15.05.2003
* Time: 17:04:24
* To change this template use Options | File Templates.
*/
public class MutateESStandard implements InterfaceMutation, java.io.Serializable {
protected double m_MutationStepSize = 0.1;
public MutateESStandard() {
}
public MutateESStandard(MutateESStandard d) {
this.m_MutationStepSize = d.m_MutationStepSize;
}
/** This method will enable you to clone a given mutation operator
* @return The clone
*/
public Object clone() {
return new MutateESStandard(this);
}
/** This method allows you to evaluate wether two mutation operators
* are actually the same.
* @param mutator The other mutation operator
*/
public boolean equals(Object mutator) {
if (mutator instanceof MutateESStandard) {
MutateESStandard mut = (MutateESStandard)mutator;
if (this.m_MutationStepSize != mut.m_MutationStepSize) return false;
return true;
} else return false;
}
/** This method allows you to init the mutation operator
* @param individual The individual that will be mutated.
* @param opt The optimization problem.
*/
public void init(AbstractEAIndividual individual, InterfaceOptimizationProblem opt) {
}
/** This method will mutate a given AbstractEAIndividual. If the individual
* doesn't implement InterfaceESIndividual nothing happens.
* @param individual The individual that is to be mutated
*/
public void mutate(AbstractEAIndividual individual) {
//System.out.println("Before Mutate: " +((GAIndividual)individual).getSolutionRepresentationFor());
if (individual instanceof InterfaceESIndividual) {
double[] x = ((InterfaceESIndividual)individual).getDGenotype();
double[][] range = ((InterfaceESIndividual)individual).getDoubleRange();
for (int i = 0; i < x.length; i++) {
x[i] += ((range[i][1] -range[i][0])/2)*RNG.gaussianDouble(this.m_MutationStepSize);
if (range[i][0] > x[i]) x[i] = range[i][0];
if (range[i][1] < x[i]) x[i] = range[i][1];
}
((InterfaceESIndividual)individual).SetDGenotype(x);
}
//System.out.println("After Mutate: " +((GAIndividual)individual).getSolutionRepresentationFor());
}
/** This method allows you to perform either crossover on the strategy parameters
* or to deal in some other way with the crossover event.
* @param indy1 The original mother
* @param partners The original partners
*/
public void crossoverOnStrategyParameters(AbstractEAIndividual indy1, Population partners) {
// nothing to do here
}
/** This method allows you to get a string representation of the mutation
* operator
* @return A descriptive string.
*/
public String getStringRepresentation() {
return "ES standard mutation";
}
/**********************************************************************************************************************
* These are for GUI
*/
/** This method allows the CommonJavaObjectEditorPanel to read the
* name to the current object.
* @return The name.
*/
public String getName() {
return "ES standard mutation ";
}
/** This method returns a global info string
* @return description
*/
public String globalInfo() {
return "The standard mutation alters all elements of the double attributes with a fixed mutation step size.";
}
/** This method allows you to set the fixed mutation step size
* @param step The new mutation step size
*/
public void setMutationStepSize(double step) {
if (step < 0) step = 0.0000001;
this.m_MutationStepSize = step;
}
public double getMutationStepSize() {
return this.m_MutationStepSize;
}
public String mutationStepSizeTipText() {
return "Set the value for the fixed mutation step size.";
}
}
//package eva2.server.go.operators.mutation;
//
//import eva2.server.go.individuals.AbstractEAIndividual;
//import eva2.server.go.individuals.InterfaceDataTypeDouble;
//import eva2.server.go.individuals.InterfaceESIndividual;
//import eva2.server.go.populations.Population;
//import eva2.server.go.problems.InterfaceOptimizationProblem;
//import wsi.ra.math.RNG;
//
///**
// * Created by IntelliJ IDEA.
// * User: streiche
// * Date: 15.05.2003
// * Time: 17:04:24
// * To change this template use Options | File Templates.
// */
//public class MutateESStandard implements InterfaceMutation, java.io.Serializable {
// protected double m_MutationStepSize = 0.1;
// public MutateESStandard() {
// }
//
// public MutateESStandard(MutateESStandard d) {
// this.m_MutationStepSize = d.m_MutationStepSize;
// }
//
// /** This method will enable you to clone a given mutation operator
// * @return The clone
// */
// public Object clone() {
// return new MutateESStandard(this);
// }
//
// /** This method allows you to evaluate wether two mutation operators
// * are actually the same.
// * @param mutator The other mutation operator
// */
// public boolean equals(Object mutator) {
// if (mutator instanceof MutateESStandard) {
// MutateESStandard mut = (MutateESStandard)mutator;
// if (this.m_MutationStepSize != mut.m_MutationStepSize) return false;
// return true;
// } else return false;
// }
//
// /** This method allows you to init the mutation operator
// * @param individual The individual that will be mutated.
// * @param opt The optimization problem.
// */
// public void init(AbstractEAIndividual individual, InterfaceOptimizationProblem opt) {
//
// }
//
// /** This method will mutate a given AbstractEAIndividual. If the individual
// * doesn't implement InterfaceESIndividual nothing happens.
// * @param individual The individual that is to be mutated
// */
// public void mutate(AbstractEAIndividual individual) {
// //System.out.println("Before Mutate: " +((GAIndividual)individual).getSolutionRepresentationFor());
// if (individual instanceof InterfaceESIndividual) {
// double[] x = ((InterfaceESIndividual)individual).getDGenotype();
// double[][] range = ((InterfaceESIndividual)individual).getDoubleRange();
// for (int i = 0; i < x.length; i++) {
// x[i] += ((range[i][1] -range[i][0])/2)*RNG.gaussianDouble(this.m_MutationStepSize);
// if (range[i][0] > x[i]) x[i] = range[i][0];
// if (range[i][1] < x[i]) x[i] = range[i][1];
// }
// ((InterfaceESIndividual)individual).SetDGenotype(x);
//
// }
// //System.out.println("After Mutate: " +((GAIndividual)individual).getSolutionRepresentationFor());
// }
//
// /** This method allows you to perform either crossover on the strategy parameters
// * or to deal in some other way with the crossover event.
// * @param indy1 The original mother
// * @param partners The original partners
// */
// public void crossoverOnStrategyParameters(AbstractEAIndividual indy1, Population partners) {
// // nothing to do here
// }
//
// /** This method allows you to get a string representation of the mutation
// * operator
// * @return A descriptive string.
// */
// public String getStringRepresentation() {
// return "ES standard mutation";
// }
//
///**********************************************************************************************************************
// * These are for GUI
// */
// /** This method allows the CommonJavaObjectEditorPanel to read the
// * name to the current object.
// * @return The name.
// */
// public String getName() {
// return "ES standard mutation ";
// }
// /** This method returns a global info string
// * @return description
// */
// public String globalInfo() {
// return "The standard mutation alters all elements of the double attributes with a fixed mutation step size.";
// }
//
// /** This method allows you to set the fixed mutation step size
// * @param step The new mutation step size
// */
// public void setMutationStepSize(double step) {
// if (step < 0) step = 0.0000001;
// this.m_MutationStepSize = step;
// }
// public double getMutationStepSize() {
// return this.m_MutationStepSize;
// }
// public String mutationStepSizeTipText() {
// return "Set the value for the fixed mutation step size.";
// }
//}

View File

@ -14,11 +14,7 @@ import wsi.ra.math.RNG;
* Time: 14:11:49
* To change this template use File | Settings | File Templates.
*/
public class MutateESSuccessRule extends MutateESStandard implements InterfaceMutation, java.io.Serializable {
/*
* This is a bit of a cheat as the implementation does only hold some
* more parameters while the ES strategy really acts on it.
*/
public class MutateESSuccessRule extends MutateESFixedStepSize implements InterfaceMutationGenerational, java.io.Serializable {
// it would be quite nice to make this variable static, but in that case
// no one could runs n independent ES runs in parallel anymore *sigh*
// protected static double m_MutationStepSize = 0.2;
@ -30,7 +26,7 @@ public class MutateESSuccessRule extends MutateESStandard implements InterfaceMu
}
public MutateESSuccessRule(MutateESSuccessRule mutator) {
this.m_MutationStepSize = mutator.m_MutationStepSize;
super(mutator);
this.m_SuccessRate = mutator.m_SuccessRate;
this.m_Alpha = mutator.m_Alpha;
}
@ -49,12 +45,13 @@ public class MutateESSuccessRule extends MutateESStandard implements InterfaceMu
public boolean equals(Object mutator) {
if (mutator instanceof MutateESSuccessRule) {
MutateESSuccessRule mut = (MutateESSuccessRule)mutator;
if (this.m_MutationStepSize != mut.m_MutationStepSize) return false;
if (this.m_Sigma != mut.m_Sigma) return false;
if (this.m_SuccessRate != mut.m_SuccessRate) return false;
if (this.m_Alpha != mut.m_Alpha) return false;
return true;
} else return false;
}
/** This method allows you to get a string representation of the mutation
* operator
* @return A descriptive string.
@ -66,12 +63,12 @@ public class MutateESSuccessRule extends MutateESStandard implements InterfaceMu
/** This method increases the mutation step size.
*/
public void increaseMutationStepSize() {
this.m_MutationStepSize = this.m_MutationStepSize * this.m_Alpha;
this.m_Sigma = this.m_Sigma * this.m_Alpha;
}
/** This method decrease the mutation step size.
*/
public void decreaseMutationStepSize() {
this.m_MutationStepSize = this.m_MutationStepSize / this.m_Alpha;
this.m_Sigma = this.m_Sigma / this.m_Alpha;
}
/**********************************************************************************************************************
@ -121,6 +118,36 @@ public class MutateESSuccessRule extends MutateESStandard implements InterfaceMu
return this.m_Alpha;
}
public String alphaTipText() {
return "Choose the factor by which the mutation step size is to be increased/decreased.";
return "Choose the factor > 1 by which the mutation step size is to be increased/decreased.";
}
public void adaptAfterSelection(Population oldGen, Population selected) {
// nothing to do here
}
public void adaptGenerational(Population selectedPop, Population parentPop, Population newPop, boolean updateSelected) {
double rate = 0.;
for (int i = 0; i < parentPop.size(); i++) {
// calculate success rate
// System.out.println("new fit / old fit: " + BeanInspector.toString(newPop.getEAIndividual(i).getFitness()) + " , " + BeanInspector.toString(parentPop.getEAIndividual(i).getFitness()));
if (newPop.getEAIndividual(i).getFitness(0) < parentPop.getEAIndividual(i).getFitness(0)) rate++;
}
rate = rate / parentPop.size();
if (updateSelected) for (int i = 0; i < selectedPop.size(); i++) { // applied to the old population as well in case of plus strategy
MutateESSuccessRule mutator = (MutateESSuccessRule)((AbstractEAIndividual)selectedPop.get(i)).getMutationOperator();
updateMutator(rate, mutator);
// System.out.println("old pop step size " + mutator.getSigma()+ " (" + mutator+ ")");
}
for (int i = 0; i < newPop.size(); i++) {
MutateESSuccessRule mutator = (MutateESSuccessRule)((AbstractEAIndividual)newPop.get(i)).getMutationOperator();
updateMutator(rate, mutator);
// System.out.println("new pop step size " + mutator.getSigma()+ " (" + mutator+ ")");
}
}
private void updateMutator(double rate, MutateESSuccessRule mutator) {
if (rate < mutator.getSuccessRate()) mutator.decreaseMutationStepSize();
else mutator.increaseMutationStepSize();
}
}

View File

@ -62,6 +62,14 @@ Serializable {
else convergenceCondition.setSelectedTag("Relative");
}
public FitnessConvergenceTerminator(FitnessConvergenceTerminator other) {
pMetric = new PhenotypeMetric();
convThresh = other.convThresh;
this.m_stagTime = other.m_stagTime;
stagnationMeasure.setSelectedTag(other.getStagnationMeasure().getSelectedTagID());
convergenceCondition.setSelectedTag(other.getConvergenceCondition().getSelectedTagID());
}
/**
*
*/

View File

@ -941,6 +941,9 @@ public class Population extends ArrayList implements PopulationInterface, Clonea
/**
* Fire an event every n function calls, the event sends the public String funCallIntervalReached.
* Be aware that if this interval is smaller than the population size, it may happen that a notification
* is fired before all individuals have been evaluated once, meaning that a false zero fitness
* appears at the beginning of the optimization.
*
* @param notifyEvalInterval the notifyEvalInterval to set
*/

View File

@ -56,7 +56,7 @@ public abstract class AbstractOptimizationProblem implements InterfaceOptimizati
// System.err.println("Population evaluation seems not required!");
// } else {
// @todo This is the position to implement a granular
// @todo paralliziation scheme
// @todo paralleliziation scheme
evaluatePopulationStart(population);
for (int i = 0; i < population.size(); i++) {
tmpIndy = (AbstractEAIndividual) population.get(i);

View File

@ -90,8 +90,10 @@ public class CHCAdaptiveSearchAlgorithm implements InterfaceOptimizer, java.io.S
System.out.println("Problem does not apply InterfaceGAIndividual, which is the only individual type valid for CHC!");
}
this.evaluatePopulation(this.m_Population);
this.firePropertyChangedEvent("NextGenerationPerformed");
if (reset) {
this.evaluatePopulation(this.m_Population);
this.firePropertyChangedEvent("NextGenerationPerformed");
}
}
/** This method will evaluate the current population using the

View File

@ -124,9 +124,11 @@ public class ClusteringHillClimbing implements InterfacePopulationChangedEventLi
loopCnt = 0;
this.m_Population = (Population)pop.clone();
m_Population.addPopulationChangedEventListener(null);
if (reset) this.m_Population.init();
this.m_Problem.evaluate(this.m_Population);
this.firePropertyChangedEvent("NextGenerationPerformed");
if (reset) {
this.m_Population.init();
this.m_Problem.evaluate(this.m_Population);
this.firePropertyChangedEvent("NextGenerationPerformed");
}
}
/** Something has changed

View File

@ -93,11 +93,13 @@ public class DifferentialEvolution implements InterfaceOptimizer, java.io.Serial
*/
public void initByPopulation(Population pop, boolean reset) {
this.m_Population = (Population)pop.clone();
if (reset) this.m_Population.init();
if (reset) {
this.m_Population.init();
this.evaluatePopulation(this.m_Population);
this.firePropertyChangedEvent("NextGenerationPerformed");
}
// if (reset) this.m_Population.init();
// else children = new Population(m_Population.size());
this.evaluatePopulation(this.m_Population);
this.firePropertyChangedEvent("NextGenerationPerformed");
}
/** This method will evaluate the current population using the

View File

@ -1,7 +1,10 @@
package eva2.server.go.strategies;
import eva2.gui.BeanInspector;
import eva2.gui.GenericObjectEditor;
import eva2.server.go.InterfacePopulationChangedEventListener;
import eva2.server.go.individuals.AbstractEAIndividual;
import eva2.server.go.operators.mutation.InterfaceMutationGenerational;
import eva2.server.go.operators.mutation.MutateESSuccessRule;
import eva2.server.go.operators.selection.InterfaceSelection;
import eva2.server.go.operators.selection.SelectBestIndividuals;
@ -33,7 +36,6 @@ public class EvolutionStrategies implements InterfaceOptimizer, java.io.Serializ
//private double m_MyuRatio = 6;
private int m_Mu = 5;
private int m_Lambda = 20;
private int m_InitialPopulationSize = 0;
private boolean m_UsePlusStrategy = false;
private Population m_Population = new Population();
private InterfaceOptimizationProblem m_Problem = new B1Problem();
@ -42,7 +44,7 @@ public class EvolutionStrategies implements InterfaceOptimizer, java.io.Serializ
private InterfaceSelection m_EnvironmentSelection = new SelectBestIndividuals();
private int m_NumberOfPartners = 1;
private int origPopSize = -1; // especially for CBN
private double[] m_FitnessOfParents = null;
// private double[] m_FitnessOfParents = null;
private boolean forceOrigPopSize = true;// especially for CBN
transient private String m_Identifier = "";
@ -64,7 +66,6 @@ public class EvolutionStrategies implements InterfaceOptimizer, java.io.Serializ
this.m_Problem = (InterfaceOptimizationProblem)a.m_Problem.clone();
this.m_Mu = a.m_Mu;
this.m_Lambda = a.m_Lambda;
this.m_InitialPopulationSize = a.m_InitialPopulationSize;
this.m_UsePlusStrategy = a.m_UsePlusStrategy;
this.m_NumberOfPartners = a.m_NumberOfPartners;
this.m_ParentSelection = (InterfaceSelection)a.m_ParentSelection.clone();
@ -72,6 +73,10 @@ public class EvolutionStrategies implements InterfaceOptimizer, java.io.Serializ
this.m_EnvironmentSelection = (InterfaceSelection)a.m_EnvironmentSelection.clone();
}
public void hideHideable() {
GenericObjectEditor.setHideProperty(this.getClass(), "population", true);
}
public Object clone() {
return (Object) new EvolutionStrategies(this);
}
@ -86,7 +91,7 @@ public class EvolutionStrategies implements InterfaceOptimizer, java.io.Serializ
this.m_Problem.initPopulation(this.m_Population);
this.evaluatePopulation(this.m_Population);
// this.m_Population.setPopulationSize(orgPopSize);
this.firePropertyChangedEvent("NextGenerationPerformed");
// this.firePropertyChangedEvent("NextGenerationPerformed");// not necessary if incrGeneration is called
}
@ -98,9 +103,11 @@ public class EvolutionStrategies implements InterfaceOptimizer, java.io.Serializ
origPopSize = pop.getPopulationSize();
// System.out.println("ES: orig popsize is " + origPopSize);
this.m_Population = (Population)pop.clone();
if (reset) this.m_Population.init();
this.evaluatePopulation(this.m_Population);
this.firePropertyChangedEvent("NextGenerationPerformed");
if (reset) {
this.m_Population.init();
this.evaluatePopulation(this.m_Population);
// this.firePropertyChangedEvent("NextGenerationPerformed"); // not necessary if incrGeneration is called
}
}
/** This method will evaluate the current population using the
@ -129,94 +136,88 @@ public class EvolutionStrategies implements InterfaceOptimizer, java.io.Serializ
/** This method will generate the offspring population from the
* given population of evaluated individuals.
*/
private Population generateChildren() {
Population result = this.m_Population.cloneWithoutInds(), parents;
protected Population generateEvalChildren(Population fromPopulation) {
Population result = m_Population.cloneWithoutInds(), parents;
AbstractEAIndividual[] offSprings;
AbstractEAIndividual tmpIndy;
result.clear();
this.m_ParentSelection.prepareSelection(this.m_Population);
this.m_PartnerSelection.prepareSelection(this.m_Population);
parents = this.m_ParentSelection.selectFrom(this.m_Population, this.m_Lambda);
this.m_ParentSelection.prepareSelection(fromPopulation);
this.m_PartnerSelection.prepareSelection(fromPopulation);
parents = this.m_ParentSelection.selectFrom(fromPopulation, this.m_Lambda);
for (int i = 0; i < parents.size(); i++) {
tmpIndy = (AbstractEAIndividual)parents.get(i);
if (tmpIndy == null) System.out.println("Individual null "+i);
if (parents == null) System.out.println("parents null "+i);
if (tmpIndy.getMutationOperator() instanceof MutateESSuccessRule) {
if (this.m_FitnessOfParents == null) this.m_FitnessOfParents = new double[this.m_Lambda];
this.m_FitnessOfParents[i] = tmpIndy.getFitness(0);
}
offSprings = tmpIndy.mateWith(this.m_PartnerSelection.findPartnerFor(tmpIndy, this.m_Population, this.m_NumberOfPartners));
// for (int j = 0; j < offSprings.length; j++) {
// offSprings[j].mutate();
// }
offSprings = tmpIndy.mateWith(this.m_PartnerSelection.findPartnerFor(tmpIndy, fromPopulation, this.m_NumberOfPartners));
offSprings[0].mutate();
result.add(i, offSprings[0]);
}
this.evaluatePopulation(result);
if (result.getEAIndividual(0).getMutationOperator() instanceof InterfaceMutationGenerational) {
// this seems to be the right moment for the 1/5-success rule
// parents and result have the same size and correspond per individual
((InterfaceMutationGenerational)parents.getEAIndividual(0).getMutationOperator()).adaptGenerational(fromPopulation, parents, result, m_UsePlusStrategy);
}
return result;
}
protected Population selectParents() {
this.m_EnvironmentSelection.prepareSelection(this.m_Population);
return this.m_EnvironmentSelection.selectFrom(this.m_Population, this.m_Mu);
}
/** The optimize method will compute a 'improved' and evaluated population
*/
public void optimize() {
Population nextGeneration, parents;
// // calculate myu and lambda from the current population size and settings
// if (this.m_UsePlusStrategy) {
// this.m_Myu = (int)Math.round((this.m_Population.size()/this.m_MyuRatio) - (this.m_Population.size()/Math.pow(this.m_MyuRatio, 2)));
// this.m_Myu = Math.max(1, this.m_Myu);
// this.m_Lambda = this.m_Population.size() - this.m_Myu;
//// System.out.println("Parameters: (Pop.size:"+this.m_Population.size()+"; MyuRatio:"+this.m_MyuRatio+")");
//// System.out.println("Population Strategy: ("+ this.m_Myu+"+"+this.m_Lambda+")");
// }
// else {
// this.m_Lambda = this.m_Population.size();
// this.m_Myu = (int)Math.round(this.m_Population.size()/this.m_MyuRatio);
// this.m_Myu = Math.max(1, this.m_Myu);
//// System.out.println("Parameters: (Pop.size:"+this.m_Population.size()+"; MyuRatio:"+this.m_MyuRatio+")");
//// System.out.println("Population Strategy: ("+ this.m_Myu+","+this.m_Lambda+")");
// }
//System.out.println("optimize");
// first perform the environment selection to select myu parents
this.m_EnvironmentSelection.prepareSelection(this.m_Population);
parents = this.m_EnvironmentSelection.selectFrom(this.m_Population, this.m_Mu);
this.m_Population.clear();
this.m_Population.addPopulation(parents);
parents = selectParents();
// System.out.println("-- selected avg fit " + BeanInspector.toString(parents.getMeanFitness()) + " from last gen " + BeanInspector.toString(m_Population.getMeanFitness()));
// m_Population / parents are of sizes lambda / mu
if (parents.getEAIndividual(0).getMutationOperator() instanceof InterfaceMutationGenerational) {
((InterfaceMutationGenerational)parents.getEAIndividual(0).getMutationOperator()).adaptAfterSelection(getPopulation(), parents);
}
// now generate the lambda offsprings
this.m_FitnessOfParents = null;
nextGeneration = this.generateChildren();
this.evaluatePopulation(nextGeneration);
if ((this.m_FitnessOfParents != null) && (((AbstractEAIndividual)parents.get(0)).getMutationOperator() instanceof MutateESSuccessRule)) {
double rate = 0;
for (int i = 0; i < this.m_FitnessOfParents.length; i++) {
if (((AbstractEAIndividual)nextGeneration.get(i)).getFitness(0) < this.m_FitnessOfParents[i]) rate++;
}
this.applySuccessRule((rate/((double)this.m_FitnessOfParents.length)), this.m_Population, nextGeneration);
}
if (this.m_UsePlusStrategy) nextGeneration.addPopulation(this.m_Population);
nextGeneration = this.generateEvalChildren(parents); // create lambda new ones from mu parents
if (forceOrigPopSize && (origPopSize > 0) && (origPopSize < nextGeneration.size())) {
// this is especially for CBN:
this.m_EnvironmentSelection.prepareSelection(nextGeneration);
Population tmpPop = (Population)nextGeneration.clone();
nextGeneration.clear();
nextGeneration.addPopulation(this.m_EnvironmentSelection.selectFrom(tmpPop, origPopSize));
// System.out.println("ES post selection! " + origPopSize + " from " + tmpPop.size());
m_Population = nextGeneration;
} else {
if ((origPopSize > 0) && (origPopSize != nextGeneration.size())) {
System.err.println("Warning in ES! orig: " + origPopSize + " / " + nextGeneration.size());
}
this.m_Population = nextGeneration;
}
//System.out.println("Population size: " + this.m_Population.size());
//System.out.println("-- Best Fitness " + this.m_Population.getBestFitness()[0]);
if (this.isPlusStrategy()) nextGeneration.addPopulation(parents);
setPop(getReplacePop(nextGeneration));
// System.out.println("Population size: " + this.m_Population.size());
// System.out.println("-- Best Fitness " + this.m_Population.getBestFitness()[0]);
this.firePropertyChangedEvent("NextGenerationPerformed");
this.firePropertyChangedEvent("NextGenerationPerformed"); // necessary here because evalPop was not called on m_Population
}
/**
* Usually, this just returns the given population.
* However, in case of CBN this method prepares the next generation according to the species size.
*
* @param nextGeneration
* @return
*/
protected Population getReplacePop(Population nextGeneration) {
if (forceOrigPopSize && (origPopSize > 0) && (origPopSize < nextGeneration.size())) {
// this is especially for CBN:
this.m_EnvironmentSelection.prepareSelection(nextGeneration);
Population tmpPop = (Population)nextGeneration.clone();
nextGeneration.clear();
nextGeneration.addPopulation(this.m_EnvironmentSelection.selectFrom(tmpPop, origPopSize));
// System.out.println("ES post selection! " + origPopSize + " from " + tmpPop.size());
} else {
if ((origPopSize > 0) && (origPopSize != nextGeneration.size())) {
System.err.println("Warning in ES! orig: " + origPopSize + " / " + nextGeneration.size());
}
}
return nextGeneration;
}
/** This method is just a shortcut to set the mutation step size for
@ -227,46 +228,48 @@ public class EvolutionStrategies implements InterfaceOptimizer, java.io.Serializ
* @param oldPop The old population
* @param newPop The new population
*/
private void applySuccessRule(double successRate, Population oldPop, Population newPop) {
MutateESSuccessRule mutator = (MutateESSuccessRule)((AbstractEAIndividual)oldPop.get(0)).getMutationOperator();
boolean success = (successRate < mutator.getSuccessRate());
// this was the old solution when the mutation step size was still static
// if (successRate < mutator.getSuccessRate()) {
// mutator.decreaseMutationStepSize();
// } else {
// mutator.increaseMutationStepSize();
// private void applySuccessRule(double successRate, Population oldPop, Population newPop) {
// MutateESSuccessRule mutator = (MutateESSuccessRule)((AbstractEAIndividual)oldPop.get(0)).getMutationOperator();
// boolean success = (successRate < mutator.getSuccessRate());
// // this was the old solution when the mutation step size was still static
//// if (successRate < mutator.getSuccessRate()) {
//// mutator.decreaseMutationStepSize();
//// } else {
//// mutator.increaseMutationStepSize();
//// }
// if (isPlusStrategy()) for (int i = 0; i < oldPop.size(); i++) { // applied to the old population as well for plus strategy
// if (((AbstractEAIndividual)oldPop.get(i)).getMutationOperator() instanceof MutateESSuccessRule) {
// mutator = (MutateESSuccessRule)((AbstractEAIndividual)oldPop.get(i)).getMutationOperator();
// if (success) mutator.decreaseMutationStepSize();
// else mutator.increaseMutationStepSize();
// System.out.println("old pop step size " + mutator.getSigma()+ " (" + mutator+ ")");
// }
// }
for (int i = 0; i < oldPop.size(); i++) {
if (((AbstractEAIndividual)oldPop.get(i)).getMutationOperator() instanceof MutateESSuccessRule) {
mutator = (MutateESSuccessRule)((AbstractEAIndividual)oldPop.get(i)).getMutationOperator();
if (success) mutator.decreaseMutationStepSize();
else mutator.increaseMutationStepSize();
}
}
for (int i = 0; i < newPop.size(); i++) {
if (((AbstractEAIndividual)newPop.get(i)).getMutationOperator() instanceof MutateESSuccessRule) {
mutator = (MutateESSuccessRule)((AbstractEAIndividual)newPop.get(i)).getMutationOperator();
if (success) mutator.decreaseMutationStepSize();
else mutator.increaseMutationStepSize();
}
}
this.m_FitnessOfParents = null;
}
// for (int i = 0; i < newPop.size(); i++) {
// if (((AbstractEAIndividual)newPop.get(i)).getMutationOperator() instanceof MutateESSuccessRule) {
// mutator = (MutateESSuccessRule)((AbstractEAIndividual)newPop.get(i)).getMutationOperator();
// if (success) mutator.decreaseMutationStepSize();
// else mutator.increaseMutationStepSize();
// System.out.println("new pop step size " + mutator.getSigma() + " (" + mutator+ ")");
// }
// }
//// this.m_FitnessOfParents = null;
// }
/** This is for debugging only
*/
private String showFitness(Population pop) {
String result = "";
AbstractEAIndividual indy;
double[] fitness;
for (int i = 0; i < pop.size(); i++) {
indy = (AbstractEAIndividual)pop.get(i);
fitness = indy.getFitness();
for (int j = 0; j < fitness.length; j++) result += fitness[j] +"; ";
result += "\n";
}
return result;
}
// /** This is for debugging only
// */
// private String showFitness(Population pop) {
// String result = "";
// AbstractEAIndividual indy;
// double[] fitness;
// for (int i = 0; i < pop.size(); i++) {
// indy = (AbstractEAIndividual)pop.get(i);
// fitness = indy.getFitness();
// for (int j = 0; j < fitness.length; j++) result += fitness[j] +"; ";
// result += "\n";
// }
// return result;
// }
/** This method allows you to add the LectureGUI as listener to the Optimizer
* @param ea
@ -276,7 +279,7 @@ public class EvolutionStrategies implements InterfaceOptimizer, java.io.Serializ
}
/** Something has changed
*/
protected void firePropertyChangedEvent (String name) {
protected void firePropertyChangedEvent(String name) {
if (this.m_Listener != null) this.m_Listener.registerPopulationStateChanged(this, name);
}
@ -354,7 +357,7 @@ public class EvolutionStrategies implements InterfaceOptimizer, java.io.Serializ
* @return The name of the algorithm
*/
public String getName() {
return "("+getMu()+(getPlusStrategy() ? "+" : ",")+getLambda()+")-ES";
return "("+getMu()+(isPlusStrategy() ? "+" : ",")+getLambda()+")-ES";
}
/**
@ -366,6 +369,12 @@ public class EvolutionStrategies implements InterfaceOptimizer, java.io.Serializ
public Population getPopulation() {
return this.m_Population;
}
// for internal usage
protected void setPop(Population pop) {
m_Population = pop;
}
public void setPopulation(Population pop){
origPopSize = pop.size();
// System.out.println("ES: orig popsize is " + origPopSize);
@ -437,7 +446,7 @@ public class EvolutionStrategies implements InterfaceOptimizer, java.io.Serializ
this.m_UsePlusStrategy = elitism;
this.checkPopulationConstraints();
}
public boolean getPlusStrategy() {
public boolean isPlusStrategy() {
return this.m_UsePlusStrategy;
}
public String plusStrategyTipText() {
@ -513,17 +522,4 @@ public class EvolutionStrategies implements InterfaceOptimizer, java.io.Serializ
public String lambdaTipText() {
return "This is the children population size.";
}
/** Set an initial population size (if smaller lambda this is ignored).
* @param l The inital population size.
*/
public void setInitialPopulationSize(int l) {
this.m_InitialPopulationSize = l;
}
public int getInitialPopulationSize() {
return this.m_InitialPopulationSize;
}
public String initialPopulationSizeTipText() {
return "Set an initial population size (if smaller lambda this is ignored).";
}
}

View File

@ -0,0 +1,251 @@
package eva2.server.go.strategies;
import java.util.Arrays;
import java.util.LinkedList;
import eva2.gui.GenericObjectEditor;
import eva2.server.go.InterfacePopulationChangedEventListener;
import eva2.server.go.individuals.AbstractEAIndividual;
import eva2.server.go.operators.mutation.MutateESRankMuCMA;
import eva2.server.go.operators.terminators.FitnessConvergenceTerminator;
import eva2.server.go.populations.Population;
import eva2.server.go.populations.SolutionSet;
/**
* This implements the IPOP (increased population size restart) strategy ES, which increases
* the ES population size (lambda) after phases or stagnation and restarts the optimization.
* Stagnation is for this implementation defined by a FitnessConvergenceTerminator instance
* which terminates if the absolute change in fitness is below a threshold (default 10e-12) for a
* certain number of generations (default: 10+floor(30*n/lambda) for problem dimension n).
*
* If the MutateESRankMuCMA mutation operator is used, additional criteria are used for restarts,
* such as numeric conditions of the covariance matrix.
* Lambda is increased multiplicatively for every restart, and typical initial values are
* mu=5, lambda=10, incFact=2.
* The IPOP-CMA-ES won the CEC 2005 benchmark challenge.
* Refer to Auger&Hansen 05 for more details.
*
* A.Auger & N.Hansen. A Restart CMA Evolution Strategy With Increasing Population Size. CEC 2005.
*
* @author mkron
*
*/
public class EvolutionStrategyIPOP extends EvolutionStrategies implements InterfacePopulationChangedEventListener {
private static final long serialVersionUID = 4102736881931867818L;
int dim = -1;
int initialLambda = 10;
private double stagThreshold = 10e-12;
private int stagTime = -1;
double incPopSizeFact = 2.;
FitnessConvergenceTerminator fitConvTerm = null;
LinkedList<AbstractEAIndividual> bestList = null;
AbstractEAIndividual best = null;
public EvolutionStrategyIPOP() {
super();
setMu(5);
setLambda(10);
}
public EvolutionStrategyIPOP(EvolutionStrategyIPOP other) {
dim = other.dim;
initialLambda = other.initialLambda;
incPopSizeFact = other.incPopSizeFact;
stagThreshold = other.stagThreshold;
stagTime = other.stagTime;
if (other.fitConvTerm != null) fitConvTerm = new FitnessConvergenceTerminator(other.fitConvTerm);
}
public Object clone() {
return new EvolutionStrategyIPOP(this);
}
/** The optimize method will compute a 'improved' and evaluated population
*/
public void optimize() {
// Population nextGeneration, parents;
//
// // first perform the environment selection to select myu parents
// parents = selectParents();
//
// // m_Population / parents are of sizes lambda / mu
// if (parents.getEAIndividual(0).getMutationOperator() instanceof InterfaceMutationGenerational) {
// ((InterfaceMutationGenerational)parents.getEAIndividual(0).getMutationOperator()).adaptAfterSelection(getPopulation(), parents);
// }
//
// // now generate the lambda offsprings
// nextGeneration = this.generateEvalChildren(parents); // create lambda new ones from mu parents
//
// if (this.isPlusStrategy()) nextGeneration.addPopulation(parents);
//
// setPop(getReplacePop(nextGeneration));
//
// this.firePropertyChangedEvent("NextGenerationPerformed");
//////////////////////////
super.optimize();
// remember the best indy
if ((best == null) || !best.isDominating(getPopulation().getBestEAIndividual())) {
best = getPopulation().getBestEAIndividual();
}
if (testIPOPStopCrit(getPopulation())) {
// reinitialize population with increased mu,lambda
boostPopSize();
}
}
public void hideHideable() {
GenericObjectEditor.setHideProperty(this.getClass(), "population", true);
}
/**
* Reinitialize population with increased mu,lambda
**/
private void boostPopSize() {
// increase by at least one
int newLambda = Math.max((int)(getLambda()*incPopSizeFact), getLambda() + 1);
super.setLambda(newLambda);
bestList.add(best);
best = null;
Population newPop = getPopulation().cloneWithoutInds();
getProblem().initPopulation(newPop);
double[] badFit = getPopulation().getBestFitness().clone();
Arrays.fill(badFit, Double.MAX_VALUE);
newPop.setAllFitnessValues(badFit);
getPopulation().clear();
getPopulation().addAll(newPop);
getProblem().evaluate(getPopulation());
}
protected void firePropertyChangedEvent(String name) {
if (name.equals(Population.funCallIntervalReached)) {
super.firePropertyChangedEvent("NextGenerationPerformed");
}
else {} // nothing, evt is produced in #registerPopulationStateChanged, dont forward original due to changing pop size
}
public void init() {
// setMu(initialMu);
super.setLambda(initialLambda);
getPopulation().setNotifyEvalInterval(initialLambda);
super.init();
bestList = new LinkedList<AbstractEAIndividual>();
best = getPopulation().getBestEAIndividual();
dim = AbstractEAIndividual.getDoublePosition(getPopulation().getEAIndividual(0)).length;
stagTime = (int)(10+Math.floor(30*dim/getPopulation().size()));
fitConvTerm = new FitnessConvergenceTerminator(stagThreshold, stagTime, false, true); // gen. based, absolute
getPopulation().addPopulationChangedEventListener(this);
getPopulation().setNotifyEvalInterval(initialLambda);
}
/**
* Test for the IPOP stopping criteria.
* @param population
* @return
*/
private boolean testIPOPStopCrit(Population pop) {
int curGen = pop.getGeneration();
MutateESRankMuCMA rcmaMute = null;
if (pop.getEAIndividual(0).getMutationOperator() instanceof MutateESRankMuCMA) {
rcmaMute = (MutateESRankMuCMA)pop.getEAIndividual(0).getMutationOperator();
}
// stop if the range of the best fitness of the last 10 + flor(30 n /lambda) generations is zero
// or if the range of these values and all fit values of the recent generation is below Tolfun = 10^-12
//// interpret it a bit differently using FitnessConvergenceTerminator
if (fitConvTerm.isTerminated(new SolutionSet(pop))) {
return true;
}
if (rcmaMute != null) {
// stop if the std dev of the normal distribution is smaller than TolX in all coords
// and sigma p_c is smaller than TolX in all components; TolX = 10^-12 sigma_0
if (rcmaMute.testAllDistBelow(10e-12*rcmaMute.getFirstSigma())) return true;
// stop if adding a 0.1 std dev vector in a principal axis dir. of C does not change <x>_w^g
if (rcmaMute.testNoChangeAddingDevAxis(0.1, curGen)) return true;
// stop if adding a 0.2 std dev in each coordinate does (not???) change <x>_w^g
if (rcmaMute.testNoEffectCoord(0.2)) return true;
// stop if the condition number of C exceeds 10^14
if (rcmaMute.testCCondition(10e14)) return true;
}
return false;
}
/**
* Returns the current population and a set of best individuals found (best current
* and best single ones before
* reinitializing the population after boosting the population size).
*
* @return A solution set of the current population and possibly earlier solutions
*/
public SolutionSet getAllSolutions() {
Population sols = getPopulation().cloneWithoutInds();
if (bestList != null) sols.addAll(bestList);
if (best != null) sols.add(best);
else sols.add(getPopulation().getBestEAIndividual());
SolutionSet solSet = new SolutionSet(getPopulation(), sols);
return solSet;
}
public void registerPopulationStateChanged(Object source, String name) {
if (name.equals(Population.funCallIntervalReached)) {
getPopulation().SetFunctionCalls(((Population)source).getFunctionCalls()); // TODO this is ugly
super.firePropertyChangedEvent(name);
} else {
// System.err.println("Not forwarding event " + name);
}
}
public String getName() {
return "ES-IPOP";
}
public String globalInfo() {
return "An ES with increasing population size.";
}
/** Set an initial population size (if smaller lambda this is ignored).
* @param l The inital population size.
*/
public void setInitialLambda(int l) {
initialLambda = l;
if (initialLambda < getMu()) setMu((initialLambda/2)+1);
}
public int getInitialLambda() {
return initialLambda;
}
public String initialLambdaTipText() {
return "Set the initial population size (lambda); mu should be about lambda/2";
}
/**
* @return the incPopSizeFact
*/
public double getIncPopSizeFact() {
return incPopSizeFact;
}
/**
* @param incPopSizeFact the incPopSizeFact to set
*/
public void setIncPopSizeFact(double incPopSizeFact) {
this.incPopSizeFact = incPopSizeFact;
}
public String incPopSizeFactTipText() {
return "Factor by which to increase lambda for each restart event, default is 2.";
}
}

View File

@ -58,9 +58,11 @@ public class EvolutionaryProgramming implements InterfaceOptimizer, java.io.Seri
*/
public void initByPopulation(Population pop, boolean reset) {
this.m_Population = (Population)pop.clone();
if (reset) this.m_Population.init();
this.evaluatePopulation(this.m_Population);
this.firePropertyChangedEvent("NextGenerationPerformed");
if (reset) {
this.m_Population.init();
this.evaluatePopulation(this.m_Population);
this.firePropertyChangedEvent("NextGenerationPerformed");
}
}
/** This method will evaluate the current population using the

View File

@ -67,10 +67,12 @@ public class FloodAlgorithm implements InterfaceOptimizer, java.io.Serializable
*/
public void initByPopulation(Population pop, boolean reset) {
this.m_Population = (Population)pop.clone();
if (reset) this.m_Population.init();
this.m_Problem.evaluate(this.m_Population);
if (reset) {
this.m_Population.init();
this.m_Problem.evaluate(this.m_Population);
this.firePropertyChangedEvent("NextGenerationPerformed");
}
this.m_CurrentFloodPeak = this.m_InitialFloodPeak;
this.firePropertyChangedEvent("NextGenerationPerformed");
}
/** This method will optimize

View File

@ -3,6 +3,7 @@ package eva2.server.go.strategies;
import eva2.server.go.InterfacePopulationChangedEventListener;
import eva2.server.go.individuals.AbstractEAIndividual;
import eva2.server.go.individuals.GAIndividualBinaryData;
import eva2.server.go.operators.mutation.InterfaceMutationGenerational;
import eva2.server.go.operators.selection.InterfaceSelection;
import eva2.server.go.operators.selection.SelectTournament;
import eva2.server.go.populations.InterfaceSolutionSet;
@ -66,9 +67,11 @@ public class GeneticAlgorithm implements InterfaceOptimizer, java.io.Serializabl
*/
public void initByPopulation(Population pop, boolean reset) {
this.m_Population = (Population)pop.clone();
if (reset) this.m_Population.init();
this.evaluatePopulation(this.m_Population);
this.firePropertyChangedEvent("NextGenerationPerformed");
if (reset) {
this.m_Population.init();
this.evaluatePopulation(this.m_Population);
this.firePropertyChangedEvent("NextGenerationPerformed");
}
}
/** This method will evaluate the current population using the
@ -110,6 +113,10 @@ public class GeneticAlgorithm implements InterfaceOptimizer, java.io.Serializabl
parents = this.m_ParentSelection.selectFrom(this.m_Population, this.m_Population.getPopulationSize());
//System.out.println("Parents:"+parents.getSolutionRepresentationFor());
if (parents.getEAIndividual(0).getMutationOperator() instanceof InterfaceMutationGenerational) {
((InterfaceMutationGenerational)parents.getEAIndividual(0).getMutationOperator()).adaptAfterSelection(m_Population, parents);
}
for (int i = 0; i < parents.size(); i++) {
tmpIndy = ((AbstractEAIndividual)parents.get(i));
if (tmpIndy == null) System.out.println("Individual null " + i + " Population size: "+ parents.size());
@ -121,13 +128,18 @@ public class GeneticAlgorithm implements InterfaceOptimizer, java.io.Serializabl
}
result.add(i, offSprings[0]);
}
this.evaluatePopulation(result);
if (parents.getEAIndividual(0).getMutationOperator() instanceof InterfaceMutationGenerational) {
((InterfaceMutationGenerational)parents.getEAIndividual(0).getMutationOperator()).adaptGenerational(m_Population, parents, result, true);
}
return result;
}
public void optimize() {
Population nextGeneration;
nextGeneration = this.generateChildren();
this.evaluatePopulation(nextGeneration);
if (this.m_UseElitism) {
AbstractEAIndividual elite = this.m_Population.getBestEAIndividual();
if (elite != null) {

View File

@ -53,9 +53,11 @@ public class GradientDescentAlgorithm implements InterfaceOptimizer, java.io.Ser
public void initByPopulation(Population pop, boolean reset) {
this.setPopulation((Population) pop.clone());
if (reset) this.getPopulation().init();
this.m_Problem.evaluate(this.getPopulation());
this.firePropertyChangedEvent("NextGenerationPerformed");
if (reset) {
this.getPopulation().init();
this.m_Problem.evaluate(this.getPopulation());
this.firePropertyChangedEvent("NextGenerationPerformed");
}
//System.out.println("initByPopulation() called");
indyhash = new Hashtable();
}

View File

@ -58,15 +58,13 @@ public class HillClimbing implements InterfaceOptimizer, java.io.Serializable {
this.firePropertyChangedEvent("NextGenerationPerformed");
}
/** This method will init the optimizer with a given population
* @param pop The initial population
* @param reset If true the population is reset.
*/
public void initByPopulation(Population pop, boolean reset) {
this.m_Population = (Population)pop.clone();
if (reset) this.m_Population.init();
this.m_Problem.evaluate(this.m_Population);
this.firePropertyChangedEvent("NextGenerationPerformed");
if (reset) {
this.m_Population.init();
this.m_Problem.evaluate(this.m_Population);
this.firePropertyChangedEvent("NextGenerationPerformed");
}
}
/** This method will optimize

View File

@ -38,9 +38,11 @@ public interface InterfaceOptimizer {
*/
public void init();
/** This method will init the optimizer with a given population
/**
* This method will init the optimizer with a given population.
*
* @param pop The initial population
* @param reset If true the population is reset.
* @param reset If true the population is reinitialized and reevaluated.
*/
public void initByPopulation(Population pop, boolean reset);
@ -66,7 +68,7 @@ public interface InterfaceOptimizer {
* May return the the same set as getPopulation if the optimizer makes no distinction, i.e. does
* not collect solutions outside the current population.
*
* @return A population of found solutions.
* @return A solution set of the current population and possibly earlier solutions.
*/
public InterfaceSolutionSet getAllSolutions();

View File

@ -142,6 +142,7 @@ public class IslandModelEA implements InterfacePopulationChangedEventListener, I
* @param reset If true the population is reset.
*/
public void initByPopulation(Population tpop, boolean reset) {
// TODO this is again evil copy&paste style
if (this.m_Show) {
if (this.m_Plot == null) {
double[] tmpD = new double[2];
@ -152,8 +153,10 @@ public class IslandModelEA implements InterfacePopulationChangedEventListener, I
}
this.m_Population = (Population)tpop.clone();
if (reset) this.m_Population.init();
this.m_Population.incrGeneration();
if (reset) {
this.m_Population.init();
this.m_Population.incrGeneration();
}
this.m_Optimizer.init();
this.m_Optimizer.SetProblem(this.m_Problem);
InterfacePopulationChangedEventListener myLocal = null;

View File

@ -89,9 +89,11 @@ public class MemeticAlgorithm implements InterfaceOptimizer,
public void initByPopulation(Population pop, boolean reset) {
this.setPopulation((Population) pop.clone());
if (reset) this.getPopulation().init();
this.m_Problem.evaluate(this.getPopulation());
this.firePropertyChangedEvent("NextGenerationPerformed");
if (reset) {
this.getPopulation().init();
this.m_Problem.evaluate(this.getPopulation());
this.firePropertyChangedEvent("NextGenerationPerformed");
}
}
public void init() {

View File

@ -64,9 +64,11 @@ public class MonteCarloSearch implements InterfaceOptimizer, java.io.Serializabl
*/
public void initByPopulation(Population pop, boolean reset) {
this.m_Population = (Population)pop.clone();
if (reset) this.m_Population.init();
this.m_Problem.evaluate(this.m_Population);
this.firePropertyChangedEvent("NextGenerationPerformed");
if (reset) {
this.m_Population.init();
this.m_Problem.evaluate(this.m_Population);
this.firePropertyChangedEvent("NextGenerationPerformed");
}
}
/** This method will optimize

View File

@ -85,9 +85,11 @@ public class ParticleFilterOptimization implements InterfaceOptimizer, java.io.S
*/
public void initByPopulation(Population pop, boolean reset) {
this.m_Population = (Population)pop.clone();
if (reset) this.m_Population.init();
this.evaluatePopulation(this.m_Population);
this.firePropertyChangedEvent("NextGenerationPerformed");
if (reset) {
this.m_Population.init();
this.evaluatePopulation(this.m_Population);
this.firePropertyChangedEvent("NextGenerationPerformed");
}
}
/** This method will evaluate the current population using the

View File

@ -372,7 +372,7 @@ public class ParticleSwarmOptimization implements InterfaceOptimizer, java.io.Se
indy.SetData(indexKey, i);
indy.setIndividualIndex(i);
}
this.evaluatePopulation(this.m_Population);
if (reset) this.evaluatePopulation(this.m_Population);
for (int i = 0; i < this.m_Population.size(); i++) {
indy = (AbstractEAIndividual) this.m_Population.get(i);
@ -382,7 +382,7 @@ public class ParticleSwarmOptimization implements InterfaceOptimizer, java.io.Se
}
this.m_BestIndividual = (AbstractEAIndividual)this.m_Population.getBestEAIndividual().clone();
this.firePropertyChangedEvent("NextGenerationPerformed");
if (reset) this.firePropertyChangedEvent("NextGenerationPerformed");
treeLevels = 0;
// the HPSO tree will contain layers 0...HPSOLevels, the last one is "incomplete" with only HPSOOrphans number of nodes

View File

@ -72,10 +72,12 @@ public class PopulationBasedIncrementalLearning implements InterfaceOptimizer, j
System.err.println("Error: PBIL only works with GAIndividuals!");
}
this.m_Population = new PBILPopulation();
if (reset) this.m_Population.init();
this.m_Population.addPopulation((Population)pop.clone());
if (reset) {
this.m_Population.init();
this.evaluatePopulation(this.m_Population);
}
((PBILPopulation)this.m_Population).buildProbabilityVector();
this.evaluatePopulation(this.m_Population);
this.firePropertyChangedEvent("NextGenerationPerformed");
}

View File

@ -67,10 +67,12 @@ public class SimulatedAnnealing implements InterfaceOptimizer, java.io.Serializa
*/
public void initByPopulation(Population pop, boolean reset) {
this.m_Population = (Population)pop.clone();
if (reset) this.m_Population.init();
this.m_Problem.evaluate(this.m_Population);
this.m_CurrentTemperature = this.m_InitialTemperature;
this.firePropertyChangedEvent("NextGenerationPerformed");
if (reset) {
this.m_Population.init();
this.m_Problem.evaluate(this.m_Population);
this.firePropertyChangedEvent("NextGenerationPerformed");
}
}
/** This method will optimize

View File

@ -62,9 +62,11 @@ public class SteadyStateGA implements InterfaceOptimizer, java.io.Serializable {
*/
public void initByPopulation(Population pop, boolean reset) {
this.m_Population = (Population)pop.clone();
if (reset) this.m_Population.init();
this.evaluatePopulation(this.m_Population);
this.firePropertyChangedEvent("NextGenerationPerformed");
if (reset) {
this.m_Population.init();
this.evaluatePopulation(this.m_Population);
this.firePropertyChangedEvent("NextGenerationPerformed");
}
}
/** This method will evaluate the current population using the

View File

@ -65,10 +65,12 @@ public class ThresholdAlgorithm implements InterfaceOptimizer, java.io.Serializa
*/
public void initByPopulation(Population pop, boolean reset) {
this.m_Population = (Population)pop.clone();
if (reset) this.m_Population.init();
this.m_Problem.evaluate(this.m_Population);
this.m_CurrentT = this.m_InitialT;
this.firePropertyChangedEvent("NextGenerationPerformed");
if (reset) {
this.m_Population.init();
this.m_Problem.evaluate(this.m_Population);
this.firePropertyChangedEvent("NextGenerationPerformed");
}
}
/** This method will optimize

View File

@ -240,6 +240,11 @@ public class Tribes implements InterfaceOptimizer, java.io.Serializable {
}
/**
* As TRIBES manages an own structured set of particles (the list of Tribes containing explorers
* and memories), the setPopulation method is only telling Tribes the range
* of the indiviuals in the beginning of the run, the individuals will be discarded.
*/
public void initByPopulation(Population pop, boolean reset) {
setPopulation(pop);
}

View File

@ -675,4 +675,16 @@ public class Mathematics {
}
return A;
}
public static double max(double[] vals) {
double maxVal = vals[0];
for (int i=1; i<vals.length; i++) maxVal = Math.max(maxVal, vals[i]);
return maxVal;
}
public static double min(double[] vals) {
double minVal = vals[0];
for (int i=1; i<vals.length; i++) minVal = Math.min(minVal, vals[i]);
return minVal;
}
}

View File

@ -9,9 +9,9 @@ import java.text.DecimalFormatSymbols;
import java.text.NumberFormat;
import java.util.Locale;
import eva2.gui.BeanInspector;
import wsi.ra.math.Jama.util.Maths;
import eva2.gui.BeanInspector;
import eva2.tools.Pair;
/**
@ -260,6 +260,17 @@ public class Matrix implements Cloneable, java.io.Serializable {
return vals;
}
/** Copy a column from the matrix.
@return Matrix elements packed in a one-dimensional array by columns.
*/
public double[] getColumn(int k) {
double[] vals = new double[m];
for (int i = 0; i < m; i++) {
vals[i] = A[i][k];
}
return vals;
}
/** Make a one-dimensional row packed copy of the internal array.
@return Matrix elements packed in a one-dimensional array by rows.
*/
@ -764,6 +775,34 @@ public class Matrix implements Cloneable, java.io.Serializable {
return X;
}
/** Multiply a matrix by a vector, returning A*v.
*
@param v vector
@return result vector
*/
public double[] times (double[] v) {
// m: no rows
double[] result = new double[m];
times(v, result);
return result;
}
/** Multiply a matrix by a vector in place, result=A*v.
*
@param v vector
@param result
@return result vector
*/
public void times (double[] v, double[] result) {
// m: no rows
for (int i = 0; i < m; i++) {
result[i] = 0;
for (int j = 0; j < n; j++) {
result[i] += get(i,j)*v[j];
}
}
}
public String toString() {
StringBuffer sb = new StringBuffer();
for (int i=0; i<m; i++) {
@ -976,6 +1015,25 @@ public class Matrix implements Cloneable, java.io.Serializable {
return A;
}
/**
* Return the minimum and maximum value on the diagonal
* as a pair.
*
* @return
*/
public Pair<Double,Double> getMinMaxDiag() {
if (m<1 || n<1) return null;
double v = get(0,0);
Pair<Double,Double> ret = new Pair<Double,Double>(v,v);
for (int i=1; i<Math.min(m,n); i++) {
v = get(i,i);
ret.head = Math.min(ret.head, v);
ret.tail = Math.max(ret.tail, v);
}
return ret;
}
/** Print the matrix to stdout. Line the elements up in columns
* with a Fortran-like 'Fw.d' style format.