Index: /branches/DataAnalysis Refactoring/HeuristicLab.Algorithms.DataAnalysis/3.4/Linear/LinearDiscriminantAnalysis.cs
===================================================================
--- /branches/DataAnalysis Refactoring/HeuristicLab.Algorithms.DataAnalysis/3.4/Linear/LinearDiscriminantAnalysis.cs	(revision 5735)
+++ /branches/DataAnalysis Refactoring/HeuristicLab.Algorithms.DataAnalysis/3.4/Linear/LinearDiscriminantAnalysis.cs	(revision 5736)
@@ -119,12 +119,5 @@
       IClassificationProblemData problemData,
       IEnumerable<int> rows) {
-      string targetVariable = problemData.TargetVariable;
-      var estimatedValues = interpreter.GetSymbolicExpressionTreeValues(tree, problemData.Dataset, rows);
-      var targetClassValues = problemData.Dataset.GetEnumeratedVariableValues(targetVariable, rows);
-
-      double[] classValues;
-      double[] thresholds;
-      NormalDistributionCutPointsThresholdCalculator.CalculateThresholds(problemData, estimatedValues, targetClassValues, out classValues, out thresholds);
-      return new SymbolicDiscriminantFunctionClassificationModel(tree, interpreter, classValues, thresholds);
+      return new SymbolicDiscriminantFunctionClassificationModel(tree, interpreter);
     }
   }
Index: /branches/DataAnalysis Refactoring/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification.Views/3.4/InteractiveSymbolicDiscriminantFunctionClassificationSolutionSimplifierView.cs
===================================================================
--- /branches/DataAnalysis Refactoring/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification.Views/3.4/InteractiveSymbolicDiscriminantFunctionClassificationSolutionSimplifierView.cs	(revision 5735)
+++ /branches/DataAnalysis Refactoring/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification.Views/3.4/InteractiveSymbolicDiscriminantFunctionClassificationSolutionSimplifierView.cs	(revision 5736)
@@ -48,21 +48,11 @@
       ISymbolicExpressionTreeNode root = new ProgramRootSymbol().CreateTreeNode();
       ISymbolicExpressionTreeNode start = new StartSymbol().CreateTreeNode();
-      root.AddSubTree(start);
+      root.AddSubtree(start);
       tempTree = new SymbolicExpressionTree(root);
     }
 
     protected override void UpdateModel(ISymbolicExpressionTree tree) {
-      var dataset = Content.ProblemData.Dataset;
-      var interpreter = Content.Model.Interpreter;
-      var rows = Content.ProblemData.TrainingIndizes;
-      string targetVariable = Content.ProblemData.TargetVariable;
-
-      var targetClassValues = dataset.GetEnumeratedVariableValues(targetVariable, rows);
-      var originalOutput = interpreter.GetSymbolicExpressionTreeValues(tree, dataset, rows)
-        .ToArray();
-      double[] classValues;
-      double[] thresholds;
-      NormalDistributionCutPointsThresholdCalculator.CalculateThresholds(Content.ProblemData, originalOutput, targetClassValues, out classValues, out thresholds);
-      Content.Model = new SymbolicDiscriminantFunctionClassificationModel(tree, Content.Model.Interpreter, classValues, thresholds);
+      Content.Model = new SymbolicDiscriminantFunctionClassificationModel(tree, Content.Model.Interpreter);
+      Content.SetClassDistibutionCutPointThresholds();
     }
 
@@ -83,13 +73,15 @@
       string targetVariable = Content.ProblemData.TargetVariable;
       Dictionary<ISymbolicExpressionTreeNode, double> impactValues = new Dictionary<ISymbolicExpressionTreeNode, double>();
-      List<ISymbolicExpressionTreeNode> nodes = tree.Root.GetSubTree(0).GetSubTree(0).IterateNodesPostfix().ToList();
+      List<ISymbolicExpressionTreeNode> nodes = tree.Root.GetSubtree(0).GetSubtree(0).IterateNodesPostfix().ToList();
 
       var targetClassValues = dataset.GetEnumeratedVariableValues(targetVariable, rows);
       var originalOutput = interpreter.GetSymbolicExpressionTreeValues(tree, dataset, rows)
+        .LimitToRange(Content.Model.LowerEstimationLimit, Content.Model.UpperEstimationLimit)
         .ToArray();
       double[] classValues;
       double[] thresholds;
       NormalDistributionCutPointsThresholdCalculator.CalculateThresholds(Content.ProblemData, originalOutput, targetClassValues, out classValues, out thresholds);
-      var classifier = new SymbolicDiscriminantFunctionClassificationModel(tree, interpreter, classValues, thresholds);
+      var classifier = new SymbolicDiscriminantFunctionClassificationModel(tree, interpreter);
+      classifier.SetThresholdsAndClassValues(thresholds, classValues);
       double originalAccuracy = OnlineAccuracyEvaluator.Calculate(targetClassValues, classifier.GetEstimatedClassValues(dataset, rows));
 
@@ -99,7 +91,10 @@
         ISymbolicExpressionTreeNode replacementNode = constantNode;
         SwitchNode(parent, node, replacementNode);
-        var newOutput = interpreter.GetSymbolicExpressionTreeValues(tree, dataset, rows);
+        var newOutput = interpreter.GetSymbolicExpressionTreeValues(tree, dataset, rows)
+          .LimitToRange(Content.Model.LowerEstimationLimit, Content.Model.UpperEstimationLimit)
+          .ToArray();
         NormalDistributionCutPointsThresholdCalculator.CalculateThresholds(Content.ProblemData, newOutput, targetClassValues, out classValues, out thresholds);
-        classifier = new SymbolicDiscriminantFunctionClassificationModel(tree, interpreter, classValues, thresholds);
+        classifier = new SymbolicDiscriminantFunctionClassificationModel(tree, interpreter);
+        classifier.SetThresholdsAndClassValues(thresholds, classValues);
         double newAccuracy = OnlineAccuracyEvaluator.Calculate(targetClassValues, classifier.GetEstimatedClassValues(dataset, rows));
 
