diff --git a/src/eva2/EvAInfo.java b/src/eva2/EvAInfo.java index 96f545d9..32f3c2b8 100644 --- a/src/eva2/EvAInfo.java +++ b/src/eva2/EvAInfo.java @@ -4,13 +4,13 @@ package eva2; * Main product and version information strings. * * --- Changelog - * 2.030: Added an EnumEditor to access enums easily through the GUI. + * 2.030: Added an EnumEditor to access enums easily through the GUI, which will replace SelectedTags sometimes. * IPOP-ES and RankMuCMA mutator have been added lately (wow!). * Cleaned up the IndividualInterface and reduced the usage of InterfaceESIndividual. This * means that, e.g., that DE and PSO now also work on GAIndividualDoubleData. Because this * requires much time for transcoding, however, this is not useful by itself. Yet it could be * interesting for combined individuals composed of two data types. - * Cleaned up MutateXXDefault to a single MutateDefault, too. + * Cleaned up MutateXXDefault to a single MutateDefault, too. DE may now do range checking. * 2.029: Tuned the 2d-graphs which now paints quicker and changes size depending on the * surrounding plot window. Added a preloader-thread to accelerate the GUI at starting time. * 2.028: Tuned the Population to sort only when necessary on calls to getBestN... Added StatisticsDummy. diff --git a/src/eva2/OptimizerFactory.java b/src/eva2/OptimizerFactory.java index 49cecf41..2d9d545b 100644 --- a/src/eva2/OptimizerFactory.java +++ b/src/eva2/OptimizerFactory.java @@ -9,6 +9,7 @@ import java.util.Vector; import eva2.server.go.IndividualInterface; import eva2.server.go.InterfacePopulationChangedEventListener; import eva2.server.go.InterfaceTerminator; +import eva2.server.go.enums.DETypeEnum; import eva2.server.go.individuals.AbstractEAIndividual; import eva2.server.go.individuals.InterfaceDataTypeBinary; import eva2.server.go.individuals.InterfaceDataTypeDouble; @@ -25,10 +26,12 @@ import eva2.server.go.operators.mutation.InterfaceMutation; import eva2.server.go.operators.mutation.MutateESCovarianceMatrixAdaption; import eva2.server.go.operators.mutation.MutateESFixedStepSize; import eva2.server.go.operators.mutation.MutateESGlobal; +import eva2.server.go.operators.mutation.MutateESRankMuCMA; import eva2.server.go.operators.mutation.NoMutation; import eva2.server.go.operators.postprocess.InterfacePostProcessParams; import eva2.server.go.operators.postprocess.PostProcessParams; import eva2.server.go.operators.selection.InterfaceSelection; +import eva2.server.go.operators.selection.SelectBestIndividuals; import eva2.server.go.operators.terminators.CombinedTerminator; import eva2.server.go.operators.terminators.EvaluationTerminator; import eva2.server.go.operators.terminators.FitnessConvergenceTerminator; @@ -38,6 +41,7 @@ import eva2.server.go.strategies.ClusterBasedNichingEA; import eva2.server.go.strategies.ClusteringHillClimbing; import eva2.server.go.strategies.DifferentialEvolution; import eva2.server.go.strategies.EvolutionStrategies; +import eva2.server.go.strategies.EvolutionStrategyIPOP; import eva2.server.go.strategies.GeneticAlgorithm; import eva2.server.go.strategies.GradientDescentAlgorithm; import eva2.server.go.strategies.HillClimbing; @@ -96,6 +100,8 @@ public class OptimizerFactory { public final static int CBN_ES = 9; public final static int CL_HILLCL = 10; + + public final static int CMA_ES_IPOP = 11; public final static int defaultFitCalls = 10000; @@ -121,69 +127,6 @@ public class OptimizerFactory { newTerm, bAnd)); } - public static final GOParameters cbnES(AbstractOptimizationProblem problem) { - ClusterBasedNichingEA cbn = new ClusterBasedNichingEA(); - EvolutionStrategies es = new EvolutionStrategies(); - 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(0); // don't do graphical output - - Population pop = new Population(); - pop.setPopulationSize(100); - problem.initPopulation(pop); - - return makeParams(cbn, pop, problem, randSeed, defaultTerminator()); - } - - public static final 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()); - } - - public static final GOParameters cmaES(AbstractOptimizationProblem problem) { - EvolutionStrategies es = new EvolutionStrategies(); - es.setMu(15); - es.setLambda(50); - es.setPlusStrategy(false); - - AbstractEAIndividual indyTemplate = problem.getIndividualTemplate(); - if ((indyTemplate != null) - && (indyTemplate instanceof InterfaceESIndividual)) { - // Set CMA operator for mutation - AbstractEAIndividual indy = (AbstractEAIndividual) indyTemplate; - MutateESCovarianceMatrixAdaption cmaMut = new MutateESCovarianceMatrixAdaption(); - cmaMut.setCheckConstraints(true); - indy.setMutationOperator(cmaMut); - indy.setCrossoverOperator(new CrossoverESDefault()); - } else { - System.err - .println("Error, CMA-ES is implemented for ES individuals only (requires double data types)"); - return null; - } - - Population pop = new Population(); - pop.setPopulationSize(es.getLambda()); - - return makeParams(es, pop, problem, randSeed, defaultTerminator()); - } - /** * This method optimizes the given problem using differential evolution. * @@ -211,7 +154,7 @@ public class OptimizerFactory { DifferentialEvolution de = new DifferentialEvolution(); de.SetProblem(problem); de.getPopulation().setPopulationSize(popsize); - de.getDEType().setSelectedTag(1); + de.setDEType(DETypeEnum.DE2_CurrentToBest); de.setF(f); de.setK(CR); de.setLambda(lambda); @@ -232,38 +175,69 @@ public class OptimizerFactory { * @param pm * @param crossoveroperator * @param pc - * @param selection + * @param selection environmental selection operator * @param problem * @param listener - * @return An optimization algorithm that employes an evolution strategy. + * @return An optimization algorithm that employs an evolution strategy. */ public static final EvolutionStrategies createEvolutionStrategy(int mu, int lambda, boolean plus, InterfaceMutation mutationoperator, double pm, InterfaceCrossover crossoveroperator, double pc, InterfaceSelection selection, AbstractOptimizationProblem problem, InterfacePopulationChangedEventListener listener) { + return createES(new EvolutionStrategies(mu, lambda, plus), mutationoperator, pm, crossoveroperator, pc, selection, problem, listener); + } + + /** + * This method initializes the optimization using an Evolution strategy with + * increasing population size. + * + * @param mu + * @param lambda + * @param plus + * if true this operator uses elitism otherwise a comma strategy. + * @param mutationoperator + * @param pm + * @param crossoveroperator + * @param pc + * @param incPopSizeFact factor by which to inrease lambda ro restart, default is 2 + * @param stagThresh if the fitness changes below this value during a stagnation phase, a restart is initiated + * @param problem + * @param listener + * @return An optimization algorithm that employs an IPOP-ES. + */ + public static final EvolutionStrategyIPOP createEvolutionStrategyIPOP(int mu, + int lambda, boolean plus, InterfaceMutation mutationoperator, + double pm, InterfaceCrossover crossoveroperator, double pc, double incPopSizeFact, double stagThresh, + AbstractOptimizationProblem problem, InterfacePopulationChangedEventListener listener) { + EvolutionStrategyIPOP esIPOP = (EvolutionStrategyIPOP)createES(new EvolutionStrategyIPOP(mu, lambda, plus), mutationoperator, pm, crossoveroperator, pc, new SelectBestIndividuals(), problem, listener); + esIPOP.setIncPopSizeFact(incPopSizeFact); +// esIPOP.setStagnationGenerations(stagTimeGens); + esIPOP.setStagThreshold(stagThresh); + return esIPOP; + } + + private static final EvolutionStrategies createES(EvolutionStrategies theES, InterfaceMutation mutationoperator, + double pm, InterfaceCrossover crossoveroperator, double pc, + InterfaceSelection selection, AbstractOptimizationProblem problem, + InterfacePopulationChangedEventListener listener) { problem.initProblem(); - // RNG.setRandomSeed(100); AbstractEAIndividual tmpIndi = problem.getIndividualTemplate(); - tmpIndi.setMutationOperator(mutationoperator); - tmpIndi.setMutationProbability(pm);// */ // 1/tmpIndi.size() - tmpIndi.setCrossoverOperator(crossoveroperator); - tmpIndi.setCrossoverProbability(pc);// */ // 0.95 + AbstractEAIndividual.setOperators(tmpIndi, mutationoperator, pm, crossoveroperator, pc); EvolutionStrategies es = new EvolutionStrategies(); es.addPopulationChangedEventListener(listener); - es.setParentSelection(selection); - es.setPartnerSelection(selection); + //es.setParentSelection(selection); + //es.setPartnerSelection(selection); es.setEnvironmentSelection(selection); - es.setGenerationStrategy(mu, lambda, plus); // comma strategy es.SetProblem(problem); es.init(); - return es; + return theES; } - + /** * This method performs a Genetic Algorithm. * @@ -544,6 +518,13 @@ public class OptimizerFactory { // /////////////////////////// constructing a default OptimizerRunnable + /** + * For an optimizer identifier, return the corresponding default parameter set including + * initialization (thats why the problem is required). + * + * @param optType optimizer identifier + * @param problem corresponding optimization problem + */ public static GOParameters getParams(final int optType, AbstractOptimizationProblem problem) { switch (optType) { @@ -567,6 +548,8 @@ public class OptimizerFactory { return cbnES(problem); case CL_HILLCL: return clusteringHillClimbing(problem); + case CMA_ES_IPOP: + return cmaESIPOP(problem); default: System.err.println("Error: optimizer type " + optType + " is unknown!"); @@ -574,6 +557,27 @@ public class OptimizerFactory { } } + /** + * 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 \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 \n11: IPOP-CMA-ES."; + } + + /** + * Produce a runnable optimizer from a strategy identifier, a problem instance and with a given + * number of fitness calls to be performed. Output is written to a file if the prefix String is given. + * + * @param optType + * @param problem + * @param fitCalls + * @param outputFilePrefix + * @return a runnable optimizer + */ public static OptimizerRunnable getOptRunnable(final int optType, AbstractOptimizationProblem problem, int fitCalls, String outputFilePrefix) { @@ -589,31 +593,86 @@ public class OptimizerFactory { } // /////////////////////////// constructing a default OptimizerRunnable + /** + * Produce a runnable optimizer from a strategy identifier, a problem instance and with the default + * number of fitness calls to be performed. Output is written to a file if the prefix String is given. + * @see #getOptRunnable(int, AbstractOptimizationProblem, int, String) + * @param optType + * @param problem + * @param outputFilePrefix + * @return a runnable optimizer + */ public static OptimizerRunnable getOptRunnable(final int optType, AbstractOptimizationProblem problem, String outputFilePrefix) { return getOptRunnable(optType, problem, defaultFitCalls, outputFilePrefix); } + /** + * Return the current default terminator. + * + * @return the current default terminator + */ public static InterfaceTerminator getTerminator() { return OptimizerFactory.term; } - public static final GOParameters hillClimbing( - AbstractOptimizationProblem problem) { - HillClimbing hc = new HillClimbing(); - hc.SetProblem(problem); - Population pop = new Population(); - pop.setPopulationSize(50); - problem.initPopulation(pop); - return makeParams(hc, pop, problem, randSeed, defaultTerminator()); - } - + /** + * Return the number of evaluations performed during the last run or -1 if unavailable. + * + * @return the number of evaluations performed during the last run or -1 + */ public static int lastEvalsPerformed() { return (lastRunnable != null) ? lastRunnable.getProgress() : -1; } // /////////////////////// Creating default strategies + + /** + * Use lambda, default random seed and terminator to produce GOParameters. + * + * @param es + * @param problem + * @return + */ + public static GOParameters makeESParams(EvolutionStrategies es, + AbstractOptimizationProblem problem) { + return makeParams(es, es.getLambda(), problem, randSeed, defaultTerminator()); + } + + /** + * Use default random seed and terminator for a parameter set. + * + * @see #makeParams(InterfaceOptimizer, int, AbstractOptimizationProblem, long, InterfaceTerminator) + * @param opt + * @param popSize + * @param problem + * @return + */ + public static GOParameters makeParams(InterfaceOptimizer opt, int popSize, AbstractOptimizationProblem problem) { + return makeParams(opt, popSize, problem, randSeed, defaultTerminator()); + } + + public static GOParameters makeParams(InterfaceOptimizer opt, + int popSize, AbstractOptimizationProblem problem, long seed, + InterfaceTerminator term) { + Population pop = new Population(popSize); + problem.initPopulation(pop); + return makeParams(opt, pop, problem, seed, term); + } + + /** + * Create a GOParameters instance and prepare it with the given arguments. The result can be + * modified and then used to create an OptimizerRunnable, which of course can simply be run. + * + * @see OptimizerRunnable + * @param opt + * @param pop + * @param problem + * @param seed + * @param term + * @return + */ public static GOParameters makeParams(InterfaceOptimizer opt, Population pop, AbstractOptimizationProblem problem, long seed, InterfaceTerminator term) { @@ -627,16 +686,6 @@ public class OptimizerFactory { return params; } - public static final GOParameters monteCarlo( - AbstractOptimizationProblem problem) { - MonteCarloSearch mc = new MonteCarloSearch(); - Population pop = new Population(); - pop.setPopulationSize(50); - problem.initPopulation(pop); - return makeParams(mc, pop, problem, randSeed, defaultTerminator()); - } - - // TODO hier weiter kommentieren public static OptimizerRunnable optimize(final int optType, AbstractOptimizationProblem problem, String outputFilePrefix) { return optimize(getOptRunnable(optType, problem, outputFilePrefix)); @@ -849,7 +898,7 @@ public class OptimizerFactory { : null; } - // /////////////////////////// post processing + ///////////////////////////// post processing public static Vector postProcessIndVec( OptimizerRunnable runnable, int steps, double sigma, int nBest) { return postProcessIndVec(runnable, new PostProcessParams(steps, sigma, @@ -869,7 +918,8 @@ public class OptimizerFactory { } return ret; } - + + ///////////////////////////// termination management public static void setEvaluationTerminator(int maxEvals) { setTerminator(new EvaluationTerminator(maxEvals)); } @@ -883,30 +933,124 @@ public class OptimizerFactory { OptimizerFactory.term = term; } + public static String terminatedBecause() { + return (lastRunnable != null) ? lastRunnable.terminatedBecause() : null; + } + + ///////////////////////////// default parameters /** - * Return a simple String showing the accessible optimizers. For external - * access." - * - * @return a String listing the accessible optimizers + * Create a standard multi-start hill-climber parameter set with 50 initial individuals. + * + * @return a standard multi-start hill-climber */ - public static String showOptimizers() { - 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"; + public static final GOParameters hillClimbing( + AbstractOptimizationProblem problem) { + return makeParams(new HillClimbing(), 50, problem, randSeed, defaultTerminator()); } + public static final GOParameters monteCarlo( + AbstractOptimizationProblem problem) { + return makeParams(new MonteCarloSearch(), 50, problem, randSeed, defaultTerminator()); + } + + public static final GOParameters cbnES(AbstractOptimizationProblem problem) { + ClusterBasedNichingEA cbn = new ClusterBasedNichingEA(); + EvolutionStrategies es = new EvolutionStrategies(); + 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(0); // don't do graphical output + + return makeParams(cbn, 100, problem, randSeed, defaultTerminator()); + } + + public static final GOParameters clusteringHillClimbing( + AbstractOptimizationProblem problem) { + ClusteringHillClimbing chc = new ClusteringHillClimbing(); + chc.SetProblem(problem); + + 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, 100, problem, randSeed, defaultTerminator()); + } + + public static final GOParameters cmaES(AbstractOptimizationProblem problem) { + EvolutionStrategies es = new EvolutionStrategies(); + es.setMu(15); + es.setLambda(50); + es.setPlusStrategy(false); + + AbstractEAIndividual indyTemplate = problem.getIndividualTemplate(); + if ((indyTemplate != null) + && (indyTemplate instanceof InterfaceESIndividual)) { + // Set CMA operator for mutation + AbstractEAIndividual indy = (AbstractEAIndividual) indyTemplate; + MutateESCovarianceMatrixAdaption cmaMut = new MutateESCovarianceMatrixAdaption(); + cmaMut.setCheckConstraints(true); + AbstractEAIndividual.setOperators(indy, cmaMut, 1., new CrossoverESDefault(), 0.); + } else { + System.err + .println("Error, CMA-ES is implemented for ES individuals only (requires double data types)"); + return null; + } + + return makeESParams(es, problem); + } + + /** + * Create a new IPOP-CMA-ES strategy with Rank-mu-CMA. The population size is set to + * lambda = (int) (4.0 + 3.0 * Math.log(dim)) and mu = Math.floor(lambda/2.), but + * lambda may grow during optimization due to restarts with increased lambda. + * Operator probabilities are set to p_mut = 1 and p_c = 0. + * The given problem must work with an individual template which implements + * InterfaceDataTypeDouble. + * + * @param problem the optimization problem + * @return + */ + public static final GOParameters cmaESIPOP(AbstractOptimizationProblem problem) { + EvolutionStrategies es = new EvolutionStrategyIPOP(); + + AbstractEAIndividual indyTemplate = problem.getIndividualTemplate(); + if ((indyTemplate != null) && ((indyTemplate instanceof InterfaceESIndividual) || (indyTemplate instanceof InterfaceDataTypeDouble))) { + // set selection strategy + int dim; + if (indyTemplate instanceof InterfaceESIndividual) dim=((InterfaceESIndividual)indyTemplate).getDGenotype().length; + else dim = ((InterfaceDataTypeDouble)indyTemplate).getDoubleData().length; + int lambda = (int) (4.0 + 3.0 * Math.log(dim)); + es.setGenerationStrategy((int)Math.floor(lambda/2.),lambda, false); + es.setForceOrigPopSize(false); + // Set CMA operator for mutation + AbstractEAIndividual indy = (AbstractEAIndividual) indyTemplate; + MutateESRankMuCMA cmaMut = new MutateESRankMuCMA(); + AbstractEAIndividual.setOperators(indy, cmaMut, 1., new CrossoverESDefault(), 0.); + } else { + System.err + .println("Error, CMA-ES is implemented for ES individuals only (requires double data types)"); + return null; + } + + return makeESParams(es, problem); + } + public static final GOParameters standardDE( AbstractOptimizationProblem problem) { DifferentialEvolution de = new DifferentialEvolution(); - Population pop = new Population(); - pop.setPopulationSize(50); - de.setPopulation(pop); - de.getDEType().setSelectedTag(1); // this sets current-to-best + de.setDEType(DETypeEnum.DE2_CurrentToBest); // this sets current-to-best de.setF(0.8); de.setK(0.6); de.setLambda(0.6); de.setMt(0.05); - - return makeParams(de, pop, problem, randSeed, defaultTerminator()); + return makeParams(de, 50, problem, randSeed, defaultTerminator()); } public static final GOParameters standardES( @@ -928,43 +1072,26 @@ public class OptimizerFactory { return null; } - Population pop = new Population(); - pop.setPopulationSize(es.getLambda()); - - return makeParams(es, pop, problem, randSeed, defaultTerminator()); + return makeESParams(es, problem); } public static final GOParameters standardGA( AbstractOptimizationProblem problem) { GeneticAlgorithm ga = new GeneticAlgorithm(); - Population pop = new Population(); - pop.setPopulationSize(100); - ga.setPopulation(pop); ga.setElitism(true); - return makeParams(ga, pop, problem, randSeed, defaultTerminator()); + return makeParams(ga, 100, problem, randSeed, defaultTerminator()); } public static final GOParameters standardPSO( AbstractOptimizationProblem problem) { ParticleSwarmOptimization pso = new ParticleSwarmOptimization(); - Population pop = new Population(); - pop.setPopulationSize(30); - pso.setPopulation(pop); pso.setPhiValues(2.05, 2.05); pso.getTopology().setSelectedTag("Grid"); - return makeParams(pso, pop, problem, randSeed, defaultTerminator()); - } - - public static String terminatedBecause() { - return (lastRunnable != null) ? lastRunnable.terminatedBecause() : null; + return makeParams(pso, 30, problem, randSeed, defaultTerminator()); } public static final GOParameters tribes(AbstractOptimizationProblem problem) { - Tribes tr = new Tribes(); - Population pop = new Population(); - pop.setPopulationSize(1); // only for init - problem.initPopulation(pop); - return makeParams(tr, pop, problem, randSeed, defaultTerminator()); + return makeParams(new Tribes(), 1, problem, randSeed, defaultTerminator()); } } diff --git a/src/eva2/gui/BeanInspector.java b/src/eva2/gui/BeanInspector.java index 7cfa910b..224a5f1e 100644 --- a/src/eva2/gui/BeanInspector.java +++ b/src/eva2/gui/BeanInspector.java @@ -158,6 +158,10 @@ public class BeanInspector { sbuf.append(" ]"); return sbuf.toString(); } + + if (type.isEnum()) { + return Target.toString(); + } if (Target instanceof List && !(Target instanceof Population)) { // handle the list case StringBuffer sbuf = new StringBuffer("[ "); @@ -566,6 +570,7 @@ public class BeanInspector { * @return */ public static Object decodeType(Class destType, Object value) { +// System.err.println("desttype: " + destType.toString() + ", val: " + value.getClass().toString()); if (destType.isAssignableFrom(value.getClass())) { // value is already of destType or assignable (subclass), so just return it return value; @@ -575,8 +580,9 @@ public class BeanInspector { else return value.toString(); } else if (isJavaPrimitive(destType)) { try { - if (value.getClass() == String.class) return stringToPrimitive((String)value, destType); - else { + if (value.getClass() == String.class) { + return stringToPrimitive((String)value, destType); + } else { return doubleToPrimitive(toDouble(value), destType); } } catch(Exception e) { diff --git a/src/eva2/server/go/enums/DETypeEnum.java b/src/eva2/server/go/enums/DETypeEnum.java new file mode 100644 index 00000000..0bd1d48f --- /dev/null +++ b/src/eva2/server/go/enums/DETypeEnum.java @@ -0,0 +1,6 @@ +package eva2.server.go.enums; + +public enum DETypeEnum { + DE1_Rand_1, DE2_CurrentToBest, DE_Best_2, TrigonometricDE; + //", "DE2 - DE/current-to-best/1", "DE/best/2", "Trigonometric DE"}; +} diff --git a/src/eva2/server/go/enums/ESMutationInitialSigma.java b/src/eva2/server/go/enums/ESMutationInitialSigma.java new file mode 100644 index 00000000..f058c5c7 --- /dev/null +++ b/src/eva2/server/go/enums/ESMutationInitialSigma.java @@ -0,0 +1,5 @@ +package eva2.server.go.enums; + +public enum ESMutationInitialSigma { + halfRange, avgInitialDistance, userDefined; +} diff --git a/src/eva2/server/go/individuals/AbstractEAIndividual.java b/src/eva2/server/go/individuals/AbstractEAIndividual.java index 25a4739a..c1c45885 100644 --- a/src/eva2/server/go/individuals/AbstractEAIndividual.java +++ b/src/eva2/server/go/individuals/AbstractEAIndividual.java @@ -753,9 +753,13 @@ public abstract class AbstractEAIndividual implements IndividualInterface, java. m_dataHash.put(name, obj); } - /** This method will return a stored object. - * @param name The name of the requested Object. - * @return Object + /** + * This method will return a stored object associated with a key String. + * The String "Fitness" is always a valid key connected to the + * individual fitness array. + * + * @param name The name of the requested Object + * @return Object The associated object or null if none is found */ public Object getData(String name) { // if (name.equalsIgnoreCase("SelectionProbability")) return this.getSelectionProbability(); @@ -764,13 +768,32 @@ public abstract class AbstractEAIndividual implements IndividualInterface, java. // if (name.equalsIgnoreCase("FitnessArray")) return this.getFitness(); Object data = m_dataHash.get(name); if (data==null) { // Fitness is actually in use... so lets have a minor special treatment - if (name.compareToIgnoreCase("Fitness")==0) data = getFitness(); - else { - EVAERROR.errorMsgOnce("Warning: data key " + name + " unknown (pot. multiple errors)!"); - } +// try { + if (name.compareToIgnoreCase("Fitness")==0) data = getFitness(); + else { + EVAERROR.errorMsgOnce("Warning: data key " + name + " unknown (pot. multiple errors)!"); +// throw new RuntimeException(name + ": unknown key!"); + } +// } catch(Exception e) { +// e.printStackTrace(System.err); +// } } return data; } + + /** + * Check whether the individual has an object in store which is associated with + * the given key String. The String "Fitness" is always a valid key connected to the + * individual fitness array. + * + * @param key The name of the requested Object. + * @return true if data is associated with the key, else false + */ + public boolean hasData(String key) { + if (m_dataHash.get(key)==null) { + return (key.compareToIgnoreCase("Fitness")==0); + } else return true; + } /** This method will return a string description of the Individal * noteably the Genotype. @@ -794,8 +817,10 @@ public abstract class AbstractEAIndividual implements IndividualInterface, java. sb.append(BeanInspector.toString(individual.getFitness())); sb.append(", ID: "); sb.append(individual.getIndyID()); - sb.append(", parents: "); - sb.append(BeanInspector.toString(individual.getParentIDs())); + if (individual.getParentIDs()!=null) { + sb.append(", parents: "); + sb.append(BeanInspector.toString(individual.getParentIDs())); + } return sb.toString(); } diff --git a/src/eva2/server/go/operators/distancemetric/PhenotypeMetric.java b/src/eva2/server/go/operators/distancemetric/PhenotypeMetric.java index 7a7078a9..fd3d29d4 100644 --- a/src/eva2/server/go/operators/distancemetric/PhenotypeMetric.java +++ b/src/eva2/server/go/operators/distancemetric/PhenotypeMetric.java @@ -13,13 +13,11 @@ import eva2.server.go.individuals.InterfaceDataTypePermutation; import eva2.server.go.individuals.InterfaceDataTypeProgram; import eva2.server.go.individuals.codings.gp.InterfaceProgram; -/** A phenotype metric suited for some of the most common - * data types. - * Created by IntelliJ IDEA. +/** + * A phenotype metric suited for the most common data types. + * * User: streiche * Date: 19.07.2005 - * Time: 14:50:17 - * To change this template use File | Settings | File Templates. */ public class PhenotypeMetric implements InterfaceDistanceMetric, java.io.Serializable { private static PhenotypeMetric pMetric = null; diff --git a/src/eva2/server/go/operators/mutation/MutateESCovarianceMatrixAdaption.java b/src/eva2/server/go/operators/mutation/MutateESCovarianceMatrixAdaption.java index 93f0d0f9..23f25fc2 100644 --- a/src/eva2/server/go/operators/mutation/MutateESCovarianceMatrixAdaption.java +++ b/src/eva2/server/go/operators/mutation/MutateESCovarianceMatrixAdaption.java @@ -4,6 +4,7 @@ import eva2.server.go.individuals.AbstractEAIndividual; import eva2.server.go.individuals.InterfaceESIndividual; import eva2.server.go.populations.Population; import eva2.server.go.problems.InterfaceOptimizationProblem; +import eva2.tools.Mathematics; import wsi.ra.math.RNG; import wsi.ra.math.Jama.EigenvalueDecomposition; import wsi.ra.math.Jama.Matrix; @@ -252,11 +253,8 @@ public class MutateESCovarianceMatrixAdaption implements InterfaceMutation, java } } } - if (this.m_CheckConstraints == true) { // CSpieth - for (int i = 0; i < this.m_D; i++) { - if (x[i] < range[i][0]) x[i] = range[i][0]; - if (x[i] > range[i][1]) x[i] = range[i][1]; - } + if (this.m_CheckConstraints) { // CSpieth + Mathematics.projectToRange(x, range); } } diff --git a/src/eva2/server/go/operators/mutation/MutateESMainVectorAdaption.java b/src/eva2/server/go/operators/mutation/MutateESMainVectorAdaption.java index 83e11b89..033621ff 100644 --- a/src/eva2/server/go/operators/mutation/MutateESMainVectorAdaption.java +++ b/src/eva2/server/go/operators/mutation/MutateESMainVectorAdaption.java @@ -4,6 +4,7 @@ import eva2.server.go.individuals.AbstractEAIndividual; import eva2.server.go.individuals.InterfaceESIndividual; import eva2.server.go.populations.Population; import eva2.server.go.problems.InterfaceOptimizationProblem; +import eva2.tools.Mathematics; import wsi.ra.math.RNG; /** @@ -182,10 +183,7 @@ public class MutateESMainVectorAdaption implements InterfaceMutation, java.io.Se x[i] = x[i] + this.m_SigmaScalar * (this.m_Z[i] + this.Z1 * this.w_v * this.m_main_v[i]); } if (getCheckConstraints()) { // MK: lets actually do a constraint check - for (int i = 0; i < x.length; i++) { - if (x[i] < range[i][0]) x[i] = range[i][0]; - if (x[i] > range[i][1]) x[i] = range[i][1]; - } + Mathematics.projectToRange(x, range); } } diff --git a/src/eva2/server/go/operators/mutation/MutateESRankMuCMA.java b/src/eva2/server/go/operators/mutation/MutateESRankMuCMA.java index 111934cc..3cb02005 100644 --- a/src/eva2/server/go/operators/mutation/MutateESRankMuCMA.java +++ b/src/eva2/server/go/operators/mutation/MutateESRankMuCMA.java @@ -7,6 +7,8 @@ import wsi.ra.math.RNG; import wsi.ra.math.Jama.EigenvalueDecomposition; import wsi.ra.math.Jama.Matrix; import eva2.gui.BeanInspector; +import eva2.gui.GenericObjectEditor; +import eva2.server.go.enums.ESMutationInitialSigma; import eva2.server.go.individuals.AbstractEAIndividual; import eva2.server.go.individuals.InterfaceDataTypeDouble; import eva2.server.go.populations.Population; @@ -17,11 +19,10 @@ import eva2.tools.Pair; /** - * Implementing CMA ES with rank-mu-update and weighted recombination. This is partly based on the - * java implementation provided on http://www.bionik.tu-berlin.de/user/niko/cmaes_inmatlab.html. - * - * N.Hansen & S.Kern 2004: Evaluating the CMA Evolution Strategy on Multimodal Test Functions. - * Parallel Problem Solving from Nature 2004. + * Implementing CMA ES with rank-mu-update and weighted recombination. More information can be found here: + * - http://www.bionik.tu-berlin.de/user/niko/cmaesintro.html + * - N.Hansen & S.Kern 2004: Evaluating the CMA Evolution Strategy on Multimodal Test Functions. + * Parallel Problem Solving from Nature 2004. * * @author mkron * @@ -31,7 +32,8 @@ public class MutateESRankMuCMA implements InterfaceMutationGenerational, Seriali private double c_c, expRandStepLen; private double[] z, zCor; - private InitialSigmaEnum initialSig = InitialSigmaEnum.avgInitialDistance; + private ESMutationInitialSigma initializeSig = ESMutationInitialSigma.avgInitialDistance; + private double userDefInitSig = 0.2; private static double firstSigma = -1.; private static double sigma; private static double d_sig, c_sig; @@ -58,7 +60,7 @@ public class MutateESRankMuCMA implements InterfaceMutationGenerational, Seriali // this.d_sig = mutator.d_sig; this.expRandStepLen = mutator.expRandStepLen; this.dim = mutator.dim; - this.initialSig = mutator.initialSig; + this.initializeSig = mutator.initializeSig; // if (mutator.meanX != null) this.meanX = (double[]) mutator.meanX.clone(); // if (mutator.pathC != null) this.pathC = (double[]) mutator.pathC.clone(); @@ -81,11 +83,14 @@ public class MutateESRankMuCMA implements InterfaceMutationGenerational, Seriali * @return */ private double getInitSigma(Population initGen) { - switch (initialSig) { + switch (initializeSig) { case avgInitialDistance: // scaled by average range as the measures are normed - return initGen.getPopulationMeasures()[0]*getAvgRange(); + //return initGen.getPopulationMeasures(null)[0]*getAvgRange(); + // use euclidian measures without normation and scaling + return initGen.getPopulationMeasures(null)[0]; case halfRange: return getAvgRange()/2.; + case userDefined: return userDefInitSig ; default: return 0.2; } } @@ -97,7 +102,7 @@ public class MutateESRankMuCMA implements InterfaceMutationGenerational, Seriali mu = selectedP.size(); lambda = oldGen.size(); if (mu>= lambda) { - EVAERROR.errorMsgOnce("Warning: invalid mu/lambda ratio! Setting mu to lambda/2."); + EVAERROR.errorMsgOnce("Warning: invalid mu/lambda ratio (" + mu + "/" + lambda + ") ! Setting mu to lambda/2."); mu = lambda/2; } if (!firstAdaptionDone) { @@ -107,6 +112,7 @@ public class MutateESRankMuCMA implements InterfaceMutationGenerational, Seriali // c_u_sig = Math.sqrt(c_sig * (2.-c_sig)); d_sig = c_sig+1+2*Math.max(0, Math.sqrt((muEff-1)/(dim+1)) - 1); sigma = getInitSigma(oldGen); +// System.out.println("INitial sigma: "+sigma); firstSigma = sigma; meanX = oldGen.getCenter(); // this might be ok? } @@ -496,16 +502,16 @@ public class MutateESRankMuCMA implements InterfaceMutationGenerational, Seriali private double[] mutate(double[] x, double[][] range, int count) { if (firstAdaptionDone) { - double[] artmp = new double[x.length]; + double[] sampl = new double[x.length]; // generate scaled random vector (D * z) for (int i = 0; i < dim; ++i) { - artmp[i] = Math.sqrt(eigenvalues[i]) * RNG.gaussianDouble(1.); + sampl[i] = Math.sqrt(eigenvalues[i]) * RNG.gaussianDouble(1.); } // System.out.println("Sampling around " + BeanInspector.toString(meanX)); /* add mutation (sigma * B * (D*z)) */ for (int i = 0; i < dim; ++i) { double sum = 0.; for (int j = 0; j < dim; ++j) - sum += mB.get(i,j) * artmp[j]; + sum += mB.get(i,j) * sampl[j]; x[i] = meanX[i]+getSigma(i)*sum; } } else { @@ -551,21 +557,26 @@ public class MutateESRankMuCMA implements InterfaceMutationGenerational, Seriali return firstSigma; } + public void hideHideable() { + this.setInitializeSigma(getInitializeSigma()); + } + /** * @return the initialSig */ - public InitialSigmaEnum getInitialSigma() { - return initialSig; + public ESMutationInitialSigma getInitializeSigma() { + return initializeSig; } /** * @param initialSig the initialSig to set */ - public void setInitialSigma(InitialSigmaEnum initialSig) { - this.initialSig = initialSig; + public void setInitializeSigma(ESMutationInitialSigma initialSig) { + this.initializeSig = initialSig; + GenericObjectEditor.setHideProperty(this.getClass(), "userDefInitSig", initialSig!=ESMutationInitialSigma.userDefined); } - public String initialSigmaTipText() { + public String initializeSigmaTipText() { return "Method to use for setting the initial step size."; } @@ -646,8 +657,18 @@ public class MutateESRankMuCMA implements InterfaceMutationGenerational, Seriali return true; } else return false; } -} -enum InitialSigmaEnum { - halfRange, avgInitialDistance; -} + /** + * @return the userDefInitSig + */ + public double getUserDefInitSig() { + return userDefInitSig; + } + + /** + * @param userDefInitSig the userDefInitSig to set + */ + public void setUserDefInitSig(double userDefInitSig) { + this.userDefInitSig = userDefInitSig; + } +} \ No newline at end of file diff --git a/src/eva2/server/go/populations/Population.java b/src/eva2/server/go/populations/Population.java index 7434a7d3..24cfa124 100644 --- a/src/eva2/server/go/populations/Population.java +++ b/src/eva2/server/go/populations/Population.java @@ -16,6 +16,7 @@ import eva2.server.go.individuals.AbstractEAIndividualComparator; import eva2.server.go.individuals.GAIndividualBinaryData; import eva2.server.go.operators.distancemetric.InterfaceDistanceMetric; import eva2.server.go.operators.distancemetric.PhenotypeMetric; +import eva2.server.go.operators.selection.probability.AbstractSelProb; import eva2.tools.EVAERROR; import eva2.tools.Mathematics; import eva2.tools.Pair; @@ -884,6 +885,9 @@ public class Population extends ArrayList implements PopulationInterface, Clonea /** * Returns the average, minimal and maximal individual distance as diversity measure for the population. + * If the given metric argument is null, the euclidian distance of individual positions is used, which + * presumes that {@link AbstractEAIndividual.getDoublePosition(indy)} returns a valid double position for the + * individuals of the population. * This is of course rather expensive computationally. * * @return the average, minimal and maximal mean distance of individuals in an array of three @@ -898,7 +902,9 @@ public class Population extends ArrayList implements PopulationInterface, Clonea for (int i = 0; i < this.size(); i++) { for (int j = i+1; j < this.size(); j++) { - d = metric.distance((AbstractEAIndividual)this.get(i), (AbstractEAIndividual)this.get(j)); + if (metric == null) d = PhenotypeMetric.euclidianDistance(AbstractEAIndividual.getDoublePosition(getEAIndividual(i)), + AbstractEAIndividual.getDoublePosition(getEAIndividual(j))); + else d = metric.distance((AbstractEAIndividual)this.get(i), (AbstractEAIndividual)this.get(j)); meanDist += d; if (d < minDist) minDist = d; if (d > maxDist) maxDist = d; @@ -941,6 +947,32 @@ public class Population extends ArrayList implements PopulationInterface, Clonea return centerPos; } + /** + * Return the population center weighted by fitness, using the same scaling as provided + * by a SelectionProbability instance. + * This only works for those individuals that have a position representation, meaning that + * AbstractEAIndidivual.getDoublePosition(individual) returns a valid position. + * If they dont, null is returned. + * + * @see AbstractEAIndidivual.getDoublePosition(individual) + * @param criterion + * @return + */ + public double[] getCenterWeighted(AbstractSelProb selProb, int criterion, boolean obeyConst) { + selProb.computeSelectionProbability(this, "Fitness", obeyConst); + double[] mean = AbstractEAIndividual.getDoublePosition(getEAIndividual(0)); + if (mean != null) { + Arrays.fill(mean, 0.); + AbstractEAIndividual indy = null; + for (int i=0; i getPopulationSize()) remove(size()-1); + if (size() < getPopulationSize()) { + if (size() == 0) System.err.println("Cannot grow empty population!"); + else { + int origSize=size(); + int k=0; + while (size()< getPopulationSize()) { + addIndividual((AbstractEAIndividual)getEAIndividual(k%origSize).clone()); + } + } + } + } + } + + /** + * Calculate the fitness sum over all individuals for one criterion. + * + * @param criterion + * @return the fitness sum over all individuals for one criterio + */ + public double getFitSum(int criterion) { + double fSum = 0.; + for (int i=0; i range[i][1]) newPos[i] = range[i][1]; - } - } - + Mathematics.vvAdd(newPos, rand, newPos); + if (m_CheckConstraints) { + Mathematics.projectToRange(newPos, range); + } + if (indy instanceof InterfaceDataTypeDouble) ((InterfaceDataTypeDouble)indy).SetDoubleGenotype(newPos); else endy.SetDoubleGenotype(newPos); diff --git a/src/eva2/server/go/strategies/EvolutionStrategies.java b/src/eva2/server/go/strategies/EvolutionStrategies.java index add9803b..cc888b95 100644 --- a/src/eva2/server/go/strategies/EvolutionStrategies.java +++ b/src/eva2/server/go/strategies/EvolutionStrategies.java @@ -45,7 +45,7 @@ public class EvolutionStrategies implements InterfaceOptimizer, java.io.Serializ private int m_NumberOfPartners = 1; private int origPopSize = -1; // especially for CBN // private double[] m_FitnessOfParents = null; - private boolean forceOrigPopSize = true;// especially for CBN + private boolean forceOrigPopSize = true;// especially for CBN transient private String m_Identifier = ""; transient private InterfacePopulationChangedEventListener m_Listener; @@ -73,6 +73,14 @@ public class EvolutionStrategies implements InterfaceOptimizer, java.io.Serializ this.m_EnvironmentSelection = (InterfaceSelection)a.m_EnvironmentSelection.clone(); } + /** + * Set to true in CBN, false for any extension which changes the population size during optimization. + * @param force + */ + public void setForceOrigPopSize(boolean force) { + forceOrigPopSize = force; + } + public void hideHideable() { GenericObjectEditor.setHideProperty(this.getClass(), "population", true); } @@ -88,6 +96,7 @@ public class EvolutionStrategies implements InterfaceOptimizer, java.io.Serializ // this.m_Population.setPopulationSize(this.m_InitialPopulationSize); // } //System.out.println("init"); + checkPopulationConstraints(); this.m_Problem.initPopulation(this.m_Population); this.evaluatePopulation(this.m_Population); // this.m_Population.setPopulationSize(orgPopSize); @@ -318,14 +327,19 @@ public class EvolutionStrategies implements InterfaceOptimizer, java.io.Serializ this.checkPopulationConstraints(); } - /** This method will check the population constraints + /** + * This method will check the population constraints * myu <= lambda and will calculate the population size * accordingly. */ - private void checkPopulationConstraints() { - if (this.m_Lambda < this.m_Mu) this.m_Lambda = this.m_Mu; + protected void checkPopulationConstraints() { + if (this.m_Lambda < this.m_Mu) { + System.err.println("Invalid mu/lambda ratio! Setting mu=lambda="+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); + origPopSize=m_Population.getPopulationSize(); } /** This method allows you to set an identifier for the algorithm @@ -377,7 +391,7 @@ public class EvolutionStrategies implements InterfaceOptimizer, java.io.Serializ public void setPopulation(Population pop){ origPopSize = pop.size(); -// System.out.println("ES: orig popsize is " + origPopSize); +// System.err.println("In ES: orig popsize is " + origPopSize); this.m_Population = pop; } public String populationTipText() { @@ -444,7 +458,7 @@ public class EvolutionStrategies implements InterfaceOptimizer, java.io.Serializ */ public void setPlusStrategy (boolean elitism) { this.m_UsePlusStrategy = elitism; - this.checkPopulationConstraints(); +// this.checkPopulationConstraints(); // do this on init only } public boolean isPlusStrategy() { return this.m_UsePlusStrategy; @@ -500,7 +514,7 @@ public class EvolutionStrategies implements InterfaceOptimizer, java.io.Serializ */ public void setMu(int mu) { this.m_Mu = mu; - this.checkPopulationConstraints(); +// this.checkPopulationConstraints(); // do this on init only } public int getMu() { return this.m_Mu; @@ -514,7 +528,7 @@ public class EvolutionStrategies implements InterfaceOptimizer, java.io.Serializ */ public void setLambda(int lambda) { this.m_Lambda = lambda; - this.checkPopulationConstraints(); +// this.checkPopulationConstraints(); // do this on init only } public int getLambda() { return this.m_Lambda; diff --git a/src/eva2/server/go/strategies/EvolutionStrategyIPOP.java b/src/eva2/server/go/strategies/EvolutionStrategyIPOP.java index 934c48dd..f0cf6858 100644 --- a/src/eva2/server/go/strategies/EvolutionStrategyIPOP.java +++ b/src/eva2/server/go/strategies/EvolutionStrategyIPOP.java @@ -45,13 +45,21 @@ public class EvolutionStrategyIPOP extends EvolutionStrategies implements Interf LinkedList bestList = null; AbstractEAIndividual best = null; + public EvolutionStrategyIPOP(int mu, int lambda, boolean usePlus) { + super(mu, lambda, usePlus); + setForceOrigPopSize(false); + setInitialLambda(lambda); + } + public EvolutionStrategyIPOP() { super(); + setForceOrigPopSize(false); setMu(5); setLambda(10); } public EvolutionStrategyIPOP(EvolutionStrategyIPOP other) { + super(other); dim = other.dim; initialLambda = other.initialLambda; incPopSizeFact = other.incPopSizeFact; @@ -109,6 +117,7 @@ public class EvolutionStrategyIPOP extends EvolutionStrategies implements Interf // increase by at least one int newLambda = Math.max((int)(getLambda()*incPopSizeFact), getLambda() + 1); setLambda(newLambda); + checkPopulationConstraints(); // update the stagnation time in the terminator if (!isStagnationTimeUserDef() && (fitConvTerm != null)) { fitConvTerm.setStagnationTime(calcDefaultStagnationTime()); @@ -136,9 +145,12 @@ public class EvolutionStrategyIPOP extends EvolutionStrategies implements Interf public void init() { // setMu(initialMu); if (getMu()>initialLambda) { + System.err.println("mu is " + getMu() + ", initial lambda was "+initialLambda); setMu((initialLambda/2)+1); System.err.println("Warning, too small initial lambda, adapting mu to " + getMu()); } + checkPopulationConstraints(); + setForceOrigPopSize(false); super.setLambda(initialLambda); getPopulation().setNotifyEvalInterval(initialLambda); super.init(); @@ -233,12 +245,18 @@ public class EvolutionStrategyIPOP extends EvolutionStrategies implements Interf return "An ES with increasing population size."; } + protected void checkPopulationConstraints() { + if (getLambda()!=initialLambda) setLambda(initialLambda); + if (getMu()>getLambda()) System.err.println("Invalid mu/lambda ratio!"); + super.checkPopulationConstraints(); + } + /** Set an initial population size (if smaller lambda this is ignored). * @param l The inital population size. */ public void setInitialLambda(int l) { initialLambda = l; - if (initialLambda < getMu()) setMu((initialLambda/2)+1); +// if (initialLambda < getMu()) setMu((initialLambda/2)+1); // do this on init } public int getInitialLambda() { diff --git a/src/eva2/server/go/strategies/ParticleSwarmOptimization.java b/src/eva2/server/go/strategies/ParticleSwarmOptimization.java index 441d8abf..32e7a28a 100644 --- a/src/eva2/server/go/strategies/ParticleSwarmOptimization.java +++ b/src/eva2/server/go/strategies/ParticleSwarmOptimization.java @@ -160,6 +160,7 @@ public class ParticleSwarmOptimization implements InterfaceOptimizer, java.io.Se this.m_Problem.initPopulation(this.m_Population); tracedVelocity = null; // evaluation needs to be done here now, as its omitted if reset is false + initDefaults(this.m_Population); this.evaluatePopulation(this.m_Population); initByPopulation(m_Population, false); } @@ -211,7 +212,10 @@ public class ParticleSwarmOptimization implements InterfaceOptimizer, java.io.Se */ protected void traceEMA(Population population) { if (population.get(0) instanceof InterfaceDataTypeDouble) { - double[] curAvVelAndSpeed = getPopulationVelSpeed(population, 3); + double[] curAvVelAndSpeed; + if (population.getGeneration() == 0) return; + + curAvVelAndSpeed = getPopulationVelSpeed(population, 3); double[][] range = ((InterfaceDataTypeDouble)population.get(0)).getDoubleRange(); if (tracedVelocity == null) { tracedVelocity = new double[((InterfaceDataTypeDouble)population.get(0)).getDoubleData().length]; @@ -362,16 +366,9 @@ public class ParticleSwarmOptimization implements InterfaceOptimizer, java.io.Se if (reset) this.m_Population.init(); AbstractEAIndividual indy; -// double[] tmpD, writeData; -// double sum; - for (int i = 0; i < this.m_Population.size(); i++) { - indy = (AbstractEAIndividual) this.m_Population.get(i); - if (indy instanceof InterfaceDataTypeDouble) { - initIndividualDefaults(indy); - } - indy.SetData(indexKey, i); - indy.setIndividualIndex(i); - } + + if (!defaultsDone(m_Population.getEAIndividual(0))) initDefaults(m_Population); + if (reset) this.evaluatePopulation(this.m_Population); for (int i = 0; i < this.m_Population.size(); i++) { @@ -391,6 +388,27 @@ public class ParticleSwarmOptimization implements InterfaceOptimizer, java.io.Se treeOrphans = pop.size()-getMaxNodes(treeBranchDeg, treeLevels-1); treeLastFullLevelNodeCnt = (int)Math.pow(treeBranchDeg, treeLevels-1); } + + private boolean defaultsDone(AbstractEAIndividual individual) { + return individual.hasData(indexKey); + } + + /** + * Initialize individual defaults for the given population. + * + * @param pop + */ + protected void initDefaults(Population pop) { + AbstractEAIndividual indy; + for (int i = 0; i < pop.size(); i++) { + indy = (AbstractEAIndividual) pop.get(i); + if (indy instanceof InterfaceDataTypeDouble) { + initIndividualDefaults(indy); + } + indy.SetData(indexKey, i); + indy.setIndividualIndex(i); + } + } /** * Return the number of nodes of a complete n-ary tree with given branching factor and depth. @@ -727,7 +745,7 @@ public class ParticleSwarmOptimization implements InterfaceOptimizer, java.io.Se return accel; } - public static void main(String[] args) { +// public static void main(String[] args) { // ParticleSwarmOptimization pso = new ParticleSwarmOptimization(); // GVector tmp, vec = new GVector(5); // GVector vecSum = new GVector(5); @@ -750,7 +768,7 @@ public class ParticleSwarmOptimization implements InterfaceOptimizer, java.io.Se // } // //vecSum.normalize(); // //System.out.println(vec.toString() + " -> " + vecSum.toString()); - } +// } /** * Return a random vector after a gaussian distribution oriented along dir, meaning that @@ -1120,6 +1138,17 @@ public class ParticleSwarmOptimization implements InterfaceOptimizer, java.io.Se this.firePropertyChangedEvent("NextGenerationPerformed"); if (sleepTime > 0 ) try { Thread.sleep(sleepTime); } catch(Exception e) {} + + maybeClearPlot(); + } + + protected void maybeClearPlot() { + if (((m_Population.getGeneration() % 23) == 0) && isShow() && (m_Plot != null)) { + m_Plot.clearAll(); + InterfaceDataTypeDouble indy = (InterfaceDataTypeDouble)this.m_Population.get(0); + double[][] range = indy.getDoubleRange(); + m_Plot.setCornerPoints(range, 0); + } } /** @@ -1312,9 +1341,6 @@ public class ParticleSwarmOptimization implements InterfaceOptimizer, java.io.Se if (this.m_Plot == null) { InterfaceDataTypeDouble indy = (InterfaceDataTypeDouble)this.m_Population.get(0); double[][] range = indy.getDoubleRange(); - double[] tmpD = new double[2]; - tmpD[0] = 0; - tmpD[1] = 0; this.m_Plot = new eva2.gui.Plot("PSO "+ m_Population.getGeneration(), "x1", "x2", range[0], range[1]); // this.m_Plot.setUnconnectedPoint(range[0][0], range[1][0], 0); // this.m_Plot.setUnconnectedPoint(range[0][1], range[1][1], 0); @@ -1399,9 +1425,11 @@ public class ParticleSwarmOptimization implements InterfaceOptimizer, java.io.Se } public void setPopulation(Population pop){ this.m_Population = pop; - for (int i=0; i= 2)); -// GenericObjectEditor.setHideProperty(getClass(), "subSwarmRadius", (s.getSelectedTag().getID() != 3)); -// GenericObjectEditor.setHideProperty(getClass(), "subSwarmSize", (s.getSelectedTag().getID() != 3)); } public SelectedTag getTopology() { return ((ParticleSwarmOptimization)this.m_Optimizer).getTopology(); diff --git a/src/eva2/tools/Mathematics.java b/src/eva2/tools/Mathematics.java index 56b5025e..99a962b7 100644 --- a/src/eva2/tools/Mathematics.java +++ b/src/eva2/tools/Mathematics.java @@ -687,4 +687,30 @@ public class Mathematics { for (int i=1; irange.length) System.err.println("Invalid vector length, x is longer than range! (Mathematics.projectToRange)"); + for (int i=0; irange[i][1]) { + viols++; + x[i]=range[i][1]; + } + } + return viols; + } } diff --git a/src/wsi/ra/math/RNG.java b/src/wsi/ra/math/RNG.java index 27dad673..d4c95318 100644 --- a/src/wsi/ra/math/RNG.java +++ b/src/wsi/ra/math/RNG.java @@ -307,5 +307,37 @@ public class RNG extends Random { Mathematics.normVect(result, result); return result; } + + /** + * Create a uniform random double vector within the given bounds (inclusive) in every dimension. + * + * @param n + * @param lower + * @param upper + * @return + */ + public static double[] randomVector(int n, double lower, double upper) { + double[] result = new double[n]; + for (int i = 0; i < result.length; i++) { + result[i] = RNG.randomDouble(lower, upper); + } + return result; + } + + /** + * Create a uniform random integer vector within the given bounds (inclusive) in every dimension. + * + * @param n + * @param lower + * @param upper + * @return + */ + public static int[] randomVector(int n, int lower, int upper) { + int[] result = new int[n]; + for (int i = 0; i < result.length; i++) { + result[i] = RNG.randomInt(lower, upper); + } + return result; + } }