diff --git a/.gitignore b/.gitignore index b6785257..35aa8432 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ /build/ out/ *.ser +*.yml .settings/ .project .classpath diff --git a/src/eva2/json/package-info.java b/src/eva2/json/package-info.java deleted file mode 100644 index c0261a75..00000000 --- a/src/eva2/json/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -/** - * JSON package for serializing and deserializing optimization configurations. - */ -package eva2.json; \ No newline at end of file diff --git a/src/eva2/optimization/modules/AbstractOptimizationParameters.java b/src/eva2/optimization/modules/AbstractOptimizationParameters.java index 16ba1d97..94a50f95 100644 --- a/src/eva2/optimization/modules/AbstractOptimizationParameters.java +++ b/src/eva2/optimization/modules/AbstractOptimizationParameters.java @@ -3,18 +3,18 @@ package eva2.optimization.modules; import eva2.gui.BeanInspector; import eva2.optimization.go.InterfaceNotifyOnInformers; import eva2.optimization.go.InterfaceOptimizationParameters; -import eva2.optimization.population.InterfacePopulationChangedEventListener; import eva2.optimization.operator.postprocess.InterfacePostProcessParams; import eva2.optimization.operator.postprocess.PostProcessParams; import eva2.optimization.operator.terminators.InterfaceTerminator; +import eva2.optimization.population.InterfacePopulationChangedEventListener; +import eva2.optimization.strategies.InterfaceOptimizer; import eva2.problems.InterfaceAdditionalPopulationInformer; import eva2.problems.InterfaceOptimizationProblem; -import eva2.optimization.strategies.InterfaceOptimizer; -import eva2.tools.Serializer; import eva2.util.annotation.Parameter; +import eva2.yaml.BeanSerializer; -import java.io.FileNotFoundException; import java.io.FileOutputStream; +import java.io.IOException; import java.io.Serializable; import java.util.LinkedList; import java.util.List; @@ -121,15 +121,17 @@ public abstract class AbstractOptimizationParameters implements InterfaceOptimiz public void saveInstance(String fileName) { try { FileOutputStream fileStream = new FileOutputStream(fileName); - Serializer.storeObject(fileStream, this); - } catch (FileNotFoundException ex) { + String yaml = BeanSerializer.serializeObject(this); + fileStream.write(yaml.getBytes()); + fileStream.close(); + } catch (IOException ex) { LOGGER.log(Level.WARNING, "Could not store instance object.", ex); } } @Override public void saveInstance() { - String fileName = this.getClass().getSimpleName() + ".ser"; + String fileName = this.getClass().getSimpleName() + ".yml"; saveInstance(fileName); } diff --git a/src/eva2/optimization/modules/OptimizationParameters.java b/src/eva2/optimization/modules/OptimizationParameters.java index 1fc6ccb1..26d2b38a 100644 --- a/src/eva2/optimization/modules/OptimizationParameters.java +++ b/src/eva2/optimization/modules/OptimizationParameters.java @@ -4,12 +4,11 @@ import eva2.optimization.go.InterfaceOptimizationParameters; import eva2.optimization.operator.terminators.EvaluationTerminator; import eva2.optimization.operator.terminators.InterfaceTerminator; import eva2.optimization.strategies.DifferentialEvolution; +import eva2.optimization.strategies.InterfaceOptimizer; import eva2.problems.F1Problem; import eva2.problems.InterfaceOptimizationProblem; -import eva2.optimization.strategies.GeneticAlgorithm; -import eva2.optimization.strategies.InterfaceOptimizer; -import eva2.tools.Serializer; import eva2.util.annotation.Description; +import org.yaml.snakeyaml.Yaml; import java.io.FileInputStream; import java.io.FileNotFoundException; @@ -35,21 +34,21 @@ public class OptimizationParameters extends AbstractOptimizationParameters imple * @return */ public static OptimizationParameters getInstance() { - return getInstance("OptimizationParameters.ser", true); + return getInstance("OptimizationParameters.yml", true); } /** * Create an instance from a given serialized parameter file. * - * @param serParamFile Serialized Parameter File + * @param yamlFile Serialized Parameter File * @param casually if true, standard parameters are used quietly if the params cannot be loaded * @return a OptimizationParameters instance */ - public static OptimizationParameters getInstance(String serParamFile, final boolean casually) { + public static OptimizationParameters getInstance(String yamlFile, final boolean casually) { OptimizationParameters instance = null; try { - FileInputStream fileStream = new FileInputStream(serParamFile); - instance = (OptimizationParameters) Serializer.loadObject(fileStream, casually); + FileInputStream fileStream = new FileInputStream(yamlFile); + instance = (OptimizationParameters) new Yaml().load(fileStream); } catch (FileNotFoundException ex) { LOGGER.log(Level.WARNING, "Could not load instance object.", ex); } diff --git a/src/eva2/optimization/modules/Processor.java b/src/eva2/optimization/modules/Processor.java index bb249e18..35e17817 100644 --- a/src/eva2/optimization/modules/Processor.java +++ b/src/eva2/optimization/modules/Processor.java @@ -4,7 +4,6 @@ import eva2.gui.BeanInspector; import eva2.optimization.OptimizationStateListener; import eva2.optimization.go.InterfaceNotifyOnInformers; import eva2.optimization.go.InterfaceOptimizationParameters; -import eva2.optimization.population.InterfacePopulationChangedEventListener; import eva2.optimization.operator.paramcontrol.ConstantParameters; import eva2.optimization.operator.paramcontrol.InterfaceParameterControl; import eva2.optimization.operator.postprocess.PostProcess; @@ -12,13 +11,14 @@ import eva2.optimization.operator.postprocess.PostProcessParams; import eva2.optimization.operator.terminators.EvaluationTerminator; import eva2.optimization.operator.terminators.GenerationTerminator; import eva2.optimization.operator.terminators.InterfaceTerminator; +import eva2.optimization.population.InterfacePopulationChangedEventListener; import eva2.optimization.population.Population; -import eva2.problems.AbstractOptimizationProblem; -import eva2.problems.InterfaceAdditionalPopulationInformer; import eva2.optimization.statistics.InterfaceStatistics; import eva2.optimization.statistics.InterfaceTextListener; import eva2.optimization.statistics.StatisticsWithGUI; import eva2.optimization.strategies.InterfaceOptimizer; +import eva2.problems.AbstractOptimizationProblem; +import eva2.problems.InterfaceAdditionalPopulationInformer; import eva2.problems.InterfaceOptimizationProblem; import eva2.tools.EVAERROR; import eva2.tools.StringTools; @@ -48,7 +48,7 @@ public class Processor extends Thread implements InterfaceProcessor, InterfacePo private InterfaceStatistics statistics; private InterfaceOptimizationParameters optimizationParameters; private boolean createInitialPopulations = true; - private boolean saveParams = false; + private boolean saveParams = true; private OptimizationStateListener optimizationStateListener; private boolean wasRestarted = false; private int runCounter = 0; @@ -167,7 +167,6 @@ public class Processor extends Thread implements InterfaceProcessor, InterfacePo EVAERROR.clearMsgCache(); while (isOptimizationRunning()) { setPriority(3); - // ToDo: Do we need this really? if (saveParams) { try { optimizationParameters.saveInstance(); diff --git a/src/eva2/optimization/statistics/AbstractStatistics.java b/src/eva2/optimization/statistics/AbstractStatistics.java index 5cf849a1..17260e7f 100644 --- a/src/eva2/optimization/statistics/AbstractStatistics.java +++ b/src/eva2/optimization/statistics/AbstractStatistics.java @@ -12,6 +12,7 @@ import eva2.tools.StringSelection; import eva2.tools.StringTools; import eva2.tools.ToolBox; import eva2.tools.math.Mathematics; +import eva2.yaml.BeanSerializer; import java.io.File; import java.io.FileOutputStream; @@ -195,7 +196,7 @@ public abstract class AbstractStatistics implements InterfaceTextListener, Inter * * @param infoString */ - protected void initOutput(String infoString) { + protected void initializeOutput(String infoString) { String startDate = getDateString(); // open the result file: if (doFileOutput() // not "text-window only" @@ -271,15 +272,11 @@ public abstract class AbstractStatistics implements InterfaceTextListener, Inter if (saveParams) { statisticsParameter.saveInstance(); } - initOutput(infoString); + initializeOutput(infoString); bestIndyAllRuns = null; bestFeasibleAllRuns = null; -// meanBestOfRunFitness = null; -// meanBestFeasibleFit = null; runBestFeasibleList = new ArrayList<>(); runBestFitList = new ArrayList<>(); -// if (refineMultiRuns) meanCollection = new ArrayList(); -// else meanCollection = null; if (refineMultiRuns) { sumDataCollection = new ArrayList<>(); } else { @@ -289,7 +286,6 @@ public abstract class AbstractStatistics implements InterfaceTextListener, Inter finalObjectData = null; statDataSumOverAll = null; -// lastAdditionalInfoSums = null; feasibleFoundAfterSum = -1; numOfRunsFeasibleFound = 0; @@ -305,14 +301,14 @@ public abstract class AbstractStatistics implements InterfaceTextListener, Inter if (printRunIntroVerbosity()) { printToTextListener("\n****** Multirun " + runNumber); } - /* - ToDo: Figure out if we need this. Right now it is just spamming the text output if (params != null) { if (printRunIntroVerbosity()) { - printToTextListener("\nOptimization parameters: "); - printToTextListener(BeanInspector.niceToString(params)); + printToTextListener("\nOptimization parameters: \n"); + printToTextListener(BeanSerializer.serializeObject(params)); } } + /* + ToDo: Figure out if we need this. Right now it is just spamming the text output if (printRunIntroVerbosity()) { printToTextListener("\nStatistics parameters: "); printToTextListener(BeanInspector.niceToString(getStatisticsParameter()) + '\n'); diff --git a/src/eva2/optimization/statistics/StatisticsParameters.java b/src/eva2/optimization/statistics/StatisticsParameters.java index 849c36cd..179c8a57 100644 --- a/src/eva2/optimization/statistics/StatisticsParameters.java +++ b/src/eva2/optimization/statistics/StatisticsParameters.java @@ -9,6 +9,7 @@ import eva2.tools.SelectedTag; import eva2.tools.Serializer; import eva2.tools.StringSelection; import eva2.util.annotation.Description; +import eva2.util.annotation.Parameter; import java.io.FileInputStream; import java.io.FileNotFoundException; @@ -31,7 +32,6 @@ import java.util.logging.Logger; */ @Description(value = "Configure statistics and output of the optimization run. Changes to the data selection state will not take effect during a run.") public class StatisticsParameters implements InterfaceStatisticsParameters, InterfaceNotifyOnInformers, Serializable { - private static final long serialVersionUID = -8681061379203108390L; private static final Logger LOGGER = Logger.getLogger(StatisticsParameters.class.getName()); public final static int VERBOSITY_NONE = 0; public final static int VERBOSITY_FINAL = 1; @@ -169,13 +169,6 @@ public class StatisticsParameters implements InterfaceStatisticsParameters, Inte return "Number of independent optimization runs to evaluate."; } - /** - * - */ - public String infoStringTipText() { - return "Infostring displayed on fitness graph by pressing the right mouse button."; - } - /** * Use averaged graph for multi-run plots or not */ @@ -232,14 +225,11 @@ public class StatisticsParameters implements InterfaceStatisticsParameters, Inte return outputTo.getSelectedTagID() > 0; } - public String convergenceRateThresholdTipText() { - return "Provided the optimal fitness is at zero, give the threshold below which it is considered as 'reached'"; - } - /** * @param x */ @Override + @Parameter(description = "Provided the optimal fitness is at zero, give the threshold below which it is considered as 'reached'") public void setConvergenceRateThreshold(double x) { convergenceRateThreshold = x; } @@ -258,14 +248,11 @@ public class StatisticsParameters implements InterfaceStatisticsParameters, Inte } @Override + @Parameter(description = "Output all available data fields or only the selected entries as value.") public void setOutputAllFieldsAsText(boolean bShowFullText) { showAdditionalProblemInfo = bShowFullText; } - public String outputAllFieldsAsTextTipText() { - return "Output all available data fields or only the selected entries as value."; - } - public void hideHideable() { setOutputVerbosity(getOutputVerbosity()); } @@ -296,14 +283,11 @@ public class StatisticsParameters implements InterfaceStatisticsParameters, Inte } @Override + @Parameter(description = "Set the interval of data output for intermediate verbosity (in generations).") public void setOutputVerbosityK(int k) { verbosityK = k; } - public String outputVerbosityKTipText() { - return "Set the interval of data output for intermediate verbosity (in generations)."; - } - @Override public SelectedTag getOutputTo() { return outputTo; @@ -314,13 +298,11 @@ public class StatisticsParameters implements InterfaceStatisticsParameters, Inte outputTo = tag; } + @Parameter(description = "Set the output destination; to deactivate output, set verbosity to none.") public void setOutputTo(int i) { outputTo.setSelectedTag(i); } - public String outputToTipText() { - return "Set the output destination; to deactivate output, set verbosity to none."; - } @Override public StringSelection getFieldSelection() { @@ -328,13 +310,11 @@ public class StatisticsParameters implements InterfaceStatisticsParameters, Inte } @Override + @Parameter(description = "Select the data fields to be collected and plotted. Note that only simple types can be plotted to the GUI.") public void setFieldSelection(StringSelection v) { graphSel = v; } - public String fieldSelectionTipText() { - return "Select the data fields to be collected and plotted. Note that only simple types can be plotted to the GUI."; - } /** * May be called to dynamically alter the set of graphs that can be diff --git a/src/eva2/optimization/tools/FileTools.java b/src/eva2/optimization/tools/FileTools.java index 9ecd4e68..300b35c5 100644 --- a/src/eva2/optimization/tools/FileTools.java +++ b/src/eva2/optimization/tools/FileTools.java @@ -110,7 +110,6 @@ public class FileTools { * a PrintWriter while other objects are written using an ObjectOutputStream. * * @param parentComponent the parent component - * @param fc a filechooser or null to create a new one * @param object The object to save. */ public static boolean saveObjectWithFileChooser(Component parentComponent, Object object) { @@ -208,10 +207,10 @@ public class FileTools { String predefName = null; try { predefName = (String) BeanInspector.callIfAvailable(object, "getName", null); - predefName = StringTools.simplifySymbols(predefName) + ".ser"; + predefName = StringTools.simplifySymbols(predefName) + ".yml"; } catch (Exception e) { predefName = object.getClass().getName(); - predefName = StringTools.simplifySymbols(predefName) + ".ser"; + predefName = StringTools.simplifySymbols(predefName) + ".yml"; } if (!folder.exists()) { diff --git a/src/eva2/yaml/BeanSerializer.java b/src/eva2/yaml/BeanSerializer.java new file mode 100644 index 00000000..44fce8cc --- /dev/null +++ b/src/eva2/yaml/BeanSerializer.java @@ -0,0 +1,61 @@ +package eva2.yaml; + +import eva2.util.annotation.Hidden; +import org.yaml.snakeyaml.DumperOptions; +import org.yaml.snakeyaml.Yaml; +import org.yaml.snakeyaml.introspector.Property; +import org.yaml.snakeyaml.representer.Representer; + +import java.beans.BeanInfo; +import java.beans.IntrospectionException; +import java.beans.Introspector; +import java.beans.PropertyDescriptor; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Set; +import java.util.TreeSet; + +/** + * Created by becker on 02.11.2014. + */ +public class BeanSerializer { + + public static String serializeObject(Object obj) { + DumperOptions options = new DumperOptions(); + options.setAllowReadOnlyProperties(false); + options.setIndent(4); + Yaml yaml = new Yaml(new OptimizationRepresenter(), options); + return yaml.dump(obj); + } + + +} + +class OptimizationRepresenter extends Representer { + @Override + protected Set getProperties(Class type) + throws IntrospectionException { + + Set set = super.getProperties(type); + Set filtered = new TreeSet<>(); + BeanInfo info = Introspector.getBeanInfo(type, Object.class); + PropertyDescriptor[] properties = info.getPropertyDescriptors(); + ArrayList hiddenProperties = new ArrayList<>(); + + // We don't want to save Hidden properties + for (PropertyDescriptor p : properties) { + Method setter = p.getWriteMethod(); + if (setter != null && setter.isAnnotationPresent(Hidden.class) || p.isHidden()) { + hiddenProperties.add(p.getName()); + } + } + + for (Property prop : set) { + String name = prop.getName(); + if (!hiddenProperties.contains(name)) { + filtered.add(prop); + } + } + return filtered; + } +} \ No newline at end of file diff --git a/src/eva2/json/OptimizationRun.java b/src/eva2/yaml/OptimizationRun.java similarity index 93% rename from src/eva2/json/OptimizationRun.java rename to src/eva2/yaml/OptimizationRun.java index 30ba0519..b4c2f12a 100644 --- a/src/eva2/json/OptimizationRun.java +++ b/src/eva2/yaml/OptimizationRun.java @@ -1,4 +1,4 @@ -package eva2.json; +package eva2.yaml; import java.util.ArrayList; import java.util.List; diff --git a/src/eva2/yaml/package-info.java b/src/eva2/yaml/package-info.java new file mode 100644 index 00000000..7e3bade4 --- /dev/null +++ b/src/eva2/yaml/package-info.java @@ -0,0 +1,4 @@ +/** + * YAML package for serializing and deserializing optimization configurations. + */ +package eva2.yaml; \ No newline at end of file