Index: /stable/HeuristicLab.Algorithms.NSGA2/3.3/NSGA2.cs
===================================================================
--- /stable/HeuristicLab.Algorithms.NSGA2/3.3/NSGA2.cs	(revision 12275)
+++ /stable/HeuristicLab.Algorithms.NSGA2/3.3/NSGA2.cs	(revision 12276)
@@ -88,4 +88,8 @@
       get { return (ValueParameter<IntValue>)Parameters["SelectedParents"]; }
     }
+
+    private IFixedValueParameter<BoolValue> DominateOnEqualQualitiesParameter {
+      get { return (IFixedValueParameter<BoolValue>)Parameters["DominateOnEqualQualities"]; }
+    }
     #endregion
 
@@ -135,4 +139,9 @@
       set { SelectedParentsParameter.Value = value; }
     }
+    public bool DominateOnEqualQualities {
+      get { return DominateOnEqualQualitiesParameter.Value.Value; }
+      set { DominateOnEqualQualitiesParameter.Value.Value = value; }
+    }
+
     private RandomCreator RandomCreator {
       get { return (RandomCreator)OperatorGraph.InitialOperator; }
@@ -171,4 +180,5 @@
       Parameters.Add(new ValueParameter<IntValue>("MaximumGenerations", "The maximum number of generations which should be processed.", new IntValue(1000)));
       Parameters.Add(new ValueParameter<IntValue>("SelectedParents", "Each two parents form a new child, typically this value should be twice the population size, but because the NSGA-II is maximally elitist it can be any multiple of 2 greater than 0.", new IntValue(200)));
+      Parameters.Add(new FixedValueParameter<BoolValue>("DominateOnEqualQualities", "Flag which determines wether solutions with equal quality values should be treated as dominated.", new BoolValue(false)));
 
       RandomCreator randomCreator = new RandomCreator();
@@ -195,4 +205,5 @@
       subScopesCounter.Successor = rankAndCrowdingSorter;
 
+      rankAndCrowdingSorter.DominateOnEqualQualitiesParameter.ActualName = DominateOnEqualQualitiesParameter.Name;
       rankAndCrowdingSorter.CrowdingDistanceParameter.ActualName = "CrowdingDistance";
       rankAndCrowdingSorter.RankParameter.ActualName = "Rank";
@@ -311,4 +322,10 @@
     [StorableHook(HookType.AfterDeserialization)]
     private void AfterDeserialization() {
+      // BackwardsCompatibility3.3
+      #region Backwards compatible code, remove with 3.4
+      if (!Parameters.ContainsKey("DominateOnEqualQualities"))
+        Parameters.Add(new FixedValueParameter<BoolValue>("DominateOnEqualQualities", "Flag which determines wether solutions with equal quality values should be treated as dominated.", new BoolValue(false)));
+      #endregion
+
       PopulationSizeParameter.ValueChanged += new EventHandler(PopulationSizeParameter_ValueChanged);
       PopulationSize.ValueChanged += new EventHandler(PopulationSize_ValueChanged);
Index: /stable/HeuristicLab.Algorithms.NSGA2/3.3/NSGA2MainLoop.cs
===================================================================
--- /stable/HeuristicLab.Algorithms.NSGA2/3.3/NSGA2MainLoop.cs	(revision 12275)
+++ /stable/HeuristicLab.Algorithms.NSGA2/3.3/NSGA2MainLoop.cs	(revision 12276)
@@ -79,8 +79,20 @@
       get { return (LookupParameter<IntValue>)Parameters["EvaluatedSolutions"]; }
     }
+    public IValueLookupParameter<BoolValue> DominateOnEqualQualitiesParameter {
+      get { return (ValueLookupParameter<BoolValue>)Parameters["DominateOnEqualQualities"]; }
+    }
     #endregion
 
     [StorableConstructor]
     protected NSGA2MainLoop(bool deserializing) : base(deserializing) { }
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      // BackwardsCompatibility3.3
+      #region Backwards compatible code, remove with 3.4
+      if (!Parameters.ContainsKey("DominateOnEqualQualities"))
+        Parameters.Add(new ValueLookupParameter<BoolValue>("DominateOnEqualQualities", "Flag which determines wether solutions with equal quality values should be treated as dominated."));
+      #endregion
+    }
+
     protected NSGA2MainLoop(NSGA2MainLoop original, Cloner cloner) : base(original, cloner) { }
     public NSGA2MainLoop()
