Commit of mk branch revs. 499:507, 494:496. Major revision of statistics class - all statistical informations are now pipelined in a clean way. Any additional information provided by InterfaceAdditionalPopulationInformer from an optimizer or problem class can be plotted in analogy to data collected internally within the statistics class.

This commit is contained in:
Marcel Kronfeld 2010-04-09 14:12:16 +00:00
parent 860b4cae15
commit 8fe9ab2648
31 changed files with 1878 additions and 759 deletions

View File

@ -38,6 +38,8 @@ public class OptimizerRunnable implements Runnable {
private boolean postProcessOnly = false;
private InterfaceTextListener listener = null;
private String ident="OptimizerRunnable";
private static int cntID = 0;
private int rnblID = -1;
/**
* Construct an OptimizerRunnable with given parameters and a StatisticsStandalone instance without restart,
@ -83,6 +85,8 @@ public class OptimizerRunnable implements Runnable {
* @param restart
*/
public OptimizerRunnable(GOParameters params, InterfaceStatistics stats, boolean restart) {
rnblID = cntID;
cntID++;
proc = new Processor(stats, null, params);
if (proc.getStatistics() instanceof AbstractStatistics) ((AbstractStatistics)proc.getStatistics()).setSaveParams(false);
doRestart = restart;
@ -96,6 +100,14 @@ public class OptimizerRunnable implements Runnable {
return ident;
}
/**
* A unique ID for the runnable.
* @return
*/
public int getID() {
return rnblID;
}
public InterfaceGOParameters getGOParams() {
return proc.getGOParams();
}
@ -156,6 +168,10 @@ public class OptimizerRunnable implements Runnable {
return isFinished;
}
public boolean wasAborted() {
return (proc!=null && (proc.wasAborted()));
}
public void restartOpt() {
proc.restartOpt();
}
@ -243,12 +259,12 @@ public class OptimizerRunnable implements Runnable {
}
/**
* Set the additional info output.
* Indicate whether full stats should be printed as text (or only selected entries).
* @see StatsParameter
* @param addInfo
*/
public void setOutputAdditionalInfo(boolean addInfo) {
((AbstractStatistics)proc.getStatistics()).getStatisticsParameter().setOutputAdditionalInfo(addInfo);
public void setOutputFullStatsToText(boolean addInfo) {
((AbstractStatistics)proc.getStatistics()).getStatisticsParameter().setOutputAllFieldsAsText(addInfo);
}
// public void configureStats(int verbosityLevel, int outputDirection, int multiRuns, boolean additionalInfo) {

View File

@ -17,14 +17,20 @@ import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
import eva2.server.go.InterfaceNotifyOnInformers;
import eva2.server.go.problems.InterfaceAdditionalPopulationInformer;
/**
* Produces the main EvA2 frame and a tool bar instance.
* TODO This class should be removed alltogether.
*/
public class EvATabbedFrameMaker implements Serializable, PanelMaker {
public class EvATabbedFrameMaker implements Serializable, PanelMaker, InterfaceNotifyOnInformers {
private static final long serialVersionUID = 2637376545826821423L;
private ArrayList<PanelMaker> guiContainer;
private JExtToolBar m_BarStandard;
EvAModuleButtonPanelMaker butPanelMkr=null;
@ -42,7 +48,24 @@ public class EvATabbedFrameMaker implements Serializable, PanelMaker {
gbconst.weighty = 1;
gbconst.gridwidth = GridBagConstraints.REMAINDER;
JTabbedPane m_MainPanel = new JTabbedPane();
final JTabbedPane m_MainPanel = new JTabbedPane();
// m_MainPanel.addChangeListener(new ChangeListener() {
// /*
// * This listener was added to catch the switch to the statistics panel. In that event,
// * the stats selection string may have to be updated.
// */
// public void stateChanged(ChangeEvent e) {
//// System.out.println("AAAA " + e.toString());
// if (m_MainPanel.getSelectedIndex()==1) {
// // the statistics panel is being activated!
//// System.out.println(guiContainer);
// // the third object should be the statistics panel, refer to GenericModuleAdapter
// JParaPanel statsPan = (JParaPanel) guiContainer.get(2);
//// System.out.println(statsPan.m_LocalParameter);
//// statsPan.m_Editor.setValue(statsPan.m_Editor.getValue()); // really update the contents of the stats panel --
// this is now done in a cleaner way using this class as a listener from AbstractGOParameters
// }
// }});
m_BarStandard = new JExtToolBar();
m_BarStandard.setFloatable(false);
@ -73,4 +96,20 @@ public class EvATabbedFrameMaker implements Serializable, PanelMaker {
butPanelMkr.onUserStart();
} else System.err.println("Error: button panel was null (EvATabbedFrameMaker)");
}
public void setInformers(
List<InterfaceAdditionalPopulationInformer> informers) {
// if the informers have changed, update the GUI element which displays them
try {
JParaPanel statsPan = (JParaPanel) guiContainer.get(2);
if (statsPan.m_Editor!=null) {
statsPan.m_Editor.setValue(statsPan.m_Editor.getValue()); // really update the contents of the stats panel
// System.out.println("OOO setting informers to stats panel succeeded!");
}
} catch(Exception e) {
System.err.println("Failed to update statistics panel from " + this.getClass());
System.err.println(e.getMessage());
e.printStackTrace(System.err);
}
}
}

View File

@ -26,6 +26,7 @@ import javax.swing.JTabbedPane;
import javax.swing.SwingUtilities;
import eva2.client.EvAClient;
import eva2.gui.BeanInspector;
import eva2.gui.JParaPanel;
import eva2.server.go.individuals.AbstractEAIndividual;
import eva2.server.go.individuals.ESIndividualDoubleData;
@ -410,7 +411,7 @@ public class GOStandaloneVersion implements InterfaceGOStandalone, InterfacePopu
if (Thread.interrupted())
throw new InterruptedException();
// write header to file
this.writeToFile(" FitnessCalls\t Best\t Mean\t Worst \t" + this.m_GO.getProblem().getAdditionalFileStringHeader(this.m_GO.getOptimizer().getPopulation()));
this.writeToFile(" FitnessCalls\t Best\t Mean\t Worst \t" + BeanInspector.toString(this.m_GO.getProblem().getAdditionalFileStringHeader(this.m_GO.getOptimizer().getPopulation()), '\t', false));
if ((this.m_ContinueFlag) && (this.m_Backup != null)) {
this.m_RecentFC += this.m_Backup.getFunctionCalls();
this.m_GO.getOptimizer().getProblem().initProblem();

View File

@ -1,7 +1,7 @@
package eva2.server.go;
import eva2.gui.GenericObjectEditor;
import eva2.server.go.operators.postprocess.InterfacePostProcessParams;
import eva2.server.go.problems.InterfaceAdditionalPopulationInformer;
import eva2.server.go.problems.InterfaceOptimizationProblem;
import eva2.server.go.strategies.InterfaceOptimizer;
@ -69,15 +69,13 @@ public interface InterfaceGOParameters {
public void setPostProcessParams(InterfacePostProcessParams ppp);
public String postProcessParamsTipText();
public void setDoPostProcessing(boolean doPP);
// public int getPostProcessSteps();
// public void setPostProcessSteps(int ppSteps);
// public String postProcessStepsTipText();
//
// public boolean isPostProcess();
// public void setPostProcess(boolean postProcess);
// public String postProcessTipText();
//
// public double getPostProcessClusterSigma();
// public void setPostProcessClusterSigma(double postProcessClusterSigma);
// public String postProcessClusterSigmaTipText();
/**
* Give an instance which should be informed about elements which are additional informers.
*
* @see InterfaceAdditionalPopulationInformer
* @param o
*/
public void addInformableInstance(InterfaceNotifyOnInformers o);
public boolean removeInformableInstance(InterfaceNotifyOnInformers o);
}

View File

@ -0,0 +1,12 @@
package eva2.server.go;
import java.util.List;
import eva2.server.go.problems.InterfaceAdditionalPopulationInformer;
public interface InterfaceNotifyOnInformers {
/**
* Notify the object about informer instances.
*/
public void setInformers(List<InterfaceAdditionalPopulationInformer> informers);
}

View File

@ -3,6 +3,7 @@ package eva2.server.go.operators.postprocess;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Vector;
import eva2.OptimizerFactory;
import eva2.OptimizerRunnable;
@ -34,7 +35,6 @@ 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.InterfaceFirstOrderDerivableProblem;
import eva2.server.go.problems.InterfaceInterestingHistogram;
import eva2.server.go.problems.InterfaceMultimodalProblemKnown;
import eva2.server.go.strategies.EvolutionStrategies;
@ -63,7 +63,7 @@ public class PostProcess {
// 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 ppRunnable = null;
private static Vector<OptimizerRunnable> ppRunnables = new Vector<OptimizerRunnable>();
public static final String movedDistanceKey = "PostProcessingMovedBy";
public static final String movedToPositionKey = "PostProcessingMovedTo";
@ -401,9 +401,10 @@ public class PostProcess {
}
hc.setPopulation(pop);
// hc.initByPopulation(pop, false);
ppRunnable = new OptimizerRunnable(OptimizerFactory.makeParams(hc, pop, problem, 0, term), true);
OptimizerRunnable ppRunnable = new OptimizerRunnable(OptimizerFactory.makeParams(hc, pop, problem, 0, term), true);
runPP(ppRunnable);
runPP();
}
// TODO ! test this
@ -419,8 +420,9 @@ public class PostProcess {
int funCallsBefore = pop.getFunctionCalls();
pop.SetFunctionCalls(baseEvals);
ppRunnable = new OptimizerRunnable(OptimizerFactory.makeParams(gda, pop, problem, 0, term), true);
ppRunnable.getStats().createNextGenerationPerformed(gda.getPopulation(), gda, null);
OptimizerRunnable ppRunnable = new OptimizerRunnable(OptimizerFactory.makeParams(gda, pop, problem, 0, term), true);
runPP(ppRunnable);
// ppRunnable.getStats().createNextGenerationPerformed(gda.getPopulation(), gda, null);
int funCallsDone = pop.getFunctionCalls()-baseEvals;
pop.SetFunctionCalls(funCallsBefore);
@ -432,7 +434,8 @@ public class PostProcess {
* 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.
* Returns the number of function calls really performed by the method; sets the number of function calls
* Returns the number of function calls really performed by the method and a flag indicating whether the
* processing was aborted by the user. Sets the number of function calls
* in the population back to the original count.
* If the baseEvals parameter (which should be >= 0) is > 0, then the number of evaluations is set as
* number of evaluations before the optimization using the given terminator.
@ -441,9 +444,9 @@ public class PostProcess {
* @param problem
* @param term
* @param baseEvals
* @return
* @return pair of the number of performed function calls and a flag indicating whether the processing was aborted by the user
*/
public static int processWithNMS(Population pop, AbstractOptimizationProblem problem, InterfaceTerminator term, int baseEvals) {
public static Pair<Integer,Boolean> processWithNMS(Population pop, AbstractOptimizationProblem problem, InterfaceTerminator term, int baseEvals) {
NelderMeadSimplex nms = new NelderMeadSimplex();
nms.setProblemAndPopSize(problem);
nms.setGenerationCycle(5);
@ -451,7 +454,7 @@ public class PostProcess {
int funCallsBefore = pop.getFunctionCalls();
pop.SetFunctionCalls(baseEvals);
ppRunnable = new OptimizerRunnable(OptimizerFactory.makeParams(nms, pop, problem, 0, term), true);
OptimizerRunnable 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(), nms, null);
@ -460,7 +463,7 @@ public class PostProcess {
// System.out.println("grads: " + BeanInspector.toString(((InterfaceFirstOrderDerivableProblem)problem).getFirstOrderGradients(x)));
// }
runPP();
runPP(ppRunnable);
// if (problem instanceof InterfaceFirstOrderDerivableProblem) {
// double[] x = pop.getBestEAIndividual().getDoublePosition();
@ -470,14 +473,15 @@ public class PostProcess {
int funCallsDone = pop.getFunctionCalls()-baseEvals;
pop.SetFunctionCalls(funCallsBefore);
return funCallsDone;
return new Pair<Integer, Boolean>(funCallsDone, ppRunnable.wasAborted());
}
/**
* Search for a local minimum using CMA 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.
* Returns the number of function calls really performed by the method; sets the number of function calls
* Returns the number of function calls really performed by the method and a flag indicating whether the
* processing was aborted by the user. Sets the number of function calls
* in the population back to the original count. If the baseEvals parameter (which should be >= 0) is > 0,
* then the number of evaluations is set as
* number of evaluations before the optimization using the given terminator.
@ -488,7 +492,7 @@ public class PostProcess {
* @param baseEvals
* @return
*/
public static int processWithCMA(Population pop, AbstractOptimizationProblem problem, InterfaceTerminator term, int baseEvals) {
public static Pair<Integer,Boolean> processWithCMA(Population pop, AbstractOptimizationProblem problem, InterfaceTerminator term, int baseEvals) {
MutateESRankMuCMA mutator = new MutateESRankMuCMA();
mutator.setInitializeSigma(ESMutationInitialSigma.avgInitialDistance);
EvolutionStrategies es = OptimizerFactory.createEvolutionStrategy(pop.size()/2, pop.size(), false, mutator, 1., new CrossoverESDefault(), 0.,
@ -503,17 +507,17 @@ public class PostProcess {
int funCallsBefore = pop.getFunctionCalls();
pop.SetFunctionCalls(baseEvals);
ppRunnable = new OptimizerRunnable(cmaParams, true);
OptimizerRunnable ppRunnable = new OptimizerRunnable(cmaParams, true);
ppRunnable.getStats().createNextGenerationPerformed(cmaParams.getOptimizer().getPopulation(), cmaParams.getOptimizer(), null);
runPP();
runPP(ppRunnable);
pop.clear();
pop.addPopulation(es.getPopulation());
int funCallsDone = es.getPopulation().getFunctionCalls()-baseEvals;
pop.SetFunctionCalls(funCallsBefore);
return funCallsDone;
return new Pair<Integer,Boolean>(funCallsDone, ppRunnable.wasAborted());
}
private static boolean checkRange(AbstractEAIndividual indy) {
@ -686,18 +690,27 @@ public class PostProcess {
}
term = new EvaluationTerminator(stepsPerCand);
}
Pair<Integer, Boolean> stepsAbortedFlag = null;
for (int i=0; i<candidates.size(); i++) { // improve each single sub pop
subPop = nmPops.get(i);
term.init(prob);
// if (TRACE) System.out.println("*** before " + subPop.getBestEAIndividual().getStringRepresentation());
switch (method) {
case nelderMead: stepsPerf += PostProcess.processWithNMS(subPop, prob, term, subPop.size()-1);
case nelderMead: stepsAbortedFlag = PostProcess.processWithNMS(subPop, prob, term, subPop.size()-1);
break;
case cmaES: stepsPerf += PostProcess.processWithCMA(subPop, prob, term, subPop.size()-1);
case cmaES: stepsAbortedFlag = PostProcess.processWithCMA(subPop, prob, term, subPop.size()-1);
break;
default: System.err.println("Invalid pp method in processSingleCandidatesNMCMA!");
}
// if (TRACE) System.out.println("*** after: " + subPop.getBestEAIndividual().getStringRepresentation());
if (stepsAbortedFlag==null) System.err.println("Error in processSingleCandidatesNMCMA!");
stepsPerf += stepsAbortedFlag.head;
if (stepsAbortedFlag.tail) { // user aborted post processing
System.err.println("Warning: Post processing interrupted after " + i + " of " + candidates.size() + " candidates were processed.");
break;
}
// if (TRACE) System.out.println("*** after: " + subPop.getBestEAIndividual().getStringRepresentation());
if (checkRange(subPop.getBestEAIndividual())) {
// and replace corresponding individual (should usually be better)
// if (subPop.getBestEAIndividual().isDominant(candidates.getEAIndividual(i))) { // TODO Multiobjective???
@ -785,20 +798,42 @@ public class PostProcess {
/**
* 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;
private static void runPP(OptimizerRunnable rnbl) {
rnbl.getGOParams().setDoPostProcessing(false);
rnbl.setVerbosityLevel(StatsParameter.VERBOSITY_NONE);
ppRunnables.add(rnbl);
// System.err.println("Starting runbl " + rnbl);
rnbl.run();
// System.err.println("Aborted: " + rnbl.wasAborted());
rnbl.getGOParams().setDoPostProcessing(true);
ppRunnables.remove(rnbl);
}
/**
* Stop the post processing thread with the given ID.
*/
public static void stopPP(int rnblID) {
// System.err.println("Stopping pp " + rnblID);
OptimizerRunnable rnbl = getRunnable(rnblID);
stopPP(rnbl);
}
private static OptimizerRunnable getRunnable(int rnblID) {
synchronized (ppRunnables) {
for (int i=0; i<ppRunnables.size(); i++) {
if (rnblID == ppRunnables.get(i).getID()) return ppRunnables.get(i);
}
}
return null; // no runnable with that ID was found
}
/**
* Stop the post processing if its currently running.
*/
public static void stopPP() {
if (ppRunnable != null) synchronized (ppRunnable) {
if (ppRunnable != null) ppRunnable.stopOpt();
public static void stopPP(OptimizerRunnable rnbl) {
// System.err.println("Stopping rnbl " + rnbl);
if (rnbl != null) synchronized (rnbl) {
rnbl.stopOpt();
}
}
@ -923,9 +958,9 @@ public class PostProcess {
listener.println("default epsilon is " + mmkProb.getDefaultAccuracy());
listener.println("optima found with default epsilon: " + getFoundOptima(solutions, mmkProb.getRealOptima(), mmkProb.getDefaultAccuracy(), true).size());
listener.println("max peak ratio is " + mmkProb.getMaximumPeakRatio(getFoundOptima(solutions, mmkProb.getRealOptima(), mmkProb.getDefaultAccuracy(), true)));
for (double epsilon=0.1; epsilon > 0.00000001; epsilon/=10.) {
if (mmkProb.fullListAvailable()) for (double epsilon=0.1; epsilon > 0.00000001; epsilon/=10.) {
// out.println("no optima found: " + ((InterfaceMultimodalProblemKnown)mmProb).getNumberOfFoundOptima(pop));
listener.println("found " + getFoundOptima(solutions, mmkProb.getRealOptima(), epsilon, true).size() + " for epsilon = " + epsilon + ", maxPeakRatio: " + AbstractMultiModalProblemKnown.getMaximumPeakRatio(mmkProb,solutions, epsilon));
listener.println("found " + getFoundOptima(solutions, mmkProb.getRealOptima(), epsilon, true).size() + " for epsilon = " + epsilon + ", maxPeakRatio: " + mmkProb.getMaximumPeakRatio(solutions));
}
} else {
// TODO in this form it may cost a lot of time and cant be stopped, which is bad
@ -980,14 +1015,12 @@ public class PostProcess {
Population clusteredPop, outputPop, stateBeforeLS;
if (params.getPostProcessClusterSigma() > 0) {
// ##### pre clustering
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) {
@ -1001,12 +1034,14 @@ public class PostProcess {
} else {
mutator = null;
}
// #### Actuall call to post processing
stepsDone = processSingleCandidates(params.getPPMethod(), clusteredPop, params.getPostProcessSteps(), stepSize, problem, mutator);
if (listener != null) listener.println("Post processing: " + stepsDone + " steps done.");
if (params.isWithPlot()) {
plot = draw("After " + stepsDone + " steps ("+ params.getPPMethod() + ")", null, stateBeforeLS, clusteredPop, problem);
}
// ##### post clustering
// some individuals may have now converged again
if (params.getPostProcessClusterSigma() > 0) {
// so if wished, cluster again.
@ -1020,6 +1055,7 @@ public class PostProcess {
if (params.isWithPlot()) {
plot = draw("After " + stepsDone + " steps (" + params.getPPMethod() + ")" + ((params.getPostProcessClusterSigma()>0) ? " and second clustering" : ""), null, outputPop, null, problem);
}
// ##### some statistics
double upBnd = PhenotypeMetric.norm(outputPop.getWorstEAIndividual().getFitness())*1.1;
upBnd = Math.pow(10,Math.floor(Math.log10(upBnd)+1));
double lowBnd = 0;
@ -1040,7 +1076,7 @@ public class PostProcess {
evaluateMultiModal(outputPop, problem, listener);
Population nBestPop = outputPop.getBestNIndividuals(params.getPrintNBest()); // n individuals are returned and sorted, all of them if n<=0
if (listener != null) listener.println("Best after post process:" + ((outputPop.size()>nBestPop.size()) ? ( "(first " + nBestPop.size() + " of " + outputPop.size() + ")") : ""));
if (listener != null) listener.println("Best after post process:" + ((outputPop.size()>nBestPop.size()) ? ( " (first " + nBestPop.size() + " of " + outputPop.size() + ")") : (" (" + nBestPop.size() + ")") ));
//////////// output some individual data
if (listener != null) for (int i=0; i<nBestPop.size(); i++) {
listener.println(AbstractEAIndividual.getDefaultStringRepresentation(nBestPop.getEAIndividual(i)));
@ -1208,5 +1244,17 @@ public class PostProcess {
}
return Math.sqrt(scoreSum);
}
/**
* Try to abort all post processing threads currently running.
*
*/
public static void stopAllPP() {
synchronized (ppRunnables) {
for (OptimizerRunnable rnbl : ppRunnables) {
rnbl.stopOpt();
}
}
}
}

View File

@ -10,9 +10,9 @@ import eva2.server.go.operators.distancemetric.InterfaceDistanceMetric;
import eva2.server.go.operators.distancemetric.PhenotypeMetric;
import eva2.server.go.operators.postprocess.PostProcess;
import eva2.server.go.populations.Population;
import eva2.server.go.problems.Interface2DBorderProblem;
import eva2.tools.EVAERROR;
import eva2.tools.ToolBox;
import eva2.tools.math.Mathematics;
public abstract class AbstractMultiModalProblemKnown extends AbstractProblemDouble implements Interface2DBorderProblem, InterfaceMultimodalProblemKnown {
protected static InterfaceDistanceMetric m_Metric = new PhenotypeMetric();
@ -121,26 +121,18 @@ public abstract class AbstractMultiModalProblemKnown extends AbstractProblemDoub
*/
public abstract double[] evalUnnormalized(double[] x);
/**
* This method returns the header for the additional data that is to be written into a file
* @param pop The population that is to be refined.
* @return String
*/
public String getAdditionalFileStringHeader(PopulationInterface pop) {
return "#Optima found \tMaximum Peak Ratio \t" + super.getAdditionalFileStringHeader(pop);
@Override
public String[] getAdditionalFileStringHeader(PopulationInterface pop) {
return ToolBox.appendArrays(new String[]{"numOptsFound", "maxPeakRatio"}, super.getAdditionalFileStringHeader(pop));
}
/**
* This method returns the additional data that is to be written into a file
* @param pop The population that is to be refined.
* @return String
*/
public String getAdditionalFileStringValue(PopulationInterface pop) {
String result = "";
@Override
public Object[] getAdditionalFileStringValue(PopulationInterface pop) {
Object[] result = new Object[2];
// result += AbstractEAIndividual.getDefaultDataString(pop.getBestIndividual()) +"\t";
result += this.getNumberOfFoundOptima((Population)pop)+"\t";
result += this.getMaximumPeakRatio((Population)pop);
return result +"\t"+ super.getAdditionalFileStringValue(pop);
result[0] = this.getNumberOfFoundOptima((Population)pop);
result[1] = this.getMaximumPeakRatio((Population)pop);
return ToolBox.appendArrays(result, super.getAdditionalFileStringValue(pop));
}
//
// /** This method returns a string describing the optimization problem.
@ -253,22 +245,28 @@ public abstract class AbstractMultiModalProblemKnown extends AbstractProblemDoub
* @return double
*/
public double getMaximumPeakRatio(Population pop) {
return getMaximumPeakRatio(this, pop, m_Epsilon);
if (!this.fullListAvailable()) return -1;
else return getMaximumPeakRatio(this.getRealOptima(), pop, m_Epsilon);
}
/**
* Returns -1 if the full list is not available. Otherwise calculates the maximum peak ratio
* based on the full list of known optima.
* This assumes that the realOpts have fitness values assigned as for maximization and the
* pop has fitness values assigned for minimization (mirrored by maximum fitness within realOpts).
*
* This is in analogy to the original implementation by F.Streichert.
*
* @param mmProb
* @param pop
* @param epsilon
* @return
*/
public static double getMaximumPeakRatio(InterfaceMultimodalProblemKnown mmProb, Population pop, double epsilon) {
public static double getMaximumPeakRatio(Population realOpts, Population pop, double epsilon) {
double foundInvertedSum = 0, sumRealMaxima = 0;
if (!mmProb.fullListAvailable()) return -1;
Population realOpts = mmProb.getRealOptima();
if (realOpts==null || (realOpts.size()==0)) return -1;
// if (!mmProb.fullListAvailable()) return -1;
// Population realOpts = mmProb.getRealOptima();
double tmp, maxOpt = realOpts.getEAIndividual(0).getFitness(0);
sumRealMaxima = maxOpt;
for (int i=1; i<realOpts.size(); i++) {
@ -292,6 +290,87 @@ public abstract class AbstractMultiModalProblemKnown extends AbstractProblemDoub
return foundInvertedSum/sumRealMaxima;
}
/**
* Returns -1 if the full list is not available. Otherwise calculates the maximum peak ratio
* based on the full list of known optima. Assumes that both realOpts and pop have fitness
* values assigned as in a maximization problem. This is the standard formulation of MPR.
*
* @param mmProb
* @param pop
* @param epsilon
* @return
*/
public static double getMaximumPeakRatioMaximization(Population realOpts, Population pop, double epsilon, int fitCrit) {
AbstractEAIndividual[] optsFound = PostProcess.getFoundOptimaArray(pop, realOpts, epsilon, true);
double mpr = 0;
for (int i=0; i<realOpts.size(); i++) {
// sum up the specific optimal fitness values relative to optimal fitness
if (optsFound[i] != null) {
double tmp = optsFound[i].getFitness(fitCrit);
if (tmp < 0) EVAERROR.errorMsgOnce("warning: for the MPR calculation, negative fitness values may disturb the allover result (AbstractMultiModalProblemKnown)");
mpr += (Math.max(0., tmp)/realOpts.getEAIndividual(i).getFitness(fitCrit));
}
}
return mpr;
}
/**
* Calculates the maximum peak ratio based on the given fitness values.
* This is the standard formulation of MPR which assumes that all fitness
* values are positive (and for a corresponding pair, foundFits[i]<realFits[i]).
* If these assumptions hold, the MPR lies in [0,1].
*
* @param mmProb
* @param pop
* @param epsilon
* @return
*/
public static double getMaximumPeakRatioMaximization(double[] realFits, double[] foundFits) {
double mpr = Mathematics.sum(foundFits)/Mathematics.sum(realFits);
return mpr;
}
/**
* Returns -1 if the full list is not available. Otherwise calculates the maximum peak ratio
* based on the full list of known optima. Assumes that both realOpts and pop have fitness
* values assigned as in a maximization problem. This is the standard formulation of MPR.
*
* @param mmProb
* @param pop
* @param epsilon
* @return
*/
public static double getMaximumPeakRatioMinimization(Population realOpts, Population pop, double epsilon, int fitCrit, double fitThreshold) {
AbstractEAIndividual[] optsFound = PostProcess.getFoundOptimaArray(pop, realOpts, epsilon, true);
double[] realFits = new double[realOpts.size()];
double[] foundFits = new double[realOpts.size()];
double minOpt = Double.MAX_VALUE;
for (int i=0; i<realOpts.size(); i++) {
// store the optimal fitness values and remember the smallest one
realFits[i]=realOpts.getEAIndividual(i).getFitness(fitCrit);
if (realFits[i]>fitThreshold) System.err.println("Warning: The fitness threshold to turn minimization fitness values into " +
"maximization values should be larger than any optimal fitness! (AbstractMultiModalProblemKnown)");
if (i==0 || (minOpt>realFits[i])) minOpt = realFits[i];
// check if the opt. was found and store the corr. found fitness
if (optsFound[i]!=null) {
foundFits[i] = new Double(optsFound[i].getFitness(fitCrit));
} else foundFits[i]=fitThreshold; // note that it wasnt found -- will result in zero
}
// now we mirror all values with the threshold - provided they are below the threshold...
for (int i=0; i<realOpts.size(); i++) {
realFits[i] = fitThreshold-realFits[i];
foundFits[i] = fitThreshold-foundFits[i];
if (foundFits[i]>realFits[i] && (foundFits[i]-realFits[i]>1e-10)) {
// this can happen if the real fitness is wrong or if the threshold allows individuals close to better optima to
// be counted for actually inferior optima
System.err.println("Warning: found fitness is better than real fitness - wrong predefined solution or suboptimal epsilon-criterion? Diff was: " + (foundFits[i]-realFits[i]));
}
if ((realFits[i] < 0) || (foundFits[i] < 0)) EVAERROR.errorMsgOnce("warning: for the MPR calculation, negative fitness values may disturb the allover result (AbstractMultiModalProblemKnown)");
}
// now we can call the standard calculation method
return getMaximumPeakRatioMaximization(realFits, foundFits);
}
// public double getMaximumPeakRatio(Population pop) {
// double result = 0, sum = 0;
// AbstractEAIndividual posOpt, opt;

View File

@ -11,6 +11,7 @@ import javax.swing.JFrame;
import eva2.gui.GraphPointSet;
import eva2.gui.Plot;
import eva2.server.go.PopulationInterface;
import eva2.server.go.individuals.AbstractEAIndividual;
import eva2.server.go.individuals.ESIndividualDoubleData;
import eva2.server.go.operators.archiving.ArchivingAllDominating;
@ -514,11 +515,11 @@ public abstract class AbstractMultiObjectiveOptimizationProblem extends Abstract
* would be best, since log y can be used. But the value can depend on the problem.
*/
public Double getDoublePlotValue(Population pop) {
if (this.isPopulationMultiObjective(pop)) {
if (AbstractMultiObjectiveOptimizationProblem.isPopulationMultiObjective(pop)) {
return new Double(this.calculateMetric(pop));
} else {
// in this case the local Pareto-Front could be multi-objective
if (this.isPopulationMultiObjective(this.m_ParetoFront)) {
if (AbstractMultiObjectiveOptimizationProblem.isPopulationMultiObjective(this.m_ParetoFront)) {
return new Double(this.calculateMetric(this.m_ParetoFront));
} else {
return new Double(pop.getBestEAIndividual().getFitness(0));
@ -533,29 +534,23 @@ public abstract class AbstractMultiObjectiveOptimizationProblem extends Abstract
return this.m_ParetoFront;
}
/** This method returns the header for the additional data that is to be written into a file
* @param pop The population that is to be refined.
* @return String
*/
public String getAdditionalFileStringHeader(Population pop) {
String result;
if (this.isPopulationMultiObjective(pop))
result = "SMetric";
@Override
public String[] getAdditionalFileStringHeader(PopulationInterface pop) {
String[] result = new String[1];
if (AbstractMultiObjectiveOptimizationProblem.isPopulationMultiObjective((Population)pop))
result[0] = "SMetric";
else
result = "BestFitness";
result[0] = "BestFitness";
return result;
}
/** This method returns the additional data that is to be written into a file
* @param pop The population that is to be refined.
* @return String
*/
public String getAdditionalFileStringValue(Population pop) {
String result = "";
if (this.isPopulationMultiObjective(pop))
result += this.calculateMetric(pop);
@Override
public Object[] getAdditionalFileStringValue(PopulationInterface pop) {
Object[] result = new Object[1];
if (AbstractMultiObjectiveOptimizationProblem.isPopulationMultiObjective((Population)pop))
result[0] = this.calculateMetric((Population)pop);
else
result += pop.getBestEAIndividual().getFitness()[0];
result[0] = ((Population)pop).getBestEAIndividual().getFitness()[0];
return result;
}

View File

@ -239,22 +239,22 @@ implements InterfaceOptimizationProblem /*, InterfaceParamControllable*/, Serial
* @param pop The population that is to be refined.
* @return String
*/
public String getAdditionalFileStringHeader(PopulationInterface pop) {
if (this instanceof InterfaceInterestingHistogram) return "Solution \t Histogram(c0) \t Score";
else return "Solution";
public String[] getAdditionalFileStringHeader(PopulationInterface pop) {
if (this instanceof InterfaceInterestingHistogram) return new String[]{"Solution","Histogram(c0)","Score"};
else return new String[]{"Solution"};
}
/** This method returns the additional data that is to be written into a file
* @param pop The population that is to be refined.
* @return String
*/
public String getAdditionalFileStringValue(PopulationInterface pop) {
public Object[] getAdditionalFileStringValue(PopulationInterface pop) {
String solStr = AbstractEAIndividual.getDefaultDataString(pop.getBestIndividual());
if (this instanceof InterfaceInterestingHistogram) {
SolutionHistogram hist = ((InterfaceInterestingHistogram)this).getHistogram();
Population sols = PostProcess.clusterBestUpdateHistogram((Population)pop, this, hist, 0, getDefaultAccuracy());
return solStr + " \t " + hist + "\t" + hist.getScore();
} else return solStr;
return new Object[]{solStr, hist, hist.getScore()};
} else return new Object[]{solStr};
}
/**

View File

@ -1,17 +1,20 @@
package eva2.server.go.problems;
import eva2.gui.BeanInspector;
import eva2.gui.GenericObjectEditor;
import eva2.gui.TopoPlot;
import eva2.server.go.PopulationInterface;
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.operators.constraint.AbstractConstraint;
import eva2.server.go.operators.constraint.GenericConstraint;
import eva2.server.go.operators.postprocess.PostProcess;
import eva2.server.go.operators.terminators.FitnessConvergenceTerminator;
import eva2.server.go.populations.Population;
import eva2.server.go.strategies.InterfaceOptimizer;
import eva2.tools.Pair;
import eva2.tools.ToolBox;
import eva2.tools.diagram.ColorBarCalculator;
import eva2.tools.math.Mathematics;
import eva2.tools.math.RNG;
@ -139,6 +142,7 @@ public abstract class AbstractProblemDouble extends AbstractOptimizationProblem
}
return x;
}
/**
* Add all constraint violations to the individual. Expect that the fitness has already been set.
*
@ -352,6 +356,70 @@ public abstract class AbstractProblemDouble extends AbstractOptimizationProblem
public double functionValue(double[] point) {
return eval(project2DPoint(point))[0];
}
/**
* Add a position as a known optimum to a list of optima. This method evaluates the fitness
* and applies inverse rotation if necessary.
*
* @param optimas
* @param prob
* @param pos
*/
public static void addUnrotatedOptimum(Population optimas, AbstractProblemDouble prob, double[] pos) {
InterfaceDataTypeDouble tmpIndy;
tmpIndy = (InterfaceDataTypeDouble)prob.getIndividualTemplate().clone();
tmpIndy.SetDoubleGenotype(pos);
if (prob.isDoRotation()) {
pos = prob.inverseRotateMaybe(pos); // theres an inverse rotation required
tmpIndy.SetDoubleGenotype(pos);
}
((AbstractEAIndividual)tmpIndy).SetFitness(prob.eval(pos));
if (!Mathematics.isInRange(pos, prob.makeRange())) {
System.err.println("Warning, add optimum which is out of range!");
}
optimas.add(tmpIndy);
}
/**
* Refine a potential solution using Nelder-Mead-Simplex.
* @param prob
* @param pos
* @return
*/
public static double[] refineSolutionNMS(AbstractProblemDouble prob, double[] pos) {
Population pop = new Population();
InterfaceDataTypeDouble tmpIndy;
tmpIndy = (InterfaceDataTypeDouble)prob.getIndividualTemplate().clone();
tmpIndy.SetDoubleGenotype(pos);
((AbstractEAIndividual)tmpIndy).SetFitness(prob.eval(pos));
pop.add(tmpIndy);
FitnessConvergenceTerminator convTerm = new FitnessConvergenceTerminator(1e-25, 10, false, true);
int calls = PostProcess.processSingleCandidatesNMCMA(PostProcessMethod.nelderMead, pop, convTerm, 0.001, prob);
return ((InterfaceDataTypeDouble)pop.getBestEAIndividual()).getDoubleData();
}
/**
* Refine a candidate solution vector regarding rotations. Saves the
* new solution vector in pos and returns the number of dimensions
* that had to be modified after rotation due to range restrictions.
*
* The given position is expected to be unrotated! The returned solution
* is unrotated as well.
*
* @param pos
* @param prob
* @return
*/
public static int refineWithRotation(double[] pos, AbstractProblemDouble prob) {
double[] res = prob.inverseRotateMaybe(pos);
int modifiedInPrjct = Mathematics.projectToRange(res, prob.makeRange());
res = AbstractProblemDouble.refineSolutionNMS(prob, res);
res = prob.rotateMaybe(res);
System.arraycopy(res, 0, pos, 0, res.length);
return modifiedInPrjct;
}
/**********************************************************************************************************************
* These are for GUI
*/
@ -424,19 +492,22 @@ public abstract class AbstractProblemDouble extends AbstractOptimizationProblem
}
@Override
public String getAdditionalFileStringHeader(PopulationInterface pop) {
String superHeader = super.getAdditionalFileStringHeader(pop);
if (isWithConstraints()) return superHeader + " \tRawFit. \tNum.Viol. \t Sum.Viol.";
public String[] getAdditionalFileStringHeader(PopulationInterface pop) {
String[] superHeader = super.getAdditionalFileStringHeader(pop);
if (isWithConstraints()) return ToolBox.appendArrays(superHeader, new String[]{"RawFit.","Num.Viol.","Sum.Viol."});
else return superHeader;
}
@Override
public String getAdditionalFileStringValue(PopulationInterface pop) {
String superVal = super.getAdditionalFileStringValue(pop);
public Object[] getAdditionalFileStringValue(PopulationInterface pop) {
Object[] superVal = super.getAdditionalFileStringValue(pop);
if (isWithConstraints()) {
AbstractEAIndividual indy = (AbstractEAIndividual)pop.getBestIndividual();
Pair<Integer,Double> violation= getConstraintViolation(indy);
return superVal + " \t" + BeanInspector.toString(indy.getData(rawFitKey)) + " \t" + violation.head() + " \t" + violation.tail();
return ToolBox.appendArrays(superVal, new Object[]{indy.getData(rawFitKey),
violation.head(),
violation.tail()});
// return superVal + " \t" + BeanInspector.toString(indy.getData(rawFitKey)) + " \t" + violation.head() + " \t" + violation.tail();
} else return superVal;
}
@ -458,7 +529,11 @@ public abstract class AbstractProblemDouble extends AbstractOptimizationProblem
if (!isShowing && showP) {
TopoPlot plot = new TopoPlot(getName(), "x1", "x2");
plot.setParams(60,60, ColorBarCalculator.BLUE_TO_RED);
this.initProblem();
plot.setTopology(this, makeRange(), true);
if (this instanceof InterfaceMultimodalProblemKnown && ((InterfaceMultimodalProblemKnown)this).fullListAvailable()) {
plot.drawPopulation("Opt", ((InterfaceMultimodalProblemKnown)this).getRealOptima());
}
}
isShowing = showP;
}

View File

@ -1,5 +1,15 @@
package eva2.server.go.problems;
import java.util.Arrays;
import eva2.server.go.PopulationInterface;
import eva2.server.go.individuals.AbstractEAIndividual;
import eva2.server.go.operators.distancemetric.EuclideanMetric;
import eva2.server.go.operators.postprocess.SolutionHistogram;
import eva2.server.go.populations.Population;
import eva2.tools.ToolBox;
import eva2.tools.math.Mathematics;
/**
* Created by IntelliJ IDEA.
@ -8,8 +18,12 @@ package eva2.server.go.problems;
* Time: 19:40:28
* To change this template use File | Settings | File Templates.
*/
public class F8Problem extends AbstractProblemDoubleOffset implements InterfaceMultimodalProblem, java.io.Serializable {
public class F8Problem extends AbstractProblemDoubleOffset
implements InterfaceInterestingHistogram, InterfaceMultimodalProblem, //InterfaceFirstOrderDerivableProblem,
InterfaceMultimodalProblemKnown, java.io.Serializable {
transient protected Population m_ListOfOptima = null;
private static transient boolean state_initializing_optima = false;
private double a = 20;
private double b = 0.2;
private double c = 2*Math.PI;
@ -29,6 +43,9 @@ public class F8Problem extends AbstractProblemDoubleOffset implements InterfaceM
super(dim);
setDefaultRange(f8Range);
}
// make this a multimodal problem known and add the best optima as in the niching ES papers!
/** This method returns a deep clone of the problem.
* @return the clone
*/
@ -73,7 +90,14 @@ public class F8Problem extends AbstractProblemDoubleOffset implements InterfaceM
return result;
}
/**********************************************************************************************************************
@Override
public void initProblem() {
super.initProblem();
initListOfOptima();
}
/**********************************************************************************************************************
* These are for GUI
*/
/** This method allows the CommonJavaObjectEditorPanel to read the
@ -90,4 +114,181 @@ public class F8Problem extends AbstractProblemDoubleOffset implements InterfaceM
public static String globalInfo() {
return "Ackley's function.";
}
public SolutionHistogram getHistogram() {
if (getProblemDimension() < 15) return new SolutionHistogram(-0.1, 7.9, 16);
else if (getProblemDimension() < 25) return new SolutionHistogram(-0.5, 15.5, 16);
else return new SolutionHistogram(0, 16, 16);
}
// public double[] getFirstOrderGradients(double[] x) {
// double sum1=0, sum2=0;
// double[] derivs = new double[x.length];
// x = rotateMaybe(x);
// double dim = (double)this.m_ProblemDimension;
//
// for (int i = 0; i < x.length; i++) {
// double xi = x[i]-m_XOffSet;
// sum1 += (xi)*(xi);
// sum2 += Math.cos(c * (xi));
// }
//
// for (int i=0; i<x.length; i++) {
// if (sum1==0) derivs[i]=0;
// else derivs[i]=((this.b*2*x[i]*this.a)/(Math.sqrt(sum1/dim)))*Math.exp(-this.b*Math.sqrt(sum1/dim));
// derivs[i]+= ((this.c/dim)*(Math.sin(this.c*x[i])))*Math.exp(sum2/dim);
// }
// System.out.println("at " + BeanInspector.toString(x) + " sum1 " + sum1 + " sum2 " + sum2 + " deriv " + BeanInspector.toString(derivs));
// return derivs;
// }
public boolean fullListAvailable() {
return true;
}
public double getMaximumPeakRatio(Population pop) {
return AbstractMultiModalProblemKnown.getMaximumPeakRatioMinimization(m_ListOfOptima, pop, getDefaultAccuracy(), 0, 5);
}
public int getNumberOfFoundOptima(Population pop) {
return AbstractMultiModalProblemKnown.getNoFoundOptimaOf(this, pop);
}
public Population getRealOptima() {
return m_ListOfOptima;
}
@Override
public String[] getAdditionalFileStringHeader(PopulationInterface pop) {
String[] superHd = super.getAdditionalFileStringHeader(pop);
return ToolBox.appendArrays(new String[]{"numOptimaFound","maxPeakRatio"}, superHd);
// return "#Optima found \tMaximum Peak Ratio \t" + super.getAdditionalFileStringHeader(pop);
}
@Override
public Object[] getAdditionalFileStringValue(PopulationInterface pop) {
Object[] myRet = new Object[2];
myRet[0] = this.getNumberOfFoundOptima((Population)pop);
myRet[1] = this.getMaximumPeakRatio((Population)pop);
return ToolBox.appendArrays(myRet, super.getAdditionalFileStringValue(pop));
}
/**
* We identify a set of 2*n+1 optima, which are the global and the first level
* of local optima.
* Interestingly, the local optima in the first sphere (close to (1,0,0,0,...) vanish starting
* with n=18 (checked with Matlab). The next sphere contains O(n^2) optima (I think 3*n*(n-1)).
* This is unfortunately not mentioned in the papers by Shir
* and Bäck who still seemed to be able to find 2*n+1...
*/
public void initListOfOptima() {
if (listOfOptimaNeedsUpdate()) {
state_initializing_optima=true;
m_ListOfOptima=new Population();
// ingeniously avoid recursive calls during refinement!
double[] pos = new double[getProblemDimension()];
Arrays.fill(pos, getXOffSet());
addOptimum(pos); // the global optimum
double refinedX = 0;
if (getProblemDimension()<18) for (int i=0; i<getProblemDimension(); i++) {
// TODO what about dimensions higher than 18???
for (int k=-1; k<=1; k+=2) {
Arrays.fill(pos, getXOffSet());
if (refinedX == 0) { // we dont know the exact x-offset for the optima, so refine once
pos[i]=k+getXOffSet();
double[] dir = pos.clone();
dir[i]-=0.05;
pos = inverseRotateMaybe(pos);
// ab dim 18/20 oder so finde ich plötzlich keine optima bei x[i]<1 mehr???
dir = inverseRotateMaybe(dir);
pos = refineSolution(this, pos, dir, 0.0005, 1e-20, 0);
if (EuclideanMetric.euclideanDistance(pos, m_ListOfOptima.getEAIndividual(0).getDoublePosition())<0.5) {
System.err.println("Warning, possibly converged to a wrong optimum in F8Problem.initListOfOptima!");
}
pos = rotateMaybe(pos);
refinedX = Math.abs(pos[i]-getXOffSet()); // store the refined position which is equal in any direction and dimension
} else {
pos[i]=(k*refinedX)+getXOffSet();
}
addOptimum(pos);
}
}
// System.out.println("Inited " + m_ListOfOptima.size() + " optima, measures: " + BeanInspector.toString(m_ListOfOptima.getPopulationMeasures(new PhenotypeMetric())));
// System.out.println("Inited " + m_ListOfOptima.size() + " optima, measures: " + BeanInspector.toString(m_ListOfOptima.getPopulationMeasures(new EuclideanMetric())));
// System.out.println(m_ListOfOptima.getStringRepresentation());
state_initializing_optima=false;
}
}
private double[] refineSolution(AbstractProblemDouble prob, double[] pos, double[] vect, double initStep, double thresh, int fitCrit) {
// return AbstractProblemDouble.refineSolutionNMS(prob, pos);
// a line search along a vector
double[] tmpP = pos.clone();
double[] normedVect = Mathematics.normVect(vect);
double dx = initStep;
double tmpFit, oldFit = prob.eval(pos)[fitCrit];
int dir = 1;
while (dx>thresh) {
// add a step to tmpP
Mathematics.svvAddScaled(dx*dir, normedVect, pos, tmpP);
// evaluate tmpP
tmpFit = prob.eval(tmpP)[fitCrit];
if (tmpFit < oldFit) {
// if tmpP is better than pos continue at new pos
double[] tmp=pos;
pos = tmpP;
tmpP=tmp;
oldFit = tmpFit;
} else {
// otherwise invert direction, reduce step, continue
dx*=0.73;
dir*=-1;
}
}
return pos;
}
private boolean listOfOptimaNeedsUpdate() {
if (state_initializing_optima) return false; // avoid recursive call during refining with GDA
if (m_ListOfOptima==null || (m_ListOfOptima.size() != (1+2*getProblemDimension()))) {
return true;
} else { // the number of optima is corret - now check different offset or rotation by comparing one fitness value
AbstractEAIndividual indy = m_ListOfOptima.getEAIndividual(1);
double[] curFit = eval(indy.getDoublePosition());
if (Math.abs(Mathematics.dist(curFit, indy.getFitness(), 2))>1e-10) {
return true;
} else return false;
}
// else {
// if (m_ListOfOptima.isEmpty()) return true;
// else {
// // test for correctness of the second optimum - if its gradient is nonzero, reinit optima
// AbstractEAIndividual testIndy = m_ListOfOptima.getEAIndividual(1);
// double grad[] = this.getFirstOrderGradients(testIndy.getDoublePosition());
// for (int i=0; i<grad.length; i++) {
// if (Math.abs(grad[i])>1e-20) {
// m_ListOfOptima.clear();
// return true;
// }
// }
// return false;
// }
// }
}
private void addOptimum(double[] pos) {
AbstractProblemDouble.addUnrotatedOptimum(m_ListOfOptima, this, pos);
}
// private double[] refineSolution(double[] pos) {
// Population pop = new Population();
// InterfaceDataTypeDouble tmpIndy;
// tmpIndy = (InterfaceDataTypeDouble)((AbstractEAIndividual)this.m_Template).clone();
// tmpIndy.SetDoubleGenotype(pos);
// ((AbstractEAIndividual)tmpIndy).SetFitness(eval(pos));
// pop.add(tmpIndy);
// FitnessConvergenceTerminator convTerm = new FitnessConvergenceTerminator(1e-15, 10, false, true);
// int calls = PostProcess.processWithGDA(pop, this, convTerm, 0, 0.0000000000000001, 0.01);
// return ((InterfaceDataTypeDouble)pop.getBestEAIndividual()).getDoubleData();
// }
}

View File

@ -19,6 +19,7 @@ import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import eva2.server.go.GOStandaloneVersion;
import eva2.server.go.PopulationInterface;
import eva2.server.go.individuals.AbstractEAIndividual;
import eva2.server.go.individuals.ESIndividualDoubleData;
import eva2.server.go.individuals.InterfaceDataTypeDouble;
@ -344,24 +345,17 @@ public class FLensProblem extends AbstractOptimizationProblem implements Interfa
return result;
}
/** This method returns the header for the additional data that is to be written into a file
* @param pop The population that is to be refined.
* @return String
*/
public String getAdditionalFileStringHeader(Population pop) {
return "Solution";
@Override
public String[] getAdditionalFileStringHeader(PopulationInterface pop) {
return new String[]{"Solution"};
}
/** This method returns the additional data that is to be written into a file
* @param pop The population that is to be refined.
* @return String
*/
public String getAdditionalFileStringValue(Population pop) {
@Override
public Object[] getAdditionalFileStringValue(PopulationInterface pop) {
String result ="{";
double[] data = ((InterfaceDataTypeDouble) pop.getBestEAIndividual()).getDoubleData();
double[] data = ((InterfaceDataTypeDouble) pop.getBestIndividual()).getDoubleData();
for (int i = 0; i < data.length; i++) result += data[i] +"; ";
result += "}";
return result;
return new Object[]{result};
}
/** This method allows you to output a string that describes a found solution

View File

@ -2,16 +2,27 @@ package eva2.server.go.problems;
import eva2.server.go.PopulationInterface;
/**
* An interface for an instance providing specialized statistical data on an optimization run.
* This may be statistics depending on specific optimization methods or a specific application
* problem.
* For every additional field, a field name (header) and a value at every iteration must be provided.
*
* @author mkron
*
*/
public interface InterfaceAdditionalPopulationInformer {
/** This method returns the header for the additional data that is to be written into a file
* @param pop The population that is to be refined.
/**
* This method returns the header for additional statistical data.
* @param pop The population of the optimization run.
* @return String
*/
public String getAdditionalFileStringHeader(PopulationInterface pop);
public String[] getAdditionalFileStringHeader(PopulationInterface pop);
/** This method returns the additional data that is to be written into a file
/**
* This method returns additional statistical data.
* @param pop The population that is to be refined.
* @return String
*/
public String getAdditionalFileStringValue(PopulationInterface pop);
public Object[] getAdditionalFileStringValue(PopulationInterface pop);
}

View File

@ -265,7 +265,7 @@ public class MatlabProblem extends AbstractOptimizationProblem implements Interf
runnable.setVerbosityLevel(verbosityLevel);
if (verbosityLevel>0) runnable.setOutputTo(2); // both file + window
else runnable.setOutputTo(1); // only window
runnable.setOutputAdditionalInfo(true);
runnable.setOutputFullStatsToText(true);
// log("in MP optimize C\n");
if ((specParams != null) && (specParams.length > 0)) {
@ -346,12 +346,16 @@ public class MatlabProblem extends AbstractOptimizationProblem implements Interf
requestPostProcessing(steps, sigma, -1);
}
/**
* Try and stop the current optimization as well as any post processing
* currently running.
*/
public void stopOptimize() {
log(">>>>>>>>>> Stop event!\n");
if (runnable != null) {
runnable.stopOpt();
}
PostProcess.stopPP();
PostProcess.stopAllPP();
}
public String getInfoString() {

View File

@ -1141,13 +1141,18 @@ public class ClusterBasedNichingEA implements InterfacePopulationChangedEventLis
return "If fitness improves less than this value within the halting window, convergence is assumed. May be set to zero.";
}
public String getAdditionalFileStringHeader(PopulationInterface pop) {
return " Undiff. \t #Act.spec. \tAvg.Spec.Meas. \t #Archived.";
public String[] getAdditionalFileStringHeader(PopulationInterface pop) {
return new String[]{"Undiff.","#Act.spec.","Avg.Spec.Meas.","#Archived."};
}
public String getAdditionalFileStringValue(PopulationInterface pop) {
public Object[] getAdditionalFileStringValue(PopulationInterface pop) {
// int actives = countActiveSpec();
return m_Undifferentiated.size() + " \t " + m_Species.size() + " \t " + BeanInspector.toString(getAvgSpeciesMeasures()[0]) + " \t " + (m_Archive.size());
return new Object[] {
m_Undifferentiated.size(),
m_Species.size(),
getAvgSpeciesMeasures()[0],
m_Archive.size()};
// return m_Undifferentiated.size() + " \t " + m_Species.size() + " \t " + BeanInspector.toString(getAvgSpeciesMeasures()[0]) + " \t " + (m_Archive.size());
}
/**

View File

@ -418,12 +418,12 @@ public class ClusteringHillClimbing implements InterfacePopulationChangedEventLi
return "Set the method to be used for the hill climbing as local search";
}
public String getAdditionalFileStringHeader(PopulationInterface pop) {
return "#Indies";
public String[] getAdditionalFileStringHeader(PopulationInterface pop) {
return new String[]{"#Indies"};
}
public String getAdditionalFileStringValue(PopulationInterface pop) {
return ""+m_Population.size();
public Object[] getAdditionalFileStringValue(PopulationInterface pop) {
return new Object[]{m_Population.size()};
}
public boolean isDoReinitialization() {

View File

@ -1991,6 +1991,10 @@ public class ParticleSwarmOptimization implements InterfaceOptimizer, java.io.Se
this.emaPeriods = emaPeriods;
}
/**
* This method is necessary to allow access from the Processor.
* @return
*/
public ParameterControlManager getParamControl() {
return paramControl;
}
@ -1998,10 +2002,12 @@ public class ParticleSwarmOptimization implements InterfaceOptimizer, java.io.Se
public ParamAdaption[] getParameterControl() {
return paramControl.getSingleAdapters();
}
public void setParameterControl(ParamAdaption[] paramControl) {
this.paramControl.setSingleAdapters(paramControl);
}
public String parameterControlTipText() {
return "You may define dynamic paramter control strategies using the parameter name.";
}
/**
* Retrieve the set of personal best positions contained in the given population.
@ -2055,20 +2061,19 @@ public class ParticleSwarmOptimization implements InterfaceOptimizer, java.io.Se
// this.doLocalSearch = doLocalSearch;
// }
public String getAdditionalFileStringHeader(PopulationInterface pop) {
if (emaPeriods > 0) return " \tMeanCurSpeed \tMeanEMASpeed";
else return " \tMeanCurSpeed";
public String[] getAdditionalFileStringHeader(PopulationInterface pop) {
if (emaPeriods > 0) return new String[]{"MeanCurSpeed","MeanEMASpeed"};
else return new String[]{"MeanCurSpeed"};
}
public String getAdditionalFileStringValue(PopulationInterface pop) {
String res=" \t";
public Object[] getAdditionalFileStringValue(PopulationInterface pop) {
AbstractEAIndividual indy = (AbstractEAIndividual)pop.get(0);
if (emaPeriods>0) {
double relSp;
if (indy instanceof InterfaceDataTypeDouble) {
res = getRelativeEMASpeed(((InterfaceDataTypeDouble)indy).getDoubleRange()) + " \t";
} else res=Double.NaN + " \t";;
}
res += getPopulationAvgNormedVelocity((Population) pop);
return res;
relSp = getRelativeEMASpeed(((InterfaceDataTypeDouble)indy).getDoubleRange());
} else relSp=Double.NaN;
return new Object[]{relSp, getPopulationAvgNormedVelocity((Population) pop)};
} else return new Object[]{getPopulationAvgNormedVelocity((Population) pop)};
}
}

View File

@ -1,13 +1,17 @@
package eva2.server.modules;
import java.io.Serializable;
import java.util.LinkedList;
import java.util.List;
import eva2.gui.BeanInspector;
import eva2.server.go.InterfaceGOParameters;
import eva2.server.go.InterfaceNotifyOnInformers;
import eva2.server.go.InterfacePopulationChangedEventListener;
import eva2.server.go.InterfaceTerminator;
import eva2.server.go.operators.postprocess.InterfacePostProcessParams;
import eva2.server.go.operators.postprocess.PostProcessParams;
import eva2.server.go.problems.InterfaceAdditionalPopulationInformer;
import eva2.server.go.problems.InterfaceOptimizationProblem;
import eva2.server.go.strategies.InterfaceOptimizer;
@ -22,11 +26,13 @@ public abstract class AbstractGOParameters implements InterfaceGOParameters, Ser
protected InterfaceTerminator m_Terminator;
protected InterfacePostProcessParams m_PostProc = new PostProcessParams(false);
transient protected InterfacePopulationChangedEventListener m_Listener;
transient private List<InterfaceNotifyOnInformers> toInformAboutInformers = null;
protected AbstractGOParameters() {
}
protected AbstractGOParameters(AbstractGOParameters Source) {
this();
this.m_Optimizer = Source.m_Optimizer;
this.m_Problem = Source.m_Problem;
this.m_Terminator = Source.m_Terminator;
@ -36,6 +42,7 @@ public abstract class AbstractGOParameters implements InterfaceGOParameters, Ser
}
public AbstractGOParameters(InterfaceOptimizer opt, InterfaceOptimizationProblem prob, InterfaceTerminator term) {
this();
m_Optimizer = opt;
m_Problem = prob;
m_Terminator = term;
@ -76,11 +83,37 @@ public abstract class AbstractGOParameters implements InterfaceGOParameters, Ser
return sb.toString();
}
public void addInformableInstance(InterfaceNotifyOnInformers o) {
if (toInformAboutInformers==null) toInformAboutInformers=new LinkedList<InterfaceNotifyOnInformers>();
if (!toInformAboutInformers.contains(o)) toInformAboutInformers.add(o);
o.setInformers(getInformerList());
}
public boolean removeInformableInstance(InterfaceNotifyOnInformers o) {
if (toInformAboutInformers==null) return false;
else return toInformAboutInformers.remove(o);
}
private void fireNotifyOnInformers() {
if (toInformAboutInformers!=null) for (InterfaceNotifyOnInformers listener : toInformAboutInformers) {
listener.setInformers(getInformerList());
}
}
public void setOptimizer(InterfaceOptimizer optimizer) {
this.m_Optimizer = optimizer;
this.m_Optimizer.SetProblem(this.m_Problem);
if (this.m_Listener != null) this.m_Optimizer.addPopulationChangedEventListener(this.m_Listener);
fireNotifyOnInformers();
}
private List<InterfaceAdditionalPopulationInformer> getInformerList() {
LinkedList<InterfaceAdditionalPopulationInformer> ret = new LinkedList<InterfaceAdditionalPopulationInformer>();
if (m_Problem instanceof InterfaceAdditionalPopulationInformer) ret.add(m_Problem);
if (m_Optimizer instanceof InterfaceAdditionalPopulationInformer) ret.add((InterfaceAdditionalPopulationInformer)m_Optimizer);
return ret;
}
public InterfaceOptimizer getOptimizer() {
return this.m_Optimizer;
}
@ -99,7 +132,9 @@ public abstract class AbstractGOParameters implements InterfaceGOParameters, Ser
public void setProblem (InterfaceOptimizationProblem problem) {
this.m_Problem = problem;
this.m_Optimizer.SetProblem(this.m_Problem);
fireNotifyOnInformers();
}
public InterfaceOptimizationProblem getProblem() {
return this.m_Problem;
}

View File

@ -11,6 +11,7 @@ import eva2.gui.GenericObjectEditor;
import eva2.gui.JParaPanel;
import eva2.gui.PanelMaker;
import eva2.server.go.InterfaceGOParameters;
import eva2.server.go.InterfaceNotifyOnInformers;
import eva2.server.stat.AbstractStatistics;
import eva2.server.stat.InterfaceStatisticsParameter;
import eva2.server.stat.StatisticsStandalone;
@ -47,6 +48,9 @@ public class GenericModuleAdapter extends AbstractModuleAdapter implements Seria
}
m_Processor = new Processor(m_StatisticsModul,this, params);
// the statistics want to be informed if the strategy or the optimizer (which provide statistical data as InterfaceAdditionalInformer) change.
if (m_StatisticsModul.getStatisticsParameter() instanceof InterfaceNotifyOnInformers)
params.addInformableInstance((InterfaceNotifyOnInformers)m_StatisticsModul.getStatisticsParameter());
// this prevents the optimizer property to be shown by the GOE if optimizerExpert is true
GenericObjectEditor.setExpertProperty(params.getClass(), "optimizer", optimizerExpert);
@ -89,7 +93,9 @@ public class GenericModuleAdapter extends AbstractModuleAdapter implements Seria
if (m_RMI && !Proxy.isProxyClass(Stat.getClass())) GUIContainer.add(new JParaPanel( RMIProxyLocal.newInstance(Stat), Stat.getName()));
else GUIContainer.add(new JParaPanel(Stat, Stat.getName()));
return new EvATabbedFrameMaker(GUIContainer);
EvATabbedFrameMaker frmMkr = new EvATabbedFrameMaker(GUIContainer);
((Processor)m_Processor).getGOParams().addInformableInstance(frmMkr);
return frmMkr;
}
public static String getName() {

View File

@ -58,6 +58,7 @@ public class Processor extends Thread implements InterfaceProcessor, InterfacePo
// private int postProcessSteps = 0;
private int runCounter = 0;
private Population resPop = null;
private boolean userAborted = false;
// transient private String m_OutputPath = "";
// transient private BufferedWriter m_OutputFile = null;
@ -110,10 +111,21 @@ public class Processor extends Thread implements InterfaceProcessor, InterfacePo
return;
}
resPop = null;
userAborted = false;
wasRestarted = false;
setOptRunning(true);
}
/**
* Return true if the optimization was stopped by the user instead of
* the termination criterion.
*
* @return
*/
public boolean wasAborted() {
return userAborted;
}
/**
*
*/
@ -124,6 +136,7 @@ public class Processor extends Thread implements InterfaceProcessor, InterfacePo
System.err.println("ERROR: Processor is already running !!");
return;
}
userAborted = false;
wasRestarted = true;
setOptRunning(true);
}
@ -233,12 +246,12 @@ public class Processor extends Thread implements InterfaceProcessor, InterfacePo
} while (isOptRunning() && !this.goParams.getTerminator().isTerminated(this.goParams.getOptimizer().getAllSolutions()));
runCounter++;
maybeFinishParamCtrl(goParams);
userAborted = !isOptRunning(); // stop is "normal" if opt wasnt set false by the user (and thus still true)
//////////////// Default stats
m_Statistics.stopOptPerformed(isOptRunning(), goParams.getTerminator().lastTerminationMessage()); // stop is "normal" if opt wasnt set false by the user (and thus still true)
m_Statistics.stopOptPerformed(!userAborted, goParams.getTerminator().lastTerminationMessage()); // stop is "normal" if opt wasnt set false by the user (and thus still true)
//////////////// PP or set results without further PP
if (isOptRunning()) {
if (!userAborted) {
resultPop = performPostProcessing();
if (resultPop==null) { // post processing disabled, so use opt. solutions
resultPop = goParams.getOptimizer().getAllSolutions().getSolutions();

View File

@ -8,6 +8,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import eva2.gui.BeanInspector;
@ -19,6 +20,9 @@ import eva2.server.go.populations.Population;
import eva2.server.go.problems.InterfaceAdditionalPopulationInformer;
import eva2.server.go.strategies.InterfaceOptimizer;
import eva2.tools.Pair;
import eva2.tools.StringSelection;
import eva2.tools.StringTools;
import eva2.tools.ToolBox;
import eva2.tools.math.Mathematics;
/**
@ -28,6 +32,17 @@ import eva2.tools.math.Mathematics;
* Several different verbosity levels are regarded.
* The method plotCurrentResults should be implemented to plot further results per iteration.
*
* All displayable data is now routed through a single pipeline, which consists in a
* list of Objects assembled in the getOutputValues method. This allows all simple data types which are
* provided by the external informer instances to be handled uniformly to the internally collected data, and
* thus they can be plotted and text-dumped in the same manner.
* Depending on the field selection state and the informers, the list of data fields is dynamically altered,
* however changes during a multi-run are ignored, since the potential of inconsistencies is too high.
*
* Listeners implementing InterfaceTextListener receive String output (human readable).
* Listeners implementing InterfaceStatisticsListener receive the raw data per iteration.
*
* @see StatsParameter
* @author mkron
*
*/
@ -45,13 +60,18 @@ public abstract class AbstractStatistics implements InterfaceTextListener, Inter
* by dynamic population optimizers, also due to the graph output.
*/
private boolean refineMultiRuns = true;
private ArrayList<double[][]> meanCollection;
private Double[] additionalInfoSums = null, lastAdditionalInfoSums=null;
// private ArrayList<double[][]> meanCollection;
private ArrayList<Double[]> sumDataCollection; // collect summed-up data of multiple runs indexed per iteration
protected Object[] currentStatObjectData = null; // the raw Object data collected in an iteration
protected Double[] currentStatDoubleData = null; // the parsed doubles collected in an iteration (or null for complex data fields)
protected String[] currentHeaderData = null; // the header Strings of the currently provided data
private Double[] statDataSumOverAll = null;
// , lastAdditionalInfoSums=null;
// say whether the object should be written to a file every time
private boolean saveParams = true;
private boolean firstPlot = true;
private int runIterCnt = 0;
private int iterationCounter = 0;
// show this many iterations of the averaged performance after a full multi-run
private int showAvgIntervals = 9;
@ -66,20 +86,27 @@ public abstract class AbstractStatistics implements InterfaceTextListener, Inter
protected double[] currentBestFit;
protected double[] currentBestFeasibleFit;
// protected double[] meanBestFeasibleFit;
protected double[] meanFitness;
protected double[] currentMeanFit;
protected double[] currentWorstFit;
// protected double[] meanBestOfRunFitness;
protected double avgPopDist;
protected double maxPopDist;
protected double currentAvgPopDist;
protected double currentMaxPopDist;
protected IndividualInterface bestCurrentIndy, bestOfRunIndy, bestOfRunFeasibleIndy, bestFeasibleAllRuns, bestIndyAllRuns;
// collect feasible results of a run
private ArrayList<IndividualInterface> runBestFeasibleList;
private ArrayList<IndividualInterface> runBestFitList;
private ArrayList<InterfaceTextListener> textListeners;
private transient ArrayList<InterfaceTextListener> textListeners;
private transient List<InterfaceStatisticsListener> dataListeners = null;
private List<InterfaceAdditionalPopulationInformer> lastInformerList = null;
private PopulationInterface lastSols = null;
private String textFieldDelimiter = "\t";
private int defaultFitCriterion = 0; // TODO this might be a user chosen int - or even more elegantly, a MOSOConverter
protected StringSelection lastFieldSelection = null; // store the graph selection at the beginning of a multi-run
protected boolean lastIsShowFull = false; // store the "show full text" stats property at the beginning of a multi-run
public AbstractStatistics() {
firstPlot = true;
@ -87,10 +114,42 @@ public abstract class AbstractStatistics implements InterfaceTextListener, Inter
functionCallSum = 0;
convergenceCnt = 0;
optRunsPerformed = 0;
runIterCnt = 0;
iterationCounter = 0;
textListeners = new ArrayList<InterfaceTextListener>();
}
public void addDataListener(InterfaceStatisticsListener l) {
if (dataListeners==null) {
dataListeners=new LinkedList<InterfaceStatisticsListener>();
}
if (!dataListeners.contains(l)) dataListeners.add(l);
}
public boolean removeDataListener(InterfaceStatisticsListener l) {
if (dataListeners==null) return false;
else return dataListeners.remove(l);
}
private void fireDataListeners() {
if (dataListeners!=null) for (InterfaceStatisticsListener l : dataListeners) {
l.notifyGenerationPerformed(currentHeaderData, currentStatObjectData, currentStatDoubleData);
}
}
/**
* Notify listeners on the start and stop of a run.
*
* @param runNumber current run (started or stopped)
* @param normal in case of stop: the stop was terminated normally (as opposted to manually)
* @param start if true, give the start signal, otherwise the stop signal
*/
private void fireDataListenersStartStop(int runNumber, boolean normal, boolean start) {
if (dataListeners!=null) for (InterfaceStatisticsListener l : dataListeners) {
if (start) l.notifyRunStarted(runNumber, m_StatsParams.getMultiRuns());
else l.notifyRunStopped(optRunsPerformed, normal);
}
}
public void addTextListener(InterfaceTextListener listener) {
if (!textListeners.contains(listener)) {
textListeners.add(listener);
@ -165,6 +224,10 @@ public abstract class AbstractStatistics implements InterfaceTextListener, Inter
}
if (runNumber == 0) {
currentHeaderData=null;
currentStatDoubleData=null;
currentStatObjectData=null;
functionCallSum = 0;
firstPlot = true;
optRunsPerformed = 0;
@ -177,12 +240,19 @@ public abstract class AbstractStatistics implements InterfaceTextListener, Inter
// meanBestFeasibleFit = null;
runBestFeasibleList = new ArrayList<IndividualInterface>();
runBestFitList = new ArrayList<IndividualInterface>();
if (refineMultiRuns) meanCollection = new ArrayList<double[][]>();
else meanCollection = null;
additionalInfoSums = null;
lastAdditionalInfoSums = null;
// if (refineMultiRuns) meanCollection = new ArrayList<double[][]>();
// else meanCollection = null;
if (refineMultiRuns) sumDataCollection = new ArrayList<Double[]>();
else sumDataCollection = null;
statDataSumOverAll = null;
// lastAdditionalInfoSums = null;
feasibleFoundAfterSum=-1;
numOfRunsFeasibleFound=0;
// store the intial graph selection state, so that modifications during runtime cannot cause inconsistencies
lastFieldSelection = (StringSelection)m_StatsParams.getFieldSelection().clone();
lastIsShowFull = m_StatsParams.isOutputAllFieldsAsText();
}
feasibleFoundAfter=-1;
bestCurrentIndy = null;
@ -191,7 +261,7 @@ public abstract class AbstractStatistics implements InterfaceTextListener, Inter
bestOfRunFeasibleIndy = null;
lastInformerList = null;
lastSols = null;
runIterCnt = 0;
iterationCounter = 0;
if (printRunIntroVerbosity()) printToTextListener("\n****** Multirun "+runNumber);
if (params != null) {
if (printRunIntroVerbosity()) printToTextListener("\nModule parameters: ");
@ -200,16 +270,17 @@ public abstract class AbstractStatistics implements InterfaceTextListener, Inter
if (printRunIntroVerbosity()) printToTextListener("\nStatistics parameters: ");
if (printRunIntroVerbosity()) printToTextListener(BeanInspector.toString(getStatisticsParameter()) + '\n');
functionCalls = 0;
fireDataListenersStartStop(runNumber, true, true);
}
public void stopOptPerformed(boolean normal, String stopMessage) {
if (TRACE) System.out.println("AbstractStatistics.stopOptPerformed");
if (lastSols==null) System.err.println("WARNING, possibly there was no call to createNextGenerationPerformed before calling stopOptPerformed (AnstractStatistics).");
if (runIterCnt < meanCollection.size()) {
if (iterationCounter < sumDataCollection.size()) {
// no good: later run was shorter than the first one. What to do? Discard the longer one:
if (TRACE) System.err.println("Error in AbstractStatistics: later run was shorter than earlier one... discarding rest...");
for (int i=meanCollection.size()-1; i>=runIterCnt; i--) meanCollection.remove(i);
for (int i=sumDataCollection.size()-1; i>=iterationCounter; i--) sumDataCollection.remove(i);
}
optRunsPerformed++;
functionCallSum += functionCalls;
@ -254,7 +325,6 @@ public abstract class AbstractStatistics implements InterfaceTextListener, Inter
}
}
if (printFinalVerbosity()) printToTextListener(".");
if (m_StatsParams.isOutputAdditionalInfo()) updateLastAdditionalInfo();
// if (currentBestFit!= null) {
// if (printRunStoppedVerbosity()) printToTextListener(" Best Fitness: " + BeanInspector.toString(currentBestFit) + "\n");
// }
@ -262,6 +332,7 @@ public abstract class AbstractStatistics implements InterfaceTextListener, Inter
if (printFinalVerbosity()) printToTextListener("\n");
finalizeOutput();
}
fireDataListenersStartStop(optRunsPerformed, normal, false);
}
private PopulationInterface makeStatsPop() {
@ -286,6 +357,24 @@ public abstract class AbstractStatistics implements InterfaceTextListener, Inter
}
/**
* Calculate the mean fitness of final best individuals over the last series of multi-runs.
*
* @return
*/
public double[] getMeanBestFit(boolean requireFeasible) {
return calcMeanFit(requireFeasible ? runBestFeasibleList : runBestFitList);
}
/**
* Calculate the median fitness of final best individuals over the last series of multi-runs.
*
* @return
*/
public double[] getMedianBestFit(boolean requireFeasible) {
return calcMedianFit(requireFeasible ? runBestFeasibleList : runBestFitList);
}
protected void finalizeOutput() {
if (printFinalVerbosity()) printToTextListener("*******\n Runs performed: " + optRunsPerformed + ", reached target " + convergenceCnt + " times with threshold " + m_StatsParams.getConvergenceRateThreshold() + ", rate " + convergenceCnt/(double)m_StatsParams.getMultiRuns() + '\n');
if (printFinalVerbosity()) printToTextListener(" Average function calls: " + (functionCallSum/optRunsPerformed) + "\n");
@ -295,41 +384,44 @@ public abstract class AbstractStatistics implements InterfaceTextListener, Inter
printToTextListener(" Average evaluations until feasible ind. was found in " + numOfRunsFeasibleFound + " runs: " + feasibleFoundAfterSum/numOfRunsFeasibleFound + " evaluations\n");
}
if (printFinalVerbosity() && (additionalInfoSums != null)) {
printToTextListener(" Averaged additional info sums: ");
for (int i=0; i<additionalInfoSums.length; i++) if (additionalInfoSums[i]!=null) printToTextListener(" \t"+(additionalInfoSums[i]/optRunsPerformed));
printToTextListener("\n Averaged last additional info: ");
for (int i=0; i<lastAdditionalInfoSums.length; i++) if (lastAdditionalInfoSums[i]!=null) printToTextListener(" \t"+(lastAdditionalInfoSums[i]/optRunsPerformed));
if (printFinalVerbosity() && (statDataSumOverAll != null)) {
printToTextListener(" Averaged sum of run statistical data: ");
for (int i=0; i<statDataSumOverAll.length; i++) if (statDataSumOverAll[i]!=null) printToTextListener(textFieldDelimiter+(statDataSumOverAll[i]/optRunsPerformed));
printToTextListener("\n Averaged last statistical data: ");
Double[] lastSum = sumDataCollection.get(sumDataCollection.size()-1);
for (int i=0; i<lastSum.length; i++) if (lastSum[i]!=null) printToTextListener(textFieldDelimiter+(lastSum[i]/optRunsPerformed));
// for (int i=0; i<lastAdditionalInfoSums.length; i++) if (lastAdditionalInfoSums[i]!=null) printToTextListener(" \t"+(lastAdditionalInfoSums[i]/optRunsPerformed));
printToTextListener("\n");
}
if (printFinalVerbosity() && (bestIndyAllRuns != null)) printIndy("Overall best", bestIndyAllRuns);
if (printFinalVerbosity() && (m_StatsParams.isOutputAdditionalInfo())) printToTextListener(getFinalAdditionalInfo()+'\n');
if (printFinalVerbosity()) printToTextListener(getFinalAdditionalInfo()+'\n');
if (optRunsPerformed>1) {
if (runBestFitList.size()>0) {
// Mathematics.svDiv((double)optRunsPerformed, meanBestOfRunFitness, meanBestOfRunFitness);
if (printFinalVerbosity()) {
double[] meanBestFit=calcMeanFit(runBestFitList);
double[] meanBestFit=getMeanBestFit(false);
printToTextListener(" MultiRun stats: Mean best fitness: " + BeanInspector.toString(meanBestFit)+"\n");
if (meanBestFit.length==1) printToTextListener(" MultiRun stats: Variance/Std.Dev.: " + BeanInspector.toString(calcStdDevVar(runBestFitList, meanBestFit[0])) + "\n");
printToTextListener(" MultiRun stats: Median best fitn.: " + BeanInspector.toString(calcMedianFit(runBestFitList))+"\n");
printToTextListener(" MultiRun stats: Median best fitn.: " + BeanInspector.toString(getMedianBestFit(false))+"\n");
}
}
if (printFinalVerbosity() && (bestFeasibleAllRuns != null)) printIndy("Overall best feasible", bestFeasibleAllRuns);
// if ((runBestFeasibleList.size()>0) && (!equalLists(runBestFeasibleList, runBestFitList))) { // is there a difference between best feasibles and best fit?
if (runBestFeasibleList.size()>0) { // always output feasible stats even if theyre equal
if (printFinalVerbosity()) {
double[] meanBestFeasibleFit=calcMeanFit(runBestFeasibleList);
double[] meanBestFeasibleFit=getMeanBestFit(true);
printToTextListener(" MultiRun stats: Mean best feasible fitness (" + numOfRunsFeasibleFound + " runs): " + BeanInspector.toString(meanBestFeasibleFit)+"\n");
if (meanBestFeasibleFit.length==1) printToTextListener(" MultiRun stats: Variance/Std.Dev.: " + BeanInspector.toString(calcStdDevVar(runBestFeasibleList, meanBestFeasibleFit[0])) + "\n");
printToTextListener(" MultiRun stats: Median best feasible fitn. (: " + numOfRunsFeasibleFound + " runs): " + BeanInspector.toString(calcMedianFit(runBestFeasibleList))+"\n");
printToTextListener(" MultiRun stats: Median best feasible fitn. (: " + numOfRunsFeasibleFound + " runs): " + BeanInspector.toString(getMedianBestFit(true))+"\n");
}
}
if (refineMultiRuns && (meanCollection != null)) {
if (refineMultiRuns && (sumDataCollection != null)) {
if (printFinalVerbosity()) printToTextListener(" Averaged performance:\n");
for (int i=0; i<meanCollection.size(); i++) divideMean(meanCollection.get(i), optRunsPerformed);
if (printFinalVerbosity()) printToTextListener(refineToText(meanCollection, showAvgIntervals));
// the summed-up values of the mean collection is divided by the number of runs
for (int i=0; i<sumDataCollection.size(); i++) divideMean(sumDataCollection.get(i), optRunsPerformed);
if (printFinalVerbosity()) printToTextListener(refineToText(sumDataCollection, showAvgIntervals));
}
}
@ -344,37 +436,24 @@ public abstract class AbstractStatistics implements InterfaceTextListener, Inter
private String getFinalAdditionalInfo() {
PopulationInterface bestPop = makeStatsPop();
StringBuffer sbuf = new StringBuffer("Overall best additional data: "+ getAdditionalInfoHeader(lastInformerList, bestPop));
// List<String> additionalFields = getAdditionalInfoHeader(lastInformerList, bestPop);
String additionalFields = getOutputHeaderString(lastInformerList, bestPop);
// String header = getOutputHeader(lastInformerList, bestPop);
List<Object> vals = getOutputValues(lastInformerList, bestPop);
StringBuffer sbuf = new StringBuffer("Overall best statistical data: ");
sbuf.append(additionalFields);
sbuf.append('\n');
appendAdditionalInfo(lastInformerList, bestPop, sbuf);
sbuf.append(StringTools.concatValues(vals, textFieldDelimiter));
// appendAdditionalInfo(lastInformerList, bestPop, sbuf);
// getOutputLine(lastInformerList, makeStatsPop());
return sbuf.toString();
}
/**
* Perform a deep equals test on the fitness vectors of both individual lists.
* @param l1
* @param l2
* @return
*/
private boolean equalLists(
ArrayList<IndividualInterface> l1,
ArrayList<IndividualInterface> l2) {
boolean equal = true;
Iterator<IndividualInterface> iter1=l1.iterator();
Iterator<IndividualInterface> iter2=l2.iterator();
IndividualInterface indy1, indy2;
if (l1.size()!=l2.size()) return false;
else while (equal && (iter1.hasNext() && iter2.hasNext())) {
equal = Arrays.equals(iter1.next().getFitness(), iter2.next().getFitness());
}
return equal;
}
private double[] calcStdDevVar(ArrayList<IndividualInterface> list, double meanFit) {
double tmp=0, sum=0;
for (Iterator iter = list.iterator(); iter.hasNext();) {
IndividualInterface indy = (IndividualInterface) iter.next();
for (Iterator<IndividualInterface> iter = list.iterator(); iter.hasNext();) {
IndividualInterface indy = iter.next();
tmp=indy.getFitness()[0]-meanFit;
sum+=(tmp*tmp);
}
@ -391,7 +470,7 @@ public abstract class AbstractStatistics implements InterfaceTextListener, Inter
*/
public static double[] calcMeanFit(List<IndividualInterface> list) {
double[] sumFit = list.get(0).getFitness().clone();
for (int i=1; i<list.size(); i++) addSecond(sumFit, list.get(i).getFitness());
for (int i=1; i<list.size(); i++) Mathematics.vvAdd(sumFit, list.get(i).getFitness(), sumFit);
Mathematics.svDiv(list.size(), sumFit, sumFit);
return sumFit;
@ -403,31 +482,59 @@ public abstract class AbstractStatistics implements InterfaceTextListener, Inter
return Mathematics.median(dblAList, false);
}
public static String refineToText(ArrayList<double[][]> result, int iterationsToShow) {
double[][] mean;
StringBuffer sbuf = new StringBuffer("Iteration\tFun.Calls\tBest\tMean\tWorst\n");
double step = result.size()/(iterationsToShow-1.);
int printedIteration=0;
public String refineToText(ArrayList<Double[]> data, int iterationsToShow) {
String hd = getOutputHeaderString(lastInformerList, null);
StringBuffer sbuf = new StringBuffer("Iteration");
sbuf.append(textFieldDelimiter);
sbuf.append(hd);
sbuf.append("\n");
refineToText(data, iterationsToShow, sbuf, textFieldDelimiter);
return sbuf.toString();
}
for(int i = 1; i < result.size()+1; i++) {
public static void refineToText(ArrayList<Double[]> data, int iterationsToShow, StringBuffer sbuf, String delim) {
double step = data.size()/(iterationsToShow-1.);
int printedIteration=0;
Double[] meanData;
for(int i = 1; i < data.size()+1; i++) {
// print the first, last and intermediate iterations requested by the integer parameter
// first one is printed always, as printedIteration=0
if ((i==result.size()) || ((i-1)==Math.round(printedIteration*step))) {
if ((i==data.size()) || ((i-1)==Math.round(printedIteration*step))) {
printedIteration++;
mean = result.get(i-1);
meanData = data.get(i-1);
sbuf.append(i);
sbuf.append("\t");
sbuf.append(BeanInspector.toString(mean[0]));
sbuf.append("\t");
sbuf.append(BeanInspector.toString(mean[1]));
sbuf.append("\t");
sbuf.append(BeanInspector.toString(mean[2]));
sbuf.append("\t");
sbuf.append(BeanInspector.toString(mean[3]));
for (int k=0; k<meanData.length; k++) {
sbuf.append(delim);
sbuf.append(BeanInspector.toString(meanData[k]));
}
sbuf.append("\n");
}
}
return sbuf.toString();
// double[][] mean;
// StringBuffer sbuf = new StringBuffer("Iteration\tFun.Calls\tBest\tMean\tWorst\n");
// double step = result.size()/(iterationsToShow-1.);
// int printedIteration=0;
//
// for(int i = 1; i < result.size()+1; i++) {
// // print the first, last and intermediate iterations requested by the integer parameter
// // first one is printed always, as printedIteration=0
// if ((i==result.size()) || ((i-1)==Math.round(printedIteration*step))) {
// printedIteration++;
// mean = result.get(i-1);
// sbuf.append(i);
// sbuf.append("\t");
// sbuf.append(BeanInspector.toString(mean[0]));
// sbuf.append("\t");
// sbuf.append(BeanInspector.toString(mean[1]));
// sbuf.append("\t");
// sbuf.append(BeanInspector.toString(mean[2]));
// sbuf.append("\t");
// sbuf.append(BeanInspector.toString(mean[3]));
// sbuf.append("\n");
// }
// }
// return sbuf.toString();
}
public abstract String getHostName();
@ -457,85 +564,231 @@ public abstract class AbstractStatistics implements InterfaceTextListener, Inter
return (resultOut != null) || (textListeners.size()>0);
}
protected String getOutputHeader(List<InterfaceAdditionalPopulationInformer> informerList, PopulationInterface pop) {
String headline = "Fun.calls\t Best\t Mean\t Worst ";
if ((informerList == null) || !m_StatsParams.isOutputAdditionalInfo()) {
return headline;
} else {
return headline + getAdditionalInfoHeader(informerList, pop);
}
}
protected String getAdditionalInfoHeader(List<InterfaceAdditionalPopulationInformer> informerList, PopulationInterface pop) {
String hdr="";
for (InterfaceAdditionalPopulationInformer informer : informerList) {
hdr = hdr + "\t " + informer.getAdditionalFileStringHeader(pop);
}
return hdr;
}
protected Pair<String,Double[]> getOutputLine(List<InterfaceAdditionalPopulationInformer> informerList, PopulationInterface pop) {
StringBuffer sbuf = new StringBuffer(Integer.toString(functionCalls));
Double[] addNums = null;
sbuf.append(" \t ");
sbuf.append(BeanInspector.toString(currentBestFit));
if (meanFitness != null) {
sbuf.append(" \t ");
sbuf.append(BeanInspector.toString(meanFitness));
} else sbuf.append(" \t #");
if (currentWorstFit != null) {
sbuf.append(" \t ");
sbuf.append(BeanInspector.toString(currentWorstFit));
} else sbuf.append(" # \t");
if (m_StatsParams.isOutputAdditionalInfo()) addNums = appendAdditionalInfo(informerList, pop, sbuf);
return new Pair<String,Double[]>(sbuf.toString(),addNums);
}
/**
* Append additional informer informations to the given StringBuffer.
* Collect all field names of both internal fields and fields of external informers. Then
* concatenate them to a string using the textFieldDelimiter of the instance.
*
* @param informerList
* @param pop
* @param sbuf
* @return
*/
protected Double[] appendAdditionalInfo(List<InterfaceAdditionalPopulationInformer> informerList, PopulationInterface pop, StringBuffer sbuf) {
if (informerList != null) {
StringBuffer addBuffer = new StringBuffer();
for (InterfaceAdditionalPopulationInformer informer : informerList) {
addBuffer.append(" \t ");
addBuffer.append(informer.getAdditionalFileStringValue(pop));
}
String addInfo = addBuffer.toString();
Double[] retVals = parseDoubles(addInfo, "\t");
if (sbuf!=null) sbuf.append(addInfo);
return retVals;
}
return null;
protected String getOutputHeaderString(List<InterfaceAdditionalPopulationInformer> informerList, PopulationInterface pop) {
List<String> headlineFields = getOutputHeaderFieldNames(informerList, pop);
return StringTools.concatFields(headlineFields, textFieldDelimiter);
}
/**
* Parse Double from a String separated by the given regular expression.
* For Substrings which do not convert to Double by Double.parseDouble(String),
* a null value is added as representative.
* Collect all field names of both internal fields and fields of external informers.
* The length of this list depends on the field selection state.
*
* @param str
* @param colSplit
* @param informerList
* @param pop
* @return
*/
public static Double[] parseDoubles(String str, String splitRegExp) {
ArrayList<Double> vals = new ArrayList<Double>();
String[] entries = str.split(splitRegExp);
for (int i=0; i<entries.length; i++) {
Double d = null;
try {
d = Double.parseDouble(entries[i]);
} catch(Exception e) { }
vals.add(d); // null if unsuccessfull
protected List<String> getOutputHeaderFieldNames(List<InterfaceAdditionalPopulationInformer> informerList, PopulationInterface pop) {
ArrayList<String> headlineFields = new ArrayList<String>(5);
headlineFields.addAll(Arrays.asList(getSimpleOutputHeader()));
if (informerList != null) {
headlineFields.addAll(getAdditionalInfoHeader(informerList, pop));
}
return (Double[])vals.toArray(new Double[vals.size()]);
return headlineFields;
}
/**
* Collect the names of data fields which are collected internally.This must correspond to the
* method {@link #getSimpleOutputValues()}.
*
* @see #getSimpleOutputValues()
* @return
*/
protected String[] getSimpleOutputHeader() {
// collect the full header by using the entries of the GraphSelectionEnum
GraphSelectionEnum[] vals = GraphSelectionEnum.values();
ArrayList<String>headerEntries = new ArrayList<String>();
headerEntries.add("FunctionCalls");
for (int i=0; i<vals.length; i++) {
if (isRequestedField(vals[i])) headerEntries.add(vals[i].toString());
}
// return new String[]{"Fun.calls","Best","Mean", "Worst"};
return headerEntries.toArray(new String[headerEntries.size()]);
}
/**
* Indicate whether the given statistics data type is requested to
* be displayed (and thus needs to be calculated).
*
* @param graphSelectionEnum
* @return
*/
protected boolean isRequestedField(GraphSelectionEnum graphSelectionEnum) {
return (lastIsShowFull || (lastFieldSelection.isSelected(graphSelectionEnum)));
}
/**
* Indicate whether the given statistics data type is requested to
* be displayed (and thus needs to be calculated).
*
* @param index the index of the field within the string selection object
* @return
*/
protected boolean isRequestedField(int index) {
return (lastIsShowFull || (lastFieldSelection.isSelected(index)));
}
/**
* Indicate whether the given statistics data type is requested to
* be displayed (and thus needs to be calculated).
*
* @param header the header string of the field in question
* @return
*/
protected boolean isRequestedAdditionalField(String header) {
return (lastIsShowFull || (lastFieldSelection.isSelected(header)));
}
/**
* Return all simple data fields collected internally. This must correspond to the
* method {@link #getSimpleOutputHeader()}.
*
* @see #getSimpleOutputHeader()
* @return
*/
protected Object[] getSimpleOutputValues() {
GraphSelectionEnum[] selEnumVals=null;
selEnumVals = GraphSelectionEnum.values();
// else selEnumVals = (GraphSelectionEnum[]) (m_StatsParams.getGraphSelection().getSelectedEnum(GraphSelectionEnum.values()));
Object[] ret = new Object[1+selEnumVals.length];
ret[0]=functionCalls;
for (int i=1; i<=selEnumVals.length; i++) {
switch (selEnumVals[i-1]) { // the field i+1 contains enum value i, because field 0 is reserved for the number of function calls
// currentBest, currentWorst, runBest, currentBestFeasible, runBestFeasible, avgPopDistance, maxPopDistance;
case currentBest: ret[i]=currentBestFit[defaultFitCriterion ]; break;
case meanFit: ret[i] = (currentMeanFit==null) ? Double.NaN : currentMeanFit[defaultFitCriterion]; break;
case currentWorst: ret[i] = (currentWorstFit==null) ? Double.NaN : currentWorstFit[defaultFitCriterion]; break;
case runBest: ret[i] = bestOfRunIndy.getFitness()[defaultFitCriterion]; break;
case currentBestFeasible: ret[i] = currentBestFeasibleFit[defaultFitCriterion]; break;
case runBestFeasible: ret[i] = bestOfRunFeasibleIndy.getFitness()[defaultFitCriterion]; break;
case avgPopDistance: ret[i] = currentAvgPopDist; break;
case maxPopDistance: ret[i] = currentMaxPopDist; break;
}
}
// all standard fields should be filled now
return ret;
// Object[] ret = new Object[4];
// ret[0]=functionCalls;
// ret[1]=currentBestFit;
// if (meanFitness!=null) ret[2]=meanFitness;
// else ret[2]="#";
// if (currentWorstFit!=null) ret[3] = currentWorstFit;
// else ret[3]="#";
// return ret;
}
/**
* Assemble a list of data fields which should be traced by the statistics class.
* Both internal fields as well as external informer data are collected in this list.
* It should be consistent with the getOutputHeader method, which provides the
* names of the corresponding fields in the same order.
* The length of this list depends on the field selection state.
*
* @see #getOutputHeader(List, PopulationInterface)
* @param informerList
* @param pop
* @return
*/
protected List<Object> getOutputValues(List<InterfaceAdditionalPopulationInformer> informerList, PopulationInterface pop) {
LinkedList<Object> values = new LinkedList<Object>();
values.addAll(Arrays.asList(getSimpleOutputValues()));
if (informerList != null) {
for (InterfaceAdditionalPopulationInformer informer : informerList) {
List<Object> reqList = Arrays.asList(informer.getAdditionalFileStringValue(pop));
values.addAll(reqList);
}
}
// remove those which are not requested
Iterator<Object> iter = values.iterator();
int cnt=0;
iter.next(); // skip the first field (function calls) which is not regarded here
if (!lastIsShowFull) while (iter.hasNext()) {
iter.next();
if (!isRequestedField(cnt++)) iter.remove();
// the cnt variable is one behind the index in the values list, because of the function calls field.
}
return values;
// return StringTools.concatValues(values, textFieldDelimiter);
}
/**
* Collect all field names of external informer instances.
* The length of this list depends on the field selection state.
* @param informerList
* @param pop
* @return
*/
protected List<String> getAdditionalInfoHeader(List<InterfaceAdditionalPopulationInformer> informerList, PopulationInterface pop) {
LinkedList<String> additionals = new LinkedList<String>();
for (InterfaceAdditionalPopulationInformer informer : informerList) {
additionals.addAll(Arrays.asList(informer.getAdditionalFileStringHeader(pop)));
// hdr = hdr + "\t " + informer.getAdditionalFileStringHeader(pop);
}
Iterator<String> iter = additionals.iterator();
if (!lastIsShowFull) while (iter.hasNext()) {
if (!isRequestedAdditionalField(iter.next())) iter.remove();
}
return additionals;
}
/**
* Take the output values and convert them to a concatenated String and a Double array.
* The array will have null entries whenever a field contained non-primitive numeric types (such
* as arrays or other non-numeric data).
* The string concatenation uses the textFieldDelimiter of the instance.
*
* @param informerList
* @param pop
* @return
*/
protected Pair<String,Object[]> getOutputData(List<InterfaceAdditionalPopulationInformer> informerList, PopulationInterface pop) {
List<Object> statValues = getOutputValues(informerList, pop);
String statValuesString = StringTools.concatValues(statValues, textFieldDelimiter);
return new Pair<String,Object[]>(statValuesString, statValues.toArray(new Object[statValues.size()]));
}
// /**
// * Append additional informer informations to the given StringBuffer.
// *
// * @param informerList
// * @param pop
// * @param sbuf
// */
// protected Double[] appendAdditionalInfo(List<InterfaceAdditionalPopulationInformer> informerList, PopulationInterface pop, StringBuffer sbuf) {
// if (informerList != null) {
// ArrayList<Object> additionalObjects = new ArrayList<Object>(5);
//
// for (InterfaceAdditionalPopulationInformer informer : informerList) {
// additionalObjects.addAll(Arrays.asList(informer.getAdditionalFileStringValue(pop)));
// }
// String addInfo = StringTools.concatValues(additionalObjects, textFieldDelimiter);
// Double[] retVals = parseDoubles(additionalObjects);
// if (sbuf!=null) sbuf.append(addInfo);
// return retVals;
//
//// StringBuffer addBuffer = new StringBuffer();
//// for (InterfaceAdditionalPopulationInformer informer : informerList) {
//// addBuffer.append(" \t ");
//// addBuffer.append(informer.getAdditionalFileStringValue(pop));
//// }
//// String addInfo = addBuffer.toString().trim();
//// if (addInfo.startsWith("\t")) addInfo.substring(2); // remove first separator to avoid returning empty field as double
//// Double[] retVals = parseDoubles(addInfo, "\t");
//// if (sbuf!=null) sbuf.append(addInfo);
//// return retVals;
// }
// return null;
// }
/**
* @deprecated The method {@link #createNextGenerationPerformed(PopulationInterface, List)} should be used instead.
*/
@ -545,24 +798,24 @@ public abstract class AbstractStatistics implements InterfaceTextListener, Inter
currentBestFit = bestfit;
currentWorstFit = worstfit;
currentBestFeasibleFit = null;
meanFitness = null;
currentMeanFit = null;
if (firstPlot) {
initPlots(m_StatsParams.getPlotDescriptions());
initPlots(null, null);
// if (doTextOutput()) printToTextListener(getOutputHeader(null, null)+'\n');
firstPlot = false;
}
if ((runIterCnt == 0) && printHeaderByVerbosity()) printToTextListener(getOutputHeader(null, null)+'\n');
if ((iterationCounter == 0) && printHeaderByVerbosity()) printToTextListener(getOutputHeaderString(null, null)+'\n');
if (doTextOutput() && printLineByVerbosity(calls)) {
Pair<String,Double[]> addInfo = getOutputLine(null, null);
Pair<String,Object[]> addInfo = getOutputData(null, null);
printToTextListener(addInfo.head()+'\n');
if (addInfo.tail()!=null) {
additionalInfoSums = updateAdditionalInfo(additionalInfoSums, addInfo.tail());
statDataSumOverAll = updateSum(statDataSumOverAll, ToolBox.parseDoubles(addInfo.tail()));
}
}
plotCurrentResults();
runIterCnt++;
iterationCounter++;
}
/**
@ -572,7 +825,7 @@ public abstract class AbstractStatistics implements InterfaceTextListener, Inter
*
* @param curInfo
*/
private Double[] updateAdditionalInfo(Double[] resultSum, Double[] curInfo) {
private static Double[] updateSum(Double[] resultSum, Double[] curInfo) {
if (resultSum==null) {
resultSum = curInfo.clone();
} else {
@ -588,17 +841,6 @@ public abstract class AbstractStatistics implements InterfaceTextListener, Inter
return resultSum;
}
/**
* Re-request the last additional information from the lastInfomerList and update the
* Double value sums.
*
* @param pop
*/
private void updateLastAdditionalInfo() {
Double[] lastVals = appendAdditionalInfo(lastInformerList, lastSols, null);
lastAdditionalInfoSums = updateAdditionalInfo(lastAdditionalInfoSums, lastVals);
}
/**
* If the population returns a specific data array, this method is called instead of doing standard output
* @param pop
@ -611,41 +853,34 @@ public abstract class AbstractStatistics implements InterfaceTextListener, Inter
/**
* Called at the very first (multirun mode) plot of a fitness curve.
*/
protected abstract void initPlots(List<String[]> description);
protected abstract void initPlots(PopulationInterface pop, List<InterfaceAdditionalPopulationInformer> informerList);
/**
* Do some data collection on the population. The informer parameter will not be handled by this method.
*
* To set a list of informers (even before the actual run is started).
* @param informerList
*/
public synchronized void createNextGenerationPerformed(PopulationInterface
pop, InterfaceOptimizer opt, List<InterfaceAdditionalPopulationInformer> informerList) {
lastInformerList = informerList;
if (firstPlot) {
initPlots(m_StatsParams.getPlotDescriptions());
// if (doTextOutput()) printToTextListener(getOutputHeader(informer, pop)+'\n');
firstPlot = false;
currentBestFeasibleFit=null;
}
if ((runIterCnt==0) && printHeaderByVerbosity()) printToTextListener(getOutputHeader(informerList, pop)+'\n');
public void setInitialInformerList(List<InterfaceAdditionalPopulationInformer> informerList) {
lastInformerList = informerList;
}
if (pop.getSpecificData() != null) {
plotSpecificData(pop, informerList);
return;
}
// by default plotting only the best
/**
* Collect statistical data for the given population, such as best individual, best fitness,
* population measures.
* This should be called exactly once per generation.
*
* @param pop
*/
private void collectPopData(PopulationInterface pop) {
bestCurrentIndy = pop.getBestIndividual().getClone();
if ((bestIndyAllRuns == null) || (secondIsBetter(bestIndyAllRuns, bestCurrentIndy))) {
bestIndyAllRuns = bestCurrentIndy;
// printToTextListener("new best found!, last was " + BeanInspector.toString(bestIndividualAllover) + "\n");
}
if ((bestOfRunIndy==null) || (secondIsBetter(bestOfRunIndy, bestCurrentIndy))) {
bestOfRunIndy=bestCurrentIndy;
}
// IndividualInterface WorstInd = Pop.getWorstIndividual();
if (bestCurrentIndy == null) {
System.err.println("createNextGenerationPerformed BestInd==null");
}
currentBestFit = bestCurrentIndy.getFitness().clone();
if (currentBestFit == null) {
System.err.println("BestFitness==null !");
@ -656,7 +891,7 @@ public abstract class AbstractStatistics implements InterfaceTextListener, Inter
if (currentBestFeasibleFit==null) { // feasible indy found for the first time
numOfRunsFeasibleFound++;
feasibleFoundAfter=((Population)pop).getFunctionCalls();
if (feasibleFoundAfterSum<0) feasibleFoundAfterSum=0.; // initial signalling value was -1.
if (feasibleFoundAfterSum<0) feasibleFoundAfterSum=0.; // initial signaling value was -1.
feasibleFoundAfterSum+=feasibleFoundAfter;
}
currentBestFeasibleFit = curBestFeasible.getFitness().clone();
@ -670,52 +905,104 @@ public abstract class AbstractStatistics implements InterfaceTextListener, Inter
}
} else System.err.println("INVALID POPULATION (AbstractStatistics)");
meanFitness = pop.getMeanFitness().clone();
currentWorstFit = pop.getWorstIndividual().getFitness().clone();
// collect these data fields only if requested by the user
if (lastIsShowFull || GraphSelectionEnum.doPlotMean(lastFieldSelection)) currentMeanFit = pop.getMeanFitness().clone();
else currentMeanFit = null;
if (lastIsShowFull || GraphSelectionEnum.doPlotWorst(lastFieldSelection)) currentWorstFit = pop.getWorstIndividual().getFitness().clone();
else currentWorstFit = null;
functionCalls = pop.getFunctionCalls();
if (GraphSelectionEnum.doPlotAvgDist(m_StatsParams.getGraphSelection())
|| GraphSelectionEnum.doPlotMaxPopDist(m_StatsParams.getGraphSelection())) {
if (lastIsShowFull || GraphSelectionEnum.doPlotAvgDist(lastFieldSelection)
|| GraphSelectionEnum.doPlotMaxPopDist(lastFieldSelection)) {
double[] measures = ((Population)pop).getPopulationMeasures((InterfaceDistanceMetric)null);
if (measures != null) {
avgPopDist = measures[0];
maxPopDist = measures[2];
currentAvgPopDist = measures[0];
currentMaxPopDist = measures[2];
}
}
}
if (meanCollection != null) {
/**
* Do some data collection on the population. The informer parameter will not be handled by this method.
*
*/
public synchronized void createNextGenerationPerformed(PopulationInterface
pop, InterfaceOptimizer opt, List<InterfaceAdditionalPopulationInformer> informerList) {
lastInformerList = informerList;
if (firstPlot) {
initPlots(pop, informerList);
// if (doTextOutput()) printToTextListener(getOutputHeader(informer, pop)+'\n');
firstPlot = false;
currentBestFeasibleFit=null;
}
if (pop.getSpecificData() != null) { // this is more or less deprecated. the standard population implementation will always return null. However the ES module wont
plotSpecificData(pop, informerList);
return;
}
collectPopData(pop);
if (iterationCounter==0) {
List<String> headerFields=getOutputHeaderFieldNames(informerList, pop);
currentHeaderData = headerFields.toArray(new String[headerFields.size()]);
String headerLine = StringTools.concatFields(headerFields, textFieldDelimiter);
if (printHeaderByVerbosity()) printToTextListener(headerLine+'\n');
}
lastSols = (opt!=null) ? new Population(opt.getAllSolutions().getSolutions()) : pop;
// Pair<String,Double[]> addData = getOutputData(informerList, lastSols);
Pair<String,Object[]> addData = getOutputData(informerList, lastSols);
if (doTextOutput()) { // this is where the text output is actually written
if (printLineByVerbosity(iterationCounter)) {
// printToTextListener(functionCalls + textFieldDelimiter);
printToTextListener(addData.head()+'\n');
}
}
currentStatObjectData = addData.tail();
currentStatDoubleData = ToolBox.parseDoubles(currentStatObjectData);
if (currentStatObjectData!=null) {
statDataSumOverAll = updateSum(statDataSumOverAll, currentStatDoubleData); // this adds up all data of a single run
} else {
System.err.println("Warning in AbstractStatistics!");
}
if (sumDataCollection != null) {
// Collect average data
double[][] means = null;
if ((optRunsPerformed==0) && (meanCollection.size()<=runIterCnt)) {
Double[] sumDataEntry = null;
if ((optRunsPerformed==0) && (sumDataCollection.size()<=iterationCounter)) {
// in the first run, newly allocate the arrays
means = new double[4][currentBestFit.length];
meanCollection.add(means);
// assume that all later data sets will have the same format
// means = new double[4][currentBestFit.length]; // this only fits fitness vectors! of course this is sensible for multi-crit fitnesses...
sumDataEntry = currentStatDoubleData.clone();
sumDataCollection.add(sumDataEntry);
} else {
if (meanCollection.size()<=runIterCnt) {// bad case!
if (sumDataCollection.size()<=iterationCounter) {// bad case!
// may happen for dynamic pop-sizes, e.g. in Tribes, when runs do not necessarily send the
// "generation performed" event the same number of times.
// thus: dont do an update for events that are "too late"
means = null;
} else means = meanCollection.get(runIterCnt);
}
if (means != null) updateMeans(means, functionCalls, currentBestFit, meanFitness, currentWorstFit);
}
// meanCollection.set(pop.getGenerations()-1, means);
lastSols = (opt!=null) ? new Population(opt.getAllSolutions().getSolutions()) : pop;
if (doTextOutput()) {
Pair<String,Double[]> addInfo = getOutputLine(informerList, lastSols);
if (printLineByVerbosity(runIterCnt)) {
printToTextListener(addInfo.head()+'\n');
}
// updateAdditionalInfo(addInfo.tail());
if (addInfo.tail()!=null) {
additionalInfoSums = updateAdditionalInfo(additionalInfoSums, addInfo.tail());
sumDataEntry = null;
} else sumDataEntry = sumDataCollection.get(iterationCounter);
if (sumDataEntry != null) updateSum(sumDataEntry, currentStatDoubleData); // this adds up data of a single iteration across multiple runs
}
}
// if (doTextOutput()) {
// Pair<String,Double[]> addInfo = getOutputLine(informerList, lastSols);
//
// if (printLineByVerbosity(runIterCnt)) {
// printToTextListener(addInfo.head()+'\n');
// }
// currentAdditionalInfo = addInfo.tail();
// if (addInfo.tail()!=null) {
// additionalInfoSums = updateAdditionalInfo(additionalInfoSums, addInfo.tail());
// }
// }
plotCurrentResults();
fireDataListeners();
runIterCnt++;
iterationCounter++;
}
/**
@ -759,21 +1046,11 @@ public abstract class AbstractStatistics implements InterfaceTextListener, Inter
return (m_StatsParams.getOutputVerbosity().getSelectedTagID() >= StatsParameter.VERBOSITY_KTH_IT);
}
private void updateMeans(double[][] means, double funCalls, double[] bestFit, double[] meanFit, double[] worstFit) {
means[0][0]+=funCalls;
addSecond(means[1], bestFit);
addSecond(means[2], meanFit);
addSecond(means[3], worstFit);
}
private static void divideMean(double[][] mean, double d) {
for (int i=0; i<mean.length; i++) {
for (int j=0; j<mean[i].length; j++) mean[i][j] /= d;
}
}
public static void addSecond(double[] mean, double[] fit) {
for (int i=0; i<mean.length; i++) mean[i] += fit[i];
private static void divideMean(Double[] mean, double d) {
for (int j=0; j<mean.length; j++) if (mean[j]!=null) mean[j] /= d;
// for (int i=0; i<mean.length; i++) {
// for (int j=0; j<mean[i].length; j++) mean[i][j] /= d;
// }
}
/**

View File

@ -2,29 +2,40 @@ package eva2.server.stat;
import eva2.tools.StringSelection;
/**
* An Enum to be used in the statistics classes for identifying data fields.
*
* @see AbstractStatistics
* @author mkron
*
*/
public enum GraphSelectionEnum {
currentBest, currentWorst, runBest, currentBestFeasible, runBestFeasible, avgPopDistance, maxPopDistance;
public static boolean doPlotCurrentBest(StringSelection sel) {
return sel.isSelected(GraphSelectionEnum.currentBest.ordinal());
}
public static boolean doPlotRunBest(StringSelection sel) {
return sel.isSelected(GraphSelectionEnum.runBest.ordinal());
}
// DONT change this order, or the relation to AbstractStatistics will be lost
currentBest, meanFit, currentWorst, runBest, currentBestFeasible, runBestFeasible, avgPopDistance, maxPopDistance;
// public static boolean doPlotCurrentBest(StringSelection sel) {
// return sel.isSelected(GraphSelectionEnum.currentBest.ordinal());
// }
//
// public static boolean doPlotRunBest(StringSelection sel) {
// return sel.isSelected(GraphSelectionEnum.runBest.ordinal());
// }
//
public static boolean doPlotWorst(StringSelection sel) {
return sel.isSelected(GraphSelectionEnum.currentWorst.ordinal());
}
public static boolean doPlotCurrentBestFeasible(StringSelection sel) {
return sel.isSelected(GraphSelectionEnum.currentBestFeasible.ordinal());
public static boolean doPlotMean(StringSelection sel) {
return sel.isSelected(GraphSelectionEnum.meanFit.ordinal());
}
public static boolean doPlotRunBestFeasible(StringSelection sel) {
return sel.isSelected(GraphSelectionEnum.runBestFeasible.ordinal());
}
// public static boolean doPlotCurrentBestFeasible(StringSelection sel) {
// return sel.isSelected(GraphSelectionEnum.currentBestFeasible.ordinal());
// }
//
// public static boolean doPlotRunBestFeasible(StringSelection sel) {
// return sel.isSelected(GraphSelectionEnum.runBestFeasible.ordinal());
// }
//
public static boolean doPlotAvgDist(StringSelection sel) {
return sel.isSelected(GraphSelectionEnum.avgPopDistance.ordinal());
}

View File

@ -0,0 +1,36 @@
package eva2.server.stat;
/**
* An interface to listen to statistical data of an optimization run.
*
* @see AbstractStatistics
* @author mkron
*
*/
public interface InterfaceStatisticsListener {
/**
* Method called by the statistics class with the current data header, raw Objects and
* Double values (as far as the raw objects could be converted to double - otherwise null).
*
* @param header
* @param statObjects
* @param statDoubles
*/
public void notifyGenerationPerformed(String[] header, Object[] statObjects, Double[] statDoubles);
/**
* Method called at the start of a single run.
*
* @param runNumber the number of the new run, starting with 0
* @param plannedMultiRuns the number of planned multi-runs
*/
public void notifyRunStarted(int runNumber, int plannedMultiRuns);
/**
* Method called at the end of a single run.
*
* @param runsPerformed the number of runs performed
* @param completedLastRun true, if the last run was stopped normally, otherwise false, e.g. indicating a user break
*/
public void notifyRunStopped(int runsPerformed, boolean completedLastRun);
}

View File

@ -1,35 +1,20 @@
package eva2.server.stat;
/*
* Title: EvA2
* Description:
* Copyright: Copyright (c) 2003
* Company: University of Tuebingen, Computer Architecture
* @author Holger Ulmer, Felix Streichert, Hannes Planatscher
* @version: $Revision: 10 $
* $Date: 2006-01-18 11:02:22 +0100 (Wed, 18 Jan 2006) $
* $Author: streiche $
*/
/*==========================================================================*
* IMPORTS
*==========================================================================*/
import java.util.List;
import eva2.tools.SelectedTag;
import eva2.tools.StringSelection;
/*==========================================================================*
* INTERFACE DECLARATION
*==========================================================================*/
/**
* An interface to encapsulate statistics parameters.
*
* @see StatsParameter
*/
public interface InterfaceStatisticsParameter {
public String getName();
public void saveInstance();
// public String globalInfo();
// public void setTextoutput(int i);
public void setPlotoutput(int i);
public int GetPlotoutput();
// public void setPlotoutput(int i); // noone knows what these were useful for...
// public int GetPlotoutput();
// public int GetTextoutput();
// public String textoutputTipText();
// public String plotFrequencyTipText();
@ -37,19 +22,19 @@ public interface InterfaceStatisticsParameter {
public int getMultiRuns();
public String multiRunsTipText();
public String GetInfoString();
public void setInfoString(String s);
// public String GetInfoString();
// public void setInfoString(String s);
public boolean GetuseStatPlot();
public void setuseStatPlot(boolean x);
public boolean GetUseStatPlot(); // use averaged graph for multi-run plots or not
public void setUseStatPlot(boolean x); // activate averaged graph for multi-run plots
public List<String[]> getPlotDescriptions();
// public List<String[]> getPlotDescriptions();
// public SelectedTag getPlotData();
// public void setPlotData(SelectedTag newMethod);
public StringSelection getGraphSelection();
public void setGraphSelection(StringSelection v);
public StringSelection getFieldSelection();
public void setFieldSelection(StringSelection v);
public String getResultFilePrefix();
public void SetResultFilePrefix(String x);
@ -60,8 +45,8 @@ public interface InterfaceStatisticsParameter {
public void SetShowTextOutput(boolean show);
public boolean isShowTextOutput();
public boolean isOutputAdditionalInfo();
public void setOutputAdditionalInfo(boolean bShowAdd);
public boolean isOutputAllFieldsAsText();
public void setOutputAllFieldsAsText(boolean bShowFullText);
public void setOutputVerbosity(SelectedTag sTag);
public SelectedTag getOutputVerbosity();

View File

@ -1,5 +1,11 @@
package eva2.server.stat;
/**
* A very simple interface class to receive raw String data.
*
* @author mkron
*
*/
public interface InterfaceTextListener {
public void print(String str);
public void println(String str);

View File

@ -13,9 +13,6 @@ package eva2.server.stat;
/*==========================================================================*
* IMPORTS
*==========================================================================*/
import java.io.File;
import java.io.FileOutputStream;
import java.io.PrintWriter;
import java.io.Serializable;
import java.net.InetAddress;
import java.util.ArrayList;
@ -23,31 +20,32 @@ import java.util.List;
import eva2.server.go.PopulationInterface;
import eva2.server.go.problems.InterfaceAdditionalPopulationInformer;
import eva2.tools.math.Mathematics;
/*
* ==========================================================================*
* CLASS DECLARATION
* ==========================================================================
*/
/**
* This simple statistics implementation can collect all Object data available during runs.
* Be aware that the memory requirements can be excessive depending on the data produced by
* the additional informers, and depending on the selected fields to be collected.
* Therefore, the default is not to log the data but just print it using the super class.
*
* @see InterfaceAdditionalPopulationInformer
* @see AbstractStatistics
*/
public class StatisticsStandalone extends AbstractStatistics implements InterfaceStatistics, Serializable {
private static final long serialVersionUID = 2621394534751748968L;
private static final long serialVersionUID = -8451652609212653368L;
private static String m_MyHostName = "unknown";
private String m_InfoString;
private ArrayList<ArrayList<double[]>[]> m_Result;
private ArrayList<String> m_ResultString;
// private String m_InfoString;
private ArrayList<ArrayList<Object[]>> m_ResultData = null;
private ArrayList<String> m_ResultHeaderStrings = null;
private boolean collectData = false;
// private boolean m_useMedian = false;
private double m_FitnessMeanofALL;
private double m_SumOfBestFit = 0;
private double[] m_BestFitnessAtEnd;
private double m_FitnessMedianofALL;
// private double m_MeanFinalFitness;
// private double m_SumLastBestCurrentFit = 0;
// private double[] m_LastBestCurrentFit;
// private double m_FitnessMedianofALL;
public StatisticsStandalone(InterfaceStatisticsParameter statParams) {
super();
@ -76,13 +74,24 @@ public class StatisticsStandalone extends AbstractStatistics implements Interfac
this(new StatsParameter());
}
protected void initPlots(List<String[]> description) {
if (m_Result.size() == 0)
initContainer(new String[] {"Fitness"});
protected void initPlots(PopulationInterface pop, List<InterfaceAdditionalPopulationInformer> informerList) {
if (collectData) {
m_ResultData = new ArrayList<ArrayList<Object[]>>(m_StatsParams.getMultiRuns());
List<String> description = getOutputHeaderFieldNames(informerList, pop);
m_ResultHeaderStrings = new ArrayList<String>();
for (String str : description) m_ResultHeaderStrings.add(str);
for (int i = 0; i < m_StatsParams.getMultiRuns(); i++)
m_ResultData.add(new ArrayList<Object[]>());
} else {
m_ResultData=null;
m_ResultHeaderStrings = null;
}
}
protected void plotCurrentResults() {
((ArrayList<double[]>[]) m_Result.get(0))[optRunsPerformed].add(new double[] {functionCalls, currentBestFit[0]});
if (collectData && (m_ResultData!=null)) {
m_ResultData.get(optRunsPerformed).add(currentStatObjectData);
}
}
public void plotSpecificData(PopulationInterface pop, List<InterfaceAdditionalPopulationInformer> informerList) {
@ -90,110 +99,103 @@ public class StatisticsStandalone extends AbstractStatistics implements Interfac
double[] specificData = pop.getSpecificData();
if (specificData != null) {
for (int i = 0; i < specificData.length; i++) {
((ArrayList<double[]>[]) m_Result.get(i))[optRunsPerformed].add(new double[] {functionCalls, specificData[i]});
// ((ArrayList<Object[]>[]) m_Result.get(i))[optRunsPerformed].add(new Double[] {new Double(functionCalls), specificData[i]});
m_ResultData.get(optRunsPerformed).add(new Object[] {new Double(functionCalls), specificData});
}
}
}
private void initContainer(String[] description) {
for (int i = 0; i < description.length; i++) {
m_Result.add(new ArrayList[m_StatsParams.getMultiRuns()]);
m_ResultString.add(description[i]);
}
for (int i = 0; i < m_Result.size(); i++)
((ArrayList[]) m_Result.get(i))[optRunsPerformed] = new ArrayList<double[]>();
}
// public void startOptPerformed(String infoString, int runNumber, Object params) {
// super.startOptPerformed(infoString, runNumber, params);
// if (runNumber == 0) {
// m_Result = new ArrayList<ArrayList<Object[]>>();
// m_ResultString = new ArrayList<String>();
//// m_LastBestCurrentFit = new double[this.m_StatsParams.getMultiRuns()];
//// m_SumLastBestCurrentFit=0;
// } else {
// for (int i = 0; i < m_Result.size(); i++)
// ((ArrayList[]) m_Result.get(i))[optRunsPerformed] = new ArrayList<ArrayList<double[]>[]>();
// }
// m_InfoString = infoString;
// }
public void startOptPerformed(String infoString, int runNumber, Object params) {
super.startOptPerformed(infoString, runNumber, params);
if (runNumber == 0) {
m_Result = new ArrayList<ArrayList<double[]>[]>();
m_ResultString = new ArrayList<String>();
m_BestFitnessAtEnd = new double[this.m_StatsParams.getMultiRuns()];
} else {
for (int i = 0; i < m_Result.size(); i++)
((ArrayList[]) m_Result.get(i))[optRunsPerformed] = new ArrayList<ArrayList<double[]>[]>();
}
m_InfoString = infoString;
}
// public void stopOptPerformed(boolean normal, String stopMessage) {
// super.stopOptPerformed(normal, stopMessage);
// if (bestCurrentIndy != null) {
// m_SumLastBestCurrentFit = m_SumLastBestCurrentFit + bestCurrentIndy.getFitness()[0];
// m_LastBestCurrentFit[optRunsPerformed-1] = bestCurrentIndy.getFitness()[0];
// }
//
// //System.out.println("stopOptPerformed :"+m_OptRunsPerformed);
// if (optRunsPerformed == m_StatsParams.getMultiRuns()) {
// m_MeanFinalFitness = m_SumLastBestCurrentFit / ((double) optRunsPerformed);
// //System.out.println("m_FitnessMeanofALL "+m_FitnessMeanofALL);
// m_FitnessMedianofALL = Mathematics.median(m_LastBestCurrentFit, true);
//
//// finalizeOutput();
// }
// }
public void stopOptPerformed(boolean normal, String stopMessage) {
super.stopOptPerformed(normal, stopMessage);
if (bestCurrentIndy != null) {
m_SumOfBestFit = m_SumOfBestFit + bestCurrentIndy.getFitness()[0];
m_BestFitnessAtEnd[optRunsPerformed-1] = bestCurrentIndy.getFitness()[0];
}
//System.out.println("stopOptPerformed :"+m_OptRunsPerformed);
if (optRunsPerformed == m_StatsParams.getMultiRuns()) {
m_FitnessMeanofALL = m_SumOfBestFit / ((double) optRunsPerformed);
//System.out.println("m_FitnessMeanofALL "+m_FitnessMeanofALL);
m_FitnessMedianofALL = Mathematics.median(m_BestFitnessAtEnd, true);
// finalizeOutput();
}
}
/**
* write result of all runs.
*/
public static File[] writeResult_All_Container(ArrayList<StatisticsStandalone> StatList, String FileName) {
File ret[] = new File[((StatisticsStandalone) StatList.get(0)).m_Result.size()];
//System.out.println("StatList.size " + StatList.size());
for (int counter = 0; counter < ret.length; counter++) {
ArrayList<String> staticResult = new ArrayList<String>();
String staticDescription = "calls ";
for (int index = 0; index < StatList.size(); index++) {
StatisticsStandalone Stat = (StatisticsStandalone) StatList.get(index);
staticDescription = staticDescription + Stat.m_InfoString + " ";
for (int row = 0; row < ((ArrayList[]) Stat.m_Result.get(counter))[0].size();
row++) {
double mean = 0;
double calls = 0;
double[] value = new double[((ArrayList[]) Stat.m_Result.get(counter)).
length];
for (int i = 0; i < ((ArrayList[]) Stat.m_Result.get(counter)).length; i++) {
//double[] result = (double[]) Stat.m_QRestultContainer[i].get(row);
double[] result = (double[]) ((ArrayList[]) Stat.m_Result.get(counter))[i].get(row);
mean = mean + result[1];
calls = result[0];
value[i] = result[1];
}
//mean = mean / Stat.m_QRestultContainer.length;
mean = mean / ((ArrayList[]) Stat.m_Result.get(counter)).length;
// if (m_useMedian == true) // use the median
// mean = getMedian(value);
if (row == staticResult.size())
staticResult.add(new String("" + calls));
String temp = (String) staticResult.get(row);
String newrow = new String(temp + " " + mean);
//System.out.println("newrow"+newrow);
staticResult.set(row, newrow);
} // end of for row
} // end of for index
try {
File d = new File(m_MyHostName);
d.mkdir();
String info = (String) ((StatisticsStandalone) StatList.get(0)).m_ResultString.get(counter);
ret[counter] = new File(m_MyHostName + "//" + FileName + "_" + info + "_" + counter + ".txt");
ret[counter].createNewFile();
PrintWriter Out = new PrintWriter(new FileOutputStream(ret[counter]));
Out.println(staticDescription);
for (int i = 0; i < staticResult.size(); i++) {
Out.println((String) staticResult.get(i));
//System.out.println("print " + (String) staticResult.get(i));
}
Out.flush();
Out.close();
} catch (Exception e) {
System.out.println("Error in wreiteresult" + e.getMessage());
e.printStackTrace();
}
staticResult = null;
staticDescription = "";
}
return ret;
}
// /**
// * write result of all runs.
// */
// public static File[] writeResult_All_Container(ArrayList<StatisticsStandalone> StatList, String FileName) {
// File ret[] = new File[((StatisticsStandalone) StatList.get(0)).m_Result.size()];
// //System.out.println("StatList.size " + StatList.size());
// for (int counter = 0; counter < ret.length; counter++) {
// ArrayList<String> staticResult = new ArrayList<String>();
// String staticDescription = "calls ";
// for (int index = 0; index < StatList.size(); index++) {
// StatisticsStandalone Stat = (StatisticsStandalone) StatList.get(index);
// staticDescription = staticDescription + Stat.m_InfoString + " ";
// for (int row = 0; row < ((ArrayList[]) Stat.m_Result.get(counter))[0].size();
// row++) {
// double mean = 0;
// double calls = 0;
// double[] value = new double[((ArrayList[]) Stat.m_Result.get(counter)).
// length];
// for (int i = 0; i < ((ArrayList[]) Stat.m_Result.get(counter)).length; i++) {
// //double[] result = (double[]) Stat.m_QRestultContainer[i].get(row);
// double[] result = (double[]) ((ArrayList[]) Stat.m_Result.get(counter))[i].get(row);
// mean = mean + result[1];
// calls = result[0];
// value[i] = result[1];
// }
// //mean = mean / Stat.m_QRestultContainer.length;
// mean = mean / ((ArrayList[]) Stat.m_Result.get(counter)).length;
//// if (m_useMedian == true) // use the median
//// mean = getMedian(value);
// if (row == staticResult.size())
// staticResult.add(new String("" + calls));
// String temp = (String) staticResult.get(row);
// String newrow = new String(temp + " " + mean);
// //System.out.println("newrow"+newrow);
// staticResult.set(row, newrow);
// } // end of for row
// } // end of for index
// try {
// File d = new File(m_MyHostName);
// d.mkdir();
// String info = (String) ((StatisticsStandalone) StatList.get(0)).m_ResultString.get(counter);
// ret[counter] = new File(m_MyHostName + "//" + FileName + "_" + info + "_" + counter + ".txt");
// ret[counter].createNewFile();
// PrintWriter Out = new PrintWriter(new FileOutputStream(ret[counter]));
// Out.println(staticDescription);
// for (int i = 0; i < staticResult.size(); i++) {
// Out.println((String) staticResult.get(i));
// //System.out.println("print " + (String) staticResult.get(i));
// }
// Out.flush();
// Out.close();
// } catch (Exception e) {
// System.out.println("Error in wreiteresult" + e.getMessage());
// e.printStackTrace();
// }
// staticResult = null;
// staticDescription = "";
// }
// return ret;
// }
// /**
// * write result of all runs.
@ -243,21 +245,52 @@ public class StatisticsStandalone extends AbstractStatistics implements Interfac
// return ret;
// }
/**
*
*/
public double getBestFitnessMeanofALL() {
return m_FitnessMeanofALL;
}
/**
*
*/
public double getBestFitnessMedianofALL() {
return m_FitnessMedianofALL;
}
// /**
// *
// */
// public double getBestFitnessMeanofALL() {
// return m_MeanFinalFitness;
// }
//
// /**
// *
// */
// public double getBestFitnessMedianofALL() {
// return m_FitnessMedianofALL;
// }
public String getHostName() {
return m_MyHostName;
}
/**
* Check whether data collection is activated, which stores an Object[] for every iteration and
* every multi-run.
* @return
*/
public boolean isCollectData() {
return collectData;
}
/**
* Set state of full data collection, which stores an Object[] for every iteration and
* every multi-run.
*
* @param collectFullData
*/
public void setCollectData(boolean collectFullData) {
this.collectData = collectFullData;
}
public ArrayList<ArrayList<Object[]>> getCollectedData() {
return m_ResultData;
}
public ArrayList<Object[]> getCollectedRunData(int runIndex) {
return m_ResultData.get(runIndex);
}
public ArrayList<String> getCollectedDataHeaders() {
return m_ResultHeaderStrings;
}
}

View File

@ -29,21 +29,17 @@ import eva2.server.EvAServer;
import eva2.server.go.PopulationInterface;
import eva2.server.go.problems.InterfaceAdditionalPopulationInformer;
import eva2.tools.EVAERROR;
import eva2.tools.StringSelection;
import eva2.tools.Pair;
import eva2.tools.jproxy.MainAdapterClient;
import eva2.tools.jproxy.RMIProxyLocal;
import eva2.tools.jproxy.RMIProxyRemote;
/*==========================================================================*
* CLASS DECLARATION
*==========================================================================*/
/**
* A statistics class to plot fitness curves in client-server mode.
* A statistics class to plot fitness curves in client-server mode. Mainly, arrays of GraphWindows
* and Graphs are managed and the selected data fields are plotted.
*
*/
public class StatisticsWithGUI extends AbstractStatistics implements Serializable, InterfaceStatistics {
/**
*
*/
private static final long serialVersionUID = 3213603978877954103L;
// Plot frames:
private GraphWindow[] m_FitnessFrame; // frame for the fitness plots
@ -55,7 +51,7 @@ public class StatisticsWithGUI extends AbstractStatistics implements Serializabl
private MainAdapterClient m_MainAdapterClient; // the connection to the client MainAdapter
private JTextoutputFrameInterface m_ProxyPrinter;
private StringSelection lastGraphSelection;
private transient List<Pair<String, Integer>> graphDesc=null; // list of descriptor strings and optional indices. strictly its redundant since super.lastGraphSelection is always available. However it spares some time.
//////////////
protected static String m_MyHostName = null;
@ -105,12 +101,9 @@ public class StatisticsWithGUI extends AbstractStatistics implements Serializabl
public synchronized void startOptPerformed(String infoString, int runNumber, Object goParams) {
super.startOptPerformed(infoString, runNumber, goParams);
m_GraphInfoString = infoString;
if (runNumber == 0) {
lastGraphSelection = (StringSelection)m_StatsParams.getGraphSelection().clone();
}
// m_TextCounter = m_StatisticsParameter.GetTextoutput();
m_PlotCounter = m_StatsParams.GetPlotoutput();
// m_PlotCounter = m_StatsParams.GetPlotoutput();
if ((m_FitnessFrame!=null) && (m_FitnessFrame[0]!=null)) {
PlotInterface p = m_FitnessFrame[0].getPlotter();
if ((p!=null) && p.isValid()) ((Plot)p).getFunctionArea().clearLegend();
@ -135,8 +128,8 @@ public class StatisticsWithGUI extends AbstractStatistics implements Serializabl
for (int j = 0; j < m_FitnessGraph[i].length; j++) {
m_StatGraph[i][j].setInfoString(
(m_FitnessGraph[i][j].getInfo().length() > 0 ? (m_FitnessGraph[i][j].getInfo() + "_") : "" )
+ (m_StatsParams.GetInfoString().length() > 0 ? (m_StatsParams.GetInfoString() + "_") : "" )
+ m_StatsParams.GetInfoString()
// + (m_StatsParams.GetInfoString().length() > 0 ? (m_StatsParams.GetInfoString() + "_") : "" )
// + m_StatsParams.GetInfoString()
+ "Mean_of_" + fullRuns + " ",
(float) 2.0);
if (normal && m_FitnessFrame[i].isValid()) {
@ -159,42 +152,55 @@ public class StatisticsWithGUI extends AbstractStatistics implements Serializabl
if (m_ProxyPrinter != null) m_ProxyPrinter.setShow(m_StatsParams.isShowTextOutput());
}
protected void initPlots(List<String[]> description) {
protected void initPlots(PopulationInterface pop, List<InterfaceAdditionalPopulationInformer> informerList) {
if (TRACE) System.out.println("initPlots");
if (m_StatsParams instanceof StatsParameter) {
// StringSelection ss = ((StatsParameter)m_StatsParams).getGraphSelection();
graphDesc = lastFieldSelection.getSelectedWithIndex();
// for (int i=0; i<description.get(0).length; i++) graphDesc.add(description.get(0)[i]);
} else {
graphDesc = null;
System.err.println("Error in StatisticsWithGUI.initPlots()!");
}
maybeShowProxyPrinter();
int graphCount = description.size();
int windowCount = 1; // TODO this was earlier description.length for the 2-D String-Array returned by m_StatsParams.getPlotDescriptions, which however always returned an array of length 1 (in the first dim).
int graphCount = graphDesc.size();
// System.out.println("Initializing " + graphCount + " plots (StatisticsWithGUI)");
m_FitnessFrame = new GraphWindow[graphCount];
m_FitnessFrame = new GraphWindow[windowCount];
for (int i = 0; i < m_FitnessFrame.length; i++) {
// m_FitnessFrame[i] = GraphWindow.getInstance(m_MainAdapterClient, m_GraphInfoString + " " + i + " " + " on " + m_MyHostName + ", VM " + EvAServer.m_NumberOfVM, "function calls", "fitness");
m_FitnessFrame[i] = GraphWindow.getInstance(m_MainAdapterClient, "Optimization " + i + " " + " on " + m_MyHostName + ", VM " + EvAServer.m_NumberOfVM, "function calls", "fitness");
}
m_FitnessGraph = new Graph[graphCount][];
m_FitnessGraph = new Graph[windowCount][];
// contains one graph for every value to be plotted (best / worst / best+worst)
// TODO Im really not sure why this is a 2-dimensional array. shouldnt one be enough?
for (int i = 0; i < m_FitnessGraph.length; i++) {
m_FitnessGraph[i] = new Graph[((String[]) description.get(i)).length];
m_FitnessGraph[i] = new Graph[graphCount];
for (int j = 0; j < m_FitnessGraph[i].length; j++) {
String[] d = (String[]) description.get(i);
// String[] d = (String[]) description.get(i);
// this is where the column string for ascii export is created! Uah!
m_FitnessGraph[i][j] =
m_FitnessFrame[i].getNewGraph(d[j] + "_" +
m_StatsParams.GetInfoString() +
m_FitnessFrame[i].getNewGraph(graphDesc.get(j).head + "_" +
// m_StatsParams.GetInfoString() +
m_GraphInfoString);
// m_FitnessGraph[i][j] =
// m_FitnessFrame[i].getNewGraph(d[j] + "_" +
// m_StatsParams.GetInfoString() +
// m_GraphInfoString);
m_FitnessGraph[i][j].jump();
}
}
if (m_StatsParams.getMultiRuns() > 1 &&
m_StatsParams.GetuseStatPlot() == true) {
String Info = m_StatsParams.GetInfoString();
m_StatGraph = new Graph[graphCount][];
m_StatsParams.GetUseStatPlot() == true) {
// String Info = m_StatsParams.GetInfoString();
m_StatGraph = new Graph[windowCount][];
for (int i = 0; i < m_StatGraph.length; i++) {
m_StatGraph[i] = new Graph[((String[]) description.get(i)).length];
m_StatGraph[i] = new Graph[graphCount];
for (int j = 0; j < m_StatGraph[i].length; j++) {
String[] d = (String[]) description.get(i);
m_StatGraph[i][j] = m_FitnessFrame[i].getNewGraph(d[j] + "_" + Info +
// String[] d = (String[]) description.get(i);
m_StatGraph[i][j] = m_FitnessFrame[i].getNewGraph(graphDesc.get(j).head + "_" + //Info +
m_GraphInfoString);
}
}
@ -220,44 +226,29 @@ public class StatisticsWithGUI extends AbstractStatistics implements Serializabl
if (isValidGraph) m_FitnessGraph[graph][subGraph].setConnectedPoint(x, y);
}
/**
* Plots the selected data to the fitness graphs.
*/
protected void plotCurrentResults() {
// Plots
m_PlotCounter--;
// int fitnessplot_setting = m_StatsParams.getPlotData().getSelectedTag().getID();
if (m_PlotCounter == 0) {
m_PlotCounter = m_StatsParams.GetPlotoutput();
// boolean doPlotBest = (fitnessplot_setting == StatsParameter.PLOT_BEST)
// || (fitnessplot_setting == StatsParameter.PLOT_BEST_AND_WORST)
// || (fitnessplot_setting == StatsParameter.PLOT_CURBEST_AND_RUNBEST)
// || (fitnessplot_setting == StatsParameter.PLOT_BEST_AND_MEASURES);
// boolean doPlotWorst = (fitnessplot_setting == StatsParameter.PLOT_WORST)
// || (fitnessplot_setting == StatsParameter.PLOT_BEST_AND_WORST);
// boolean doPlotMeasures = (fitnessplot_setting == StatsParameter.PLOT_BEST_AND_MEASURES);
boolean doPlotCurrentBest = GraphSelectionEnum.doPlotCurrentBest(lastGraphSelection);
boolean doPlotRunBest = GraphSelectionEnum.doPlotRunBest(lastGraphSelection);
boolean doPlotWorst= GraphSelectionEnum.doPlotWorst(lastGraphSelection);
boolean doPlotCurBestFeasible = GraphSelectionEnum.doPlotCurrentBestFeasible(lastGraphSelection);
boolean doPlotRunBestFeasible = GraphSelectionEnum.doPlotRunBestFeasible(lastGraphSelection);
boolean doPlotAvgDist= GraphSelectionEnum.doPlotAvgDist(lastGraphSelection);
boolean doPlotMaxPopDist= GraphSelectionEnum.doPlotMaxPopDist(lastGraphSelection);
// m_PlotCounter--;
// if (m_PlotCounter == 0) {
// m_PlotCounter = m_StatsParams.GetPlotoutput();
int subGraph=0;
if (doPlotCurrentBest) plotFitnessPoint(0, subGraph++, functionCalls, currentBestFit[0]);
if (doPlotRunBest) plotFitnessPoint(0, subGraph++, functionCalls, bestOfRunIndy.getFitness()[0]);
if (doPlotWorst) plotFitnessPoint(0, subGraph++ , functionCalls, currentWorstFit[0]);
if (doPlotAvgDist) plotFitnessPoint(0, subGraph++, functionCalls, avgPopDist);
if (doPlotMaxPopDist) plotFitnessPoint(0, subGraph++, functionCalls, maxPopDist);
if (doPlotCurBestFeasible && currentBestFeasibleFit!=null) plotFitnessPoint(0, subGraph++, functionCalls, currentBestFeasibleFit[0]);
if (doPlotRunBestFeasible && bestOfRunFeasibleIndy!=null) plotFitnessPoint(0, subGraph++, functionCalls, bestOfRunFeasibleIndy.getFitness()[0]);
}
// boolean doPlotAdditionalInfo = m_StatsParams.isOutputAdditionalInfo();
for (int i=0; i<graphDesc.size(); i++) {
Integer colIndex = i+1; // always add one because the function calls are located in column zero
if (lastIsShowFull) colIndex = 1+graphDesc.get(i).tail;
// plot the column as indicated by the graph description
if (currentStatDoubleData[colIndex]!=null) plotFitnessPoint(0, subGraph++, functionCalls, currentStatDoubleData[colIndex]);
else EVAERROR.errorMsgOnce("Error, data field " + graphDesc.get(i).head + " does not contain primitive data and cannot be plotted.");
}
// }
}
/**
*
* This method is more or less deprecated. The current standard population does not
* define specific data. However its used by the ES module implementation.
*/
public void plotSpecificData(PopulationInterface pop, List<InterfaceAdditionalPopulationInformer> informer) {
double[] specificData = pop.getSpecificData();
@ -291,9 +282,9 @@ public class StatisticsWithGUI extends AbstractStatistics implements Serializabl
printToTextListener(s + "\n");
}
m_PlotCounter--;
if (m_PlotCounter == 0) {
m_PlotCounter = m_StatsParams.GetPlotoutput();
// m_PlotCounter--;
// if (m_PlotCounter == 0) {
// m_PlotCounter = m_StatsParams.GetPlotoutput();
int index = 0;
for (int i = 0; i < m_FitnessGraph.length; i++) {
for (int j = 0; j < m_FitnessGraph[i].length; j++) {
@ -301,8 +292,7 @@ public class StatisticsWithGUI extends AbstractStatistics implements Serializabl
index++;
}
}
}
// }
}
public String getHostName() {

View File

@ -1,40 +1,33 @@
package eva2.server.stat;
/*
* Title: EvA2
* Description:
* Copyright: Copyright (c) 2003
* Company: University of Tuebingen, Computer Architecture
* @author Holger Ulmer, Felix Streichert, Hannes Planatscher
* @version: $Revision: 284 $
* $Date: 2007-11-27 14:37:05 +0100 (Tue, 27 Nov 2007) $
* $Author: mkron $
*/
/*==========================================================================*
* IMPORTS
*==========================================================================*/
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import eva2.gui.BeanInspector;
import eva2.gui.GenericObjectEditor;
import eva2.server.go.InterfaceNotifyOnInformers;
import eva2.server.go.problems.InterfaceAdditionalPopulationInformer;
import eva2.tools.SelectedTag;
import eva2.tools.Serializer;
import eva2.tools.StringSelection;
public class StatsParameter implements InterfaceStatisticsParameter, Serializable {
/**
* A set of parameters for statistics in EvA2. Several data entries are provided by the AbstractStatistics class,
* others by the additional informers. This class allows customization of entries and frequency of data output.
* Data entries can be selected using a StringSelection instance.
* There is a switch called "output full data as text" which will be interpreted by AbstractStatistics showing
* all or only the selected entities.
*
* @see AbstractStatistics
* @author mkron
*/
public class StatsParameter implements InterfaceStatisticsParameter, InterfaceNotifyOnInformers, Serializable {
private static final long serialVersionUID = -8681061379203108390L;
private static boolean TRACE = false;
// public final static int PLOT_BEST = 0;
// public final static int PLOT_WORST = 1;
// public final static int PLOT_BEST_AND_WORST = 2;
// public final static int PLOT_BEST_AND_MEASURES = 3;
// public final static int PLOT_CURBEST_AND_RUNBEST = 4;
// public final static Tag[] TAGS_PLOT_FITNESS = {
// new Tag(PLOT_BEST, "plot best fitness"),
// new Tag(PLOT_WORST, "plot worst fitness"),
// new Tag(PLOT_BEST_AND_WORST, "both best and worst"),
// new Tag(PLOT_BEST_AND_MEASURES, "both best and population measures"),
// new Tag(PLOT_CURBEST_AND_RUNBEST, "current best and best of run")
// };
public final static int VERBOSITY_NONE = 0;
public final static int VERBOSITY_FINAL = 1;
@ -50,11 +43,11 @@ public class StatsParameter implements InterfaceStatisticsParameter, Serializabl
// private int m_PlotFitness = PLOT_BEST;
private int m_Textoutput = 0;
private int m_Plotoutput = 1;
// private int m_Plotoutput = 1;
private int m_MultiRuns = 1;
private String m_ResultFilePrefix = "EvA2";
protected String m_Name = "not defined";
protected String m_InfoString = "";
// protected String m_InfoString = "";
private boolean m_useStatPlot = true;
private boolean showAdditionalProblemInfo = false;
private double m_ConvergenceRateThreshold=0.001;
@ -95,47 +88,30 @@ public class StatsParameter implements InterfaceStatisticsParameter, Serializabl
*
*/
public String toString() {
String ret = "\r\nStatParameter:\r\nm_MultiRuns=" + m_MultiRuns +
"\nm_Textoutput=" + m_Textoutput +
"\nm_Plotoutput=" + m_Plotoutput +
"\nverbosity= " + outputVerbosity.getSelectedString() +
"\n" + outputTo.getSelectedString() +
"\n";
String ret = "\r\nStatParameter (" + super.toString() + "):\r\nm_MultiRuns=" + m_MultiRuns +
", m_Textoutput=" + m_Textoutput +
// ", m_Plotoutput=" + m_Plotoutput +
", verbosity= " + outputVerbosity.getSelectedString() +
"\nTo " + outputTo.getSelectedString() +
", " + BeanInspector.toString(graphSel.getStrings());
return ret;
}
/**
* Return a list of String arrays describing the selected plot options, e.g. {"Best"} or {"Best", "Worst"}.
* For now, only one array is returned.
*
* @return a list of String arrays describing the selected plot options
*/
public ArrayList<String[]> getPlotDescriptions() {
ArrayList<String> desc = new ArrayList<String>();
for (int i=0; i<GraphSelectionEnum.values().length; i++) {
if (graphSel.isSelected(i)) desc.add(graphSel.getElement(i));
}
ArrayList<String[]> alist = new ArrayList<String[]>();
alist.add(desc.toArray(new String[desc.size()]));
return alist;
// switch (getPlotData().getSelectedTagID()) {
// case StatsParameter.PLOT_BEST_AND_WORST:
// desc.add(new String[] {"Best", "Worst"});
// break;
// case StatsParameter.PLOT_BEST:
// desc.add(new String[] {"Best"});
// break;
// case StatsParameter.PLOT_WORST:
// desc.add(new String[] {"Worst"});
// break;
// case StatsParameter.PLOT_BEST_AND_MEASURES:
// desc.add(new String[] {"Best", "AvgDist", "MaxDist"});
// break;
// case StatsParameter.PLOT_CURBEST_AND_RUNBEST:
// desc.add(new String[] {"Cur.Best", "Run Best"});
// break; }
// return desc;
}
// /**
// * Return a list of String arrays describing the selected plot options, e.g. {"Best"} or {"Best", "Worst"}.
// * For now, only one array is returned.
// *
// * @return a list of String arrays describing the selected plot options
// */
// public ArrayList<String[]> getPlotDescriptions() {
// ArrayList<String> desc = new ArrayList<String>();
// for (int i=0; i<graphSel.getLength(); i++) {
// if (graphSel.isSelected(i)) desc.add(graphSel.getElement(i));
// }
// ArrayList<String[]> alist = new ArrayList<String[]>();
// alist.add(desc.toArray(new String[desc.size()]));
// return alist;
// }
/**
*
@ -151,7 +127,7 @@ public class StatsParameter implements InterfaceStatisticsParameter, Serializabl
m_ConvergenceRateThreshold = Source.m_ConvergenceRateThreshold;
m_useStatPlot = Source.m_useStatPlot;
m_Textoutput = Source.m_Textoutput;
m_Plotoutput = Source.m_Plotoutput;
// m_Plotoutput = Source.m_Plotoutput;
// m_PlotFitness = Source.m_PlotFitness;
m_MultiRuns = Source.m_MultiRuns;
m_ResultFilePrefix = Source.m_ResultFilePrefix;
@ -173,21 +149,7 @@ public class StatsParameter implements InterfaceStatisticsParameter, Serializabl
}
public static String globalInfo() {
return "Configure statistics and output of the optimization run.";
}
/**
*
*/
public void setPlotoutput(int i) {
m_Plotoutput = i;
}
/**
*
*/
public int GetPlotoutput() {
return m_Plotoutput;
return "Configure statistics and output of the optimization run. Changes to the data selection state will not take effect during a run.";
}
// /**
@ -225,19 +187,19 @@ public class StatsParameter implements InterfaceStatisticsParameter, Serializabl
return "Number of independent optimization runs to evaluate.";
}
/**
*
*/
public String GetInfoString() {
return m_InfoString;
}
/**
*
*/
public void setInfoString(String s) {
m_InfoString = s;
}
// /**
// *
// */
// public String GetInfoString() {
// return m_InfoString;
// }
//
// /**
// *
// */
// public void setInfoString(String s) {
// m_InfoString = s;
// }
/**
*
@ -247,24 +209,21 @@ public class StatsParameter implements InterfaceStatisticsParameter, Serializabl
}
/**
*
* Use averaged graph for multi-run plots or not
*/
public boolean GetuseStatPlot() {
public boolean GetUseStatPlot() {
return m_useStatPlot;
}
/**
*
* Activate or deactivate averaged graph for multi-run plots
*/
public void setuseStatPlot(boolean x) {
public void setUseStatPlot(boolean x) {
m_useStatPlot = x;
}
/**
*
*/
public String useStatPlotTipText() {
return "Plotting each fitness graph separate if multiruns > 1.";
return "Plotting each fitness graph separately if multiruns > 1.";
}
/**
@ -338,16 +297,16 @@ public class StatsParameter implements InterfaceStatisticsParameter, Serializabl
// return "Indicates whether further text output should be printed";
// }
public boolean isOutputAdditionalInfo() {
public boolean isOutputAllFieldsAsText() {
return showAdditionalProblemInfo;
}
public void setOutputAdditionalInfo(boolean showAdd) {
showAdditionalProblemInfo = showAdd;
public void setOutputAllFieldsAsText(boolean bShowFullText) {
showAdditionalProblemInfo = bShowFullText;
}
public String outputAdditionalInfoTipText() {
return "Activate to output additional problem information per iteration, such as the current solution representation.";
public String outputAllFieldsAsTextTipText() {
return "Output all available data fields or only the selected entries as text.";
}
public void hideHideable() {
@ -400,15 +359,40 @@ public class StatsParameter implements InterfaceStatisticsParameter, Serializabl
return "Set the output destination; to deactivate output, set verbosity to none.";
}
public StringSelection getGraphSelection() {
public StringSelection getFieldSelection() {
return graphSel;
}
public void setGraphSelection(StringSelection v) {
public void setFieldSelection(StringSelection v) {
graphSel = v;
}
public String graphSelectionTipText() {
return "Select the graphs to be plotted.";
public String fieldSelectionTipText() {
return "Select the data fields to be collected and plotted. Note that only simple types can be plotted to the GUI.";
}
/**
* May be called to dynamically alter the set of graphs that can be selected,
* using a list of informer instances, which usually are the problem and the
* optimizer instance.
*
* @see InterfaceAdditionalPopulationInformer
*/
public void setInformers(
List<InterfaceAdditionalPopulationInformer> informers) {
ArrayList<String> headerFields = new ArrayList<String>();
// parse list of header elements, show additional Strings according to names.
for (InterfaceAdditionalPopulationInformer inf : informers) {
headerFields.addAll(Arrays.asList(inf.getAdditionalFileStringHeader(null)));
// header += inf.getAdditionalFileStringHeader(null); // lets hope this works with a null
}
// create additional fields to be selectable by the user, defined by the informer headers
// StringSelection ss = new StringSelection(GraphSelectionEnum.getAndAppendArray(headerFields.toArray(new String[headerFields.size()])));
StringSelection ss = new StringSelection(GraphSelectionEnum.currentBest, headerFields);
ss.takeOverSelection(graphSel);
// System.out.println("In " + this + ": setting new informers: " + BeanInspector.toString(ss.getStrings()));
// This works!
setFieldSelection(ss);
// System.out.println("After: " + this);
}
}

View File

@ -1,6 +1,13 @@
package eva2.tools;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import eva2.gui.BeanInspector;
/**
* An array of Strings that can be selected and deselected. May be created directly from an Enum.
@ -9,17 +16,23 @@ import java.io.Serializable;
*
*/
public class StringSelection implements Serializable {
private static final long serialVersionUID = -1512329288445831907L;
private String[] strObjects;
boolean[] selStates;
private transient HashMap<String,Integer> stringToIndexHash = null;
private transient Class<? extends Enum> enumClass = null;
public StringSelection(String[] sArr) {
strObjects = sArr;
selStates=new boolean[sArr.length];
stringToIndexHash = null;
enumClass = null;
}
public StringSelection(String[] sArr, int initialSel) {
this(sArr);
if (initialSel<getLength()) setSelected(initialSel, true);
enumClass = null;
}
public StringSelection(Enum<?> e) {
@ -29,11 +42,28 @@ public class StringSelection implements Serializable {
strObjects[i] = e.getClass().getEnumConstants()[i].toString();
}
setSelected(e.ordinal(), true);
stringToIndexHash = null;
enumClass = e.getClass();
}
public StringSelection(StringSelection stringSelection) {
strObjects = stringSelection.strObjects.clone();
selStates = stringSelection.selStates.clone();
stringToIndexHash = null;
enumClass = stringSelection.enumClass;
}
/**
* Construct a string selection that allows all enum fields of the given type plus a list of additional
* strings to be selected. The enum fields will be first in the selection list.
*
* @param e
* @param headerFields
*/
public StringSelection(Enum<?> e,
List<String> headerFields) {
this(ToolBox.appendEnumAndArray(e, headerFields.toArray(new String[headerFields.size()])));
enumClass = e.getClass();
}
public Object clone() {
@ -58,15 +88,51 @@ public class StringSelection implements Serializable {
/**
* Returns true if the given enum is selected (as its string representation)
* within the instance.
* within the instance. This only works if the enum was used for the
* creation of this instance.
*
* @param e
* @return
*/
public boolean isSelected(Enum<?> e) {
if (isSelected(e.ordinal())) {
return e.toString().equals(strObjects[e.ordinal()]);
} else return false;
// if (isSelected(e.ordinal())) {
// return e.toString().equals(strObjects[e.ordinal()]);
// } else return false;
if (enumClass!=null) {
if (e.getClass().equals(enumClass)) return isSelected(e.ordinal());
else {
System.err.println("Error, the string selection was constructed with a different enum class - invalid request (StringSelection.isSelected(Enum)");
return false;
}
} else {
System.err.println("Error, the string selection was constructed without an enum class - invalid request (StringSelection.isSelected(Enum)");
return false;
}
}
/**
* Check if a given string is selected within this instance. If the
* String is not found, false is returned.
*
* @param str
* @return
*/
public boolean isSelected(String str) {
if (stringToIndexHash == null) { // for some time efficiency...
stringToIndexHash = new HashMap<String,Integer>(2*strObjects.length);
for (int i=0; i<strObjects.length; i++) {
stringToIndexHash.put(strObjects[i], i);
}
}
Integer selIndex = stringToIndexHash.get(str);
if (selIndex==null) {
System.err.println("Error, unknown string for StringSelection: " + str + ", selectable were " + BeanInspector.toString(getStrings()));
return false;
} return isSelected(selIndex);
// for (int i=0; i<strObjects.length; i++) {
// if (strObjects[i].equals(str)) return isSelected(i);
// }
// return false;
}
public void setSelected(int i, boolean v) {
@ -76,4 +142,60 @@ public class StringSelection implements Serializable {
public void toggleSelected(int i) {
selStates[i]=!selStates[i];
}
/**
* Apply the selection state of the given instance to this instance. Is only done
* for Strings which are equivalent and at the same index.
*
* @param sel
*/
public void takeOverSelection(StringSelection sel) {
// try to apply the same selection for equivalent string (must be in same order)
for (int i=0; i<sel.getLength() && i<getLength(); i++) {
if (sel.getElement(i).equals(getElement(i))) {
setSelected(i, sel.isSelected(i));
}
}
}
/**
* Return a sub-list of the selected items.
*
* @return
*/
public String[] getSelected() {
ArrayList<String> ret = new ArrayList<String>();
for (int i=0; i<getLength(); i++) if (isSelected(i)) ret.add(getElement(i));
return ret.toArray(new String[ret.size()]);
}
/**
* Return a sub-list of the selected items paired up with the respective index.
*
* @return
*/
public List<Pair<String,Integer>> getSelectedWithIndex() {
ArrayList<Pair<String,Integer>> ret = new ArrayList<Pair<String,Integer>>();
for (int i=0; i<getLength(); i++) if (isSelected(i)) ret.add(new Pair<String,Integer>(getElement(i), i));
return ret;
}
/**
* Return only those selected fields which are members of the given enum.
* @param e
* @return
*/
public Enum[] getSelectedEnum(Enum[] e) {
LinkedList<Integer> selectedList = new LinkedList<Integer>();
for (int i=0; i<e.length; i++) {
if (isSelected(e[i])) selectedList.add(i);
}
Enum[] ret = (Enum[]) java.lang.reflect.Array.newInstance(e[0].getClass(), selectedList.size());
Iterator<Integer> iter = selectedList.iterator();
int i=0;
while (iter.hasNext()) {
ret[i++]=e[iter.next()];
}
return ret;
}
}

View File

@ -2,6 +2,7 @@ package eva2.tools;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.StringTokenizer;
import eva2.gui.BeanInspector;
@ -218,4 +219,44 @@ public class StringTools {
}
return -1;
}
/**
* Concatenate a list of Strings using a given delimiter string.
*
* @param headlineFields
* @param delim
* @return
*/
public static String concatFields(List<String> strings,
String delim) {
StringBuffer sb = new StringBuffer();
int cnt=0;
for (String field : strings) {
if (cnt>0) sb.append(delim);
sb.append(field);
cnt++;
}
return sb.toString();
}
/**
* Concatenate a list of Objects using a given delimiter string.
* The objects are converted to strings using the BeanInspector class.
*
* @param headlineFields
* @param delim
* @return
*/
public static String concatValues(List<Object> objects,
String delim) {
StringBuffer sb = new StringBuffer();
int cnt=0;
for (Object v : objects) {
if (cnt>0) sb.append(delim);
sb.append(BeanInspector.toString(v));
cnt++;
}
return sb.toString();
}
}

View File

@ -0,0 +1,97 @@
package eva2.tools;
import java.util.ArrayList;
import java.util.List;
import eva2.gui.BeanInspector;
/**
* Collection of miscellaneous static helper methods.
*
* @author mkron
*
*/
public class ToolBox {
/**
* Convert all items of an enum to a String array and append the given String array at the end.
*
* @param additionals
* @return
*/
public static String[] appendEnumAndArray(Enum<?> e, String[] additionals) {
Enum<?>[] fields = e.getClass().getEnumConstants();
int enumLen = fields.length; //values().length;
int len = enumLen+additionals.length;
String[] ret = new String[len];
for (int i=0; i<enumLen; i++) ret[i]=fields[i].toString();
for (int i=enumLen; i<ret.length; i++) ret[i] = additionals[i-enumLen];
return ret;
}
public static String[] appendArrays(String[] strArr1,
String[] strArr2) {
String[] ret = new String[strArr1.length + strArr2.length];
System.arraycopy(strArr1, 0, ret, 0, strArr1.length);
System.arraycopy(strArr2, 0, ret, strArr1.length, strArr2.length);
return ret;
}
public static Object[] appendArrays(Object[] strArr1,
Object[] strArr2) {
Object[] ret = new Object[strArr1.length + strArr2.length];
System.arraycopy(strArr1, 0, ret, 0, strArr1.length);
System.arraycopy(strArr2, 0, ret, strArr1.length, strArr2.length);
return ret;
}
/**
* For a list of objects, generate an array of Double which contains thee.getClass().getEnumConstants()
* converted double arrays whenever this is directly possible, or null otherwise.
* The length of the array will correspond to the length of the given list.
*
* @see BeanInspector.toString(Object)
* @param l
* @return
*/
public static Double[] parseDoubles(List<Object> l) {
ArrayList<Double> vals = new ArrayList<Double>();
for (Object o : l) {
vals.add(toDouble(o)); // null if unsuccessfull
}
return vals.toArray(new Double[vals.size()]);
}
/**
* Try to convert a Double from a given Object. Return null
* if conversion fails (e.g. because the Object is a complex data type
* which has no straight-forward numeric representation, e.g. an array).
*
* @param o
* @return
*/
public static Double toDouble(Object o) {
if (o instanceof Number) return ((Number)o).doubleValue();
else try {
Double d = Double.parseDouble(BeanInspector.toString(o));
return d;
} catch(Exception e) { }
return null;
}
/**
* For an array of objects, generate an array of Double which contains the
* converted double arrays whenever this is directly possible, or null otherwise.
*
* @see BeanInspector.toString(Object)
* @param l
* @return
*/
public static Double[] parseDoubles(Object [] os) {
Double[] vals = new Double[os.length];
for (int i=0; i<os.length; i++) {
vals[i]=toDouble(os[i]);
}
return vals;
}
}