Index: /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/Linear/LinearDiscriminantAnalysis.cs
===================================================================
--- /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/Linear/LinearDiscriminantAnalysis.cs	(revision 8593)
+++ /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/Linear/LinearDiscriminantAnalysis.cs	(revision 8594)
@@ -111,6 +111,6 @@
       IClassificationProblemData problemData,
       IEnumerable<int> rows) {
-      var model = new SymbolicDiscriminantFunctionClassificationModel(tree, interpreter);
-      model.SetAccuracyMaximizingThresholds(problemData);
+      var model = new SymbolicDiscriminantFunctionClassificationModel(tree, interpreter, new AccuracyMaximizationThresholdCalculator());
+      model.RecalculateModelParameters(problemData, rows);
       return model;
     }
Index: /trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification.Views/3.4/InteractiveSymbolicDiscriminantFunctionClassificationSolutionSimplifierView.cs
===================================================================
--- /trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification.Views/3.4/InteractiveSymbolicDiscriminantFunctionClassificationSolutionSimplifierView.cs	(revision 8593)
+++ /trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification.Views/3.4/InteractiveSymbolicDiscriminantFunctionClassificationSolutionSimplifierView.cs	(revision 8594)
@@ -50,10 +50,6 @@
 
     protected override void UpdateModel(ISymbolicExpressionTree tree) {
-      var model = new SymbolicDiscriminantFunctionClassificationModel(tree, Content.Model.Interpreter, Content.Model.LowerEstimationLimit, Content.Model.UpperEstimationLimit);
-      // the default policy for setting thresholds in classification models is the accuarcy maximizing policy.
-      // This is rather slow to calculate and can lead to a very laggy UI in the interactive solution simplifier.
-      // However, since we automatically prune sub-trees based on the threshold reaching the maximum accuracy we must
-      // also use maximum accuracy threshold calculation here in order to prevent incoherent behavior of the simplifier.
-      model.SetAccuracyMaximizingThresholds(Content.ProblemData);
+      var model = new SymbolicDiscriminantFunctionClassificationModel(tree, Content.Model.Interpreter, Content.Model.ThresholdCalculator, Content.Model.LowerEstimationLimit, Content.Model.UpperEstimationLimit);
+      model.RecalculateModelParameters(Content.ProblemData, Content.ProblemData.TrainingIndices);
       Content.Model = model;
     }
Index: /trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification-3.4.csproj
===================================================================
--- /trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification-3.4.csproj	(revision 8593)
+++ /trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification-3.4.csproj	(revision 8594)
@@ -112,5 +112,10 @@
   </ItemGroup>
   <ItemGroup>
+    <Compile Include="Interfaces\ISymbolicClassificationModelCreatorOperator.cs" />
+    <Compile Include="Interfaces\ISymbolicDiscriminantFunctionClassificationModelCreator.cs" />
+    <Compile Include="Interfaces\ISymbolicClassificationModelCreator.cs" />
     <Compile Include="Interfaces\ISymbolicDiscriminantFunctionClassificationModel.cs" />
+    <Compile Include="ModelCreators\AccuracyMaximizingThresholdsModelCreator.cs" />
+    <Compile Include="ModelCreators\NormalDistributedThresholdsModelCreator.cs" />
     <Compile Include="MultiObjective\SymbolicClassificationMultiObjectiveValidationBestSolutionAnalyzer.cs" />
     <Compile Include="Plugin.cs" />
@@ -177,4 +182,8 @@
       <Private>False</Private>
     </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.Common.Resources\3.3\HeuristicLab.Common.Resources-3.3.csproj">
+      <Project>{0E27A536-1C4A-4624-A65E-DC4F4F23E3E1}</Project>
+      <Name>HeuristicLab.Common.Resources-3.3</Name>
+    </ProjectReference>
     <ProjectReference Include="..\..\HeuristicLab.Common\3.3\HeuristicLab.Common-3.3.csproj">
       <Project>{A9AD58B9-3EF9-4CC1-97E5-8D909039FF5C}</Project>
Index: /trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/Interfaces/ISymbolicClassificationModel.cs
===================================================================
--- /trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/Interfaces/ISymbolicClassificationModel.cs	(revision 8593)
+++ /trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/Interfaces/ISymbolicClassificationModel.cs	(revision 8594)
@@ -20,7 +20,11 @@
 #endregion
 
-using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+using System.Collections.Generic;
 namespace HeuristicLab.Problems.DataAnalysis.Symbolic.Classification {
   public interface ISymbolicClassificationModel : IClassificationModel, ISymbolicDataAnalysisModel {
+    double LowerEstimationLimit { get; }
+    double UpperEstimationLimit { get; }
+    void RecalculateModelParameters(IClassificationProblemData problemData, IEnumerable<int> rows);
+    new ISymbolicClassificationSolution CreateClassificationSolution(IClassificationProblemData problemData);
   }
 }
