Index: trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ClassificationEnsembleModel.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ClassificationEnsembleModel.cs	(revision 6238)
+++ trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ClassificationEnsembleModel.cs	(revision 6239)
@@ -39,4 +39,5 @@
       get { return new List<IClassificationModel>(models); }
     }
+
     [StorableConstructor]
     protected ClassificationEnsembleModel(bool deserializing) : base(deserializing) { }
Index: trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ClassificationEnsembleProblemData.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ClassificationEnsembleProblemData.cs	(revision 6239)
+++ trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ClassificationEnsembleProblemData.cs	(revision 6239)
@@ -0,0 +1,64 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2011 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.IO;
+using System.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.DataAnalysis {
+  [StorableClass]
+  [Item("ClassificationEnsembleProblemData", "Represents an item containing all data defining a classification problem.")]
+  public class ClassificationEnsembleProblemData : ClassificationProblemData {
+
+    public override IEnumerable<int> TrainingIndizes {
+      get {
+        return Enumerable.Range(TrainingPartition.Start, TestPartition.End - TestPartition.Start);
+      }
+    }
+    public override IEnumerable<int> TestIndizes {
+      get {
+        return Enumerable.Range(TestPartition.Start, TestPartition.End - TestPartition.Start);
+      }
+    }
+
+    [StorableConstructor]
+    protected ClassificationEnsembleProblemData(bool deserializing) : base(deserializing) { }
+
+    protected ClassificationEnsembleProblemData(ClassificationEnsembleProblemData original, Cloner cloner)
+      : base(original, cloner) {
+    }
+    public override IDeepCloneable Clone(Cloner cloner) { return new ClassificationEnsembleProblemData(this, cloner); }
+
+    public ClassificationEnsembleProblemData(IClassificationProblemData classificationProblemData)
+      : base(classificationProblemData.Dataset, classificationProblemData.AllowedInputVariables, classificationProblemData.TargetVariable) {
+      this.TrainingPartition.Start = classificationProblemData.TrainingPartition.Start;
+      this.TrainingPartition.End = classificationProblemData.TrainingPartition.End;
+      this.TestPartition.Start = classificationProblemData.TestPartition.Start;
+      this.TestPartition.End = classificationProblemData.TestPartition.End;
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ClassificationEnsembleSolution.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ClassificationEnsembleSolution.cs	(revision 6238)
+++ trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ClassificationEnsembleSolution.cs	(revision 6239)
@@ -25,4 +25,6 @@
 using HeuristicLab.Core;
 using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Data;
+using System;
 
 namespace HeuristicLab.Problems.DataAnalysis {
@@ -33,22 +35,57 @@
   [Item("Classification Ensemble Solution", "A classification solution that contains an ensemble of multiple classification models")]
   // [Creatable("Data Analysis")]
-  public class ClassificationEnsembleSolution : NamedItem, IClassificationEnsembleSolution {
+  public class ClassificationEnsembleSolution : ClassificationSolution, IClassificationEnsembleSolution {
+
+    public new IClassificationEnsembleModel Model {
+      set { base.Model = value; }
+      get { return (IClassificationEnsembleModel)base.Model; }
+    }
 
     [Storable]
-    private List<IClassificationModel> models;
-    public IEnumerable<IClassificationModel> Models {
-      get { return new List<IClassificationModel>(models); }
-    }
+    private Dictionary<IClassificationModel, IntRange> trainingPartitions;
+    [Storable]
+    private Dictionary<IClassificationModel, IntRange> testPartitions;
+
+
     [StorableConstructor]
     protected ClassificationEnsembleSolution(bool deserializing) : base(deserializing) { }
     protected ClassificationEnsembleSolution(ClassificationEnsembleSolution original, Cloner cloner)
       : base(original, cloner) {
-      this.models = original.Models.Select(m => cloner.Clone(m)).ToList();
+      trainingPartitions = new Dictionary<IClassificationModel, IntRange>();
+      testPartitions = new Dictionary<IClassificationModel, IntRange>();
+      foreach (var model in Model.Models) {
+        trainingPartitions[model] = (IntRange)ProblemData.TrainingPartition.Clone();
+        testPartitions[model] = (IntRange)ProblemData.TestPartition.Clone();
+      }
+      RecalculateResults();
     }
-    public ClassificationEnsembleSolution(IEnumerable<IClassificationModel> models)
-      : base() {
+    public ClassificationEnsembleSolution(IEnumerable<IClassificationModel> models, IClassificationProblemData problemData)
+      : base(new ClassificationEnsembleModel(models), new ClassificationEnsembleProblemData(problemData)) {
       this.name = ItemName;
       this.description = ItemDescription;
-      this.models = new List<IClassificationModel>(models);
+      trainingPartitions = new Dictionary<IClassificationModel, IntRange>();
+      testPartitions = new Dictionary<IClassificationModel, IntRange>();
+      foreach (var model in models) {
+        trainingPartitions[model] = (IntRange)problemData.TrainingPartition.Clone();
+        testPartitions[model] = (IntRange)problemData.TestPartition.Clone();
+      }
+      RecalculateResults();
+    }
+
+    public ClassificationEnsembleSolution(IEnumerable<IClassificationModel> models, IClassificationProblemData problemData, IEnumerable<IntRange> trainingPartitions, IEnumerable<IntRange> testPartitions)
+      : base(new ClassificationEnsembleModel(models), new ClassificationEnsembleProblemData(problemData)) {
+      this.trainingPartitions = new Dictionary<IClassificationModel, IntRange>();
+      this.testPartitions = new Dictionary<IClassificationModel, IntRange>();
+      var modelEnumerator = models.GetEnumerator();
+      var trainingPartitionEnumerator = trainingPartitions.GetEnumerator();
+      var testPartitionEnumerator = testPartitions.GetEnumerator();
+      while (modelEnumerator.MoveNext() & trainingPartitionEnumerator.MoveNext() & testPartitionEnumerator.MoveNext()) {
+        this.trainingPartitions[modelEnumerator.Current] = (IntRange)trainingPartitionEnumerator.Current.Clone();
+        this.testPartitions[modelEnumerator.Current] = (IntRange)testPartitionEnumerator.Current.Clone();
+      }
+      if (modelEnumerator.MoveNext() | trainingPartitionEnumerator.MoveNext() | testPartitionEnumerator.MoveNext()) {
+        throw new ArgumentException();
+      }
+      RecalculateResults();
     }
 
@@ -57,8 +94,52 @@
     }
 
-    #region IClassificationEnsembleModel Members
+    public override IEnumerable<double> EstimatedTrainingClassValues {
+      get {
+        var rows = ProblemData.TrainingIndizes;
+        var estimatedValuesEnumerators = (from model in Model.Models
+                                          select new { Model = model, EstimatedValuesEnumerator = model.GetEstimatedClassValues(ProblemData.Dataset, rows).GetEnumerator() })
+                                         .ToList();
+        var rowsEnumerator = rows.GetEnumerator();
+        // aggregate to make sure that MoveNext is called for all enumerators 
+        while (rowsEnumerator.MoveNext() & estimatedValuesEnumerators.Select(en => en.EstimatedValuesEnumerator.MoveNext()).Aggregate(true, (acc, b) => acc & b)) {
+          int currentRow = rowsEnumerator.Current;
+
+          var selectedEnumerators = from pair in estimatedValuesEnumerators
+                                    where trainingPartitions == null || !trainingPartitions.ContainsKey(pair.Model) ||
+                                         (trainingPartitions[pair.Model].Start <= currentRow && currentRow < trainingPartitions[pair.Model].End)
+                                    select pair.EstimatedValuesEnumerator;
+          yield return AggregateEstimatedClassValues(selectedEnumerators.Select(x => x.Current));
+        }
+      }
+    }
+
+    public override IEnumerable<double> EstimatedTestClassValues {
+      get {
+        var rows = ProblemData.TestIndizes;
+        var estimatedValuesEnumerators = (from model in Model.Models
+                                          select new { Model = model, EstimatedValuesEnumerator = model.GetEstimatedClassValues(ProblemData.Dataset, rows).GetEnumerator() })
+                                         .ToList();
+        var rowsEnumerator = ProblemData.TestIndizes.GetEnumerator();
+        // aggregate to make sure that MoveNext is called for all enumerators 
+        while (rowsEnumerator.MoveNext() & estimatedValuesEnumerators.Select(en => en.EstimatedValuesEnumerator.MoveNext()).Aggregate(true, (acc, b) => acc & b)) {
+          int currentRow = rowsEnumerator.Current;
+
+          var selectedEnumerators = from pair in estimatedValuesEnumerators
+                                    where testPartitions == null || !testPartitions.ContainsKey(pair.Model) ||
+                                      (testPartitions[pair.Model].Start <= currentRow && currentRow < testPartitions[pair.Model].End)
+                                    select pair.EstimatedValuesEnumerator;
+
+          yield return AggregateEstimatedClassValues(selectedEnumerators.Select(x => x.Current));
+        }
+      }
+    }
+
+    public override IEnumerable<double> GetEstimatedClassValues(IEnumerable<int> rows) {
+      return from xs in GetEstimatedClassValueVectors(ProblemData.Dataset, rows)
+             select AggregateEstimatedClassValues(xs);
+    }
 
     public IEnumerable<IEnumerable<double>> GetEstimatedClassValueVectors(Dataset dataset, IEnumerable<int> rows) {
-      var estimatedValuesEnumerators = (from model in models
+      var estimatedValuesEnumerators = (from model in Model.Models
                                         select model.GetEstimatedClassValues(dataset, rows).GetEnumerator())
                                        .ToList();
@@ -70,21 +151,11 @@
     }
 
-    #endregion
-
-    #region IClassificationModel Members
-
-    public IEnumerable<double> GetEstimatedClassValues(Dataset dataset, IEnumerable<int> rows) {
-      foreach (var estimatedValuesVector in GetEstimatedClassValueVectors(dataset, rows)) {
-        // return the class which is most often occuring
-        yield return
-          estimatedValuesVector
-          .GroupBy(x => x)
-          .OrderBy(g => -g.Count())
-          .Select(g => g.Key)
-          .First();
-      }
+    private double AggregateEstimatedClassValues(IEnumerable<double> estimatedClassValues) {
+      return estimatedClassValues
+      .GroupBy(x => x)
+      .OrderBy(g => -g.Count())
+      .Select(g => g.Key)
+      .First();
     }
-
-    #endregion
   }
 }
Index: trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Regression/RegressionEnsembleSolution.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Regression/RegressionEnsembleSolution.cs	(revision 6238)
+++ trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Regression/RegressionEnsembleSolution.cs	(revision 6239)
@@ -49,5 +49,12 @@
     protected RegressionEnsembleSolution(RegressionEnsembleSolution original, Cloner cloner)
       : base(original, cloner) {
+      trainingPartitions = new Dictionary<IRegressionModel, IntRange>();
+      testPartitions = new Dictionary<IRegressionModel, IntRange>();
+      foreach (var model in Model.Models) {
+        trainingPartitions[model] = (IntRange)ProblemData.TrainingPartition.Clone();
+        testPartitions[model] = (IntRange)ProblemData.TestPartition.Clone();
+      }
     }
+
     public RegressionEnsembleSolution(IEnumerable<IRegressionModel> models, IRegressionProblemData problemData)
       : base(new RegressionEnsembleModel(models), new RegressionEnsembleProblemData(problemData)) {
@@ -141,65 +148,5 @@
     private double AggregateEstimatedValues(IEnumerable<double> estimatedValues) {
       return estimatedValues.DefaultIfEmpty(double.NaN).Average();
-    }
-
-    //[Storable]
-    //private string name;
-    //public string Name {
-    //  get {
-    //    return name;
-    //  }
-    //  set {
-    //    if (value != null && value != name) {
-    //      var cancelEventArgs = new CancelEventArgs<string>(value);
-    //      OnNameChanging(cancelEventArgs);
-    //      if (cancelEventArgs.Cancel == false) {
-    //        name = value;
-    //        OnNamedChanged(EventArgs.Empty);
-    //      }
-    //    }
-    //  }
-    //}
-
-    //public bool CanChangeName {
-    //  get { return true; }
-    //}
-
-    //[Storable]
-    //private string description;
-    //public string Description {
-    //  get {
-    //    return description;
-    //  }
-    //  set {
-    //    if (value != null && value != description) {
-    //      description = value;
-    //      OnDescriptionChanged(EventArgs.Empty);
-    //    }
-    //  }
-    //}
-
-    //public bool CanChangeDescription {
-    //  get { return true; }
-    //}
-
-    //#region events
-    //public event EventHandler<CancelEventArgs<string>> NameChanging;
-    //private void OnNameChanging(CancelEventArgs<string> cancelEventArgs) {
-    //  var listener = NameChanging;
-    //  if (listener != null) listener(this, cancelEventArgs);
-    //}
-
-    //public event EventHandler NameChanged;
-    //private void OnNamedChanged(EventArgs e) {
-    //  var listener = NameChanged;
-    //  if (listener != null) listener(this, e);
-    //}
-
-    //public event EventHandler DescriptionChanged;
-    //private void OnDescriptionChanged(EventArgs e) {
-    //  var listener = DescriptionChanged;
-    //  if (listener != null) listener(this, e);
-    //}
-    // #endregion
+    }   
   }
 }
