Index: trunk/sources/HeuristicLab.Algorithms.NSGA2/3.3/CrowdedComparisonSorter.cs
===================================================================
--- trunk/sources/HeuristicLab.Algorithms.NSGA2/3.3/CrowdedComparisonSorter.cs	(revision 4039)
+++ trunk/sources/HeuristicLab.Algorithms.NSGA2/3.3/CrowdedComparisonSorter.cs	(revision 4039)
@@ -0,0 +1,93 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2008 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 <http://www.gnu.org/licenses/>.
+ */
+#endregion
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using HeuristicLab.Core;
+using HeuristicLab.Common;
+using HeuristicLab.Data;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Operators;
+using HeuristicLab.Parameters;
+
+namespace HeuristicLab.Algorithms.NSGA2 {
+  /// <summary>
+  /// CrowdedComparisonSorter 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
+  /// </summary>
+  [Item("CrowdedComparisonSorter", @"CrowdedComparisonSorter 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 CrowdedComparisonSorter : SingleSuccessorOperator {
+
+    public IScopeTreeLookupParameter<IntValue> RankParameter {
+      get { return (IScopeTreeLookupParameter<IntValue>)Parameters["Rank"]; }
+    }
+
+    public IScopeTreeLookupParameter<DoubleValue> CrowdingDistanceParameter {
+      get { return (IScopeTreeLookupParameter<DoubleValue>)Parameters["CrowdingDistance"]; }
+    }
+
+    public CrowdedComparisonSorter() {
+      Parameters.Add(new ScopeTreeLookupParameter<IntValue>("Rank", "The rank of the solution."));
+      Parameters.Add(new ScopeTreeLookupParameter<DoubleValue>("CrowdingDistance", "The crowding distance of the solution."));
+    }
+
+    public override IOperation Apply() {
+      ItemArray<IntValue> ranks = RankParameter.ActualValue;
+      ItemArray<DoubleValue> distances = CrowdingDistanceParameter.ActualValue;
+      int size = ranks.Length;
+      int[] indices = Enumerable.Range(0, size).ToArray();
+
+      Array.Sort(indices, new CustomComparer(ranks, distances));
+      IScope[] scopes = ExecutionContext.Scope.SubScopes.ToArray();
+      Array.Sort(indices, scopes);
+      ExecutionContext.Scope.SubScopes.Clear();
+      ExecutionContext.Scope.SubScopes.AddRange(scopes);
+      return base.Apply();
+    }
+
+    private class CustomComparer : IComparer<int> {
+      ItemArray<IntValue> ranks;
+      ItemArray<DoubleValue> distances;
+
+      public CustomComparer(ItemArray<IntValue> ranks, ItemArray<DoubleValue> distances) {
+        this.ranks = ranks;
+        this.distances = distances;
+      }
+
+      #region IComparer<int> Members
+
+      public int Compare(int x, int y) {
+        if (ranks[x].Value < ranks[y].Value) return -1;
+        else if (ranks[x].Value > ranks[y].Value) return 1;
+        else { // ranks are the same -> compare by distance
+          if (distances[x].Value > distances[y].Value) return -1;
+          else if (distances[x].Value < distances[y].Value) return 1;
+          else return 0; // same distance
+        }
+      }
+
+      #endregion
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.Algorithms.NSGA2/3.3/FastNonDominatedSort.cs
===================================================================
--- trunk/sources/HeuristicLab.Algorithms.NSGA2/3.3/FastNonDominatedSort.cs	(revision 4039)
+++ trunk/sources/HeuristicLab.Algorithms.NSGA2/3.3/FastNonDominatedSort.cs	(revision 4039)
@@ -0,0 +1,159 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2008 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 <http://www.gnu.org/licenses/>.
+ */
+#endregion
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using HeuristicLab.Core;
+using HeuristicLab.Common;
+using HeuristicLab.Data;
+using HeuristicLab.Operators;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Parameters;
+
+namespace HeuristicLab.Algorithms.NSGA2 {
+  /// <summary>
+  /// 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
+  /// </summary>
+  [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<BoolArray> MaximizationsParameter {
+      get { return (IValueLookupParameter<BoolArray>)Parameters["Maximizations"]; }
+    }
+
+    public IScopeTreeLookupParameter<DoubleArray> QualitiesParameter {
+      get { return (IScopeTreeLookupParameter<DoubleArray>)Parameters["Qualities"]; }
+    }
+
+    public IScopeTreeLookupParameter<IntValue> RankParameter {
+      get { return (IScopeTreeLookupParameter<IntValue>)Parameters["Rank"]; }
+    }
+
+    public FastNonDominatedSort() {
+      Parameters.Add(new ValueLookupParameter<BoolArray>("Maximizations", "Whether each objective is maximization or minimization."));
+      Parameters.Add(new ScopeTreeLookupParameter<DoubleArray>("Qualities", "The qualities of a solution.", 1));
+      Parameters.Add(new ScopeTreeLookupParameter<IntValue>("Rank", "The rank of a solution.", 1));
+    }
+
+    public override IOperation Apply() {
+      BoolArray maximizations = MaximizationsParameter.ActualValue;
+      ItemArray<DoubleArray> qualities = QualitiesParameter.ActualValue;
+      if (qualities == null) throw new InvalidOperationException(Name + ": No qualities found.");
+
+      IScope scope = ExecutionContext.Scope;
+      int populationSize = scope.SubScopes.Count;
+
+      List<ScopeList> fronts = new List<ScopeList>();
+      Dictionary<IScope, List<int>> dominatedScopes = new Dictionary<IScope, List<int>>();
+      int[] dominationCounter = new int[populationSize];
+      ItemArray<IntValue> rank = new ItemArray<IntValue>(populationSize);
+
+      for (int pI = 0; pI < populationSize - 1; pI++) {
+        IScope p = scope.SubScopes[pI];
+        dominatedScopes[p] = new List<int>();
+        for (int qI = pI + 1; qI < populationSize; qI++) {
+          DominationResult test = Dominates(qualities[pI], qualities[qI], maximizations);
+          if (test == DominationResult.Dominates) {
+            dominatedScopes[p].Add(qI);
+            dominationCounter[qI] += 1;
+          } else if (test == DominationResult.IsDominated) {
+            dominationCounter[pI] += 1;
+            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]) {
+          for (int k = 0; k < dominatedScopes[p].Count; k++) {
+            int dominatedScope = dominatedScopes[p][k];
+            dominationCounter[k] -= 1;
+            if (dominationCounter[k] == 0) {
+              rank[k] = new IntValue(i + 1);
+              nextFront.Add(scope.SubScopes[k]);
+            }
+          }
+        }
+        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 Dominates(DoubleArray left, DoubleArray right, BoolArray maximizations) {
+      for (int i = 0; i < left.Length; i++) {
+        if (IsDominated(left[i], right[i], maximizations[i]))
+          return false;
+      }
+      return true;
+    }*/
+
+    private bool IsDominated(double left, double right, bool maximization) {
+      return maximization && left < right
+        || !maximization && left > right;
+    }
+
+    private void AddToFront(IScope p, List<ScopeList> fronts, int i) {
+      if (i == fronts.Count) fronts.Add(new ScopeList());
+      fronts[i].Add(p);
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.Algorithms.NSGA2/3.3/HeuristicLab.Algorithms.NSGA2-3.3.csproj
===================================================================
--- trunk/sources/HeuristicLab.Algorithms.NSGA2/3.3/HeuristicLab.Algorithms.NSGA2-3.3.csproj	(revision 4038)
+++ trunk/sources/HeuristicLab.Algorithms.NSGA2/3.3/HeuristicLab.Algorithms.NSGA2-3.3.csproj	(revision 4039)
@@ -76,5 +76,7 @@
     <None Include="HeuristicLab.snk" />
     <None Include="HeuristicLabAlgorithmsNSGA2Plugin.cs.frame" />
+    <Compile Include="CrowdedComparisonSorter.cs" />
     <Compile Include="CrowdingDistanceAssignment.cs" />
+    <Compile Include="FastNonDominatedSort.cs" />
     <Compile Include="HeuristicLabAlgorithmsNSGA2Plugin.cs" />
     <Compile Include="NSGA2.cs" />