@@ -114,7 +109,7 @@
 
     private double CalculateReplacementValue(ISymbolicExpressionTreeNode node) {
-      var start = tempTree.Root.GetSubTree(0);
-      while (start.SubTrees.Count() > 0) start.RemoveSubTree(0);
-      start.AddSubTree((ISymbolicExpressionTreeNode)node.Clone());
+      var start = tempTree.Root.GetSubtree(0);
+      while (start.SubtreesCount > 0) start.RemoveSubtree(0);
+      start.AddSubtree((ISymbolicExpressionTreeNode)node.Clone());
       var interpreter = Content.Model.Interpreter;
       var rows = Content.ProblemData.TrainingIndizes;
@@ -124,8 +119,8 @@
 
     private void SwitchNode(ISymbolicExpressionTreeNode root, ISymbolicExpressionTreeNode oldBranch, ISymbolicExpressionTreeNode newBranch) {
-      for (int i = 0; i < root.SubTrees.Count(); i++) {
-        if (root.GetSubTree(i) == oldBranch) {
-          root.RemoveSubTree(i);
-          root.InsertSubTree(i, newBranch);
+      for (int i = 0; i < root.SubtreesCount; i++) {
+        if (root.GetSubtree(i) == oldBranch) {
+          root.RemoveSubtree(i);
+          root.InsertSubtree(i, newBranch);
           return;
         }
Index: /branches/DataAnalysis Refactoring/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/Interfaces/ISymbolicDiscriminantFunctionClassificationModel.cs
===================================================================
--- /branches/DataAnalysis Refactoring/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/Interfaces/ISymbolicDiscriminantFunctionClassificationModel.cs	(revision 5735)
+++ /branches/DataAnalysis Refactoring/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/Interfaces/ISymbolicDiscriminantFunctionClassificationModel.cs	(revision 5736)
@@ -23,4 +23,6 @@
 namespace HeuristicLab.Problems.DataAnalysis.Symbolic.Classification {
   public interface ISymbolicDiscriminantFunctionClassificationModel : IDiscriminantFunctionClassificationModel, ISymbolicClassificationModel {
+    double LowerEstimationLimit { get; }
+    double UpperEstimationLimit { get; }
   }
 }
Index: /branches/DataAnalysis Refactoring/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/MultiObjective/SymbolicClassificationMultiObjectiveTrainingBestSolutionAnalyzer.cs
===================================================================
--- /branches/DataAnalysis Refactoring/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/MultiObjective/SymbolicClassificationMultiObjectiveTrainingBestSolutionAnalyzer.cs	(revision 5735)
+++ /branches/DataAnalysis Refactoring/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/MultiObjective/SymbolicClassificationMultiObjectiveTrainingBestSolutionAnalyzer.cs	(revision 5736)
@@ -95,14 +95,11 @@
     }
 
-
     protected override ISymbolicClassificationSolution CreateSolution(ISymbolicExpressionTree bestTree, double[] bestQuality) {
-      double[] classValues;
-      double[] thresholds;
-      var estimatedValues = SymbolicDataAnalysisTreeInterpreter.GetSymbolicExpressionTreeValues(bestTree, ProblemData.Dataset, ProblemData.TrainingIndizes)
-        .LimitToRange(LowerEstimationLimit.Value, UpperEstimationLimit.Value);
-      var targetValues = ProblemData.Dataset.GetEnumeratedVariableValues(ProblemData.TargetVariable, ProblemData.TrainingIndizes);
-      AccuracyMaximizationThresholdCalculator.CalculateThresholds(ProblemData, estimatedValues, targetValues, out classValues, out thresholds);
-      var model = new SymbolicDiscriminantFunctionClassificationModel(bestTree, SymbolicDataAnalysisTreeInterpreter, classValues, thresholds, LowerEstimationLimit.Value, UpperEstimationLimit.Value);
-      return new SymbolicDiscriminantFunctionClassificationSolution(model, ProblemData);
+      var model = new SymbolicDiscriminantFunctionClassificationModel(bestTree, SymbolicDataAnalysisTreeInterpreter, LowerEstimationLimit.Value, UpperEstimationLimit.Value);
+      var solution = new SymbolicDiscriminantFunctionClassificationSolution(model, ProblemData);
+      if (ApplyLinearScaling.Value) {
+        solution.ScaleModel();
+      }
+      return solution;
     }
   }
Index: /branches/DataAnalysis Refactoring/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/MultiObjective/SymbolicClassificationMultiObjectiveValidationBestSolutionAnalyzer.cs
===================================================================
--- /branches/DataAnalysis Refactoring/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/MultiObjective/SymbolicClassificationMultiObjectiveValidationBestSolutionAnalyzer.cs	(revision 5735)
+++ /branches/DataAnalysis Refactoring/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/MultiObjective/SymbolicClassificationMultiObjectiveValidationBestSolutionAnalyzer.cs	(revision 5736)
@@ -81,13 +81,10 @@
 
     protected override ISymbolicClassificationSolution CreateSolution(ISymbolicExpressionTree bestTree, double[] bestQualities) {
-      double[] classValues;
-      double[] thresholds;
-      // calculate thresholds on the whole training set even for the validation best solution
-      var estimatedValues = SymbolicDataAnalysisTreeInterpreter.GetSymbolicExpressionTreeValues(bestTree, ProblemData.Dataset, ProblemData.TrainingIndizes)
-        .LimitToRange(LowerEstimationLimit.Value, UpperEstimationLimit.Value);
-      var targetClassValues = ProblemData.Dataset.GetEnumeratedVariableValues(ProblemData.TargetVariable, ProblemData.TrainingIndizes);
-      AccuracyMaximizationThresholdCalculator.CalculateThresholds(ProblemData, estimatedValues, targetClassValues, out classValues, out thresholds);
-      var model = new SymbolicDiscriminantFunctionClassificationModel(bestTree, SymbolicDataAnalysisTreeInterpreter, classValues, thresholds, LowerEstimationLimit.Value, UpperEstimationLimit.Value);
-      return new SymbolicDiscriminantFunctionClassificationSolution(model, ProblemData);
+      var model = new SymbolicDiscriminantFunctionClassificationModel(bestTree, SymbolicDataAnalysisTreeInterpreter, LowerEstimationLimit.Value, UpperEstimationLimit.Value);
+      var solution = new SymbolicDiscriminantFunctionClassificationSolution(model, ProblemData);
+      if (ApplyLinearScaling.Value) {
+        solution.ScaleModel();
+      }
+      return solution;
     }
   }
Index: /branches/DataAnalysis Refactoring/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SingleObjective/SymbolicClassificationSingleObjectiveTrainingBestSolutionAnalyzer.cs
===================================================================
--- /branches/DataAnalysis Refactoring/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SingleObjective/SymbolicClassificationSingleObjectiveTrainingBestSolutionAnalyzer.cs	(revision 5735)
+++ /branches/DataAnalysis Refactoring/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SingleObjective/SymbolicClassificationSingleObjectiveTrainingBestSolutionAnalyzer.cs	(revision 5736)
@@ -96,12 +96,10 @@
 
     protected override ISymbolicClassificationSolution CreateSolution(ISymbolicExpressionTree bestTree, double bestQuality) {
-      double[] classValues;
-      double[] thresholds;
-      var estimatedValues = SymbolicDataAnalysisTreeInterpreter.GetSymbolicExpressionTreeValues(bestTree, ProblemData.Dataset, ProblemData.TrainingIndizes)
-        .LimitToRange(LowerEstimationLimit.Value, UpperEstimationLimit.Value);
-      var targetValues = ProblemData.Dataset.GetEnumeratedVariableValues(ProblemData.TargetVariable, ProblemData.TrainingIndizes);
-      AccuracyMaximizationThresholdCalculator.CalculateThresholds(ProblemData, estimatedValues, targetValues, out classValues, out thresholds);
-      var model = new SymbolicDiscriminantFunctionClassificationModel(bestTree, SymbolicDataAnalysisTreeInterpreter, classValues, thresholds, LowerEstimationLimit.Value, UpperEstimationLimit.Value);
-      return new SymbolicDiscriminantFunctionClassificationSolution(model, ProblemData);
+      var model = new SymbolicDiscriminantFunctionClassificationModel(bestTree, SymbolicDataAnalysisTreeInterpreter, LowerEstimationLimit.Value, UpperEstimationLimit.Value);
+      var solution = new SymbolicDiscriminantFunctionClassificationSolution(model, ProblemData);
+      if (ApplyLinearScaling.Value) {
+        solution.ScaleModel();
+      }
+      return solution;
     }
   }
Index: /branches/DataAnalysis Refactoring/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SingleObjective/SymbolicClassificationSingleObjectiveValidationBestSolutionAnalyzer.cs
===================================================================
--- /branches/DataAnalysis Refactoring/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SingleObjective/SymbolicClassificationSingleObjectiveValidationBestSolutionAnalyzer.cs	(revision 5735)
+++ /branches/DataAnalysis Refactoring/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SingleObjective/SymbolicClassificationSingleObjectiveValidationBestSolutionAnalyzer.cs	(revision 5736)
@@ -82,13 +82,10 @@
 
     protected override ISymbolicClassificationSolution CreateSolution(ISymbolicExpressionTree bestTree, double bestQuality) {
-      double[] classValues;
-      double[] thresholds;
-      // calculate thresholds on the whole training set even for the validation best solution
-      var estimatedValues = SymbolicDataAnalysisTreeInterpreter.GetSymbolicExpressionTreeValues(bestTree, ProblemData.Dataset, ProblemData.TrainingIndizes)
-        .LimitToRange(LowerEstimationLimit.Value, UpperEstimationLimit.Value);
-      var targetClassValues = ProblemData.Dataset.GetEnumeratedVariableValues(ProblemData.TargetVariable, ProblemData.TrainingIndizes);
-      AccuracyMaximizationThresholdCalculator.CalculateThresholds(ProblemData, estimatedValues, targetClassValues, out classValues, out thresholds);
-      var model = new SymbolicDiscriminantFunctionClassificationModel(bestTree, SymbolicDataAnalysisTreeInterpreter, classValues, thresholds, LowerEstimationLimit.Value, UpperEstimationLimit.Value);
-      return new SymbolicDiscriminantFunctionClassificationSolution(model, ProblemData);
+      var model = new SymbolicDiscriminantFunctionClassificationModel(bestTree, SymbolicDataAnalysisTreeInterpreter, LowerEstimationLimit.Value, UpperEstimationLimit.Value);
+      var solution = new SymbolicDiscriminantFunctionClassificationSolution(model, ProblemData);
+      if (ApplyLinearScaling.Value) {
+        solution.ScaleModel();
+      }
+      return solution;
     }
   }
