/*
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.pso3d;
import sim.util.Double3D;
import sim.util.MutableDouble3D;
/**
@author Ankur Desai and Joey Harrison
*/
public class Particle3D
{
private static final long serialVersionUID = 1;
double bestVal = 0;
MutableDouble3D bestPosition = new MutableDouble3D();
MutableDouble3D position = new MutableDouble3D();
MutableDouble3D velocity = new MutableDouble3D();
private PSO3D pso;
private Evaluatable3D fitnessFunction;
private int index; // this kludge is necessary because the particles are individually scheduled
public Particle3D()
{
super();
}
public Particle3D(double x, double y, double z, double vx, double vy, double vz, PSO3D pso, Evaluatable3D f, int index)
{
super();
this.position.setTo(x, y, z);
this.velocity.setTo(vx, vy, vz);
this.pso = pso;
this.fitnessFunction = f;
pso.space.setObjectLocation(this,new Double3D(position));
this.index = index;
}
public void updateBest(double currVal, double currX, double currY, double currZ)
{
if (currVal > bestVal)
{
bestVal = currVal;
bestPosition.setTo(currX, currY, currZ);
pso.updateBest(currVal, currX, currY, currZ);
}
}
public double getFitness()
{
return fitnessFunction.calcFitness(position.x,position.y,position.z);
}
public void stepUpdateFitness()
{
updateBest(getFitness(), position.x, position.y, position.z);
}
public void stepUpdateVelocity()
{
double x = position.x;
double y = position.y;
double z = position.z;
MutableDouble3D nBestPosition = new MutableDouble3D();
pso.getNeighborhoodBest(index, nBestPosition); // updates the location of nBestPos
// calc new velocity
// calc x component
double inertia = velocity.x;
double pDelta = bestPosition.x - x;
double nDelta = nBestPosition.x - x;
double gDelta = pso.bestPosition.x - x;
double pWeight = Math.random() + 0.4;
double nWeight = Math.random() + 0.4;
double gWeight = Math.random() + 0.4;
double vx = (0.9*inertia + pWeight*pDelta + nWeight*nDelta + gWeight*gDelta) / (1+pWeight+nWeight+gWeight);
// calc y component
inertia = velocity.y;
pDelta = bestPosition.y - y;
nDelta = nBestPosition.y - y;
gDelta = pso.bestPosition.y - y;
pWeight = Math.random() + 0.4;
nWeight = Math.random() + 0.4;
gWeight = Math.random() + 0.4;
double vy = (0.9*inertia + pWeight*pDelta + nWeight*nDelta + gWeight*gDelta) / (1+pWeight+nWeight+gWeight);
// calc z component
inertia = velocity.z;
pDelta = bestPosition.z - z;
nDelta= nBestPosition.z - z;
gDelta = pso.bestPosition.z - z;
pWeight = Math.random() + 0.4;
nWeight = Math.random() + 0.4;
gWeight = Math.random() + 0.4;
double vz = (0.9*inertia + pWeight*pDelta + nWeight*nDelta + gWeight*gDelta) / (1+pWeight+nWeight+gWeight);
vx *= pso.velocityScalar;
vy *= pso.velocityScalar;
vz *= pso.velocityScalar;
// update velocity
velocity.setTo(vx, vy, vz);
}
public void stepUpdatePosition()
{
position.addIn(velocity);
pso.space.setObjectLocation(this, new Double3D(position));
}
}