From 85732ec88d2472e4e1674bfa263329aaccf50a94 Mon Sep 17 00:00:00 2001 From: Marcel Kronfeld Date: Fri, 6 Aug 2010 11:17:56 +0000 Subject: [PATCH] Merging mk branch revs. 587:589 (tool tips for statistics data fields) --- src/eva2/gui/AbstractListSelectionEditor.java | 11 +++++ src/eva2/gui/StringSelectionEditor.java | 7 ++- .../problems/AbstractOptimizationProblem.java | 47 +++++++++++++++---- .../go/problems/AbstractProblemDouble.java | 19 ++++++-- ...InterfaceAdditionalPopulationInformer.java | 8 ++++ .../go/strategies/ClusterBasedNichingEA.java | 29 ++++++++++-- .../go/strategies/ClusteringHillClimbing.java | 8 +++- .../strategies/ParticleSwarmOptimization.java | 10 ++-- src/eva2/server/stat/GraphSelectionEnum.java | 21 ++++++++- src/eva2/server/stat/StatsParameter.java | 11 ++++- 10 files changed, 147 insertions(+), 24 deletions(-) diff --git a/src/eva2/gui/AbstractListSelectionEditor.java b/src/eva2/gui/AbstractListSelectionEditor.java index 115f3add..dd4c94d5 100644 --- a/src/eva2/gui/AbstractListSelectionEditor.java +++ b/src/eva2/gui/AbstractListSelectionEditor.java @@ -67,6 +67,16 @@ public abstract class AbstractListSelectionEditor extends JPanel implements Prop */ protected abstract String getElementName(int i); + /** + * Get the tool tip of an element or null if none is available. + * + * @param i + * @return + */ + protected String getElementToolTip(int i) { + return null; + } + /** * Get the selection state of an element. * @@ -85,6 +95,7 @@ public abstract class AbstractListSelectionEditor extends JPanel implements Prop this.m_BlackCheck = new JCheckBox[getElementCount()]; for (int i = 0; i < getElementCount(); i++) { this.m_BlackCheck[i] = new JCheckBox(getElementName(i), isElementSelected(i)); + this.m_BlackCheck[i].setToolTipText(getElementToolTip(i)); this.m_BlackCheck[i].addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ev) { if (actionOnSelect()) m_Support.firePropertyChange("AbstractListSelectionEditor", null, this); diff --git a/src/eva2/gui/StringSelectionEditor.java b/src/eva2/gui/StringSelectionEditor.java index 2399c20f..b13553f6 100644 --- a/src/eva2/gui/StringSelectionEditor.java +++ b/src/eva2/gui/StringSelectionEditor.java @@ -6,7 +6,7 @@ public class StringSelectionEditor extends AbstractListSelectionEditor { StringSelection strs; public StringSelectionEditor() { - strs = new StringSelection(new String[]{}); + strs = new StringSelection(new String[]{}, null); } @Override @@ -26,6 +26,11 @@ public class StringSelectionEditor extends AbstractListSelectionEditor { protected String getElementName(int i) { return strs.getElement(i); } + + @Override + protected String getElementToolTip(int i) { + return strs.getElementInfo(i); + } @Override public Object getValue() { diff --git a/src/eva2/server/go/problems/AbstractOptimizationProblem.java b/src/eva2/server/go/problems/AbstractOptimizationProblem.java index 588e6c14..d98b5b65 100644 --- a/src/eva2/server/go/problems/AbstractOptimizationProblem.java +++ b/src/eva2/server/go/problems/AbstractOptimizationProblem.java @@ -32,7 +32,6 @@ import eva2.server.go.operators.terminators.EvaluationTerminator; import eva2.server.go.operators.terminators.PhenotypeConvergenceTerminator; import eva2.server.go.populations.Population; import eva2.server.go.strategies.InterfaceOptimizer; -import eva2.tools.math.Mathematics; /** * Created by IntelliJ IDEA. @@ -243,7 +242,19 @@ implements InterfaceOptimizationProblem /*, InterfaceParamControllable*/, Serial if (this instanceof InterfaceInterestingHistogram) return new String[]{"Solution","Histogram","Score"}; else return new String[]{"Solution"}; } - + + /** This method returns the header for the additional data that is to be written into a file + * @param pop The population that is to be refined. + * @return String + */ + public String[] getAdditionalFileStringInfo(PopulationInterface pop) { + if (this instanceof InterfaceInterestingHistogram) + return new String[]{"Representation of the current best individual", + "Fitness histogram of the current population", + "Fitness threshold based score of the current population"}; + else return new String[]{"Representation of the current best individual"}; + } + /** This method returns the additional data that is to be written into a file * @param pop The population that is to be refined. * @return String @@ -251,8 +262,16 @@ implements InterfaceOptimizationProblem /*, InterfaceParamControllable*/, Serial public Object[] getAdditionalFileStringValue(PopulationInterface pop) { String solStr = AbstractEAIndividual.getDefaultDataString(pop.getBestIndividual()); if (this instanceof InterfaceInterestingHistogram) { + int fitCrit=0; SolutionHistogram hist = ((InterfaceInterestingHistogram)this).getHistogram(); - Population sols = PostProcess.clusterBestUpdateHistogram((Population)pop, this, hist, 0, getDefaultAccuracy()); + if (pop.getBestFitness()[fitCrit] < hist.getUpperBound()) { + Population maybeFiltered = (Population)pop; + if (pop.size()>100) { // for efficiency reasons... + maybeFiltered = maybeFiltered.filterByFitness(hist.getUpperBound(), fitCrit); +// System.out.println("Reduced " + pop.size() + " to " + maybeFiltered.size()); + } + Population sols = PostProcess.clusterBestUpdateHistogram((Population)maybeFiltered, this, hist, fitCrit, getDefaultAccuracy()); + } return new Object[]{solStr, hist, hist.getScore()}; } else return new Object[]{solStr}; } @@ -341,13 +360,15 @@ implements InterfaceOptimizationProblem /*, InterfaceParamControllable*/, Serial * @param epsilonPhenoSpace maximal allowed improvement of an individual before considered premature (given as distance in the search space) * @param epsilonFitConv if positive: additional absolute convergence criterion (fitness space) as termination criterion of the local search * @param clusterSigma minimum cluster distance - * @param maxEvalsPerIndy + * @param maxEvalsPerIndy maximum number of evaluations or -1 to take the maximum * @see #isPotentialOptimumNMS(AbstractEAIndividual, double, double, int) * @return */ - public static Population extractPotentialOptima(AbstractOptimizationProblem prob, Population pop, double epsilonPhenoSpace, double epsilonFitConv, double clusterSigma, int maxEvalsPerIndy) { + public static Population extractPotentialOptima(AbstractOptimizationProblem prob, Population pop, + double epsilonPhenoSpace, double epsilonFitConv, double clusterSigma, int maxEvalsPerIndy) { Population potOptima = new Population(); for (int i = 0; i < pop.size(); ++i){ + //System.out.println("Refining " + i + " of " + pop.size()); AbstractEAIndividual indy = pop.getEAIndividual(i); // System.out.println("bef: " + indy.toString()); boolean isConverged = AbstractOptimizationProblem.isPotentialOptimumNMS(prob, indy, epsilonPhenoSpace, epsilonFitConv, maxEvalsPerIndy); @@ -429,7 +450,8 @@ implements InterfaceOptimizationProblem /*, InterfaceParamControllable*/, Serial * distance from the original individual in phenotype space. The maxEvaluations parameter gives the maximum evaluations * for the local search. Using the epsilonFitConv parameter one may define a convergence criterion as PhenotypeConvergenceTerminator * which is combined (using OR) with the evaluation counter. - * If maxEvaluations is smaller than zero, 100*dim is used. Be aware that this may cost quite some runtime depending on the target + * If maxEvaluations is smaller than zero, a maximum of 500*dim evaluations is employed. + * Be aware that this may cost quite some runtime depending on the target * function. * A double value for the distance by which it was moved is added to the individual using the key PostProcess.movedDistanceKey. * @@ -452,7 +474,7 @@ implements InterfaceOptimizationProblem /*, InterfaceParamControllable*/, Serial // initPerturb = epsilonPhenoSpace/(2*(Mathematics.getAvgRange(((InterfaceDataTypeDouble)orig).getDoubleRange()))); initRelPerturb = epsilonPhenoSpace*0.5; dim=((InterfaceDataTypeDouble)orig).getDoubleRange().length; - if (maxEvaluations<0) maxEvaluations = 100*AbstractEAIndividual.getDoublePositionShallow(prob.m_Template).length; // scales the effort with the number of problem dimensions + if (maxEvaluations<0) maxEvaluations = 500*AbstractEAIndividual.getDoublePositionShallow(prob.m_Template).length; // scales the effort with the number of problem dimensions } else { System.err.println("Cannot initialize NMS on non-double valued individuals!"); return false; @@ -461,9 +483,10 @@ 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, 10*dim, true, true), term, false); + if (epsilonFitConv > 0) term = new CombinedTerminator(new PhenotypeConvergenceTerminator(epsilonFitConv, 100*dim, true, 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); // System.out.println("aft: " + pop.getBestEAIndividual().toString() + ", evals performed: " + evalsPerf + ", opt moved by " + overallDist); // System.out.println("terminated because: " + term.lastTerminationMessage()); orig.putData(PostProcess.movedDistanceKey, overallDist); @@ -471,6 +494,14 @@ implements InterfaceOptimizationProblem /*, InterfaceParamControllable*/, Serial // if (overallDist==0) { // PostProcess.processSingleCandidatesNMCMA(PostProcessMethod.nelderMead, pop, term, initPerturb, this); // } + +// System.out.println("Checked "+ indy.getStringRepresentation()); +// String msg = "----discarding "; +// if (overallDist <= epsilonPhenoSpace) msg= "++++keeping "; +// System.out.println(msg + BeanInspector.toString(indy.getDoublePosition())); +// System.out.println("which moved to " + BeanInspector.toString(pop.getBestEAIndividual().getDoublePosition())); +// System.out.println(" by " + overallDist + " > " + epsilonPhenoSpace); + return (overallDist < epsilonPhenoSpace); } diff --git a/src/eva2/server/go/problems/AbstractProblemDouble.java b/src/eva2/server/go/problems/AbstractProblemDouble.java index 7a1c07da..ce896b84 100644 --- a/src/eva2/server/go/problems/AbstractProblemDouble.java +++ b/src/eva2/server/go/problems/AbstractProblemDouble.java @@ -255,7 +255,8 @@ public abstract class AbstractProblemDouble extends AbstractOptimizationProblem // rotation = new Matrix(dim, dim); // rotation = Mathematics.getRotationMatrix(vec).transpose(); rotation = Mathematics.getRotationMatrix((rotAngle*Math.PI/180.), dim).transpose(); - // System.out.println(BeanInspector.toString(eval(vec.getColumnPackedCopy()))); + //double[] t= new double[dim]; Arrays.fill(t, 1.); + //System.out.println(BeanInspector.toString(rotation.times(t))); return rotation; } @@ -354,7 +355,9 @@ public abstract class AbstractProblemDouble extends AbstractOptimizationProblem } public double functionValue(double[] point) { - return eval(project2DPoint(point))[0]; + double[] x=project2DPoint(point); + double v = eval(x)[0]; + return v; } /** @@ -497,7 +500,17 @@ public abstract class AbstractProblemDouble extends AbstractOptimizationProblem if (isWithConstraints()) return ToolBox.appendArrays(superHeader, new String[]{"rawFit","numViol","sumViol"}); else return superHeader; } - + + @Override + public String[] getAdditionalFileStringInfo(PopulationInterface pop) { + String[] superInfo = super.getAdditionalFileStringInfo(pop); + if (isWithConstraints()) + return ToolBox.appendArrays(superInfo, new String[]{"Raw fitness (unpenalized) of the current best individual", + "The number of constraints violated by the current best individual", + "The sum of constraint violations of the current best individual"}); + else return superInfo; + } + @Override public Object[] getAdditionalFileStringValue(PopulationInterface pop) { Object[] superVal = super.getAdditionalFileStringValue(pop); diff --git a/src/eva2/server/go/problems/InterfaceAdditionalPopulationInformer.java b/src/eva2/server/go/problems/InterfaceAdditionalPopulationInformer.java index 54476b7c..0900c411 100644 --- a/src/eva2/server/go/problems/InterfaceAdditionalPopulationInformer.java +++ b/src/eva2/server/go/problems/InterfaceAdditionalPopulationInformer.java @@ -19,6 +19,14 @@ public interface InterfaceAdditionalPopulationInformer { */ public String[] getAdditionalFileStringHeader(PopulationInterface pop); + /** + * Optionally return informative descriptions of the data fields. + * + * @param pop + * @return + */ + public String[] getAdditionalFileStringInfo(PopulationInterface pop); + /** * This method returns additional statistical data. * @param pop The population that is to be refined. diff --git a/src/eva2/server/go/strategies/ClusterBasedNichingEA.java b/src/eva2/server/go/strategies/ClusterBasedNichingEA.java index e5a63e34..a6073720 100644 --- a/src/eva2/server/go/strategies/ClusterBasedNichingEA.java +++ b/src/eva2/server/go/strategies/ClusterBasedNichingEA.java @@ -1143,19 +1143,40 @@ public class ClusterBasedNichingEA implements InterfacePopulationChangedEventLis } public String[] getAdditionalFileStringHeader(PopulationInterface pop) { - return new String[]{"Undiff.","#Act.spec.","Avg.Spec.Meas.","#Archived."}; + return new String[]{"numUndiff","numActSpec","avgSpecMeas","numArchived", + "archivedMedCorr", "archivedMeanDist" +// , "numCollisions", "clustSig" + }; } - + + public String[] getAdditionalFileStringInfo(PopulationInterface pop) { // TODO use these as Tool Tip Texts??? + return new String[] { + "The number of exploring individuals in the main population", + "The number of active species (sub-populations)", + "The average of the mean distance of individuals within a species", + "The number of stored potential local optima", + "The median correlation of archived solutions", + "The mean distance of archived solutions", +// "The number of collisions events that happened so far", +// "The clustering distance" + }; + } + public Object[] getAdditionalFileStringValue(PopulationInterface pop) { // int actives = countActiveSpec(); return new Object[] { m_Undifferentiated.size(), m_Species.size(), getAvgSpeciesMeasures()[0], - m_Archive.size()}; + m_Archive.size(), + m_Archive.getCorrelations()[3], + m_Archive.getPopulationMeasures()[0], +// collisions, +// getClusterDiffDist() + }; // return m_Undifferentiated.size() + " \t " + m_Species.size() + " \t " + BeanInspector.toString(getAvgSpeciesMeasures()[0]) + " \t " + (m_Archive.size()); } - + /** * Calculate average of Population measures (mean, minimal and maximal distance within a species) * @return average population measures diff --git a/src/eva2/server/go/strategies/ClusteringHillClimbing.java b/src/eva2/server/go/strategies/ClusteringHillClimbing.java index 5a87b84c..9df27eec 100644 --- a/src/eva2/server/go/strategies/ClusteringHillClimbing.java +++ b/src/eva2/server/go/strategies/ClusteringHillClimbing.java @@ -419,9 +419,13 @@ public class ClusteringHillClimbing implements InterfacePopulationChangedEventLi } public String[] getAdditionalFileStringHeader(PopulationInterface pop) { - return new String[]{"#Indies"}; + return new String[]{"numIndies"}; } - + + public String[] getAdditionalFileStringInfo(PopulationInterface pop) { + return new String[]{"The current population size"}; + } + public Object[] getAdditionalFileStringValue(PopulationInterface pop) { return new Object[]{m_Population.size()}; } diff --git a/src/eva2/server/go/strategies/ParticleSwarmOptimization.java b/src/eva2/server/go/strategies/ParticleSwarmOptimization.java index f6aca4a5..0469166f 100644 --- a/src/eva2/server/go/strategies/ParticleSwarmOptimization.java +++ b/src/eva2/server/go/strategies/ParticleSwarmOptimization.java @@ -2060,10 +2060,14 @@ public class ParticleSwarmOptimization implements InterfaceOptimizer, java.io.Se // public void setDoLocalSearch(boolean doLocalSearch) { // this.doLocalSearch = doLocalSearch; // } - public String[] getAdditionalFileStringHeader(PopulationInterface pop) { - if (emaPeriods > 0) return new String[]{"MeanCurSpeed","MeanEMASpeed"}; - else return new String[]{"MeanCurSpeed"}; + if (emaPeriods > 0) return new String[]{"meanEMASpeed", "meanCurSpeed"}; + else return new String[]{"meanCurSpeed"}; + } + + public String[] getAdditionalFileStringInfo(PopulationInterface pop) { + if (emaPeriods > 0) return new String[]{"Exponential moving average of the (range-relative) speed of all particles", "The mean (range-relative) current speed of all particles"}; + else return new String[]{"The mean (range-relative) current speed of all particles"}; } public Object[] getAdditionalFileStringValue(PopulationInterface pop) { diff --git a/src/eva2/server/stat/GraphSelectionEnum.java b/src/eva2/server/stat/GraphSelectionEnum.java index a7182379..d279a1aa 100644 --- a/src/eva2/server/stat/GraphSelectionEnum.java +++ b/src/eva2/server/stat/GraphSelectionEnum.java @@ -11,7 +11,26 @@ import eva2.tools.StringSelection; */ public enum GraphSelectionEnum { // DONT change this order, or the relation to AbstractStatistics will be lost - currentBest, meanFit, currentWorst, runBest, currentBestFeasible, runBestFeasible, avgPopDistance, maxPopDistance; + currentBest, meanFit, currentWorst, runBest, currentBestFeasible, runBestFeasible, + avgPopDistance, maxPopDistance; + + private static String[] toolTips = { + "The current best fitness within the population", + "The mean fitness within the population", + "The current worst fitness within the population", + "The best fitness up to the current generation", + "The best feasible fitness within the population", + "The best feasible fitness up to the current generation", + "The average phenotypic distance of individuals in the population", + "The maximum phenotypic distance of individuals in the population" + }; + + public static String[] getInfoStrings() { + if (GraphSelectionEnum.values().length != toolTips.length) { + System.err.println("Error, mismatching length of info strings in GraphSelectionEnum"); + return null; + } else return toolTips; + } // public static boolean doPlotCurrentBest(StringSelection sel) { // return sel.isSelected(GraphSelectionEnum.currentBest.ordinal()); diff --git a/src/eva2/server/stat/StatsParameter.java b/src/eva2/server/stat/StatsParameter.java index 3aed16f3..0f1f7c8c 100644 --- a/src/eva2/server/stat/StatsParameter.java +++ b/src/eva2/server/stat/StatsParameter.java @@ -52,7 +52,7 @@ public class StatsParameter implements InterfaceStatisticsParameter, InterfaceNo private boolean showAdditionalProblemInfo = false; private double m_ConvergenceRateThreshold=0.001; - private StringSelection graphSel = new StringSelection(GraphSelectionEnum.currentBest); + private StringSelection graphSel = new StringSelection(GraphSelectionEnum.currentBest, GraphSelectionEnum.getInfoStrings()); /** * @@ -381,14 +381,21 @@ public class StatsParameter implements InterfaceStatisticsParameter, InterfaceNo public void setInformers( List informers) { ArrayList headerFields = new ArrayList(); + ArrayList infoFields = new ArrayList(); // parse list of header elements, show additional Strings according to names. for (InterfaceAdditionalPopulationInformer inf : informers) { headerFields.addAll(Arrays.asList(inf.getAdditionalFileStringHeader(null))); + if (infoFields.size()