#region License Information /* HeuristicLab * Copyright (C) 2002-2010 Heuristic and Evolutionary Algorithms Laboratory (HEAL) * * This file is part of HeuristicLab. * * HeuristicLab 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 3 of the License, or * (at your option) any later version. * * HeuristicLab 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 HeuristicLab. If not, see . */ #endregion using System; using System.Collections.Generic; using HeuristicLab.Core; using HeuristicLab.Data; using HeuristicLab.Operators; using HeuristicLab.Parameters; using HeuristicLab.Persistence.Default.CompositeSerializers.Storable; using HeuristicLab.Common; namespace HeuristicLab.Algorithms.NSGA2 { /// /// FastNonDominatedSort as described in: Deb, Pratap, Agrawal and Meyarivan, "A Fast and Elitist Multiobjective /// Genetic Algorithm: NSGA-II", IEEE Transactions On Evolutionary Computation, Vol. 6, No. 2, April 2002 /// [Item("FastNonDominatedSort", @"FastNonDominatedSort as described in: Deb, Pratap, Agrawal and Meyarivan, ""A Fast and Elitist Multiobjective Genetic Algorithm: NSGA-II"", IEEE Transactions On Evolutionary Computation, Vol. 6, No. 2, April 2002")] [StorableClass] public class FastNonDominatedSort : SingleSuccessorOperator { private enum DominationResult { Dominates, IsDominated, IsNonDominated }; public IValueLookupParameter MaximizationParameter { get { return (IValueLookupParameter)Parameters["Maximization"]; } } public IScopeTreeLookupParameter QualitiesParameter { get { return (IScopeTreeLookupParameter)Parameters["Qualities"]; } } public IScopeTreeLookupParameter RankParameter { get { return (IScopeTreeLookupParameter)Parameters["Rank"]; } } [StorableConstructor] protected FastNonDominatedSort(bool deserializing) : base(deserializing) { } protected FastNonDominatedSort(FastNonDominatedSort original, Cloner cloner) : base(original, cloner) { } public FastNonDominatedSort() { Parameters.Add(new ValueLookupParameter("Maximization", "Whether each objective is maximization or minimization.")); Parameters.Add(new ScopeTreeLookupParameter("Qualities", "The qualities of a solution.", 1)); Parameters.Add(new ScopeTreeLookupParameter("Rank", "The rank of a solution.", 1)); } public override IOperation Apply() { BoolArray maximization = MaximizationParameter.ActualValue; ItemArray qualities = QualitiesParameter.ActualValue; if (qualities == null) throw new InvalidOperationException(Name + ": No qualities found."); IScope scope = ExecutionContext.Scope; int populationSize = scope.SubScopes.Count; List fronts = new List(); Dictionary> dominatedScopes = new Dictionary>(); int[] dominationCounter = new int[populationSize]; ItemArray rank = new ItemArray(populationSize); for (int pI = 0; pI < populationSize - 1; pI++) { IScope p = scope.SubScopes[pI]; if (!dominatedScopes.ContainsKey(p)) dominatedScopes[p] = new List(); for (int qI = pI + 1; qI < populationSize; qI++) { DominationResult test = Dominates(qualities[pI], qualities[qI], maximization); if (test == DominationResult.Dominates) { dominatedScopes[p].Add(qI); dominationCounter[qI] += 1; } else if (test == DominationResult.IsDominated) { dominationCounter[pI] += 1; if (!dominatedScopes.ContainsKey(scope.SubScopes[qI])) dominatedScopes.Add(scope.SubScopes[qI], new List()); dominatedScopes[scope.SubScopes[qI]].Add(pI); } if (pI == populationSize - 2 && qI == populationSize - 1 && dominationCounter[qI] == 0) { rank[qI] = new IntValue(0); AddToFront(scope.SubScopes[qI], fronts, 0); } } if (dominationCounter[pI] == 0) { rank[pI] = new IntValue(0); AddToFront(p, fronts, 0); } } int i = 0; while (i < fronts.Count && fronts[i].Count > 0) { ScopeList nextFront = new ScopeList(); foreach (IScope p in fronts[i]) { if (dominatedScopes.ContainsKey(p)) { for (int k = 0; k < dominatedScopes[p].Count; k++) { int dominatedScope = dominatedScopes[p][k]; dominationCounter[dominatedScope] -= 1; if (dominationCounter[dominatedScope] == 0) { rank[dominatedScope] = new IntValue(i + 1); nextFront.Add(scope.SubScopes[dominatedScope]); } } } } i += 1; fronts.Add(nextFront); } RankParameter.ActualValue = rank; scope.SubScopes.Clear(); for (i = 0; i < fronts.Count; i++) { Scope frontScope = new Scope("Front " + i); foreach (var p in fronts[i]) frontScope.SubScopes.Add(p); if (frontScope.SubScopes.Count > 0) scope.SubScopes.Add(frontScope); } return base.Apply(); } private DominationResult Dominates(DoubleArray left, DoubleArray right, BoolArray maximizations) { bool leftIsBetter = false, rightIsBetter = false; for (int i = 0; i < left.Length; i++) { if (IsDominated(left[i], right[i], maximizations[i])) rightIsBetter = true; else if (IsDominated(right[i], left[i], maximizations[i])) leftIsBetter = true; if (leftIsBetter && rightIsBetter) break; } if (leftIsBetter && !rightIsBetter) return DominationResult.Dominates; if (!leftIsBetter && rightIsBetter) return DominationResult.IsDominated; return DominationResult.IsNonDominated; } private bool IsDominated(double left, double right, bool maximization) { return maximization && left < right || !maximization && left > right; } private void AddToFront(IScope p, List fronts, int i) { if (i == fronts.Count) fronts.Add(new ScopeList()); fronts[i].Add(p); } public override IDeepCloneable Clone(Cloner cloner) { return new FastNonDominatedSort(this, cloner); } } }