Index: branches/2886_SymRegGrammarEnumeration/HeuristicLab.Algorithms.DataAnalysis.SymRegGrammarEnumeration/HeuristicLab.Algorithms.DataAnalysis.SymRegGrammarEnumeration.csproj
===================================================================
--- branches/2886_SymRegGrammarEnumeration/HeuristicLab.Algorithms.DataAnalysis.SymRegGrammarEnumeration/HeuristicLab.Algorithms.DataAnalysis.SymRegGrammarEnumeration.csproj	(revision 15927)
+++ branches/2886_SymRegGrammarEnumeration/HeuristicLab.Algorithms.DataAnalysis.SymRegGrammarEnumeration/HeuristicLab.Algorithms.DataAnalysis.SymRegGrammarEnumeration.csproj	(revision 15928)
@@ -119,4 +119,10 @@
     <Compile Include="GrammarEnumeration\SearchDataStructure.cs" />
     <Compile Include="GrammarEnumeration\Sentence.cs" />
+    <Compile Include="ProblemInstances\AircraftMaximumLift.cs" />
+    <Compile Include="ProblemInstances\FluidDynamics.cs" />
+    <Compile Include="ProblemInstances\PhysicsInstanceProvider.cs" />
+    <Compile Include="ProblemInstances\AircraftLift.cs" />
+    <Compile Include="ProblemInstances\RocketFuelFlow.cs" />
+    <Compile Include="ProblemInstances\ValueGenerator.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
     <Compile Include="GrammarEnumeration\Symbol.cs" />
@@ -126,4 +132,5 @@
     <None Include="Plugin.cs.frame" />
   </ItemGroup>
+  <ItemGroup />
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
   <PropertyGroup>
