Merge branch '30-dynamic-cli'
This commit is contained in:
commit
97d79612c2
21
pom.xml
21
pom.xml
@ -27,27 +27,6 @@
|
|||||||
<artifactId>javahelp</artifactId>
|
<artifactId>javahelp</artifactId>
|
||||||
<version>2.0.05</version>
|
<version>2.0.05</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.commons</groupId>
|
|
||||||
<artifactId>commons-math3</artifactId>
|
|
||||||
<version>3.1.1</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>commons-cli</groupId>
|
|
||||||
<artifactId>commons-cli</artifactId>
|
|
||||||
<version>1.2</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.google.code.gson</groupId>
|
|
||||||
<artifactId>gson</artifactId>
|
|
||||||
<version>2.3</version>
|
|
||||||
<scope>compile</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.reflections</groupId>
|
|
||||||
<artifactId>reflections</artifactId>
|
|
||||||
<version>0.9.9</version>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,719 +1,15 @@
|
|||||||
package eva2.cli;
|
package eva2.cli;
|
||||||
|
|
||||||
import com.google.gson.*;
|
import eva2.optimization.go.InterfaceOptimizationParameters;
|
||||||
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;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Main Class for the EvA2 Command Line Interface
|
* Created by becker on 01.11.2014.
|
||||||
*
|
|
||||||
* 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)
|
|
||||||
*/
|
*/
|
||||||
public class Main implements OptimizationStateListener, InterfacePopulationChangedEventListener {
|
public class Main {
|
||||||
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<String, Class<? extends InterfaceOptimizer>> createOptimizerList() {
|
|
||||||
Map<String, Class<? extends InterfaceOptimizer>> optimizerList = new TreeMap<>();
|
|
||||||
|
|
||||||
Reflections reflections = new Reflections("eva2.optimization.strategies");
|
|
||||||
Set<Class<? extends InterfaceOptimizer>> optimizers = reflections.getSubTypesOf(InterfaceOptimizer.class);
|
|
||||||
for (Class<? extends InterfaceOptimizer> 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<String, Class<? extends AbstractProblemDoubleOffset>> createProblemList() {
|
|
||||||
Map<String, Class<? extends AbstractProblemDoubleOffset>> problemList = new TreeMap<>();
|
|
||||||
Reflections reflections = new Reflections("eva2.problems");
|
|
||||||
Set<Class<? extends AbstractProblemDoubleOffset>> problems = reflections.getSubTypesOf(AbstractProblemDoubleOffset.class);
|
|
||||||
for (Class<? extends AbstractProblemDoubleOffset> 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<String, Class<? extends InterfaceMutation>> createMutatorList() {
|
|
||||||
Map<String, Class<? extends InterfaceMutation>> mutationList = new TreeMap<>();
|
|
||||||
Reflections reflections = new Reflections("eva2.optimization.operator.mutation");
|
|
||||||
Set<Class<? extends InterfaceMutation>> mutators = reflections.getSubTypesOf(InterfaceMutation.class);
|
|
||||||
for (Class<? extends InterfaceMutation> 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<String, Class<? extends InterfaceCrossover>> createCrossoverList() {
|
|
||||||
Map<String, Class<? extends InterfaceCrossover>> crossoverList = new TreeMap<>();
|
|
||||||
Reflections reflections = new Reflections("eva2.optimization.operator.crossover");
|
|
||||||
Set<Class<? extends InterfaceCrossover>> crossovers = reflections.getSubTypesOf(InterfaceCrossover.class);
|
|
||||||
for (Class<? extends InterfaceCrossover> 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<String, Class<? extends InterfaceSelection>> createSelectionList() {
|
|
||||||
Map<String, Class<? extends InterfaceSelection>> selectionList = new TreeMap<>();
|
|
||||||
Reflections reflections = new Reflections("eva2.optimization.operator.selection");
|
|
||||||
Set<Class<? extends InterfaceSelection>> selections = reflections.getSubTypesOf(InterfaceSelection.class);
|
|
||||||
for (Class<? extends InterfaceSelection> 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 static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
Main optimizationMain = new Main(args);
|
InterfaceOptimizationParameters parameters = OptimizationBuilder.parseArguments(args);
|
||||||
optimizationMain.runOptimization();
|
|
||||||
}
|
|
||||||
|
|
||||||
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<String, Class<? extends InterfaceMutation>> mutatorList = createMutatorList();
|
|
||||||
|
|
||||||
Class<? extends InterfaceMutation> 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<String, Class<? extends InterfaceCrossover>> crossoverList = createCrossoverList();
|
|
||||||
|
|
||||||
Class<? extends InterfaceCrossover> 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<String, Class<? extends InterfaceSelection>> selectionList = createSelectionList();
|
|
||||||
|
|
||||||
Class<? extends InterfaceSelection> 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<String, Class<? extends AbstractProblemDoubleOffset>> problemList = createProblemList();
|
|
||||||
|
|
||||||
Class<? extends AbstractProblemDoubleOffset> 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<String, Class<? extends InterfaceOptimizer>> optimizerList = createOptimizerList();
|
|
||||||
|
|
||||||
System.out.println("Available Optimizers:");
|
|
||||||
for (String name : optimizerList.keySet()) {
|
|
||||||
System.out.printf("%s\n", name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void listProblems() {
|
|
||||||
Map<String, Class<? extends AbstractProblemDoubleOffset>> 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
208
src/eva2/cli/OptimizationBuilder.java
Normal file
208
src/eva2/cli/OptimizationBuilder.java
Normal file
@ -0,0 +1,208 @@
|
|||||||
|
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<String, Object> {
|
||||||
|
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<String, String> 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> T constructFromArgumentTree(Class<T> 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 constructor = clazz.getConstructor(params);
|
||||||
|
instance = (T)constructor.newInstance(new Object[]{});
|
||||||
|
} 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()) {
|
||||||
|
info = Introspector.getBeanInfo(clazz);
|
||||||
|
} else {
|
||||||
|
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();
|
||||||
|
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)) {
|
||||||
|
foundParameters++;
|
||||||
|
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();
|
||||||
|
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
|
||||||
|
// We preserve the default if obj is null
|
||||||
|
if (obj != null) {
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
@ -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
|
* This method allows you to request a certain amount of double data
|
||||||
*
|
*
|
||||||
@ -235,9 +232,6 @@ public class ESIndividualDoubleData extends AbstractEAIndividual implements Inte
|
|||||||
System.arraycopy(doubleData, 0, this.genotype, 0, doubleData.length);
|
System.arraycopy(doubleData, 0, this.genotype, 0, doubleData.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
|
||||||
* AbstractEAIndividual methods
|
|
||||||
*/
|
|
||||||
/**
|
/**
|
||||||
* This method will allow a default initialisation of the individual
|
* This method will allow a default initialisation of the individual
|
||||||
*
|
*
|
||||||
@ -304,9 +298,6 @@ public class ESIndividualDoubleData extends AbstractEAIndividual implements Inte
|
|||||||
return strB.toString();
|
return strB.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
|
||||||
* InterfaceESIndividual methods
|
|
||||||
*/
|
|
||||||
/**
|
/**
|
||||||
* This method will allow the user to read the ES 'genotype'
|
* This method will allow the user to read the ES 'genotype'
|
||||||
*
|
*
|
||||||
|
@ -10,6 +10,7 @@ import eva2.optimization.operator.mutation.MutateGAUniform;
|
|||||||
import eva2.problems.InterfaceOptimizationProblem;
|
import eva2.problems.InterfaceOptimizationProblem;
|
||||||
import eva2.tools.math.RNG;
|
import eva2.tools.math.RNG;
|
||||||
import eva2.util.annotation.Description;
|
import eva2.util.annotation.Description;
|
||||||
|
import eva2.util.annotation.Parameter;
|
||||||
|
|
||||||
import java.util.BitSet;
|
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
|
* This method will initialize the individual with a given value for the
|
||||||
* phenotype.
|
* phenotype.
|
||||||
@ -373,6 +370,7 @@ public class GAIndividualDoubleData extends AbstractEAIndividual implements Inte
|
|||||||
*
|
*
|
||||||
* @param coding The used genotype coding method
|
* @param coding The used genotype coding method
|
||||||
*/
|
*/
|
||||||
|
@Parameter(name = "coding", description = "Choose the coding to use.")
|
||||||
public void setGACoding(InterfaceGADoubleCoding coding) {
|
public void setGACoding(InterfaceGADoubleCoding coding) {
|
||||||
this.doubleCoding = coding;
|
this.doubleCoding = coding;
|
||||||
}
|
}
|
||||||
@ -381,16 +379,13 @@ public class GAIndividualDoubleData extends AbstractEAIndividual implements Inte
|
|||||||
return this.doubleCoding;
|
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,
|
* This method allows you to set the number of mulitruns that are to be performed,
|
||||||
* necessary for stochastic optimizers to ensure reliable results.
|
* necessary for stochastic optimizers to ensure reliable results.
|
||||||
*
|
*
|
||||||
* @param precision The number of multiruns that are to be performed
|
* @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) {
|
public void setPrecision(int precision) {
|
||||||
this.precision = precision;
|
this.precision = precision;
|
||||||
}
|
}
|
||||||
@ -398,8 +393,4 @@ public class GAIndividualDoubleData extends AbstractEAIndividual implements Inte
|
|||||||
public int getPrecision() {
|
public int getPrecision() {
|
||||||
return this.precision;
|
return this.precision;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String precisionTipText() {
|
|
||||||
return "Gives the number of bits to be used to code a double.";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,7 @@ import eva2.tools.math.Mathematics;
|
|||||||
import eva2.tools.math.RNG;
|
import eva2.tools.math.RNG;
|
||||||
import eva2.tools.math.StatisticUtils;
|
import eva2.tools.math.StatisticUtils;
|
||||||
import eva2.util.annotation.Description;
|
import eva2.util.annotation.Description;
|
||||||
|
import eva2.util.annotation.Hidden;
|
||||||
import eva2.util.annotation.Parameter;
|
import eva2.util.annotation.Parameter;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
@ -602,6 +603,7 @@ public class Population extends ArrayList implements PopulationInterface, Clonea
|
|||||||
return historyList;
|
return historyList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Hidden
|
||||||
public void setHistory(LinkedList<AbstractEAIndividual> theHist) {
|
public void setHistory(LinkedList<AbstractEAIndividual> theHist) {
|
||||||
historyList = theHist;
|
historyList = theHist;
|
||||||
}
|
}
|
||||||
@ -684,6 +686,7 @@ public class Population extends ArrayList implements PopulationInterface, Clonea
|
|||||||
*
|
*
|
||||||
* @param d The new number of functioncalls.
|
* @param d The new number of functioncalls.
|
||||||
*/
|
*/
|
||||||
|
@Hidden
|
||||||
public void setFunctionCalls(int d) {
|
public void setFunctionCalls(int d) {
|
||||||
this.functionCallCount = 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
|
* @param gen the value to set as new generation index
|
||||||
*/
|
*/
|
||||||
|
@Hidden
|
||||||
public void setGeneration(int gen) {
|
public void setGeneration(int gen) {
|
||||||
this.generationCount = gen;
|
this.generationCount = gen;
|
||||||
}
|
}
|
||||||
@ -2519,11 +2523,8 @@ public class Population extends ArrayList implements PopulationInterface, Clonea
|
|||||||
return seedCardinality;
|
return seedCardinality;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Parameter(description = "The initial cardinality for binary genotype individuals, given as pair of mean and std.dev.")
|
||||||
public void setSeedCardinality(Pair<Integer, Integer> seedCardinality) {
|
public void setSeedCardinality(Pair<Integer, Integer> seedCardinality) {
|
||||||
this.seedCardinality = seedCardinality;
|
this.seedCardinality = seedCardinality;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String seedCardinalityTipText() {
|
|
||||||
return "The initial cardinality for binary genotype individuals, given as pair of mean and std.dev.";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -6,11 +6,12 @@ import eva2.optimization.enums.StatisticsOnTwoSampledData;
|
|||||||
import eva2.tools.ReflectPackage;
|
import eva2.tools.ReflectPackage;
|
||||||
import eva2.tools.StringTools;
|
import eva2.tools.StringTools;
|
||||||
import eva2.tools.math.Mathematics;
|
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.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;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -257,19 +258,15 @@ public class EvAStatisticalEvaluation {
|
|||||||
private static String calculateMannWhitney(String field, OptimizationJob job1, OptimizationJob job2) {
|
private static String calculateMannWhitney(String field, OptimizationJob job1, OptimizationJob job2) {
|
||||||
double[] dat1 = job1.getDoubleDataColumn(field);
|
double[] dat1 = job1.getDoubleDataColumn(field);
|
||||||
double[] dat2 = job2.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;
|
double t = Double.NaN;
|
||||||
if (dat1 != null && dat2 != null) {
|
if (dat1 != null && dat2 != null) {
|
||||||
|
|
||||||
return "" + mU.mannWhitneyUTest(dat1, dat2);
|
|
||||||
/*
|
|
||||||
Object obj = ReflectPackage.instantiateWithParams("jsc.independentsamples.MannWhitneyTest", new Object[]{dat1, dat2}, null);
|
Object obj = ReflectPackage.instantiateWithParams("jsc.independentsamples.MannWhitneyTest", new Object[]{dat1, dat2}, null);
|
||||||
if (obj != null) {
|
if (obj != null) {
|
||||||
Object sp = BeanInspector.callIfAvailable(obj, "getSP", new Object[]{});
|
Object sp = BeanInspector.callIfAvailable(obj, "getSP", new Object[]{});
|
||||||
t = (Double) sp;
|
t = (Double) sp;
|
||||||
} else {
|
} else {
|
||||||
LOGGER.warning("For the MannWhitney test, the JSC package is required on the class path!");
|
LOGGER.warning("For the MannWhitney test, the JSC package is required on the class path!");
|
||||||
}*/
|
}
|
||||||
}
|
}
|
||||||
return "" + t;
|
return "" + t;
|
||||||
}
|
}
|
||||||
|
@ -100,7 +100,7 @@ public class MultiObjectiveCMAES extends AbstractOptimizer implements Serializab
|
|||||||
/*
|
/*
|
||||||
* (non-Javadoc)
|
* (non-Javadoc)
|
||||||
*
|
*
|
||||||
* @see eva2.optimization.strategies.InterfaceOptimizer#init()
|
* @see eva2.optimization.strategies.InterfaceOptimizer#initialize()
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void initialize() {
|
public void initialize() {
|
||||||
|
@ -87,13 +87,11 @@ public abstract class AbstractOptimizationProblem implements InterfaceOptimizati
|
|||||||
return parallelThreads;
|
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) {
|
public void setParallelThreads(int parallelThreads) {
|
||||||
this.parallelThreads = 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.
|
* This method initializes the problem instance.
|
||||||
@ -406,10 +404,6 @@ public abstract class AbstractOptimizationProblem implements InterfaceOptimizati
|
|||||||
return template;
|
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.
|
* 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
|
* Similar individuals are clustered together with a density based clustering method
|
||||||
|
@ -22,6 +22,7 @@ import eva2.tools.diagram.ColorBarCalculator;
|
|||||||
import eva2.tools.math.Jama.Matrix;
|
import eva2.tools.math.Jama.Matrix;
|
||||||
import eva2.tools.math.Mathematics;
|
import eva2.tools.math.Mathematics;
|
||||||
import eva2.tools.math.RNG;
|
import eva2.tools.math.RNG;
|
||||||
|
import eva2.util.annotation.Parameter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For a double valued problem, there are two main methods to implement:
|
* 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.
|
* @param noise The sigma for a gaussian random number.
|
||||||
*/
|
*/
|
||||||
|
@Parameter(description = "Gaussian noise level on the fitness value.")
|
||||||
public void setNoise(double noise) {
|
public void setNoise(double noise) {
|
||||||
if (noise < 0) {
|
if (noise < 0) {
|
||||||
noise = 0;
|
noise = 0;
|
||||||
@ -301,15 +303,12 @@ public abstract class AbstractProblemDouble extends AbstractOptimizationProblem
|
|||||||
return this.noise;
|
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.
|
* This method allows you to choose the EA individual used by the problem.
|
||||||
*
|
*
|
||||||
* @param indy The EAIndividual type
|
* @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) {
|
public void setEAIndividual(InterfaceDataTypeDouble indy) {
|
||||||
this.template = (AbstractEAIndividual) indy;
|
this.template = (AbstractEAIndividual) indy;
|
||||||
}
|
}
|
||||||
@ -324,10 +323,6 @@ public abstract class AbstractProblemDouble extends AbstractOptimizationProblem
|
|||||||
return (InterfaceDataTypeDouble) this.template;
|
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.
|
* 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";
|
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) {
|
public void setDoRotation(boolean doRotation) {
|
||||||
this.doRotation = doRotation;
|
this.doRotation = doRotation;
|
||||||
if (!doRotation) {
|
if (!doRotation) {
|
||||||
@ -362,10 +358,6 @@ public abstract class AbstractProblemDouble extends AbstractOptimizationProblem
|
|||||||
return doRotation;
|
return doRotation;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String doRotationTipText() {
|
|
||||||
return "If marked, the function is rotated by 22.5 degrees along every axis.";
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* *******************************************************************************************************************
|
* *******************************************************************************************************************
|
||||||
* These are for InterfaceParamControllable
|
* These are for InterfaceParamControllable
|
||||||
|
@ -12,6 +12,7 @@ import eva2.problems.simple.InterfaceSimpleProblem;
|
|||||||
import eva2.problems.simple.SimpleF1;
|
import eva2.problems.simple.SimpleF1;
|
||||||
import eva2.problems.simple.SimpleProblemBinary;
|
import eva2.problems.simple.SimpleProblemBinary;
|
||||||
import eva2.problems.simple.SimpleProblemDouble;
|
import eva2.problems.simple.SimpleProblemDouble;
|
||||||
|
import eva2.util.annotation.Parameter;
|
||||||
|
|
||||||
import java.util.BitSet;
|
import java.util.BitSet;
|
||||||
|
|
||||||
@ -164,6 +165,7 @@ public class SimpleProblemWrapper extends AbstractOptimizationProblem {
|
|||||||
/**
|
/**
|
||||||
* @param simProb the simProb to set
|
* @param simProb the simProb to set
|
||||||
*/
|
*/
|
||||||
|
@Parameter(description = "Set the simple problem class which is to be optimized")
|
||||||
public void setSimpleProblem(InterfaceSimpleProblem<?> simProb) {
|
public void setSimpleProblem(InterfaceSimpleProblem<?> simProb) {
|
||||||
this.simProb = simProb;
|
this.simProb = simProb;
|
||||||
initTemplate();
|
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
|
* 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.
|
* fitness. This can be used to make the optimization problem more difficult.
|
||||||
*
|
*
|
||||||
* @param noise The sigma for a gaussian random number.
|
* @param noise The sigma for a gaussian random number.
|
||||||
*/
|
*/
|
||||||
|
@Parameter(description = "Gaussian noise level on the fitness value.")
|
||||||
public void setNoise(double noise) {
|
public void setNoise(double noise) {
|
||||||
if (noise < 0) {
|
if (noise < 0) {
|
||||||
noise = 0;
|
noise = 0;
|
||||||
@ -210,11 +206,6 @@ public class SimpleProblemWrapper extends AbstractOptimizationProblem {
|
|||||||
return this.noise;
|
return this.noise;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String noiseTipText() {
|
|
||||||
return "Gaussian noise level on the fitness value.";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A (symmetric) absolute range limit.
|
* A (symmetric) absolute range limit.
|
||||||
*
|
*
|
||||||
@ -229,15 +220,12 @@ public class SimpleProblemWrapper extends AbstractOptimizationProblem {
|
|||||||
*
|
*
|
||||||
* @param defaultRange
|
* @param defaultRange
|
||||||
*/
|
*/
|
||||||
|
@Parameter(name = "range", description = "Absolute limit for the symmetric range in any dimension")
|
||||||
public void setDefaultRange(double defaultRange) {
|
public void setDefaultRange(double defaultRange) {
|
||||||
this.defaultRange = defaultRange;
|
this.defaultRange = defaultRange;
|
||||||
initTemplate();
|
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.
|
* 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.
|
* This is called by PropertySheetPanel in use with the GenericObjectEditor.
|
||||||
@ -246,16 +234,12 @@ public class SimpleProblemWrapper extends AbstractOptimizationProblem {
|
|||||||
setSimpleProblem(getSimpleProblem());
|
setSimpleProblem(getSimpleProblem());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Parameter(name = "individual", description = "Set the individual properties for the optimization")
|
||||||
public void setIndividualTemplate(AbstractEAIndividual indy) {
|
public void setIndividualTemplate(AbstractEAIndividual indy) {
|
||||||
resetTemplate = false;
|
resetTemplate = false;
|
||||||
template = indy;
|
template = indy;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public String individualTemplateTipText() {
|
|
||||||
return "Set the individual properties for the optimization";
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method returns a string describing the optimization problem.
|
* This method returns a string describing the optimization problem.
|
||||||
*
|
*
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
package eva2.tools;
|
package eva2.tools;
|
||||||
|
|
||||||
import com.google.gson.Gson;
|
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user