Adding NichePSO and ANPSO from the MModal branch (adaptation of M.Aschoffs implementations)

This commit is contained in:
Marcel Kronfeld 2011-05-03 13:47:07 +00:00
parent 15cd21b8f1
commit d557e86cd0
22 changed files with 5641 additions and 0 deletions

View File

@ -0,0 +1,42 @@
package eva2.server.go.operators.nichepso.absorption;
import eva2.server.go.individuals.AbstractEAIndividual;
import eva2.server.go.strategies.ParticleSubSwarmOptimization;
/**
* Particles are absorbed into a subswarm if they move into an area covered by that subswarm.
* To prevent the destabilisation of a subswarm only particles are absorbed which do not know
* a position that is better than the best position known by the subswarm.
*/
public class ConsiderPBestAbsorptionStrategy extends StandardAbsorptionStrategy{
/** @tested
* true if
* the subswarm is active and
* the particle lies in the radius of the subswarm and
* the particles pbest is not better than the subswarms gbest (this would "pull the subswarm away")
* (non-Javadoc) @see javaeva.server.oa.go.Operators.NichePSO.StandardAbsorptionStrategy#shouldAbsorbParticleIntoSubswarm(javaeva.server.oa.go.EAIndividuals.AbstractEAIndividual, javaeva.server.oa.go.Strategies.ParticleSubSwarmOptimization)
*/
public boolean shouldAbsorbParticleIntoSubswarm(AbstractEAIndividual indy, ParticleSubSwarmOptimization subswarm, ParticleSubSwarmOptimization mainswarm) {
if (!super.shouldAbsorbParticleIntoSubswarm(indy, subswarm, mainswarm)){
return false;
}
if (absorbtionConstraintViolation(indy, subswarm)){
return false;
}
return true;
}
/** @tested
* @param indy
* @param subswarm
* @return
*/
private boolean absorbtionConstraintViolation(AbstractEAIndividual indy, ParticleSubSwarmOptimization subswarm) {
AbstractEAIndividual indysPBest = (AbstractEAIndividual)indy.getData("PersonalBestKey");
AbstractEAIndividual subswarmsGBest = subswarm.getGBestIndividual();
if (indysPBest.isDominating(subswarmsGBest)) return true;
return false;
}
}

View File

@ -0,0 +1,77 @@
package eva2.server.go.operators.nichepso.absorption;
import eva2.server.go.individuals.AbstractEAIndividual;
import eva2.server.go.strategies.ParticleSubSwarmOptimization;
/**
* A threshold epsilon is proposed in [1] in order to prevent premature absorptions
* of particles into subswarms which cover large parts of the search space.
* A particle is absorbed into a subswarm if it lies within the radius of that subswarm
* and the diversity of this subswarm is below the given threshold epsilon.
* The diversity of a subswarm is defined as the average euclidean distance between
* the particles of that subswarm and the global best position of that subswarm.
* In [1], a threshold value of epsilon = 0.1 produced good results.
* [1] A.P. Engelbrecht and L.N.H. van Loggerenberg.
* Enhancing the nichepso.
* In IEEE Congress on Evolutionary Computation,
* 2007.
*/
public class EuclideanDiversityAbsorptionStrategy extends StandardAbsorptionStrategy{
private double epsilon = 0.1; // 0.1 used in "Enhancing the NichePSO" by Engelbrecht et al.
/**********************************************************************************************************************
* ctors
*/
public EuclideanDiversityAbsorptionStrategy() {
}
public EuclideanDiversityAbsorptionStrategy(EuclideanDiversityAbsorptionStrategy other){
this.epsilon = other.epsilon;
}
public EuclideanDiversityAbsorptionStrategy(double eps) {
epsilon = eps;
}
/**********************************************************************************************************************
* shouldAbsorbParticleIntoSubswarm
*/
/** @tested
* true if
* the subswarm is active and
* the particle lies in the radius of the subswarm and
* the diversity (mean distance from the gbest) of the subswarm < epsilon
* (non-Javadoc) @see javaeva.server.oa.go.Operators.NichePSO.StandardAbsorptionStrategy#shouldAbsorbParticleIntoSubswarm(javaeva.server.oa.go.EAIndividuals.AbstractEAIndividual, javaeva.server.oa.go.Strategies.ParticleSubSwarmOptimization)
*/
public boolean shouldAbsorbParticleIntoSubswarm(AbstractEAIndividual indy, ParticleSubSwarmOptimization subswarm, ParticleSubSwarmOptimization mainswarm) {
if (!super.shouldAbsorbParticleIntoSubswarm(indy, subswarm, mainswarm)){
return false; //
}
if (!diversityIsBelowThreshold(subswarm)){
return false;
}
return true;
}
private boolean diversityIsBelowThreshold(ParticleSubSwarmOptimization subswarm) {
double meanDistanceFromGBestPos = subswarm.getEuclideanDiversity();
if (meanDistanceFromGBestPos < getEpsilon()){
return true;
} else return false;
}
/**********************************************************************************************************************
* setter, getter
*/
public void setEpsilon(double epsilon) {
this.epsilon = epsilon;
}
public double getEpsilon() {
return epsilon;
}
public String epsilonTipText(){
return "threshold for the diversity of the subswarm that confines the absorption of main swarm particles";
}
}

View File

@ -0,0 +1,36 @@
package eva2.server.go.operators.nichepso.absorption;
import eva2.server.go.individuals.AbstractEAIndividual;
import eva2.server.go.strategies.ParticleSubSwarmOptimization;
/**
* interface for the absorption strategies used in NichePSO
*/
public interface InterfaceAbsorptionStrategy {
/** @tested
* decides whether indy should be absorbed into the subswarm according to the absorption strategie
* @param indy
* @param subswarm the swarm indy will be absorbed from
* @param mainswarm the swarm indy currently belongs to
* (population statistics from that swarm may be used to decide whether indy should be absorbed)
* @return
*/
public abstract boolean shouldAbsorbParticleIntoSubswarm(
AbstractEAIndividual indy,
ParticleSubSwarmOptimization subswarm,
ParticleSubSwarmOptimization mainswarm);
/** @tested
* absorbs indy according to the absorbtion strategy
* @param indy
* @param subswarm the swarm indy will be absorbed from
* @param mainswarm the swarm indy currently belongs to
*/
public abstract void absorbParticle(
AbstractEAIndividual indy,
ParticleSubSwarmOptimization subswarm,
ParticleSubSwarmOptimization mainswarm);
public abstract Object clone();
}

View File

@ -0,0 +1,78 @@
package eva2.server.go.operators.nichepso.absorption;
import eva2.server.go.individuals.AbstractEAIndividual;
import eva2.server.go.strategies.ParticleSubSwarmOptimization;
/**
* Particles are absorbed into a subswarm when they move into an area
* within the radius of that subswarm.
* This strategy is proposed in
* R. Brits, A. P. Engelbrecht and B. Bergh.
* A Niching Particle Swarm Optimizer
* In Proceedings of the 4th Asia-Pacific Conference on Simulated Evolution and Learning (SEAL'02),
* 2002, 2, 692-696
*/
public class StandardAbsorptionStrategy implements InterfaceAbsorptionStrategy, java.io.Serializable {
/**********************************************************************************************************************
* ctors, init, clone
*/
public Object clone(){
return (Object) new StandardAbsorptionStrategy();
}
public String globalInfo(){
return "Strategy to absorb main swarm particles into a subswarm";
}
/**********************************************************************************************************************
* shouldAbsorbParticleIntoSubswarm
*/
/** @tested
* true if
* the subswarm is active and
* the particle lies in the radius of the subswarm
* (non-Javadoc) @see javaeva.server.oa.go.Operators.NichePSO.InterfaceAbsorptionStrategy#shouldAbsorbParticleIntoSubswarm(javaeva.server.oa.go.EAIndividuals.AbstractEAIndividual, javaeva.server.oa.go.Strategies.ParticleSubSwarmOptimization)
*/
public boolean shouldAbsorbParticleIntoSubswarm(AbstractEAIndividual indy, ParticleSubSwarmOptimization subswarm, ParticleSubSwarmOptimization mainswarm) {
if (!subswarm.isActive()){
return false; // no interaction between active mainswarmparticle and inactive subswarm
}
if (!particleLiesInSubswarmRadius(indy, subswarm)) {
return false;
}
return true;
}
private boolean particleLiesInSubswarmRadius(AbstractEAIndividual indy, ParticleSubSwarmOptimization subswarm) {
double R = subswarm.getBoundSwarmRadius(); // uses euclidean distance
AbstractEAIndividual gbest = subswarm.getGBestIndividual();
double dist = subswarm.distance(indy,gbest); // euclidean distance
if (dist <= R){
return true;
}else return false;
}
/**********************************************************************************************************************
* absorbParticle
*/
/** @tested junit
* adds indy to an active subswarm, then removes indy from the mainswarm.
* (non-Javadoc) @see javaeva.server.oa.go.Operators.NichePSO.InterfaceAbsorptionStrategy#absorbParticle(javaeva.server.oa.go.EAIndividuals.AbstractEAIndividual, javaeva.server.oa.go.Strategies.ParticleSubSwarmOptimization, javaeva.server.oa.go.Strategies.ParticleSubSwarmOptimization)
*/
public void absorbParticle(AbstractEAIndividual indy, ParticleSubSwarmOptimization subswarm, ParticleSubSwarmOptimization mainswarm) {
if (!subswarm.isActive()){
System.out.println("absorbParticle: trying to absorb a particle into an inactive subswarm.");
return;
}
subswarm.add(indy);
subswarm.populationSizeHasChanged();
mainswarm.removeSubIndividual(indy);
mainswarm.populationSizeHasChanged();
}
}

View File

@ -0,0 +1,25 @@
package eva2.server.go.operators.nichepso.deactivation;
import eva2.server.go.strategies.ParticleSubSwarmOptimization;
/**
* dummy strategy does not deactivate anything
*
*/
public class DummyDeactivationStrategy implements InterfaceDeactivationStrategy, java.io.Serializable {
public Object clone(){
return (Object) new DummyDeactivationStrategy();
}
public int[] deactivateSubswarm(ParticleSubSwarmOptimization subswarm,
ParticleSubSwarmOptimization mainswarm) {
return null;
}
public boolean shouldDeactivateSubswarm(
ParticleSubSwarmOptimization subswarm) {
return false;
}
}

View File

@ -0,0 +1,155 @@
package eva2.server.go.operators.nichepso.deactivation;
import java.util.List;
import java.util.Vector;
import eva2.server.go.InterfaceTerminator;
import eva2.server.go.individuals.AbstractEAIndividual;
import eva2.server.go.operators.terminators.HistoryConvergenceTerminator;
import eva2.server.go.populations.Population;
import eva2.server.go.strategies.NichePSO;
import eva2.server.go.strategies.ParticleSubSwarmOptimization;
import eva2.tools.EVAERROR;
/**
* A subswarm is deactivated if all its particles are converged.
* A particle is considered converged if the standard deviation of its fitness values
* over the last 3 iterations is less or equal a given threshold epsilon
* Experiments showed good results using epsilon = 0.0001.
*
*/
public class ImprovementDeactivationStrategy implements InterfaceDeactivationStrategy, java.io.Serializable {
private double epsilon = 0.0001;
private int haltingWindow = 15;
/**********************************************************************************************************************
* ctors
*/
public ImprovementDeactivationStrategy(){
}
public ImprovementDeactivationStrategy(double thresh, int hwLen) {
epsilon=thresh;
haltingWindow=hwLen;
}
public ImprovementDeactivationStrategy(ImprovementDeactivationStrategy other){
this.epsilon = other.epsilon;
this.haltingWindow=other.haltingWindow;
}
public ImprovementDeactivationStrategy(double eps) {
this.epsilon = eps;
}
public Object clone(){
return (Object) new ImprovementDeactivationStrategy(this);
}
public String globalInfo(){
return "Strategy to deactivate subswarms";
}
/**********************************************************************************************************************
* shouldDeactivateSubswarm
*/
public boolean isConverged(Population pop){
// Vector<AbstractEAIndividual> bests = new Vector<AbstractEAIndividual>(pop.size());
Vector<Double> bests = (Vector<Double>)pop.getEAIndividual(0).getData(NichePSO.fitArchiveKey);
if (bests.size()<haltingWindow) {
return false;
} else {
List<Double> lst = bests.subList(bests.size()-haltingWindow, bests.size());
bests = new Vector<Double>(haltingWindow);
bests.addAll(lst);
for (int i=1; i<pop.size(); i++) {
for (int k = 0; k < haltingWindow; k++) {
Vector<Double> fitArch = (Vector<Double>)pop.getEAIndividual(i).getData(NichePSO.fitArchiveKey);
int archIndex=fitArch.size()-haltingWindow+k; // index within the fitness archive of the current particle, which may be larger than the bests list - the tail is important
if (archIndex>=0 && (fitArch.get(archIndex)<bests.get(k))) bests.set(k, fitArch.get(archIndex));
}
}
}
// bests contains now the sequence of best fitness values across the last generations
Double historicHWAgo = bests.get(0);
boolean res=true;
for (int i = 1; i < haltingWindow; i++) {
// if historic[-hW] is worse than historic[-hW+i] return false
Double historicIter = bests.get(i);
// if the iterated value (the later one in history) has improved, there is no convergence.
boolean improvementHappened = (historicIter < historicHWAgo);// testSecondForImprovement(historicHWAgo, historicIter));
if (improvementHappened) {
res = false;
break;
}
}
return res;
}
/** @tested
* true if the subswarm is active and all particles are completely converged
* (i.e. the stddev over the past 3 iterations is < epsilson)
* (non-Javadoc) @see javaeva.server.oa.go.Operators.NichePSO.InterfaceDeactivationStrategy#shouldDeactivateSubswarm(javaeva.server.oa.go.Strategies.ParticleSubSwarmOptimization)
*/
public boolean shouldDeactivateSubswarm(ParticleSubSwarmOptimization subswarm) {
if (!subswarm.isActive()){
return false;
}
if (subswarm.getFitnessArchiveSize()<haltingWindow) EVAERROR.errorMsgOnce("Warning: halting window length " + haltingWindow + " too long for sub swarm template, which stores only " + subswarm.getFitnessArchiveSize() + " fitness values!");
return (isConverged(subswarm.getPopulation()));
}
/**********************************************************************************************************************
* deactivateSubswarm
*/
/** @tested
* the subswarm is deactivated and the particles indices are returned. They are
* to be reinitialized into the mainswarm.
* (non-Javadoc) @see javaeva.server.oa.go.Operators.NichePSO.InterfaceDeactivationStrategy#deactivateSubswarm(javaeva.server.oa.go.Strategies.ParticleSubSwarmOptimization, javaeva.server.oa.go.Strategies.ParticleSubSwarmOptimization)
*/
public int[] deactivateSubswarm(ParticleSubSwarmOptimization subswarm, ParticleSubSwarmOptimization mainswarm) {
if (!subswarm.isActive()){
System.out.println("deactivateSubSwarm: try to deactivate inactive subswarm");
return null;
}
// use the indizes of the deactivated particles for the reinitialized particles (important for ANPSO)
Population pop = subswarm.getPopulation();
int[] particleIndices = new int[pop.size()];
for (int i = 0; i < pop.size(); ++i){
AbstractEAIndividual indy = pop.getEAIndividual(i);
//Integer index = (Integer)indy.getData("particleIndex");
particleIndices[i] = indy.getIndividualIndex();//index.intValue();
}
subswarm.SetActive(false);
return particleIndices;
}
/**********************************************************************************************************************
* getter, setter
*/
public void setEpsilon(double epsilon) {
this.epsilon = epsilon;
}
public double getEpsilon() {
return epsilon;
}
public String epsilonTipText(){
return "If the fitness improves by less than this threshold within the halting window, convergence is assumed.";
}
public int getHaltingWindowLen() {
return haltingWindow;
}
public void setHaltingWindowLen(int hwLen) {
this.haltingWindow = hwLen;
}
public String haltingWindowLenTipText() {
return "The number of generations to be tested for improvement";
}
}

View File

@ -0,0 +1,28 @@
package eva2.server.go.operators.nichepso.deactivation;
import eva2.server.go.strategies.ParticleSubSwarmOptimization;
/**
* interface for the deactivation strategies used in NichePSO/ANPSO
*/
public interface InterfaceDeactivationStrategy {
/** @tested
* decides whether a subswarm should be deacitvated according to the deactivation strategy
* @param subswarm
* @return
*/
public abstract boolean shouldDeactivateSubswarm(ParticleSubSwarmOptimization subswarm);
/** @tested
* deactivates a given subswarm.
* What happens to the particles in this subswarm depends on the concrete strategy.
* Return the list of indices to be reinitialized or null.
* @param subswarm
* @param mainswarm
*/
public abstract int[] deactivateSubswarm(ParticleSubSwarmOptimization subswarm, ParticleSubSwarmOptimization mainswarm);
public abstract Object clone();
}

View File

@ -0,0 +1,153 @@
package eva2.server.go.operators.nichepso.deactivation;
import java.util.Vector;
import eva2.server.go.individuals.AbstractEAIndividual;
import eva2.server.go.populations.Population;
import eva2.server.go.strategies.NichePSO;
import eva2.server.go.strategies.ParticleSubSwarmOptimization;
import eva2.tools.EVAERROR;
/**
* A subswarm is deactivated if all its particles are converged.
* A particle is considered converged if the standard deviation of its fitness values
* over the last 3 iterations is less or equal a given threshold epsilon
* Experiments showed good results using epsilon = 0.0001.
*
*/
public class StandardDeactivationStrategy implements InterfaceDeactivationStrategy, java.io.Serializable {
private double epsilon = 0.0001;
private int stdDevHorizon = 3;
/**********************************************************************************************************************
* ctors
*/
public StandardDeactivationStrategy(){
}
public StandardDeactivationStrategy(StandardDeactivationStrategy other){
this.epsilon = other.epsilon;
this.stdDevHorizon = other.stdDevHorizon;
}
public StandardDeactivationStrategy(double eps, int horizon) {
this.epsilon = eps;
this.stdDevHorizon = horizon;
}
public StandardDeactivationStrategy(double eps) {
this.epsilon = eps;
}
public Object clone(){
return (Object) new StandardDeactivationStrategy(this);
}
public String globalInfo(){
return "Strategy to deactivate subswarms";
}
/**********************************************************************************************************************
* shouldDeactivateSubswarm
*/
/** @tested
* @param pop
* @return
*/
// public boolean areAllConverged(Population pop){
// for (int i = 0; i < pop.size(); ++i){
// AbstractEAIndividual currentindy = pop.getEAIndividual(i);
// Double sd = (Double)currentindy.getData(NichePSO.stdDevKey);
// if (sd.doubleValue() > getEpsilon()){
// return false; // particle not converged...
// }
// }
// return true;
// }
public boolean areAllConverged(Population pop){
for (int i = 0; i < pop.size(); ++i){
AbstractEAIndividual currentindy = pop.getEAIndividual(i);
double value;
if (stdDevHorizon == NichePSO.defaultFitStdDevHorizon) {
value = ((Double)currentindy.getData(NichePSO.stdDevKey)).doubleValue();
} else {
Vector<Double> fitArch = (Vector<Double>)currentindy.getData(NichePSO.fitArchiveKey);
value = ParticleSubSwarmOptimization.stdDev(fitArch,stdDevHorizon);
}
if (value > getEpsilon()){
return false; // particle not converged...
}
}
return true;
}
/** @tested
* true if the subswarm is active and all particles are completely converged
* (i.e. the stddev over the past 3 iterations is < epsilson)
* (non-Javadoc) @see javaeva.server.oa.go.Operators.NichePSO.InterfaceDeactivationStrategy#shouldDeactivateSubswarm(javaeva.server.oa.go.Strategies.ParticleSubSwarmOptimization)
*/
public boolean shouldDeactivateSubswarm(ParticleSubSwarmOptimization subswarm) {
if (!subswarm.isActive()){
return false;
}
if (subswarm.getFitnessArchiveSize()<stdDevHorizon) EVAERROR.errorMsgOnce("Warning: halting window length " + stdDevHorizon + " too long for sub swarm template, which stores only " + subswarm.getFitnessArchiveSize() + " fitness values!");
return (areAllConverged(subswarm.getPopulation()));
}
/**********************************************************************************************************************
* deactivateSubswarm
*/
/** @tested
* the subswarm is deactivated and the particles indices are returned. They are
* to be reinitialized into the mainswarm.
* (non-Javadoc) @see javaeva.server.oa.go.Operators.NichePSO.InterfaceDeactivationStrategy#deactivateSubswarm(javaeva.server.oa.go.Strategies.ParticleSubSwarmOptimization, javaeva.server.oa.go.Strategies.ParticleSubSwarmOptimization)
*/
public int[] deactivateSubswarm(ParticleSubSwarmOptimization subswarm, ParticleSubSwarmOptimization mainswarm) {
if (!subswarm.isActive()){
System.out.println("deactivateSubSwarm: try to deactivate inactive subswarm");
return null;
}
// use the indizes of the deactivated particles for the reinitialized particles (important for ANPSO)
Population pop = subswarm.getPopulation();
int[] particleIndices = new int[pop.size()];
for (int i = 0; i < pop.size(); ++i){
AbstractEAIndividual indy = pop.getEAIndividual(i);
//Integer index = (Integer)indy.getData("particleIndex");
particleIndices[i] = indy.getIndividualIndex();//index.intValue();
}
subswarm.SetActive(false);
return particleIndices;
}
/**********************************************************************************************************************
* getter, setter
*/
public void setEpsilon(double epsilon) {
this.epsilon = epsilon;
}
public double getEpsilon() {
return epsilon;
}
public String epsilonTipText(){
return "threshold used to identify converged particles";
}
public int getStdDevHorizon() {
return stdDevHorizon;
}
public void setStdDevHorizon(int stdDevHorizon) {
this.stdDevHorizon = stdDevHorizon;
}
public String stdDevHorizonTipText() {
return "The number of past fitness values to use for deactivation indication, note theres a maximum defined by the NichePSO fitness archiving.";
}
}

