Index: /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/GaussianProcess/GaussianProcessModel.cs
===================================================================
--- /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/GaussianProcess/GaussianProcessModel.cs	(revision 12701)
+++ /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/GaussianProcess/GaussianProcessModel.cs	(revision 12702)
@@ -117,5 +117,5 @@
       this.x = original.x;
     }
-    public GaussianProcessModel(Dataset ds, string targetVariable, IEnumerable<string> allowedInputVariables, IEnumerable<int> rows,
+    public GaussianProcessModel(IDataset ds, string targetVariable, IEnumerable<string> allowedInputVariables, IEnumerable<int> rows,
       IEnumerable<double> hyp, IMeanFunction meanFunction, ICovarianceFunction covarianceFunction)
       : base() {
@@ -141,5 +141,5 @@
     }
 
-    private void CalculateModel(Dataset ds, IEnumerable<int> rows) {
+    private void CalculateModel(IDataset ds, IEnumerable<int> rows) {
       inputScaling = new Scaling(ds, allowedInputVariables, rows);
       x = AlglibUtil.PrepareAndScaleInputMatrix(ds, allowedInputVariables, rows, inputScaling);
@@ -245,5 +245,5 @@
 
     #region IRegressionModel Members
-    public IEnumerable<double> GetEstimatedValues(Dataset dataset, IEnumerable<int> rows) {
+    public IEnumerable<double> GetEstimatedValues(IDataset dataset, IEnumerable<int> rows) {
       return GetEstimatedValuesHelper(dataset, rows);
     }
@@ -257,5 +257,5 @@
 
 
-    private IEnumerable<double> GetEstimatedValuesHelper(Dataset dataset, IEnumerable<int> rows) {
+    private IEnumerable<double> GetEstimatedValuesHelper(IDataset dataset, IEnumerable<int> rows) {
       var newX = AlglibUtil.PrepareAndScaleInputMatrix(dataset, allowedInputVariables, rows, inputScaling);
       int newN = newX.GetLength(0);
@@ -277,5 +277,5 @@
     }
 
-    public IEnumerable<double> GetEstimatedVariance(Dataset dataset, IEnumerable<int> rows) {
+    public IEnumerable<double> GetEstimatedVariance(IDataset dataset, IEnumerable<int> rows) {
       var newX = AlglibUtil.PrepareAndScaleInputMatrix(dataset, allowedInputVariables, rows, inputScaling);
       int newN = newX.GetLength(0);
Index: /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/Interfaces/IGaussianProcessModel.cs
===================================================================
--- /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/Interfaces/IGaussianProcessModel.cs	(revision 12701)
+++ /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/Interfaces/IGaussianProcessModel.cs	(revision 12702)
@@ -34,5 +34,5 @@
     double[] HyperparameterGradients { get; }
 
-    IEnumerable<double> GetEstimatedVariance(Dataset ds, IEnumerable<int> rows);
+    IEnumerable<double> GetEstimatedVariance(IDataset ds, IEnumerable<int> rows);
     void FixParameters();
   }
Index: /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/Interfaces/INcaModel.cs
===================================================================
--- /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/Interfaces/INcaModel.cs	(revision 12701)
+++ /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/Interfaces/INcaModel.cs	(revision 12702)
@@ -27,5 +27,5 @@
     new INcaClassificationSolution CreateClassificationSolution(IClassificationProblemData problemData);
 
-    double[,] Reduce(Dataset dataset, IEnumerable<int> rows);
+    double[,] Reduce(IDataset dataset, IEnumerable<int> rows);
   }
 }
Index: /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/Linear/AlglibUtil.cs
===================================================================
--- /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/Linear/AlglibUtil.cs	(revision 12701)
+++ /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/Linear/AlglibUtil.cs	(revision 12702)
@@ -26,5 +26,5 @@
 namespace HeuristicLab.Algorithms.DataAnalysis {
   public static class AlglibUtil {
-    public static double[,] PrepareInputMatrix(Dataset dataset, IEnumerable<string> variables, IEnumerable<int> rows) {
+    public static double[,] PrepareInputMatrix(IDataset dataset, IEnumerable<string> variables, IEnumerable<int> rows) {
       List<string> variablesList = variables.ToList();
       List<int> rowsList = rows.ToList();
@@ -45,5 +45,5 @@
       return matrix;
     }
-    public static double[,] PrepareAndScaleInputMatrix(Dataset dataset, IEnumerable<string> variables, IEnumerable<int> rows, Scaling scaling) {
+    public static double[,] PrepareAndScaleInputMatrix(IDataset dataset, IEnumerable<string> variables, IEnumerable<int> rows, Scaling scaling) {
       List<string> variablesList = variables.ToList();
       List<int> rowsList = rows.ToList();
Index: /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/Linear/LinearDiscriminantAnalysis.cs
===================================================================
--- /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/Linear/LinearDiscriminantAnalysis.cs	(revision 12701)
+++ /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/Linear/LinearDiscriminantAnalysis.cs	(revision 12702)
@@ -65,5 +65,5 @@
 
     public static IClassificationSolution CreateLinearDiscriminantAnalysisSolution(IClassificationProblemData problemData) {
-      Dataset dataset = problemData.Dataset;
+      var dataset = problemData.Dataset;
       string targetVariable = problemData.TargetVariable;
       IEnumerable<string> allowedInputVariables = problemData.AllowedInputVariables;
Index: /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/Linear/LinearRegression.cs
===================================================================
--- /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/Linear/LinearRegression.cs	(revision 12701)
+++ /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/Linear/LinearRegression.cs	(revision 12702)
@@ -69,5 +69,5 @@
 
     public static ISymbolicRegressionSolution CreateLinearRegressionSolution(IRegressionProblemData problemData, out double rmsError, out double cvRmsError) {
-      Dataset dataset = problemData.Dataset;
+      var dataset = problemData.Dataset;
       string targetVariable = problemData.TargetVariable;
       IEnumerable<string> allowedInputVariables = problemData.AllowedInputVariables;
Index: /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/Linear/MultinomialLogitClassification.cs
===================================================================
--- /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/Linear/MultinomialLogitClassification.cs	(revision 12701)
+++ /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/Linear/MultinomialLogitClassification.cs	(revision 12702)
@@ -66,5 +66,5 @@
 
     public static IClassificationSolution CreateLogitClassificationSolution(IClassificationProblemData problemData, out double rmsError, out double relClassError) {
-      Dataset dataset = problemData.Dataset;
+      var dataset = problemData.Dataset;
       string targetVariable = problemData.TargetVariable;
       IEnumerable<string> allowedInputVariables = problemData.AllowedInputVariables;
Index: /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/Linear/MultinomialLogitModel.cs
===================================================================
--- /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/Linear/MultinomialLogitModel.cs	(revision 12701)
+++ /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/Linear/MultinomialLogitModel.cs	(revision 12702)
@@ -82,5 +82,5 @@
     }
 
-    public IEnumerable<double> GetEstimatedClassValues(Dataset dataset, IEnumerable<int> rows) {
+    public IEnumerable<double> GetEstimatedClassValues(IDataset dataset, IEnumerable<int> rows) {
       double[,] inputData = AlglibUtil.PrepareInputMatrix(dataset, allowedInputVariables, rows);
 
Index: /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/Linear/Scaling.cs
===================================================================
--- /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/Linear/Scaling.cs	(revision 12701)
+++ /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/Linear/Scaling.cs	(revision 12702)
@@ -41,5 +41,5 @@
         scalingParameters.Add(pair.Key, Tuple.Create(pair.Value.Item1, pair.Value.Item2));
     }
-    public Scaling(Dataset ds, IEnumerable<string> variables, IEnumerable<int> rows) {
+    public Scaling(IDataset ds, IEnumerable<string> variables, IEnumerable<int> rows) {
       foreach (var variable in variables) {
         var values = ds.GetDoubleValues(variable, rows);
@@ -54,5 +54,5 @@
     }
 
-    public IEnumerable<double> GetScaledValues(Dataset ds, string variable, IEnumerable<int> rows) {
+    public IEnumerable<double> GetScaledValues(IDataset ds, string variable, IEnumerable<int> rows) {
       double min = scalingParameters[variable].Item1;
       double max = scalingParameters[variable].Item2;
Index: /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/Nca/NcaModel.cs
===================================================================
--- /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/Nca/NcaModel.cs	(revision 12701)
+++ /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/Nca/NcaModel.cs	(revision 12702)
@@ -56,5 +56,5 @@
       this.classValues = (double[])original.classValues.Clone();
     }
-    public NcaModel(int k, double[,] transformationMatrix, Dataset dataset, IEnumerable<int> rows, string targetVariable, IEnumerable<string> allowedInputVariables, double[] classValues) {
+    public NcaModel(int k, double[,] transformationMatrix, IDataset dataset, IEnumerable<int> rows, string targetVariable, IEnumerable<string> allowedInputVariables, double[] classValues) {
       Name = ItemName;
       Description = ItemDescription;
@@ -72,5 +72,5 @@
     }
 
-    public IEnumerable<double> GetEstimatedClassValues(Dataset dataset, IEnumerable<int> rows) {
+    public IEnumerable<double> GetEstimatedClassValues(IDataset dataset, IEnumerable<int> rows) {
       var ds = ReduceDataset(dataset, rows);
       return nnModel.GetEstimatedClassValues(ds, Enumerable.Range(0, ds.Rows));
@@ -85,5 +85,5 @@
     }
 
-    public double[,] Reduce(Dataset dataset, IEnumerable<int> rows) {
+    public double[,] Reduce(IDataset dataset, IEnumerable<int> rows) {
       var data = AlglibUtil.PrepareInputMatrix(dataset, allowedInputVariables, rows);
 
@@ -100,5 +100,5 @@
     }
 
-    public Dataset ReduceDataset(Dataset dataset, IEnumerable<int> rows) {
+    public Dataset ReduceDataset(IDataset dataset, IEnumerable<int> rows) {
       return new Dataset(Enumerable
           .Range(0, transformationMatrix.GetLength(1))
Index: /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/NearestNeighbour/NearestNeighbourModel.cs
===================================================================
--- /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/NearestNeighbour/NearestNeighbourModel.cs	(revision 12701)
+++ /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/NearestNeighbour/NearestNeighbourModel.cs	(revision 12702)
@@ -96,5 +96,5 @@
         this.classValues = (double[])original.classValues.Clone();
     }
-    public NearestNeighbourModel(Dataset dataset, IEnumerable<int> rows, int k, string targetVariable, IEnumerable<string> allowedInputVariables, double[] classValues = null) {
+    public NearestNeighbourModel(IDataset dataset, IEnumerable<int> rows, int k, string targetVariable, IEnumerable<string> allowedInputVariables, double[] classValues = null) {
       Name = ItemName;
       Description = ItemDescription;
@@ -135,5 +135,5 @@
     }
 
-    public IEnumerable<double> GetEstimatedValues(Dataset dataset, IEnumerable<int> rows) {
+    public IEnumerable<double> GetEstimatedValues(IDataset dataset, IEnumerable<int> rows) {
       double[,] inputData = AlglibUtil.PrepareInputMatrix(dataset, allowedInputVariables, rows);
 
@@ -163,5 +163,5 @@
     }
 
-    public IEnumerable<double> GetEstimatedClassValues(Dataset dataset, IEnumerable<int> rows) {
+    public IEnumerable<double> GetEstimatedClassValues(IDataset dataset, IEnumerable<int> rows) {
       if (classValues == null) throw new InvalidOperationException("No class values are defined.");
       double[,] inputData = AlglibUtil.PrepareInputMatrix(dataset, allowedInputVariables, rows);
Index: /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/NeuralNetwork/NeuralNetworkClassification.cs
===================================================================
--- /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/NeuralNetwork/NeuralNetworkClassification.cs	(revision 12701)
+++ /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/NeuralNetwork/NeuralNetworkClassification.cs	(revision 12702)
@@ -179,5 +179,5 @@
     public static IClassificationSolution CreateNeuralNetworkClassificationSolution(IClassificationProblemData problemData, int nLayers, int nHiddenNodes1, int nHiddenNodes2, double decay, int restarts,
       out double rmsError, out double avgRelError, out double relClassError) {
-      Dataset dataset = problemData.Dataset;
+      var dataset = problemData.Dataset;
       string targetVariable = problemData.TargetVariable;
       IEnumerable<string> allowedInputVariables = problemData.AllowedInputVariables;
Index: /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/NeuralNetwork/NeuralNetworkEnsembleClassification.cs
===================================================================
--- /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/NeuralNetwork/NeuralNetworkEnsembleClassification.cs	(revision 12701)
+++ /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/NeuralNetwork/NeuralNetworkEnsembleClassification.cs	(revision 12702)
@@ -165,5 +165,5 @@
     public static IClassificationSolution CreateNeuralNetworkEnsembleClassificationSolution(IClassificationProblemData problemData, int ensembleSize, int nLayers, int nHiddenNodes1, int nHiddenNodes2, double decay, int restarts,
       out double rmsError, out double avgRelError, out double relClassError) {
-      Dataset dataset = problemData.Dataset;
+      var dataset = problemData.Dataset;
       string targetVariable = problemData.TargetVariable;
       IEnumerable<string> allowedInputVariables = problemData.AllowedInputVariables;
Index: /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/NeuralNetwork/NeuralNetworkEnsembleModel.cs
===================================================================
--- /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/NeuralNetwork/NeuralNetworkEnsembleModel.cs	(revision 12701)
+++ /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/NeuralNetwork/NeuralNetworkEnsembleModel.cs	(revision 12702)
@@ -86,5 +86,5 @@
     }
 
-    public IEnumerable<double> GetEstimatedValues(Dataset dataset, IEnumerable<int> rows) {
+    public IEnumerable<double> GetEstimatedValues(IDataset dataset, IEnumerable<int> rows) {
       double[,] inputData = AlglibUtil.PrepareInputMatrix(dataset, allowedInputVariables, rows);
 
@@ -103,5 +103,5 @@
     }
 
-    public IEnumerable<double> GetEstimatedClassValues(Dataset dataset, IEnumerable<int> rows) {
+    public IEnumerable<double> GetEstimatedClassValues(IDataset dataset, IEnumerable<int> rows) {
       double[,] inputData = AlglibUtil.PrepareInputMatrix(dataset, allowedInputVariables, rows);
 
Index: /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/NeuralNetwork/NeuralNetworkEnsembleRegression.cs
===================================================================
--- /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/NeuralNetwork/NeuralNetworkEnsembleRegression.cs	(revision 12701)
+++ /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/NeuralNetwork/NeuralNetworkEnsembleRegression.cs	(revision 12702)
@@ -164,5 +164,5 @@
     public static IRegressionSolution CreateNeuralNetworkEnsembleRegressionSolution(IRegressionProblemData problemData, int ensembleSize, int nLayers, int nHiddenNodes1, int nHiddenNodes2, double decay, int restarts,
       out double rmsError, out double avgRelError) {
-      Dataset dataset = problemData.Dataset;
+      var dataset = problemData.Dataset;
       string targetVariable = problemData.TargetVariable;
       IEnumerable<string> allowedInputVariables = problemData.AllowedInputVariables;
Index: /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/NeuralNetwork/NeuralNetworkModel.cs
===================================================================
--- /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/NeuralNetwork/NeuralNetworkModel.cs	(revision 12701)
+++ /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/NeuralNetwork/NeuralNetworkModel.cs	(revision 12702)
@@ -94,5 +94,5 @@
     }
 
-    public IEnumerable<double> GetEstimatedValues(Dataset dataset, IEnumerable<int> rows) {
+    public IEnumerable<double> GetEstimatedValues(IDataset dataset, IEnumerable<int> rows) {
       double[,] inputData = AlglibUtil.PrepareInputMatrix(dataset, allowedInputVariables, rows);
 
@@ -111,5 +111,5 @@
     }
 
-    public IEnumerable<double> GetEstimatedClassValues(Dataset dataset, IEnumerable<int> rows) {
+    public IEnumerable<double> GetEstimatedClassValues(IDataset dataset, IEnumerable<int> rows) {
       double[,] inputData = AlglibUtil.PrepareInputMatrix(dataset, allowedInputVariables, rows);
 
Index: /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/NeuralNetwork/NeuralNetworkRegression.cs
===================================================================
--- /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/NeuralNetwork/NeuralNetworkRegression.cs	(revision 12701)
+++ /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/NeuralNetwork/NeuralNetworkRegression.cs	(revision 12702)
@@ -180,5 +180,5 @@
     public static IRegressionSolution CreateNeuralNetworkRegressionSolution(IRegressionProblemData problemData, int nLayers, int nHiddenNodes1, int nHiddenNodes2, double decay, int restarts,
       out double rmsError, out double avgRelError) {
-      Dataset dataset = problemData.Dataset;
+      var dataset = problemData.Dataset;
       string targetVariable = problemData.TargetVariable;
       IEnumerable<string> allowedInputVariables = problemData.AllowedInputVariables;
Index: /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/RandomForest/RandomForestModel.cs
===================================================================
--- /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/RandomForest/RandomForestModel.cs	(revision 12701)
+++ /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/RandomForest/RandomForestModel.cs	(revision 12702)
@@ -129,5 +129,5 @@
     }
 
-    public IEnumerable<double> GetEstimatedValues(Dataset dataset, IEnumerable<int> rows) {
+    public IEnumerable<double> GetEstimatedValues(IDataset dataset, IEnumerable<int> rows) {
       double[,] inputData = AlglibUtil.PrepareInputMatrix(dataset, AllowedInputVariables, rows);
       AssertInputMatrix(inputData);
@@ -147,5 +147,5 @@
     }
 
-    public IEnumerable<double> GetEstimatedClassValues(Dataset dataset, IEnumerable<int> rows) {
+    public IEnumerable<double> GetEstimatedClassValues(IDataset dataset, IEnumerable<int> rows) {
       double[,] inputData = AlglibUtil.PrepareInputMatrix(dataset, AllowedInputVariables, rows);
       AssertInputMatrix(inputData);
@@ -205,5 +205,5 @@
       outOfBagRmsError = rep.oobrmserror;
 
-      return new RandomForestModel(dForest,seed, problemData,nTrees, r, m);
+      return new RandomForestModel(dForest, seed, problemData, nTrees, r, m);
     }
 
@@ -242,5 +242,5 @@
       outOfBagRelClassificationError = rep.oobrelclserror;
 
-      return new RandomForestModel(dForest,seed, problemData,nTrees, r, m, classValues);
+      return new RandomForestModel(dForest, seed, problemData, nTrees, r, m, classValues);
     }
 
Index: /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/RandomForest/RandomForestUtil.cs
===================================================================
--- /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/RandomForest/RandomForestUtil.cs	(revision 12701)
+++ /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/RandomForest/RandomForestUtil.cs	(revision 12702)
@@ -90,6 +90,4 @@
 
   public static class RandomForestUtil {
-    private static readonly object locker = new object();
-
     private static void CrossValidate(IRegressionProblemData problemData, Tuple<IEnumerable<int>, IEnumerable<int>>[] partitions, int nTrees, double r, double m, int seed, out double avgTestMse) {
       avgTestMse = 0;
@@ -132,5 +130,11 @@
     }
 
-    // grid search without cross-validation since in the case of random forests, the out-of-bag estimate is unbiased
+    /// <summary>
+    /// Grid search without crossvalidation (since for random forests the out-of-bag estimate is unbiased)
+    /// </summary>
+    /// <param name="problemData">The regression problem data</param>
+    /// <param name="parameterRanges">The ranges for each parameter in the grid search</param>
+    /// <param name="seed">The random seed (required by the random forest model)</param>
+    /// <param name="maxDegreeOfParallelism">The maximum allowed number of threads (to parallelize the grid search)</param>
     public static RFParameter GridSearch(IRegressionProblemData problemData, Dictionary<string, IEnumerable<double>> parameterRanges, int seed = 12345, int maxDegreeOfParallelism = 1) {
       var setters = parameterRanges.Keys.Select(GenerateSetter).ToList();
@@ -139,4 +143,5 @@
       RFParameter bestParameters = new RFParameter();
 
+      var locker = new object();
       Parallel.ForEach(crossProduct, new ParallelOptions { MaxDegreeOfParallelism = maxDegreeOfParallelism }, parameterCombination => {
         var parameterValues = parameterCombination.ToList();
@@ -156,4 +161,11 @@
     }
 
+    /// <summary>
+    /// Grid search without crossvalidation (since for random forests the out-of-bag estimate is unbiased)
+    /// </summary>
+    /// <param name="problemData">The classification problem data</param>
+    /// <param name="parameterRanges">The ranges for each parameter in the grid search</param>
+    /// <param name="seed">The random seed (required by the random forest model)</param>
+    /// <param name="maxDegreeOfParallelism">The maximum allowed number of threads (to parallelize the grid search)</param>
     public static RFParameter GridSearch(IClassificationProblemData problemData, Dictionary<string, IEnumerable<double>> parameterRanges, int seed = 12345, int maxDegreeOfParallelism = 1) {
       var setters = parameterRanges.Keys.Select(GenerateSetter).ToList();
@@ -163,4 +175,5 @@
       RFParameter bestParameters = new RFParameter();
 
+      var locker = new object();
       Parallel.ForEach(crossProduct, new ParallelOptions { MaxDegreeOfParallelism = maxDegreeOfParallelism }, parameterCombination => {
         var parameterValues = parameterCombination.ToList();
@@ -181,4 +194,14 @@
     }
 
+    /// <summary>
+    /// Grid search with crossvalidation
+    /// </summary>
+    /// <param name="problemData">The regression problem data</param>
+    /// <param name="numberOfFolds">The number of folds for crossvalidation</param>
+    /// <param name="shuffleFolds">Specifies whether the folds should be shuffled</param>
+    /// <param name="parameterRanges">The ranges for each parameter in the grid search</param>
+    /// <param name="seed">The random seed (required by the random forest model)</param>
+    /// <param name="maxDegreeOfParallelism">The maximum allowed number of threads (to parallelize the grid search)</param>
+    /// <returns>The best parameter values found by the grid search</returns>
     public static RFParameter GridSearch(IRegressionProblemData problemData, int numberOfFolds, bool shuffleFolds, Dictionary<string, IEnumerable<double>> parameterRanges, int seed = 12345, int maxDegreeOfParallelism = 1) {
       DoubleValue mse = new DoubleValue(Double.MaxValue);
@@ -189,4 +212,5 @@
       var crossProduct = parameterRanges.Values.CartesianProduct();
 
+      var locker = new object();
       Parallel.ForEach(crossProduct, new ParallelOptions { MaxDegreeOfParallelism = maxDegreeOfParallelism }, parameterCombination => {
         var parameterValues = parameterCombination.ToList();
@@ -208,4 +232,13 @@
     }
 
+    /// <summary>
+    /// Grid search with crossvalidation
+    /// </summary>
+    /// <param name="problemData">The classification problem data</param>
+    /// <param name="numberOfFolds">The number of folds for crossvalidation</param>
+    /// <param name="shuffleFolds">Specifies whether the folds should be shuffled</param>
+    /// <param name="parameterRanges">The ranges for each parameter in the grid search</param>
+    /// <param name="seed">The random seed (for shuffling)</param>
+    /// <param name="maxDegreeOfParallelism">The maximum allowed number of threads (to parallelize the grid search)</param>
     public static RFParameter GridSearch(IClassificationProblemData problemData, int numberOfFolds, bool shuffleFolds, Dictionary<string, IEnumerable<double>> parameterRanges, int seed = 12345, int maxDegreeOfParallelism = 1) {
       DoubleValue accuracy = new DoubleValue(0);
@@ -216,4 +249,5 @@
       var partitions = GenerateRandomForestPartitions(problemData, numberOfFolds, shuffleFolds);
 
+      var locker = new object();
       Parallel.ForEach(crossProduct, new ParallelOptions { MaxDegreeOfParallelism = maxDegreeOfParallelism }, parameterCombination => {
         var parameterValues = parameterCombination.ToList();
Index: /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/SupportVectorMachine/SupportVectorClassification.cs
===================================================================
--- /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/SupportVectorMachine/SupportVectorClassification.cs	(revision 12701)
+++ /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/SupportVectorMachine/SupportVectorClassification.cs	(revision 12702)
@@ -149,5 +149,5 @@
     public static SupportVectorClassificationSolution CreateSupportVectorClassificationSolution(IClassificationProblemData problemData, IEnumerable<string> allowedInputVariables,
       int svmType, int kernelType, double cost, double nu, double gamma, int degree, out double trainingAccuracy, out double testAccuracy, out int nSv) {
-      Dataset dataset = problemData.Dataset;
+      var dataset = problemData.Dataset;
       string targetVariable = problemData.TargetVariable;
       IEnumerable<int> rows = problemData.TrainingIndices;
Index: /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/SupportVectorMachine/SupportVectorMachineModel.cs
===================================================================
--- /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/SupportVectorMachine/SupportVectorMachineModel.cs	(revision 12701)
+++ /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/SupportVectorMachine/SupportVectorMachineModel.cs	(revision 12702)
@@ -120,5 +120,5 @@
 
     #region IRegressionModel Members
-    public IEnumerable<double> GetEstimatedValues(Dataset dataset, IEnumerable<int> rows) {
+    public IEnumerable<double> GetEstimatedValues(IDataset dataset, IEnumerable<int> rows) {
       return GetEstimatedValuesHelper(dataset, rows);
     }
@@ -132,5 +132,5 @@
 
     #region IClassificationModel Members
-    public IEnumerable<double> GetEstimatedClassValues(Dataset dataset, IEnumerable<int> rows) {
+    public IEnumerable<double> GetEstimatedClassValues(IDataset dataset, IEnumerable<int> rows) {
       if (classValues == null) throw new NotSupportedException();
       // return the original class value instead of the predicted value of the model
@@ -159,5 +159,5 @@
     }
     #endregion
-    private IEnumerable<double> GetEstimatedValuesHelper(Dataset dataset, IEnumerable<int> rows) {
+    private IEnumerable<double> GetEstimatedValuesHelper(IDataset dataset, IEnumerable<int> rows) {
       // calculate predictions for the currently requested rows
       svm_problem problem = SupportVectorMachineUtil.CreateSvmProblem(dataset, targetVariable, allowedInputVariables, rows);
Index: /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/SupportVectorMachine/SupportVectorMachineUtil.cs
===================================================================
--- /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/SupportVectorMachine/SupportVectorMachineUtil.cs	(revision 12701)
+++ /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/SupportVectorMachine/SupportVectorMachineUtil.cs	(revision 12702)
@@ -40,5 +40,5 @@
     /// <param name="rowIndices">The rows of the dataset that should be contained in the resulting SVM-problem</param>
     /// <returns>A problem data type that can be used to train a support vector machine.</returns>
-    public static svm_problem CreateSvmProblem(Dataset dataset, string targetVariable, IEnumerable<string> inputVariables, IEnumerable<int> rowIndices) {
+    public static svm_problem CreateSvmProblem(IDataset dataset, string targetVariable, IEnumerable<string> inputVariables, IEnumerable<int> rowIndices) {
       double[] targetVector = dataset.GetDoubleValues(targetVariable, rowIndices).ToArray();
       svm_node[][] nodes = new svm_node[targetVector.Length][];
Index: /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/SupportVectorMachine/SupportVectorRegression.cs
===================================================================
--- /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/SupportVectorMachine/SupportVectorRegression.cs	(revision 12701)
+++ /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/SupportVectorMachine/SupportVectorRegression.cs	(revision 12702)
@@ -152,5 +152,5 @@
       string svmType, string kernelType, double cost, double nu, double gamma, double epsilon, int degree,
       out double trainingR2, out double testR2, out int nSv) {
-      Dataset dataset = problemData.Dataset;
+      var dataset = problemData.Dataset;
       string targetVariable = problemData.TargetVariable;
       IEnumerable<int> rows = problemData.TrainingIndices;
Index: /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/kMeans/KMeansClustering.cs
===================================================================
--- /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/kMeans/KMeansClustering.cs	(revision 12701)
+++ /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/kMeans/KMeansClustering.cs	(revision 12702)
@@ -83,5 +83,5 @@
 
     public static KMeansClusteringSolution CreateKMeansSolution(IClusteringProblemData problemData, int k, int restarts) {
-      Dataset dataset = problemData.Dataset;
+      var dataset = problemData.Dataset;
       IEnumerable<string> allowedInputVariables = problemData.AllowedInputVariables;
       IEnumerable<int> rows = problemData.TrainingIndices;
Index: /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/kMeans/KMeansClusteringModel.cs
===================================================================
--- /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/kMeans/KMeansClusteringModel.cs	(revision 12701)
+++ /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/kMeans/KMeansClusteringModel.cs	(revision 12702)
@@ -81,5 +81,5 @@
 
 
-    public IEnumerable<int> GetClusterValues(Dataset dataset, IEnumerable<int> rows) {
+    public IEnumerable<int> GetClusterValues(IDataset dataset, IEnumerable<int> rows) {
       return KMeansClusteringUtil.FindClosestCenters(centers, dataset, allowedInputVariables, rows);
     }
Index: /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/kMeans/KMeansClusteringUtil.cs
===================================================================
--- /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/kMeans/KMeansClusteringUtil.cs	(revision 12701)
+++ /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/kMeans/KMeansClusteringUtil.cs	(revision 12702)
@@ -27,5 +27,5 @@
 namespace HeuristicLab.Algorithms.DataAnalysis {
   public static class KMeansClusteringUtil {
-    public static IEnumerable<int> FindClosestCenters(IEnumerable<double[]> centers, Dataset dataset, IEnumerable<string> allowedInputVariables, IEnumerable<int> rows) {
+    public static IEnumerable<int> FindClosestCenters(IEnumerable<double[]> centers, IDataset dataset, IEnumerable<string> allowedInputVariables, IEnumerable<int> rows) {
       int nRows = rows.Count();
       int nCols = allowedInputVariables.Count();
@@ -58,5 +58,5 @@
     }
 
-    public static double CalculateIntraClusterSumOfSquares(KMeansClusteringModel model, Dataset dataset, IEnumerable<int> rows) {
+    public static double CalculateIntraClusterSumOfSquares(KMeansClusteringModel model, IDataset dataset, IEnumerable<int> rows) {
       List<int> clusterValues = model.GetClusterValues(dataset, rows).ToList();
       List<string> allowedInputVariables = model.AllowedInputVariables.ToList();
Index: /stable/HeuristicLab.DataPreprocessing/3.4/Implementations/PreprocessingData.cs
===================================================================
--- /stable/HeuristicLab.DataPreprocessing/3.4/Implementations/PreprocessingData.cs	(revision 12701)
+++ /stable/HeuristicLab.DataPreprocessing/3.4/Implementations/PreprocessingData.cs	(revision 12702)
@@ -94,5 +94,5 @@
       selection = new Dictionary<int, IList<int>>();
 
-      Dataset dataset = problemData.Dataset;
+      Dataset dataset = (Dataset)problemData.Dataset;
       variableNames = new List<string>(problemData.Dataset.VariableNames);
 
Index: /stable/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding/3.4/Crossovers/SubtreeCrossover.cs
===================================================================
--- /stable/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding/3.4/Crossovers/SubtreeCrossover.cs	(revision 12701)
+++ /stable/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding/3.4/Crossovers/SubtreeCrossover.cs	(revision 12702)
@@ -134,5 +134,7 @@
       parent0.Root.ForEachNodePostfix((n) => {
         if (n.SubtreeCount > 0 && n != parent0.Root) {
-          foreach (var child in n.Subtrees) {
+          //avoid linq to reduce memory pressure
+          for (int i = 0; i < n.SubtreeCount; i++) {
+            var child = n.GetSubtree(i);
             if (child.GetLength() <= maxBranchLength &&
                 child.GetDepth() <= maxBranchDepth) {
Index: /stable/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding/3.4/Grammars/SymbolicExpressionGrammarBase.cs
===================================================================
--- /stable/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding/3.4/Grammars/SymbolicExpressionGrammarBase.cs	(revision 12701)
+++ /stable/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding/3.4/Grammars/SymbolicExpressionGrammarBase.cs	(revision 12702)
@@ -330,7 +330,11 @@
         List<string> temp;
         if (allowedChildSymbols.TryGetValue(parent.Name, out temp)) {
-          if (temp.SelectMany(s => GetSymbol(s).Flatten()).Any(s => s.Name == child.Name)) {
-            cachedIsAllowedChildSymbol.Add(key, true);
-            return true;
+          for (int i = 0; i < temp.Count; i++) {
+            var symbol = GetSymbol(temp[i]);
+            foreach (var s in symbol.Flatten())
+              if (s.Name == child.Name) {
+                cachedIsAllowedChildSymbol.Add(key, true);
+                return true;
+              }
           }
         }
@@ -357,7 +361,11 @@
         List<string> temp;
         if (allowedChildSymbolsPerIndex.TryGetValue(Tuple.Create(parent.Name, argumentIndex), out temp)) {
-          if (temp.SelectMany(s => GetSymbol(s).Flatten()).Any(s => s.Name == child.Name)) {
-            cachedIsAllowedChildSymbolIndex.Add(key, true);
-            return true;
+          for (int i = 0; i < temp.Count; i++) {
+            var symbol = GetSymbol(temp[i]);
+            foreach (var s in symbol.Flatten())
+              if (s.Name == child.Name) {
+                cachedIsAllowedChildSymbolIndex.Add(key, true);
+                return true;
+              }
           }
         }
Index: /stable/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding/3.4/SymbolicExpressionTreeNode.cs
===================================================================
--- /stable/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding/3.4/SymbolicExpressionTreeNode.cs	(revision 12701)
+++ /stable/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding/3.4/SymbolicExpressionTreeNode.cs	(revision 12702)
@@ -175,5 +175,5 @@
 
     public IEnumerable<ISymbolicExpressionTreeNode> IterateNodesBreadth() {
-      var list = new List<ISymbolicExpressionTreeNode>() { this };
+      var list = new List<ISymbolicExpressionTreeNode>(GetLength()) { this };
       int i = 0;
       while (i != list.Count) {
@@ -193,7 +193,8 @@
     public void ForEachNodePrefix(Action<ISymbolicExpressionTreeNode> a) {
       a(this);
-      if (Subtrees != null) {
-        foreach (var subtree in Subtrees) {
-          subtree.ForEachNodePrefix(a);
+      if (subtrees != null) {
+        //avoid linq to reduce memory pressure
+        for (int i = 0; i < subtrees.Count; i++) {
+          subtrees[i].ForEachNodePrefix(a);
         }
       }
@@ -207,7 +208,8 @@
 
     public void ForEachNodePostfix(Action<ISymbolicExpressionTreeNode> a) {
-      if (Subtrees != null) {
-        foreach (var subtree in Subtrees) {
-          subtree.ForEachNodePostfix(a);
+      if (subtrees != null) {
+        //avoid linq to reduce memory pressure
+        for (int i = 0; i < subtrees.Count; i++) {
+          subtrees[i].ForEachNodePostfix(a);
         }
       }
Index: /stable/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SymbolicClassificationModel.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SymbolicClassificationModel.cs	(revision 12701)
+++ /stable/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SymbolicClassificationModel.cs	(revision 12702)
@@ -41,5 +41,5 @@
       : base(tree, interpreter, lowerEstimationLimit, upperEstimationLimit) { }
 
-    public abstract IEnumerable<double> GetEstimatedClassValues(Dataset dataset, IEnumerable<int> rows);
+    public abstract IEnumerable<double> GetEstimatedClassValues(IDataset dataset, IEnumerable<int> rows);
     public abstract void RecalculateModelParameters(IClassificationProblemData problemData, IEnumerable<int> rows);
 
Index: /stable/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SymbolicDiscriminantFunctionClassificationModel.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SymbolicDiscriminantFunctionClassificationModel.cs	(revision 12701)
+++ /stable/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SymbolicDiscriminantFunctionClassificationModel.cs	(revision 12702)
@@ -88,7 +88,7 @@
       var classValuesArr = classValues.ToArray();
       var thresholdsArr = thresholds.ToArray();
-      if (thresholdsArr.Length != classValuesArr.Length || thresholdsArr.Length < 1) 
+      if (thresholdsArr.Length != classValuesArr.Length || thresholdsArr.Length < 1)
         throw new ArgumentException();
-      if (!double.IsNegativeInfinity(thresholds.First())) 
+      if (!double.IsNegativeInfinity(thresholds.First()))
         throw new ArgumentException();
 
@@ -107,9 +107,9 @@
     }
 
-    public IEnumerable<double> GetEstimatedValues(Dataset dataset, IEnumerable<int> rows) {
+    public IEnumerable<double> GetEstimatedValues(IDataset dataset, IEnumerable<int> rows) {
       return Interpreter.GetSymbolicExpressionTreeValues(SymbolicExpressionTree, dataset, rows).LimitToRange(LowerEstimationLimit, UpperEstimationLimit);
     }
 
-    public override IEnumerable<double> GetEstimatedClassValues(Dataset dataset, IEnumerable<int> rows) {
+    public override IEnumerable<double> GetEstimatedClassValues(IDataset dataset, IEnumerable<int> rows) {
       if (!Thresholds.Any() && !ClassValues.Any()) throw new ArgumentException("No thresholds and class values were set for the current symbolic classification model.");
       foreach (var x in GetEstimatedValues(dataset, rows)) {
Index: /stable/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SymbolicNearestNeighbourClassificationModel.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SymbolicNearestNeighbourClassificationModel.cs	(revision 12701)
+++ /stable/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SymbolicNearestNeighbourClassificationModel.cs	(revision 12702)
@@ -66,5 +66,5 @@
     }
 
-    public override IEnumerable<double> GetEstimatedClassValues(Dataset dataset, IEnumerable<int> rows) {
+    public override IEnumerable<double> GetEstimatedClassValues(IDataset dataset, IEnumerable<int> rows) {
       var estimatedValues = Interpreter.GetSymbolicExpressionTreeValues(SymbolicExpressionTree, dataset, rows)
                                        .LimitToRange(LowerEstimationLimit, UpperEstimationLimit);
Index: /stable/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SingleObjective/Evaluators/SymbolicRegressionConstantOptimizationEvaluator.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SingleObjective/Evaluators/SymbolicRegressionConstantOptimizationEvaluator.cs	(revision 12701)
+++ /stable/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SingleObjective/Evaluators/SymbolicRegressionConstantOptimizationEvaluator.cs	(revision 12702)
@@ -202,5 +202,5 @@
       int info;
 
-      Dataset ds = problemData.Dataset;
+      IDataset ds = problemData.Dataset;
       double[,] x = new double[rows.Count(), variableNames.Count];
       int row = 0;
Index: /stable/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SymbolicRegressionModel.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SymbolicRegressionModel.cs	(revision 12701)
+++ /stable/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SymbolicRegressionModel.cs	(revision 12702)
@@ -47,5 +47,5 @@
     }
 
-    public IEnumerable<double> GetEstimatedValues(Dataset dataset, IEnumerable<int> rows) {
+    public IEnumerable<double> GetEstimatedValues(IDataset dataset, IEnumerable<int> rows) {
       return Interpreter.GetSymbolicExpressionTreeValues(SymbolicExpressionTree, dataset, rows)
         .LimitToRange(LowerEstimationLimit, UpperEstimationLimit);
Index: /stable/HeuristicLab.Problems.DataAnalysis.Symbolic.TimeSeriesPrognosis/3.4/Interfaces/ISymbolicTimeSeriesPrognogisExpressionTreeInterpreter.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis.Symbolic.TimeSeriesPrognosis/3.4/Interfaces/ISymbolicTimeSeriesPrognogisExpressionTreeInterpreter.cs	(revision 12701)
+++ /stable/HeuristicLab.Problems.DataAnalysis.Symbolic.TimeSeriesPrognosis/3.4/Interfaces/ISymbolicTimeSeriesPrognogisExpressionTreeInterpreter.cs	(revision 12702)
@@ -26,6 +26,6 @@
   public interface ISymbolicTimeSeriesPrognosisExpressionTreeInterpreter : ISymbolicDataAnalysisExpressionTreeInterpreter {
     string TargetVariable { get; set; }
-    IEnumerable<IEnumerable<double>> GetSymbolicExpressionTreeValues(ISymbolicExpressionTree tree, Dataset dataset, IEnumerable<int> rows, int horizon);
-    IEnumerable<IEnumerable<double>> GetSymbolicExpressionTreeValues(ISymbolicExpressionTree tree, Dataset dataset, IEnumerable<int> rows, IEnumerable<int> horizon);
+    IEnumerable<IEnumerable<double>> GetSymbolicExpressionTreeValues(ISymbolicExpressionTree tree, IDataset dataset, IEnumerable<int> rows, int horizon);
+    IEnumerable<IEnumerable<double>> GetSymbolicExpressionTreeValues(ISymbolicExpressionTree tree, IDataset dataset, IEnumerable<int> rows, IEnumerable<int> horizon);
   }
 }
Index: /stable/HeuristicLab.Problems.DataAnalysis.Symbolic.TimeSeriesPrognosis/3.4/SymbolicTimeSeriesPrognosisExpressionTreeInterpreter.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis.Symbolic.TimeSeriesPrognosis/3.4/SymbolicTimeSeriesPrognosisExpressionTreeInterpreter.cs	(revision 12701)
+++ /stable/HeuristicLab.Problems.DataAnalysis.Symbolic.TimeSeriesPrognosis/3.4/SymbolicTimeSeriesPrognosisExpressionTreeInterpreter.cs	(revision 12702)
@@ -69,9 +69,9 @@
 
     // for each row several (=#horizon) future predictions
-    public IEnumerable<IEnumerable<double>> GetSymbolicExpressionTreeValues(ISymbolicExpressionTree tree, Dataset dataset, IEnumerable<int> rows, int horizon) {
+    public IEnumerable<IEnumerable<double>> GetSymbolicExpressionTreeValues(ISymbolicExpressionTree tree, IDataset dataset, IEnumerable<int> rows, int horizon) {
       return GetSymbolicExpressionTreeValues(tree, dataset, rows, rows.Select(row => horizon));
     }
 
-    public IEnumerable<IEnumerable<double>> GetSymbolicExpressionTreeValues(ISymbolicExpressionTree tree, Dataset dataset, IEnumerable<int> rows, IEnumerable<int> horizons) {
+    public IEnumerable<IEnumerable<double>> GetSymbolicExpressionTreeValues(ISymbolicExpressionTree tree, IDataset dataset, IEnumerable<int> rows, IEnumerable<int> horizons) {
       if (CheckExpressionsWithIntervalArithmetic.Value)
         throw new NotSupportedException("Interval arithmetic is not yet supported in the symbolic data analysis interpreter.");
@@ -116,5 +116,5 @@
     }
 
-    private static InterpreterState PrepareInterpreterState(ISymbolicExpressionTree tree, Dataset dataset, double[] targetVariableCache, string targetVariable) {
+    private static InterpreterState PrepareInterpreterState(ISymbolicExpressionTree tree, IDataset dataset, double[] targetVariableCache, string targetVariable) {
       Instruction[] code = SymbolicExpressionTreeCompiler.Compile(tree, OpCodes.MapSymbolToOpCode);
       int necessaryArgStackSize = 0;
Index: /stable/HeuristicLab.Problems.DataAnalysis.Symbolic.TimeSeriesPrognosis/3.4/SymbolicTimeSeriesPrognosisModel.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis.Symbolic.TimeSeriesPrognosis/3.4/SymbolicTimeSeriesPrognosisModel.cs	(revision 12701)
+++ /stable/HeuristicLab.Problems.DataAnalysis.Symbolic.TimeSeriesPrognosis/3.4/SymbolicTimeSeriesPrognosisModel.cs	(revision 12702)
@@ -49,5 +49,5 @@
     public SymbolicTimeSeriesPrognosisModel(ISymbolicExpressionTree tree, ISymbolicTimeSeriesPrognosisExpressionTreeInterpreter interpreter, double lowerLimit = double.MinValue, double upperLimit = double.MaxValue) : base(tree, interpreter, lowerLimit, upperLimit) { }
 
-    public IEnumerable<IEnumerable<double>> GetPrognosedValues(Dataset dataset, IEnumerable<int> rows, IEnumerable<int> horizons) {
+    public IEnumerable<IEnumerable<double>> GetPrognosedValues(IDataset dataset, IEnumerable<int> rows, IEnumerable<int> horizons) {
       var estimatedValues = Interpreter.GetSymbolicExpressionTreeValues(SymbolicExpressionTree, dataset, rows, horizons);
       return estimatedValues.Select(predictionPerRow => predictionPerRow.LimitToRange(LowerEstimationLimit, UpperEstimationLimit));
Index: /stable/HeuristicLab.Problems.DataAnalysis.Symbolic.Views/3.4/Exporters/SymbolicSolutionExcelExporter.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis.Symbolic.Views/3.4/Exporters/SymbolicSolutionExcelExporter.cs	(revision 12701)
+++ /stable/HeuristicLab.Problems.DataAnalysis.Symbolic.Views/3.4/Exporters/SymbolicSolutionExcelExporter.cs	(revision 12702)
@@ -324,5 +324,5 @@
     }
 
-    protected void WriteInputSheet(ExcelWorksheet inputsWorksheet, ExcelWorksheet datasetWorksheet, IEnumerable<string> list, Dataset dataset) {
+    protected void WriteInputSheet(ExcelWorksheet inputsWorksheet, ExcelWorksheet datasetWorksheet, IEnumerable<string> list, IDataset dataset) {
       //remark the performance of EPPlus drops dramatically 
       //if the data is not written row wise (from left to right) due the internal indices used.
@@ -341,5 +341,5 @@
       //remark the performance of EPPlus drops dramatically 
       //if the data is not written row wise (from left to right) due the internal indices used.
-      Dataset dataset = problemData.Dataset;
+      IDataset dataset = problemData.Dataset;
       var variableNames = dataset.VariableNames.ToList();
       var doubleVariables = new HashSet<string>(dataset.DoubleVariables);
Index: /stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/SymbolicDataAnalysisExpressionExcelFormatter.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/SymbolicDataAnalysisExpressionExcelFormatter.cs	(revision 12701)
+++ /stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/SymbolicDataAnalysisExpressionExcelFormatter.cs	(revision 12702)
@@ -71,5 +71,5 @@
     }
 
-    public string Format(ISymbolicExpressionTree symbolicExpressionTree, Dataset dataset) {
+    public string Format(ISymbolicExpressionTree symbolicExpressionTree, IDataset dataset) {
       var stringBuilder = new StringBuilder();
       if (dataset != null) CalculateVariableMapping(symbolicExpressionTree, dataset);
@@ -85,5 +85,5 @@
     }
 
-    private void CalculateVariableMapping(ISymbolicExpressionTree tree, Dataset dataset) {
+    private void CalculateVariableMapping(ISymbolicExpressionTree tree, IDataset dataset) {
       int columnIndex = 0;
       int inputIndex = 0;
Index: /stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/ISymbolicDataAnalysisExpressionTreeInterpreter.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/ISymbolicDataAnalysisExpressionTreeInterpreter.cs	(revision 12701)
+++ /stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/ISymbolicDataAnalysisExpressionTreeInterpreter.cs	(revision 12702)
@@ -27,5 +27,5 @@
 namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
   public interface ISymbolicDataAnalysisExpressionTreeInterpreter : INamedItem, IStatefulItem {
-    IEnumerable<double> GetSymbolicExpressionTreeValues(ISymbolicExpressionTree tree, Dataset dataset, IEnumerable<int> rows);
+    IEnumerable<double> GetSymbolicExpressionTreeValues(ISymbolicExpressionTree tree, IDataset dataset, IEnumerable<int> rows);
     IntValue EvaluatedSolutions { get; set; }
   }
Index: /stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeILEmittingInterpreter.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeILEmittingInterpreter.cs	(revision 12701)
+++ /stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeILEmittingInterpreter.cs	(revision 12702)
@@ -138,5 +138,5 @@
     #endregion
 
-    public IEnumerable<double> GetSymbolicExpressionTreeValues(ISymbolicExpressionTree tree, Dataset dataset, IEnumerable<int> rows) {
+    public IEnumerable<double> GetSymbolicExpressionTreeValues(ISymbolicExpressionTree tree, IDataset dataset, IEnumerable<int> rows) {
       if (CheckExpressionsWithIntervalArithmetic.Value)
         throw new NotSupportedException("Interval arithmetic is not yet supported in the symbolic data analysis interpreter.");
@@ -161,5 +161,5 @@
     }
 
-    private InterpreterState PrepareInterpreterState(ISymbolicExpressionTree tree, Dataset dataset) {
+    private InterpreterState PrepareInterpreterState(ISymbolicExpressionTree tree, IDataset dataset) {
       Instruction[] code = SymbolicExpressionTreeCompiler.Compile(tree, OpCodes.MapSymbolToOpCode);
       Dictionary<string, int> doubleVariableNames = dataset.DoubleVariables.Select((x, i) => new { x, i }).ToDictionary(e => e.x, e => e.i);
@@ -182,5 +182,5 @@
     }
 
-    private void CompileInstructions(ILGenerator il, InterpreterState state, Dataset ds) {
+    private void CompileInstructions(ILGenerator il, InterpreterState state, IDataset ds) {
       Instruction currentInstr = state.NextInstruction();
       int nArgs = currentInstr.nArguments;
Index: /stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeInterpreter.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeInterpreter.cs	(revision 12701)
+++ /stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeInterpreter.cs	(revision 12702)
@@ -95,5 +95,5 @@
     #endregion
 
-    public IEnumerable<double> GetSymbolicExpressionTreeValues(ISymbolicExpressionTree tree, Dataset dataset, IEnumerable<int> rows) {
+    public IEnumerable<double> GetSymbolicExpressionTreeValues(ISymbolicExpressionTree tree, IDataset dataset, IEnumerable<int> rows) {
       if (CheckExpressionsWithIntervalArithmetic.Value)
         throw new NotSupportedException("Interval arithmetic is not yet supported in the symbolic data analysis interpreter.");
@@ -111,5 +111,5 @@
     }
 
-    private static InterpreterState PrepareInterpreterState(ISymbolicExpressionTree tree, Dataset dataset) {
+    private static InterpreterState PrepareInterpreterState(ISymbolicExpressionTree tree, IDataset dataset) {
       Instruction[] code = SymbolicExpressionTreeCompiler.Compile(tree, OpCodes.MapSymbolToOpCode);
       int necessaryArgStackSize = 0;
@@ -132,5 +132,5 @@
 
 
-    public virtual double Evaluate(Dataset dataset, ref int row, InterpreterState state) {
+    public virtual double Evaluate(IDataset dataset, ref int row, InterpreterState state) {
       Instruction currentInstr = state.NextInstruction();
       switch (currentInstr.opCode) {
Index: /stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeLinearInterpreter.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeLinearInterpreter.cs	(revision 12701)
+++ /stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeLinearInterpreter.cs	(revision 12702)
@@ -102,5 +102,5 @@
     #endregion
 
-    public IEnumerable<double> GetSymbolicExpressionTreeValues(ISymbolicExpressionTree tree, Dataset dataset, IEnumerable<int> rows) {
+    public IEnumerable<double> GetSymbolicExpressionTreeValues(ISymbolicExpressionTree tree, IDataset dataset, IEnumerable<int> rows) {
       if (CheckExpressionsWithIntervalArithmetic.Value)
         throw new NotSupportedException("Interval arithmetic is not yet supported in the symbolic data analysis interpreter.");
@@ -115,5 +115,5 @@
     }
 
-    private double Evaluate(Dataset dataset, int row, LinearInstruction[] code) {
+    private double Evaluate(IDataset dataset, int row, LinearInstruction[] code) {
       for (int i = code.Length - 1; i >= 0; --i) {
         if (code[i].skip) continue;
@@ -352,5 +352,5 @@
     }
 
-    public static void PrepareInstructions(LinearInstruction[] code, Dataset dataset) {
+    public static void PrepareInstructions(LinearInstruction[] code, IDataset dataset) {
       for (int i = 0; i != code.Length; ++i) {
         var instr = code[i];
Index: /stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisSolutionImpactValuesCalculator.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisSolutionImpactValuesCalculator.cs	(revision 12701)
+++ /stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisSolutionImpactValuesCalculator.cs	(revision 12702)
@@ -41,5 +41,5 @@
 
     protected static double CalculateReplacementValue(ISymbolicExpressionTreeNode node, ISymbolicExpressionTree sourceTree, ISymbolicDataAnalysisExpressionTreeInterpreter interpreter,
-      Dataset dataset, IEnumerable<int> rows) {
+      IDataset dataset, IEnumerable<int> rows) {
       //optimization: constant nodes return always the same value
       ConstantTreeNode constantNode = node as ConstantTreeNode;
Index: /stable/HeuristicLab.Problems.DataAnalysis.Trading/3.4/Interfaces/IModel.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis.Trading/3.4/Interfaces/IModel.cs	(revision 12701)
+++ /stable/HeuristicLab.Problems.DataAnalysis.Trading/3.4/Interfaces/IModel.cs	(revision 12702)
@@ -23,5 +23,5 @@
 namespace HeuristicLab.Problems.DataAnalysis.Trading {
   public interface IModel : IDataAnalysisModel {
-    IEnumerable<double> GetSignals(Dataset dataset, IEnumerable<int> rows);
+    IEnumerable<double> GetSignals(IDataset dataset, IEnumerable<int> rows);
   }
 }
Index: /stable/HeuristicLab.Problems.DataAnalysis.Trading/3.4/Symbolic/Model.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis.Trading/3.4/Symbolic/Model.cs	(revision 12701)
+++ /stable/HeuristicLab.Problems.DataAnalysis.Trading/3.4/Symbolic/Model.cs	(revision 12702)
@@ -47,5 +47,5 @@
     }
 
-    public IEnumerable<double> GetSignals(Dataset dataset, IEnumerable<int> rows) {
+    public IEnumerable<double> GetSignals(IDataset dataset, IEnumerable<int> rows) {
       ISymbolicDataAnalysisExpressionTreeInterpreter interpreter = Interpreter;
       ISymbolicExpressionTree tree = SymbolicExpressionTree;
Index: /stable/HeuristicLab.Problems.DataAnalysis.Trading/3.4/Symbolic/SingleObjective/ProfitEvaluator.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis.Trading/3.4/Symbolic/SingleObjective/ProfitEvaluator.cs	(revision 12701)
+++ /stable/HeuristicLab.Problems.DataAnalysis.Trading/3.4/Symbolic/SingleObjective/ProfitEvaluator.cs	(revision 12702)
@@ -66,5 +66,5 @@
     }
 
-    private static IEnumerable<double> GetSignals(ISymbolicDataAnalysisExpressionTreeInterpreter interpreter, ISymbolicExpressionTree solution, Dataset dataset, IEnumerable<int> rows) {
+    private static IEnumerable<double> GetSignals(ISymbolicDataAnalysisExpressionTreeInterpreter interpreter, ISymbolicExpressionTree solution, IDataset dataset, IEnumerable<int> rows) {
       return Model.GetSignals(interpreter.GetSymbolicExpressionTreeValues(solution, dataset, rows));
     }
Index: /stable/HeuristicLab.Problems.DataAnalysis.Trading/3.4/Symbolic/SingleObjective/SharpeRatioEvaluator.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis.Trading/3.4/Symbolic/SingleObjective/SharpeRatioEvaluator.cs	(revision 12701)
+++ /stable/HeuristicLab.Problems.DataAnalysis.Trading/3.4/Symbolic/SingleObjective/SharpeRatioEvaluator.cs	(revision 12702)
@@ -66,5 +66,5 @@
     }
 
-    private static IEnumerable<double> GetSignals(ISymbolicDataAnalysisExpressionTreeInterpreter interpreter, ISymbolicExpressionTree solution, Dataset dataset, IEnumerable<int> rows) {
+    private static IEnumerable<double> GetSignals(ISymbolicDataAnalysisExpressionTreeInterpreter interpreter, ISymbolicExpressionTree solution, IDataset dataset, IEnumerable<int> rows) {
       return Model.GetSignals(interpreter.GetSymbolicExpressionTreeValues(solution, dataset, rows));
     }
Index: /stable/HeuristicLab.Problems.DataAnalysis.Views/3.4/Clustering/ClusteringSolutionVisualizationView.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis.Views/3.4/Clustering/ClusteringSolutionVisualizationView.cs	(revision 12701)
+++ /stable/HeuristicLab.Problems.DataAnalysis.Views/3.4/Clustering/ClusteringSolutionVisualizationView.cs	(revision 12702)
@@ -89,5 +89,5 @@
     }
 
-    private static double[,] PCAReduce(Dataset dataset, IEnumerable<int> rows, IEnumerable<string> variables) {
+    private static double[,] PCAReduce(IDataset dataset, IEnumerable<int> rows, IEnumerable<string> variables) {
       var instances = rows.ToArray();
       var attributes = variables.ToArray();
Index: /stable/HeuristicLab.Problems.DataAnalysis.Views/3.4/FeatureCorrelation/FeatureCorrelationCalculator.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis.Views/3.4/FeatureCorrelation/FeatureCorrelationCalculator.cs	(revision 12701)
+++ /stable/HeuristicLab.Problems.DataAnalysis.Views/3.4/FeatureCorrelation/FeatureCorrelationCalculator.cs	(revision 12702)
@@ -72,5 +72,5 @@
     }
 
-    private void CalculateElements(Dataset dataset, IDependencyCalculator calc, string partition, string variable = null, int frames = 0, double[,] alreadyCalculated = null) {
+    private void CalculateElements(IDataset dataset, IDependencyCalculator calc, string partition, string variable = null, int frames = 0, double[,] alreadyCalculated = null) {
       var indices = GetRelevantIndices(problemData, partition);
       bwInfo = new BackgroundWorkerInfo {
@@ -117,5 +117,5 @@
 
       BackgroundWorkerInfo bwInfo = (BackgroundWorkerInfo)e.Argument;
-      Dataset dataset = bwInfo.Dataset;
+      var dataset = bwInfo.Dataset;
       IEnumerable<int> indices = bwInfo.Indices;
       IDependencyCalculator calc = bwInfo.Calculator;
@@ -156,5 +156,5 @@
 
       BackgroundWorkerInfo bwInfo = (BackgroundWorkerInfo)e.Argument;
-      Dataset dataset = bwInfo.Dataset;
+      var dataset = bwInfo.Dataset;
       IEnumerable<int> indices = bwInfo.Indices;
       IDependencyCalculator calc = bwInfo.Calculator;
@@ -255,5 +255,5 @@
 
     private class BackgroundWorkerInfo {
-      public Dataset Dataset { get; set; }
+      public IDataset Dataset { get; set; }
       public IDependencyCalculator Calculator { get; set; }
       public string Partition { get; set; }
Index: /stable/HeuristicLab.Problems.DataAnalysis.Views/3.4/HeuristicLab.Problems.DataAnalysis.Views-3.4.csproj
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis.Views/3.4/HeuristicLab.Problems.DataAnalysis.Views-3.4.csproj	(revision 12701)
+++ /stable/HeuristicLab.Problems.DataAnalysis.Views/3.4/HeuristicLab.Problems.DataAnalysis.Views-3.4.csproj	(revision 12702)
@@ -177,4 +177,10 @@
     <Compile Include="Interfaces\IDataPreprocessorStarter.cs" />
     <Compile Include="MenuItems\ShrinkDataAnalysisRunsMenuItem.cs" />
+    <Compile Include="ModifiableDatasetView.cs">
+      <SubType>UserControl</SubType>
+    </Compile>
+    <Compile Include="ModifiableDatasetView.Designer.cs">
+      <DependentUpon>ModifiableDatasetView.cs</DependentUpon>
+    </Compile>
     <Compile Include="Plugin.cs" />
     <Compile Include="ProblemDataView.cs">
Index: /stable/HeuristicLab.Problems.DataAnalysis.Views/3.4/MenuItems/ShrinkDataAnalysisRunsMenuItem.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis.Views/3.4/MenuItems/ShrinkDataAnalysisRunsMenuItem.cs	(revision 12701)
+++ /stable/HeuristicLab.Problems.DataAnalysis.Views/3.4/MenuItems/ShrinkDataAnalysisRunsMenuItem.cs	(revision 12702)
@@ -82,7 +82,9 @@
         var variableValuesMapping = new Dictionary<ValuesType, ValuesType>();
         foreach (var problemData in view.Content.GetObjectGraphObjects(excludeStaticMembers: true).OfType<IDataAnalysisProblemData>()) {
-          var originalValues = variableValuesGetter(problemData.Dataset);
+          var dataset = problemData.Dataset as Dataset;
+          if (dataset == null) continue;
+          var originalValues = variableValuesGetter(dataset);
           var matchingValues = GetEqualValues(originalValues, variableValuesMapping);
-          variableValuesSetter(problemData.Dataset, matchingValues);
+          variableValuesSetter(dataset, matchingValues);
         }
       };
Index: /stable/HeuristicLab.Problems.DataAnalysis.Views/3.4/ModifiableDatasetView.Designer.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis.Views/3.4/ModifiableDatasetView.Designer.cs	(revision 12702)
+++ /stable/HeuristicLab.Problems.DataAnalysis.Views/3.4/ModifiableDatasetView.Designer.cs	(revision 12702)
@@ -0,0 +1,32 @@
+﻿namespace HeuristicLab.Problems.DataAnalysis.Views {
+  partial class ModifiableDatasetView {
+    /// <summary> 
+    /// Required designer variable.
+    /// </summary>
+    private System.ComponentModel.IContainer components = null;
+
+    /// <summary> 
+    /// Clean up any resources being used.
+    /// </summary>
+    /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+    protected override void Dispose(bool disposing) {
+      if (disposing && (components != null)) {
+        components.Dispose();
+      }
+      base.Dispose(disposing);
+    }
+
+    #region Component Designer generated code
+
+    /// <summary> 
+    /// Required method for Designer support - do not modify 
+    /// the contents of this method with the code editor.
+    /// </summary>
+    private void InitializeComponent() {
+      components = new System.ComponentModel.Container();
+      this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+    }
+
+    #endregion
+  }
+}
Index: /stable/HeuristicLab.Problems.DataAnalysis.Views/3.4/ModifiableDatasetView.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis.Views/3.4/ModifiableDatasetView.cs	(revision 12702)
+++ /stable/HeuristicLab.Problems.DataAnalysis.Views/3.4/ModifiableDatasetView.cs	(revision 12702)
@@ -0,0 +1,75 @@
+﻿#region License Information
+
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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.Windows.Forms;
+using HeuristicLab.Data.Views;
+using HeuristicLab.MainForm;
+
+namespace HeuristicLab.Problems.DataAnalysis.Views {
+  [View("ModifiableDataset View")]
+  [Content(typeof(ModifiableDataset), true)]
+  public partial class ModifiableDatasetView : StringConvertibleMatrixView {
+    public new ModifiableDataset Content {
+      get { return (ModifiableDataset)base.Content; }
+      set {
+        if (base.Content != value)
+          base.Content = value;
+      }
+    }
+
+    public ModifiableDatasetView() {
+      InitializeComponent();
+    }
+
+    #region register/deregister content events
+    protected override void RegisterContentEvents() {
+      base.RegisterContentEvents();
+      dataGridView.CellContentDoubleClick += dataGridView_cellContentDoubleClicked;
+      dataGridView.CellLeave += dataGridView_cellLeave;
+    }
+
+    protected override void DeregisterContentEvents() {
+      dataGridView.CellContentDoubleClick -= dataGridView_cellContentDoubleClicked;
+      dataGridView.CellLeave -= dataGridView_cellLeave;
+      base.DeregisterContentEvents();
+    }
+    #endregion
+
+    #region event handlers
+    private void dataGridView_cellContentDoubleClicked(object sender, DataGridViewCellEventArgs args) {
+      var currentCell = dataGridView[args.ColumnIndex, args.RowIndex];
+      dataGridView.ReadOnly = false;
+      currentCell.ReadOnly = false;
+      dataGridView.CurrentCell = currentCell;
+      dataGridView.BeginEdit(true);
+    }
+
+    private void dataGridView_cellLeave(object sender, DataGridViewCellEventArgs args) {
+      var currentCell = dataGridView[args.ColumnIndex, args.RowIndex];
+      dataGridView.ReadOnly = true;
+      currentCell.ReadOnly = true;
+      dataGridView.EndEdit();
+    }
+    #endregion
+  }
+}
Index: /stable/HeuristicLab.Problems.DataAnalysis.Views/3.4/Regression/RegressionSolutionScatterPlotView.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis.Views/3.4/Regression/RegressionSolutionScatterPlotView.cs	(revision 12701)
+++ /stable/HeuristicLab.Problems.DataAnalysis.Views/3.4/Regression/RegressionSolutionScatterPlotView.cs	(revision 12702)
@@ -142,5 +142,5 @@
       else {
         string targetVariableName = Content.ProblemData.TargetVariable;
-        Dataset dataset = Content.ProblemData.Dataset;
+        var dataset = Content.ProblemData.Dataset;
         if (this.chart.Series[ALL_SERIES].Points.Count > 0)
           this.chart.Series[ALL_SERIES].Points.DataBindXY(Content.EstimatedValues.ToArray(), "",
Index: /stable/HeuristicLab.Problems.DataAnalysis/3.4/Dataset.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis/3.4/Dataset.cs	(revision 12701)
+++ /stable/HeuristicLab.Problems.DataAnalysis/3.4/Dataset.cs	(revision 12702)
@@ -33,8 +33,8 @@
   [Item("Dataset", "Represents a dataset containing data that should be analyzed.")]
   [StorableClass]
-  public sealed class Dataset : NamedItem, IStringConvertibleMatrix {
+  public class Dataset : NamedItem, IDataset {
     [StorableConstructor]
-    private Dataset(bool deserializing) : base(deserializing) { }
-    private Dataset(Dataset original, Cloner cloner)
+    protected Dataset(bool deserializing) : base(deserializing) { }
+    protected Dataset(Dataset original, Cloner cloner)
       : base(original, cloner) {
       variableValues = new Dictionary<string, IList>(original.variableValues);
@@ -118,4 +118,6 @@
     }
 
+    protected Dataset(Dataset dataset) : this(dataset.variableNames, dataset.variableValues.Values) { }
+
     #region Backwards compatible code, remove with 3.5
     private double[,] storableData;
@@ -143,82 +145,51 @@
 
     [Storable(Name = "VariableValues")]
-    private Dictionary<string, IList> variableValues;
-
-    private List<string> variableNames;
+    protected Dictionary<string, IList> variableValues;
+
+    protected List<string> variableNames;
     [Storable]
     public IEnumerable<string> VariableNames {
       get { return variableNames; }
-      private set {
+      protected set {
         if (variableNames != null) throw new InvalidOperationException();
         variableNames = new List<string>(value);
       }
     }
-
     public IEnumerable<string> DoubleVariables {
       get { return variableValues.Where(p => p.Value is List<double>).Select(p => p.Key); }
     }
-
     public IEnumerable<double> GetDoubleValues(string variableName) {
+      return GetValues<double>(variableName);
+    }
+    public IEnumerable<string> GetStringValues(string variableName) {
+      return GetValues<string>(variableName);
+    }
+    public IEnumerable<DateTime> GetDateTimeValues(string variableName) {
+      return GetValues<DateTime>(variableName);
+    }
+
+    public ReadOnlyCollection<double> GetReadOnlyDoubleValues(string variableName) {
+      var values = GetValues<double>(variableName);
+      return values.AsReadOnly();
+    }
+    public double GetDoubleValue(string variableName, int row) {
+      var values = GetValues<double>(variableName);
+      return values[row];
+    }
+    public IEnumerable<double> GetDoubleValues(string variableName, IEnumerable<int> rows) {
+      return GetValues<double>(variableName, rows);
+    }
+    private IEnumerable<T> GetValues<T>(string variableName, IEnumerable<int> rows) {
+      var values = GetValues<T>(variableName);
+      return rows.Select(x => values[x]);
+    }
+    private List<T> GetValues<T>(string variableName) {
       IList list;
       if (!variableValues.TryGetValue(variableName, out list))
         throw new ArgumentException("The variable " + variableName + " does not exist in the dataset.");
-      List<double> values = list as List<double>;
-      if (values == null) throw new ArgumentException("The variable " + variableName + " is not a double variable.");
-
-      //mkommend yield return used to enable lazy evaluation
-      foreach (double value in values)
-        yield return value;
-    }
-
-    public IEnumerable<string> GetStringValues(string variableName) {
-      IList list;
-      if (!variableValues.TryGetValue(variableName, out list))
-        throw new ArgumentException("The variable " + variableName + " does not exist in the dataset.");
-      List<string> values = list as List<string>;
-      if (values == null) throw new ArgumentException("The variable " + variableName + " is not a string variable.");
-
-      //mkommend yield return used to enable lazy evaluation
-      foreach (string value in values)
-        yield return value;
-    }
-
-    public IEnumerable<DateTime> GetDateTimeValues(string variableName) {
-      IList list;
-      if (!variableValues.TryGetValue(variableName, out list))
-        throw new ArgumentException("The variable " + variableName + " does not exist in the dataset.");
-      List<DateTime> values = list as List<DateTime>;
-      if (values == null) throw new ArgumentException("The variable " + variableName + " is not a datetime variable.");
-
-      //mkommend yield return used to enable lazy evaluation
-      foreach (DateTime value in values)
-        yield return value;
-    }
-
-    public ReadOnlyCollection<double> GetReadOnlyDoubleValues(string variableName) {
-      IList list;
-      if (!variableValues.TryGetValue(variableName, out list))
-        throw new ArgumentException("The variable " + variableName + " does not exist in the dataset.");
-      List<double> values = list as List<double>;
-      if (values == null) throw new ArgumentException("The variable " + variableName + " is not a double variable.");
-      return values.AsReadOnly();
-    }
-    public double GetDoubleValue(string variableName, int row) {
-      IList list;
-      if (!variableValues.TryGetValue(variableName, out list))
-        throw new ArgumentException("The variable " + variableName + " does not exist in the dataset.");
-      List<double> values = list as List<double>;
-      if (values == null) throw new ArgumentException("The variable " + variableName + " is not a double variable.");
-      return values[row];
-    }
-    public IEnumerable<double> GetDoubleValues(string variableName, IEnumerable<int> rows) {
-      IList list;
-      if (!variableValues.TryGetValue(variableName, out list))
-        throw new ArgumentException("The variable " + variableName + " does not exist in the dataset.");
-      List<double> values = list as List<double>;
-      if (values == null) throw new ArgumentException("The variable " + variableName + " is not a double variable.");
-
-      return rows.Select(index => values[index]);
-    }
-
+      List<T> values = list as List<T>;
+      if (values == null) throw new ArgumentException("The variable " + variableName + " is not a " + typeof(T) + " variable.");
+      return values;
+    }
     public bool VariableHasType<T>(string variableName) {
       return variableValues[variableName] is IList<T>;
@@ -227,5 +198,5 @@
     #region IStringConvertibleMatrix Members
     [Storable]
-    private int rows;
+    protected int rows;
     public int Rows {
       get { return rows; }
@@ -236,5 +207,4 @@
       set { throw new NotSupportedException(); }
     }
-
     public bool SortableView {
       get { return false; }
@@ -244,5 +214,4 @@
       get { return true; }
     }
-
     IEnumerable<string> IStringConvertibleMatrix.ColumnNames {
       get { return this.VariableNames; }
@@ -253,22 +222,21 @@
       set { throw new NotSupportedException(); }
     }
-
     public string GetValue(int rowIndex, int columnIndex) {
       return variableValues[variableNames[columnIndex]][rowIndex].ToString();
     }
-    public bool SetValue(string value, int rowIndex, int columnIndex) {
+    bool IStringConvertibleMatrix.SetValue(string value, int rowIndex, int columnIndex) {
       throw new NotSupportedException();
     }
-    public bool Validate(string value, out string errorMessage) {
+    bool IStringConvertibleMatrix.Validate(string value, out string errorMessage) {
       throw new NotSupportedException();
     }
 
-    public event EventHandler ColumnsChanged { add { } remove { } }
-    public event EventHandler RowsChanged { add { } remove { } }
-    public event EventHandler ColumnNamesChanged { add { } remove { } }
-    public event EventHandler RowNamesChanged { add { } remove { } }
-    public event EventHandler SortableViewChanged { add { } remove { } }
-    public event EventHandler<EventArgs<int, int>> ItemChanged { add { } remove { } }
-    public event EventHandler Reset { add { } remove { } }
+    public virtual event EventHandler ColumnsChanged { add { } remove { } }
+    public virtual event EventHandler RowsChanged { add { } remove { } }
+    public virtual event EventHandler ColumnNamesChanged { add { } remove { } }
+    public virtual event EventHandler RowNamesChanged { add { } remove { } }
+    public virtual event EventHandler SortableViewChanged { add { } remove { } }
+    public virtual event EventHandler<EventArgs<int, int>> ItemChanged { add { } remove { } }
+    public virtual event EventHandler Reset { add { } remove { } }
     #endregion
   }
Index: /stable/HeuristicLab.Problems.DataAnalysis/3.4/HeuristicLab.Problems.DataAnalysis-3.4.csproj
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis/3.4/HeuristicLab.Problems.DataAnalysis-3.4.csproj	(revision 12701)
+++ /stable/HeuristicLab.Problems.DataAnalysis/3.4/HeuristicLab.Problems.DataAnalysis-3.4.csproj	(revision 12702)
@@ -165,4 +165,5 @@
     <Compile Include="Interfaces\Classification\IDiscriminantFunctionThresholdCalculator.cs" />
     <Compile Include="Interfaces\IDataAnalysisSolutionExporter.cs" />
+    <Compile Include="Interfaces\IDataset.cs" />
     <Compile Include="Interfaces\IDependencyCalculator.cs" />
     <Compile Include="Interfaces\ITransformation.cs" />
@@ -178,4 +179,5 @@
     <Compile Include="Interfaces\TimeSeriesPrognosis\ITimeSeriesPrognosisProblemData.cs" />
     <Compile Include="Interfaces\TimeSeriesPrognosis\ITimeSeriesPrognosisSolution.cs" />
+    <Compile Include="ModifiableDataset.cs" />
     <Compile Include="OnlineCalculators\AutoCorrelationCalculator.cs" />
     <Compile Include="OnlineCalculators\ClassificationPerformanceMeasuresCalculator.cs" />
Index: /stable/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ClassificationEnsembleModel.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ClassificationEnsembleModel.cs	(revision 12701)
+++ /stable/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ClassificationEnsembleModel.cs	(revision 12702)
@@ -67,5 +67,5 @@
     }
 
-    public IEnumerable<IEnumerable<double>> GetEstimatedClassValueVectors(Dataset dataset, IEnumerable<int> rows) {
+    public IEnumerable<IEnumerable<double>> GetEstimatedClassValueVectors(IDataset dataset, IEnumerable<int> rows) {
       var estimatedValuesEnumerators = (from model in models
                                         select model.GetEstimatedClassValues(dataset, rows).GetEnumerator())
@@ -82,5 +82,5 @@
     #region IClassificationModel Members
 
-    public IEnumerable<double> GetEstimatedClassValues(Dataset dataset, IEnumerable<int> rows) {
+    public IEnumerable<double> GetEstimatedClassValues(IDataset dataset, IEnumerable<int> rows) {
       foreach (var estimatedValuesVector in GetEstimatedClassValueVectors(dataset, rows)) {
         // return the class which is most often occuring
Index: /stable/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ClassificationEnsembleSolution.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ClassificationEnsembleSolution.cs	(revision 12701)
+++ /stable/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ClassificationEnsembleSolution.cs	(revision 12702)
@@ -231,5 +231,5 @@
     }
 
-    public IEnumerable<IEnumerable<double>> GetEstimatedClassValueVectors(Dataset dataset, IEnumerable<int> rows) {
+    public IEnumerable<IEnumerable<double>> GetEstimatedClassValueVectors(IDataset dataset, IEnumerable<int> rows) {
       if (!Model.Models.Any()) yield break;
       var estimatedValuesEnumerators = (from model in Model.Models
Index: /stable/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ClassificationProblemData.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ClassificationProblemData.cs	(revision 12701)
+++ /stable/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ClassificationProblemData.cs	(revision 12702)
@@ -324,5 +324,5 @@
     }
 
-    public ClassificationProblemData(Dataset dataset, IEnumerable<string> allowedInputVariables, string targetVariable, IEnumerable<ITransformation> transformations = null)
+    public ClassificationProblemData(IDataset dataset, IEnumerable<string> allowedInputVariables, string targetVariable, IEnumerable<ITransformation> transformations = null)
       : base(dataset, allowedInputVariables, transformations ?? Enumerable.Empty<ITransformation>()) {
       var validTargetVariableValues = CheckVariablesForPossibleTargetVariables(dataset).Select(x => new StringValue(x).AsReadOnly()).ToList();
@@ -338,5 +338,5 @@
     }
 
-    public static IEnumerable<string> CheckVariablesForPossibleTargetVariables(Dataset dataset) {
+    public static IEnumerable<string> CheckVariablesForPossibleTargetVariables(IDataset dataset) {
       int maxSamples = Math.Min(InspectedRowsToDetermineTargets, dataset.Rows);
       var validTargetVariables = (from v in dataset.DoubleVariables
Index: /stable/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/DiscriminantFunctionClassificationModel.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/DiscriminantFunctionClassificationModel.cs	(revision 12701)
+++ /stable/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/DiscriminantFunctionClassificationModel.cs	(revision 12702)
@@ -111,9 +111,9 @@
 
 
-    public IEnumerable<double> GetEstimatedValues(Dataset dataset, IEnumerable<int> rows) {
+    public IEnumerable<double> GetEstimatedValues(IDataset dataset, IEnumerable<int> rows) {
       return model.GetEstimatedValues(dataset, rows);
     }
 
-    public IEnumerable<double> GetEstimatedClassValues(Dataset dataset, IEnumerable<int> rows) {
+    public IEnumerable<double> GetEstimatedClassValues(IDataset dataset, IEnumerable<int> rows) {
       if (!Thresholds.Any() && !ClassValues.Any()) throw new ArgumentException("No thresholds and class values were set for the current classification model.");
       foreach (var x in GetEstimatedValues(dataset, rows)) {
Index: /stable/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/DataAnalysisProblemData.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/DataAnalysisProblemData.cs	(revision 12701)
+++ /stable/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/DataAnalysisProblemData.cs	(revision 12702)
@@ -63,5 +63,5 @@
       get { return isEmpty; }
     }
-    public Dataset Dataset {
+    public IDataset Dataset {
       get { return DatasetParameter.Value; }
     }
@@ -126,5 +126,5 @@
     }
 
-    protected DataAnalysisProblemData(Dataset dataset, IEnumerable<string> allowedInputVariables, IEnumerable<ITransformation> transformations = null) {
+    protected DataAnalysisProblemData(IDataset dataset, IEnumerable<string> allowedInputVariables, IEnumerable<ITransformation> transformations = null) {
       if (dataset == null) throw new ArgumentNullException("The dataset must not be null.");
       if (allowedInputVariables == null) throw new ArgumentNullException("The allowedInputVariables must not be null.");
@@ -144,5 +144,5 @@
       var transformationsList = new ItemList<ITransformation>(transformations ?? Enumerable.Empty<ITransformation>());
 
-      Parameters.Add(new FixedValueParameter<Dataset>(DatasetParameterName, "", dataset));
+      Parameters.Add(new FixedValueParameter<Dataset>(DatasetParameterName, "", (Dataset)dataset));
       Parameters.Add(new FixedValueParameter<ReadOnlyCheckedItemList<StringValue>>(InputVariablesParameterName, "", inputVariables.AsReadOnly()));
       Parameters.Add(new FixedValueParameter<IntRange>(TrainingPartitionParameterName, "", new IntRange(trainingPartitionStart, trainingPartitionEnd)));
Index: /stable/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Regression/ConstantRegressionModel.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Regression/ConstantRegressionModel.cs	(revision 12701)
+++ /stable/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Regression/ConstantRegressionModel.cs	(revision 12702)
@@ -51,5 +51,5 @@
     }
 
-    public IEnumerable<double> GetEstimatedValues(Dataset dataset, IEnumerable<int> rows) {
+    public IEnumerable<double> GetEstimatedValues(IDataset dataset, IEnumerable<int> rows) {
       return rows.Select(row => Constant);
     }
Index: /stable/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Regression/RegressionEnsembleModel.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Regression/RegressionEnsembleModel.cs	(revision 12701)
+++ /stable/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Regression/RegressionEnsembleModel.cs	(revision 12702)
@@ -80,5 +80,5 @@
     }
 
-    public IEnumerable<IEnumerable<double>> GetEstimatedValueVectors(Dataset dataset, IEnumerable<int> rows) {
+    public IEnumerable<IEnumerable<double>> GetEstimatedValueVectors(IDataset dataset, IEnumerable<int> rows) {
       var estimatedValuesEnumerators = (from model in models
                                         select model.GetEstimatedValues(dataset, rows).GetEnumerator())
@@ -95,5 +95,5 @@
     #region IRegressionModel Members
 
-    public IEnumerable<double> GetEstimatedValues(Dataset dataset, IEnumerable<int> rows) {
+    public IEnumerable<double> GetEstimatedValues(IDataset dataset, IEnumerable<int> rows) {
       foreach (var estimatedValuesVector in GetEstimatedValueVectors(dataset, rows)) {
         yield return estimatedValuesVector.Average();
Index: /stable/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Regression/RegressionEnsembleSolution.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Regression/RegressionEnsembleSolution.cs	(revision 12701)
+++ /stable/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Regression/RegressionEnsembleSolution.cs	(revision 12702)
@@ -232,5 +232,5 @@
     }
 
-    public IEnumerable<IEnumerable<double>> GetEstimatedValueVectors(Dataset dataset, IEnumerable<int> rows) {
+    public IEnumerable<IEnumerable<double>> GetEstimatedValueVectors(IDataset dataset, IEnumerable<int> rows) {
       if (!Model.Models.Any()) yield break;
       var estimatedValuesEnumerators = (from model in Model.Models
Index: /stable/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Regression/RegressionProblemData.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Regression/RegressionProblemData.cs	(revision 12701)
+++ /stable/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Regression/RegressionProblemData.cs	(revision 12702)
@@ -137,5 +137,5 @@
     }
 
-    public RegressionProblemData(Dataset dataset, IEnumerable<string> allowedInputVariables, string targetVariable, IEnumerable<ITransformation> transformations = null)
+    public RegressionProblemData(IDataset dataset, IEnumerable<string> allowedInputVariables, string targetVariable, IEnumerable<ITransformation> transformations = null)
       : base(dataset, allowedInputVariables, transformations ?? Enumerable.Empty<ITransformation>()) {
       var variables = InputVariables.Select(x => x.AsReadOnly()).ToList();
Index: /stable/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Regression/RegressionSolution.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Regression/RegressionSolution.cs	(revision 12701)
+++ /stable/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Regression/RegressionSolution.cs	(revision 12702)
@@ -63,5 +63,5 @@
 
     public override IEnumerable<double> GetEstimatedValues(IEnumerable<int> rows) {
-      var rowsToEvaluate = rows.Except(evaluationCache.Keys);
+      var rowsToEvaluate = rows.Where(row => !evaluationCache.ContainsKey(row));
       var rowsEnumerator = rowsToEvaluate.GetEnumerator();
       var valuesEnumerator = Model.GetEstimatedValues(ProblemData.Dataset, rowsToEvaluate).GetEnumerator();
Index: /stable/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/TimeSeriesPrognosis/Models/ConstantTimeSeriesPrognosisModel.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/TimeSeriesPrognosis/Models/ConstantTimeSeriesPrognosisModel.cs	(revision 12701)
+++ /stable/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/TimeSeriesPrognosis/Models/ConstantTimeSeriesPrognosisModel.cs	(revision 12702)
@@ -39,5 +39,5 @@
     public ConstantTimeSeriesPrognosisModel(double constant) : base(constant) { }
 
-    public IEnumerable<IEnumerable<double>> GetPrognosedValues(Dataset dataset, IEnumerable<int> rows, IEnumerable<int> horizons) {
+    public IEnumerable<IEnumerable<double>> GetPrognosedValues(IDataset dataset, IEnumerable<int> rows, IEnumerable<int> horizons) {
       return horizons.Select(horizon => Enumerable.Repeat(Constant, horizon));
     }
Index: /stable/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/TimeSeriesPrognosis/Models/TimeSeriesPrognosisAutoRegressiveModel.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/TimeSeriesPrognosis/Models/TimeSeriesPrognosisAutoRegressiveModel.cs	(revision 12701)
+++ /stable/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/TimeSeriesPrognosis/Models/TimeSeriesPrognosisAutoRegressiveModel.cs	(revision 12702)
@@ -58,5 +58,5 @@
     }
 
-    public IEnumerable<IEnumerable<double>> GetPrognosedValues(Dataset dataset, IEnumerable<int> rows, IEnumerable<int> horizons) {
+    public IEnumerable<IEnumerable<double>> GetPrognosedValues(IDataset dataset, IEnumerable<int> rows, IEnumerable<int> horizons) {
       var rowsEnumerator = rows.GetEnumerator();
       var horizonsEnumerator = horizons.GetEnumerator();
@@ -91,5 +91,5 @@
     }
 
-    public IEnumerable<double> GetEstimatedValues(Dataset dataset, IEnumerable<int> rows) {
+    public IEnumerable<double> GetEstimatedValues(IDataset dataset, IEnumerable<int> rows) {
       var targetVariables = dataset.GetReadOnlyDoubleValues(TargetVariable);
       foreach (int row in rows) {
Index: /stable/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/TimeSeriesPrognosis/TimeSeriesPrognosisProblemData.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/TimeSeriesPrognosis/TimeSeriesPrognosisProblemData.cs	(revision 12701)
+++ /stable/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/TimeSeriesPrognosis/TimeSeriesPrognosisProblemData.cs	(revision 12702)
@@ -1582,5 +1582,5 @@
       TrainingPartition.Start = 50;
     }
-    public TimeSeriesPrognosisProblemData(Dataset dataset, IEnumerable<string> allowedInputVariables, string targetVariable, IEnumerable<ITransformation> transformations = null)
+    public TimeSeriesPrognosisProblemData(IDataset dataset, IEnumerable<string> allowedInputVariables, string targetVariable, IEnumerable<ITransformation> transformations = null)
       : base(dataset, allowedInputVariables, targetVariable, transformations ?? Enumerable.Empty<ITransformation>()) {
       Parameters.Add(new FixedValueParameter<IntValue>(TrainingHorizonParameterName, "Specifies the horizon (how far the prognosis reaches in the future) for each training sample.", new IntValue(1)));
Index: /stable/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Classification/IClassificationEnsembleModel.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Classification/IClassificationEnsembleModel.cs	(revision 12701)
+++ /stable/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Classification/IClassificationEnsembleModel.cs	(revision 12702)
@@ -26,5 +26,5 @@
     void Remove(IClassificationModel model);
     IEnumerable<IClassificationModel> Models { get; }
-    IEnumerable<IEnumerable<double>> GetEstimatedClassValueVectors(Dataset dataset, IEnumerable<int> rows);
+    IEnumerable<IEnumerable<double>> GetEstimatedClassValueVectors(IDataset dataset, IEnumerable<int> rows);
   }
 }
Index: /stable/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Classification/IClassificationEnsembleSolution.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Classification/IClassificationEnsembleSolution.cs	(revision 12701)
+++ /stable/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Classification/IClassificationEnsembleSolution.cs	(revision 12702)
@@ -26,5 +26,5 @@
     new IClassificationEnsembleModel Model { get; }
     IItemCollection<IClassificationSolution> ClassificationSolutions { get; }
-    IEnumerable<IEnumerable<double>> GetEstimatedClassValueVectors(Dataset dataset, IEnumerable<int> rows);
+    IEnumerable<IEnumerable<double>> GetEstimatedClassValueVectors(IDataset dataset, IEnumerable<int> rows);
   }
 }
Index: /stable/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Classification/IClassificationModel.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Classification/IClassificationModel.cs	(revision 12701)
+++ /stable/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Classification/IClassificationModel.cs	(revision 12702)
@@ -23,5 +23,5 @@
 namespace HeuristicLab.Problems.DataAnalysis {
   public interface IClassificationModel : IDataAnalysisModel {
-    IEnumerable<double> GetEstimatedClassValues(Dataset dataset, IEnumerable<int> rows);
+    IEnumerable<double> GetEstimatedClassValues(IDataset dataset, IEnumerable<int> rows);
     IClassificationSolution CreateClassificationSolution(IClassificationProblemData problemData);
   }
Index: /stable/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Classification/IDiscriminantFunctionClassificationModel.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Classification/IDiscriminantFunctionClassificationModel.cs	(revision 12701)
+++ /stable/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Classification/IDiscriminantFunctionClassificationModel.cs	(revision 12702)
@@ -30,5 +30,5 @@
     // class values and thresholds can only be assigned simultanously
     void SetThresholdsAndClassValues(IEnumerable<double> thresholds, IEnumerable<double> classValues);
-    IEnumerable<double> GetEstimatedValues(Dataset dataset, IEnumerable<int> rows);
+    IEnumerable<double> GetEstimatedValues(IDataset dataset, IEnumerable<int> rows);
 
     event EventHandler ThresholdsChanged;
Index: /stable/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Clustering/IClusteringModel.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Clustering/IClusteringModel.cs	(revision 12701)
+++ /stable/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Clustering/IClusteringModel.cs	(revision 12702)
@@ -23,5 +23,5 @@
 namespace HeuristicLab.Problems.DataAnalysis {
   public interface IClusteringModel : IDataAnalysisModel {
-    IEnumerable<int> GetClusterValues(Dataset dataset, IEnumerable<int> rows);
+    IEnumerable<int> GetClusterValues(IDataset dataset, IEnumerable<int> rows);
   }
 }
Index: /stable/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/IDataAnalysisProblemData.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/IDataAnalysisProblemData.cs	(revision 12701)
+++ /stable/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/IDataAnalysisProblemData.cs	(revision 12702)
@@ -29,5 +29,5 @@
     bool IsEmpty { get; }
 
-    Dataset Dataset { get; }
+    IDataset Dataset { get; }
     ICheckedItemList<StringValue> InputVariables { get; }
     IEnumerable<string> AllowedInputVariables { get; }
Index: /stable/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/IDataset.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/IDataset.cs	(revision 12702)
+++ /stable/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/IDataset.cs	(revision 12702)
@@ -0,0 +1,41 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2014 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.Collections.ObjectModel;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+
+namespace HeuristicLab.Problems.DataAnalysis {
+  public interface IDataset : IItem, IStringConvertibleMatrix {
+    IEnumerable<string> VariableNames { get; }
+    IEnumerable<string> DoubleVariables { get; }
+
+    double GetDoubleValue(string variableName, int row);
+    IEnumerable<double> GetDoubleValues(string variableName);
+    IEnumerable<double> GetDoubleValues(string variableName, IEnumerable<int> rows);
+    ReadOnlyCollection<double> GetReadOnlyDoubleValues(string variableName);
+
+    IEnumerable<string> GetStringValues(string variableName);
+    IEnumerable<DateTime> GetDateTimeValues(string variableName);
+  }
+}
Index: /stable/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Regression/IRegressionEnsembleModel.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Regression/IRegressionEnsembleModel.cs	(revision 12701)
+++ /stable/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Regression/IRegressionEnsembleModel.cs	(revision 12702)
@@ -26,5 +26,5 @@
     void Remove(IRegressionModel model);
     IEnumerable<IRegressionModel> Models { get; }
-    IEnumerable<IEnumerable<double>> GetEstimatedValueVectors(Dataset dataset, IEnumerable<int> rows);
+    IEnumerable<IEnumerable<double>> GetEstimatedValueVectors(IDataset dataset, IEnumerable<int> rows);
   }
 }
Index: /stable/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Regression/IRegressionEnsembleSolution.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Regression/IRegressionEnsembleSolution.cs	(revision 12701)
+++ /stable/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Regression/IRegressionEnsembleSolution.cs	(revision 12702)
@@ -27,5 +27,5 @@
     new RegressionEnsembleProblemData ProblemData { get; set; }
     IItemCollection<IRegressionSolution> RegressionSolutions { get; }
-    IEnumerable<IEnumerable<double>> GetEstimatedValueVectors(Dataset dataset, IEnumerable<int> rows);
+    IEnumerable<IEnumerable<double>> GetEstimatedValueVectors(IDataset dataset, IEnumerable<int> rows);
   }
 }
Index: /stable/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Regression/IRegressionModel.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Regression/IRegressionModel.cs	(revision 12701)
+++ /stable/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Regression/IRegressionModel.cs	(revision 12702)
@@ -23,5 +23,5 @@
 namespace HeuristicLab.Problems.DataAnalysis {
   public interface IRegressionModel : IDataAnalysisModel {
-    IEnumerable<double> GetEstimatedValues(Dataset dataset, IEnumerable<int> rows);
+    IEnumerable<double> GetEstimatedValues(IDataset dataset, IEnumerable<int> rows);
     IRegressionSolution CreateRegressionSolution(IRegressionProblemData problemData);
   }
Index: /stable/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/TimeSeriesPrognosis/ITimeSeriesPrognosisModel.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/TimeSeriesPrognosis/ITimeSeriesPrognosisModel.cs	(revision 12701)
+++ /stable/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/TimeSeriesPrognosis/ITimeSeriesPrognosisModel.cs	(revision 12702)
@@ -23,5 +23,5 @@
 namespace HeuristicLab.Problems.DataAnalysis {
   public interface ITimeSeriesPrognosisModel : IRegressionModel {
-    IEnumerable<IEnumerable<double>> GetPrognosedValues(Dataset dataset, IEnumerable<int> rows, IEnumerable<int> horizons);
+    IEnumerable<IEnumerable<double>> GetPrognosedValues(IDataset dataset, IEnumerable<int> rows, IEnumerable<int> horizons);
     ITimeSeriesPrognosisSolution CreateTimeSeriesPrognosisSolution(ITimeSeriesPrognosisProblemData problemData);
   }
Index: /stable/HeuristicLab.Problems.DataAnalysis/3.4/ModifiableDataset.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis/3.4/ModifiableDataset.cs	(revision 12702)
+++ /stable/HeuristicLab.Problems.DataAnalysis/3.4/ModifiableDataset.cs	(revision 12702)
@@ -0,0 +1,199 @@
+﻿#region License Information
+
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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;
+using System.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.DataAnalysis {
+  [Item("ModifiableDataset", "Represents a dataset containing data that should be analyzed, which can be modified by adding or replacing variables and values.")]
+  [StorableClass]
+  public sealed class ModifiableDataset : Dataset, IStringConvertibleMatrix {
+    [StorableConstructor]
+    private ModifiableDataset(bool deserializing) : base(deserializing) { }
+    private ModifiableDataset(ModifiableDataset original, Cloner cloner) : base(original, cloner) { }
+    public override IDeepCloneable Clone(Cloner cloner) { return new ModifiableDataset(this, cloner); }
+    public ModifiableDataset() : base() { }
+
+    public ModifiableDataset(Dataset dataset) : base(dataset) { }
+    public ModifiableDataset(IEnumerable<string> variableNames, IEnumerable<IList> variableValues) : base(variableNames, variableValues) { }
+
+    public void ReplaceRow(int row, IEnumerable<object> values) {
+      var list = values.ToList();
+      if (list.Count != variableNames.Count)
+        throw new ArgumentException("The number of values must be equal to the number of variable names.");
+      // check if all the values are of the correct type
+      for (int i = 0; i < list.Count; ++i) {
+        if (list[i].GetType() != GetVariableType(variableNames[i])) {
+          throw new ArgumentException("The type of the provided value does not match the variable type.");
+        }
+      }
+      // replace values
+      for (int i = 0; i < list.Count; ++i) {
+        variableValues[variableNames[i]][row] = list[i];
+      }
+      OnReset();
+    }
+
+    public void AddRow(IEnumerable<object> values) {
+      var list = values.ToList();
+      if (list.Count != variableNames.Count)
+        throw new ArgumentException("The number of values must be equal to the number of variable names.");
+      // check if all the values are of the correct type
+      for (int i = 0; i < list.Count; ++i) {
+        if (list[i].GetType() != GetVariableType(variableNames[i])) {
+          throw new ArgumentException("The type of the provided value does not match the variable type.");
+        }
+      }
+      // add values
+      for (int i = 0; i < list.Count; ++i) {
+        variableValues[variableNames[i]].Add(list[i]);
+      }
+      rows++;
+      OnRowsChanged();
+      OnReset();
+    }
+
+    // adds a new variable to the dataset
+    public void AddVariable<T>(string variableName, IEnumerable<T> values) {
+      if (variableValues.ContainsKey(variableName))
+        throw new ArgumentException("Variable " + variableName + " is already present in the dataset.");
+      int count = values.Count();
+      if (count != rows)
+        throw new ArgumentException("The number of values must exactly match the number of rows in the dataset.");
+      variableValues[variableName] = new List<T>(values);
+      variableNames.Add(variableName);
+      OnColumnsChanged();
+      OnColumnNamesChanged();
+      OnReset();
+    }
+
+    public void RemoveVariable(string variableName) {
+      if (!variableValues.ContainsKey(variableName))
+        throw new ArgumentException("The variable " + variableName + " does not exist in the dataset.");
+      variableValues.Remove(variableName);
+      variableNames.Remove(variableName);
+      OnColumnsChanged();
+      OnColumnNamesChanged();
+      OnReset();
+    }
+
+    // slow, avoid to use this
+    public void RemoveRow(int row) {
+      foreach (var list in variableValues.Values)
+        list.RemoveAt(row);
+      rows--;
+      OnRowsChanged();
+      OnReset();
+    }
+
+    public void SetVariableValue(object value, string variableName, int row) {
+      IList list;
+      variableValues.TryGetValue(variableName, out list);
+      if (list == null)
+        throw new ArgumentException("The variable " + variableName + " does not exist in the dataset.");
+      if (row < 0 || list.Count < row)
+        throw new ArgumentOutOfRangeException("Invalid row value");
+      if (GetVariableType(variableName) != value.GetType())
+        throw new ArgumentException("The type of the provided value does not match the variable type.");
+
+      list[row] = value;
+      OnItemChanged(row, variableNames.IndexOf(variableName));
+    }
+
+    private Type GetVariableType(string variableName) {
+      IList list;
+      variableValues.TryGetValue(variableName, out list);
+      if (list == null)
+        throw new ArgumentException("The variable " + variableName + " does not exist in the dataset.");
+      return list.GetType().GetGenericArguments()[0];
+    }
+
+    bool IStringConvertibleMatrix.SetValue(string value, int rowIndex, int columnIndex) {
+      var variableName = variableNames[columnIndex];
+      // if value represents a double
+      double dv;
+      if (double.TryParse(value, out dv)) {
+        SetVariableValue(dv, variableName, rowIndex);
+        return true;
+      }
+      // if value represents a DateTime object
+      DateTime dt;
+      if (DateTime.TryParse(value, out dt)) {
+        SetVariableValue(dt, variableName, rowIndex);
+        return true;
+      }
+      // if value is simply a string
+      SetVariableValue(value, variableName, rowIndex);
+      return true;
+    }
+
+    bool IStringConvertibleMatrix.Validate(string value, out string errorMessage) {
+      errorMessage = string.Empty;
+      return true;
+    }
+
+    #region event handlers
+    public override event EventHandler RowsChanged;
+    private void OnRowsChanged() {
+      var handler = RowsChanged;
+      if (handler != null)
+        handler(this, EventArgs.Empty);
+    }
+
+    public override event EventHandler ColumnsChanged;
+    private void OnColumnsChanged() {
+      var handler = ColumnsChanged;
+      if (handler != null)
+        handler(this, EventArgs.Empty);
+    }
+
+    public override event EventHandler ColumnNamesChanged;
+    private void OnColumnNamesChanged() {
+      var handler = ColumnNamesChanged;
+      if (handler != null)
+        handler(this, EventArgs.Empty);
+    }
+
+    public override event EventHandler Reset;
+    private void OnReset() {
+      var handler = Reset;
+      if (handler != null)
+        handler(this, EventArgs.Empty);
+    }
+
+    public override event EventHandler<EventArgs<int, int>> ItemChanged;
+    private void OnItemChanged(int rowIndex, int columnIndex) {
+      var handler = ItemChanged;
+      if (handler != null) {
+        handler(this, new EventArgs<int, int>(rowIndex, columnIndex));
+      }
+    }
+    #endregion
+  }
+}
Index: /stable/HeuristicLab.Problems.Instances.DataAnalysis/3.3/Regression/FeatureSelection/FeatureSelectionRegressionProblemData.cs
===================================================================
--- /stable/HeuristicLab.Problems.Instances.DataAnalysis/3.3/Regression/FeatureSelection/FeatureSelectionRegressionProblemData.cs	(revision 12701)
+++ /stable/HeuristicLab.Problems.Instances.DataAnalysis/3.3/Regression/FeatureSelection/FeatureSelectionRegressionProblemData.cs	(revision 12702)
@@ -22,5 +22,4 @@
 using System;
 using System.Collections.Generic;
-using System.Linq;
 using HeuristicLab.Common;
 using HeuristicLab.Core;
@@ -29,5 +28,4 @@
 using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
 using HeuristicLab.Problems.DataAnalysis;
-using HeuristicLab.Random;
 
 namespace HeuristicLab.Problems.Instances.DataAnalysis {
@@ -57,5 +55,5 @@
     }
 
-    public FeatureSelectionRegressionProblemData(Dataset ds, IEnumerable<string> allowedInputVariables, string targetVariable, string[] selectedFeatures, double[] weights, double optimalRSquared)
+    public FeatureSelectionRegressionProblemData(IDataset ds, IEnumerable<string> allowedInputVariables, string targetVariable, string[] selectedFeatures, double[] weights, double optimalRSquared)
       : base(ds, allowedInputVariables, targetVariable) {
       if (selectedFeatures.Length != weights.Length) throw new ArgumentException("Length of selected features vector does not match the length of the weights vector");
