Merging mk branch rev 205, added post-processing methods (nelder-mead, cma-es); some cosmetics.
This commit is contained in:
parent
211c7a4477
commit
676fbb8498
@ -13,6 +13,7 @@ package eva2;
|
||||
* 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.
|
||||
|
@ -10,6 +10,7 @@ import eva2.server.go.IndividualInterface;
|
||||
import eva2.server.go.InterfacePopulationChangedEventListener;
|
||||
import eva2.server.go.InterfaceTerminator;
|
||||
import eva2.server.go.enums.DETypeEnum;
|
||||
import eva2.server.go.enums.PostProcessMethod;
|
||||
import eva2.server.go.individuals.AbstractEAIndividual;
|
||||
import eva2.server.go.individuals.InterfaceDataTypeBinary;
|
||||
import eva2.server.go.individuals.InterfaceDataTypeDouble;
|
||||
@ -798,11 +799,13 @@ public class OptimizerFactory {
|
||||
return (runnable != null) ? runnable.getSolutionSet() : null;
|
||||
}
|
||||
|
||||
public static Population postProcess(int steps, double sigma, int nBest) {
|
||||
return (lastRunnable == null) ? null : postProcess(lastRunnable,
|
||||
new PostProcessParams(steps, sigma, nBest));
|
||||
}
|
||||
///////////////////////////// post processing
|
||||
|
||||
public static Population postProcess(PostProcessMethod method, int steps, double sigma, int nBest) {
|
||||
return (lastRunnable == null) ? null : postProcess(lastRunnable,
|
||||
new PostProcessParams(method, steps, sigma, nBest));
|
||||
}
|
||||
|
||||
public static Population postProcess(InterfacePostProcessParams ppp) {
|
||||
return (lastRunnable == null) ? null : postProcess(lastRunnable, ppp);
|
||||
}
|
||||
@ -898,7 +901,6 @@ public class OptimizerFactory {
|
||||
: null;
|
||||
}
|
||||
|
||||
///////////////////////////// post processing
|
||||
public static Vector<AbstractEAIndividual> postProcessIndVec(
|
||||
OptimizerRunnable runnable, int steps, double sigma, int nBest) {
|
||||
return postProcessIndVec(runnable, new PostProcessParams(steps, sigma,
|
||||
|
@ -249,9 +249,12 @@ public class EvAClient implements RemoteStateListener, Serializable {
|
||||
m_LogPanel.logMessage("Class path is: " + System.getProperty("java.class.path","."));
|
||||
|
||||
if (!(m_Frame.isVisible())) {
|
||||
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
|
||||
m_Frame.setLocation((int)((screenSize.width-m_Frame.getWidth())/2), (int)((screenSize.height-m_Frame.getHeight())/2.5));
|
||||
m_Frame.pack();
|
||||
m_Frame.setVisible(true);
|
||||
}
|
||||
m_LogPanel.logMessage("EvA2 ready"); // if this message is omitted, the stupid scroll pane runs to the end of the last line which is ugly for a long class path
|
||||
}
|
||||
|
||||
/**
|
||||
@ -583,6 +586,7 @@ public class EvAClient implements RemoteStateListener, Serializable {
|
||||
|
||||
JPanel moduleContainer = Temp.createContentPane(); // MK the frame is actually painted in here
|
||||
// m_Frame.setLayout(new BorderLayout());
|
||||
boolean wasVisible = m_Frame.isVisible();
|
||||
m_Frame.setVisible(false);
|
||||
m_Frame.getContentPane().removeAll();
|
||||
|
||||
@ -599,7 +603,7 @@ public class EvAClient implements RemoteStateListener, Serializable {
|
||||
m_Frame.add(infoPanel, BorderLayout.SOUTH);
|
||||
|
||||
m_Frame.pack();
|
||||
m_Frame.setVisible(true);
|
||||
m_Frame.setVisible(wasVisible);
|
||||
|
||||
currentModule = selectedModule;
|
||||
// m_ModulGUIContainer.add(Temp);
|
||||
|
@ -318,6 +318,13 @@ public class FunctionArea extends DArea implements Serializable {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public void setConnectedPoint(double[] p, int graphLabel) {
|
||||
setConnectedPoint(p[0], p[1], graphLabel);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@ -334,8 +341,8 @@ public class FunctionArea extends DArea implements Serializable {
|
||||
// y = 1e-30;
|
||||
// }
|
||||
getGraphPointSet(graphLabel).addDPoint(x, y);
|
||||
|
||||
}
|
||||
|
||||
// public void setConnectedPoint(double x, double y, int GraphLabel) {
|
||||
// if (m_log == true && y <= 0.0) {
|
||||
//// y = Double.MIN_VALUE;
|
||||
@ -454,7 +461,10 @@ public class FunctionArea extends DArea implements Serializable {
|
||||
//addGraphPointSet(NewPointSet); already done within GraphPointSet!!!
|
||||
return NewPointSet;
|
||||
}
|
||||
|
||||
|
||||
public void setUnconnectedPoint(double[] p, int GraphLabel) {
|
||||
setUnconnectedPoint(p[0], p[1], GraphLabel);
|
||||
}
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
@ -32,100 +32,101 @@ import javax.swing.event.ChangeListener;
|
||||
import wsi.ra.tool.BasicResourceLoader;
|
||||
import eva2.EvAInfo;
|
||||
/*==========================================================================*
|
||||
* CLASS DECLARATION
|
||||
*==========================================================================*/
|
||||
* CLASS DECLARATION
|
||||
*==========================================================================*/
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class LogPanel extends JPanel {
|
||||
// protected JLabel m_Message = new JLabel("OK");
|
||||
protected JTextArea m_LogText = new JTextArea(10,20);
|
||||
protected boolean m_first = true;
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public LogPanel() {
|
||||
m_LogText.setEditable(false);
|
||||
m_LogText.setBorder(BorderFactory.createEmptyBorder(4,4,4,4));
|
||||
// m_Message.setBorder(BorderFactory.createCompoundBorder(
|
||||
// BorderFactory.createTitledBorder("Message"),
|
||||
// BorderFactory.createEmptyBorder(0,4,4,4)));
|
||||
JPanel panel_1 = new JPanel();
|
||||
panel_1.setBorder(BorderFactory.createTitledBorder("Info"));
|
||||
panel_1.setLayout(new BorderLayout());
|
||||
final JScrollPane scrollpane = new JScrollPane(m_LogText);
|
||||
panel_1.add(scrollpane, BorderLayout.CENTER);
|
||||
scrollpane.getViewport().addChangeListener(new ChangeListener() {
|
||||
private int lastHeight;
|
||||
//
|
||||
public void stateChanged(ChangeEvent e) {
|
||||
JViewport viewport = (JViewport)e.getSource();
|
||||
int Height = viewport.getViewSize().height;
|
||||
if (Height != lastHeight) {
|
||||
lastHeight = Height;
|
||||
int x = Height - viewport.getExtentSize().height;
|
||||
viewport.setViewPosition(new Point(0, x));
|
||||
// protected JLabel m_Message = new JLabel("OK");
|
||||
protected JTextArea m_LogText = new JTextArea(10,20);
|
||||
protected boolean m_first = true;
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public LogPanel() {
|
||||
m_LogText.setEditable(false);
|
||||
m_LogText.setBorder(BorderFactory.createEmptyBorder(4,4,4,4));
|
||||
// m_Message.setBorder(BorderFactory.createCompoundBorder(
|
||||
// BorderFactory.createTitledBorder("Message"),
|
||||
// BorderFactory.createEmptyBorder(0,4,4,4)));
|
||||
JPanel panel_1 = new JPanel();
|
||||
panel_1.setBorder(BorderFactory.createTitledBorder("Info"));
|
||||
panel_1.setLayout(new BorderLayout());
|
||||
final JScrollPane scrollpane = new JScrollPane(m_LogText);
|
||||
// scrollpane.setAutoscrolls(false);
|
||||
panel_1.add(scrollpane, BorderLayout.CENTER);
|
||||
scrollpane.getViewport().addChangeListener(new ChangeListener() {
|
||||
private int lastHeight;
|
||||
//
|
||||
public void stateChanged(ChangeEvent e) {
|
||||
JViewport viewport = (JViewport)e.getSource();
|
||||
int Height = viewport.getViewSize().height;
|
||||
if (Height != lastHeight) {
|
||||
lastHeight = Height;
|
||||
int x = Height - viewport.getExtentSize().height;
|
||||
viewport.setViewPosition(new Point(0, x));
|
||||
}
|
||||
}
|
||||
});
|
||||
setLayout(new BorderLayout());
|
||||
add(panel_1, BorderLayout.CENTER);
|
||||
JPanel panel_2 = new JPanel();
|
||||
panel_2.setLayout(new BorderLayout());
|
||||
// panel_2.add(m_Message,BorderLayout.CENTER);
|
||||
add(panel_2, BorderLayout.SOUTH);
|
||||
}
|
||||
}
|
||||
});
|
||||
setLayout(new BorderLayout());
|
||||
add(panel_1, BorderLayout.CENTER);
|
||||
JPanel panel_2 = new JPanel();
|
||||
panel_2.setLayout(new BorderLayout());
|
||||
// panel_2.add(m_Message,BorderLayout.CENTER);
|
||||
add(panel_2, BorderLayout.SOUTH);
|
||||
}
|
||||
/**
|
||||
*
|
||||
*/
|
||||
protected static String getTimestamp() {
|
||||
return (new SimpleDateFormat("HH:mm:ss:")).format(new Date());
|
||||
}
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public void logMessage(String message) {
|
||||
if (m_first)
|
||||
m_first = false;
|
||||
m_LogText.append("\n");
|
||||
m_LogText.append(LogPanel.getTimestamp() + ' ' + message);
|
||||
}
|
||||
// /**
|
||||
// *
|
||||
// */
|
||||
// public void statusMessage(String message) {
|
||||
// m_Message.setText(message);
|
||||
// }
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public static void main(String [] args) {
|
||||
try {
|
||||
final JFrame frame = new JFrame("Log_Panel_Test");
|
||||
frame.getContentPane().setLayout(new BorderLayout());
|
||||
BasicResourceLoader loader = BasicResourceLoader.instance();
|
||||
byte[] bytes = loader.getBytesFromResourceLocation(EvAInfo.iconLocation);
|
||||
try {
|
||||
frame.setIconImage(Toolkit.getDefaultToolkit().createImage(bytes));
|
||||
} catch (java.lang.NullPointerException e) {
|
||||
System.out.println("Could not find EvA2 icon, please move resources folder to working directory!");
|
||||
}
|
||||
LogPanel panel = new LogPanel();
|
||||
frame.getContentPane().add(panel, BorderLayout.CENTER);
|
||||
frame.addWindowListener(new WindowAdapter() {
|
||||
public void windowClosing(WindowEvent e) {
|
||||
frame.dispose();
|
||||
System.exit(0);
|
||||
/**
|
||||
*
|
||||
*/
|
||||
protected static String getTimestamp() {
|
||||
return (new SimpleDateFormat("HH:mm:ss:")).format(new Date());
|
||||
}
|
||||
});
|
||||
frame.pack();
|
||||
frame.setVisible(true);
|
||||
panel.logMessage("HI!");
|
||||
panel.logMessage("Test");
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public void logMessage(String message) {
|
||||
if (m_first)
|
||||
m_first = false;
|
||||
m_LogText.append("\n");
|
||||
m_LogText.append(LogPanel.getTimestamp() + ' ' + message);
|
||||
}
|
||||
// /**
|
||||
// *
|
||||
// */
|
||||
// public void statusMessage(String message) {
|
||||
// m_Message.setText(message);
|
||||
// }
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public static void main(String [] args) {
|
||||
try {
|
||||
final JFrame frame = new JFrame("Log_Panel_Test");
|
||||
frame.getContentPane().setLayout(new BorderLayout());
|
||||
BasicResourceLoader loader = BasicResourceLoader.instance();
|
||||
byte[] bytes = loader.getBytesFromResourceLocation(EvAInfo.iconLocation);
|
||||
try {
|
||||
frame.setIconImage(Toolkit.getDefaultToolkit().createImage(bytes));
|
||||
} catch (java.lang.NullPointerException e) {
|
||||
System.out.println("Could not find EvA2 icon, please move resources folder to working directory!");
|
||||
}
|
||||
LogPanel panel = new LogPanel();
|
||||
frame.getContentPane().add(panel, BorderLayout.CENTER);
|
||||
frame.addWindowListener(new WindowAdapter() {
|
||||
public void windowClosing(WindowEvent e) {
|
||||
frame.dispose();
|
||||
System.exit(0);
|
||||
}
|
||||
});
|
||||
frame.pack();
|
||||
frame.setVisible(true);
|
||||
panel.logMessage("HI!");
|
||||
panel.logMessage("Test ------------------------------------------------------------------------");
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
System.out.println(e.getMessage());
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
System.out.println(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
5
src/eva2/server/go/enums/PostProcessMethod.java
Normal file
5
src/eva2/server/go/enums/PostProcessMethod.java
Normal file
@ -0,0 +1,5 @@
|
||||
package eva2.server.go.enums;
|
||||
|
||||
public enum PostProcessMethod {
|
||||
hillClimber, nelderMead, cmaES;
|
||||
}
|
@ -16,6 +16,7 @@ import eva2.server.go.operators.crossover.NoCrossover;
|
||||
import eva2.server.go.operators.mutation.InterfaceMutation;
|
||||
import eva2.server.go.operators.mutation.NoMutation;
|
||||
import eva2.server.go.populations.Population;
|
||||
import eva2.server.go.problems.AbstractOptimizationProblem;
|
||||
import eva2.server.go.problems.InterfaceOptimizationProblem;
|
||||
import eva2.tools.EVAERROR;
|
||||
|
||||
@ -61,7 +62,7 @@ public abstract class AbstractEAIndividual implements IndividualInterface, java.
|
||||
protected HashMap<String,Object> m_dataHash = new HashMap<String,Object>();
|
||||
|
||||
// introduced for the nichingPSO/ANPSO (M.Aschoff)
|
||||
private int individualIndex;
|
||||
private int individualIndex = -1;
|
||||
|
||||
public AbstractEAIndividual() {
|
||||
m_IDcounter++;
|
||||
@ -77,7 +78,7 @@ public abstract class AbstractEAIndividual implements IndividualInterface, java.
|
||||
return individualIndex;
|
||||
}
|
||||
|
||||
public void setIndividualIndex(int index) {
|
||||
public void SetIndividualIndex(int index) {
|
||||
this.individualIndex = index;
|
||||
}
|
||||
|
||||
@ -94,13 +95,31 @@ public abstract class AbstractEAIndividual implements IndividualInterface, java.
|
||||
* @param coOp
|
||||
* @param pCross
|
||||
*/
|
||||
public void initOperators(InterfaceMutation mutOp, double pMut, InterfaceCrossover coOp, double pCross) {
|
||||
public void setOperators(InterfaceMutation mutOp, double pMut, InterfaceCrossover coOp, double pCross) {
|
||||
m_MutationProbability = pMut;
|
||||
m_MutationOperator = mutOp;
|
||||
m_CrossoverProbability = pCross;
|
||||
m_CrossoverOperator = coOp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clone and init the mutation/crossover operator for the individual
|
||||
* and initialize the operators and probabilities to the given values.
|
||||
*
|
||||
* @param mutOp
|
||||
* @param pMut
|
||||
* @param coOp
|
||||
* @param pCross
|
||||
*/
|
||||
public void initCloneOperators(InterfaceMutation mutOp, double pMut, InterfaceCrossover coOp, double pCross, InterfaceOptimizationProblem problem) {
|
||||
m_MutationProbability = pMut;
|
||||
m_MutationOperator = (InterfaceMutation)mutOp.clone();
|
||||
m_MutationOperator.init(this, problem);
|
||||
m_CrossoverProbability = pCross;
|
||||
m_CrossoverOperator = (InterfaceCrossover)coOp.clone();
|
||||
m_CrossoverOperator.init(this, problem);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the mutation/crossover operator and probabilities of the given individual to the given values.
|
||||
*
|
||||
@ -112,7 +131,7 @@ public abstract class AbstractEAIndividual implements IndividualInterface, java.
|
||||
* @return the modified AbstractEAIndividual
|
||||
*/
|
||||
public static AbstractEAIndividual setOperators(AbstractEAIndividual indy, InterfaceMutation mutOp, double pMut, InterfaceCrossover coOp, double pCross) {
|
||||
indy.initOperators(mutOp, pMut, coOp, pCross);
|
||||
indy.setOperators(mutOp, pMut, coOp, pCross);
|
||||
return indy;
|
||||
}
|
||||
|
||||
|
@ -43,7 +43,7 @@ class CMAParamSet implements InterfacePopulationChangedEventListener, Serializab
|
||||
protected boolean firstAdaptionDone = false;
|
||||
|
||||
public String toString() {
|
||||
return "d_sig " + d_sig + ", c_sig" + ", sigma " + sigma + ", firstSigma " + firstSigma+ ", firstAdaptionDone " + firstAdaptionDone
|
||||
return "d_sig " + d_sig + ", c_sig " + c_sig + ", sigma " + sigma + ", firstSigma " + firstSigma+ ", firstAdaptionDone " + firstAdaptionDone
|
||||
+ ",\n meanX " + Arrays.toString(meanX) + ", pathC " + Arrays.toString(pathC)+ ", pathS " + Arrays.toString(pathS)+ ", eigenvalues " + Arrays.toString(eigenvalues)
|
||||
+ ", weights " + Arrays.toString(weights)+ ",\n mC " + mC.toString() + ",\n mB " + mB.toString();
|
||||
}
|
||||
@ -100,6 +100,10 @@ class CMAParamSet implements InterfacePopulationChangedEventListener, Serializab
|
||||
params.d_sig = params.c_sig+1+2*Math.max(0, Math.sqrt((muEff-1)/(dim+1)) - 1);
|
||||
|
||||
if (initialSigma<0) initialSigma = getAvgRange(params.range);
|
||||
if (initialSigma <= 0) {
|
||||
EVAERROR.errorMsgOnce("warning: initial sigma <= zero! Working with converged population?");
|
||||
initialSigma = 10e-10;
|
||||
}
|
||||
params.sigma = initialSigma;
|
||||
// System.out.println("INitial sigma: "+sigma);
|
||||
params.firstSigma = params.sigma;
|
||||
@ -273,7 +277,7 @@ public class MutateESRankMuCMA implements InterfaceMutationGenerational, Seriali
|
||||
mu = selectedP.size();
|
||||
lambda = oldGen.size();
|
||||
if (mu>= lambda) {
|
||||
EVAERROR.errorMsgOnce("Warning: invalid mu/lambda ratio (" + mu + "/" + lambda + ") ! Setting mu to lambda/2.");
|
||||
EVAERROR.errorMsgOnce("Warning: invalid mu/lambda ratio! Setting mu to lambda/2.");
|
||||
mu = lambda/2;
|
||||
}
|
||||
CMAParamSet params;
|
||||
@ -282,7 +286,7 @@ public class MutateESRankMuCMA implements InterfaceMutationGenerational, Seriali
|
||||
else params = CMAParamSet.initCMAParams(mu, lambda, oldGen, getInitSigma(oldGen));
|
||||
} else {
|
||||
if (!oldGen.hasData(cmaParamsKey)) {
|
||||
if (oldGen.getGeneration() > 1) System.err.println("pop had no params at gen " + oldGen.getGeneration());
|
||||
if (oldGen.getGeneration() > 1) EVAERROR.errorMsgOnce("Error: population lost cma parameters. Incompatible optimizer?");
|
||||
params = CMAParamSet.initCMAParams(mu, lambda, oldGen, getInitSigma(oldGen));
|
||||
} else params = (CMAParamSet)oldGen.getData(cmaParamsKey);
|
||||
}
|
||||
@ -676,7 +680,7 @@ public class MutateESRankMuCMA implements InterfaceMutationGenerational, Seriali
|
||||
x[i] += RNG.gaussianDouble(getSigma(params, i));
|
||||
}
|
||||
}
|
||||
if (isInRange(x, range)) return x;
|
||||
if (Mathematics.isInRange(x, range)) return x;
|
||||
else {
|
||||
if (count > 5) return repairMutation(x, range); // allow some nice tries before using brute force
|
||||
else return mutate(params, x, range, count+1); // for really bad initial deviations this might be a quasi infinite loop
|
||||
@ -695,13 +699,6 @@ public class MutateESRankMuCMA implements InterfaceMutationGenerational, Seriali
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
private boolean isInRange(double[] x, double[][] range) {
|
||||
for (int i=0; i<x.length; i++) {
|
||||
if (x[i]<range[i][0] || (x[i]>range[i][1])) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* After optimization start, this returns the initial sigma value
|
||||
|
@ -1,5 +1,7 @@
|
||||
package eva2.server.go.operators.postprocess;
|
||||
|
||||
import eva2.server.go.enums.PostProcessMethod;
|
||||
|
||||
/**
|
||||
* Parameters for an optional post processing of found solutions. Mainly contains
|
||||
* parameters for a hill climbing step, namely the number of evaluations and
|
||||
@ -25,4 +27,8 @@ public interface InterfacePostProcessParams {
|
||||
public int getPrintNBest();
|
||||
public void setPrintNBest(int nBest);
|
||||
public String printNBestTipText();
|
||||
|
||||
public void setPPMethod(PostProcessMethod meth);
|
||||
public PostProcessMethod getPPMethod();
|
||||
public String PPMethodTipText();
|
||||
}
|
||||
|
@ -1,28 +1,44 @@
|
||||
package eva2.server.go.operators.postprocess;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
||||
import eva2.OptimizerFactory;
|
||||
import eva2.OptimizerRunnable;
|
||||
import eva2.gui.BeanInspector;
|
||||
import eva2.gui.Plot;
|
||||
import eva2.gui.TopoPlot;
|
||||
import eva2.server.go.InterfaceTerminator;
|
||||
import eva2.server.go.enums.ESMutationInitialSigma;
|
||||
import eva2.server.go.enums.PostProcessMethod;
|
||||
import eva2.server.go.individuals.AbstractEAIndividual;
|
||||
import eva2.server.go.individuals.ESIndividualDoubleData;
|
||||
import eva2.server.go.individuals.InterfaceDataTypeDouble;
|
||||
import eva2.server.go.individuals.InterfaceESIndividual;
|
||||
import eva2.server.go.operators.cluster.ClusteringDensityBased;
|
||||
import eva2.server.go.operators.cluster.InterfaceClustering;
|
||||
import eva2.server.go.operators.crossover.CrossoverESDefault;
|
||||
import eva2.server.go.operators.distancemetric.InterfaceDistanceMetric;
|
||||
import eva2.server.go.operators.distancemetric.PhenotypeMetric;
|
||||
import eva2.server.go.operators.mutation.InterfaceMutation;
|
||||
import eva2.server.go.operators.mutation.MutateESFixedStepSize;
|
||||
import eva2.server.go.operators.mutation.MutateESMutativeStepSizeControl;
|
||||
import eva2.server.go.operators.mutation.MutateESRankMuCMA;
|
||||
import eva2.server.go.operators.selection.SelectBestIndividuals;
|
||||
import eva2.server.go.operators.terminators.EvaluationTerminator;
|
||||
import eva2.server.go.populations.Population;
|
||||
import eva2.server.go.problems.AbstractMultiModalProblemKnown;
|
||||
import eva2.server.go.problems.AbstractOptimizationProblem;
|
||||
import eva2.server.go.problems.FM0Problem;
|
||||
import eva2.server.go.problems.Interface2DBorderProblem;
|
||||
import eva2.server.go.problems.InterfaceMultimodalProblemKnown;
|
||||
import eva2.server.go.strategies.EvolutionStrategies;
|
||||
import eva2.server.go.strategies.HillClimbing;
|
||||
import eva2.server.go.strategies.NelderMeadSimplex;
|
||||
import eva2.server.modules.GOParameters;
|
||||
import eva2.server.stat.InterfaceTextListener;
|
||||
import eva2.server.stat.StatsParameter;
|
||||
import eva2.tools.Mathematics;
|
||||
import eva2.tools.Pair;
|
||||
|
||||
|
||||
@ -35,12 +51,14 @@ import eva2.tools.Pair;
|
||||
public class PostProcess {
|
||||
protected static InterfaceDistanceMetric metric = new PhenotypeMetric();
|
||||
private static final boolean TRACE = false;
|
||||
private static final boolean DRAW_PPPOP = true;
|
||||
|
||||
// the default mutation step size for HC post processing
|
||||
private static double defaultMutationStepSize = 0.01;
|
||||
// lower limit mutation step size for HC post processing
|
||||
private static double minMutationStepSize = 0.0000000000000001;
|
||||
// used for hill climbing post processing and only alive during that period
|
||||
private static OptimizerRunnable hcRunnable = null;
|
||||
private static OptimizerRunnable ppRunnable = null;
|
||||
|
||||
public static final int BEST_ONLY = 1;
|
||||
public static final int BEST_RAND = 2;
|
||||
@ -251,9 +269,9 @@ public class PostProcess {
|
||||
double lower = lowerBound;
|
||||
double step = (upperBound - lowerBound) / nBins;
|
||||
for (int i=0; i<nBins; i++) {
|
||||
if (TRACE) System.out.println("checking between " + lower + " and " + (lower+step));
|
||||
// if (TRACE) System.out.println("checking between " + lower + " and " + (lower+step));
|
||||
res[i] = filterFitnessIn(pop, lower, lower+step).size();
|
||||
if (TRACE) System.out.println("found " + res[i]);
|
||||
// if (TRACE) System.out.println("found " + res[i]);
|
||||
lower += step;
|
||||
}
|
||||
return res;
|
||||
@ -372,23 +390,346 @@ public class PostProcess {
|
||||
}
|
||||
hc.setPopulation(pop);
|
||||
// hc.initByPopulation(pop, false);
|
||||
hcRunnable = new OptimizerRunnable(OptimizerFactory.makeParams(hc, pop, problem, 0, term), true);
|
||||
hcRunnable.getGOParams().setDoPostProcessing(false);
|
||||
hcRunnable.setVerbosityLevel(StatsParameter.VERBOSITY_NONE);
|
||||
hcRunnable.run();
|
||||
hcRunnable.getGOParams().setDoPostProcessing(true);
|
||||
hcRunnable = null;
|
||||
ppRunnable = new OptimizerRunnable(OptimizerFactory.makeParams(hc, pop, problem, 0, term), true);
|
||||
|
||||
runPP();
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop the hill-climbing post processing if its currently running.
|
||||
* Search for a local minimum using nelder mead and return the solution found and the number of steps
|
||||
* (evaluations) actually performed. This uses the whole population as starting population for nelder mead
|
||||
* meaning that typically only one best is returned.
|
||||
*
|
||||
* @param pop
|
||||
* @param problem
|
||||
* @param term
|
||||
* @return
|
||||
*/
|
||||
public static void stopHC() {
|
||||
if (hcRunnable != null) synchronized (hcRunnable) {
|
||||
if (hcRunnable != null) hcRunnable.stopOpt();
|
||||
public static int processWithNMS(Population pop, AbstractOptimizationProblem problem, InterfaceTerminator term) {
|
||||
NelderMeadSimplex nms = new NelderMeadSimplex();
|
||||
nms.setProblemAndPopSize(problem);
|
||||
nms.setGenerationCycle(5);
|
||||
nms.initByPopulation(pop, false);
|
||||
int funCallsBefore = pop.getFunctionCalls();
|
||||
pop.SetFunctionCalls(0);
|
||||
|
||||
ppRunnable = new OptimizerRunnable(OptimizerFactory.makeParams(nms, pop, problem, 0, term), true);
|
||||
// as nms creates a new population and has already evaluated them, send a signal to stats
|
||||
ppRunnable.getStats().createNextGenerationPerformed(nms.getPopulation(), null);
|
||||
|
||||
runPP();
|
||||
|
||||
int funCallsDone = pop.getFunctionCalls();
|
||||
pop.SetFunctionCalls(funCallsBefore+funCallsDone);
|
||||
|
||||
return funCallsDone;
|
||||
}
|
||||
|
||||
/**
|
||||
* Search for a local minimum using nelder mead and return the solution found and the number of steps
|
||||
* (evaluations) actually performed. This uses the whole population as starting population for nelder mead
|
||||
* meaning that typically only one best is returned.
|
||||
*
|
||||
* @param pop
|
||||
* @param problem
|
||||
* @param term
|
||||
* @return
|
||||
*/
|
||||
public static int processWithCMA(Population pop, AbstractOptimizationProblem problem, InterfaceTerminator term) {
|
||||
// GOParameters cmaParams = OptimizerFactory.cmaESIPOP(problem);
|
||||
MutateESRankMuCMA mutator = new MutateESRankMuCMA();
|
||||
mutator.setInitializeSigma(ESMutationInitialSigma.avgInitialDistance);
|
||||
// mutator.
|
||||
EvolutionStrategies es = OptimizerFactory.createEvolutionStrategy(pop.size()/2, pop.size(), false, mutator, 1., new CrossoverESDefault(), 0.,
|
||||
new SelectBestIndividuals(), problem, null);
|
||||
for (int i=0; i<pop.size(); i++) {
|
||||
pop.getEAIndividual(i).initCloneOperators(mutator, 1., new CrossoverESDefault(), 0., problem);
|
||||
}
|
||||
es.initByPopulation(pop, false);
|
||||
|
||||
GOParameters cmaParams = OptimizerFactory.makeParams(es, pop, problem, 0, term);
|
||||
|
||||
int funCallsBefore = pop.getFunctionCalls();
|
||||
pop.SetFunctionCalls(0);
|
||||
|
||||
ppRunnable = new OptimizerRunnable(cmaParams, true);
|
||||
ppRunnable.getStats().createNextGenerationPerformed(cmaParams.getOptimizer().getPopulation(), null);
|
||||
|
||||
runPP();
|
||||
pop.clear();
|
||||
pop.addPopulation(es.getPopulation());
|
||||
|
||||
int funCallsDone = es.getPopulation().getFunctionCalls();
|
||||
pop.SetFunctionCalls(funCallsBefore+funCallsDone);
|
||||
|
||||
return funCallsDone;
|
||||
}
|
||||
|
||||
private static boolean checkRange(AbstractEAIndividual indy) {
|
||||
InterfaceDataTypeDouble idd = (InterfaceDataTypeDouble)indy;
|
||||
return Mathematics.isInRange(idd.getDoubleData(), idd.getDoubleRange());
|
||||
}
|
||||
|
||||
/**
|
||||
* For a given candidate solution, perform a nelder-mead-simplex refining search by producing a sample
|
||||
* population around the candidate (with given perturbation ratio relative to the problem range).
|
||||
* Then, the nelder mead algorithm is started and the best individual returned together with
|
||||
* the evaluations actually performed.
|
||||
*
|
||||
* @see NelderMeadSimplex.createNMSPopulation(candidate, perturbRatio, range, includeCand)
|
||||
*
|
||||
* @param cand
|
||||
* @param hcSteps
|
||||
* @param initPerturbation
|
||||
* @param prob
|
||||
* @return
|
||||
*/
|
||||
public static Pair<AbstractEAIndividual, Integer> localSolverNMS(AbstractEAIndividual cand, int hcSteps,
|
||||
double initPerturbation, AbstractOptimizationProblem prob) {
|
||||
|
||||
Population pop = new Population(1);
|
||||
pop.add(cand);
|
||||
int evalsDone = processSingleCandidates(PostProcessMethod.nelderMead, pop, hcSteps, initPerturbation, prob);
|
||||
|
||||
return new Pair<AbstractEAIndividual, Integer>(pop.getBestEAIndividual(), evalsDone);
|
||||
|
||||
// Population candidates = NelderMeadSimplex.createNMSPopulation(cand, initPerturbation , range, false);
|
||||
// prob.evaluate(candidates);
|
||||
//// refSet.incrFunctionCallsby(candidates.size());
|
||||
// int evalsDone = candidates.size();
|
||||
// int hcStepsRest = hcSteps - candidates.size();
|
||||
//
|
||||
// candidates.add(cand);
|
||||
// candidates.setPopulationSize(candidates.size());
|
||||
// if (hcStepsRest < 1) {
|
||||
// System.err.println("Error: Less steps than dimensions! " + hcSteps + " vs " + candidates.size());
|
||||
// return new Pair<AbstractEAIndividual, Integer>(candidates.getBestEAIndividual(), evalsDone);
|
||||
// } else {
|
||||
//// candidates.setEvaluated(); // they have all been evaluated at this point and no mod. is due
|
||||
//// if (!candidates.isEvaluated()) {
|
||||
//// System.err.println("this is bad!");
|
||||
//// }
|
||||
// InterfaceTerminator term = new EvaluationTerminator(hcStepsRest);
|
||||
//
|
||||
// evalsDone += PostProcess.processWithNMS(candidates, prob, term);
|
||||
// if (Math.abs(evalsDone-hcSteps)>1) {
|
||||
// System.err.println("Error in localSolverNMS " + evalsDone + " / " + hcSteps);
|
||||
// }
|
||||
// }
|
||||
// return new Pair<AbstractEAIndividual, Integer>(candidates.getBestEAIndividual(), evalsDone);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a subpopulation around an indicated individual from the candidate set.
|
||||
* Depending on the post processing method, this is done slightly differently. For hill-climbing,
|
||||
* an error message is produced.
|
||||
*/
|
||||
private static Population createLSSupPopulation(PostProcessMethod method, AbstractOptimizationProblem problem, Population candidates, int index, double maxPerturbation, boolean includeCand) {
|
||||
Population subPop = null;
|
||||
switch (method) {
|
||||
case cmaES:
|
||||
subPop = createPopInSubRange(maxPerturbation, problem, candidates.getEAIndividual(index));
|
||||
break;
|
||||
case hillClimber:
|
||||
System.err.println("INVALID in createLSSupPopulation");
|
||||
break;
|
||||
case nelderMead:
|
||||
double[][] range = ((InterfaceDataTypeDouble)candidates.getEAIndividual(index)).getDoubleRange();
|
||||
double perturb = findNMSPerturn(candidates, index, maxPerturbation);
|
||||
if (TRACE) System.out.println("perturb " + index + " is " + perturb);
|
||||
subPop = NelderMeadSimplex.createNMSPopulation(candidates.getEAIndividual(index), perturb, range, false);
|
||||
}
|
||||
return subPop;
|
||||
}
|
||||
|
||||
/**
|
||||
* For each candidate individual, create an own nm-population and optimize it separately.
|
||||
* The allowed steps must be large enough to perform a Nelder-Mead-Simplex step for all individuals, namely
|
||||
* for problem dimension n it should be (n+k)*candPopSize for a positive integer k.
|
||||
* At the moment, the function calls are distributed evenly between all candidate solutions. This could be
|
||||
* improved by checking the convergence state in the future.
|
||||
*
|
||||
* @param candidates
|
||||
* @param steps
|
||||
* @param maxPerturbation
|
||||
* @param prob
|
||||
* @return
|
||||
*/
|
||||
public static int processSingleCandidates(PostProcessMethod method, Population candidates, int steps, double maxPerturbation, AbstractOptimizationProblem prob) {
|
||||
ArrayList<Population> nmPops = new ArrayList<Population>();
|
||||
int stepsPerf = 0;
|
||||
Population subPop;
|
||||
|
||||
for (int i=0; i<candidates.size(); i++) { // create all subPopulations
|
||||
subPop = createLSSupPopulation(method, prob, candidates, i, maxPerturbation, false);
|
||||
|
||||
prob.evaluate(subPop);
|
||||
stepsPerf += subPop.size();
|
||||
subPop.add(candidates.getEAIndividual(i));
|
||||
nmPops.add(subPop);
|
||||
}
|
||||
|
||||
int stepsPerCand = (steps-stepsPerf)/candidates.size();
|
||||
if (TRACE) System.out.println("rest is " + (steps-stepsPerf) + ", thats " + stepsPerCand + " per candidate.");
|
||||
if (stepsPerCand < 1) System.err.println("Too few steps allowed!");
|
||||
else {
|
||||
for (int i=0; i<candidates.size(); i++) { // improve each single sub pop
|
||||
subPop = nmPops.get(i);
|
||||
EvaluationTerminator term = new EvaluationTerminator(stepsPerCand);
|
||||
if (TRACE) System.out.println("*** before " + subPop.getBestEAIndividual().getStringRepresentation());
|
||||
|
||||
switch (method) {
|
||||
case nelderMead: stepsPerf += PostProcess.processWithNMS(subPop, prob, term);
|
||||
break;
|
||||
case cmaES: stepsPerf += PostProcess.processWithCMA(subPop, prob, term);
|
||||
break;
|
||||
}
|
||||
if (checkRange(subPop.getBestEAIndividual())) {
|
||||
// and replace corresponding individual (should usually be better)
|
||||
if (subPop.getBestEAIndividual().isDominant(candidates.getEAIndividual(i))) candidates.set(i, subPop.getBestEAIndividual());
|
||||
} else {
|
||||
// TODO esp. in nelder mead
|
||||
//System.err.println("Warning, individual left the problem range during PP!");
|
||||
}
|
||||
|
||||
if (TRACE) System.out.println("refined to " + subPop.getBestEAIndividual().getStringRepresentation());
|
||||
}
|
||||
}
|
||||
|
||||
return stepsPerf;
|
||||
}
|
||||
|
||||
public static boolean isDoubleCompliant(AbstractEAIndividual indy) {
|
||||
return (indy instanceof InterfaceDataTypeDouble || (indy instanceof InterfaceESIndividual));
|
||||
}
|
||||
|
||||
public static double[][] getDoubleRange(AbstractEAIndividual indy) {
|
||||
if (indy instanceof InterfaceDataTypeDouble || (indy instanceof InterfaceESIndividual)) {
|
||||
if (indy instanceof InterfaceESIndividual) return ((InterfaceESIndividual)indy).getDoubleRange();
|
||||
else return ((InterfaceDataTypeDouble)indy).getDoubleRange();
|
||||
} else return null;
|
||||
}
|
||||
|
||||
public static double[] getDoubleData(AbstractEAIndividual indy) {
|
||||
if (indy instanceof InterfaceDataTypeDouble || (indy instanceof InterfaceESIndividual)) {
|
||||
if (indy instanceof InterfaceESIndividual) return ((InterfaceESIndividual)indy).getDGenotype();
|
||||
else return ((InterfaceDataTypeDouble)indy).getDoubleData();
|
||||
} else return null;
|
||||
}
|
||||
|
||||
public static void setDoubleData(AbstractEAIndividual indy, double[] data) {
|
||||
if (indy instanceof InterfaceDataTypeDouble || (indy instanceof InterfaceESIndividual)) {
|
||||
if (indy instanceof InterfaceESIndividual) ((InterfaceESIndividual)indy).SetDGenotype(data);
|
||||
else ((InterfaceDataTypeDouble)indy).SetDoubleGenotype(data);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a population of clones of the given individual in a sub range around the individual.
|
||||
* The given individual must be double compliant. The population size is determined by the range dimension
|
||||
* using the formula for lambda=4+3*log(dim).
|
||||
* The individuals are randomly initialized in a box of side length searchBoxLen around indy holding the
|
||||
* problem constraints, meaning that the box may be smaller at the brim of the problem-defined search range.
|
||||
*
|
||||
* @param searchBoxLen
|
||||
* @param prob
|
||||
* @param indy
|
||||
* @return
|
||||
*/
|
||||
private static Population createPopInSubRange(double searchBoxLen,
|
||||
AbstractOptimizationProblem prob,
|
||||
AbstractEAIndividual indy) {
|
||||
if (isDoubleCompliant(indy)) {
|
||||
double[][] range = getDoubleRange(indy);
|
||||
double[] data = getDoubleData(indy);
|
||||
int lambda= (int) (4.0 + 3.0 * Math.log(range.length));
|
||||
double[][] newRange = new double[2][range.length];
|
||||
for (int dim=0; dim<range.length; dim++) {
|
||||
// create a small range array around the expected local optimum
|
||||
newRange[dim][0] = Math.max(range[dim][0], data[dim]-(searchBoxLen/2.));
|
||||
newRange[dim][1] = Math.min(range[dim][1], data[dim]+(searchBoxLen/2.));
|
||||
}
|
||||
Population pop = new Population();
|
||||
for (int i=0; i<lambda-1; i++) { // minus one because indy is added later
|
||||
AbstractEAIndividual tmpIndy = (AbstractEAIndividual)indy.clone();
|
||||
data = getDoubleData(tmpIndy);
|
||||
ESIndividualDoubleData.defaultInit(data, newRange);
|
||||
setDoubleData(tmpIndy, data);
|
||||
pop.addIndividual(tmpIndy);
|
||||
}
|
||||
pop.synchSize();
|
||||
return pop;
|
||||
} else {
|
||||
System.err.println("invalid individual type!");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Just execute the runnable.
|
||||
*/
|
||||
private static void runPP() {
|
||||
ppRunnable.getGOParams().setDoPostProcessing(false);
|
||||
ppRunnable.setVerbosityLevel(StatsParameter.VERBOSITY_NONE);
|
||||
ppRunnable.run();
|
||||
ppRunnable.getGOParams().setDoPostProcessing(true);
|
||||
ppRunnable = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop the post processing if its currently running.
|
||||
*/
|
||||
public static void stopPP() {
|
||||
if (ppRunnable != null) synchronized (ppRunnable) {
|
||||
if (ppRunnable != null) ppRunnable.stopOpt();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw the given population in a (topo)plot. If two populations are given, the first
|
||||
* is interpreted as "before optimization", the second as "after optimization", and
|
||||
* thats how they are displayed.
|
||||
*
|
||||
* @param title
|
||||
* @param plot
|
||||
* @param popBef
|
||||
* @param popAft
|
||||
* @param prob
|
||||
* @return
|
||||
*/
|
||||
private static TopoPlot draw(String title, TopoPlot plot, Population popBef, Population popAft, AbstractOptimizationProblem prob) {
|
||||
double[][] range = ((InterfaceDataTypeDouble)popBef.getEAIndividual(0)).getDoubleRange();
|
||||
|
||||
if (plot == null) {
|
||||
plot = new TopoPlot("PostProcessing: " + title, "x", "y",range[0],range[1]);
|
||||
if (prob instanceof Interface2DBorderProblem) {
|
||||
plot.gridx=60;
|
||||
plot.gridy=60;
|
||||
plot.setTopology((Interface2DBorderProblem)prob);
|
||||
}
|
||||
}
|
||||
else plot.clearAll();
|
||||
|
||||
InterfaceDataTypeDouble tmpIndy1;
|
||||
for (int i = 0; i < popBef.size(); i++) {
|
||||
tmpIndy1 = (InterfaceDataTypeDouble)popBef.get(i);
|
||||
plot.getFunctionArea().drawCircle(popBef.getEAIndividual(i).getFitness(0), tmpIndy1.getDoubleData(), 0);
|
||||
}
|
||||
if (popAft!=null) {
|
||||
InterfaceDataTypeDouble tmpIndy2;
|
||||
plot.getFunctionArea().setGraphColor(0, 2);
|
||||
for (int i = 0; i < popAft.size(); i++) {
|
||||
tmpIndy1 = (InterfaceDataTypeDouble)popBef.get(i);
|
||||
tmpIndy2 = (InterfaceDataTypeDouble)popAft.get(i);
|
||||
plot.getFunctionArea().drawCircle(popAft.getEAIndividual(i).getFitness(0), tmpIndy2.getDoubleData(), 0);
|
||||
plot.getFunctionArea().setConnectedPoint(tmpIndy1.getDoubleData(), i+1);
|
||||
plot.getFunctionArea().setConnectedPoint(tmpIndy2.getDoubleData(), i+1);
|
||||
plot.getFunctionArea().setGraphColor(i+1, 0);
|
||||
}
|
||||
}
|
||||
return plot;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
AbstractOptimizationProblem problem = new FM0Problem();
|
||||
InterfaceMultimodalProblemKnown mmp = (InterfaceMultimodalProblemKnown)problem;
|
||||
@ -510,7 +851,7 @@ public class PostProcess {
|
||||
}
|
||||
|
||||
/**
|
||||
* Universal post processing method, receiving parameter instance for specification.
|
||||
* General post processing method, receiving parameter instance for specification.
|
||||
* Optional clustering and HC step, output contains population measures, fitness histogram and
|
||||
* a list of solutions after post processing.
|
||||
*
|
||||
@ -522,17 +863,34 @@ public class PostProcess {
|
||||
*/
|
||||
public static Population postProcess(InterfacePostProcessParams params, Population inputPop, AbstractOptimizationProblem problem, InterfaceTextListener listener) {
|
||||
if (params.isDoPostProcessing()) {
|
||||
Population clusteredPop, outputPop;
|
||||
Plot plot;
|
||||
|
||||
Population clusteredPop, outputPop, stateBeforeLS;
|
||||
if (params.getPostProcessClusterSigma() > 0) {
|
||||
clusteredPop = (Population)PostProcess.clusterBest(inputPop, params.getPostProcessClusterSigma(), 0, PostProcess.KEEP_LONERS, PostProcess.BEST_ONLY).clone();
|
||||
if (clusteredPop.size() < inputPop.size()) {
|
||||
if (listener != null) listener.println("Initial clustering reduced population size from " + inputPop.size() + " to " + clusteredPop.size());
|
||||
} else if (listener != null) listener.println("Initial clustering yielded no size reduction.");
|
||||
} else clusteredPop = inputPop;
|
||||
|
||||
// if (DRAW_PPPOP) {
|
||||
// plot = draw((params.getPostProcessClusterSigma()>0) ? "After first clustering" : "Initial population", null, clusteredPop, null, problem);
|
||||
// }
|
||||
|
||||
int stepsDone = 0;
|
||||
if (params.getPostProcessSteps() > 0) {
|
||||
int stepsDone = processWithHC(clusteredPop, problem, params.getPostProcessSteps());
|
||||
if (listener != null) listener.println("HC post processing: " + stepsDone + " steps done.");
|
||||
double stepSize = selectMaxSearchRange(params.getPPMethod(), params.getPostProcessClusterSigma());
|
||||
stateBeforeLS = (Population)clusteredPop.clone();
|
||||
// Actual local search comes here
|
||||
if (params.getPPMethod() == PostProcessMethod.hillClimber){
|
||||
stepsDone = processWithHC(clusteredPop, problem, params.getPostProcessSteps(), stepSize, minMutationStepSize);
|
||||
} else {
|
||||
stepsDone = processSingleCandidates(params.getPPMethod(), clusteredPop, params.getPostProcessSteps(), stepSize, problem);
|
||||
}
|
||||
|
||||
if (listener != null) listener.println("Post processing: " + stepsDone + " steps done.");
|
||||
if (DRAW_PPPOP) {
|
||||
plot = draw("After " + stepsDone + " steps", null, stateBeforeLS, clusteredPop, problem);
|
||||
}
|
||||
// some individuals may have now converged again
|
||||
if (params.getPostProcessClusterSigma() > 0) {
|
||||
// so if wished, cluster again.
|
||||
@ -543,6 +901,9 @@ public class PostProcess {
|
||||
} else outputPop = clusteredPop;
|
||||
} else outputPop = clusteredPop;
|
||||
|
||||
if (DRAW_PPPOP) {
|
||||
plot = draw("After " + stepsDone + " steps" + ((params.getPostProcessClusterSigma()>0) ? " and second clustering" : ""), null, outputPop, null, problem);
|
||||
}
|
||||
double upBnd = PhenotypeMetric.norm(outputPop.getWorstEAIndividual().getFitness())*1.1;
|
||||
upBnd = Math.pow(10,Math.floor(Math.log10(upBnd)+1));
|
||||
double lowBnd = 0;
|
||||
@ -565,5 +926,56 @@ public class PostProcess {
|
||||
return nBestPop;
|
||||
} else return inputPop;
|
||||
}
|
||||
|
||||
/**
|
||||
* Select a local search range for a given method based on the clustering parameter.
|
||||
* If clustering was deactivated (sigma <= 0), then the default mutation step size is used.
|
||||
* The specific search method may interpret the search range differently.
|
||||
*
|
||||
* @param method
|
||||
* @param postProcessClusterSigma
|
||||
* @return
|
||||
*/
|
||||
private static double selectMaxSearchRange(PostProcessMethod method,
|
||||
double postProcessClusterSigma) {
|
||||
double resolution = defaultMutationStepSize*2; // somewhat keep the ratio between mutation and resolution
|
||||
if (postProcessClusterSigma > 0.) resolution = postProcessClusterSigma;
|
||||
switch (method) {
|
||||
case hillClimber:
|
||||
return resolution/2.;
|
||||
case nelderMead:
|
||||
return resolution/3.;
|
||||
default:
|
||||
System.err.println("Invalid method!");
|
||||
case cmaES:
|
||||
return resolution;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Select a perturbation for individual i fitting to the population - avoiding overlap.
|
||||
* In this case, return the third of the minimum distance to the next neighbor in the population.
|
||||
* The maxPerturb can be given as upper bound of the perturbation if it is > 0.
|
||||
*
|
||||
* @param candidates population of solutions to look at
|
||||
* @param i index of the individual in the population to look at
|
||||
* @param maxPerturb optional upper bound of the returned perturbation
|
||||
* @return
|
||||
*/
|
||||
private static double findNMSPerturn(Population candidates, int i, double maxPerturb) {
|
||||
double minDistNeighbour = Double.MAX_VALUE;
|
||||
AbstractEAIndividual indy = candidates.getEAIndividual(i);
|
||||
for (int k=0; k<candidates.size(); k++) {
|
||||
if (k!=i) {
|
||||
double dist = PhenotypeMetric.euclidianDistance(AbstractEAIndividual.getDoublePosition(indy), AbstractEAIndividual.getDoublePosition(candidates.getEAIndividual(k)));
|
||||
if (dist < minDistNeighbour) {
|
||||
minDistNeighbour = dist;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (maxPerturb>0) return Math.min(maxPerturb, minDistNeighbour/3.);
|
||||
else return minDistNeighbour/3.;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,6 +3,7 @@ package eva2.server.go.operators.postprocess;
|
||||
import java.io.Serializable;
|
||||
|
||||
import eva2.gui.GenericObjectEditor;
|
||||
import eva2.server.go.enums.PostProcessMethod;
|
||||
|
||||
|
||||
public class PostProcessParams implements InterfacePostProcessParams, Serializable {
|
||||
@ -11,6 +12,7 @@ public class PostProcessParams implements InterfacePostProcessParams, Serializab
|
||||
private boolean postProcess = false;
|
||||
protected double postProcessClusterSigma = 0.05;
|
||||
protected int printNBest = 10;
|
||||
protected PostProcessMethod method = PostProcessMethod.nelderMead;
|
||||
|
||||
public PostProcessParams() {
|
||||
postProcessSteps = 5000;
|
||||
@ -36,6 +38,14 @@ public class PostProcessParams implements InterfacePostProcessParams, Serializab
|
||||
printNBest = nBest;
|
||||
}
|
||||
|
||||
public PostProcessParams(PostProcessMethod meth, int steps, double clusterSigma, int nBest) {
|
||||
method = meth;
|
||||
postProcessSteps = steps;
|
||||
postProcess = true;
|
||||
postProcessClusterSigma = clusterSigma;
|
||||
printNBest = nBest;
|
||||
}
|
||||
|
||||
public void hideHideable() {
|
||||
setDoPostProcessing(isDoPostProcessing());
|
||||
}
|
||||
@ -54,6 +64,7 @@ public class PostProcessParams implements InterfacePostProcessParams, Serializab
|
||||
GenericObjectEditor.setShowProperty(this.getClass(), "postProcessSteps", postProcess);
|
||||
GenericObjectEditor.setShowProperty(this.getClass(), "postProcessClusterSigma", postProcess);
|
||||
GenericObjectEditor.setShowProperty(this.getClass(), "printNBest", postProcess);
|
||||
GenericObjectEditor.setShowProperty(this.getClass(), "PPMethod", postProcess);
|
||||
}
|
||||
public String doPostProcessingTipText() {
|
||||
return "Toggle post processing of the solutions.";
|
||||
@ -102,4 +113,16 @@ public class PostProcessParams implements InterfacePostProcessParams, Serializab
|
||||
public String globalInfo() {
|
||||
return "Combined clustering and hill-climbing for post-processing of solutions.";
|
||||
}
|
||||
|
||||
public PostProcessMethod getPPMethod() {
|
||||
return method;
|
||||
}
|
||||
|
||||
public String PPMethodTipText() {
|
||||
return "The method to use for post-processing.";
|
||||
}
|
||||
|
||||
public void setPPMethod(PostProcessMethod meth) {
|
||||
method=meth;
|
||||
}
|
||||
}
|
||||
|
@ -25,6 +25,7 @@ public class SelectParticleWheel implements InterfaceSelection, java.io.Serializ
|
||||
*/
|
||||
private static final long serialVersionUID = 1L;
|
||||
private InterfaceSelectionProbability m_SelProbCalculator = new SelProbStandard();
|
||||
private boolean selectFixedSteps = false;
|
||||
|
||||
public SelectParticleWheel() {
|
||||
}
|
||||
@ -55,22 +56,8 @@ public class SelectParticleWheel implements InterfaceSelection, java.io.Serializ
|
||||
Population result = new Population();
|
||||
result.setPopulationSize(size);
|
||||
|
||||
// use a fixed segment roulette wheel selection
|
||||
double segment = 1./(size+1);
|
||||
double selPoint = RNG.randomDouble(0., segment);
|
||||
|
||||
int selIndex = 0;
|
||||
double selFitSum = ((AbstractEAIndividual)population.getIndividual(selIndex)).getSelectionProbability(0);
|
||||
|
||||
for (int i=0; i < size; i++) {
|
||||
while (selFitSum < selPoint) {
|
||||
selIndex++;
|
||||
selFitSum += ((AbstractEAIndividual)population.getIndividual(selIndex)).getSelectionProbability(0);
|
||||
}
|
||||
result.add(((AbstractEAIndividual)population.get(selIndex)).clone());
|
||||
((AbstractEAIndividual)result.getIndividual(i)).SetAge(0);
|
||||
selPoint += segment;
|
||||
}
|
||||
if (selectFixedSteps ) selectFixed(population, size, result);
|
||||
else selectDrawIndependent(population, size, result);
|
||||
|
||||
//// Unfortunately, this was really problem specific (mk)
|
||||
//
|
||||
@ -96,6 +83,42 @@ public class SelectParticleWheel implements InterfaceSelection, java.io.Serializ
|
||||
return result;
|
||||
}
|
||||
|
||||
private void selectDrawIndependent(Population population, int size,
|
||||
Population result) {
|
||||
double sum=0, selPoint=0;
|
||||
int selIndex;
|
||||
for (int i=0; i < size; i++) {
|
||||
selPoint = RNG.randomDouble();
|
||||
selIndex = 0;
|
||||
sum = ((AbstractEAIndividual)population.getIndividual(0)).getSelectionProbability(0);
|
||||
while (selPoint>=sum) {
|
||||
selIndex++;
|
||||
sum += ((AbstractEAIndividual)population.getIndividual(selIndex)).getSelectionProbability(0);
|
||||
}
|
||||
result.add(((AbstractEAIndividual)population.get(selIndex)).clone());
|
||||
((AbstractEAIndividual)result.getIndividual(i)).SetAge(0);
|
||||
}
|
||||
}
|
||||
|
||||
private void selectFixed(Population population, int size, Population result) {
|
||||
// use a fixed segment roulette wheel selection
|
||||
double segment = 1./(size+1);
|
||||
double selPoint = RNG.randomDouble(0., segment);
|
||||
|
||||
int selIndex = 0;
|
||||
double selFitSum = ((AbstractEAIndividual)population.getIndividual(selIndex)).getSelectionProbability(0);
|
||||
|
||||
for (int i=0; i < size; i++) {
|
||||
while (selFitSum < selPoint) {
|
||||
selIndex++;
|
||||
selFitSum += ((AbstractEAIndividual)population.getIndividual(selIndex)).getSelectionProbability(0);
|
||||
}
|
||||
result.add(((AbstractEAIndividual)population.get(selIndex)).clone());
|
||||
((AbstractEAIndividual)result.getIndividual(i)).SetAge(0);
|
||||
selPoint += segment;
|
||||
}
|
||||
}
|
||||
|
||||
/** This method allows you to select partners for a given Individual
|
||||
* @param dad The already seleceted parent
|
||||
* @param avaiablePartners The mating pool.
|
||||
@ -138,4 +161,41 @@ public class SelectParticleWheel implements InterfaceSelection, java.io.Serializ
|
||||
public String obeyDebsConstViolationPrincipleToolTip() {
|
||||
return "Toggle the use of Deb's coonstraint violation principle(todo).";
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the selectFixedSteps
|
||||
*/
|
||||
public boolean isSelectFixedSteps() {
|
||||
return selectFixedSteps;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param selectFixedSteps the selectFixedSteps to set
|
||||
*/
|
||||
public void setSelectFixedSteps(boolean selectFixedSteps) {
|
||||
this.selectFixedSteps = selectFixedSteps;
|
||||
}
|
||||
|
||||
public String selectFixedStepsTipText() {
|
||||
return "Use fixed segment wheel for selection if marked or independent draws if not.";
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the m_SelProbCalculator
|
||||
*/
|
||||
public InterfaceSelectionProbability getSelProbCalculator() {
|
||||
return m_SelProbCalculator;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param selProbCalculator the m_SelProbCalculator to set
|
||||
*/
|
||||
public void setSelProbCalculator(
|
||||
InterfaceSelectionProbability selProbCalculator) {
|
||||
m_SelProbCalculator = selProbCalculator;
|
||||
}
|
||||
|
||||
public String selProbCalculatorTipText() {
|
||||
return "The method for calculating selection probability from the fitness.";
|
||||
}
|
||||
}
|
@ -12,6 +12,7 @@ import eva2.server.go.operators.postprocess.PostProcess;
|
||||
import eva2.server.go.populations.Population;
|
||||
|
||||
import eva2.server.go.problems.Interface2DBorderProblem;
|
||||
import eva2.tools.EVAERROR;
|
||||
|
||||
public abstract class AbstractMultiModalProblemKnown extends AbstractProblemDouble implements Interface2DBorderProblem, InterfaceMultimodalProblemKnown {
|
||||
protected static InterfaceDistanceMetric m_Metric = new PhenotypeMetric();
|
||||
@ -239,17 +240,26 @@ public abstract class AbstractMultiModalProblemKnown extends AbstractProblemDoub
|
||||
}
|
||||
|
||||
public static double getMaximumPeakRatio(InterfaceMultimodalProblemKnown mmProb, Population pop, double epsilon) {
|
||||
double optimaInvertedSum = 0, foundInvertedSum = 0;
|
||||
Population realOpts = mmProb.getRealOptima();
|
||||
double foundInvertedSum = 0, sumRealMaxima = 0;
|
||||
Population realOpts = mmProb.getRealOptima();
|
||||
double maxOpt = realOpts.getEAIndividual(0).getFitness(0);
|
||||
sumRealMaxima = maxOpt;
|
||||
for (int i=1; i<realOpts.size(); i++) {
|
||||
// search for the maximum fitness (for the maximization problem)
|
||||
// also sum up the fitness values
|
||||
maxOpt = Math.max(maxOpt, realOpts.getEAIndividual(i).getFitness(0));
|
||||
sumRealMaxima += realOpts.getEAIndividual(i).getFitness(0);
|
||||
if (realOpts.getEAIndividual(i).getFitness(0)<0) EVAERROR.errorMsgOnce("Warning: avoid negative maxima in AbstractMultiModalProblemKnown!");
|
||||
}
|
||||
AbstractEAIndividual[] optsFound = PostProcess.getFoundOptimaArray(pop, realOpts, epsilon, true);
|
||||
for (int i=0; i<realOpts.size(); i++) {
|
||||
// sum up known optimal fitness values
|
||||
optimaInvertedSum += realOpts.getEAIndividual(i).getFitness(0);
|
||||
// sum up best found hits, with inverted fitness
|
||||
if (optsFound[i] != null) foundInvertedSum += realOpts.getBestEAIndividual().getFitness(0) - optsFound[i].getFitness(0);
|
||||
// sum up the found optimal fitness values
|
||||
if (optsFound[i] != null) {
|
||||
foundInvertedSum += (maxOpt - optsFound[i].getFitness(0));
|
||||
}
|
||||
}
|
||||
|
||||
return foundInvertedSum/optimaInvertedSum;
|
||||
// System.out.println("foundSum: " + foundInvertedSum + " realsum: " + sumRealMaxima + " ratio: " + foundInvertedSum/sumRealMaxima);
|
||||
return foundInvertedSum/sumRealMaxima;
|
||||
}
|
||||
|
||||
// public double getMaximumPeakRatio(Population pop) {
|
||||
|
@ -1,10 +1,10 @@
|
||||
package eva2.server.go.problems;
|
||||
|
||||
import wsi.ra.math.RNG;
|
||||
import eva2.server.go.individuals.AbstractEAIndividual;
|
||||
import eva2.server.go.individuals.InterfaceDataTypeDouble;
|
||||
import eva2.server.go.populations.Population;
|
||||
import eva2.server.go.strategies.InterfaceOptimizer;
|
||||
import eva2.server.go.problems.Interface2DBorderProblem;
|
||||
|
||||
/**
|
||||
* Created by IntelliJ IDEA.
|
||||
@ -45,7 +45,32 @@ public class F1Problem extends AbstractProblemDouble implements Interface2DBorde
|
||||
public Object clone() {
|
||||
return (Object) new F1Problem(this);
|
||||
}
|
||||
|
||||
|
||||
// @Override
|
||||
// public void initPopulation(Population population) {
|
||||
// AbstractEAIndividual tmpIndy;
|
||||
// population.clear();
|
||||
// initTemplate();
|
||||
//
|
||||
// for (int i = 0; i < population.getPopulationSize(); i++) {
|
||||
// tmpIndy = (AbstractEAIndividual)((AbstractEAIndividual)this.m_Template).clone();
|
||||
// tmpIndy.init(this);
|
||||
// if (tmpIndy instanceof InterfaceDataTypeDouble) {
|
||||
// double[] v = ((InterfaceDataTypeDouble)tmpIndy).getDoubleData();
|
||||
// for (int j=0; j<v.length; j++) {
|
||||
// v[j] = 3; //getDefaultRange() * ((j % 2 == 0) ? 1 : 1);
|
||||
// v[j]+=RNG.gaussianDouble(.2);
|
||||
// }
|
||||
// ((InterfaceDataTypeDouble)tmpIndy).SetDoubleGenotype(v);
|
||||
// }
|
||||
//
|
||||
// population.add(tmpIndy);
|
||||
// }
|
||||
// // population init must be last
|
||||
// // it set's fitcalls and generation to zero
|
||||
// population.init();
|
||||
// }
|
||||
|
||||
/** This method inits the Problem to log multiruns
|
||||
*/
|
||||
public void initProblem() {
|
||||
|
@ -1,9 +1,5 @@
|
||||
package eva2.server.go.problems;
|
||||
|
||||
import eva2.server.go.individuals.AbstractEAIndividual;
|
||||
import eva2.server.go.individuals.ESIndividualDoubleData;
|
||||
import eva2.server.go.individuals.InterfaceDataTypeDouble;
|
||||
import eva2.server.go.populations.Population;
|
||||
|
||||
/**
|
||||
* Created by IntelliJ IDEA.
|
||||
|
@ -316,7 +316,7 @@ public class MatlabProblem extends AbstractProblemDouble implements InterfaceTex
|
||||
if (runnable != null) {
|
||||
runnable.stopOpt();
|
||||
}
|
||||
PostProcess.stopHC();
|
||||
PostProcess.stopPP();
|
||||
}
|
||||
|
||||
public String getInfoString() {
|
||||
|
420
src/eva2/server/go/strategies/NelderMeadSimplex.java
Normal file
420
src/eva2/server/go/strategies/NelderMeadSimplex.java
Normal file
@ -0,0 +1,420 @@
|
||||
package eva2.server.go.strategies;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Vector;
|
||||
|
||||
import eva2.OptimizerFactory;
|
||||
import eva2.OptimizerRunnable;
|
||||
import eva2.gui.BeanInspector;
|
||||
import eva2.server.go.InterfacePopulationChangedEventListener;
|
||||
import eva2.server.go.InterfaceTerminator;
|
||||
import eva2.server.go.individuals.AbstractEAIndividual;
|
||||
import eva2.server.go.individuals.InterfaceDataTypeDouble;
|
||||
import eva2.server.go.populations.InterfaceSolutionSet;
|
||||
import eva2.server.go.populations.Population;
|
||||
import eva2.server.go.populations.SolutionSet;
|
||||
import eva2.server.go.problems.AbstractOptimizationProblem;
|
||||
import eva2.server.go.problems.AbstractProblemDouble;
|
||||
import eva2.server.go.problems.InterfaceOptimizationProblem;
|
||||
import eva2.server.stat.StatsParameter;
|
||||
|
||||
/**
|
||||
* Nelder-Mead-Simplex does not guarantee an equal number of evaluations within each optimize call
|
||||
* because of the different step types.
|
||||
*
|
||||
* @author mkron
|
||||
*
|
||||
*/
|
||||
public class NelderMeadSimplex implements InterfaceOptimizer, Serializable, InterfacePopulationChangedEventListener {
|
||||
|
||||
private int populationSize = 100;
|
||||
// simulating the generational cycle. Set rather small (eg 5) for use as local search, higher for global search (eg 50)
|
||||
private int generationCycle = 50;
|
||||
|
||||
private Population m_Population;
|
||||
private AbstractOptimizationProblem m_Problem;
|
||||
private transient Vector<InterfacePopulationChangedEventListener> m_Listener;
|
||||
private String m_Identifier = "NelderMeadSimplex";
|
||||
|
||||
public NelderMeadSimplex() {
|
||||
setPopulation(new Population(populationSize));
|
||||
}
|
||||
|
||||
public NelderMeadSimplex(NelderMeadSimplex a) {
|
||||
m_Problem = (AbstractOptimizationProblem)a.m_Problem.clone();
|
||||
setPopulation((Population)a.m_Population.clone());
|
||||
populationSize = a.populationSize;
|
||||
generationCycle = a.generationCycle;
|
||||
m_Identifier = a.m_Identifier;
|
||||
}
|
||||
|
||||
public NelderMeadSimplex clone() {
|
||||
return new NelderMeadSimplex(this);
|
||||
}
|
||||
|
||||
|
||||
public void SetIdentifier(String name) {
|
||||
m_Identifier = name;
|
||||
|
||||
}
|
||||
|
||||
public void SetProblem(InterfaceOptimizationProblem problem) {
|
||||
m_Problem = (AbstractOptimizationProblem)problem;
|
||||
}
|
||||
|
||||
public boolean setProblemAndPopSize(InterfaceOptimizationProblem problem) {
|
||||
SetProblem(problem);
|
||||
if (m_Problem instanceof AbstractProblemDouble) {
|
||||
setPopulationSize(((AbstractProblemDouble)problem).getProblemDimension()+1);
|
||||
return true;
|
||||
} else {
|
||||
Object ret=BeanInspector.callIfAvailable(problem, "getProblemDimension", null);
|
||||
if (ret!=null) {
|
||||
setPopulationSize(((Integer)ret)+1);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void addPopulationChangedEventListener(
|
||||
InterfacePopulationChangedEventListener ea) {
|
||||
if (m_Listener == null) m_Listener = new Vector<InterfacePopulationChangedEventListener>();
|
||||
if (!m_Listener.contains(ea)) m_Listener.add(ea);
|
||||
}
|
||||
|
||||
public void freeWilly() {}
|
||||
|
||||
public AbstractEAIndividual simplexStep(Population subpop) {
|
||||
// parameter
|
||||
|
||||
|
||||
// hole die n-1 besten individuen
|
||||
Population bestpop = subpop.getBestNIndividuals(subpop.size()-1);
|
||||
// und das schlechteste
|
||||
AbstractEAIndividual worst = subpop.getWorstEAIndividual();
|
||||
AbstractEAIndividual best=subpop.getBestEAIndividual();
|
||||
double[] u_q = ((InterfaceDataTypeDouble) worst).getDoubleData();
|
||||
int dim = u_q.length;
|
||||
|
||||
// Centroid berechnen
|
||||
double[] g = new double[dim];
|
||||
for (int i=0; i<bestpop.size(); i++) {
|
||||
for (int j=0; j<dim; j++) {
|
||||
AbstractEAIndividual bestIndi= (AbstractEAIndividual) bestpop.getIndividual(i);
|
||||
g[j] +=((InterfaceDataTypeDouble)bestIndi).getDoubleData()[j]/bestpop.size(); // bug?
|
||||
}
|
||||
}
|
||||
|
||||
// Reflection
|
||||
double[] r = new double[dim];
|
||||
for (int i=0; i<dim; i++)
|
||||
r[i] = 2*g[i] - u_q[i];
|
||||
AbstractEAIndividual r_ind = (AbstractEAIndividual)((AbstractEAIndividual)bestpop.getIndividual(1)).clone();
|
||||
((InterfaceDataTypeDouble)r_ind).SetDoubleGenotype(r);
|
||||
|
||||
m_Problem.evaluate(r_ind);
|
||||
this.m_Population.incrFunctionCalls();
|
||||
|
||||
if ((best.getFitness(0)<r_ind.getFitness(0))&(r_ind.getFitness(0) < bestpop.getWorstEAIndividual().getFitness(0))) { // Problem: Fitnesswert ist vektor
|
||||
|
||||
return r_ind;
|
||||
} else if (best.getFitness(0)>r_ind.getFitness(0)){ //neues besser als bisher bestes => Expansion
|
||||
|
||||
double[] e = new double[dim];
|
||||
for (int i=0; i<dim; i++) e[i] = 3*g[i] - 2*u_q[i];
|
||||
AbstractEAIndividual e_ind = (AbstractEAIndividual)((AbstractEAIndividual)bestpop.getIndividual(1)).clone();
|
||||
((InterfaceDataTypeDouble)e_ind).SetDoubleGenotype(e);
|
||||
m_Problem.evaluate(e_ind);
|
||||
this.m_Population.incrFunctionCalls();
|
||||
if(e_ind.getFitness(0)<r_ind.getFitness(0)){//expandiertes ist besser als reflektiertes
|
||||
return e_ind;
|
||||
} else {
|
||||
return r_ind;
|
||||
}
|
||||
|
||||
} else if(r_ind.getFitness(0) >= bestpop.getWorstEAIndividual().getFitness(0)){//kontrahiere da neues indi keine verbesserung brachte
|
||||
double[] c = new double[dim];
|
||||
for (int i=0; i<dim; i++) c[i] = 0.5*g[i] + 0.5*u_q[i];
|
||||
AbstractEAIndividual c_ind = (AbstractEAIndividual)((AbstractEAIndividual)bestpop.getIndividual(1)).clone();
|
||||
((InterfaceDataTypeDouble)c_ind).SetDoubleGenotype(c);
|
||||
m_Problem.evaluate(c_ind);
|
||||
this.m_Population.incrFunctionCalls();
|
||||
if(c_ind.getFitness(0)<=worst.getFitness(0)){
|
||||
return c_ind;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getIdentifier() {
|
||||
return m_Identifier;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return "NelderMeadSimplex";
|
||||
}
|
||||
|
||||
public String globalInfo() {
|
||||
return m_Identifier;
|
||||
}
|
||||
|
||||
public Population getPopulation() {
|
||||
return m_Population;
|
||||
}
|
||||
|
||||
public InterfaceOptimizationProblem getProblem() {
|
||||
return m_Problem;
|
||||
}
|
||||
|
||||
public String getStringRepresentation() {
|
||||
StringBuilder strB = new StringBuilder(200);
|
||||
strB.append("Nelder-Mead-Simplex Strategy:\nOptimization Problem: ");
|
||||
strB.append(this.m_Problem.getStringRepresentationForProblem(this));
|
||||
strB.append("\n");
|
||||
strB.append(this.m_Population.getStringRepresentation());
|
||||
return strB.toString();
|
||||
}
|
||||
|
||||
public void init() {
|
||||
initByPopulation(m_Population, true);
|
||||
}
|
||||
|
||||
public void initByPopulation(Population pop, boolean reset) {
|
||||
setPopulation(pop);
|
||||
if (reset) {
|
||||
m_Problem.initPopulation(m_Population);
|
||||
m_Problem.evaluate(m_Population);
|
||||
}
|
||||
// fireNextGenerationPerformed();
|
||||
}
|
||||
|
||||
private void fireNextGenerationPerformed() {
|
||||
if (m_Listener != null) {
|
||||
for (int i=0; i<m_Listener.size(); i++)
|
||||
m_Listener.elementAt(i).registerPopulationStateChanged(this, Population.nextGenerationPerformed);
|
||||
}
|
||||
}
|
||||
|
||||
public void optimize() {
|
||||
// make at least as many calls as there are individuals within the population.
|
||||
// this simulates the generational loop expected by some other modules
|
||||
int evalCntStart = m_Population.getFunctionCalls();
|
||||
int evalsDone = 0;
|
||||
m_Problem.evaluatePopulationStart(m_Population);
|
||||
do {
|
||||
AbstractEAIndividual ind = simplexStep(m_Population);
|
||||
if(ind!=null){ //Verbesserung gefunden
|
||||
m_Population.set(m_Population.getIndexOfWorstIndividual(), ind);
|
||||
}else{//keine Verbesserung gefunden shrink!!
|
||||
|
||||
double[] u_1 = ((InterfaceDataTypeDouble) m_Population.getBestEAIndividual()).getDoubleData();
|
||||
|
||||
for(int j=0;j<m_Population.size();j++){
|
||||
double [] c= ((InterfaceDataTypeDouble) m_Population.getEAIndividual(j)).getDoubleData();
|
||||
for (int i=0; i<c.length; i++) c[i] = 0.5*c[i] + 0.5*u_1[i];
|
||||
((InterfaceDataTypeDouble) m_Population.getEAIndividual(j)).SetDoubleGenotype(c);
|
||||
}
|
||||
m_Problem.evaluate(m_Population);
|
||||
}
|
||||
evalsDone = m_Population.getFunctionCalls() - evalCntStart;
|
||||
} while (evalsDone < generationCycle);
|
||||
m_Problem.evaluatePopulationEnd(m_Population);
|
||||
}
|
||||
|
||||
public void setPopulation(Population pop) {
|
||||
m_Population = pop;
|
||||
m_Population.addPopulationChangedEventListener(this);
|
||||
m_Population.setNotifyEvalInterval(populationSize);
|
||||
}
|
||||
|
||||
public InterfaceSolutionSet getAllSolutions() {
|
||||
Population pop = getPopulation();
|
||||
return new SolutionSet(pop, pop);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the populationSize
|
||||
*/
|
||||
public int getPopulationSize() {
|
||||
return populationSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param populationSize the populationSize to set
|
||||
*/
|
||||
public void setPopulationSize(int populationSize) {
|
||||
this.populationSize = populationSize;
|
||||
if (m_Population!=null) {
|
||||
m_Population.setPopulationSize(populationSize);
|
||||
m_Population.setNotifyEvalInterval(m_Population.getPopulationSize());
|
||||
}
|
||||
}
|
||||
|
||||
public String populationSizeTipText() {
|
||||
return "The population size should be adapted to the dimensions of the problem (e.g. n+1)";
|
||||
}
|
||||
|
||||
public void registerPopulationStateChanged(Object source, String name) {
|
||||
if (name.compareTo(Population.funCallIntervalReached) == 0) {
|
||||
fireNextGenerationPerformed();
|
||||
}// else System.err.println("unknown event!");
|
||||
}
|
||||
|
||||
/**
|
||||
* This method creates a Nelder-Mead instance.
|
||||
*
|
||||
* @param pop
|
||||
* The size of the population
|
||||
* @param problem
|
||||
* The problem to be optimized
|
||||
* @param listener
|
||||
* @return An optimization procedure that performs nelder mead optimization.
|
||||
*/
|
||||
public static final NelderMeadSimplex createNelderMeadSimplex(AbstractOptimizationProblem problem,
|
||||
InterfacePopulationChangedEventListener listener) {
|
||||
|
||||
problem.initProblem();
|
||||
NelderMeadSimplex nms = new NelderMeadSimplex();
|
||||
nms.setProblemAndPopSize(problem);
|
||||
|
||||
nms.addPopulationChangedEventListener(listener);
|
||||
nms.init();
|
||||
|
||||
if (listener!=null) listener.registerPopulationStateChanged(nms.getPopulation(), "");
|
||||
|
||||
return nms;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method creates a Nelder-Mead instance with an initial population
|
||||
* around a given candidate solution. The population is created as a simplex with given
|
||||
* perturbation ratio or randomly across the search range if the perturbation ratio is
|
||||
* zero or below zero.
|
||||
*
|
||||
*
|
||||
* @param problem
|
||||
* The problem to be optimized
|
||||
* @param candidate starting point of the search
|
||||
* @param perturbationRatio perturbation ratio relative to the problem range for the initial simplex creation
|
||||
* @param listener
|
||||
* @return An optimization procedure that performs nelder mead optimization.
|
||||
*/
|
||||
public static final NelderMeadSimplex createNelderMeadSimplexLocal(AbstractOptimizationProblem problem,
|
||||
AbstractEAIndividual candidate, double perturbationRatio,
|
||||
InterfacePopulationChangedEventListener listener) {
|
||||
|
||||
// TODO this method might be superfluous when using PostProcess
|
||||
problem.initProblem();
|
||||
NelderMeadSimplex nms = new NelderMeadSimplex();
|
||||
nms.setProblemAndPopSize(problem);
|
||||
|
||||
Population initialPop;
|
||||
if (perturbationRatio <= 0) { // random case
|
||||
initialPop = new Population(nms.getPopulationSize());
|
||||
problem.initPopulation(initialPop);
|
||||
initialPop.set(0, candidate);
|
||||
} else {
|
||||
double[][] range = ((InterfaceDataTypeDouble)candidate).getDoubleRange();
|
||||
if (range.length != nms.getPopulationSize()-1) System.err.println("Unexpected population size for nelder mead!");
|
||||
initialPop = createNMSPopulation(candidate, perturbationRatio, range, true);
|
||||
}
|
||||
if (listener != null) nms.addPopulationChangedEventListener(listener);
|
||||
nms.initByPopulation(initialPop, false);
|
||||
//nms.setPopulation(initialPop);
|
||||
|
||||
return nms;
|
||||
}
|
||||
|
||||
/**
|
||||
* From a given candidate solution, create n solutions around the candidate, where every i-th
|
||||
* new candidate differs in i dimensions by a distance of perturbRatio relative to the range in
|
||||
* that dimension (respecting the range).
|
||||
* The new solutions are returned as a population, which, if includeCand is true,
|
||||
* also contains the initial candidate. However, the new candidates have not been evaluated.
|
||||
*
|
||||
* @param candidate
|
||||
* @param perturbRatio
|
||||
* @param range
|
||||
* @param includeCand
|
||||
* @return
|
||||
*/
|
||||
public static Population createNMSPopulation(AbstractEAIndividual candidate, double perturbRatio, double[][] range, boolean includeCand) {
|
||||
Population initPop = new Population();
|
||||
if (includeCand) initPop.add(candidate);
|
||||
addPerturbedPopulation(perturbRatio, initPop, range, candidate);
|
||||
return initPop;
|
||||
}
|
||||
|
||||
private static void addPerturbedPopulation(double perturbationRatio,
|
||||
Population initialPop, double[][] range, AbstractEAIndividual candidate) {
|
||||
AbstractEAIndividual indy = (AbstractEAIndividual)candidate.clone();
|
||||
// span by perturbation, every new individual i is modified in dimension i by
|
||||
// a value of perturbRatio*range_i such that a simplex of relative side length perturbRatio is created.
|
||||
for (int i=0; i<range.length; i+=1) {
|
||||
double curPerturb = ((range[i][1]-range[i][0])*perturbationRatio);
|
||||
double[] dat = ((InterfaceDataTypeDouble)indy).getDoubleData();
|
||||
if (dat[i]==range[i][1]) { // in this case the bound is said to be too close
|
||||
dat[i]=Math.max(dat[i]-curPerturb, range[i][0]);
|
||||
} else dat[i] = Math.min(dat[i]+curPerturb, range[i][1]);
|
||||
((InterfaceDataTypeDouble)indy).SetDoubleGenotype(dat);
|
||||
initialPop.add((AbstractEAIndividual)indy.clone());
|
||||
}
|
||||
initialPop.setPopulationSize(initialPop.size());
|
||||
}
|
||||
|
||||
// /**
|
||||
// * Search for a local optimizer using nelder mead and return the solution found and the number of steps
|
||||
// * (evaluations) actually performed.
|
||||
// *
|
||||
// * @param candidate
|
||||
// * @param problem
|
||||
// * @param term
|
||||
// * @param perturbationRatio
|
||||
// * @return
|
||||
// */
|
||||
// public static int processWithNMS(Population candidates, AbstractOptimizationProblem problem, InterfaceTerminator term, double perturbationRatio) {
|
||||
// NelderMeadSimplex nms = new NelderMeadSimplex();
|
||||
// nms.setProblemAndPopSize(problem);
|
||||
// nms.setGenerationCycle(5);
|
||||
// nms.initByPopulation(candidates, false);
|
||||
// int funCallsBefore = candidates.getFunctionCalls();
|
||||
// candidates.SetFunctionCalls(0);
|
||||
//
|
||||
// OptimizerRunnable hcRunnable = new OptimizerRunnable(OptimizerFactory.makeParams(nms, candidates, problem, 0, term), true);
|
||||
// // as nms creates a new population and has already evaluated them, send a signal to stats
|
||||
// hcRunnable.getStats().createNextGenerationPerformed(nms.getPopulation(), null);
|
||||
// hcRunnable.getGOParams().setDoPostProcessing(false);
|
||||
// hcRunnable.setVerbosityLevel(StatsParameter.VERBOSITY_NONE);
|
||||
// hcRunnable.run();
|
||||
// hcRunnable.getGOParams().setDoPostProcessing(true);
|
||||
// hcRunnable = null;
|
||||
// int funCallsDone = candidates.getFunctionCalls();
|
||||
// candidates.SetFunctionCalls(funCallsBefore+funCallsDone);
|
||||
//
|
||||
// return funCallsDone;
|
||||
// }
|
||||
|
||||
// /**
|
||||
// * @return the generationCycle
|
||||
// */
|
||||
// public int getGenerationCycle() {
|
||||
// return generationCycle;
|
||||
// }
|
||||
|
||||
/**
|
||||
* @param generationCycle the generationCycle to set
|
||||
*/
|
||||
public void setGenerationCycle(int generationCycle) {
|
||||
this.generationCycle = generationCycle;
|
||||
}
|
||||
|
||||
//
|
||||
// public static final GOParameters standardNMS(AbstractOptimizationProblem problem) {
|
||||
// NelderMeadSimplex nms = NelderMeadSimplex.createNelderMeadSimplex(problem, null);
|
||||
// Population pop = new Population();
|
||||
// pop.setPopulationSize(nms.getPopulationSize());
|
||||
//
|
||||
// return makeParams(nms, pop, problem, randSeed, defaultTerminator());
|
||||
// }
|
||||
}
|
@ -12,6 +12,7 @@ import eva2.server.go.operators.selection.SelectParticleWheel;
|
||||
import eva2.server.go.populations.InterfaceSolutionSet;
|
||||
import eva2.server.go.populations.Population;
|
||||
import eva2.server.go.populations.SolutionSet;
|
||||
import eva2.server.go.problems.AbstractOptimizationProblem;
|
||||
import eva2.server.go.problems.F1Problem;
|
||||
import eva2.server.go.problems.InterfaceOptimizationProblem;
|
||||
|
||||
@ -70,13 +71,15 @@ public class ParticleFilterOptimization implements InterfaceOptimizer, java.io.S
|
||||
|
||||
public void init() {
|
||||
this.m_Problem.initPopulation(this.m_Population);
|
||||
//System.out.println("popsize is " + m_Population.size());
|
||||
//System.out.println("pops targ is " + m_Population.getPopulationSize());
|
||||
for (int i=0; i<m_Population.size(); i++) {
|
||||
((AbstractEAIndividual)m_Population.getIndividual(i)).setMutationOperator(new MutateESFixedStepSize(mutationSigma));
|
||||
}
|
||||
|
||||
setWithShow(withShow);
|
||||
this.evaluatePopulation(this.m_Population);
|
||||
this.firePropertyChangedEvent("NextGenerationPerformed");
|
||||
this.firePropertyChangedEvent(Population.nextGenerationPerformed);
|
||||
}
|
||||
|
||||
/** This method will init the optimizer with a given population
|
||||
@ -88,7 +91,7 @@ public class ParticleFilterOptimization implements InterfaceOptimizer, java.io.S
|
||||
if (reset) {
|
||||
this.m_Population.init();
|
||||
this.evaluatePopulation(this.m_Population);
|
||||
this.firePropertyChangedEvent("NextGenerationPerformed");
|
||||
this.firePropertyChangedEvent(Population.nextGenerationPerformed);
|
||||
}
|
||||
}
|
||||
|
||||
@ -117,35 +120,41 @@ public class ParticleFilterOptimization implements InterfaceOptimizer, java.io.S
|
||||
parents.SetFunctionCalls(pop.getFunctionCalls());
|
||||
parents.setGenerationTo(pop.getGeneration());
|
||||
|
||||
if (withShow) drawPop(parents, 3, true);
|
||||
return parents;
|
||||
}
|
||||
|
||||
protected void predict(Population pop) {
|
||||
indCount = 0;
|
||||
if (withShow) {
|
||||
drawPop(pop, 0, false);
|
||||
}
|
||||
for (int i = 0; i < pop.getPopulationSize(); i++) {
|
||||
applyMotionModel((AbstractEAIndividual)((AbstractEAIndividual)pop.get(i)), 0.);
|
||||
indCount++;
|
||||
}
|
||||
if (withShow) drawPop(pop, 1, false);
|
||||
}
|
||||
|
||||
protected void applyMotionModel(AbstractEAIndividual indy, double noise) {
|
||||
private void drawPop(Population pop, int graphLabel, boolean useCircles) {
|
||||
if (myPlot != null) {
|
||||
if (graphLabel < 0) graphLabel = indCount;
|
||||
for (int i=0; i<pop.size(); i++) {
|
||||
InterfaceDataTypeDouble endy = (InterfaceDataTypeDouble) pop.getEAIndividual(i);
|
||||
double[] curPosition = endy.getDoubleData();
|
||||
|
||||
if (useCircles) myPlot.getFunctionArea().drawCircle("", curPosition, graphLabel);
|
||||
else myPlot.setUnconnectedPoint(curPosition[0], curPosition[1], graphLabel);
|
||||
// myPlot.setConnectedPoint(curPosition[0], curPosition[1], graphLabel);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void applyMotionModel(AbstractEAIndividual indy, double noise) {
|
||||
// this currently only performs a mutation
|
||||
indy.mutate();
|
||||
indy.SetFitness(0, 0);
|
||||
|
||||
if (this.withShow) {
|
||||
InterfaceDataTypeDouble endy = (InterfaceDataTypeDouble) indy;
|
||||
double[] curPosition = endy.getDoubleData();
|
||||
|
||||
myPlot.setUnconnectedPoint(curPosition[0], curPosition[1], indCount);
|
||||
myPlot.setConnectedPoint(curPosition[0], curPosition[1], indCount);
|
||||
|
||||
// this.m_Plot.setConnectedPoint(curPosition[0], curPosition[1], index+1);
|
||||
// this.m_Plot.setConnectedPoint(localBestPosition[0], localBestPosition[1], index+1);
|
||||
// this.m_Plot.setConnectedPoint(curPosition[0], curPosition[1], index+1);
|
||||
// this.m_Plot.setConnectedPoint(bestPosition[0], bestPosition[1], index+1);
|
||||
// this.m_Plot.setUnconnectedPoint(curPosition[0], curPosition[1], 100*index+1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -159,6 +168,9 @@ public class ParticleFilterOptimization implements InterfaceOptimizer, java.io.S
|
||||
// resample using selection
|
||||
nextGeneration = resample(m_Population);
|
||||
|
||||
if (sleepTime > 0 ) try { Thread.sleep(sleepTime); } catch(Exception e) {}
|
||||
if (withShow) clearPlot();
|
||||
|
||||
// predict step
|
||||
predict(nextGeneration);
|
||||
|
||||
@ -166,9 +178,8 @@ public class ParticleFilterOptimization implements InterfaceOptimizer, java.io.S
|
||||
|
||||
// collectStatistics(m_Population);
|
||||
|
||||
this.firePropertyChangedEvent("NextGenerationPerformed");
|
||||
this.firePropertyChangedEvent(Population.nextGenerationPerformed);
|
||||
|
||||
if (sleepTime > 0 ) try { Thread.sleep(sleepTime); } catch(Exception e) {}
|
||||
}
|
||||
|
||||
// protected void collectStatistics(Population population) {
|
||||
@ -194,6 +205,9 @@ public class ParticleFilterOptimization implements InterfaceOptimizer, java.io.S
|
||||
*/
|
||||
public void SetProblem (InterfaceOptimizationProblem problem) {
|
||||
this.m_Problem = problem;
|
||||
if (problem instanceof AbstractOptimizationProblem) {
|
||||
((AbstractOptimizationProblem)problem).informAboutOptimizer(this);
|
||||
}
|
||||
}
|
||||
public InterfaceOptimizationProblem getProblem () {
|
||||
return this.m_Problem;
|
||||
@ -252,6 +266,7 @@ public class ParticleFilterOptimization implements InterfaceOptimizer, java.io.S
|
||||
return this.m_Population;
|
||||
}
|
||||
public void setPopulation(Population pop){
|
||||
// if (pop.size()!=pop.getPopulationSize()) pop.fitToSize();
|
||||
this.m_Population = pop;
|
||||
}
|
||||
public String populationTipText() {
|
||||
@ -281,6 +296,17 @@ public class ParticleFilterOptimization implements InterfaceOptimizer, java.io.S
|
||||
return withShow;
|
||||
}
|
||||
|
||||
protected void clearPlot() {
|
||||
if (myPlot!=null) {
|
||||
myPlot.clearAll();
|
||||
double[][] range = null;
|
||||
if ((m_Population != null) && (m_Population.size() > 0)) range = ((InterfaceDataTypeDouble)this.m_Population.get(0)).getDoubleRange();
|
||||
if (range != null) {
|
||||
myPlot.setCornerPoints(range, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param withShow the withShow to set
|
||||
**/
|
||||
@ -297,7 +323,7 @@ public class ParticleFilterOptimization implements InterfaceOptimizer, java.io.S
|
||||
range[0][1] = 0;
|
||||
range[1] = range[0]; // this is evil
|
||||
}
|
||||
myPlot = new eva2.gui.Plot("PF", "x1", "x2", true);
|
||||
myPlot = new eva2.gui.Plot("PF", "x1", "x2", range[0], range[1]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -406,7 +406,7 @@ public class ParticleSwarmOptimization implements InterfaceOptimizer, java.io.Se
|
||||
initIndividualDefaults(indy);
|
||||
}
|
||||
indy.putData(indexKey, i);
|
||||
indy.setIndividualIndex(i);
|
||||
indy.SetIndividualIndex(i);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1435,7 +1435,7 @@ public class ParticleSwarmOptimization implements InterfaceOptimizer, java.io.Se
|
||||
initIndividualDefaults(indy);
|
||||
initIndividualMemory(indy);
|
||||
indy.putData(indexKey, i);
|
||||
indy.setIndividualIndex(i);
|
||||
indy.SetIndividualIndex(i);
|
||||
if (TRACE) System.err.println("init indy " + i + " " + AbstractEAIndividual.getDefaultDataString(indy));
|
||||
}
|
||||
}
|
||||
|
@ -51,7 +51,7 @@ public class GOParameters extends AbstractGOParameters implements InterfaceGOPar
|
||||
*/
|
||||
public GOParameters() {
|
||||
super(new GeneticAlgorithm(), new F1Problem(), new EvaluationTerminator(1000));
|
||||
((F1Problem)m_Problem).setEAIndividual(new GAIndividualDoubleData());
|
||||
// ((F1Problem)m_Problem).setEAIndividual(new GAIndividualDoubleData());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -688,6 +688,20 @@ public class Mathematics {
|
||||
return minVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the given vector lies within the range in every dimension.
|
||||
*
|
||||
* @param x
|
||||
* @param range
|
||||
* @return true if the vector lies within the range, else false
|
||||
*/
|
||||
public static boolean isInRange(double[] x, double[][] range) {
|
||||
for (int i=0; i<x.length; i++) {
|
||||
if (x[i]<range[i][0] || (x[i]>range[i][1])) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Project the values in x to the range given. The range must be an vector of 2d-arrays
|
||||
* each of which containing lower and upper bound in the i-th dimension.
|
||||
|
Loading…
x
Reference in New Issue
Block a user