Tuning of the new terminators.

This commit is contained in:
Marcel Kronfeld 2010-08-16 08:22:11 +00:00
parent 453520096f
commit 1220e81039
8 changed files with 77 additions and 116 deletions

View File

@ -13,8 +13,8 @@ import eva2.tools.SelectedTag;
/**
* The diversity terminator uses the distance of individuals
* in the population as termination criterion. If the average distance
* sinks below the given limit, the optimization stops.
* in the population as termination criterion. If the average (min./max.) distance
* stagnates, the optimization stops.
* May be computationally expensive.
*
* @see Population.getPopulationMeasures()
@ -22,88 +22,26 @@ import eva2.tools.SelectedTag;
* @author mkron
*
*/
public class DiversityTerminator implements InterfaceTerminator, Serializable {
private double distanceLimit = 0.001;
public class DiversityTerminator extends PopulationMeasureTerminator implements InterfaceTerminator, Serializable {
public enum DiversityCriterion {averageDistance, minimumDistance, maximumDistance};
// private double distanceLimit = 0.001;
private InterfaceDistanceMetric metric = new PhenotypeMetric();
private String msg = "";
// leave the string order for this SelectedTag! (analogy to Population.getPopulationMeasures)
private SelectedTag criterion = new SelectedTag("Average distance", "Minimum distance", "Maximum distance");
private DiversityCriterion criterion = DiversityCriterion.averageDistance;
public DiversityTerminator() {}
/**
* The default uses Phenotype metric and average distance as criterion.
*
* @param limit
*/
public DiversityTerminator(double limit) {
distanceLimit = limit;
metric = new PhenotypeMetric();
criterion.setSelectedTag(0);
public DiversityTerminator() {
super();
}
/**
* Create a special DiversityTerminator defining distance limit, metric and distance
* criterion to use (average, minimum or maximum distance).
*
* @param limit the distance limit of individuals below which termination is triggered
* @param metric the metric to be used to calculate individual distances
* @param criterionID 0 for average distance, 1 for minimum distance and 2 for maximum distance
*/
public DiversityTerminator(double limit, InterfaceDistanceMetric metric, int criterionID) {
distanceLimit = limit;
public DiversityTerminator(DiversityCriterion divCrit, InterfaceDistanceMetric metric, double convergenceThreshold, int stagnationTime, StagnationTypeEnum stagType, ChangeTypeEnum changeType, DirectionTypeEnum dirType) {
super(convergenceThreshold, stagnationTime, stagType, changeType, dirType);
this.metric = metric;
criterion.setSelectedTag(criterionID);
this.criterion = divCrit;
}
public void init(InterfaceOptimizationProblem prob) {
msg = "Not terminated.";
}
public static String globalInfo() {
return "The diversity terminator uses the distance of individuals in the population as a termination criterion.";
}
/**
* Returns true if the average phenotypic distance within the given
* population is below the limit set in the terminator instance.
*
* @return true if the population is seen as converged due to low average phenotypic distance, else false
*/
public boolean isTerminated(PopulationInterface pop) {
double[] measures = ((Population)pop).getPopulationMeasures(metric);
int measureIndex = criterion.getSelectedTagID();
if (measures[measureIndex] < distanceLimit) {
msg = "Average individual distance below " + distanceLimit;
return true;
} else return false;
}
public boolean isTerminated(InterfaceSolutionSet sols) {
return isTerminated(sols.getCurrentPopulation());
}
public String lastTerminationMessage() {
return msg;
}
/**
* @return the avgDistanceLimit
*/
public double getDistanceLimit() {
return distanceLimit;
}
/**
* @param avgDistanceLimit the avgDistanceLimit to set
*/
public void setDistanceLimit(double avgDistanceLimit) {
this.distanceLimit = avgDistanceLimit;
}
public String distanceLimitTipText() {
return "Set the distance limit of individuals below which termination is triggered.";
}
/**
* @return the metric
@ -111,10 +49,6 @@ public class DiversityTerminator implements InterfaceTerminator, Serializable {
public InterfaceDistanceMetric getMetric() {
return metric;
}
/**
* @param metric the metric to set
*/
public void setMetric(InterfaceDistanceMetric metric) {
this.metric = metric;
}
@ -126,18 +60,30 @@ public class DiversityTerminator implements InterfaceTerminator, Serializable {
/**
* @return the criterion
*/
public SelectedTag getCriterion() {
public DiversityCriterion getCriterion() {
return criterion;
}
/**
* @param criterion the criterion to set
*/
public void setCriterion(SelectedTag criterion) {
public void setCriterion(DiversityCriterion criterion) {
this.criterion = criterion;
}
public String criterionTipText() {
return "Define the distance criterion to check for in a population.";
}
@Override
protected double calcInitialMeasure(PopulationInterface pop) {
return calcPopulationMeasure(pop);
}
@Override
protected double calcPopulationMeasure(PopulationInterface pop) {
double[] measures = ((Population)pop).getPopulationMeasures(metric);
int measureIndex = criterion.ordinal();
return measures[measureIndex];
}
@Override
protected String getMeasureName() {
return "Population diversity ("+criterion+")";
}
}

View File

@ -20,8 +20,8 @@ implements InterfaceTerminator, Serializable {
super();
}
public FitnessConvergenceTerminator(double thresh, int stagnPeriod, boolean bFitCallBased, boolean bAbsolute, boolean bImprovement) {
super(thresh, stagnPeriod, bFitCallBased, ChangeTypeEnum.absoluteChange, bImprovement);
public FitnessConvergenceTerminator(double thresh, int stagnPeriod, StagnationTypeEnum stagType, ChangeTypeEnum changeType, DirectionTypeEnum dirType) {
super(thresh, stagnPeriod, stagType, changeType, dirType);
}
public FitnessConvergenceTerminator(FitnessConvergenceTerminator other) {

View File

@ -32,8 +32,8 @@ public class ParetoMetricTerminator extends PopulationMeasureTerminator implemen
//public PopulationMeasureTerminator(double convergenceThreshold, int stagnationTime, boolean bFitCallBased, ChangeTypeEnum detectChangeType, boolean bImprovement) {
public ParetoMetricTerminator(InterfaceParetoFrontMetric metric, boolean useCurrentPop, double convergenceThreshold, int stagnationTime, boolean bFitCallBased, ChangeTypeEnum detectChangeType, boolean bImprovement) {
super(convergenceThreshold, stagnationTime, bFitCallBased, detectChangeType, bImprovement);
public ParetoMetricTerminator(InterfaceParetoFrontMetric metric, boolean useCurrentPop, double convergenceThreshold, int stagnationTime, StagnationTypeEnum stagType, ChangeTypeEnum changeType, DirectionTypeEnum dirType) {
super(convergenceThreshold, stagnationTime, stagType, changeType, dirType);
this.pMetric = metric;
this.useCurrentPop = useCurrentPop;
}

View File

@ -16,8 +16,8 @@ public class PhenotypeConvergenceTerminator extends PopulationMeasureTerminator
pMetric = new PhenotypeMetric();
}
public PhenotypeConvergenceTerminator(double thresh, int stagnTime, boolean bFitCallBased, ChangeTypeEnum changeType, boolean bImprovement) {
super(thresh, stagnTime, bFitCallBased, changeType, bImprovement);
public PhenotypeConvergenceTerminator(double thresh, int stagnTime, StagnationTypeEnum stagType, ChangeTypeEnum changeType, DirectionTypeEnum dirType) {
super(thresh, stagnTime, stagType, changeType, dirType);
pMetric = new PhenotypeMetric();
}

View File

@ -28,6 +28,8 @@ import eva2.tools.SelectedTag;
public abstract class PopulationMeasureTerminator implements InterfaceTerminator,
Serializable {
public enum ChangeTypeEnum {relativeChange, absoluteChange, absoluteValue};
public enum DirectionTypeEnum {decreaseImprovement, bidirectional};
public enum StagnationTypeEnum {fitnessCallBased, generationBased};
protected static boolean TRACE = false;
private double convThresh = 0.01; //, convThreshLower=0.02;
@ -36,21 +38,23 @@ Serializable {
private int oldPopFitCalls = 1000;
private int oldPopGens = 1000;
private boolean firstTime = true;
private SelectedTag stagnationMeasure = new SelectedTag("Fitness calls", "Generations");
private StagnationTypeEnum stagnationMeasure = StagnationTypeEnum.fitnessCallBased;
// private SelectedTag convCondition = new SelectedTag("Relative change", "Absolute change", "Absolute value");
private ChangeTypeEnum changeType = ChangeTypeEnum.relativeChange;
private SelectedTag condImprovementOrChange = new SelectedTag("Improvement", "Improvement and Deterioration");
private DirectionTypeEnum condDirection = DirectionTypeEnum.decreaseImprovement;
// private SelectedTag condImprovementOrChange = new SelectedTag("Decrease", "Improvement and Deterioration");
protected String msg="Not terminated.";
public PopulationMeasureTerminator() {}
public PopulationMeasureTerminator(double convergenceThreshold, int stagnationTime, boolean bFitCallBased, ChangeTypeEnum detectChangeType, boolean bImprovement) {
convThresh = convergenceThreshold;
stagTime = stagnationTime;
stagnationMeasure.setSelectedTag(bFitCallBased ? 0 : 1);
// convergenceCondition.setSelectedTag(bAbsolute ? 1 : 0);
changeType = detectChangeType;
condImprovementOrChange.setSelectedTag(bImprovement ? 0 : 1);
public PopulationMeasureTerminator(double convergenceThreshold, int stagnationTime, StagnationTypeEnum stagType, ChangeTypeEnum changeType, DirectionTypeEnum dirType) {
this.convThresh = convergenceThreshold;
this.stagTime = stagnationTime;
this.stagnationMeasure = stagType;
// this.convergenceCondition.setSelectedTag(bAbsolute ? 1 : 0);
this.changeType = changeType;
this.condDirection = dirType;
// this.condImprovementOrChange.setSelectedTag(bImprovement ? 0 : 1);
}
public PopulationMeasureTerminator(PopulationMeasureTerminator o) {
@ -62,10 +66,11 @@ Serializable {
// oldFit = o.oldFit.clone();
// oldNorm = o.oldNorm;
msg = o.msg;
this.stagnationMeasure.setSelectedTag(o.stagnationMeasure.getSelectedTagID());
this.stagnationMeasure = o.stagnationMeasure;
// this.convergenceCondition.setSelectedTag(o.convergenceCondition.getSelectedTagID());
this.changeType = o.changeType;
this.condImprovementOrChange.setSelectedTag(o.condImprovementOrChange.getSelectedTagID());
this.condDirection = o.condDirection;
// this.condImprovementOrChange.setSelectedTag(o.condImprovementOrChange.getSelectedTagID());
}
// public void hideHideable() {
@ -163,7 +168,7 @@ Serializable {
}
sb.append(" for ");
sb.append(stagTime);
if (stagnationMeasure.isSelectedString("Generations")) sb.append(" generations.");
if (stagnationMeasure == StagnationTypeEnum.generationBased) sb.append(" generations.");
else sb.append(" function calls.");
return sb.toString();
}
@ -238,7 +243,8 @@ Serializable {
}
public boolean doCheckImprovement() {
return condImprovementOrChange.isSelectedString("Improvement");
return (condDirection==DirectionTypeEnum.decreaseImprovement);
// return condImprovementOrChange.isSelectedString("Improvement");
}
public boolean isRelativeConvergence() {
@ -253,7 +259,7 @@ Serializable {
* @return
*/
private boolean stagnationTimeHasPassed(PopulationInterface pop) {
if (stagnationMeasure.isSelectedString("Fitness calls")) { // by fitness calls
if (stagnationMeasure==StagnationTypeEnum.fitnessCallBased) { // by fitness calls
// System.out.println("stagnationTimeHasPassed returns " + ((pop.getFunctionCalls() - popFitCalls) >= m_stagTime) + " after " + (pop.getFunctionCalls() - popFitCalls));
return (pop.getFunctionCalls() - oldPopFitCalls) >= stagTime;
} else {// by generation
@ -269,7 +275,7 @@ Serializable {
return convThresh;
}
public String convergenceThresholdTipText() {
return "Ratio of improvement or absolute value of improvement or change to determine convergence.";
return "Ratio of improvement/change or absolute value of improvement/change to determine convergence.";
}
// public void setConvergenceThresholdLower(double x) {
@ -292,14 +298,14 @@ Serializable {
return "Terminate if the population has not improved for this time";
}
public SelectedTag getStagnationMeasure() {
public StagnationTypeEnum getStagnationMeasure() {
return stagnationMeasure;
}
public void setStagnationMeasure(SelectedTag stagnationTimeIn) {
public void setStagnationMeasure(StagnationTypeEnum stagnationTimeIn) {
this.stagnationMeasure = stagnationTimeIn;
}
public String stagnationMeasureTipText() {
return "Stagnation time is measured in fitness calls or generations, to be selected here.";
return "Stagnation time is measured in fitness calls or generations.";
}
public ChangeTypeEnum getConvergenceCondition() {
@ -313,14 +319,15 @@ Serializable {
return "Select between absolute and relative convergence condition";
}
public SelectedTag getCheckType() {
return condImprovementOrChange;
public DirectionTypeEnum getCheckType() {
return condDirection;
// return condImprovementOrChange;
}
public void setCheckType(SelectedTag ct) {
this.condImprovementOrChange = ct;
public void setCheckType(DirectionTypeEnum dt) {
this.condDirection = dt;
// GenericObjectEditor.setHideProperty(this.getClass(), "convergenceThresholdUpper", isRelativeConvergence() || doCheckImprovement());
}
public String checkTypeTipText() {
return "Detect improvement only (one-directional change) or improvement and deterioration (two-directional change).";
return "Detect improvement only (decreasing measure) or change in both directions (de- and increase).";
}
}

View File

@ -31,6 +31,8 @@ import eva2.server.go.operators.terminators.CombinedTerminator;
import eva2.server.go.operators.terminators.EvaluationTerminator;
import eva2.server.go.operators.terminators.PhenotypeConvergenceTerminator;
import eva2.server.go.operators.terminators.PopulationMeasureTerminator.ChangeTypeEnum;
import eva2.server.go.operators.terminators.PopulationMeasureTerminator.DirectionTypeEnum;
import eva2.server.go.operators.terminators.PopulationMeasureTerminator.StagnationTypeEnum;
import eva2.server.go.populations.Population;
import eva2.server.go.strategies.InterfaceOptimizer;
@ -484,7 +486,7 @@ implements InterfaceOptimizationProblem /*, InterfaceParamControllable*/, Serial
Population pop = new Population(1);
pop.add(orig);
InterfaceTerminator term = new EvaluationTerminator(maxEvaluations);
if (epsilonFitConv > 0) term = new CombinedTerminator(new PhenotypeConvergenceTerminator(epsilonFitConv, 100*dim, true, ChangeTypeEnum.absoluteChange, true), term, false);
if (epsilonFitConv > 0) term = new CombinedTerminator(new PhenotypeConvergenceTerminator(epsilonFitConv, 100*dim, StagnationTypeEnum.fitnessCallBased, ChangeTypeEnum.absoluteChange, DirectionTypeEnum.decreaseImprovement), term, false);
int evalsPerf = PostProcess.processSingleCandidatesNMCMA(PostProcessMethod.nelderMead, pop, term, initRelPerturb, prob);
overallDist = metric.distance(indy, pop.getBestEAIndividual());
//System.out.println(System.currentTimeMillis() + " in " + evalsPerf + " evals moved by "+ overallDist);

View File

@ -11,6 +11,9 @@ import eva2.server.go.operators.constraint.AbstractConstraint;
import eva2.server.go.operators.constraint.GenericConstraint;
import eva2.server.go.operators.postprocess.PostProcess;
import eva2.server.go.operators.terminators.FitnessConvergenceTerminator;
import eva2.server.go.operators.terminators.PopulationMeasureTerminator.ChangeTypeEnum;
import eva2.server.go.operators.terminators.PopulationMeasureTerminator.DirectionTypeEnum;
import eva2.server.go.operators.terminators.PopulationMeasureTerminator.StagnationTypeEnum;
import eva2.server.go.populations.Population;
import eva2.server.go.strategies.InterfaceOptimizer;
import eva2.tools.Pair;
@ -396,7 +399,7 @@ public abstract class AbstractProblemDouble extends AbstractOptimizationProblem
tmpIndy.SetDoubleGenotype(pos);
((AbstractEAIndividual)tmpIndy).SetFitness(prob.eval(pos));
pop.add(tmpIndy);
FitnessConvergenceTerminator convTerm = new FitnessConvergenceTerminator(1e-25, 10, false, true, true);
FitnessConvergenceTerminator convTerm = new FitnessConvergenceTerminator(1e-25, 10, StagnationTypeEnum.generationBased, ChangeTypeEnum.absoluteChange, DirectionTypeEnum.decreaseImprovement);
int calls = PostProcess.processSingleCandidatesNMCMA(PostProcessMethod.nelderMead, pop, convTerm, 0.001, prob);
return ((InterfaceDataTypeDouble)pop.getBestEAIndividual()).getDoubleData();
}

View File

@ -8,6 +8,9 @@ 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.operators.terminators.PopulationMeasureTerminator.ChangeTypeEnum;
import eva2.server.go.operators.terminators.PopulationMeasureTerminator.DirectionTypeEnum;
import eva2.server.go.operators.terminators.PopulationMeasureTerminator.StagnationTypeEnum;
import eva2.server.go.populations.Population;
import eva2.server.go.populations.SolutionSet;
@ -156,7 +159,7 @@ public class EvolutionStrategyIPOP extends EvolutionStrategies implements Interf
bestList = new LinkedList<AbstractEAIndividual>();
best = getPopulation().getBestEAIndividual();
dim = AbstractEAIndividual.getDoublePositionShallow(getPopulation().getEAIndividual(0)).length;
fitConvTerm = new FitnessConvergenceTerminator(stagThreshold, (isStagnationTimeUserDef()) ? stagTimeArbitrary : calcDefaultStagnationTime(), false, true, true); // gen. based, absolute
fitConvTerm = new FitnessConvergenceTerminator(stagThreshold, (isStagnationTimeUserDef()) ? stagTimeArbitrary : calcDefaultStagnationTime(), StagnationTypeEnum.generationBased, ChangeTypeEnum.absoluteChange, DirectionTypeEnum.decreaseImprovement); // gen. based, absolute
getPopulation().addPopulationChangedEventListener(this);
getPopulation().setNotifyEvalInterval(initialLambda);
}