Index: /branches/DataAnalysis Refactoring/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SymbolicClassificationSolution.cs
===================================================================
--- /branches/DataAnalysis Refactoring/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SymbolicClassificationSolution.cs	(revision 5735)
+++ /branches/DataAnalysis Refactoring/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SymbolicClassificationSolution.cs	(revision 5736)
@@ -39,5 +39,6 @@
   [Item(Name = "SymbolicClassificationSolution", Description = "Represents a symbolic classification solution (model + data) and attributes of the solution like accuracy and complexity.")]
   public sealed class SymbolicClassificationSolution : ClassificationSolution, ISymbolicClassificationSolution {
-    #region ISymbolicClassificationSolution Members
+    private const string ModelLengthResultName = "ModelLength";
+    private const string ModelDepthResultName = "ModelDepth";
 
     public new ISymbolicClassificationModel Model {
@@ -49,6 +50,14 @@
       get { return (ISymbolicDataAnalysisModel)base.Model; }
     }
+    public int ModelLength {
+      get { return ((IntValue)this[ModelLengthResultName].Value).Value; }
+      private set { ((IntValue)this[ModelLengthResultName].Value).Value = value; }
+    }
 
-    #endregion
+    public int ModelDepth {
+      get { return ((IntValue)this[ModelDepthResultName].Value).Value; }
+      private set { ((IntValue)this[ModelDepthResultName].Value).Value = value; }
+    }
+
     [StorableConstructor]
     private SymbolicClassificationSolution(bool deserializing) : base(deserializing) { }
@@ -58,4 +67,7 @@
     public SymbolicClassificationSolution(ISymbolicClassificationModel model, IClassificationProblemData problemData)
       : base(model, problemData) {
+      Add(new Result(ModelLengthResultName, "Length of the symbolic classification model.", new IntValue()));
+      Add(new Result(ModelDepthResultName, "Depth of the symbolic classification model.", new IntValue()));
+      RecalculateResults();
     }
 
@@ -63,4 +75,14 @@
       return new SymbolicClassificationSolution(this, cloner);
     }
