From 372e0cf5e9750001d897c04753fbabf39871b12b Mon Sep 17 00:00:00 2001 From: Marcel Kronfeld Date: Thu, 15 Apr 2010 09:43:49 +0000 Subject: [PATCH] Minor updates, merging MK branch revs. 511:515 --- src/eva2/gui/GenericObjectEditor.java | 3 +- src/eva2/gui/JTextoutputFrame.java | 1 - src/eva2/gui/Plot.java | 18 +- src/eva2/gui/PropertySheetPanel.java | 1 - .../go/enums/MutateESCrossoverTypeEnum.java | 5 + .../go/individuals/AbstractEAIndividual.java | 20 +- .../individuals/ESIndividualDoubleData.java | 3 +- .../IndividualDistanceComparator.java | 40 +++ .../go/mocco/MOCCOProblemInitialization.java | 1 - .../operators/archiving/ArchivingMaxiMin.java | 2 +- .../operators/archiving/ArchivingNSGAII.java | 2 +- .../operators/archiving/ArchivingSPEAII.java | 2 +- .../constraint/GenericConstraint.java | 6 +- .../crossover/CrossoverESDefault.java | 5 +- .../distancemetric/EuclideanMetric.java | 4 +- .../distancemetric/IndividualDataMetric.java | 1 - .../migration/MOClusteringSeparation.java | 4 +- .../server/go/operators/moso/MOSOMaxiMin.java | 2 +- .../go/operators/mutation/MutateESGlobal.java | 76 +++-- .../selection/SelectBestIndividuals.java | 3 +- .../operators/selection/SelectBestSingle.java | 17 +- .../HistoryConvergenceTerminator.java | 2 + .../server/go/populations/Population.java | 251 +++++++++++++--- .../problems/AbstractOptimizationProblem.java | 2 +- .../go/problems/AbstractProblemDouble.java | 2 +- .../go/strategies/ClusterBasedNichingEA.java | 9 +- src/eva2/server/modules/Processor.java | 2 +- src/eva2/server/stat/AbstractStatistics.java | 7 +- src/eva2/server/stat/StatisticsWithGUI.java | 5 +- src/eva2/tools/Serializer.java | 95 ++++-- src/eva2/tools/math/Mathematics.java | 32 +- src/eva2/tools/math/StatisticUtils.java | 282 +++++++++++++++--- 32 files changed, 709 insertions(+), 196 deletions(-) create mode 100644 src/eva2/server/go/enums/MutateESCrossoverTypeEnum.java create mode 100644 src/eva2/server/go/individuals/IndividualDistanceComparator.java diff --git a/src/eva2/gui/GenericObjectEditor.java b/src/eva2/gui/GenericObjectEditor.java index eb1c0911..7c54b07d 100644 --- a/src/eva2/gui/GenericObjectEditor.java +++ b/src/eva2/gui/GenericObjectEditor.java @@ -320,9 +320,8 @@ public class GenericObjectEditor implements PropertyEditor { */ private void setObject(Object c) { // This should really call equals() for comparison. - if (TRACE) System.out.println("setObject "+ c.getClass().getName()); + if (TRACE) System.out.println("setObject "+ c.getClass().getName() + " " + c); boolean trueChange = (c != getValue()); - //System.err.println("Didn't even try to make a Object copy!! "+ "(using original)"); m_Backup = m_Object; m_Object = c; diff --git a/src/eva2/gui/JTextoutputFrame.java b/src/eva2/gui/JTextoutputFrame.java index 1bb6640e..dab47b3b 100644 --- a/src/eva2/gui/JTextoutputFrame.java +++ b/src/eva2/gui/JTextoutputFrame.java @@ -153,7 +153,6 @@ Serializable { try { Thread.sleep(100); } catch (InterruptedException e) { - // TODO Auto-generated catch block e.printStackTrace(); } } diff --git a/src/eva2/gui/Plot.java b/src/eva2/gui/Plot.java index 7a701181..378ca2af 100644 --- a/src/eva2/gui/Plot.java +++ b/src/eva2/gui/Plot.java @@ -33,6 +33,8 @@ import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; +import java.util.Formatter; +import java.util.Locale; import javax.imageio.ImageIO; import javax.swing.JButton; @@ -260,22 +262,24 @@ public class Plot implements PlotInterface, Serializable { */ public void drawPopulation(String prefix, Population pop) { for (int i = 0; i < pop.size(); i++) { - drawIndividual(1, 2, prefix, pop.getEAIndividual(i)); + drawIndividual(0, 2, prefix, pop.getEAIndividual(i)); } } /** - * Draw an individual to the Plot instance. It is annotated with the given - * prefix and its fitness. + * Draw an individual to the Plot instance. It is annotated with the + * given prefix and its fitness with short scientific notation. * * @param prefix * @param pop * @see FunctionArea.drawIcon */ - public void drawIndividual(int iconType, int graphID, String prefix, - AbstractEAIndividual indy) { - getFunctionArea().drawIcon(iconType, prefix + " " + indy.getFitness(0), - indy.getDoublePosition(), graphID); + public void drawIndividual(int iconType, int graphID, String prefix, AbstractEAIndividual indy) { + StringBuffer sb = new StringBuffer(); + Formatter formatter = new Formatter(sb, Locale.US); + formatter.format("%s %.3e", prefix, indy.getFitness(0)); + + getFunctionArea().drawIcon(iconType, sb.toString(), indy.getDoublePosition(), graphID); } public void setPreferredSize(Dimension prefSize) { diff --git a/src/eva2/gui/PropertySheetPanel.java b/src/eva2/gui/PropertySheetPanel.java index 42ae3bab..40c3e53d 100644 --- a/src/eva2/gui/PropertySheetPanel.java +++ b/src/eva2/gui/PropertySheetPanel.java @@ -912,7 +912,6 @@ public class PropertySheetPanel extends JPanel implements PropertyChangeListener try { val = getter.invoke(m_Target, (Object[])null); } catch (Exception e) { - // TODO Auto-generated catch block val = null; e.printStackTrace(); } diff --git a/src/eva2/server/go/enums/MutateESCrossoverTypeEnum.java b/src/eva2/server/go/enums/MutateESCrossoverTypeEnum.java new file mode 100644 index 00000000..bac3ed20 --- /dev/null +++ b/src/eva2/server/go/enums/MutateESCrossoverTypeEnum.java @@ -0,0 +1,5 @@ +package eva2.server.go.enums; + +public enum MutateESCrossoverTypeEnum { + none, intermediate, discrete; +} diff --git a/src/eva2/server/go/individuals/AbstractEAIndividual.java b/src/eva2/server/go/individuals/AbstractEAIndividual.java index b4c09b7a..9b4f5825 100644 --- a/src/eva2/server/go/individuals/AbstractEAIndividual.java +++ b/src/eva2/server/go/individuals/AbstractEAIndividual.java @@ -3,6 +3,7 @@ package eva2.server.go.individuals; import java.util.ArrayList; import java.util.BitSet; +import java.util.Formatter; import java.util.HashMap; import java.util.List; @@ -805,7 +806,7 @@ public abstract class AbstractEAIndividual implements IndividualInterface, java. public double getCrossoverProbability() { return this.m_CrossoverProbability; } - public String crossoverProbalilityTipText() { + public String crossoverProbabilityTipText() { return "The chance that crossover occurs."; } @@ -876,13 +877,13 @@ public abstract class AbstractEAIndividual implements IndividualInterface, java. public static String getDefaultStringRepresentation(AbstractEAIndividual individual) { // Note that changing this method might change the hashcode of an individual // which might interfere with some functionality. - StringBuffer sb = new StringBuffer("Fit.: "); + StringBuffer sb = new StringBuffer("Fit.:\t"); sb.append(BeanInspector.toString(individual.getFitness())); if (individual.isMarkedPenalized() || individual.violatesConstraint()) sb.append(", X"); sb.append(", ID: "); sb.append(individual.getIndyID()); - sb.append(", "); + sb.append(",\t"); sb.append(getDefaultDataString(individual)); if (individual.getParentIDs()!=null) { @@ -902,7 +903,7 @@ public abstract class AbstractEAIndividual implements IndividualInterface, java. public static String getDefaultDataString(IndividualInterface individual) { // Note that changing this method might change the hashcode of an individual // which might interfere with some functionality. - return getDefaultDataString(individual, ", "); + return getDefaultDataString(individual, ","); } /** @@ -917,6 +918,7 @@ public abstract class AbstractEAIndividual implements IndividualInterface, java. // which might interfere with some functionality. if (individual == null) return "null"; StringBuffer sb = new StringBuffer(""); + Formatter fm = new Formatter(sb); char left = '{'; char right = '}'; sb.append(left); @@ -933,10 +935,12 @@ public abstract class AbstractEAIndividual implements IndividualInterface, java. if ((i+1) < b.length) sb.append(separator); } } else if (individual instanceof InterfaceDataTypeDouble) { - double[] b = ((InterfaceDataTypeDouble)individual).getDoubleData(); - for (int i = 0; i < b.length; i++) { - sb.append(b[i]); - if ((i+1) < b.length) sb.append(separator); + double[] d = ((InterfaceDataTypeDouble)individual).getDoubleData(); + for (int i = 0; i < d.length; i++) { +// sb.append(d[i]); +// if ((i+1) < d.length) sb.append(separator); + fm.format("% .3f", d[i]); + if ((i+1) < d.length) sb.append(separator); } } else if (individual instanceof InterfaceDataTypePermutation) { int[] b = ((InterfaceDataTypePermutation)individual).getPermutationData()[0]; diff --git a/src/eva2/server/go/individuals/ESIndividualDoubleData.java b/src/eva2/server/go/individuals/ESIndividualDoubleData.java index 2a56a312..ae2d3130 100644 --- a/src/eva2/server/go/individuals/ESIndividualDoubleData.java +++ b/src/eva2/server/go/individuals/ESIndividualDoubleData.java @@ -1,6 +1,7 @@ package eva2.server.go.individuals; +import eva2.server.go.enums.MutateESCrossoverTypeEnum; import eva2.server.go.operators.crossover.CrossoverESDefault; import eva2.server.go.operators.mutation.InterfaceMutation; import eva2.server.go.operators.mutation.MutateESGlobal; @@ -25,7 +26,7 @@ public class ESIndividualDoubleData extends AbstractEAIndividual implements Inte public ESIndividualDoubleData() { this.m_MutationProbability = 1.0; - this.m_MutationOperator = new MutateESGlobal(); + this.m_MutationOperator = new MutateESGlobal(0.2, MutateESCrossoverTypeEnum.intermediate); this.m_CrossoverProbability = 0.5; this.m_CrossoverOperator = new CrossoverESDefault(); this.m_Genotype = new double[1]; diff --git a/src/eva2/server/go/individuals/IndividualDistanceComparator.java b/src/eva2/server/go/individuals/IndividualDistanceComparator.java new file mode 100644 index 00000000..ad387e4f --- /dev/null +++ b/src/eva2/server/go/individuals/IndividualDistanceComparator.java @@ -0,0 +1,40 @@ +package eva2.server.go.individuals; + +import java.util.Comparator; + +import eva2.server.go.operators.distancemetric.InterfaceDistanceMetric; + +/** + * Compare two AbstractEAIndividuals by their distance to a reference individual. + * Usable to sort by a distance. + **/ +public class IndividualDistanceComparator implements Comparator { + + private AbstractEAIndividual refIndy=null; + private InterfaceDistanceMetric distMetric = null; + private boolean closerMeansLess = true; + + /** + * Constructor with a reference individual to which the distance is measured and the corresponding desired metric. + * Using closerIsLess it can be switched between increasing and decreasing order. + * + * @param referenceIndy + * @param metric + * @param closerIsLess + */ + public IndividualDistanceComparator(AbstractEAIndividual referenceIndy, InterfaceDistanceMetric metric, boolean closerIsLess) { + refIndy = referenceIndy; + distMetric = metric; + closerMeansLess = closerIsLess; + } + + public int compare(Object o1, Object o2) { + double d1 = distMetric.distance((AbstractEAIndividual)o1, refIndy); + double d2 = distMetric.distance((AbstractEAIndividual)o2, refIndy); + + if (d1==d2) return 0; + if (closerMeansLess) return ((d1 tmpList = new ArrayList(); - if (indy1.getMutationOperator() instanceof MutateESGlobal) tmpList.add(new Double(((MutateESGlobal)indy1.getMutationOperator()).m_MutationStepSize)); - for (int i = 0; i < partners.size(); i++) { - if (((AbstractEAIndividual)partners.get(i)).getMutationOperator() instanceof MutateESGlobal) tmpList.add(new Double(((MutateESGlobal)((AbstractEAIndividual)partners.get(i)).getMutationOperator()).m_MutationStepSize)); - } - double[] list = new double[tmpList.size()]; - for (int i = 0; i < tmpList.size(); i++) list[i] = ((Double)tmpList.get(i)).doubleValue(); - if (list.length <= 1) return; - switch (this.m_CrossoverType.getSelectedTag().getID()) { - case 1 : { - this.m_MutationStepSize = 0; - for (int i = 0; i < list.length; i++) this.m_MutationStepSize += list[i]; - this.m_MutationStepSize = this.m_MutationStepSize/(double)list.length; - break; - } - case 2 : { - this.m_MutationStepSize = list[RNG.randomInt(0, list.length-1)]; - break; - } - default : { - // do nothing - } - } + if (m_CrossoverType!=MutateESCrossoverTypeEnum.none) { + ArrayList tmpList = new ArrayList(); + if (indy1.getMutationOperator() instanceof MutateESGlobal) tmpList.add(new Double(((MutateESGlobal)indy1.getMutationOperator()).m_MutationStepSize)); + for (int i = 0; i < partners.size(); i++) { + if (((AbstractEAIndividual)partners.get(i)).getMutationOperator() instanceof MutateESGlobal) tmpList.add(new Double(((MutateESGlobal)((AbstractEAIndividual)partners.get(i)).getMutationOperator()).m_MutationStepSize)); + } + double[] list = new double[tmpList.size()]; + for (int i = 0; i < tmpList.size(); i++) list[i] = ((Double)tmpList.get(i)).doubleValue(); + if (list.length <= 1) return; + + switch (this.m_CrossoverType) { + case intermediate : + this.m_MutationStepSize = 0; + for (int i = 0; i < list.length; i++) this.m_MutationStepSize += list[i]; + this.m_MutationStepSize = this.m_MutationStepSize/(double)list.length; + break; + case discrete : + this.m_MutationStepSize = list[RNG.randomInt(0, list.length-1)]; + break; + case none : // do nothing + break; + } + } } /** This method allows you to get a string representation of the mutation @@ -195,10 +205,10 @@ public class MutateESGlobal implements InterfaceMutation, java.io.Serializable { /** Set the value for tau1 with this method. * @param d The mutation operator. */ - public void setCrossoverType(SelectedTag d) { + public void setCrossoverType(MutateESCrossoverTypeEnum d) { this.m_CrossoverType = d; } - public SelectedTag getCrossoverType() { + public MutateESCrossoverTypeEnum getCrossoverType() { return this.m_CrossoverType; } public String crossoverTypeTipText() { diff --git a/src/eva2/server/go/operators/selection/SelectBestIndividuals.java b/src/eva2/server/go/operators/selection/SelectBestIndividuals.java index 12601a1e..29e571e2 100644 --- a/src/eva2/server/go/operators/selection/SelectBestIndividuals.java +++ b/src/eva2/server/go/operators/selection/SelectBestIndividuals.java @@ -41,7 +41,8 @@ public class SelectBestIndividuals implements InterfaceSelection, java.io.Serial // nothing to prepare here } - /** This method will select one Individual from the given + /** + * This method will select n best individuals from the given * Population. * @param population The source population where to select from * @param size The number of Individuals to select diff --git a/src/eva2/server/go/operators/selection/SelectBestSingle.java b/src/eva2/server/go/operators/selection/SelectBestSingle.java index 049da2b2..ad506e1e 100644 --- a/src/eva2/server/go/operators/selection/SelectBestSingle.java +++ b/src/eva2/server/go/operators/selection/SelectBestSingle.java @@ -56,6 +56,7 @@ public class SelectBestSingle implements InterfaceSelection, java.io.Serializabl int currentCriteria = 0, critSize; double currentBestValue; + if (population.size()==0) return population; // trivial critSize = ((AbstractEAIndividual)population.get(0)).getFitness().length; result.setTargetSize(size); if (this.m_ObeyDebsConstViolationPrinciple) { @@ -99,13 +100,21 @@ public class SelectBestSingle implements InterfaceSelection, java.io.Serializabl /** This method allows you to select >size< partners for a given Individual * @param dad The already selected parent - * @param avaiablePartners The mating pool. + * @param availablePartners The mating pool. * @param size The number of partners needed. * @return The selected partners. */ - public Population findPartnerFor(AbstractEAIndividual dad, Population avaiablePartners, int size) { - if (excludeSelfAsPartner) return this.selectFrom(avaiablePartners.filter(new Population().addToPop(dad)), size); - else return this.selectFrom(avaiablePartners, size); + public Population findPartnerFor(AbstractEAIndividual dad, Population availablePartners, int size) { + if (excludeSelfAsPartner) { + Population newPartners = availablePartners.filter(new Population().addToPop(dad)); + if (newPartners.size()==0) { + // no problem if crossover is deactivated +// EVAERROR.errorMsgOnce("Warning, no partners available when excluding self (SelectBestSingle.findPartnerFor)"); +// EVAERROR.errorMsgOnce("Partners where: " + availablePartners.getStringRepresentation()); + return newPartners; + } + return this.selectFrom(newPartners, size); + } else return this.selectFrom(availablePartners, size); } /********************************************************************************************************************** * These are for GUI diff --git a/src/eva2/server/go/operators/terminators/HistoryConvergenceTerminator.java b/src/eva2/server/go/operators/terminators/HistoryConvergenceTerminator.java index a738fae9..eab83299 100644 --- a/src/eva2/server/go/operators/terminators/HistoryConvergenceTerminator.java +++ b/src/eva2/server/go/operators/terminators/HistoryConvergenceTerminator.java @@ -73,6 +73,8 @@ public class HistoryConvergenceTerminator implements InterfaceTerminator, Serial msg = "History did not improve" + (convergenceThreshold>0 ? (" by more than " + convergenceThreshold) : "") + " for " + haltingWindowLen + " iterations."; } } + } else { + if (haltingWindowLen > ((Population)pop).getMaxHistLength()) System.err.println("Warning, population history length not long enough for window length " + haltingWindowLen + " (HistoryConvergenceTerminator)"); } return res; } diff --git a/src/eva2/server/go/populations/Population.java b/src/eva2/server/go/populations/Population.java index d70b07ca..7e47ec01 100644 --- a/src/eva2/server/go/populations/Population.java +++ b/src/eva2/server/go/populations/Population.java @@ -2,8 +2,10 @@ package eva2.server.go.populations; import java.util.ArrayList; import java.util.Arrays; +import java.util.Comparator; import java.util.HashMap; import java.util.Iterator; +import java.util.LinkedList; import java.util.List; import java.util.PriorityQueue; import java.util.Set; @@ -22,6 +24,7 @@ import eva2.server.go.operators.postprocess.PostProcess; import eva2.server.go.operators.selection.probability.AbstractSelProb; import eva2.tools.EVAERROR; import eva2.tools.Pair; +import eva2.tools.Serializer; import eva2.tools.math.Mathematics; import eva2.tools.math.RNG; import eva2.tools.math.StatisticUtils; @@ -58,9 +61,10 @@ public class Population extends ArrayList implements PopulationInterface, Clonea protected int notifyEvalInterval = 0; // additional data connected to the population protected HashMap additionalPopData = null; - // historical best indidivuals may be traced - boolean useHistory = false; - private transient ArrayList m_History = new ArrayList(); + // historical best indidivuals may be traced for a given number of generations. Set to -1 to trace all, set to 0 to not trace at all + int historyMaxLen = 0; +// boolean useHistory = false; + private transient LinkedList m_History = new LinkedList(); // remember when the last sorted queue was prepared private int lastQModCount = -1; @@ -78,7 +82,7 @@ public class Population extends ArrayList implements PopulationInterface, Clonea } /** - * Constructor setting initial capacity and population size to the given + * Constructor setting initial capacity and target population size to the given * integer value. * * @param initialCapacity initial capacity and population size of the instance @@ -123,7 +127,7 @@ public class Population extends ArrayList implements PopulationInterface, Clonea public Population(InterfaceSolutionSet allSolutions) { this(allSolutions.getCurrentPopulation().size()+allSolutions.getSolutions().size()); if (TRACE) System.err.println("TRACING POP"); - addPopulation(allSolutions.getCurrentPopulation()); + addPopulation(allSolutions.getCurrentPopulation(), false); HashMap checkCols = new HashMap(size()); for (int i=0; i)population.m_History.clone(); + if (population.m_History != null) this.m_History = (LinkedList)population.m_History.clone(); if (population.additionalPopData!=null) { this.additionalPopData = (HashMap)additionalPopData.clone(); if (population.additionalPopData.size()>0) { @@ -161,7 +169,7 @@ public class Population extends ArrayList implements PopulationInterface, Clonea this.m_Generation = population.m_Generation; this.m_FunctionCalls = population.m_FunctionCalls; this.m_TargetSize = population.m_TargetSize; - this.useHistory = population.useHistory; + this.historyMaxLen = population.historyMaxLen; this.notifyEvalInterval = population.notifyEvalInterval; this.initMethod = population.initMethod; this.aroundDist = population.aroundDist; @@ -190,7 +198,7 @@ public class Population extends ArrayList implements PopulationInterface, Clonea if (this.m_Generation != opop.m_Generation) return false; if (this.m_FunctionCalls != opop.m_FunctionCalls) return false; if (this.m_TargetSize != opop.m_TargetSize) return false; - if (this.useHistory != opop.useHistory) return false; + if (this.historyMaxLen != opop.historyMaxLen) return false; if (this.notifyEvalInterval != opop.notifyEvalInterval) return false; if (this.initMethod != opop.initMethod) return false; if (this.aroundDist != opop.aroundDist) return false; @@ -253,7 +261,7 @@ public class Population extends ArrayList implements PopulationInterface, Clonea * have been inited by a problem */ public void init() { - this.m_History = new ArrayList(); + this.m_History = new LinkedList(); this.m_Generation = 0; this.m_FunctionCalls = 0; // evaluationTimeHashes = null; @@ -371,10 +379,19 @@ public class Population extends ArrayList implements PopulationInterface, Clonea * @param useHist */ public void setUseHistory(boolean useHist) { - useHistory = useHist; + if (useHist) setMaxHistoryLength(-1); // trace full history! + else setMaxHistoryLength(0); // dont trace at all! // this.setUseHistory(useHist, (useHist ? (new AbstractEAIndividualComparator()) : null)); } - + public boolean isUsingHistory() { + return historyMaxLen!=0; + } + public void setMaxHistoryLength(int len) { + historyMaxLen = len; + } + public int getMaxHistLength() { + return historyMaxLen; + } // /** // * Activate or deactivate the history tracking, which stores the best individual in every // * generation in the incrGeneration() method. @@ -388,15 +405,15 @@ public class Population extends ArrayList implements PopulationInterface, Clonea // } public int getHistoryLength() { - if (useHistory) return m_History.size(); + if (historyMaxLen!=0) return m_History.size(); else return 0; } - public ArrayList getHistory() { + public LinkedList getHistory() { return m_History; } - public void SetHistory(ArrayList theHist) { + public void SetHistory(LinkedList theHist) { m_History = theHist; } @@ -485,8 +502,12 @@ public class Population extends ArrayList implements PopulationInterface, Clonea * Stagnation measured etc. pp. */ public void incrGeneration() { - if (useHistory && (this.size() >= 1)) { - this.m_History.add((AbstractEAIndividual)this.getBestEAIndividual().clone());// TODO + if (isUsingHistory() && (this.size() >= 1)) { + if (historyMaxLen>0 && (m_History.size()>=historyMaxLen)) { + // oldest one must be replaced.. should be the one in front + m_History.removeFirst(); + } + this.m_History.add((AbstractEAIndividual)this.getBestEAIndividual().clone()); } for (int i=0; i getSorted(AbstractEAIndividualComparator comp) { + public ArrayList getSorted(Comparator comp) { if (super.size()==0) return new ArrayList(); PriorityQueue sQueue = new PriorityQueue(super.size(), comp); for (int i = 0; i < super.size(); i++) { @@ -1206,7 +1245,7 @@ public class Population extends ArrayList implements PopulationInterface, Clonea * This method relies on the implementation of the equals method * in the individuals. */ - public void removeDoubleInstances() { + public void removeRedundantIndies() { for (int i = 0; i < this.size(); i++) { for (int j = i+1; j < this.size(); j++) { if (((AbstractEAIndividual)this.get(i)).equals(this.get(j))) { @@ -1217,9 +1256,34 @@ public class Population extends ArrayList implements PopulationInterface, Clonea } } + public Population removeRedundantIndiesAsNew() { + Population pop = this.cloneShallowInds(); + pop.removeRedundantIndies(); + return pop; + } + /** + * Return the number of individuals within this instance that are + * seen as being equal by the equals relation of the individual. + * + * @return the number of equal individuals + * + */ + public int getRedundancyCount() { + int redund = 0; + for (int i=0; imaxCor) maxCor=cor; + if (cor curDist))) { - dist = curDist; - sel = i; + if (pop.getEAIndividual(i)!=null) { + double curDist = metric.distance(refIndy, pop.getEAIndividual(i)); + if ((dist<0) || (!closestOrFarthest && (dist < curDist)) + || (closestOrFarthest && (dist > curDist))) { + dist = curDist; + sel = i; + } } } return new Pair(sel,dist); @@ -1693,7 +1803,14 @@ public class Population extends ArrayList implements PopulationInterface, Clonea */ public boolean isWithinPopDist(AbstractEAIndividual indy, double d, InterfaceDistanceMetric metric) { Pair closest = Population.getClosestFarthestIndy(indy, this, metric, true); - return (closest.tail()<=d); + if (closest.tail()<=d) { + return true; + } else { +// if (size()==1) { +// System.out.println("dist is " + metric.distance(getEAIndividual(0), indy)); +// } + return false; + } } /** @@ -1711,13 +1828,29 @@ public class Population extends ArrayList implements PopulationInterface, Clonea return centerPos; } + /** + * Return an individual which is located at the center of the population. + * The fitness will be invalid. + * + * @return + */ + public IndividualInterface getCenterIndy() { + AbstractEAIndividual indy = (AbstractEAIndividual)getEAIndividual(0).clone(); + double[] center = getCenter(); + indy.setDoublePosition(indy, center); + indy.SetFitness(null); + return indy; + } + /** * Calculate the weighted center position of the population. Weights must add up to one! * * @return the average position of the population */ public double[] getCenterWeighted(double[] weights) { - if (size()==0 || (weights.length > size())) EVAERROR.errorMsgOnce("Invalid pop size in DistractingPopulation:getCenterWeighted!"); + if (size()==0 || (weights.length > size()) || (weights.length==0)) { + EVAERROR.errorMsgOnce("Invalid pop size in DistractingPopulation:getCenterWeighted!"); + } double[] centerPos = AbstractEAIndividual.getDoublePosition(getEAIndividual(0)); Mathematics.svMult(weights[0], centerPos, centerPos); for (int i=1; i=0) cut.add(getEAIndividual(i)); + } + return cut; + } + + /** + * Copy all additional population data of the given instance + * into the current instance (by references only). + * + * @param pop + */ + public void copyHashData(Population pop) { + if (pop!=null && (pop.additionalPopData!=null)) { + for (String key : pop.additionalPopData.keySet()) { + Object origData = pop.getData(key); + Object maybeClone = Serializer.deepClone(origData); + if (maybeClone!=null) putData(key, maybeClone); + else { + System.err.println("Warning, additional pop data could not be cloned!"); + putData(key, origData); + } + } + } + } + + public void clearHistory() { + m_History.clear(); + } + // /** // * Mark the population at the current state as evaluated. Changes to the modCount or hashes of individuals // * will invalidate the mark. diff --git a/src/eva2/server/go/problems/AbstractOptimizationProblem.java b/src/eva2/server/go/problems/AbstractOptimizationProblem.java index 7edfe60e..588e6c14 100644 --- a/src/eva2/server/go/problems/AbstractOptimizationProblem.java +++ b/src/eva2/server/go/problems/AbstractOptimizationProblem.java @@ -240,7 +240,7 @@ implements InterfaceOptimizationProblem /*, InterfaceParamControllable*/, Serial * @return String */ public String[] getAdditionalFileStringHeader(PopulationInterface pop) { - if (this instanceof InterfaceInterestingHistogram) return new String[]{"Solution","Histogram(c0)","Score"}; + if (this instanceof InterfaceInterestingHistogram) return new String[]{"Solution","Histogram","Score"}; else return new String[]{"Solution"}; } diff --git a/src/eva2/server/go/problems/AbstractProblemDouble.java b/src/eva2/server/go/problems/AbstractProblemDouble.java index f701feea..290bdf72 100644 --- a/src/eva2/server/go/problems/AbstractProblemDouble.java +++ b/src/eva2/server/go/problems/AbstractProblemDouble.java @@ -494,7 +494,7 @@ public abstract class AbstractProblemDouble extends AbstractOptimizationProblem @Override public String[] getAdditionalFileStringHeader(PopulationInterface pop) { String[] superHeader = super.getAdditionalFileStringHeader(pop); - if (isWithConstraints()) return ToolBox.appendArrays(superHeader, new String[]{"RawFit.","Num.Viol.","Sum.Viol."}); + if (isWithConstraints()) return ToolBox.appendArrays(superHeader, new String[]{"rawFit","numViol","sumViol"}); else return superHeader; } diff --git a/src/eva2/server/go/strategies/ClusterBasedNichingEA.java b/src/eva2/server/go/strategies/ClusterBasedNichingEA.java index 84995fe7..93d590bb 100644 --- a/src/eva2/server/go/strategies/ClusterBasedNichingEA.java +++ b/src/eva2/server/go/strategies/ClusterBasedNichingEA.java @@ -2,6 +2,8 @@ package eva2.server.go.strategies; import java.util.ArrayList; import java.util.Collections; +import java.util.LinkedList; +import java.util.List; import java.util.PriorityQueue; import eva2.gui.BeanInspector; @@ -17,7 +19,6 @@ import eva2.server.go.individuals.InterfaceDataTypeDouble; import eva2.server.go.operators.cluster.ClusteringDensityBased; import eva2.server.go.operators.cluster.InterfaceClustering; import eva2.server.go.operators.distancemetric.ObjectiveSpaceMetric; -//import eva2.server.go.populations.Distraction; import eva2.server.go.populations.Population; import eva2.server.go.populations.SolutionSet; import eva2.server.go.problems.B1Problem; @@ -327,7 +328,7 @@ public class ClusterBasedNichingEA implements InterfacePopulationChangedEventLis * @return True if converged. */ private boolean testSpeciesForConvergence(Population pop) { - ArrayList speciesHistory = pop.getHistory(); + List speciesHistory = pop.getHistory(); int histLen = speciesHistory.size(); if (histLen <= haltingWindow) { @@ -780,10 +781,10 @@ public class ClusterBasedNichingEA implements InterfacePopulationChangedEventLis newSp.setUseHistory(true); if (startAtP1Gen) { // start explicitely as a child population of p1 newSp.setGenerationTo(parentSp.getGeneration()); - newSp.SetHistory((ArrayList) parentSp.getHistory().clone()); + newSp.SetHistory((LinkedList) parentSp.getHistory().clone()); } else { // start anew (from undiff) newSp.setGenerationTo(0); - newSp.SetHistory(new ArrayList()); + newSp.SetHistory(new LinkedList()); } if (m_Optimizer instanceof InterfaceSpeciesAware) ((InterfaceSpeciesAware)m_Optimizer).splitFromFirst(parentSp, newSp); diff --git a/src/eva2/server/modules/Processor.java b/src/eva2/server/modules/Processor.java index 033e3363..f9910e2c 100644 --- a/src/eva2/server/modules/Processor.java +++ b/src/eva2/server/modules/Processor.java @@ -310,7 +310,7 @@ public class Processor extends Thread implements InterfaceProcessor, InterfacePo else if (terminator instanceof EvaluationTerminator) args = new Object[] {optimizer, optimizer.getPopulation(), optimizer.getPopulation().getFunctionCalls(), ((EvaluationTerminator)terminator).getFitnessCalls()}; // ((InterfaceParameterControl)paramCtrl).updateParameters(optimizer, optimizer.getPopulation().getFunctionCalls(), ((EvaluationTerminator)terminator).getFitnessCalls()); - else args = null;//new Object[]{optimizer, optimizer.getPopulation()}; + else args = new Object[]{optimizer, optimizer.getPopulation()}; // ((InterfaceParameterControl)paramCtrl).updateParameters(optimizer); if (args != null) { // only if iteration counting is available diff --git a/src/eva2/server/stat/AbstractStatistics.java b/src/eva2/server/stat/AbstractStatistics.java index df0a7f7e..064a5af7 100644 --- a/src/eva2/server/stat/AbstractStatistics.java +++ b/src/eva2/server/stat/AbstractStatistics.java @@ -305,6 +305,9 @@ public abstract class AbstractStatistics implements InterfaceTextListener, Inter } else { if (printRunStoppedVerbosity()) printToTextListener(" NO feasible individual found.\n"); } + if (printRunStoppedVerbosity()) { + printToTextListener(" Solution correlations (min,max,avg,med,var): " + BeanInspector.toString(((Population)lastSols).getCorrelations((Population)lastSols)) + "\n"); + } if (bestOfRunFeasibleIndy != null) { runBestFeasibleList.add(bestOfRunFeasibleIndy); // if (meanBestFeasibleFit==null) { @@ -666,8 +669,8 @@ public abstract class AbstractStatistics implements InterfaceTextListener, Inter case meanFit: ret[i] = (currentMeanFit==null) ? Double.NaN : currentMeanFit[defaultFitCriterion]; break; case currentWorst: ret[i] = (currentWorstFit==null) ? Double.NaN : currentWorstFit[defaultFitCriterion]; break; case runBest: ret[i] = bestOfRunIndy.getFitness()[defaultFitCriterion]; break; - case currentBestFeasible: ret[i] = currentBestFeasibleFit[defaultFitCriterion]; break; - case runBestFeasible: ret[i] = bestOfRunFeasibleIndy.getFitness()[defaultFitCriterion]; break; + case currentBestFeasible: ret[i] = (currentBestFeasibleFit==null) ? Double.NaN : currentBestFeasibleFit[defaultFitCriterion]; break; + case runBestFeasible: ret[i] = (bestOfRunFeasibleIndy==null) ? Double.NaN : bestOfRunFeasibleIndy.getFitness()[defaultFitCriterion]; break; case avgPopDistance: ret[i] = currentAvgPopDist; break; case maxPopDistance: ret[i] = currentMaxPopDist; break; } diff --git a/src/eva2/server/stat/StatisticsWithGUI.java b/src/eva2/server/stat/StatisticsWithGUI.java index c97e03a6..10081394 100644 --- a/src/eva2/server/stat/StatisticsWithGUI.java +++ b/src/eva2/server/stat/StatisticsWithGUI.java @@ -241,7 +241,10 @@ public class StatisticsWithGUI extends AbstractStatistics implements Serializabl if (lastIsShowFull) colIndex = 1+graphDesc.get(i).tail; // plot the column as indicated by the graph description if (currentStatDoubleData[colIndex]!=null) plotFitnessPoint(0, subGraph++, functionCalls, currentStatDoubleData[colIndex]); - else EVAERROR.errorMsgOnce("Error, data field " + graphDesc.get(i).head + " does not contain primitive data and cannot be plotted."); + else { + EVAERROR.errorMsgOnce("Error, data field " + graphDesc.get(i).head + " does not contain primitive data and cannot be plotted."); + subGraph++; // increase index anyways or the name assignment gets inconsistent + } } // } } diff --git a/src/eva2/tools/Serializer.java b/src/eva2/tools/Serializer.java index b29c5627..e1dfd8f3 100644 --- a/src/eva2/tools/Serializer.java +++ b/src/eva2/tools/Serializer.java @@ -12,6 +12,8 @@ package eva2.tools; /*==========================================================================* * IMPORTS *==========================================================================*/ +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; @@ -68,6 +70,35 @@ public class Serializer { return ret; } + /** + * Returns a copy of the object, or null if the object cannot + * be serialized. + */ + public static Object deepClone(Object orig) { + Object obj = null; + try { + // Write the object out to a byte array + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + ObjectOutputStream out = new ObjectOutputStream(bos); + out.writeObject(orig); + out.flush(); + out.close(); + + // Make an input stream from the byte array and read + // a copy of the object back in. + ObjectInputStream in = new ObjectInputStream( + new ByteArrayInputStream(bos.toByteArray())); + obj = in.readObject(); + } + catch(IOException e) { + e.printStackTrace(); + } + catch(ClassNotFoundException cnfe) { + cnfe.printStackTrace(); + } + return obj; + } + /** * Use object serialization to make a "deep clone" of the object o. @@ -77,35 +108,35 @@ public class Serializer { * usually implemented to produce a "shallow" clone that copies references * to other objects, instead of copying all referenced objects. **/ - static public Object deepclone(final Serializable o) throws IOException, ClassNotFoundException { - // Create a connected pair of "piped" streams. - // We'll write bytes to one, and them from the other one. - final PipedOutputStream pipeout = new PipedOutputStream(); - PipedInputStream pipein = new PipedInputStream(pipeout); - // Now define an independent thread to serialize the object and write - // its bytes to the PipedOutputStream - Thread writer = new Thread() { - public void run() { - ObjectOutputStream out = null; - try { - out = new ObjectOutputStream(pipeout); - out.writeObject(o); } - catch(IOException e) { - System.out.println("ERROR in Serialization1"+ e.getMessage()); - } - finally { - try { out.close(); } catch (Exception e) { - System.out.println("ERROR in Serialization2"+ e.getMessage()); - } - } - } - }; - writer.start(); - // Meanwhile, in this thread, read and deserialize from the piped - // input stream. The resulting object is a deep clone of the original. - ObjectInputStream in = new ObjectInputStream(pipein); - return in.readObject(); - } +// static public Object deepclone(final Serializable o) throws IOException, ClassNotFoundException { +// // Create a connected pair of "piped" streams. +// // We'll write bytes to one, and them from the other one. +// final PipedOutputStream pipeout = new PipedOutputStream(); +// PipedInputStream pipein = new PipedInputStream(pipeout); +// // Now define an independent thread to serialize the object and write +// // its bytes to the PipedOutputStream +// Thread writer = new Thread() { +// public void run() { +// ObjectOutputStream out = null; +// try { +// out = new ObjectOutputStream(pipeout); +// out.writeObject(o); } +// catch(IOException e) { +// System.out.println("ERROR in Serialization1"+ e.getMessage()); +// } +// finally { +// try { out.close(); } catch (Exception e) { +// System.out.println("ERROR in Serialization2"+ e.getMessage()); +// } +// } +// } +// }; +// writer.start(); +// // Meanwhile, in this thread, read and deserialize from the piped +// // input stream. The resulting object is a deep clone of the original. +// ObjectInputStream in = new ObjectInputStream(pipein); +// return in.readObject(); +// } /** * This is a simple serializable data structure that we use below for * testing the methods above @@ -123,8 +154,6 @@ public class Serializer { } } - /** This class defines a main() method for testing */ - public static class Test { public static void main(String[] args) throws IOException, ClassNotFoundException { // Create a simple object graph DataStructure ds = new DataStructure(); @@ -144,11 +173,11 @@ public class Serializer { System.out.println("Read from the file: " + ds); // Create a deep clone and display that. After making the copy // modify the original to prove that the clone is "deep". - DataStructure ds2 = (DataStructure) Serializer.deepclone(ds); + DataStructure ds2 = (DataStructure) Serializer.deepClone(ds); ds.other.message = null; ds.other.data = null; // Change original System.out.println("Deep clone: " + ds2); } - } + /** * Serialize the string s and * store its serialized state in File with name Filename. diff --git a/src/eva2/tools/math/Mathematics.java b/src/eva2/tools/math/Mathematics.java index 54366be3..d0f7549e 100644 --- a/src/eva2/tools/math/Mathematics.java +++ b/src/eva2/tools/math/Mathematics.java @@ -485,8 +485,8 @@ public class Mathematics { * @return the median */ public static double[] median(List dblArrList, boolean interpolate) { - java.util.Collections.sort(dblArrList, new DoubleArrayComparator()); - + java.util.Collections.sort(dblArrList, new DoubleArrayComparator()); // by default, the comparator uses pareto dominance + int len = dblArrList.size(); if (len % 2 != 0) return dblArrList.get((len-1) / 2); else { @@ -1081,6 +1081,21 @@ public class Mathematics { vvAddOffs(v1, 0, v2, 0, res, 0, v1.length); } + /** + * Calculate r=1/2 * sqrt(sum(sqr(upperBound_i - lowerBound_i))). + * + * @param range + * @return the average length of the range intervals + */ + public static double getAvgRangeL2(double[][] range) { + double sum = 0.; + for (int i=0; i