From 232113e061b12c0327373d0cf03d69ab78e5313b Mon Sep 17 00:00:00 2001 From: Marcel Kronfeld Date: Wed, 19 Mar 2008 14:00:16 +0000 Subject: [PATCH] Some updates to OptimizerFactory, PostProcess. Minor clean-up in benchmarks. --- src/javaeva/OptimizerFactory.java | 245 +++++++++++++- src/javaeva/OptimizerRunnable.java | 62 +++- .../go/individuals/AbstractEAIndividual.java | 19 +- .../cluster/ClusteringDensityBased.java | 9 + .../go/operators/mutation/MutateESGlobal.java | 14 +- .../go/operators/postprocess/PostProcess.java | 77 +++-- .../postprocess/PostProcessParams.java | 9 +- .../terminators/CombinedTerminator.java | 4 +- .../FitnessConvergenceTerminator.java | 4 +- .../terminators/FitnessValueTerminator.java | 4 +- .../terminators/GenerationTerminator.java | 8 +- .../PhenotypeConvergenceTerminator.java | 2 +- .../server/go/populations/Population.java | 18 +- .../AbstractMultiModalProblemKnown.java | 306 ++++++++++++++++++ .../problems/AbstractOptimizationProblem.java | 12 + .../go/problems/AbstractProblemBinary.java | 25 +- .../go/problems/AbstractProblemDouble.java | 124 +++++-- src/javaeva/server/go/problems/B1Problem.java | 6 +- .../server/go/problems/F10Problem.java | 2 +- .../server/go/problems/F11Problem.java | 6 +- .../server/go/problems/F12Problem.java | 2 +- .../server/go/problems/F13Problem.java | 2 +- src/javaeva/server/go/problems/F1Problem.java | 32 +- src/javaeva/server/go/problems/F2Problem.java | 2 +- src/javaeva/server/go/problems/F3Problem.java | 2 +- src/javaeva/server/go/problems/F4Problem.java | 2 +- src/javaeva/server/go/problems/F5Problem.java | 2 +- src/javaeva/server/go/problems/F6Problem.java | 2 +- src/javaeva/server/go/problems/F7Problem.java | 4 +- src/javaeva/server/go/problems/F8Problem.java | 2 +- src/javaeva/server/go/problems/F9Problem.java | 2 +- .../server/go/problems/FM0Problem.java | 275 +--------------- .../go/strategies/ClusterBasedNichingEA.java | 22 +- .../go/strategies/ClusteringHillClimbing.java | 97 ++++-- .../go/strategies/EvolutionStrategies.java | 26 +- .../go/strategies/tribes/TribesSwarm.java | 1 + .../server/modules/AbstractGOParameters.java | 2 +- src/javaeva/server/modules/Processor.java | 66 ++-- .../server/stat/AbstractStatistics.java | 9 +- 39 files changed, 1010 insertions(+), 498 deletions(-) create mode 100644 src/javaeva/server/go/problems/AbstractMultiModalProblemKnown.java diff --git a/src/javaeva/OptimizerFactory.java b/src/javaeva/OptimizerFactory.java index 7ce14ab6..48b8de41 100644 --- a/src/javaeva/OptimizerFactory.java +++ b/src/javaeva/OptimizerFactory.java @@ -1,19 +1,28 @@ package javaeva; +import java.util.BitSet; +import java.util.Vector; + import javaeva.gui.BeanInspector; import javaeva.server.go.IndividualInterface; import javaeva.server.go.InterfaceTerminator; import javaeva.server.go.individuals.AbstractEAIndividual; +import javaeva.server.go.individuals.InterfaceDataTypeBinary; +import javaeva.server.go.individuals.InterfaceDataTypeDouble; import javaeva.server.go.individuals.InterfaceESIndividual; import javaeva.server.go.operators.cluster.ClusteringDensityBased; import javaeva.server.go.operators.crossover.CrossoverESDefault; import javaeva.server.go.operators.mutation.MutateESCovarianceMartixAdaption; import javaeva.server.go.operators.mutation.MutateESGlobal; +import javaeva.server.go.operators.postprocess.InterfacePostProcessParams; +import javaeva.server.go.operators.postprocess.PostProcessParams; import javaeva.server.go.operators.terminators.CombinedTerminator; import javaeva.server.go.operators.terminators.EvaluationTerminator; +import javaeva.server.go.operators.terminators.FitnessConvergenceTerminator; import javaeva.server.go.populations.Population; import javaeva.server.go.problems.AbstractOptimizationProblem; import javaeva.server.go.strategies.ClusterBasedNichingEA; +import javaeva.server.go.strategies.ClusteringHillClimbing; import javaeva.server.go.strategies.DifferentialEvolution; import javaeva.server.go.strategies.EvolutionStrategies; import javaeva.server.go.strategies.GeneticAlgorithm; @@ -43,17 +52,21 @@ public class OptimizerFactory { public final static int RANDOM = 7; public final static int HILLCL = 8; public final static int CBN_ES = 9; + public final static int CL_HILLCL = 10; public final static int defaultFitCalls = 10000; public final static int randSeed = 0; + private static OptimizerRunnable lastRunnable = null; + /** * Return a simple String showing the accessible optimizers. For external access." * * @return a String listing the accessible optimizers */ public static String showOptimizers() { - return "1: Standard ES; 2: CMA-ES; 3: GA; 4: PSO; 5: DE; 6: Tribes; 7: Random (Monte Carlo); 8: HillClimbing; 9: Cluster-based niching ES"; + return "1: Standard ES \n2: CMA-ES \n3: GA \n4: PSO \n5: DE \n6: Tribes \n7: Random (Monte Carlo) " + + "\n8: Hill-Climbing \n9: Cluster-based niching ES \n10: Clustering Hill-Climbing"; } /** @@ -81,14 +94,195 @@ public class OptimizerFactory { } // TODO hier weiter kommentieren - public static IndividualInterface optimize(final int optType, AbstractOptimizationProblem problem, String outputFilePrefix) { - OptimizerRunnable runnable = getOptRunnable(optType, problem, outputFilePrefix); + public static OptimizerRunnable optimize(final int optType, AbstractOptimizationProblem problem, String outputFilePrefix) { + return optimize(getOptRunnable(optType, problem, outputFilePrefix)); + } + + public static OptimizerRunnable optimize(OptimizerRunnable runnable) { if (runnable != null) { new Thread(runnable).run(); - return runnable.getSolution(); + lastRunnable = runnable; + return runnable; } else return null; } + public static String terminatedBecause() { + if (lastRunnable != null) return lastRunnable.terminatedBecause(); + else return null; + } + + public static int lastEvalsPerformed() { + if (lastRunnable != null) return lastRunnable.getProgress(); + else return -1; + } + +/////////////////////////////// Optimize a given parameter instance + public static BitSet optimizeToBinary(GOParameters params, String outputFilePrefix) { + OptimizerRunnable runnable = optimize(new OptimizerRunnable(params, outputFilePrefix)); + return runnable.getBinarySolution(); + } + + public static double[] optimizeToDouble(GOParameters params, String outputFilePrefix) { + OptimizerRunnable runnable = optimize(new OptimizerRunnable(params, outputFilePrefix)); + return runnable.getDoubleSolution(); + } + + public static IndividualInterface optimizeToInd(GOParameters params, String outputFilePrefix) { + OptimizerRunnable runnable = optimize(new OptimizerRunnable(params, outputFilePrefix)); + return runnable.getResult(); + } + + public static Population optimizeToPop(GOParameters params, String outputFilePrefix) { + OptimizerRunnable runnable = optimize(new OptimizerRunnable(params, outputFilePrefix)); + return runnable.getSolutionSet(); + } + +/////////////////////////////// Optimize a given runnable + public static BitSet optimizeToBinary(OptimizerRunnable runnable) { + optimize(runnable); + if (runnable != null) return runnable.getBinarySolution(); + else return null; + } + + public static double[] optimizeToDouble(OptimizerRunnable runnable) { + optimize(runnable); + if (runnable != null) return runnable.getDoubleSolution(); + else return null; + } + + public static IndividualInterface optimizeToInd(OptimizerRunnable runnable) { + optimize(runnable); + if (runnable != null) return runnable.getResult(); + else return null; + } + + public static Population optimizeToPop(OptimizerRunnable runnable) { + optimize(runnable); + if (runnable != null) return runnable.getSolutionSet(); + else return null; + } + +/////////////////////////////// Optimize using a default strategy + public static BitSet optimizeToBinary(final int optType, AbstractOptimizationProblem problem, String outputFilePrefix) { + OptimizerRunnable runnable = optimize(optType, problem, outputFilePrefix); + if (runnable != null) return runnable.getBinarySolution(); + else return null; + } + + public static double[] optimizeToDouble(final int optType, AbstractOptimizationProblem problem, String outputFilePrefix) { + OptimizerRunnable runnable = optimize(optType, problem, outputFilePrefix); + if (runnable != null) return runnable.getDoubleSolution(); + else return null; + } + + public static IndividualInterface optimizeToInd(final int optType, AbstractOptimizationProblem problem, String outputFilePrefix) { + OptimizerRunnable runnable = optimize(optType, problem, outputFilePrefix); + if (runnable != null) return runnable.getResult(); + else return null; + } + + public static Population optimizeToPop(final int optType, AbstractOptimizationProblem problem, String outputFilePrefix) { + OptimizerRunnable runnable = optimize(optType, problem, outputFilePrefix); + if (runnable != null) return runnable.getSolutionSet(); + else return null; + } + +///////////////////////////// post processing + public static Vector postProcessIndVec(OptimizerRunnable runnable, int steps, double sigma, int nBest) { + return postProcessIndVec(runnable, new PostProcessParams(steps, sigma, nBest)); + } + + public static Vector postProcessIndVec(int steps, double sigma, int nBest) { + return (lastRunnable != null) ? postProcessIndVec(lastRunnable, new PostProcessParams(steps, sigma, nBest)) : null; + } + + public static Vector postProcessIndVec(InterfacePostProcessParams ppp) { + return (lastRunnable != null) ? postProcessIndVec(lastRunnable, ppp) : null; + } + + public static Vector postProcessIndVec(OptimizerRunnable runnable, InterfacePostProcessParams ppp) { + Population resPop = postProcess(runnable, ppp); + Vector ret = new Vector(resPop.size()); + for (Object o : resPop) { + if (o instanceof AbstractEAIndividual) { + AbstractEAIndividual indy = (AbstractEAIndividual)o; + ret.add(indy); + } + } + return ret; + } + + public static Vector postProcessBinVec(InterfacePostProcessParams ppp) { + return (lastRunnable != null) ? postProcessBinVec(lastRunnable, ppp) : null; + } + + public static Vector postProcessBinVec(OptimizerRunnable runnable, InterfacePostProcessParams ppp) { + Population resPop = postProcess(runnable, ppp); + Vector ret = new Vector(resPop.size()); + for (Object o : resPop) { + if (o instanceof InterfaceDataTypeBinary) { + InterfaceDataTypeBinary indy = (InterfaceDataTypeBinary)o; + ret.add(indy.getBinaryData()); + } + } + return ret; + } + + public static Vector postProcessBinVec(int steps, double sigma, int nBest) { + return (lastRunnable != null) ? postProcessBinVec(lastRunnable, new PostProcessParams(steps, sigma, nBest)) : null; + } + + public static Vector postProcessBinVec(OptimizerRunnable runnable, int steps, double sigma, int nBest) { + return postProcessBinVec(runnable, new PostProcessParams(steps, sigma, nBest)); + } + + public static Vector postProcessDblVec(InterfacePostProcessParams ppp) { + if (lastRunnable != null) return postProcessDblVec(lastRunnable, ppp); + else return null; + } + + public static Vector postProcessDblVec(OptimizerRunnable runnable, InterfacePostProcessParams ppp) { + Population resPop = postProcess(runnable, ppp); + Vector ret = new Vector(resPop.size()); + for (Object o : resPop) { + if (o instanceof InterfaceDataTypeDouble) { + InterfaceDataTypeDouble indy = (InterfaceDataTypeDouble)o; + ret.add(indy.getDoubleData()); + } + } + return ret; + } + + public static Vector postProcessDblVec(int steps, double sigma, int nBest) { + return (lastRunnable == null) ? null : postProcessDblVec(lastRunnable, new PostProcessParams(steps, sigma, nBest)); + } + + public static Vector postProcessDblVec(OptimizerRunnable runnable, int steps, double sigma, int nBest) { + return postProcessDblVec(runnable, new PostProcessParams(steps, sigma, nBest)); + } + + public static Population postProcess(int steps, double sigma, int nBest) { + return (lastRunnable == null) ? null : postProcess(lastRunnable, new PostProcessParams(steps, sigma, nBest)); + } + + public static Population postProcess(OptimizerRunnable runnable, int steps, double sigma, int nBest) { + PostProcessParams ppp = new PostProcessParams(steps, sigma, nBest); + return postProcess(runnable, ppp); + } + + public static Population postProcess(InterfacePostProcessParams ppp) { + return (lastRunnable == null) ? null : postProcess(lastRunnable, ppp); + } + + public static Population postProcess(OptimizerRunnable runnable, InterfacePostProcessParams ppp) { + runnable.setDoRestart(true); + runnable.setDoPostProcessOnly(true); + runnable.setPostProcessingParams(ppp); + runnable.run(); // this run will not set the lastRunnable - postProcessing starts always anew + return runnable.getSolutionSet(); + } + +///////////////////////////// constructing a default OptimizerRunnable public static OptimizerRunnable getOptRunnable(final int optType, AbstractOptimizationProblem problem, String outputFilePrefix) { return getOptRunnable(optType, problem, defaultFitCalls, outputFilePrefix); } @@ -123,6 +317,9 @@ public class OptimizerFactory { case CBN_ES: opt = new OptimizerRunnable(cbnES(problem), outputFilePrefix); break; + case CL_HILLCL: + opt = new OptimizerRunnable(clusteringHillClimbing(problem), outputFilePrefix); + break; default: System.err.println("Error: optimizer type " + optType + " is unknown!"); return null; @@ -131,10 +328,19 @@ public class OptimizerFactory { return opt; } +///////////////////////////// Termination criteria public static InterfaceTerminator defaultTerminator() { if (term == null) term = new EvaluationTerminator(defaultFitCalls); return term; } + + public static void setEvaluationTerminator(int maxEvals) { + setTerminator(new EvaluationTerminator(maxEvals)); + } + + public static void setFitnessConvergenceTerminator(double fitThresh) { + setTerminator(new FitnessConvergenceTerminator(fitThresh, 100, true, true)); + } public static void setTerminator(InterfaceTerminator term) { OptimizerFactory.term = term; @@ -156,6 +362,7 @@ public class OptimizerFactory { else setTerminator(new CombinedTerminator(OptimizerFactory.term, newTerm, bAnd)); } +///////////////////////// Creating default strategies public static GOParameters makeParams(InterfaceOptimizer opt, Population pop, AbstractOptimizationProblem problem, long seed, InterfaceTerminator term) { GOParameters params = new GOParameters(); params.setProblem(problem); @@ -169,14 +376,14 @@ public class OptimizerFactory { public static GOParameters standardES(AbstractOptimizationProblem problem) { EvolutionStrategies es = new EvolutionStrategies(); - es.setMyu(15); + es.setMu(15); es.setLambda(50); es.setPlusStrategy(false); - Object maybeTemplate = BeanInspector.callIfAvailable(problem, "getEAIndividual", null); - if ((maybeTemplate != null) && (maybeTemplate instanceof InterfaceESIndividual)) { + AbstractEAIndividual indy = problem.getIndividualTemplate(); + + if ((indy != null) && (indy instanceof InterfaceESIndividual)) { // Set CMA operator for mutation - AbstractEAIndividual indy = (AbstractEAIndividual)maybeTemplate; indy.setMutationOperator(new MutateESGlobal()); indy.setCrossoverOperator(new CrossoverESDefault()); } else { @@ -192,7 +399,7 @@ public class OptimizerFactory { public static GOParameters cmaES(AbstractOptimizationProblem problem) { EvolutionStrategies es = new EvolutionStrategies(); - es.setMyu(15); + es.setMu(15); es.setLambda(50); es.setPlusStrategy(false); @@ -278,14 +485,14 @@ public class OptimizerFactory { public static GOParameters cbnES(AbstractOptimizationProblem problem) { ClusterBasedNichingEA cbn = new ClusterBasedNichingEA(); EvolutionStrategies es = new EvolutionStrategies(); - es.setMyu(15); + es.setMu(15); es.setLambda(50); es.setPlusStrategy(false); cbn.setOptimizer(es); ClusteringDensityBased clustering = new ClusteringDensityBased(0.1); cbn.setConvergenceCA((ClusteringDensityBased)clustering.clone()); cbn.setDifferentationCA(clustering); - cbn.setShowCycle(10); // dont do graphical output + cbn.setShowCycle(0); // dont do graphical output Population pop = new Population(); pop.setPopulationSize(100); @@ -293,4 +500,20 @@ public class OptimizerFactory { return makeParams(cbn, pop, problem, randSeed, defaultTerminator()); } + + public static GOParameters clusteringHillClimbing(AbstractOptimizationProblem problem) { + ClusteringHillClimbing chc = new ClusteringHillClimbing(); + chc.SetProblem(problem); + Population pop = new Population(); + pop.setPopulationSize(100); + problem.initPopulation(pop); + chc.setHcEvalCycle(1000); + chc.setInitialPopSize(100); + chc.setStepSizeInitial(0.05); + chc.setMinImprovement(0.000001); + chc.setNotifyGuiEvery(0); + chc.setStepSizeThreshold(0.000001); + chc.setSigmaClust(0.05); + return makeParams(chc, pop, problem, randSeed, defaultTerminator()); + } } diff --git a/src/javaeva/OptimizerRunnable.java b/src/javaeva/OptimizerRunnable.java index e50b6b69..d93dd3fe 100644 --- a/src/javaeva/OptimizerRunnable.java +++ b/src/javaeva/OptimizerRunnable.java @@ -4,16 +4,18 @@ import java.io.PrintWriter; import java.io.StringWriter; import java.util.BitSet; -import javaeva.gui.BeanInspector; import javaeva.server.go.IndividualInterface; -import javaeva.server.go.InterfaceTerminator; import javaeva.server.go.InterfaceGOParameters; +import javaeva.server.go.InterfaceTerminator; import javaeva.server.go.individuals.InterfaceDataTypeBinary; import javaeva.server.go.individuals.InterfaceDataTypeDouble; import javaeva.server.go.individuals.InterfaceDataTypeInteger; -import javaeva.server.go.operators.terminators.CombinedTerminator; +import javaeva.server.go.operators.postprocess.InterfacePostProcessParams; +import javaeva.server.go.operators.postprocess.PostProcessParams; +import javaeva.server.go.populations.Population; import javaeva.server.modules.GOParameters; import javaeva.server.modules.Processor; +import javaeva.server.stat.InterfaceTextListener; import javaeva.server.stat.StatisticsStandalone; /** @@ -26,6 +28,8 @@ public class OptimizerRunnable implements Runnable { Processor proc; boolean isFinished = false; boolean doRestart = false; // indicate whether start or restart should be done --> whether pop will be reinitialized. + boolean postProcessOnly = false; + InterfaceTextListener listener = null; public OptimizerRunnable(GOParameters params, String outputFilePrefix) { this(params, outputFilePrefix, false); @@ -40,13 +44,25 @@ public class OptimizerRunnable implements Runnable { return proc.getGOParams(); } + public void setTextListener(InterfaceTextListener lsnr) { + this.listener = lsnr; + } + + public void setDoRestart(boolean restart) { + doRestart = restart; + } + public void run() { isFinished = false; try { proc.setSaveParams(false); - if (doRestart) proc.restartOpt(); - else proc.startOpt(); - proc.runOptOnce(); + if (postProcessOnly) { + proc.performNewPostProcessing((PostProcessParams)proc.getGOParams().getPostProcessParams(), listener); + } else { + if (doRestart) proc.restartOpt(); + else proc.startOpt(); + proc.runOptOnce(); + } } catch(Exception e) { proc.getStatistics().printToTextListener("Exception in OptimizeThread::run: " + e.getMessage() + "\n"); StringWriter sw = new StringWriter(); @@ -59,45 +75,65 @@ public class OptimizerRunnable implements Runnable { } } + public void setDoPostProcessOnly(boolean poPO) { + postProcessOnly = poPO; + } + public boolean isFinished() { return isFinished; } + public void restartOpt() { + proc.restartOpt(); + } + public void stopOpt() { proc.stopOpt(); } - public IndividualInterface getSolution() { + public IndividualInterface getResult() { return proc.getStatistics().getBestSolution(); } - + + public Population getSolutionSet() { + return proc.getResultPopulation(); + } + + public void setPostProcessingParams(InterfacePostProcessParams ppp) { + proc.getGOParams().setPostProcessParams(ppp); + } + public int getProgress() { return proc.getGOParams().getOptimizer().getPopulation().getFunctionCalls(); } public String terminatedBecause() { if (isFinished) { - InterfaceTerminator term = proc.getGOParams().getTerminator(); - return term.terminatedBecause(proc.getGOParams().getOptimizer().getPopulation()); + if (postProcessOnly) { + return "Post processing finished"; + } else { + InterfaceTerminator term = proc.getGOParams().getTerminator(); + return term.terminatedBecause(proc.getGOParams().getOptimizer().getPopulation()); + } } else return "Not yet terminated"; } public double[] getDoubleSolution() { - IndividualInterface indy = getSolution(); + IndividualInterface indy = getResult(); if (indy instanceof InterfaceDataTypeDouble) { return ((InterfaceDataTypeDouble)indy).getDoubleData(); } else return null; } public BitSet getBinarySolution() { - IndividualInterface indy = getSolution(); + IndividualInterface indy = getResult(); if (indy instanceof InterfaceDataTypeBinary) { return ((InterfaceDataTypeBinary)indy).getBinaryData(); } else return null; } public int[] getIntegerSolution() { - IndividualInterface indy = getSolution(); + IndividualInterface indy = getResult(); if (indy instanceof InterfaceDataTypeInteger) { return ((InterfaceDataTypeInteger)indy).getIntegerData(); } else return null; diff --git a/src/javaeva/server/go/individuals/AbstractEAIndividual.java b/src/javaeva/server/go/individuals/AbstractEAIndividual.java index 88de753f..1b236317 100644 --- a/src/javaeva/server/go/individuals/AbstractEAIndividual.java +++ b/src/javaeva/server/go/individuals/AbstractEAIndividual.java @@ -658,6 +658,17 @@ public abstract class AbstractEAIndividual implements IndividualInterface, java. * @return */ public static String getDefaultDataString(IndividualInterface individual) { + return getDefaultDataString(individual, "; "); + } + + /** + * This method creates a default String representation for a number Individual interfaces + * containing the genotype. + * + * @param individual + * @return + */ + public static String getDefaultDataString(IndividualInterface individual, String separator) { StringBuffer sb = new StringBuffer(""); char left = '['; char right = ']'; @@ -672,25 +683,25 @@ public abstract class AbstractEAIndividual implements IndividualInterface, java. int[] b = ((InterfaceDataTypeInteger)individual).getIntegerData(); for (int i = 0; i < b.length; i++) { sb.append(b[i]); - if ((i+1) < b.length) sb.append("; "); + 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("; "); + if ((i+1) < b.length) sb.append(separator); } } else if (individual instanceof InterfaceDataTypePermutation) { int[] b = ((InterfaceDataTypePermutation)individual).getPermutationData()[0]; for (int i = 0; i < b.length; i++) { sb.append(b[i]); - if ((i+1) < b.length) sb.append("; "); + if ((i+1) < b.length) sb.append(separator); } } else if (individual instanceof InterfaceDataTypeProgram) { InterfaceProgram[] b = ((InterfaceDataTypeProgram)individual).getProgramData(); for (int i = 0; i < b.length; i++) { sb.append(b[i].getStringRepresentation()); - if ((i+1) < b.length) sb.append("; "); + if ((i+1) < b.length) sb.append(separator); } } else { System.err.println("error in AbstractEAIndividual::getDefaultDataString: type " + individual.getClass() + " not implemented"); diff --git a/src/javaeva/server/go/operators/cluster/ClusteringDensityBased.java b/src/javaeva/server/go/operators/cluster/ClusteringDensityBased.java index b5fad117..3ae8de0a 100644 --- a/src/javaeva/server/go/operators/cluster/ClusteringDensityBased.java +++ b/src/javaeva/server/go/operators/cluster/ClusteringDensityBased.java @@ -35,6 +35,15 @@ public class ClusteringDensityBased implements InterfaceClustering, java.io.Seri m_ClusterDistance = sigma; } + /** + * Directly set the minimum cluster distance sigma and minimum group size. + * @param sigma the minimum cluster distance + */ + public ClusteringDensityBased(double sigma, int minGSize) { + m_ClusterDistance = sigma; + m_MinimumGroupSize = minGSize; + } + public ClusteringDensityBased(ClusteringDensityBased a) { if (a.m_Metric != null) this.m_Metric = (InterfaceDistanceMetric)a.m_Metric.clone(); this.m_TestConvergingSpeciesOnBestOnly = a.m_TestConvergingSpeciesOnBestOnly; diff --git a/src/javaeva/server/go/operators/mutation/MutateESGlobal.java b/src/javaeva/server/go/operators/mutation/MutateESGlobal.java index 831ddc6a..83af62e8 100644 --- a/src/javaeva/server/go/operators/mutation/MutateESGlobal.java +++ b/src/javaeva/server/go/operators/mutation/MutateESGlobal.java @@ -1,16 +1,14 @@ package javaeva.server.go.operators.mutation; +import java.util.ArrayList; + import javaeva.server.go.individuals.AbstractEAIndividual; -import javaeva.server.go.individuals.InterfaceDataTypeDouble; import javaeva.server.go.individuals.InterfaceESIndividual; import javaeva.server.go.populations.Population; import javaeva.server.go.problems.InterfaceOptimizationProblem; import javaeva.server.go.tools.RandomNumberGenerator; -import javaeva.tools.Tag; import javaeva.tools.SelectedTag; -import java.util.ArrayList; - /** * Created by IntelliJ IDEA. * User: streiche @@ -41,11 +39,7 @@ public class MutateESGlobal implements InterfaceMutation, java.io.Serializable { } protected void initTags() { - Tag[] tag = new Tag[3]; - tag[0] = new Tag(0, "None"); - tag[1] = new Tag(1, "Intermediate"); - tag[2] = new Tag(2, "Discrete"); - this.m_CrossoverType = new SelectedTag(0, tag); + this.m_CrossoverType = new SelectedTag(new String[]{"None", "Intermediate", "Discrete"}); } /** This method will enable you to clone a given mutation operator @@ -105,7 +99,7 @@ public class MutateESGlobal implements InterfaceMutation, java.io.Serializable { * @param partners The original partners */ public void crossoverOnStrategyParameters(AbstractEAIndividual indy1, Population partners) { - ArrayList tmpList = new ArrayList(); + 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)); diff --git a/src/javaeva/server/go/operators/postprocess/PostProcess.java b/src/javaeva/server/go/operators/postprocess/PostProcess.java index 029dca5e..04365b64 100644 --- a/src/javaeva/server/go/operators/postprocess/PostProcess.java +++ b/src/javaeva/server/go/operators/postprocess/PostProcess.java @@ -1,8 +1,6 @@ package javaeva.server.go.operators.postprocess; -import java.io.PrintStream; import java.util.Collection; -import java.util.List; import javaeva.OptimizerFactory; import javaeva.OptimizerRunnable; @@ -19,7 +17,6 @@ import javaeva.server.go.operators.terminators.EvaluationTerminator; import javaeva.server.go.populations.Population; import javaeva.server.go.problems.AbstractOptimizationProblem; import javaeva.server.go.problems.FM0Problem; -import javaeva.server.go.problems.InterfaceMultimodalProblem; import javaeva.server.go.problems.InterfaceMultimodalProblemKnown; import javaeva.server.go.strategies.HillClimbing; import javaeva.server.stat.InterfaceTextListener; @@ -36,6 +33,8 @@ public class PostProcess { private static final boolean TRACE = false; // the default mutation step size for HC post processing private static double defaultMutationStepSize = 0.01; + // used for hill climbing post processing and only alive during that period + private static OptimizerRunnable hcRunnable = null; public static final int BEST_ONLY = 1; public static final int BEST_RAND = 2; @@ -108,11 +107,13 @@ public class PostProcess { for (int i=0; i clusterHC(Population pop, AbstractOptimizationProblem problem, double sigmaCluster, int funCalls, double keepClusterRatio, InterfaceMutation mute) { - Population clust = (Population)clusterBest(pop, new ClusteringDensityBased(sigmaCluster), keepClusterRatio, KEEP_LONERS, BEST_RAND).clone(); + Population clust = (Population)clusterBest(pop, new ClusteringDensityBased(sigmaCluster, 2), keepClusterRatio, KEEP_LONERS, BEST_RAND).clone(); // System.out.println("keeping " + clust.size() + " for hc...."); double[] meanFit = clust.getMeanFitness(); processWithHC(clust, problem, new EvaluationTerminator(pop.getFunctionCalls()+funCalls), mute); double improvement = PhenotypeMetric.euclidianDistance(meanFit, clust.getMeanFitness()); - System.out.println("improvement by " + improvement); + if (TRACE) System.out.println("improvement by " + improvement); return new Pair(clust, improvement); } @@ -457,15 +467,18 @@ public class PostProcess { // } /** - * Do some data output for multimodal problems with known optima. + * Do some data output for multimodal problems with known optima. The listener may be null, but then the method is + * not really doing much at this state. */ public static void procMultiModalKnown(Population solutions, InterfaceMultimodalProblemKnown mmkProb, InterfaceTextListener listener) { // Population found = getFoundOptima(solutions, mmkProb.getRealOptima(), mmkProb.getEpsilon(), true); - listener.println("default epsilon is " + mmkProb.getEpsilon()); - listener.println("max peak ratio is " + mmkProb.getMaximumPeakRatio(getFoundOptima(solutions, mmkProb.getRealOptima(), mmkProb.getEpsilon(), true))); + if (listener != null) { + listener.println("default epsilon is " + mmkProb.getEpsilon()); + listener.println("max peak ratio is " + mmkProb.getMaximumPeakRatio(getFoundOptima(solutions, mmkProb.getRealOptima(), mmkProb.getEpsilon(), true))); + } for (double epsilon=0.1; epsilon > 0.00000001; epsilon/=10.) { // out.println("no optima found: " + ((InterfaceMultimodalProblemKnown)mmProb).getNumberOfFoundOptima(pop)); - listener.println("found " + getFoundOptima(solutions, mmkProb.getRealOptima(), epsilon, true).size() + " for epsilon = " + epsilon); + if (listener != null) listener.println("found " + getFoundOptima(solutions, mmkProb.getRealOptima(), epsilon, true).size() + " for epsilon = " + epsilon); } } @@ -478,38 +491,50 @@ public class PostProcess { * @param solutions * @param problem * @param listener + * @return the clustered, post-processed population */ - public static void postProcess(InterfacePostProcessParams params, Population solutions, AbstractOptimizationProblem problem, InterfaceTextListener listener) { + public static Population postProcess(InterfacePostProcessParams params, Population solutions, AbstractOptimizationProblem problem, InterfaceTextListener listener) { if (params.isDoPostProcessing()) { Population outputPop; if (params.getPostProcessClusterSigma() > 0) { outputPop = (Population)PostProcess.clusterBest(solutions, params.getPostProcessClusterSigma(), 0, PostProcess.KEEP_LONERS, PostProcess.BEST_ONLY).clone(); if (outputPop.size() < solutions.size()) { - listener.println("Clustering reduced population size from " + solutions.size() + " to " + outputPop.size()); - } else listener.println("Clustering yielded no size reduction."); + if (listener != null) listener.println("Initial clustering reduced population size from " + solutions.size() + " to " + outputPop.size()); + } else if (listener != null) listener.println("Initial clustering yielded no size reduction."); } else outputPop = solutions; + if (params.getPostProcessSteps() > 0) { processWithHC(outputPop, problem, params.getPostProcessSteps()); - listener.println("HC post processing done."); + if (listener != null) listener.println("HC post processing done."); + // some individuals may have now converged again + if (params.getPostProcessClusterSigma() > 0) { + // so if wished, cluster again. + outputPop = (Population)PostProcess.clusterBest(outputPop, params.getPostProcessClusterSigma(), 0, PostProcess.KEEP_LONERS, PostProcess.BEST_ONLY).clone(); + if (outputPop.size() < solutions.size()) { + if (listener != null) listener.println("Second clustering reduced population size from " + solutions.size() + " to " + outputPop.size()); + } else if (listener != null) listener.println("Second clustering yielded no size reduction."); + } } + double upBnd = PhenotypeMetric.norm(outputPop.getWorstEAIndividual().getFitness())*1.1; upBnd = Math.pow(10,Math.floor(Math.log10(upBnd)+1)); double lowBnd = 0; int[] sols = PostProcess.createFitNormHistogram(outputPop, lowBnd, upBnd, 20); // PostProcessInterim.outputResult((AbstractOptimizationProblem)goParams.getProblem(), outputPop, 0.01, System.out, 0, 2000, 20, goParams.getPostProcessSteps()); - listener.println("measures: " + BeanInspector.toString(outputPop.getPopulationMeasures())); - listener.println("solution histogram in [" + lowBnd + "," + upBnd + "]: " + BeanInspector.toString(sols)); + if (listener != null) listener.println("measures: " + BeanInspector.toString(outputPop.getPopulationMeasures())); + if (listener != null) listener.println("solution histogram in [" + lowBnd + "," + upBnd + "]: " + BeanInspector.toString(sols)); //////////// multimodal data output? if (problem instanceof InterfaceMultimodalProblemKnown) procMultiModalKnown(outputPop, (InterfaceMultimodalProblemKnown)problem, listener); + Population resPop = outputPop.getBestNIndividuals(params.getPrintNBest()); // n individuals are returned and sorted, all of them if n<=0 + if (listener != null) listener.println("Best after post process:" + ((outputPop.size()>resPop.size()) ? ( "(first " + resPop.size() + " of " + outputPop.size() + ")") : "")); //////////// output some individual data - List bestList = outputPop.getBestNIndividuals(params.getPrintNBest()); // n individuals are returned and sorted, all of them if n<=0 - listener.println("Best after post process:" + ((outputPop.size()>bestList.size()) ? ( "(first " + bestList.size() + " of " + outputPop.size() + ")") : "")); - for (AbstractEAIndividual indy : bestList) { - listener.println(AbstractEAIndividual.getDefaultStringRepresentation(indy)); + if (listener != null) for (int i=0; i getBestNIndividuals(int n) { - LinkedList indList = new LinkedList(); + public Population getBestNIndividuals(int n) { + if (n <= 0) n = super.size(); + Population result = new Population(n); PriorityQueue queue = new PriorityQueue(super.size(), new AbstractEAIndividualComparator()); for (int i = 0; i < super.size(); i++) { queue.add(getEAIndividual(i)); } - if (n <= 0) n = queue.size(); for (int i = 0; i=m_GlobalOpt) { + m_GlobalOpt = ((AbstractEAIndividual)tmpIndy).getFitness(0); + if (makeGlobalOptUnreachable) { + double tmp=m_GlobalOpt; + double dx = 1e-30; + while (tmp==m_GlobalOpt) { + // this increases the optimum until there is a real difference. + // tries to avoid zero y-values which break the logarithmic plot + tmp+=dx; + dx *= 10; + } + m_GlobalOpt = tmp; + } + } + this.m_Optima.add(tmpIndy); + } + + /** + * This method will prepare the problem to return a list of all optima + * if possible and to return quality measures like NumberOfOptimaFound and + * the MaximumPeakRatio. When implementing, use the addOptimum(double[]) + * method for every optimum, as it keeps track the global optimum. + * This method will be called on initialization. + */ + public abstract void initListOfOptima(); + + /** This method returns a list of all optima as population + * @return population + */ + public Population getRealOptima() { + return this.m_Optima; + } + + /** This method returns the Number of Identified optima + * @param pop A population of possible solutions. + * @return int + */ + public int getNumberOfFoundOptima(Population pop) { + List sols = PostProcess.getFoundOptima(pop, m_Optima, m_Epsilon, true); + return sols.size(); + } + + /** + * This method returns the maximum peak ratio, which is the ratio of found fitness values corresponding to + * known optima with the internal epsilon criterion and the sum of all fitness values seen as maximization. + * Thus, if all optima are perfectly found, 1 is returned. If no optimum is found, zero is returned. + * A return value of 0.5 may mean, e.g., that half of n similar optima have been found perfectly, or that 1 major + * optimum of equal weight than all the others has been found perfectly, or that all optima have been found + * with about 50% accuracy, etc. + * + * @param pop A population of possible solutions. + * @return double + */ + public double getMaximumPeakRatio(Population pop) { + double optimaInvertedSum = 0, foundInvertedSum = 0; + AbstractEAIndividual[] optsFound = PostProcess.getFoundOptimaArray(pop, m_Optima, m_Epsilon, true); + + for (int i=0; i 0) { // avoid evil case setting dim to 0 during object init + ((ESIndividualDoubleData)this.m_Template).setDoubleDataLength(getProblemDimension()); + ((ESIndividualDoubleData)this.m_Template).SetDoubleRange(makeRange()); } } + protected void cloneObjects(AbstractProblemDouble o) { + this.m_DefaultRange = o.m_DefaultRange; + this.m_Noise = o.m_Noise; + if (o.m_Template != null) this.m_Template = (AbstractEAIndividual)o.m_Template.clone(); + } + + /** + * Retrieve and copy the double solution representation from an individual. + * + * @param individual + * @return the double solution representation + */ protected double[] getEvalArray(AbstractEAIndividual individual){ double[] x = new double[((InterfaceDataTypeDouble) individual).getDoubleData().length]; System.arraycopy(((InterfaceDataTypeDouble) individual).getDoubleData(), 0, x, 0, x.length); @@ -55,17 +59,30 @@ public abstract class AbstractProblemDouble extends AbstractOptimizationProblem setEvalFitness(individual, x, fitness); } + /** + * Write a fitness value back to an individual. May be overridden to add constraints. + * + * @param individual + * @param x + * @param fit + */ protected void setEvalFitness(AbstractEAIndividual individual, double[] x, double[] fit) { individual.SetFitness(fit); } /** - * Evaluate a double vector - * @param x - * @return + * Evaluate a double vector, representing the target function. + * + * @param x the vector to evaluate + * @return the target function value */ public abstract double[] eval(double[] x); + /** + * Get the problem dimension. + * + * @return the problem dimension + */ public abstract int getProblemDimension(); @Override @@ -84,6 +101,11 @@ public abstract class AbstractProblemDouble extends AbstractOptimizationProblem population.init(); } + /** + * Create a new range array by using the getRangeLowerBound and getRangeUpperBound methods. + * + * @return a range array + */ protected double[][] makeRange() { double[][] range = new double[this.getProblemDimension()][2]; for (int i = 0; i < range.length; i++) { @@ -93,10 +115,28 @@ public abstract class AbstractProblemDouble extends AbstractOptimizationProblem return range; } + /** + * Get the lower bound of the double range in the given dimension. Override + * this to implement non-symmetric ranges. User setDefaultRange for symmetric ranges. + * + * @see makeRange() + * @see getRangeUpperBound(int dim) + * @param dim + * @return the lower bound of the double range in the given dimension + */ protected double getRangeLowerBound(int dim) { return -m_DefaultRange; } + /** + * Get the upper bound of the double range in the given dimension. Override + * this to implement non-symmetric ranges. User setDefaultRange for symmetric ranges. + * + * @see makeRange() + * @see getRangeLowerBound(int dim) + * @param dim + * @return the upper bound of the double range in the given dimension + */ protected double getRangeUpperBound(int dim) { return m_DefaultRange; } @@ -106,7 +146,8 @@ public abstract class AbstractProblemDouble extends AbstractOptimizationProblem initTemplate(); } - /** This method allows you to choose how much noise is to be added to the + /** + * This method allows you to choose how much noise is to be added to the * fitness. This can be used to make the optimization problem more difficult. * @param noise The sigma for a gaussian random number. */ @@ -114,6 +155,10 @@ public abstract class AbstractProblemDouble extends AbstractOptimizationProblem if (noise < 0) noise = 0; this.m_Noise = noise; } + /** + * Get the current noise level. + * @return the current noise level + */ public double getNoise() { return this.m_Noise; } @@ -121,13 +166,20 @@ public abstract class AbstractProblemDouble extends AbstractOptimizationProblem return "Gaussian noise level on the fitness value."; } - /** This method allows you to choose the EA individual + /** + * This method allows you to choose the EA individual used by the problem. + * * @param indy The EAIndividual type */ public void setEAIndividual(InterfaceDataTypeDouble indy) { this.m_Template = (AbstractEAIndividual)indy; } + /** + * Get the EA individual template currently used by the problem. + * + * @return the EA individual template currently used + */ public InterfaceDataTypeDouble getEAIndividual() { return (InterfaceDataTypeDouble)this.m_Template; } @@ -160,18 +212,36 @@ public abstract class AbstractProblemDouble extends AbstractOptimizationProblem return "Absolute limit for the symmetric range in any dimension"; } + + /********************************************************************************************************************** + * These are for Interface2DBorderProblem + */ + public double[][] get2DBorder() { + return makeRange(); + } + + + public double functionValue(double[] point) { + double x[] = new double[getProblemDimension()]; + for (int i=0; i= 1."; } - - public double functionValue(double[] point) { - double x[] = new double[m_ProblemDimension]; - for (int i=0; i=m_GlobalOpt) { - m_GlobalOpt = ((AbstractEAIndividual)tmpIndy).getFitness(0); - double tmp=m_GlobalOpt; - double dx = 1e-30; - while (tmp==m_GlobalOpt) { - // this increases the optimum until there is a real difference. - // tries to avoid zero y-values which break the logarithmic plot - tmp+=dx; - dx *= 10; - } - m_GlobalOpt = tmp; - } - this.m_Optima.add(tmpIndy); - } - /** This method will prepare the problem to return a list of all optima * if possible and to return quality measures like NumberOfOptimaFound and * the MaximumPeakRatio. This method should be called by the user. */ public void initListOfOptima() { - this.m_GlobalOpt = Double.NEGATIVE_INFINITY; - this.m_Optima = new Population(); //this.add2DOptimum((Math.PI - (Math.PI - Math.acos(-1/4.0)) + Math.PI/2.0)/2.0, 0); //this.add2DOptimum((-Math.PI - (Math.PI - Math.acos(-1/4.0)) + Math.PI/2.0)/2.0, 0); @@ -222,71 +91,7 @@ public class FM0Problem extends AbstractProblemDouble implements Interface2DBord this.add2DOptimum(-1.44445618316078, 0.00000000700284); } - /** This method returns a list of all optima as population - * @return population - */ - public Population getRealOptima() { - return this.m_Optima; - } - /** This method returns the Number of Identified optima - * @param pop A population of possible solutions. - * @return int - */ - public int getNumberOfFoundOptima(Population pop) { - List sols = PostProcess.getFoundOptima(pop, m_Optima, m_Epsilon, true); - return sols.size(); - } - - /** - * This method returns the maximum peak ratio, which is the ratio of found fitness values corresponding to - * known optima with the internal epsilon criterion and the sum of all fitness values seen as maximization. - * Thus, if all optima are perfectly found, 1 is returned. If no optimum is found, zero is returned. - * A return value of 0.5 may mean, e.g., that half of n similar optima have been found perfectly, or that 1 major - * optimum of equal weight than all the others has been found perfectly, or that all optima have been found - * with about 50% accuracy, etc. - * - * @param pop A population of possible solutions. - * @return double - */ - public double getMaximumPeakRatio(Population pop) { - double optimaInvertedSum = 0, foundInvertedSum = 0; - AbstractEAIndividual[] optsFound = PostProcess.getFoundOptimaArray(pop, m_Optima, m_Epsilon, true); - - for (int i=0; i= lambda.. reducing to mu=lambda-1"); mu = species.size() - 1; } - es.setMyu(mu); + es.setMu(mu); es.setLambda(species.size()); } if (TRACE) { @@ -384,12 +384,12 @@ public class ClusterBasedNichingEA implements InterfacePopulationChangedEventLis m_Species.remove(i); //REMOVES the converged Species reinitCount = curSpecies.size(); // add all as new } else { - // now reset the converged species to inactivity size = 1 - curSpecies.setPopulationSize(1); -// m_Undifferentiated.incrFunctionCallsby(1); // TODO not so good - curSpecies.clear(); - curSpecies.add(best); - reinitCount = curSpecies.size()-1; // add all but one as new + // now reset the converged species to inactivity size = 1 + reinitCount = curSpecies.size()-1; // add all but one as new + curSpecies.setPopulationSize(1); +// m_Undifferentiated.incrFunctionCallsby(1); // TODO not so good + curSpecies.clear(); + curSpecies.add(best); } // reinit the surplus individuals and add these new individuals to undifferentiated m_Undifferentiated.addPopulation(this.initializeIndividuals(reinitCount)); @@ -427,8 +427,8 @@ public class ClusterBasedNichingEA implements InterfacePopulationChangedEventLis m_Undifferentiated.incrFunctionCallsby(m_Undifferentiated.size()); } if (this.m_Undifferentiated.getFunctionCalls() % this.m_PopulationSize != 0) { - if (true) System.out.println("### mismatching number of funcalls, inactive species? Correcting by " + (m_PopulationSize - (m_Undifferentiated.getFunctionCalls() % m_PopulationSize))); - if (true) System.out.println("### undiff " + ((isActive(m_Undifferentiated)) ? "active!" : "inactive!")); + if (TRACE) System.out.println("### mismatching number of funcalls, inactive species? Correcting by " + (m_PopulationSize - (m_Undifferentiated.getFunctionCalls() % m_PopulationSize))); + if (TRACE) System.out.println("### undiff " + ((isActive(m_Undifferentiated)) ? "active!" : "inactive!")); m_Undifferentiated.incrFunctionCallsby(m_PopulationSize - (m_Undifferentiated.getFunctionCalls() % m_PopulationSize)); } else if (TRACE) System.out.println("### undiff active: " + isActive(m_Undifferentiated)); @@ -438,7 +438,7 @@ public class ClusterBasedNichingEA implements InterfacePopulationChangedEventLis if (this.m_UseSpeciesDifferentation) { // species differentation phase - if (TRACE) System.out.println("-Sepecies Differentation:"); + if (TRACE) System.out.println("-Species Differentation:"); Population[] ClusterResult; ArrayList newSpecies = new ArrayList(); //cluster the undifferentiated population @@ -755,7 +755,7 @@ public class ClusterBasedNichingEA implements InterfacePopulationChangedEventLis this.m_Optimizer = b; if (b instanceof EvolutionStrategies) { EvolutionStrategies es = (EvolutionStrategies)b; - setMuLambdaRatio(es.getMyu()/(double)es.getLambda()); + setMuLambdaRatio(es.getMu()/(double)es.getLambda()); } } public String optimizerTipText() { diff --git a/src/javaeva/server/go/strategies/ClusteringHillClimbing.java b/src/javaeva/server/go/strategies/ClusteringHillClimbing.java index ceb92f77..64fa5388 100644 --- a/src/javaeva/server/go/strategies/ClusteringHillClimbing.java +++ b/src/javaeva/server/go/strategies/ClusteringHillClimbing.java @@ -12,21 +12,40 @@ import javaeva.server.go.problems.F1Problem; import javaeva.server.go.problems.InterfaceOptimizationProblem; import javaeva.tools.Pair; +/** + * The clustering hill climber is similar to a multi-start hill climber. In addition so optimizing + * a set of individuals in parallel using a (1+1) strategy, the population is clustered in regular + * intervals. If several individuals have gathered together in the sense that they are interpreted + * as a cluster, only a subset of representatives of the cluster is taken over to the next HC step + * while the rest is discarded. This means that the population size may be reduced. + * + * As soon as the improvement by HC lies below a threshold, the mutation step size is decreased. + * If the step size is decreased below a certain threshold, the current population is stored to + * an archive and reinitialized. Thus, the number of optima that may be found and returned by + * getAllSolutions is higher than the population size. + * + * @author mkron + * + */ public class ClusteringHillClimbing implements InterfacePopulationChangedEventListener, InterfaceOptimizer, Serializable { transient private InterfacePopulationChangedEventListener m_Listener; + public static final boolean TRACE = false; + transient private String m_Identifier = ""; private Population m_Population = new Population(); private transient Population archive = new Population(); private InterfaceOptimizationProblem m_Problem = new F1Problem(); private int hcEvalCycle = 1000; - private int initialPopSize = 200; + private int initialPopSize = 100; private int loopCnt = 0; // private int baseEvalCnt = 0; private int notifyGuiEvery = 50; - private double sigma = 0.01; + private double sigmaClust = 0.01; private double minImprovement = 0.000001; - private double reinitForStepSize = 0.000001; + private double stepSizeThreshold = 0.000001; private double initialStepSize = 0.1; + // reduce the step size when there is hardy improvement. + private double reduceFactor = 0.2; private MutateESFixedStepSize mutator = new MutateESFixedStepSize(0.1); public ClusteringHillClimbing() { @@ -37,8 +56,16 @@ public class ClusteringHillClimbing implements InterfacePopulationChangedEventLi hideHideable(); m_Population = (Population)other.m_Population.clone(); m_Problem = (InterfaceOptimizationProblem)other.m_Problem.clone(); + hcEvalCycle = other.hcEvalCycle; initialPopSize = other.initialPopSize; + notifyGuiEvery = other.notifyGuiEvery; + sigmaClust = other.sigmaClust; + minImprovement = other.minImprovement; + stepSizeThreshold = other.stepSizeThreshold; + initialStepSize = other.initialStepSize; + reduceFactor = other.reduceFactor; + mutator = (MutateESFixedStepSize)other.mutator.clone(); loopCnt = 0; } @@ -81,7 +108,7 @@ public class ClusteringHillClimbing implements InterfacePopulationChangedEventLi hideHideable(); m_Population.setPopulationSize(initialPopSize); this.m_Problem.initPopulation(this.m_Population); - m_Population.addPopulationChangedEventListener(null); + m_Population.addPopulationChangedEventListener(null); // noone will be notified directly on pop changes this.m_Problem.evaluate(this.m_Population); this.firePropertyChangedEvent("NextGenerationPerformed"); } @@ -111,16 +138,16 @@ public class ClusteringHillClimbing implements InterfacePopulationChangedEventLi loopCnt++; m_Population.addPopulationChangedEventListener(this); m_Population.setNotifyEvalInterval(notifyGuiEvery); - Pair popD = PostProcess.clusterHC(m_Population, (AbstractOptimizationProblem)m_Problem, sigma, hcEvalCycle - (m_Population.getFunctionCalls() % hcEvalCycle), 0.5, mutator); + Pair popD = PostProcess.clusterHC(m_Population, (AbstractOptimizationProblem)m_Problem, sigmaClust, hcEvalCycle - (m_Population.getFunctionCalls() % hcEvalCycle), 0.5, mutator); improvement = popD.tail(); + m_Population = popD.head(); popD.head().setGenerationTo(m_Population.getGeneration()+1); - m_Population = popD.head(); if (improvement < minImprovement) { - System.out.println("improvement below " + minImprovement); - if (mutator.getSigma() < reinitForStepSize) { // reinit! - System.out.println("REINIT!!"); + if (TRACE) System.out.println("improvement below " + minImprovement); + if (mutator.getSigma() < stepSizeThreshold) { // reinit! + if (TRACE) System.out.println("REINIT!!"); // store results mutator.setSigma(initialStepSize); archive.SetFunctionCalls(m_Population.getFunctionCalls()); @@ -139,12 +166,12 @@ public class ClusteringHillClimbing implements InterfacePopulationChangedEventLi m_Population.incrFunctionCallsby(tmpPop.size()); } else { // decrease step size - mutator.setSigma(mutator.getSigma()/2); - System.out.println("halfed sigma to " + mutator.getSigma()); + mutator.setSigma(mutator.getSigma()*reduceFactor); + if (TRACE) System.out.println("mutation stepsize reduced to " + mutator.getSigma()); } } // System.out.println("funcalls: " + evalCnt); -// this.firePropertyChangedEvent("NextGenerationPerformed"); + this.firePropertyChangedEvent("NextGenerationPerformed"); } @@ -219,6 +246,10 @@ public class ClusteringHillClimbing implements InterfacePopulationChangedEventLi public void setHcEvalCycle(int hcEvalCycle) { this.hcEvalCycle = hcEvalCycle; } + + public String hcEvalCycleTipText() { + return "The number of evaluations between two clustering/adaption steps."; + } /** * @return the initialPopSize @@ -234,21 +265,25 @@ public class ClusteringHillClimbing implements InterfacePopulationChangedEventLi this.initialPopSize = initialPopSize; } + public String initialPopSizeTipText() { + return "Population size at the start and at reinitialization times."; + } + /** * @return the sigma */ - public double getSigma() { - return sigma; + public double getSigmaClust() { + return sigmaClust; } /** * @param sigma the sigma to set */ - public void setSigma(double sigma) { - this.sigma = sigma; + public void setSigmaClust(double sigma) { + this.sigmaClust = sigma; } - public String sigmaTipText() { + public String sigmaClustTipText() { return "Defines the sigma distance parameter for density based clustering."; } @@ -266,6 +301,10 @@ public class ClusteringHillClimbing implements InterfacePopulationChangedEventLi this.notifyGuiEvery = notifyGuiEvery; } + public String notifyGuiEveryTipText() { + return "How often to notify the GUI to plot the fitness etc."; + } + /** * @return the minImprovement */ @@ -280,33 +319,45 @@ public class ClusteringHillClimbing implements InterfacePopulationChangedEventLi this.minImprovement = minImprovement; } + public String minImprovementTipText() { + return "Improvement threshold below which the mutation step size is reduced or the population reinitialized."; + } + /** * @return the reinitForStepSize */ - public double getReinitForStepSize() { - return reinitForStepSize; + public double getStepSizeThreshold() { + return stepSizeThreshold; } /** * @param reinitForStepSize the reinitForStepSize to set */ - public void setReinitForStepSize(double reinitForStepSize) { - this.reinitForStepSize = reinitForStepSize; + public void setStepSizeThreshold(double reinitForStepSize) { + this.stepSizeThreshold = reinitForStepSize; } + public String stepSizeThresholdTipText() { + return "Threshold for the mutation step size below which the population is seen as converged and reinitialized."; + } + /** * @return the initialStepSize */ - public double getInitialStepSize() { + public double getStepSizeInitial() { return initialStepSize; } /** * @param initialStepSize the initialStepSize to set */ - public void setInitialStepSize(double initialStepSize) { + public void setStepSizeInitial(double initialStepSize) { this.initialStepSize = initialStepSize; } + + public String stepSizeInitialTipText() { + return "Initial mutation step size, relative to the problem range."; + } // /** // * @return the mutator diff --git a/src/javaeva/server/go/strategies/EvolutionStrategies.java b/src/javaeva/server/go/strategies/EvolutionStrategies.java index 0df662e2..46de3f44 100644 --- a/src/javaeva/server/go/strategies/EvolutionStrategies.java +++ b/src/javaeva/server/go/strategies/EvolutionStrategies.java @@ -29,7 +29,7 @@ import javaeva.server.go.problems.InterfaceOptimizationProblem; public class EvolutionStrategies implements InterfaceOptimizer, java.io.Serializable { //private double m_MyuRatio = 6; - private int m_Myu = 5; + private int m_Mu = 5; private int m_Lambda = 20; private int m_InitialPopulationSize = 0; private boolean m_UsePlusStrategy = false; @@ -49,7 +49,7 @@ public class EvolutionStrategies implements InterfaceOptimizer, java.io.Serializ } public EvolutionStrategies(int mu, int lambda, boolean usePlus) { - setMyu(mu); + setMu(mu); setLambda(lambda); setPlusStrategy(usePlus); this.m_Population.setPopulationSize(this.m_Lambda); @@ -58,7 +58,7 @@ public class EvolutionStrategies implements InterfaceOptimizer, java.io.Serializ public EvolutionStrategies(EvolutionStrategies a) { this.m_Population = (Population)a.m_Population.clone(); this.m_Problem = (InterfaceOptimizationProblem)a.m_Problem.clone(); - this.m_Myu = a.m_Myu; + this.m_Mu = a.m_Mu; this.m_Lambda = a.m_Lambda; this.m_InitialPopulationSize = a.m_InitialPopulationSize; this.m_UsePlusStrategy = a.m_UsePlusStrategy; @@ -183,7 +183,7 @@ public class EvolutionStrategies implements InterfaceOptimizer, java.io.Serializ //System.out.println("optimize"); // first perform the environment selection to select myu parents this.m_EnvironmentSelection.prepareSelection(this.m_Population); - parents = this.m_EnvironmentSelection.selectFrom(this.m_Population, this.m_Myu); + parents = this.m_EnvironmentSelection.selectFrom(this.m_Population, this.m_Mu); this.m_Population.clear(); this.m_Population.addPopulation(parents); // now generate the lambda offsprings @@ -296,7 +296,7 @@ public class EvolutionStrategies implements InterfaceOptimizer, java.io.Serializ * @param plus True if plus, false if comma strategy */ public void setGenerationStrategy(int myu, int lambda, boolean plus) { - this.m_Myu = myu; + this.m_Mu = myu; this.m_Lambda = lambda; this.m_UsePlusStrategy = plus; this.checkPopulationConstraints(); @@ -307,8 +307,8 @@ public class EvolutionStrategies implements InterfaceOptimizer, java.io.Serializ * accordingly. */ private void checkPopulationConstraints() { - if (this.m_Lambda < this.m_Myu) this.m_Lambda = this.m_Myu; - if (this.m_UsePlusStrategy) this.m_Population.setPopulationSize(this.m_Myu + this.m_Lambda); + if (this.m_Lambda < this.m_Mu) this.m_Lambda = this.m_Mu; + if (this.m_UsePlusStrategy) this.m_Population.setPopulationSize(this.m_Mu + this.m_Lambda); else this.m_Population.setPopulationSize(this.m_Lambda); } @@ -341,7 +341,7 @@ public class EvolutionStrategies implements InterfaceOptimizer, java.io.Serializ * @return The name of the algorithm */ public String getName() { - return "("+getMyu()+(getPlusStrategy() ? "+" : ",")+getLambda()+")-ES"; + return "("+getMu()+(getPlusStrategy() ? "+" : ",")+getLambda()+")-ES"; } /** Assuming that all optimizer will store thier data in a population @@ -473,14 +473,14 @@ public class EvolutionStrategies implements InterfaceOptimizer, java.io.Serializ /** This method allows you to set parent population size myu * @param myu The parent population size. */ - public void setMyu(int myu) { - this.m_Myu = myu; + public void setMu(int mu) { + this.m_Mu = mu; this.checkPopulationConstraints(); } - public int getMyu() { - return this.m_Myu; + public int getMu() { + return this.m_Mu; } - public String myuTipText() { + public String muTipText() { return "This is the parent population size."; } diff --git a/src/javaeva/server/go/strategies/tribes/TribesSwarm.java b/src/javaeva/server/go/strategies/tribes/TribesSwarm.java index daeda1f5..db0f40d7 100644 --- a/src/javaeva/server/go/strategies/tribes/TribesSwarm.java +++ b/src/javaeva/server/go/strategies/tribes/TribesSwarm.java @@ -64,6 +64,7 @@ public class TribesSwarm implements java.io.Serializable{ for (int i=0; i