+
+    protected override void OnModelChanged(EventArgs e) {
+      base.OnModelChanged(e);
+      RecalculateResults();
+    }
+
+    private new void RecalculateResults() {
+      ModelLength = Model.SymbolicExpressionTree.Length;
+      ModelDepth = Model.SymbolicExpressionTree.Depth;
+    }
   }
 }
Index: /branches/DataAnalysis Refactoring/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SymbolicDiscriminantFunctionClassificationModel.cs
===================================================================
--- /branches/DataAnalysis Refactoring/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SymbolicDiscriminantFunctionClassificationModel.cs	(revision 5735)
+++ /branches/DataAnalysis Refactoring/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SymbolicDiscriminantFunctionClassificationModel.cs	(revision 5736)
@@ -44,8 +44,5 @@
     public IEnumerable<double> Thresholds {
       get { return (IEnumerable<double>)thresholds.Clone(); }
-      set {
-        thresholds = value.ToArray();
-        OnThresholdsChanged(EventArgs.Empty);
-      }
+      private set { thresholds = value.ToArray(); }
     }
     [Storable]
@@ -53,5 +50,5 @@
     public IEnumerable<double> ClassValues {
       get { return (IEnumerable<double>)classValues.Clone(); }
-      set { classValues = value.ToArray(); }
+      private set { classValues = value.ToArray(); }
     }
     [Storable]
@@ -72,9 +69,8 @@
     }
     public SymbolicDiscriminantFunctionClassificationModel(ISymbolicExpressionTree tree, ISymbolicDataAnalysisExpressionTreeInterpreter interpreter,
-      IEnumerable<double> classValues, IEnumerable<double> thresholds,
       double lowerEstimationLimit = double.MinValue, double upperEstimationLimit = double.MaxValue)
       : base(tree, interpreter) {
-      this.classValues = classValues.ToArray();
-      this.thresholds = thresholds.ToArray();
+      thresholds = new double[] { double.NegativeInfinity };
+      classValues = new double[] { 0.0 };
       this.lowerEstimationLimit = lowerEstimationLimit;
       this.upperEstimationLimit = upperEstimationLimit;
@@ -85,6 +81,17 @@
     }
 
+    public void SetThresholdsAndClassValues(IEnumerable<double> thresholds, IEnumerable<double> classValues) {
+      var classValuesArr = classValues.ToArray();
+      var thresholdsArr = thresholds.ToArray();
+      if (thresholdsArr.Length != classValuesArr.Length) throw new ArgumentException();
+
+      this.classValues = classValuesArr;
+      this.thresholds = thresholdsArr;
+      OnThresholdsChanged(EventArgs.Empty);
+    }
+
     public IEnumerable<double> GetEstimatedValues(Dataset dataset, IEnumerable<int> rows) {
-      return Interpreter.GetSymbolicExpressionTreeValues(SymbolicExpressionTree, dataset, rows);
+      return Interpreter.GetSymbolicExpressionTreeValues(SymbolicExpressionTree, dataset, rows)
+        .LimitToRange(lowerEstimationLimit, upperEstimationLimit);
     }
 
Index: /branches/DataAnalysis Refactoring/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SymbolicDiscriminantFunctionClassificationSolution.cs
===================================================================
--- /branches/DataAnalysis Refactoring/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SymbolicDiscriminantFunctionClassificationSolution.cs	(revision 5735)
+++ /branches/DataAnalysis Refactoring/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SymbolicDiscriminantFunctionClassificationSolution.cs	(revision 5736)
@@ -39,4 +39,6 @@
   [Item(Name = "SymbolicDiscriminantFunctionClassificationSolution", Description = "Represents a symbolic classification solution (model + data) and attributes of the solution like accuracy and complexity.")]
   public sealed class SymbolicDiscriminantFunctionClassificationSolution : DiscriminantFunctionClassificationSolution, ISymbolicClassificationSolution {
+    private const string ModelLengthResultName = "ModelLength";
+    private const string ModelDepthResultName = "ModelDepth";
 
     public new ISymbolicDiscriminantFunctionClassificationModel Model {
@@ -52,5 +54,13 @@
       get { return Model; }
     }
+    public int ModelLength {
+      get { return ((IntValue)this[ModelLengthResultName].Value).Value; }
+      private set { ((IntValue)this[ModelLengthResultName].Value).Value = value; }
+    }
 
+    public int ModelDepth {
+      get { return ((IntValue)this[ModelDepthResultName].Value).Value; }
+      private set { ((IntValue)this[ModelDepthResultName].Value).Value = value; }
+    }
     [StorableConstructor]
     private SymbolicDiscriminantFunctionClassificationSolution(bool deserializing) : base(deserializing) { }
@@ -60,4 +70,7 @@
     public SymbolicDiscriminantFunctionClassificationSolution(ISymbolicDiscriminantFunctionClassificationModel model, IClassificationProblemData problemData)
       : base(model, problemData) {
+      Add(new Result(ModelLengthResultName, "Length of the symbolic classification model.", new IntValue()));
+      Add(new Result(ModelDepthResultName, "Depth of the symbolic classification model.", new IntValue()));
+      RecalculateResults();
     }
 
@@ -65,4 +78,83 @@
       return new SymbolicDiscriminantFunctionClassificationSolution(this, cloner);
     }
