Index: /branches/2825-NSGA3/HeuristicLab.Algorithms.NSGA3/3.3/HeuristicLab.Algorithms.NSGA3-3.3.csproj
===================================================================
--- /branches/2825-NSGA3/HeuristicLab.Algorithms.NSGA3/3.3/HeuristicLab.Algorithms.NSGA3-3.3.csproj	(revision 17656)
+++ /branches/2825-NSGA3/HeuristicLab.Algorithms.NSGA3/3.3/HeuristicLab.Algorithms.NSGA3-3.3.csproj	(revision 17657)
@@ -69,4 +69,5 @@
       <Private>False</Private>
     </Reference>
+    <Reference Include="HeuristicLab.Operators-3.3, Version=3.3.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec" />
     <Reference Include="HeuristicLab.Optimization-3.3, Version=3.3.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL">
       <SpecificVersion>False</SpecificVersion>
@@ -112,4 +113,5 @@
     <Compile Include="Properties\AssemblyInfo.cs" />
     <Compile Include="ReferencePoint.cs" />
+    <Compile Include="SimulatedBinaryCrossover.cs" />
     <Compile Include="Solution.cs" />
     <Compile Include="Utility.cs" />
Index: /branches/2825-NSGA3/HeuristicLab.Algorithms.NSGA3/3.3/NSGA3.cs
===================================================================
--- /branches/2825-NSGA3/HeuristicLab.Algorithms.NSGA3/3.3/NSGA3.cs	(revision 17656)
+++ /branches/2825-NSGA3/HeuristicLab.Algorithms.NSGA3/3.3/NSGA3.cs	(revision 17657)
@@ -1,4 +1,5 @@
 ﻿using System;
 using System.Collections.Generic;
+using System.Diagnostics;
 using System.Linq;
 using System.Threading;
@@ -64,5 +65,6 @@
         private const string SetSeedRandomlyName = "SetSeedRandomly";
         private const string PopulationSizeName = "PopulationSize";
-        private const string CrossoverProbabilityName = "CrossOverProbability";
+        private const string CrossoverProbabilityName = "CrossoverProbability";
+        private const string CrossoverContiguityName = "CrossoverContiguity";
         private const string MutationProbabilityName = "MutationProbability";
         private const string MaximumGenerationsName = "MaximumGenerations";
@@ -98,4 +100,9 @@
         }
 
+        private IFixedValueParameter<DoubleValue> CrossoverContiguityParameter
+        {
+            get { return (IFixedValueParameter<DoubleValue>)Parameters[CrossoverContiguityName]; }
+        }
+
         private IFixedValueParameter<PercentValue> MutationProbabilityParameter
         {
@@ -124,4 +131,6 @@
 
         public PercentValue CrossoverProbability => CrossoverProbabilityParameter.Value;
+
+        public DoubleValue CrossoverContiguity => CrossoverContiguityParameter.Value;
 
         public PercentValue MutationProbability => MutationProbabilityParameter.Value;
@@ -159,6 +168,7 @@
             Parameters.Add(new FixedValueParameter<IntValue>(SeedName, "The random seed used to initialize the new pseudo random number generator.", new IntValue(0)));
             Parameters.Add(new FixedValueParameter<BoolValue>(SetSeedRandomlyName, "True if the random seed should be set to a random value, otherwise false.", new BoolValue(true)));
-            Parameters.Add(new FixedValueParameter<IntValue>(PopulationSizeName, "The size of the population of Individuals.", new IntValue(100)));
+            Parameters.Add(new FixedValueParameter<IntValue>(PopulationSizeName, "The size of the population of Individuals.", new IntValue(200)));
             Parameters.Add(new FixedValueParameter<PercentValue>(CrossoverProbabilityName, "The probability that the crossover operator is applied on two parents.", new PercentValue(0.9)));
+            Parameters.Add(new FixedValueParameter<DoubleValue>(CrossoverContiguityName, "The contiguity value for the Simulated Binary Crossover that specifies how close a child should be to its parents (larger value means closer). The value must be greater than or equal than 0. Typical values are in the range [2;5]."));
             Parameters.Add(new FixedValueParameter<PercentValue>(MutationProbabilityName, "The probability that the mutation operator is applied on a Individual.", new PercentValue(0.05)));
             Parameters.Add(new FixedValueParameter<IntValue>(MaximumGenerationsName, "The maximum number of generations which should be processed.", new IntValue(1000)));
@@ -195,6 +205,6 @@
 
             InitFields();
+            InitResults();
             InitReferencePoints();
-            InitResults();
             Analyze();
         }
@@ -218,8 +228,5 @@
                 RealVector randomRealVector = new RealVector(Problem.Encoding.Length, random, minBound, maxBound);
 
