Merging mk branch rev 205, added post-processing methods (nelder-mead, cma-es); some cosmetics.

This commit is contained in:
Marcel Kronfeld 2008-09-16 13:11:48 +00:00
parent 211c7a4477
commit 676fbb8498
21 changed files with 1215 additions and 184 deletions

View File

@ -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.

View File

@ -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,

View File

@ -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);

View File

@ -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);
}
/**
*
*/

View File

@ -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());
}
}
}

View File

@ -0,0 +1,5 @@
package eva2.server.go.enums;
public enum PostProcessMethod {
hillClimber, nelderMead, cmaES;
}

View File

@ -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;
}

View File

@ -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

View File

@ -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();
}

View File

@ -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.;
}
}

View File

@ -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;
}
}

View File

@ -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.";
}
}

View File

@ -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) {

View File

@ -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() {

View File

@ -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.

View File

@ -316,7 +316,7 @@ public class MatlabProblem extends AbstractProblemDouble implements InterfaceTex
if (runnable != null) {
runnable.stopOpt();
}
PostProcess.stopHC();
PostProcess.stopPP();
}
public String getInfoString() {

View 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());
// }
}

View File

@ -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]);
}
}

View File

@ -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));
}
}

View File

@ -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());
}
/**

View File

@ -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.