/*
Copyright 2006 by Ankur Desai, Sean Luke, and George Mason University
Licensed under the Academic Free License version 3.0
See the file "LICENSE" for more information
*/
package sim.app.pso;
import ec.util.MersenneTwisterFast;
import sim.engine.Schedule;
import sim.engine.SimState;
import sim.engine.Steppable;
import sim.field.continuous.Continuous2D;
import sim.util.MutableDouble2D;
/**
@author Ankur Desai and Joey Harrison
*/
public class PSO extends SimState
{
private static final long serialVersionUID = 1;
public Continuous2D space;
public double width = 10.24;
public double height = 10.24;
public Particle[] particles;
int prevSuccessCount = -1;
// public modifier values
public int numParticles = 1000;
public int getNumParticles() { return numParticles; }
public void setNumParticles(int val) { if (val >= 0) numParticles = val; }
public int neighborhoodSize = 10;
public int getNeighborhoodSize() { return neighborhoodSize; }
public void setNeighborhoodSize(int val) { if ((val >= 0) && (val <= numParticles)) neighborhoodSize = val; }
public double initialVelocityRange = 1.0;
public double getInitialVelocityRange() { return initialVelocityRange; }
public void setInitialVelocityRange(double val) { if (val >= 0.0) initialVelocityRange = val; }
public double velocityScalar = 2.7;
public double getVelocityScalar() { return velocityScalar; }
public void setVelocityScalar(double val) { if (val >= 0.0) velocityScalar = val; }
public int fitnessFunction = 0;
public int getFitnessFunction() { return fitnessFunction; }
public void setFitnessFunction(int val) { fitnessFunction = val; }
public Object domFitnessFunction()
{
return new String[] { "Booth", "Rastrigin", "Griewangk", "Rosenbrock" };
}
private Evaluatable mapFitnessFunction(int val)
{
switch (val)
{
case 0: return new Booth();
case 1: return new Rastrigin();
case 2: return new Griewangk();
case 3: return new Rosenbrock();
}
return new Booth();
}
public double[] fitnessFunctionLowerBound =
{
920,
950,
998,
200
};
public double successThreshold = 1.0e-8;
public double getSuccessThreshold() { return successThreshold; }
public void setSuccessThreshold(double val) { if (val >= 0.0) successThreshold = val; }
public double bestVal = 0;
MutableDouble2D bestPosition = new MutableDouble2D();
public PSO(long seed)
{
super(seed);
}
public void updateBest(double currVal, double currX, double currY)
{
if (currVal > bestVal)
{
bestVal = currVal;
bestPosition.setTo(currX, currY);
}
}
public double getNeighborhoodBest(int index, MutableDouble2D pos)
{
double bv = Double.NEGATIVE_INFINITY;
Particle p;
int start = (index - neighborhoodSize / 2);
if (start < 0)
start += numParticles;
for (int i = 0; i < neighborhoodSize; i++)
{
p = particles[(start + i) % numParticles];
if (p.bestVal > bv)
{
bv = p.bestVal;
pos.setTo(p.bestPosition);
}
}
return 1.0;
}
public void start()
{
// reset the global best
bestVal = 0;
super.start();
particles = new Particle[numParticles];
space = new Continuous2D(height, width, height);
Evaluatable f = mapFitnessFunction(fitnessFunction);
for (int i = 0; i < numParticles; i++)
{
double x = (random.nextDouble() * width) - (width * 0.5);
double y = (random.nextDouble() * height) - (height * 0.5);
double vx = (random.nextDouble() * initialVelocityRange) - (initialVelocityRange * 0.5);
double vy = (random.nextDouble() * initialVelocityRange) - (initialVelocityRange * 0.5);
final Particle p = new Particle(x, y, vx, vy, this, f, i);
particles[i] = p;
schedule.scheduleRepeating(Schedule.EPOCH,1,new Steppable()
{
public void step(SimState state) { p.stepUpdateFitness(); }
});
schedule.scheduleRepeating(Schedule.EPOCH,2,new Steppable()
{
public void step(SimState state) { p.stepUpdateVelocity(); }
});
schedule.scheduleRepeating(Schedule.EPOCH,3,new Steppable()
{
public void step(SimState state) { p.stepUpdatePosition(); }
});
}
schedule.scheduleRepeating(Schedule.EPOCH, 4, new Steppable()
{
public void step(SimState state)
{
int successCount = 0;
for (int i = 0; i < space.allObjects.numObjs; i++)
{
Particle p = (Particle)space.allObjects.get(i);
if (Math.abs(p.getFitness() - 1000) <= successThreshold)
successCount++;
}
if (successCount != prevSuccessCount)
{
prevSuccessCount = successCount;
//System.out.println("SuccessCount = " + successCount);
if (successCount == numParticles)
state.kill();
}
}
});
}
public static void main(String[] args)
{
doLoop(PSO.class, args);
System.exit(0);
}
}