package eva2.optimization.strategies; import eva2.OptimizerFactory; import eva2.gui.editor.GenericObjectEditor; import eva2.optimization.OptimizationParameters; import eva2.optimization.enums.PSOTopology; import eva2.optimization.individuals.AbstractEAIndividual; import eva2.optimization.individuals.InterfaceDataTypeDouble; import eva2.optimization.operator.nichepso.deactivation.StandardDeactivationStrategy; import eva2.optimization.operator.paramcontrol.LinearParamAdaption; import eva2.optimization.operator.paramcontrol.ParamAdaption; import eva2.optimization.operator.terminators.EvaluationTerminator; import eva2.optimization.operator.terminators.InterfaceTerminator; import eva2.optimization.population.Population; import eva2.optimization.population.PopulationInterface; import eva2.problems.AbstractOptimizationProblem; import eva2.problems.Interface2DBorderProblem; import eva2.problems.InterfaceAdditionalPopulationInformer; import eva2.tools.ToolBox; import eva2.tools.chart2d.DPoint; import eva2.tools.chart2d.DPointSet; import java.util.Iterator; import java.util.List; import java.util.Set; import java.util.Vector; /** * The Adaptive Niching PSO(ANPSO)[1] extends the particle swarm optimizer (PSO) * by Kennedy and Eberhart to locate multiple optima of a multimodal objective function. * The Algorithm uses similar concepts as the NichePSO such as a main swarm to explore * the search space and subswarms to refine and represent single niches. * The implemented version uses the "inertness weight" PSO to train the main swarm. * mainSwarmInertness sets the inertia weight omega and weights the particles tendency to follow its former movement. * This controls exploration (favored by larger values) against exploitation (favored by smaller values). * mainSwarmPhi1 sets Phi1 and weights the cognitive component. * The term corresponds to the particles tendency to return to its personal best position. * mainSwarmPhi2 sets Phi2 and weights the social component. * The term corresonds to the particles tendency to be attracted towards its neighborhood best position. * A small value for mainSwarmPhi2 reduces the influence of the neighborhood and each particle tend to * perfom a local search on its own. This results in a high exploration ability of the main swarm and * potentially leads to a good amount of identified optima. * Larger values for mainSwarmPhi2 on the other hand might help to concentrate on fewer optima with superior fitness values. *

* To avoid further parameters and the need to specify adequate values, which are often difficult to decide, * the following adaption mechanism is employed: * ANPSO adaptively determines a threshold parameter r during every generation by computing the average * distance a particle has to its neighbor. Subsequently, a so called s-matrix is calculated that keeps * track of how long any two particles are close (i.e. within r) to each other. * The s-matrix is used to build a niche graph that represents particles as vertices and connects all particles * that have been close to each other for at least two consecutive generations. * Particles that are connected in the niche graph form a subswarm. * The implemented version uses a strategy to deactivate subswarms when all containing particles converged on a solution. * Furthermore, different neighborhood topologies can be choosen for the main swarm. * In case the Multi-Swarm topology is used, the species radius is adaptively determined as well. *

* [1] S. Bird and X. Li: * Adaptively choosing niching parameters in a PSO. * In: GECCO '06: Proceedings of the 8th annual conference on Genetic and evolutionary computation, * Seiten 3--10, New York, NY, USA, 2006. ACM * * @author aschoff, mkron */ public class ANPSO extends NichePSO implements InterfaceAdditionalPopulationInformer, java.io.Serializable { /** * ******************************************************************************************************************* * members */ // for ANPSO it is necessary to keep an own archiv of inactive subswarms, because the standard set of // subswarms is completely renewed every iteration. public Vector inactiveSubSwarms = new Vector<>(); // the s matrix keeps track of how long particles are close to each other int[][] s = new int[mainSwarmSize][mainSwarmSize]; // the niche graph represents particles as vertices and connects all particles that // have been close to each other for at least two consecutive generations protected NicheGraph nicheGraph = new NicheGraph(); // defines the minimal distance for neighboring particles at which they form a subswarm // (this is proposed by Bird and Lee for further investigation) protected double minimalR = 0; private double updateRadius = 0.; // maximum subswarm size private int maxInitialSubSwarmSize = 0; private int maxNeighborCntNicheGraph = 4; // maximum for neighborhood matrix private int minNeighborCntNicheGraph = 0; // minimum for neighborhood matrix private int neighborCntNicheGraphForEdge = 2; // number of steps req. to build an edge /** * ******************************************************************************************************************* * ctors, clone */ public ANPSO() { // NichePSO.stdNPSO(anpso, problem, randSeed, evalCnt); // NichePSO.stdNPSO((ANPSO)this, (AbstractOptimizationProblem)this.problem, 0, 1000); /////////// from NichePSO // super.initMainSwarm(); // not really necessary if initialize is called before optimization but this way initialize doesnt change the parameters of a newly constructed object // super.initSubswarmOptimizerTemplate(); // setMergingStrategy(new StandardMergingStrategy(0.001)); // setAbsorptionStrategy(new StandardAbsorptionStrategy()); // setSubswarmCreationStrategy(new StandardSubswarmCreationStrategy(0.0001)); // // setMaxAllowedSwarmRadius(0.0001); // formally limits the swarm radius of the subswarms // Parameter for the mainswarm // npso.getMainSwarm().setSpeedLimit(avgRange/2.); // npso.getMainSwarm().setCheckSpeedLimit(true); // parameter for the subswarms // System.out.println(BeanInspector.niceToString(getSubswarmOptimizerTemplate())); // getSubswarmOptimizerTemplate().setGcpso(true); // getSubswarmOptimizerTemplate().setRho(0.1); // on 2D Problems empirically better than default value 1 // getSubswarmOptimizerTemplate().setAlgoType(new SelectedTag("Constriction")); // getSubswarmOptimizerTemplate().setConstriction(2.05, 2.05); // System.out.println(BeanInspector.niceToString(getSubswarmOptimizerTemplate())); ///////////end from NichePSO getMainSwarm().setPhi1(2.05); getMainSwarm().setPhi2(2.05); getMainSwarm().setInertnessOrChi(0.7298437881283576); getMainSwarm().setAlgoType(ParticleSwarmOptimization.PSOType.Constriction); setMainSwarmAlgoType(ParticleSwarmOptimization.PSOType.Constriction); // constriction setMaxInitialSubSwarmSize(0); // deactivate early reinits setMainSwarmTopology(PSOTopology.grid); setMainSwarmTopologyRange(1); setDeactivationStrategy(new StandardDeactivationStrategy(0.000001, 8)); setMainSwarmSize(100); } /*public ANPSO(){ // Parameter for the mainswarm // //Earlier standard settings: // this.setMainSwarmAlgoType(getMainSwarm().getAlgoType().setSelectedTag("Inertness")); // this.mainSwarmPhi1 = 1.2; // this.mainSwarmPhi2 = 0.6; // ANPSO uses communication in the main swarm // this.mainSwarmTopology = PSOTopologyEnum.multiSwarm; //"Multi-Swarm" favors the formation of groups in the main swarm // this.mainSwarmTopologyRange = 2; // range for topologies like random, grid etc. (does not affect "Multi-Swarm") // this.setMainSwarmInertness(new NoParameterAging(0.73)); this.setMainSwarmPhi1(2.05); this.setMainSwarmPhi2(2.05); this.setMainSwarmInertness(new NoParameterAging(0.7298437881283576)); this.setMainSwarmAlgoType(getMainSwarm().getAlgoType().setSelectedTag("Constriction")); // constriction this.setMaxInitialSubSwarmSize(0); // deactivate early reinits this.setMainSwarmTopology(PSOTopologyEnum.grid); this.setMainSwarmTopologyRange(1); this.setDeactivationStrategy(new StandardDeactivationStrategy(0.000001, 8)); hideHideable(); initMainSwarm(); }*/ public ANPSO(int mainSwarmSize, double phi1, double phi2, PSOTopology mainSwarmTopo, int mainSwarmTopoRange, int maxInitialSubSwarmSize) { this(); setMainSwarmSize(mainSwarmSize); getMainSwarm().setPhi1(phi1); getMainSwarm().setPhi2(phi2); // setMainSwarmPhi1(phi1); // setMainSwarmPhi2(phi2); setMainSwarmTopologyRange(mainSwarmTopoRange); setMainSwarmTopology(mainSwarmTopo); setMaxInitialSubSwarmSize(maxInitialSubSwarmSize); } /** * Take care that all properties which may be hidden (and currently are) send a "hide" message to the Java Bean properties. * This is called by PropertySheetPanel in use with the GenericObjectEditor. */ @Override public void hideHideable() { // hide the following unused properties from the GUI GenericObjectEditor.setHideProperty(getClass(), "subswarmCreationStrategy", true); GenericObjectEditor.setHideProperty(getClass(), "mergingStrategy", true); GenericObjectEditor.setHideProperty(getClass(), "absorptionStrategy", true); GenericObjectEditor.setHideProperty(getClass(), "maxAllowedSwarmRadius", true); GenericObjectEditor.setHideProperty(getClass(), "mainSwarmTopologyRange", mainSwarmTopology == PSOTopology.multiSwarm); // "Multi-Swarm" has no topologyRange // population size is set via setMainSwarmSize GenericObjectEditor.setHideProperty(getClass(), "population", true); // setGOEShowProperties(getClass()); } public ANPSO(ANPSO o) { super(o); this.inactiveSubSwarms = (Vector) o.inactiveSubSwarms.clone(); this.s = new int[mainSwarmSize][mainSwarmSize]; for (int i = 0; i < s.length; ++i) { System.arraycopy(o.s[i], 0, s[i], 0, s[i].length); } this.nicheGraph = (NicheGraph) nicheGraph.clone(); this.minimalR = o.minimalR; this.minNeighborCntNicheGraph = o.minNeighborCntNicheGraph; this.maxNeighborCntNicheGraph = o.maxNeighborCntNicheGraph; this.neighborCntNicheGraphForEdge = o.neighborCntNicheGraphForEdge; } @Override public Object clone() { return new ANPSO(this); } /** * ******************************************************************************************************************* * inits */ @Override public void initialize() { // MOE: wird vor Optimierung / n�chstem multirun 1x aufgerufen super.initialize(); initMainSwarm(); initSTo(0); initNicheGraph(); inactiveSubSwarms = new Vector<>(); // dont want to use subswarms from old optimization run (especially not in multiruns)... } /** * resets all entries of the s matrix that correspond to any * particle in the given subswarm * * @param subswarm */ private void resetSMatrixEntriesFor(ParticleSubSwarmOptimization subswarm) { Population pop = subswarm.getPopulation(); for (int i = 0; i < pop.size(); ++i) { //Integer index = pop.getEAIndividual(i).getIndividualIndex();(Integer)pop.getEAIndividual(i).getData("particleIndex"); resetSMatrixForIndex(pop.getEAIndividual(i).getIndividualIndex(), 0); } } /** * sets the given row and column to the given value * (i.e. all entries corresponding to a specific particle) * * @param index * @param val */ private void resetSMatrixForIndex(int index, int val) { for (int i = 0; i < s.length; ++i) { for (int j = 0; j < s[i].length; ++j) { if (i == index || j == index) { s[i][j] = val; } } } } /** * sets every entry of the s matrix to the given value * * @param val */ private void initSTo(int val) { for (int i = 0; i < s.length; ++i) { for (int j = 0; j < s[i].length; ++j) { s[i][j] = val; } } } /** * this inits the "niche graph". * Every particle is represented as a vertex in the "niche graph". */ private void initNicheGraph() { nicheGraph = new NicheGraph(); Population activePop = getActivePopulation(); for (int i = 0; i < activePop.size(); ++i) { //Integer index = activePop.getEAIndividual(i).getParticleIndex();//(Integer)activePop.getEAIndividual(i).getData("particleIndex"); String vertex = "" + activePop.getEAIndividual(i).getIndividualIndex(); nicheGraph.addVertex(vertex); } } /********************************************************************************************************************** * ANPSO core // /** // * @param pop // * @param normalized use a normalized metric to compute distances? // * @return ave distance to neighbor in the given population // */ // public double getAveDistToClosestNeighbor(Population pop, boolean normalized){ // PhenotypeMetric metric = new PhenotypeMetric(); //// ArrayList distances = new ArrayList(pop.size()); // double sum = 0; // double d=0; // for (int i = 0; i < pop.size(); ++i){ // AbstractEAIndividual neighbor, indy = pop.getEAIndividual(i); // int neighborIndex = pop.getNeighborIndex(indy); // if (neighborIndex >= 0) neighbor = pop.getEAIndividual(neighborIndex); // else return -1; // if (normalized){ // d = metric.distance(indy, neighbor); // } else { // d = PhenotypeMetric.euclidianDistance(AbstractEAIndividual.getDoublePosition(indy), // AbstractEAIndividual.getDoublePosition(neighbor)); // } //// distances.add(d); // sum += d; // } // double avg = sum/(double)pop.size(); //// if (normalized && (pop.getGeneration()==1)) { //// double var = 0; //// for (int i=0; i maxNeighborCntNicheGraph) { s[i][j] = maxNeighborCntNicheGraph; } // if i and j had been close to each other for at least two generations // they are connected by an edge if (s[i][j] >= neighborCntNicheGraphForEdge) { String pi = "" + i; String pj = "" + j; nicheGraph.addEdge(pi, pj); } } else { // decrement entry that counts the number of generations // i and j have been close to each other --s[i][j]; if (s[i][j] < minNeighborCntNicheGraph) { s[i][j] = minNeighborCntNicheGraph; } } } } } /** * The returned array may contain null entries (for indies scheduled for reinitialization). * * @return an array of references sorted according to the particle indices * (i.e. returnedArray[i] = individual with individualIndex i) */ protected AbstractEAIndividual[] sortActivePopByParticleIndex() { Population pop = getActivePopulation(); AbstractEAIndividual[] sorted; if (pop.size() < mainSwarmSize) { int reinitSize = 0; if (indicesToReinit != null) { for (int i = 0; i < indicesToReinit.size(); i++) { reinitSize += indicesToReinit.get(i).length; } } if (pop.size() + reinitSize == mainSwarmSize) { // good case, extend pop size; null entries are to be tolerated. sorted = new AbstractEAIndividual[pop.size() + reinitSize]; } else { throw new RuntimeException("Error, invalid size of active population (ANPSO.sortActivePopByParticleIndex()"); } } else { sorted = new AbstractEAIndividual[pop.size()]; } for (int i = 0; i < pop.size(); ++i) { AbstractEAIndividual indy = pop.getEAIndividual(i); if (sorted[indy.getIndividualIndex()] != null) { System.err.println("error in sortByParticleIndex!"); } if (sorted[indy.getIndividualIndex()] != null) { throw new RuntimeException("Error, inconsistency in ANPSO! (index wrong)"); } sorted[indy.getIndividualIndex()] = indy; } return sorted; } /** * uses the sets of particles as different subswarms and removes the particles from the mainswarm * * @param setOfSubswarms */ public void useAsSubSwarms(Vector setOfSubswarms) { Vector newSubSwarms = new Vector<>(); for (int i = 0; i < setOfSubswarms.size(); ++i) { Population pop = setOfSubswarms.get(i); ParticleSubSwarmOptimization subswarm = getNewSubSwarmOptimizer(); subswarm.getPopulation().clear(); subswarm.getPopulation().addAll(pop); subswarm.populationSizeHasChanged(); newSubSwarms.add(subswarm); getMainSwarm().removeSubPopulation(pop, true); // the new subswarm can also come from an earlier subswarm getMainSwarm().populationSizeHasChanged(); } if (isVerbose()) { System.out.println(); for (int i = 0; i < newSubSwarms.size(); i++) { System.out.println("Swarm " + i + " (" + newSubSwarms.get(i).getPopulation().size() + "), best " + newSubSwarms.get(i).getBestIndividual()); } } // add the function calls from the subswarms of the last iteration to the mainswarm before forgetting them // the function calls from the inactivated subswarms are transfered to the mainswarm as well // -> do not count them in getPopulation a second time int calls = 0; for (int i = 0; i < getSubSwarms().size(); ++i) { ParticleSubSwarmOptimization subswarm = getSubSwarms().get(i); calls += subswarm.getPopulation().getFunctionCalls(); } getMainSwarm().getPopulation().incrFunctionCallsBy(calls); this.setSubSwarms(newSubSwarms); } /** * uses the population as the mainswarm * * @param pop */ public void useAsMainSwarm(Population pop) { int generations = getMainSwarm().getPopulation().getGeneration(); int calls = getMainSwarm().getPopulation().getFunctionCalls(); getMainSwarm().setPopulation(pop); getMainSwarm().populationSizeHasChanged(); getMainSwarm().getPopulation().setGeneration(generations); getMainSwarm().getPopulation().setFunctionCalls(calls); } /** * creates subswarms from all particles that correspond to connected vertices in the niche graph. * Particles corresponding to unconnected vertices belong to the mainswarm. */ public void createSubswarmsFromNicheGraph() { // get all sets of vertices that are connected in the niche graph... //(subSwarms = new Vector(); // too early, particles would be lost... List> connectedComps = nicheGraph.getConnectedComponents(); Population tmpPop = new Population(), newMainPop = new Population(); Vector setOfSubswarms = new Vector<>(); boolean reinitSuperfl = true; for (Set connSet : connectedComps) { if (connSet.size() > 1) {// create niche Population pop = new Population(connSet.size()); for (String indexStr : connSet) { Integer index = Integer.valueOf(indexStr); AbstractEAIndividual indy = getIndyByParticleIndex(index); // may be taken from a main swarm or current subwarm if (indy == null) { System.err.println("createNichesFromNicheGraph problem -> getIndyByParticleIndex returned null"); } pop.add(indy); } if (maxInitialSubSwarmSize > 0 && (pop.size() > maxInitialSubSwarmSize)) { tmpPop = pop.getWorstNIndividuals(pop.size() - maxInitialSubSwarmSize, -1); tmpPop.synchSize(); pop.removeMembers(tmpPop, true); if (reinitSuperfl) { for (int i = 0; i < tmpPop.size(); i++) { AbstractEAIndividual indy = tmpPop.getEAIndividual(i); indy.initialize(optimizationProblem); indy.resetFitness(Double.MAX_VALUE); // TODO this is not so nice... they should be collected in a reinit-list and inserted at the beginning of the next optimize step ParticleSwarmOptimization.initIndividualDefaults(indy, 0.2); ParticleSwarmOptimization.initIndividualMemory(indy); ParticleSubSwarmOptimization.initSubSwarmDefaultsOf(indy); } } newMainPop.addPopulation(tmpPop); pop.synchSize(); } setOfSubswarms.add(pop); } else { // move particles corresponding to unconnected vertices to the mainswarm Iterator it = connSet.iterator(); Integer index = Integer.valueOf(it.next()); AbstractEAIndividual indy = getIndyByParticleIndex(index); newMainPop.add(indy); } } newMainPop.synchSize(); for (Population setOfSubswarm : setOfSubswarms) { setOfSubswarm.synchSize(); } useAsSubSwarms(setOfSubswarms); useAsMainSwarm(newMainPop); } /** */ @Override public void optimize() { // main swarm: if (getMainSwarm().getPopulation().size() == 0) {// || mainSwarm.getPopulation().size() == 1){ if (isVerbose()) { System.out.print("MainSwarm size is 0\n"); } // increment the generationcount for the Terminator: // 1 Generation equals one optimize call including the optimization of the // (possibly empty) mainSwarm and all subSwarms getMainSwarm().getPopulation().incrGeneration(); } else { getMainSwarm().optimize(); } maybeReinitIndies(); // sub swarms: for (int i = 0; i < getSubSwarms().size(); ++i) { ParticleSubSwarmOptimization subswarm = getSubSwarms().get(i); if (subswarm.isActive()) { subswarm.optimize(); } } // deactivation: deactivateSubSwarmsIfPossible(); if (isVerbose()) { System.out.print("active swarms: " + countActiveSubswarms() + " of " + getSubSwarms().size()); } // build the s matrix and the niche graph // these data structures represent particles that have been close to each other // for at least two consecutive generations updateSMatrixAndNicheGraph(); // create subswarms from the particles corresponding to connected vertices in the niche graph createSubswarmsFromNicheGraph(); // one might create additional subswarms from the main swarm // using the standard strategie from the NichePSO // createSubswarmIfPossible(); // adapt the species radius of the SPSO using similar population statistics as for the radius parameter r if ((mainSwarm.getTopology() == PSOTopology.multiSwarm) && (mainSwarm.getMaxSubSwarmSize() > 1)) { //Multi-Swarm double aveDistToNeighInMain = getMainSwarm().getPopulation().getAvgDistToClosestNeighbor(true, false)[0]; getMainSwarm().setSubSwarmRadius(aveDistToNeighInMain); } if (isVerbose()) { System.out.println(); } firePropertyChangedEvent("NextGenerationPerformed"); // calls Listener that sth changed... /** plotting **********************************************************************************/ if (isPlot()) { doPlot(); } // reset flags etc for: // deactivation deactivationOccured = false; deactivatedSwarm = new Vector<>(); // merging mergingOccurd = false; borg = new Vector<>(); others = new Vector<>(); borgbest = new Vector<>(); othersbest = new Vector<>(); // absorbtion absorbtionOccurd = false; indytoabsorb = new Vector<>(); // subswarmcreation creationOccurd = false; indyconverged = new Vector<>(); convergedneighbor = new Vector<>(); //clearing - deprecated //reinitoccurd = false; } /** * ******************************************************************************************************************* * Deactivation */ @Override protected void deactivationEventFor(ParticleSubSwarmOptimization subswarm) { super.deactivationEventFor(subswarm); resetSMatrixEntriesFor(subswarm); inactiveSubSwarms.add(subswarm); // ANPSO will later remove the inactive subswarm from the standard set of subswarms... } /********************************************************************************************************************** * setter, getter */ /** * @param size * sets the !initial! size of the mainswarm population * use this instead of getPopulation.setPopulationSize() */ @Override public void setMainSwarmSize(int size) { // set member this.mainSwarmSize = size; // pass on to the mainswarm optimizer getMainSwarm().getPopulation().setTargetSize(size); // update s s = new int[size][size]; initSTo(0); initNicheGraph(); } /** * @param includeInactive * @return a population with clones from all subswarms */ public Population getSubswarmMetapop(boolean includeInactive) { // construct a metapop with clones from all subswarms Population metapop = new Population(); for (int i = 0; i < getSubSwarms().size(); ++i) { ParticleSubSwarmOptimization currentsubswarm = getSubSwarms().get(i); if (includeInactive || currentsubswarm.isActive()) { Population currentsubswarmpop = (Population) currentsubswarm.getPopulation().clone(); metapop.addPopulation(currentsubswarmpop); } } return metapop; } /** * @return a population consisting of copies from the mainswarm and all subswarms. * returns a population consisting of copies from the mainswarm and all subswarms * (active and inactive, so the size of this Population is not necessarily constant). * Especially important for the call back regarding the output file... * Beware: getPopulation().getPopulationSize() returns the !initial! size of the main swarm, * the actual size of the complete population is accessed via getPopulation().size() */ @Override public Population getPopulation() { // construct a metapop with clones from the mainswarm and all subswarms Population metapop = (Population) getMainSwarm().getPopulation().clone(); Population currentsubswarm = new Population(); for (int i = 0; i < getSubSwarms().size(); ++i) { currentsubswarm = (Population) getSubSwarms().get(i).getPopulation().clone(); metapop.addPopulation(currentsubswarm); } for (ParticleSubSwarmOptimization inactiveSubSwarm : inactiveSubSwarms) { // in the case of ANPSO currentsubswarm = (Population) inactiveSubSwarm.getPopulation().clone(); metapop.addPopulation(currentsubswarm); } // set correct number of generations metapop.setGeneration(getMainSwarm().getPopulation().getGeneration()); // set correct number of function calls int calls = getMainSwarm().getPopulation().getFunctionCalls(); for (int i = 0; i < getSubSwarms().size(); ++i) { ParticleSubSwarmOptimization subswarm = getSubSwarms().get(i); calls += subswarm.getPopulation().getFunctionCalls(); } // calls from inactivated subswarms were transfered to the mainswarm, see useAsSubSwarms method metapop.setFunctionCalls(calls); return metapop; } /** * @return array with copies of the gbest individuals * returns the cloned global best individuals (ie best of all time) from every subswarm */ public Population getSubswarmRepresentatives() { //boolean includeMainSwarm = false; int mainSize = 0; //if (includeMainSwarm) mainSize = getMainSwarm().getPopulation().size(); Population elitePop = new Population(getSubSwarms().size() + inactiveSubSwarms.size() + mainSize); for (int i = 0; i < getSubSwarms().size(); ++i) { AbstractEAIndividual bestSS = getSubSwarms().get(i).getBestIndividual(); elitePop.addIndividual((AbstractEAIndividual) getSubSwarms().get(i).bestIndividual.clone()); } for (ParticleSubSwarmOptimization inactiveSubSwarm : inactiveSubSwarms) { elitePop.addIndividual((AbstractEAIndividual) inactiveSubSwarm.bestIndividual.clone()); } return elitePop; } /** * @return descriptive string of the elite * returns a string that lists the global best individuals (ie best of all time) from every subswarm */ public String getSubswarmRepresentativesAsString() { String result = "\nSubswarmRepresentatives: \n"; Population elite = getSubswarmRepresentatives(); for (int i = 0; i < getSubSwarms().size() + inactiveSubSwarms.size(); ++i) { result += elite.getEAIndividual(i).getStringRepresentation() + "\n"; } return result; } /** */ @Override protected void plotSubSwarms() { if (this.optimizationProblem instanceof Interface2DBorderProblem) { //DPointSet popRep = new DPointSet(); InterfaceDataTypeDouble tmpIndy1; //cleanPlotSubSwarms(); // for all inactive SubSwarms from ANPSO... for (int i = 0; i < this.inactiveSubSwarms.size(); i++) { ParticleSubSwarmOptimization currentsubswarm = this.inactiveSubSwarms.get(i); InterfaceDataTypeDouble best = (InterfaceDataTypeDouble) currentsubswarm.bestIndividual; plotCircleForIndy((AbstractEAIndividual) best, "[I]"); } // for all SubSwarms... for (int i = 0; i < this.getSubSwarms().size(); i++) { ParticleSubSwarmOptimization currentsubswarm = this.getSubSwarms().get(i); Population currentsubswarmpop = currentsubswarm.getPopulation(); //InterfaceDataTypeDouble best = (InterfaceDataTypeDouble)currentsubswarmpop.getBestIndividual(); InterfaceDataTypeDouble best = (InterfaceDataTypeDouble) currentsubswarm.bestIndividual; DPointSet popRep = new DPointSet(); //...draw SubSwarm as points for (int j = 0; j < currentsubswarmpop.size(); j++) { popRep.setConnected(false); tmpIndy1 = (InterfaceDataTypeDouble) currentsubswarmpop.get(j); popRep.addDPoint(new DPoint(tmpIndy1.getDoubleData()[0], tmpIndy1.getDoubleData()[1])); } this.topoPlot.getFunctionArea().addDElement(popRep); // time consuming //...draw circle for best if (!currentsubswarm.isActive()) { plotCircleForIndy((AbstractEAIndividual) best, "[I]"); } else { if (getSubswarmOptimizerTemplate().isGcpso()) { String rhoAsString = String.format("%6.3f", currentsubswarm.getRho()); } } //...draw SubSwarm as connected lines to best popRep = new DPointSet(); for (int j = 0; j < currentsubswarmpop.size(); j++) { //popRep.setConnected(false); tmpIndy1 = (InterfaceDataTypeDouble) currentsubswarmpop.get(j); //popRep.addDPoint(new DPoint(tmpIndy1.getDoubleData()[0], tmpIndy1.getDoubleData()[1])); popRep.setConnected(true); popRep.addDPoint(new DPoint(tmpIndy1.getDoubleData()[0], tmpIndy1.getDoubleData()[1])); popRep.addDPoint(new DPoint(best.getDoubleData()[0], best.getDoubleData()[1])); } this.topoPlot.getFunctionArea().addDElement(popRep); // time consuming } } // endif } /** * @param index * @return inactive particles with given index * (may return more than one particle for a given index because indizes are reused during deactivation * and the reinitialized particle may be deactivated again...) */ public Vector getInactiveIndiesByParticleIndex(Integer index) { Vector indies = null; AbstractEAIndividual indy = null; for (int i = 0; i < inactiveSubSwarms.size(); ++i) { Population pop = inactiveSubSwarms.get(i).getPopulation(); indy = getIndyByParticleIndexAndPopulation(pop, index); // fix if needed: only returns the first occurence... if (indy != null) { indies.add(indy); } } return indies; } /** * @return The name of the algorithm * This method will return a naming String */ @Override public String getName() { return "ANPSO-" + getMainSwarmSize(); } public void SetMinimalR(double minimalR) { this.minimalR = minimalR; } public int getMaxInitialSubSwarmSize() { return maxInitialSubSwarmSize; } public String maxInitialSubSwarmSizeTipText() { return "The maximum size of sub swarms at creation time."; } public void setMaxInitialSubSwarmSize(int maxSubSwarmSize) { this.maxInitialSubSwarmSize = maxSubSwarmSize; } public String mainSwarmTopologyTipText() { return "sets the topology type used to train the main swarm"; } public String mainSwarmTopologyRangeTipText() { return "sets the range of the neighborhood topology for the main swarm"; } public static OptimizationParameters aNichePSO(AbstractOptimizationProblem problem, long randSeed, InterfaceTerminator term) { ANPSO anpso = new ANPSO(); anpso.setMainSwarmSize(75); return OptimizerFactory.makeParams(anpso, 75, problem, randSeed, term); } /** * Creates a standard ANPSO variant with default constricted PSO parameters and a grid topology. * * @param problem * @param randSeed * @param evalCnt * @return */ public static OptimizationParameters stdANPSO(AbstractOptimizationProblem problem, long randSeed, int evalCnt) { ANPSO anpso = new ANPSO(); NichePSO.stdNPSO(anpso, problem, randSeed, evalCnt); anpso.getMainSwarm().setPhi1(2.05); anpso.getMainSwarm().setPhi2(2.05); anpso.getMainSwarm().setInertnessOrChi(0.7298437881283576); anpso.getMainSwarm().setAlgoType(ParticleSwarmOptimization.PSOType.Constriction); anpso.setMainSwarmAlgoType(ParticleSwarmOptimization.PSOType.Constriction); // constriction anpso.setMaxInitialSubSwarmSize(0); // deactivate early reinits anpso.setMainSwarmTopology(PSOTopology.grid); anpso.setMainSwarmTopologyRange(1); anpso.setDeactivationStrategy(new StandardDeactivationStrategy(0.000001, 8)); // es gibt kein species size limit wie im orig-paper, aber sie berichten dort, dass sie für // höhere dimensionsn (3,4), eh keines benutzen. return OptimizerFactory.makeParams(anpso, anpso.getMainSwarmSize(), problem, randSeed, new EvaluationTerminator(evalCnt)); } public static OptimizationParameters starANPSO(AbstractOptimizationProblem problem, long randSeed, int evalCnt) { ANPSO anpso = new ANPSO(); NichePSO.starNPSO(anpso, problem, randSeed, evalCnt); anpso.getMainSwarm().setParameterControl(new ParamAdaption[]{new LinearParamAdaption("inertnessOrChi", 0.7, 0.2)}); // anpso.setMainSwarmInertness(new LinearParameterAging(0.7, 0.2, evalCnt/anpso.getMainSwarmSize())); anpso.getMainSwarm().setAlgoType(ParticleSwarmOptimization.PSOType.Inertness); anpso.setMainSwarmAlgoType(ParticleSwarmOptimization.PSOType.Inertness); // inertness anpso.getMainSwarm().setPhi1(1.2); anpso.getMainSwarm().setPhi2(0.6); // ANPSO uses communication in the main swarm //Possible topologies are: "Linear", "Grid", "Star", "Multi-Swarm", "Tree", "HPSO", "Random" in that order starting by 0. anpso.setMainSwarmTopologyTag(3); //"Multi-Swarm" favors the formation of groups in the main swarm anpso.setMainSwarmTopologyRange(2); // range for topologies like random, grid etc. (does not affect "Multi-Swarm") anpso.setMaxInitialSubSwarmSize(0); // deactivate early reinits // es gibt kein species size limit wie im orig-paper, aber sie berichten dort, dass sie für // höhere dimensionsn (3,4), eh keines benutzen. return OptimizerFactory.makeParams(anpso, anpso.getMainSwarmSize(), problem, randSeed, new EvaluationTerminator(evalCnt)); } public static OptimizationParameters gmakANPSO(AbstractOptimizationProblem problem, long randSeed, int evalCnt) { ANPSO anpso = new ANPSO(); NichePSO.starNPSO(anpso, problem, randSeed, evalCnt); anpso.getMainSwarm().setParameterControl(new ParamAdaption[]{new LinearParamAdaption("inertnessOrChi", 0.7, 0.2)}); anpso.getMainSwarm().setAlgoType(ParticleSwarmOptimization.PSOType.Inertness); anpso.setMainSwarmAlgoType(ParticleSwarmOptimization.PSOType.Inertness); anpso.getMainSwarm().setPhi1(1.2); anpso.getMainSwarm().setPhi2(1.2); // ANPSO uses communication in the main swarm //Possible topologies are: "Linear", "Grid", "Star", "Multi-Swarm", "Tree", "HPSO", "Random" in that order starting by 0. anpso.setMainSwarmTopologyTag(3); //"Multi-Swarm" favors the formation of groups in the main swarm anpso.setMainSwarmTopologyRange(4); // range for topologies like random, grid etc. (does not affect "Multi-Swarm") // es gibt kein species size limit wie im orig-paper, aber sie berichten dort, dass sie für // höhere dimensionsn (3,4), eh keines benutzen. anpso.getSubswarmOptimizerTemplate().setRho(1); anpso.getSubswarmOptimizerTemplate().SetRhoIncreaseFactor(2); anpso.getSubswarmOptimizerTemplate().SetRhoDecreaseFactor(0.5); return OptimizerFactory.makeParams(anpso, anpso.getMainSwarmSize(), problem, randSeed, new EvaluationTerminator(evalCnt)); } /** * Create a grid-star-ANPSO with range 2. * * @param problem * @param randSeed * @param evalCnt * @return */ public static OptimizationParameters sgANPSO(AbstractOptimizationProblem problem, long randSeed, int evalCnt) { return starTopoANPSO(problem, randSeed, evalCnt, 1, 2); } /** * Create a starANPSO with a given main swarm topology. * * @param problem * @param randSeed * @param evalCnt * @param topology * @param topologyRange * @return */ public static OptimizationParameters starTopoANPSO(AbstractOptimizationProblem problem, long randSeed, int evalCnt, int topology, int topologyRange) { OptimizationParameters params = starANPSO(problem, randSeed, evalCnt); ((ANPSO) params.getOptimizer()).setMainSwarmTopologyTag(topology); ((ANPSO) params.getOptimizer()).setMainSwarmTopologyRange(topologyRange); ((ANPSO) params.getOptimizer()).getMainSwarm().setInertnessOrChi(0.73); return params; } @Override public String[] getAdditionalDataHeader() { return ToolBox.appendArrays(super.getAdditionalDataHeader(), new String[]{"mainSwarmBestFit", "swarmRad"}); } @Override public Object[] getAdditionalDataValue(PopulationInterface pop) { return ToolBox.appendArrays(super.getAdditionalDataValue(pop), new Object[]{getMainSwarm().getPopulation().getBestFitness()[0], updateRadius}); } @Override public String[] getAdditionalDataInfo() { return ToolBox.appendArrays(super.getAdditionalDataInfo(), new String[]{"The best fitness within the main swarm", "The current value of the adapted swarm radius"}); } @Override public Population getSubswarmRepresentatives(boolean onlyInactive) { Population representatives = super.getSubswarmRepresentatives(onlyInactive); // this vector does not yet contain the archived solutions for (int i = 0; i < inactiveSubSwarms.size(); i++) { representatives.add(inactiveSubSwarms.get(i).getBestIndividual()); } representatives.synchSize(); return representatives; } /** * Return the median correlation of the best individuals of the given set of swarms. */ private double getMedCorrelation( Vector swarms) { Population pop = new Population(swarms.size()); for (int i = 0; i < swarms.size(); i++) { if (swarms.get(i) != null) { pop.addIndividual(swarms.get(i).getBestIndividual()); } } return pop.getCorrelations()[3]; } /** * Return the mean distance of the best individuals of the given set of swarms. * * @param swarms * @return */ private double getMeanDist( Vector swarms) { Population pop = new Population(swarms.size()); for (int i = 0; i < swarms.size(); i++) { if (swarms.get(i) != null) { pop.addIndividual(swarms.get(i).getBestIndividual()); } } return pop.getPopulationMeasures()[0]; } @Override protected int getNumArchived() { return (inactiveSubSwarms.size()); } }