diff --git a/src/eva2/EvAInfo.java b/src/eva2/EvAInfo.java index 6932786a..823d3f06 100644 --- a/src/eva2/EvAInfo.java +++ b/src/eva2/EvAInfo.java @@ -1,86 +1,10 @@ package eva2; +import eva2.tools.BasicResourceLoader; import java.io.InputStream; import java.util.Properties; -import eva2.tools.BasicResourceLoader; - -/** - * Main product and version information strings. - * - * ---- Changelog - * 2.05: Added ScatterSearch (real-valued), BinaryScatterSearch, and the Bayesian Optimization Algorithm (thanks - * to Alexander Seitz) to the base package. Added JobList and some statistical measures. Requires to put - * the JSC package on the class path for Mann-Whitney test. - * 2.046: Adaptions to the MatlabInterface: explicit data types are used now, added integer problem support. - * Additional Integer operators: segment-wise mutation and crossover. Added an abstraction over individual - * initialization methods. Added the ERPStarter class which is an example for running a csv-configured - * optimization. Some bug-fixes and clean-ups. - * 2.045: Added MOOCMAES (de Paly); compatibility with Java 1.5 (Draeger); Revision of the statistics class - * with improved pipelining of data (InterfaceAdditionalPopulationInformer); improved FunctionArea - * concerning history, labels, legend and graph coloring; improved StringSelection; restructured - * Terminators, additional ParetoMetricTerminator. Further bugfixes and clean-ups. - * 2.043: Added proper Population equality predicate. - * 2.042: Some bugfixes. Removing dependency on sun.beans.editors, replaced non-free jpeg-codec. There should - * be no more problems on OpenJDK. Added a simple initialization range, especially for use from Matlab. - * Some restructurings (RNG and Mathematics is now in eva2.tools.math). Some cleanup. - * 2.040: Several updates: The clustering interface has been changed for easier implementation of adaptive clustering - * methods. The GradientDescentAlgorithm has been updated and some benchmark problems been made derivable. - * The ClusterBasedNiching algorithm has been slightly restructured updated according to the new clustering. - * An additional clustering method is included: nearest-best clustering with dynamic adaption of niche radius. - * Some changes to (text) statistics: they are now printed regarding the full solution set instead of the - * last population. The Population field "size" is now termed "targetSize" to avoid misunderstandigs. Populations - * can be initialized using a Random Latin Hypercube sampling. Some basic console options are recognized: - * EvA2 can be started without splash screen and even without GUI. If configuration file is given which was - * earlier saved from the GUI, the thus defined optimization run is then processed automatically by EvA2. - * 2.036: New graph selection mode for statistic plots: every property may be selected independently. - * A simple plot legend is produced in the graph window, which can be deactivated. - * 2.035: Reactivated some of the model-based functionality within the GO framework. Minor bugfixes. - * 2.034: Adding a generic parameter control method for optimizers, currently used by PSO to adapt inertness depending - * on EvaluationTerminator or GenerationTerminator instances defining the number of function evaluations. - * The new package is eva2.server.go.operators.paramcontrol. - * A Population may now be ordered by a specific fitness criterion, employed, e.g., by Nelder-Mead-Simplex. - * 2.033: There was an interesting problem with the Matlab-Interface, which just hung up after extensive optimization - * loops, yet only if Matlab was started without X-forwarding (which is necessary for qsub, e.g.). - * Debugging was tedious, since the debugging using System.out. itself caused threading deadlocks. The - * problem showed up to be with System.out itself. Whatever Matlab does with that stream, it does it differently - * depending on the X-forwarding option. More specifically, the text written to System.out when X-forwarding - * is not available seems to never show up (as opposed to being printed to the console when X-forwarding is on) - * and silently fill up the JVM-memory. I havent the faintest idea why there havnt been OutOfMemory exceptions - * earlier or whether and how the deadlocks have to do with it. - * The ingenious solution was: dont print anything to System.out, which is now done at verbosity 0. - * 2.032: Some cosmetics, e.g. to AbstractEAIndividualComparator and older MOCCO classes. - * 2.031: Some updates to the OptimizerFactory. Review of the MatlabInterface with adding an own options structure. - * Better access to the EvAClient, which now may have a RemoteStateListener added monitoring the optimization run. - * 2.030: Added an EnumEditor to access enums easily through the GUI, which will replace SelectedTags sometimes. - * IPOP-ES and RankMuCMA mutator have been added lately (wow!). - * Cleaned up the IndividualInterface and reduced the usage of InterfaceESIndividual. This - * means that, e.g., that DE and PSO now also work on GAIndividualDoubleData. Because this - * requires much time for transcoding, however, this is not useful by itself. Yet it could be - * interesting for combined individuals composed of two data types. - * Cleaned up MutateXXDefault to a single MutateDefault, too. DE may now do range checking. - * The "Description" button has made space for a "Show Solution" button. The Rank-Mu-CMA was improved - * to use a CMAParameterSet which is associated with populations and not static any more. - * Included Nelder-Mead-Simplex and CMA-ES as post processing methods. - * 2.029: Tuned the 2d-graphs which now paints quicker and changes size depending on the - * surrounding plot window. Added a preloader-thread to accelerate the GUI at starting time. - * 2.028: Tuned the Population to sort only when necessary on calls to getBestN... Added StatisticsDummy. - * Slightly tuned SimpleProblemWrapper to call initProblem of simple problems if available. - * 2.027: Renamed SetData and SetDataLamarckian from individual data type interfaces to SetGenotype and SetPhenotype. - * Repaired the GenericArrayEditor. Population measures can now be plotted in stats. - * 2.026: Added DiversityTerminator and KnownOptimaTerminator, slightly changed InterfaceTerminator for these - * and InterfaceStatistics to provide termination message to text window. - * Killed redundant method getGenerations() in Population. Population.getAllSolutions now returns a - * SolutionSet combining last population with a set of possibly archived solutions. - * Post processing with HC may now use variable step size mutation. - * 2.025: FunctionArea may now plot circles easily. The FLensProblemViewer seems to be cured. - * 2.024: Cleaned up AbstractGOParams, deactivated parent logging (saving memory) - * 2.023: Cleaned up the PF strategy - * 2.022: Some changes to the SimpleProblemWrapper, not of great interest. However, - * simple problems may now access a plot quite easily. - * - * --- End Changelog - * +/** * @author mkron * */ diff --git a/src/eva2/OptimizerFactory.java b/src/eva2/OptimizerFactory.java index 64f1b3a2..57b00fab 100644 --- a/src/eva2/OptimizerFactory.java +++ b/src/eva2/OptimizerFactory.java @@ -1,11 +1,5 @@ -/* - * Copyright (c) ZBiT, University of Tübingen, Germany - */ package eva2; -import java.util.BitSet; -import java.util.Vector; - import eva2.server.go.IndividualInterface; import eva2.server.go.InterfacePopulationChangedEventListener; import eva2.server.go.InterfaceTerminator; @@ -27,12 +21,7 @@ import eva2.server.go.operators.crossover.CrossoverESDefault; import eva2.server.go.operators.crossover.InterfaceCrossover; import eva2.server.go.operators.crossover.NoCrossover; import eva2.server.go.operators.distancemetric.IndividualDataMetric; -import eva2.server.go.operators.mutation.InterfaceMutation; -import eva2.server.go.operators.mutation.MutateESCovarianceMatrixAdaption; -import eva2.server.go.operators.mutation.MutateESFixedStepSize; -import eva2.server.go.operators.mutation.MutateESGlobal; -import eva2.server.go.operators.mutation.MutateESRankMuCMA; -import eva2.server.go.operators.mutation.NoMutation; +import eva2.server.go.operators.mutation.*; import eva2.server.go.operators.postprocess.InterfacePostProcessParams; import eva2.server.go.operators.postprocess.PostProcessParams; import eva2.server.go.operators.selection.InterfaceSelection; @@ -42,27 +31,13 @@ import eva2.server.go.operators.terminators.EvaluationTerminator; import eva2.server.go.populations.PBILPopulation; import eva2.server.go.populations.Population; import eva2.server.go.problems.AbstractOptimizationProblem; -import eva2.server.go.strategies.ClusterBasedNichingEA; -import eva2.server.go.strategies.ClusteringHillClimbing; -import eva2.server.go.strategies.DifferentialEvolution; -import eva2.server.go.strategies.EsDpiNiching; -import eva2.server.go.strategies.EsDpiNichingCma; -import eva2.server.go.strategies.EvolutionStrategies; -import eva2.server.go.strategies.EvolutionStrategyIPOP; -import eva2.server.go.strategies.GeneticAlgorithm; -import eva2.server.go.strategies.GradientDescentAlgorithm; -import eva2.server.go.strategies.HillClimbing; -import eva2.server.go.strategies.InterfaceOptimizer; -import eva2.server.go.strategies.MonteCarloSearch; -import eva2.server.go.strategies.MultiObjectiveEA; -import eva2.server.go.strategies.NelderMeadSimplex; -import eva2.server.go.strategies.ParticleSwarmOptimization; -import eva2.server.go.strategies.PopulationBasedIncrementalLearning; -import eva2.server.go.strategies.SimulatedAnnealing; -import eva2.server.go.strategies.Tribes; +import eva2.server.go.strategies.*; import eva2.server.modules.GOParameters; import eva2.server.stat.InterfaceStatistics; import eva2.tools.math.RNG; +import java.util.ArrayList; +import java.util.BitSet; +import java.util.List; /** *

@@ -1011,19 +986,19 @@ public class OptimizerFactory { return runnable.getResultPopulation(); } - public static Vector postProcessBinVec(int steps, double sigma, + public static List postProcessBinVec(int steps, double sigma, int nBest) { return (lastRunnable != null) ? postProcessBinVec(lastRunnable, new PostProcessParams(steps, sigma, nBest)) : null; } - public static Vector postProcessBinVec( + public static List postProcessBinVec( InterfacePostProcessParams ppp) { return (lastRunnable != null) ? postProcessBinVec(lastRunnable, ppp) : null; } - public static Vector postProcessBinVec(OptimizerRunnable runnable, + public static List postProcessBinVec(OptimizerRunnable runnable, int steps, double sigma, int nBest) { return postProcessBinVec(runnable, new PostProcessParams(steps, sigma, nBest)); @@ -1037,10 +1012,10 @@ public class OptimizerFactory { * @param ppp * @return */ - public static Vector postProcessBinVec(OptimizerRunnable runnable, + public static List postProcessBinVec(OptimizerRunnable runnable, InterfacePostProcessParams ppp) { Population resPop = postProcess(runnable, ppp); - Vector ret = new Vector(resPop.size()); + List ret = new ArrayList(resPop.size()); for (Object o : resPop) { if (o instanceof InterfaceDataTypeBinary) { InterfaceDataTypeBinary indy = (InterfaceDataTypeBinary) o; @@ -1050,19 +1025,19 @@ public class OptimizerFactory { return ret; } - public static Vector postProcessDblVec(int steps, double sigma, + public static List postProcessDblVec(int steps, double sigma, int nBest) { return (lastRunnable == null) ? null : postProcessDblVec(lastRunnable, new PostProcessParams(steps, sigma, nBest)); } - public static Vector postProcessDblVec( + public static List postProcessDblVec( InterfacePostProcessParams ppp) { return (lastRunnable != null) ? postProcessDblVec(lastRunnable, ppp) : null; } - public static Vector postProcessDblVec( + public static List postProcessDblVec( OptimizerRunnable runnable, int steps, double sigma, int nBest) { return postProcessDblVec(runnable, new PostProcessParams(steps, sigma, nBest)); @@ -1076,10 +1051,10 @@ public class OptimizerFactory { * @param ppp * @return */ - public static Vector postProcessDblVec( + public static List postProcessDblVec( OptimizerRunnable runnable, InterfacePostProcessParams ppp) { Population resPop = postProcess(runnable, ppp); - Vector ret = new Vector(resPop.size()); + List ret = new ArrayList(resPop.size()); for (Object o : resPop) { if (o instanceof InterfaceDataTypeDouble) { InterfaceDataTypeDouble indy = (InterfaceDataTypeDouble) o; @@ -1089,19 +1064,19 @@ public class OptimizerFactory { return ret; } - public static Vector postProcessIndVec(int steps, + public static List postProcessIndVec(int steps, double sigma, int nBest) { return (lastRunnable != null) ? postProcessIndVec(lastRunnable, new PostProcessParams(steps, sigma, nBest)) : null; } - public static Vector postProcessIndVec( + public static List postProcessIndVec( InterfacePostProcessParams ppp) { return (lastRunnable != null) ? postProcessIndVec(lastRunnable, ppp) : null; } - public static Vector postProcessIndVec( + public static List postProcessIndVec( OptimizerRunnable runnable, int steps, double sigma, int nBest) { return postProcessIndVec(runnable, new PostProcessParams(steps, sigma, nBest)); @@ -1115,10 +1090,10 @@ public class OptimizerFactory { * @param ppp * @return */ - public static Vector postProcessIndVec( + public static List postProcessIndVec( OptimizerRunnable runnable, InterfacePostProcessParams ppp) { Population resPop = postProcess(runnable, ppp); - Vector ret = new Vector( + List ret = new ArrayList( resPop.size()); for (Object o : resPop) { if (o instanceof AbstractEAIndividual) { @@ -1428,8 +1403,7 @@ public class OptimizerFactory { MutateESRankMuCMA cmaMut = new MutateESRankMuCMA(); AbstractEAIndividual.setOperators(indy, cmaMut, 1., new CrossoverESDefault(), 0.); } else { - System.err - .println("Error, CMA-ES is implemented for ES individuals only (requires double data types)"); + System.err.println("Error, CMA-ES is implemented for ES individuals only (requires double data types)"); return null; } diff --git a/src/eva2/examples/TestingCbnPostProc.java b/src/eva2/examples/TestingCbnPostProc.java index 340df7dd..16b2cc57 100644 --- a/src/eva2/examples/TestingCbnPostProc.java +++ b/src/eva2/examples/TestingCbnPostProc.java @@ -1,18 +1,18 @@ package eva2.examples; -import java.util.Vector; import eva2.OptimizerFactory; import eva2.server.go.individuals.AbstractEAIndividual; import eva2.server.go.operators.postprocess.PostProcessParams; import eva2.server.go.operators.terminators.EvaluationTerminator; import eva2.server.go.problems.FM0Problem; import eva2.server.modules.GOParameters; +import java.util.List; public class TestingCbnPostProc { public static void main(String[] args) { // a simple bimodal target function, two optima near (1.7,0) and (-1.44/0) FM0Problem fm0 = new FM0Problem(); AbstractEAIndividual best; - Vector ppSols; + List ppSols; GOParameters esParams = OptimizerFactory.standardCbnES(fm0); esParams.setTerminator(new EvaluationTerminator(2000)); diff --git a/src/eva2/gui/FunctionArea.java b/src/eva2/gui/FunctionArea.java index 7f48f7cb..cd2d6655 100644 --- a/src/eva2/gui/FunctionArea.java +++ b/src/eva2/gui/FunctionArea.java @@ -185,179 +185,186 @@ public class FunctionArea extends DArea implements Serializable { /** * Add a popup menu for displaying certain information. */ - private void addPopup() { - addMouseListener(new MouseAdapter() { - public void mouseClicked(MouseEvent e) { - if ((e.getModifiers() & InputEvent.BUTTON1_MASK) == InputEvent.BUTTON1_MASK) { - // do nothing - } else { - JPopupMenu graphPopupMenu = new JPopupMenu(); - m_x = e.getX(); - m_y = e.getY(); + private void addPopup() { + addMouseListener(new MouseAdapter() { - addMenuItem(graphPopupMenu, "Rename graph", new ActionListener() { - public void actionPerformed(ActionEvent ee) { - renameGraph(getNearestGraphIndex(FunctionArea.this.m_x, FunctionArea.this.m_y)); - } - }); - // General entries - String togGTTName = (isShowGraphToolTips() ? "Deactivate" - : "Activate") - + " graph tool tips"; - addMenuItem(graphPopupMenu, togGTTName, - new ActionListener() { - public void actionPerformed(ActionEvent ee) { - setShowGraphToolTips(!isShowGraphToolTips()); - } - }); + public void mouseClicked(MouseEvent e) { + if ((e.getModifiers() & InputEvent.BUTTON1_MASK) == InputEvent.BUTTON1_MASK) { + // do nothing + } else { + JPopupMenu graphPopupMenu = new JPopupMenu(); + m_x = e.getX(); + m_y = e.getY(); - String togLName = (isShowLegend() ? "Hide" : "Show") - + " legend"; - addMenuItem(graphPopupMenu, togLName, new ActionListener() { - public void actionPerformed(ActionEvent ee) { - toggleLegend(); - } - }); + addMenuItem(graphPopupMenu, "Rename graph", new ActionListener() { - addMenuItem(graphPopupMenu, "Toggle scientific format", new ActionListener() { - public void actionPerformed(ActionEvent ee) { - toggleScientificY(true); - } - }); - - if (FunctionArea.this.m_PointSetContainer.size() > 0) { - addMenuItem(graphPopupMenu, "Recolor all graphs", - new ActionListener() { + public void actionPerformed(ActionEvent ee) { + renameGraph(getNearestGraphIndex(FunctionArea.this.m_x, FunctionArea.this.m_y)); + } + }); + // General entries + String togGTTName = (isShowGraphToolTips() ? "Deactivate" + : "Activate") + + " graph tool tips"; + addMenuItem(graphPopupMenu, togGTTName, + new ActionListener() { - public void actionPerformed(ActionEvent ee) { - recolorAllGraphsByIndex(); - } - }); - } + public void actionPerformed(ActionEvent ee) { + setShowGraphToolTips(!isShowGraphToolTips()); + } + }); - if (m_RefPointListener != null) { - DPoint temp = getDMeasures().getDPoint(m_x, m_y); - addMenuItem(graphPopupMenu, "Select Reference Point:(" - + temp.x + "/" + temp.y + ")", - new ActionListener() { - public void actionPerformed(ActionEvent ee) { - DPoint temp = getDMeasures().getDPoint( - m_x, m_y); - double[] point = new double[2]; - point[0] = temp.x; - point[1] = temp.y; - m_RefPointListener.refPointGiven(point); - } - }); - } + String togLName = (isShowLegend() ? "Hide" : "Show") + + " legend"; + addMenuItem(graphPopupMenu, togLName, new ActionListener() { - // darn this point is an empty copy !! - DPoint point = getNearestDPoint(e.getX(), e.getY()); - if (point != null) { - // the point info element - addMenuItem(graphPopupMenu, "Nearest point: (" - + point.x + "/" + point.y + ")", - new ActionListener() { - public void actionPerformed(ActionEvent ee) { - } - }, false); + public void actionPerformed(ActionEvent ee) { + toggleLegend(); + } + }); - addMenuItem(graphPopupMenu, " Remove point", - new ActionListener() { - public void actionPerformed(ActionEvent ee) { - removePoint(FunctionArea.this.m_x, - FunctionArea.this.m_y); - } - }); + addMenuItem(graphPopupMenu, "Toggle scientific format", new ActionListener() { - if (point.getIcon() instanceof InterfaceSelectablePointIcon) { - m_CurrentPointIcon = point.getIcon(); - if (((InterfaceSelectablePointIcon) m_CurrentPointIcon) - .getSelectionListener() != null) { - AbstractEAIndividual indy = ((InterfaceSelectablePointIcon) m_CurrentPointIcon) - .getEAIndividual(); - String selectTitle = indy.isMarked() ? " Deselect individual" - : " Select individual"; - addMenuItem(graphPopupMenu, selectTitle, - new ActionListener() { - public void actionPerformed( - ActionEvent ee) { - ((InterfaceSelectablePointIcon) m_CurrentPointIcon) - .getSelectionListener() - .individualSelected( - ((InterfaceSelectablePointIcon) m_CurrentPointIcon) - .getEAIndividual()); - } - }); - } - } + public void actionPerformed(ActionEvent ee) { + toggleScientificY(true); + } + }); - if (point.getIcon() instanceof InterfaceDPointWithContent) { - m_CurrentPointIcon = point.getIcon(); - addMenuItem(graphPopupMenu, " Show individual", - new ActionListener() { - public void actionPerformed( - ActionEvent ee) { - ((InterfaceDPointWithContent) m_CurrentPointIcon) - .showIndividual(); - } - }); - } + if (FunctionArea.this.m_PointSetContainer.size() > 0) { + addMenuItem(graphPopupMenu, "Recolor all graphs", + new ActionListener() { - } - if (FunctionArea.this.m_PointSetContainer.size() > 0) { // there - // is - // at - // least - // one - // graph - // The graph info element - // int gIndex = getNearestGraphIndex(e.getX(), - // e.getY()); - addMenuItem(graphPopupMenu, "Graph Info: " - + getGraphInfo(e.getX(), e.getY()), - new ActionListener() { - public void actionPerformed(ActionEvent ee) { - DPoint temp = FunctionArea.this - .getDMeasures().getDPoint( - FunctionArea.this.m_x, - FunctionArea.this.m_y); - DPointIcon icon1 = new DPointIcon() { - public DBorder getDBorder() { - return new DBorder(4, 4, 4, 4); - } + public void actionPerformed(ActionEvent ee) { + recolorAllGraphsByIndex(); + } + }); + } - public void paint(Graphics g) { - g.drawLine(-2, 0, 2, 0); - g.drawLine(0, 0, 0, 4); - } - }; - temp.setIcon(icon1); - FunctionArea.this.addDElement(temp); - } - }, false); + if (m_RefPointListener != null) { + DPoint temp = getDMeasures().getDPoint(m_x, m_y); + addMenuItem(graphPopupMenu, "Select Reference Point:(" + + temp.x + "/" + temp.y + ")", + new ActionListener() { - addMenuItem(graphPopupMenu, " Remove graph", - new ActionListener() { - public void actionPerformed(ActionEvent ee) { - clearGraph(FunctionArea.this.m_x, - FunctionArea.this.m_y); - } - }); + public void actionPerformed(ActionEvent ee) { + DPoint temp = getDMeasures().getDPoint( + m_x, m_y); + double[] point = new double[2]; + point[0] = temp.x; + point[1] = temp.y; + m_RefPointListener.refPointGiven(point); + } + }); + } - addMenuItem(graphPopupMenu, " Change graph color", - new ActionListener() { - public void actionPerformed(ActionEvent ee) { - changeColorGraph(FunctionArea.this.m_x, - FunctionArea.this.m_y); - } - }); - } - graphPopupMenu.show(FunctionArea.this, e.getX(), e.getY()); - } - } - }); - } + // darn this point is an empty copy !! + DPoint point = getNearestDPoint(e.getX(), e.getY()); + if (point != null) { + // the point info element + addMenuItem(graphPopupMenu, "Nearest point: (" + + point.x + "/" + point.y + ")", + new ActionListener() { + + public void actionPerformed(ActionEvent ee) { + } + }, false); + + addMenuItem(graphPopupMenu, " Remove point", + new ActionListener() { + + public void actionPerformed(ActionEvent ee) { + removePoint(FunctionArea.this.m_x, + FunctionArea.this.m_y); + } + }); + + if (point.getIcon() instanceof InterfaceSelectablePointIcon) { + m_CurrentPointIcon = point.getIcon(); + if (((InterfaceSelectablePointIcon) m_CurrentPointIcon).getSelectionListener() != null) { + AbstractEAIndividual indy = ((InterfaceSelectablePointIcon) m_CurrentPointIcon).getEAIndividual(); + String selectTitle = indy.isMarked() ? " Deselect individual" + : " Select individual"; + addMenuItem(graphPopupMenu, selectTitle, + new ActionListener() { + + public void actionPerformed( + ActionEvent ee) { + ((InterfaceSelectablePointIcon) m_CurrentPointIcon).getSelectionListener().individualSelected( + ((InterfaceSelectablePointIcon) m_CurrentPointIcon).getEAIndividual()); + } + }); + } + } + + if (point.getIcon() instanceof InterfaceDPointWithContent) { + m_CurrentPointIcon = point.getIcon(); + addMenuItem(graphPopupMenu, " Show individual", + new ActionListener() { + + public void actionPerformed( + ActionEvent ee) { + ((InterfaceDPointWithContent) m_CurrentPointIcon).showIndividual(); + } + }); + } + + } + if (FunctionArea.this.m_PointSetContainer.size() > 0) { // there + // is + // at + // least + // one + // graph + // The graph info element + // int gIndex = getNearestGraphIndex(e.getX(), + // e.getY()); + addMenuItem(graphPopupMenu, "Graph Info: " + + getGraphInfo(e.getX(), e.getY()), + new ActionListener() { + + public void actionPerformed(ActionEvent ee) { + DPoint temp = FunctionArea.this.getDMeasures().getDPoint( + FunctionArea.this.m_x, + FunctionArea.this.m_y); + DPointIcon icon1 = new DPointIcon() { + + public DBorder getDBorder() { + return new DBorder(4, 4, 4, 4); + } + + public void paint(Graphics g) { + g.drawLine(-2, 0, 2, 0); + g.drawLine(0, 0, 0, 4); + } + }; + temp.setIcon(icon1); + FunctionArea.this.addDElement(temp); + } + }, false); + + addMenuItem(graphPopupMenu, " Remove graph", + new ActionListener() { + + public void actionPerformed(ActionEvent ee) { + clearGraph(FunctionArea.this.m_x, + FunctionArea.this.m_y); + } + }); + + addMenuItem(graphPopupMenu, " Change graph color", + new ActionListener() { + + public void actionPerformed(ActionEvent ee) { + changeColorGraph(FunctionArea.this.m_x, + FunctionArea.this.m_y); + } + }); + } + graphPopupMenu.show(FunctionArea.this, e.getX(), e.getY()); + } + } + }); + } /** * Create an enabled menu item with given title and listener, add it to the diff --git a/src/eva2/gui/JClassTree.java b/src/eva2/gui/JClassTree.java deleted file mode 100644 index 0997e69e..00000000 --- a/src/eva2/gui/JClassTree.java +++ /dev/null @@ -1,488 +0,0 @@ -package eva2.gui; -/* - * Title: EvA2 - * Description: - * Copyright: Copyright (c) 2003 - * Company: University of Tuebingen, Computer Architecture - * @author Holger Ulmer, Felix Streichert, Hannes Planatscher - * @version: $Revision: 201 $ - * $Date: 2007-10-25 16:11:23 +0200 (Thu, 25 Oct 2007) $ - * $Author: mkron $ - */ -import java.awt.*; -import java.awt.event.*; -import javax.swing.*; -import javax.swing.tree.DefaultMutableTreeNode; -import javax.swing.tree.TreePath; - -/** - * - */ -public class JClassTree extends JDialog { -// private ESPara m_Para; - JScrollPane jScrollPane1 = new JScrollPane(); - JTree treeView_ = new JTree(); - JPanel treeControlsPanel = new JPanel(); - JButton expandButton = new JButton(); - JButton collapseButton = new JButton(); - JButton editButton = new JButton(); - JButton cancelButton = new JButton(); - // Used for addNotify check. - private boolean fComponentsAdjusted = false; - /** - * Default constructor. - */ - public JClassTree() { - getContentPane().setLayout(new BorderLayout(0, 0)); - setVisible(false); - setSize(405, 362); - jScrollPane1 = new javax.swing.JScrollPane(); - jScrollPane1.setOpaque(true); - getContentPane().add(BorderLayout.CENTER, jScrollPane1); - treeView_ = new JTree(); - treeView_.setBounds(0, 0, 402, 324); - treeView_.setFont(new Font("Dialog", Font.PLAIN, 12)); - treeView_.setBackground(java.awt.Color.white); - jScrollPane1.getViewport().add(treeView_); - treeControlsPanel = new javax.swing.JPanel(); - treeControlsPanel.setLayout(new FlowLayout(FlowLayout.CENTER, 5, 5)); - treeControlsPanel.setFont(new Font("Dialog", Font.PLAIN, 12)); - treeControlsPanel.setForeground(java.awt.Color.black); - treeControlsPanel.setBackground(new java.awt.Color(204, 204, 204)); - getContentPane().add(BorderLayout.SOUTH, treeControlsPanel); - expandButton = new javax.swing.JButton(); - expandButton.setText("Expand All"); - expandButton.setActionCommand("Expand All"); - expandButton.setFont(new Font("Dialog", Font.BOLD, 12)); - expandButton.setBackground(new java.awt.Color(204, 204, 204)); - treeControlsPanel.add(expandButton); - collapseButton = new javax.swing.JButton(); - collapseButton.setText("Collapse All"); - collapseButton.setActionCommand("Collapse All"); - collapseButton.setFont(new Font("Dialog", Font.BOLD, 12)); - collapseButton.setBackground(new java.awt.Color(204, 204, 204)); - treeControlsPanel.add(collapseButton); - editButton = new javax.swing.JButton(); - editButton.setText("Edit Selected"); - editButton.setActionCommand("Edit Selected"); - editButton.setFont(new Font("Dialog", Font.BOLD, 12)); - editButton.setBackground(new java.awt.Color(204, 204, 204)); - treeControlsPanel.add(editButton); - cancelButton = new javax.swing.JButton(); - cancelButton.setText("Close"); - cancelButton.setActionCommand("Close"); - cancelButton.setFont(new Font("Dialog", Font.BOLD, 12)); - cancelButton.setBackground(new java.awt.Color(204, 204, 204)); - treeControlsPanel.add(cancelButton); - setTitle("Class View"); - - SymWindow aSymWindow = new SymWindow(); - this.addWindowListener(aSymWindow); - SymAction lSymAction = new SymAction(); - expandButton.addActionListener(lSymAction); - collapseButton.addActionListener(lSymAction); - editButton.addActionListener(lSymAction); - cancelButton.addActionListener(lSymAction); - - MouseListener ml = - new MouseAdapter() { - public void mouseClicked(MouseEvent e) { - int selRow = treeView_.getRowForLocation(e.getX(), e.getY()); - TreePath selPath = treeView_.getPathForLocation(e.getX(), e.getY()); - if (selRow != -1) { - if ((e.getClickCount() == 2) || - ((e.getModifiers() & InputEvent.BUTTON3_MASK) != 0)) { - doubleClick(selRow, selPath); - } - } - } - }; - treeView_.addMouseListener(ml); - // - Insets inset = new Insets(0, 5, 0, 5); - expandButton.setMargin(inset); - collapseButton.setMargin(inset); - editButton.setMargin(inset); - cancelButton.setMargin(inset); - } - - - /** - * Description of the Method - * - *@param selRow Description of the Parameter - *@param selPath Description of the Parameter - */ - void doubleClick(int selRow, TreePath selPath) { - System.out.println("row " + selRow + " selected"); - Object[] objs = selPath.getPath(); - Object thing = ((DefaultMutableTreeNode) objs[objs.length - 1]).getUserObject(); - showProperties(thing); - } - - - /** - * Constructor for the JClassTree object - * - *@param sTitle Description of the Parameter - */ - public JClassTree(String sTitle) { - this(); - setTitle(sTitle); - } - - - /** - * Make the dialog visible. - * - *@param b The new visible value - */ - public void setVisible(boolean b) { - if (b) { - setLocation(50, 50); - } - super.setVisible(b); - } - - - - /** - * Adds a feature to the Notify attribute of the JClassTree object - */ - public void addNotify() { - // Record the size of the window prior to calling parents addNotify. - Dimension d = getSize(); - Insets in = getInsets(); - - super.addNotify(); - - if (fComponentsAdjusted) { - return; - } - // Adjust components according to the insets - setSize(in.left + in.right + d.width, in.top + in.bottom + d.height); - Component components[] = getContentPane().getComponents(); - for (int i = 0; i < components.length; i++) { - Point p = components[i].getLocation(); - p.translate(in.left, in.top); - components[i].setLocation(p); - } - fComponentsAdjusted = true; - } - - - /** - * The main program for the JClassTree class - * - *@param args The command line arguments - */ - public static void main(String[] args) { - JClassTree Main = new JClassTree(); - Main.setVisible(true); - } - - - /** - * Description of the Class - * - *@author ulmerh - *@created 20. Januar 2003 - */ - class SymWindow extends WindowAdapter { - /** - * Description of the Method - * - *@param event Description of the Parameter - */ - public void windowClosing(java.awt.event.WindowEvent event) { - Object object = event.getSource(); - if (object == JClassTree.this) { - JClassTree_WindowClosing(event); - } - } - } - - - /** - * Description of the Method - * - *@param event Description of the Parameter - */ - void JClassTree_WindowClosing(WindowEvent event) { - setVisible(false); - // hide the Frame - } - - - /** - * Description of the Class - * - *@author ulmerh - *@created 20. Januar 2003 - */ - class SymAction implements ActionListener { - /** - * Description of the Method - * - *@param event Description of the Parameter - */ - public void actionPerformed(java.awt.event.ActionEvent event) { - Object object = event.getSource(); - if (object == expandButton) { - expandButton_actionPerformed(event); - } else if (object == collapseButton) { - collapseButton_actionPerformed(event); - } else if (object == editButton) { - editButton_actionPerformed(event); - } else if (object == cancelButton) { - cancelButton_actionPerformed(event); - } - } - } - - - /** - * Description of the Method - * - *@param event Description of the Parameter - */ - void expandButton_actionPerformed(java.awt.event.ActionEvent event) { - expandTree(); - } - - - /** - * Expand the tree to show all nodes. - */ - public void expandTree() { - int row = 0; - while (row < treeView_.getRowCount()) { - if (treeView_.isCollapsed(row)) { - treeView_.expandRow(row); - } - row++; - } - } - - - /** - * Description of the Method - * - *@param event Description of the Parameter - */ - void collapseButton_actionPerformed(java.awt.event.ActionEvent event) { - treeView_.collapseRow(0); - } - - - /** - * Description of the Method - * - *@param event Description of the Parameter - */ - void editButton_actionPerformed(java.awt.event.ActionEvent event) { - Object[] objs = treeView_.getSelectionPath().getPath(); - showProperties(((DefaultMutableTreeNode) objs[objs.length - 1]).getUserObject()); - } - - - /** - * Description of the Method - * - *@param event Description of the Parameter - */ - void cancelButton_actionPerformed(java.awt.event.ActionEvent event) { - setVisible(false); - } - - - /** - * Set the JPane for which the JTree is to be - * built. - * - *@param obj Description of the Parameter - */ -// public void setPara(JPane Para) { -// Enumeration layers; -// Layer ly; -// LayerChild child; -// Graph graph; -// Axis axis; -// CartesianRenderer rend; -// LineAttribute attr; -// GridAttribute gattr; -// PointAttribute pattr; -// // -// DefaultTreeModel treeModel; -// DefaultMutableTreeNode node; -// DefaultMutableTreeNode paneNode; -// -// DefaultMutableTreeNode layerNode; -// DefaultMutableTreeNode childNode; -// DefaultMutableTreeNode graphNode; -// DefaultMutableTreeNode attrNode; -// DefaultMutableTreeNode gattrNode; -// DefaultMutableTreeNode pattrNode; -// DefaultMutableTreeNode axisNode; -// DefaultMutableTreeNode titleNode; -// -// m_Para = Para; -// paneNode = new DefaultMutableTreeNode(m_Para); -// treeModel = new DefaultTreeModel(paneNode); -// treeView_.setModel(treeModel); -// // -// Component[] comps = pane_.getComponents(); -// for(int il=0; il < comps.length; il++) { -// if(comps[il] instanceof Layer) { -// ly = (Layer)comps[il]; -// } else { -// continue; -// } -// String name, className; -// layerNode = new DefaultMutableTreeNode(ly); -// treeModel.insertNodeInto(layerNode, paneNode, treeModel.getChildCount(paneNode)); -// for(Enumeration childs = ly.childElements(); childs.hasMoreElements();) { -// child = (LayerChild)childs.nextElement(); -// className = child.getClass().getName(); -// name = className.substring(className.lastIndexOf(".")+1); -// childNode = new DefaultMutableTreeNode(child); -// treeModel.insertNodeInto(childNode,layerNode,treeModel.getChildCount(layerNode)); -// } -// graph = ly.getGraph(); -// className = graph.getClass().getName(); -// name = className.substring(className.lastIndexOf(".")+1); -// if(graph instanceof CartesianGraph) { -// graphNode = new DefaultMutableTreeNode(graph); -// treeModel.insertNodeInto(graphNode,layerNode,treeModel.getChildCount(layerNode)); -// rend = ((CartesianGraph)graph).getRenderer(); -// if(rend instanceof LineCartesianRenderer) { -// attr = (LineAttribute)((LineCartesianRenderer)rend).getAttribute(); -// if(attr != null) { -// className = attr.getClass().getName(); -// name = className.substring(className.lastIndexOf(".")+1); -// attrNode = new DefaultMutableTreeNode(attr); -// treeModel.insertNodeInto(attrNode,graphNode,treeModel.getChildCount(graphNode)); -// } -// } else if(rend instanceof GridCartesianRenderer) { -// gattr = (GridAttribute)((GridCartesianRenderer)rend).getAttribute(); -// if(gattr != null) { -// className = gattr.getClass().getName(); -// name = className.substring(className.lastIndexOf(".")+1); -// gattrNode = new DefaultMutableTreeNode(gattr); -// treeModel.insertNodeInto(gattrNode, -// graphNode, -// treeModel.getChildCount(graphNode)); -// } -// } else if(rend instanceof PointCartesianRenderer) { -// pattr = (PointAttribute)((PointCartesianRenderer)rend).getAttribute(); -// if(pattr != null) { -// className = pattr.getClass().getName(); -// name = className.substring(className.lastIndexOf(".")+1); -// pattrNode = new DefaultMutableTreeNode(pattr); -// treeModel.insertNodeInto(pattrNode, -// graphNode, -// treeModel.getChildCount(graphNode)); -// } -// } -// for(Enumeration axes = ((CartesianGraph)graph).xAxisElements(); -// axes.hasMoreElements();) { -// axis = (Axis)axes.nextElement(); -// className = axis.getClass().getName(); -// name = className.substring(className.lastIndexOf(".")+1); -// if(axis instanceof SpaceAxis) { -// axisNode = new DefaultMutableTreeNode(axis); -// treeModel.insertNodeInto(axisNode, -// graphNode, -// treeModel.getChildCount(graphNode)); -// SGLabel title = axis.getTitle(); -// if(title != null) { -// titleNode = new DefaultMutableTreeNode(title); -// treeModel.insertNodeInto(titleNode, -// axisNode, -// treeModel.getChildCount(axisNode)); -// } -// } else { // not a SpaceAxis -// axisNode = new DefaultMutableTreeNode(axis); -// treeModel.insertNodeInto(axisNode, -// graphNode, -// treeModel.getChildCount(graphNode)); -// } -// } -// for(Enumeration axes = ((CartesianGraph)graph).yAxisElements(); -// axes.hasMoreElements();) { -// axis = (Axis)axes.nextElement(); -// className = axis.getClass().getName(); -// name = className.substring(className.lastIndexOf(".")+1); -// if(axis instanceof SpaceAxis) { -// axisNode = new DefaultMutableTreeNode(axis); -// treeModel.insertNodeInto(axisNode, -// graphNode, -// treeModel.getChildCount(graphNode)); -// SGLabel title = axis.getTitle(); -// if(title != null) { -// titleNode = new DefaultMutableTreeNode(title); -// treeModel.insertNodeInto(titleNode, -// axisNode, -// treeModel.getChildCount(axisNode)); -// } -// } else { // not a SpaceAxis -// axisNode = new DefaultMutableTreeNode(axis); -// treeModel.insertNodeInto(axisNode, -// graphNode, -// treeModel.getChildCount(graphNode)); -// } -// } -// } else { // not a CartesianGraph -// graphNode = new DefaultMutableTreeNode(graph); -// treeModel.insertNodeInto(graphNode, -// layerNode, -// treeModel.getChildCount(layerNode)); -// } -// } // for layers -// int row=0; -// while(row < treeView_.getRowCount()) { -// if(treeView_.isCollapsed(row)) { -// treeView_.expandRow(row); -// } -// row++; -// } -// } - - void showProperties(Object obj) { - System.out.println("showProperties obj=" + obj.getClass()); -// if(obj instanceof SGLabel) { -// if(sg_ == (SGLabelDialog) null) -// sg_ = new SGLabelDialog(); -// -// sg_.setSGLabel((SGLabel) obj, pane_); -// if(!sg_.isShowing()) -// sg_.setVisible(true); -// } -// else -// if(obj instanceof Logo) { -// if(lg_ == null) { -// lg_ = new LogoDialog(); -// } -// lg_.setLogo((Logo) obj, pane_); -// if(!lg_.isShowing()) -// lg_.setVisible(true); -// } - } - - - /** - * Gets the frame attribute of the JClassTree object - * - *@return The frame value - */ - private Frame getFrame() { - Container theFrame = this; - do { - theFrame = theFrame.getParent(); - } while ((theFrame != null) && !(theFrame instanceof Frame)); - if (theFrame == null) { - theFrame = new Frame(); - } - return (Frame) theFrame; - } -} diff --git a/src/eva2/gui/Plot.java b/src/eva2/gui/Plot.java index ad88d899..43e7a9ba 100644 --- a/src/eva2/gui/Plot.java +++ b/src/eva2/gui/Plot.java @@ -1,18 +1,11 @@ package eva2.gui; /* - * Title: EvA2 - * Description: - * Copyright: Copyright (c) 2003 - * Company: University of Tuebingen, Computer Architecture - * @author Holger Ulmer, Felix Streichert, Hannes Planatscher - * @version: $Revision: 322 $ - * $Date: 2007-12-11 17:24:07 +0100 (Tue, 11 Dec 2007) $ - * $Author: mkron $ + * Title: EvA2 Description: Copyright: Copyright (c) 2003 Company: University of + * Tuebingen, Computer Architecture @author Holger Ulmer, Felix Streichert, + * Hannes Planatscher @version: $Revision: 322 $ $Date: 2007-12-11 17:24:07 + * +0100 (Tue, 11 Dec 2007) $ $Author: mkron $ */ -/*==========================================================================* - * IMPORTS - *==========================================================================*/ import java.awt.AWTException; import java.awt.Dimension; import java.awt.FlowLayout; @@ -48,491 +41,489 @@ import eva2.server.go.individuals.AbstractEAIndividual; import eva2.server.go.populations.Population; import eva2.tools.BasicResourceLoader; import eva2.tools.chart2d.DPointSet; +import java.awt.*; import javax.swing.*; import javax.swing.event.InternalFrameAdapter; import javax.swing.event.InternalFrameEvent; -/*==========================================================================* - * CLASS DECLARATION - *==========================================================================*/ /** - * + * ToDo: Rename to PlotWindow */ public class Plot implements PlotInterface, Serializable { - /** - * Generated serial version identifier. - */ - private static final long serialVersionUID = -9027101244918249825L; - public static boolean TRACE = false; - private JFileChooser m_FileChooser; - private JPanel m_ButtonPanel; - private String m_PlotName; - private String m_xname; - private String m_yname; - protected FunctionArea m_PlotArea; - protected JInternalFrame m_Frame; + /** + * Generated serial version identifier. + */ + private static final long serialVersionUID = -9027101244918249825L; + private JFileChooser m_FileChooser; + private JPanel m_ButtonPanel; + private String plotName; + private String xAxisText; + private String yAxisText; + protected FunctionArea m_PlotArea; + protected JInternalFrame m_Frame; - /** - * You might want to try to assign the x-range as x and y-range as y array - * parameters. - */ - public Plot(String PlotName, String xname, String yname, double[] x, double[] y) { - this(PlotName, xname, yname, true); - DPointSet points = new DPointSet(); - for (int i = 0; i < x.length; i++) { - points.addDPoint(x[i], y[i]); - } - m_PlotArea.addDElement(points); - } + /** + * You might want to try to assign the x-range as x and y-range as y array + * parameters. + */ + public Plot(String plotName, String xname, String yname, double[] x, double[] y) { + this(plotName, xname, yname, true); + DPointSet points = new DPointSet(); + for (int i = 0; i < x.length; i++) { + points.addDPoint(x[i], y[i]); + } + m_PlotArea.addDElement(points); + } - /** - * A basic constructor. - * - * @param PlotName - * @param xname - * @param yname - * @param init - */ - public Plot(String PlotName, String xname, String yname) { - this(PlotName, xname, yname, true); - } - - /** - * A basic constructor. - * - * @param PlotName - * @param xname - * @param yname - * @param init - */ - public Plot(String PlotName, String xname, String yname, boolean init) { - if (TRACE) - System.out.println("Constructor Plot " + PlotName); - m_xname = xname; - m_yname = yname; - m_PlotName = PlotName; - if (init) - init(); - } + /** + * A basic constructor. + * + * @param PlotName + * @param xname + * @param yname + * @param init + */ + public Plot(String PlotName, String xname, String yname) { + this(PlotName, xname, yname, true); + } - protected void installButtons(JPanel buttonPan) { - JButton ClearButton = new JButton("Clear"); - ClearButton.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - clearAll(); - } - }); - JButton LOGButton = new JButton("Log/Lin"); - LOGButton - .setToolTipText("Toggle between a linear and a log scale on the y-axis."); - LOGButton.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - m_PlotArea.toggleLog(); - } - }); - JButton ExportButton = new JButton("Export..."); - ExportButton - .setToolTipText("Exports the graph data to a simple ascii file."); - ExportButton.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - exportPlot(); - } - }); - JButton DumpButton = new JButton("Dump"); - DumpButton.setToolTipText("Dump the graph data to standard output"); - DumpButton.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - m_PlotArea.exportToAscii(); - } - }); + /** + * A basic constructor. + * + * @param plotName + * @param xname + * @param yname + * @param init + */ + public Plot(String plotName, String xname, String yname, boolean init) { + xAxisText = xname; + yAxisText = yname; + this.plotName = plotName; + if (init) { + this.init(); + } + } - JButton saveImageButton = new JButton("Save as PNG..."); - saveImageButton.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - try { - Robot robot = new Robot(); - Rectangle area; - area = m_Frame.getBounds(); - BufferedImage bufferedImage = robot - .createScreenCapture(area); - JFileChooser fc = new JFileChooser(); - if (fc.showSaveDialog(m_Frame) != JFileChooser.APPROVE_OPTION) - return; - // System.out.println("Name " + outfile); - try { - /* - * Old version FileOutputStream fos = new - * FileOutputStream - * (fc.getSelectedFile().getAbsolutePath()+".jpeg"); - * BufferedOutputStream bos = new - * BufferedOutputStream(fos); JPEGImageEncoder encoder = - * JPEGCodec.createJPEGEncoder(bos); - * encoder.encode(bufferedImage); bos.close(); - */ - File file = new File(fc.getSelectedFile() - .getAbsolutePath() - + ".png"); - ImageIO.write(bufferedImage, "png", file); - /* - * JPEG version with javax.imageio float compression = - * 0.8f; FileImageOutputStream out = new - * FileImageOutputStream(new - * File(fc.getSelectedFile().getAbsolutePath - * ()+".jpeg")); ImageWriter encoder = - * (ImageWriter)ImageIO - * .getImageWritersByFormatName("JPEG").next(); - * JPEGImageWriteParam param = new - * JPEGImageWriteParam(null); - * - * - * param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT - * ); param.setCompressionQuality(compression); - * - * encoder.setOutput(out); encoder.write((IIOMetadata) - * null, new IIOImage(bufferedImage,null,null), param); - * - * out.close(); - */ + protected void installButtons(JPanel buttonPan) { + JButton ClearButton = new JButton("Clear"); + ClearButton.addActionListener(new ActionListener() { - } catch (Exception eee) { - System.err.println("Error on exporting PNG: " - + eee.getMessage()); - } - } catch (AWTException ee) { - System.err.println("Error on creating PNG: " - + ee.getMessage()); - ee.printStackTrace(); - } - } - }); + public void actionPerformed(ActionEvent e) { + clearAll(); + } + }); + JButton LOGButton = new JButton("Log/Lin"); + LOGButton.setToolTipText("Toggle between a linear and a log scale on the y-axis."); + LOGButton.addActionListener(new ActionListener() { - buttonPan.add(ClearButton); - buttonPan.add(LOGButton); - buttonPan.add(DumpButton); - buttonPan.add(ExportButton); - // m_ButtonPanel.add(PrintButton); - // m_ButtonPanel.add(OpenButton); - // m_ButtonPanel.add(SaveButton); - buttonPan.add(saveImageButton); - } + public void actionPerformed(ActionEvent e) { + m_PlotArea.toggleLog(); + } + }); + JButton ExportButton = new JButton("Export..."); + ExportButton.setToolTipText("Exports the graph data to a simple ascii file."); + ExportButton.addActionListener(new ActionListener() { - /** - * - */ - public void init() { - m_Frame = new JEFrame("Plot: " + m_PlotName); - BasicResourceLoader loader = BasicResourceLoader.instance(); - byte[] bytes = loader.getBytesFromResourceLocation(EvAInfo.iconLocation, true); + public void actionPerformed(ActionEvent e) { + exportPlot(); + } + }); + JButton DumpButton = new JButton("Dump"); + DumpButton.setToolTipText("Dump the graph data to standard output"); + DumpButton.addActionListener(new ActionListener() { + + public void actionPerformed(ActionEvent e) { + m_PlotArea.exportToAscii(); + } + }); + + JButton saveImageButton = new JButton("Save as PNG..."); + saveImageButton.addActionListener(new ActionListener() { + + public void actionPerformed(ActionEvent e) { + try { + Robot robot = new Robot(); + Rectangle area; + area = m_Frame.getBounds(); + BufferedImage bufferedImage = robot.createScreenCapture(area); + JFileChooser fc = new JFileChooser(); + if (fc.showSaveDialog(m_Frame) != JFileChooser.APPROVE_OPTION) { + return; + } + // System.out.println("Name " + outfile); + try { + /* + * Old version FileOutputStream fos = new + * FileOutputStream + * (fc.getSelectedFile().getAbsolutePath()+".jpeg"); + * BufferedOutputStream bos = new + * BufferedOutputStream(fos); JPEGImageEncoder encoder = + * JPEGCodec.createJPEGEncoder(bos); + * encoder.encode(bufferedImage); bos.close(); + */ + File file = new File(fc.getSelectedFile().getAbsolutePath() + + ".png"); + ImageIO.write(bufferedImage, "png", file); + /* + * JPEG version with javax.imageio float compression = + * 0.8f; FileImageOutputStream out = new + * FileImageOutputStream(new + * File(fc.getSelectedFile().getAbsolutePath + * ()+".jpeg")); ImageWriter encoder = + * (ImageWriter)ImageIO + * .getImageWritersByFormatName("JPEG").next(); + * JPEGImageWriteParam param = new + * JPEGImageWriteParam(null); + * + * + * param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT + * ); param.setCompressionQuality(compression); + * + * encoder.setOutput(out); encoder.write((IIOMetadata) + * null, new IIOImage(bufferedImage,null,null), param); + * + * out.close(); + */ + + } catch (Exception eee) { + System.err.println("Error on exporting PNG: " + + eee.getMessage()); + } + } catch (AWTException ee) { + System.err.println("Error on creating PNG: " + + ee.getMessage()); + ee.printStackTrace(); + } + } + }); + + buttonPan.add(ClearButton); + buttonPan.add(LOGButton); + buttonPan.add(DumpButton); + buttonPan.add(ExportButton); + // m_ButtonPanel.add(PrintButton); + // m_ButtonPanel.add(OpenButton); + // m_ButtonPanel.add(SaveButton); + buttonPan.add(saveImageButton); + } + + /** + * + */ + public void init() { + m_Frame = new JEFrame("Plot: " + plotName); + BasicResourceLoader loader = BasicResourceLoader.instance(); + byte[] bytes = loader.getBytesFromResourceLocation(EvAInfo.iconLocation, true); // m_Frame.setIconImage(Toolkit.getDefaultToolkit().createImage(bytes)); - m_ButtonPanel = new JPanel(); - m_PlotArea = new FunctionArea(m_xname, m_yname); - m_ButtonPanel.setLayout(new FlowLayout(FlowLayout.LEFT, 10, 10)); + m_ButtonPanel = new JPanel(); + m_PlotArea = new FunctionArea(xAxisText, yAxisText); + m_ButtonPanel.setLayout(new FlowLayout(FlowLayout.LEFT, 10, 10)); - installButtons(m_ButtonPanel); + installButtons(m_ButtonPanel); - // getContentPane().smultetLayout( new GridLayout(1, 4) ); - m_Frame.getContentPane().add(m_ButtonPanel, "South"); - m_Frame.getContentPane().add(m_PlotArea, "Center"); // north was not so - // nice - m_Frame.addInternalFrameListener(new InternalFrameAdapter() { + // getContentPane().smultetLayout( new GridLayout(1, 4) ); + m_Frame.add(m_ButtonPanel, BorderLayout.PAGE_END); + m_Frame.add(m_PlotArea, BorderLayout.CENTER); // north was not so + // nice + m_Frame.addInternalFrameListener(new InternalFrameAdapter() { @Override public void internalFrameClosing(InternalFrameEvent e) { super.internalFrameClosing(e); m_PlotArea.clearAll(); // this was a memory leak - m_PlotArea = null; - m_Frame.dispose(); + m_PlotArea = null; + m_Frame.dispose(); } - }); - m_Frame.pack(); - m_Frame.setVisible(true); - } - - /** - * Indicate whether graph legend entries should show their unique number. - */ - public void setAppendIndexInLegend(boolean appendIndexInLegend) { - this.m_PlotArea.setAppendIndexInLegend(appendIndexInLegend); - } - - /** - * Indicates whether graph legend entries show their unique number. - */ - public boolean isAppendIndexInLegend() { - return m_PlotArea.isAppendIndexInLegend(); - } - - /** - * Indicate whether the graphs are annotated by tool tip info strings. - * @return true if the graphs are annotated by tool tip info strings - */ - public boolean isShowGraphToolTips() { - return m_PlotArea.isShowGraphToolTips(); - } - - /** - * Toggle whether the graphs should be annotated by tool tip info strings. - * @param doShowGraphToolTips true if the graphs should be annotated by tool tip info strings - */ - public void setShowGraphToolTips(boolean doShowGraphToolTips) { - m_PlotArea.setShowGraphToolTips(doShowGraphToolTips); - } - - /** - * Draw a population to the Plot instance. Each individual is annotated with - * the given prefix and its fitness. - * - * @param prefix - * @param pop - */ - public void drawPopulation(String prefix, Population pop) { - for (int i = 0; i < pop.size(); i++) { - drawIndividual(0, 2, prefix, pop.getEAIndividual(i)); - } - } + }); + m_Frame.pack(); + m_Frame.setVisible(true); + } - /** - * Draw an individual to the Plot instance. It is annotated with the - * given prefix and its fitness with short scientific notation. - * - * @param prefix - * @param pop - * @see FunctionArea.drawIcon - */ - public void drawIndividual(int iconType, int graphID, String prefix, AbstractEAIndividual indy) { - StringBuffer sb = new StringBuffer(); - Formatter formatter = new Formatter(sb, Locale.US); - formatter.format("%s %.3e", prefix, indy.getFitness(0)); + /** + * Indicate whether graph legend entries should show their unique number. + */ + public void setAppendIndexInLegend(boolean appendIndexInLegend) { + this.m_PlotArea.setAppendIndexInLegend(appendIndexInLegend); + } - getFunctionArea().drawIcon(iconType, sb.toString(), indy.getDoublePosition(), graphID); - } + /** + * Indicates whether graph legend entries show their unique number. + */ + public boolean isAppendIndexInLegend() { + return m_PlotArea.isAppendIndexInLegend(); + } - public void setPreferredSize(Dimension prefSize) { - if (m_Frame != null) { - m_Frame.setPreferredSize(prefSize); - m_Frame.pack(); - } - } + /** + * Indicate whether the graphs are annotated by tool tip info strings. + * + * @return true if the graphs are annotated by tool tip info strings + */ + public boolean isShowGraphToolTips() { + return m_PlotArea.isShowGraphToolTips(); + } - /** - * Return true if the Plot object is valid. - * - * @return true if the Plot object is valid - */ - public boolean isValid() { - return (m_Frame != null) && (m_PlotArea != null); - } + /** + * Toggle whether the graphs should be annotated by tool tip info strings. + * + * @param doShowGraphToolTips true if the graphs should be annotated by tool + * tip info strings + */ + public void setShowGraphToolTips(boolean doShowGraphToolTips) { + m_PlotArea.setShowGraphToolTips(doShowGraphToolTips); + } - /** - * - */ - public void setConnectedPoint(double x, double y, int func) { - if (TRACE) - System.out.println("size before is " - + m_PlotArea.getPointCount(func)); - m_PlotArea.setConnectedPoint(x, y, func); - if (TRACE) { - System.out.println("added " + x + "/" + y + " to graph " + func); - System.out.println("size is now " + m_PlotArea.getPointCount(func)); - } - } + /** + * Draw a population to the Plot instance. Each individual is annotated with + * the given prefix and its fitness. + * + * @param prefix + * @param pop + */ + public void drawPopulation(String prefix, Population pop) { + for (int i = 0; i < pop.size(); i++) { + drawIndividual(0, 2, prefix, pop.getEAIndividual(i)); + } + } - public int getPointCount(int graphLabel) { - return m_PlotArea.getPointCount(graphLabel); - } + /** + * Draw an individual to the Plot instance. It is annotated with the given + * prefix and its fitness with short scientific notation. + * + * @param prefix + * @param pop + * @see FunctionArea.drawIcon + */ + public void drawIndividual(int iconType, int graphID, String prefix, AbstractEAIndividual indy) { + StringBuffer sb = new StringBuffer(); + Formatter formatter = new Formatter(sb, Locale.US); + formatter.format("%s %.3e", prefix, indy.getFitness(0)); - /** - * - */ - public void addGraph(int g1, int g2, boolean forceAdd) { - m_PlotArea.addGraph(g1, g2, forceAdd); - } + getFunctionArea().drawIcon(iconType, sb.toString(), indy.getDoublePosition(), graphID); + } - /** - * - */ - public void setUnconnectedPoint(double x, double y, int GraphLabel) { - m_PlotArea.setUnconnectedPoint(x, y, GraphLabel); - } + public void setPreferredSize(Dimension prefSize) { + if (m_Frame != null) { + m_Frame.setPreferredSize(prefSize); + m_Frame.pack(); + } + } - /** - * - */ - public void clearAll() { - m_PlotArea.clearAll(); - m_PlotArea.removeAllDElements(); - m_PlotArea.clearLegend(); - m_Frame.repaint(); - } + /** + * Return true if the Plot object is valid. + * + * @return true if the Plot object is valid + */ + public boolean isValid() { + return (m_Frame != null) && (m_PlotArea != null); + } - /** - * - */ - public void clearGraph(int GraphNumber) { - m_PlotArea.clearGraph(GraphNumber); - } + /** + * + */ + public void setConnectedPoint(double x, double y, int func) { + m_PlotArea.setConnectedPoint(x, y, func); + } - /** - * - */ - public void setInfoString(int GraphLabel, String Info, float stroke) { - m_PlotArea.setInfoString(GraphLabel, Info, stroke); - } + public int getPointCount(int graphLabel) { + return m_PlotArea.getPointCount(graphLabel); + } - /** - * - */ - public void jump() { - m_PlotArea.jump(); - } + /** + * + */ + public void addGraph(int g1, int g2, boolean forceAdd) { + m_PlotArea.addGraph(g1, g2, forceAdd); + } - /** - */ - protected Object openObject() { - if (m_FileChooser == null) - createFileChooser(); - int returnVal = m_FileChooser.showOpenDialog(m_Frame); - if (returnVal == JFileChooser.APPROVE_OPTION) { - File selected = m_FileChooser.getSelectedFile(); - try { - ObjectInputStream oi = new ObjectInputStream( - new BufferedInputStream(new FileInputStream(selected))); - Object obj = oi.readObject(); - oi.close(); - Class ClassType = Class.forName("FunctionArea"); - if (!ClassType.isAssignableFrom(obj.getClass())) - throw new Exception("Object not of type: " - + ClassType.getName()); - return obj; - } catch (Exception ex) { - JOptionPane.showMessageDialog(m_Frame, "Couldn't read object: " - + selected.getName() + "\n" + ex.getMessage(), - "Open object file", JOptionPane.ERROR_MESSAGE); - } - } - return null; - } + /** + * + */ + public void setUnconnectedPoint(double x, double y, int GraphLabel) { + m_PlotArea.setUnconnectedPoint(x, y, GraphLabel); + } - /** - * Just dump the plot to stdout. - */ - protected void dumpPlot() { - m_PlotArea.exportToAscii(); - } + /** + * + */ + public void clearAll() { + m_PlotArea.clearAll(); + m_PlotArea.removeAllDElements(); + m_PlotArea.clearLegend(); + m_Frame.repaint(); + } - /** - * - */ - protected void exportPlot() { - if (m_FileChooser == null) - createFileChooser(); - int returnVal = m_FileChooser.showSaveDialog(m_Frame); - if (returnVal == JFileChooser.APPROVE_OPTION) { - File sFile = m_FileChooser.getSelectedFile(); - if (sFile.exists()) { - returnVal = JOptionPane.showConfirmDialog(m_Frame, "The file " - + sFile.getName() + " already exists. Overwrite?"); - if (returnVal != JOptionPane.YES_OPTION) - return; - } - if (!(m_PlotArea.exportToAscii(sFile))) { - JOptionPane.showMessageDialog(m_Frame, - "Couldn't write to file: " + sFile.getName(), - "Export error", JOptionPane.ERROR_MESSAGE); - } - } - } + /** + * + */ + public void clearGraph(int GraphNumber) { + m_PlotArea.clearGraph(GraphNumber); + } - /** - * - */ - protected void saveObject(Object object) { - if (m_FileChooser == null) - createFileChooser(); - int returnVal = m_FileChooser.showSaveDialog(m_Frame); - if (returnVal == JFileChooser.APPROVE_OPTION) { - File sFile = m_FileChooser.getSelectedFile(); - try { - ObjectOutputStream oo = new ObjectOutputStream( - new BufferedOutputStream(new FileOutputStream(sFile))); - oo.writeObject(object); - oo.close(); - } catch (IOException ex) { - JOptionPane.showMessageDialog(m_Frame, - "Couldn't write to file: " + sFile.getName() + "\n" - + ex.getMessage(), "Save object", - JOptionPane.ERROR_MESSAGE); - } - } - } + /** + * + */ + public void setInfoString(int GraphLabel, String Info, float stroke) { + m_PlotArea.setInfoString(GraphLabel, Info, stroke); + } - /** - * - */ - protected void createFileChooser() { - m_FileChooser = new JFileChooser(new File("/resources")); - m_FileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY); - } + /** + * + */ + public void jump() { + m_PlotArea.jump(); + } - /** - * - */ - public String getName() { - return this.m_PlotName; - } + /** + */ + protected Object openObject() { + if (m_FileChooser == null) { + createFileChooser(); + } + int returnVal = m_FileChooser.showOpenDialog(m_Frame); + if (returnVal == JFileChooser.APPROVE_OPTION) { + File selected = m_FileChooser.getSelectedFile(); + try { + ObjectInputStream oi = new ObjectInputStream( + new BufferedInputStream(new FileInputStream(selected))); + Object obj = oi.readObject(); + oi.close(); + Class ClassType = Class.forName("FunctionArea"); + if (!ClassType.isAssignableFrom(obj.getClass())) { + throw new Exception("Object not of type: " + + ClassType.getName()); + } + return obj; + } catch (Exception ex) { + JOptionPane.showMessageDialog(m_Frame, "Couldn't read object: " + + selected.getName() + "\n" + ex.getMessage(), + "Open object file", JOptionPane.ERROR_MESSAGE); + } + } + return null; + } - /** - * - */ - public FunctionArea getFunctionArea() { - return m_PlotArea; - } + /** + * Just dump the plot to stdout. + */ + protected void dumpPlot() { + m_PlotArea.exportToAscii(); + } - /** - * - */ - public void dispose() { - m_Frame.dispose(); - m_Frame = null; - } + /** + * + */ + protected void exportPlot() { + if (m_FileChooser == null) { + createFileChooser(); + } + int returnVal = m_FileChooser.showSaveDialog(m_Frame); + if (returnVal == JFileChooser.APPROVE_OPTION) { + File sFile = m_FileChooser.getSelectedFile(); + if (sFile.exists()) { + returnVal = JOptionPane.showConfirmDialog(m_Frame, "The file " + + sFile.getName() + " already exists. Overwrite?"); + if (returnVal != JOptionPane.YES_OPTION) { + return; + } + } + if (!(m_PlotArea.exportToAscii(sFile))) { + JOptionPane.showMessageDialog(m_Frame, + "Couldn't write to file: " + sFile.getName(), + "Export error", JOptionPane.ERROR_MESSAGE); + } + } + } - /** - * Add the corners of the given range as unconnected points. - * - * @param range - * @param graphLabel - */ - public void setCornerPoints(double[][] range, int graphLabel) { - setUnconnectedPoint(range[0][0], range[1][0], graphLabel); - setUnconnectedPoint(range[0][1], range[1][1], graphLabel); - } + /** + * + */ + protected void saveObject(Object object) { + if (m_FileChooser == null) { + createFileChooser(); + } + int returnVal = m_FileChooser.showSaveDialog(m_Frame); + if (returnVal == JFileChooser.APPROVE_OPTION) { + File sFile = m_FileChooser.getSelectedFile(); + try { + ObjectOutputStream oo = new ObjectOutputStream( + new BufferedOutputStream(new FileOutputStream(sFile))); + oo.writeObject(object); + oo.close(); + } catch (IOException ex) { + JOptionPane.showMessageDialog(m_Frame, + "Couldn't write to file: " + sFile.getName() + "\n" + + ex.getMessage(), "Save object", + JOptionPane.ERROR_MESSAGE); + } + } + } - public void setColorByIndex(int graphLabel, int index) { - getFunctionArea().setColorByIndex(graphLabel, index); - } + /** + * + */ + protected void createFileChooser() { + m_FileChooser = new JFileChooser(new File("/resources")); + m_FileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY); + } - public void recolorAllGraphsByIndex() { - getFunctionArea().recolorAllGraphsByIndex(); - } - - // /** - // * Just for testing the Plot class. - // */ - // public static void main( String[] args ){ - // Plot plot = new Plot("Plot-Test","x-value","y-value"); - // plot.init(); - // double x; - // for (x= 0; x <6000; x++) { - // //double y = SpecialFunction.getnormcdf(x); - // // double yy = 0.5*SpecialFunction.getnormpdf(x); - // double n = Math.sin(((double)x/1000*Math.PI)); - // //plot.setConnectedPoint(x,Math.sin(x),0); - // //plot.setConnectedPoint(x,Math.cos(x),1); - // //plot.setConnectedPoint(x,y,0); - // plot.setConnectedPoint(x,n,1); - // } - // //plot.addGraph(1,2); - // } + /** + * + */ + public String getName() { + return this.plotName; + } + + /** + * + */ + public FunctionArea getFunctionArea() { + return m_PlotArea; + } + + /** + * + */ + public void dispose() { + m_Frame.dispose(); + m_Frame = null; + } + + /** + * Add the corners of the given range as unconnected points. + * + * @param range + * @param graphLabel + */ + public void setCornerPoints(double[][] range, int graphLabel) { + setUnconnectedPoint(range[0][0], range[1][0], graphLabel); + setUnconnectedPoint(range[0][1], range[1][1], graphLabel); + } + + public void setColorByIndex(int graphLabel, int index) { + getFunctionArea().setColorByIndex(graphLabel, index); + } + + public void recolorAllGraphsByIndex() { + getFunctionArea().recolorAllGraphsByIndex(); + } + // /** + // * Just for testing the Plot class. + // */ + // public static void main( String[] args ){ + // Plot plot = new Plot("Plot-Test","x-value","y-value"); + // plot.init(); + // double x; + // for (x= 0; x <6000; x++) { + // //double y = SpecialFunction.getnormcdf(x); + // // double yy = 0.5*SpecialFunction.getnormpdf(x); + // double n = Math.sin(((double)x/1000*Math.PI)); + // //plot.setConnectedPoint(x,Math.sin(x),0); + // //plot.setConnectedPoint(x,Math.cos(x),1); + // //plot.setConnectedPoint(x,y,0); + // plot.setConnectedPoint(x,n,1); + // } + // //plot.addGraph(1,2); + // } } diff --git a/src/eva2/server/go/strategies/EsDpiNiching.java b/src/eva2/server/go/strategies/EsDpiNiching.java index a7baa4e4..127c193c 100644 --- a/src/eva2/server/go/strategies/EsDpiNiching.java +++ b/src/eva2/server/go/strategies/EsDpiNiching.java @@ -34,540 +34,617 @@ import eva2.tools.math.Mathematics; import eva2.tools.math.RNG; /** - * The ES niching with dynamic peak identification. Basically, for a set of "peaks" a set of (mu,lambda)-ESes are - * performed in parallel, with interaction based on a niche radius (fixed so far). - * The number of peaks must be predefined, and lambda new samples are drawn for every peak in every iteration. - * Thus, in relation to the standard ES, some new parameters are due. On the other hand, the selection schemes - * are predefined. This is done according to Shir&Bäck, Niching in Evolution Strategies, Tec.Report 2005. - * - * Unfortunately the algorithm was not described in every detail. It remained unclear how exactly the - * peak population where filled and esp. what happens if DPI returns less than q peaks. - * In this implementation, this is solved by setting a maximum size to each peak cluster (muPerPeak). For - * a peak population, only the best muPerPeak remain and the rest is assigned to the unclustered set. From these, - * pseudo-peaks are then formed until the expected number of peak populations is produced. - * - * Also, they gave a general rule for setting the niche radius depending on the problem domain, however in their - * experiments, they were able to identify optima which were much closer (i.e., on Ackley's), so it is unclear - * which niche radius was actually used there - * - * Due to the "non-standard" environmental selection mechanism (a fixed proportion is chosen from the children, the - * rest from the parents), a preselection mechanism was implemented here, slightly breaking the ES framework - * which is still used to optimize the single peak populations. - * - * This class should also cover "Dynamic niching in evolution strategies with covariance matrix adaptation" - * by Shir & Bäck, CEC 2005, when employing SelectBest as parent selection and muPerPeak=1. - * - * Some notes: - * - * If strictNiching is deactivated, niches are disappearing because they are sometimes - * assigned the global opt. and in that niche are very bad so they get thrown away due to the maximum niche count - * if strictNiching is activated, niches are very small - or even empty. Why is that? This can hardly be sensible - * esp. with a very small niche radius for F8. This would mean that in the beginning, nearly all offspring - * are created from very few pairs of peaks. - * - * The mu/lambda information was lost on the way to the MutateESRankMuCMA class... I added it now as additional pop.data - * which is only loaded if the mu/lambda ratio deduced from the orig/selected population sizes does not make sense. - * - * With the explorer peaks reinited every 100 generations or so, the course of the MPR for a *single* run - * will not be a clear logistic function, because "finding" additional peaks produces small steps in the MPR. - * - * The Niching ES is now using the Population to catch the generational events, not producing it itself, similar - * to Tribes, ScatterSearch or IPOP-ES. Thus it could be used with a dynamic population size without too much - * hassle. + * The ES niching with dynamic peak identification. Basically, for a set of + * "peaks" a set of (mu,lambda)-ESes are performed in parallel, with interaction + * based on a niche radius (fixed so far). The number of peaks must be + * predefined, and lambda new samples are drawn for every peak in every + * iteration. Thus, in relation to the standard ES, some new parameters are due. + * On the other hand, the selection schemes are predefined. This is done + * according to Shir&Bäck, Niching in Evolution Strategies, Tec.Report 2005. + * + * Unfortunately the algorithm was not described in every detail. It remained + * unclear how exactly the peak population where filled and esp. what happens if + * DPI returns less than q peaks. In this implementation, this is solved by + * setting a maximum size to each peak cluster (muPerPeak). For a peak + * population, only the best muPerPeak remain and the rest is assigned to the + * unclustered set. From these, pseudo-peaks are then formed until the expected + * number of peak populations is produced. + * + * Also, they gave a general rule for setting the niche radius depending on the + * problem domain, however in their experiments, they were able to identify + * optima which were much closer (i.e., on Ackley's), so it is unclear which + * niche radius was actually used there + * + * Due to the "non-standard" environmental selection mechanism (a fixed + * proportion is chosen from the children, the rest from the parents), a + * preselection mechanism was implemented here, slightly breaking the ES + * framework which is still used to optimize the single peak populations. + * + * This class should also cover "Dynamic niching in evolution strategies with + * covariance matrix adaptation" by Shir & Bäck, CEC 2005, when employing + * SelectBest as parent selection and muPerPeak=1. + * + * Some notes: + * + * If strictNiching is deactivated, niches are disappearing because they are + * sometimes assigned the global opt. and in that niche are very bad so they get + * thrown away due to the maximum niche count if strictNiching is activated, + * niches are very small - or even empty. Why is that? This can hardly be + * sensible esp. with a very small niche radius for F8. This would mean that in + * the beginning, nearly all offspring are created from very few pairs of peaks. + * + * The mu/lambda information was lost on the way to the MutateESRankMuCMA + * class... I added it now as additional pop.data which is only loaded if the + * mu/lambda ratio deduced from the orig/selected population sizes does not make + * sense. + * + * With the explorer peaks reinited every 100 generations or so, the course of + * the MPR for a *single* run will not be a clear logistic function, because + * "finding" additional peaks produces small steps in the MPR. + * + * The Niching ES is now using the Population to catch the generational events, + * not producing it itself, similar to Tribes, ScatterSearch or IPOP-ES. Thus it + * could be used with a dynamic population size without too much hassle. + * + * TODO Add adaptive niche radius. Add parameter to every indy which is adapted + * after all new peaks have been found. + * * - * TODO - * Add adaptive niche radius. Add parameter to every indy which is adapted after all new peaks have been found. - * - * * @author mkron * */ public class EsDpiNiching implements InterfaceOptimizer, Serializable, InterfaceAdditionalPopulationInformer, InterfacePopulationChangedEventListener { - private static final boolean TRACE=false, TRACE_DEMES=false; - private double nicheRadius = 0.3; - private int expectedPeaks = 5; - private int explorerPeaks = 0; - private int muPerPeak = 50; - private int lambdaPerPeak = 60; - private int eta = 30; - private boolean doEtaPreselection = true; - private int numRndImmigrants = 100; - private boolean useNicheRadiusEstimation = true; + + private static final boolean TRACE = false, TRACE_DEMES = false; + private double nicheRadius = 0.3; + private int expectedPeaks = 5; + private int explorerPeaks = 0; + private int muPerPeak = 50; + private int lambdaPerPeak = 60; + private int eta = 30; + private boolean doEtaPreselection = true; + private int numRndImmigrants = 100; + private boolean useNicheRadiusEstimation = true; private boolean reinitAlreadyFound = true; // check if current species have converged to already archived solutions - if so, deactivate them - private transient Population archive = new Population(); // collect deactivated optima - protected ParameterControlManager paramControl = new ParameterControlManager(); - - private transient EvolutionStrategies[] peakOpts = null; - - Population population = new Population(); - private InterfaceOptimizationProblem problem; - private transient InterfacePopulationChangedEventListener m_Listener; - private String identifier = "Niching-ES"; - private transient TopoPlot plot = null; - private transient Population randomNewIndies = null; - private int plotInterval = 0; - private InterfaceDistanceMetric metric = new PhenotypeMetric(); - private boolean addLonersToPeaks = false; - private InterfaceSelection parentSel = new SelectTournament(); - private boolean allowSingularPeakPops = false; - private int resetExplorerInterval = 1; // how often are the exploring peaks reset? - private int convCount = 0; - private int haltingWindowLen = 15; // the window length along which species convergence is measured - private double deactConvThresh = 1e-5; // the threshold for species convergence and deactivation (std. dev of historical fitnesses) - private int fitCriterion = 0; // fitness criterion to check for species convergence - private int collisions = 0; - private boolean doNumPeakAdaption = false; - private double collisionDetNicheRadius = 0.001; // distance below which collision between active species and archived solutios is assumed - private static final String origPeakIndyKey = "originalPeakIndividualKey"; + private transient Population archive = new Population(); // collect deactivated optima + protected ParameterControlManager paramControl = new ParameterControlManager(); + private transient EvolutionStrategies[] peakOpts = null; + Population population = new Population(); + private InterfaceOptimizationProblem problem; + private transient InterfacePopulationChangedEventListener m_Listener; + private String identifier = "Niching-ES"; + private transient TopoPlot plot = null; + private transient Population randomNewIndies = null; + private int plotInterval = 0; + private InterfaceDistanceMetric metric = new PhenotypeMetric(); + private boolean addLonersToPeaks = false; + private InterfaceSelection parentSel = new SelectTournament(); + private boolean allowSingularPeakPops = false; + private int resetExplorerInterval = 1; // how often are the exploring peaks reset? + private int convCount = 0; + private int haltingWindowLen = 15; // the window length along which species convergence is measured + private double deactConvThresh = 1e-5; // the threshold for species convergence and deactivation (std. dev of historical fitnesses) + private int fitCriterion = 0; // fitness criterion to check for species convergence + private int collisions = 0; + private boolean doNumPeakAdaption = false; + private double collisionDetNicheRadius = 0.001; // distance below which collision between active species and archived solutios is assumed + private static final String origPeakIndyKey = "originalPeakIndividualKey"; + public static final String originalPeakPop = "originalPeakPopulationID"; - public static final String originalPeakPop = "originalPeakPopulationID"; - - public EsDpiNiching() { - } - - /** - * Use the given parameters, the maximal estimation for the niche radius, no preselection and no explorers. - * - * @param muPerPeak - * @param lambdaPerPeak - * @param expectedPeaks - * @param rndImmigrants - */ - public EsDpiNiching(int muPerPeak, int lambdaPerPeak, int expectedPeaks, int rndImmigrants) { - this(-1., muPerPeak, lambdaPerPeak, expectedPeaks, rndImmigrants, 0, 0, 0); - } - - /** - * Use the given parameters, no preselection and no explorers. - * - * @param nicheRadius - * @param muPerPeak - * @param lambdaPerPeak - * @param expectedPeaks - * @param rndImmigrants - */ - public EsDpiNiching(double nicheRadius, int muPerPeak, int lambdaPerPeak, int expectedPeaks, int rndImmigrants) { - this(nicheRadius, muPerPeak, lambdaPerPeak, expectedPeaks, rndImmigrants, 0, 0, 0); - } - - /** - * If the niche radius is zero or negative, the automatic estimation is used. Otherwise the given radius is used. - * If etaPresel is positive, eta-preselection is activated, otherwise it is inactive. - * - * @param nicheRadius - * @param muPerPeak - * @param lambdaPerPeak - * @param expectedPeaks - * @param rndImmigrants - * @param explorerPeaks - * @param resetExplInterval - * @param etaPresel - */ - public EsDpiNiching(double nicheRadius, int muPerPeak, int lambdaPerPeak, int expectedPeaks, int rndImmigrants, int explorerPeaks, int resetExplInterval, int etaPresel) { - doEtaPreselection=(etaPresel > 0); - if (nicheRadius>0) { - setNicheRadius(nicheRadius); - setUseNicheRadiusEstimation(false); - } else setUseNicheRadiusEstimation(true); - this.eta=etaPresel; - this.muPerPeak = muPerPeak; - this.lambdaPerPeak = lambdaPerPeak; - this.numRndImmigrants = rndImmigrants; - this.expectedPeaks = expectedPeaks; - this.resetExplorerInterval = resetExplInterval; - } - - public EsDpiNiching(EsDpiNiching o) { - // TODO update! - this.nicheRadius = o.nicheRadius; - this.resetExplorerInterval = o.resetExplorerInterval; - this.expectedPeaks = o.expectedPeaks; - this.explorerPeaks = o.explorerPeaks; - this.muPerPeak = o.muPerPeak; - this.lambdaPerPeak = o.lambdaPerPeak; - this.eta = o.eta; - this.doEtaPreselection = o.doEtaPreselection; - this.numRndImmigrants = o.numRndImmigrants; - this.useNicheRadiusEstimation = o.useNicheRadiusEstimation; - this.setAllowSingularPeakPops(o.isAllowSingularPeakPops()); - - if (o.population!=null) this.population = (Population)o.population.clone(); - if (o.problem!=null) this.problem = (InterfaceOptimizationProblem)o.problem.clone(); - this.identifier = o.identifier; - this.plotInterval = o.plotInterval; - } - - public void hideHideable() { - setDoEtaPreselection(isDoEtaPreselection()); - setUseNicheRadiusEstimation(isUseNicheRadiusEstimation()); - GenericObjectEditor.setHideProperty(this.getClass(), "population", true); - } - - public Object clone() { - return new EsDpiNiching(this); + public EsDpiNiching() { } - - public void init() { - convCount=0; // reset number of converged species (found peaks) - collisions=0; // reset the number of collisions - population = new Population((getExpectedPeaks()+getExplorerPeaks())*lambdaPerPeak); - population.setMaxHistoryLength(haltingWindowLen); - - archive = new Population(); - peakOpts = new EvolutionStrategies[getExpectedPeaks()+getExplorerPeaks()]; - for (int i=0; i 0); + if (nicheRadius > 0) { + setNicheRadius(nicheRadius); + setUseNicheRadiusEstimation(false); + } else { + setUseNicheRadiusEstimation(true); + } + this.eta = etaPresel; + this.muPerPeak = muPerPeak; + this.lambdaPerPeak = lambdaPerPeak; + this.numRndImmigrants = rndImmigrants; + this.expectedPeaks = expectedPeaks; + this.resetExplorerInterval = resetExplInterval; + } + + public EsDpiNiching(EsDpiNiching o) { + // TODO update! + this.nicheRadius = o.nicheRadius; + this.resetExplorerInterval = o.resetExplorerInterval; + this.expectedPeaks = o.expectedPeaks; + this.explorerPeaks = o.explorerPeaks; + this.muPerPeak = o.muPerPeak; + this.lambdaPerPeak = o.lambdaPerPeak; + this.eta = o.eta; + this.doEtaPreselection = o.doEtaPreselection; + this.numRndImmigrants = o.numRndImmigrants; + this.useNicheRadiusEstimation = o.useNicheRadiusEstimation; + this.setAllowSingularPeakPops(o.isAllowSingularPeakPops()); + + if (o.population != null) { + this.population = (Population) o.population.clone(); + } + if (o.problem != null) { + this.problem = (InterfaceOptimizationProblem) o.problem.clone(); + } + this.identifier = o.identifier; + this.plotInterval = o.plotInterval; + } + + public void hideHideable() { + setDoEtaPreselection(isDoEtaPreselection()); + setUseNicheRadiusEstimation(isUseNicheRadiusEstimation()); + GenericObjectEditor.setHideProperty(this.getClass(), "population", true); + } + + public Object clone() { + return new EsDpiNiching(this); + } + + public void init() { + convCount = 0; // reset number of converged species (found peaks) + collisions = 0; // reset the number of collisions + population = new Population((getExpectedPeaks() + getExplorerPeaks()) * lambdaPerPeak); + population.setMaxHistoryLength(haltingWindowLen); + + archive = new Population(); + peakOpts = new EvolutionStrategies[getExpectedPeaks() + getExplorerPeaks()]; + for (int i = 0; i < peakOpts.length; i++) { + if (doEtaPreselection) { + // When preselection is employed in this.optimize, the ESes only "get to see" muPerPeak individuals, + // but they should generate lambdaPerPeak individuals, this lambda is set only after initialization. + peakOpts[i] = new EvolutionStrategies(muPerPeak, muPerPeak, false); + } else { + peakOpts[i] = new EvolutionStrategies(muPerPeak, lambdaPerPeak, false); + } + // Trying to come close to the selection scheme of Shir&Bäck'05: + peakOpts[i].setParentSelection(parentSel); + peakOpts[i].setPartnerSelection(new SelectBestSingle(true)); + peakOpts[i].SetProblem(problem); + peakOpts[i].init(); + peakOpts[i].setLambda(lambdaPerPeak); // set lambda after initialization + peakOpts[i].setForceOrigPopSize(false); + peakOpts[i].checkPopulationConstraints(); + peakOpts[i].getPopulation().setMaxHistoryLength(haltingWindowLen); + population.incrFunctionCallsBy(peakOpts[i].getPopulation().getFunctionCalls()); + } + // possibly reduce immigrants to produce a conforming number of initial evaluations (same number as in later iterations: numPeaks*muLambda+immigrants) // int initialImmigrants = (fullNumPeaks()*lambdaPerPeak+getNumRndImmigrants())-(fullNumPeaks()*muPerPeak+getNumRndImmigrants()); - if (getNumRndImmigrants()>0) { - generateEvalImmigrants(getNumRndImmigrants()); - } - if (isDoEtaPreselection() && (getEta()>getMuPerPeak())) { - System.err.println("Warning, eta should be less-equal mu... setting eta="+getMuPerPeak()); - setEta(getMuPerPeak()); - } - collectPopulationIncGen(population, peakOpts, randomNewIndies); - population.addPopulationChangedEventListener(this); - population.setNotifyEvalInterval(50); + if (getNumRndImmigrants() > 0) { + generateEvalImmigrants(getNumRndImmigrants()); + } + if (isDoEtaPreselection() && (getEta() > getMuPerPeak())) { + System.err.println("Warning, eta should be less-equal mu... setting eta=" + getMuPerPeak()); + setEta(getMuPerPeak()); + } + collectPopulationIncGen(population, peakOpts, randomNewIndies); + population.addPopulationChangedEventListener(this); + population.setNotifyEvalInterval(50); - if (isUseNicheRadiusEstimation()) updateNicheRadius(); - } + if (isUseNicheRadiusEstimation()) { + updateNicheRadius(); + } + } - private void updateNicheRadius() { - AbstractEAIndividual indy=population.getEAIndividual(0); - if (indy instanceof InterfaceDataTypeDouble) { - setEstimatedNicheRadius(((InterfaceDataTypeDouble)indy).getDoubleRange()); - } else System.err.println("Error, default niche radius can only be estimated for individuals of type InterfaceDataTypeDouble!"); - } + private void updateNicheRadius() { + AbstractEAIndividual indy = population.getEAIndividual(0); + if (indy instanceof InterfaceDataTypeDouble) { + setEstimatedNicheRadius(((InterfaceDataTypeDouble) indy).getDoubleRange()); + } else { + System.err.println("Error, default niche radius can only be estimated for individuals of type InterfaceDataTypeDouble!"); + } + } - /** - * Use the deactivation of converged species, storing them to an archive, - * with the given parameters. If windowLen <= 0, the deactivation - * mechanism is disabled. - * This provides for semi-sequential niching with DPI-ES - * - * @param threshold - * @param windowLen - */ - public void setSpeciesDeactivation(double threshold, int windowLen) { - setHaltingWindow(windowLen); - setEpsilonBound(threshold); - } - - private void setEstimatedNicheRadius(double[][] range) { - double estRad = EsDpiNiching.calcEstimatedNicheRadius(range, expectedPeaks, metric); - setNicheRadius(estRad); - } - - /** - * Calculate the estimated maximal niche radius for a given problem range. This - * is an estimate on the q-th part of the volume transfered to the radius of a hypersphere, - * where q is the number of expected peaks. - * - * @param range - * @param numExpectedOptima - * @param metric - * @return - */ - public static double calcEstimatedNicheRadius(double[][] range, int numExpectedOptima, InterfaceDistanceMetric metric) { - int dim = range.length; - double r; - if (metric instanceof EuclideanMetric) { - r = Mathematics.getAvgRangeL2(range); - } else { //if (metric instanceof PhenotypeMetric) { // r can be assumed to be 0.5*sqrt(dim) - if (!(metric instanceof PhenotypeMetric)) { - if ((metric instanceof IndividualDataMetric) && (((IndividualDataMetric)metric).getBaseMetric() instanceof EuclideanMetric)) {} // this is ok as well - else System.err.println("Warning, unexpected metric in EsDpiNiching! Estimated niche radius may fail..."); - } - r = 0.5*Math.sqrt(dim); - } + /** + * Use the deactivation of converged species, storing them to an archive, + * with the given parameters. If windowLen <= 0, the deactivation mechanism + * is disabled. This provides for semi-sequential niching with DPI-ES + * + + * + * @param threshold + * @param windowLen + */ + public void setSpeciesDeactivation(double threshold, int windowLen) { + setHaltingWindow(windowLen); + setEpsilonBound(threshold); + } + + private void setEstimatedNicheRadius(double[][] range) { + double estRad = EsDpiNiching.calcEstimatedNicheRadius(range, expectedPeaks, metric); + setNicheRadius(estRad); + } + + /** + * Calculate the estimated maximal niche radius for a given problem range. + * This is an estimate on the q-th part of the volume transfered to the + * radius of a hypersphere, where q is the number of expected peaks. + * + * @param range + * @param numExpectedOptima + * @param metric + * @return + */ + public static double calcEstimatedNicheRadius(double[][] range, int numExpectedOptima, InterfaceDistanceMetric metric) { + int dim = range.length; + double r; + if (metric instanceof EuclideanMetric) { + r = Mathematics.getAvgRangeL2(range); + } else { //if (metric instanceof PhenotypeMetric) { // r can be assumed to be 0.5*sqrt(dim) + if (!(metric instanceof PhenotypeMetric)) { + if ((metric instanceof IndividualDataMetric) && (((IndividualDataMetric) metric).getBaseMetric() instanceof EuclideanMetric)) { + } // this is ok as well + else { + System.err.println("Warning, unexpected metric in EsDpiNiching! Estimated niche radius may fail..."); + } + } + r = 0.5 * Math.sqrt(dim); + } // setNicheRadius(r*Math.pow(numExpectedPeaks, -1./(double)dim)); - return r*Math.pow(numExpectedOptima, -1./(double)dim); - } - - public void addExpectedPeaks(int k) { - // TODO what to do if new peaks should be introduced? - // inc. expected peaks, allocate new optimizers, possibly adapt clustering distance - - // this must happen to a specific time, namely before or after one iteration. - if (k<=0) System.err.println("Invalid k in addExpectedPeaks (" + k + ")."); - setExpectedPeaks(getExpectedPeaks()+k); - EvolutionStrategies[] newPeakOpts = new EvolutionStrategies[getExpectedPeaks()+getExplorerPeaks()]; - for (int i=0; i=getExpectedPeaks())) { - return (int)Math.max(((double)getExpectedPeaks())*1.2, 2.); - } else return 0; - } - - public boolean isDoNumPeakAdaption() { - return doNumPeakAdaption ; - } - public void setDoNumPeakAdaption(boolean doApt) { - doNumPeakAdaption = doApt; - } - public String doNumPeakAdaptionTipText() { - return "Activate online adaption of the number of expected peaks"; - } + if (isDoNumPeakAdaption() && (archive.size() >= getExpectedPeaks())) { + return (int) Math.max(((double) getExpectedPeaks()) * 1.2, 2.); + } else { + return 0; + } + } - public void optimize() { - Population peakPopSet[]; - if (increaseExpectedPeaksCriterion()>0) { - addExpectedPeaks(increaseExpectedPeaksCriterion()); - } - if (TRACE) System.out.println("--- FULL POP SIZE: " + population.size() + " , funcalls: " + population.getFunctionCalls() + ", gen " + population.getGeneration()); - ClusteringDynPeakIdent dpiClustering = new ClusteringDynPeakIdent(getExpectedPeaks(), getLambdaPerPeak(), nicheRadius, true, metric ); - // perform dynamic peak identification resulting in the dynamic peak set dps - dpiClustering.initClustering(population); - peakPopSet = dpiClustering.cluster(population, population); - // remove this instance as listener because we only want to "hear" events of the main population - for (int i=0; i 0) { + addExpectedPeaks(increaseExpectedPeaksCriterion()); + } + if (TRACE) { + System.out.println("--- FULL POP SIZE: " + population.size() + " , funcalls: " + population.getFunctionCalls() + ", gen " + population.getGeneration()); + } + ClusteringDynPeakIdent dpiClustering = new ClusteringDynPeakIdent(getExpectedPeaks(), getLambdaPerPeak(), nicheRadius, true, metric); + // perform dynamic peak identification resulting in the dynamic peak set dps + dpiClustering.initClustering(population); + peakPopSet = dpiClustering.cluster(population, population); + // remove this instance as listener because we only want to "hear" events of the main population + for (int i = 0; i < peakPopSet.length; i++) { + peakPopSet[i].removePopulationChangedEventListener(this); + } + setGeneration(population.getGeneration(), peakPopSet); + if (TRACE_DEMES) { + printDemes("After clustering: ", peakPopSet); + } + + int curNumPeaks = peakPopSet.length - 1; // boolean copyHashFromParents=true; - // transfer population hash data along the peaks -> for each peak chose the original last population - // and transfer the data to the new cluster + // transfer population hash data along the peaks -> for each peak chose the original last population + // and transfer the data to the new cluster // if (copyHashFromParents) { - copyDataFromParents(peakPopSet); + copyDataFromParents(peakPopSet); // } else { // copyDataFromClosest(clusteredPeakPops); // } - - int reqNewPeaks = 0; - if (curNumPeaks0) { - if ((getPopulation().getGeneration() % resetExplorerInterval == 0)) { - // reset the explorers - reqNewPeaks += getExplorerPeaks(); - } else { - // take over the last explorers - // TODO only if they have not made it to the desired peak populations? - Population[] clustersWithExplorers = new Population[peakPopSet.length + getExplorerPeaks()]; - for (int i=0; i 0) { + if ((getPopulation().getGeneration() % resetExplorerInterval == 0)) { + // reset the explorers + reqNewPeaks += getExplorerPeaks(); + } else { + // take over the last explorers + // TODO only if they have not made it to the desired peak populations? + Population[] clustersWithExplorers = new Population[peakPopSet.length + getExplorerPeaks()]; + for (int i = 0; i < clustersWithExplorers.length; i++) { + if (i < peakPopSet.length) { + clustersWithExplorers[i] = peakPopSet[i]; + } // index i-1 because unclustered indies do not have an optimizer + else { + clustersWithExplorers[i] = peakOpts[i - 1].getPopulation(); + } + } + peakPopSet = clustersWithExplorers; + } } // add missing and explorer peaks as new random individuals (or old unclustered ones) - peakPopSet = generateMissingSpecies(peakPopSet, getMuPerPeak(), reqNewPeaks, false); - - if (TRACE_DEMES) printDemes("After expansion: ", peakPopSet); - - if (archive!=null && (archive.size()>0) && isReinitOnCollision()) { - double origNicheRad=dpiClustering.getNicheRadius(); - dpiClustering.setNicheRadius(collisionDetNicheRadius); - int[] assoc = dpiClustering.associateLoners(archive, peakPopSet, population); - for (int i=0; i=0) { - collisions++; - // if an association was found, there is a peak close to an archived solution, so reset it. - if (!archive.getEAIndividual(i).isDominating(peakPopSet[assoc[i]].getBestEAIndividual())) { - // the new found species is actually better than the archived solution - archive.set(i, peakPopSet[assoc[i]].getBestEAIndividual().clone()); // replace archived indy - } - if (TRACE) System.out.println(" Converged on archived solution.. resetting peak pop " + assoc[i]); - peakPopSet[assoc[i]] = initRandomPeakPop(getMuPerPeak()); - } - } - dpiClustering.setNicheRadius(origNicheRad); - if (TRACE_DEMES) printDemes("After archivie-merge: ", peakPopSet); + peakPopSet = generateMissingSpecies(peakPopSet, getMuPerPeak(), reqNewPeaks, false); + + if (TRACE_DEMES) { + printDemes("After expansion: ", peakPopSet); } - - if (TRACE) for (int k=0; k0) { - System.err.println("duplicate inherited in EsDpiNiching! OK if explorer peaks exist that are not always reinited and " + j + ">"+getExpectedPeaks() + " and " + k + "==0."); - } - } - } - plot=null; + + if (archive != null && (archive.size() > 0) && isReinitOnCollision()) { + double origNicheRad = dpiClustering.getNicheRadius(); + dpiClustering.setNicheRadius(collisionDetNicheRadius); + int[] assoc = dpiClustering.associateLoners(archive, peakPopSet, population); + for (int i = 0; i < assoc.length; i++) { + if (assoc[i] >= 0) { + collisions++; + // if an association was found, there is a peak close to an archived solution, so reset it. + if (!archive.getEAIndividual(i).isDominating(peakPopSet[assoc[i]].getBestEAIndividual())) { + // the new found species is actually better than the archived solution + archive.set(i, peakPopSet[assoc[i]].getBestEAIndividual().clone()); // replace archived indy + } + if (TRACE) { + System.out.println(" Converged on archived solution.. resetting peak pop " + assoc[i]); + } + peakPopSet[assoc[i]] = initRandomPeakPop(getMuPerPeak()); + } + } + dpiClustering.setNicheRadius(origNicheRad); + if (TRACE_DEMES) { + printDemes("After archivie-merge: ", peakPopSet); + } + } + + if (TRACE) { + for (int k = 0; k < peakPopSet.length - 1; k++) { + for (int j = k + 1; j < peakPopSet.length; j++) { + Population cut = peakPopSet[k].setCut(peakPopSet[j]); + if (cut.size() > 0) { + System.err.println("duplicate inherited in EsDpiNiching! OK if explorer peaks exist that are not always reinited and " + j + ">" + getExpectedPeaks() + " and " + k + "==0."); + } + } + } + } + plot = null; // now generate the lambda offsprings // nextGeneration = this.generateEvalChildren(dps); // create lambda new ones from mu parents - for (int clustIndex=1; clustIndex0) { - // possibly deactivate a converged species and add its representative to the archive - HistoryConvergenceTerminator hConv = new HistoryConvergenceTerminator(haltingWindowLen, deactConvThresh , fitCriterion , true); - if (hConv.isTerminated(curSpecies)) { // species is terminated - peakPopSet[clustIndex]=deactivateSpecies(clustIndex, true); // store best, reinitialize randomly - } + for (int clustIndex = 1; clustIndex < peakPopSet.length; clustIndex++) { + AbstractEAIndividual curPeak = (AbstractEAIndividual) peakPopSet[clustIndex].getBestEAIndividual().clone(); + // set the population + Population curSpecies = peakPopSet[clustIndex]; + if (curSpecies.size() == 1 && (!isAllowSingularPeakPops())) { + // Quoting SB05: "In case that the niche only contains one individual, the second parent will be the best indidivual of another niche." + AbstractEAIndividual bestOther = (AbstractEAIndividual) selectBestFromOtherSpecies(clustIndex, peakPopSet).clone(); + if (TRACE) { + System.out.println("Adding best from other species: " + bestOther); + } + curSpecies.add(bestOther); + } else if (curSpecies.size() == 0) { + System.err.println("Warning, empty niche population in EsDpiNiching!"); } - - Population optimizedSpecies = peakOpts[clustIndex-1].getPopulation(); - if (doDraw(population.getGeneration())) drawPeakPop(""+clustIndex, curSpecies); - if (TRACE) System.out.println("Optimizing cluster index " + (clustIndex) + ", size " + curSpecies.size()); - peakOpts[clustIndex-1].optimize(); // !!!!!!!! Actual optimization step - optimizedSpecies = peakOpts[clustIndex-1].getPopulation(); - optimizedSpecies.putData(origPeakIndyKey , curPeak); - population.incrFunctionCallsBy(optimizedSpecies.size()); + peakOpts[clustIndex - 1].setPop((Population) curSpecies); // -1 because clustering delivers first cluster at index 1 + + // check for deactivation of that niche + if (getHaltingWindow() > 0) { + // possibly deactivate a converged species and add its representative to the archive + HistoryConvergenceTerminator hConv = new HistoryConvergenceTerminator(haltingWindowLen, deactConvThresh, fitCriterion, true); + if (hConv.isTerminated(curSpecies)) { // species is terminated + peakPopSet[clustIndex] = deactivateSpecies(clustIndex, true); // store best, reinitialize randomly + } + } + + Population optimizedSpecies = peakOpts[clustIndex - 1].getPopulation(); + if (doDraw(population.getGeneration())) { + drawPeakPop("" + clustIndex, curSpecies); + } + if (TRACE) { + System.out.println("Optimizing cluster index " + (clustIndex) + ", size " + curSpecies.size()); + } + peakOpts[clustIndex - 1].optimize(); // !!!!!!!! Actual optimization step + optimizedSpecies = peakOpts[clustIndex - 1].getPopulation(); + optimizedSpecies.putData(origPeakIndyKey, curPeak); + population.incrFunctionCallsBy(optimizedSpecies.size()); // optimizedSpecies.incrGeneration(); // is already done in the .optimize() call above // optimizedSpecies.incrFunctionCallsBy(optimizedSpecies.size()); - if (TRACE) System.out.println(" ..." + optimizedSpecies.size() + " more funcalls... "); + if (TRACE) { + System.out.println(" ..." + optimizedSpecies.size() + " more funcalls... "); + } } - + // we may have a problem if, by chance, all species have been deactivated simultaneously AND there are no unclustered ! - if (dynamicPopSize()==0) { + if (dynamicPopSize() == 0) { // if this is the case, we just reinit a single in analogy to a missing peak - peakOpts[0].getPopulation().addPopulation(initRandomPeakPop(getMuPerPeak())); + peakOpts[0].getPopulation().addPopulation(initRandomPeakPop(getMuPerPeak())); + } + + if (TRACE) { + for (int k = 0; k < peakPopSet.length - 1; k++) { + for (int j = k + 1; j < peakPopSet.length; j++) { + Population cut = peakPopSet[k].setCut(peakPopSet[j]); + if (cut.size() > 1) { + // one may happen after a cluster had a size of one, since then another leader is added + if (cut.size() == 2 && (peakPopSet[k].size() == 2) && (peakPopSet[j].size() == 2)) { + // two may happen since they can be added reciprocally to each other + } else { + System.err.println("duplicate indy in EsDpiNiching. OK if explorer peaks exist that are not always reinited and " + j + ">" + getExpectedPeaks() + " and " + k + "==0."); + } + } + } + } } - - if (TRACE) for (int k=0; k1) { - // one may happen after a cluster had a size of one, since then another leader is added - if (cut.size()==2 && (peakPopSet[k].size()==2) && (peakPopSet[j].size()==2)) { - // two may happen since they can be added reciprocally to each other - } else { - System.err.println("duplicate indy in EsDpiNiching. OK if explorer peaks exist that are not always reinited and " + j + ">"+getExpectedPeaks() + " and " + k + "==0."); - } - } - } - } if (doEtaPreselection) { // this basically replaces ES-environment selection - // select the eta best from the offspring per peak population - // fill up to muPerPeak by adding from the old peak population - SelectBestIndividuals selBest = new SelectBestIndividuals(); - Population loners = peakPopSet[0]; - plot=null; - for (int i=0; i=peakPopSet.length) { - System.err.println("Warning: fewer clusters than expected peaks in EsDpiNiching!"); - offspring.clear(); // empty set to avoid duplicates! - } else { - if (TRACE) System.out.println("EtaPresel: from " + offspring.size() + " offspring selecting "+ eta); - Population selected = selBest.selectFrom(offspring, eta ); - if (!selected.isSubSet(offspring)) { - System.err.println("fatal problem in EsDpiNiching!!!"); - } - if (offspring.setCut(peakPopSet[i+1]).size()>0) { - System.err.println("problem in EsDpiNiching!!!"); - } - int delta = muPerPeak - eta; - if (delta>0) { - Population filterPeakPop = peakPopSet[i+1].filter(selected); - if (TRACE) System.out.println("Adding " + Math.min(delta, filterPeakPop.size()) + " from peak population."); - // (few) duplicates may happen because parents are copied to another peak population - // if a cluster had a size of 1 AND parents may survive due to elitism. - selected.addPopulation(selBest.selectFrom(filterPeakPop, Math.min(delta, filterPeakPop.size())), false); - if (selected.size()2) { //one may happen after a cluster had size one (see above) - System.err.println("Warning, nonempty set cut between " + k + " and " + i + " !"); - } - peakOpts[i].m_Population.clear(); - peakOpts[i].m_Population.addAll(selected); - if (doDraw(population.getGeneration())) drawPeakPop(""+i, selected); - } - } + // select the eta best from the offspring per peak population + // fill up to muPerPeak by adding from the old peak population + SelectBestIndividuals selBest = new SelectBestIndividuals(); + Population loners = peakPopSet[0]; + plot = null; + for (int i = 0; i < peakOpts.length; i++) { + Population offspring = peakOpts[i].getPopulation(); + if (i + 1 >= peakPopSet.length) { + System.err.println("Warning: fewer clusters than expected peaks in EsDpiNiching!"); + offspring.clear(); // empty set to avoid duplicates! + } else { + if (TRACE) { + System.out.println("EtaPresel: from " + offspring.size() + " offspring selecting " + eta); + } + Population selected = selBest.selectFrom(offspring, eta); + if (!selected.isSubSet(offspring)) { + System.err.println("fatal problem in EsDpiNiching!!!"); + } + if (offspring.setCut(peakPopSet[i + 1]).size() > 0) { + System.err.println("problem in EsDpiNiching!!!"); + } + int delta = muPerPeak - eta; + if (delta > 0) { + Population filterPeakPop = peakPopSet[i + 1].filter(selected); + if (TRACE) { + System.out.println("Adding " + Math.min(delta, filterPeakPop.size()) + " from peak population."); + } + // (few) duplicates may happen because parents are copied to another peak population + // if a cluster had a size of 1 AND parents may survive due to elitism. + selected.addPopulation(selBest.selectFrom(filterPeakPop, Math.min(delta, filterPeakPop.size())), false); + if (selected.size() < muPerPeak && (addLonersToPeaks)) { + delta = Math.min(muPerPeak - selected.size(), loners.size()); + if (TRACE) { + System.out.println("filling up with lucky loners: " + delta); + } + // fill up with loner indies + SelectRandom selRnd = new SelectRandom(false); // no duplicates wanted! + Population luckyLosers = selRnd.selectFrom(loners, delta); + selected.addPopulation(luckyLosers, true); + loners.removeMembers(luckyLosers, true); + // fill up with random indies + // Population randomNewIndies = new Population(lambdaPerPeak - selected.size()); + // problem.initPopulation(randomNewIndies); // function calls?? + // selected.addAll(randomNewIndies); + } + } + if (TRACE) { + for (int k = 0; k < i; k++) { + if (selected.setCut(peakOpts[k].getPopulation()).size() > 2) { //one may happen after a cluster had size one (see above) + System.err.println("Warning, nonempty set cut between " + k + " and " + i + " !"); + } + } + } + peakOpts[i].population.clear(); + peakOpts[i].population.addAll(selected); + if (doDraw(population.getGeneration())) { + drawPeakPop("" + i, selected); + } + } + } } // System.out.println("Best of second peak: " + clusteredPeakPops[2].getBestEAIndividual()); - if (doDraw(population.getGeneration()) && archive!=null) { - for (int i = 0; i < this.archive.size(); i++) { - ClusterBasedNichingEA.plotIndy(plot, 'x',(InterfaceDataTypeDouble)archive.get(i)); - } + if (doDraw(population.getGeneration()) && archive != null) { + for (int i = 0; i < this.archive.size(); i++) { + ClusterBasedNichingEA.plotIndy(plot, 'x', (InterfaceDataTypeDouble) archive.get(i)); + } + } + if (getNumRndImmigrants() > 0) { + generateEvalImmigrants(getNumRndImmigrants()); } - if (getNumRndImmigrants()>0) generateEvalImmigrants(getNumRndImmigrants()); collectPopulationIncGen(population, peakOpts, randomNewIndies); //this.firePropertyChangedEvent(Population.nextGenerationPerformed); // moved this to registerPopulationStateChanged which is called from the population - } + } - private Population deactivateSpecies(int clustIndex, boolean resetRandomly) { - Population optimizedSpecies = peakOpts[clustIndex-1].getPopulation(); - if (TRACE) System.out.println("Terminated species: " + clustIndex + ", optimizer " + (clustIndex-1)); - if (TRACE) System.out.println(optimizedSpecies.getHistory()); - convCount++; - // get best indy, add it to archive, clear population of the optimizer for a reset - archive.add(optimizedSpecies.getBestIndividual()); - if (resetRandomly) { - optimizedSpecies.clear(); - optimizedSpecies.clearHistory(); - optimizedSpecies = initRandomPeakPop(getMuPerPeak()); - peakOpts[clustIndex-1].setPop(optimizedSpecies); - } - return optimizedSpecies; - } + private Population deactivateSpecies(int clustIndex, boolean resetRandomly) { + Population optimizedSpecies = peakOpts[clustIndex - 1].getPopulation(); + convCount++; + // get best indy, add it to archive, clear population of the optimizer for a reset + archive.add(optimizedSpecies.getBestIndividual()); + if (resetRandomly) { + optimizedSpecies.clear(); + optimizedSpecies.clearHistory(); + optimizedSpecies = initRandomPeakPop(getMuPerPeak()); + peakOpts[clustIndex - 1].setPop(optimizedSpecies); + } + return optimizedSpecies; + } - /** - * Copy the additional data from the parent populations to the new clusters. - * - * @param clusteredPeakPops - */ - private void copyDataFromParents(Population[] clusteredPeakPops) { - for (int i=1; i=0)) { - Population origPop = peakOpts[origEsPop].getPopulation(); - clusteredPeakPops[i].copyHashData(origPop); - clusteredPeakPops[i].SetHistory(origPop.getHistory()); // copy the history for deactivation! + /** + * Copy the additional data from the parent populations to the new clusters. + * + * @param clusteredPeakPops + */ + private void copyDataFromParents(Population[] clusteredPeakPops) { + for (int i = 1; i < clusteredPeakPops.length; i++) { + Integer origEsPop = (Integer) clusteredPeakPops[i].getBestEAIndividual().getData(originalPeakPop); + if (origEsPop != null && (origEsPop >= 0)) { + Population origPop = peakOpts[origEsPop].getPopulation(); + clusteredPeakPops[i].copyHashData(origPop); + clusteredPeakPops[i].SetHistory(origPop.getHistory()); // copy the history for deactivation! // System.out.println("Copied hash for peak " + clusteredPeakPops[i].getBestEAIndividual() + ", cluster " + i + " from " + origEsPop); - } else { // ok in the first iteration of if the indy was a random immigrant - if (population.getGeneration()>1 && (getNumRndImmigrants()==0)) System.err.println("Error, empty original es pop ID!"); - } - } - } + } else { // ok in the first iteration of if the indy was a random immigrant + if (population.getGeneration() > 1 && (getNumRndImmigrants() == 0)) { + System.err.println("Error, empty original es pop ID!"); + } + } + } + } // /** // * For each new cluster copy the additional data from the closest parent population. @@ -593,545 +670,634 @@ public class EsDpiNiching implements InterfaceOptimizer, Serializable, Interface // clusteredPeakPops[i].copyHashData(closestPop); // } // } - - private void printDemes(String prefix, Population[] peakPops) { - System.out.print(prefix + " demes: "); - for (int i=0; i0) System.out.print(format(peakPops[i].getBestEAIndividual().getFitness(0), 3, 3)); - } catch(Exception e) { - System.err.println("NARG!"); - } - - } - System.out.println(); - } - - public static String format(double d, int len, int prec) { - StringBuffer sb = new StringBuffer(); - Formatter fm = new Formatter(sb); - if (Math.abs(d)>1e6) fm.format("%"+prec+"."+len+"e ", d); - else fm.format("%"+prec+"."+len+"f ", d); - return sb.toString(); - } - - private void setGeneration(int gen, Population[] pops) { - for (int i=0; i 0) { + System.out.print(format(peakPops[i].getBestEAIndividual().getFitness(0), 3, 3)); + } + } catch (Exception e) { + System.err.println("NARG!"); + } - /** - * Generate additional pseudo peak populations (species) by either moving unclustered ones - * or by creating new ones randomly. If unclustered indies are to be used, there must - * be enough of them available. - * The new peaks are appended to the given cluster list and returned (as a new array instance). - * - * @param origClusters the original clusters, where index 0 is the unclustered rest - * @param cntPerNewSpecies the number of indies to use per new peak population - * @param fromUnclusteredOrRandomly if true, use unclustered indies as new pops, otherwise create them randomly - * @return - */ - private Population[] generateMissingSpecies(Population[] origClusters, int cntPerNewSpecies, int newPops, boolean fromUnclusteredOrRandomly) { - if (newPops==0) return origClusters; - else { - Population[] newClusters = new Population[origClusters.length + newPops]; - if (fromUnclusteredOrRandomly) { - // int missingPeaks = newClusters.length-origClusters.length; - for (int i=origClusters.length; i 1e6) { + fm.format("%" + prec + "." + len + "e ", d); + } else { + fm.format("%" + prec + "." + len + "f ", d); + } + return sb.toString(); + } + + private void setGeneration(int gen, Population[] pops) { + for (int i = 0; i < pops.length; i++) { + pops[i].setGenerationTo(gen); + } + } /** - * Initialize a new peak population with the given number of indies, - * which are initialized randomly (using the problem instance) and assigned - * a maximally bad fitness. - * + * Generate additional pseudo peak populations (species) by either moving + * unclustered ones or by creating new ones randomly. If unclustered indies + * are to be used, there must be enough of them available. The new peaks are + * appended to the given cluster list and returned (as a new array + * instance). + * + * @param origClusters the original clusters, where index 0 is the + * unclustered rest + * @param cntPerNewSpecies the number of indies to use per new peak + * population + * @param fromUnclusteredOrRandomly if true, use unclustered indies as new + * pops, otherwise create them randomly + * @return + */ + private Population[] generateMissingSpecies(Population[] origClusters, int cntPerNewSpecies, int newPops, boolean fromUnclusteredOrRandomly) { + if (newPops == 0) { + return origClusters; + } else { + Population[] newClusters = new Population[origClusters.length + newPops]; + if (fromUnclusteredOrRandomly) { + // int missingPeaks = newClusters.length-origClusters.length; + for (int i = origClusters.length; i < newClusters.length; i++) { // for each new species to be formed: + newClusters[i] = origClusters[0].moveRandNIndividuals(cntPerNewSpecies); + } + } else { // create random indies with really bad fitness + for (int i = origClusters.length; i < newClusters.length; i++) { // for each new species to be formed: + newClusters[i] = initRandomPeakPop(cntPerNewSpecies); + } + } + for (int i = 0; i < origClusters.length; i++) { + newClusters[i] = origClusters[i]; + } + if (TRACE) { + System.out.println("Generated missing peak species..."); + } + return newClusters; + } + } + + /** + * Initialize a new peak population with the given number of indies, which + * are initialized randomly (using the problem instance) and assigned a + * maximally bad fitness. + * * @param cntPerNewSpecies * @return */ - private Population initRandomPeakPop(int cntPerNewSpecies) { - Population newPop = new Population(cntPerNewSpecies); - problem.initPopulation(newPop); - newPop.putData(EvolutionStrategies.esLambdaParam, getLambdaPerPeak()); - newPop.putData(EvolutionStrategies.esMuParam, getMuPerPeak()); - newPop.setMaxHistoryLength(haltingWindowLen); - double[] badFit = population.getEAIndividual(0).getFitness().clone(); - Arrays.fill(badFit, Double.MAX_VALUE); - newPop.setAllFitnessValues(badFit); - return newPop; - } + private Population initRandomPeakPop(int cntPerNewSpecies) { + Population newPop = new Population(cntPerNewSpecies); + problem.initPopulation(newPop); + newPop.putData(EvolutionStrategies.esLambdaParam, getLambdaPerPeak()); + newPop.putData(EvolutionStrategies.esMuParam, getMuPerPeak()); + newPop.setMaxHistoryLength(haltingWindowLen); + double[] badFit = population.getEAIndividual(0).getFitness().clone(); + Arrays.fill(badFit, Double.MAX_VALUE); + newPop.setAllFitnessValues(badFit); + return newPop; + } - private void generateEvalImmigrants(int cnt) { + private void generateEvalImmigrants(int cnt) { if (cnt > 0) { - randomNewIndies = new Population(cnt); - problem.initPopulation(randomNewIndies); - problem.evaluate(randomNewIndies); - population.incrFunctionCallsBy(cnt); - if (TRACE) System.out.println("evaluated immigrants: " + randomNewIndies.size()); - } else randomNewIndies = null; - } + randomNewIndies = new Population(cnt); + problem.initPopulation(randomNewIndies); + problem.evaluate(randomNewIndies); + population.incrFunctionCallsBy(cnt); + if (TRACE) { + System.out.println("evaluated immigrants: " + randomNewIndies.size()); + } + } else { + randomNewIndies = null; + } + } - /** Something has changed + /** + * Something has changed */ protected void firePropertyChangedEvent(String name) { - if (this.m_Listener != null) this.m_Listener.registerPopulationStateChanged(this, name); + if (this.m_Listener != null) { + this.m_Listener.registerPopulationStateChanged(this, name); + } } - - private AbstractEAIndividual selectBestFromOtherSpecies(int i, Population[] clusteredSpecies) { - // the index must be >0 and != i: - int rndIndex = RNG.randomInt(clusteredSpecies.length-2); - if (rndIndex==0) rndIndex++; - if (rndIndex==i) rndIndex++; - if (TRACE) System.out.println("selected spec index " + rndIndex); - return clusteredSpecies[rndIndex].getBestEAIndividual(); - } - private Population[] getOptPops() { - Population pops[] = new Population[peakOpts.length]; - for (int i=0; i0 and != i: + int rndIndex = RNG.randomInt(clusteredSpecies.length - 2); + if (rndIndex == 0) { + rndIndex++; + } + if (rndIndex == i) { + rndIndex++; + } + if (TRACE) { + System.out.println("selected spec index " + rndIndex); + } + return clusteredSpecies[rndIndex].getBestEAIndividual(); + } - private void drawPeakPop(String prefix, Population npop) { - if (npop!=null && (npop.size()>0)) try { - if (plot == null) { - plot = new TopoPlot("Niching-ES " + npop.getGeneration(), "x", "y"); - plot.setParams(50, 50); - if (problem instanceof Interface2DBorderProblem) plot.setTopology((Interface2DBorderProblem)problem); - } - ClusterBasedNichingEA.plotPopConnected(plot, npop); - plot.drawIndividual(1, 0, "", npop.getBestEAIndividual()); + private Population[] getOptPops() { + Population pops[] = new Population[peakOpts.length]; + for (int i = 0; i < peakOpts.length; i++) { + pops[i] = peakOpts[i].getPopulation(); + } + return pops; + } + + private void drawPeakPop(String prefix, Population npop) { + if (npop != null && (npop.size() > 0)) { + try { + if (plot == null) { + plot = new TopoPlot("Niching-ES " + npop.getGeneration(), "x", "y"); + plot.setParams(50, 50); + if (problem instanceof Interface2DBorderProblem) { + plot.setTopology((Interface2DBorderProblem) problem); + } + } + ClusterBasedNichingEA.plotPopConnected(plot, npop); + plot.drawIndividual(1, 0, "", npop.getBestEAIndividual()); // plot.drawPopulation(prefix, npop); - } catch(Exception e) { - plot=null; - } - } + } catch (Exception e) { + plot = null; + } + } + } - private boolean doDraw(int gen) { - return (plotInterval>0) && ((gen%plotInterval)==0) ; - } + private boolean doDraw(int gen) { + return (plotInterval > 0) && ((gen % plotInterval) == 0); + } - /** - * Within pop, replace all individuals which are better than indy by indy. - * This makes sure that SelectBest will select indy on the population. - * - * @param pop - * @param indy - */ - private static void replaceWorstAndAllBetterIndiesBy(Population pop, - AbstractEAIndividual indy) { - int lastIndex = -1; - if (!pop.contains(indy)) { // replace best - int bestIndex = pop.getIndexOfBestIndividualPrefFeasible(); - pop.set(bestIndex, indy); - lastIndex=bestIndex; - } - int bestIndex = pop.getIndexOfBestIndividualPrefFeasible(); - while ((lastIndex!=bestIndex) && (pop.getEAIndividual(bestIndex).isDominatingDebConstraints(indy))) {// remove best, add indy - pop.set(bestIndex, indy); - lastIndex = bestIndex; - bestIndex = pop.getIndexOfBestIndividualPrefFeasible(); - } - } + /** + * Within pop, replace all individuals which are better than indy by indy. + * This makes sure that SelectBest will select indy on the population. + * + * @param pop + * @param indy + */ + private static void replaceWorstAndAllBetterIndiesBy(Population pop, + AbstractEAIndividual indy) { + int lastIndex = -1; + if (!pop.contains(indy)) { // replace best + int bestIndex = pop.getIndexOfBestIndividualPrefFeasible(); + pop.set(bestIndex, indy); + lastIndex = bestIndex; + } + int bestIndex = pop.getIndexOfBestIndividualPrefFeasible(); + while ((lastIndex != bestIndex) && (pop.getEAIndividual(bestIndex).isDominatingDebConstraints(indy))) {// remove best, add indy + pop.set(bestIndex, indy); + lastIndex = bestIndex; + bestIndex = pop.getIndexOfBestIndividualPrefFeasible(); + } + } - /** - * Perform mutation adaption for instances of InterfaceMutationGenerational. - * Specifically, the original population of each dps-member is cloned and the method - * adaptAfterSelection is called which may modify the population. The vector of these - * new populations is returned. - * - * @param collectedPop - * @param dps - * @param opts - * @return the vector of Population instances - */ - private static Population[] performDPSGenerationalAdaption(Population collectedPop, - Population dps, EvolutionStrategies[] opts) { - // loop over all dps individuals and - // clone the new mutator instance from the original population - // call the generational adaption for the new instance - Population[] resPops = new Population[dps.size()]; - for (int i=0; i0) expectedPeaks = ep; - else System.err.println("Error, expecting positive number of peaks!"); - } - public String expectedPeaksTipText() { - return "The number of expected peaks on the problem."; - } - - public int getExplorerPeaks() { - return explorerPeaks; - } - public void setExplorerPeaks(int ep) { - if (ep>=0) explorerPeaks = ep; - else System.err.println("Error, expecting nonzero number of explorer peaks!"); - } - public String explorerPeaksTipText() { - return "The number of additional explorer peaks."; - } - - public String getName() { - return identifier + "_" + getExpectedPeaks() + "_" + getNicheRadius(); - } - - public static String globalInfo() { - return "A niching ES with dynamic peak identification, after Shir and Bäck: Niching in Evolution Strategies, " + - "GECCO 2005. Basically, there are several variants of a (mu,lambda)-ES performed " + - "in parallel, which are reclustered in each iteration based on the dynamic peak set."; - } - - public void addPopulationChangedEventListener( - InterfacePopulationChangedEventListener ea) { - m_Listener = ea; - } - public boolean removePopulationChangedEventListener( - InterfacePopulationChangedEventListener ea) { - if (ea.equals(m_Listener)) { - m_Listener=null; - return true; - } else return false; - } - - public void freeWilly() {} - - public InterfaceSolutionSet getAllSolutions() { - Population peaks = new Population(peakOpts.length); - for (int i=0; i 0) { + expectedPeaks = ep; + } else { + System.err.println("Error, expecting positive number of peaks!"); + } + } + + public String expectedPeaksTipText() { + return "The number of expected peaks on the problem."; + } + + public int getExplorerPeaks() { + return explorerPeaks; + } + + public void setExplorerPeaks(int ep) { + if (ep >= 0) { + explorerPeaks = ep; + } else { + System.err.println("Error, expecting nonzero number of explorer peaks!"); + } + } + + public String explorerPeaksTipText() { + return "The number of additional explorer peaks."; + } + + public String getName() { + return identifier + "_" + getExpectedPeaks() + "_" + getNicheRadius(); + } + + public static String globalInfo() { + return "A niching ES with dynamic peak identification, after Shir and Bäck: Niching in Evolution Strategies, " + + "GECCO 2005. Basically, there are several variants of a (mu,lambda)-ES performed " + + "in parallel, which are reclustered in each iteration based on the dynamic peak set."; + } + + public void addPopulationChangedEventListener( + InterfacePopulationChangedEventListener ea) { + m_Listener = ea; + } + + public boolean removePopulationChangedEventListener( + InterfacePopulationChangedEventListener ea) { + if (ea.equals(m_Listener)) { + m_Listener = null; + return true; + } else { + return false; + } + } + + public void freeWilly() { + } + + public InterfaceSolutionSet getAllSolutions() { + Population peaks = new Population(peakOpts.length); + for (int i = 0; i < peakOpts.length; i++) { + peaks.add(peakOpts[i].getPopulation().getBestEAIndividual()); + } + if (archive != null) { + peaks.addPopulation(archive); // add stored indies + } + peaks.synchSize(); + return new SolutionSet(getPopulation(), peaks); + } + + public String getIdentifier() { + return identifier; + } + + public void SetIdentifier(String name) { + identifier = name; + } + + public void setPopulation(Population pop) { + // this might cause problems if the pop.size() does not fit the EsDpiNiching parameters mu/lamba per peak + this.population = pop; + } + + public Population getPopulation() { + return population; + } + + public InterfaceOptimizationProblem getProblem() { + return problem; + } + + public void SetProblem(InterfaceOptimizationProblem prob) { + this.problem = prob; + } + + public String getStringRepresentation() { StringBuffer sb = new StringBuffer("EsDpiNiching:\n"); sb.append("Optimization Problem: "); sb.append(this.problem.getStringRepresentationForProblem(this)); sb.append("\n"); sb.append(this.population.getStringRepresentation()); return sb.toString(); - } + } - public void initByPopulation(Population pop, boolean reset) { + public void initByPopulation(Population pop, boolean reset) { // int pSize = pop.size(); - this.population = (Population)pop.clone(); + this.population = (Population) pop.clone(); if (reset) { - this.population.init(); + this.population.init(); this.problem.evaluate(population); population.incrGeneration(); } - } + } - public int getPlotInterval() { - return plotInterval; - } - public void setPlotInterval(int plotInterval) { - this.plotInterval = plotInterval; - } - public String plotIntervalTipText() { - return "If > 0, show debug visualization at indicated iterations."; - } - - public int getEta() { - return eta; - } - public void setEta(int eta) { - this.eta = eta; - } - public String etaTipText() { - return "The number of offspring individuals per peak which will be preselected."; - } - - public boolean isDoEtaPreselection() { - return doEtaPreselection; - } - public void setDoEtaPreselection(boolean doEtaPreselection) { - this.doEtaPreselection = doEtaPreselection; - GenericObjectEditor.setShowProperty(this.getClass(), "eta", doEtaPreselection); - } - public String doEtaPreselectionTipText() { - return "Replace ES environmental selection by choosing some individuals from the offspring within a niche and some from the former niche population."; - } + public int getPlotInterval() { + return plotInterval; + } - public void setNumRndImmigrants(int numRndImmigrants) { - this.numRndImmigrants = numRndImmigrants; - } - public int getNumRndImmigrants() { - return numRndImmigrants; - } - public String numRndImmigrantsTipText() { - return "A number of individuals will be randomly created in every iteration."; - } + public void setPlotInterval(int plotInterval) { + this.plotInterval = plotInterval; + } - public int getMuPerPeak() { - return muPerPeak; - } - public void setMuPerPeak(int muPerPeak) { - this.muPerPeak = muPerPeak; - } - public String muPerPeakTipText() { - return "Number of parent individuals per niche."; - } + public String plotIntervalTipText() { + return "If > 0, show debug visualization at indicated iterations."; + } - public void setUseNicheRadiusEstimation(boolean useNicheRadiusEstimation) { - this.useNicheRadiusEstimation = useNicheRadiusEstimation; - GenericObjectEditor.setHideProperty(this.getClass(), "nicheRadius", useNicheRadiusEstimation); - } - public boolean isUseNicheRadiusEstimation() { - return useNicheRadiusEstimation; - } - public String useNicheRadiusEstimationTipText() { - return "Activate to use a niche radius corresponding to the q-th part of the search space (q number of peaks expected) - often niche radii should be smaller since this is close to the upper bound."; - } + public int getEta() { + return eta; + } - public InterfaceSelection getParentSelection() { - return parentSel; - } - public void setParentSelection(InterfaceSelection parentSel) { - this.parentSel = parentSel; - } - public String parentSelectionTipText() { - return "Set the parent selection method for the underlying ES."; - } + public void setEta(int eta) { + this.eta = eta; + } - public void setAllowSingularPeakPops(boolean allowSingularPeakPops) { - this.allowSingularPeakPops = allowSingularPeakPops; - } - public boolean isAllowSingularPeakPops() { - return allowSingularPeakPops; - } - public String allowSingularPeakPopsTipText() { - return "Allow peak populations of size 1 or force a randomly selected other peak as second indy."; - } + public String etaTipText() { + return "The number of offspring individuals per peak which will be preselected."; + } - public int getResetExplorerInterval() { - return resetExplorerInterval; - } - public void setResetExplorerInterval(int resInt) { - if (resInt>0) this.resetExplorerInterval = resInt; - else System.err.println("The explorer reset interval should be positive!"); - } - public String resetExplorerIntervalTipText() { - return "The explorer peaks are reset in intervals of iterations (generations)."; - } + public boolean isDoEtaPreselection() { + return doEtaPreselection; + } - public int getHaltingWindow() { - return haltingWindowLen; - } - public void setHaltingWindow(int hw) { - haltingWindowLen = hw; - } - public String haltingWindowTipText() { - return "Number of generations after which a species without improvement is seen as converged and deactivated; set to zero to disable."; - } - - public double getEpsilonBound() { - return deactConvThresh; - } - public void setEpsilonBound(double epsilonBound) { - this.deactConvThresh = epsilonBound; - } - public String epsilonBoundTipText() { - return "If fitness std. dev. changes less than this value within the halting window, convergence is assumed."; - } + public void setDoEtaPreselection(boolean doEtaPreselection) { + this.doEtaPreselection = doEtaPreselection; + GenericObjectEditor.setShowProperty(this.getClass(), "eta", doEtaPreselection); + } - public String[] getAdditionalDataHeader() { - return new String[]{"nicheRadius", "numExpectedPeaks", "numArchived", "archivedMeanDist", "numCollisions"}; - } - - public String[] getAdditionalDataInfo() { - return new String[]{"The niche radius employed for Dynamic Peak Identificatio", "The number of expected peaks", - "The number of stored potential local optima", "Mean distance of archived solutions", - "The number of collisions detected so far"}; - } + public String doEtaPreselectionTipText() { + return "Replace ES environmental selection by choosing some individuals from the offspring within a niche and some from the former niche population."; + } - public Object[] getAdditionalDataValue(PopulationInterface pop) { - return new Object[]{getNicheRadius(), getExpectedPeaks(), archive.size(), archive.getPopulationMeasures()[0], collisions}; - } + public void setNumRndImmigrants(int numRndImmigrants) { + this.numRndImmigrants = numRndImmigrants; + } - /** - * This method is necessary to allow access from the Processor. - * @return - */ - public ParameterControlManager getParamControl() { - return paramControl; - } - - public ParamAdaption[] getParameterControl() { - return paramControl.getSingleAdapters(); - } - public void setParameterControl(ParamAdaption[] paramControl) { - this.paramControl.setSingleAdapters(paramControl); - } - public String parameterControlTipText() { - return "You may define dynamic paramter control strategies using the parameter name."; - } + public int getNumRndImmigrants() { + return numRndImmigrants; + } - public void setReinitOnCollision(boolean reinitAlreadyFound) { - this.reinitAlreadyFound = reinitAlreadyFound; - } - public boolean isReinitOnCollision() { - return reinitAlreadyFound; - } - public String reinitOnCollisionTipText() { - return "Indicate whether already known (archived) peaks should trigger a reset of close-by species (corresp. to niche radius)."; - } + public String numRndImmigrantsTipText() { + return "A number of individuals will be randomly created in every iteration."; + } - public void registerPopulationStateChanged(Object source, String name) { - if (getPopulation() != source) { - System.err.println("Warning, mismatching population in " + this.getClass().getName()); - } - if (name.equals(Population.funCallIntervalReached)) { + public int getMuPerPeak() { + return muPerPeak; + } + + public void setMuPerPeak(int muPerPeak) { + this.muPerPeak = muPerPeak; + } + + public String muPerPeakTipText() { + return "Number of parent individuals per niche."; + } + + public void setUseNicheRadiusEstimation(boolean useNicheRadiusEstimation) { + this.useNicheRadiusEstimation = useNicheRadiusEstimation; + GenericObjectEditor.setHideProperty(this.getClass(), "nicheRadius", useNicheRadiusEstimation); + } + + public boolean isUseNicheRadiusEstimation() { + return useNicheRadiusEstimation; + } + + public String useNicheRadiusEstimationTipText() { + return "Activate to use a niche radius corresponding to the q-th part of the search space (q number of peaks expected) - often niche radii should be smaller since this is close to the upper bound."; + } + + public InterfaceSelection getParentSelection() { + return parentSel; + } + + public void setParentSelection(InterfaceSelection parentSel) { + this.parentSel = parentSel; + } + + public String parentSelectionTipText() { + return "Set the parent selection method for the underlying ES."; + } + + public void setAllowSingularPeakPops(boolean allowSingularPeakPops) { + this.allowSingularPeakPops = allowSingularPeakPops; + } + + public boolean isAllowSingularPeakPops() { + return allowSingularPeakPops; + } + + public String allowSingularPeakPopsTipText() { + return "Allow peak populations of size 1 or force a randomly selected other peak as second indy."; + } + + public int getResetExplorerInterval() { + return resetExplorerInterval; + } + + public void setResetExplorerInterval(int resInt) { + if (resInt > 0) { + this.resetExplorerInterval = resInt; + } else { + System.err.println("The explorer reset interval should be positive!"); + } + } + + public String resetExplorerIntervalTipText() { + return "The explorer peaks are reset in intervals of iterations (generations)."; + } + + public int getHaltingWindow() { + return haltingWindowLen; + } + + public void setHaltingWindow(int hw) { + haltingWindowLen = hw; + } + + public String haltingWindowTipText() { + return "Number of generations after which a species without improvement is seen as converged and deactivated; set to zero to disable."; + } + + public double getEpsilonBound() { + return deactConvThresh; + } + + public void setEpsilonBound(double epsilonBound) { + this.deactConvThresh = epsilonBound; + } + + public String epsilonBoundTipText() { + return "If fitness std. dev. changes less than this value within the halting window, convergence is assumed."; + } + + public String[] getAdditionalDataHeader() { + return new String[]{"nicheRadius", "numExpectedPeaks", "numArchived", "archivedMeanDist", "numCollisions"}; + } + + public String[] getAdditionalDataInfo() { + return new String[]{"The niche radius employed for Dynamic Peak Identificatio", "The number of expected peaks", + "The number of stored potential local optima", "Mean distance of archived solutions", + "The number of collisions detected so far"}; + } + + public Object[] getAdditionalDataValue(PopulationInterface pop) { + return new Object[]{getNicheRadius(), getExpectedPeaks(), archive.size(), archive.getPopulationMeasures()[0], collisions}; + } + + /** + * This method is necessary to allow access from the Processor. + * + * @return + */ + public ParameterControlManager getParamControl() { + return paramControl; + } + + public ParamAdaption[] getParameterControl() { + return paramControl.getSingleAdapters(); + } + + public void setParameterControl(ParamAdaption[] paramControl) { + this.paramControl.setSingleAdapters(paramControl); + } + + public String parameterControlTipText() { + return "You may define dynamic paramter control strategies using the parameter name."; + } + + public void setReinitOnCollision(boolean reinitAlreadyFound) { + this.reinitAlreadyFound = reinitAlreadyFound; + } + + public boolean isReinitOnCollision() { + return reinitAlreadyFound; + } + + public String reinitOnCollisionTipText() { + return "Indicate whether already known (archived) peaks should trigger a reset of close-by species (corresp. to niche radius)."; + } + + public void registerPopulationStateChanged(Object source, String name) { + if (getPopulation() != source) { + System.err.println("Warning, mismatching population in " + this.getClass().getName()); + } + if (name.equals(Population.funCallIntervalReached)) { // getPopulation().SetFunctionCalls(((Population)source).getFunctionCalls()); // this is ugly and I dont know what its for.. possibly if the population instance changes along the GUi? - this.firePropertyChangedEvent(Population.nextGenerationPerformed); - } else { - // this may come from cloned instances with the same listener - should not happen since they are removed. - // it may still come from "incGeneration" calls - we can ignore those + this.firePropertyChangedEvent(Population.nextGenerationPerformed); + } else { + // this may come from cloned instances with the same listener - should not happen since they are removed. + // it may still come from "incGeneration" calls - we can ignore those // System.err.println("Not forwarding event " + name); - } - } + } + } } diff --git a/src/eva2/server/go/strategies/EvolutionStrategies.java b/src/eva2/server/go/strategies/EvolutionStrategies.java index a8b7603f..63056a0c 100644 --- a/src/eva2/server/go/strategies/EvolutionStrategies.java +++ b/src/eva2/server/go/strategies/EvolutionStrategies.java @@ -27,63 +27,60 @@ import eva2.server.go.problems.InterfaceOptimizationProblem; * $Date: 2007-12-04 14:31:47 +0100 (Tue, 04 Dec 2007) $ * $Author: mkron $ */ - public class EvolutionStrategies implements InterfaceOptimizer, java.io.Serializable { - //private double m_MyuRatio = 6; - protected int m_Mu = 5; - protected int m_Lambda = 20; - protected boolean m_UsePlusStrategy = false; - protected Population m_Population = new Population(); - protected InterfaceOptimizationProblem m_Problem = new B1Problem(); - private InterfaceSelection m_ParentSelection = new SelectRandom(); - private InterfaceSelection m_PartnerSelection = new SelectRandom(); - private InterfaceSelection m_EnvironmentSelection = new SelectBestIndividuals(); - private int m_NumberOfPartners = 1; - protected int origPopSize = -1; // especially for CBN -// private double[] m_FitnessOfParents = null; - private boolean forceOrigPopSize = true;// especially for CBN - - transient private String m_Identifier = ""; - transient private InterfacePopulationChangedEventListener m_Listener; - private static final boolean TRACE = false; + protected int mu = 5; + protected int lambda = 20; + protected boolean usePlusStrategy = false; + protected Population population = new Population(); + protected InterfaceOptimizationProblem optimizationProblem = new B1Problem(); + private InterfaceSelection parentSelection = new SelectRandom(); + private InterfaceSelection partnerSelection = new SelectRandom(); + private InterfaceSelection environmentSelection = new SelectBestIndividuals(); + private int numberOfPartners = 1; + protected int origPopSize = -1; // especially for CBN + private boolean forceOrigPopSize = true;// especially for CBN + transient private String identifier = ""; + transient private InterfacePopulationChangedEventListener changeListener; public static final String esMuParam = "EvolutionStrategyMuParameter"; public static final String esLambdaParam = "EvolutionStrategyLambdaParameter"; public EvolutionStrategies() { - this.m_Population.setTargetSize(this.m_Lambda); + this.population.setTargetSize(this.lambda); } - + public EvolutionStrategies(int mu, int lambda, boolean usePlus) { - setMu(mu); - setLambda(lambda); - setPlusStrategy(usePlus); - this.checkPopulationConstraints(); + setMu(mu); + setLambda(lambda); + setPlusStrategy(usePlus); + this.checkPopulationConstraints(); } - - public EvolutionStrategies(EvolutionStrategies a) { - this.m_Mu = a.m_Mu; - this.m_Lambda = a.m_Lambda; - this.m_UsePlusStrategy = a.m_UsePlusStrategy; - this.m_Population = (Population)a.m_Population.clone(); - this.m_Problem = (InterfaceOptimizationProblem)a.m_Problem.clone(); - this.m_NumberOfPartners = a.m_NumberOfPartners; - this.m_ParentSelection = (InterfaceSelection)a.m_ParentSelection.clone(); - this.m_PartnerSelection = (InterfaceSelection)a.m_PartnerSelection.clone(); - this.m_EnvironmentSelection = (InterfaceSelection)a.m_EnvironmentSelection.clone(); - this.m_NumberOfPartners = a.m_NumberOfPartners; - this.origPopSize = a.origPopSize; - this.forceOrigPopSize = a.forceOrigPopSize; + + public EvolutionStrategies(EvolutionStrategies evStrategies) { + this.mu = evStrategies.mu; + this.lambda = evStrategies.lambda; + this.usePlusStrategy = evStrategies.usePlusStrategy; + this.population = (Population) evStrategies.population.clone(); + this.optimizationProblem = (InterfaceOptimizationProblem) evStrategies.optimizationProblem.clone(); + this.numberOfPartners = evStrategies.numberOfPartners; + this.parentSelection = (InterfaceSelection) evStrategies.parentSelection.clone(); + this.partnerSelection = (InterfaceSelection) evStrategies.partnerSelection.clone(); + this.environmentSelection = (InterfaceSelection) evStrategies.environmentSelection.clone(); + this.numberOfPartners = evStrategies.numberOfPartners; + this.origPopSize = evStrategies.origPopSize; + this.forceOrigPopSize = evStrategies.forceOrigPopSize; } /** - * Set to true in CBN, false for any extension which changes the population size during optimization. + * Set to true in CBN, false for any extension which changes the population + * size during optimization. + * * @param force */ public void setForceOrigPopSize(boolean force) { - forceOrigPopSize = force; + forceOrigPopSize = force; } - + public void hideHideable() { // GenericObjectEditor.setHideProperty(this.getClass(), "population", true); } @@ -93,496 +90,430 @@ public class EvolutionStrategies implements InterfaceOptimizer, java.io.Serializ } public void init() { - // @todo In case of CBN-ES i need to read the population size!? -// int orgPopSize = this.m_Population.getPopulationSize(); -// if (this.m_InitialPopulationSize > orgPopSize) { -// this.m_Population.setPopulationSize(this.m_InitialPopulationSize); -// } - //System.out.println("init"); - - checkPopulationConstraints(); - m_Population.putData(esMuParam, getMu()); - m_Population.putData(esLambdaParam, getLambda()); - this.m_Problem.initPopulation(this.m_Population); - this.evaluatePopulation(this.m_Population); -// this.m_Population.setPopulationSize(orgPopSize); -// this.firePropertyChangedEvent(Population.nextGenerationPerformed);// not necessary if incrGeneration is called + checkPopulationConstraints(); + population.putData(esMuParam, getMu()); + population.putData(esLambdaParam, getLambda()); + this.optimizationProblem.initPopulation(this.population); + this.evaluatePopulation(this.population); } - - /** This method will init the optimizer with a given population - * @param pop The initial population - * @param reset If true the population is reset. + /** + * This method will init the optimizer with a given population + * + * @param pop The initial population + * @param reset If true the population is reset. */ public void initByPopulation(Population pop, boolean reset) { - origPopSize = pop.getTargetSize(); -// System.out.println("ES: orig popsize is " + origPopSize); - this.m_Population = (Population)pop.clone(); + origPopSize = pop.getTargetSize(); + this.population = (Population) pop.clone(); if (reset) { - this.m_Population.init(); - this.evaluatePopulation(this.m_Population); -// this.firePropertyChangedEvent(Population.nextGenerationPerformed); // not necessary if incrGeneration is called + this.population.init(); + this.evaluatePopulation(this.population); } } - /** This method will evaluate the current population using the - * given problem. + /** + * This method will evaluate the current population using the given problem. + * * @param population The population that is to be evaluated */ protected void evaluatePopulation(Population population) { - this.m_Problem.evaluate(population); + this.optimizationProblem.evaluate(population); population.incrGeneration(); - if (TRACE) System.out.println("ES Evaluated " + population.size()); } -// /** This method allows you to set myu and lambda -// * @param myu The size of the temporary population -// * @param lambda The size of the offsprings created -// * @param plus The general population strategy. -// */ -// public void setGenerationStrategy(int myu, int lambda, boolean plus) { -// this.m_UsePlusStrategy = plus; -// this.m_Myu = myu; -// this.m_Lambda = lambda; -// this.m_MyuRatio = this.m_Lambda/(double)this.m_Myu; -// if (this.m_UsePlusStrategy) this.m_Population.setPopulationSize(myu+lambda); -// else this.m_Population.setPopulationSize(lambda); -// } - /** - * This method will generate the offspring population from the - * given population of evaluated individuals. + * This method will generate the offspring population from the given + * population of evaluated individuals. */ protected Population generateEvalChildren(Population fromPopulation) { - Population result = m_Population.cloneWithoutInds(), parents; + Population result = population.cloneWithoutInds(), parents; result.clear(); - parents = generateChildren(fromPopulation, result, this.m_Lambda); - + parents = generateChildren(fromPopulation, result, this.lambda); + this.evaluatePopulation(result); - + if (result.getEAIndividual(0).getMutationOperator() instanceof InterfaceAdaptOperatorGenerational) { - // this seems to be the right moment for the 1/5-success rule - // parents and result have the same size and correspond per individual - ((InterfaceAdaptOperatorGenerational)parents.getEAIndividual(0).getMutationOperator()).adaptGenerational(fromPopulation, parents, result, m_UsePlusStrategy); + // this seems to be the right moment for the 1/5-success rule + // parents and result have the same size and correspond per individual + ((InterfaceAdaptOperatorGenerational) parents.getEAIndividual(0).getMutationOperator()).adaptGenerational(fromPopulation, parents, result, usePlusStrategy); } if (parents.getEAIndividual(0).getCrossoverOperator() instanceof InterfaceAdaptOperatorGenerational) { - ((InterfaceAdaptOperatorGenerational)parents.getEAIndividual(0).getCrossoverOperator()).adaptGenerational(fromPopulation, parents, result, m_UsePlusStrategy); + ((InterfaceAdaptOperatorGenerational) parents.getEAIndividual(0).getCrossoverOperator()).adaptGenerational(fromPopulation, parents, result, usePlusStrategy); } return result; } - + /** - * Create a new population by parent selection, partner selection, recombination and crossover. - * The new population is added to the result population, while the selected parent population (after - * selection but before recombination/crossover) is returned. - * Returned parents and result population are to have the same size and correspond per individual. - * + * Create a new population by parent selection, partner selection, + * recombination and crossover. The new population is added to the result + * population, while the selected parent population (after selection but + * before recombination/crossover) is returned. Returned parents and result + * population are to have the same size and correspond per individual. + * * @param fromPopulation * @param result * @param lambda * @return */ protected Population generateChildren(Population fromPopulation, Population result, int lambda) { - AbstractEAIndividual tmpIndy; - AbstractEAIndividual[] offSprings; + AbstractEAIndividual tmpIndy; + AbstractEAIndividual[] offSprings; Population parents; - if (TRACE ) System.out.println("ES From pop size " + fromPopulation.size() + " selecting parents/creating children: " + lambda); - this.m_ParentSelection.prepareSelection(fromPopulation); - this.m_PartnerSelection.prepareSelection(fromPopulation); - parents = this.m_ParentSelection.selectFrom(fromPopulation, lambda); + this.parentSelection.prepareSelection(fromPopulation); + this.partnerSelection.prepareSelection(fromPopulation); + parents = this.parentSelection.selectFrom(fromPopulation, lambda); for (int i = 0; i < parents.size(); i++) { - tmpIndy = (AbstractEAIndividual)parents.get(i); - offSprings = tmpIndy.mateWith(this.m_PartnerSelection.findPartnerFor(tmpIndy, fromPopulation, this.m_NumberOfPartners)); + tmpIndy = (AbstractEAIndividual) parents.get(i); + offSprings = tmpIndy.mateWith(this.partnerSelection.findPartnerFor(tmpIndy, fromPopulation, this.numberOfPartners)); offSprings[0].mutate(); result.add(i, offSprings[0]); } return parents; } - + protected Population selectParents(Population fromPop, int mu) { - if (TRACE) System.out.println("ES env selecting parents: " + mu + " of " + fromPop.size()); - this.m_EnvironmentSelection.prepareSelection(fromPop); - return this.m_EnvironmentSelection.selectFrom(fromPop, mu); + this.environmentSelection.prepareSelection(fromPop); + return this.environmentSelection.selectFrom(fromPop, mu); } - - /** + + /** * The optimize method will compute an improved and evaluated population. */ + @Override public void optimize() { - Population nextGeneration, parents; + Population nextGeneration, parents; - //System.out.println("optimize"); - // first perform the environment selection to select myu parents - parents = selectParents(m_Population, this.m_Mu); - -// System.out.println("-- selected avg fit " + BeanInspector.toString(parents.getMeanFitness()) + " from last gen " + BeanInspector.toString(m_Population.getMeanFitness())); - - // m_Population / parents are of sizes lambda / mu + parents = selectParents(population, this.mu); + + // population / parents are of sizes lambda / mu if (parents.getEAIndividual(0).getMutationOperator() instanceof InterfaceAdaptOperatorGenerational) { - ((InterfaceAdaptOperatorGenerational)parents.getEAIndividual(0).getMutationOperator()).adaptAfterSelection(getPopulation(), parents); + ((InterfaceAdaptOperatorGenerational) parents.getEAIndividual(0).getMutationOperator()).adaptAfterSelection(getPopulation(), parents); } if (parents.getEAIndividual(0).getCrossoverOperator() instanceof InterfaceAdaptOperatorGenerational) { - ((InterfaceAdaptOperatorGenerational)parents.getEAIndividual(0).getCrossoverOperator()).adaptAfterSelection(getPopulation(), parents); + ((InterfaceAdaptOperatorGenerational) parents.getEAIndividual(0).getCrossoverOperator()).adaptAfterSelection(getPopulation(), parents); } - + // now generate the lambda offsprings - nextGeneration = this.generateEvalChildren(parents); // create lambda new ones from mu parents - - if (this.isPlusStrategy()) nextGeneration.addPopulation(parents); - + // create lambda new ones from mu parents + nextGeneration = this.generateEvalChildren(parents); + + if (this.isPlusStrategy()) { + nextGeneration.addPopulation(parents); + } + setPop(getReplacePop(nextGeneration)); -// System.out.println("Population size: " + this.m_Population.size()); -// System.out.println("-- Best Fitness " + this.m_Population.getBestFitness()[0]); - this.firePropertyChangedEvent(Population.nextGenerationPerformed); // necessary here because evalPop was not called on m_Population - } - + // necessary here because evalPop was not called on population + this.firePropertyChangedEvent(Population.nextGenerationPerformed); + } + /** - * Usually, this just returns the given population. - * However, in case of CBN this method prepares the next generation according to the species size. - * + * Usually, this just returns the given population. However, in case of CBN + * this method prepares the next generation according to the species size. + * * @param nextGeneration * @return */ protected Population getReplacePop(Population nextGeneration) { - if (forceOrigPopSize && (origPopSize > 0) && (origPopSize < nextGeneration.size())) { - // this is especially for CBN: earlier selection to immediately reduce the size of mu+lambda to lambda - this.m_EnvironmentSelection.prepareSelection(nextGeneration); - Population tmpPop = (Population)nextGeneration.clone(); - nextGeneration.clear(); - nextGeneration.addPopulation(this.m_EnvironmentSelection.selectFrom(tmpPop, origPopSize)); -// System.out.println("ES post selection! " + origPopSize + " from " + tmpPop.size()); - } else { - if ((origPopSize > 0) && (origPopSize != nextGeneration.size())) { - System.err.println("Warning in ES! orig: " + origPopSize + " / " + nextGeneration.size()); - } - } - return nextGeneration; + if (forceOrigPopSize && (origPopSize > 0) && (origPopSize < nextGeneration.size())) { + // this is especially for CBN: earlier selection to immediately reduce the size of mu+lambda to lambda + this.environmentSelection.prepareSelection(nextGeneration); + Population tmpPop = (Population) nextGeneration.clone(); + nextGeneration.clear(); + nextGeneration.addPopulation(this.environmentSelection.selectFrom(tmpPop, origPopSize)); + } else { + if ((origPopSize > 0) && (origPopSize != nextGeneration.size())) { + System.err.println("Warning in ES! orig: " + origPopSize + " / " + nextGeneration.size()); + } + } + return nextGeneration; } - /** This method is just a shortcut to set the mutation step size for - * all individuals of these two populations for the 1/5 Success rule. - * This is only necessary because i decided to make the variable - * non static - * @param successRate The success rate - * @param oldPop The old population - * @param newPop The new population - */ -// private void applySuccessRule(double successRate, Population oldPop, Population newPop) { -// MutateESSuccessRule mutator = (MutateESSuccessRule)((AbstractEAIndividual)oldPop.get(0)).getMutationOperator(); -// boolean success = (successRate < mutator.getSuccessRate()); -// // this was the old solution when the mutation step size was still static -//// if (successRate < mutator.getSuccessRate()) { -//// mutator.decreaseMutationStepSize(); -//// } else { -//// mutator.increaseMutationStepSize(); -//// } -// if (isPlusStrategy()) for (int i = 0; i < oldPop.size(); i++) { // applied to the old population as well for plus strategy -// if (((AbstractEAIndividual)oldPop.get(i)).getMutationOperator() instanceof MutateESSuccessRule) { -// mutator = (MutateESSuccessRule)((AbstractEAIndividual)oldPop.get(i)).getMutationOperator(); -// if (success) mutator.decreaseMutationStepSize(); -// else mutator.increaseMutationStepSize(); -// System.out.println("old pop step size " + mutator.getSigma()+ " (" + mutator+ ")"); -// } -// } -// for (int i = 0; i < newPop.size(); i++) { -// if (((AbstractEAIndividual)newPop.get(i)).getMutationOperator() instanceof MutateESSuccessRule) { -// mutator = (MutateESSuccessRule)((AbstractEAIndividual)newPop.get(i)).getMutationOperator(); -// if (success) mutator.decreaseMutationStepSize(); -// else mutator.increaseMutationStepSize(); -// System.out.println("new pop step size " + mutator.getSigma() + " (" + mutator+ ")"); -// } -// } -//// this.m_FitnessOfParents = null; -// } - -// /** This is for debugging only -// */ -// private String showFitness(Population pop) { -// String result = ""; -// AbstractEAIndividual indy; -// double[] fitness; -// for (int i = 0; i < pop.size(); i++) { -// indy = (AbstractEAIndividual)pop.get(i); -// fitness = indy.getFitness(); -// for (int j = 0; j < fitness.length; j++) result += fitness[j] +"; "; -// result += "\n"; -// } -// return result; -// } - - /** This method allows you to add the LectureGUI as listener to the Optimizer + /** + * This method allows you to add the LectureGUI as listener to the Optimizer + * * @param ea */ + @Override public void addPopulationChangedEventListener(InterfacePopulationChangedEventListener ea) { - this.m_Listener = ea; + this.changeListener = ea; } - public boolean removePopulationChangedEventListener( - InterfacePopulationChangedEventListener ea) { - if (m_Listener==ea) { - m_Listener=null; - return true; - } else return false; - } - /** Something has changed + + @Override + public boolean removePopulationChangedEventListener(InterfacePopulationChangedEventListener ea) { + if (changeListener == ea) { + changeListener = null; + return true; + } else { + return false; + } + } + + /** + * Something has changed */ protected void firePropertyChangedEvent(String name) { - if (this.m_Listener != null) this.m_Listener.registerPopulationStateChanged(this, name); + if (this.changeListener != null) { + this.changeListener.registerPopulationStateChanged(this, name); + } } - /** This method will set the problem that is to be optimized + /** + * This method will set the problem that is to be optimized + * * @param problem */ - public void SetProblem (InterfaceOptimizationProblem problem) { - this.m_Problem = problem; - } - public InterfaceOptimizationProblem getProblem () { - return this.m_Problem; + public void SetProblem(InterfaceOptimizationProblem problem) { + this.optimizationProblem = problem; } - /** This method will return a string describing all properties of the optimizer - * and the applied methods. + public InterfaceOptimizationProblem getProblem() { + return this.optimizationProblem; + } + + /** + * This method will return a string describing all properties of the + * optimizer and the applied methods. + * * @return A descriptive string */ public String getStringRepresentation() { String result = ""; result += "Evolution Strategies:\n"; result += "Optimization Problem: "; - result += this.m_Problem.getStringRepresentationForProblem(this) +"\n"; - result += this.m_Population.getStringRepresentation(); + result += this.optimizationProblem.getStringRepresentationForProblem(this) + "\n"; + result += this.population.getStringRepresentation(); return result; } - /** This method allows you to set myu and lambda in one step + /** + * This method allows you to set myu and lambda in one step + * * @param myu * @param lambda - * @param plus True if plus, false if comma strategy + * @param plus True if plus, false if comma strategy */ public void setGenerationStrategy(int myu, int lambda, boolean plus) { - this.m_Mu = myu; - this.m_Lambda = lambda; - this.m_UsePlusStrategy = plus; + this.mu = myu; + this.lambda = lambda; + this.usePlusStrategy = plus; this.checkPopulationConstraints(); } - /** - * This method will check the population constraints - * myu <= lambda and will calculate the population size - * accordingly. + /** + * This method will check the population constraints myu <= lambda and will + * calculate the population size accordingly. */ protected void checkPopulationConstraints() { - if (this.m_Lambda < this.m_Mu) { - System.err.println("Invalid mu/lambda ratio! Setting mu=lambda="+m_Mu); - this.m_Lambda = this.m_Mu; + if (this.lambda < this.mu) { + System.err.println("Invalid mu/lambda ratio! Setting mu=lambda=" + mu); + this.lambda = this.mu; } -// if (this.m_UsePlusStrategy) this.m_Population.setTargetSize(this.m_Mu + this.m_Lambda); -// else this.m_Population.setTargetSize(this.m_Lambda); - this.m_Population.setTargetSize(this.m_Lambda); - origPopSize=m_Population.getTargetSize(); + this.population.setTargetSize(this.lambda); + origPopSize = population.getTargetSize(); } - /** This method allows you to set an identifier for the algorithm - * @param name The indenifier + /** + * This method allows you to set an identifier for the algorithm + * + * @param name The indenifier */ - public void SetIdentifier(String name) { - this.m_Identifier = name; + public void SetIdentifier(String name) { + this.identifier = name; } - public String getIdentifier() { - return this.m_Identifier; - } - /** This method is required to free the memory on a RMIServer, - * but there is nothing to implement. + public String getIdentifier() { + return this.identifier; + } + + /** + * This method is required to free the memory on a RMIServer, but there is + * nothing to implement. */ public void freeWilly() { + } - } -/********************************************************************************************************************** - * These are for GUI - */ - /** This method returns a global info string + /** + * These are for GUI + */ + + /** + * This method returns a global info string + * * @return description */ public static String globalInfo() { return "This is an Evolution Strategy. Note that the population size depends on mu (number of parents) and lambda (number of offspring)."; } - + public String[] customPropertyOrder() { - return new String[]{"mu", "lambda"}; + return new String[]{"mu", "lambda"}; } - - /** This method will return a naming String + + /** + * This method will return a naming String + * * @return The name of the algorithm */ public String getName() { - return "("+getMu()+(isPlusStrategy() ? "+" : ",")+getLambda()+")-ES"; + return "(" + getMu() + (isPlusStrategy() ? "+" : ",") + getLambda() + ")-ES"; } - /** - * Assuming that all optimizer will store their data in a population - * we will allow access to this population to query to current state - * of the optimizer. + /** + * Assuming that all optimizer will store their data in a population we will + * allow access to this population to query to current state of the + * optimizer. + * * @return The population of current solutions to a given problem. */ public Population getPopulation() { - return this.m_Population; + return this.population; } // for internal usage protected void setPop(Population pop) { - if (TRACE) System.out.println("ES Setting pop of " + pop.size()); - m_Population = pop; + this.population = pop; } - - public void setPopulation(Population pop){ - if (TRACE) System.out.println("ES Setting pop of " + pop.size()); - origPopSize = pop.size(); -// System.err.println("In ES: orig popsize is " + origPopSize); - this.m_Population = pop; + + public void setPopulation(Population pop) { + origPopSize = pop.size(); + this.population = pop; } + public String populationTipText() { return "Edit the properties of the population used."; } - - public InterfaceSolutionSet getAllSolutions() { - return new SolutionSet(getPopulation()); - } -// /** This method will set the normation method that is to be used. -// * @param normation -// */ -// public void setNormationMethod (InterfaceNormation normation) { -// this.m_NormationOperator = normation; -// } -// public InterfaceNormation getNormationMethod () { -// return this.m_NormationOperator; -// } -// public String normationMethodTipText() { -// return "Select the normation method."; -// } - /** This method will set the selection method that is to be used + public InterfaceSolutionSet getAllSolutions() { + return new SolutionSet(getPopulation()); + } + + /** + * This method will set the selection method that is to be used + * * @param selection */ public void setEnvironmentSelection(InterfaceSelection selection) { - this.m_EnvironmentSelection = selection; + this.environmentSelection = selection; } + public InterfaceSelection getEnvironmentSelection() { - return this.m_EnvironmentSelection; + return this.environmentSelection; } + public String environmentSelectionTipText() { return "Choose a method for selecting the reduced population."; } - /** This method will set the selection method that is to be used to select the partners + /** + * This method will set the selection method that is to be used to select + * the partners + * * @param selection */ public void setPartnerSelection(InterfaceSelection selection) { - this.m_PartnerSelection = selection; + this.partnerSelection = selection; } + public InterfaceSelection getPartnerSelection() { - return this.m_PartnerSelection; + return this.partnerSelection; } + public String partnerSelectionTipText() { return "Choose a selection method for selecting recombination partners."; } - /** This method will set the selection method that is to be used to select the parents + /** + * This method will set the selection method that is to be used to select + * the parents + * * @param selection */ public void setParentSelection(InterfaceSelection selection) { - this.m_ParentSelection = selection; + this.parentSelection = selection; } + public InterfaceSelection getParentSelection() { - return this.m_ParentSelection; + return this.parentSelection; } + public String parentSelectionTipText() { return "Choose a selection method for selecting parents."; } - /** This method will toggel between plus and comma selection strategy + /** + * This method will toggle between plus and comma selection strategy + * * @param elitism */ - public void setPlusStrategy (boolean elitism) { - this.m_UsePlusStrategy = elitism; -// this.checkPopulationConstraints(); // do this on init only + public void setPlusStrategy(boolean elitism) { + this.usePlusStrategy = elitism; } + public boolean isPlusStrategy() { - return this.m_UsePlusStrategy; + return this.usePlusStrategy; } + public String plusStrategyTipText() { return "Select between plus and comma strategy."; } - /** This method will set the number of partners that are needed to create + /** + * This method will set the number of partners that are needed to create * offsprings by mating + * * @param partners */ public void setNumberOfPartners(int partners) { - if (partners < 0) partners = 0; - this.m_NumberOfPartners = partners; + if (partners < 0) { + partners = 0; + } + this.numberOfPartners = partners; } + public int getNumberOfPartners() { - return this.m_NumberOfPartners; + return this.numberOfPartners; } + public String numberOfPartnersTipText() { return "The number of mating partners needed to create offsprings."; } -// /** This method will set the ratio between myu and lambda -// * @param lambdaratio -// */ -// public void setLambdaRatio(int lambdaratio) { -// if (lambdaratio < 1) lambdaratio = 1; -// this.m_LambdaRatio = lambdaratio; -// } -// public int getLambdaRatio() { -// return this.m_LambdaRatio; -// } -// public String lambdaRatioTipText() { -// return "This is the myu/lambda ratio."; -// } - /** This method will set the ratio between myu and lambda - * @param myuratio - */ -// public void setMyuRatio(double myuratio) { -// if (myuratio < 1) myuratio = 1; -// this.m_MyuRatio = myuratio; -// } -// public double getMyuRatio() { -// return this.m_MyuRatio; -// } -// public String myuRatioTipText() { -// return "This is the lambda/myu ratio."; -// } - - /** This method allows you to set parent population size myu - * @param myu The parent population size. + /** + * This method allows you to set parent population size myu + * + * @param myu The parent population size. */ public void setMu(int mu) { - this.m_Mu = mu; -// this.checkPopulationConstraints(); // do this on init only + this.mu = mu; } + public int getMu() { - return this.m_Mu; + return this.mu; } + public String muTipText() { return "This is the parent population size."; } - /** This is the children population size lambda - * @param lambda The children population size. + /** + * This is the children population size lambda + * + * @param lambda The children population size. */ public void setLambda(int lambda) { - this.m_Lambda = lambda; -// this.checkPopulationConstraints(); // do this on init only + this.lambda = lambda; } + public int getLambda() { - return this.m_Lambda; + return this.lambda; } + public String lambdaTipText() { return "This is the children population size."; } diff --git a/src/eva2/server/modules/Processor.java b/src/eva2/server/modules/Processor.java index cb87fff0..4bcdc34b 100644 --- a/src/eva2/server/modules/Processor.java +++ b/src/eva2/server/modules/Processor.java @@ -1,18 +1,8 @@ package eva2.server.modules; import eva2.EvAInfo; -import java.util.List; -import java.util.Vector; - -import javax.swing.JOptionPane; - import eva2.gui.BeanInspector; -import eva2.server.go.InterfaceGOParameters; -import eva2.server.go.InterfaceNotifyOnInformers; -import eva2.server.go.InterfacePopulationChangedEventListener; -import eva2.server.go.InterfaceProcessor; -import eva2.server.go.InterfaceTerminator; -import eva2.server.go.PopulationInterface; +import eva2.server.go.*; import eva2.server.go.operators.paramcontrol.ConstantParameters; import eva2.server.go.operators.paramcontrol.InterfaceParameterControl; import eva2.server.go.operators.postprocess.PostProcess; @@ -32,8 +22,11 @@ import eva2.tools.EVAHELP; import eva2.tools.StringTools; import eva2.tools.jproxy.RemoteStateListener; import eva2.tools.math.RNG; +import java.util.ArrayList; +import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; +import javax.swing.JOptionPane; /** * The Processor may run as a thread permanently (GenericModuleAdapter) and is then stopped and started @@ -400,7 +393,7 @@ public class Processor extends Thread implements InterfaceProcessor, InterfacePo } protected List getInformerList() { - Vector informerList = new Vector(2); + List informerList = new ArrayList(2); informerList.add(this.goParams.getProblem()); if (this.goParams.getOptimizer() instanceof InterfaceAdditionalPopulationInformer) { informerList.add((InterfaceAdditionalPopulationInformer) this.goParams.getOptimizer());