-                solutions.Add(new Solution(StorableConstructorFlag.Default)
-                {
-                    Chromosome = randomRealVector
-                });
+                solutions.Add(new Solution(randomRealVector));
                 solutions[i].Fitness = Evaluate(solutions[i].Chromosome);
             }
@@ -236,5 +243,5 @@
         private void InitResults()
         {
-            Results.Add(new Result(GeneratedReferencePointsResultName, "The initially generated reference points", Utility.ConvertToDoubleMatrix(ReferencePoints)));
+            Results.Add(new Result(GeneratedReferencePointsResultName, "The initially generated reference points", new DoubleMatrix()));
             Results.Add(new Result(CurrentFrontResultName, "The Pareto Front", new DoubleMatrix()));
         }
@@ -288,5 +295,5 @@
 
             // Do non-dominated sort
-            var qualities = Utility.ToFitnessMatrix(solutions);
+            var qualities = Utility.ToFitnessMatrix(rt);
             // compute the pareto fronts using the DominationCalculator and discard the qualities
             // part in the inner tuples
@@ -578,10 +585,38 @@
         private List<Solution> Recombine(List<Solution> solutions)
         {
-            throw new NotImplementedException();
+            List<Solution> childSolutions = new List<Solution>();
+
+            for (int i = 0; i < solutions.Count; i += 2)
+            {
+                int parentIndex1 = random.Next(solutions.Count);
+                int parentIndex2 = random.Next(solutions.Count);
+                // ensure that the parents are not the same object
+                if (parentIndex1 == parentIndex2) parentIndex2 = (parentIndex2 + 1) % solutions.Count;
+                var parent1 = solutions[parentIndex1];
+                var parent2 = solutions[parentIndex2];
+
+                // Do crossover with crossoverProbabilty == 1 in order to guarantee that a crossover happens
+                var children = SimulatedBinaryCrossover.Apply(random, Problem.Encoding.Bounds, parent1.Chromosome, parent2.Chromosome, 1);
+                Debug.Assert(children != null);
+
+                var child1 = new Solution(children.Item1);
+                var child2 = new Solution(children.Item2);
+                child1.Fitness = Evaluate(child1.Chromosome);
+                child2.Fitness = Evaluate(child1.Chromosome);
+
+                childSolutions.Add(child1);
+                childSolutions.Add(child2);
+            }
+
+            return childSolutions;
         }
 
         private List<Solution> Mutate(List<Solution> solutions)
         {
-            throw new NotImplementedException();
+            foreach (var solution in solutions)
+            {
+                UniformOnePositionManipulator.Apply(random, solution.Chromosome, Problem.Encoding.Bounds);
+            }
+            return solutions;
         }
 
Index: /branches/2825-NSGA3/HeuristicLab.Algorithms.NSGA3/3.3/Plugin.cs
===================================================================
--- /branches/2825-NSGA3/HeuristicLab.Algorithms.NSGA3/3.3/Plugin.cs	(revision 17656)
+++ /branches/2825-NSGA3/HeuristicLab.Algorithms.NSGA3/3.3/Plugin.cs	(revision 17657)
@@ -17,4 +17,5 @@
     [PluginDependency("HeuristicLab.Encodings.BinaryVectorEncoding", "3.3")]
     [PluginDependency("HeuristicLab.Encodings.RealVectorEncoding", "3.3")]
+    [PluginDependency("HeuristicLab.Operators", "3.3")]
     [PluginDependency("HeuristicLab.Optimization", "3.3")]
     [PluginDependency("HeuristicLab.Parameters", "3.3")]