@@ -105,4 +117,5 @@
       Parameters.Add(new ValueLookupParameter<IOperator>("Analyzer", "The operator used to analyze each generation."));
       Parameters.Add(new LookupParameter<IntValue>("EvaluatedSolutions", "The number of times solutions have been evaluated."));
+      Parameters.Add(new ValueLookupParameter<BoolValue>("DominateOnEqualQualities", "Flag which determines wether solutions with equal quality values should be treated as dominated."));
       #endregion
 
@@ -171,4 +184,5 @@
       subScopesCounter.ValueParameter.ActualName = EvaluatedSolutionsParameter.Name;
 
+      rankAndCrowdingSorter.DominateOnEqualQualitiesParameter.ActualName = DominateOnEqualQualitiesParameter.Name;
       rankAndCrowdingSorter.CrowdingDistanceParameter.ActualName = "CrowdingDistance";
       rankAndCrowdingSorter.RankParameter.ActualName = "Rank";
Index: /stable/HeuristicLab.Optimization.Operators/3.3/MultiObjective/FastNonDominatedSort.cs
===================================================================
--- /stable/HeuristicLab.Optimization.Operators/3.3/MultiObjective/FastNonDominatedSort.cs	(revision 12275)
+++ /stable/HeuristicLab.Optimization.Operators/3.3/MultiObjective/FastNonDominatedSort.cs	(revision 12276)
@@ -22,4 +22,5 @@
 using System;
 using System.Collections.Generic;
+using System.Linq;
 using HeuristicLab.Common;
 using HeuristicLab.Core;
@@ -40,15 +41,18 @@
     private enum DominationResult { Dominates, IsDominated, IsNonDominated };
 
+    #region Parameter properties
     public IValueLookupParameter<BoolArray> MaximizationParameter {
       get { return (IValueLookupParameter<BoolArray>)Parameters["Maximization"]; }
     }
-
+    public IValueLookupParameter<BoolValue> DominateOnEqualQualitiesParameter {
+      get { return (ValueLookupParameter<BoolValue>)Parameters["DominateOnEqualQualities"]; }
+    }
     public IScopeTreeLookupParameter<DoubleArray> QualitiesParameter {
       get { return (IScopeTreeLookupParameter<DoubleArray>)Parameters["Qualities"]; }
     }
-
     public IScopeTreeLookupParameter<IntValue> RankParameter {
       get { return (IScopeTreeLookupParameter<IntValue>)Parameters["Rank"]; }
     }
+    #endregion
 
     [StorableConstructor]
