// OMOPSO.java
//
// Author:
// Antonio J. Nebro <antonio@lcc.uma.es>
// Juan J. Durillo <durillo@lcc.uma.es>
//
// Copyright (c) 2011 Antonio J. Nebro, Juan J. Durillo
//
// This program 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 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 Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
package jmetal.metaheuristics.omopso;
import jmetal.core.*;
import jmetal.operators.mutation.Mutation;
import jmetal.util.Distance;
import jmetal.util.JMException;
import jmetal.util.NonDominatedSolutionList;
import jmetal.util.PseudoRandom;
import jmetal.util.archive.CrowdingArchive;
import jmetal.util.comparators.CrowdingDistanceComparator;
import jmetal.util.comparators.DominanceComparator;
import jmetal.util.comparators.EpsilonDominanceComparator;
import java.util.Comparator;
/**
* This class representing an asynchronous version of OMOPSO algorithm
*/
public class OMOPSO extends Algorithm {
/**
* Stores the number of particles_ used
*/
private int particlesSize_;
/**
* Stores the maximum size for the archive
*/
private int archiveSize_;
/**
* Stores the maximum number of iteration_
*/
private int maxIterations_;
/**
* Stores the current number of iteration_
*/
private int iteration_;
/**
* Stores the perturbation used by the non-uniform mutation
*/
private double perturbation_;
/**
* Stores the particles
*/
private SolutionSet particles_;
/**
* Stores the best_ solutions founds so far for each particles
*/
private Solution[] best_;
/**
* Stores the leaders_
*/
private CrowdingArchive leaders_ ;
/**
* Stores the epsilon-archive
*/
private NonDominatedSolutionList eArchive_;
/**
* Stores the speed_ of each particle
*/
private double [][] speed_;
/**
* Stores a comparator for checking dominance
*/
private Comparator dominance_;
/**
* Stores a comparator for crowding checking
*/
private Comparator crowdingDistanceComparator_;
/**
* Stores a <code>Distance</code> object
*/
private Distance distance_;
/**
* Stores a operator for uniform mutations
*/
private Operator uniformMutation_;
/**
* Stores a operator for non uniform mutations
*/
private Operator nonUniformMutation_;
/**
* eta_ value
*/
private double eta_ = 0.0075;
/**
* Constructor
* @param problem Problem to solve
*/
public OMOPSO(Problem problem) {
super (problem) ;
} // OMOPSO
/**
* Initialize all parameter of the algorithm
*/
public void initParams(){
particlesSize_ = ((Integer)getInputParameter("swarmSize")).intValue();
archiveSize_ = ((Integer)getInputParameter("archiveSize")).intValue();
maxIterations_ = ((Integer)getInputParameter("maxIterations")).intValue();
particles_ = new SolutionSet(particlesSize_);
best_ = new Solution[particlesSize_];
leaders_ = new CrowdingArchive(archiveSize_,problem_.getNumberOfObjectives());
eArchive_ = new NonDominatedSolutionList(new EpsilonDominanceComparator(eta_));
uniformMutation_ = (Mutation)operators_.get("uniformMutation") ;
nonUniformMutation_ = (Mutation)operators_.get("nonUniformMutation") ;
// Create the dominator for equadless and dominance
dominance_ = new DominanceComparator();
crowdingDistanceComparator_ = new CrowdingDistanceComparator();
distance_ = new Distance();
// Create the speed_ vector
speed_ = new double[particlesSize_][problem_.getNumberOfVariables()];
} // initParams
/**
* Update the spped of each particle
* @throws JMException
*/
private void computeSpeed() throws JMException{
double r1,r2,W,C1,C2;
Variable[] bestGlobal;
for (int i = 0; i < particlesSize_; i++){
Variable[] particle = particles_.get(i).getDecisionVariables();
Variable[] bestParticle = best_[i].getDecisionVariables();
//Select a global best_ for calculate the speed of particle i, bestGlobal
Solution one, two;
int pos1 = PseudoRandom.randInt(0,leaders_.size()-1);
int pos2 = PseudoRandom.randInt(0,leaders_.size()-1);
one = leaders_.get(pos1);
two = leaders_.get(pos2);
if (crowdingDistanceComparator_.compare(one,two) < 1)
bestGlobal = one.getDecisionVariables();
else
bestGlobal = two.getDecisionVariables();
//
//Params for velocity equation
r1 = PseudoRandom.randDouble();
r2 = PseudoRandom.randDouble();
C1 = PseudoRandom.randDouble(1.5,2.0);
C2 = PseudoRandom.randDouble(1.5,2.0);
W = PseudoRandom.randDouble(0.1,0.5);
//
for (int var = 0; var < particle.length; var++){
//Computing the velocity of this particle
speed_[i][var] = W * speed_[i][var] +
C1 * r1 * (bestParticle[var].getValue() -
particle[var].getValue()) +
C2 * r2 * (bestGlobal[var].getValue() -
particle[var].getValue());
}
}
} // computeSpeed
/**
* Update the position of each particle
* @throws JMException
*/
private void computeNewPositions() throws JMException{
for (int i = 0; i < particlesSize_; i++){
Variable[] particle = particles_.get(i).getDecisionVariables();
//particle.move(speed_[i]);
for (int var = 0; var < particle.length; var++){
particle[var].setValue(particle[var].getValue()+ speed_[i][var]);
if (particle[var].getValue() < problem_.getLowerLimit(var)){
particle[var].setValue(problem_.getLowerLimit(var));
speed_[i][var] = speed_[i][var] * -1.0;
}
if (particle[var].getValue() > problem_.getUpperLimit(var)){
particle[var].setValue(problem_.getUpperLimit(var));
speed_[i][var] = speed_[i][var] * -1.0;
}
}
}
} // computeNewPositions
/**
* Apply a mutation operator to all particles in the swarm
* @throws JMException
*/
private void mopsoMutation(int actualIteration, int totalIterations) throws JMException{
//There are three groups of particles_, the ones that are mutated with
//a non-uniform mutation operator, the ones that are mutated with a
//uniform mutation and the one that no are mutated
nonUniformMutation_.setParameter("currentIteration",actualIteration);
//*/
for (int i = 0; i < particles_.size();i++)
if (i % 3 == 0) { //particles_ mutated with a non-uniform mutation
nonUniformMutation_.execute(particles_.get(i));
} else if (i % 3 == 1) { //particles_ mutated with a uniform mutation operator
uniformMutation_.execute(particles_.get(i));
} else //particles_ without mutation
;
} // mopsoMutation
/**
* Runs of the OMOPSO algorithm.
* @return a <code>SolutionSet</code> that is a set of non dominated solutions
* as a result of the algorithm execution
* @throws JMException
*/
public SolutionSet execute() throws JMException, ClassNotFoundException {
initParams();
//->Step 1 (and 3) Create the initial population and evaluate
for (int i = 0; i < particlesSize_; i++){
Solution particle = new Solution(problem_);
problem_.evaluate(particle);
problem_.evaluateConstraints(particle);
particles_.add(particle);
}
//-> Step2. Initialize the speed_ of each particle to 0
for (int i = 0; i < particlesSize_; i++) {
for (int j = 0; j < problem_.getNumberOfVariables(); j++) {
speed_[i][j] = 0.0;
}
}
// Step4 and 5
for (int i = 0; i < particles_.size(); i++){
Solution particle = new Solution(particles_.get(i));
if (leaders_.add(particle)){
eArchive_.add(new Solution(particle));
}
}
//-> Step 6. Initialice the memory of each particle
for (int i = 0; i < particles_.size(); i++){
Solution particle = new Solution(particles_.get(i));
best_[i] = particle;
}
//Crowding the leaders_
distance_.crowdingDistanceAssignment(leaders_,problem_.getNumberOfObjectives());
//-> Step 7. Iterations ..
while (iteration_ < maxIterations_){
//Compute the speed_
computeSpeed();
//Compute the new positions for the particles_
computeNewPositions();
//Mutate the particles_
mopsoMutation(iteration_,maxIterations_);
//Evaluate the new particles_ in new positions
for (int i = 0; i < particles_.size(); i++){
Solution particle = particles_.get(i);
problem_.evaluate(particle);
problem_.evaluateConstraints(particle);
}
//Actualize the archive
for (int i = 0; i < particles_.size(); i++){
Solution particle = new Solution(particles_.get(i));
if (leaders_.add(particle)){
eArchive_.add(new Solution(particle));
}
}
//Actualize the memory of this particle
for (int i = 0; i < particles_.size();i++){
int flag = dominance_.compare(particles_.get(i),best_[i]);
if (flag != 1) { // the new particle is best_ than the older remeber
Solution particle = new Solution(particles_.get(i));
//this.best_.reemplace(i,particle);
best_[i] = particle;
}
}
//Crowding the leaders_
distance_.crowdingDistanceAssignment(leaders_,
problem_.getNumberOfObjectives());
iteration_++;
}
return this.leaders_;
//return eArchive_;
} // execute
/**
* Gets the leaders of the OMOPSO algorithm
*/
public SolutionSet getLeader(){
return leaders_;
} // getLeader
} // OMOPSO