From: Andrich <avw...@gm...> - 2009-07-02 13:11:10
|
Added a velocity update strategy for a Constriction PSO as well as its unit test. --- .../ConstrictionVelocityUpdate.java | 243 ++++++++++++++++++++ .../ConstrictionVelocityUpdateTest.java | 144 ++++++++++++ xml/constrictionPSO.xml | 57 +++++ 3 files changed, 444 insertions(+), 0 deletions(-) create mode 100644 src/main/java/net/sourceforge/cilib/pso/velocityupdatestrategies/ConstrictionVelocityUpdate.java create mode 100644 src/test/java/net/sourceforge/cilib/pso/velocityupdatestrategies/ConstrictionVelocityUpdateTest.java create mode 100644 xml/constrictionPSO.xml diff --git a/src/main/java/net/sourceforge/cilib/pso/velocityupdatestrategies/ConstrictionVelocityUpdate.java b/src/main/java/net/sourceforge/cilib/pso/velocityupdatestrategies/ConstrictionVelocityUpdate.java new file mode 100644 index 0000000..41d955b --- /dev/null +++ b/src/main/java/net/sourceforge/cilib/pso/velocityupdatestrategies/ConstrictionVelocityUpdate.java @@ -0,0 +1,243 @@ +/** + * Copyright (C) 2003 - 2009 + * Computational Intelligence Research Group (CIRG@UP) + * Department of Computer Science + * University of Pretoria + * South Africa + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package net.sourceforge.cilib.pso.velocityupdatestrategies; + +import net.sourceforge.cilib.controlparameter.ConstantControlParameter; +import net.sourceforge.cilib.controlparameter.ControlParameter; +import net.sourceforge.cilib.controlparameter.RandomizingControlParameter; +import net.sourceforge.cilib.entity.Particle; +import net.sourceforge.cilib.type.types.container.Vector; + +/** + * A velocity update strategy that utilizes the constriction coefficient as + * developed by Clerc. References: + * <ul> + * <li> + * Inproceedings (Clerc1999) + * Clerc, M. + * The swarm and the queen: towards a deterministic and adaptive particle swarm + * optimization + * Evolutionary Computation, 1999. CEC 99. Proceedings of the 1999 Congress on, + * 1999, 3, -1957 Vol. 3 + * </li> + * <li> + * Article (Clerc2002) + * Clerc, M. & Kennedy, J. + * The particle swarm - explosion, stability, and convergence in a + * multidimensional complex space Evolutionary Computation, + * IEEE Transactions on, 2002, 6, 58-73 + * </li> + * </ul> + * + * Note, this strategy does not the inertia control parameter. + * Certain constraints are imposed on the other control parameters in order to + * calculate the constriction coefficient, namely: + * $c1r1 + c2r2 \leq 4$ , and + * $\kappa \in [0, 1]$ + * + * @author andrich + */ +public class ConstrictionVelocityUpdate implements VelocityUpdateStrategy { + + protected ControlParameter socialAcceleration; + protected ControlParameter cognitiveAcceleration; + protected ControlParameter vMax; + protected ControlParameter kappa; + + /** + * Default constructor. The values given to the control parameters attempt to + * adhere to the constraints of calculating the constriction constant, but do not + * necessarily represent good values. + */ + public ConstrictionVelocityUpdate() { + socialAcceleration = new RandomizingControlParameter(); + cognitiveAcceleration = new RandomizingControlParameter(); + vMax = new ConstantControlParameter(); + kappa = new ConstantControlParameter(); + + socialAcceleration.setParameter(3.0); + cognitiveAcceleration.setParameter(3.0); + vMax.setParameter(Double.MAX_VALUE); + kappa.setParameter(0.1); + } + + /** + * Copy constructor. + * @param orig the ConstrictionVelocityUpdate to copy. + */ + public ConstrictionVelocityUpdate(ConstrictionVelocityUpdate orig) { + this.socialAcceleration = new RandomizingControlParameter((RandomizingControlParameter) orig.socialAcceleration); + this.cognitiveAcceleration = new RandomizingControlParameter((RandomizingControlParameter) orig.cognitiveAcceleration); + this.vMax = new ConstantControlParameter((ConstantControlParameter) orig.vMax); + this.kappa = new ConstantControlParameter((ConstantControlParameter) orig.kappa); + } + + /** + * {@inheritDoc } + */ + @Override + public VelocityUpdateStrategy getClone() { + return new ConstrictionVelocityUpdate(this); + } + + /** + * {@inheritDoc } + */ + @Override + public void updateVelocity(Particle particle) { + assertAccelerationConstraints(); + + Vector velocity = (Vector) particle.getVelocity(); + Vector position = (Vector) particle.getPosition(); + Vector bestPosition = (Vector) particle.getBestPosition(); + Vector nBestPosition = (Vector) particle.getNeighbourhoodBest().getBestPosition(); + + + for (int i = 0; i < particle.getDimension(); ++i) { + // calculate the constriction coefficient + double c1 = cognitiveAcceleration.getParameter(); + double c2 = socialAcceleration.getParameter(); + // c1r1 + c2r2 has to be greater or equal to 4 + while ((c1 + c2) < 4) { + c1 = cognitiveAcceleration.getParameter(); + c2 = socialAcceleration.getParameter(); + } + double phi = c1 + c2; + double constrictionCoefficient = (2 * kappa.getParameter()) / + Math.abs(2 - phi - Math.sqrt(phi * (phi - 4.0))); + + double value = velocity.getReal(i) + + (bestPosition.getReal(i) - position.getReal(i)) * c1 + + (nBestPosition.getReal(i) - position.getReal(i)) * c2; + value = constrictionCoefficient * value; + velocity.setReal(i, value); + + clamp(velocity, i); + } + } + + /** + * Clamp to maximum velocity. + * @param velocity The {@link Vector} to be clamped. + * @param i The dimension index to be clamped + */ + protected void clamp(Vector velocity, int i) { + // if vMax is not set (or set as max), it is unnecessary to clamp + if (Double.compare(vMax.getParameter(), Double.MAX_VALUE) == 0) { + return; + } + if (velocity.getReal(i) < -vMax.getParameter()) { + velocity.setReal(i, -vMax.getParameter()); + } else if (velocity.getReal(i) > vMax.getParameter()) { + velocity.setReal(i, vMax.getParameter()); + } + } + + /** + * {@inheritDoc } + */ + @Override + public void updateControlParameters(Particle particle) { + this.kappa.updateParameter(); + this.cognitiveAcceleration.updateParameter(); + this.socialAcceleration.updateParameter(); + this.vMax.updateParameter(); + } + + /** + * Ensure that values of c1 and c2 make it possible to calculate the + * constriction coefficient. + */ + private void assertAccelerationConstraints() { + double c1 = ((RandomizingControlParameter) cognitiveAcceleration).getControlParameter().getParameter(); + double c2 = ((RandomizingControlParameter) socialAcceleration).getControlParameter().getParameter(); + if (c1 + c2 < 4) { + throw new UnsupportedOperationException("Parameter constraint violation: " + + "The sum of the Cognitive (" + c1 + ") and Social (" + c2 + ") acceleration parameters " + + "has to be greater than or equal to 4."); + } + } + + /** + * Get the coginitive acceleration parameter. + * @return the cognitive acceleration {@link ControlParameter control parameter }. + */ + public ControlParameter getCognitiveAcceleration() { + return cognitiveAcceleration; + } + + /** + * Set the coginitive acceleration parameter. + * @param cognitiveAcceleration the new cognitive acceleration {@link ControlParameter control parameter }. + */ + public void setCognitiveAcceleration(ControlParameter cognitiveAcceleration) { + this.cognitiveAcceleration = cognitiveAcceleration; + } + + /** + * Get the Kappa control parameter. + * @return the kappa {@link ControlParameter control parameter }. + */ + public ControlParameter getKappa() { + return kappa; + } + + /** + * Set the Kappa control parameter. + * @param kappa the new kappa {@link ControlParameter control parameter }. + */ + public void setKappa(ControlParameter kappa) { + this.kappa = kappa; + } + + /** + * Get the social acceleration parameter. + * @return the social acceleration {@link ControlParameter control parameter }. + */ + public ControlParameter getSocialAcceleration() { + return socialAcceleration; + } + + /** + * Set the social acceleration parameter. + * @param socialAcceleration the new social accerelation {@link ControlParameter control parameter }. + */ + public void setSocialAcceleration(ControlParameter socialAcceleration) { + this.socialAcceleration = socialAcceleration; + } + + /** + * Get the maximum velocity parameter. + * @return the maximum velocity {@link ControlParameter control parameter }. + */ + public ControlParameter getVMax() { + return vMax; + } + + /** + * Set the maximum velocity parameter. + * @param vMax the new maximum velocity {@link ControlParameter control parameter }. + */ + public void setVMax(ControlParameter vMax) { + this.vMax = vMax; + } +} diff --git a/src/test/java/net/sourceforge/cilib/pso/velocityupdatestrategies/ConstrictionVelocityUpdateTest.java b/src/test/java/net/sourceforge/cilib/pso/velocityupdatestrategies/ConstrictionVelocityUpdateTest.java new file mode 100644 index 0000000..189cca9 --- /dev/null +++ b/src/test/java/net/sourceforge/cilib/pso/velocityupdatestrategies/ConstrictionVelocityUpdateTest.java @@ -0,0 +1,144 @@ +/** + * Copyright (C) 2003 - 2009 + * Computational Intelligence Research Group (CIRG@UP) + * Department of Computer Science + * University of Pretoria + * South Africa + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package net.sourceforge.cilib.pso.velocityupdatestrategies; + +import net.sourceforge.cilib.controlparameter.ConstantControlParameter; +import net.sourceforge.cilib.controlparameter.RandomizingControlParameter; +import net.sourceforge.cilib.functions.continuous.Spherical; +import net.sourceforge.cilib.math.Maths; +import net.sourceforge.cilib.math.random.generator.MersenneTwister; +import net.sourceforge.cilib.problem.FunctionMinimisationProblem; +import net.sourceforge.cilib.pso.particle.StandardParticle; +import net.sourceforge.cilib.type.types.Numeric; +import net.sourceforge.cilib.type.types.container.Vector; +import org.junit.Assert; +import org.junit.Test; + +/** + * Unit test for the constriction velocity update. + * @author andrich + */ +public class ConstrictionVelocityUpdateTest { + + /** + * Test cloning and implicetly the copy constructor. + */ + @Test + public void testClone() { + ConstrictionVelocityUpdate original = new ConstrictionVelocityUpdate(); + ConstrictionVelocityUpdate copy = (ConstrictionVelocityUpdate) original.getClone(); + + Assert.assertEquals(original.getKappa().getParameter(), copy.getKappa().getParameter(), Maths.EPSILON); + Assert.assertEquals(original.getVMax().getParameter(), copy.getVMax().getParameter(), Maths.EPSILON); + Assert.assertEquals(((RandomizingControlParameter)original.cognitiveAcceleration).getControlParameter().getParameter(), + ((RandomizingControlParameter)copy.cognitiveAcceleration).getControlParameter().getParameter(), Maths.EPSILON); + Assert.assertEquals(((RandomizingControlParameter)original.socialAcceleration).getControlParameter().getParameter(), + ((RandomizingControlParameter)copy.socialAcceleration).getControlParameter().getParameter(), Maths.EPSILON); + + copy.setKappa(new ConstantControlParameter(0.7)); + copy.setVMax(new ConstantControlParameter(0.7)); + RandomizingControlParameter randomizingControlParameter = new RandomizingControlParameter(); + randomizingControlParameter.setParameter(4.0); + copy.setSocialAcceleration(new RandomizingControlParameter(randomizingControlParameter.getClone())); + copy.setCognitiveAcceleration(new RandomizingControlParameter(randomizingControlParameter.getClone())); + + Assert.assertFalse(Double.compare(original.getKappa().getParameter(), copy.getKappa().getParameter()) == 0); + Assert.assertFalse(Double.compare(original.getVMax().getParameter(), copy.getVMax().getParameter()) == 0); + Assert.assertFalse(Double.compare(((RandomizingControlParameter)original.cognitiveAcceleration).getControlParameter().getParameter(), + ((RandomizingControlParameter)copy.cognitiveAcceleration).getControlParameter().getParameter()) == 0); + Assert.assertFalse(Double.compare(((RandomizingControlParameter)original.socialAcceleration).getControlParameter().getParameter(), + ((RandomizingControlParameter)copy.socialAcceleration).getControlParameter().getParameter()) == 0); + } + + /** + * Test the velocity update as well as the constraint assertion. + */ + @Test + public void testUpdateAndConstraintAssertion() { + MersenneTwister twister = new MersenneTwister(); + FunctionMinimisationProblem problem = new FunctionMinimisationProblem(); + problem.setFunction(new Spherical()); + + StandardParticle nBest = new StandardParticle(); + StandardParticle particle = new StandardParticle(); + particle.initialise(problem); + nBest.initialise(problem); + ((Vector)particle.getVelocity()).randomize(twister); + particle.setNeighbourhoodBest(nBest); + + ConstrictionVelocityUpdate constrictionVelocityUpdate = new ConstrictionVelocityUpdate(); + + boolean assertionExceptionOccured = false; + try { + constrictionVelocityUpdate.updateVelocity(particle); + } + catch(UnsupportedOperationException ex) { + assertionExceptionOccured = true; + } + + Assert.assertFalse(assertionExceptionOccured); + + RandomizingControlParameter randomizingControlParameter = new RandomizingControlParameter(); + randomizingControlParameter.setParameter(1.0); + constrictionVelocityUpdate.setSocialAcceleration(new RandomizingControlParameter(randomizingControlParameter.getClone())); + constrictionVelocityUpdate.setCognitiveAcceleration(new RandomizingControlParameter(randomizingControlParameter.getClone())); + + assertionExceptionOccured = false; + try { + constrictionVelocityUpdate.updateVelocity(particle); + } + catch(UnsupportedOperationException ex) { + assertionExceptionOccured = true; + } + + Assert.assertTrue(assertionExceptionOccured); + + } + + /** + * Test velocity clamping. + */ + @Test + public void testClamping() { + MersenneTwister twister = new MersenneTwister(); + FunctionMinimisationProblem problem = new FunctionMinimisationProblem(); + problem.setFunction(new Spherical()); + + StandardParticle nBest = new StandardParticle(); + StandardParticle particle = new StandardParticle(); + particle.initialise(problem); + nBest.initialise(problem); + ((Vector)particle.getVelocity()).randomize(twister); + particle.setNeighbourhoodBest(nBest); + + ConstrictionVelocityUpdate constrictionVelocityUpdate = new ConstrictionVelocityUpdate(); + constrictionVelocityUpdate.setVMax(new ConstantControlParameter(0.5)); + constrictionVelocityUpdate.updateVelocity(particle); + Vector velocity = particle.getVelocity(); + for (Numeric number : velocity) { + Assert.assertTrue(Double.compare(number.getReal(), 0.5) <= 0); + Assert.assertTrue(Double.compare(number.getReal(), -0.5) >= 0); + } + + } + +} diff --git a/xml/constrictionPSO.xml b/xml/constrictionPSO.xml new file mode 100644 index 0000000..77c3eb4 --- /dev/null +++ b/xml/constrictionPSO.xml @@ -0,0 +1,57 @@ +<?xml version="1.0"?> +<!DOCTYPE simulator [ +<!ATTLIST algorithm id ID #IMPLIED> +<!ATTLIST problem id ID #IMPLIED> +<!ATTLIST measurements id ID #IMPLIED> +]> +<simulator> + <algorithms> + <algorithm id="constrictionPSO" class="pso.PSO"> + <initialisationStrategy class="algorithm.initialisation.ClonedPopulationInitialisationStrategy"> + <entityType class="pso.particle.StandardParticle"> + <velocityUpdateStrategy class="pso.velocityupdatestrategies.ConstrictionVelocityUpdate"> + <kappa class="controlparameter.ConstantControlParameter" parameter="0.1" /> + <socialAcceleration class="controlparameter.RandomizingControlParameter" parameter="3.0" /> + <cognitiveAcceleration class="controlparameter.RandomizingControlParameter" parameter="3.0" /> + <!--vMax class="controlparameter.ConstantControlParameter" parameter="0.1" /--> + </velocityUpdateStrategy> + </entityType> + </initialisationStrategy> + <topology class="entity.topologies.GBestTopology"/> + <addStoppingCondition class="stoppingcondition.MaximumIterations" maximumIterations="1000"/> + </algorithm> + </algorithms> + + <problems> + <problem id="spherical" class="problem.FunctionMinimisationProblem"> + <function class="functions.continuous.Spherical"/> + </problem> + <problem id="rosenbrock" class="problem.FunctionMinimisationProblem"> + <function class="functions.continuous.Rosenbrock"/> + </problem> + <problem id="rastrigin" class="problem.FunctionMinimisationProblem"> + <function class="functions.continuous.unconstrained.Rastrigin"/> + </problem> + </problems> + + <measurements id="fitness" class="simulator.MeasurementSuite" resolution="10" samples="1"> + <addMeasurement class="measurement.single.Fitness"/> + </measurements> + <simulations> + <simulation> + <algorithm idref="constrictionPSO"/> + <problem idref="spherical"/> + <measurements idref="fitness" file="data/constrictionpso_spherical.txt"/> + </simulation> + <simulation> + <algorithm idref="constrictionPSO"/> + <problem idref="rosenbrock"/> + <measurements idref="fitness" file="data/constrictionpso_rosenbrock.txt"/> + </simulation> + <simulation> + <algorithm idref="constrictionPSO"/> + <problem idref="rastrigin"/> + <measurements idref="fitness" file="data/constrictionpso_rastrigin.txt"/> + </simulation> + </simulations> +</simulator> -- 1.6.0.4 |