View File

@ -0,0 +1,40 @@
package eva2.server.go.operators.nichepso.merging;
import java.util.Vector;
import eva2.server.go.strategies.ParticleSubSwarmOptimization;
/**
* interface for the merging strategies used in NichePSO
*/
public interface InterfaceMergingStrategy {
/**
* decides whether the two subswarms should be merged according to the merging strategie
* @param subswarm1
* @param subswarm2
* @return
*/
public abstract boolean shouldMergeSubswarms(
ParticleSubSwarmOptimization subswarm1,
ParticleSubSwarmOptimization subswarm2);
/**
* Merges the i. and j. subswarm from subSwarms.
* The meaning of this depends on the concrete strategy but two aspects schould be taken care of:
* 1. the overall population size (in all subSwarms and the mainSwarm) should remain constant
* 2. call populationSizeHasChanged() for changed swarms
* @param i
* @param j
* @param subSwarms
* @param mainSwarm
*/
public abstract void mergeSubswarms(
int i,
int j,
Vector<ParticleSubSwarmOptimization> subSwarms,
ParticleSubSwarmOptimization mainSwarm);
public abstract Object clone();
}

View File

@ -0,0 +1,96 @@
package eva2.server.go.operators.nichepso.merging;
import java.util.Vector;
import eva2.server.go.strategies.ParticleSubSwarmOptimization;
/**
* Two subswarms are merged if their radii overlap.
* In case both radii equal zero the subswarms are merged if their distance is below a given threshold mu.
* During merging, the particles of one of these subswarms are reinitialized into the main swarm.
* This improves exploration compared to the StandardMergingStrategy.
* This strategy is proposed in [1] and a small value, such as mu = 0.001, is suggested.
* [1] A.P. Engelbrecht and L.N.H. van Loggerenberg.
* Enhancing the nichepso.
* In IEEE Congress on Evolutionary Computation,
* 2007.
*/
public class ScatterMergingStrategy extends StandardMergingStrategy{
public ScatterMergingStrategy() {
super();
}
public ScatterMergingStrategy(double theMu) {
super(theMu);
}
public String globalInfo(){
return "Strategy to merge subswarms";
}
/**********************************************************************************************************************
* mergeSubswarms
*/
/** @tested
* if both active: reinitializes subswarm j back into the main swarm and deletes it from the subswarms.
* if both inactive: adds population of subswarm j to population of subswarm i, then deletes subswarm j.
* @param i
* @param j
*/
public void mergeSubswarms(
int i,
int j,
Vector<ParticleSubSwarmOptimization> subSwarms,
ParticleSubSwarmOptimization mainSwarm)
{
ParticleSubSwarmOptimization borg= subSwarms.get(i);
ParticleSubSwarmOptimization others= subSwarms.get(j);
if (borg.isActive() && others.isActive()){
mergeActiveSubswarms(i,j,subSwarms,mainSwarm);
return;
}
if (!borg.isActive() && !others.isActive()){
mergeInactiveSubswarms(i,j,subSwarms,mainSwarm);
return;
}
System.out.print("ScatterMergingStrategy.mergeSubswarms problem: subswarms not of equal state.");
}
private void mergeInactiveSubswarms(
int i,
int j,
Vector<ParticleSubSwarmOptimization> subSwarms,
ParticleSubSwarmOptimization mainSwarm) {
ParticleSubSwarmOptimization borg = subSwarms.get(i);
ParticleSubSwarmOptimization others= subSwarms.get(j);
borg.addPopulation(others);
borg.populationSizeHasChanged();
subSwarms.remove(j);
}
/** @tested
* subswarm j is reinited into the mainswarm and deleted, the function calls are added to the main swarm
* @param i
* @param j
* @param subSwarms
* @param mainSwarm
*/
private void mergeActiveSubswarms(
int i,
int j,
Vector<ParticleSubSwarmOptimization> subSwarms,
ParticleSubSwarmOptimization mainSwarm) {
mainSwarm.reinitIndividuals(subSwarms.get(j).getPopulation().size()); // add to the mainswarm
//mainSwarm.populationSizeHasChanged(); // already called in addNewParticlesToPopulation
// transfer functioncalls from the subswarm to the mainswarm before deleting it:
int calls = subSwarms.get(j).getPopulation().getFunctionCalls();
mainSwarm.getPopulation().incrFunctionCallsBy(calls);
subSwarms.remove(j);
}
}

View File

@ -0,0 +1,146 @@
package eva2.server.go.operators.nichepso.merging;
import java.util.Vector;
import eva2.server.go.individuals.AbstractEAIndividual;
import eva2.server.go.individuals.InterfaceESIndividual;
import eva2.server.go.operators.distancemetric.EuclideanMetric;
import eva2.server.go.operators.distancemetric.PhenotypeMetric;
import eva2.server.go.strategies.ParticleSubSwarmOptimization;
/**
* Two subswarms are merged if their radii overlap.
* In case both radii equal zero the subswarms are merged if their distance is below a given threshold mu.
* This strategy is proposed in [1] and a small value, such as mu = 0.001, is suggested.
* [1] R. Brits, A. P. Engelbrecht and B. Bergh.
* A Niching Particle Swarm Optimizer
* In Proceedings of the 4th Asia-Pacific Conference on Simulated Evolution and Learning (SEAL'02),
* 2002, 2, 692-696
*/
public class StandardMergingStrategy implements InterfaceMergingStrategy, java.io.Serializable {
private double mu = 0.001; // "experimentally found to be effective" according to "a niching particle swarm optimizer" by Brits et al.
public String globalInfo(){
return "Strategy to merge subswarms";
}
/**********************************************************************************************************************
* ctors
*/
public StandardMergingStrategy(){
}
public StandardMergingStrategy(double theMu){
mu = theMu;
}
public StandardMergingStrategy(StandardMergingStrategy other){
this.mu = other.mu;
}
public Object clone(){
return (Object) new StandardMergingStrategy(this);
}
/**********************************************************************************************************************
* shouldMergeSubswarms
*/
/** @tested
* the subswarms are merged, if they overlap (or are very close) and if they are of equal state
* (non-Javadoc) @see javaeva.server.oa.go.Operators.NichePSO.InterfaceMergingStrategie#shouldMergeSubswarms(javaeva.server.oa.go.Strategies.ParticleSubSwarmOptimization, javaeva.server.oa.go.Strategies.ParticleSubSwarmOptimization)
*/
public boolean shouldMergeSubswarms(ParticleSubSwarmOptimization subswarm1, ParticleSubSwarmOptimization subswarm2) {
// check for equal state
if (subswarm1.isActive() && !subswarm2.isActive()) return false;
if (!subswarm1.isActive() && subswarm2.isActive()) return false;
if (!subswarmsOverlapOrAreVeryClose(subswarm1,subswarm2)){
return false;
}
return true;
}
private boolean subswarmsOverlapOrAreVeryClose(ParticleSubSwarmOptimization subswarm1,ParticleSubSwarmOptimization subswarm2) {
// check if they overlap
AbstractEAIndividual gbesti = subswarm1.getGBestIndividual();
AbstractEAIndividual gbestj = subswarm2.getGBestIndividual();
InterfaceESIndividual i1=null, i2=null;
double dist;
if (gbesti instanceof InterfaceESIndividual) {
i1=(InterfaceESIndividual)gbesti;
i2=(InterfaceESIndividual)gbestj;
}
if (i1 != null) dist = EuclideanMetric.euclideanDistance(i1.getDGenotype(), i2.getDGenotype());
else dist = subswarm1.distance(gbesti, gbestj); // euclidean distance
// System.out.println("dist is " + dist);
if (dist < (subswarm1.getMaxAllowedSwarmRadiusAbs() + subswarm2.getMaxAllowedSwarmRadiusAbs())) {
// only then is the next (expensive) test feasible
double Ri = subswarm1.getBoundSwarmRadius(); // uses euclidean distance
double Rj = subswarm2.getBoundSwarmRadius(); // uses euclidean distance
if (dist < Ri+Rj ){ // all in euclidean metric
return true;
}
}
// check if they are "very close"
double dist_norm;
if (i1 != null) {
dist_norm = EuclideanMetric.normedEuclideanDistance(i1.getDGenotype(), i1.getDoubleRange(),
i2.getDGenotype(), i2.getDoubleRange());
} else dist_norm = PhenotypeMetric.dist(gbesti, gbestj); // normalised distance
//if (Ri == 0 && Rj == 0 && dist_norm < getEpsilon()){ // see "Enhancing the NichePSO" paper
if (dist_norm < getMu()){ // Ri und Rj auf null testen sinvoll ?
return true;
}
return false;
}
/**********************************************************************************************************************
* mergeSubswarms
*/
/** @tested junit
* adds population of subswarm j to population of subswarm i, then deletes subswarm j.
* @param i
* @param j
*/
public void mergeSubswarms(
int i,
int j,
Vector<ParticleSubSwarmOptimization> subSwarms,
ParticleSubSwarmOptimization mainSwarm)
{
ParticleSubSwarmOptimization borg = subSwarms.get(i);
ParticleSubSwarmOptimization others= subSwarms.get(j);
// System.out.println("merging " + (borg.isActive() ? " active " : " inactive ") + " with " + (others.isActive() ? "active" : "inactive"));
borg.addPopulation(others);
borg.populationSizeHasChanged();
subSwarms.remove(j); // ok: function calls added to borg swarm...
}
/**********************************************************************************************************************
* getter, setter
*/
public void setMu(double mu) {
this.mu = mu;
}
public double getMu() {
return mu;
}
public String muTipText(){
return "threshold used to merge subswarms that lie very close but have no spatial extent";
}
}

