Index: branches/2719_HeuristicLab.DatastreamAnalysis/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ClassificationEnsembleModel.cs
===================================================================
--- branches/2719_HeuristicLab.DatastreamAnalysis/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ClassificationEnsembleModel.cs	(revision 15866)
+++ branches/2719_HeuristicLab.DatastreamAnalysis/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ClassificationEnsembleModel.cs	(revision 17980)
@@ -1,5 +1,5 @@
 #region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
@@ -24,5 +24,5 @@
 using HeuristicLab.Common;
 using HeuristicLab.Core;
-using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HEAL.Attic;
 
 namespace HeuristicLab.Problems.DataAnalysis {
@@ -30,5 +30,5 @@
   /// Represents classification solutions that contain an ensemble of multiple classification models
   /// </summary>
-  [StorableClass]
+  [StorableType("0F720A40-5CC2-4E2B-8D4E-CCAD8EB56E43")]
   [Item("ClassificationEnsembleModel", "A classification model that contains an ensemble of multiple classification models")]
   public class ClassificationEnsembleModel : ClassificationModel, IClassificationEnsembleModel {
@@ -44,5 +44,5 @@
 
     [StorableConstructor]
-    protected ClassificationEnsembleModel(bool deserializing) : base(deserializing) { }
+    protected ClassificationEnsembleModel(StorableConstructorFlag _) : base(_) { }
     protected ClassificationEnsembleModel(ClassificationEnsembleModel original, Cloner cloner)
       : base(original, cloner) {
Index: branches/2719_HeuristicLab.DatastreamAnalysis/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ClassificationEnsembleProblemData.cs
===================================================================
--- branches/2719_HeuristicLab.DatastreamAnalysis/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ClassificationEnsembleProblemData.cs	(revision 15866)
+++ branches/2719_HeuristicLab.DatastreamAnalysis/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ClassificationEnsembleProblemData.cs	(revision 17980)
@@ -1,5 +1,5 @@
 ﻿#region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
@@ -25,8 +25,8 @@
 using HeuristicLab.Data;
 using HeuristicLab.Parameters;
-using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HEAL.Attic;
 
 namespace HeuristicLab.Problems.DataAnalysis {
-  [StorableClass]
+  [StorableType("58768587-0920-4B52-95E4-66B54E8E837C")]
   [Item("ClassificationEnsembleProblemData", "Represents an item containing all data defining a classification problem.")]
   public class ClassificationEnsembleProblemData : ClassificationProblemData {
@@ -65,5 +65,5 @@
 
     [StorableConstructor]
-    protected ClassificationEnsembleProblemData(bool deserializing) : base(deserializing) { }
+    protected ClassificationEnsembleProblemData(StorableConstructorFlag _) : base(_) { }
     protected ClassificationEnsembleProblemData(ClassificationEnsembleProblemData original, Cloner cloner) : base(original, cloner) { }
     public override IDeepCloneable Clone(Cloner cloner) {
Index: branches/2719_HeuristicLab.DatastreamAnalysis/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ClassificationEnsembleSolution.cs
===================================================================
--- branches/2719_HeuristicLab.DatastreamAnalysis/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ClassificationEnsembleSolution.cs	(revision 15866)
+++ branches/2719_HeuristicLab.DatastreamAnalysis/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ClassificationEnsembleSolution.cs	(revision 17980)
@@ -1,5 +1,5 @@
 #region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
@@ -27,5 +27,5 @@
 using HeuristicLab.Core;
 using HeuristicLab.Data;
-using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HEAL.Attic;
 
 namespace HeuristicLab.Problems.DataAnalysis {
@@ -33,5 +33,5 @@
   /// Represents classification solutions that contain an ensemble of multiple classification models
   /// </summary>
-  [StorableClass]
+  [StorableType("4CDD22EE-B53D-4899-A77E-C503FF9EBC8E")]
   [Item("Classification Ensemble Solution", "A classification solution that contains an ensemble of multiple classification models")]
   [Creatable(CreatableAttribute.Categories.DataAnalysisEnsembles, Priority = 110)]
@@ -61,6 +61,5 @@
 
     [StorableConstructor]
-    private ClassificationEnsembleSolution(bool deserializing)
-      : base(deserializing) {
+    private ClassificationEnsembleSolution(StorableConstructorFlag _) : base(_) {
       classificationSolutions = new ItemCollection<IClassificationSolution>();
     }
Index: branches/2719_HeuristicLab.DatastreamAnalysis/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ClassificationModel.cs
===================================================================
--- branches/2719_HeuristicLab.DatastreamAnalysis/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ClassificationModel.cs	(revision 15866)
+++ branches/2719_HeuristicLab.DatastreamAnalysis/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ClassificationModel.cs	(revision 17980)
@@ -1,5 +1,5 @@
 ﻿#region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
@@ -24,8 +24,8 @@
 using HeuristicLab.Common;
 using HeuristicLab.Core;
-using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HEAL.Attic;
 
 namespace HeuristicLab.Problems.DataAnalysis {
-  [StorableClass]
+  [StorableType("7E6091F9-86FD-4C47-8935-9C35CAB4261B")]
   [Item("Classification Model", "Base class for all classification models.")]
   public abstract class ClassificationModel : DataAnalysisModel, IClassificationModel {
@@ -41,6 +41,7 @@
     }
 
-    protected ClassificationModel(bool deserializing)
-      : base(deserializing) {
+    [StorableConstructor]
+    protected ClassificationModel(StorableConstructorFlag _)
+      : base(_) {
       targetVariable = string.Empty;
     }
@@ -66,4 +67,32 @@
     public abstract IClassificationSolution CreateClassificationSolution(IClassificationProblemData problemData);
 
+    public virtual bool IsProblemDataCompatible(IClassificationProblemData problemData, out string errorMessage) {
+      return IsProblemDataCompatible(this, problemData, out errorMessage);
+    }
+
+    public override bool IsProblemDataCompatible(IDataAnalysisProblemData problemData, out string errorMessage) {
+      if (problemData == null) throw new ArgumentNullException("problemData", "The provided problemData is null.");
+      var classificationProblemData = problemData as IClassificationProblemData;
+      if (classificationProblemData == null)
+        throw new ArgumentException("The problem data is not compatible with this classification model. Instead a " + problemData.GetType().GetPrettyName() + " was provided.", "problemData");
+      return IsProblemDataCompatible(classificationProblemData, out errorMessage);
+    }
+
+    public static bool IsProblemDataCompatible(IClassificationModel model, IClassificationProblemData problemData, out string errorMessage) {
+      if (model == null) throw new ArgumentNullException("model", "The provided model is null.");
+      if (problemData == null) throw new ArgumentNullException("problemData", "The provided problemData is null.");
+      errorMessage = string.Empty;
+
+      if (model.TargetVariable != problemData.TargetVariable)
+        errorMessage = string.Format("The target variable of the model {0} does not match the target variable of the problemData {1}.", model.TargetVariable, problemData.TargetVariable);
+
+      var evaluationErrorMessage = string.Empty;
+      var datasetCompatible = model.IsDatasetCompatible(problemData.Dataset, out evaluationErrorMessage);
+      if (!datasetCompatible)
+        errorMessage += evaluationErrorMessage;
+
+      return string.IsNullOrEmpty(errorMessage);
+    }
+
     #region events
     public event EventHandler TargetVariableChanged;
Index: branches/2719_HeuristicLab.DatastreamAnalysis/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ClassificationPerformanceMeasures.cs
===================================================================
--- branches/2719_HeuristicLab.DatastreamAnalysis/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ClassificationPerformanceMeasures.cs	(revision 15866)
+++ branches/2719_HeuristicLab.DatastreamAnalysis/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ClassificationPerformanceMeasures.cs	(revision 17980)
@@ -1,5 +1,5 @@
 ﻿#region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
@@ -24,8 +24,8 @@
 using HeuristicLab.Data;
 using HeuristicLab.Optimization;
-using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HEAL.Attic;
 
 namespace HeuristicLab.Problems.DataAnalysis {
-  [StorableClass]
+  [StorableType("6F44E140-22CF-48D3-B100-B6013F2B6608")]
   public class ClassificationPerformanceMeasuresResultCollection : ResultCollection {
     #region result names
@@ -54,6 +54,5 @@
     }
     [StorableConstructor]
-    protected ClassificationPerformanceMeasuresResultCollection(bool deserializing)
-      : base(deserializing) {
+    protected ClassificationPerformanceMeasuresResultCollection(StorableConstructorFlag _) : base(_) {
     }
 
Index: branches/2719_HeuristicLab.DatastreamAnalysis/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ClassificationProblem.cs
===================================================================
--- branches/2719_HeuristicLab.DatastreamAnalysis/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ClassificationProblem.cs	(revision 15866)
+++ branches/2719_HeuristicLab.DatastreamAnalysis/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ClassificationProblem.cs	(revision 17980)
@@ -1,5 +1,5 @@
 #region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
@@ -22,8 +22,8 @@
 using HeuristicLab.Common;
 using HeuristicLab.Core;
-using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HEAL.Attic;
 
 namespace HeuristicLab.Problems.DataAnalysis {
-  [StorableClass]
+  [StorableType("93696570-A410-4885-A210-7220771B6050")]
   [Item("Classification Problem", "A general classification problem.")]
   public class ClassificationProblem : DataAnalysisProblem<IClassificationProblemData>, IClassificationProblem, IStorableContent {
@@ -31,5 +31,5 @@
 
     [StorableConstructor]
-    protected ClassificationProblem(bool deserializing) : base(deserializing) { }
+    protected ClassificationProblem(StorableConstructorFlag _) : base(_) { }
     protected ClassificationProblem(ClassificationProblem original, Cloner cloner) : base(original, cloner) { }
     public override IDeepCloneable Clone(Cloner cloner) { return new ClassificationProblem(this, cloner); }
Index: branches/2719_HeuristicLab.DatastreamAnalysis/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ClassificationProblemData.cs
===================================================================
--- branches/2719_HeuristicLab.DatastreamAnalysis/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ClassificationProblemData.cs	(revision 15866)
+++ branches/2719_HeuristicLab.DatastreamAnalysis/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ClassificationProblemData.cs	(revision 17980)
@@ -1,5 +1,5 @@
 ﻿#region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
@@ -27,8 +27,8 @@
 using HeuristicLab.Data;
 using HeuristicLab.Parameters;
-using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HEAL.Attic;
 
 namespace HeuristicLab.Problems.DataAnalysis {
-  [StorableClass]
+  [StorableType("1C8DCCCF-4E2A-421D-9C61-7C017D584054")]
   [Item("ClassificationProblemData", "Represents an item containing all data defining a classification problem.")]
   public class ClassificationProblemData : DataAnalysisProblemData, IClassificationProblemData, IStorableContent {
@@ -279,5 +279,5 @@
 
     [StorableConstructor]
-    protected ClassificationProblemData(bool deserializing) : base(deserializing) { }
+    protected ClassificationProblemData(StorableConstructorFlag _) : base(_) { }
     [StorableHook(HookType.AfterDeserialization)]
     private void AfterDeserialization() {
@@ -467,53 +467,4 @@
     }
     #endregion
-
-    protected override bool IsProblemDataCompatible(IDataAnalysisProblemData problemData, out string errorMessage) {
-      if (problemData == null) throw new ArgumentNullException("problemData", "The provided problemData is null.");
-      IClassificationProblemData classificationProblemData = problemData as IClassificationProblemData;
-      if (classificationProblemData == null)
-        throw new ArgumentException("The problem data is no classification problem data. Instead a " + problemData.GetType().GetPrettyName() + " was provided.", "problemData");
-
-      var returnValue = base.IsProblemDataCompatible(classificationProblemData, out errorMessage);
-      //check targetVariable
-      if (classificationProblemData.InputVariables.All(var => var.Value != TargetVariable)) {
-        errorMessage = string.Format("The target variable {0} is not present in the new problem data.", TargetVariable)
-                       + Environment.NewLine + errorMessage;
-        return false;
-      }
-
-      var newClassValues = classificationProblemData.Dataset.GetDoubleValues(TargetVariable).Distinct().OrderBy(x => x);
-      if (!newClassValues.SequenceEqual(ClassValues)) {
-        errorMessage = errorMessage + string.Format("The class values differ in the provided classification problem data.");
-        returnValue = false;
-      }
-
-      var newPositivieClassName = classificationProblemData.PositiveClass;
-      if (newPositivieClassName != PositiveClass) {
-        errorMessage = errorMessage + string.Format("The positive class differs in the provided classification problem data.");
-        returnValue = false;
-      }
-
-      return returnValue;
-    }
-
-    public override void AdjustProblemDataProperties(IDataAnalysisProblemData problemData) {
-      if (problemData == null) throw new ArgumentNullException("problemData", "The provided problemData is null.");
-      ClassificationProblemData classificationProblemData = problemData as ClassificationProblemData;
-      if (classificationProblemData == null)
-        throw new ArgumentException("The problem data is not a classification problem data. Instead a " + problemData.GetType().GetPrettyName() + " was provided.", "problemData");
-
-      base.AdjustProblemDataProperties(problemData);
-      TargetVariable = classificationProblemData.TargetVariable;
-      for (int i = 0; i < classificationProblemData.ClassNames.Count(); i++)
-        ClassNamesParameter.Value[i, 0] = classificationProblemData.ClassNames.ElementAt(i);
-
-      PositiveClass = classificationProblemData.PositiveClass;
-
-      for (int i = 0; i < Classes; i++) {
-        for (int j = 0; j < Classes; j++) {
-          ClassificationPenaltiesParameter.Value[i, j] = classificationProblemData.GetClassificationPenalty(ClassValuesCache[i], ClassValuesCache[j]);
-        }
-      }
-    }
   }
 }
Index: branches/2719_HeuristicLab.DatastreamAnalysis/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ClassificationSolution.cs
===================================================================
--- branches/2719_HeuristicLab.DatastreamAnalysis/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ClassificationSolution.cs	(revision 15866)
+++ branches/2719_HeuristicLab.DatastreamAnalysis/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ClassificationSolution.cs	(revision 17980)
@@ -1,5 +1,5 @@
 #region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
@@ -23,5 +23,5 @@
 using System.Linq;
 using HeuristicLab.Common;
-using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HEAL.Attic;
 
 namespace HeuristicLab.Problems.DataAnalysis {
@@ -29,11 +29,10 @@
   /// Represents a classification data analysis solution
   /// </summary>
-  [StorableClass]
+  [StorableType("A240D831-23D6-4432-A105-12D02D2EA75A")]
   public class ClassificationSolution : ClassificationSolutionBase {
     protected readonly Dictionary<int, double> evaluationCache;
 
     [StorableConstructor]
-    protected ClassificationSolution(bool deserializing)
-      : base(deserializing) {
+    protected ClassificationSolution(StorableConstructorFlag _) : base(_) {
       evaluationCache = new Dictionary<int, double>();
     }
Index: branches/2719_HeuristicLab.DatastreamAnalysis/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ClassificationSolutionBase.cs
===================================================================
--- branches/2719_HeuristicLab.DatastreamAnalysis/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ClassificationSolutionBase.cs	(revision 15866)
+++ branches/2719_HeuristicLab.DatastreamAnalysis/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ClassificationSolutionBase.cs	(revision 17980)
@@ -1,5 +1,5 @@
 ﻿#region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
@@ -20,4 +20,5 @@
 #endregion
 
+using System;
 using System.Collections.Generic;
 using System.Linq;
@@ -25,9 +26,9 @@
 using HeuristicLab.Data;
 using HeuristicLab.Optimization;
-using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HEAL.Attic;
 using HeuristicLab.Problems.DataAnalysis.OnlineCalculators;
 
 namespace HeuristicLab.Problems.DataAnalysis {
-  [StorableClass]
+  [StorableType("60599497-EAF0-4DB0-B2E4-D58F34458D8F")]
   public abstract class ClassificationSolutionBase : DataAnalysisSolution, IClassificationSolution {
     private const string TrainingAccuracyResultName = "Accuracy (training)";
@@ -44,5 +45,11 @@
     public new IClassificationProblemData ProblemData {
       get { return (IClassificationProblemData)base.ProblemData; }
-      set { base.ProblemData = value; }
+      set {
+        if (value == null) throw new ArgumentNullException("The problemData must not be null.");
+        string errorMessage = string.Empty;
+        if (!Model.IsProblemDataCompatible(value, out errorMessage)) throw new ArgumentException(errorMessage);
+
+        base.ProblemData = value;
+      }
     }
 
@@ -71,5 +78,5 @@
 
     [StorableConstructor]
-    protected ClassificationSolutionBase(bool deserializing) : base(deserializing) { }
+    protected ClassificationSolutionBase(StorableConstructorFlag _) : base(_) { }
     protected ClassificationSolutionBase(ClassificationSolutionBase original, Cloner cloner)
       : base(original, cloner) {
Index: branches/2719_HeuristicLab.DatastreamAnalysis/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ClassificationSolutionVariableImpactsCalculator.cs
===================================================================
--- branches/2719_HeuristicLab.DatastreamAnalysis/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ClassificationSolutionVariableImpactsCalculator.cs	(revision 15866)
+++ branches/2719_HeuristicLab.DatastreamAnalysis/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ClassificationSolutionVariableImpactsCalculator.cs	(revision 17980)
@@ -2,5 +2,5 @@
 
 /* HeuristicLab
- * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
@@ -23,4 +23,5 @@
 
 using System;
+using System.Collections;
 using System.Collections.Generic;
 using System.Linq;
@@ -29,11 +30,13 @@
 using HeuristicLab.Data;
 using HeuristicLab.Parameters;
-using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HEAL.Attic;
 using HeuristicLab.Random;
 
 namespace HeuristicLab.Problems.DataAnalysis {
-  [StorableClass]
+  [StorableType("768AFEDB-5641-429E-85A1-A0BE8DFDD56F")]
   [Item("ClassificationSolution Impacts Calculator", "Calculation of the impacts of input variables for any classification solution")]
   public sealed class ClassificationSolutionVariableImpactsCalculator : ParameterizedNamedItem {
+    #region Parameters/Properties
+    [StorableType("e6cd2226-10cd-4765-ae1a-924e316b6aac")]
     public enum ReplacementMethodEnum {
       Median,
@@ -42,4 +45,6 @@
       Noise
     }
+
+    [StorableType("84d84ccf-5d6d-432f-a946-eb499935e5c8")]
     public enum FactorReplacementMethodEnum {
       Best,
@@ -47,4 +52,6 @@
       Shuffle
     }
+
+    [StorableType("70f30113-df01-41b4-9e3b-2982035de498")]
     public enum DataPartitionEnum {
       Training,
@@ -54,8 +61,12 @@
 
     private const string ReplacementParameterName = "Replacement Method";
+    private const string FactorReplacementParameterName = "Factor Replacement Method";
     private const string DataPartitionParameterName = "DataPartition";
 
     public IFixedValueParameter<EnumValue<ReplacementMethodEnum>> ReplacementParameter {
       get { return (IFixedValueParameter<EnumValue<ReplacementMethodEnum>>)Parameters[ReplacementParameterName]; }
+    }
+    public IFixedValueParameter<EnumValue<FactorReplacementMethodEnum>> FactorReplacementParameter {
+      get { return (IFixedValueParameter<EnumValue<FactorReplacementMethodEnum>>)Parameters[FactorReplacementParameterName]; }
     }
     public IFixedValueParameter<EnumValue<DataPartitionEnum>> DataPartitionParameter {
@@ -67,135 +78,154 @@
       set { ReplacementParameter.Value.Value = value; }
     }
+    public FactorReplacementMethodEnum FactorReplacementMethod {
+      get { return FactorReplacementParameter.Value.Value; }
+      set { FactorReplacementParameter.Value.Value = value; }
+    }
     public DataPartitionEnum DataPartition {
       get { return DataPartitionParameter.Value.Value; }
       set { DataPartitionParameter.Value.Value = value; }
     }
-
-
+    #endregion
+
+    #region Ctor/Cloner
     [StorableConstructor]
-    private ClassificationSolutionVariableImpactsCalculator(bool deserializing) : base(deserializing) { }
+    private ClassificationSolutionVariableImpactsCalculator(StorableConstructorFlag _) : base(_) { }
     private ClassificationSolutionVariableImpactsCalculator(ClassificationSolutionVariableImpactsCalculator original, Cloner cloner)
       : base(original, cloner) { }
+    public ClassificationSolutionVariableImpactsCalculator()
+      : base() {
+      Parameters.Add(new FixedValueParameter<EnumValue<ReplacementMethodEnum>>(ReplacementParameterName, "The replacement method for variables during impact calculation.", new EnumValue<ReplacementMethodEnum>(ReplacementMethodEnum.Shuffle)));
+      Parameters.Add(new FixedValueParameter<EnumValue<FactorReplacementMethodEnum>>(FactorReplacementParameterName, "The replacement method for factor variables during impact calculation.", new EnumValue<FactorReplacementMethodEnum>(FactorReplacementMethodEnum.Best)));
+      Parameters.Add(new FixedValueParameter<EnumValue<DataPartitionEnum>>(DataPartitionParameterName, "The data partition on which the impacts are calculated.", new EnumValue<DataPartitionEnum>(DataPartitionEnum.Training)));
+    }
+
     public override IDeepCloneable Clone(Cloner cloner) {
       return new ClassificationSolutionVariableImpactsCalculator(this, cloner);
     }
-
-    public ClassificationSolutionVariableImpactsCalculator()
-      : base() {
-      Parameters.Add(new FixedValueParameter<EnumValue<ReplacementMethodEnum>>(ReplacementParameterName, "The replacement method for variables during impact calculation.", new EnumValue<ReplacementMethodEnum>(ReplacementMethodEnum.Median)));
-      Parameters.Add(new FixedValueParameter<EnumValue<DataPartitionEnum>>(DataPartitionParameterName, "The data partition on which the impacts are calculated.", new EnumValue<DataPartitionEnum>(DataPartitionEnum.Training)));
-    }
+    #endregion
 
     //mkommend: annoying name clash with static method, open to better naming suggestions
     public IEnumerable<Tuple<string, double>> Calculate(IClassificationSolution solution) {
-      return CalculateImpacts(solution, DataPartition, ReplacementMethod);
+      return CalculateImpacts(solution, ReplacementMethod, FactorReplacementMethod, DataPartition);
     }
 
     public static IEnumerable<Tuple<string, double>> CalculateImpacts(
       IClassificationSolution solution,
-      DataPartitionEnum data = DataPartitionEnum.Training,
-      ReplacementMethodEnum replacementMethod = ReplacementMethodEnum.Median,
+      ReplacementMethodEnum replacementMethod = ReplacementMethodEnum.Shuffle,
+      FactorReplacementMethodEnum factorReplacementMethod = FactorReplacementMethodEnum.Best,
+      DataPartitionEnum dataPartition = DataPartitionEnum.Training) {
+
+      IEnumerable<int> rows = GetPartitionRows(dataPartition, solution.ProblemData);
+      IEnumerable<double> estimatedClassValues = solution.GetEstimatedClassValues(rows);
+      var model = (IClassificationModel)solution.Model.Clone(); //mkommend: clone of model is necessary, because the thresholds for IDiscriminantClassificationModels are updated
+
+      return CalculateImpacts(model, solution.ProblemData, estimatedClassValues, rows, replacementMethod, factorReplacementMethod);
+    }
+
+    public static IEnumerable<Tuple<string, double>> CalculateImpacts(
+     IClassificationModel model,
+     IClassificationProblemData problemData,
+     IEnumerable<double> estimatedClassValues,
+     IEnumerable<int> rows,
+     ReplacementMethodEnum replacementMethod = ReplacementMethodEnum.Shuffle,
+     FactorReplacementMethodEnum factorReplacementMethod = FactorReplacementMethodEnum.Best) {
+
+      //fholzing: try and catch in case a different dataset is loaded, otherwise statement is neglectable
+      var missingVariables = model.VariablesUsedForPrediction.Except(problemData.Dataset.VariableNames);
+      if (missingVariables.Any()) {
+        throw new InvalidOperationException(string.Format("Can not calculate variable impacts, because the model uses inputs missing in the dataset ({0})", string.Join(", ", missingVariables)));
+      }
+      IEnumerable<double> targetValues = problemData.Dataset.GetDoubleValues(problemData.TargetVariable, rows);
+      var originalQuality = CalculateQuality(targetValues, estimatedClassValues);
+
+      var impacts = new Dictionary<string, double>();
+      var inputvariables = new HashSet<string>(problemData.AllowedInputVariables.Union(model.VariablesUsedForPrediction));
+      var modifiableDataset = ((Dataset)(problemData.Dataset).Clone()).ToModifiable();
+
+      foreach (var inputVariable in inputvariables) {
+        impacts[inputVariable] = CalculateImpact(inputVariable, model, problemData, modifiableDataset, rows, replacementMethod, factorReplacementMethod, targetValues, originalQuality);
+      }
+
+      return impacts.Select(i => Tuple.Create(i.Key, i.Value));
+    }
+
+    public static double CalculateImpact(string variableName,
+      IClassificationModel model,
+      IClassificationProblemData problemData,
+      ModifiableDataset modifiableDataset,
+      IEnumerable<int> rows,
+      ReplacementMethodEnum replacementMethod = ReplacementMethodEnum.Shuffle,
+      FactorReplacementMethodEnum factorReplacementMethod = FactorReplacementMethodEnum.Best,
+      IEnumerable<double> targetValues = null,
+      double quality = double.NaN) {
+
+      if (!model.VariablesUsedForPrediction.Contains(variableName)) { return 0.0; }
+      if (!problemData.Dataset.VariableNames.Contains(variableName)) {
+        throw new InvalidOperationException(string.Format("Can not calculate variable impact, because the model uses inputs missing in the dataset ({0})", variableName));
+      }
+
+      if (targetValues == null) {
+        targetValues = problemData.Dataset.GetDoubleValues(problemData.TargetVariable, rows);
+      }
+      if (quality == double.NaN) {
+        quality = CalculateQuality(model.GetEstimatedClassValues(modifiableDataset, rows), targetValues);
+      }
+
+      IList originalValues = null;
+      IList replacementValues = GetReplacementValues(modifiableDataset, variableName, model, rows, targetValues, out originalValues, replacementMethod, factorReplacementMethod);
+
+      double newValue = CalculateQualityForReplacement(model, modifiableDataset, variableName, originalValues, rows, replacementValues, targetValues);
+      double impact = quality - newValue;
+
+      return impact;
+    }
+
+    private static IList GetReplacementValues(ModifiableDataset modifiableDataset,
+      string variableName,
+      IClassificationModel model,
+      IEnumerable<int> rows,
+      IEnumerable<double> targetValues,
+      out IList originalValues,
+      ReplacementMethodEnum replacementMethod = ReplacementMethodEnum.Shuffle,
       FactorReplacementMethodEnum factorReplacementMethod = FactorReplacementMethodEnum.Best) {
 
-      var problemData = solution.ProblemData;
-      var dataset = problemData.Dataset;
-
-      IEnumerable<int> rows;
-      IEnumerable<double> targetValues;
-      double originalAccuracy;
-
-      OnlineCalculatorError error;
-
-      switch (data) {
-        case DataPartitionEnum.All:
-          rows = problemData.AllIndices;
-          targetValues = problemData.Dataset.GetDoubleValues(problemData.TargetVariable, problemData.AllIndices).ToList();
-          originalAccuracy = OnlineAccuracyCalculator.Calculate(targetValues, solution.EstimatedClassValues, out error);
-          if (error != OnlineCalculatorError.None) throw new InvalidOperationException("Error during accuracy calculation.");
-          break;
-        case DataPartitionEnum.Training:
-          rows = problemData.TrainingIndices;
-          targetValues = problemData.Dataset.GetDoubleValues(problemData.TargetVariable, problemData.TrainingIndices).ToList();
-          originalAccuracy = OnlineAccuracyCalculator.Calculate(targetValues, solution.EstimatedTrainingClassValues, out error);
-          if (error != OnlineCalculatorError.None) throw new InvalidOperationException("Error during accuracy calculation.");
-          break;
-        case DataPartitionEnum.Test:
-          rows = problemData.TestIndices;
-          targetValues = problemData.Dataset.GetDoubleValues(problemData.TargetVariable, problemData.TestIndices).ToList();
-          originalAccuracy = OnlineAccuracyCalculator.Calculate(targetValues, solution.EstimatedTestClassValues, out error);
-          if (error != OnlineCalculatorError.None) throw new InvalidOperationException("Error during accuracy calculation.");
-          break;
-        default: throw new ArgumentException(string.Format("DataPartition {0} cannot be handled.", data));
-      }
-
-      var impacts = new Dictionary<string, double>();
-      var modifiableDataset = ((Dataset)dataset).ToModifiable();
-
-      var inputvariables = new HashSet<string>(problemData.AllowedInputVariables.Union(solution.Model.VariablesUsedForPrediction));
-      var allowedInputVariables = dataset.VariableNames.Where(v => inputvariables.Contains(v)).ToList();
-
-      // calculate impacts for double variables
-      foreach (var inputVariable in allowedInputVariables.Where(problemData.Dataset.VariableHasType<double>)) {
-        var newEstimates = EvaluateModelWithReplacedVariable(solution.Model, inputVariable, modifiableDataset, rows, replacementMethod);
-        var newAccuracy = OnlineAccuracyCalculator.Calculate(targetValues, newEstimates, out error);
-        if (error != OnlineCalculatorError.None) throw new InvalidOperationException("Error during R² calculation with replaced inputs.");
-
-        impacts[inputVariable] = originalAccuracy - newAccuracy;
-      }
-
-      // calculate impacts for string variables
-      foreach (var inputVariable in allowedInputVariables.Where(problemData.Dataset.VariableHasType<string>)) {
-        if (factorReplacementMethod == FactorReplacementMethodEnum.Best) {
-          // try replacing with all possible values and find the best replacement value
-          var smallestImpact = double.PositiveInfinity;
-          foreach (var repl in problemData.Dataset.GetStringValues(inputVariable, rows).Distinct()) {
-            var newEstimates = EvaluateModelWithReplacedVariable(solution.Model, inputVariable, modifiableDataset, rows,
-              Enumerable.Repeat(repl, dataset.Rows));
-            var newAccuracy = OnlineAccuracyCalculator.Calculate(targetValues, newEstimates, out error);
-            if (error != OnlineCalculatorError.None)
-              throw new InvalidOperationException("Error during accuracy calculation with replaced inputs.");
-
-            var impact = originalAccuracy - newAccuracy;
-            if (impact < smallestImpact) smallestImpact = impact;
-          }
-          impacts[inputVariable] = smallestImpact;
-        } else {
-          // for replacement methods shuffle and mode
-          // calculate impacts for factor variables
-
-          var newEstimates = EvaluateModelWithReplacedVariable(solution.Model, inputVariable, modifiableDataset, rows,
-            factorReplacementMethod);
-          var newAccuracy = OnlineAccuracyCalculator.Calculate(targetValues, newEstimates, out error);
-          if (error != OnlineCalculatorError.None)
-            throw new InvalidOperationException("Error during accuracy calculation with replaced inputs.");
-
-          impacts[inputVariable] = originalAccuracy - newAccuracy;
-        }
-      } // foreach
-      return impacts.OrderByDescending(i => i.Value).Select(i => Tuple.Create(i.Key, i.Value));
-    }
-
-    private static IEnumerable<double> EvaluateModelWithReplacedVariable(IClassificationModel model, string variable, ModifiableDataset dataset, IEnumerable<int> rows, ReplacementMethodEnum replacement = ReplacementMethodEnum.Median) {
-      var originalValues = dataset.GetReadOnlyDoubleValues(variable).ToList();
+      IList replacementValues = null;
+      if (modifiableDataset.VariableHasType<double>(variableName)) {
+        originalValues = modifiableDataset.GetReadOnlyDoubleValues(variableName).ToList();
+        replacementValues = GetReplacementValuesForDouble(modifiableDataset, rows, (List<double>)originalValues, replacementMethod);
+      } else if (modifiableDataset.VariableHasType<string>(variableName)) {
+        originalValues = modifiableDataset.GetReadOnlyStringValues(variableName).ToList();
+        replacementValues = GetReplacementValuesForString(model, modifiableDataset, variableName, rows, (List<string>)originalValues, targetValues, factorReplacementMethod);
+      } else {
+        throw new NotSupportedException("Variable not supported");
+      }
+
+      return replacementValues;
+    }
+
+    private static IList GetReplacementValuesForDouble(ModifiableDataset modifiableDataset,
+      IEnumerable<int> rows,
+      List<double> originalValues,
+      ReplacementMethodEnum replacementMethod = ReplacementMethodEnum.Shuffle) {
+
+      IRandom random = new FastRandom(31415);
+      List<double> replacementValues;
       double replacementValue;
-      List<double> replacementValues;
-      IRandom rand;
-
-      switch (replacement) {
+
+      switch (replacementMethod) {
         case ReplacementMethodEnum.Median:
           replacementValue = rows.Select(r => originalValues[r]).Median();
-          replacementValues = Enumerable.Repeat(replacementValue, dataset.Rows).ToList();
+          replacementValues = Enumerable.Repeat(replacementValue, modifiableDataset.Rows).ToList();
           break;
         case ReplacementMethodEnum.Average:
           replacementValue = rows.Select(r => originalValues[r]).Average();
-          replacementValues = Enumerable.Repeat(replacementValue, dataset.Rows).ToList();
+          replacementValues = Enumerable.Repeat(replacementValue, modifiableDataset.Rows).ToList();
           break;
         case ReplacementMethodEnum.Shuffle:
           // new var has same empirical distribution but the relation to y is broken
-          rand = new FastRandom(31415);
           // prepare a complete column for the dataset
-          replacementValues = Enumerable.Repeat(double.NaN, dataset.Rows).ToList();
+          replacementValues = Enumerable.Repeat(double.NaN, modifiableDataset.Rows).ToList();
           // shuffle only the selected rows
-          var shuffledValues = rows.Select(r => originalValues[r]).Shuffle(rand).ToList();
+          var shuffledValues = rows.Select(r => originalValues[r]).Shuffle(random).ToList();
           int i = 0;
           // update column values 
@@ -207,29 +237,46 @@
           var avg = rows.Select(r => originalValues[r]).Average();
           var stdDev = rows.Select(r => originalValues[r]).StandardDeviation();
-          rand = new FastRandom(31415);
           // prepare a complete column for the dataset
-          replacementValues = Enumerable.Repeat(double.NaN, dataset.Rows).ToList();
+          replacementValues = Enumerable.Repeat(double.NaN, modifiableDataset.Rows).ToList();
           // update column values 
           foreach (var r in rows) {
-            replacementValues[r] = NormalDistributedRandom.NextDouble(rand, avg, stdDev);
+            replacementValues[r] = NormalDistributedRandom.NextDouble(random, avg, stdDev);
           }
           break;
 
         default:
-          throw new ArgumentException(string.Format("ReplacementMethod {0} cannot be handled.", replacement));
-      }
-
-      return EvaluateModelWithReplacedVariable(model, variable, dataset, rows, replacementValues);
-    }
-
-    private static IEnumerable<double> EvaluateModelWithReplacedVariable(
-      IClassificationModel model, string variable, ModifiableDataset dataset,
-      IEnumerable<int> rows,
-      FactorReplacementMethodEnum replacement = FactorReplacementMethodEnum.Shuffle) {
-      var originalValues = dataset.GetReadOnlyStringValues(variable).ToList();
-      List<string> replacementValues;
-      IRandom rand;
-
-      switch (replacement) {
+          throw new ArgumentException(string.Format("ReplacementMethod {0} cannot be handled.", replacementMethod));
+      }
+
+      return replacementValues;
+    }
+
+    private static IList GetReplacementValuesForString(IClassificationModel model,
+      ModifiableDataset modifiableDataset,
+      string variableName,
+      IEnumerable<int> rows,
+      List<string> originalValues,
+      IEnumerable<double> targetValues,
+      FactorReplacementMethodEnum factorReplacementMethod = FactorReplacementMethodEnum.Shuffle) {
+
+      List<string> replacementValues = null;
+      IRandom random = new FastRandom(31415);
+
+      switch (factorReplacementMethod) {
+        case FactorReplacementMethodEnum.Best:
+          // try replacing with all possible values and find the best replacement value
+          var bestQuality = double.NegativeInfinity;
+          foreach (var repl in modifiableDataset.GetStringValues(variableName, rows).Distinct()) {
+            List<string> curReplacementValues = Enumerable.Repeat(repl, modifiableDataset.Rows).ToList();
+            //fholzing: this result could be used later on (theoretically), but is neglected for better readability/method consistency 
+            var newValue = CalculateQualityForReplacement(model, modifiableDataset, variableName, originalValues, rows, curReplacementValues, targetValues);
+            var curQuality = newValue;
+
+            if (curQuality > bestQuality) {
+              bestQuality = curQuality;
+              replacementValues = curReplacementValues;
+            }
+          }
+          break;
         case FactorReplacementMethodEnum.Mode:
           var mostCommonValue = rows.Select(r => originalValues[r])
@@ -237,13 +284,12 @@
             .OrderByDescending(g => g.Count())
             .First().Key;
-          replacementValues = Enumerable.Repeat(mostCommonValue, dataset.Rows).ToList();
+          replacementValues = Enumerable.Repeat(mostCommonValue, modifiableDataset.Rows).ToList();
           break;
         case FactorReplacementMethodEnum.Shuffle:
           // new var has same empirical distribution but the relation to y is broken
-          rand = new FastRandom(31415);
           // prepare a complete column for the dataset
-          replacementValues = Enumerable.Repeat(string.Empty, dataset.Rows).ToList();
+          replacementValues = Enumerable.Repeat(string.Empty, modifiableDataset.Rows).ToList();
           // shuffle only the selected rows
-          var shuffledValues = rows.Select(r => originalValues[r]).Shuffle(rand).ToList();
+          var shuffledValues = rows.Select(r => originalValues[r]).Shuffle(random).ToList();
           int i = 0;
           // update column values 
@@ -253,29 +299,59 @@
           break;
         default:
-          throw new ArgumentException(string.Format("FactorReplacementMethod {0} cannot be handled.", replacement));
-      }
-
-      return EvaluateModelWithReplacedVariable(model, variable, dataset, rows, replacementValues);
-    }
-
-    private static IEnumerable<double> EvaluateModelWithReplacedVariable(IClassificationModel model, string variable,
-      ModifiableDataset dataset, IEnumerable<int> rows, IEnumerable<double> replacementValues) {
-      var originalValues = dataset.GetReadOnlyDoubleValues(variable).ToList();
-      dataset.ReplaceVariable(variable, replacementValues.ToList());
+          throw new ArgumentException(string.Format("FactorReplacementMethod {0} cannot be handled.", factorReplacementMethod));
+      }
+
+      return replacementValues;
+    }
+
+    private static double CalculateQualityForReplacement(
+      IClassificationModel model,
+      ModifiableDataset modifiableDataset,
+      string variableName,
+      IList originalValues,
+      IEnumerable<int> rows,
+      IList replacementValues,
+      IEnumerable<double> targetValues) {
+
+      modifiableDataset.ReplaceVariable(variableName, replacementValues);
+      var discModel = model as IDiscriminantFunctionClassificationModel;
+      if (discModel != null) {
+        var problemData = new ClassificationProblemData(modifiableDataset, modifiableDataset.VariableNames, model.TargetVariable);
+        discModel.RecalculateModelParameters(problemData, rows);
+      }
+
       //mkommend: ToList is used on purpose to avoid lazy evaluation that could result in wrong estimates due to variable replacements
-      var estimates = model.GetEstimatedClassValues(dataset, rows).ToList();
-      dataset.ReplaceVariable(variable, originalValues);
-
-      return estimates;
-    }
-    private static IEnumerable<double> EvaluateModelWithReplacedVariable(IClassificationModel model, string variable,
-      ModifiableDataset dataset, IEnumerable<int> rows, IEnumerable<string> replacementValues) {
-      var originalValues = dataset.GetReadOnlyStringValues(variable).ToList();
-      dataset.ReplaceVariable(variable, replacementValues.ToList());
-      //mkommend: ToList is used on purpose to avoid lazy evaluation that could result in wrong estimates due to variable replacements
-      var estimates = model.GetEstimatedClassValues(dataset, rows).ToList();
-      dataset.ReplaceVariable(variable, originalValues);
-
-      return estimates;
+      var estimates = model.GetEstimatedClassValues(modifiableDataset, rows).ToList();
+      var ret = CalculateQuality(targetValues, estimates);
+      modifiableDataset.ReplaceVariable(variableName, originalValues);
+
+      return ret;
+    }
+
+    public static double CalculateQuality(IEnumerable<double> targetValues, IEnumerable<double> estimatedClassValues) {
+      OnlineCalculatorError errorState;
+      var ret = OnlineAccuracyCalculator.Calculate(targetValues, estimatedClassValues, out errorState);
+      if (errorState != OnlineCalculatorError.None) { throw new InvalidOperationException("Error during calculation with replaced inputs."); }
+      return ret;
+    }
+
+    public static IEnumerable<int> GetPartitionRows(DataPartitionEnum dataPartition, IClassificationProblemData problemData) {
+      IEnumerable<int> rows;
+
+      switch (dataPartition) {
+        case DataPartitionEnum.All:
+          rows = problemData.AllIndices;
+          break;
+        case DataPartitionEnum.Test:
+          rows = problemData.TestIndices;
+          break;
+        case DataPartitionEnum.Training:
+          rows = problemData.TrainingIndices;
+          break;
+        default:
+          throw new NotSupportedException("DataPartition not supported");
+      }
+
+      return rows;
     }
   }
Index: branches/2719_HeuristicLab.DatastreamAnalysis/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ConstantClassificationSolution.cs
===================================================================
--- branches/2719_HeuristicLab.DatastreamAnalysis/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ConstantClassificationSolution.cs	(revision 15866)
+++ branches/2719_HeuristicLab.DatastreamAnalysis/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ConstantClassificationSolution.cs	(revision 17980)
@@ -1,5 +1,5 @@
 ﻿#region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
@@ -22,8 +22,8 @@
 using HeuristicLab.Common;
 using HeuristicLab.Core;
-using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HEAL.Attic;
 
 namespace HeuristicLab.Problems.DataAnalysis {
-  [StorableClass]
+  [StorableType("D5A42FE7-D21B-48F7-A812-FE69724D0098")]
   [Item(Name = "Constant Classification Solution", Description = "Represents a constant classification solution (model + data).")]
   public class ConstantClassificationSolution : ClassificationSolution {
@@ -34,5 +34,5 @@
 
     [StorableConstructor]
-    protected ConstantClassificationSolution(bool deserializing) : base(deserializing) { }
+    protected ConstantClassificationSolution(StorableConstructorFlag _) : base(_) { }
     protected ConstantClassificationSolution(ConstantClassificationSolution original, Cloner cloner) : base(original, cloner) { }
     public ConstantClassificationSolution(ConstantModel model, IClassificationProblemData problemData)
Index: branches/2719_HeuristicLab.DatastreamAnalysis/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/DiscriminantFunctionClassificationModel.cs
===================================================================
--- branches/2719_HeuristicLab.DatastreamAnalysis/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/DiscriminantFunctionClassificationModel.cs	(revision 15866)
+++ branches/2719_HeuristicLab.DatastreamAnalysis/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/DiscriminantFunctionClassificationModel.cs	(revision 17980)
@@ -1,5 +1,5 @@
 #region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
@@ -23,7 +23,7 @@
 using System.Collections.Generic;
 using System.Linq;
+using HEAL.Attic;
 using HeuristicLab.Common;
 using HeuristicLab.Core;
-using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
 
 namespace HeuristicLab.Problems.DataAnalysis {
@@ -31,5 +31,5 @@
   /// Represents discriminant function classification data analysis models.
   /// </summary>
-  [StorableClass]
+  [StorableType("E7A8648D-C938-499F-A712-185542095708")]
   [Item("DiscriminantFunctionClassificationModel", "Represents a classification model that uses a discriminant function and classification thresholds.")]
   public class DiscriminantFunctionClassificationModel : ClassificationModel, IDiscriminantFunctionClassificationModel {
@@ -68,5 +68,5 @@
 
     [StorableConstructor]
-    protected DiscriminantFunctionClassificationModel(bool deserializing) : base(deserializing) { }
+    protected DiscriminantFunctionClassificationModel(StorableConstructorFlag _) : base(_) { }
     protected DiscriminantFunctionClassificationModel(DiscriminantFunctionClassificationModel original, Cloner cloner)
       : base(original, cloner) {
@@ -121,6 +121,11 @@
 
     public override IEnumerable<double> GetEstimatedClassValues(IDataset dataset, IEnumerable<int> rows) {
+      var estimatedValues = GetEstimatedValues(dataset, rows);
+      return GetEstimatedClassValues(estimatedValues);
+    }
+
+    public virtual IEnumerable<double> GetEstimatedClassValues(IEnumerable<double> estimatedValues) {
       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)) {
+      foreach (var x in estimatedValues) {
         int classIndex = 0;
         // find first threshold value which is larger than x => class index = threshold index + 1
@@ -132,4 +137,5 @@
       }
     }
+
     #region events
     public event EventHandler ThresholdsChanged;
Index: branches/2719_HeuristicLab.DatastreamAnalysis/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/DiscriminantFunctionClassificationSolution.cs
===================================================================
--- branches/2719_HeuristicLab.DatastreamAnalysis/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/DiscriminantFunctionClassificationSolution.cs	(revision 15866)
+++ branches/2719_HeuristicLab.DatastreamAnalysis/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/DiscriminantFunctionClassificationSolution.cs	(revision 17980)
@@ -1,5 +1,5 @@
 #region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
@@ -24,5 +24,5 @@
 using HeuristicLab.Common;
 using HeuristicLab.Core;
-using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HEAL.Attic;
 
 namespace HeuristicLab.Problems.DataAnalysis {
@@ -30,5 +30,5 @@
   /// Represents a classification solution that uses a discriminant function and classification thresholds.
   /// </summary>
-  [StorableClass]
+  [StorableType("A3480DF9-49E7-4329-AD23-57B4441033C1")]
   [Item("DiscriminantFunctionClassificationSolution", "Represents a classification solution that uses a discriminant function and classification thresholds.")]
   public class DiscriminantFunctionClassificationSolution : DiscriminantFunctionClassificationSolutionBase {
@@ -37,6 +37,5 @@
 
     [StorableConstructor]
-    protected DiscriminantFunctionClassificationSolution(bool deserializing)
-      : base(deserializing) {
+    protected DiscriminantFunctionClassificationSolution(StorableConstructorFlag _) : base(_) {
       valueEvaluationCache = new Dictionary<int, double>();
       classValueEvaluationCache = new Dictionary<int, double>();
Index: branches/2719_HeuristicLab.DatastreamAnalysis/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/DiscriminantFunctionClassificationSolutionBase.cs
===================================================================
--- branches/2719_HeuristicLab.DatastreamAnalysis/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/DiscriminantFunctionClassificationSolutionBase.cs	(revision 15866)
+++ branches/2719_HeuristicLab.DatastreamAnalysis/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/DiscriminantFunctionClassificationSolutionBase.cs	(revision 17980)
@@ -1,5 +1,5 @@
 ﻿#region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
@@ -27,5 +27,5 @@
 using HeuristicLab.Data;
 using HeuristicLab.Optimization;
-using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HEAL.Attic;
 
 namespace HeuristicLab.Problems.DataAnalysis {
@@ -33,5 +33,5 @@
   /// Represents a classification solution that uses a discriminant function and classification thresholds.
   /// </summary>
-  [StorableClass]
+  [StorableType("3668EBE0-128C-4BC4-902C-161670F98FAD")]
   [Item("DiscriminantFunctionClassificationSolution", "Represents a classification solution that uses a discriminant function and classification thresholds.")]
   public abstract class DiscriminantFunctionClassificationSolutionBase : ClassificationSolutionBase, IDiscriminantFunctionClassificationSolution {
@@ -74,5 +74,5 @@
 
     [StorableConstructor]
-    protected DiscriminantFunctionClassificationSolutionBase(bool deserializing) : base(deserializing) { }
+    protected DiscriminantFunctionClassificationSolutionBase(StorableConstructorFlag _) : base(_) { }
     protected DiscriminantFunctionClassificationSolutionBase(DiscriminantFunctionClassificationSolutionBase original, Cloner cloner)
       : base(original, cloner) {
Index: branches/2719_HeuristicLab.DatastreamAnalysis/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ThresholdCalculators/AccuracyMaximizationThresholdCalculator.cs
===================================================================
--- branches/2719_HeuristicLab.DatastreamAnalysis/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ThresholdCalculators/AccuracyMaximizationThresholdCalculator.cs	(revision 15866)
+++ branches/2719_HeuristicLab.DatastreamAnalysis/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ThresholdCalculators/AccuracyMaximizationThresholdCalculator.cs	(revision 17980)
@@ -1,5 +1,5 @@
 #region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
@@ -25,5 +25,5 @@
 using HeuristicLab.Common;
 using HeuristicLab.Core;
-using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HEAL.Attic;
 
 namespace HeuristicLab.Problems.DataAnalysis {
@@ -31,10 +31,10 @@
   /// Represents a threshold calculator that maximizes the weighted accuracy of the classifcation model.
   /// </summary>
-  [StorableClass]
+  [StorableType("30BB9513-542D-4CB8-931B-9767C9CB2EFB")]
   [Item("AccuracyMaximizationThresholdCalculator", "Represents a threshold calculator that maximizes the weighted accuracy of the classifcation model.")]
   public class AccuracyMaximizationThresholdCalculator : ThresholdCalculator {
 
     [StorableConstructor]
-    protected AccuracyMaximizationThresholdCalculator(bool deserializing) : base(deserializing) { }
+    protected AccuracyMaximizationThresholdCalculator(StorableConstructorFlag _) : base(_) { }
     protected AccuracyMaximizationThresholdCalculator(AccuracyMaximizationThresholdCalculator original, Cloner cloner)
       : base(original, cloner) {
Index: branches/2719_HeuristicLab.DatastreamAnalysis/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ThresholdCalculators/NormalDistributionCutPointsThresholdCalculator.cs
===================================================================
--- branches/2719_HeuristicLab.DatastreamAnalysis/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ThresholdCalculators/NormalDistributionCutPointsThresholdCalculator.cs	(revision 15866)
+++ branches/2719_HeuristicLab.DatastreamAnalysis/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ThresholdCalculators/NormalDistributionCutPointsThresholdCalculator.cs	(revision 17980)
@@ -1,5 +1,5 @@
 #region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
@@ -25,5 +25,5 @@
 using HeuristicLab.Common;
 using HeuristicLab.Core;
-using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HEAL.Attic;
 
 namespace HeuristicLab.Problems.DataAnalysis {
@@ -31,10 +31,10 @@
   /// Represents a threshold calculator that calculates thresholds as the cutting points between the estimated class distributions (assuming normally distributed class values).
   /// </summary>
-  [StorableClass]
+  [StorableType("D01CB5DC-606B-4CE9-B293-2D4D80A70BB8")]
   [Item("NormalDistributionCutPointsThresholdCalculator", "Represents a threshold calculator that calculates thresholds as the cutting points between the estimated class distributions (assuming normally distributed class values).")]
   public class NormalDistributionCutPointsThresholdCalculator : ThresholdCalculator {
 
     [StorableConstructor]
-    protected NormalDistributionCutPointsThresholdCalculator(bool deserializing) : base(deserializing) { }
+    protected NormalDistributionCutPointsThresholdCalculator(StorableConstructorFlag _) : base(_) { }
     protected NormalDistributionCutPointsThresholdCalculator(NormalDistributionCutPointsThresholdCalculator original, Cloner cloner)
       : base(original, cloner) {
Index: branches/2719_HeuristicLab.DatastreamAnalysis/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ThresholdCalculators/ThresholdCalculator.cs
===================================================================
--- branches/2719_HeuristicLab.DatastreamAnalysis/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ThresholdCalculators/ThresholdCalculator.cs	(revision 15866)
+++ branches/2719_HeuristicLab.DatastreamAnalysis/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ThresholdCalculators/ThresholdCalculator.cs	(revision 17980)
@@ -1,5 +1,5 @@
 #region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
@@ -23,5 +23,5 @@
 using HeuristicLab.Common;
 using HeuristicLab.Core;
-using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HEAL.Attic;
 
 namespace HeuristicLab.Problems.DataAnalysis {
@@ -29,9 +29,9 @@
   /// Base class for threshold calculators for discriminant function classification models.
   /// </summary>
-  [StorableClass]
+  [StorableType("F56CDC6C-D4F5-4B2D-A7C4-04E0D2255699")]
   public abstract class ThresholdCalculator : NamedItem, IDiscriminantFunctionThresholdCalculator {
 
     [StorableConstructor]
-    protected ThresholdCalculator(bool deserializing) : base(deserializing) { }
+    protected ThresholdCalculator(StorableConstructorFlag _) : base(_) { }
     protected ThresholdCalculator(ThresholdCalculator original, Cloner cloner)
       : base(original, cloner) {