@@ -57,4 +61,5 @@
     public FastNonDominatedSort() {
       Parameters.Add(new ValueLookupParameter<BoolArray>("Maximization", "Whether each objective is maximization or minimization."));
+      Parameters.Add(new ValueLookupParameter<BoolValue>("DominateOnEqualQualities", "Flag which determines wether solutions with equal quality values should be treated as dominated."));
       Parameters.Add(new ScopeTreeLookupParameter<DoubleArray>("Qualities", "The qualities of a solution.", 1));
       Parameters.Add(new ScopeTreeLookupParameter<IntValue>("Rank", "The rank of a solution.", 1));
@@ -62,4 +67,5 @@
 
     public override IOperation Apply() {
+      bool dominateOnEqualQualities = DominateOnEqualQualitiesParameter.ActualValue.Value;
       BoolArray maximization = MaximizationParameter.ActualValue;
       ItemArray<DoubleArray> qualities = QualitiesParameter.ActualValue;
@@ -79,5 +85,5 @@
           dominatedScopes[p] = new List<int>();
         for (int qI = pI + 1; qI < populationSize; qI++) {
-          DominationResult test = Dominates(qualities[pI], qualities[qI], maximization);
+          DominationResult test = Dominates(qualities[pI], qualities[qI], maximization, dominateOnEqualQualities);
           if (test == DominationResult.Dominates) {
             dominatedScopes[p].Add(qI);
@@ -134,5 +140,7 @@
     }
 
-    private DominationResult Dominates(DoubleArray left, DoubleArray right, BoolArray maximizations) {
+    private static DominationResult Dominates(DoubleArray left, DoubleArray right, BoolArray maximizations, bool dominateOnEqualQualities) {
+      if (dominateOnEqualQualities && left.SequenceEqual(right)) return DominationResult.Dominates;
+
       bool leftIsBetter = false, rightIsBetter = false;
       for (int i = 0; i < left.Length; i++) {
@@ -141,4 +149,5 @@
         if (leftIsBetter && rightIsBetter) break;
       }
+
       if (leftIsBetter && !rightIsBetter) return DominationResult.Dominates;
       if (!leftIsBetter && rightIsBetter) return DominationResult.IsDominated;
@@ -146,10 +155,10 @@
     }
 
-    private bool IsDominated(double left, double right, bool maximization) {
+    private static 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) {
+    private static void AddToFront(IScope p, List<ScopeList> fronts, int i) {
       if (i == fronts.Count) fronts.Add(new ScopeList());
       fronts[i].Add(p);
@@ -159,4 +168,13 @@
       return new FastNonDominatedSort(this, cloner);
     }
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      // BackwardsCompatibility3.3
+      #region Backwards compatible code, remove with 3.4
+      if (!Parameters.ContainsKey("DominateOnEqualQualities"))
+        Parameters.Add(new ValueLookupParameter<BoolValue>("DominateOnEqualQualities", "Flag which determines wether solutions with equal quality values should be treated as dominated."));
+      #endregion
+    }
   }
 }
Index: /stable/HeuristicLab.Optimization.Operators/3.3/MultiObjective/RankAndCrowdingSorter.cs
===================================================================
--- /stable/HeuristicLab.Optimization.Operators/3.3/MultiObjective/RankAndCrowdingSorter.cs	(revision 12275)
+++ /stable/HeuristicLab.Optimization.Operators/3.3/MultiObjective/RankAndCrowdingSorter.cs	(revision 12276)
@@ -30,4 +30,5 @@
 namespace HeuristicLab.Optimization.Operators {
   public class RankAndCrowdingSorter : AlgorithmOperator, IMultiObjectiveOperator {
+    #region Parameter properties
     public ValueLookupParameter<BoolArray> MaximizationParameter {
       get { return (ValueLookupParameter<BoolArray>)Parameters["Maximization"]; }
@@ -42,4 +43,8 @@
       get { return (ScopeTreeLookupParameter<DoubleValue>)Parameters["CrowdingDistance"]; }
     }
+    public IValueLookupParameter<BoolValue> DominateOnEqualQualitiesParameter {
+      get { return (ValueLookupParameter<BoolValue>)Parameters["DominateOnEqualQualities"]; }
+    }
+    #endregion
 
     [StorableConstructor]
@@ -49,4 +54,5 @@
       : base() {
       Parameters.Add(new ValueLookupParameter<BoolArray>("Maximization", "For each objective a value that is true if that objective should be maximized, or false if it should be minimized."));
+      Parameters.Add(new ValueLookupParameter<BoolValue>("DominateOnEqualQualities", "Flag which determines wether solutions with equal quality values should be treated as dominated."));
       Parameters.Add(new ScopeTreeLookupParameter<DoubleArray>("Qualities", "The vector of quality values."));
       Parameters.Add(new ScopeTreeLookupParameter<IntValue>("Rank", "The rank of a solution (to which front it belongs)."));
@@ -60,4 +66,5 @@
 
       fastNonDominatedSort.MaximizationParameter.ActualName = MaximizationParameter.Name;
+      fastNonDominatedSort.DominateOnEqualQualitiesParameter.ActualName = DominateOnEqualQualitiesParameter.Name;
       fastNonDominatedSort.QualitiesParameter.ActualName = QualitiesParameter.Name;
       fastNonDominatedSort.RankParameter.ActualName = RankParameter.Name;
@@ -81,4 +88,13 @@
       return new RankAndCrowdingSorter(this, cloner);
     }
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      // BackwardsCompatibility3.3
+      #region Backwards compatible code, remove with 3.4
+      if (!Parameters.ContainsKey("DominateOnEqualQualities"))
+        Parameters.Add(new ValueLookupParameter<BoolValue>("DominateOnEqualQualities", "Flag which determines wether solutions with equal quality values should be treated as dominated."));
+      #endregion
+    }
   }
 }