View File

@ -0,0 +1,24 @@
package eva2.server.go.operators.nichepso.subswarmcreation;
import eva2.server.go.individuals.AbstractEAIndividual;
import eva2.server.go.strategies.ParticleSubSwarmOptimization;
public class DummySubswarmCreationStrategy implements InterfaceSubswarmCreationStrategy {
public Object clone(){
return (Object) new DummySubswarmCreationStrategy();
}
public void createSubswarm(ParticleSubSwarmOptimization preparedSubswarm,
AbstractEAIndividual indy, ParticleSubSwarmOptimization mainSwarm) {
// TODO Auto-generated method stub
}
public boolean shouldCreateSubswarm(AbstractEAIndividual indy,
ParticleSubSwarmOptimization mainswarm) {
// TODO Auto-generated method stub
return false;
}
}

View File

@ -0,0 +1,97 @@
package eva2.server.go.operators.nichepso.subswarmcreation;
import eva2.server.go.individuals.AbstractEAIndividual;
import eva2.server.go.individuals.ESIndividualDoubleData;
import eva2.server.go.operators.mutation.MutateESFixedStepSize;
import eva2.server.go.populations.Population;
import eva2.server.go.strategies.ParticleSubSwarmOptimization;
/**
* The standard deviation in the fitness of each main swarm particle over the last 3 iterations is calculated.
* If this standard deviation falls below a given threshold delta it is assumed that the particle is converging
* on an optimum and a subswarm is created with that particle and a generated neighbor.
* This neighbor is generated by mutating the converged particle using the mutation step size mu.
* delta = 0.0001 and mu = 0.1 could experimentally produce acceptable results
* but further effort to obtain appropriate values for mu may significantly improve the performance of this strategy.
*/
public class GenerateNeighborSubswarmCreationStrategy extends
StandardSubswarmCreationStrategy {
private double mu = 0.1;
/**********************************************************************************************************************
* shouldCreateSubswarm
*/
// same as in StandardSubswarmCreationStrategy
/**********************************************************************************************************************
* createSubswarm
*/
/** @tested
* creates a subswarm from the given particle and its neighbor in the mainswarm.
* If the neighbors pbest is better than the particles pbest, a new neighbor is generated.
* (non-Javadoc) @see javaeva.server.oa.go.Operators.NichePSO.StandardSubswarmCreationStrategy#createSubswarm(javaeva.server.oa.go.Strategies.ParticleSubSwarmOptimization, javaeva.server.oa.go.EAIndividuals.AbstractEAIndividual, javaeva.server.oa.go.Strategies.ParticleSubSwarmOptimization)
*/
public void createSubswarm(ParticleSubSwarmOptimization preparedSubswarm, AbstractEAIndividual indy, ParticleSubSwarmOptimization mainSwarm) {
// get the neighbor in the mainswarm
AbstractEAIndividual neighbor = mainSwarm.getMemberNeighbor(indy);
AbstractEAIndividual worst;
// check if neighbor would "pull the indy away from its niche" because it has a better pbest
AbstractEAIndividual indypbest = (AbstractEAIndividual)indy.getData("PersonalBestKey");
AbstractEAIndividual neighpbest = (AbstractEAIndividual)neighbor.getData("PersonalBestKey");
if (true){//neighpbest.isDominating(indypbest)) {
neighbor = generateNeighborFrom(indy,mainSwarm); // neighbor wouldnt help with indies niche
worst = mainSwarm.getParticleWithWorstPBestButNot(indy); // delete another particle for the gnerated neighbor
}else{
worst = neighbor; // use the neighbor particle and delete it from the mainswarm
}
Population pop = new Population(2);
pop.add(indy);
pop.add(neighbor);
preparedSubswarm.setPopulation(pop);
preparedSubswarm.populationSizeHasChanged();
// remove particles from the main swarm:
mainSwarm.removeSubIndividual(indy);
mainSwarm.removeSubIndividual(worst);
mainSwarm.populationSizeHasChanged();
}
private AbstractEAIndividual generateNeighborFrom(AbstractEAIndividual indy, ParticleSubSwarmOptimization mainswarm) {
// generate a neighbor
ESIndividualDoubleData neighbor = (ESIndividualDoubleData)indy.clone();
MutateESFixedStepSize mutator = new MutateESFixedStepSize();
mutator.setSigma(getMu());
neighbor.setMutationOperator(mutator);
neighbor.setMutationProbability(1);
neighbor.mutate();
//TODO more stuff: stddev ... from indy
//TODO mutate velocity? evaluate?
neighbor.putData("BestFitness", neighbor.getFitness());
neighbor.putData("BestPosition", neighbor.getDGenotype());
return neighbor;
}
/**********************************************************************************************************************
* getter, setter
*/
public void setMu(
double generateNeighborWithMutationStep) {
this.mu = generateNeighborWithMutationStep;
}
public double getMu() {
return mu;
}
public String muTipText(){
return "mutation step size used to generate a neighbor";
}
}

View File

@ -0,0 +1,35 @@
package eva2.server.go.operators.nichepso.subswarmcreation;
import eva2.server.go.individuals.AbstractEAIndividual;
import eva2.server.go.strategies.ParticleSubSwarmOptimization;
/**
* interface for the subswarm creation strategies used in NichePSO
*/
public interface InterfaceSubswarmCreationStrategy {
/** @tested
* decides whether a subswarm should be created for the given indy and mainswarm according to the creation strategie
* @param indy
* @param mainswarm
* @return
*/
public abstract boolean shouldCreateSubswarm(
AbstractEAIndividual indy,
ParticleSubSwarmOptimization mainswarm);
/** @tested
* creates a subswarm from indy, the details depend on the concrete strategy.
* @param preparedSubswarm a subswarm which is appropriatly prepared
* (ie its problem, optimization strategy etc. are set correctly from the "meta-optimizer")
* Afterwards the subswarm containes the generated particles
* @param indy a particle from which a subswarm should be created
* @param mainSwarm the main swarm which contains indy
*/
public abstract void createSubswarm(
ParticleSubSwarmOptimization preparedSubswarm,
AbstractEAIndividual indy,
ParticleSubSwarmOptimization mainSwarm);
public abstract Object clone();
}

View File

