/* Copyright 2009-2016 David Hadka * * This file is part of the MOEA Framework. * * The MOEA Framework 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. * * The MOEA Framework 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 Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the MOEA Framework. If not, see <http://www.gnu.org/licenses/>. */ package org.moeaframework.algorithm.pso; import org.moeaframework.core.PRNG; import org.moeaframework.core.Problem; import org.moeaframework.core.Solution; import org.moeaframework.core.comparator.CrowdingComparator; import org.moeaframework.core.comparator.ParetoDominanceComparator; import org.moeaframework.core.fitness.CrowdingDistanceFitnessEvaluator; import org.moeaframework.core.fitness.FitnessBasedArchive; import org.moeaframework.core.operator.real.PM; import org.moeaframework.core.variable.EncodingUtils; import org.moeaframework.core.variable.RealVariable; //NOTE: This implementation is derived from the original manuscripts and the //JMetal implementation. /** * Implementation of SMPSO, the speed-constrained multi-objective particle * swarm optimizer. * <p> * References: * <ol> * <li>Nebro, A. J., J. J. Durillo, J. Garcia-Nieto, and C. A. Coello Coello * (2009). SMPSO: A New PSO-based Metaheuristic for Multi-objective * Optimization. 2009 IEEE Symposium on Computational Intelligence in * Multi-Criteria Decision-Making, pp. 66-73. * <li>Durillo, J. J., J. Garc�a-Nieto, A. J. Nebro, C. A. Coello Coello, * F. Luna, and E. Alba (2009). Multi-Objective Particle Swarm * Optimizers: An Experimental Comparison. Evolutionary Multi-Criterion * Optimization, pp. 495-509. * </ol> */ public class SMPSO extends AbstractPSOAlgorithm { /** * The minimum velocity for each variable. */ private double[] minimumVelocity; /** * The maximum velocity for each varaible. */ private double[] maximumVelocity; public SMPSO(Problem problem, int swarmSize, int leaderSize, double mutationProbability, double distributionIndex) { super(problem, swarmSize, leaderSize, new CrowdingComparator(), new ParetoDominanceComparator(), new FitnessBasedArchive(new CrowdingDistanceFitnessEvaluator(), leaderSize), null, new PM(mutationProbability, distributionIndex)); // initialize the minimum and maximum velocities minimumVelocity = new double[problem.getNumberOfVariables()]; maximumVelocity = new double[problem.getNumberOfVariables()]; Solution prototypeSolution = problem.newSolution(); for (int i = 0; i < problem.getNumberOfVariables(); i++) { RealVariable variable = (RealVariable)prototypeSolution.getVariable(i); maximumVelocity[i] = (variable.getUpperBound() - variable.getLowerBound()) / 2.0; minimumVelocity[i] = -maximumVelocity[i]; } } @Override protected void updateVelocity(int i) { Solution particle = particles[i]; Solution localBestParticle = localBestParticles[i]; Solution leader = selectLeader(); double r1 = PRNG.nextDouble(); double r2 = PRNG.nextDouble(); double C1 = PRNG.nextDouble(1.5, 2.5); double C2 = PRNG.nextDouble(1.5, 2.5); double W = PRNG.nextDouble(0.1, 0.1); for (int j = 0; j < problem.getNumberOfVariables(); j++) { double particleValue = EncodingUtils.getReal(particle.getVariable(j)); double localBestValue = EncodingUtils.getReal(localBestParticle.getVariable(j)); double leaderValue = EncodingUtils.getReal(leader.getVariable(j)); double velocity = constrictionCoefficient(C1, C2) * (W * velocities[i][j] + C1*r1*(localBestValue - particleValue) + C2*r2*(leaderValue - particleValue)); if (velocity > maximumVelocity[j]) { velocity = maximumVelocity[j]; } else if (velocity < minimumVelocity[j]) { velocity = minimumVelocity[j]; } velocities[i][j] = velocity; } } /** * Returns the velocity constriction coefficient. * * @param c1 the velocity coefficient for the local best * @param c2 the velocity coefficient for the leader * @return the velocity constriction coefficient */ protected double constrictionCoefficient(double c1, double c2) { double rho = c1 + c2; if (rho <= 4) { return 1.0; } else { return 2.0 / (2.0 - rho - Math.sqrt(Math.pow(rho, 2.0) - 4.0 * rho)); } } @Override protected void mutate(int i) { // The SMPSO paper [1] states that mutation is applied 15% of the time, // but the JMetal implementation applies to every 6th particle. Should // the application of mutation be random instead? if (i % 6 == 0) { particles[i] = mutation.evolve(new Solution[] { particles[i] })[0]; } } }