/**
*
* This file is part of EvoSuite.
*
* EvoSuite 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.0 of the License, or
* (at your option) any later version.
*
* EvoSuite 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 Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with EvoSuite. If not, see <http://www.gnu.org/licenses/>.
*/
package org.evosuite.ga.metaheuristics.mosa;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.evosuite.ga.Chromosome;
import org.evosuite.ga.FitnessFunction;
import org.evosuite.ga.metaheuristics.mosa.comparators.MOSADominanceComparator;
/**
* This class ranks the test cases according to the
* the "PreferenceCriterion" defined for the MOSA algorithm
*
* @author Annibale Panichella, Fitsum M. Kifetew
*/
public class FastNonDominatedSorting<T extends Chromosome> implements Ranking<T> {
/**
* An array containing all the fronts found during the search
*/
private List<T>[] ranking_;
/**
* Set used to store the goals that are covered from a population being sorted
*/
private Map<FitnessFunction<T>, T> newCoveredGoals = new HashMap<FitnessFunction<T>, T>();
@SuppressWarnings("unchecked")
@Override
public void computeRankingAssignment(List<T> solutions, Set<FitnessFunction<T>> uncovered_goals) {
List<T>[] fronts = getNextNonDominatedFronts(solutions, uncovered_goals);
ranking_ = new ArrayList[fronts.length];
for (int i = 0; i < fronts.length; i++)
ranking_[i] = fronts[i];
}
/**
* This method ranks the remaining test cases using the traditional "Non-Dominated Sorting Algorithm"
* @param solutionSet set of test cases to rank with "Non-Dominated Sorting Algorithm"
* @param covered_goal set of goals
* @return the list of fronts according to the uncovered goals
*/
@SuppressWarnings("unchecked")
private List<T>[] getNextNonDominatedFronts(List<T> solutionSet, Set<FitnessFunction<T>> uncovered_goals) {
MOSADominanceComparator<T> criterion_ = new MOSADominanceComparator<T>(uncovered_goals);
List<T> solutionSet_ = solutionSet;
// dominateMe[i] contains the number of solutions dominating i
int[] dominateMe = new int[solutionSet_.size()];
// iDominate[k] contains the list of solutions dominated by k
List<Integer>[] iDominate = new List[solutionSet_.size()];
// front[i] contains the list of individuals belonging to the front i
List<Integer>[] front = new List[solutionSet_.size() + 1];
// flagDominate is an auxiliary encodings.variable
int flagDominate;
// Initialize the fronts
for (int i = 0; i < front.length; i++)
front[i] = new LinkedList<Integer>();
// Initialize distance
for (int p = 0; p < (solutionSet_.size()); p++) {
solutionSet.get(p).setDistance(Double.MAX_VALUE);
}
// -> Fast non dominated sorting algorithm
for (int p = 0; p < solutionSet_.size(); p++) {
// Initialize the list of individuals that i dominate and the number
// of individuals that dominate me
iDominate[p] = new LinkedList<Integer>();
dominateMe[p] = 0;
}
for (int p = 0; p < (solutionSet_.size() - 1); p++) {
// For all q individuals , calculate if p dominates q or vice versa
for (int q = p + 1; q < solutionSet_.size(); q++) {
flagDominate = criterion_.compare(solutionSet.get(p), solutionSet.get(q));
if (flagDominate == -1) {
iDominate[p].add(q);
dominateMe[q]++;
} else if (flagDominate == 1) {
iDominate[q].add(p);
dominateMe[p]++;
}
}
// If nobody dominates p, p belongs to the first front
}
for (int p = 0; p < solutionSet_.size(); p++) {
if (dominateMe[p] == 0) {
front[0].add(p);
solutionSet.get(p).setRank(1);
}
}
// Obtain the rest of fronts
int i = 0;
Iterator<Integer> it1, it2; // Iterators
while (front[i].size() != 0) {
i++;
it1 = front[i - 1].iterator();
while (it1.hasNext()) {
it2 = iDominate[it1.next()].iterator();
while (it2.hasNext()) {
int index = it2.next();
dominateMe[index]--;
if (dominateMe[index] == 0) {
front[i].add(index);
solutionSet_.get(index).setRank(i+1);
}
}
}
}
List<T>[] fronts = new ArrayList[i];
// 0,1,2,....,i-1 are front, then i fronts
for (int j = 0; j < i; j++) {
fronts[j] = new ArrayList<T>();
it1 = front[j].iterator();
while (it1.hasNext()) {
fronts[j].add(solutionSet.get(it1.next()));
}
}
return fronts;
} // Ranking
/* (non-Javadoc)
* @see org.evosuite.ga.metaheuristics.mosa.Ranking#getSubfront(int)
*/
public List<T> getSubfront(int rank) {
return ranking_[rank];
} // getSubFront
/* (non-Javadoc)
* @see org.evosuite.ga.metaheuristics.mosa.Ranking#getNumberOfSubfronts()
*/
public int getNumberOfSubfronts() {
return ranking_.length;
} // getNumberOfSubfronts
public Map<FitnessFunction<T>, T> getNewCoveredGoals() {
return newCoveredGoals;
}
} // Ranking