Index: /trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/Interfaces/ISymbolicClassificationModelCreator.cs
===================================================================
--- /trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/Interfaces/ISymbolicClassificationModelCreator.cs	(revision 8594)
+++ /trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/Interfaces/ISymbolicClassificationModelCreator.cs	(revision 8594)
@@ -0,0 +1,30 @@
+﻿#region License Information
+
+/* HeuristicLab
+ * Copyright (C) 2002-2012 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 HeuristicLab.Core;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic.Classification {
+  public interface ISymbolicClassificationModelCreator : IItem {
+    ISymbolicClassificationModel CreateSymbolicClassificationModel(ISymbolicExpressionTree tree, ISymbolicDataAnalysisExpressionTreeInterpreter interpreter, double lowerEstimationLimit, double upperEstimationLimit);
+  }
+}
Index: /trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/Interfaces/ISymbolicClassificationModelCreatorOperator.cs
===================================================================
--- /trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/Interfaces/ISymbolicClassificationModelCreatorOperator.cs	(revision 8594)
+++ /trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/Interfaces/ISymbolicClassificationModelCreatorOperator.cs	(revision 8594)
@@ -0,0 +1,30 @@
+﻿#region License Information
+
+/* HeuristicLab
+ * Copyright (C) 2002-2012 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 HeuristicLab.Core;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic.Classification {
+  public interface ISymbolicClassificationModelCreatorOperator : IOperator {
+    ILookupParameter<ISymbolicClassificationModelCreator> ModelCreatorParameter { get; }
+  }
+}
Index: /trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/Interfaces/ISymbolicDiscriminantFunctionClassificationModel.cs
===================================================================
--- /trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/Interfaces/ISymbolicDiscriminantFunctionClassificationModel.cs	(revision 8593)
+++ /trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/Interfaces/ISymbolicDiscriminantFunctionClassificationModel.cs	(revision 8594)
@@ -20,9 +20,7 @@
 #endregion
 
-using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
 namespace HeuristicLab.Problems.DataAnalysis.Symbolic.Classification {
   public interface ISymbolicDiscriminantFunctionClassificationModel : IDiscriminantFunctionClassificationModel, ISymbolicClassificationModel {
-    double LowerEstimationLimit { get; }
-    double UpperEstimationLimit { get; }
+    IDiscriminantFunctionThresholdCalculator ThresholdCalculator { get; }
   }
 }
Index: /trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/Interfaces/ISymbolicDiscriminantFunctionClassificationModelCreator.cs
===================================================================
--- /trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/Interfaces/ISymbolicDiscriminantFunctionClassificationModelCreator.cs	(revision 8594)
+++ /trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/Interfaces/ISymbolicDiscriminantFunctionClassificationModelCreator.cs	(revision 8594)
@@ -0,0 +1,29 @@
+﻿#region License Information
+
+/* HeuristicLab
+ * Copyright (C) 2002-2012 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 HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic.Classification {
+  public interface ISymbolicDiscriminantFunctionClassificationModelCreator : ISymbolicClassificationModelCreator {
+    ISymbolicDiscriminantFunctionClassificationModel CreateSymbolicDiscriminantFunctionClassificationModel(ISymbolicExpressionTree tree, ISymbolicDataAnalysisExpressionTreeInterpreter interpreter, double lowerEstimationLimit, double upperEstimationLimit);
+  }
+}
Index: /trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/ModelCreators/AccuracyMaximizingThresholdsModelCreator.cs
===================================================================
--- /trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/ModelCreators/AccuracyMaximizingThresholdsModelCreator.cs	(revision 8594)
+++ /trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/ModelCreators/AccuracyMaximizingThresholdsModelCreator.cs	(revision 8594)
@@ -0,0 +1,55 @@
+﻿#region License Information
+
+/* HeuristicLab
+ * Copyright (C) 2002-2012 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.Drawing;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic.Classification {
+  [StorableClass]
+  [Item("AccuracyMaximizingThresholdsModelCreator", "")]
+  public sealed class AccuracyMaximizingThresholdsModelCreator : Item, ISymbolicDiscriminantFunctionClassificationModelCreator {
+    public static new Image StaticItemImage {
+      get { return HeuristicLab.Common.Resources.VSImageLibrary.Method; }
+    }
+    public override Image ItemImage {
+      get { return HeuristicLab.Common.Resources.VSImageLibrary.Method; }
+    }
+    [StorableConstructor]
+    private AccuracyMaximizingThresholdsModelCreator(bool deserializing) : base(deserializing) { }
+    private AccuracyMaximizingThresholdsModelCreator(AccuracyMaximizingThresholdsModelCreator original, Cloner cloner) : base(original, cloner) { }
+    public AccuracyMaximizingThresholdsModelCreator() : base() { }
+
+    public override IDeepCloneable Clone(Cloner cloner) { return new AccuracyMaximizingThresholdsModelCreator(this, cloner); }
+
+
+    public ISymbolicClassificationModel CreateSymbolicClassificationModel(ISymbolicExpressionTree tree, ISymbolicDataAnalysisExpressionTreeInterpreter interpreter, double lowerEstimationLimit = double.MinValue, double upperEstimationLimit = double.MaxValue) {
+      return CreateSymbolicDiscriminantFunctionClassificationModel(tree, interpreter, lowerEstimationLimit, upperEstimationLimit);
+    }
+    public ISymbolicDiscriminantFunctionClassificationModel CreateSymbolicDiscriminantFunctionClassificationModel(ISymbolicExpressionTree tree, ISymbolicDataAnalysisExpressionTreeInterpreter interpreter, double lowerEstimationLimit = double.MinValue, double upperEstimationLimit = double.MaxValue) {
+      return new SymbolicDiscriminantFunctionClassificationModel(tree, interpreter, new AccuracyMaximizationThresholdCalculator(), lowerEstimationLimit, upperEstimationLimit);
+    }
+
+  }
+}
Index: /trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/ModelCreators/NormalDistributedThresholdsModelCreator.cs
===================================================================
--- /trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/ModelCreators/NormalDistributedThresholdsModelCreator.cs	(revision 8594)
+++ /trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/ModelCreators/NormalDistributedThresholdsModelCreator.cs	(revision 8594)
@@ -0,0 +1,56 @@
+﻿#region License Information
+
+/* HeuristicLab
+ * Copyright (C) 2002-2012 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.Drawing;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic.Classification {
+  [StorableClass]
+  [Item("NormalDistributedThresholdsModelCreator", "")]
+  public sealed class NormalDistributedThresholdsModelCreator : Item, ISymbolicDiscriminantFunctionClassificationModelCreator {
+    public static new Image StaticItemImage {
+      get { return HeuristicLab.Common.Resources.VSImageLibrary.Method; }
+    }
+    public override Image ItemImage {
+      get { return HeuristicLab.Common.Resources.VSImageLibrary.Method; }
+    }
+    [StorableConstructor]
+    private NormalDistributedThresholdsModelCreator(bool deserializing) : base(deserializing) { }
+    private NormalDistributedThresholdsModelCreator(NormalDistributedThresholdsModelCreator original, Cloner cloner) : base(original, cloner) { }
+    public NormalDistributedThresholdsModelCreator() : base() { }
+
+    public override IDeepCloneable Clone(Cloner cloner) { return new NormalDistributedThresholdsModelCreator(this, cloner); }
+
+
+    public ISymbolicClassificationModel CreateSymbolicClassificationModel(ISymbolicExpressionTree tree, ISymbolicDataAnalysisExpressionTreeInterpreter interpreter, double lowerEstimationLimit = double.MinValue, double upperEstimationLimit = double.MaxValue) {
+      return CreateSymbolicDiscriminantFunctionClassificationModel(tree, interpreter, lowerEstimationLimit, upperEstimationLimit);
+    }
+    public ISymbolicDiscriminantFunctionClassificationModel CreateSymbolicDiscriminantFunctionClassificationModel(ISymbolicExpressionTree tree, ISymbolicDataAnalysisExpressionTreeInterpreter interpreter, double lowerEstimationLimit = double.MinValue, double upperEstimationLimit = double.MaxValue) {
+      return new SymbolicDiscriminantFunctionClassificationModel(tree, interpreter, new NormalDistributionCutPointsThresholdCalculator(), lowerEstimationLimit, upperEstimationLimit);
+    }
+
+  }
+}
Index: /trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/MultiObjective/SymbolicClassificationMultiObjectiveProblem.cs
===================================================================
--- /trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/MultiObjective/SymbolicClassificationMultiObjectiveProblem.cs	(revision 8593)
+++ /trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/MultiObjective/SymbolicClassificationMultiObjectiveProblem.cs	(revision 8594)
@@ -36,4 +36,6 @@
     private const string EstimationLimitsParameterName = "EstimationLimits";
     private const string EstimationLimitsParameterDescription = "The lower and upper limit for the estimated value that can be returned by the symbolic classification model.";
+    private const string ModelCreatorParameterName = "ModelCreator";
+
 
     #region parameter properties
@@ -41,8 +43,14 @@
       get { return (IFixedValueParameter<DoubleLimit>)Parameters[EstimationLimitsParameterName]; }
     }
+    public IValueParameter<ISymbolicClassificationModelCreator> ModelCreatorParameter {
+      get { return (IValueParameter<ISymbolicClassificationModelCreator>)Parameters[ModelCreatorParameterName]; }
+    }
     #endregion
     #region properties
     public DoubleLimit EstimationLimits {
       get { return EstimationLimitsParameter.Value; }
+    }
+    public ISymbolicClassificationModelCreator ModelCreator {
+      get { return ModelCreatorParameter.Value; }
     }
     #endregion
@@ -58,4 +66,5 @@
       : base(new ClassificationProblemData(), new SymbolicClassificationMultiObjectiveMeanSquaredErrorTreeSizeEvaluator(), new SymbolicDataAnalysisExpressionTreeCreator()) {
       Parameters.Add(new FixedValueParameter<DoubleLimit>(EstimationLimitsParameterName, EstimationLimitsParameterDescription));
+      Parameters.Add(new ValueParameter<ISymbolicClassificationModelCreator>(ModelCreatorParameterName, "", new AccuracyMaximizingThresholdsModelCreator()));
 
       EstimationLimitsParameter.Hidden = true;
@@ -74,4 +83,6 @@
     [StorableHook(HookType.AfterDeserialization)]
     private void AfterDeserialization() {
+      if (!Parameters.ContainsKey(ModelCreatorParameterName))
+        Parameters.Add(new ValueParameter<ISymbolicClassificationModelCreator>(ModelCreatorParameterName, "", new AccuracyMaximizingThresholdsModelCreator()));
       RegisterEventHandlers();
     }
@@ -79,4 +90,5 @@
     private void RegisterEventHandlers() {
       SymbolicExpressionTreeGrammarParameter.ValueChanged += (o, e) => ConfigureGrammarSymbols();
+      ModelCreatorParameter.NameChanged += (o, e) => ParameterizeOperators();
     }
 
@@ -110,11 +122,12 @@
     }
 
-    protected new void ParameterizeOperators() {
+    protected override void ParameterizeOperators() {
       base.ParameterizeOperators();
       if (Parameters.ContainsKey(EstimationLimitsParameterName)) {
         var operators = Parameters.OfType<IValueParameter>().Select(p => p.Value).OfType<IOperator>().Union(Operators);
-        foreach (var op in operators.OfType<ISymbolicDataAnalysisBoundedOperator>()) {
-          op.EstimationLimitsParameter.ActualName = EstimationLimitsParameterName;
-        }
+        foreach (var op in operators.OfType<ISymbolicDataAnalysisBoundedOperator>())
+          op.EstimationLimitsParameter.ActualName = EstimationLimitsParameter.Name;
+        foreach (var op in operators.OfType<ISymbolicClassificationModelCreatorOperator>())
+          op.ModelCreatorParameter.ActualName = ModelCreatorParameter.Name;
       }
     }
Index: /trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/MultiObjective/SymbolicClassificationMultiObjectiveTrainingBestSolutionAnalyzer.cs
===================================================================
--- /trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/MultiObjective/SymbolicClassificationMultiObjectiveTrainingBestSolutionAnalyzer.cs	(revision 8593)
+++ /trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/MultiObjective/SymbolicClassificationMultiObjectiveTrainingBestSolutionAnalyzer.cs	(revision 8594)
@@ -34,6 +34,7 @@
   [StorableClass]
   public sealed class SymbolicClassificationMultiObjectiveTrainingBestSolutionAnalyzer : SymbolicDataAnalysisMultiObjectiveTrainingBestSolutionAnalyzer<ISymbolicClassificationSolution>,
-    ISymbolicDataAnalysisInterpreterOperator, ISymbolicDataAnalysisBoundedOperator {
+    ISymbolicDataAnalysisInterpreterOperator, ISymbolicDataAnalysisBoundedOperator, ISymbolicClassificationModelCreatorOperator {
     private const string ProblemDataParameterName = "ProblemData";
+    private const string ModelCreatorParameterName = "ModelCreator";
     private const string SymbolicDataAnalysisTreeInterpreterParameterName = "SymbolicDataAnalysisTreeInterpreter";
     private const string EstimationLimitsParameterName = "EstimationLimits";
@@ -43,4 +44,10 @@
     public ILookupParameter<IClassificationProblemData> ProblemDataParameter {
       get { return (ILookupParameter<IClassificationProblemData>)Parameters[ProblemDataParameterName]; }
+    }
+    public IValueLookupParameter<ISymbolicClassificationModelCreator> ModelCreatorParameter {
+      get { return (IValueLookupParameter<ISymbolicClassificationModelCreator>)Parameters[ModelCreatorParameterName]; }
+    }
+    ILookupParameter<ISymbolicClassificationModelCreator> ISymbolicClassificationModelCreatorOperator.ModelCreatorParameter {
+      get { return ModelCreatorParameter; }
     }
     public ILookupParameter<ISymbolicDataAnalysisExpressionTreeInterpreter> SymbolicDataAnalysisTreeInterpreterParameter {
@@ -67,4 +74,5 @@
       : base() {
       Parameters.Add(new LookupParameter<IClassificationProblemData>(ProblemDataParameterName, "The problem data for the symbolic classification solution."));
+      Parameters.Add(new ValueLookupParameter<ISymbolicClassificationModelCreator>(ModelCreatorParameterName, ""));
       Parameters.Add(new LookupParameter<ISymbolicDataAnalysisExpressionTreeInterpreter>(SymbolicDataAnalysisTreeInterpreterParameterName, "The symbolic data analysis tree interpreter for the symbolic expression tree."));
       Parameters.Add(new ValueLookupParameter<DoubleLimit>(EstimationLimitsParameterName, "The lower and upper limit for the estimated values produced by the symbolic classification model."));
@@ -75,10 +83,16 @@
     }
 
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      if (!Parameters.ContainsKey(ModelCreatorParameterName))
+        Parameters.Add(new ValueLookupParameter<ISymbolicClassificationModelCreator>(ModelCreatorParameterName, ""));
+    }
+
     protected override ISymbolicClassificationSolution CreateSolution(ISymbolicExpressionTree bestTree, double[] bestQuality) {
-      var model = new SymbolicDiscriminantFunctionClassificationModel((ISymbolicExpressionTree)bestTree.Clone(), SymbolicDataAnalysisTreeInterpreterParameter.ActualValue, EstimationLimitsParameter.ActualValue.Lower, EstimationLimitsParameter.ActualValue.Upper);
-      if (ApplyLinearScaling.Value) SymbolicDiscriminantFunctionClassificationModel.Scale(model, ProblemDataParameter.ActualValue);
+      var model = ModelCreatorParameter.ActualValue.CreateSymbolicClassificationModel((ISymbolicExpressionTree)bestTree.Clone(), SymbolicDataAnalysisTreeInterpreterParameter.ActualValue, EstimationLimitsParameter.ActualValue.Lower, EstimationLimitsParameter.ActualValue.Upper);
+      if (ApplyLinearScaling.Value) SymbolicClassificationModel.Scale(model, ProblemDataParameter.ActualValue);
 
-      model.SetAccuracyMaximizingThresholds(ProblemDataParameter.ActualValue);
-      return new SymbolicDiscriminantFunctionClassificationSolution(model, (IClassificationProblemData)ProblemDataParameter.ActualValue.Clone());
+      model.RecalculateModelParameters(ProblemDataParameter.ActualValue, ProblemDataParameter.ActualValue.TrainingIndices);
+      return model.CreateClassificationSolution((IClassificationProblemData)ProblemDataParameter.ActualValue.Clone());
     }
   }
Index: /trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/MultiObjective/SymbolicClassificationMultiObjectiveValidationBestSolutionAnalyzer.cs
===================================================================
--- /trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/MultiObjective/SymbolicClassificationMultiObjectiveValidationBestSolutionAnalyzer.cs	(revision 8593)
+++ /trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/MultiObjective/SymbolicClassificationMultiObjectiveValidationBestSolutionAnalyzer.cs	(revision 8594)
@@ -34,5 +34,6 @@
   [StorableClass]
   public sealed class SymbolicClassificationMultiObjectiveValidationBestSolutionAnalyzer : SymbolicDataAnalysisMultiObjectiveValidationBestSolutionAnalyzer<ISymbolicClassificationSolution, ISymbolicClassificationMultiObjectiveEvaluator, IClassificationProblemData>,
-  ISymbolicDataAnalysisBoundedOperator {
+  ISymbolicDataAnalysisBoundedOperator, ISymbolicClassificationModelCreatorOperator {
+    private const string ModelCreatorParameterName = "ModelCreator";
     private const string EstimationLimitsParameterName = "EstimationLimits";
     private const string ApplyLinearScalingParameterName = "ApplyLinearScaling";
@@ -44,4 +45,10 @@
     public IValueParameter<BoolValue> ApplyLinearScalingParameter {
       get { return (IValueParameter<BoolValue>)Parameters[ApplyLinearScalingParameterName]; }
+    }
+    public IValueLookupParameter<ISymbolicClassificationModelCreator> ModelCreatorParameter {
+      get { return (IValueLookupParameter<ISymbolicClassificationModelCreator>)Parameters[ModelCreatorParameterName]; }
+    }
+    ILookupParameter<ISymbolicClassificationModelCreator> ISymbolicClassificationModelCreatorOperator.ModelCreatorParameter {
+      get { return ModelCreatorParameter; }
     }
     #endregion
@@ -59,4 +66,5 @@
       Parameters.Add(new ValueLookupParameter<DoubleLimit>(EstimationLimitsParameterName, "The loewr and upper limit for the estimated values produced by the symbolic classification model."));
       Parameters.Add(new ValueParameter<BoolValue>(ApplyLinearScalingParameterName, "Flag that indicates if the produced symbolic classification solution should be linearly scaled.", new BoolValue(false)));
+      Parameters.Add(new ValueLookupParameter<ISymbolicClassificationModelCreator>(ModelCreatorParameterName, ""));
     }
     public override IDeepCloneable Clone(Cloner cloner) {
@@ -64,10 +72,16 @@
     }
 
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      if (!Parameters.ContainsKey(ModelCreatorParameterName))
+        Parameters.Add(new ValueLookupParameter<ISymbolicClassificationModelCreator>(ModelCreatorParameterName, ""));
+    }
+
     protected override ISymbolicClassificationSolution CreateSolution(ISymbolicExpressionTree bestTree, double[] bestQualities) {
-      var model = new SymbolicDiscriminantFunctionClassificationModel((ISymbolicExpressionTree)bestTree.Clone(), SymbolicDataAnalysisTreeInterpreterParameter.ActualValue, EstimationLimitsParameter.ActualValue.Lower, EstimationLimitsParameter.ActualValue.Upper);
-      if (ApplyLinearScaling.Value) SymbolicDiscriminantFunctionClassificationModel.Scale(model, ProblemDataParameter.ActualValue);
+      var model = ModelCreatorParameter.ActualValue.CreateSymbolicClassificationModel((ISymbolicExpressionTree)bestTree.Clone(), SymbolicDataAnalysisTreeInterpreterParameter.ActualValue, EstimationLimitsParameter.ActualValue.Lower, EstimationLimitsParameter.ActualValue.Upper);
+      if (ApplyLinearScaling.Value) SymbolicClassificationModel.Scale(model, ProblemDataParameter.ActualValue);
 
-      model.SetAccuracyMaximizingThresholds(ProblemDataParameter.ActualValue);
-      return new SymbolicDiscriminantFunctionClassificationSolution(model, (IClassificationProblemData)ProblemDataParameter.ActualValue.Clone());
+      model.RecalculateModelParameters(ProblemDataParameter.ActualValue, ProblemDataParameter.ActualValue.TrainingIndices);
+      return model.CreateClassificationSolution((IClassificationProblemData)ProblemDataParameter.ActualValue.Clone());
     }
   }
Index: /trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SingleObjective/SymbolicClassificationSingleObjectivePenaltyScoreEvaluator.cs
===================================================================
--- /trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SingleObjective/SymbolicClassificationSingleObjectivePenaltyScoreEvaluator.cs	(revision 8593)
+++ /trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SingleObjective/SymbolicClassificationSingleObjectivePenaltyScoreEvaluator.cs	(revision 8594)
@@ -25,4 +25,5 @@
 using HeuristicLab.Data;
 using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+using HeuristicLab.Parameters;
 using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
 
@@ -30,15 +31,33 @@
   [Item("Penalty Score Evaluator", "Calculates the penalty score of a symbolic classification solution.")]
   [StorableClass]
-  public class SymbolicClassificationSingleObjectivePenaltyScoreEvaluator : SymbolicClassificationSingleObjectiveEvaluator {
+  public class SymbolicClassificationSingleObjectivePenaltyScoreEvaluator : SymbolicClassificationSingleObjectiveEvaluator, ISymbolicClassificationModelCreatorOperator {
+    private const string ModelCreatorParameterName = "ModelCreator";
     public override bool Maximization { get { return false; } }
+
+    public IValueLookupParameter<ISymbolicClassificationModelCreator> ModelCreatorParameter {
+      get { return (IValueLookupParameter<ISymbolicClassificationModelCreator>)Parameters[ModelCreatorParameterName]; }
+    }
+    ILookupParameter<ISymbolicClassificationModelCreator> ISymbolicClassificationModelCreatorOperator.ModelCreatorParameter {
+      get { return ModelCreatorParameter; }
+    }
 
     [StorableConstructor]
     protected SymbolicClassificationSingleObjectivePenaltyScoreEvaluator(bool deserializing) : base(deserializing) { }
     protected SymbolicClassificationSingleObjectivePenaltyScoreEvaluator(SymbolicClassificationSingleObjectivePenaltyScoreEvaluator original, Cloner cloner) : base(original, cloner) { }
-    public SymbolicClassificationSingleObjectivePenaltyScoreEvaluator() : base() { }
+    public SymbolicClassificationSingleObjectivePenaltyScoreEvaluator()
+      : base() {
+      Parameters.Add(new ValueLookupParameter<ISymbolicClassificationModelCreator>(ModelCreatorParameterName, ""));
+    }
 
     public override IDeepCloneable Clone(Cloner cloner) {
       return new SymbolicClassificationSingleObjectivePenaltyScoreEvaluator(this, cloner);
     }
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      if (!Parameters.ContainsKey(ModelCreatorParameterName))
+        Parameters.Add(new ValueLookupParameter<ISymbolicClassificationModelCreator>(ModelCreatorParameterName, ""));
+    }
+
 
     public override IOperation Apply() {
@@ -66,11 +85,13 @@
       SymbolicDataAnalysisTreeInterpreterParameter.ExecutionContext = context;
       EstimationLimitsParameter.ExecutionContext = context;
+      ModelCreatorParameter.ExecutionContext = context;
 
-      var model = new SymbolicDiscriminantFunctionClassificationModel(tree, SymbolicDataAnalysisTreeInterpreterParameter.ActualValue, EstimationLimitsParameter.ActualValue.Lower, EstimationLimitsParameter.ActualValue.Upper);
-      model.SetAccuracyMaximizingThresholds(problemData);
+      var model = ModelCreatorParameter.ActualValue.CreateSymbolicClassificationModel(tree, SymbolicDataAnalysisTreeInterpreterParameter.ActualValue, EstimationLimitsParameter.ActualValue.Lower, EstimationLimitsParameter.ActualValue.Upper);
+      model.RecalculateModelParameters(problemData, rows);
       double penalty = Calculate(model, problemData, rows);
 
       SymbolicDataAnalysisTreeInterpreterParameter.ExecutionContext = null;
       EstimationLimitsParameter.ExecutionContext = null;
+      ModelCreatorParameter.ExecutionContext = null;
 
       return penalty;
Index: /trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SingleObjective/SymbolicClassificationSingleObjectiveProblem.cs
===================================================================
--- /trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SingleObjective/SymbolicClassificationSingleObjectiveProblem.cs	(revision 8593)
+++ /trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SingleObjective/SymbolicClassificationSingleObjectiveProblem.cs	(revision 8594)
@@ -35,4 +35,5 @@
     private const string EstimationLimitsParameterName = "EstimationLimits";
     private const string EstimationLimitsParameterDescription = "The lower and upper limit for the estimated value that can be returned by the symbolic classification model.";
+    private const string ModelCreatorParameterName = "ModelCreator";
 
     #region parameter properties
@@ -40,8 +41,14 @@
       get { return (IFixedValueParameter<DoubleLimit>)Parameters[EstimationLimitsParameterName]; }
     }
+    public IValueParameter<ISymbolicClassificationModelCreator> ModelCreatorParameter {
+      get { return (IValueParameter<ISymbolicClassificationModelCreator>)Parameters[ModelCreatorParameterName]; }
+    }
     #endregion
     #region properties
     public DoubleLimit EstimationLimits {
       get { return EstimationLimitsParameter.Value; }
+    }
+    public ISymbolicClassificationModelCreator ModelCreator {
+      get { return ModelCreatorParameter.Value; }
     }
     #endregion
@@ -57,4 +64,5 @@
       : base(new ClassificationProblemData(), new SymbolicClassificationSingleObjectiveMeanSquaredErrorEvaluator(), new SymbolicDataAnalysisExpressionTreeCreator()) {
       Parameters.Add(new FixedValueParameter<DoubleLimit>(EstimationLimitsParameterName, EstimationLimitsParameterDescription));
+      Parameters.Add(new ValueParameter<ISymbolicClassificationModelCreator>(ModelCreatorParameterName, "", new AccuracyMaximizingThresholdsModelCreator()));
 
       EstimationLimitsParameter.Hidden = true;
@@ -71,6 +79,8 @@
     [StorableHook(HookType.AfterDeserialization)]
     private void AfterDeserialization() {
-      RegisterEventHandlers();
-      // compatibility
+
+      if (!Parameters.ContainsKey(ModelCreatorParameterName))
+        Parameters.Add(new ValueParameter<ISymbolicClassificationModelCreator>(ModelCreatorParameterName, "", new AccuracyMaximizingThresholdsModelCreator()));
+
       bool changed = false;
       if (!Operators.OfType<SymbolicClassificationSingleObjectiveTrainingParetoBestSolutionAnalyzer>().Any()) {
@@ -83,8 +93,10 @@
       }
       if (changed) ParameterizeOperators();
+      RegisterEventHandlers();
     }
 
     private void RegisterEventHandlers() {
       SymbolicExpressionTreeGrammarParameter.ValueChanged += (o, e) => ConfigureGrammarSymbols();
+      ModelCreatorParameter.NameChanged += (o, e) => ParameterizeOperators();
     }
 
@@ -125,7 +137,8 @@
       if (Parameters.ContainsKey(EstimationLimitsParameterName)) {
         var operators = Parameters.OfType<IValueParameter>().Select(p => p.Value).OfType<IOperator>().Union(Operators);
-        foreach (var op in operators.OfType<ISymbolicDataAnalysisBoundedOperator>()) {
+        foreach (var op in operators.OfType<ISymbolicDataAnalysisBoundedOperator>())
           op.EstimationLimitsParameter.ActualName = EstimationLimitsParameter.Name;
-        }
+        foreach (var op in operators.OfType<ISymbolicClassificationModelCreatorOperator>())
+          op.ModelCreatorParameter.ActualName = ModelCreatorParameter.Name;
       }
     }
Index: /trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SingleObjective/SymbolicClassificationSingleObjectiveTrainingBestSolutionAnalyzer.cs
===================================================================
--- /trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SingleObjective/SymbolicClassificationSingleObjectiveTrainingBestSolutionAnalyzer.cs	(revision 8593)
+++ /trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SingleObjective/SymbolicClassificationSingleObjectiveTrainingBestSolutionAnalyzer.cs	(revision 8594)
@@ -34,6 +34,7 @@
   [StorableClass]
   public sealed class SymbolicClassificationSingleObjectiveTrainingBestSolutionAnalyzer : SymbolicDataAnalysisSingleObjectiveTrainingBestSolutionAnalyzer<ISymbolicClassificationSolution>,
-    ISymbolicDataAnalysisInterpreterOperator, ISymbolicDataAnalysisBoundedOperator {
+    ISymbolicDataAnalysisInterpreterOperator, ISymbolicDataAnalysisBoundedOperator, ISymbolicClassificationModelCreatorOperator {
     private const string ProblemDataParameterName = "ProblemData";
+    private const string ModelCreatorParameterName = "ModelCreator";
     private const string SymbolicDataAnalysisTreeInterpreterParameterName = "SymbolicDataAnalysisTreeInterpreter";
     private const string EstimationLimitsParameterName = "UpperEstimationLimit";
@@ -42,4 +43,10 @@
     public ILookupParameter<IClassificationProblemData> ProblemDataParameter {
       get { return (ILookupParameter<IClassificationProblemData>)Parameters[ProblemDataParameterName]; }
+    }
+    public IValueLookupParameter<ISymbolicClassificationModelCreator> ModelCreatorParameter {
+      get { return (IValueLookupParameter<ISymbolicClassificationModelCreator>)Parameters[ModelCreatorParameterName]; }
+    }
+    ILookupParameter<ISymbolicClassificationModelCreator> ISymbolicClassificationModelCreatorOperator.ModelCreatorParameter {
+      get { return ModelCreatorParameter; }
     }
     public ILookupParameter<ISymbolicDataAnalysisExpressionTreeInterpreter> SymbolicDataAnalysisTreeInterpreterParameter {
@@ -65,18 +72,25 @@
       : base() {
       Parameters.Add(new LookupParameter<IClassificationProblemData>(ProblemDataParameterName, "The problem data for the symbolic classification solution."));
+      Parameters.Add(new ValueLookupParameter<ISymbolicClassificationModelCreator>(ModelCreatorParameterName, ""));
       Parameters.Add(new LookupParameter<ISymbolicDataAnalysisExpressionTreeInterpreter>(SymbolicDataAnalysisTreeInterpreterParameterName, "The symbolic data analysis tree interpreter for the symbolic expression tree."));
       Parameters.Add(new ValueLookupParameter<DoubleLimit>(EstimationLimitsParameterName, "The lower and upper limit for the estimated values produced by the symbolic classification model."));
       Parameters.Add(new ValueParameter<BoolValue>(ApplyLinearScalingParameterName, "Flag that indicates if the produced symbolic classification solution should be linearly scaled.", new BoolValue(false)));
     }
+
     public override IDeepCloneable Clone(Cloner cloner) {
       return new SymbolicClassificationSingleObjectiveTrainingBestSolutionAnalyzer(this, cloner);
     }
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      if (!Parameters.ContainsKey(ModelCreatorParameterName))
+        Parameters.Add(new ValueLookupParameter<ISymbolicClassificationModelCreator>(ModelCreatorParameterName, ""));
+    }
 
     protected override ISymbolicClassificationSolution CreateSolution(ISymbolicExpressionTree bestTree, double bestQuality) {
-      var model = new SymbolicDiscriminantFunctionClassificationModel((ISymbolicExpressionTree)bestTree.Clone(), SymbolicDataAnalysisTreeInterpreterParameter.ActualValue, EstimationLimitsParameter.ActualValue.Lower, EstimationLimitsParameter.ActualValue.Upper);
-      if (ApplyLinearScaling.Value) SymbolicDiscriminantFunctionClassificationModel.Scale(model, ProblemDataParameter.ActualValue);
+      var model = ModelCreatorParameter.ActualValue.CreateSymbolicClassificationModel((ISymbolicExpressionTree)bestTree.Clone(), SymbolicDataAnalysisTreeInterpreterParameter.ActualValue, EstimationLimitsParameter.ActualValue.Lower, EstimationLimitsParameter.ActualValue.Upper);
+      if (ApplyLinearScaling.Value) SymbolicClassificationModel.Scale(model, ProblemDataParameter.ActualValue);
 
-      model.SetAccuracyMaximizingThresholds(ProblemDataParameter.ActualValue);
-      return new SymbolicDiscriminantFunctionClassificationSolution(model, (IClassificationProblemData)ProblemDataParameter.ActualValue.Clone());
+      model.RecalculateModelParameters(ProblemDataParameter.ActualValue, ProblemDataParameter.ActualValue.TrainingIndices);
+      return model.CreateClassificationSolution((IClassificationProblemData)ProblemDataParameter.ActualValue.Clone());
     }
   }
Index: /trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SingleObjective/SymbolicClassificationSingleObjectiveTrainingParetoBestSolutionAnalyzer.cs
===================================================================
--- /trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SingleObjective/SymbolicClassificationSingleObjectiveTrainingParetoBestSolutionAnalyzer.cs	(revision 8593)
+++ /trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SingleObjective/SymbolicClassificationSingleObjectiveTrainingParetoBestSolutionAnalyzer.cs	(revision 8594)
@@ -33,9 +33,16 @@
   [Item("SymbolicClassificationSingleObjectiveTrainingParetoBestSolutionAnalyzer", "An operator that collects the training Pareto-best symbolic classification solutions for single objective symbolic classification problems.")]
   [StorableClass]
-  public sealed class SymbolicClassificationSingleObjectiveTrainingParetoBestSolutionAnalyzer : SymbolicDataAnalysisSingleObjectiveTrainingParetoBestSolutionAnalyzer<IClassificationProblemData, ISymbolicClassificationSolution> {
+  public sealed class SymbolicClassificationSingleObjectiveTrainingParetoBestSolutionAnalyzer : SymbolicDataAnalysisSingleObjectiveTrainingParetoBestSolutionAnalyzer<IClassificationProblemData, ISymbolicClassificationSolution>, ISymbolicClassificationModelCreatorOperator {
     private const string ApplyLinearScalingParameterName = "ApplyLinearScaling";
+    private const string ModelCreatorParameterName = "ModelCreator";
     #region parameter properties
     public IValueParameter<BoolValue> ApplyLinearScalingParameter {
       get { return (IValueParameter<BoolValue>)Parameters[ApplyLinearScalingParameterName]; }
+    }
+    public IValueLookupParameter<ISymbolicClassificationModelCreator> ModelCreatorParameter {
+      get { return (IValueLookupParameter<ISymbolicClassificationModelCreator>)Parameters[ModelCreatorParameterName]; }
+    }
+    ILookupParameter<ISymbolicClassificationModelCreator> ISymbolicClassificationModelCreatorOperator.ModelCreatorParameter {
+      get { return ModelCreatorParameter; }
     }
     #endregion
@@ -53,4 +60,5 @@
       : base() {
       Parameters.Add(new ValueParameter<BoolValue>(ApplyLinearScalingParameterName, "Flag that indicates if the produced symbolic classification solution should be linearly scaled.", new BoolValue(false)));
+      Parameters.Add(new ValueLookupParameter<ISymbolicClassificationModelCreator>(ModelCreatorParameterName, ""));
     }
     public override IDeepCloneable Clone(Cloner cloner) {
@@ -58,10 +66,16 @@
     }
 
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      if (!Parameters.ContainsKey(ModelCreatorParameterName))
+        Parameters.Add(new ValueLookupParameter<ISymbolicClassificationModelCreator>(ModelCreatorParameterName, ""));
+    }
+
     protected override ISymbolicClassificationSolution CreateSolution(ISymbolicExpressionTree bestTree) {
-      var model = new SymbolicDiscriminantFunctionClassificationModel((ISymbolicExpressionTree)bestTree.Clone(), SymbolicDataAnalysisTreeInterpreterParameter.ActualValue, EstimationLimitsParameter.ActualValue.Lower, EstimationLimitsParameter.ActualValue.Upper);
-      if (ApplyLinearScaling.Value) SymbolicDiscriminantFunctionClassificationModel.Scale(model, ProblemDataParameter.ActualValue);
+      var model = ModelCreatorParameter.ActualValue.CreateSymbolicClassificationModel((ISymbolicExpressionTree)bestTree.Clone(), SymbolicDataAnalysisTreeInterpreterParameter.ActualValue, EstimationLimitsParameter.ActualValue.Lower, EstimationLimitsParameter.ActualValue.Upper);
+      if (ApplyLinearScaling.Value) SymbolicClassificationModel.Scale(model, ProblemDataParameter.ActualValue);
 
-      model.SetAccuracyMaximizingThresholds(ProblemDataParameter.ActualValue);
-      return new SymbolicDiscriminantFunctionClassificationSolution(model, (IClassificationProblemData)ProblemDataParameter.ActualValue.Clone());
+      model.RecalculateModelParameters(ProblemDataParameter.ActualValue, ProblemDataParameter.ActualValue.TrainingIndices);
+      return model.CreateClassificationSolution((IClassificationProblemData)ProblemDataParameter.ActualValue.Clone());
     }
   }
Index: /trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SingleObjective/SymbolicClassificationSingleObjectiveValidationBestSolutionAnalyzer.cs
===================================================================
--- /trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SingleObjective/SymbolicClassificationSingleObjectiveValidationBestSolutionAnalyzer.cs	(revision 8593)
+++ /trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SingleObjective/SymbolicClassificationSingleObjectiveValidationBestSolutionAnalyzer.cs	(revision 8594)
@@ -34,7 +34,8 @@
   [StorableClass]
   public sealed class SymbolicClassificationSingleObjectiveValidationBestSolutionAnalyzer : SymbolicDataAnalysisSingleObjectiveValidationBestSolutionAnalyzer<ISymbolicClassificationSolution, ISymbolicClassificationSingleObjectiveEvaluator, IClassificationProblemData>,
-  ISymbolicDataAnalysisBoundedOperator {
+  ISymbolicDataAnalysisBoundedOperator, ISymbolicClassificationModelCreatorOperator {
     private const string EstimationLimitsParameterName = "EstimationLimits";
     private const string ApplyLinearScalingParameterName = "ApplyLinearScaling";
+    private const string ModelCreatorParameterName = "ModelCreator";
 
     #region parameter properties
@@ -44,4 +45,10 @@
     public IValueParameter<BoolValue> ApplyLinearScalingParameter {
       get { return (IValueParameter<BoolValue>)Parameters[ApplyLinearScalingParameterName]; }
+    }
+    public IValueLookupParameter<ISymbolicClassificationModelCreator> ModelCreatorParameter {
+      get { return (IValueLookupParameter<ISymbolicClassificationModelCreator>)Parameters[ModelCreatorParameterName]; }
+    }
+    ILookupParameter<ISymbolicClassificationModelCreator> ISymbolicClassificationModelCreatorOperator.ModelCreatorParameter {
+      get { return ModelCreatorParameter; }
     }
     #endregion
@@ -59,4 +66,5 @@
       Parameters.Add(new ValueLookupParameter<DoubleLimit>(EstimationLimitsParameterName, "The lower and upper limit for the estimated values produced by the symbolic classification model."));
       Parameters.Add(new ValueParameter<BoolValue>(ApplyLinearScalingParameterName, "Flag that indicates if the produced symbolic classification solution should be linearly scaled.", new BoolValue(false)));
+      Parameters.Add(new ValueLookupParameter<ISymbolicClassificationModelCreator>(ModelCreatorParameterName, ""));
     }
     public override IDeepCloneable Clone(Cloner cloner) {
@@ -64,10 +72,16 @@
     }
 
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      if (!Parameters.ContainsKey(ModelCreatorParameterName))
+        Parameters.Add(new ValueLookupParameter<ISymbolicClassificationModelCreator>(ModelCreatorParameterName, ""));
+    }
+
     protected override ISymbolicClassificationSolution CreateSolution(ISymbolicExpressionTree bestTree, double bestQuality) {
-      var model = new SymbolicDiscriminantFunctionClassificationModel((ISymbolicExpressionTree)bestTree.Clone(), SymbolicDataAnalysisTreeInterpreterParameter.ActualValue, EstimationLimitsParameter.ActualValue.Lower, EstimationLimitsParameter.ActualValue.Upper);
-      if (ApplyLinearScaling.Value) SymbolicDiscriminantFunctionClassificationModel.Scale(model, ProblemDataParameter.ActualValue);
+      var model = ModelCreatorParameter.ActualValue.CreateSymbolicClassificationModel((ISymbolicExpressionTree)bestTree.Clone(), SymbolicDataAnalysisTreeInterpreterParameter.ActualValue, EstimationLimitsParameter.ActualValue.Lower, EstimationLimitsParameter.ActualValue.Upper);
+      if (ApplyLinearScaling.Value) SymbolicClassificationModel.Scale(model, ProblemDataParameter.ActualValue);
 
-      model.SetAccuracyMaximizingThresholds(ProblemDataParameter.ActualValue);
-      return new SymbolicDiscriminantFunctionClassificationSolution(model, (IClassificationProblemData)ProblemDataParameter.ActualValue.Clone());
+      model.RecalculateModelParameters(ProblemDataParameter.ActualValue, ProblemDataParameter.ActualValue.TrainingIndices);
+      return model.CreateClassificationSolution((IClassificationProblemData)ProblemDataParameter.ActualValue.Clone());
     }
   }
Index: /trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SingleObjective/SymbolicClassificationSingleObjectiveValidationParetoBestSolutionAnalyzer.cs
===================================================================
--- /trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SingleObjective/SymbolicClassificationSingleObjectiveValidationParetoBestSolutionAnalyzer.cs	(revision 8593)
+++ /trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SingleObjective/SymbolicClassificationSingleObjectiveValidationParetoBestSolutionAnalyzer.cs	(revision 8594)
@@ -33,9 +33,16 @@
   [Item("SymbolicClassificationSingleObjectiveValidationParetoBestSolutionAnalyzer", "An operator that collects the validation Pareto-best symbolic classification solutions for single objective symbolic classification problems.")]
   [StorableClass]
-  public sealed class SymbolicClassificationSingleObjectiveValidationParetoBestSolutionAnalyzer : SymbolicDataAnalysisSingleObjectiveValidationParetoBestSolutionAnalyzer<ISymbolicClassificationSolution, ISymbolicClassificationSingleObjectiveEvaluator, IClassificationProblemData> {
+  public sealed class SymbolicClassificationSingleObjectiveValidationParetoBestSolutionAnalyzer : SymbolicDataAnalysisSingleObjectiveValidationParetoBestSolutionAnalyzer<ISymbolicClassificationSolution, ISymbolicClassificationSingleObjectiveEvaluator, IClassificationProblemData>, ISymbolicClassificationModelCreatorOperator {
     private const string ApplyLinearScalingParameterName = "ApplyLinearScaling";
+    private const string ModelCreatorParameterName = "ModelCreator";
     #region parameter properties
     public IValueParameter<BoolValue> ApplyLinearScalingParameter {
       get { return (IValueParameter<BoolValue>)Parameters[ApplyLinearScalingParameterName]; }
+    }
+    public IValueLookupParameter<ISymbolicClassificationModelCreator> ModelCreatorParameter {
+      get { return (IValueLookupParameter<ISymbolicClassificationModelCreator>)Parameters[ModelCreatorParameterName]; }
+    }
+    ILookupParameter<ISymbolicClassificationModelCreator> ISymbolicClassificationModelCreatorOperator.ModelCreatorParameter {
+      get { return ModelCreatorParameter; }
     }
     #endregion
@@ -53,4 +60,5 @@
       : base() {
       Parameters.Add(new ValueParameter<BoolValue>(ApplyLinearScalingParameterName, "Flag that indicates if the produced symbolic classification solution should be linearly scaled.", new BoolValue(false)));
+      Parameters.Add(new ValueLookupParameter<ISymbolicClassificationModelCreator>(ModelCreatorParameterName, ""));
     }
     public override IDeepCloneable Clone(Cloner cloner) {
@@ -58,10 +66,16 @@
     }
 
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      if (!Parameters.ContainsKey(ModelCreatorParameterName))
+        Parameters.Add(new ValueLookupParameter<ISymbolicClassificationModelCreator>(ModelCreatorParameterName, ""));
+    }
+
     protected override ISymbolicClassificationSolution CreateSolution(ISymbolicExpressionTree bestTree) {
-      var model = new SymbolicDiscriminantFunctionClassificationModel((ISymbolicExpressionTree)bestTree.Clone(), SymbolicDataAnalysisTreeInterpreterParameter.ActualValue, EstimationLimitsParameter.ActualValue.Lower, EstimationLimitsParameter.ActualValue.Upper);
-      if (ApplyLinearScaling.Value) SymbolicDiscriminantFunctionClassificationModel.Scale(model, ProblemDataParameter.ActualValue);
+      var model = ModelCreatorParameter.ActualValue.CreateSymbolicClassificationModel((ISymbolicExpressionTree)bestTree.Clone(), SymbolicDataAnalysisTreeInterpreterParameter.ActualValue, EstimationLimitsParameter.ActualValue.Lower, EstimationLimitsParameter.ActualValue.Upper);
+      if (ApplyLinearScaling.Value) SymbolicClassificationModel.Scale(model, ProblemDataParameter.ActualValue);
 
-      model.SetAccuracyMaximizingThresholds(ProblemDataParameter.ActualValue);
-      return new SymbolicDiscriminantFunctionClassificationSolution(model, (IClassificationProblemData)ProblemDataParameter.ActualValue.Clone());
+      model.RecalculateModelParameters(ProblemDataParameter.ActualValue, ProblemDataParameter.ActualValue.TrainingIndices);
+      return model.CreateClassificationSolution((IClassificationProblemData)ProblemDataParameter.ActualValue.Clone());
     }
   }
Index: /trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SymbolicClassificationModel.cs
===================================================================
--- /trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SymbolicClassificationModel.cs	(revision 8593)
+++ /trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SymbolicClassificationModel.cs	(revision 8594)
@@ -32,30 +32,106 @@
   [StorableClass]
   [Item(Name = "SymbolicClassificationModel", Description = "Represents a symbolic classification model.")]
-  public class SymbolicClassificationModel : SymbolicDataAnalysisModel, ISymbolicClassificationModel {
+  public abstract class SymbolicClassificationModel : SymbolicDataAnalysisModel, ISymbolicClassificationModel {
+    [Storable]
+    private double lowerEstimationLimit;
+    public double LowerEstimationLimit { get { return lowerEstimationLimit; } }
+    [Storable]
+    private double upperEstimationLimit;
+    public double UpperEstimationLimit { get { return upperEstimationLimit; } }
+
     [StorableConstructor]
     protected SymbolicClassificationModel(bool deserializing) : base(deserializing) { }
     protected SymbolicClassificationModel(SymbolicClassificationModel original, Cloner cloner)
       : base(original, cloner) {
+      lowerEstimationLimit = original.lowerEstimationLimit;
+      upperEstimationLimit = original.upperEstimationLimit;
     }
-    public SymbolicClassificationModel(ISymbolicExpressionTree tree, ISymbolicDataAnalysisExpressionTreeInterpreter interpreter)
+    protected SymbolicClassificationModel(ISymbolicExpressionTree tree, ISymbolicDataAnalysisExpressionTreeInterpreter interpreter, double lowerEstimationLimit = double.MinValue, double upperEstimationLimit = double.MaxValue)
       : base(tree, interpreter) {
+      this.lowerEstimationLimit = lowerEstimationLimit;
+      this.upperEstimationLimit = upperEstimationLimit;
     }
 
-    public override IDeepCloneable Clone(Cloner cloner) {
-      return new SymbolicClassificationModel(this, cloner);
-    }
+    public abstract IEnumerable<double> GetEstimatedClassValues(Dataset dataset, IEnumerable<int> rows);
+    public abstract void RecalculateModelParameters(IClassificationProblemData problemData, IEnumerable<int> rows);
 
-    public IEnumerable<double> GetEstimatedClassValues(Dataset dataset, IEnumerable<int> rows) {
-      return Interpreter.GetSymbolicExpressionTreeValues(SymbolicExpressionTree, dataset, rows);
-    }
+    public abstract ISymbolicClassificationSolution CreateClassificationSolution(IClassificationProblemData problemData);
 
-    public ISymbolicClassificationSolution CreateClassificationSolution(IClassificationProblemData problemData) {
-      return new SymbolicClassificationSolution(this, new ClassificationProblemData(problemData));
-    }
     IClassificationSolution IClassificationModel.CreateClassificationSolution(IClassificationProblemData problemData) {
       return CreateClassificationSolution(problemData);
     }
 
+    #region scaling
+    public static void Scale(ISymbolicClassificationModel model, IClassificationProblemData problemData) {
+      var dataset = problemData.Dataset;
+      var targetVariable = problemData.TargetVariable;
+      var rows = problemData.TrainingIndices;
+      var estimatedValues = model.Interpreter.GetSymbolicExpressionTreeValues(model.SymbolicExpressionTree, dataset, rows);
+      var targetValues = dataset.GetDoubleValues(targetVariable, rows);
+      double alpha;
+      double beta;
+      OnlineCalculatorError errorState;
+      OnlineLinearScalingParameterCalculator.Calculate(estimatedValues, targetValues, out alpha, out beta, out errorState);
+      if (errorState != OnlineCalculatorError.None) return;
 
+      ConstantTreeNode alphaTreeNode = null;
+      ConstantTreeNode betaTreeNode = null;
+      // check if model has been scaled previously by analyzing the structure of the tree
+      var startNode = model.SymbolicExpressionTree.Root.GetSubtree(0);
+      if (startNode.GetSubtree(0).Symbol is Addition) {
+        var addNode = startNode.GetSubtree(0);
+        if (addNode.SubtreeCount == 2 && addNode.GetSubtree(0).Symbol is Multiplication && addNode.GetSubtree(1).Symbol is Constant) {
+          alphaTreeNode = addNode.GetSubtree(1) as ConstantTreeNode;
+          var mulNode = addNode.GetSubtree(0);
+          if (mulNode.SubtreeCount == 2 && mulNode.GetSubtree(1).Symbol is Constant) {
+            betaTreeNode = mulNode.GetSubtree(1) as ConstantTreeNode;
+          }
+        }
+      }
+      // if tree structure matches the structure necessary for linear scaling then reuse the existing tree nodes
+      if (alphaTreeNode != null && betaTreeNode != null) {
+        betaTreeNode.Value *= beta;
+        alphaTreeNode.Value *= beta;
+        alphaTreeNode.Value += alpha;
+      } else {
+        var mainBranch = startNode.GetSubtree(0);
+        startNode.RemoveSubtree(0);
+        var scaledMainBranch = MakeSum(MakeProduct(mainBranch, beta), alpha);
+        startNode.AddSubtree(scaledMainBranch);
+      }
+    }
+
+    private static ISymbolicExpressionTreeNode MakeSum(ISymbolicExpressionTreeNode treeNode, double alpha) {
+      if (alpha.IsAlmost(0.0)) {
+        return treeNode;
+      } else {
+        var addition = new Addition();
+        var node = addition.CreateTreeNode();
+        var alphaConst = MakeConstant(alpha);
+        node.AddSubtree(treeNode);
+        node.AddSubtree(alphaConst);
+        return node;
+      }
+    }
+
+    private static ISymbolicExpressionTreeNode MakeProduct(ISymbolicExpressionTreeNode treeNode, double beta) {
+      if (beta.IsAlmost(1.0)) {
+        return treeNode;
+      } else {
+        var multipliciation = new Multiplication();
+        var node = multipliciation.CreateTreeNode();
+        var betaConst = MakeConstant(beta);
+        node.AddSubtree(treeNode);
+        node.AddSubtree(betaConst);
+        return node;
+      }
+    }
+
+    private static ISymbolicExpressionTreeNode MakeConstant(double c) {
+      var node = (ConstantTreeNode)(new Constant()).CreateTreeNode();
+      node.Value = c;
+      return node;
+    }
+    #endregion
   }
 }
Index: /trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SymbolicDiscriminantFunctionClassificationModel.cs
===================================================================
--- /trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SymbolicDiscriminantFunctionClassificationModel.cs	(revision 8593)
+++ /trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SymbolicDiscriminantFunctionClassificationModel.cs	(revision 8594)
@@ -34,5 +34,5 @@
   [StorableClass]
   [Item(Name = "SymbolicDiscriminantFunctionClassificationModel", Description = "Represents a symbolic classification model unsing a discriminant function.")]
-  public class SymbolicDiscriminantFunctionClassificationModel : SymbolicDataAnalysisModel, ISymbolicDiscriminantFunctionClassificationModel {
+  public class SymbolicDiscriminantFunctionClassificationModel : SymbolicClassificationModel, ISymbolicDiscriminantFunctionClassificationModel {
 
     [Storable]
@@ -48,10 +48,12 @@
       private set { classValues = value.ToArray(); }
     }
+
+    private IDiscriminantFunctionThresholdCalculator thresholdCalculator;
     [Storable]
-    private double lowerEstimationLimit;
-    public double LowerEstimationLimit { get { return lowerEstimationLimit; } }
-    [Storable]
-    private double upperEstimationLimit;
-    public double UpperEstimationLimit { get { return upperEstimationLimit; } }
+    public IDiscriminantFunctionThresholdCalculator ThresholdCalculator {
+      get { return thresholdCalculator; }
+      private set { thresholdCalculator = value; }
+    }
+
 
     [StorableConstructor]
@@ -61,14 +63,17 @@
       classValues = (double[])original.classValues.Clone();
       thresholds = (double[])original.thresholds.Clone();
-      lowerEstimationLimit = original.lowerEstimationLimit;
-      upperEstimationLimit = original.upperEstimationLimit;
+      thresholdCalculator = cloner.Clone(original.thresholdCalculator);
     }
-    public SymbolicDiscriminantFunctionClassificationModel(ISymbolicExpressionTree tree, ISymbolicDataAnalysisExpressionTreeInterpreter interpreter,
+    public SymbolicDiscriminantFunctionClassificationModel(ISymbolicExpressionTree tree, ISymbolicDataAnalysisExpressionTreeInterpreter interpreter, IDiscriminantFunctionThresholdCalculator thresholdCalculator,
       double lowerEstimationLimit = double.MinValue, double upperEstimationLimit = double.MaxValue)
-      : base(tree, interpreter) {
+      : base(tree, interpreter, lowerEstimationLimit, upperEstimationLimit) {
       this.thresholds = new double[0];
       this.classValues = new double[0];
-      this.lowerEstimationLimit = lowerEstimationLimit;
-      this.upperEstimationLimit = upperEstimationLimit;
+      this.ThresholdCalculator = thresholdCalculator;
+    }
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      if (ThresholdCalculator == null) ThresholdCalculator = new AccuracyMaximizationThresholdCalculator();
     }
 
@@ -87,9 +92,18 @@
     }
 
-    public IEnumerable<double> GetEstimatedValues(Dataset dataset, IEnumerable<int> rows) {
-      return Interpreter.GetSymbolicExpressionTreeValues(SymbolicExpressionTree, dataset, rows).LimitToRange(lowerEstimationLimit, upperEstimationLimit);
+    public override void RecalculateModelParameters(IClassificationProblemData problemData, IEnumerable<int> rows) {
+      double[] classValues;
+      double[] thresholds;
+      var targetClassValues = problemData.Dataset.GetDoubleValues(problemData.TargetVariable, rows);
+      var estimatedTrainingValues = GetEstimatedValues(problemData.Dataset, rows);
+      thresholdCalculator.Calculate(problemData, estimatedTrainingValues, targetClassValues, out classValues, out thresholds);
+      SetThresholdsAndClassValues(thresholds, classValues);
     }
 
-    public IEnumerable<double> GetEstimatedClassValues(Dataset dataset, IEnumerable<int> rows) {
+    public IEnumerable<double> GetEstimatedValues(Dataset dataset, IEnumerable<int> rows) {
+      return Interpreter.GetSymbolicExpressionTreeValues(SymbolicExpressionTree, dataset, rows).LimitToRange(LowerEstimationLimit, UpperEstimationLimit);
+    }
+
+    public override IEnumerable<double> GetEstimatedClassValues(Dataset dataset, IEnumerable<int> rows) {
       if (!Thresholds.Any() && !ClassValues.Any()) throw new ArgumentException("No thresholds and class values were set for the current symbolic classification model.");
       foreach (var x in GetEstimatedValues(dataset, rows)) {
@@ -104,12 +118,16 @@
     }
 
-    public SymbolicDiscriminantFunctionClassificationSolution CreateClassificationSolution(IClassificationProblemData problemData) {
+
+    public override ISymbolicClassificationSolution CreateClassificationSolution(IClassificationProblemData problemData) {
+      return CreateDiscriminantClassificationSolution(problemData);
+    }
+    public SymbolicDiscriminantFunctionClassificationSolution CreateDiscriminantClassificationSolution(IClassificationProblemData problemData) {
       return new SymbolicDiscriminantFunctionClassificationSolution(this, new ClassificationProblemData(problemData));
     }
     IClassificationSolution IClassificationModel.CreateClassificationSolution(IClassificationProblemData problemData) {
-      return CreateClassificationSolution(problemData);
+      return CreateDiscriminantClassificationSolution(problemData);
     }
     IDiscriminantFunctionClassificationSolution IDiscriminantFunctionClassificationModel.CreateDiscriminantFunctionClassificationSolution(IClassificationProblemData problemData) {
-      return CreateClassificationSolution(problemData);
+      return CreateDiscriminantClassificationSolution(problemData);
     }
 
@@ -121,95 +139,4 @@
     }
     #endregion
-
-    public void SetAccuracyMaximizingThresholds(IClassificationProblemData problemData) {
-      double[] classValues;
-      double[] thresholds;
-      var targetClassValues = problemData.Dataset.GetDoubleValues(problemData.TargetVariable, problemData.TrainingIndices);
-      var estimatedTrainingValues = GetEstimatedValues(problemData.Dataset, problemData.TrainingIndices);
-      AccuracyMaximizationThresholdCalculator.CalculateThresholds(problemData, estimatedTrainingValues, targetClassValues, out classValues, out thresholds);
-
-      SetThresholdsAndClassValues(thresholds, classValues);
-    }
-
-    public void SetClassDistributionCutPointThresholds(IClassificationProblemData problemData) {
-      double[] classValues;
-      double[] thresholds;
-      var targetClassValues = problemData.Dataset.GetDoubleValues(problemData.TargetVariable, problemData.TrainingIndices);
-      var estimatedTrainingValues = GetEstimatedValues(problemData.Dataset, problemData.TrainingIndices);
-      NormalDistributionCutPointsThresholdCalculator.CalculateThresholds(problemData, estimatedTrainingValues, targetClassValues, out classValues, out thresholds);
-
-      SetThresholdsAndClassValues(thresholds, classValues);
-    }
-
-    public static void Scale(SymbolicDiscriminantFunctionClassificationModel model, IClassificationProblemData problemData) {
-      var dataset = problemData.Dataset;
-      var targetVariable = problemData.TargetVariable;
-      var rows = problemData.TrainingIndices;
-      var estimatedValues = model.Interpreter.GetSymbolicExpressionTreeValues(model.SymbolicExpressionTree, dataset, rows);
-      var targetValues = dataset.GetDoubleValues(targetVariable, rows);
-      double alpha;
-      double beta;
-      OnlineCalculatorError errorState;
-      OnlineLinearScalingParameterCalculator.Calculate(estimatedValues, targetValues, out alpha, out beta, out errorState);
-      if (errorState != OnlineCalculatorError.None) return;
-
-      ConstantTreeNode alphaTreeNode = null;
-      ConstantTreeNode betaTreeNode = null;
-      // check if model has been scaled previously by analyzing the structure of the tree
-      var startNode = model.SymbolicExpressionTree.Root.GetSubtree(0);
-      if (startNode.GetSubtree(0).Symbol is Addition) {
-        var addNode = startNode.GetSubtree(0);
-        if (addNode.SubtreeCount == 2 && addNode.GetSubtree(0).Symbol is Multiplication && addNode.GetSubtree(1).Symbol is Constant) {
-          alphaTreeNode = addNode.GetSubtree(1) as ConstantTreeNode;
-          var mulNode = addNode.GetSubtree(0);
-          if (mulNode.SubtreeCount == 2 && mulNode.GetSubtree(1).Symbol is Constant) {
-            betaTreeNode = mulNode.GetSubtree(1) as ConstantTreeNode;
-          }
-        }
-      }
-      // if tree structure matches the structure necessary for linear scaling then reuse the existing tree nodes
-      if (alphaTreeNode != null && betaTreeNode != null) {
-        betaTreeNode.Value *= beta;
-        alphaTreeNode.Value *= beta;
-        alphaTreeNode.Value += alpha;
-      } else {
-        var mainBranch = startNode.GetSubtree(0);
-        startNode.RemoveSubtree(0);
-        var scaledMainBranch = MakeSum(MakeProduct(mainBranch, beta), alpha);
-        startNode.AddSubtree(scaledMainBranch);
-      }
-    }
-
-    private static ISymbolicExpressionTreeNode MakeSum(ISymbolicExpressionTreeNode treeNode, double alpha) {
-      if (alpha.IsAlmost(0.0)) {
-        return treeNode;
-      } else {
-        var addition = new Addition();
-        var node = addition.CreateTreeNode();
-        var alphaConst = MakeConstant(alpha);
-        node.AddSubtree(treeNode);
-        node.AddSubtree(alphaConst);
-        return node;
-      }
-    }
-
-    private static ISymbolicExpressionTreeNode MakeProduct(ISymbolicExpressionTreeNode treeNode, double beta) {
-      if (beta.IsAlmost(1.0)) {
-        return treeNode;
-      } else {
-        var multipliciation = new Multiplication();
-        var node = multipliciation.CreateTreeNode();
-        var betaConst = MakeConstant(beta);
-        node.AddSubtree(treeNode);
-        node.AddSubtree(betaConst);
-        return node;
-      }
-    }
-
-    private static ISymbolicExpressionTreeNode MakeConstant(double c) {
-      var node = (ConstantTreeNode)(new Constant()).CreateTreeNode();
-      node.Value = c;
-      return node;
-    }
   }
 }