Index: /branches/2825-NSGA3/HeuristicLab.Algorithms.NSGA3/3.3/SimulatedBinaryCrossover.cs
===================================================================
--- /branches/2825-NSGA3/HeuristicLab.Algorithms.NSGA3/3.3/SimulatedBinaryCrossover.cs	(revision 17657)
+++ /branches/2825-NSGA3/HeuristicLab.Algorithms.NSGA3/3.3/SimulatedBinaryCrossover.cs	(revision 17657)
@@ -0,0 +1,91 @@
+﻿using System;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.RealVectorEncoding;
+
+namespace HeuristicLab.Algorithms.NSGA3
+{
+    /*
+     * Implements the simulated binary crossover based on the Tsung Che Chiang's NSGA3 implementation.
+     * http://web.ntnu.edu.tw/~tcchiang/publications/nsga3cpp/nsga3cpp.htm
+     *
+     * The simulated binary crossover in HeuristicLab.Encodings.RealVectorEncoding/Crossovers/SimulatedBinaryCrossover.cs
+     * is insufficient for NSGA3, because the static Apply-method only returns 1 child.
+     */
+
+    public static class SimulatedBinaryCrossover
+    {
+        private const double EPSILON = 10e-6; // a tiny number that is greater than 0
+
+        public static Tuple<RealVector, RealVector> Apply(IRandom random, DoubleMatrix bounds, RealVector parent1, RealVector parent2, double crossoverProbability = 1.0, double eta = 30)
+        {
+            var child1 = new RealVector(parent1);
+            var child2 = new RealVector(parent2);
+
+            if (random.NextDouble() > crossoverProbability) return null;
+
+            for (int i = 0; i < child1.Length; i++)
+            {
+                if (random.NextDouble() > 0.5) continue; // these two variables are not crossovered
+                if (Math.Abs(parent1[i] - parent2[i]) < EPSILON) continue; // two values are the same
+
+                double y1 = Math.Min(parent1[i], parent2[i]);
+                double y2 = Math.Max(parent1[i], parent2[i]);
+
+                // todo: is this correct? test it with Encoding.Length != Number of objectives
+                double lb;
+                double ub;
+                if (bounds.Rows == 1)
+                {
+                    lb = bounds[0, 0];
+                    ub = bounds[0, 1];
+                }
+                else
+                {
+                    lb = bounds[i, 0];
+                    ub = bounds[i, 1];
+                }
+
+                double rand = random.NextDouble();
+
+                // child 1
+                double beta = 1.0 + (2.0 * (y1 - lb) / (y2 - y1));
+                double alpha = 2.0 - Math.Pow(beta, -(eta + 1.0));
+                double betaq = Get_Betaq(rand, alpha, eta);
+
+                child1[i] = 0.5 * ((y1 + y2) - betaq * (y2 - y1));
+
+                // child 2
+                beta = 1.0 + (2.0 * (ub - y2) / (y2 - y1));
+                alpha = 2.0 - Math.Pow(beta, -(eta + 1.0));
+                betaq = Get_Betaq(rand, alpha, eta);
+
+                child2[i] = 0.5 * ((y1 + y2) + betaq * (y2 - y1));
+
+                // boundary checking
+                child1[i] = Math.Min(ub, Math.Max(lb, child1[i]));
+                child2[i] = Math.Min(ub, Math.Max(lb, child2[i]));
+
+                if (random.NextDouble() <= 0.5)
+                {
+                    // swap values
+                    var tmp = child1[i];
+                    child1[i] = child2[i];
+                    child2[i] = tmp;
+                }
+            }
+
+            return Tuple.Create(child1, child2);
+        }
+
+        private static double Get_Betaq(double rand, double alpha, double eta)
+        {
+            double betaq;
+            if (rand <= (1.0 / alpha))
+                betaq = Math.Pow((rand * alpha), (1.0 / (eta + 1.0)));
+            else
+                betaq = Math.Pow((1.0 / (2.0 - rand * alpha)), (1.0 / (eta + 1.0)));
+            return betaq;
+        }
+    }
+}
Index: /branches/2825-NSGA3/HeuristicLab.Algorithms.NSGA3/3.3/Solution.cs
===================================================================
--- /branches/2825-NSGA3/HeuristicLab.Algorithms.NSGA3/3.3/Solution.cs	(revision 17656)
+++ /branches/2825-NSGA3/HeuristicLab.Algorithms.NSGA3/3.3/Solution.cs	(revision 17657)
@@ -3,10 +3,9 @@
 using HeuristicLab.Common;
 using HeuristicLab.Encodings.RealVectorEncoding;
-using HeuristicLab.Optimization;
 
 namespace HeuristicLab.Algorithms.NSGA3
 {
     [StorableType("D35C9D79-77DF-4CF3-AB44-FCCC00E44C5F")]
-    public class Solution : Individual, IDeepCloneable
+    public class Solution : IDeepCloneable
     {
         // Chromosome
@@ -16,26 +15,24 @@
         public double[] Fitness { get; set; }
 
-        public Solution(StorableConstructorFlag _) : base(_)
+        public Solution(RealVector chromosome)
         {
+            Chromosome = chromosome;
+        }
+
+        public Solution(Solution solution, Cloner cloner)
+        {
+            Chromosome = cloner.Clone(solution.Chromosome);
+            Fitness = new double[solution.Fitness.Length];
+            Array.Copy(solution.Fitness, Fitness, solution.Fitness.Length);
         }
 
         public IDeepCloneable Clone(Cloner cloner)
         {
-            throw new NotImplementedException();
+            return new Solution(this, cloner);
         }
 
         public object Clone()
         {
-            throw new NotImplementedException();
-        }
-
-        public override TEncoding GetEncoding<TEncoding>()
-        {
-            throw new NotImplementedException();
-        }
-
-        public override Individual Copy()
-        {
-            throw new NotImplementedException();
+            return new Cloner().Clone(this);
         }
     }