@ -0,0 +1,119 @@
package eva2.server.go.operators.nichepso.subswarmcreation;
import eva2.server.go.individuals.AbstractEAIndividual;
import eva2.server.go.populations.Population;
import eva2.server.go.strategies.NichePSO;
import eva2.server.go.strategies.ParticleSubSwarmOptimization;
/**
* The standard deviation in the fitness of each main swarm particle over the last 3 iterations is calculated.
* If this standard deviation falls below a given threshold delta it is assumed
* that the particle is converging on an optimum and a subswarm is created with that particle and its topological neighbor.
* The strategy is proposed in [1] suggesting a value of delta = 0.0001.
* [1] R. Brits, A. P. Engelbrecht and B. Bergh.
* A Niching Particle Swarm Optimizer
* In Proceedings of the 4th Asia-Pacific Conference on Simulated Evolution and Learning (SEAL'02),
* 2002, 2, 692-696
*/
public class StandardSubswarmCreationStrategy implements InterfaceSubswarmCreationStrategy, java.io.Serializable {
protected double delta = 0.0001; // "experimentally found to be effective" according to "a niching particle swarm optimizer" by Brits et al.
public StandardSubswarmCreationStrategy(double theDelta) {
delta = theDelta;
}
public StandardSubswarmCreationStrategy() {
delta = 0.0001;
}
public Object clone(){
return (Object) new StandardSubswarmCreationStrategy(delta);
}
public String globalInfo(){
return "Strategy to create subswarms from the main swarm";
}
/**********************************************************************************************************************
* shouldCreateSubswarm
*/
/** @tested junit
* true if the stddev of the particles fitness < delta and no constraints are violated
* @param indy main swarm particle
* @return
*/
public boolean shouldCreateSubswarm(AbstractEAIndividual indy, ParticleSubSwarmOptimization mainswarm) {
if (createSubswarmConstraintViolation(indy, mainswarm)){
return false;
}
// check for stddev < delta condition
double stddev = (((Double)indy.getData(NichePSO.stdDevKey))).doubleValue();
if (stddev >= getDelta()){
return false;
}
return true;
}
/** @tested junit
* true, if reasons exist why no subswarm should be created from indy.
* Reasons like:
* poor fitness (not implemented),
* convergence on plateau (not implemented),
* indy is the only particle in the mainswarm and therefor has no neighbor
* @param indy main swarm particle
* @return
*/
public boolean createSubswarmConstraintViolation(AbstractEAIndividual indy, ParticleSubSwarmOptimization mainswarm){
boolean result = false;
// check for MainSwarm-Size
if (mainswarm.getPopulation().size() < 2){
//if (verbose) System.out.print("createSubswarmConstraintViolation: MainSwarm too small, no subswarm can be created\n");
result = true;
}
return result;
}
/**********************************************************************************************************************
* createSubswarm
*/
/** @tested
* creates a subswarm from the given particle and its neighbor in the mainswarm,
* then deletes the two particles from the mainswarm.
* (non-Javadoc) @see javaeva.server.oa.go.Operators.NichePSO.InterfaceSubswarmCreationStrategy#createSubswarm(javaeva.server.oa.go.Strategies.ParticleSubSwarmOptimization, javaeva.server.oa.go.EAIndividuals.AbstractEAIndividual, javaeva.server.oa.go.Strategies.ParticleSubSwarmOptimization)
*/
public void createSubswarm(ParticleSubSwarmOptimization preparedSubswarm, AbstractEAIndividual indy, ParticleSubSwarmOptimization mainSwarm) {
// get the neighbor to create the subswarm
AbstractEAIndividual neighbor = mainSwarm.getMemberNeighbor(indy);
Population pop = new Population(2);
pop.add(indy);
pop.add(neighbor);
preparedSubswarm.setPopulation(pop);
preparedSubswarm.populationSizeHasChanged();
// remove particles from the main swarm:
mainSwarm.removeSubIndividual(indy);
mainSwarm.removeSubIndividual(neighbor);
mainSwarm.populationSizeHasChanged();
}
public double getDelta() {
return delta;
}
public void setDelta(double delta) {
this.delta = delta;
}
public String deltaTipText(){
return "threshold used to identify converging particles which lead to the creation of subswarms";
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,130 @@
package eva2.server.go.strategies;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
/**
* This is a small implementation of an undirected graph which is able
* to compute the connected components.
* This class is used to represent the NicheGraph for the ANPSO algorithm.
*/
public class NicheGraph implements java.io.Serializable {
/**********************************************************************************************************************
* members
*/
// key is vertex, value is set of adjacent vertices
protected TreeMap<String, TreeSet<String>> graphTable;
// set of visited vertices in bfs
protected HashSet<String> set;
/**********************************************************************************************************************
* ctor
*/
public NicheGraph(){
graphTable = new TreeMap<String, TreeSet<String>>();
set = new HashSet<String>();
}
public NicheGraph(NicheGraph o){
this.graphTable = (TreeMap<String, TreeSet<String>>)o.graphTable.clone();
this.set = (HashSet<String>)o.set.clone();
}
public Object clone(){
return (Object) new NicheGraph(this);
}
/**********************************************************************************************************************
* vertices and edges
*/
/**
* adds a new vertex without neighbors
* @param v
*/
public void addVertex(String v){
if (!containsVertex(v)) graphTable.put(v, new TreeSet<String>());
}
/**
* adds an edge to the graph (previously adds the vertices if necessary)
* @param v1
* @param v2
*/
public void addEdge(String v1, String v2){
if (!containsVertex(v1)) addVertex(v1);
if (!containsVertex(v2)) addVertex(v2);
// mutually add the vertices as neighbors
graphTable.get(v1).add(v2);
graphTable.get(v2).add(v1);
}
public boolean containsVertex(String v) {
return graphTable.containsKey(v);
}
// return iterator over all vertices in graph
public Iterable<String> getVertexIterator() {
return graphTable.keySet();
}
// return an iterator over the neighbors of vertex v
public Iterable<String> getNeighborIterator(String v) {
return graphTable.get(v);
}
/**********************************************************************************************************************
* BFS, getConnectedComponents
*/
// run BFS from given root vertex r
public void runBFS(String r) {
set = new HashSet<String>();
// put root on the queue
java.util.Queue<String> q = new LinkedList<String>();
q.offer(r);
set.add(r);
// remove next vertex and put all neighbors on queue (if not visited)...
while (!q.isEmpty()) {
String v = q.poll();
for (String w : getNeighborIterator(v)) {
if (!set.contains(w)){
q.offer(w);
set.add(w);
}
}
}
}
/**
* @return connected components of the graph
*/
public List<Set<String>> getConnectedComponents(){
ArrayList<Set<String>> l = new ArrayList<Set<String>>();
for (String v : getVertexIterator()){
if (!isComponent(v,l)){
// use current vertex to start a bfs
runBFS(v);
// add visited vertices to the set of connected components
l.add(set);
}
}
return l;
}
private boolean isComponent(String v, ArrayList<Set<String>> l) {
for (Set<String> set : l){
if (set.contains(v)) return true;
}
return false;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,754 @@
package eva2.server.go.strategies;
import java.util.Vector;
import eva2.server.go.IndividualInterface;
import eva2.server.go.individuals.AbstractEAIndividual;
import eva2.server.go.individuals.ESIndividualDoubleData;
import eva2.server.go.individuals.InterfaceDataTypeDouble;
import eva2.server.go.operators.distancemetric.EuclideanMetric;
import eva2.server.go.populations.Population;
import eva2.server.go.problems.AbstractOptimizationProblem;
import eva2.server.go.problems.InterfaceOptimizationProblem;
import eva2.tools.math.Mathematics;
/**
* This implements a particle swarm optimizer which is used by the NichePSO and ANPSO
* to represent and train the mainswarm or any subswarm.
* This is done by extending the standard particle swarm optimizer so that
* - additional member variables (characterizing and parameterizing the subswarm) are available
* - additional information is added to the particles during an optimization loop
* - additional functions to add, remove and reinitialize particles are available
*/
public class ParticleSubSwarmOptimization extends ParticleSwarmOptimizationGCPSO {
protected double maxAllowedSwarmRadiusNormal; // maximal allowed swarmradius (relative to the search space)
public static boolean hideFromGOE = true; // dont want it to be available in the GUI
protected boolean active; // marks the swarm active or inactive
protected double maxPosDist; // maximal possible distance in the search space, depends on problem -> initMaxPosDist()
private int particleIndexCounter; // used to give each particle a unique index (for debbugging and plotting)
private int fitnessArchiveSize = 15; // maximal number of fitnessvalues remembered from former iterations
//ParameterupdateStrategies
// InterfaceParameterAging inertnessAging = new NoParameterAging();
/**********************************************************************************************************************
* ctors, clone
*/
/** @tested ps
* ctor
*/
public ParticleSubSwarmOptimization() {
updateMaxPosDist();
this.maxAllowedSwarmRadiusNormal = 0.1; // set similar to "particle swarms for multimodal optimization" by Oezcan and Yilmaz
this.active = true;
particleIndexCounter = getPopulation().size(); // newly added particles will start at this index
// setInitialVelocity(1.);
}
/** @tested
* cpyctor
*/
public ParticleSubSwarmOptimization(ParticleSubSwarmOptimization a) {
super(a);
if (a.m_BestIndividual != null){
m_BestIndividual = (AbstractEAIndividual)a.m_BestIndividual.clone();
}
maxAllowedSwarmRadiusNormal = a.maxAllowedSwarmRadiusNormal;
active = a.active;
maxPosDist = a.maxPosDist;
particleIndexCounter = a.particleIndexCounter;
// inertnessAging = (InterfaceParameterAging)a.inertnessAging.clone();
fitnessArchiveSize = a.fitnessArchiveSize;
}
/** @tested
* (non-Javadoc) @see javaeva.server.oa.go.Strategies.ParticleSwarmOptimization#clone()
*/
public Object clone() {
return (Object) new ParticleSubSwarmOptimization(this);
}
/**********************************************************************************************************************
* inits
*/
/** @tested ps
* (non-Javadoc) @see javaeva.server.oa.go.Strategies.ParticleSwarmOptimization#init()
*/
public void init(){
super.init();
initIndividuals();
updateMBestIndividual();
updateMaxPosDist();
particleIndexCounter = getPopulation().size();
// setInertnessOrChi(inertnessAging.getStartValue());
}
/** @tested ps
* (non-Javadoc) @see javaeva.server.oa.go.Strategies.ParticleSwarmOptimization#initByPopulation(javaeva.server.oa.go.Populations.Population, boolean)
*/
public void initByPopulation(Population pop, boolean reset){
super.initByPopulation(pop, reset);
initIndividuals();
updateMBestIndividual();
updateMaxPosDist();
particleIndexCounter = getPopulation().size();
}
/** @tested junit&
* adds a vector for fitnessvalues to all individuals in the swarm
* and sets the current fitness as the first value
*/
protected void initIndividuals(){
for (int i = 0; i < m_Population.size(); ++i){
AbstractEAIndividual indy = (AbstractEAIndividual)(m_Population.getEAIndividual(i));
initSubSwarmDefaultsOf(indy);
}
}
public static void initSubSwarmDefaultsOf(AbstractEAIndividual indy) {
initFitnessArchiveOf(indy);
initFitnessStdDevOf(indy);
initPersonalBestOf(indy);
initPBestImprInARowOf(indy);
}
public static void initFitnessArchiveOf(AbstractEAIndividual indy) {
Vector<Double> vec = new Vector<Double>();
double scalarFitness = sum(indy.getFitness()); // if multiobjective, use the sum of all fitnessvalues (dont use the norm because fitnessvalues may be negative)
vec.add(new Double(scalarFitness));
indy.putData(NichePSO.fitArchiveKey, vec);
}
/** @tested emp
* adds a std deviation value to an individual
* and initially sets this value to infinity.
*/
public static void initFitnessStdDevOf(AbstractEAIndividual indy) {
// init stddev to inf, dont want immediate convergence...
indy.putData(NichePSO.stdDevKey, new Double(Double.POSITIVE_INFINITY));
}
public static void initPBestImprInARowOf(AbstractEAIndividual indy) {
indy.putData("PBestImprovementsInARow", new Integer(0));
}
/** @tested junit
* adds a representation of the personal best to an individual
* and initially sets the current individual as its personal best.
*/
public static void initPersonalBestOf(AbstractEAIndividual indy) {
AbstractEAIndividual newpbest = (AbstractEAIndividual)indy.clone();
newpbest.putData("PersonalBestKey", null); // dont want to have a chain of pbests
indy.putData("PersonalBestKey", newpbest);
}
/**********************************************************************************************************************
* Optimization
*/
/** @tested ps
* (non-Javadoc) @see javaeva.server.oa.go.Strategies.ParticleSwarmOptimization#optimize()
*/
public void optimize(){
super.optimize();
updateFitnessArchives();
updateFitnessStdDev();
updatePersonalBest();
updateMBestIndividual();
// updateParameters();
}
public void reinitIndividuals(Vector<int[]> indicesToReinit) {
for (int[] indices : indicesToReinit) {
addNewParticlesToPopulation(indices);
}
}
/**
* Get the next set of indices increasing the internal particle counter.
* Should only be called immediately before adding the new individuals.
*
* @param num
* @return
*/
private int[] getNextIndices(int num) {
int[] indices = new int[num];
for (int i = 0; i < num; ++i){
indices[i] = particleIndexCounter;
++particleIndexCounter;
}
return indices;
}
public void reinitIndividuals(int numIndies) {
addNewParticlesToPopulation(getNextIndices(numIndies));
}
/**********************************************************************************************************************
* updateTopology
*/
protected AbstractEAIndividual getIndyByParticleIndexAndPopulation(Population pop, Integer index){
for (int i = 0; i < pop.size(); ++i)
{
AbstractEAIndividual indy = pop.getEAIndividual(i);
// Integer tmp = (Integer)indy.getData("particleIndex"); // CPU-Time Hotspot
// if (index.equals(tmp)) return indy;
if (index.intValue() == indy.getIndividualIndex()) return indy;
}
return null;
}
/* (non-Javadoc)
* @see eva2.server.go.strategies.ParticleSwarmOptimization#addSortedIndizesTo(eva2.server.go.populations.Population)
*/
protected void addSortedIndicesTo(Object[] sortedPopulation, Population pop) {
int origIndex;
for (int i=0; i<pop.size(); i++) {
// cross-link the sorted list for faster access
// (since NichePSO and ANPSO allow individuals
// to leave and enter a population the index in the
// population does not necessarily match the individual index)
origIndex = ((AbstractEAIndividual)sortedPopulation[i]).getIndividualIndex();
AbstractEAIndividual indy = getIndyByParticleIndexAndPopulation(pop, origIndex);
indy.putData(sortedIndexKey, new Integer(i));
}
}
/**********************************************************************************************************************
* updates
*/
/** @tested ps
* when particles enter or leave the population,
* call this method to update the status of the population
*/
public void populationSizeHasChanged(){
updateMBestIndividual();
}
/** @tested junit&
* updates the m_BestIndividual member which represents the gbest individual
* (i.e. the best position and fitness encountered by any particle of the swarm)
* Beware: if a particle enters the swarm its knowledge about its pbest enters the swarm,
* on the other side: if a particle leaves the swarm its knowledge leaves the swarm as well.
*/
protected void updateMBestIndividual(){
if (getPopulation().size() == 0) return;
// First: set m_BestIndividual to any personal best position in the swarm (-> bestindypbest).
// This is necessary because the current m_BestIndividual my came from
// an individual that left the swarm and would never be replaced if it
// would dominate all remaining positions in the swarm.
AbstractEAIndividual bestindy = getPopulation().getBestEAIndividual();
AbstractEAIndividual bestindypbest = (AbstractEAIndividual)bestindy.getData("PersonalBestKey");
m_BestIndividual = (AbstractEAIndividual)bestindypbest.clone();
for (int i = 0; i < getPopulation().size(); ++i){
AbstractEAIndividual currentindy = getPopulation().getEAIndividual(i);
AbstractEAIndividual currentindypbest = (AbstractEAIndividual)currentindy.getData("PersonalBestKey");
if (currentindypbest.isDominating(m_BestIndividual)){
m_BestIndividual = (AbstractEAIndividual)currentindypbest.clone();
// ++gbestImprovmentsInARow;
} //else gbestImprovmentsInARow = 0;
}
}
/** @tested junit, dbg
* adds the current fitnessvalue to the fitnessarchive for every individual in the swarm.
* Keeps the fitnessarchive at a limited size (lim+1).
*/
public void updateFitnessArchives(){
//int lim = 3; // maximal number of fitnessvalues remembered from former iterations
for (int i = 0; i < m_Population.size(); ++i){
AbstractEAIndividual indy = (AbstractEAIndividual)m_Population.getEAIndividual(i);
Vector<Double> fitArchive_old = (Vector<Double>)(indy.getData(NichePSO.fitArchiveKey));
double scalarFitness = sum(indy.getFitness()); // if multiobjective, use the sum of all fitnessvalues (dont use the norm because fitnessvalues may be negative)
Double fitness = new Double(scalarFitness);
Vector<Double> fitArchive_new = new Vector<Double>();
int end = fitArchive_old.size();
int start = 0;
if (end >= fitnessArchiveSize) start = end-fitnessArchiveSize;
for (int j = start; j < end; ++j){
fitArchive_new.add(fitArchive_old.get(j));
}
fitArchive_new.add(fitness);
indy.putData(NichePSO.fitArchiveKey, fitArchive_new);
}
}
/** @tested junit
* sets the std dev value of all individuals in the swarm
* to the std deviation over the last 3 fitness values
*/
public void updateFitnessStdDev(){
for (int i = 0; i < m_Population.size(); ++i){
AbstractEAIndividual currentindy = m_Population.getEAIndividual(i);
Vector<Double> fitnessArchive = (Vector<Double>)(currentindy.getData(NichePSO.fitArchiveKey));
// the stddev is computed over 3 values as suggested in
// "a niching particle swarm optimizer" by Brits et al.
double sd = stdDev(fitnessArchive,NichePSO.defaultFitStdDevHorizon);
currentindy.putData(NichePSO.stdDevKey, new Double(sd));
}
}
/** @tested junit&, junit
* update the personal best representation if the current individual is better than the pbest
*/
public void updatePersonalBest(){
for (int i = 0; i < m_Population.size(); ++i){
AbstractEAIndividual currentindy = m_Population.getEAIndividual(i);
AbstractEAIndividual pbest = (AbstractEAIndividual)currentindy.getData("PersonalBestKey");
if (currentindy.isDominating(pbest)){
initPersonalBestOf(currentindy);
//PBestImprovementsInARow
Integer counter = (Integer)currentindy.getData("PBestImprovementsInARow");
counter = new Integer(counter.intValue()+1);
currentindy.putData("PBestImprovementsInARow",counter);
}else{
initPBestImprInARowOf(currentindy);
}
}
}
/** @tested junit ..
* updates the member representing the maximal possible distance in the current searchspace
*/
public void updateMaxPosDist(){
// compute the maximal possible distance in the search space:
AbstractOptimizationProblem prob = (AbstractOptimizationProblem)m_Problem;
// m_Problem must have called initProblem, so that the template is set correctly. This shouls always be the case here...
AbstractEAIndividual template = prob.getIndividualTemplate();
if (template == null){
System.out.println("Problem does not implement getIndividualTemplate, updateMaxPosDist could not infer dimensions");
return;
}
if (!(template instanceof ESIndividualDoubleData) && !(template instanceof InterfaceDataTypeDouble)){
System.out.println("Problem does not use ESIndividualDoubleData or InterfaceDataTypeDouble. UpdateMaxPosDist could not infer dimensions.");
return;
}
// ESIndividualDoubleData min = (ESIndividualDoubleData)template.clone();
// ESIndividualDoubleData max = (ESIndividualDoubleData)template.clone();
double[][] range = null;
if (template instanceof ESIndividualDoubleData) range = ((ESIndividualDoubleData)template).getDoubleRange();
else range = ((InterfaceDataTypeDouble)template).getDoubleRange();
double[] minValInDim = new double[range.length];
double[] maxValInDim = new double[range.length];
for (int i = 0; i < minValInDim.length; ++i){
minValInDim[i] = range[i][0]; // get lower boarder for dimension i
maxValInDim[i] = range[i][1]; // get upper boarder for dimension i
}
// min.SetDoubleGenotype(minValInDim); // set all dimensions to min
// max.SetDoubleGenotype(maxValInDim); // set all dimensions to max
this.maxPosDist = Mathematics.euclidianDist(minValInDim, maxValInDim);
}
// /**
// * Parametervalues of the optimizer may change over time
// */
// protected void updateParameters() {
// setInertnessOrChi(inertnessAging.getNewParameterValue(getInertnessOrChi(), getPopulation().getGeneration()));
// }
/**********************************************************************************************************************
* dist, mean, stddev, sum
*/
/** @tested junit
* returns the euclidean distance in the search space between indy1 and indy2.
* @param indy1
* @param indy2
* @return
*/
public double distance(AbstractEAIndividual indy1, AbstractEAIndividual indy2){
return EuclideanMetric.euclideanDistance(AbstractEAIndividual.getDoublePositionShallow(indy1),
AbstractEAIndividual.getDoublePositionShallow(indy2));
}
/** @tested junit
* returns the mean value for the provided data vec but only for a given number of values.
* If range > vec.size() the mean is computed only for the available data.
* @param vec
* @param range number of values (beginning at the end of vec!) considered to compute the mean
* @return
*/
protected static double mean(Vector<Double> vec,int range){
if (vec.size() < range) range = vec.size();
double sum = 0;
for (int i = vec.size()-range; i < vec.size(); ++i){
sum += vec.get(i).doubleValue();
}
return sum/range;
}
/** @tested junit
* returns the std deviation for the provided data vec but only for a given number of values
* @param vec data
* @param range number of values (beginning at the end of vec!) considered to compute the std deviation
* @return
*/
public static double stdDev(Vector<Double> vec, int range){
double ssum = 0;
if (vec.size()-range < 0 || range < 2) return Double.POSITIVE_INFINITY; // not enough values, dont risk early convergence
double mean = mean(vec,range);
for (int i = vec.size()-range; i < vec.size(); ++i){
ssum += Math.pow(vec.get(i).doubleValue()-mean,2);
}
double result = Math.sqrt(ssum/(range-1));
return result;
}
private static double sum(double[] fitness) {
double ret = 0.;
for(double d : fitness){
ret += d;
}
return ret;
}
/** @tested ps
* Interpretes the given maximal radius as normalised according to the current search space.
* Values from [0,1], 1 means the radius can be as large as the maximal possible distance
* (between any two points) in the search space.
* Because the swarmradius and distances (e.g. in merging and absortion) are given in a standard euclidean metric,
* this function converts the normalised distance into the standard euclidean distance.
* @param normalisedRadius
* @return
*/
public double interpreteAsNormalisedSwarmRadius(double normalisedRadius){
if(normalisedRadius > 1 || normalisedRadius < 0){
System.out.println("interpreteAsNormalisedSwarmRadius: Radius not normalised to [0,1]");
}
// compute standard euclidean radius from normalised radius:
return normalisedRadius*maxPosDist;
}
/**********************************************************************************************************************
* addNewParticlesToPopulation ...
*/
/** @tested junit ...
* adds new particles to this swarm, rndly inited over the search space by the problem
* @param particleIndices set of indices that should be used for the added particles, if null new indices are created
*/
private void addNewParticlesToPopulation(int[] particleIndices) {
if (particleIndices == null) throw new RuntimeException("Error, unable to use null index array (ParticleSubSwarmOptimization.addNewParticlesToPOpulation)");
Population tmp = new Population();
tmp.setTargetSize(particleIndices.length);
//////////////
AbstractOptimizationProblem prob = (AbstractOptimizationProblem)m_Problem;
AbstractEAIndividual template = prob.getIndividualTemplate(); // problem must be inited at this point
AbstractEAIndividual tmpIndy;
for (int i = 0; i < tmp.getTargetSize(); i++) {
tmpIndy = (AbstractEAIndividual)((AbstractEAIndividual)template).clone();
tmpIndy.init(prob);
tmp.add(tmpIndy);
}
tmp.init();
///////////
ParticleSubSwarmOptimization tmpopt = new ParticleSubSwarmOptimization();
tmpopt.SetProblem(this.m_Problem);
tmpopt.evaluatePopulation(tmp);
tmpopt.initByPopulation(tmp, false); // + size FCs
if (particleIndices != null){ // use given indices
for (int i = 0; i < tmpopt.getPopulation().size(); ++i){
AbstractEAIndividual indy = tmpopt.getPopulation().getEAIndividual(i);
indy.SetIndividualIndex(particleIndices[i]);//SetData("particleIndex", new Integer(particleIndices[i]));
indy.putData("newParticleFlag",new Boolean(true)); // for plotting
}
}
addPopulation(tmpopt); // add to the mainswarm (FCs will be considered)
populationSizeHasChanged();
}
/**********************************************************************************************************************
* add and remove functions that keep the function calls of the population "accurate"
* (here "accurate" applies to the situation where an added population is always deleted in the next step, like in merging...)
*/
/** @tested nn
* adds a population and its function calls to this.population
* @param pop
*/
public void addPopulation(ParticleSubSwarmOptimization pop){
addPopulation(pop.getPopulation());
}
/** @tested junit& ..
* adds a population and its function calls to this.population
* @param pop
*/
public void addPopulation(Population pop){
m_Population.addPopulation(pop);
// dont peculate the function calls from the added population (which is going to be deleted in NichePSO)
m_Population.incrFunctionCallsBy(pop.getFunctionCalls());
}
/** @tested nn
* adss an inidividual
* @param ind
* @return
*/
public boolean addIndividual(IndividualInterface ind) {
// nothing to do regarding function calls
// old calls were counted in old population new calls are now counted in this population
return m_Population.addIndividual(ind);
}
/** @tested nn
* @param o
* @return
*/
public boolean add(Object o) {
return addIndividual((IndividualInterface)o);
}
/** @tested nn
* adds indy to the swarm
* @param indy
*/
public void add(AbstractEAIndividual indy){
addIndividual(indy);
}
/** @tested nn
* removes an individual
* @param ind
*/
public boolean removeSubIndividual (IndividualInterface ind) {
return m_Population.removeMember(ind);
}
public void removeSubPopulation(Population pop, boolean allowMissing) { // this is very slow...
for (int i = 0; i < pop.size(); ++i){
AbstractEAIndividual indy = pop.getEAIndividual(i);
if (!removeSubIndividual(indy)) {
if (!allowMissing) {
throw new RuntimeException("Warning, assumed sub population was not contained (ParticleSubSwarmOptimization).");
}
}
}
}
/*
public void removeNIndividuals(int n) {
}
public void removeDoubleInstances() {
}
public void removeDoubleInstancesUsingFitness() {
}
public void removeIndexSwitched(int index) {
}*/
/**********************************************************************************************************************
* getter, setter
*/
/** @tested ps
* This method will set the problem that is to be optimized
* @param problem
*/
public void SetProblem (InterfaceOptimizationProblem problem) {
this.m_Problem = problem;
updateMaxPosDist();
}
/** @tested junit
* @return the maximal euclidean distance between the swarms gbest and any other particle in the swarm.
*/
public double getSwarmRadius(){
if (getPopulation().size() == 0 || getPopulation().size() == 1) return 0;
double max = Double.NEGATIVE_INFINITY;
//PhenotypeMetric metric = new PhenotypeMetric();
for (int i = 0; i < m_Population.size(); ++i){
AbstractEAIndividual indy = m_Population.getEAIndividual(i);
//double dist = metric.distance(m_BestIndividual, indy);
double sqrdDist = EuclideanMetric.squaredEuclideanDistance(AbstractEAIndividual.getDoublePositionShallow(m_BestIndividual),
AbstractEAIndividual.getDoublePositionShallow(indy));
//dist = distance(m_BestIndividual, indy);
if (sqrdDist > max){
max = sqrdDist;
}
}
return Math.sqrt(max);
}
/** @tested ps
* returns the maximal distance between the gbest position and any individual in the swarm
* this distance is not allowed to exceed a given threshold
* @return
*/
public double getBoundSwarmRadius(){
// convert the normalised (i.e. relative) maxrad to a standard euclidean (i.e. absolute) maxrad
double maxAllowedSwarmRadiusAbs = getMaxAllowedSwarmRadiusAbs();
// only compare (absolute) euclidean distances
return Math.min(getSwarmRadius(), maxAllowedSwarmRadiusAbs);
}
public double getMaxAllowedSwarmRadiusAbs() {
// convert the normalised (i.e. relative) maxrad to a standard euclidean (i.e. absolute) maxrad
return interpreteAsNormalisedSwarmRadius(maxAllowedSwarmRadiusNormal);
}
/**
* @return the average distance a particle has to its neighbor
*/
public double getAveDistToNeighbor() {
Population pop = getPopulation();
double sum = 0;
for (int i = 0; i < pop.size(); ++i){
AbstractEAIndividual indy = pop.getEAIndividual(i);
AbstractEAIndividual neigbor = getMemberNeighbor(indy);
if (neigbor == null) return -1;
sum += distance(indy, neigbor);
}
return sum/(double)pop.size();
}
/**
* @return a measure for the diversity of the swarm
*/
public double getEuclideanDiversity(){
double meanDistanceFromGBestPos = 0;
AbstractEAIndividual gbest = getGBestIndividual();
for (int i = 0; i < getPopulation().size(); ++i){
AbstractEAIndividual indy = getPopulation().getEAIndividual(i);
meanDistanceFromGBestPos += distance(gbest, indy);
}
meanDistanceFromGBestPos = meanDistanceFromGBestPos/(double)getPopulation().size();
return meanDistanceFromGBestPos;
}
/** @tested nn
* binds the swarmradius to the given normalised value
* (f.e. 1 means, that the swarmradius is allowed to take the maximal possible range in the search space)
* @param maxAllowedSwarmRadius value from the intervall [0,1]
*/
public void SetMaxAllowedSwarmRadius(double maxAllowedSwarmRadius) {
this.maxAllowedSwarmRadiusNormal = maxAllowedSwarmRadius;
}
/** @tested nn
* @return
*/
public double getMaxAllowedSwarmRadius() {
return this.maxAllowedSwarmRadiusNormal;
}
/** @tested nn
* marks the swarm as active or inactive
* @param active
*/
public void SetActive(boolean active) {
this.active = active;
}
/** @tested nn
* @return
*/
public boolean isActive() {
return active;
}
// public InterfaceParameterAging getInertnessAging() {
// return inertnessAging;
// }
//
// /**
// * sets a strategy that changes the value of the inertness parameter during an optimization run
// * @param inertnessAging
// */
// public void setInertnessAging(InterfaceParameterAging inertnessAging) {
// this.inertnessAging = inertnessAging;
// }
/** @tested junit
* returns the particle with the minimal distance to indy
* @param indy particle should be from this swarm
* @return null if there is no neighbor else neighbor
*/
public AbstractEAIndividual getMemberNeighbor(AbstractEAIndividual indy){
if (getPopulation().size() == 0){
System.out.println("getNeighbor: swarm empty");
return null;
}
// check if there is at least a second particle...
if (getPopulation().size() == 1){
//System.out.println("getNeighbor: swarm too small, no neighbor available");
//return (AbstractEAIndividual)indy.clone(); // would conflict with constant size for overall population...
return null;
}
// get the neighbor...
int index = -1;
double mindist = Double.POSITIVE_INFINITY;
boolean found=false;
for (int i = 0; i < getPopulation().size(); ++i){
AbstractEAIndividual currentindy = getPopulation().getEAIndividual(i);
if (indy.getIndyID()!=currentindy.getIndyID()){ // dont compare particle to itself or a copy of itself
double dist = distance(indy,currentindy);
if (dist < mindist){
mindist = dist;
index = i;
}
} else found=true;
}
if (!found) System.err.println("getNeighbor: particle searching for neighbor is not part of the swarm");
return getPopulation().getEAIndividual(index);
}
public AbstractEAIndividual getGBestIndividual(){
return m_BestIndividual;
}
/**
* @param indyToExclude
* @return particle with worst personal best position in the swarm. The given particle is excluded.
*/
public AbstractEAIndividual getParticleWithWorstPBestButNot(AbstractEAIndividual indyToExclude) {
Population pop = getPopulation();
if (pop.size() < 2){
System.out.println("getParticleWithWorstPBestButNot: Population < 2 - returning null");
return null;
}
AbstractEAIndividual indyWithWorstPBest = pop.getEAIndividual(0);
if (indyWithWorstPBest == indyToExclude){
indyWithWorstPBest = pop.getEAIndividual(1);
}
AbstractEAIndividual worstPBest = (AbstractEAIndividual)indyWithWorstPBest.getData("PersonalBestKey");
for (int i = 0; i < pop.size(); ++i){
AbstractEAIndividual currentindy = pop.getEAIndividual(i);
AbstractEAIndividual currentpbest = (AbstractEAIndividual)currentindy.getData("PersonalBestKey");
if (currentindy!=indyToExclude && worstPBest.isDominating(currentpbest)){
indyWithWorstPBest = currentindy;
worstPBest = currentpbest;
}
}
return indyWithWorstPBest;
}
public int getFitnessArchiveSize() {
return fitnessArchiveSize;
}
public void setFitnessArchiveSize(int fitnessArchiveSize) {
this.fitnessArchiveSize = fitnessArchiveSize;
}
public String fitnessArchiveSizeTipText() {
return "The number of fitness values stored per individual for deactivation strategies.";
}
}

View File

@ -160,6 +160,7 @@ public class ParticleSwarmOptimization implements InterfaceOptimizer, java.io.Se
this.m_Phi2 = a.m_Phi2; this.m_Phi2 = a.m_Phi2;
this.m_InertnessOrChi = a.m_InertnessOrChi; this.m_InertnessOrChi = a.m_InertnessOrChi;
this.m_TopologyRange = a.m_TopologyRange; this.m_TopologyRange = a.m_TopologyRange;
this.paramControl = (ParameterControlManager) a.paramControl.clone();
//this.setCheckSpeedLimit(a.isCheckSpeedLimit()); //this.setCheckSpeedLimit(a.isCheckSpeedLimit());
} }

View File

@ -0,0 +1,275 @@
package eva2.server.go.strategies;
import eva2.tools.math.RNG;
import eva2.server.go.individuals.AbstractEAIndividual;
import eva2.server.go.populations.Population;
/**
* This extends the particle swarm optimization implementation
* so that the guaranteed global convergence pso can be used as suggested by
* Franz van den Bergh in "An Analysis of Particle Swarm Optimizers".
* In this modification the velocity of the global best particle is updated differently.
*/
public class ParticleSwarmOptimizationGCPSO extends ParticleSwarmOptimization {
// choosable parameters:
protected boolean gcpso;
protected int sc;
protected int fc;
protected double rhoIncreaseFactor;
protected double rhoDecreaseFactor;
// members updated via updateGCPSOMember:
protected int gbestParticleIndex = -1;
protected boolean gbestParticleHasChanged;
protected int numOfSuccesses;
protected int numOfFailures;
protected AbstractEAIndividual gbestParticle;
private double rho; //initial rho value can be chosen
protected int getAccelerationForGlobalBestParticleCounter = 0; // only for testing
/**********************************************************************************************************************
* ctors, inits
*/
/** @tested ps
* ctor - sets default values according to
* "An Analyis of Paricle Swarm Optimizers" by Franz van den Bergh
*/
public ParticleSwarmOptimizationGCPSO(){
setGcpso(true);
gbestParticleIndex = -1;
//gbestParticle
gbestParticleHasChanged = false;
numOfSuccesses = 0;
numOfFailures = 0;
setRho(1);
SetSc(15);
SetFc(5);
SetRhoIncreaseFactor(2.0);
SetRhoDecreaseFactor(0.5);
}
/** @tested ps
* @param a
*/
public ParticleSwarmOptimizationGCPSO(ParticleSwarmOptimizationGCPSO a){
super(a);
this.setGcpso(a.gcpso);
this.gbestParticleIndex = a.gbestParticleIndex;
if (a.gbestParticle != null){
this.gbestParticle = (AbstractEAIndividual)a.gbestParticle.clone();
double[] aFitness= (double[])a.gbestParticle.getData(partBestFitKey);
this.gbestParticle.putData(partBestFitKey, aFitness.clone());
}
this.gbestParticleHasChanged = a.gbestParticleHasChanged;
this.numOfSuccesses = a.numOfSuccesses;
this.numOfFailures = a.numOfFailures;
this.setRho(a.getRho());
this.SetSc(a.getSc());
this.SetFc(a.getFc());
this.SetRhoIncreaseFactor(a.getRhoIncreaseFactor());
this.SetRhoDecreaseFactor(a.getRhoDecreaseFactor());
}
/** This method returns a global info string
* @return description
*/
public static String globalInfo() {
return "Guaranteed Convergence Particle Swarm Optimiser (GCPSO) " +
"as proposed by F. van den Bergh.";
}
/**********************************************************************************************************************
* overwritten
*/
/** @tested
* (non-Javadoc) @see javaeva.server.go.strategies.ParticleSwarmOptimization#optimize()
*/
public void optimize() {
super.optimize(); //updatePopulation->updateIndividual->updateVelocity (s.u.)
updateGCPSOMember();
}
/** @tested junit&
* (non-Javadoc) @see javaeva.server.go.strategies.ParticleSwarmOptimization#updateVelocity(int, double[], double[], double[], double[], double[][])
* uses a special velocity update strategy for the gobal best particle.
*/
protected double[] updateVelocity(int index, double[] lastVelocity, double[] personalBestPos, double[] curPosition, double[] neighbourBestPos, double[][] range) {
double[] accel, curVelocity = new double[lastVelocity.length];
if (useAlternative) {
accel = getAccelerationAlternative(index, personalBestPos, neighbourBestPos, curPosition, range);
} else {
if (index == gbestParticleIndex && isGcpso()) accel = getAccelerationForGlobalBestParticle(personalBestPos, neighbourBestPos, curPosition, range);
else accel = getAcceleration(personalBestPos, neighbourBestPos, curPosition, range);
}
for (int i = 0; i < lastVelocity.length; i++) {
curVelocity[i] = this.m_InertnessOrChi * lastVelocity[i];
curVelocity[i] += accel[i];
}
return curVelocity;
}
/**********************************************************************************************************************
* GCPSO core
*/
/** @tested ps
* @return the acceleration component.
* Should only be called for the global best particle
* (i.e. the particle with the best personal best position)
*/
private double[] getAccelerationForGlobalBestParticle(
double[] personalBestPos, double[] neighbourBestPos,
double[] curPosition, double[][] range)
{
++getAccelerationForGlobalBestParticleCounter;
double[] accel = new double[curPosition.length];
for (int i = 0; i < personalBestPos.length; i++) {
// reset position to the global best position
accel[i] = -curPosition[i]+personalBestPos[i]; //pbestpos of gbestparticle is gbestpos
// random search around the global best position
accel[i] += getRho()*(1.0-2.0*RNG.randomDouble(0,1));
}
//System.out.println("rho: " +getVecNorm(accel));
//System.out.println("accel: " +getVecNorm(accel));
return accel;
}
/** @tested junit
* @return the index of the particle with the best personal best position
* (i.e. the index of the global best particle)
*/
protected int getIndexOfGlobalBestParticle() {
if (getPopulation().size() == 0){
System.out.println("getIndexOfGlobalBestParticle error: no particle in population");
return -1;
}
int index = 0;
double[] gbestFitness = (double[])getPopulation().getEAIndividual(0).getData(partBestFitKey);
for (int i = 1; i < getPopulation().size(); ++i){
AbstractEAIndividual indy = getPopulation().getEAIndividual(i);
double[] currentBestFitness = (double[])indy.getData(partBestFitKey);
if (AbstractEAIndividual.isDominatingFitness(currentBestFitness,gbestFitness)){
gbestFitness = currentBestFitness;
index = i;
}
}
return index;
}
/**********************************************************************************************************************
* updateGCPSOMember
*/
/** @tested junit
* updates: gbestParticleIndex,gbestParticleHasChanged,numOfSuccesses,numOfFailures,gbestParticle,rho
*/
protected void updateGCPSOMember() {
int index = getIndexOfGlobalBestParticle();
/** gbestParticleIndex,gbestParticleHasChanged */
// check if the gbestParticle changed in the last optimization loop
if (index != gbestParticleIndex)
{
gbestParticleHasChanged = true;
gbestParticleIndex = index;
} else gbestParticleHasChanged = false;
/** numOfSuccesses,numOfFailures */
// check if the gbestParticle improved over the last iteration
if (gbestParticle == null){ // no previous gbest on first call available
AbstractEAIndividual gbestParticleCurrent = (AbstractEAIndividual)getPopulation().getEAIndividual(gbestParticleIndex);
gbestParticle = (AbstractEAIndividual)gbestParticleCurrent.clone();
}
AbstractEAIndividual gbestParticleOld = gbestParticle;
double[] gbestParticleFitnessOld = (double[])gbestParticleOld.getData(partBestFitKey);
AbstractEAIndividual gbestParticleCurrent = (AbstractEAIndividual)getPopulation().getEAIndividual(gbestParticleIndex);
double[] gbestParticleFitnessCurrent = (double[])gbestParticleCurrent.getData(partBestFitKey);
// if (gbestParticleHasChanged && false){ // reset rho on change?
// numOfFailures = 0;
// numOfSuccesses = 0;
// setRho(1);
// } else {
if (AbstractEAIndividual.isDominatingFitnessNotEqual(gbestParticleFitnessCurrent,gbestParticleFitnessOld)){
++numOfSuccesses;
numOfFailures = 0;
} else{
++numOfFailures;
numOfSuccesses = 0;
}
// }
/** gbestParticle */
gbestParticle = (AbstractEAIndividual)gbestParticleCurrent.clone();
/** rho */
if (numOfSuccesses > getSc()) {
setRho(getRhoIncreaseFactor()*getRho());
//System.out.println("rho increased");
}
//System.out.println(getRhoIncreaseFactor());
if (numOfFailures > getFc()) {
setRho(getRhoDecreaseFactor()*getRho());
//System.out.println("rho decreased");
}
//System.out.println(getRhoDecreaseFactor());
}
/**********************************************************************************************************************
* getter, setter
*/
public void setGcpso(boolean gcpso) {
this.gcpso = gcpso;
}
public boolean isGcpso() {
return gcpso;
}
public String gcpsoTipText(){
return "deactivate to use the standard PSO by Kennedy and Eberhart";
}
public void SetSc(int sc) {
this.sc = sc;
}
public int getSc() {
return sc;
}
public void SetFc(int fc) {
this.fc = fc;
}
public int getFc() {
return fc;
}
public void SetRhoIncreaseFactor(double rhoIncreaseFactor) {
this.rhoIncreaseFactor = rhoIncreaseFactor;
}
public double getRhoIncreaseFactor() {
return rhoIncreaseFactor;
}
public void SetRhoDecreaseFactor(double rhoDecreaseFactor) {
this.rhoDecreaseFactor = rhoDecreaseFactor;
}
public double getRhoDecreaseFactor() {
return rhoDecreaseFactor;
}
public void setRho(double rho) {
this.rho = rho;
}
public String rhoTipText(){
return "controls the initial radius of a random search in an area surrounding the global best position of the swarm";
}
public double getRho() {
return rho;
}
}

View File

@ -0,0 +1,39 @@
package eva2.server.go.strategies;
import eva2.server.go.operators.paramcontrol.LinearParamAdaption;
import eva2.server.go.operators.paramcontrol.ParamAdaption;
public class StarANPSO extends ANPSO {
private int defaultEvalCnt=10000;
public StarANPSO() {
super();
NichePSO.starNPSO(this, defaultEvalCnt);
setMainSwarmAlgoType(getMainSwarm().getAlgoType().setSelectedTag("Inertness"));
getMainSwarm().setParameterControl(new ParamAdaption[]{new LinearParamAdaption("inertnessOrChi", 0.7, 0.2)});
// setMainSwarmInertness(new LinearParameterAging(0.7, 0.2, defaultEvalCnt/getMainSwarmSize()));
getMainSwarm().setPhi1(1.2);
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.
SetMainSwarmTopologyTag(3); //"Multi-Swarm" favors the formation of groups in the main swarm
setMainSwarmTopologyRange(2); // range for topologies like random, grid etc. (does not affect "Multi-Swarm")
setMaxInitialSubSwarmSize(0); // deactivate early reinits
}
// public void setEvaluationCount(int evalCnt) {
// setMainSwarmInertness(new LinearParameterAging(0.7, 0.2, evalCnt/getMainSwarmSize()));
// }
public StarANPSO(StarANPSO o) {
super(o);
this.defaultEvalCnt=o.defaultEvalCnt;
}
@Override
public String getName() {
return "Star-"+super.getName();
}
}