Adding NichePSO and ANPSO from the MModal branch (adaptation of M.Aschoffs implementations)
This commit is contained in:
parent
15cd21b8f1
commit
d557e86cd0
@ -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;
|
||||
}
|
||||
}
|
@ -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";
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -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";
|
||||
}
|
||||
}
|
@ -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();
|
||||
|
||||
}
|
@ -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.";
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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";
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -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";
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -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();
|
||||
}
|
@ -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";
|
||||
}
|
||||
|
||||
}
|
1092
src/eva2/server/go/strategies/ANPSO.java
Normal file
1092
src/eva2/server/go/strategies/ANPSO.java
Normal file
File diff suppressed because it is too large
Load Diff
130
src/eva2/server/go/strategies/NicheGraph.java
Normal file
130
src/eva2/server/go/strategies/NicheGraph.java
Normal 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;
|
||||
}
|
||||
|
||||
}
|
2199
src/eva2/server/go/strategies/NichePSO.java
Normal file
2199
src/eva2/server/go/strategies/NichePSO.java
Normal file
File diff suppressed because it is too large
Load Diff
754
src/eva2/server/go/strategies/ParticleSubSwarmOptimization.java
Normal file
754
src/eva2/server/go/strategies/ParticleSubSwarmOptimization.java
Normal 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.";
|
||||
}
|
||||
}
|
@ -160,6 +160,7 @@ public class ParticleSwarmOptimization implements InterfaceOptimizer, java.io.Se
|
||||
this.m_Phi2 = a.m_Phi2;
|
||||
this.m_InertnessOrChi = a.m_InertnessOrChi;
|
||||
this.m_TopologyRange = a.m_TopologyRange;
|
||||
this.paramControl = (ParameterControlManager) a.paramControl.clone();
|
||||
//this.setCheckSpeedLimit(a.isCheckSpeedLimit());
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
39
src/eva2/server/go/strategies/StarANPSO.java
Normal file
39
src/eva2/server/go/strategies/StarANPSO.java
Normal 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();
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user