Restructured Terminators, added ParetoFrontTerminator (may terminate on a pareto metric) and an alternative comparator using weighted recombinations of the individual fitness (and a terminator that employs this).
This commit is contained in:
		@@ -21,7 +21,6 @@ import java.util.Comparator;
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
public class AbstractEAIndividualComparator implements Comparator<Object>, Serializable {
 | 
			
		||||
 | 
			
		||||
	// flag whether a data field should be used.
 | 
			
		||||
	private String indyDataKey = "";
 | 
			
		||||
	private int fitCriterion = -1;
 | 
			
		||||
@@ -51,7 +50,7 @@ public class AbstractEAIndividualComparator implements Comparator<Object>, Seria
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	/**
 | 
			
		||||
	 * Constructor for a specific fitness criterion in the multiobjective case. 
 | 
			
		||||
	 * Constructor for a specific fitness criterion in the multi-objective case. 
 | 
			
		||||
	 * For comparison, only the given fitness criterion is used if it is >= 0.
 | 
			
		||||
	 * 
 | 
			
		||||
	 * @param fitnessCriterion
 | 
			
		||||
@@ -60,10 +59,34 @@ public class AbstractEAIndividualComparator implements Comparator<Object>, Seria
 | 
			
		||||
		this("", fitnessCriterion, true);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	/**
 | 
			
		||||
	 * Constructor for a specific fitness criterion in the multi-objective case. 
 | 
			
		||||
	 * For comparison, only the given fitness criterion is used if it is >= 0.
 | 
			
		||||
	 * If preferFeasible is true, feasible individuals will always be prefered.
 | 
			
		||||
	 * 
 | 
			
		||||
	 * @param fitIndex
 | 
			
		||||
	 * @param preferFeasible
 | 
			
		||||
	 */
 | 
			