+
+    protected override void OnModelChanged(EventArgs e) {
+      base.OnModelChanged(e);
+      RecalculateResults();
+    }
+
+    private new void RecalculateResults() {
+      ModelLength = Model.SymbolicExpressionTree.Length;
+      ModelDepth = Model.SymbolicExpressionTree.Depth;
+    }
+
+    public void ScaleModel() {
+      var dataset = ProblemData.Dataset;
+      var targetVariable = ProblemData.TargetVariable;
+      var rows = ProblemData.TrainingIndizes;
+      var estimatedValues = GetEstimatedValues(rows);
+      var targetValues = dataset.GetEnumeratedVariableValues(targetVariable, rows);
+      double alpha;
+      double beta;
+      OnlineLinearScalingParameterCalculator.Calculate(estimatedValues, targetValues, out alpha, out beta);
+
+      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.SubtreesCount == 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.SubtreesCount == 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(beta, mainBranch), alpha);
+        startNode.AddSubtree(scaledMainBranch);
+      }
+
+      OnModelChanged(EventArgs.Empty);
+    }
+
+    private static ISymbolicExpressionTreeNode MakeSum(ISymbolicExpressionTreeNode treeNode, double alpha) {
+      if (alpha.IsAlmost(0.0)) {
+        return treeNode;
+      } else {
+        var node = (new Addition()).CreateTreeNode();
+        var alphaConst = MakeConstant(alpha);
+        node.AddSubtree(treeNode);
+        node.AddSubtree(alphaConst);
+        return node;
+      }
+    }
+
+    private static ISymbolicExpressionTreeNode MakeProduct(double beta, ISymbolicExpressionTreeNode treeNode) {
+      if (beta.IsAlmost(1.0)) {
+        return treeNode;
+      } else {
+        var node = (new Multiplication()).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;
+    }
   }
 }
Index: /branches/DataAnalysis Refactoring/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression.Views/3.4/InteractiveSymbolicRegressionSolutionSimplifierView.cs
===================================================================
--- /branches/DataAnalysis Refactoring/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression.Views/3.4/InteractiveSymbolicRegressionSolutionSimplifierView.cs	(revision 5735)
+++ /branches/DataAnalysis Refactoring/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression.Views/3.4/InteractiveSymbolicRegressionSolutionSimplifierView.cs	(revision 5736)
@@ -48,5 +48,5 @@
       ISymbolicExpressionTreeNode root = new ProgramRootSymbol().CreateTreeNode();
       ISymbolicExpressionTreeNode start = new StartSymbol().CreateTreeNode();
-      root.AddSubTree(start);
+      root.AddSubtree(start);
       tempTree = new SymbolicExpressionTree(root);
     }
@@ -73,5 +73,5 @@
       string targetVariable = Content.ProblemData.TargetVariable;
       Dictionary<ISymbolicExpressionTreeNode, double> impactValues = new Dictionary<ISymbolicExpressionTreeNode, double>();
-      List<ISymbolicExpressionTreeNode> nodes = tree.Root.GetSubTree(0).GetSubTree(0).IterateNodesPostfix().ToList();
+      List<ISymbolicExpressionTreeNode> nodes = tree.Root.GetSubtree(0).GetSubtree(0).IterateNodesPostfix().ToList();
       var originalOutput = interpreter.GetSymbolicExpressionTreeValues(tree, dataset, rows)
         .ToArray();
