From 29b6c840ac4ee390673ada526b08dfeef182faac Mon Sep 17 00:00:00 2001 From: Marcel Kronfeld Date: Thu, 27 Mar 2008 14:55:01 +0000 Subject: [PATCH] Minor adaptions to post-processing, BeanInspector. --- src/javaeva/OptimizerFactory.java | 101 ++--- src/javaeva/OptimizerRunnable.java | 4 + src/javaeva/gui/BeanInspector.java | 401 ++++++++++++++++-- src/javaeva/gui/PropertySheetPanel.java | 4 +- .../go/operators/postprocess/PostProcess.java | 46 +- .../problems/AbstractOptimizationProblem.java | 4 +- .../server/go/problems/DynJumpProblem.java | 6 +- src/javaeva/server/modules/Processor.java | 18 +- .../server/stat/AbstractStatistics.java | 15 +- .../server/stat/StatisticsStandalone.java | 2 +- 10 files changed, 451 insertions(+), 150 deletions(-) diff --git a/src/javaeva/OptimizerFactory.java b/src/javaeva/OptimizerFactory.java index 73f99deb..ba7ff4a2 100644 --- a/src/javaeva/OptimizerFactory.java +++ b/src/javaeva/OptimizerFactory.java @@ -3,7 +3,6 @@ package javaeva; import java.util.BitSet; import java.util.Vector; -import javaeva.gui.BeanInspector; import javaeva.server.go.IndividualInterface; import javaeva.server.go.InterfacePopulationChangedEventListener; import javaeva.server.go.InterfaceTerminator; @@ -41,7 +40,6 @@ import javaeva.server.go.strategies.ParticleSwarmOptimization; import javaeva.server.go.strategies.SimulatedAnnealing; import javaeva.server.go.strategies.Tribes; import javaeva.server.modules.GOParameters; -import javaeva.tools.SelectedTag; /** *

@@ -73,49 +71,20 @@ public class OptimizerFactory { private static InterfaceTerminator term = null; public final static int STD_ES = 1; - public final static int CMA_ES = 2; - public final static int STD_GA = 3; - public final static int PSO = 4; - public final static int DE = 5; - public final static int TRIBES = 6; - public final static int RANDOM = 7; - public final static int HILLCL = 8; - public final static int CBN_ES = 9; - public final static int CL_HILLCL = 10; public final static int defaultFitCalls = 10000; - public final static int randSeed = 0; - private static OptimizerRunnable lastRunnable = null; - /** - * The topologies for the PSO algorithm. Contains - *

- */ - public static SelectedTag topology = new SelectedTag( - "Linear", "Grid", - "Star", "Multi-Swarm", - "Tree", "HPSO", - "Random"); - /** * Add an InterfaceTerminator to any new optimizer in a boolean combination. * The old and the given terminator will be combined as in (TOld && TNew) if @@ -174,27 +143,24 @@ public class OptimizerFactory { es.setMu(15); es.setLambda(50); es.setPlusStrategy(false); - - // TODO improve this by adding getEAIndividual to AbstractEAIndividual? - Object maybeTemplate = BeanInspector.callIfAvailable(problem, - "getEAIndividual", null); - if ((maybeTemplate != null) - && (maybeTemplate instanceof InterfaceESIndividual)) { + + // TODO improve this by adding getEAIndividual to AbstractEAIndividual? + AbstractEAIndividual indyTemplate = problem.getIndividualTemplate(); + if ((indyTemplate != null) && (indyTemplate instanceof InterfaceESIndividual)) { // Set CMA operator for mutation - AbstractEAIndividual indy = (AbstractEAIndividual) maybeTemplate; + AbstractEAIndividual indy = (AbstractEAIndividual)indyTemplate; MutateESCovarianceMartixAdaption cmaMut = new MutateESCovarianceMartixAdaption(); cmaMut.setCheckConstraints(true); indy.setMutationOperator(cmaMut); indy.setCrossoverOperator(new CrossoverESDefault()); } else { - System.err - .println("Error, CMA-ES is implemented for ES individuals only (requires double data types)"); + System.err.println("Error, CMA-ES is implemented for ES individuals only (requires double data types)"); return null; } - + Population pop = new Population(); pop.setPopulationSize(es.getLambda()); - + return makeParams(es, pop, problem, randSeed, defaultTerminator()); } @@ -442,8 +408,7 @@ public class OptimizerFactory { pso.setPhi1(phi1); pso.setPhi2(phi2); pso.setSpeedLimit(k); - topology.setSelectedTag(selectedTopology); - pso.setTopology(topology); + pso.getTopology().setSelectedTag(selectedTopology); pso.addPopulationChangedEventListener(listener); pso.init(); @@ -508,48 +473,44 @@ public class OptimizerFactory { public static int getDefaultFitCalls() { return defaultFitCalls; } + +///////////////////////////// constructing a default OptimizerRunnable - public static OptimizerRunnable getOptRunnable(final int optType, - AbstractOptimizationProblem problem, int fitCalls, String outputFilePrefix) { - OptimizerRunnable opt = null; + public static GOParameters getParams(final int optType, AbstractOptimizationProblem problem) { switch (optType) { case STD_ES: - opt = new OptimizerRunnable(standardES(problem), outputFilePrefix); - break; + return standardES(problem); case CMA_ES: - opt = new OptimizerRunnable(cmaES(problem), outputFilePrefix); - break; + return cmaES(problem); case STD_GA: - opt = new OptimizerRunnable(standardGA(problem), outputFilePrefix); - break; + return standardGA(problem); case PSO: - opt = new OptimizerRunnable(standardPSO(problem), outputFilePrefix); - break; + return standardPSO(problem); case DE: - opt = new OptimizerRunnable(standardDE(problem), outputFilePrefix); - break; + return standardDE(problem); case TRIBES: - opt = new OptimizerRunnable(tribes(problem), outputFilePrefix); - break; + return tribes(problem); case RANDOM: - opt = new OptimizerRunnable(monteCarlo(problem), outputFilePrefix); - break; + return monteCarlo(problem); case HILLCL: - opt = new OptimizerRunnable(hillClimbing(problem), outputFilePrefix); - break; + return hillClimbing(problem); case CBN_ES: - opt = new OptimizerRunnable(cbnES(problem), outputFilePrefix); - break; + return cbnES(problem); case CL_HILLCL: - opt = new OptimizerRunnable(clusteringHillClimbing(problem), - outputFilePrefix); - break; + return clusteringHillClimbing(problem); default: System.err.println("Error: optimizer type " + optType + " is unknown!"); return null; } - if (fitCalls != defaultFitCalls) - opt.getGOParams().setTerminator(new EvaluationTerminator(fitCalls)); + } + + public static OptimizerRunnable getOptRunnable(final int optType, AbstractOptimizationProblem problem, int fitCalls, String outputFilePrefix) { + OptimizerRunnable opt = null; + GOParameters params = getParams(optType, problem); + if (params != null) { + opt = new OptimizerRunnable(params, outputFilePrefix); + if (fitCalls != defaultFitCalls) opt.getGOParams().setTerminator(new EvaluationTerminator(fitCalls)); + } return opt; } diff --git a/src/javaeva/OptimizerRunnable.java b/src/javaeva/OptimizerRunnable.java index d93dd3fe..4417cac6 100644 --- a/src/javaeva/OptimizerRunnable.java +++ b/src/javaeva/OptimizerRunnable.java @@ -15,6 +15,7 @@ import javaeva.server.go.operators.postprocess.PostProcessParams; import javaeva.server.go.populations.Population; import javaeva.server.modules.GOParameters; import javaeva.server.modules.Processor; +import javaeva.server.stat.AbstractStatistics; import javaeva.server.stat.InterfaceTextListener; import javaeva.server.stat.StatisticsStandalone; @@ -37,6 +38,7 @@ public class OptimizerRunnable implements Runnable { public OptimizerRunnable(GOParameters params, String outputFilePrefix, boolean restart) { proc = new Processor(new StatisticsStandalone(outputFilePrefix), null, params); + ((AbstractStatistics)proc.getStatistics()).setSaveParams(false); doRestart = restart; } @@ -45,7 +47,9 @@ public class OptimizerRunnable implements Runnable { } public void setTextListener(InterfaceTextListener lsnr) { + proc.getStatistics().removeTextListener(listener); this.listener = lsnr; + if (listener != null) proc.getStatistics().addTextListener(listener); } public void setDoRestart(boolean restart) { diff --git a/src/javaeva/gui/BeanInspector.java b/src/javaeva/gui/BeanInspector.java index e029a92e..ba261eea 100644 --- a/src/javaeva/gui/BeanInspector.java +++ b/src/javaeva/gui/BeanInspector.java @@ -18,8 +18,12 @@ import java.beans.Introspector; import java.beans.PropertyDescriptor; import java.lang.reflect.Array; import java.lang.reflect.Method; +import java.util.ArrayList; import java.util.List; +import javaeva.tools.SelectedTag; +import javaeva.tools.Tag; + /* * ==========================================================================* * CLASS DECLARATION @@ -30,24 +34,27 @@ public class BeanInspector { // public static int step = 0; // public static String check(String s) { -// -// s=s.replace('$','_'); -// s=s.replace(';','_'); -//// String ret = null; -//// try { -//// RE r = new RE("\\["); -//// ret = r.subst(s,""); -//// //ret.substring(); -//// //ret -//// } catch (Exception e) {e.getMessage();}; -//// System.out.println("s="+s+" ret"+ret); -// if (s.equals("[D")) return "Double_Array"; -// if (s.startsWith("[D")) return s.substring(2); -// if (s.startsWith("[L")) return s.substring(2); -// -// return s; + +// s=s.replace('$','_'); +// s=s.replace(';','_'); +//// String ret = null; +//// try { +//// RE r = new RE("\\["); +//// ret = r.subst(s,""); +//// //ret.substring(); +//// //ret +//// } catch (Exception e) {e.getMessage();}; +//// System.out.println("s="+s+" ret"+ret); +// if (s.equals("[D")) return "Double_Array"; +// if (s.startsWith("[D")) return s.substring(2); +// if (s.startsWith("[L")) return s.substring(2); + +// return s; // } + /** + * Check for equality based on bean properties of two target objects. + */ public static boolean equalProperties(Object Target_1, Object Target_2) { if (Target_1 == null || Target_2 == null) { System.out.println(""); @@ -135,7 +142,7 @@ public class BeanInspector { // try the object itself if (Target instanceof String) return (String)Target; // directly return a string object Class type = Target.getClass(); - + if (type.isArray()) { // handle the array case StringBuffer sbuf = new StringBuffer("[ "); int len = Array.getLength(Target); @@ -149,7 +156,7 @@ public class BeanInspector { if (Target instanceof List) { // handle the list case StringBuffer sbuf = new StringBuffer("[ "); - List lst = (List)Target; + List lst = (List)Target; for (Object o : lst) { sbuf.append(o.toString()); sbuf.append("; "); @@ -159,7 +166,7 @@ public class BeanInspector { return sbuf.toString(); } - + Method[] methods = Target.getClass().getDeclaredMethods(); for (int ii = 0; ii < methods.length; ii++) { // check if the object has its own toString method, in this case use it if ((methods[ii].getName().equals("toString") /*|| (methods[ii].getName().equals("getStringRepresentation"))*/) && (methods[ii].getParameterTypes().length == 0)) { @@ -291,27 +298,341 @@ public class BeanInspector { } } } - - - public static Object callIfAvailable(Object obj, String mName, Object[] args) { - Method meth = hasMethod(obj, mName); - if (meth != null) { - try { - return meth.invoke(obj, args); - } catch(Exception e) { - System.err.println("Error on calling method "+mName + " on " + obj.getClass().getName()); - return null; - } - } else return null; - } - - public static Method hasMethod(Object obj, String mName) { - Class cls = obj.getClass(); - Method[] meths = cls.getMethods(); - for (Method method : meths) { + + /** + * Call a method by a given name with given arguments, if the method is available. + * Returns the return values of the call or null if it isnt found. + * This of course means that the caller is unable to distinguish between "method not found" + * and "method found and it returned null". + * + * @param obj + * @param mName + * @param args + * @return the return value of the called method or null + */ + public static Object callIfAvailable(Object obj, String mName, Object[] args) { + Method meth = hasMethod(obj, mName); + if (meth != null) { + try { + return meth.invoke(obj, args); + } catch(Exception e) { + System.err.println("Error on calling method "+mName + " on " + obj.getClass().getName()); + return null; + } + } else return null; + } + + /** + * Check whether an object has a method by the given name. Return + * it if found, or null if not. + * + * @param obj + * @param mName the method name + * @return the method or null if it isn't found + */ + public static Method hasMethod(Object obj, String mName) { + Class cls = obj.getClass(); + Method[] meths = cls.getMethods(); + for (Method method : meths) { if (method.getName().equals(mName)) return method; } - return null; - } -} + return null; + } + + /** + * Just concatenates getClassDescription(obj) and getMemberDescriptions(obj, withValues). + * + * @param obj target object + * @param withValues if true, member values are displayed as well + * @return an info string about class and members of the given object + */ + public static String getDescription(Object obj, boolean withValues) { + StringBuffer sbuf = new StringBuffer(getClassDescription(obj)); + sbuf.append("\n"); + String[] mems = getMemberDescriptions(obj, withValues); + for (String str : mems) { + sbuf.append(str); + } + return sbuf.toString(); + } + + /** + * Check for info methods on the object to be provided by the developer + * and return their text as String. + * + * @param obj + * @return String information about the object's class + */ + public static String getClassDescription(Object obj) { + StringBuffer infoBf = new StringBuffer("Type: "); + infoBf.append(obj.getClass().getName()); + infoBf.append("\t"); + + Object args[] = { }; + Object ret; + + for (String meth : new String[]{"getName", "globalInfo"}) { + ret = callIfAvailable(obj, meth, args); + if (ret != null) { + infoBf.append("\t"); + infoBf.append((String)ret); + } + } + + return infoBf.toString(); + } + /** + * Return an info string on the members of the object class, containing name, type, optional + * value and tool tip text if available. The type is accompagnied by a tag "common" or "restricted", + * indicating whether the member property is normal or hidden, meaning it may have effect depending + * on settings of other members only, for instance. + * + * @param obj target object + * @param withValues if true, member values are displayed as well + * @return an info string about class and members of the given object + */ + public static String[] getMemberDescriptions(Object obj, boolean withValues) { + BeanInfo bi; + try { + bi = Introspector.getBeanInfo(obj.getClass()); + } catch(IntrospectionException e) { + e.printStackTrace(); + return null; + } + PropertyDescriptor[] m_Properties = bi.getPropertyDescriptors(); + ArrayList memberInfoList = new ArrayList(); + + for (int i = 0; i < m_Properties.length; i++) { + if (m_Properties[i].isExpert()) continue; + + String name = m_Properties[i].getDisplayName(); + if (TRACE) System.out.println("PSP looking at "+ name); + + Method getter = m_Properties[i].getReadMethod(); + Method setter = m_Properties[i].getWriteMethod(); + // Only display read/write properties. + if (getter == null || setter == null) continue; + + try { + Object args[] = { }; + Object value = getter.invoke(obj, args); + + // Don't try to set null values: + if (value == null) { + // If it's a user-defined property we give a warning. + String getterClass = m_Properties[i].getReadMethod().getDeclaringClass().getName(); + if (getterClass.indexOf("java.") != 0) System.err.println("Warning: Property \"" + name+ "\" has null initial value. Skipping."); + continue; + } + + StringBuffer memberInfoBf = new StringBuffer("Member:\t"); + memberInfoBf.append(name); + + memberInfoBf.append("\tType: "); + + if (m_Properties[i].isHidden()) { + memberInfoBf.append("restricted, "); + } else { + memberInfoBf.append("common, "); + } + String typeName = value.getClass().getName(); + if (value instanceof SelectedTag) { + Tag[] tags = ((SelectedTag)value).getTags(); + memberInfoBf.append("String in {"); + for (int k=0; k destType) throws NumberFormatException { + if ((destType == Integer.class) || (destType == int.class)) return Integer.valueOf(str); + else if ((destType == Double.class) || (destType == double.class)) return Double.valueOf(str); + else if ((destType == Boolean.class) || (destType == boolean.class)) return Boolean.valueOf(str); + else if ((destType == Byte.class) || (destType == byte.class)) return Byte.valueOf(str); + else if ((destType == Short.class) || (destType == short.class)) return Short.valueOf(str); + else if ((destType == Long.class) || (destType == long.class)) return Long.valueOf(str); + else if ((destType == Float.class) || (destType == float.class)) return Float.valueOf(str); + else if ((destType == Character.class) || (destType == char.class)) return str.charAt(0); + else { + // if (destType == Void.class) + System.err.println("warning, value interpreted as void type"); + return 0; + } + } + + /** + * Take a double value and convert it to a primitive object. + * + * @param d + * @param destType + * @return + */ + public static Object doubleToPrimitive(Double d, Class destType) { + if ((destType == Double.class) || (destType == double.class)) return d; + if ((destType == Integer.class) || (destType == int.class)) return new Integer(d.intValue()); + else if ((destType == Boolean.class) || (destType == boolean.class)) return new Boolean(d != 0); + else if ((destType == Byte.class) || (destType == byte.class)) return new Byte(d.byteValue()); + else if ((destType == Short.class) || (destType == short.class)) return new Short(d.shortValue()); + else if ((destType == Long.class) || (destType == long.class)) return new Long(d.longValue()); + else if ((destType == Float.class) || (destType == float.class)) return new Float(d.floatValue()); + else { // this makes hardly sense... + System.err.println("warning: converting from double to character or void..."); + if ((destType == Character.class) || (destType == char.class)) return new Character(d.toString().charAt(0)); + else //if (destType == Void.class) return 0; + return 0; + } + } + + /** + * Checks whether a type belongs to primitive (int, long, double, char etc.) or the Java encapsulations (Integer, Long etc.) + * + * @param cls + * @return + */ + public static boolean isJavaPrimitive(Class cls) { + if (cls.isPrimitive()) return true; + if ((cls == Double.class) || (cls == Integer.class) || (cls == Boolean.class) + || (cls == Byte.class) || (cls == Short.class) || (cls == Long.class) || (cls == Float.class)) return true; + return false; + } + + /** + * Try to convert an object to a destination type, especially for primitive types (int, double etc. + * but also Integer, Double etc.). + * + * @param destType + * @param value + * @return + */ + public static Object decodeType(Class destType, Object value) { + if (destType.isAssignableFrom(value.getClass())) { + // value is already of destType or assignable (subclass), so just return it + return value; + } + if (destType == String.class || destType == SelectedTag.class) { + if (value.getClass() == String.class) return value; + else return value.toString(); + } else if (isJavaPrimitive(destType)) { + try { + if (value.getClass() == String.class) return stringToPrimitive((String)value, destType); + else { + return doubleToPrimitive(toDouble(value), destType); + } + } catch(Exception e) { + System.err.println("Error in converting type of " + value + " to " + destType.getName() + ": " + e.getMessage()); + return null; + } + } + System.err.println("Error: unknown type, skipping decode " + value.getClass().getName() + " to " + destType.getName()); + return value; + } + + /** + * Try to set an object member to a given value. + * Returns true if successful, else false. The types are adapted as generally as possible, + * converting using the decodeType() method. + * + * @param obj + * @param mem + * @param val + * @return true if successful, else false + */ + public static boolean setMem(Object obj, String mem, Object val) { + BeanInfo bi; + try { + bi = Introspector.getBeanInfo(obj.getClass()); + } catch(IntrospectionException e) { + e.printStackTrace(); + return false; + } + PropertyDescriptor[] m_Properties = bi.getPropertyDescriptors(); +// Method getter = null; + Method setter = null; + Class type = null; +// System.err.println("looking at " + toString(obj)); + for (int i = 0; i < m_Properties.length; i++) { + if (m_Properties[i].getDisplayName().equals(mem)) { +// System.err.println("looking at " + m_Properties[i].getDisplayName()); +// getter = m_Properties[i].getReadMethod(); + setter = m_Properties[i].getWriteMethod(); + type = m_Properties[i].getPropertyType(); + break; + } + } + if (setter != null) { + try { +// System.out.println("setting value..."); + Object[] args = new Object[]{ decodeType(type, val) }; + if (args[0] != null) { + setter.invoke(obj, args); + return true; + } else { + System.err.println("no value to set"); + return false; + } + } catch (Exception e) { + System.err.println("Exception in invoking setter: "+e.getMessage()); +// e.printStackTrace(); + return false; + } + } else { + System.err.println("Setter method for " + mem + " not found!"); + return false; + } + } +} diff --git a/src/javaeva/gui/PropertySheetPanel.java b/src/javaeva/gui/PropertySheetPanel.java index 08dc4041..b32ef6a6 100644 --- a/src/javaeva/gui/PropertySheetPanel.java +++ b/src/javaeva/gui/PropertySheetPanel.java @@ -215,8 +215,8 @@ public class PropertySheetPanel extends JPanel implements PropertyChangeListener for (int i = 0; i < m_Properties.length; i++) { // For each property do this // Don't display hidden or expert properties. - //if (m_Properties[i].isHidden() || m_Properties[i].isExpert()) continue; - // we now display hidden properties (MK) + // if (m_Properties[i].isHidden() || m_Properties[i].isExpert()) continue; + // we now look at hidden properties, they can be shown or hidden dynamically (MK) String name = m_Properties[i].getDisplayName(); if (TRACE) System.out.println("PSP looking at "+ name); diff --git a/src/javaeva/server/go/operators/postprocess/PostProcess.java b/src/javaeva/server/go/operators/postprocess/PostProcess.java index 04365b64..3612093a 100644 --- a/src/javaeva/server/go/operators/postprocess/PostProcess.java +++ b/src/javaeva/server/go/operators/postprocess/PostProcess.java @@ -488,53 +488,55 @@ public class PostProcess { * a list of solutions after post processing. * * @param params - * @param solutions + * @param inputPop * @param problem * @param listener * @return the clustered, post-processed population */ - public static Population postProcess(InterfacePostProcessParams params, Population solutions, AbstractOptimizationProblem problem, InterfaceTextListener listener) { + public static Population postProcess(InterfacePostProcessParams params, Population inputPop, AbstractOptimizationProblem problem, InterfaceTextListener listener) { if (params.isDoPostProcessing()) { - Population outputPop; + Population clusteredPop, outputPop; if (params.getPostProcessClusterSigma() > 0) { - outputPop = (Population)PostProcess.clusterBest(solutions, params.getPostProcessClusterSigma(), 0, PostProcess.KEEP_LONERS, PostProcess.BEST_ONLY).clone(); - if (outputPop.size() < solutions.size()) { - if (listener != null) listener.println("Initial clustering reduced population size from " + solutions.size() + " to " + outputPop.size()); + 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 outputPop = solutions; + } else clusteredPop = inputPop; if (params.getPostProcessSteps() > 0) { - processWithHC(outputPop, problem, params.getPostProcessSteps()); - if (listener != null) listener.println("HC post processing done."); + processWithHC(clusteredPop, problem, params.getPostProcessSteps()); + if (listener != null) listener.println("HC post processing: " + params.getPostProcessSteps() + " steps done."); // some individuals may have now converged again if (params.getPostProcessClusterSigma() > 0) { // so if wished, cluster again. - outputPop = (Population)PostProcess.clusterBest(outputPop, params.getPostProcessClusterSigma(), 0, PostProcess.KEEP_LONERS, PostProcess.BEST_ONLY).clone(); - if (outputPop.size() < solutions.size()) { - if (listener != null) listener.println("Second clustering reduced population size from " + solutions.size() + " to " + outputPop.size()); + outputPop = (Population)PostProcess.clusterBest(clusteredPop, params.getPostProcessClusterSigma(), 0, PostProcess.KEEP_LONERS, PostProcess.BEST_ONLY).clone(); + if (outputPop.size() < clusteredPop.size()) { + if (listener != null) listener.println("Second clustering reduced population size from " + clusteredPop.size() + " to " + outputPop.size()); } else if (listener != null) listener.println("Second clustering yielded no size reduction."); - } - } + } else outputPop = clusteredPop; + } else outputPop = clusteredPop; double upBnd = PhenotypeMetric.norm(outputPop.getWorstEAIndividual().getFitness())*1.1; upBnd = Math.pow(10,Math.floor(Math.log10(upBnd)+1)); double lowBnd = 0; int[] sols = PostProcess.createFitNormHistogram(outputPop, lowBnd, upBnd, 20); // PostProcessInterim.outputResult((AbstractOptimizationProblem)goParams.getProblem(), outputPop, 0.01, System.out, 0, 2000, 20, goParams.getPostProcessSteps()); - if (listener != null) listener.println("measures: " + BeanInspector.toString(outputPop.getPopulationMeasures())); - if (listener != null) listener.println("solution histogram in [" + lowBnd + "," + upBnd + "]: " + BeanInspector.toString(sols)); + if (outputPop.size()>1) { + if (listener != null) listener.println("measures: " + BeanInspector.toString(outputPop.getPopulationMeasures())); + if (listener != null) listener.println("solution histogram in [" + lowBnd + "," + upBnd + "]: " + BeanInspector.toString(sols)); + } //////////// multimodal data output? if (problem instanceof InterfaceMultimodalProblemKnown) procMultiModalKnown(outputPop, (InterfaceMultimodalProblemKnown)problem, listener); - Population resPop = 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()>resPop.size()) ? ( "(first " + resPop.size() + " of " + outputPop.size() + ")") : "")); + 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() + ")") : "")); //////////// output some individual data - if (listener != null) for (int i=0; i