From abafb576791c5fc04bcd6ecb70f91adf2dfe02a0 Mon Sep 17 00:00:00 2001 From: Marcel Kronfeld Date: Tue, 17 Mar 2009 17:26:06 +0000 Subject: [PATCH] Merging MK branch revs. 243-249. Population sorting by fitness index, new package operators.paramcontrol for adaptive parameters, as well as minor stuff. --- src/eva2/EvAInfo.java | 4 + src/eva2/OptimizerFactory.java | 2 +- .../go/individuals/AbstractEAIndividual.java | 14 +- .../AbstractParameterControl.java | 67 +++++++++ .../paramcontrol/ActivityFeedbackControl.java | 124 ++++++++++++++++ .../paramcontrol/ConstantParameters.java | 30 ++++ .../InterfaceParameterControl.java | 46 ++++++ .../paramcontrol/LinearInertnessAdaption.java | 76 ++++++++++ .../server/go/populations/Population.java | 132 ++++++++++++++---- src/eva2/server/go/problems/F2Problem.java | 1 + .../go/strategies/DifferentialEvolution.java | 10 +- .../DynamicParticleSwarmOptimization.java | 15 +- .../go/strategies/NelderMeadSimplex.java | 73 ++++++---- .../strategies/ParticleSwarmOptimization.java | 122 ++++++++-------- src/eva2/server/modules/Processor.java | 48 ++++++- src/eva2/server/stat/AbstractStatistics.java | 3 +- src/eva2/tools/Mathematics.java | 116 ++++++++++++++- src/wsi/ra/math/RNG.java | 8 ++ 18 files changed, 761 insertions(+), 130 deletions(-) create mode 100644 src/eva2/server/go/operators/paramcontrol/AbstractParameterControl.java create mode 100644 src/eva2/server/go/operators/paramcontrol/ActivityFeedbackControl.java create mode 100644 src/eva2/server/go/operators/paramcontrol/ConstantParameters.java create mode 100644 src/eva2/server/go/operators/paramcontrol/InterfaceParameterControl.java create mode 100644 src/eva2/server/go/operators/paramcontrol/LinearInertnessAdaption.java diff --git a/src/eva2/EvAInfo.java b/src/eva2/EvAInfo.java index 1d943830..2c4ab00b 100644 --- a/src/eva2/EvAInfo.java +++ b/src/eva2/EvAInfo.java @@ -4,6 +4,10 @@ package eva2; * Main product and version information strings. * * --- Changelog + * 2.034: Adding a generic parameter control method for optimizers, currently used by PSO to adapt inertness depending + * on EvaluationTerminator or GenerationTerminator instances defining the number of function evaluations. + * The new package is eva2.server.go.operators.paramcontrol. + * A Population may now be ordered by a specific fitness criterion, employed, e.g., by Nelder-Mead-Simplex. * 2.033: There was an interesting problem with the Matlab-Interface, which just hung up after extensive optimization * loops, yet only if Matlab was started without X-forwarding (which is necessary for qsub, e.g.). * Debugging was tedious, since the debugging using System.out. itself caused threading deadlocks. The diff --git a/src/eva2/OptimizerFactory.java b/src/eva2/OptimizerFactory.java index 7db0bd17..57ca7e2b 100644 --- a/src/eva2/OptimizerFactory.java +++ b/src/eva2/OptimizerFactory.java @@ -259,7 +259,7 @@ public class OptimizerFactory { ga.addPopulationChangedEventListener(listener); ga.init(); - listener.registerPopulationStateChanged(ga.getPopulation(), ""); + if (listener!=null) listener.registerPopulationStateChanged(ga.getPopulation(), ""); return ga; } diff --git a/src/eva2/server/go/individuals/AbstractEAIndividual.java b/src/eva2/server/go/individuals/AbstractEAIndividual.java index c2a6f113..d5f91611 100644 --- a/src/eva2/server/go/individuals/AbstractEAIndividual.java +++ b/src/eva2/server/go/individuals/AbstractEAIndividual.java @@ -536,7 +536,19 @@ public abstract class AbstractEAIndividual implements IndividualInterface, java. this.m_Fitness[index] = fitness; } } - + + /** + * This method will set the fitness of the individual to the given value in every component. + * If the fitness was null, nothing will be done. + * + * @param resetVal The new fitness array + */ + public void resetFitness(double resetVal) { + if (m_Fitness!=null) { + for (int i=0; i desiredActivity) { // too high act, so decrease inertness + return Math.max(minInert, currentInertness - deltaInertness); + } else return currentInertness; + } + + private double desiredActivity(int iteration, int maxIteration) { + return Mathematics.linearInterpolation(iteration, 0, maxIteration, startAct, endAct); + } + + private double calculateActivity(ParticleSwarmOptimization pso) { + return pso.getPopulationAvgNormedVelocity(pso.getPopulation()); + } + + public double getMinInertness() { + return minInert; + } + public void setMinInertness(double minInert) { + this.minInert = minInert; + } + public String minInertnessTipText() { + return "The minimum inertness value to be used."; + } + + public double getMaxInertness() { + return maxInert; + } + public void setMaxInertness(double maxInert) { + this.maxInert = maxInert; + } + public String maxInertnessTipText() { + return "The maximum inertness value to be used."; + } + + public double getInitActivity() { + return startAct; + } + public void setInitActivity(double startAct) { + this.startAct = startAct; + } + public String initActivityTipText() { + return "The initial target activity (relative to the range)."; + } + + public double getFinalActivity() { + return endAct; + } + public void setFinalActivity(double endAct) { + this.endAct = endAct; + } + public String finalActivityTipText() { + return "The final target activity (relative to the range), should be close to zero."; + } + + public double getDeltaInertness() { + return deltaInertness; + } + public void setDeltaInertness(double deltaInertness) { + this.deltaInertness = deltaInertness; + } + public String deltaInertnessTipText() { + return "The additive change of the inertness in each adaption step."; + } + + public String globalInfo() { + return "Controls the inertness factor based on the average velocity."; + } +} diff --git a/src/eva2/server/go/operators/paramcontrol/ConstantParameters.java b/src/eva2/server/go/operators/paramcontrol/ConstantParameters.java new file mode 100644 index 00000000..d5d15171 --- /dev/null +++ b/src/eva2/server/go/operators/paramcontrol/ConstantParameters.java @@ -0,0 +1,30 @@ +package eva2.server.go.operators.paramcontrol; + +import java.io.Serializable; + +import eva2.server.go.InterfaceTerminator; + +/** + * Dummy implementation. This class is ignored by the Processor. Parameters will not be changed. + * + * @author mkron + * + */ +public class ConstantParameters extends AbstractParameterControl implements Serializable { + + public String[] getControlledParameters() { + return null; + } + + @Override + public Object[] getValues(Object obj, int iteration, int maxIteration) { + return null; + } + + public void updateParameters(Object obj) { + } + + public String globalInfo() { + return "Parameters will not be changed."; + } +} diff --git a/src/eva2/server/go/operators/paramcontrol/InterfaceParameterControl.java b/src/eva2/server/go/operators/paramcontrol/InterfaceParameterControl.java new file mode 100644 index 00000000..2dd06723 --- /dev/null +++ b/src/eva2/server/go/operators/paramcontrol/InterfaceParameterControl.java @@ -0,0 +1,46 @@ +package eva2.server.go.operators.paramcontrol; + +import eva2.server.go.populations.Population; + +/** + * Interface for dynamic changes to object parameters. + * When an optimizer has the getter method getParamControl retrieving an instance of this interface, + * an update is triggered after every optimize call. This allows parameters of the object to be + * adapted dynamically, such as linearly decreasing weights or control parameters. In case of PSO, + * this may be the linearly decreasing inertia weight or the activation feedback control mechanism. + * + * @author mkron + * + */ +public interface InterfaceParameterControl { + /** + * Initialize the parameter control instance before a run. + * + * @param obj The controlled object. + */ + public void init(Object obj); + + /** + * After an optimization run, finalizing stuff may be done. + * + * @param obj The controlled object. + */ + public void finish(Object obj); + + /** + * For a given runtime (maxIteration) and current iteration, update the parameters of the object. + * + * @param obj + * @param iteration + * @param maxIteration + */ + public void updateParameters(Object obj, int iteration, int maxIteration); + + /** + * If no runtime in terms of iterations can be specified, the parameter control may try to infer + * the state from the object itself. + * + * @param obj + */ + public void updateParameters(Object obj); +} diff --git a/src/eva2/server/go/operators/paramcontrol/LinearInertnessAdaption.java b/src/eva2/server/go/operators/paramcontrol/LinearInertnessAdaption.java new file mode 100644 index 00000000..5c0ff03e --- /dev/null +++ b/src/eva2/server/go/operators/paramcontrol/LinearInertnessAdaption.java @@ -0,0 +1,76 @@ +package eva2.server.go.operators.paramcontrol; + +import java.io.Serializable; + +import eva2.tools.Mathematics; + +/** + * Adapt PSO inertness linearly by time, from given start to end value. + * This only works if iterations are known. + * + * @author mkron + * + */ +public class LinearInertnessAdaption extends AbstractParameterControl implements Serializable { + String[] params = {"inertnessOrChi"}; + private double startV=0.7; + private double endV=0.2; + + public LinearInertnessAdaption() { + startV=0.7; + endV=0.2; + } + + public LinearInertnessAdaption(double startValue, double endValue, int functionCalls) { + startV=startValue; + endV=endValue; + } + + public String[] getControlledParameters() { + return params; + } + + public Object[] getValues(Object obj, int iteration, int maxIteration) { + if (maxIteration < 0) { // there is no maxIteration known + System.err.println("Not changing inertness - missing iteration information!"); + return null; + } else { + Object[] vals=new Object[1]; + vals[0] = new Double(calcInertness(iteration, maxIteration)); + return vals; + } + } + + private double calcInertness(int iteration, int max) { + return Mathematics.linearInterpolation(iteration, 0, max, startV, endV); +// return startV+((endV-startV)*(iteration/(double)max)); + } + + public double getStartVal() { + return startV; + } + + public void setStartVal(double startV) { + this.startV = startV; + } + + public String startValTipText() { + return "Start value for the inertness"; + } + + public double getEndVal() { + return endV; + } + + public void setEndVal(double endV) { + this.endV = endV; + } + + public String endValTipText() { + return "End value for the inertness"; + } + + public String globalInfo() { + return "Linearly adapt the inertnessOrChi value of PSO"; + } +} diff --git a/src/eva2/server/go/populations/Population.java b/src/eva2/server/go/populations/Population.java index 18e45d36..746e5051 100644 --- a/src/eva2/server/go/populations/Population.java +++ b/src/eva2/server/go/populations/Population.java @@ -57,10 +57,12 @@ public class Population extends ArrayList implements PopulationInterface, Clonea private int lastQModCount = -1; // a sorted queue (for efficiency) transient private ArrayList sortedArr = null; + private int lastFitCrit = -1; + // remember when the last evaluation was performed - private Pair evaluationTimeHashes = null; +// private Pair evaluationTimeHashes = null; // remember when the last evaluation was performed - private int evaluationTimeModCount = -1; +// private int evaluationTimeModCount = -1; public Population() { } @@ -154,8 +156,8 @@ public class Population extends ArrayList implements PopulationInterface, Clonea this.m_History = new ArrayList(); this.m_Generation = 0; this.m_FunctionCalls = 0; - evaluationTimeHashes = null; - evaluationTimeModCount = -1; +// evaluationTimeHashes = null; +// evaluationTimeModCount = -1; if (this.m_Archive != null) { this.m_Archive.clear(); this.m_Archive.init(); @@ -373,9 +375,26 @@ public class Population extends ArrayList implements PopulationInterface, Clonea return domSet; } - private boolean compareFit(boolean bChooseBetter, double[] fit1, double[] fit2) { - if (bChooseBetter) return AbstractEAIndividual.isDominatingFitness(fit1, fit2); - else return AbstractEAIndividual.isDominatingFitness(fit2, fit1); + + /** + * Compare two fitness vectors. If bChooseBetter is true, the function delivers the predicate + * "first is better than second" using the fitness component indicated by fitIndex or a dominance + * criterion if fitIndex < 0. + * + * @param bChooseBetter + * @param fit1 + * @param fit2 + * @param fitIndex + * @return + */ + private boolean compareFit(boolean bChooseBetter, double[] fit1, double[] fit2, int fitIndex) { + if (fitIndex < 0) { // multiobjective case + if (bChooseBetter) return AbstractEAIndividual.isDominatingFitness(fit1, fit2); + else return AbstractEAIndividual.isDominatingFitness(fit2, fit1); + } else { + if (bChooseBetter) return fit1[fitIndex]fit2[fitIndex]; + } } /** @@ -387,7 +406,7 @@ public class Population extends ArrayList implements PopulationInterface, Clonea */ public int getIndexOfBestIndividual() { if (size()<1) return -1; - return getIndexOfBestOrWorstIndividual(true, true); + return getIndexOfBestOrWorstIndividual(true, true, -1); } /** @@ -398,7 +417,31 @@ public class Population extends ArrayList implements PopulationInterface, Clonea * @return The index of the best individual. */ public int getIndexOfWorstIndividual() { - return getIndexOfBestOrWorstIndividual(false, false); + return getIndexOfBestOrWorstIndividual(false, false, -1); + } + + /** + * This method will return the index of the current best individual from the + * population in the given fitness component (or using dominance when fitIndex < 0). + * If the population is empty, -1 is returned. + * + * @see getIndexOfBestOrWorstIndividual() + * @return The index of the best individual. + */ + public int getIndexOfBestIndividual(int fitIndex) { + if (size()<1) return -1; + return getIndexOfBestOrWorstIndividual(true, true, fitIndex); + } + + /** + * This method will return the index of the current best individual from the + * population in the given fitness component (or using dominance when fitIndex < 0). + * + * @see getIndexOfBestOrWorstIndividual() + * @return The index of the best individual. + */ + public int getIndexOfWorstIndividual(int fitIndex) { + return getIndexOfBestOrWorstIndividual(false, false, fitIndex); } /** @@ -412,7 +455,7 @@ public class Population extends ArrayList implements PopulationInterface, Clonea * @param indicate whether constraints should be regarded * @return The index of the best (worst) individual. */ - public int getIndexOfBestOrWorstIndividual(boolean bBest, boolean checkConstraints) { + public int getIndexOfBestOrWorstIndividual(boolean bBest, boolean checkConstraints, int fitIndex) { int result = -1; double[] curSelFitness = null; boolean allViolate = true; @@ -420,7 +463,7 @@ public class Population extends ArrayList implements PopulationInterface, Clonea for (int i = 0; i < super.size(); i++) { if (!checkConstraints || !(getEAIndividual(i).violatesConstraint())) { allViolate = false; - if ((result<0) || (compareFit(bBest, getEAIndividual(i).getFitness(), curSelFitness))) { + if ((result<0) || (compareFit(bBest, getEAIndividual(i).getFitness(), curSelFitness, fitIndex))) { // fit i is better than remembered result = i; curSelFitness = getEAIndividual(i).getFitness(); // remember fit i @@ -460,16 +503,28 @@ public class Population extends ArrayList implements PopulationInterface, Clonea * @return The best individual */ public AbstractEAIndividual getBestEAIndividual() { + return getBestEAIndividual(-1); + } + + /** + * This method returns the current best individual from the population + * by a given fitness component. + * If the population is empty, null is returned. + * + * @param fitIndex the fitness criterion index or -1 + * @return The best individual + */ + public AbstractEAIndividual getBestEAIndividual(int fitIndex) { if (size()<1) return null; - int best = this.getIndexOfBestIndividual(); - if (best == -1) { - System.err.println("This shouldnt happen!"); - return null; - } else { - AbstractEAIndividual result = (AbstractEAIndividual)this.get(best); - if (result == null) System.err.println("Serious Problem! Population Size: " + this.size()); - return result; - } + int best = this.getIndexOfBestIndividual(fitIndex); + if (best == -1) { + System.err.println("This shouldnt happen!"); + return null; + } else { + AbstractEAIndividual result = (AbstractEAIndividual)this.get(best); + if (result == null) System.err.println("Serious Problem! Population Size: " + this.size()); + return result; + } } /** @@ -548,14 +603,34 @@ public class Population extends ArrayList implements PopulationInterface, Clonea } /** - * Avoids having to sort again in several calls without modifications in between. + * Set a fitness criterion for sorting procedures. This also affects getBest + * @param fitIndex + */ + public void setSortingFitnessCriterion(int fitIndex) { + getSorted(fitIndex); + } + + /** + * Reuses the last fitness criterion. Avoid having to sort again in several calls without modifications in between. * The returned array should not be modified! * * @return */ protected ArrayList getSorted() { - if (sortedArr == null || (super.modCount != lastQModCount)) { - PriorityQueue sQueue = new PriorityQueue(super.size(), new AbstractEAIndividualComparator()); + return getSorted(lastFitCrit); + } + + /** + * Avoids having to sort again in several calls without modifications in between. + * The returned array should not be modified! + * + * @param fitIndex the fitness criterion to be used or -1 for pareto dominance + * @return + */ + protected ArrayList getSorted(int fitIndex) { + if ((fitIndex != lastFitCrit) || (sortedArr == null) || (super.modCount != lastQModCount)) { + lastFitCrit=fitIndex; // TODO check if this works right? + PriorityQueue sQueue = new PriorityQueue(super.size(), new AbstractEAIndividualComparator(fitIndex)); for (int i = 0; i < super.size(); i++) { AbstractEAIndividual indy = getEAIndividual(i); if (indy != null) sQueue.add(indy); @@ -568,7 +643,7 @@ public class Population extends ArrayList implements PopulationInterface, Clonea } return sortedArr; } - + /** This method returns n random best individuals from the population. * * @param n number of individuals to look out for @@ -635,7 +710,11 @@ public class Population extends ArrayList implements PopulationInterface, Clonea * @return The best individual */ public AbstractEAIndividual getWorstEAIndividual() { - return getEAIndividual(getIndexOfWorstIndividual()); + return getWorstEAIndividual(-1); + } + + public AbstractEAIndividual getWorstEAIndividual(int fitIndex) { + return getEAIndividual(getIndexOfWorstIndividual(fitIndex)); } /** @@ -1046,7 +1125,8 @@ public class Population extends ArrayList implements PopulationInterface, Clonea */ public double[] getCenterWeighted(AbstractSelProb selProb, int criterion, boolean obeyConst) { selProb.computeSelectionProbability(this, "Fitness", obeyConst); - double[] mean = AbstractEAIndividual.getDoublePosition(getEAIndividual(0)); + double[] mean = AbstractEAIndividual.getDoublePosition(getEAIndividual(0)).clone(); + if (mean != null) { Arrays.fill(mean, 0.); AbstractEAIndividual indy = null; diff --git a/src/eva2/server/go/problems/F2Problem.java b/src/eva2/server/go/problems/F2Problem.java index fa6dc4d0..ebb46996 100644 --- a/src/eva2/server/go/problems/F2Problem.java +++ b/src/eva2/server/go/problems/F2Problem.java @@ -35,6 +35,7 @@ public class F2Problem extends F1Problem implements InterfaceMultimodalProblem, for (int i = 0; i < x.length-1; i++) { result[0] += (100*(x[i+1]-x[i]*x[i])*(x[i+1]-x[i]*x[i])+(x[i]-1)*(x[i]-1)); } + if (result[0]<=0) result[0]=Math.sqrt(Double.MIN_VALUE); // guard for plots in log scale return result; } diff --git a/src/eva2/server/go/strategies/DifferentialEvolution.java b/src/eva2/server/go/strategies/DifferentialEvolution.java index 2008a24b..08d5cc5d 100644 --- a/src/eva2/server/go/strategies/DifferentialEvolution.java +++ b/src/eva2/server/go/strategies/DifferentialEvolution.java @@ -3,6 +3,7 @@ package eva2.server.go.strategies; import java.util.Vector; import wsi.ra.math.RNG; +import eva2.gui.BeanInspector; import eva2.gui.GenericObjectEditor; import eva2.server.go.InterfacePopulationChangedEventListener; import eva2.server.go.enums.DETypeEnum; @@ -329,6 +330,11 @@ public class DifferentialEvolution implements InterfaceOptimizer, java.io.Serial } private AbstractEAIndividual getRandomIndy(Population pop) { + if (pop.size()<1) { + System.err.println("Error: invalid pop size in DE!"); + System.err.println("DE: \n"+ BeanInspector.toString(this) + "\nPop: \n" + BeanInspector.toString(pop)); + } + int randIndex = RNG.randomInt(0, pop.size()-1); return pop.getEAIndividual(randIndex); } @@ -345,7 +351,7 @@ public class DifferentialEvolution implements InterfaceOptimizer, java.io.Serial public void optimize() { AbstractEAIndividual indy = null, org; int index; - + int nextDoomed = getNextDoomed(m_Population, 0); // required for dynamic problems especially @@ -354,7 +360,7 @@ public class DifferentialEvolution implements InterfaceOptimizer, java.io.Serial * MK: added aging mechanism to provide for dynamically changing problems. If an individual * reaches the age limit, it is doomed and replaced by the next challenge vector, even if its worse. */ - + for (int i = 0; i < this.m_Population.size(); i++) { indy = this.generateNewIndividual(this.m_Population); this.m_Problem.evaluate(indy); diff --git a/src/eva2/server/go/strategies/DynamicParticleSwarmOptimization.java b/src/eva2/server/go/strategies/DynamicParticleSwarmOptimization.java index f9acae49..2ad922cd 100644 --- a/src/eva2/server/go/strategies/DynamicParticleSwarmOptimization.java +++ b/src/eva2/server/go/strategies/DynamicParticleSwarmOptimization.java @@ -122,7 +122,7 @@ public class DynamicParticleSwarmOptimization extends ParticleSwarmOptimization * @return the favourite speed limit. */ public double getFavTrackingSpeed(double[][] range) { - return 2*getRelativeSpeed(getEMASpeed(), range); + return 2*Mathematics.getRelativeLength(getEMASpeed(), range); } /** @@ -180,13 +180,13 @@ public class DynamicParticleSwarmOptimization extends ParticleSwarmOptimization protected void plotIndy(double[] curPosition, double[] curVelocity, int index) { if (this.m_Show) { if (plotBestOnly) { - return; -// if (index != ((Integer)(m_Population.getBestEAIndividual().getData(indexKey)))) return; -// else { + if (index != ((Integer)(m_Population.getBestEAIndividual().getData(indexKey)))) return; + else { // if (lastBestPlot != null) this.m_Plot.setConnectedPoint(lastBestPlot[0], lastBestPlot[1], index); // this.m_Plot.setConnectedPoint(curPosition[0], curPosition[1], index); -// lastBestPlot = curPosition.clone(); -// } + this.m_Plot.setUnconnectedPoint(curPosition[0], curPosition[1], index); + lastBestPlot = curPosition.clone(); + } } else { if (curVelocity == null) { @@ -404,6 +404,9 @@ public class DynamicParticleSwarmOptimization extends ParticleSwarmOptimization System.err.println("Could not perform PSO update, because individual is not instance of InterfaceESIndividual!"); } } + //if (AbstractEAIndividual.getDoublePosition(indy)[0]<500000) { + // System.err.println(indy.getStringRepresentation()); + //} } /** This method will evaluate the current population using the diff --git a/src/eva2/server/go/strategies/NelderMeadSimplex.java b/src/eva2/server/go/strategies/NelderMeadSimplex.java index ce05816b..d4a2965f 100644 --- a/src/eva2/server/go/strategies/NelderMeadSimplex.java +++ b/src/eva2/server/go/strategies/NelderMeadSimplex.java @@ -3,13 +3,8 @@ package eva2.server.go.strategies; import java.io.Serializable; import java.util.Vector; -import com.sun.org.apache.bcel.internal.generic.CHECKCAST; - -import eva2.OptimizerFactory; -import eva2.OptimizerRunnable; import eva2.gui.BeanInspector; import eva2.server.go.InterfacePopulationChangedEventListener; -import eva2.server.go.InterfaceTerminator; import eva2.server.go.individuals.AbstractEAIndividual; import eva2.server.go.individuals.InterfaceDataTypeDouble; import eva2.server.go.populations.InterfaceSolutionSet; @@ -18,7 +13,6 @@ import eva2.server.go.populations.SolutionSet; import eva2.server.go.problems.AbstractOptimizationProblem; import eva2.server.go.problems.AbstractProblemDouble; import eva2.server.go.problems.InterfaceOptimizationProblem; -import eva2.server.stat.StatsParameter; import eva2.tools.Mathematics; /** @@ -35,6 +29,8 @@ public class NelderMeadSimplex implements InterfaceOptimizer, Serializable, Inte // simulating the generational cycle. Set rather small (eg 5) for use as local search, higher for global search (eg 50) private int generationCycle = 50; + private int fitIndex = 0; // choose criterion for multi objective functions + private Population m_Population; private AbstractOptimizationProblem m_Problem; private transient Vector m_Listener; @@ -96,14 +92,31 @@ public class NelderMeadSimplex implements InterfaceOptimizer, Serializable, Inte return r; } + protected boolean firstIsBetter(double[] first, double[] second) { + return first[fitIndex]r_ind.getFitness(0)){ //neues besser als bisher bestes => Expansion - + if (firstIsBetter(best, reflectedInd) && firstIsBetter(reflectedInd, bestpop.getWorstEAIndividual(fitIndex))) { + return reflectedInd; + } else if (firstIsBetter(reflectedInd, best)) { //neues besser als bisher bestes => Expansion double[] e = new double[dim]; for (int i=0; i= bestpop.getWorstEAIndividual().getFitness(0)){//kontrahiere da neues indi keine verbesserung brachte + } else if (firstIsBetterEqual(bestpop.getWorstEAIndividual(fitIndex), reflectedInd)) { + //kontrahiere da neues indi keine verbesserung brachte double[] c = new double[dim]; for (int i=0; i 0); if ((calcModeSwitch & 3) == 0) System.err.println("Error, switch must be 1, 2 or 3 (getPopulationVelSpeed)"); - double[] velocity = (double[]) indy.getData(partVelKey); - if (calcVectVelocity) retSize+=velocity.length; // entries for cumulative velocity - if (calcAbsSpeedAverage) retSize++; // one entry for average absolute speed - // return length of the array depends on what should be calculated - ret = new double[retSize]; - + double[] velocity = (double[]) indy.getData(velocityKey); if (velocity != null) { + if (calcVectVelocity) retSize+=velocity.length; // entries for cumulative velocity + if (calcAbsSpeedAverage) retSize++; // one entry for average absolute speed + // return length of the array depends on what should be calculated + ret = new double[retSize]; + double[] cumulVeloc = new double[velocity.length]; double avSpeed = 0.; for (int i=0; i speedLim) { + while (Mathematics.getRelativeLength(curVelocity, range) > speedLim) { for (int i = 0; i < curVelocity.length; i++) { curVelocity[i] *= this.m_ReduceSpeed; } @@ -1145,9 +1131,9 @@ public class ParticleSwarmOptimization implements InterfaceOptimizer, java.io.Se if (sleepTime > 0 ) try { Thread.sleep(sleepTime); } catch(Exception e) {} - maybeClearPlot(); +// maybeClearPlot(); } - + protected void maybeClearPlot() { if (((m_Population.getGeneration() % 23) == 0) && isShow() && (m_Plot != null)) { m_Plot.clearAll(); @@ -1784,4 +1770,12 @@ public class ParticleSwarmOptimization implements InterfaceOptimizer, java.io.Se protected void setEmaPeriods(int emaPeriods) { this.emaPeriods = emaPeriods; } + + public InterfaceParameterControl getParamControl() { + return paramControl; + } + + public void setParamControl(InterfaceParameterControl paramControl) { + this.paramControl = paramControl; + } } \ No newline at end of file diff --git a/src/eva2/server/modules/Processor.java b/src/eva2/server/modules/Processor.java index def3d933..3e950639 100644 --- a/src/eva2/server/modules/Processor.java +++ b/src/eva2/server/modules/Processor.java @@ -8,7 +8,10 @@ import eva2.gui.BeanInspector; import eva2.server.go.InterfaceGOParameters; import eva2.server.go.InterfacePopulationChangedEventListener; import eva2.server.go.InterfaceProcessor; +import eva2.server.go.InterfaceTerminator; import eva2.server.go.PopulationInterface; +import eva2.server.go.operators.paramcontrol.ConstantParameters; +import eva2.server.go.operators.paramcontrol.InterfaceParameterControl; import eva2.server.go.operators.postprocess.PostProcess; import eva2.server.go.operators.postprocess.PostProcessParams; import eva2.server.go.operators.terminators.EvaluationTerminator; @@ -16,6 +19,7 @@ import eva2.server.go.operators.terminators.GenerationTerminator; import eva2.server.go.populations.Population; import eva2.server.go.problems.AbstractOptimizationProblem; import eva2.server.go.problems.InterfaceAdditionalPopulationInformer; +import eva2.server.go.strategies.InterfaceOptimizer; import eva2.server.stat.InterfaceStatistics; import eva2.server.stat.InterfaceTextListener; import eva2.server.stat.StatisticsWithGUI; @@ -202,14 +206,19 @@ public class Processor extends Thread implements InterfaceProcessor, InterfacePo //m_Statistics.createNextGenerationPerformed((PopulationInterface)this.m_ModulParameter.getOptimizer().getPopulation()); if (m_ListenerModule!=null) m_ListenerModule.updateProgress(getStatusPercent(goParams.getOptimizer().getPopulation(), runCounter, m_Statistics.getStatisticsParameter().getMultiRuns()), null); if (popLog != null) EVAHELP.clearLog(popLog); + maybeInitParamCtrl(goParams.getOptimizer()); + do { // main loop + maybeUpdateParamCtrl(goParams.getOptimizer(), goParams.getTerminator()); + this.goParams.getOptimizer().optimize(); // registerPopulationStateChanged *SHOULD* be fired by the optimizer or resp. the population // as we are event listener if (popLog != null) EVAHELP.logString(this.goParams.getOptimizer().getPopulation().getIndyList(), popLog); } while (isOptRunning() && !this.goParams.getTerminator().isTerminated(this.goParams.getOptimizer().getAllSolutions())); runCounter++; - + maybeFinishParamCtrl(goParams.getOptimizer()); + //////////////// Default stats m_Statistics.stopOptPerformed(isOptRunning(), goParams.getTerminator().lastTerminationMessage()); // stop is "normal" if opt wasnt set false by the user (and thus still true) @@ -228,7 +237,42 @@ public class Processor extends Thread implements InterfaceProcessor, InterfacePo return resultPop; } - /** + private void maybeInitParamCtrl(InterfaceOptimizer optimizer) { + Object paramCtrl=null; + if (null!=(paramCtrl=BeanInspector.callIfAvailable(optimizer, "getParamControl", null))) { + if (paramCtrl instanceof InterfaceParameterControl) { + if (!(paramCtrl instanceof ConstantParameters)) { + ((InterfaceParameterControl)paramCtrl).init(optimizer); + } + } + } + } + + private void maybeFinishParamCtrl(InterfaceOptimizer optimizer) { + Object paramCtrl=null; + if (null!=(paramCtrl=BeanInspector.callIfAvailable(optimizer, "getParamControl", null))) { + if (paramCtrl instanceof InterfaceParameterControl) { + if (!(paramCtrl instanceof ConstantParameters)) { + ((InterfaceParameterControl)paramCtrl).finish(optimizer); + } + } + } + } + private void maybeUpdateParamCtrl(InterfaceOptimizer optimizer, + InterfaceTerminator terminator) { + Object paramCtrl=null; + if (null!=(paramCtrl=BeanInspector.callIfAvailable(optimizer, "getParamControl", null))) { + if (paramCtrl instanceof InterfaceParameterControl) { + if (!(paramCtrl instanceof ConstantParameters)) { + if (terminator instanceof GenerationTerminator) ((InterfaceParameterControl)paramCtrl).updateParameters(optimizer, optimizer.getPopulation().getGeneration(), ((GenerationTerminator)terminator).getGenerations()); + else if (terminator instanceof EvaluationTerminator) ((InterfaceParameterControl)paramCtrl).updateParameters(optimizer, optimizer.getPopulation().getFunctionCalls(), ((EvaluationTerminator)terminator).getFitnessCalls()); + else ((InterfaceParameterControl)paramCtrl).updateParameters(optimizer); + } + } + } + } + + /** * Calculate the percentage of current (multi-)run already performed, based on evaluations/generations * for the EvaluationTerminator/GenerationTerminator or multi-runs only. * diff --git a/src/eva2/server/stat/AbstractStatistics.java b/src/eva2/server/stat/AbstractStatistics.java index 27fbd893..49df503b 100644 --- a/src/eva2/server/stat/AbstractStatistics.java +++ b/src/eva2/server/stat/AbstractStatistics.java @@ -190,6 +190,7 @@ public abstract class AbstractStatistics implements InterfaceTextListener, Inter if (printFinalVerbosity()) printToTextListener(refineToText(meanCollection, showAvgIntervals)); } } + if (TRACE) System.out.println("End of run"); if (resultOut != null) { @@ -257,7 +258,7 @@ public abstract class AbstractStatistics implements InterfaceTextListener, Inter protected String getOutputHeader(List informerList, PopulationInterface pop) { - String headline = "Fun.calls \t Best \t Mean \t Worst "; + String headline = "Fun.calls\t Best\t Mean\t Worst "; if ((informerList == null) || !m_StatsParams.isOutputAdditionalInfo()) { return headline; } else { diff --git a/src/eva2/tools/Mathematics.java b/src/eva2/tools/Mathematics.java index 94498713..d83d6d7b 100644 --- a/src/eva2/tools/Mathematics.java +++ b/src/eva2/tools/Mathematics.java @@ -2,6 +2,9 @@ package eva2.tools; import java.util.Arrays; +import eva2.server.go.individuals.InterfaceDataTypeDouble; + +import wsi.ra.math.RNG; import wsi.ra.math.Jama.Matrix; import wsi.ra.math.interpolation.BasicDataSet; import wsi.ra.math.interpolation.InterpolationException; @@ -433,7 +436,7 @@ public class Mathematics { } return result; } - + /** * Multiplies (scales) every element of the array v with s returning a new vector. * @@ -491,7 +494,20 @@ public class Mathematics { res[i] = v[i] / s; } } - + + /** + * Component wise multiplication of vectors: res[i]=u[i]*v[i] + * + * @param s + * @param v + * @return + */ + public static void vvMultCw(double[] u, double[] v, double[] res) { + for (int i = 0; i < res.length; i++) { + res[i] = u[i]*v[i]; + } + } + /** * Return a vector of given length containing zeroes. * @param n @@ -615,6 +631,41 @@ public class Mathematics { svDiv(norm(v), v, res); } + /** + * Calculates the norm of the given vector relative to the problem range. + * + * @param vector a double vector within the range + * @param range the range in each dimension + * @return measure of the length relative to the problem range + */ + public static double getRelativeLength(double[] vector, double[][] range) { + double sumV = 0; + double sumR = 0; + for (int i = 0; i < range.length; i++) { + sumV += Math.pow(vector[i], 2); + sumR += Math.pow(range[i][1] - range[i][0], 2); + } + sumV = Math.sqrt(sumV); + sumR = Math.sqrt(sumR); + return sumV/sumR; + } + + /** + * Create a random vector, the components will be set to gaussian distributed + * values with mean zero and the given standard deviation. + * + * @param dim the desired dimension + * @param stdDev the gaussian standard deviation + * @return random vector + */ + public static double[] randomVector(int dim, double stdDev) { + double[] vect = new double[dim]; + for (int j = 0; j < vect.length; j++) { + vect[j] = RNG.gaussianDouble(stdDev); + } + return vect; + } + /** * Normalizes the doubles in the array by their sum, * so that they add up to one. @@ -676,6 +727,52 @@ public class Mathematics { return A; } + /** + * Rotate the vector by angle alpha around axis i/j + * + * @param vect + * @param alpha + * @param i + * @param j + */ + public static void rotate(double[] vect, double alpha, int i, int j) { + double xi = vect[i]; + double xj = vect[j]; + vect[i] = (xi*Math.cos(alpha))-(xj*Math.sin(alpha)); + vect[j] = (xi*Math.sin(alpha))+(xj*Math.cos(alpha)); + } + + /** + * Rotate the vector along all axes by angle alpha or a uniform random value + * in [-alpha, alpha] if randomize is true. + * + * @param vect + * @param alpha + * @param randomize + */ + public static void rotateAllAxes(double[] vect, double alpha, boolean randomize) { + for (int i=0; i hi)) { + System.err.println("Error in RNG.randomInt!"); + result = Math.abs(random.nextInt()%(hi-lo+1))+lo; + } return result; }