@@ -98,7 +98,7 @@
 
     private double CalculateReplacementValue(ISymbolicExpressionTreeNode node) {
-      var start = tempTree.Root.GetSubTree(0);
-      while (start.SubTrees.Count() > 0) start.RemoveSubTree(0);
-      start.AddSubTree((ISymbolicExpressionTreeNode)node.Clone());
+      var start = tempTree.Root.GetSubtree(0);
+      while (start.SubtreesCount > 0) start.RemoveSubtree(0);
+      start.AddSubtree((ISymbolicExpressionTreeNode)node.Clone());
       var interpreter = Content.Model.Interpreter;
       var rows = Content.ProblemData.TrainingIndizes;
@@ -108,8 +108,8 @@
 
     private void SwitchNode(ISymbolicExpressionTreeNode root, ISymbolicExpressionTreeNode oldBranch, ISymbolicExpressionTreeNode newBranch) {
-      for (int i = 0; i < root.SubTrees.Count(); i++) {
-        if (root.GetSubTree(i) == oldBranch) {
-          root.RemoveSubTree(i);
-          root.InsertSubTree(i, newBranch);
+      for (int i = 0; i < root.SubtreesCount; i++) {
+        if (root.GetSubtree(i) == oldBranch) {
+          root.RemoveSubtree(i);
+          root.InsertSubtree(i, newBranch);
           return;
         }
Index: /branches/DataAnalysis Refactoring/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SymbolicRegressionSolution.cs
===================================================================
--- /branches/DataAnalysis Refactoring/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SymbolicRegressionSolution.cs	(revision 5735)
+++ /branches/DataAnalysis Refactoring/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SymbolicRegressionSolution.cs	(revision 5736)
@@ -39,4 +39,7 @@
   [Item(Name = "SymbolicRegressionSolution", Description = "Represents a symbolic regression solution (model + data) and attributes of the solution like accuracy and complexity.")]
   public sealed class SymbolicRegressionSolution : RegressionSolution, ISymbolicRegressionSolution {
+    private const string ModelLengthResultName = "ModelLength";
+    private const string ModelDepthResultName = "ModelDepth";
+
     public new ISymbolicRegressionModel Model {
       get { return (ISymbolicRegressionModel)base.Model; }
@@ -45,4 +48,13 @@
     ISymbolicDataAnalysisModel ISymbolicDataAnalysisSolution.Model {
       get { return (ISymbolicDataAnalysisModel)base.Model; }
+    }
+    public int ModelLength {
+      get { return ((IntValue)this[ModelLengthResultName].Value).Value; }
+      private set { ((IntValue)this[ModelLengthResultName].Value).Value = value; }
+    }
+
+    public int ModelDepth {
+      get { return ((IntValue)this[ModelDepthResultName].Value).Value; }
+      private set { ((IntValue)this[ModelDepthResultName].Value).Value = value; }
     }
 
@@ -54,8 +66,21 @@
     public SymbolicRegressionSolution(ISymbolicRegressionModel model, IRegressionProblemData problemData)
       : base(model, problemData) {
+      Add(new Result(ModelLengthResultName, "Length of the symbolic regression model.", new IntValue()));
+      Add(new Result(ModelDepthResultName, "Depth of the symbolic regression model.", new IntValue()));
+      RecalculateResults();
     }
 
     public override IDeepCloneable Clone(Cloner cloner) {
       return new SymbolicRegressionSolution(this, cloner);
+    }
+
+    protected override void OnModelChanged(EventArgs e) {
+      base.OnModelChanged(e);
+      RecalculateResults();
+    }
+
+    private new void RecalculateResults() {
+      ModelLength = Model.SymbolicExpressionTree.Length;
+      ModelDepth = Model.SymbolicExpressionTree.Depth;
     }
 
Index: /branches/DataAnalysis Refactoring/HeuristicLab.Problems.DataAnalysis.Symbolic.Views/3.4/InteractiveSymbolicDataAnalysisSolutionSimplifierView.cs
===================================================================
--- /branches/DataAnalysis Refactoring/HeuristicLab.Problems.DataAnalysis.Symbolic.Views/3.4/InteractiveSymbolicDataAnalysisSolutionSimplifierView.cs	(revision 5735)
+++ /branches/DataAnalysis Refactoring/HeuristicLab.Problems.DataAnalysis.Symbolic.Views/3.4/InteractiveSymbolicDataAnalysisSolutionSimplifierView.cs	(revision 5736)
@@ -92,8 +92,8 @@
 
         // automatically fold all branches with impact = 1
-        List<ISymbolicExpressionTreeNode> nodeList = Content.Model.SymbolicExpressionTree.Root.GetSubTree(0).IterateNodesPrefix().ToList();
+        List<ISymbolicExpressionTreeNode> nodeList = Content.Model.SymbolicExpressionTree.Root.GetSubtree(0).IterateNodesPrefix().ToList();
         foreach (var parent in nodeList) {
-          for (int subTreeIndex = 0; subTreeIndex < parent.SubTrees.Count(); subTreeIndex++) {
-            var child = parent.GetSubTree(subTreeIndex);
+          for (int subTreeIndex = 0; subTreeIndex < parent.SubtreesCount; subTreeIndex++) {
+            var child = parent.GetSubtree(subTreeIndex);
             if (!(child.Symbol is Constant) && nodeImpacts[child].IsAlmost(1.0)) {
               SwitchNodeWithReplacementNode(parent, subTreeIndex);
@@ -102,5 +102,5 @@
         }
         // show only interesting part of solution
-        this.treeChart.Tree = new SymbolicExpressionTree(tree.Root.GetSubTree(0).GetSubTree(0));
+        this.treeChart.Tree = new SymbolicExpressionTree(tree.Root.GetSubtree(0).GetSubtree(0));
         this.PaintNodeImpacts();
       }
@@ -124,6 +124,6 @@
       var tree = Content.Model.SymbolicExpressionTree;
       foreach (SymbolicExpressionTreeNode treeNode in tree.IterateNodesPostfix()) {
-        for (int i = 0; i < treeNode.SubTrees.Count(); i++) {
-          ISymbolicExpressionTreeNode subTree = treeNode.GetSubTree(i);
+        for (int i = 0; i < treeNode.SubtreesCount; i++) {
+          ISymbolicExpressionTreeNode subTree = treeNode.GetSubtree(i);
           if (subTree == visualTreeNode.SymbolicExpressionTreeNode) {
             SwitchNodeWithReplacementNode(treeNode, i);
@@ -133,21 +133,18 @@
 
       // show only interesting part of solution
-      this.treeChart.Tree = new SymbolicExpressionTree(tree.Root.GetSubTree(0).GetSubTree(0));
+      this.treeChart.Tree = new SymbolicExpressionTree(tree.Root.GetSubtree(0).GetSubtree(0));
 
       UpdateModel(tree);
-      this.PaintNodeImpacts();
     }
 
     private void SwitchNodeWithReplacementNode(ISymbolicExpressionTreeNode parent, int subTreeIndex) {
-      ISymbolicExpressionTreeNode subTree = parent.GetSubTree(subTreeIndex);
-      parent.RemoveSubTree(subTreeIndex);
+      ISymbolicExpressionTreeNode subTree = parent.GetSubtree(subTreeIndex);
+      parent.RemoveSubtree(subTreeIndex);
       if (replacementNodes.ContainsKey(subTree)) {
         var replacementNode = replacementNodes[subTree];
-        parent.InsertSubTree(subTreeIndex, replacementNode);
+        parent.InsertSubtree(subTreeIndex, replacementNode);
         // exchange key and value 
         replacementNodes.Remove(subTree);
         replacementNodes.Add(replacementNode, subTree);
-      } else {
-        throw new InvalidOperationException("Could not find replacement value.");
       }
     }
Index: /branches/DataAnalysis Refactoring/HeuristicLab.Problems.DataAnalysis.Views/3.4/Classification/DiscriminantFunctionClassificationSolutionView.cs
===================================================================
--- /branches/DataAnalysis Refactoring/HeuristicLab.Problems.DataAnalysis.Views/3.4/Classification/DiscriminantFunctionClassificationSolutionView.cs	(revision 5735)
+++ /branches/DataAnalysis Refactoring/HeuristicLab.Problems.DataAnalysis.Views/3.4/Classification/DiscriminantFunctionClassificationSolutionView.cs	(revision 5736)
@@ -98,7 +98,8 @@
     }
     private void Content_ModelChanged(object sender, EventArgs e) {
+      Content.Model.ThresholdsChanged += new EventHandler(Model_ThresholdsChanged);
       UpdateChart();
     }
-    private void Content_ThresholdsChanged(object sender, EventArgs e) {
+    private void Model_ThresholdsChanged(object sender, EventArgs e) {
       AddThresholds();
     }
@@ -244,5 +245,5 @@
 
       thresholds[classIndex] = e.NewLocationY;
-      Content.Model.Thresholds = thresholds;
+      Content.Model.SetThresholdsAndClassValues(thresholds, Content.Model.ClassValues);
     }
 
Index: /branches/DataAnalysis Refactoring/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ClassificationSolution.cs
===================================================================
--- /branches/DataAnalysis Refactoring/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ClassificationSolution.cs	(revision 5735)
+++ /branches/DataAnalysis Refactoring/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ClassificationSolution.cs	(revision 5736)
@@ -82,5 +82,5 @@
     }
 
-    private void RecalculateResults() {
+    protected void RecalculateResults() {
       double[] estimatedTrainingClassValues = EstimatedTrainingClassValues.ToArray(); // cache values
       IEnumerable<double> originalTrainingClassValues = ProblemData.Dataset.GetEnumeratedVariableValues(ProblemData.TargetVariable, ProblemData.TrainingIndizes);
Index: /branches/DataAnalysis Refactoring/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/DiscriminantFunctionClassificationModel.cs
===================================================================
--- /branches/DataAnalysis Refactoring/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/DiscriminantFunctionClassificationModel.cs	(revision 5735)
+++ /branches/DataAnalysis Refactoring/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/DiscriminantFunctionClassificationModel.cs	(revision 5736)
@@ -40,24 +40,17 @@
     [Storable]
     private IRegressionModel model;
+
     [Storable]
     private double[] classValues;
-    // class values are not necessarily sorted in ascending order
     public IEnumerable<double> ClassValues {
       get { return (double[])classValues.Clone(); }
-      set {
-        if (value == null) throw new ArgumentException();
-        double[] newValue = value.ToArray();
-        if (newValue.Length != classValues.Length) throw new ArgumentException();
-        classValues = newValue;
-      }
+      private set { classValues = value.ToArray(); }
     }
+
     [Storable]
     private double[] thresholds;
     public IEnumerable<double> Thresholds {
       get { return (IEnumerable<double>)thresholds.Clone(); }
-      set {
-        thresholds = value.ToArray();
-        OnThresholdsChanged(EventArgs.Empty);
-      }
+      private set { thresholds = value.ToArray(); }
     }
 
@@ -71,15 +64,26 @@
       thresholds = (double[])original.thresholds.Clone();
     }
-    public DiscriminantFunctionClassificationModel(IRegressionModel model, IEnumerable<double> classValues, IEnumerable<double> thresholds)
+
+    public DiscriminantFunctionClassificationModel(IRegressionModel model)
       : base() {
       this.name = ItemName;
       this.description = ItemDescription;
       this.model = model;
-      this.classValues = classValues.ToArray();
-      this.thresholds = thresholds.ToArray();
+      this.classValues = new double[] { 0.0 };
+      this.thresholds = new double[] { double.NegativeInfinity };
     }
 
     public override IDeepCloneable Clone(Cloner cloner) {
       return new DiscriminantFunctionClassificationModel(this, cloner);
+    }
+
+    public void SetThresholdsAndClassValues(IEnumerable<double> thresholds, IEnumerable<double> classValues) {
+      var classValuesArr = classValues.ToArray();
+      var thresholdsArr = thresholds.ToArray();
+      if (thresholdsArr.Length != classValuesArr.Length) throw new ArgumentException();
+
+      this.classValues = classValuesArr;
+      this.thresholds = thresholdsArr;
+      OnThresholdsChanged(EventArgs.Empty);
     }
 
@@ -96,5 +100,5 @@
           else break;
         }
-        yield return classValues.ElementAt(classIndex);
+        yield return classValues.ElementAt(classIndex - 1);
       }
     }
Index: /branches/DataAnalysis Refactoring/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/DiscriminantFunctionClassificationSolution.cs
===================================================================
--- /branches/DataAnalysis Refactoring/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/DiscriminantFunctionClassificationSolution.cs	(revision 5735)
+++ /branches/DataAnalysis Refactoring/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/DiscriminantFunctionClassificationSolution.cs	(revision 5736)
@@ -40,5 +40,13 @@
     public new IDiscriminantFunctionClassificationModel Model {
       get { return (IDiscriminantFunctionClassificationModel)base.Model; }
-      protected set { base.Model = value; }
+      protected set {
+        if (value != null && value != Model) {
+          if (Model != null) {
+            Model.ThresholdsChanged -= new EventHandler(Model_ThresholdsChanged);
+          }
+          value.ThresholdsChanged += new EventHandler(Model_ThresholdsChanged);
+          base.Model = value;
+        }
+      }
     }
 
@@ -47,10 +55,56 @@
     protected DiscriminantFunctionClassificationSolution(DiscriminantFunctionClassificationSolution original, Cloner cloner)
       : base(original, cloner) {
+      RegisterEventHandler();
     }
-    public DiscriminantFunctionClassificationSolution(IRegressionModel model, IClassificationProblemData problemData, IEnumerable<double> classValues, IEnumerable<double> thresholds)
-      : this(new DiscriminantFunctionClassificationModel(model, classValues, thresholds), problemData) {
+    public DiscriminantFunctionClassificationSolution(IRegressionModel model, IClassificationProblemData problemData)
+      : this(new DiscriminantFunctionClassificationModel(model), problemData) {
     }
     public DiscriminantFunctionClassificationSolution(IDiscriminantFunctionClassificationModel model, IClassificationProblemData problemData)
       : base(model, problemData) {
+      RegisterEventHandler();
+      SetAccuracyMaximizingThresholds();
+    }
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      RegisterEventHandler();
+    }
+
+    private void RegisterEventHandler() {
+      Model.ThresholdsChanged += new EventHandler(Model_ThresholdsChanged);
+    }
+    private void Model_ThresholdsChanged(object sender, EventArgs e) {
+      OnModelThresholdsChanged(e);
+    }
+
+    public void SetAccuracyMaximizingThresholds() {
+      double[] classValues;
+      double[] thresholds;
+      var targetClassValues = ProblemData.Dataset.GetEnumeratedVariableValues(ProblemData.TargetVariable, ProblemData.TrainingIndizes);
+      AccuracyMaximizationThresholdCalculator.CalculateThresholds(ProblemData, EstimatedTrainingValues, targetClassValues, out classValues, out thresholds);
+
+      Model.SetThresholdsAndClassValues(thresholds, classValues);
+    }
+
+    public void SetClassDistibutionCutPointThresholds() {
+      double[] classValues;
+      double[] thresholds;
+      var targetClassValues = ProblemData.Dataset.GetEnumeratedVariableValues(ProblemData.TargetVariable, ProblemData.TrainingIndizes);
+      NormalDistributionCutPointsThresholdCalculator.CalculateThresholds(ProblemData, EstimatedTrainingValues, targetClassValues, out classValues, out thresholds);
+
+      Model.SetThresholdsAndClassValues(thresholds, classValues);
+    }
+
+    protected override void OnModelChanged(EventArgs e) {
+      base.OnModelChanged(e);     
+      SetAccuracyMaximizingThresholds();
+    }
+
+    protected override void OnProblemDataChanged(EventArgs e) {
+      base.OnProblemDataChanged(e);
+      SetAccuracyMaximizingThresholds();
+    }
+    protected virtual void OnModelThresholdsChanged(EventArgs e) {
+      RecalculateResults();
     }
 
Index: /branches/DataAnalysis Refactoring/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ThresholdCalculators/AccuracyMaximizationThresholdCalculator.cs
===================================================================
--- /branches/DataAnalysis Refactoring/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ThresholdCalculators/AccuracyMaximizationThresholdCalculator.cs	(revision 5735)
+++ /branches/DataAnalysis Refactoring/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ThresholdCalculators/AccuracyMaximizationThresholdCalculator.cs	(revision 5736)
@@ -69,12 +69,12 @@
       classValues = problemData.ClassValues.OrderBy(x => x).ToArray();
       int nClasses = classValues.Length;
-      thresholds = new double[nClasses + 1];
+      thresholds = new double[nClasses];
       thresholds[0] = double.NegativeInfinity;
-      thresholds[thresholds.Length - 1] = double.PositiveInfinity;
+      // thresholds[thresholds.Length - 1] = double.PositiveInfinity;
 
       // incrementally calculate accuracy of all possible thresholds
       int[,] confusionMatrix = new int[nClasses, nClasses];
 
-      for (int i = 1; i < thresholds.Length - 1; i++) {
+      for (int i = 1; i < thresholds.Length; i++) {
         double lowerThreshold = thresholds[i - 1];
         double actualThreshold = Math.Max(lowerThreshold, minEstimatedValue);
Index: /branches/DataAnalysis Refactoring/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ThresholdCalculators/NormalDistributionCutPointsThresholdCalculator.cs
===================================================================
--- /branches/DataAnalysis Refactoring/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ThresholdCalculators/NormalDistributionCutPointsThresholdCalculator.cs	(revision 5735)
+++ /branches/DataAnalysis Refactoring/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ThresholdCalculators/NormalDistributionCutPointsThresholdCalculator.cs	(revision 5736)
@@ -88,15 +88,15 @@
       thresholdList.Sort();
       thresholdList.Insert(0, double.NegativeInfinity);
-      thresholdList.Add(double.PositiveInfinity);
 
       // determine class values for each partition separated by a threshold by calculating the density of all class distributions
       // all points in the partition are classified as the class with the maximal density in the parition
       List<double> classValuesList = new List<double>();
-      for (int i = 0; i < thresholdList.Count - 1; i++) {
+      for (int i = 0; i < thresholdList.Count; i++) {
         double m;
         if (double.IsNegativeInfinity(thresholdList[i])) {
           m = thresholdList[i + 1] - 1.0; // smaller than the smalles non-infinity threshold
-        } else if (double.IsPositiveInfinity(thresholdList[i + 1])) {
-          m = thresholdList[i] + 1.0; // larger than the largest non-infinity threshold
+        } else if (i == thresholdList.Count - 1) {
+          // last threshold
+          m = thresholdList[i] + 1.0; // larger than the last threshold
         } else {
           m = thresholdList[i] + (thresholdList[i + 1] - thresholdList[i]) / 2.0; // middle of partition
@@ -135,5 +135,4 @@
         }
       }
-      filteredThresholds.Add(double.PositiveInfinity);
       thresholds = filteredThresholds.ToArray();
       classValues = filteredClassValues.ToArray();
Index: /branches/DataAnalysis Refactoring/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Regression/RegressionSolution.cs
===================================================================
--- /branches/DataAnalysis Refactoring/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Regression/RegressionSolution.cs	(revision 5735)
+++ /branches/DataAnalysis Refactoring/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Regression/RegressionSolution.cs	(revision 5736)
@@ -111,5 +111,5 @@
     }
 
-    private void RecalculateResults() {
+    protected void RecalculateResults() {
       double[] estimatedTrainingValues = EstimatedTrainingValues.ToArray(); // cache values
       IEnumerable<double> originalTrainingValues = ProblemData.Dataset.GetEnumeratedVariableValues(ProblemData.TargetVariable, ProblemData.TrainingIndizes);
Index: /branches/DataAnalysis Refactoring/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Classification/IDiscriminantFunctionClassificationModel.cs
===================================================================
--- /branches/DataAnalysis Refactoring/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Classification/IDiscriminantFunctionClassificationModel.cs	(revision 5735)
+++ /branches/DataAnalysis Refactoring/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Classification/IDiscriminantFunctionClassificationModel.cs	(revision 5736)
@@ -24,6 +24,8 @@
 namespace HeuristicLab.Problems.DataAnalysis {
   public interface IDiscriminantFunctionClassificationModel : IClassificationModel {
-    IEnumerable<double> Thresholds { get; set; }
-    IEnumerable<double> ClassValues { get; set; }
+    IEnumerable<double> Thresholds { get; }
+    IEnumerable<double> ClassValues { get; }
+    // class values and thresholds can only be assigned simultaniously
+    void SetThresholdsAndClassValues(IEnumerable<double> thresholds, IEnumerable<double> classValues); 
     IEnumerable<double> GetEstimatedValues(Dataset dataset, IEnumerable<int> rows);
 