Index: branches/2886_SymRegGrammarEnumeration/HeuristicLab.Algorithms.DataAnalysis.SymRegGrammarEnumeration/ProblemInstances/AircraftLift.cs
===================================================================
--- branches/2886_SymRegGrammarEnumeration/HeuristicLab.Algorithms.DataAnalysis.SymRegGrammarEnumeration/ProblemInstances/AircraftLift.cs	(revision 15928)
+++ branches/2886_SymRegGrammarEnumeration/HeuristicLab.Algorithms.DataAnalysis.SymRegGrammarEnumeration/ProblemInstances/AircraftLift.cs	(revision 15928)
@@ -0,0 +1,64 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Problems.Instances.DataAnalysis;
+using HeuristicLab.Random;
+
+namespace HeuristicLab.Algorithms.DataAnalysis.SymRegGrammarEnumeration {
+  class AircraftLift : ArtificialRegressionDataDescriptor {
+    public override string Name { get { return "Aircraft Lift Coefficient C_L = x1*(x2 - 2) + x3*x4*x5/x6"; } }
+
+    public override string Description {
+      get {
+        return "Paper: A multilevel block building algorithm for fast modeling generalized separable systems. " + Environment.NewLine +
+               "Author: Chen Chen, Changtong Luo, Zonglin Jiang" + Environment.NewLine +
+               "Function: f(X) = x1*(x2 - 2) + x3*x4*x5/x6" + Environment.NewLine +
+               "with x1 in [0.4,0.8], x2 in [5, 10], x3 in [0.4,0.8], x4 in [5,10], x5 in [1,1.5], x6 in [5,7]";
+      }
+    }
+
+    protected override string TargetVariable { get { return "f(X)"; } }
+    protected override string[] VariableNames { get { return new string[] { "x1", "x2", "x3", "x4", "x5", "x6", "f(X)" }; } }
+    protected override string[] AllowedInputVariables { get { return new string[] { "x1", "x2", "x3", "x4", "x5", "x6" }; } }
+    protected override int TrainingPartitionStart { get { return 0; } }
+    protected override int TrainingPartitionEnd { get { return 100; } }
+    protected override int TestPartitionStart { get { return 100; } }
+    protected override int TestPartitionEnd { get { return 200; } }
+
+    public int Seed { get; private set; }
+
+    public AircraftLift() : this((int)System.DateTime.Now.Ticks) { }
+
+    public AircraftLift(int seed) {
+      Seed = seed;
+    }
+
+    protected override List<List<double>> GenerateValues() {
+      var rand = new MersenneTwister((uint)Seed);
+
+      List<List<double>> data = new List<List<double>>();
+      var x1 = ValueGenerator.GenerateUniformDistributedValues(rand.Next(), TestPartitionEnd, 0.4, 0.8).ToList();
+      var x2 = ValueGenerator.GenerateUniformDistributedValues(rand.Next(), TestPartitionEnd, 5.0, 10.0).ToList();
+      var x3 = ValueGenerator.GenerateUniformDistributedValues(rand.Next(), TestPartitionEnd, 0.4, 0.8).ToList();
+      var x4 = ValueGenerator.GenerateUniformDistributedValues(rand.Next(), TestPartitionEnd, 5.0, 10.0).ToList();
+      var x5 = ValueGenerator.GenerateUniformDistributedValues(rand.Next(), TestPartitionEnd, 1.0, 1.5).ToList();
+      var x6 = ValueGenerator.GenerateUniformDistributedValues(rand.Next(), TestPartitionEnd, 5.0, 7.0).ToList();
+
+      List<double> fx = new List<double>();
+      data.Add(x1);
+      data.Add(x2);
+      data.Add(x3);
+      data.Add(x4);
+      data.Add(x5);
+      data.Add(x6);
+      data.Add(fx);
+
+      for (int i = 0; i < x1.Count; i++) {
+        double fxi = x1[i] * (x2[i] - 2.0) + x3[i] * x4[i] * x5[i] / x6[i];
+        fx.Add(fxi);
+      }
+
+      return data;
+    }
+  }
+}
Index: branches/2886_SymRegGrammarEnumeration/HeuristicLab.Algorithms.DataAnalysis.SymRegGrammarEnumeration/ProblemInstances/AircraftMaximumLift.cs
===================================================================
--- branches/2886_SymRegGrammarEnumeration/HeuristicLab.Algorithms.DataAnalysis.SymRegGrammarEnumeration/ProblemInstances/AircraftMaximumLift.cs	(revision 15928)
+++ branches/2886_SymRegGrammarEnumeration/HeuristicLab.Algorithms.DataAnalysis.SymRegGrammarEnumeration/ProblemInstances/AircraftMaximumLift.cs	(revision 15928)
@@ -0,0 +1,106 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Problems.Instances.DataAnalysis;
+using HeuristicLab.Random;
+
+namespace HeuristicLab.Algorithms.DataAnalysis.SymRegGrammarEnumeration {
+  class AircraftMaximumLift : ArtificialRegressionDataDescriptor {
+    public override string Name { get { return "Aircraft Maximum Lift Coefficient"; } }
+
+    public override string Description {
+      get {
+        return "Paper: A multilevel block building algorithm for fast modeling generalized separable systems. " +
+               Environment.NewLine +
+               "Author: Chen Chen, Changtong Luo, Zonglin Jiang" + Environment.NewLine;
+      }
+    }
+
+    protected override string TargetVariable { get { return "f(X)"; } }
+    protected override string[] VariableNames { get { return new string[] { "x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x18", "f(X)" }; } }
+    protected override string[] AllowedInputVariables { get { return new string[] { "x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x18" }; } }
+    protected override int TrainingPartitionStart { get { return 0; } }
+    protected override int TrainingPartitionEnd { get { return 100; } }
+    protected override int TestPartitionStart { get { return 100; } }
+    protected override int TestPartitionEnd { get { return 200; } }
+
+    public int Seed { get; private set; }
+
+    public AircraftMaximumLift() : this((int)System.DateTime.Now.Ticks) { }
+
+    public AircraftMaximumLift(int seed) {
+      Seed = seed;
+    }
+
+    protected override List<List<double>> GenerateValues() {
+      var rand = new MersenneTwister((uint)Seed);
+
+      List<List<double>> data = new List<List<double>>();
+      var x1 = ValueGenerator.GenerateUniformDistributedValues(rand.Next(), TestPartitionEnd, 0.4, 0.8).ToList();
+
+      var x2 = ValueGenerator.GenerateUniformDistributedValues(rand.Next(), TestPartitionEnd, 3.0, 4.0).ToList();
+
+      var x3 = ValueGenerator.GenerateUniformDistributedValues(rand.Next(), TestPartitionEnd, 20.0, 30.0).ToList();
+
+      var x4 = ValueGenerator.GenerateUniformDistributedValues(rand.Next(), TestPartitionEnd, 2.0, 5.0).ToList();
+      var x13 = ValueGenerator.GenerateUniformDistributedValues(rand.Next(), TestPartitionEnd, 2.0, 5.0).ToList();
+      var x16 = ValueGenerator.GenerateUniformDistributedValues(rand.Next(), TestPartitionEnd, 2.0, 5.0).ToList();
+
+
+      var x5 = ValueGenerator.GenerateUniformDistributedValues(rand.Next(), TestPartitionEnd, 1.0, 1.5).ToList();
+      var x6 = ValueGenerator.GenerateUniformDistributedValues(rand.Next(), TestPartitionEnd, 5.0, 7.0).ToList();
+
+      var x7 = ValueGenerator.GenerateUniformDistributedValues(rand.Next(), TestPartitionEnd, 0.5, 1.5).ToList();
+      var x10 = ValueGenerator.GenerateUniformDistributedValues(rand.Next(), TestPartitionEnd, 0.5, 1.5).ToList();
+
+      var x8 = ValueGenerator.GenerateUniformDistributedValues(rand.Next(), TestPartitionEnd, 1.0, 1.5).ToList();
+      var x11 = ValueGenerator.GenerateUniformDistributedValues(rand.Next(), TestPartitionEnd, 1.0, 1.5).ToList();
+
+      var x9 = ValueGenerator.GenerateUniformDistributedValues(rand.Next(), TestPartitionEnd, 1.0, 2.0).ToList();
+      var x12 = ValueGenerator.GenerateUniformDistributedValues(rand.Next(), TestPartitionEnd, 1.0, 2.0).ToList();
+
+      var x14 = ValueGenerator.GenerateUniformDistributedValues(rand.Next(), TestPartitionEnd, 1.0, 1.5).ToList();
+      var x17 = ValueGenerator.GenerateUniformDistributedValues(rand.Next(), TestPartitionEnd, 1.0, 1.5).ToList();
+
+      var x15 = ValueGenerator.GenerateUniformDistributedValues(rand.Next(), TestPartitionEnd, 5.0, 7.0).ToList();
+
+      var x18 = ValueGenerator.GenerateUniformDistributedValues(rand.Next(), TestPartitionEnd, 10.0, 20.0).ToList();
+
+      List<double> fx = new List<double>();
+      data.Add(x1);
+      data.Add(x2);
+      data.Add(x3);
+      data.Add(x4);
+      data.Add(x5);
+      data.Add(x6);
+      data.Add(x7);
+      data.Add(x8);
+      data.Add(x9);
+      data.Add(x10);
+      data.Add(x11);
+      data.Add(x12);
+      data.Add(x13);
+      data.Add(x14);
+      data.Add(x15);
+      data.Add(x16);
+      data.Add(x17);
+      data.Add(x18);
+      data.Add(fx);
+
+      for (int i = 0; i < x1.Count; i++) {
+        double fxi = x1[i];
+        fxi = fxi - 0.25 * x4[i] * x5[i] * x6[i] * (4 + 0.1 * (x2[i] / x3[i]) - (x2[i] / x3[i]) * (x2[i] / x3[i]));
+        fxi = fxi + x13[i] * (x14[i] / x15[i]) * x18[i] * x7[i];
+        fxi = fxi - x13[i] * (x14[i] / x15[i]) * x8[i];
+        fxi = fxi + x13[i] * (x14[i] / x15[i]) * x9[i];
+        fxi = fxi + x16[i] * (x17[i] / x15[i]) * x18[i] * x10[i];
+        fxi = fxi - x16[i] * (x17[i] / x15[i]) * x11[i];
+        fxi = fxi + x16[i] * (x17[i] / x15[i]) * x12[i];
+
+        fx.Add(fxi);
+      }
+
+      return data;
+    }
+  }
+}
Index: branches/2886_SymRegGrammarEnumeration/HeuristicLab.Algorithms.DataAnalysis.SymRegGrammarEnumeration/ProblemInstances/FluidDynamics.cs
===================================================================
--- branches/2886_SymRegGrammarEnumeration/HeuristicLab.Algorithms.DataAnalysis.SymRegGrammarEnumeration/ProblemInstances/FluidDynamics.cs	(revision 15928)
+++ branches/2886_SymRegGrammarEnumeration/HeuristicLab.Algorithms.DataAnalysis.SymRegGrammarEnumeration/ProblemInstances/FluidDynamics.cs	(revision 15928)
@@ -0,0 +1,63 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Problems.Instances.DataAnalysis;
+using HeuristicLab.Random;
+
+namespace HeuristicLab.Algorithms.DataAnalysis.SymRegGrammarEnumeration {
+  class FluidDynamics : ArtificialRegressionDataDescriptor {
+    public override string Name { get { return "Flow psi = x1*x2*x5*(1 - x4²/x5²) + 1/(2*Pi) * x3*log(x5/x4)"; } }
+
+    public override string Description {
+      get {
+        return "Paper: A multilevel block building algorithm for fast modeling generalized separable systems. " + Environment.NewLine +
+               "Author: Chen Chen, Changtong Luo, Zonglin Jiang" + Environment.NewLine +
+               "Function: f(X) = x1*x2*x5*(1 - x4²/x5²) + 1/(2*Pi) * x3*log(x5/x4)" + Environment.NewLine +
+               "with x1 in [60,65], x2 in [30, 40], x3 in [5,10], x4 in [0.5,0.8], x5 in [0.2,0.5]";
+      }
+    }
+
+    protected override string TargetVariable { get { return "f(X)"; } }
+    protected override string[] VariableNames { get { return new string[] { "x1", "x2", "x3", "x4", "x5", "f(X)" }; } }
+    protected override string[] AllowedInputVariables { get { return new string[] { "x1", "x2", "x3", "x4", "x5" }; } }
+    protected override int TrainingPartitionStart { get { return 0; } }
+    protected override int TrainingPartitionEnd { get { return 100; } }
+    protected override int TestPartitionStart { get { return 100; } }
+    protected override int TestPartitionEnd { get { return 200; } }
+
+    public int Seed { get; private set; }
+
+    public FluidDynamics() : this((int)System.DateTime.Now.Ticks) { }
+
+    public FluidDynamics(int seed) {
+      Seed = seed;
+    }
+
+    protected override List<List<double>> GenerateValues() {
+      var rand = new MersenneTwister((uint)Seed);
+
+      List<List<double>> data = new List<List<double>>();
+      var x1 = ValueGenerator.GenerateUniformDistributedValues(rand.Next(), TestPartitionEnd, 60.0, 65.0).ToList();
+      var x2 = ValueGenerator.GenerateUniformDistributedValues(rand.Next(), TestPartitionEnd, 30.0, 40.0).ToList();
+      var x3 = ValueGenerator.GenerateUniformDistributedValues(rand.Next(), TestPartitionEnd, 5.0, 10.0).ToList();
+      var x4 = ValueGenerator.GenerateUniformDistributedValues(rand.Next(), TestPartitionEnd, 0.5, 0.8).ToList();
+      var x5 = ValueGenerator.GenerateUniformDistributedValues(rand.Next(), TestPartitionEnd, 0.2, 0.5).ToList();
+
+      List<double> fx = new List<double>();
+      data.Add(x1);
+      data.Add(x2);
+      data.Add(x3);
+      data.Add(x4);
+      data.Add(x5);
+      data.Add(fx);
+
+      for (int i = 0; i < x1.Count; i++) {
+        double fxi = x1[i] * x2[i] * x5[i] * (1 - (x4[i] * x4[i]) / (x5[i] * x5[i])) +
+                     (1 / (2 * Math.PI)) * x3[i] * Math.Log(x5[i] / x4[i]);
+        fx.Add(fxi);
+      }
+
+      return data;
+    }
+  }
+}
Index: branches/2886_SymRegGrammarEnumeration/HeuristicLab.Algorithms.DataAnalysis.SymRegGrammarEnumeration/ProblemInstances/PhysicsInstanceProvider.cs
===================================================================
--- branches/2886_SymRegGrammarEnumeration/HeuristicLab.Algorithms.DataAnalysis.SymRegGrammarEnumeration/ProblemInstances/PhysicsInstanceProvider.cs	(revision 15928)
+++ branches/2886_SymRegGrammarEnumeration/HeuristicLab.Algorithms.DataAnalysis.SymRegGrammarEnumeration/ProblemInstances/PhysicsInstanceProvider.cs	(revision 15928)
@@ -0,0 +1,23 @@
+﻿using System;
+using System.Collections.Generic;
+using HeuristicLab.Problems.Instances;
+using HeuristicLab.Problems.Instances.DataAnalysis;
+
+namespace HeuristicLab.Algorithms.DataAnalysis.SymRegGrammarEnumeration.ProblemInstances {
+  class PhysicsInstanceProvider : ArtificialRegressionInstanceProvider {
+    public override IEnumerable<IDataDescriptor> GetDataDescriptors() {
+      return new List<IDataDescriptor>()
+      {
+         new RocketFuelFlow(123),
+         new AircraftLift(456),
+         new FluidDynamics(789),
+         new AircraftMaximumLift(321)
+      };
+    }
+
+    public override string Name { get { return "Physics Benchmark Problems"; } }
+    public override string Description { get { return ""; } }
+    public override Uri WebLink { get { return new Uri(@"https://arxiv.org/pdf/1706.02281.pdf"); } }
+    public override string ReferencePublication { get { return "Chen et al., 2017 \"A multilevel block search algorithm for fast modeling generalized separable systems.\" arXiv preprint arXiv:1706.02281"; } }
+  }
+}
Index: branches/2886_SymRegGrammarEnumeration/HeuristicLab.Algorithms.DataAnalysis.SymRegGrammarEnumeration/ProblemInstances/RocketFuelFlow.cs
===================================================================
--- branches/2886_SymRegGrammarEnumeration/HeuristicLab.Algorithms.DataAnalysis.SymRegGrammarEnumeration/ProblemInstances/RocketFuelFlow.cs	(revision 15928)
+++ branches/2886_SymRegGrammarEnumeration/HeuristicLab.Algorithms.DataAnalysis.SymRegGrammarEnumeration/ProblemInstances/RocketFuelFlow.cs	(revision 15928)
@@ -0,0 +1,58 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Problems.Instances.DataAnalysis;
+using HeuristicLab.Random;
+
+namespace HeuristicLab.Algorithms.DataAnalysis.SymRegGrammarEnumeration {
+  class RocketFuelFlow : ArtificialRegressionDataDescriptor {
+    public override string Name { get { return "Rocket Fuel Flow f(X) = 4000*x1*x2/sqrt(x3)"; } }
+
+    public override string Description {
+      get {
+        return "Paper: A multilevel block building algorithm for fast modeling generalized separable systems. " + Environment.NewLine +
+               "Author: Chen Chen, Changtong Luo, Zonglin Jiang" + Environment.NewLine +
+               "Function: f(X) = 4000*x1*x2/sqrt(x3)" + Environment.NewLine +
+               "with x1 in [4,6], x2 in [0.5, 1.5], x3 in [250,260]";
+      }
+    }
+
+    protected override string TargetVariable { get { return "f(X)"; } }
+    protected override string[] VariableNames { get { return new string[] { "x1", "x2", "x3", "f(X)" }; } }
+    protected override string[] AllowedInputVariables { get { return new string[] { "x1", "x2", "x3" }; } }
+    protected override int TrainingPartitionStart { get { return 0; } }
+    protected override int TrainingPartitionEnd { get { return 100; } }
+    protected override int TestPartitionStart { get { return 100; } }
+    protected override int TestPartitionEnd { get { return 200; } }
+
+    public int Seed { get; private set; }
+
+    public RocketFuelFlow() : this((int)System.DateTime.Now.Ticks) { }
+
+    public RocketFuelFlow(int seed) {
+      Seed = seed;
+    }
+
+    protected override List<List<double>> GenerateValues() {
+      var rand = new MersenneTwister((uint)Seed);
+
+      List<List<double>> data = new List<List<double>>();
+      var x1 = ValueGenerator.GenerateUniformDistributedValues(rand.Next(), TestPartitionEnd, 4.0, 6.0).ToList();
+      var x2 = ValueGenerator.GenerateUniformDistributedValues(rand.Next(), TestPartitionEnd, 0.5, 1.5).ToList();
+      var x3 = ValueGenerator.GenerateUniformDistributedValues(rand.Next(), TestPartitionEnd, 250.0, 260.0).ToList();
+
+      List<double> fx = new List<double>();
+      data.Add(x1);
+      data.Add(x2);
+      data.Add(x3);
+      data.Add(fx);
+
+      for (int i = 0; i < x1.Count; i++) {
+        double fxi = 4000 * x1[i] * x2[i] / Math.Sqrt(x3[i]);
+        fx.Add(fxi);
+      }
+
+      return data;
+    }
+  }
+}
Index: branches/2886_SymRegGrammarEnumeration/HeuristicLab.Algorithms.DataAnalysis.SymRegGrammarEnumeration/ProblemInstances/ValueGenerator.cs
===================================================================
--- branches/2886_SymRegGrammarEnumeration/HeuristicLab.Algorithms.DataAnalysis.SymRegGrammarEnumeration/ProblemInstances/ValueGenerator.cs	(revision 15928)
+++ branches/2886_SymRegGrammarEnumeration/HeuristicLab.Algorithms.DataAnalysis.SymRegGrammarEnumeration/ProblemInstances/ValueGenerator.cs	(revision 15928)
@@ -0,0 +1,100 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Random;
+
+namespace HeuristicLab.Problems.Instances.DataAnalysis {
+  internal static class ValueGenerator {
+
+    /// <summary>
+    /// Generates uniformly distributed values between start and end (inclusive!) 
+    /// </summary>
+    /// <param name="seed">The seed for the random number generator</param>
+    /// <param name="n">Number of values to generate.</param>
+    /// <param name="start">The lower value (inclusive)</param>
+    /// <param name="end">The upper value (inclusive)</param>
+    /// <returns>An enumerable including n values in [start, end]</returns>
+    public static IEnumerable<double> GenerateUniformDistributedValues(int seed, int n, double start, double end) {
+      var rand = new FastRandom(seed);
+      for (int i = 0; i < n; i++) {
+        // we need to return a random value including end.
+        // so we cannot use rand.NextDouble() as it returns a value strictly smaller than 1.
+        double r = rand.NextUInt() / (double)uint.MaxValue;    // r \in [0,1]
+        yield return r * (end - start) + start;
+      }
+    }
+
+    /// <summary>
+    /// Generates normally distributed values sampling from N(mu, sigma) 
+    /// </summary>
+    /// <param name="seed">The seed for the random number generator</param>
+    /// <param name="n">Number of values to generate.</param>
+    /// <param name="mu">The mu parameter of the normal distribution</param>
+    /// <param name="sigma">The sigma parameter of the normal distribution</param>
+    /// <returns>An enumerable including n values ~ N(mu, sigma)</returns>
+    public static IEnumerable<double> GenerateNormalDistributedValues(int seed, int n, double mu, double sigma) {
+      var rand = new FastRandom(seed);
+      for (int i = 0; i < n; i++)
+        yield return NormalDistributedRandom.NextDouble(rand, mu, sigma);
+    }
+
+    // Generate the cartesian product.
+    // The result is transposed, therefore the inner lists represent a column of values instead of a combination-pair.
+    public static IEnumerable<IEnumerable<double>> GenerateAllCombinationsOfValuesInLists(List<List<double>> lists) {
+      List<List<double>> allCombinations = new List<List<double>>();
+      if (lists.Count < 1) {
+        return allCombinations;
+      }
+
+      List<IEnumerator<double>> enumerators = new List<IEnumerator<double>>();
+      foreach (var list in lists) {
+        allCombinations.Add(new List<double>());
+        enumerators.Add(list.GetEnumerator());
+      }
+
+      bool finished = !enumerators.All(x => x.MoveNext());
+
+      while (!finished) {
+        GetCurrentCombination(enumerators, allCombinations);
+        finished = MoveNext(enumerators, lists);
+      }
+      return allCombinations;
+    }
+
+    private static bool MoveNext(List<IEnumerator<double>> enumerators, List<List<double>> lists) {
+      int cur = enumerators.Count - 1;
+      while (cur >= 0 && !enumerators[cur].MoveNext()) {
+        enumerators[cur] = lists[cur].GetEnumerator();
+        enumerators[cur].MoveNext();
+        cur--;
+      }
+      return cur < 0;
+    }
+
+    private static void GetCurrentCombination(List<IEnumerator<double>> enumerators, List<List<double>> allCombinations) {
+      for (int i = 0; i < enumerators.Count(); i++) {
+        allCombinations[i].Add(enumerators[i].Current);
+      }
+    }
+  }
+}
