
org.dishevelled.swarm.ParticleSwarmOptimizationAlgorithm Maven / Gradle / Ivy
/*
dsh-swarm Framework for particle swarm optimization algorithms.
Copyright (c) 2006-2012 held jointly by the individual authors.
This library is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 3 of the License, or (at
your option) any later version.
This library is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this library; if not, write to the Free Software Foundation,
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
> http://www.fsf.org/licensing/licenses/lgpl.html
> http://www.opensource.org/licenses/lgpl-license.php
*/
package org.dishevelled.swarm;
import java.util.Random;
import java.beans.PropertyChangeSupport;
import java.beans.PropertyChangeListener;
import javax.swing.event.EventListenerList;
/**
* Particle swarm optimization (PSO) algorithm function.
*
* @author Michael Heuer
* @version $Revision$ $Date$
*/
public final class ParticleSwarmOptimizationAlgorithm
{
/** Listener list. */
private final EventListenerList listenerList;
/** Property change support. */
private final PropertyChangeSupport propertyChangeSupport;
/** Source of randomness. */
private Random random;
/** Inertia weight. */
private double inertiaWeight;
/** Cognitive weight. */
private double cognitiveWeight;
/** Social weight. */
private double socialWeight;
/** Minimum position. */
private double minimumPosition;
/** Maximum position. */
private double maximumPosition;
/** Minimum velocity. */
private double minimumVelocity;
/** Maximum velocity. */
private double maximumVelocity;
/** Default inertia weight. */
public static final double DEFAULT_INERTIA_WEIGHT = 0.1d;
/** Default cognitive weight. */
public static final double DEFAULT_COGNITIVE_WEIGHT = 0.2d;
/** Default social weight. */
public static final double DEFAULT_SOCIAL_WEIGHT = 0.2d;
/** Default minimum position. */
public static final double DEFAULT_MINIMUM_POSITION = 0.0d;
/** Default maximum position. */
public static final double DEFAULT_MAXIMUM_POSITION = 1.0d;
/** Default minimum velocity. */
public static final double DEFAULT_MINIMUM_VELOCITY = -0.5d;
/** Default maximum velocity. */
public static final double DEFAULT_MAXIMUM_VELOCITY = 0.5d;
/**
* Create a new particle swarm optimization algorithm function
* with default parameters.
*/
public ParticleSwarmOptimizationAlgorithm()
{
listenerList = new EventListenerList();
propertyChangeSupport = new PropertyChangeSupport(this);
this.random = new Random();
this.inertiaWeight = DEFAULT_INERTIA_WEIGHT;
this.cognitiveWeight = DEFAULT_COGNITIVE_WEIGHT;
this.socialWeight = DEFAULT_SOCIAL_WEIGHT;
this.minimumPosition = DEFAULT_MINIMUM_POSITION;
this.maximumPosition = DEFAULT_MAXIMUM_POSITION;
this.minimumVelocity = DEFAULT_MINIMUM_VELOCITY;
this.maximumVelocity = DEFAULT_MAXIMUM_VELOCITY;
}
/**
* Optimize a particle swarm of the specified size over the specified
* number of dimensions given the specified exit strategy and fitness
* functions.
*
* Returns a 2D matrix of particle positions with the specified number
* of particles as rows and the specified number of dimensions as columns.
*
* @param particles number of particles, must be >= 1
* @param dimensions number of dimensions, must be >= 1
* @param exitStrategy exit strategy function, must not be null
* @param fitness fitness function, must not be null
* @return 2D matrix of particle positions with particles
* rows and dimensions
columns
*/
public ParticleSwarm optimize(final int particles,
final int dimensions,
final ExitStrategy exitStrategy,
final Fitness fitness)
{
if (exitStrategy == null)
{
throw new IllegalArgumentException("exitStrategy must not be null");
}
if (fitness == null)
{
throw new IllegalArgumentException("fitness must not be null");
}
ParticleSwarmImpl swarm = new ParticleSwarmImpl(particles, dimensions);
double range = Math.abs(maximumPosition - minimumPosition);
for (int particle = 0; particle < particles; particle++)
{
for (int dimension = 0; dimension < dimensions; dimension++)
{
double r = (random.nextDouble() * range) + minimumPosition;
swarm.setPosition(particle, dimension, r);
swarm.setFitness(particle, -1 * Double.MAX_VALUE);
}
}
int epoch = 0;
while (!exitStrategy.evaluate(swarm, epoch))
{
fireExitFailed(swarm, epoch);
for (int particle = 0; particle < particles; particle++)
{
for (int dimension = 0; dimension < dimensions; dimension++)
{
// eq. 1
//
// v (t + 1) = w * v (t) + n * r * (p - x (t)) + n * r * (p - x (t))
// i i 1 1 i i 2 2 best i
double r1 = random.nextDouble();
double r2 = random.nextDouble();
double x = swarm.getPosition(particle, dimension);
double v = swarm.getVelocity(particle, dimension);
double p = swarm.getCognitiveMemory(particle, dimension);
double s = swarm.getSocialMemory(dimension);
v = inertiaWeight * v + cognitiveWeight * r1 * (p - x) + socialWeight * r2 * (s - x);
v = Math.max(v, minimumVelocity);
v = Math.min(v, maximumVelocity);
swarm.setVelocity(particle, dimension, v);
fireVelocityCalculated(particle, dimension, v);
// eq. 2
//
// x (t + 1) = x (t) + v (t + 1)
// i i i
x = x + v;
x = Math.max(x, minimumPosition);
x = Math.min(x, maximumPosition);
swarm.setPosition(particle, dimension, x);
firePositionUpdated(particle, dimension, x);
}
double fx = fitness.score(swarm.getPosition(particle));
swarm.setFitness(particle, fx);
fireFitnessCalculated(particle, fx);
double fp = fitness.score(swarm.getCognitiveMemory(particle));
double fs = fitness.score(swarm.getSocialMemory());
if (fx > fp)
{
swarm.updateCognitiveMemory(particle);
//fireCognitiveMemoryUpdated(particle, dimension, x);
}
if (fx > fs)
{
swarm.updateSocialMemory(particle);
//fireSocialMemoryUpdated(particle, dimension, x);
}
}
epoch++;
}
fireExitSucceeded(swarm, epoch);
return swarm;
}
/**
* Return the source of randomness for this particle swarm optimization algorithm.
* The source of randomness will not be null.
*
* @return the source of randomness for this particle swarm optimization algorithm
*/
public Random getRandom()
{
return random;
}
/**
* Set the source of randomness for this particle swarm
* optimization algorithm to random
.
*
* This is a bound property.
*
* @param random source of randomness for this particle swarm
* optimization algorithm, must not be null
*/
public void setRandom(final Random random)
{
if (random == null)
{
throw new IllegalArgumentException("random must not be null");
}
Random oldRandom = this.random;
this.random = random;
propertyChangeSupport.firePropertyChange("random", oldRandom, this.random);
}
/**
* Return the inertia weight for this particle swarm optimization algorithm.
* Defaults to 0.1d
.
*
* @see #DEFAULT_INERTIA_WEIGHT
* @return the inertia weight for this particle swarm optimization algorithm
*/
public double getInertiaWeight()
{
return inertiaWeight;
}
/**
* Set the inertia weight for this particle swarm optimization algorithm to inertiaWeight
.
*
* This is a bound property.
*
* @param inertiaWeight inertia weight for this particle swarm optimization algorithm
*/
public void setInertiaWeight(final double inertiaWeight)
{
double oldInertiaWeight = this.inertiaWeight;
this.inertiaWeight = inertiaWeight;
propertyChangeSupport.firePropertyChange("inertiaWeight", oldInertiaWeight, this.inertiaWeight);
}
/**
* Return the cognitive weight for this particle swarm optimization algorithm.
* Defaults to 0.2d
.
*
* @see #DEFAULT_COGNITIVE_WEIGHT
* @return the cognitive weight for this particle swarm optimization algorithm
*/
public double getCognitiveWeight()
{
return cognitiveWeight;
}
/**
* Set the cognitive weight for this particle swarm optimization algorithm to cognitiveWeight
.
*
* This is a bound property.
*
* @param cognitiveWeight cognitive weight for this particle swarm optimization algorithm
*/
public void setCognitiveWeight(final double cognitiveWeight)
{
double oldCognitiveWeight = this.cognitiveWeight;
this.cognitiveWeight = cognitiveWeight;
propertyChangeSupport.firePropertyChange("cognitiveWeight", oldCognitiveWeight, this.cognitiveWeight);
}
/**
* Return the social weight for this particle swarm optimization algorithm.
* Defaults to 0.2d
.
*
* @see #DEFAULT_SOCIAL_WEIGHT
* @return the social weight for this particle swarm optimization algorithm
*/
public double getSocialWeight()
{
return socialWeight;
}
/**
* Set the social weight for this particle swarm optimization algorithm to socialWeight
.
*
* This is a bound property.
*
* @param socialWeight social weight for this particle swarm optimization algorithm
*/
public void setSocialWeight(final double socialWeight)
{
double oldSocialWeight = this.socialWeight;
this.socialWeight = socialWeight;
propertyChangeSupport.firePropertyChange("socialWeight", oldSocialWeight, this.socialWeight);
}
/**
* Return the minimum position for this particle swarm optimization algorithm.
* Defaults to 0.0d
.
*
* @see #DEFAULT_MINIMUM_POSITION
* @return the minimum position for this particle swarm optimization algorithm
*/
public double getMinimumPosition()
{
return minimumPosition;
}
/**
* Set the minimum position for this particle swarm optimization algorithm to minimumPosition
.
*
* This is a bound property.
*
* @param minimumPosition minimum position for this particle swarm optimization algorithm
*/
public void setMinimumPosition(final double minimumPosition)
{
double oldMinimumPosition = this.minimumPosition;
this.minimumPosition = minimumPosition;
propertyChangeSupport.firePropertyChange("minimumPosition", oldMinimumPosition, this.minimumPosition);
}
/**
* Return the maximum position for this particle swarm optimization algorithm.
* Defaults to 1.0d
.
*
* @see #DEFAULT_MAXIMUM_POSITION
* @return the maximum position for this particle swarm optimization algorithm
*/
public double getMaximumPosition()
{
return maximumPosition;
}
/**
* Set the maximum position for this particle swarm optimization algorithm to maximumPosition
.
*
* This is a bound property.
*
* @param maximumPosition maximum position for this particle swarm optimization algorithm
*/
public void setMaximumPosition(final double maximumPosition)
{
double oldMaximumPosition = this.maximumPosition;
this.maximumPosition = maximumPosition;
propertyChangeSupport.firePropertyChange("maximumPosition", oldMaximumPosition, this.maximumPosition);
}
/**
* Return the minimum velocity for this particle swarm optimization algorithm.
* Defaults to -0.5d
.
*
* @see #DEFAULT_MINIMUM_VELOCITY
* @return the minimum velocity for this particle swarm optimization algorithm
*/
public double getMinimumVelocity()
{
return minimumVelocity;
}
/**
* Set the minimum velocity for this particle swarm optimization algorithm to minimumVelocity
.
*
* This is a bound property.
*
* @param minimumVelocity maximum velocity for this particle swarm optimization algorithm
*/
public void setMinimumVelocity(final double minimumVelocity)
{
double oldMinimumVelocity = this.minimumVelocity;
this.minimumVelocity = minimumVelocity;
propertyChangeSupport.firePropertyChange("minimumVelocity", oldMinimumVelocity, this.minimumVelocity);
}
/**
* Return the maximum velocity for this particle swarm optimization algorithm.
* Defaults to Double.MAX_VALUE
.
*
* @see #DEFAULT_MAXIMUM_VELOCITY
* @return the maximum velocity for this particle swarm optimization algorithm
*/
public double getMaximumVelocity()
{
return maximumVelocity;
}
/**
* Set the maximum velocity for this particle swarm optimization algorithm to maximumVelocity
.
*
* This is a bound property.
*
* @param maximumVelocity maximum velocity for this particle swarm optimization algorithm
*/
public void setMaximumVelocity(final double maximumVelocity)
{
double oldMaximumVelocity = this.maximumVelocity;
this.maximumVelocity = maximumVelocity;
propertyChangeSupport.firePropertyChange("maximumVelocity", oldMaximumVelocity, this.maximumVelocity);
}
/**
* Add the specified particle swarm optimization algorithm listener.
*
* @param l particle swarm optimization algorithm listener to add
*/
public void addParticleSwarmOptimizationAlgorithmListener(final ParticleSwarmOptimizationAlgorithmListener l)
{
listenerList.add(ParticleSwarmOptimizationAlgorithmListener.class, l);
}
/**
* Remove the specified particle swarm optimization algorithm listener.
*
* @param l particle swarm optimization algorithm listener to add
*/
public void removeParticleSwarmOptimizationAlgorithmListener(final ParticleSwarmOptimizationAlgorithmListener l)
{
listenerList.remove(ParticleSwarmOptimizationAlgorithmListener.class, l);
}
/**
* Return the number of particle swarm optimization algorithm listeners registered to this
* particle swarm optimization algorithm.
*
* @return the number of particle swarm optimization algorithm listeners registered to this
* particle swarm optimization algorithm
*/
public int getParticleSwarmOptimizationAlgorithmListenerCount()
{
return listenerList.getListenerCount(ParticleSwarmOptimizationAlgorithmListener.class);
}
/**
* Return an array of particle swarm optimization algorithm listeners registered to this particle
* swarm optimization algorithm. The returned array may be empty but will
* not be null.
*
* @return an array of particle swarm optimization algorithm listeners registered to this particle
* swarm optimization algorithm
*/
public ParticleSwarmOptimizationAlgorithmListener[] getParticleSwarmOptimizationAlgorithmListeners()
{
return (ParticleSwarmOptimizationAlgorithmListener[])
listenerList.getListeners(ParticleSwarmOptimizationAlgorithmListener.class);
}
/**
* Add a property change listener to this particle swarm optimization algorithm.
* The listener is registered for all properties.
*
* @param listener property change listener to add
*/
public void addPropertyChangeListener(final PropertyChangeListener listener)
{
propertyChangeSupport.addPropertyChangeListener(listener);
}
/**
* Add a property change listener for the specified property
* to this particle swarm optimization algorithm. The listener will be invoked only when a call
* on firePropertyChange names that specific property.
*
* @param propertyName specific property name
* @param listener property change listener to add
*/
public void addPropertyChangeListener(final String propertyName,
final PropertyChangeListener listener)
{
propertyChangeSupport.addPropertyChangeListener(propertyName, listener);
}
/**
* Remove a property change listener from this particle swarm optimization algorithm.
* This removes a listener that was registered for all properties.
*
* @param listener property change listener to remove
*/
public void removePropertyChangeListener(final PropertyChangeListener listener)
{
propertyChangeSupport.removePropertyChangeListener(listener);
}
/**
* Remove a property change listener for the specified property from
* this particle swarm optimization algorithm.
*
* @param propertyName specific property name
* @param listener property change listener to remove
*/
public void removePropertyChangeListener(final String propertyName,
final PropertyChangeListener listener)
{
propertyChangeSupport.removePropertyChangeListener(propertyName, listener);
}
/**
* Return the number of property change listeners registered to this
* particle swarm optimization algorithm.
*
* @return the number of property change listeners registered to this
* particle swarm optimization algorithm
*/
public int getPropertyChangeListenerCount()
{
return propertyChangeSupport.getPropertyChangeListeners().length;
}
/**
* Return the number of property change listeners registered to this
* particle swarm optimization algorithm for the specified property.
*
* @param propertyName property name
* @return the number of property change listeners registered to this
* particle swarm optimization algorithm for the specified property
*/
public int getPropertyChangeListenerCount(final String propertyName)
{
return propertyChangeSupport.getPropertyChangeListeners(propertyName).length;
}
/**
* Return an array of property change listeners registered to this particle
* swarm optimization algorithm. The returned array may be empty but will
* not be null.
*
* @return an array of property change listeners registered to this particle
* swarm optimization algorithm
*/
public PropertyChangeListener[] getPropertyChangeListeners()
{
return propertyChangeSupport.getPropertyChangeListeners();
}
/**
* Return an array of property change listeners registered to this particle
* swarm optimization algorithm for the specified property. The returned array
* may be empty but will not be null.
*
* @param propertyName property name
* @return an array of property change listeners registered to this particle
* swarm optimization algorithm
*/
public PropertyChangeListener[] getPropertyChangeListeners(final String propertyName)
{
return propertyChangeSupport.getPropertyChangeListeners(propertyName);
}
/**
* Fire an exit failed event to all registered listeners.
*
* @param swarm particle swarm, must not be null
* @param epoch epoch
*/
private void fireExitFailed(final ParticleSwarm swarm, final int epoch)
{
Object[] listeners = listenerList.getListenerList();
ParticleSwarmOptimizationAlgorithmEvent e = null;
for (int i = listeners.length - 2; i >= 0; i -= 2)
{
if (listeners[i] == ParticleSwarmOptimizationAlgorithmListener.class)
{
if (e == null)
{
e = new ParticleSwarmOptimizationAlgorithmEvent(this, swarm, epoch);
}
((ParticleSwarmOptimizationAlgorithmListener) listeners[i + 1]).exitFailed(e);
}
}
}
/**
* Fire an exit succeeded event to all registered listeners.
*
* @param swarm particle swarm, must not be null
* @param epoch epoch
*/
private void fireExitSucceeded(final ParticleSwarm swarm, final int epoch)
{
Object[] listeners = listenerList.getListenerList();
ParticleSwarmOptimizationAlgorithmEvent e = null;
for (int i = listeners.length - 2; i >= 0; i -= 2)
{
if (listeners[i] == ParticleSwarmOptimizationAlgorithmListener.class)
{
if (e == null)
{
e = new ParticleSwarmOptimizationAlgorithmEvent(this, swarm, epoch);
}
((ParticleSwarmOptimizationAlgorithmListener) listeners[i + 1]).exitSucceeded(e);
}
}
}
/**
* Fire a velocity calculated event to all registered listeners.
*
* @param particle particle
* @param dimension dimension
* @param velocity velocity
*/
private void fireVelocityCalculated(final int particle, final int dimension, final double velocity)
{
Object[] listeners = listenerList.getListenerList();
ParticleSwarmOptimizationAlgorithmEvent e = null;
for (int i = listeners.length - 2; i >= 0; i -= 2)
{
if (listeners[i] == ParticleSwarmOptimizationAlgorithmListener.class)
{
if (e == null)
{
e = new ParticleSwarmOptimizationAlgorithmEvent(this, particle, dimension, velocity);
}
((ParticleSwarmOptimizationAlgorithmListener) listeners[i + 1]).velocityCalculated(e);
}
}
}
/**
* Fire a position updated event to all registered listeners.
*
* @param particle particle
* @param dimension dimension
* @param position position
*/
private void firePositionUpdated(final int particle, final int dimension, final double position)
{
Object[] listeners = listenerList.getListenerList();
ParticleSwarmOptimizationAlgorithmEvent e = null;
for (int i = listeners.length - 2; i >= 0; i -= 2)
{
if (listeners[i] == ParticleSwarmOptimizationAlgorithmListener.class)
{
if (e == null)
{
e = new ParticleSwarmOptimizationAlgorithmEvent(this, particle, dimension, position);
}
((ParticleSwarmOptimizationAlgorithmListener) listeners[i + 1]).positionUpdated(e);
}
}
}
/**
* Fire a fitness calculated event to all registered listeners.
*
* @param particle particle
* @param fitness fitness
*/
private void fireFitnessCalculated(final int particle,
final double fitness)
{
Object[] listeners = listenerList.getListenerList();
ParticleSwarmOptimizationAlgorithmEvent e = null;
for (int i = listeners.length - 2; i >= 0; i -= 2)
{
if (listeners[i] == ParticleSwarmOptimizationAlgorithmListener.class)
{
if (e == null)
{
e = new ParticleSwarmOptimizationAlgorithmEvent(this, particle, 0, 0.0d, fitness);
}
((ParticleSwarmOptimizationAlgorithmListener) listeners[i + 1]).fitnessCalculated(e);
}
}
}
/**
* Fire a cognitive memory updated event to all registered listeners.
*
* @param particle particle
* @param dimension dimension
* @param position position
*/
private void fireCognitiveMemoryUpdated(final int particle, final int dimension, final double position)
{
Object[] listeners = listenerList.getListenerList();
ParticleSwarmOptimizationAlgorithmEvent e = null;
for (int i = listeners.length - 2; i >= 0; i -= 2)
{
if (listeners[i] == ParticleSwarmOptimizationAlgorithmListener.class)
{
if (e == null)
{
e = new ParticleSwarmOptimizationAlgorithmEvent(this, particle, dimension, position);
}
((ParticleSwarmOptimizationAlgorithmListener) listeners[i + 1]).cognitiveMemoryUpdated(e);
}
}
}
/**
* Fire a social memory updated event to all registered listeners.
*
* @param particle particle
* @param dimension dimension
* @param position position
*/
private void fireSocialMemoryUpdated(final int particle, final int dimension, final double position)
{
Object[] listeners = listenerList.getListenerList();
ParticleSwarmOptimizationAlgorithmEvent e = null;
for (int i = listeners.length - 2; i >= 0; i -= 2)
{
if (listeners[i] == ParticleSwarmOptimizationAlgorithmListener.class)
{
if (e == null)
{
e = new ParticleSwarmOptimizationAlgorithmEvent(this, particle, dimension, position);
}
((ParticleSwarmOptimizationAlgorithmListener) listeners[i + 1]).socialMemoryUpdated(e);
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy