From 9efebe8b4b7d36704368df9d7fbfb37c9136f1a0 Mon Sep 17 00:00:00 2001 From: Fabian Becker Date: Sat, 1 Nov 2014 18:13:36 +0100 Subject: [PATCH 1/5] Initial commit of new dynamic CLI mode. --- src/eva2/cli/NewMain.java | 15 ++ src/eva2/cli/OptimizationBuilder.java | 190 ++++++++++++++++++++++++++ 2 files changed, 205 insertions(+) create mode 100644 src/eva2/cli/NewMain.java create mode 100644 src/eva2/cli/OptimizationBuilder.java diff --git a/src/eva2/cli/NewMain.java b/src/eva2/cli/NewMain.java new file mode 100644 index 00000000..94105618 --- /dev/null +++ b/src/eva2/cli/NewMain.java @@ -0,0 +1,15 @@ +package eva2.cli; + +import eva2.optimization.go.InterfaceOptimizationParameters; + +/** + * Created by becker on 01.11.2014. + */ +public class NewMain { + + public static void main(String[] args) { + InterfaceOptimizationParameters parameters = OptimizationBuilder.parseArguments(args); + + + } +} diff --git a/src/eva2/cli/OptimizationBuilder.java b/src/eva2/cli/OptimizationBuilder.java new file mode 100644 index 00000000..c33b502d --- /dev/null +++ b/src/eva2/cli/OptimizationBuilder.java @@ -0,0 +1,190 @@ +package eva2.cli; + +import eva2.gui.BeanInspector; +import eva2.optimization.go.InterfaceOptimizationParameters; +import eva2.optimization.modules.OptimizationParameters; +import eva2.tools.ReflectPackage; +import eva2.util.annotation.Hidden; +import eva2.util.annotation.Parameter; + +import java.beans.BeanInfo; +import java.beans.IntrospectionException; +import java.beans.Introspector; +import java.beans.PropertyDescriptor; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.HashMap; +import java.util.LinkedHashMap; + +class ArgumentTree extends LinkedHashMap { + private Object value; + + public void setValue(Object value) { + this.value = value; + } + + public Object getValue() { + return this.value; + } + + @Override + public String toString() { + return ((value != null) ? value.toString() + ", " : "") + super.toString(); + } + + /** + * If there are no key, value pairs present and the value is unset, + * this tree belongs to a flag. + * + * @return + */ + public boolean isFlag() { + return this.size() == 0 && this.value == null; + } +} +/** + * + */ +public final class OptimizationBuilder { + private OptimizationBuilder() {} + + public static InterfaceOptimizationParameters parseArguments(String[] args) { + HashMap argumentMap = new HashMap<>(args.length/2); + int i = 0; + while (i < args.length) { + // Is it a parameter? + if (args[i].startsWith("--")) { + String key = args[i].substring(2); + String value = null; + // Is the next a value? + if (i < args.length - 1 && !args[i+1].startsWith("--")) { + value = args[i + 1]; + argumentMap.put(key, value); + i = i + 2; + } else { + argumentMap.put(key, null); + i++; + } + } + } + System.out.println(argumentMap.toString()); + ArgumentTree argumentTree = new ArgumentTree(); + for (String key : argumentMap.keySet()) { + insertIntoArgumentTree(argumentTree, key, argumentMap.get(key)); + } + System.out.println(argumentTree.toString()); + + return constructFromArgumentTree(OptimizationParameters.class, argumentTree); + } + + private static void insertIntoArgumentTree(ArgumentTree tree, String key, String value) { + // Basic type? + if (!key.contains("-")) { + if (!tree.containsKey(key)) { + tree.put(key, new ArgumentTree()); + } + ((ArgumentTree)tree.get(key)).setValue(value); + } else { + String baseKey = key.substring(0, key.indexOf('-')); + String restKey = key.substring(key.indexOf('-') + 1); + if (!tree.containsKey(baseKey)) { + tree.put(baseKey, new ArgumentTree()); + } + insertIntoArgumentTree((ArgumentTree)tree.get(baseKey), restKey, value); + } + } + + /** + * + * @param clazz + * @param tree Tree containing key, value pairs + */ + private static T constructFromArgumentTree(Class clazz, ArgumentTree tree) { + T instance = null; + + // Create new instance + if (clazz.isInterface() || Modifier.isAbstract(clazz.getModifiers())) { + // Find subclasses of clazz that match tree.getValue() + } else { + Class[] params = new Class[0]; + try { + Constructor constr = clazz.getConstructor(params); + instance = (T)constr.newInstance(null); + } catch (NoSuchMethodException | InvocationTargetException | InstantiationException | IllegalAccessException ex) { + ex.printStackTrace(); + } + } + + BeanInfo info; + try { + if (clazz.isInterface()) { + info = Introspector.getBeanInfo(clazz); + } else { + info = Introspector.getBeanInfo(clazz, Object.class); + } + PropertyDescriptor[] properties = info.getPropertyDescriptors(); + for (PropertyDescriptor pd : properties) { + String name = pd.getName(); + Method getter = pd.getReadMethod(); + Method setter = pd.getWriteMethod(); + Class type = pd.getPropertyType(); + // We skip non-existing setters or setters that are hidden by annotation + if (setter == null || setter.isAnnotationPresent(Hidden.class)) { + continue; + } + System.out.println(name + " = " + " type = " + type); + + // We use the name of the descriptor or if possible + // one that is given by the @Parameter annotation. + if (setter.isAnnotationPresent(Parameter.class)) { + Parameter param = setter.getAnnotation(Parameter.class); + if (!param.name().isEmpty()) { + name = param.name(); + } + } + + /** + * If the tree contains this property we try to set it on the object. + */ + if (tree.containsKey(name)) { + Object obj; + if (type.isPrimitive() && ((ArgumentTree)tree.get(name)).getValue() != null) { + obj = BeanInspector.stringToPrimitive((String)((ArgumentTree) tree.get(name)).getValue(), type); + } else { + // The subtree has the name of the class + String className = (String)((ArgumentTree)tree.get(name)).getValue(); + // Try to get the actual class from its name + Class subType = getClassFromName(className, type); + + // Here the recursion starts + obj = constructFromArgumentTree(subType, (ArgumentTree) tree.get(name)); + } + + // We preserve the default if obj is null + if (obj != null) { + BeanInspector.callIfAvailable(instance, setter.getName(), new Object[]{obj}); + } + } + } + } catch (IntrospectionException ex) { + ex.printStackTrace(); + } + + return instance; + } + + private static Class getClassFromName(String name, Class type) { + Class[] classes = ReflectPackage.getAssignableClassesInPackage("eva2", type, true, true); + for (Class clazz : classes) { + // We allow both the fully qualified name (eva2.optimization.strategies.GeneticAlgorithm + // and the simple name (GeneticAlgorithm) + if (clazz.getName().equals(name) || clazz.getSimpleName().equals(name)) { + return clazz; + } + } + + return null; + } +} From 2a2162c5da16e698fefe707fdbd7ad21b6282912 Mon Sep 17 00:00:00 2001 From: Fabian Becker Date: Sat, 1 Nov 2014 18:59:28 +0100 Subject: [PATCH 2/5] More @Parameters and a fix for empty getters. --- src/eva2/cli/OptimizationBuilder.java | 10 ++++++++-- .../problems/AbstractOptimizationProblem.java | 8 +------- src/eva2/problems/AbstractProblemDouble.java | 16 ++++------------ 3 files changed, 13 insertions(+), 21 deletions(-) diff --git a/src/eva2/cli/OptimizationBuilder.java b/src/eva2/cli/OptimizationBuilder.java index c33b502d..f3975b71 100644 --- a/src/eva2/cli/OptimizationBuilder.java +++ b/src/eva2/cli/OptimizationBuilder.java @@ -155,8 +155,14 @@ public final class OptimizationBuilder { } else { // The subtree has the name of the class String className = (String)((ArgumentTree)tree.get(name)).getValue(); - // Try to get the actual class from its name - Class subType = getClassFromName(className, type); + + Class subType; + if (className != null) { + // Try to get the actual class from its name + subType = getClassFromName(className, type); + } else { + subType = type; + } // Here the recursion starts obj = constructFromArgumentTree(subType, (ArgumentTree) tree.get(name)); diff --git a/src/eva2/problems/AbstractOptimizationProblem.java b/src/eva2/problems/AbstractOptimizationProblem.java index 28749526..7b23d762 100644 --- a/src/eva2/problems/AbstractOptimizationProblem.java +++ b/src/eva2/problems/AbstractOptimizationProblem.java @@ -87,13 +87,11 @@ public abstract class AbstractOptimizationProblem implements InterfaceOptimizati return parallelThreads; } + @Parameter(name = "parallel", description = "Set the number of threaded parallel function evaluations - interesting for slow functions and generational optimizers.") public void setParallelThreads(int parallelThreads) { this.parallelThreads = parallelThreads; } - public String parallelThreadsTipText() { - return "Set the number of threaded parallel function evaluations - interesting for slow functions and generational optimizers."; - } /** * This method initializes the problem instance. @@ -406,10 +404,6 @@ public abstract class AbstractOptimizationProblem implements InterfaceOptimizati return template; } - public String individualTemplateTipText() { - return "Choose the individual representation to use."; - } - /** * This method extracts the individuals from a given population that are assumed to correspond to local or global optima. * Similar individuals are clustered together with a density based clustering method diff --git a/src/eva2/problems/AbstractProblemDouble.java b/src/eva2/problems/AbstractProblemDouble.java index 74cf3d59..6bca47d6 100644 --- a/src/eva2/problems/AbstractProblemDouble.java +++ b/src/eva2/problems/AbstractProblemDouble.java @@ -22,6 +22,7 @@ import eva2.tools.diagram.ColorBarCalculator; import eva2.tools.math.Jama.Matrix; import eva2.tools.math.Mathematics; import eva2.tools.math.RNG; +import eva2.util.annotation.Parameter; /** * For a double valued problem, there are two main methods to implement: @@ -285,6 +286,7 @@ public abstract class AbstractProblemDouble extends AbstractOptimizationProblem * * @param noise The sigma for a gaussian random number. */ + @Parameter(description = "Gaussian noise level on the fitness value.") public void setNoise(double noise) { if (noise < 0) { noise = 0; @@ -301,15 +303,12 @@ public abstract class AbstractProblemDouble extends AbstractOptimizationProblem return this.noise; } - public String noiseTipText() { - return "Gaussian noise level on the fitness value."; - } - /** * This method allows you to choose the EA individual used by the problem. * * @param indy The EAIndividual type */ + @Parameter(name = "individual", description = "Base individual type defining the data representation and mutation/crossover operators") public void setEAIndividual(InterfaceDataTypeDouble indy) { this.template = (AbstractEAIndividual) indy; } @@ -324,10 +323,6 @@ public abstract class AbstractProblemDouble extends AbstractOptimizationProblem return (InterfaceDataTypeDouble) this.template; } - public String EAIndividualTipText() { - return "Set the base individual type defining the data representation and mutation/crossover operators"; - } - /** * A (symmetric) absolute range limit. * @@ -351,6 +346,7 @@ public abstract class AbstractProblemDouble extends AbstractOptimizationProblem return "Absolute limit for the symmetric range in any dimension"; } + @Parameter(name = "rotate", description = "If marked, the function is rotated by 22.5 degrees along every axis.") public void setDoRotation(boolean doRotation) { this.doRotation = doRotation; if (!doRotation) { @@ -362,10 +358,6 @@ public abstract class AbstractProblemDouble extends AbstractOptimizationProblem return doRotation; } - public String doRotationTipText() { - return "If marked, the function is rotated by 22.5 degrees along every axis."; - } - /** * ******************************************************************************************************************* * These are for InterfaceParamControllable From 29a1bb64e3b5f0c42dce63b5c285eaf81fe9c34f Mon Sep 17 00:00:00 2001 From: Fabian Becker Date: Sun, 2 Nov 2014 13:39:58 +0100 Subject: [PATCH 3/5] Performance Optimization in CLI mode refs #30 - Abort object building if all params found --- src/eva2/cli/OptimizationBuilder.java | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/eva2/cli/OptimizationBuilder.java b/src/eva2/cli/OptimizationBuilder.java index f3975b71..1d94412f 100644 --- a/src/eva2/cli/OptimizationBuilder.java +++ b/src/eva2/cli/OptimizationBuilder.java @@ -110,13 +110,18 @@ public final class OptimizationBuilder { } else { Class[] params = new Class[0]; try { - Constructor constr = clazz.getConstructor(params); - instance = (T)constr.newInstance(null); + Constructor constructor = clazz.getConstructor(params); + instance = (T)constructor.newInstance(null); } catch (NoSuchMethodException | InvocationTargetException | InstantiationException | IllegalAccessException ex) { ex.printStackTrace(); } } + /* No need to continue if there are no parameters to set */ + if (tree.isEmpty()) { + return instance; + } + BeanInfo info; try { if (clazz.isInterface()) { @@ -125,6 +130,7 @@ public final class OptimizationBuilder { info = Introspector.getBeanInfo(clazz, Object.class); } PropertyDescriptor[] properties = info.getPropertyDescriptors(); + int foundParameters = 0; for (PropertyDescriptor pd : properties) { String name = pd.getName(); Method getter = pd.getReadMethod(); @@ -149,6 +155,7 @@ public final class OptimizationBuilder { * If the tree contains this property we try to set it on the object. */ if (tree.containsKey(name)) { + foundParameters++; Object obj; if (type.isPrimitive() && ((ArgumentTree)tree.get(name)).getValue() != null) { obj = BeanInspector.stringToPrimitive((String)((ArgumentTree) tree.get(name)).getValue(), type); @@ -173,6 +180,11 @@ public final class OptimizationBuilder { BeanInspector.callIfAvailable(instance, setter.getName(), new Object[]{obj}); } } + + // If we configured all parameters in the tree we can break the loop + if (tree.size() == foundParameters) { + break; + } } } catch (IntrospectionException ex) { ex.printStackTrace(); From 89402e0b05d17bec2e64c6e0d123e8729d7ae7ee Mon Sep 17 00:00:00 2001 From: Fabian Becker Date: Sun, 2 Nov 2014 13:40:31 +0100 Subject: [PATCH 4/5] Hide several elements from the UI --- .../individuals/AbstractEAIndividual.java | 2 +- .../individuals/ESIndividualDoubleData.java | 13 ++-------- .../GAESIndividualBinaryDoubleData.java | 10 +++---- .../individuals/GAIndividualDoubleData.java | 15 +++-------- .../individuals/GAPIndividualProgramData.java | 10 +++---- ...IOBGAIndividualIntegerPermutationData.java | 10 +++---- .../operator/crossover/TestESCrossover.java | 4 +-- .../optimization/population/Population.java | 9 ++++--- src/eva2/optimization/strategies/ANPSO.java | 2 +- .../strategies/ArtificialBeeColony.java | 2 +- .../strategies/MultiObjectiveCMAES.java | 2 +- .../ParticleFilterOptimization.java | 2 +- .../ParticleSubSwarmOptimization.java | 2 +- .../strategies/tribes/TribesExplorer.java | 4 +-- .../tools/ImpactOfDimensionOnMOEAs.java | 2 +- .../AbstractMultiModalProblemKnown.java | 2 +- .../problems/AbstractOptimizationProblem.java | 2 +- src/eva2/problems/BKnapsackProblem.java | 2 +- src/eva2/problems/SimpleProblemWrapper.java | 26 ++++--------------- 19 files changed, 44 insertions(+), 77 deletions(-) diff --git a/src/eva2/optimization/individuals/AbstractEAIndividual.java b/src/eva2/optimization/individuals/AbstractEAIndividual.java index b7ad9005..5adea385 100644 --- a/src/eva2/optimization/individuals/AbstractEAIndividual.java +++ b/src/eva2/optimization/individuals/AbstractEAIndividual.java @@ -275,7 +275,7 @@ public abstract class AbstractEAIndividual implements IndividualInterface, java. * * @param opt The optimization problem that is to be solved. */ - public void init(InterfaceOptimizationProblem opt) { + public void initialize(InterfaceOptimizationProblem opt) { initializationOperator.initialize(this, opt); this.mutationOperator.initialize(this, opt); this.crossoverOperator.init(this, opt); diff --git a/src/eva2/optimization/individuals/ESIndividualDoubleData.java b/src/eva2/optimization/individuals/ESIndividualDoubleData.java index 56caa43c..c1d7aa3e 100644 --- a/src/eva2/optimization/individuals/ESIndividualDoubleData.java +++ b/src/eva2/optimization/individuals/ESIndividualDoubleData.java @@ -105,9 +105,6 @@ public class ESIndividualDoubleData extends AbstractEAIndividual implements Inte } } -/************************************************************************************ - * InterfaceDataTypeDouble methods - */ /** * This method allows you to request a certain amount of double data * @@ -235,17 +232,14 @@ public class ESIndividualDoubleData extends AbstractEAIndividual implements Inte System.arraycopy(doubleData, 0, this.genotype, 0, doubleData.length); } -/************************************************************************************ - * AbstractEAIndividual methods - */ /** * This method will allow a default initialisation of the individual * * @param opt The optimization problem that is to be solved. */ @Override - public void init(InterfaceOptimizationProblem opt) { - super.init(opt); + public void initialize(InterfaceOptimizationProblem opt) { + super.initialize(opt); // evil operators may not respect the range, so at least give some hint if (!Mathematics.isInRange(genotype, range)) { EVAERROR.errorMsgOnce("Warning: Individual out of range after initialization (and potential initial crossover/mutation)!"); @@ -304,9 +298,6 @@ public class ESIndividualDoubleData extends AbstractEAIndividual implements Inte return strB.toString(); } -/************************************************************************************ - * InterfaceESIndividual methods - */ /** * This method will allow the user to read the ES 'genotype' * diff --git a/src/eva2/optimization/individuals/GAESIndividualBinaryDoubleData.java b/src/eva2/optimization/individuals/GAESIndividualBinaryDoubleData.java index 721d6e50..37bcc469 100644 --- a/src/eva2/optimization/individuals/GAESIndividualBinaryDoubleData.java +++ b/src/eva2/optimization/individuals/GAESIndividualBinaryDoubleData.java @@ -76,9 +76,9 @@ public class GAESIndividualBinaryDoubleData extends AbstractEAIndividual impleme * @param opt The optimization problem that is to be solved. */ @Override - public void init(InterfaceOptimizationProblem opt) { - ((AbstractEAIndividual) this.doubleIndividual).init(opt); - ((AbstractEAIndividual) this.binaryIndividual).init(opt); + public void initialize(InterfaceOptimizationProblem opt) { + ((AbstractEAIndividual) this.doubleIndividual).initialize(opt); + ((AbstractEAIndividual) this.binaryIndividual).initialize(opt); } @Override @@ -105,8 +105,8 @@ public class GAESIndividualBinaryDoubleData extends AbstractEAIndividual impleme ((AbstractEAIndividual) this.binaryIndividual).initByValue(((Object[]) obj)[0], opt); } } else { - ((AbstractEAIndividual) this.doubleIndividual).init(opt); - ((AbstractEAIndividual) this.binaryIndividual).init(opt); + ((AbstractEAIndividual) this.doubleIndividual).initialize(opt); + ((AbstractEAIndividual) this.binaryIndividual).initialize(opt); System.out.println("Initial value for GAESIndividualDoubleData is not suitable!"); } } diff --git a/src/eva2/optimization/individuals/GAIndividualDoubleData.java b/src/eva2/optimization/individuals/GAIndividualDoubleData.java index 21770a5d..20682a31 100644 --- a/src/eva2/optimization/individuals/GAIndividualDoubleData.java +++ b/src/eva2/optimization/individuals/GAIndividualDoubleData.java @@ -10,6 +10,7 @@ import eva2.optimization.operator.mutation.MutateGAUniform; import eva2.problems.InterfaceOptimizationProblem; import eva2.tools.math.RNG; import eva2.util.annotation.Description; +import eva2.util.annotation.Parameter; import java.util.BitSet; @@ -229,10 +230,6 @@ public class GAIndividualDoubleData extends AbstractEAIndividual implements Inte } } -/************************************************************************************ - * AbstractEAIndividual methods - */ - /** * This method will initialize the individual with a given value for the * phenotype. @@ -373,6 +370,7 @@ public class GAIndividualDoubleData extends AbstractEAIndividual implements Inte * * @param coding The used genotype coding method */ + @Parameter(name = "coding", description = "Choose the coding to use.") public void setGACoding(InterfaceGADoubleCoding coding) { this.doubleCoding = coding; } @@ -381,16 +379,13 @@ public class GAIndividualDoubleData extends AbstractEAIndividual implements Inte return this.doubleCoding; } - public String gADoubleCodingTipText() { - return "Choose the coding to use."; - } - /** * This method allows you to set the number of mulitruns that are to be performed, * necessary for stochastic optimizers to ensure reliable results. * * @param precision The number of multiruns that are to be performed */ + @Parameter(description = "Gives the number of bits to be used to code a double.") public void setPrecision(int precision) { this.precision = precision; } @@ -398,8 +393,4 @@ public class GAIndividualDoubleData extends AbstractEAIndividual implements Inte public int getPrecision() { return this.precision; } - - public String precisionTipText() { - return "Gives the number of bits to be used to code a double."; - } } diff --git a/src/eva2/optimization/individuals/GAPIndividualProgramData.java b/src/eva2/optimization/individuals/GAPIndividualProgramData.java index c924e35d..72a47d5c 100644 --- a/src/eva2/optimization/individuals/GAPIndividualProgramData.java +++ b/src/eva2/optimization/individuals/GAPIndividualProgramData.java @@ -72,9 +72,9 @@ public class GAPIndividualProgramData extends AbstractEAIndividual implements In * @param opt The optimization problem that is to be solved. */ @Override - public void init(InterfaceOptimizationProblem opt) { - ((AbstractEAIndividual) this.numberData).init(opt); - ((AbstractEAIndividual) this.programData).init(opt); + public void initialize(InterfaceOptimizationProblem opt) { + ((AbstractEAIndividual) this.numberData).initialize(opt); + ((AbstractEAIndividual) this.programData).initialize(opt); } @Override @@ -101,8 +101,8 @@ public class GAPIndividualProgramData extends AbstractEAIndividual implements In ((AbstractEAIndividual) this.programData).initByValue(((Object[]) obj)[0], opt); } } else { - ((AbstractEAIndividual) this.numberData).init(opt); - ((AbstractEAIndividual) this.programData).init(opt); + ((AbstractEAIndividual) this.numberData).initialize(opt); + ((AbstractEAIndividual) this.programData).initialize(opt); System.out.println("Initial value for GAPIndividualDoubleData is not suitable!"); } } diff --git a/src/eva2/optimization/individuals/GIOBGAIndividualIntegerPermutationData.java b/src/eva2/optimization/individuals/GIOBGAIndividualIntegerPermutationData.java index 2dc12cdd..084fe372 100644 --- a/src/eva2/optimization/individuals/GIOBGAIndividualIntegerPermutationData.java +++ b/src/eva2/optimization/individuals/GIOBGAIndividualIntegerPermutationData.java @@ -72,9 +72,9 @@ public class GIOBGAIndividualIntegerPermutationData extends AbstractEAIndividual * @param opt The optimization problem that is to be solved. */ @Override - public void init(InterfaceOptimizationProblem opt) { - ((AbstractEAIndividual) this.integerData).init(opt); - ((AbstractEAIndividual) this.permutationData).init(opt); + public void initialize(InterfaceOptimizationProblem opt) { + ((AbstractEAIndividual) this.integerData).initialize(opt); + ((AbstractEAIndividual) this.permutationData).initialize(opt); } @Override @@ -101,8 +101,8 @@ public class GIOBGAIndividualIntegerPermutationData extends AbstractEAIndividual ((AbstractEAIndividual) this.permutationData).initByValue(((Object[]) obj)[0], opt); } } else { - ((AbstractEAIndividual) this.integerData).init(opt); - ((AbstractEAIndividual) this.permutationData).init(opt); + ((AbstractEAIndividual) this.integerData).initialize(opt); + ((AbstractEAIndividual) this.permutationData).initialize(opt); System.out.println("Initial value for GIOBGAIndividualIntegerPermutationData is not suitable!"); } } diff --git a/src/eva2/optimization/operator/crossover/TestESCrossover.java b/src/eva2/optimization/operator/crossover/TestESCrossover.java index b4ec62c8..65adef3a 100644 --- a/src/eva2/optimization/operator/crossover/TestESCrossover.java +++ b/src/eva2/optimization/operator/crossover/TestESCrossover.java @@ -110,12 +110,12 @@ public class TestESCrossover implements java.io.Serializable { tmpIndyD.setDoubleRange(newRange); for (int i = 0; i < partners.getTargetSize(); i++) { tmpIndyEA = (AbstractEAIndividual) ((AbstractEAIndividual) tmpIndyD).clone(); - tmpIndyEA.init(optimizationProblem); + tmpIndyEA.initialize(optimizationProblem); partners.add(tmpIndyEA); } partners.init(); daddy = (AbstractEAIndividual) ((AbstractEAIndividual) tmpIndyD).clone(); - daddy.init(optimizationProblem); + daddy.initialize(optimizationProblem); plot.clearAll(); plot.setUnconnectedPoint(-2, -2, 0); plot.setUnconnectedPoint(2, 2, 0); diff --git a/src/eva2/optimization/population/Population.java b/src/eva2/optimization/population/Population.java index 32f537ec..97462e20 100644 --- a/src/eva2/optimization/population/Population.java +++ b/src/eva2/optimization/population/Population.java @@ -15,6 +15,7 @@ import eva2.tools.math.Mathematics; import eva2.tools.math.RNG; import eva2.tools.math.StatisticUtils; import eva2.util.annotation.Description; +import eva2.util.annotation.Hidden; import eva2.util.annotation.Parameter; import java.util.*; @@ -602,6 +603,7 @@ public class Population extends ArrayList implements PopulationInterface, Clonea return historyList; } + @Hidden public void setHistory(LinkedList theHist) { historyList = theHist; } @@ -684,6 +686,7 @@ public class Population extends ArrayList implements PopulationInterface, Clonea * * @param d The new number of functioncalls. */ + @Hidden public void setFunctionCalls(int d) { this.functionCallCount = d; } @@ -738,6 +741,7 @@ public class Population extends ArrayList implements PopulationInterface, Clonea * * @param gen the value to set as new generation index */ + @Hidden public void setGeneration(int gen) { this.generationCount = gen; } @@ -2519,11 +2523,8 @@ public class Population extends ArrayList implements PopulationInterface, Clonea return seedCardinality; } + @Parameter(description = "The initial cardinality for binary genotype individuals, given as pair of mean and std.dev.") public void setSeedCardinality(Pair seedCardinality) { this.seedCardinality = seedCardinality; } - - public String seedCardinalityTipText() { - return "The initial cardinality for binary genotype individuals, given as pair of mean and std.dev."; - } } diff --git a/src/eva2/optimization/strategies/ANPSO.java b/src/eva2/optimization/strategies/ANPSO.java index 215ea2e6..9df2c4b7 100644 --- a/src/eva2/optimization/strategies/ANPSO.java +++ b/src/eva2/optimization/strategies/ANPSO.java @@ -541,7 +541,7 @@ public class ANPSO extends NichePSO implements InterfaceAdditionalPopulationInfo if (reinitSuperfl) { for (int i = 0; i < tmpPop.size(); i++) { AbstractEAIndividual indy = tmpPop.getEAIndividual(i); - indy.init(optimizationProblem); + indy.initialize(optimizationProblem); indy.resetFitness(Double.MAX_VALUE); // TODO this is not so nice... they should be collected in a reinit-list and inserted at the beginning of the next optimize step ParticleSwarmOptimization.initIndividualDefaults(indy, 0.2); ParticleSwarmOptimization.initIndividualMemory(indy); diff --git a/src/eva2/optimization/strategies/ArtificialBeeColony.java b/src/eva2/optimization/strategies/ArtificialBeeColony.java index 8191b8bd..beacd1d5 100644 --- a/src/eva2/optimization/strategies/ArtificialBeeColony.java +++ b/src/eva2/optimization/strategies/ArtificialBeeColony.java @@ -194,7 +194,7 @@ public class ArtificialBeeColony extends AbstractOptimizer implements Serializab */ AbstractEAIndividual oldestIndy = getOldestIndividual(); if (oldestIndy.getAge() > this.maxTrials) { - oldestIndy.init(this.optimizationProblem); + oldestIndy.initialize(this.optimizationProblem); this.optimizationProblem.evaluate(oldestIndy); this.population.incrFunctionCalls(); } diff --git a/src/eva2/optimization/strategies/MultiObjectiveCMAES.java b/src/eva2/optimization/strategies/MultiObjectiveCMAES.java index b5ab0ad2..38a42de8 100644 --- a/src/eva2/optimization/strategies/MultiObjectiveCMAES.java +++ b/src/eva2/optimization/strategies/MultiObjectiveCMAES.java @@ -100,7 +100,7 @@ public class MultiObjectiveCMAES extends AbstractOptimizer implements Serializab /* * (non-Javadoc) * - * @see eva2.optimization.strategies.InterfaceOptimizer#init() + * @see eva2.optimization.strategies.InterfaceOptimizer#initialize() */ @Override public void initialize() { diff --git a/src/eva2/optimization/strategies/ParticleFilterOptimization.java b/src/eva2/optimization/strategies/ParticleFilterOptimization.java index 379a536a..e780edf9 100644 --- a/src/eva2/optimization/strategies/ParticleFilterOptimization.java +++ b/src/eva2/optimization/strategies/ParticleFilterOptimization.java @@ -146,7 +146,7 @@ public class ParticleFilterOptimization extends AbstractOptimizer implements jav int i; for (i = 0; (i + parents.getTargetSize()) < pop.getTargetSize(); i++) { immi = (AbstractEAIndividual) pop.getEAIndividual(0).clone(); - immi.init(getProblem()); + immi.initialize(getProblem()); parents.add(immi); } parents.synchSize(); diff --git a/src/eva2/optimization/strategies/ParticleSubSwarmOptimization.java b/src/eva2/optimization/strategies/ParticleSubSwarmOptimization.java index b2996da3..2f7183c0 100644 --- a/src/eva2/optimization/strategies/ParticleSubSwarmOptimization.java +++ b/src/eva2/optimization/strategies/ParticleSubSwarmOptimization.java @@ -481,7 +481,7 @@ public class ParticleSubSwarmOptimization extends ParticleSwarmOptimizationGCPSO for (int i = 0; i < tmp.getTargetSize(); i++) { tmpIndy = (AbstractEAIndividual) template.clone(); - tmpIndy.init(prob); + tmpIndy.initialize(prob); tmp.add(tmpIndy); } tmp.init(); diff --git a/src/eva2/optimization/strategies/tribes/TribesExplorer.java b/src/eva2/optimization/strategies/tribes/TribesExplorer.java index 9be3c417..da6f85c8 100644 --- a/src/eva2/optimization/strategies/tribes/TribesExplorer.java +++ b/src/eva2/optimization/strategies/tribes/TribesExplorer.java @@ -954,7 +954,7 @@ v[d] = cmin * v[d]; } @Override - public void init(InterfaceOptimizationProblem opt) { + public void initialize(InterfaceOptimizationProblem opt) { // TODO whats this for? for (int i = 0; i < this.position.x.length; i++) { this.position.x[0] = 0.; @@ -983,7 +983,7 @@ v[d] = cmin * v[d]; } this.setDoubleGenotype(x); } else { - this.init(opt); + this.initialize(opt); System.err.println("Initial value for ESIndividualDoubleData is not double[]!"); } } diff --git a/src/eva2/optimization/tools/ImpactOfDimensionOnMOEAs.java b/src/eva2/optimization/tools/ImpactOfDimensionOnMOEAs.java index 9ee4b7d4..0fe0f795 100644 --- a/src/eva2/optimization/tools/ImpactOfDimensionOnMOEAs.java +++ b/src/eva2/optimization/tools/ImpactOfDimensionOnMOEAs.java @@ -104,7 +104,7 @@ public class ImpactOfDimensionOnMOEAs { ((InterfaceDataTypeDouble) template).setDoubleDataLength(numberOfVariables); for (int i = 0; i < popSize; i++) { tmpIndy = (AbstractEAIndividual) template.clone(); - tmpIndy.init(null); + tmpIndy.initialize(null); pop.add(tmpIndy); } } diff --git a/src/eva2/problems/AbstractMultiModalProblemKnown.java b/src/eva2/problems/AbstractMultiModalProblemKnown.java index c05714d1..26b092f8 100644 --- a/src/eva2/problems/AbstractMultiModalProblemKnown.java +++ b/src/eva2/problems/AbstractMultiModalProblemKnown.java @@ -57,7 +57,7 @@ public abstract class AbstractMultiModalProblemKnown extends AbstractProblemDoub ((InterfaceDataTypeDouble) this.template).setDoubleRange(makeRange()); for (int i = 0; i < population.getTargetSize(); i++) { tmpIndy = (AbstractEAIndividual) this.template.clone(); - tmpIndy.init(this); + tmpIndy.initialize(this); population.add(tmpIndy); } // population initialize must be last diff --git a/src/eva2/problems/AbstractOptimizationProblem.java b/src/eva2/problems/AbstractOptimizationProblem.java index 7b23d762..bf1052d6 100644 --- a/src/eva2/problems/AbstractOptimizationProblem.java +++ b/src/eva2/problems/AbstractOptimizationProblem.java @@ -189,7 +189,7 @@ public abstract class AbstractOptimizationProblem implements InterfaceOptimizati for (int i = 0; i < population.getTargetSize(); i++) { tmpIndy = (AbstractEAIndividual) template.clone(); - tmpIndy.init(prob); + tmpIndy.initialize(prob); population.add(tmpIndy); } // population initialize must be last diff --git a/src/eva2/problems/BKnapsackProblem.java b/src/eva2/problems/BKnapsackProblem.java index bea94ccc..43674ac3 100644 --- a/src/eva2/problems/BKnapsackProblem.java +++ b/src/eva2/problems/BKnapsackProblem.java @@ -160,7 +160,7 @@ public class BKnapsackProblem extends AbstractProblemBinary implements java.io.S } protected void initIndy(int k, AbstractEAIndividual indy) { - indy.init(this); + indy.initialize(this); if (RNG.flipCoin(this.problemSpecificInit)) { BitSet tmpSet = new BitSet(); tmpSet.clear(); diff --git a/src/eva2/problems/SimpleProblemWrapper.java b/src/eva2/problems/SimpleProblemWrapper.java index dc0623ab..494f65d9 100644 --- a/src/eva2/problems/SimpleProblemWrapper.java +++ b/src/eva2/problems/SimpleProblemWrapper.java @@ -12,6 +12,7 @@ import eva2.problems.simple.InterfaceSimpleProblem; import eva2.problems.simple.SimpleF1; import eva2.problems.simple.SimpleProblemBinary; import eva2.problems.simple.SimpleProblemDouble; +import eva2.util.annotation.Parameter; import java.util.BitSet; @@ -164,6 +165,7 @@ public class SimpleProblemWrapper extends AbstractOptimizationProblem { /** * @param simProb the simProb to set */ + @Parameter(description = "Set the simple problem class which is to be optimized") public void setSimpleProblem(InterfaceSimpleProblem simProb) { this.simProb = simProb; initTemplate(); @@ -186,19 +188,13 @@ public class SimpleProblemWrapper extends AbstractOptimizationProblem { } } - /** - * - */ - public String simpleProblemTipText() { - return "Set the simple problem class which is to be optimized"; - } - /** * 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. */ + @Parameter(description = "Gaussian noise level on the fitness value.") public void setNoise(double noise) { if (noise < 0) { noise = 0; @@ -210,11 +206,6 @@ public class SimpleProblemWrapper extends AbstractOptimizationProblem { return this.noise; } - public String noiseTipText() { - return "Gaussian noise level on the fitness value."; - } - - /** * A (symmetric) absolute range limit. * @@ -229,15 +220,12 @@ public class SimpleProblemWrapper extends AbstractOptimizationProblem { * * @param defaultRange */ + @Parameter(name = "range", description = "Absolute limit for the symmetric range in any dimension") public void setDefaultRange(double defaultRange) { this.defaultRange = defaultRange; initTemplate(); } - public String defaultRangeTipText() { - return "Absolute limit for the symmetric range in any dimension"; - } - /** * Take care that all properties which may be hidden (and currently are) send a "hide" message to the Java Bean properties. * This is called by PropertySheetPanel in use with the GenericObjectEditor. @@ -246,16 +234,12 @@ public class SimpleProblemWrapper extends AbstractOptimizationProblem { setSimpleProblem(getSimpleProblem()); } + @Parameter(name = "individual", description = "Set the individual properties for the optimization") public void setIndividualTemplate(AbstractEAIndividual indy) { resetTemplate = false; template = indy; } - @Override - public String individualTemplateTipText() { - return "Set the individual properties for the optimization"; - } - /** * This method returns a string describing the optimization problem. * From edaa58bd5a7df70a8ad335bc546fddf56fc02450 Mon Sep 17 00:00:00 2001 From: Fabian Becker Date: Sun, 2 Nov 2014 14:03:23 +0100 Subject: [PATCH 5/5] Remove apache, gson, cli, reflection dependencies for slimmer EvA2 package. --- pom.xml | 21 - src/eva2/cli/Main.java | 712 +----------------- src/eva2/cli/NewMain.java | 15 - src/eva2/cli/OptimizationBuilder.java | 2 +- .../statistics/EvAStatisticalEvaluation.java | 13 +- src/eva2/tools/Serializer.java | 2 - 6 files changed, 10 insertions(+), 755 deletions(-) delete mode 100644 src/eva2/cli/NewMain.java diff --git a/pom.xml b/pom.xml index 52106efb..ee9496c2 100644 --- a/pom.xml +++ b/pom.xml @@ -27,27 +27,6 @@ javahelp 2.0.05 - - org.apache.commons - commons-math3 - 3.1.1 - - - commons-cli - commons-cli - 1.2 - - - com.google.code.gson - gson - 2.3 - compile - - - org.reflections - reflections - 0.9.9 - diff --git a/src/eva2/cli/Main.java b/src/eva2/cli/Main.java index b951db4b..4d2e3308 100644 --- a/src/eva2/cli/Main.java +++ b/src/eva2/cli/Main.java @@ -1,719 +1,15 @@ package eva2.cli; -import com.google.gson.*; -import eva2.OptimizerFactory; -import eva2.optimization.OptimizationStateListener; -import eva2.optimization.enums.DEType; -import eva2.optimization.enums.PSOTopology; -import eva2.optimization.population.InterfacePopulationChangedEventListener; -import eva2.optimization.modules.OptimizationParameters; -import eva2.optimization.operator.crossover.CrossoverESDefault; -import eva2.optimization.operator.crossover.InterfaceCrossover; -import eva2.optimization.operator.mutation.InterfaceMutation; -import eva2.optimization.operator.mutation.MutateDefault; -import eva2.optimization.operator.selection.InterfaceSelection; -import eva2.optimization.operator.selection.SelectXProbRouletteWheel; -import eva2.optimization.operator.terminators.CombinedTerminator; -import eva2.optimization.operator.terminators.FitnessValueTerminator; -import eva2.optimization.population.Population; -import eva2.problems.AbstractProblemDouble; -import eva2.problems.AbstractProblemDoubleOffset; -import eva2.optimization.strategies.DifferentialEvolution; -import eva2.optimization.strategies.InterfaceOptimizer; -import org.apache.commons.cli.*; -import org.reflections.Reflections; - -import java.lang.reflect.Modifier; -import java.util.Arrays; -import java.util.Map; -import java.util.Set; -import java.util.TreeMap; -import java.util.logging.Level; -import java.util.logging.Logger; +import eva2.optimization.go.InterfaceOptimizationParameters; /** - * Main Class for the EvA2 Command Line Interface - * - * The command line interface features a limited subset of the EvA2 - * optimization suite since it's difficult to parameterize all available - * classes in EvA2 from the command line. - * Supported Features: - * - Select all optimization problems that implement InterfaceOptimizationProblem - * - Select all optimizers that implement InterfaceOptimizer - * * Not all optimizers are configurable on the command line and will run - * with default parameters. - * * Optimizers can use the @Description / @Parameter annotations to specify - * parameters for CLI - * - Configure default parameters - * * Population size - * * Number of optimization runs (multi-runs) - * - Termination: - * * Not configurable! - * * Default: EvaluationTerminator(20000) + * Created by becker on 01.11.2014. */ -public class Main implements OptimizationStateListener, InterfacePopulationChangedEventListener { - private static Logger LOGGER = Logger.getLogger(Main.class.getName()); - private int populationSize = 20; - private int numberOfRuns = 1; - private int dimension = 30; - private long seed = System.currentTimeMillis(); - - private AbstractProblemDoubleOffset problem; - private InterfaceOptimizer optimizer; - private InterfaceMutation mutator; - private InterfaceCrossover crossover; - private InterfaceSelection selection; - - private JsonObject jsonObject; - private JsonArray optimizationRuns; - private JsonArray generationsArray; - - private double[] fBias = { -4.5000000e+002, -4.5000000e+002, -4.5000000e+002, -4.5000000e+002, -3.1000000e+002, - 3.9000000e+002, -1.8000000e+002, -1.4000000e+002, -3.3000000e+002, -3.3000000e+002, 9.0000000e+001, - -4.6000000e+002, -1.3000000e+002, -3.0000000e+002, 1.2000000e+002, 1.2000000e+002, 1.2000000e+002, - 1.0000000e+001, 1.0000000e+001, 1.0000000e+001, 3.6000000e+002, 3.6000000e+002, 3.6000000e+002, - 2.6000000e+002, 2.6000000e+002}; - - /** - * Creates a set of default options used in all optimizations. - * - * @return Options Default options used for optimizations - */ - private Options createDefaultCommandLineOptions() { - Options opt = new Options(); - - opt.addOption(OptionBuilder - .withLongOpt("optimizer") - .withDescription("Optimizer") - .hasArg() - .create("op") - ); - - opt.addOption("ps", "popsize", true, "Population size"); - opt.addOption("n", "runs", true, "Number of runs to perform"); - opt.addOption("s", "seed", true, "Random seed"); - - // Those two only make sense when used in an algorithm with mutation/crossover - opt.addOption("pc", true, "Crossover Probability"); - opt.addOption("pm", true, "Mutation Probability"); - - opt.addOption("mutator", true, "Mutator Operator"); - opt.addOption("crossover", true, "Crossover Operator"); - opt.addOption("selection", true, "Selection Operator"); - - opt.addOption(OptionBuilder - .withLongOpt("help") - .withDescription("Shows this help message or specific help for [optimizer]") - .hasOptionalArgs(1) - .create('h') - ); - - opt.addOption(OptionBuilder - .withLongOpt("problem") - .withDescription("Select Optimization Problem to optimize.") - .hasArg() - .create('p') - ); - opt.addOption("dim", true, "Problem Dimension"); - return opt; - } - - - - @Override - public void performedStop() { - LOGGER.info("Optimization stopped."); - } - - @Override - public void performedStart(String infoString) { - LOGGER.info("Optimization started."); - } - - @Override - public void performedRestart(String infoString) { - LOGGER.info("Optimization restarted."); - } - - @Override - public void updateProgress(int percent, String msg) { - printProgressBar(percent); - } - - public static void printProgressBar(int percent) { - StringBuilder bar = new StringBuilder("["); - - for (int i = 0; i < 50; i++) { - if (i < (percent / 2)) { - bar.append("="); - } else if (i == (percent / 2)) { - bar.append(">"); - } else { - bar.append(" "); - } - } - - bar.append("] " + percent + "% "); - System.out.print("\r" + bar.toString()); - } - - public static Map> createOptimizerList() { - Map> optimizerList = new TreeMap<>(); - - Reflections reflections = new Reflections("eva2.optimization.strategies"); - Set> optimizers = reflections.getSubTypesOf(InterfaceOptimizer.class); - for (Class optimizer : optimizers) { - // We only want instantiable classes - if (optimizer.isInterface() || Modifier.isAbstract(optimizer.getModifiers())) { - continue; - } - optimizerList.put(optimizer.getSimpleName(), optimizer); - } - return optimizerList; - } - - public static Map> createProblemList() { - Map> problemList = new TreeMap<>(); - Reflections reflections = new Reflections("eva2.problems"); - Set> problems = reflections.getSubTypesOf(AbstractProblemDoubleOffset.class); - for (Class problem : problems) { - // We only want instantiable classes - if (problem.isInterface() || Modifier.isAbstract(problem.getModifiers())) { - continue; - } - problemList.put(problem.getSimpleName(), problem); - } - return problemList; - } - - public static Map> createMutatorList() { - Map> mutationList = new TreeMap<>(); - Reflections reflections = new Reflections("eva2.optimization.operator.mutation"); - Set> mutators = reflections.getSubTypesOf(InterfaceMutation.class); - for (Class mutator : mutators) { - // We only want instantiable classes - if (mutator.isInterface() || Modifier.isAbstract(mutator.getModifiers())) { - continue; - } - mutationList.put(mutator.getSimpleName(), mutator); - } - return mutationList; - } - - public static Map> createCrossoverList() { - Map> crossoverList = new TreeMap<>(); - Reflections reflections = new Reflections("eva2.optimization.operator.crossover"); - Set> crossovers = reflections.getSubTypesOf(InterfaceCrossover.class); - for (Class crossover : crossovers) { - // We only want instantiable classes - if (crossover.isInterface() || Modifier.isAbstract(crossover.getModifiers())) { - continue; - } - crossoverList.put(crossover.getSimpleName(), crossover); - } - return crossoverList; - } - - public static Map> createSelectionList() { - Map> selectionList = new TreeMap<>(); - Reflections reflections = new Reflections("eva2.optimization.operator.selection"); - Set> selections = reflections.getSubTypesOf(InterfaceSelection.class); - for (Class selection : selections) { - // We only want instantiable classes - if (selection.isInterface() || Modifier.isAbstract(selection.getModifiers())) { - continue; - } - selectionList.put(selection.getSimpleName(), selection); - } - return selectionList; - } - - - - public static void showHelp(Options options) { - HelpFormatter helpFormatter = new HelpFormatter(); - helpFormatter.printHelp("java -jar EvA2.jar", "Global Parameters", options, "", true); - } +public class Main { public static void main(String[] args) { - Main optimizationMain = new Main(args); - optimizationMain.runOptimization(); - } + InterfaceOptimizationParameters parameters = OptimizationBuilder.parseArguments(args); - public Main(String[] args) { - int index = Arrays.asList(args).indexOf("--"); - String[] programParams = args; - String[] optimizerParams; - - if (index >= 0) { - programParams = Arrays.copyOfRange(args, 0, index); - optimizerParams = Arrays.copyOfRange(args, index + 1, args.length); - } else { - optimizerParams = new String[]{}; - } - - this.jsonObject = new JsonObject(); - this.optimizationRuns = new JsonArray(); - this.generationsArray = new JsonArray(); - - /** - * Default command line options only require help or optimizer. - * Later we build extended command line options depending on - * the selected optimizer. - */ - Options defaultOptions = this.createDefaultCommandLineOptions(); - - /** - * Parse default options. - */ - CommandLineParser cliParser = new BasicParser(); - CommandLine commandLine = null; - try { - commandLine = cliParser.parse(defaultOptions, programParams); - } catch (ParseException e) { - showHelp(defaultOptions); - System.exit(-1); - } - - /** - * Process help and help sub pages. - */ - if (commandLine.hasOption("help")) { - String helpOption = commandLine.getOptionValue("help"); - if (helpOption == null) { - showHelp(defaultOptions); - } else { - switch (helpOption) { - case "optimizer": - showOptimizerHelp(); - break; - case "problem": - listProblems(); - break; - default: - showHelp(defaultOptions); - break; - } - } - - System.exit(0); - } - - // OK, so we've got valid parameters - let's setup the optimizer and problem - if (commandLine.hasOption("popsize")) { - this.populationSize = Integer.parseInt(commandLine.getOptionValue("popsize")); - } - - if (commandLine.hasOption("runs")) { - this.numberOfRuns = Integer.parseInt(commandLine.getOptionValue("runs")); - } - - if (commandLine.hasOption("seed")) { - this.seed = Long.parseLong(commandLine.getOptionValue("seed")); - } - - if (commandLine.hasOption("dim")) { - this.dimension = Integer.parseInt(commandLine.getOptionValue("dim")); - } - - if (commandLine.hasOption("problem")) { - String problemName = commandLine.getOptionValue("problem"); - setProblemFromName(problemName); - this.problem.setProblemDimension(this.dimension); - } else { - LOGGER.severe("No problem specified. Please specify a problem with '--problem'."); - System.exit(-1); - } - - - if (commandLine.hasOption("mutator")) { - String mutatorName = commandLine.getOptionValue("mutator"); - try { - setMutatorFromName(mutatorName); - } catch (Exception ex) { - System.out.println(ex.getMessage()); - System.exit(-1); - } - } else { - this.mutator = new MutateDefault(); - } - - if (commandLine.hasOption("crossover")) { - String crossoverName = commandLine.getOptionValue("crossover"); - try { - setCrossoverFromName(crossoverName); - } catch (Exception ex) { - System.out.println(ex.getMessage()); - System.exit(-1); - } - } else { - this.crossover = new CrossoverESDefault(); - } - - if (commandLine.hasOption("selection")) { - String selectionName = commandLine.getOptionValue("selection"); - try { - setSelectionFromName(selectionName); - } catch (Exception ex) { - System.out.println(ex.getMessage()); - System.exit(-1); - } - } else { - this.selection = new SelectXProbRouletteWheel(); - } - - // Depends on mutator/crossover/selection being set - if (commandLine.hasOption("optimizer")) { - String optimizerName = commandLine.getOptionValue("optimizer"); - try { - createOptimizerFromName(optimizerName, optimizerParams); - } catch(Exception ex) { - System.out.println(ex.getMessage()); - System.exit(-1); - } - } - - this.jsonObject.addProperty("population_size", this.populationSize); - this.jsonObject.addProperty("number_of_runs", this.numberOfRuns); - this.jsonObject.addProperty("dimension", this.dimension); - this.jsonObject.addProperty("seed", this.seed); - - JsonObject problemObject = new JsonObject(); - problemObject.addProperty("name", this.problem.getName()); - problemObject.addProperty("dimension", 30); - this.jsonObject.add("problem", problemObject); - } - - private void setMutatorFromName(String mutatorName) { - Map> mutatorList = createMutatorList(); - - Class mutator = mutatorList.get(mutatorName); - try { - this.mutator = mutator.newInstance(); - } catch (InstantiationException e) { - e.printStackTrace(); - } catch (IllegalAccessException e) { - e.printStackTrace(); - } - } - - private void setCrossoverFromName(String crossoverName) { - Map> crossoverList = createCrossoverList(); - - Class crossover = crossoverList.get(crossoverName); - try { - this.crossover = crossover.newInstance(); - } catch (InstantiationException e) { - e.printStackTrace(); - } catch (IllegalAccessException e) { - e.printStackTrace(); - } - } - - private void setSelectionFromName(String selectionName) { - Map> selectionList = createSelectionList(); - - Class selection = selectionList.get(selectionName); - try { - this.selection = selection.newInstance(); - } catch (InstantiationException e) { - e.printStackTrace(); - } catch (IllegalAccessException e) { - e.printStackTrace(); - } - } - - /** - * This method will create the various optimizers that are supported on the CLI. - * It's a really messy process since neither Java nor args4j/apache-cli can handle - * complex object parameters. The trick here is that all parameters after the - * double-dash (--) are treated as parameters for the optimization algorithm. - * - * @param optimizerName The name of the optimizer. - * @param optimizerParams The remaining command line parameters. - * @throws Exception - */ - private void createOptimizerFromName(String optimizerName, String[] optimizerParams) throws Exception { - Options opt = new Options(); - CommandLineParser cliParser = new BasicParser(); - CommandLine commandLine = null; - - switch(optimizerName) { - case "DifferentialEvolution": { - opt.addOption("F", true, "Differential Weight"); - opt.addOption("CR", true, "Crossover Rate"); - opt.addOption("DEType", true, "DE Type ()"); - /** - * Parse default options. - */ - try { - commandLine = cliParser.parse(opt, optimizerParams); - } catch (ParseException e) { - showHelp(opt); - System.exit(-1); - } - - - double f = 0.8, lambda = 0.6, cr = 0.6; - if (commandLine.hasOption("F")) { - f = Double.parseDouble(commandLine.getOptionValue("F")); - } - - if (commandLine.hasOption("CR")) { - cr = Double.parseDouble(commandLine.getOptionValue("CR")); - } - - this.optimizer = OptimizerFactory.createDifferentialEvolution(this.problem, this.populationSize, f, lambda, cr, this); - - if (commandLine.hasOption("DEType")) { - ((DifferentialEvolution)this.optimizer).setDEType( - DEType.getFromId( - Integer.parseInt(commandLine.getOptionValue("DEType")) - ) - ); - } - - break; - } - case "GeneticAlgorithm": { - double pm = 0.01, pc = 0.5; - opt.addOption("pm", true, "Mutation Probability"); - opt.addOption("pc", true, "Crossover Probability"); - - /** - * Parse default options. - */ - try { - commandLine = cliParser.parse(opt, optimizerParams); - } catch (ParseException e) { - showHelp(opt); - System.exit(-1); - } - - if (commandLine.hasOption("pm")) { - pm = Double.parseDouble(commandLine.getOptionValue("pm")); - } - - if (commandLine.hasOption("pc")) { - pc = Double.parseDouble(commandLine.getOptionValue("pc")); - } - - this.optimizer = OptimizerFactory.createGeneticAlgorithm(mutator, pm, crossover, pc, selection, this.populationSize, this.problem, this); - break; - } - case "ParticleSwarmOptimization": { - double phi1 = 2.05, phi2 = 2.05, speedLimit = 0.1; - int topoRange = 2; - PSOTopology selectedTopology = PSOTopology.star; - - opt.addOption("speedLimit", true, "Speed Limit"); - opt.addOption("topology", true, "Particle Swarm Topology (0-7)"); - opt.addOption("phi1", true, "Phi 1"); - opt.addOption("phi2", true, "Phi 2"); - - /** - * Parse default options. - */ - try { - commandLine = cliParser.parse(opt, optimizerParams); - } catch (ParseException e) { - showHelp(opt); - System.exit(-1); - } - - if (commandLine.hasOption("phi1")) { - phi1 = Double.parseDouble(commandLine.getOptionValue("phi1")); - } - - if (commandLine.hasOption("phi2")) { - phi2 = Double.parseDouble(commandLine.getOptionValue("phi2")); - } - - if (commandLine.hasOption("topology")) { - selectedTopology = PSOTopology.getFromId(Integer.parseInt(commandLine.getOptionValue("topology"))); - } - - if (commandLine.hasOption("speedLimit")) { - speedLimit = Double.parseDouble(commandLine.getOptionValue("speedLimit")); - } - - this.optimizer = OptimizerFactory.createParticleSwarmOptimization(problem, this.populationSize, phi1, phi2, speedLimit, selectedTopology, topoRange, this); - break; - } - case "EvolutionStrategies": { - double pm, pc; - int mu = 5, lambda = 20; - boolean plusStrategy = false; - - opt.addOption("pm", true, "Mutation Probability"); - opt.addOption("pc", true, "Crossover Probability"); - opt.addOption("mu", true, "Mu"); - opt.addOption("lambda", true, "Lambda"); - opt.addOption("plusStrategy", true, "Whether to use the plus or comma strategy."); - - /** - * Parse default options. - */ - try { - commandLine = cliParser.parse(opt, optimizerParams); - } catch (ParseException e) { - showHelp(opt); - System.exit(-1); - } - - if (commandLine.hasOption("pm")) { - pm = Double.parseDouble(commandLine.getOptionValue("pm")); - } else { - pm = 0.01; - } - - if (commandLine.hasOption("pc")) { - pc = Double.parseDouble(commandLine.getOptionValue("pc")); - } else { - pc = 0.9; - } - - if (commandLine.hasOption("mu")) { - mu = Integer.parseInt(commandLine.getOptionValue("mu")); - } - - if (commandLine.hasOption("lambda")) { - lambda = Integer.parseInt(commandLine.getOptionValue("lambda")); - } - - if (commandLine.hasOption("plusStrategy")) { - plusStrategy = Boolean.parseBoolean(commandLine.getOptionValue("plusStrategy")); - } - - this.optimizer = OptimizerFactory.createEvolutionStrategy(mu, lambda, plusStrategy, this.mutator, pm, this.crossover, pc, this.selection, problem, this); - break; - } - default: - throw new Exception("Unsupported Optimizer"); - } - } - - private void setProblemFromName(String problemName) { - Map> problemList = createProblemList(); - - Class problem = problemList.get(problemName); - try { - this.problem = problem.newInstance(); - } catch (InstantiationException e) { - e.printStackTrace(); - } catch (IllegalAccessException e) { - e.printStackTrace(); - } - - //setCECDefaults(this.problem); - } - - private void setCECDefaults(AbstractProblemDouble problem) { - switch(problem.getName()) { - case "F1-Problem": // F1: Shifted Sphere - this.problem.setDefaultRange(100); - this.problem.setYOffset(fBias[0]); - break; - case "F2-Problem": // F6: Shifted Rosenbrock's Function - this.problem.setDefaultRange(100); - this.problem.setYOffset(fBias[5]); - break; - case "F5-Problem": // F2: Schwefel's 1.2 - this.problem.setDefaultRange(100); - this.problem.setYOffset(fBias[1]); - break; - case "F6-Problem": // F9: Shifted Rastrigin's Function - this.problem.setDefaultRange(5); - this.problem.setYOffset(fBias[8]); - break; - default: - LOGGER.info("No CEC'05 default parameters for this problem found."); - break; - } - } - - /** - * Executes the optimization and outputs a JSON document to the command line - * with the statistics of the optimization run(s). - */ - private void runOptimization() { - for(int i = 0; i < this.numberOfRuns; i++) { - // Terminate after 10000 function evaluations OR after reaching a fitness < 0.1 - OptimizerFactory.setEvaluationTerminator(500000); - //OptimizerFactory.setTerminator(new FitnessValueTerminator(new double[]{0.0001})); - OptimizerFactory.addTerminator(new FitnessValueTerminator(new double[]{0.0001}), CombinedTerminator.OR); - - LOGGER.log(Level.INFO, "Running {0}", optimizer.getName()); - - OptimizationParameters params = OptimizerFactory.makeParams(optimizer, this.populationSize, this.problem, this.seed, OptimizerFactory.getTerminator()); - double[] result = OptimizerFactory.optimizeToDouble(params); - - JsonObject optimizationDetails = new JsonObject(); - optimizationDetails.addProperty("total_time", 1.0); - optimizationDetails.addProperty("total_function_calls", optimizer.getPopulation().getFunctionCalls()); - optimizationDetails.addProperty("termination_criteria", OptimizerFactory.terminatedBecause()); - optimizationDetails.add("generations", this.generationsArray); - - JsonArray solutionArray = new JsonArray(); - for(double val : result) { - solutionArray.add(new JsonPrimitive(val)); - } - optimizationDetails.add("solution", solutionArray); - - this.optimizationRuns.add(optimizationDetails); - - // Needs to be re-created here. - this.generationsArray = new JsonArray(); - } - - this.jsonObject.add("runs", this.optimizationRuns); - - Gson gson = new GsonBuilder().setPrettyPrinting().create(); - System.out.println(gson.toJson(this.jsonObject)); - } - - private static void showOptimizerHelp() { - Map> optimizerList = createOptimizerList(); - - System.out.println("Available Optimizers:"); - for (String name : optimizerList.keySet()) { - System.out.printf("%s\n", name); - } - } - - private static void listProblems() { - Map> problemList = createProblemList(); - - System.out.println("Available Problems:"); - for (String name : problemList.keySet()) { - System.out.printf("%s\n", name); - } - } - - @Override - public void registerPopulationStateChanged(Object source, String name) { - if (name.equals("NextGenerationPerformed")) { - InterfaceOptimizer optimizer = (InterfaceOptimizer)source; - Population population = optimizer.getPopulation(); - - JsonObject newGeneration = new JsonObject(); - newGeneration.addProperty("generation", population.getGeneration()); - newGeneration.addProperty("function_calls", population.getFunctionCalls()); - - JsonArray bestFitness = new JsonArray(); - for(double val : population.getBestFitness()) { - bestFitness.add(new JsonPrimitive(val)); - } - newGeneration.add("best_fitness", bestFitness); - - JsonArray meanFitness = new JsonArray(); - for(double val : population.getMeanFitness()) { - meanFitness.add(new JsonPrimitive(val)); - } - newGeneration.add("mean_fitness", meanFitness); - //System.out.println(newGeneration.toString()); - this.generationsArray.add(newGeneration); - } } } diff --git a/src/eva2/cli/NewMain.java b/src/eva2/cli/NewMain.java deleted file mode 100644 index 94105618..00000000 --- a/src/eva2/cli/NewMain.java +++ /dev/null @@ -1,15 +0,0 @@ -package eva2.cli; - -import eva2.optimization.go.InterfaceOptimizationParameters; - -/** - * Created by becker on 01.11.2014. - */ -public class NewMain { - - public static void main(String[] args) { - InterfaceOptimizationParameters parameters = OptimizationBuilder.parseArguments(args); - - - } -} diff --git a/src/eva2/cli/OptimizationBuilder.java b/src/eva2/cli/OptimizationBuilder.java index 1d94412f..9cf317d1 100644 --- a/src/eva2/cli/OptimizationBuilder.java +++ b/src/eva2/cli/OptimizationBuilder.java @@ -111,7 +111,7 @@ public final class OptimizationBuilder { Class[] params = new Class[0]; try { Constructor constructor = clazz.getConstructor(params); - instance = (T)constructor.newInstance(null); + instance = (T)constructor.newInstance(new Object[]{}); } catch (NoSuchMethodException | InvocationTargetException | InstantiationException | IllegalAccessException ex) { ex.printStackTrace(); } diff --git a/src/eva2/optimization/statistics/EvAStatisticalEvaluation.java b/src/eva2/optimization/statistics/EvAStatisticalEvaluation.java index 5e6d9fbb..7db8162f 100644 --- a/src/eva2/optimization/statistics/EvAStatisticalEvaluation.java +++ b/src/eva2/optimization/statistics/EvAStatisticalEvaluation.java @@ -6,11 +6,12 @@ import eva2.optimization.enums.StatisticsOnTwoSampledData; import eva2.tools.ReflectPackage; import eva2.tools.StringTools; import eva2.tools.math.Mathematics; -import org.apache.commons.math3.stat.ranking.NaNStrategy; -import org.apache.commons.math3.stat.ranking.TiesStrategy; import java.text.DecimalFormat; -import java.util.*; +import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; import java.util.logging.Logger; /** @@ -257,19 +258,15 @@ public class EvAStatisticalEvaluation { private static String calculateMannWhitney(String field, OptimizationJob job1, OptimizationJob job2) { double[] dat1 = job1.getDoubleDataColumn(field); double[] dat2 = job2.getDoubleDataColumn(field); - org.apache.commons.math3.stat.inference.MannWhitneyUTest mU = new org.apache.commons.math3.stat.inference.MannWhitneyUTest(NaNStrategy.FAILED, TiesStrategy.AVERAGE); double t = Double.NaN; if (dat1 != null && dat2 != null) { - - return "" + mU.mannWhitneyUTest(dat1, dat2); - /* Object obj = ReflectPackage.instantiateWithParams("jsc.independentsamples.MannWhitneyTest", new Object[]{dat1, dat2}, null); if (obj != null) { Object sp = BeanInspector.callIfAvailable(obj, "getSP", new Object[]{}); t = (Double) sp; } else { LOGGER.warning("For the MannWhitney test, the JSC package is required on the class path!"); - }*/ + } } return "" + t; } diff --git a/src/eva2/tools/Serializer.java b/src/eva2/tools/Serializer.java index e64e5d5b..f483a3f6 100644 --- a/src/eva2/tools/Serializer.java +++ b/src/eva2/tools/Serializer.java @@ -1,7 +1,5 @@ package eva2.tools; -import com.google.gson.Gson; - import java.io.*; import java.util.logging.Level; import java.util.logging.Logger;