		||||
	public AbstractEAIndividualComparator(int fitIndex, boolean preferFeasible) {
 | 
			
		||||
		this("", fitIndex, preferFeasible);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	@Override
 | 
			
		||||
	public boolean equals(Object other) {
 | 
			
		||||
		if (other instanceof AbstractEAIndividualComparator) {
 | 
			
		||||
			AbstractEAIndividualComparator o = (AbstractEAIndividualComparator)other;
 | 
			
		||||
			if ((indyDataKey==o.indyDataKey) || (indyDataKey!=null && (indyDataKey.equals(o.indyDataKey)))) {
 | 
			
		||||
				if ((fitCriterion == o.fitCriterion) && (preferFeasible == o.preferFeasible)) return true;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	@Override
 | 
			
		||||
	public int hashCode() {
 | 
			
		||||
		return indyDataKey.hashCode()+100+fitCriterion+(preferFeasible ? 7 : 13);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	/**
 | 
			
		||||
	 * Generic constructor.
 | 
			
		||||
	 * 
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,110 @@
 | 
			
		||||
package eva2.server.go.individuals;
 | 
			
		||||
 | 
			
		||||
import java.io.Serializable;
 | 
			
		||||
import java.util.Comparator;
 | 
			
		||||
 | 
			
		||||
import eva2.tools.EVAERROR;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Compare two individuals based on a linear combination of the fitness values.
 | 
			
		||||
 * 
 | 
			
		||||
 * @author mkron
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
public class IndividualWeightedFitnessComparator implements Comparator<Object>, Serializable {
 | 
			
		||||
	private double [] fitWeights = null;
 | 
			
		||||
	
 | 
			
		||||
	public IndividualWeightedFitnessComparator(double[] weights) {
 | 
			
		||||
		setFitWeights(weights);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	@Override
 | 
			
		||||
	public boolean equals(Object obj) {
 | 
			
		||||
		if (obj instanceof IndividualWeightedFitnessComparator) {
 | 
			
		||||
			IndividualWeightedFitnessComparator o = (IndividualWeightedFitnessComparator)obj;
 | 
			
		||||
			if (fitWeights==null && (o.fitWeights==null)) return true;
 | 
			
		||||
			if (fitWeights==null || o.fitWeights==null) return false;
 | 
			
		||||
			// now both are non null:
 | 
			
		||||
			if (fitWeights.length==o.fitWeights.length) {
 | 
			
		||||
				for (int i=0; i<fitWeights.length; i++) {
 | 
			
		||||
					if (fitWeights[i]!=o.fitWeights[i]) return false;
 | 
			
		||||
				}
 | 
			
		||||
				return true;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
	public int hashCode() {
 | 
			
		||||
		if (fitWeights==null) return super.hashCode();
 | 
			
		||||
		int code=0;
 | 
			
		||||
		for (int i=0; i<fitWeights.length; i++) {
 | 
			
		||||
			code+=(int)(fitWeights[i]*10000)%(10000*(i+1));
 | 
			
		||||
		}
 | 
			
		||||
		return code;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
	public int compare(Object o1, Object o2) {
 | 
			
		||||
		double[] f1 = ((AbstractEAIndividual) o1).getFitness();
 | 
			
		||||
		double[] f2 = ((AbstractEAIndividual) o2).getFitness();
 | 
			
		||||
		
 | 
			
		||||
		double score1 = calcScore(f1);
 | 
			
		||||
		double score2 = calcScore(f2);
 | 
			
		||||
		
 | 
			
		||||
		if (score1 < score2) return  -1;
 | 
			
		||||
		else if (score1 > score2) return 1;
 | 
			
		||||
		else return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private double calcScore(double[] f) {
 | 
			
		||||
		if (f==null || fitWeights==null) throw new RuntimeException("Error, missing information in " + this.getClass());
 | 
			
		||||
		if (f.length!=fitWeights.length) {
 | 
			
		||||
			if (f.length<fitWeights.length) EVAERROR.errorMsgOnce("Warning, fitness vector has less dimensions than the weights... some weights are ignored, in " + this.getClass());
 | 
			
		||||
			else EVAERROR.errorMsgOnce("Warning, fitness vector has more dimensions than the weights... some fitness values are ignored, in " + this.getClass());
 | 
			
		||||
		}
 | 
			
		||||
		double s = 0;
 | 
			
		||||
		for (int i=0; i<Math.min(f.length, fitWeights.length); i++) {
 | 
			
		||||
			s += f[i]*fitWeights[i];
 | 
			
		||||
		}
 | 
			
		||||
		return s;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	public double calcScore(AbstractEAIndividual indy) {
 | 
			
		||||
		double[] f = indy.getFitness();
 | 
			
		||||
		return calcScore(f);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public void setAllWeights(int dim, double v) {
 | 
			
		||||
		fitWeights = new double[dim];
 | 
			
		||||
		for (int i = 0; i < fitWeights.length; i++) {
 | 
			
		||||
			fitWeights[i]=v;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	public void setFitWeights(double [] fitWeights) {
 | 
			
		||||
		this.fitWeights = fitWeights;
 | 
			
		||||
	}
 | 
			
		||||
	public double [] getFitWeights() {
 | 
			
		||||
		return fitWeights;
 | 
			
		||||
	}
 | 
			
		||||
	public String fitWeightsTipText() {
 | 
			
		||||
		return "Weights of the fitness values in the linear combination";
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
//	public static void main(String[] args) {
 | 
			
		||||
//		TF1Problem prob = new TF1Problem();
 | 
			
		||||
//		Population pop = new Population(10);
 | 
			
		||||
//		prob.initPopulation(pop);
 | 
			
		||||
//		prob.evaluate(pop);
 | 
			
		||||
//		System.out.println(pop.getStringRepresentation());
 | 
			
		||||
//		System.out.println("***");
 | 
			
		||||
//		IndividualWeightedFitnessComparator wfComp = new IndividualWeightedFitnessComparator(new double[]{0.5,0.5});
 | 
			
		||||
//		System.out.println("***"); System.out.println(pop.getSortedPop(wfComp).getStringRepresentation());
 | 
			
		||||
//		wfComp.setFitWeights(new double[] {0.1, 0.9});
 | 
			
		||||
//		System.out.println("***"); System.out.println(pop.getSortedPop(wfComp).getStringRepresentation());
 | 
			
		||||
//		wfComp.setFitWeights(new double[] {0.9, 0.1});
 | 
			
		||||
//		System.out.println("***"); System.out.println(pop.getSortedPop(wfComp).getStringRepresentation());
 | 
			
		||||
//	}
 | 
			
		||||
}
 | 
			
		||||
@@ -2,6 +2,7 @@ package eva2.server.go.operators.cluster;
 | 
			
		||||
 | 
			
		||||
import eva2.gui.BeanInspector;
 | 
			
		||||
import eva2.server.go.individuals.AbstractEAIndividual;
 | 
			
		||||
import eva2.server.go.individuals.AbstractEAIndividualComparator;
 | 
			
		||||
import eva2.server.go.operators.distancemetric.InterfaceDistanceMetric;
 | 
			
		||||
import eva2.server.go.operators.distancemetric.PhenotypeMetric;
 | 
			
		||||
import eva2.server.go.populations.Population;
 | 
			
		||||
@@ -72,7 +73,8 @@ public class ClusteringDynPeakIdent implements InterfaceClustering, java.io.Seri
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public Population[] cluster(Population pop, Population referenceSet) {
 | 
			
		||||
		Population sorted = pop.getSortedBestFirst();
 | 
			
		||||
		AbstractEAIndividualComparator eaComparator = new AbstractEAIndividualComparator(-1);
 | 
			
		||||
		Population sorted = pop.getSortedBestFirst(eaComparator);
 | 
			
		||||
		Population peaks = performDynPeakIdent(metric, sorted, numNiches, nicheRadius);
 | 
			
		||||
		Population[] clusters = new Population[peaks.size()+1];
 | 
			
		||||
		for (int i=0; i<clusters.length; i++) clusters[i]=new Population();
 | 
			
		||||
 
 | 
			
		||||
@@ -191,7 +191,12 @@ public class PhenotypeMetric implements InterfaceDistanceMetric, java.io.Seriali
 | 
			
		||||
        System.err.println("error: unknown individual interface in PhenotypeMetric::norm " + BeanInspector.toString(indy));
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
     
 | 
			
		||||
    
 | 
			
		||||
    /**
 | 
			
		||||
     * Calculates the 2 norm of a given vector.
 | 
			
		||||
     * @param v1
 | 
			
		||||
     * @return
 | 
			
		||||
     */
 | 
			
		||||
    public static double norm(double[] v1) {
 | 
			
		||||
        double      result = 0;
 | 
			
		||||
        for (int i = 0; i < v1.length; i++) {
 | 
			
		||||
 
 | 
			
		||||
@@ -8,6 +8,7 @@ import eva2.gui.GenericObjectEditor;
 | 
			
		||||
import eva2.server.go.InterfacePopulationChangedEventListener;
 | 
			
		||||
import eva2.server.go.enums.ESMutationInitialSigma;
 | 
			
		||||
import eva2.server.go.individuals.AbstractEAIndividual;
 | 
			
		||||
import eva2.server.go.individuals.AbstractEAIndividualComparator;
 | 
			
		||||
import eva2.server.go.individuals.InterfaceDataTypeDouble;
 | 
			
		||||
import eva2.server.go.operators.distancemetric.EuclideanMetric;
 | 
			
		||||
import eva2.server.go.populations.Population;
 | 
			
		||||
@@ -306,7 +307,7 @@ public class MutateESRankMuCMA implements InterfaceMutationGenerational, Seriali
 | 
			
		||||
	 * @param selectedP
 | 
			
		||||
	 */
 | 
			
		||||
	public void adaptAfterSelection(Population oldGen, Population selectedP) {
 | 
			
		||||
		Population selectedSorted = selectedP.getSortedBestFirst();
 | 
			
		||||
		Population selectedSorted = selectedP.getSortedBestFirst(new AbstractEAIndividualComparator(-1));
 | 
			
		||||
		
 | 
			
		||||
		int mu,lambda;
 | 
			
		||||
		mu = selectedP.size();
 | 
			
		||||
 
 | 
			
		||||
@@ -215,6 +215,6 @@ public class MetricS implements InterfaceParetoFrontMetric, java.io.Serializable
 | 
			
		||||
     * @return description
 | 
			
		||||
     */
 | 
			
		||||
    public static String globalInfo() {
 | 
			
		||||
        return "Calculating the hybervolume UNDER the given Pareto-front.";
 | 
			
		||||
        return "Calculating the hypervolume UNDER the given Pareto-front.";
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -203,7 +203,7 @@ public class PostProcess {
 | 
			
		||||
        		int n = Math.max(1, (int)(returnQuota*clusters[j].size())); // return at least one per cluster!
 | 
			
		||||
        		switch (takeOverMode) {
 | 
			
		||||
        		case BEST_ONLY: // another easy case
 | 
			
		||||
        			result.addAll((Collection<AbstractEAIndividual>)(clusters[j].getBestNIndividuals(n)));
 | 
			
		||||
        			result.addAll((Collection<AbstractEAIndividual>)(clusters[j].getBestNIndividuals(n, -1)));
 | 
			
		||||
        			break;
 | 
			
		||||
        		case BEST_RAND:
 | 
			
		||||
        			Population exclude = new Population();
 | 
			
		||||
@@ -1075,7 +1075,7 @@ public class PostProcess {
 | 
			
		||||
			//////////// multimodal data output
 | 
			
		||||
			evaluateMultiModal(outputPop, problem, listener);
 | 
			
		||||
 | 
			
		||||
			Population nBestPop = outputPop.getBestNIndividuals(params.getPrintNBest()); // n individuals are returned and sorted, all of them if n<=0
 | 
			
		||||
			Population nBestPop = outputPop.getBestNIndividuals(params.getPrintNBest(), -1); // n individuals are returned and sorted, all of them if n<=0
 | 
			
		||||
			if (listener != null) listener.println("Best after post process:" + ((outputPop.size()>nBestPop.size()) ? ( " (first " + nBestPop.size() + " of " + outputPop.size() + ")") : (" (" + nBestPop.size() + ")") ));
 | 
			
		||||
			//////////// output some individual data
 | 
			
		||||
			if (listener != null) for (int i=0; i<nBestPop.size(); i++) {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,235 +1,51 @@
 | 
			
		||||
package eva2.server.go.operators.terminators;
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Title:        EvA2
 | 
			
		||||
 * Description:
 | 
			
		||||
 * Copyright:    Copyright (c) 2003
 | 
			
		||||
 * Company:      University of Tuebingen, Computer Architecture
 | 
			
		||||
 * @author Holger Ulmer, Felix Streichert, Hannes Planatscher
 | 
			
		||||
 * @version:  $Revision: 319 $
 | 
			
		||||
 *            $Date: 2007-12-05 11:29:32 +0100 (Wed, 05 Dec 2007) $
 | 
			
		||||
 *            $Author: mkron $
 | 
			
		||||
 */
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * IMPORTS
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
import java.io.Serializable;
 | 
			
		||||
 | 
			
		||||
import eva2.gui.BeanInspector;
 | 
			
		||||
import eva2.server.go.InterfaceTerminator;
 | 
			
		||||
import eva2.server.go.PopulationInterface;
 | 
			
		||||
import eva2.server.go.operators.distancemetric.EuclideanMetric;
 | 
			
		||||
import eva2.server.go.operators.distancemetric.PhenotypeMetric;
 | 
			
		||||
import eva2.server.go.populations.InterfaceSolutionSet;
 | 
			
		||||
import eva2.server.go.problems.InterfaceOptimizationProblem;
 | 
			
		||||
import eva2.tools.SelectedTag;
 | 
			
		||||
import eva2.tools.math.Mathematics;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * CLASS DECLARATION
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
/**
 | 
			
		||||
 *
 | 
			
		||||
 * Fitness convergence is measured as the norm of the best fitness of the population.
 | 
			
		||||
 * The PopulationMeasureTerminator is then used with this measure.
 | 
			
		||||
 * 
 | 
			
		||||
 * @see PopulationMeasureTerminator
 | 
			
		||||
 */
 | 
			
		||||
public class FitnessConvergenceTerminator implements InterfaceTerminator,
 | 
			
		||||
Serializable {
 | 
			
		||||
	private static final long serialVersionUID = 5749620193474954959L;
 | 
			
		||||
	protected static boolean TRACE = false;
 | 
			
		||||
	protected double convThresh = 0.01;
 | 
			
		||||
	protected int m_stagTime = 100;
 | 
			
		||||
	protected int popFitCalls = 1000;
 | 
			
		||||
	protected int popGens = 1000;
 | 
			
		||||
	protected boolean firstTime = true;
 | 
			
		||||
	protected double[] oldFit;
 | 
			
		||||
	protected double oldNorm;
 | 
			
		||||
	private SelectedTag stagnationMeasure = new SelectedTag("Fitness calls", "Generations");
 | 
			
		||||
	private SelectedTag convergenceCondition = new SelectedTag("Relative", "Absolute");
 | 
			
		||||
	private String msg="";
 | 
			
		||||
	protected String tagString = "Fitness converged";
 | 
			
		||||
	PhenotypeMetric pMetric = null;
 | 
			
		||||
 | 
			
		||||
public class FitnessConvergenceTerminator extends PopulationMeasureTerminator 
 | 
			
		||||
implements InterfaceTerminator, Serializable {
 | 
			
		||||
	
 | 
			
		||||
	public FitnessConvergenceTerminator() {
 | 
			
		||||
		pMetric = new PhenotypeMetric();
 | 
			
		||||
		super();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public FitnessConvergenceTerminator(double thresh, int stagnPeriod, boolean bFitCallBased, boolean bAbsolute) {
 | 
			
		||||
		pMetric = new PhenotypeMetric();
 | 
			
		||||
		convThresh = thresh;
 | 
			
		||||
		this.m_stagTime = stagnPeriod;
 | 
			
		||||
		if (bFitCallBased) stagnationMeasure.setSelectedTag("Fitness calls");
 | 
			
		||||
		else stagnationMeasure.setSelectedTag("Generations");
 | 
			
		||||
		if (bAbsolute) convergenceCondition.setSelectedTag("Absolute");
 | 
			
		||||
		else convergenceCondition.setSelectedTag("Relative");
 | 
			
		||||
	public FitnessConvergenceTerminator(double thresh, int stagnPeriod, boolean bFitCallBased, boolean bAbsolute, boolean bImprovement) {
 | 
			
		||||
		super(thresh, stagnPeriod, bFitCallBased, ChangeTypeEnum.absoluteChange, bImprovement);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	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());
 | 
			
		||||
		super(other);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	/**
 | 
			
		||||
	 *
 | 
			
		||||
	 */
 | 
			
		||||
	public static String globalInfo() {
 | 
			
		||||
		return "Stop if a fitness convergence criterion has been met.";
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public void init(InterfaceOptimizationProblem prob) {
 | 
			
		||||
		if (pMetric == null) pMetric = new PhenotypeMetric();
 | 
			
		||||
		firstTime = true;
 | 
			
		||||
		msg = "Not terminated.";
 | 
			
		||||
		tagString = "Fitness converged";
 | 
			
		||||
	@Override
 | 
			
		||||
	protected double calcInitialMeasure(PopulationInterface pop) {
 | 
			
		||||
		return Mathematics.norm(pop.getBestFitness());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public boolean isTerminated(InterfaceSolutionSet solSet) {
 | 
			
		||||
		return isTerminated(solSet.getCurrentPopulation());
 | 
			
		||||
	@Override
 | 
			
		||||
	protected double calcPopulationMeasure(PopulationInterface pop) {
 | 
			
		||||
//		if (oldFit==null) return Double.MAX_VALUE;
 | 
			
		||||
//		return EuclideanMetric.euclideanDistance(oldFit, pop.getBestFitness());
 | 
			
		||||
		return Mathematics.norm(pop.getBestFitness());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public boolean isTerminated(PopulationInterface Pop) {
 | 
			
		||||
		if (!firstTime && isStillConverged(Pop)) {
 | 
			
		||||
			if (stagnationTimeHasPassed(Pop)) {
 | 
			
		||||
				// population hasnt changed much for max time, criterion is met
 | 
			
		||||
				msg = getTerminationMessage(tagString);
 | 
			
		||||
				return true;
 | 
			
		||||
			} else {
 | 
			
		||||
				// population hasnt changed much for i<max time, keep running
 | 
			
		||||
				return false;
 | 
			
		||||
			}
 | 
			
		||||
		} else {
 | 
			
		||||
			// first call at all - or population improved more than "allowed" to terminate
 | 
			
		||||
			saveState(Pop);
 | 
			
		||||
 | 
			
		||||
			return false;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public String lastTerminationMessage() {
 | 
			
		||||
		return msg;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	protected String getTerminationMessage(String prefix) {
 | 
			
		||||
		StringBuffer sb = new StringBuffer(prefix);
 | 
			
		||||
		if (convergenceCondition.isSelectedString("Relative")) sb.append(" relatively below ");
 | 
			
		||||
		else sb.append(" absolutely below ");
 | 
			
		||||
		sb.append(convThresh);
 | 
			
		||||
		sb.append(" for ");
 | 
			
		||||
		sb.append(m_stagTime);
 | 
			
		||||
		if (stagnationMeasure.isSelectedString("Generations")) sb.append(" generations.");
 | 
			
		||||
		else sb.append(" function calls.");
 | 
			
		||||
		return sb.toString();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	protected void saveState(PopulationInterface Pop) {
 | 
			
		||||
		oldFit = Pop.getBestFitness().clone();
 | 
			
		||||
		oldNorm = PhenotypeMetric.norm(oldFit);
 | 
			
		||||
		popFitCalls = Pop.getFunctionCalls();
 | 
			
		||||
		popGens = Pop.getGeneration();
 | 
			
		||||
		firstTime = false;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Return true if |oldFit - curFit| < |oldFit| * thresh (relative case)
 | 
			
		||||
	 * and if |oldFit - curFit| < thresh (absolute case).
 | 
			
		||||
	 *
 | 
			
		||||
	 * @param curFit
 | 
			
		||||
	 * @return
 | 
			
		||||
	 */
 | 
			
		||||
	protected boolean isStillConverged(PopulationInterface pop) {
 | 
			
		||||
		double[] curFit = pop.getBestFitness();
 | 
			
		||||
		double dist = EuclideanMetric.euclideanDistance(oldFit, curFit);
 | 
			
		||||
		boolean ret;
 | 
			
		||||
		if (convergenceCondition.isSelectedString("Relative")) {
 | 
			
		||||
			ret = (dist < (oldNorm * convThresh));
 | 
			
		||||
		} else {
 | 
			
		||||
			ret = (dist < convThresh);
 | 
			
		||||
		}
 | 
			
		||||
		if (TRACE) System.out.println("isStillConverged returns " + ret + ", dist " + dist + ", old fit " + BeanInspector.toString(oldFit) + ", curFit " + BeanInspector.toString(curFit));
 | 
			
		||||
		return ret;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private boolean stagnationTimeHasPassed(PopulationInterface pop) {
 | 
			
		||||
		if (stagnationMeasure.isSelectedString("Fitness calls")) { // by fitness calls
 | 
			
		||||
//			System.out.println("stagnationTimeHasPassed returns " + ((pop.getFunctionCalls() - popFitCalls) >= m_stagTime) + " after " + (pop.getFunctionCalls() - popFitCalls));
 | 
			
		||||
			return (pop.getFunctionCalls() - popFitCalls) >= m_stagTime;
 | 
			
		||||
		} else {// by generation
 | 
			
		||||
//			System.out.println("stagnationTimeHasPassed returns " + ((pop.getFunctionCalls() - popGens) >= m_stagTime) + " after " + (pop.getFunctionCalls() - popGens));
 | 
			
		||||
			return (pop.getGeneration() - popGens) >= m_stagTime;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 *
 | 
			
		||||
	 */
 | 
			
		||||
	public void setConvergenceThreshold(double x) {
 | 
			
		||||
		convThresh = x;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 *
 | 
			
		||||
	 */
 | 
			
		||||
	public double getConvergenceThreshold() {
 | 
			
		||||
		return convThresh;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public String convergenceThresholdTipText() {
 | 
			
		||||
		return "Terminate if the fitness has not improved by this percentage / absolute value for a whole stagnation time period";
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 *
 | 
			
		||||
	 */
 | 
			
		||||
	public void setStagnationTime(int k) {
 | 
			
		||||
		m_stagTime = k;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 *
 | 
			
		||||
	 */
 | 
			
		||||
	public int getStagnationTime() {
 | 
			
		||||
		return m_stagTime;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public String stagnationTimeTipText() {
 | 
			
		||||
		return "Terminate if the population has not improved for this time";
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * @return the stagnationTimeIn
 | 
			
		||||
	 */
 | 
			
		||||
	public SelectedTag getStagnationMeasure() {
 | 
			
		||||
		return stagnationMeasure;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * @param stagnationTimeIn the stagnationTimeIn to set
 | 
			
		||||
	 */
 | 
			
		||||
	public void setStagnationMeasure(SelectedTag stagnationTimeIn) {
 | 
			
		||||
		this.stagnationMeasure = stagnationTimeIn;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public String stagnationMeasureTipText() {
 | 
			
		||||
		return "Stagnation time is measured in fitness calls or generations, to be selected here.";
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * @return the convergenceCondition
 | 
			
		||||
	 */
 | 
			
		||||
	public SelectedTag getConvergenceCondition() {
 | 
			
		||||
		return convergenceCondition;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * @param convergenceCondition the convergenceCondition to set
 | 
			
		||||
	 */
 | 
			
		||||
	public void setConvergenceCondition(SelectedTag convergenceCondition) {
 | 
			
		||||
		this.convergenceCondition = convergenceCondition;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public String convergenceConditionTipText() {
 | 
			
		||||
		return "Select between absolute and relative convergence condition";
 | 
			
		||||
	@Override
 | 
			
		||||
	protected String getMeasureName() {
 | 
			
		||||
		return "Fitness";
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,102 @@
 | 
			
		||||
package eva2.server.go.operators.terminators;
 | 
			
		||||
 | 
			
		||||
import java.io.Serializable;
 | 
			
		||||
 | 
			
		||||
import eva2.gui.BeanInspector;
 | 
			
		||||
import eva2.server.go.PopulationInterface;
 | 
			
		||||
import eva2.server.go.operators.paretofrontmetrics.InterfaceParetoFrontMetric;
 | 
			
		||||
import eva2.server.go.operators.paretofrontmetrics.MetricS;
 | 
			
		||||
import eva2.server.go.populations.Population;
 | 
			
		||||
import eva2.server.go.problems.AbstractMultiObjectiveOptimizationProblem;
 | 
			
		||||
import eva2.server.go.problems.InterfaceOptimizationProblem;
 | 
			
		||||
import eva2.tools.EVAERROR;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Employ a pareto metric to determine convergence of a population. Requires to be run
 | 
			
		||||
 * with a AbstractMultiObjectiveOptimizationProblem instance since the metric depend 
 | 
			
		||||
 * on the fitness range.
 | 
			
		||||
 * The metric may be employed on the current population or the current pareto front
 | 
			
		||||
 * maintained by the problem instance.
 | 
			
		||||
 * 
 | 
			
		||||
 * @author mkron
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
public class ParetoMetricTerminator extends PopulationMeasureTerminator implements Serializable {
 | 
			
		||||
	private InterfaceParetoFrontMetric pMetric = new MetricS();
 | 
			
		||||
	AbstractMultiObjectiveOptimizationProblem moProb=null;
 | 
			
		||||
	private boolean useCurrentPop = false;
 | 
			
		||||
	
 | 
			
		||||
	public ParetoMetricTerminator() {
 | 
			
		||||
		moProb=null;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	//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);
 | 
			
		||||
		this.pMetric = metric;
 | 
			
		||||
		this.useCurrentPop = useCurrentPop;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	public ParetoMetricTerminator(ParetoMetricTerminator o) {
 | 
			
		||||
		super(o);
 | 
			
		||||
		this.pMetric = (InterfaceParetoFrontMetric)o.pMetric.clone();
 | 
			
		||||
		this.moProb = o.moProb;
 | 
			
		||||
		this.useCurrentPop = o.useCurrentPop;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	@Override
 | 
			
		||||
	public void init(InterfaceOptimizationProblem prob) {
 | 
			
		||||
		super.init(prob);
 | 
			
		||||
		if (prob instanceof AbstractMultiObjectiveOptimizationProblem) moProb = (AbstractMultiObjectiveOptimizationProblem)prob;
 | 
			
		||||
		else {
 | 
			
		||||
			moProb = null;
 | 
			
		||||
			EVAERROR.errorMsgOnce("Error, " + this.getClass() + " works only with problems inheriting from " + AbstractMultiObjectiveOptimizationProblem.class + "!");
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
	protected double calcInitialMeasure(PopulationInterface pop) {
 | 
			
		||||
		if (moProb==null) return Double.MAX_VALUE;
 | 
			
		||||
		else {
 | 
			
		||||
			if (isUseCurrentPop()) return getParetoMetric().calculateMetricOn((Population)pop, moProb);
 | 
			
		||||
			else return getParetoMetric().calculateMetricOn(moProb.getLocalParetoFront(), moProb);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
	protected double calcPopulationMeasure(PopulationInterface pop) {
 | 
			
		||||
		return calcInitialMeasure(pop);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
	protected String getMeasureName() {
 | 
			
		||||
		String metricName=null;
 | 
			
		||||
		try {
 | 
			
		||||
			metricName = (String)BeanInspector.callIfAvailable(getParetoMetric(), "getName", null);
 | 
			
		||||
		} catch(ClassCastException e) {metricName=null;}
 | 
			
		||||
		
 | 
			
		||||
		if (metricName==null) return "ParetoMetric";
 | 
			
		||||
		else return metricName;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public void setParetoMetric(InterfaceParetoFrontMetric pMetric) {
 | 
			
		||||
		this.pMetric = pMetric;
 | 
			
		||||
	}
 | 
			
		||||
	public InterfaceParetoFrontMetric getParetoMetric() {
 | 
			
		||||
		return pMetric;
 | 
			
		||||
	}
 | 
			
		||||
	public String paretoMetricTipText() {
 | 
			
		||||
		return "The pareto metric to use";
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public void setUseCurrentPop(boolean useCurrentPop) {
 | 
			
		||||
		this.useCurrentPop = useCurrentPop;
 | 
			
		||||
	}
 | 
			
		||||
	public boolean isUseCurrentPop() {
 | 
			
		||||
		return useCurrentPop;
 | 
			
		||||
	}
 | 
			
		||||
	public String useCurrentPopTipText() {
 | 
			
		||||
		return "If true, the current population is used, otherwise the pareto front of the multi-objective problem instance is used";
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@@ -1,53 +1,64 @@
 | 
			
		||||
package eva2.server.go.operators.terminators;
 | 
			
		||||
 | 
			
		||||
import eva2.gui.BeanInspector;
 | 
			
		||||
import eva2.server.go.IndividualInterface;
 | 
			
		||||
import eva2.server.go.InterfaceTerminator;
 | 
			
		||||
import eva2.server.go.PopulationInterface;
 | 
			
		||||
import eva2.server.go.individuals.AbstractEAIndividual;
 | 
			
		||||
import eva2.server.go.operators.distancemetric.PhenotypeMetric;
 | 
			
		||||
import eva2.server.go.problems.InterfaceOptimizationProblem;
 | 
			
		||||
 | 
			
		||||
public class PhenotypeConvergenceTerminator extends FitnessConvergenceTerminator implements InterfaceTerminator {
 | 
			
		||||
public class PhenotypeConvergenceTerminator extends PopulationMeasureTerminator implements InterfaceTerminator {
 | 
			
		||||
	AbstractEAIndividual oldIndy = null;
 | 
			
		||||
	double oldPhenNorm = 0;
 | 
			
		||||
	private PhenotypeMetric pMetric = null;
 | 
			
		||||
//	double oldPhenNorm = 0;
 | 
			
		||||
	
 | 
			
		||||
	public PhenotypeConvergenceTerminator() {
 | 
			
		||||
		super();
 | 
			
		||||
		tagString = "Phenotype converged";
 | 
			
		||||
		pMetric = new PhenotypeMetric();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public PhenotypeConvergenceTerminator(double thresh, int stagnTime, boolean bFitCallBased, ChangeTypeEnum changeType, boolean bImprovement) {
 | 
			
		||||
		super(thresh, stagnTime, bFitCallBased, changeType, bImprovement);
 | 
			
		||||
		pMetric = new PhenotypeMetric();
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	public PhenotypeConvergenceTerminator(double thresh, int stagnTime, boolean bFitCallBased, boolean bAbsolute) {
 | 
			
		||||
		super(thresh, stagnTime, bFitCallBased, bAbsolute);
 | 
			
		||||
	public PhenotypeConvergenceTerminator(PhenotypeConvergenceTerminator o) {
 | 
			
		||||
		super(o);
 | 
			
		||||
		oldIndy = (AbstractEAIndividual)o.oldIndy.clone();
 | 
			
		||||
		pMetric = (PhenotypeMetric)o.pMetric.clone();
 | 
			
		||||
//		oldPhenNorm = o.oldPhenNorm;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	public void init(InterfaceOptimizationProblem prob) {
 | 
			
		||||
		super.init(prob);
 | 
			
		||||
		tagString = "Phenotype converged";
 | 
			
		||||
//		oldPhenNorm  = 0;
 | 
			
		||||
		oldIndy = null;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	/**
 | 
			
		||||
	 * Return true if |oldPhen - curPhen| < |oldPhen| * thresh (relative case)
 | 
			
		||||
	 * and if |oldFit - curFit| < thresh (absolute case).
 | 
			
		||||
	 * 
 | 
			
		||||
	 * @param curFit
 | 
			
		||||
	 * @return
 | 
			
		||||
	 */
 | 
			
		||||
	protected boolean isStillConverged(PopulationInterface pop) {
 | 
			
		||||
		double dist = pMetric.distance(oldIndy, (AbstractEAIndividual)pop.getBestIndividual());
 | 
			
		||||
		boolean ret;
 | 
			
		||||
		if (getConvergenceCondition().isSelectedString("Relative")) {
 | 
			
		||||
			ret = (dist < (oldPhenNorm * convThresh));
 | 
			
		||||
		} else {
 | 
			
		||||
			ret = (dist < convThresh);
 | 
			
		||||
		}
 | 
			
		||||
		if (TRACE) System.out.println("isStillConverged returns " + ret + ", dist " + dist + ", old indy " + BeanInspector.toString(oldIndy) + ", cur indy" + BeanInspector.toString(pop.getBestIndividual()));
 | 
			
		||||
		return ret;
 | 
			
		||||
		
 | 
			
		||||
	@Override
 | 
			
		||||
	protected double calcInitialMeasure(PopulationInterface pop) {
 | 
			
		||||
		oldIndy = (AbstractEAIndividual)((AbstractEAIndividual)pop.getBestIndividual()).clone();
 | 
			
		||||
//		oldPhenNorm = PhenotypeMetric.norm(oldIndy);
 | 
			
		||||
		return Double.MAX_VALUE;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
	protected double calcPopulationMeasure(PopulationInterface pop) {
 | 
			
		||||
		return pMetric.distance(oldIndy, (AbstractEAIndividual)pop.getBestIndividual());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
	protected void saveState(PopulationInterface Pop) {
 | 
			
		||||
		super.saveState(Pop);
 | 
			
		||||
		oldIndy = (AbstractEAIndividual)((AbstractEAIndividual)Pop.getBestIndividual()).clone();
 | 
			
		||||
		oldPhenNorm = PhenotypeMetric.norm(oldIndy);
 | 
			
		||||
//		oldPhenNorm = PhenotypeMetric.norm(oldIndy);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
	protected String getMeasureName() {
 | 
			
		||||
		return "Phenotype";
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	public static String globalInfo() {
 | 
			
		||||
		return "Terminate if the best individual of the current population moved less than a threshold within phenotypic space."; 
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,64 @@
 | 
			
		||||
package eva2.server.go.operators.terminators;
 | 
			
		||||
 | 
			
		||||
import eva2.server.go.PopulationInterface;
 | 
			
		||||
import eva2.server.go.individuals.IndividualWeightedFitnessComparator;
 | 
			
		||||
import eva2.server.go.populations.Population;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Terminate if a score based on the archive of the population converges.
 | 
			
		||||
 * Note that this only works if the archive is filled with sensible data.
 | 
			
		||||
 * 
 | 
			
		||||
 * @author mkron
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
public class PopulationArchiveTerminator extends PopulationMeasureTerminator {
 | 
			
		||||
	IndividualWeightedFitnessComparator wfComp = new IndividualWeightedFitnessComparator(null);
 | 
			
		||||
	
 | 
			
		||||
//	private boolean isStillConverged(PopulationInterface pop) {
 | 
			
		||||
//		Population archive = ((Population)pop).getArchive();
 | 
			
		||||
//		if (archive==null || (archive.size()<1)) {
 | 
			
		||||
//			System.err.println("Error, population had no archive in " + this.getClass());
 | 
			
		||||
//			return false;
 | 
			
		||||
//		} else {
 | 
			
		||||
//			double bestScore = Population.getScore(archive.getEAIndividual(0), fitWeights);
 | 
			
		||||
//			for (int i=1; i<archive.size(); i++) {
 | 
			
		||||
//				double tmpScore =  Population.getScore(archive.getEAIndividual(i), fitWeights);
 | 
			
		||||
//				if (tmpScore<bestScore) bestScore=tmpScore;
 | 
			
		||||
//			}
 | 
			
		||||
//			if (bestScore>=oldScore) return true;
 | 
			
		||||
//			else {
 | 
			
		||||
//				oldScore=bestScore;
 | 
			
		||||
//				return false;
 | 
			
		||||
//			}
 | 
			
		||||
//		}
 | 
			
		||||
//	}
 | 
			
		||||
	
 | 
			
		||||
	@Override
 | 
			
		||||
	protected double calcInitialMeasure(PopulationInterface pop) {
 | 
			
		||||
		Population archive = ((Population)pop).getArchive();
 | 
			
		||||
		if (archive==null || (archive.size()<1)) return Double.MAX_VALUE;
 | 
			
		||||
		else return wfComp.calcScore(archive.getBestEAIndividual(wfComp));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
	protected double calcPopulationMeasure(PopulationInterface pop) {
 | 
			
		||||
		Population archive = ((Population)pop).getArchive();
 | 
			
		||||
		if (archive==null || (archive.size()<1)) return Double.MAX_VALUE;
 | 
			
		||||
		else return wfComp.calcScore(archive.getBestEAIndividual(wfComp));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
	protected String getMeasureName() {
 | 
			
		||||
		return "Archive Weighted Score";
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public double[] getFitWeights() {
 | 
			
		||||
		return wfComp.getFitWeights();
 | 
			
		||||
	}
 | 
			
		||||
	public void setFitWeights(double[] fWeights) {
 | 
			
		||||
		wfComp.setFitWeights(fWeights);
 | 
			
		||||
	}
 | 
			
		||||
	public String fitWeightsTipText() {
 | 
			
		||||
		return wfComp.fitWeightsTipText();
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,326 @@
 | 
			
		||||
package eva2.server.go.operators.terminators;
 | 
			
		||||
 | 
			
		||||
import java.io.Serializable;
 | 
			
		||||
 | 
			
		||||
import eva2.gui.BeanInspector;
 | 
			
		||||
import eva2.server.go.InterfaceTerminator;
 | 
			
		||||
import eva2.server.go.PopulationInterface;
 | 
			
		||||
import eva2.server.go.populations.InterfaceSolutionSet;
 | 
			
		||||
import eva2.server.go.problems.InterfaceOptimizationProblem;
 | 
			
		||||
import eva2.tools.SelectedTag;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Abstract class giving the framework for a terminator that is based on
 | 
			
		||||
 * a population measure converging for a given time (number of evaluations or 
 | 
			
		||||
 * generations).
 | 
			
		||||
 * The class detects changes of a population measure over time and may signal convergence
 | 
			
		||||
 * if the measure m(P) behaved in a certain way for a given time. Convergence may
 | 
			
		||||
 * be signaled 
 | 
			
		||||
 * - if the measure reached absolute values below convThresh (absolute value),
 | 
			
		||||
 * - if the measure remained within m(P)+/-convThresh (absolute change),
 | 
			
		||||
 * - if the measure remained above m(P)-convThresh (absolute change and regard improvement only),
 | 
			
		||||
 * - if the measure remained within m(P)*[1-convThresh, 1+convThresh] (relative change),
 | 
			
		||||
 * - if the measure remained above m(P)*(1-convThresh) (relative change and regard improvement only).
 | 
			
		||||
 * 
 | 
			
		||||
 * @author mkron
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
public abstract class PopulationMeasureTerminator implements InterfaceTerminator,
 | 
			
		||||
Serializable {
 | 
			
		||||
	public enum ChangeTypeEnum {relativeChange, absoluteChange, absoluteValue};
 | 
			
		||||
	
 | 
			
		||||
	protected static boolean TRACE = false;
 | 
			
		||||
	private double convThresh = 0.01; //, convThreshLower=0.02;
 | 
			
		||||
	private double oldMeasure = -1;
 | 
			
		||||
	private int stagTime = 1000;
 | 
			
		||||
	private int oldPopFitCalls = 1000;
 | 
			
		||||
	private int oldPopGens = 1000;
 | 
			
		||||
	private boolean firstTime = true;
 | 
			
		||||
	private SelectedTag stagnationMeasure = new SelectedTag("Fitness calls", "Generations");
 | 
			
		||||
//	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");
 | 
			
		||||
	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(PopulationMeasureTerminator o) {
 | 
			
		||||
		convThresh = o.convThresh;
 | 
			
		||||
		stagTime = o.stagTime;
 | 
			
		||||
		oldPopFitCalls = o.oldPopFitCalls;
 | 
			
		||||
		oldPopGens = o.oldPopGens;
 | 
			
		||||
		firstTime = o.firstTime;
 | 
			
		||||
//		oldFit = o.oldFit.clone();
 | 
			
		||||
//		oldNorm = o.oldNorm;
 | 
			
		||||
		msg = o.msg;
 | 
			
		||||
		this.stagnationMeasure.setSelectedTag(o.stagnationMeasure.getSelectedTagID());
 | 
			
		||||
//		this.convergenceCondition.setSelectedTag(o.convergenceCondition.getSelectedTagID());
 | 
			
		||||
		this.changeType = o.changeType;
 | 
			
		||||
		this.condImprovementOrChange.setSelectedTag(o.condImprovementOrChange.getSelectedTagID());
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
//	public void hideHideable() {
 | 
			
		||||
//		setConvergenceCondition(getConvergenceCondition());
 | 
			
		||||
//	}
 | 
			
		||||
	
 | 
			
		||||
//	public PopulationMeasureTerminator() {
 | 
			
		||||
//		pMetric = new PhenotypeMetric();
 | 
			
		||||
//	}
 | 
			
		||||
//
 | 
			
		||||
//	public PopulationMeasureTerminator(double thresh, int stagnPeriod, boolean bFitCallBased, boolean bAbsolute) {
 | 
			
		||||
//		pMetric = new PhenotypeMetric();
 | 
			
		||||
//		convThresh = thresh;
 | 
			
		||||
//		this.m_stagTime = stagnPeriod;
 | 
			
		||||
//		if (bFitCallBased) stagnationMeasure.setSelectedTag("Fitness calls");
 | 
			
		||||
//		else stagnationMeasure.setSelectedTag("Generations");
 | 
			
		||||
//		if (bAbsolute) convergenceCondition.setSelectedTag("Absolute");
 | 
			
		||||
//		else convergenceCondition.setSelectedTag("Relative");
 | 
			
		||||
//	}
 | 
			
		||||
//
 | 
			
		||||
//	public PopulationMeasureTerminator(PopulationMeasureTerminator other) {
 | 
			
		||||
//		pMetric = new PhenotypeMetric();
 | 
			
		||||
//		convThresh = other.convThresh;
 | 
			
		||||
//		this.m_stagTime = other.m_stagTime;
 | 
			
		||||
//		stagnationMeasure.setSelectedTag(other.getStagnationMeasure().getSelectedTagID());
 | 
			
		||||
//		convergenceCondition.setSelectedTag(other.getConvergenceCondition().getSelectedTagID());
 | 
			
		||||
//	}
 | 
			
		||||
	
 | 
			
		||||
	public static String globalInfo() {
 | 
			
		||||
		return "Stop if a convergence criterion has been met.";
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public void init(InterfaceOptimizationProblem prob) {
 | 
			
		||||
		firstTime = true;
 | 
			
		||||
		msg = "Not terminated.";
 | 
			
		||||
//		oldFit = null;
 | 
			
		||||
//		oldNorm=-1;
 | 
			
		||||
		oldPopFitCalls=-1;
 | 
			
		||||
		oldPopGens=-1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public boolean isTerminated(InterfaceSolutionSet solSet) {
 | 
			
		||||
		return isTerminated(solSet.getCurrentPopulation());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public boolean isTerminated(PopulationInterface pop) {
 | 
			
		||||
		if (!firstTime && isStillConverged(pop)) {
 | 
			
		||||
			if (TRACE) System.out.println("Converged at " + pop.getGeneration() + "/" + pop.getFunctionCalls() + ", measure " + calcPopulationMeasure(pop));
 | 
			
		||||
			if (stagnationTimeHasPassed(pop)) {
 | 
			
		||||
				// population hasnt changed much for max time, criterion is met
 | 
			
		||||
				msg = getTerminationMessage();
 | 
			
		||||
				return true;
 | 
			
		||||
			} else {
 | 
			
		||||
				// population hasnt changed much for i<max time, keep running
 | 
			
		||||
				return false;
 | 
			
		||||
			}
 | 
			
		||||
		} else {
 | 
			
		||||
			// first call at all - or population improved more than "allowed" to terminate
 | 
			
		||||
			oldMeasure = calcInitialMeasure(pop);
 | 
			
		||||
			saveState(pop);
 | 
			
		||||
			return false;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Calculate the initial measure (on the initial population).
 | 
			
		||||
	 * @return
 | 
			
		||||
	 */
 | 
			
		||||
	protected abstract double calcInitialMeasure(PopulationInterface pop);
 | 
			
		||||
		
 | 
			
		||||
	public String lastTerminationMessage() {
 | 
			
		||||
		return msg;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Build a standard termination message based on the configuration.
 | 
			
		||||
	 * @return
 | 
			
		||||
	 */
 | 
			
		||||
	protected String getTerminationMessage() {
 | 
			
		||||
		StringBuffer sb = new StringBuffer(getMeasureName());
 | 
			
		||||
//		if (convergenceCondition.isSelectedString("Relative")) sb.append(" converged relatively ");
 | 
			
		||||
		switch (changeType) {
 | 
			
		||||
		case absoluteChange: sb.append(" changed absolutely "); break;
 | 
			
		||||
		case absoluteValue: sb.append(" reached absolute values "); break;
 | 
			
		||||
		case relativeChange: sb.append(" changed relatively "); break;
 | 
			
		||||
		}
 | 
			
		||||
		if (doCheckImprovement()) {
 | 
			
		||||
			sb.append("less than ");
 | 
			
		||||
			sb.append(convThresh);
 | 
			
		||||
		} else {
 | 
			
		||||
			sb.append("within +/-");
 | 
			
		||||
//			sb.append(convThreshLower);
 | 
			
		||||
//			sb.append("/");
 | 
			
		||||
			sb.append(convThresh);
 | 
			
		||||
		}
 | 
			
		||||
		sb.append(" for ");
 | 
			
		||||
		sb.append(stagTime);
 | 
			
		||||
		if (stagnationMeasure.isSelectedString("Generations")) sb.append(" generations.");
 | 
			
		||||
		else sb.append(" function calls.");
 | 
			
		||||
		return sb.toString();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Give a String description of the name of the population measure.
 | 
			
		||||
	 * @return
 | 
			
		||||
	 */
 | 
			
		||||
	protected abstract String getMeasureName();
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Save the population state if a change has been detected.
 | 
			
		||||
	 * When overriding, make sure to call the superclass method.
 | 
			
		||||
	 * 
 | 
			
		||||
	 * @param pop
 | 
			
		||||
	 */
 | 
			
		||||
	protected void saveState(PopulationInterface pop) {
 | 
			
		||||
//		oldFit = pop.getBestFitness().clone();
 | 
			
		||||
		oldMeasure = calcPopulationMeasure(pop);
 | 
			
		||||
		oldPopFitCalls = pop.getFunctionCalls();
 | 
			
		||||
		oldPopGens = pop.getGeneration();
 | 
			
		||||
		firstTime = false;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Calculate the population measure on which the termination
 | 
			
		||||
	 * criterion is based.
 | 
			
		||||
	 *
 | 
			
		||||
	 * @param pop
 | 
			
		||||
	 * @return
 | 
			
		||||
	 */
 | 
			
		||||
	protected abstract double calcPopulationMeasure(PopulationInterface pop);
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Return true if the population measure did not exceed the
 | 
			
		||||
	 * threshold for convergence since the last saved state.
 | 
			
		||||
	 *
 | 
			
		||||
	 * @param curFit
 | 
			
		||||
	 * @return
 | 
			
		||||
	 */
 | 
			
		||||
	protected boolean isStillConverged(PopulationInterface pop) {
 | 
			
		||||
		double measure = calcPopulationMeasure(pop);
 | 
			
		||||
		double allowedLower=Double.MIN_VALUE, allowedUpper=Double.MAX_VALUE;
 | 
			
		||||
		boolean ret;
 | 
			
		||||
		switch (changeType) {
 | 
			
		||||
		case absoluteChange:
 | 
			
		||||
			allowedLower=oldMeasure-convThresh;
 | 
			
		||||
			if (!doCheckImprovement()) allowedUpper=oldMeasure+convThresh;
 | 
			
		||||
			break;
 | 
			
		||||
		case absoluteValue:
 | 
			
		||||
			allowedLower=convThresh;
 | 
			
		||||
//			if (!doCheckImprovement()) allowedUpper = convThreshUpper;
 | 
			
		||||
			break;
 | 
			
		||||
		case relativeChange:
 | 
			
		||||
			double delta = oldMeasure*convThresh;
 | 
			
		||||
			allowedLower = oldMeasure-delta;
 | 
			
		||||
			if (!doCheckImprovement()) allowedUpper = oldMeasure+delta;
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		ret = (measure <= allowedUpper) && (measure >= allowedLower);
 | 
			
		||||
		// Old Version:
 | 
			
		||||
//		if (isRelativeConvergence()) {
 | 
			
		||||
//			double delta = oldMeasure*convThresh;
 | 
			
		||||
//			if (doCheckImprovement()) ret = (measure >= (oldMeasure - delta));
 | 
			
		||||
//			else ret = ((measure >= (oldMeasure-delta)) && (measure <= (oldMeasure+delta))); // check for rel. change which must be within +/- thresh
 | 
			
		||||
//		} else { // check absolute values
 | 
			
		||||
//			if (doCheckImprovement()) ret = (measure < oldMeasure+convThresh); // absolute improvement below fixed number
 | 
			
		||||
//			else ret = ((measure < oldMeasure+convThresh) && (measure > oldMeasure-convThresh)); // absolute change within fixed range
 | 
			
		||||
//		}
 | 
			
		||||
		if (TRACE) System.out.println("isStillConverged returns " + ret + ", measure " + measure + ", old measure " + BeanInspector.toString(oldMeasure) + ", bounds: [" + allowedLower + " , " + allowedUpper + "]");
 | 
			
		||||
		return ret;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public boolean doCheckImprovement() {
 | 
			
		||||
		return condImprovementOrChange.isSelectedString("Improvement");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public boolean isRelativeConvergence() {
 | 
			
		||||
		return changeType==ChangeTypeEnum.relativeChange;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	/**
 | 
			
		||||
	 * Return true if the defined stagnation time (function calls or generations) has passed
 | 
			
		||||
	 * since the last noteable change. 
 | 
			
		||||
	 *  
 | 
			
		||||
	 * @param pop
 | 
			
		||||
	 * @return
 | 
			
		||||
	 */
 | 
			
		||||
	private boolean stagnationTimeHasPassed(PopulationInterface pop) {
 | 
			
		||||
		if (stagnationMeasure.isSelectedString("Fitness calls")) { // 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
 | 
			
		||||
//			System.out.println("stagnationTimeHasPassed returns " + ((pop.getFunctionCalls() - popGens) >= m_stagTime) + " after " + (pop.getFunctionCalls() - popGens));
 | 
			
		||||
			return (pop.getGeneration() - oldPopGens) >= stagTime;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public void setConvergenceThreshold(double x) {
 | 
			
		||||
		convThresh = x;
 | 
			
		||||
	}
 | 
			
		||||
	public double getConvergenceThreshold() {
 | 
			
		||||
		return convThresh;
 | 
			
		||||
	}
 | 
			
		||||
	public String convergenceThresholdTipText() {
 | 
			
		||||
		return "Ratio of improvement or absolute value of improvement or change to determine convergence.";
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
//	public void setConvergenceThresholdLower(double x) {
 | 
			
		||||
//		convThreshLower = x;
 | 
			
		||||
//	}
 | 
			
		||||
//	public double getConvergenceThresholdLower() {
 | 
			
		||||
//		return convThreshLower;
 | 
			
		||||
//	}
 | 
			
		||||
//	public String convergenceThresholdUpperTipText() {
 | 
			
		||||
//		return "Lower threshold value in case of detecting absolute change, meaning the bounds [measure-convThresh,measure+convThresh] must be kept to assume convergence.";
 | 
			
		||||
//	}
 | 
			
		||||
	
 | 
			
		||||
	public void setStagnationTime(int k) {
 | 
			
		||||
		stagTime = k;
 | 
			
		||||
	}
 | 
			
		||||
	public int getStagnationTime() {
 | 
			
		||||
		return stagTime;
 | 
			
		||||
	}
 | 
			
		||||
	public String stagnationTimeTipText() {
 | 
			
		||||
		return "Terminate if the population has not improved for this time";
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public SelectedTag getStagnationMeasure() {
 | 
			
		||||
		return stagnationMeasure;
 | 
			
		||||
	}
 | 
			
		||||
	public void setStagnationMeasure(SelectedTag stagnationTimeIn) {
 | 
			
		||||
		this.stagnationMeasure = stagnationTimeIn;
 | 
			
		||||
	}
 | 
			
		||||
	public String stagnationMeasureTipText() {
 | 
			
		||||
		return "Stagnation time is measured in fitness calls or generations, to be selected here.";
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public ChangeTypeEnum getConvergenceCondition() {
 | 
			
		||||
		return changeType;
 | 
			
		||||
	}
 | 
			
		||||
	public void setConvergenceCondition(ChangeTypeEnum convergenceCondition) {
 | 
			
		||||
		this.changeType = convergenceCondition;
 | 
			
		||||
//		GenericObjectEditor.setHideProperty(this.getClass(), "convergenceThresholdUpper", isRelativeConvergence() || doCheckImprovement());
 | 
			
		||||
	}
 | 
			
		||||
	public String convergenceConditionTipText() {
 | 
			
		||||
		return "Select between absolute and relative convergence condition";
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	public SelectedTag getCheckType() {
 | 
			
		||||
		return condImprovementOrChange;
 | 
			
		||||
	}
 | 
			
		||||
	public void setCheckType(SelectedTag ct) {
 | 
			
		||||
		this.condImprovementOrChange = ct;
 | 
			
		||||
//		GenericObjectEditor.setHideProperty(this.getClass(), "convergenceThresholdUpper", isRelativeConvergence() || doCheckImprovement());
 | 
			
		||||
	}
 | 
			
		||||
	public String checkTypeTipText() {
 | 
			
		||||
		return "Detect improvement only (one-directional change) or improvement and deterioration (two-directional change).";
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@@ -70,7 +70,7 @@ public class Population extends ArrayList implements PopulationInterface, Clonea
 | 
			
		||||
    private int lastQModCount = -1;
 | 
			
		||||
    // a sorted queue (for efficiency)
 | 
			
		||||
    transient private ArrayList<AbstractEAIndividual> sortedArr = null;
 | 
			
		||||
    private int lastFitCrit = -1;
 | 
			
		||||
    private Comparator<Object> lastSortingComparator = null;
 | 
			
		||||
//	private AbstractEAIndividualComparator historyComparator = null;
 | 
			
		||||
 | 
			
		||||
    public static final String funCallIntervalReached = "FunCallIntervalReached";
 | 
			
		||||
@@ -807,21 +807,39 @@ public class Population extends ArrayList implements PopulationInterface, Clonea
 | 
			
		||||
    
 | 
			
		||||
	/** 
 | 
			
		||||
	 * This method will return the index of the current best (worst) individual from the
 | 
			
		||||
     * population. If indicated, only those are regarded which do not violate the constraints.
 | 
			
		||||
     * If all violate the constraints, the smallest (largest) violation is selected.
 | 
			
		||||
     * Comparisons are done multicriterial, but note that for incomparable sets (pareto fronts)
 | 
			
		||||
     * this selection will not be fair (always the lowest index of incomparable sets will be returned).
 | 
			
		||||
     * population. A given comparator is employed for individual comparisons.
 | 
			
		||||
     * 
 | 
			
		||||
     * @param bBest if true, smallest fitness (regarded best) index is returned, else the highest one
 | 
			
		||||
     * @param indicate whether constraints should be regarded
 | 
			
		||||
     * @param bBest if true, the best (first) index is returned, else the worst (last) one
 | 
			
		||||
     * @param comparator indicate whether constraints should be regarded
 | 
			
		||||
     * @return The index of the best (worst) individual.
 | 
			
		||||
     */
 | 
			
		||||
    public int getIndexOfBestOrWorstIndividual(boolean bBest, AbstractEAIndividualComparator comparator) {
 | 
			
		||||
    	ArrayList<AbstractEAIndividual> sorted = getSorted(comparator);
 | 
			
		||||
    public int getIndexOfBestOrWorstIndividual(boolean bBest, Comparator<Object> comparator) {
 | 
			
		||||
    	ArrayList<?> sorted = sortBy(comparator);
 | 
			
		||||
    	if (bBest) return indexOf(sorted.get(0));
 | 
			
		||||
    	else return indexOfInstance(sorted.get(sorted.size()-1));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public int getIndexOfBestEAIndividual(AbstractEAIndividualComparator comparator) {
 | 
			
		||||
    	return getIndexOfBestOrWorstIndividual(true, comparator);
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    public AbstractEAIndividual getBestEAIndividual(Comparator<Object> comparator) {
 | 
			
		||||
    	int index = getIndexOfBestOrWorstIndividual(true, comparator);
 | 
			
		||||
    	return getEAIndividual(index);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Return the index of the best (or worst) indy using an AbstractEAIndividualComparator
 | 
			
		||||
     * that checks the constraints first and then for the given fitness criterion (or 
 | 
			
		||||
     * a pareto criterion if it is -1).
 | 
			
		||||
     * 
 | 
			
		||||
     * @param bBest  if true, the best (first) index is returned, else the worst (last) one
 | 
			
		||||
     * @param checkConstraints
 | 
			
		||||
     * @param fitIndex
 | 
			
		||||
     * @see #getIndexOfBestOrWorstIndividual(boolean, Comparator)
 | 
			
		||||
     * @see AbstractEAIndividualComparator
 | 
			
		||||
     * @return
 | 
			
		||||
     */
 | 
			
		||||
    public int getIndexOfBestOrWorstIndy(boolean bBest, boolean checkConstraints, int fitIndex) {
 | 
			
		||||
    	return getIndexOfBestOrWorstIndividual(bBest, new AbstractEAIndividualComparator(fitIndex, checkConstraints));
 | 
			
		||||
    }
 | 
			
		||||
@@ -981,20 +999,22 @@ public class Population extends ArrayList implements PopulationInterface, Clonea
 | 
			
		||||
     * @return The m best individuals, where m <= n
 | 
			
		||||
     * 
 | 
			
		||||
     */
 | 
			
		||||
    public Population getBestNIndividuals(int n) {
 | 
			
		||||
    	return getSortedNIndividuals(n, true);
 | 
			
		||||
    public Population getBestNIndividuals(int n, int fitIndex) {
 | 
			
		||||
    	Population pop = new Population(n);
 | 
			
		||||
    	getSortedNIndividuals(n, true, pop, new AbstractEAIndividualComparator(fitIndex));
 | 
			
		||||
    	return pop;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    /** 
 | 
			
		||||
     * This method returns a clone of the population instance with sorted individuals, where
 | 
			
		||||
     * the sorting criterion is delivered by an AbstractEAIndividualComparator.
 | 
			
		||||
     * @see #getSortedNIndividuals(int, boolean, Population)
 | 
			
		||||
     * the sorting criterion is delivered by a Comparator.
 | 
			
		||||
     * @see #getSortedNIndividuals(int, boolean, Population, Comparator)
 | 
			
		||||
     * 
 | 
			
		||||
     * @return a clone of the population instance with sorted individuals, best fitness first
 | 
			
		||||
     */
 | 
			
		||||
    public Population getSortedBestFirst() {
 | 
			
		||||
    public Population getSortedBestFirst(Comparator<Object> comp) {
 | 
			
		||||
    	Population result = this.cloneWithoutInds();
 | 
			
		||||
    	getSortedNIndividuals(size(), true, result);
 | 
			
		||||
    	getSortedNIndividuals(size(), true, result, comp);
 | 
			
		||||
    	result.synchSize();
 | 
			
		||||
    	return result;
 | 
			
		||||
    }
 | 
			
		||||
@@ -1009,25 +1029,26 @@ public class Population extends ArrayList implements PopulationInterface, Clonea
 | 
			
		||||
     * @return The m sorted best or worst individuals, where m <= n
 | 
			
		||||
     * 
 | 
			
		||||
     */
 | 
			
		||||
    public Population getSortedNIndividuals(int n, boolean bBestOrWorst) {
 | 
			
		||||
    	Population result = new Population((n > 0) ? n : this.size());
 | 
			
		||||
    	getSortedNIndividuals(n, bBestOrWorst, result);
 | 
			
		||||
    	return result;
 | 
			
		||||
    }
 | 
			
		||||
//    public Population getSortedNIndividuals(int n, boolean bBestOrWorst) {
 | 
			
		||||
//    	Population result = new Population((n > 0) ? n : this.size());
 | 
			
		||||
//    	getSortedNIndividuals(n, bBestOrWorst, result);
 | 
			
		||||
//    	return result;
 | 
			
		||||
//    }
 | 
			
		||||
    
 | 
			
		||||
    /** 
 | 
			
		||||
     * This method returns the n current best individuals from the population, where
 | 
			
		||||
     * the sorting criterion is delivered by an AbstractEAIndividualComparator.
 | 
			
		||||
     * the sorting criterion is delivered by a Comparator instance.
 | 
			
		||||
     * There are less than n individuals returned if the population is smaller than n.
 | 
			
		||||
     * This does not check constraints!
 | 
			
		||||
     * 
 | 
			
		||||
     * @param n	number of individuals to look out for
 | 
			
		||||
     * @param bBestOrWorst if true, the best n are returned, else the worst n individuals
 | 
			
		||||
     * @param res	sorted result population, will be cleared
 | 
			
		||||
     * @param comparator the Comparator to use with individuals
 | 
			
		||||
     * @return The m sorted best or worst individuals, where m <= n
 | 
			
		||||
     * 
 | 
			
		||||
     */
 | 
			
		||||
    public void getSortedNIndividuals(int n, boolean bBestOrWorst, Population res) {
 | 
			
		||||
    public void getSortedNIndividuals(int n, boolean bBestOrWorst, Population res, Comparator<Object> comp) {
 | 
			
		||||
    	if ((n < 0) || (n>super.size())) {
 | 
			
		||||
    		// this may happen, treat it gracefully
 | 
			
		||||
    		//System.err.println("invalid request to getSortedNIndividuals: n="+n + ", size is " + super.size());
 | 
			
		||||
@@ -1036,7 +1057,8 @@ public class Population extends ArrayList implements PopulationInterface, Clonea
 | 
			
		||||
    	int skip = 0;
 | 
			
		||||
    	if (!bBestOrWorst) skip = super.size()-n;
 | 
			
		||||
    	
 | 
			
		||||
    	ArrayList<AbstractEAIndividual> sorted = getSorted(lastFitCrit);
 | 
			
		||||
//    	hier getSorted aufrufen
 | 
			
		||||
    	ArrayList<AbstractEAIndividual> sorted = getSorted(comp);
 | 
			
		||||
    	res.clear();
 | 
			
		||||
        for (int i = skip; i < skip+n; i++) {
 | 
			
		||||
        	res.add(sorted.get(i));
 | 
			
		||||
@@ -1044,6 +1066,18 @@ public class Population extends ArrayList implements PopulationInterface, Clonea
 | 
			
		||||
        res.synchSize();
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
//    /**
 | 
			
		||||
//     * Get the n best (or worst) individuals from the population. The last comparator
 | 
			
		||||
//     * is reused, or if none has been employed yet, a standard comparator is used.
 | 
			
		||||
//     * 
 | 
			
		||||
//     * @param n
 | 
			
		||||
//     * @param bBestOrWorst
 | 
			
		||||
//     * @param res
 | 
			
		||||
//     */
 | 
			
		||||
//    public void getSortedNIndividuals(int n, boolean bBestOrWorst, Population res) {
 | 
			
		||||
//    	getSortedNIndividuals(n, bBestOrWorst, res, lastSortingComparator);
 | 
			
		||||
//    }
 | 
			
		||||
    
 | 
			
		||||
    /**
 | 
			
		||||
     * From the given list, remove all but the first n elements.
 | 
			
		||||
     * @param n
 | 
			
		||||
@@ -1076,11 +1110,13 @@ public class Population extends ArrayList implements PopulationInterface, Clonea
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    /**
 | 
			
		||||
     * Set a fitness criterion for sorting procedures. This also affects getBest
 | 
			
		||||
     * Set a fitness criterion for sorting procedures. This sorts the
 | 
			
		||||
     * population once and influences further getBest* methods if no
 | 
			
		||||
     * specific comparator is given.
 | 
			
		||||
     * @param fitIndex
 | 
			
		||||
     */
 | 
			
		||||
    public void setSortingFitnessCriterion(int fitIndex) {
 | 
			
		||||
    	getSorted(fitIndex);
 | 
			
		||||
    	getSorted(new AbstractEAIndividualComparator(fitIndex));
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
//    /**
 | 
			
		||||
@@ -1100,7 +1136,7 @@ public class Population extends ArrayList implements PopulationInterface, Clonea
 | 
			
		||||
     * @param comp A comparator by which sorting is performed - it should work on AbstractEAIndividual instances.
 | 
			
		||||
     * @return
 | 
			
		||||
     */
 | 
			
		||||
    public ArrayList<AbstractEAIndividual> getSorted(Comparator<Object> comp) {
 | 
			
		||||
    protected ArrayList<AbstractEAIndividual> sortBy(Comparator<Object> comp) {
 | 
			
		||||
    	if (super.size()==0) return new ArrayList<AbstractEAIndividual>();
 | 
			
		||||
		PriorityQueue<AbstractEAIndividual> sQueue = new PriorityQueue<AbstractEAIndividual>(super.size(), comp);
 | 
			
		||||
		for (int i = 0; i < super.size(); i++) {
 | 
			
		||||
@@ -1114,26 +1150,43 @@ public class Population extends ArrayList implements PopulationInterface, Clonea
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    /**
 | 
			
		||||
     * Avoids having to sort again in several calls without modifications in between.
 | 
			
		||||
     * The returned array should not be modified!
 | 
			
		||||
     * Return a sorted list of individuals. The order is based on the
 | 
			
		||||
     * given comparator. Repeated calls do not resort the population every
 | 
			
		||||
     * time as long as an equal comparator is used (implement the equals() method!)
 | 
			
		||||
     * and the population has not been modified.
 | 
			
		||||
     * The returned array must not be altered!
 | 
			
		||||
     * 
 | 
			
		||||
     * @param fitIndex the fitness criterion to be used or -1 for pareto dominance
 | 
			
		||||
     * @return
 | 
			
		||||
     */
 | 
			
		||||
    protected ArrayList<AbstractEAIndividual> getSorted(int fitIndex) {
 | 
			
		||||
    	if ((fitIndex != lastFitCrit) || (sortedArr == null) || (super.modCount != lastQModCount)) {
 | 
			
		||||
    		lastFitCrit=fitIndex;
 | 
			
		||||
    		ArrayList<AbstractEAIndividual> sArr = getSorted(new AbstractEAIndividualComparator(fitIndex));
 | 
			
		||||
    public ArrayList<AbstractEAIndividual> getSorted(Comparator<Object> comp) {
 | 
			
		||||
//    	Comparator<Object> comp = new AbstractEAIndividualComparator(fitIndex);
 | 
			
		||||
//    	if (!comp.equals(lastSortingComparator)) return sortedArr;
 | 
			
		||||
    	if (!comp.equals(lastSortingComparator) || (sortedArr == null) || (super.modCount != lastQModCount)) {
 | 
			
		||||
//    		lastFitCrit=fitIndex;lastSortingComparator
 | 
			
		||||
    		ArrayList<AbstractEAIndividual> sArr = sortBy(comp);
 | 
			
		||||
    		if (sortedArr==null) sortedArr = sArr;
 | 
			
		||||
    		else {
 | 
			
		||||
    			sortedArr.clear();
 | 
			
		||||
    			sortedArr.addAll(sArr);
 | 
			
		||||
    		}    		
 | 
			
		||||
    		}
 | 
			
		||||
    		lastSortingComparator = (Comparator<Object>) Serializer.deepClone(comp);
 | 
			
		||||
    		lastQModCount = super.modCount;
 | 
			
		||||
    	}
 | 
			
		||||
    	return sortedArr;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Returns the sorted population as a new population instance.
 | 
			
		||||
     * @see getSorted(Comparator)
 | 
			
		||||
     */
 | 
			
		||||
    public Population getSortedPop(Comparator<Object> comp) {
 | 
			
		||||
    	Population pop = this.cloneWithoutInds();
 | 
			
		||||
    	ArrayList<AbstractEAIndividual> sortedIndies = getSorted(comp);
 | 
			
		||||
    	pop.addAll(sortedIndies);
 | 
			
		||||
    	return pop;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    /** 
 | 
			
		||||
     * This method retrieves n random individuals from the population and
 | 
			
		||||
     * returns them within a new population.
 | 
			
		||||
 
 | 
			
		||||
@@ -3,8 +3,6 @@ package eva2.server.go.problems;
 | 
			
		||||
import java.awt.Color;
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
import java.util.Vector;
 | 
			
		||||
import java.util.concurrent.ExecutorService;
 | 
			
		||||
import java.util.concurrent.Executors;
 | 
			
		||||
import java.util.concurrent.Semaphore;
 | 
			
		||||
 | 
			
		||||
import javax.swing.JFrame;
 | 
			
		||||
@@ -21,7 +19,8 @@ import eva2.server.go.operators.moso.MOSONoConvert;
 | 
			
		||||
import eva2.server.go.operators.paretofrontmetrics.InterfaceParetoFrontMetric;
 | 
			
		||||
import eva2.server.go.operators.paretofrontmetrics.MetricS;
 | 
			
		||||
import eva2.server.go.populations.Population;
 | 
			
		||||
import eva2.server.go.problems.AbstractOptimizationProblem.EvalThread;
 | 
			
		||||
import eva2.server.go.strategies.InterfaceOptimizer;
 | 
			
		||||
import eva2.tools.ToolBox;
 | 
			
		||||
import eva2.tools.chart2d.Chart2DDPointIconCircle;
 | 
			
		||||
import eva2.tools.chart2d.Chart2DDPointIconText;
 | 
			
		||||
import eva2.tools.chart2d.DPoint;
 | 
			
		||||
@@ -352,65 +351,6 @@ public abstract class AbstractMultiObjectiveOptimizationProblem extends Abstract
 | 
			
		||||
            moProblem.drawAdditionalData(plot, p, 10);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
//    /** This method will draw the current state of the optimization process
 | 
			
		||||
//     * @param p     The current population
 | 
			
		||||
//     */
 | 
			
		||||
//    public static void drawProblem(Population p, Plot plot, AbstractMultiObjectiveOptimizationProblem moProblem) {
 | 
			
		||||
//        ArchivingAllDominating  tmpArch = new ArchivingAllDominating();
 | 
			
		||||
//        Population              tmpPop = null;
 | 
			
		||||
//
 | 
			
		||||
//        if (p.getGeneration() > 2) {
 | 
			
		||||
////            m_Plot = new eva2.gui.Plot("Multiobjective Optimization", "Y1", "Y2");
 | 
			
		||||
//            // i want to plot the pareto front for MOEA and other strategies
 | 
			
		||||
//            // but i have to differentiate between the case where
 | 
			
		||||
//            // there is a true MOEA at work and where the
 | 
			
		||||
//            // MOOpt was converted into a SOOpt
 | 
			
		||||
//            if (AbstractMultiObjectiveOptimizationProblem.isPopulationMultiObjective(p)) {
 | 
			
		||||
//                // in this case i have to use my local archive
 | 
			
		||||
//                tmpPop = moProblem.m_ParetoFront;
 | 
			
		||||
//            } else {
 | 
			
		||||
//                // in this case i use the population of the optimizer
 | 
			
		||||
//                // and eventually the pop.archive if there is one
 | 
			
		||||
//                tmpPop = new Population();
 | 
			
		||||
//                tmpPop.addPopulation(p);
 | 
			
		||||
//                if (p.getArchive() != null) tmpPop.addPopulation(p.getArchive());
 | 
			
		||||
//                tmpArch.addElementsToArchive(tmpPop);
 | 
			
		||||
//                tmpPop = tmpPop.getArchive();
 | 
			
		||||
//            }
 | 
			
		||||
//            if (tmpPop != null) {
 | 
			
		||||
//                // i got either a multiobjective population or a multiobjective local population
 | 
			
		||||
//            	plot.clearAll();
 | 
			
		||||
//                tmpArch.plotParetoFront(tmpPop, plot);
 | 
			
		||||
//                if ((true) && (p.getArchive() != null)) {
 | 
			
		||||
//                    GraphPointSet   mySet = new GraphPointSet(10, plot.getFunctionArea());
 | 
			
		||||
//                    DPoint          myPoint;
 | 
			
		||||
//                    Chart2DDPointIconCircle      icon;
 | 
			
		||||
//                    double[]        tmpD;
 | 
			
		||||
//                    mySet.setConnectedMode(false);
 | 
			
		||||
//                    tmpPop = p.getArchive();
 | 
			
		||||
//                    for (int i = 0; i < tmpPop.size(); i++) {
 | 
			
		||||
//                        icon    = new Chart2DDPointIconCircle();
 | 
			
		||||
//                        tmpD    = ((AbstractEAIndividual)tmpPop.get(i)).getFitness();
 | 
			
		||||
//                        myPoint = new DPoint(tmpD[0], tmpD[1]);
 | 
			
		||||
//                        if (((AbstractEAIndividual)tmpPop.get(i)).getConstraintViolation() > 0) {
 | 
			
		||||
//                            icon.setBorderColor(Color.RED);
 | 
			
		||||
//                            icon.setFillColor(Color.RED);
 | 
			
		||||
//                        } else {
 | 
			
		||||
//                            icon.setBorderColor(Color.BLACK);
 | 
			
		||||
//                            icon.setFillColor(Color.BLACK);
 | 
			
		||||
//                        }
 | 
			
		||||
//                        myPoint.setIcon(icon);
 | 
			
		||||
//                        mySet.addDPoint(myPoint);
 | 
			
		||||
//                    }
 | 
			
		||||
//                }
 | 
			
		||||
//            } else {
 | 
			
		||||
////                // in this case i got a single objective optimization problem
 | 
			
		||||
//            }
 | 
			
		||||
//            // draw additional data
 | 
			
		||||
//            moProblem.drawAdditionalData(plot, p, 10);
 | 
			
		||||
//        }
 | 
			
		||||
//    }
 | 
			
		||||
 | 
			
		||||
    /** 
 | 
			
		||||
     * This method will plot a reference solutions or something like it
 | 
			
		||||
@@ -536,25 +476,33 @@ public abstract class AbstractMultiObjectiveOptimizationProblem extends Abstract
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public String[] getAdditionalFileStringHeader(PopulationInterface pop) {
 | 
			
		||||
        String[] result = new String[1];
 | 
			
		||||
        if (AbstractMultiObjectiveOptimizationProblem.isPopulationMultiObjective((Population)pop))
 | 
			
		||||
            result[0] = "SMetric";
 | 
			
		||||
        else
 | 
			
		||||
            result[0] = "BestFitness";
 | 
			
		||||
        return result;
 | 
			
		||||
		String[] superHd = super.getAdditionalFileStringHeader(pop);
 | 
			
		||||
		return ToolBox.appendArrays(new String[]{"paretoMetricCurrent","paretoMetricFront"}, superHd);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public Object[] getAdditionalFileStringValue(PopulationInterface pop) {
 | 
			
		||||
        Object[] result = new Object[1];
 | 
			
		||||
        if (AbstractMultiObjectiveOptimizationProblem.isPopulationMultiObjective((Population)pop))
 | 
			
		||||
            result[0] = this.calculateMetric((Population)pop);
 | 
			
		||||
        else
 | 
			
		||||
            result[0] = ((Population)pop).getBestEAIndividual().getFitness()[0];
 | 
			
		||||
        return result;
 | 
			
		||||
    	Object[] result = new Object[2];
 | 
			
		||||
    	result[0] = this.calculateMetric((Population)pop);
 | 
			
		||||
    	result[1] = this.calculateMetric(getLocalParetoFront());
 | 
			
		||||
		return ToolBox.appendArrays(result, super.getAdditionalFileStringValue(pop));
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    @Override
 | 
			
		||||
    public String[] getAdditionalFileStringInfo(PopulationInterface pop) {
 | 
			
		||||
    	String[] superInfo = super.getAdditionalFileStringInfo(pop);
 | 
			
		||||
    	return ToolBox.appendArrays(new String[]{"Pareto metric on the current population (per generation)",
 | 
			
		||||
    			"Pareto metric on the collected pareto front"}, superInfo);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public double calculateMetric(Population pop) {
 | 
			
		||||
	@Override
 | 
			
		||||
	public String getStringRepresentationForProblem(InterfaceOptimizer opt) {
 | 
			
		||||
		// TODO Auto-generated method stub
 | 
			
		||||
		return null;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public double calculateMetric(Population pop) {
 | 
			
		||||
    	if (pop==null) return Double.NaN;
 | 
			
		||||
        return this.m_Metric.calculateMetricOn(pop, this);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -30,6 +30,7 @@ import eva2.server.go.operators.postprocess.SolutionHistogram;
 | 
			
		||||
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.populations.Population;
 | 
			
		||||
import eva2.server.go.strategies.InterfaceOptimizer;
 | 
			
		||||
 | 
			
		||||
@@ -483,7 +484,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, true), term, false);
 | 
			
		||||
    	if (epsilonFitConv > 0) term = new CombinedTerminator(new PhenotypeConvergenceTerminator(epsilonFitConv, 100*dim, true, ChangeTypeEnum.absoluteChange, true), 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);
 | 
			
		||||
 
 | 
			
		||||
@@ -396,7 +396,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);
 | 
			
		||||
		FitnessConvergenceTerminator convTerm = new FitnessConvergenceTerminator(1e-25, 10, false, true, true);
 | 
			
		||||
		int calls = PostProcess.processSingleCandidatesNMCMA(PostProcessMethod.nelderMead, pop, convTerm, 0.001, prob);
 | 
			
		||||
		return ((InterfaceDataTypeDouble)pop.getBestEAIndividual()).getDoubleData();
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -156,8 +156,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); // gen. based, absolute
 | 
			
		||||
    	fitConvTerm = new FitnessConvergenceTerminator(stagThreshold, (isStagnationTimeUserDef()) ? stagTimeArbitrary : calcDefaultStagnationTime(), false, true, true); // gen. based, absolute
 | 
			
		||||
    	getPopulation().addPopulationChangedEventListener(this);
 | 
			
		||||
    	getPopulation().setNotifyEvalInterval(initialLambda);
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -126,7 +126,7 @@ public class NelderMeadSimplex implements InterfaceOptimizer, Serializable, Inte
 | 
			
		||||
 | 
			
		||||
		// hole die n-1 besten individuen der fitness dimension fitIndex
 | 
			
		||||
		subpop.setSortingFitnessCriterion(fitIndex);
 | 
			
		||||
		Population bestpop = subpop.getBestNIndividuals(subpop.size()-1);
 | 
			
		||||
		Population bestpop = subpop.getBestNIndividuals(subpop.size()-1, fitIndex);
 | 
			
		||||
		// und das schlechteste
 | 
			
		||||
		AbstractEAIndividual worst = subpop.getWorstEAIndividual(fitIndex);
 | 
			
		||||
		AbstractEAIndividual best=subpop.getBestEAIndividual(fitIndex);
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user