Index: trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Dataset.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Dataset.cs	(revision 12504)
+++ trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Dataset.cs	(revision 12509)
@@ -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: trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/HeuristicLab.Problems.DataAnalysis-3.4.csproj
===================================================================
--- trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/HeuristicLab.Problems.DataAnalysis-3.4.csproj	(revision 12504)
+++ trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/HeuristicLab.Problems.DataAnalysis-3.4.csproj	(revision 12509)
@@ -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: trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ClassificationEnsembleModel.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ClassificationEnsembleModel.cs	(revision 12504)
+++ trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ClassificationEnsembleModel.cs	(revision 12509)
@@ -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: trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ClassificationEnsembleSolution.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ClassificationEnsembleSolution.cs	(revision 12504)
+++ trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ClassificationEnsembleSolution.cs	(revision 12509)
@@ -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: trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ClassificationProblemData.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ClassificationProblemData.cs	(revision 12504)
+++ trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ClassificationProblemData.cs	(revision 12509)
@@ -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: trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/DiscriminantFunctionClassificationModel.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/DiscriminantFunctionClassificationModel.cs	(revision 12504)
+++ trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/DiscriminantFunctionClassificationModel.cs	(revision 12509)
@@ -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: trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/DataAnalysisProblemData.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/DataAnalysisProblemData.cs	(revision 12504)
+++ trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/DataAnalysisProblemData.cs	(revision 12509)
@@ -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: trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Regression/ConstantRegressionModel.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Regression/ConstantRegressionModel.cs	(revision 12504)
+++ trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Regression/ConstantRegressionModel.cs	(revision 12509)
@@ -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: trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Regression/RegressionEnsembleModel.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Regression/RegressionEnsembleModel.cs	(revision 12504)
+++ trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Regression/RegressionEnsembleModel.cs	(revision 12509)
@@ -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: trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Regression/RegressionEnsembleSolution.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Regression/RegressionEnsembleSolution.cs	(revision 12504)
+++ trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Regression/RegressionEnsembleSolution.cs	(revision 12509)
@@ -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: trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Regression/RegressionProblemData.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Regression/RegressionProblemData.cs	(revision 12504)
+++ trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Regression/RegressionProblemData.cs	(revision 12509)
@@ -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: trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Regression/RegressionSolution.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Regression/RegressionSolution.cs	(revision 12504)
+++ trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Regression/RegressionSolution.cs	(revision 12509)
@@ -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: trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/TimeSeriesPrognosis/Models/ConstantTimeSeriesPrognosisModel.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/TimeSeriesPrognosis/Models/ConstantTimeSeriesPrognosisModel.cs	(revision 12504)
+++ trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/TimeSeriesPrognosis/Models/ConstantTimeSeriesPrognosisModel.cs	(revision 12509)
@@ -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: trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/TimeSeriesPrognosis/Models/TimeSeriesPrognosisAutoRegressiveModel.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/TimeSeriesPrognosis/Models/TimeSeriesPrognosisAutoRegressiveModel.cs	(revision 12504)
+++ trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/TimeSeriesPrognosis/Models/TimeSeriesPrognosisAutoRegressiveModel.cs	(revision 12509)
@@ -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: trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/TimeSeriesPrognosis/TimeSeriesPrognosisProblemData.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/TimeSeriesPrognosis/TimeSeriesPrognosisProblemData.cs	(revision 12504)
+++ trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/TimeSeriesPrognosis/TimeSeriesPrognosisProblemData.cs	(revision 12509)
@@ -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: trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Classification/IClassificationEnsembleModel.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Classification/IClassificationEnsembleModel.cs	(revision 12504)
+++ trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Classification/IClassificationEnsembleModel.cs	(revision 12509)
@@ -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: trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Classification/IClassificationEnsembleSolution.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Classification/IClassificationEnsembleSolution.cs	(revision 12504)
+++ trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Classification/IClassificationEnsembleSolution.cs	(revision 12509)
@@ -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: trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Classification/IClassificationModel.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Classification/IClassificationModel.cs	(revision 12504)
+++ trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Classification/IClassificationModel.cs	(revision 12509)
@@ -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: trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Classification/IDiscriminantFunctionClassificationModel.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Classification/IDiscriminantFunctionClassificationModel.cs	(revision 12504)
+++ trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Classification/IDiscriminantFunctionClassificationModel.cs	(revision 12509)
@@ -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: trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Clustering/IClusteringModel.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Clustering/IClusteringModel.cs	(revision 12504)
+++ trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Clustering/IClusteringModel.cs	(revision 12509)
@@ -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: trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/IDataAnalysisProblemData.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/IDataAnalysisProblemData.cs	(revision 12504)
+++ trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/IDataAnalysisProblemData.cs	(revision 12509)
@@ -29,5 +29,5 @@
     bool IsEmpty { get; }
 
-    Dataset Dataset { get; }
+    IDataset Dataset { get; }
     ICheckedItemList<StringValue> InputVariables { get; }
     IEnumerable<string> AllowedInputVariables { get; }
Index: trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/IDataset.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/IDataset.cs	(revision 12509)
+++ trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/IDataset.cs	(revision 12509)
@@ -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: trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Regression/IRegressionEnsembleModel.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Regression/IRegressionEnsembleModel.cs	(revision 12504)
+++ trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Regression/IRegressionEnsembleModel.cs	(revision 12509)
@@ -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: trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Regression/IRegressionEnsembleSolution.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Regression/IRegressionEnsembleSolution.cs	(revision 12504)
+++ trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Regression/IRegressionEnsembleSolution.cs	(revision 12509)
@@ -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: trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Regression/IRegressionModel.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Regression/IRegressionModel.cs	(revision 12504)
+++ trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Regression/IRegressionModel.cs	(revision 12509)
@@ -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: trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/TimeSeriesPrognosis/ITimeSeriesPrognosisModel.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/TimeSeriesPrognosis/ITimeSeriesPrognosisModel.cs	(revision 12504)
+++ trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/TimeSeriesPrognosis/ITimeSeriesPrognosisModel.cs	(revision 12509)
@@ -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: trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/ModifiableDataset.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/ModifiableDataset.cs	(revision 12509)
+++ trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/ModifiableDataset.cs	(revision 12509)
@@ -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 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
+  }
+}
