Index: /branches/3040_VectorBasedGP/HeuristicLab.Algorithms.DataAnalysis/3.4/NonlinearRegression/NonlinearRegression.cs
===================================================================
--- /branches/3040_VectorBasedGP/HeuristicLab.Algorithms.DataAnalysis/3.4/NonlinearRegression/NonlinearRegression.cs	(revision 17471)
+++ /branches/3040_VectorBasedGP/HeuristicLab.Algorithms.DataAnalysis/3.4/NonlinearRegression/NonlinearRegression.cs	(revision 17472)
@@ -263,5 +263,5 @@
       }
 
-      if (!SymbolicRegressionConstantOptimizationEvaluator.CanOptimizeConstants(tree)) throw new ArgumentException("The optimizer does not support the specified model structure.");
+      if (!NonlinearLeastSquaresConstantOptimizationEvaluator.CanOptimizeConstants(tree)) throw new ArgumentException("The optimizer does not support the specified model structure.");
 
       // initialize constants randomly
@@ -275,7 +275,7 @@
       var interpreter = new SymbolicDataAnalysisExpressionTreeLinearInterpreter();
 
-      SymbolicRegressionConstantOptimizationEvaluator.OptimizeConstants(interpreter, tree, problemData, problemData.TrainingIndices,
+      tree = NonlinearLeastSquaresConstantOptimizationEvaluator.OptimizeTree(tree, problemData, problemData.TrainingIndices,
         applyLinearScaling: applyLinearScaling, maxIterations: maxIterations,
-        updateVariableWeights: false, updateConstantsInTree: true);
+        updateVariableWeights: false);
 
       var model = new SymbolicRegressionModel(problemData.TargetVariable, tree, (ISymbolicDataAnalysisExpressionTreeInterpreter)interpreter.Clone());
Index: /branches/3040_VectorBasedGP/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression.Views/3.4/InteractiveSymbolicRegressionSolutionSimplifierView.cs
===================================================================
--- /branches/3040_VectorBasedGP/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression.Views/3.4/InteractiveSymbolicRegressionSolutionSimplifierView.cs	(revision 17471)
+++ /branches/3040_VectorBasedGP/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression.Views/3.4/InteractiveSymbolicRegressionSolutionSimplifierView.cs	(revision 17472)
@@ -21,4 +21,5 @@
 
 using System;
+using System.Threading;
 using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
 using HeuristicLab.MainForm;
@@ -42,5 +43,5 @@
 
       var tree = Content?.Model?.SymbolicExpressionTree;
-      btnOptimizeConstants.Enabled = tree != null && SymbolicRegressionConstantOptimizationEvaluator.CanOptimizeConstants(tree);
+      btnOptimizeConstants.Enabled = tree != null && NonlinearLeastSquaresConstantOptimizationEvaluator.CanOptimizeConstants(tree);
     }
 
@@ -51,5 +52,5 @@
     }
 
-    protected override ISymbolicExpressionTree OptimizeConstants(ISymbolicExpressionTree tree, IProgress progress) {
+    protected override ISymbolicExpressionTree OptimizeConstants(ISymbolicExpressionTree tree, CancellationToken cancellationToken, IProgress progress) {
       const int constOptIterations = 50;
       const int maxRepetitions = 100;
@@ -64,10 +65,12 @@
       do {
         prevResult = result;
-        result = SymbolicRegressionConstantOptimizationEvaluator.OptimizeConstants(model.Interpreter, tree, regressionProblemData, regressionProblemData.TrainingIndices,
-          applyLinearScaling: true, maxIterations: constOptIterations, updateVariableWeights: true, lowerEstimationLimit: model.LowerEstimationLimit, upperEstimationLimit: model.UpperEstimationLimit,
-          iterationCallback: (args, func, obj) => {
+        tree = NonlinearLeastSquaresConstantOptimizationEvaluator.OptimizeTree(tree, regressionProblemData, regressionProblemData.TrainingIndices,
+          applyLinearScaling: true, maxIterations: constOptIterations, updateVariableWeights: true,
+          cancellationToken: cancellationToken, iterationCallback: (args, func, obj) => {
             double newProgressValue = progress.ProgressValue + (1.0 / (constOptIterations + 2) / maxRepetitions); // (constOptIterations + 2) iterations are reported
             progress.ProgressValue = Math.Min(newProgressValue, 1.0);
           });
+        result = SymbolicRegressionSingleObjectivePearsonRSquaredEvaluator.Calculate(model.Interpreter, tree,
+          model.LowerEstimationLimit, model.UpperEstimationLimit, regressionProblemData, regressionProblemData.TrainingIndices, applyLinearScaling: true);
         reps++;
         improvement = result - prevResult;
Index: /branches/3040_VectorBasedGP/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression-3.4.csproj
===================================================================
--- /branches/3040_VectorBasedGP/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression-3.4.csproj	(revision 17471)
+++ /branches/3040_VectorBasedGP/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression-3.4.csproj	(revision 17472)
@@ -126,4 +126,5 @@
     <Compile Include="Plugin.cs" />
     <Compile Include="SingleObjective\ConstantOptimizationAnalyzer.cs" />
+    <Compile Include="SingleObjective\Evaluators\NonlinearLeastSquaresConstantOptimizationEvaluator.cs" />
     <Compile Include="SingleObjective\Evaluators\SymbolicRegressionMeanRelativeErrorEvaluator.cs" />
     <Compile Include="SingleObjective\SymbolicRegressionSolutionsAnalyzer.cs" />
Index: /branches/3040_VectorBasedGP/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/MultiObjective/PearsonRSquaredAverageSimilarityEvaluator.cs
===================================================================
--- /branches/3040_VectorBasedGP/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/MultiObjective/PearsonRSquaredAverageSimilarityEvaluator.cs	(revision 17471)
+++ /branches/3040_VectorBasedGP/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/MultiObjective/PearsonRSquaredAverageSimilarityEvaluator.cs	(revision 17472)
@@ -77,5 +77,6 @@
 
       if (UseConstantOptimization) {
-        SymbolicRegressionConstantOptimizationEvaluator.OptimizeConstants(interpreter, solution, problemData, rows, applyLinearScaling, ConstantOptimizationIterations, updateVariableWeights: ConstantOptimizationUpdateVariableWeights, lowerEstimationLimit: estimationLimits.Lower, upperEstimationLimit: estimationLimits.Upper);
+        solution = NonlinearLeastSquaresConstantOptimizationEvaluator.OptimizeTree(solution, problemData, rows, applyLinearScaling, ConstantOptimizationIterations, ConstantOptimizationUpdateVariableWeights);
+        SymbolicExpressionTreeParameter.ActualValue = solution;
       }
 
Index: /branches/3040_VectorBasedGP/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/MultiObjective/PearsonRSquaredNestedTreeSizeEvaluator.cs
===================================================================
--- /branches/3040_VectorBasedGP/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/MultiObjective/PearsonRSquaredNestedTreeSizeEvaluator.cs	(revision 17471)
+++ /branches/3040_VectorBasedGP/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/MultiObjective/PearsonRSquaredNestedTreeSizeEvaluator.cs	(revision 17472)
@@ -55,5 +55,6 @@
 
       if (UseConstantOptimization) {
-        SymbolicRegressionConstantOptimizationEvaluator.OptimizeConstants(interpreter, solution, problemData, rows, applyLinearScaling, ConstantOptimizationIterations, updateVariableWeights: ConstantOptimizationUpdateVariableWeights,lowerEstimationLimit: estimationLimits.Lower, upperEstimationLimit: estimationLimits.Upper);
+        solution = NonlinearLeastSquaresConstantOptimizationEvaluator.OptimizeTree(solution, problemData, rows, applyLinearScaling, ConstantOptimizationIterations, ConstantOptimizationUpdateVariableWeights);
+        SymbolicExpressionTreeParameter.ActualValue = solution;
       }
 
@@ -76,5 +77,5 @@
       // DecimalPlaces parameter is a FixedValueParameter and doesn't need the context.
 
-      double[] quality = Calculate(SymbolicDataAnalysisTreeInterpreterParameter.ActualValue, tree, EstimationLimitsParameter.ActualValue.Lower, EstimationLimitsParameter.ActualValue.Upper, problemData, rows, ApplyLinearScalingParameter.ActualValue.Value, DecimalPlaces); 
+      double[] quality = Calculate(SymbolicDataAnalysisTreeInterpreterParameter.ActualValue, tree, EstimationLimitsParameter.ActualValue.Lower, EstimationLimitsParameter.ActualValue.Upper, problemData, rows, ApplyLinearScalingParameter.ActualValue.Value, DecimalPlaces);
 
       SymbolicDataAnalysisTreeInterpreterParameter.ExecutionContext = null;
Index: /branches/3040_VectorBasedGP/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/MultiObjective/PearsonRSquaredNumberOfVariablesEvaluator.cs
===================================================================
--- /branches/3040_VectorBasedGP/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/MultiObjective/PearsonRSquaredNumberOfVariablesEvaluator.cs	(revision 17471)
+++ /branches/3040_VectorBasedGP/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/MultiObjective/PearsonRSquaredNumberOfVariablesEvaluator.cs	(revision 17472)
@@ -55,5 +55,6 @@
 
       if (UseConstantOptimization) {
-        SymbolicRegressionConstantOptimizationEvaluator.OptimizeConstants(interpreter, solution, problemData, rows, applyLinearScaling, ConstantOptimizationIterations, updateVariableWeights: ConstantOptimizationUpdateVariableWeights, lowerEstimationLimit: estimationLimits.Lower, upperEstimationLimit: estimationLimits.Upper);
+        solution = NonlinearLeastSquaresConstantOptimizationEvaluator.OptimizeTree(solution, problemData, rows, applyLinearScaling, ConstantOptimizationIterations, ConstantOptimizationUpdateVariableWeights);
+        SymbolicExpressionTreeParameter.ActualValue = solution;
       }
       double[] qualities = Calculate(SymbolicDataAnalysisTreeInterpreterParameter.ActualValue, solution, EstimationLimitsParameter.ActualValue.Lower, EstimationLimitsParameter.ActualValue.Upper, ProblemDataParameter.ActualValue, rows, ApplyLinearScalingParameter.ActualValue.Value, DecimalPlaces);
Index: /branches/3040_VectorBasedGP/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/MultiObjective/PearsonRSquaredTreeComplexityEvaluator.cs
===================================================================
--- /branches/3040_VectorBasedGP/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/MultiObjective/PearsonRSquaredTreeComplexityEvaluator.cs	(revision 17471)
+++ /branches/3040_VectorBasedGP/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/MultiObjective/PearsonRSquaredTreeComplexityEvaluator.cs	(revision 17472)
@@ -54,5 +54,6 @@
 
       if (UseConstantOptimization) {
-        SymbolicRegressionConstantOptimizationEvaluator.OptimizeConstants(interpreter, solution, problemData, rows, applyLinearScaling, ConstantOptimizationIterations, updateVariableWeights: ConstantOptimizationUpdateVariableWeights, lowerEstimationLimit: estimationLimits.Lower, upperEstimationLimit: estimationLimits.Upper);
+        solution = NonlinearLeastSquaresConstantOptimizationEvaluator.OptimizeTree(solution, problemData, rows, applyLinearScaling, ConstantOptimizationIterations, ConstantOptimizationUpdateVariableWeights);
+        SymbolicExpressionTreeParameter.ActualValue = solution;
       }
       double[] qualities = Calculate(interpreter, solution, estimationLimits.Lower, estimationLimits.Upper, problemData, rows, applyLinearScaling, DecimalPlaces);
Index: /branches/3040_VectorBasedGP/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/MultiObjective/SymbolicRegressionMultiObjectiveMeanSquaredErrorTreeSizeEvaluator.cs
===================================================================
--- /branches/3040_VectorBasedGP/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/MultiObjective/SymbolicRegressionMultiObjectiveMeanSquaredErrorTreeSizeEvaluator.cs	(revision 17471)
+++ /branches/3040_VectorBasedGP/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/MultiObjective/SymbolicRegressionMultiObjectiveMeanSquaredErrorTreeSizeEvaluator.cs	(revision 17472)
@@ -54,5 +54,6 @@
 
       if (UseConstantOptimization) {
-        SymbolicRegressionConstantOptimizationEvaluator.OptimizeConstants(interpreter, solution, problemData, rows, applyLinearScaling, ConstantOptimizationIterations, updateVariableWeights: ConstantOptimizationUpdateVariableWeights, lowerEstimationLimit: estimationLimits.Lower, upperEstimationLimit: estimationLimits.Upper);
+        solution = NonlinearLeastSquaresConstantOptimizationEvaluator.OptimizeTree(solution, problemData, rows, applyLinearScaling, ConstantOptimizationIterations, ConstantOptimizationUpdateVariableWeights);
+        SymbolicExpressionTreeParameter.ActualValue = solution;
       }
 
Index: /branches/3040_VectorBasedGP/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/MultiObjective/SymbolicRegressionMultiObjectivePearsonRSquaredTreeSizeEvaluator.cs
===================================================================
--- /branches/3040_VectorBasedGP/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/MultiObjective/SymbolicRegressionMultiObjectivePearsonRSquaredTreeSizeEvaluator.cs	(revision 17471)
+++ /branches/3040_VectorBasedGP/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/MultiObjective/SymbolicRegressionMultiObjectivePearsonRSquaredTreeSizeEvaluator.cs	(revision 17472)
@@ -54,5 +54,6 @@
 
       if (UseConstantOptimization) {
-        SymbolicRegressionConstantOptimizationEvaluator.OptimizeConstants(interpreter, solution, problemData, rows, applyLinearScaling, ConstantOptimizationIterations, updateVariableWeights: ConstantOptimizationUpdateVariableWeights, lowerEstimationLimit: estimationLimits.Lower, upperEstimationLimit: estimationLimits.Upper);
+        solution = NonlinearLeastSquaresConstantOptimizationEvaluator.OptimizeTree(solution, problemData, rows, applyLinearScaling, ConstantOptimizationIterations, ConstantOptimizationUpdateVariableWeights);
+        SymbolicExpressionTreeParameter.ActualValue = solution;
       }
       double[] qualities = Calculate(SymbolicDataAnalysisTreeInterpreterParameter.ActualValue, solution, EstimationLimitsParameter.ActualValue.Lower, EstimationLimitsParameter.ActualValue.Upper, ProblemDataParameter.ActualValue, rows, ApplyLinearScalingParameter.ActualValue.Value, DecimalPlaces);
Index: /branches/3040_VectorBasedGP/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SingleObjective/ConstantOptimizationAnalyzer.cs
===================================================================
--- /branches/3040_VectorBasedGP/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SingleObjective/ConstantOptimizationAnalyzer.cs	(revision 17471)
+++ /branches/3040_VectorBasedGP/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SingleObjective/ConstantOptimizationAnalyzer.cs	(revision 17472)
@@ -93,5 +93,5 @@
       : base() {
       Parameters.Add(new FixedValueParameter<PercentValue>(PercentageOfBestSolutionsParameterName, "The percentage of the top solutions which should be analyzed.", new PercentValue(0.1)));
-      Parameters.Add(new FixedValueParameter<SymbolicRegressionConstantOptimizationEvaluator>(ConstantOptimizationEvaluatorParameterName, "The operator used to perform the constant optimization"));
+      Parameters.Add(new FixedValueParameter<NonlinearLeastSquaresConstantOptimizationEvaluator>(ConstantOptimizationEvaluatorParameterName, "The operator used to perform the constant optimization"));
 
       //Changed the ActualName of the EvaluationPartitionParameter so that it matches the parameter name of symbolic regression problems.
Index: /branches/3040_VectorBasedGP/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SingleObjective/Evaluators/NonlinearLeastSquaresConstantOptimizationEvaluator.cs
===================================================================
--- /branches/3040_VectorBasedGP/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SingleObjective/Evaluators/NonlinearLeastSquaresConstantOptimizationEvaluator.cs	(revision 17472)
+++ /branches/3040_VectorBasedGP/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SingleObjective/Evaluators/NonlinearLeastSquaresConstantOptimizationEvaluator.cs	(revision 17472)
@@ -0,0 +1,205 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+using HeuristicLab.Parameters;
+using HEAL.Attic;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic.Regression {
+  [StorableType("24B68851-036D-4446-BD6F-3823E9028FF4")]
+  [Item("NonlinearLeastSquaresOptimizer", "")]
+  public class NonlinearLeastSquaresConstantOptimizationEvaluator : SymbolicRegressionConstantOptimizationEvaluator {
+
+    private const string ConstantOptimizationIterationsName = "ConstantOptimizationIterations";
+
+    #region Parameter Properties
+    public IFixedValueParameter<IntValue> ConstantOptimizationIterationsParameter {
+      get { return (IFixedValueParameter<IntValue>)Parameters[ConstantOptimizationIterationsName]; }
+    }
+    #endregion
+
+    #region Properties
+    public int ConstantOptimizationIterations {
+      get { return ConstantOptimizationIterationsParameter.Value.Value; }
+    }
+    #endregion
+
+    public NonlinearLeastSquaresConstantOptimizationEvaluator()
+      : base() {
+      Parameters.Add(new FixedValueParameter<IntValue>(ConstantOptimizationIterationsName, "Determines how many iterations should be calculated while optimizing the constant of a symbolic expression tree(0 indicates other or default stopping criterion).", new IntValue(10)));
+    }
+
+    protected NonlinearLeastSquaresConstantOptimizationEvaluator(NonlinearLeastSquaresConstantOptimizationEvaluator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new NonlinearLeastSquaresConstantOptimizationEvaluator(this, cloner);
+    }
+    [StorableConstructor]
+    protected NonlinearLeastSquaresConstantOptimizationEvaluator(StorableConstructorFlag _) : base(_) { }
+
+    protected override ISymbolicExpressionTree OptimizeConstants(
+      ISymbolicExpressionTree tree, IRegressionProblemData problemData, IEnumerable<int> rows,
+      CancellationToken cancellationToken = default(CancellationToken), EvaluationsCounter counter = null) {
+      return OptimizeTree(tree,
+        problemData, rows,
+        ApplyLinearScalingParameter.ActualValue.Value, ConstantOptimizationIterations, UpdateVariableWeights,
+        cancellationToken, counter);
+    }
+
+    public static ISymbolicExpressionTree OptimizeTree(
+      ISymbolicExpressionTree tree,
+      IRegressionProblemData problemData, IEnumerable<int> rows,
+      bool applyLinearScaling, int maxIterations, bool updateVariableWeights,
+      CancellationToken cancellationToken = default(CancellationToken), EvaluationsCounter counter = null, Action<double[], double, object> iterationCallback = null) {
+
+      // numeric constants in the tree become variables for constant opt
+      // variables in the tree become parameters (fixed values) for constant opt
+      // for each parameter (variable in the original tree) we store the 
+      // variable name, variable value (for factor vars) and lag as a DataForVariable object.
+      // A dictionary is used to find parameters
+      bool success = TreeToAutoDiffTermConverter.TryConvertToAutoDiff(
+        tree, updateVariableWeights, applyLinearScaling,
+        out var parameters, out var initialConstants, out var func, out var func_grad);
+      if (!success)
+        throw new NotSupportedException("Could not optimize constants of symbolic expression tree due to not supported symbols used in the tree.");
+      if (parameters.Count == 0) return (ISymbolicExpressionTree)tree.Clone();
+      var parameterEntries = parameters.ToArray(); // order of entries must be the same for x
+
+      //extract initial constants
+      double[] c;
+      if (applyLinearScaling) {
+        c = new double[initialConstants.Length + 2];
+        c[0] = 0.0;
+        c[1] = 1.0;
+        Array.Copy(initialConstants, 0, c, 2, initialConstants.Length);
+      } else {
+        c = (double[])initialConstants.Clone();
+      }
+
+      IDataset ds = problemData.Dataset;
+      double[,] x = new double[rows.Count(), parameters.Count];
+      int row = 0;
+      foreach (var r in rows) {
+        int col = 0;
+        foreach (var info in parameterEntries) {
+          if (ds.VariableHasType<double>(info.variableName)) {
+            x[row, col] = ds.GetDoubleValue(info.variableName, r + info.lag);
+          } else if (ds.VariableHasType<string>(info.variableName)) {
+            x[row, col] = ds.GetStringValue(info.variableName, r) == info.variableValue ? 1 : 0;
+          } else throw new InvalidProgramException("found a variable of unknown type");
+          col++;
+        }
+        row++;
+      }
+      double[] y = ds.GetDoubleValues(problemData.TargetVariable, rows).ToArray();
+      int n = x.GetLength(0);
+      int m = x.GetLength(1);
+      int k = c.Length;
+
+      alglib.ndimensional_pfunc function_cx_1_func = CreatePFunc(func);
+      alglib.ndimensional_pgrad function_cx_1_grad = CreatePGrad(func_grad);
+      alglib.ndimensional_rep xrep = (p, f, obj) => {
+        iterationCallback?.Invoke(p, f, obj);
+        cancellationToken.ThrowIfCancellationRequested();
+      };
+      var rowEvaluationsCounter = new EvaluationsCounter();
+
+      try {
+        alglib.lsfitcreatefg(x, y, c, n, m, k, false, out var state);
+        alglib.lsfitsetcond(state, 0.0, 0.0, maxIterations);
+        alglib.lsfitsetxrep(state, iterationCallback != null || cancellationToken != default(CancellationToken));
+        //alglib.lsfitsetgradientcheck(state, 0.001);
+        alglib.lsfitfit(state, function_cx_1_func, function_cx_1_grad, xrep, rowEvaluationsCounter);
+        alglib.lsfitresults(state, out var retVal, out c, out alglib.lsfitreport rep);
+
+        //retVal == -7  => constant optimization failed due to wrong gradient
+        if (retVal == -1)
+          return (ISymbolicExpressionTree)tree.Clone();
+      } catch (ArithmeticException) {
+        return (ISymbolicExpressionTree)tree.Clone();
+      } catch (alglib.alglibexception) {
+        return (ISymbolicExpressionTree)tree.Clone();
+      }
+
+      if (counter != null) {
+        counter.FunctionEvaluations += rowEvaluationsCounter.FunctionEvaluations / n;
+        counter.GradientEvaluations += rowEvaluationsCounter.GradientEvaluations / n;
+      }
+
+      var newTree = (ISymbolicExpressionTree)tree.Clone();
+      if (applyLinearScaling) {
+        var tmp = new double[c.Length - 2];
+        Array.Copy(c, 2, tmp, 0, tmp.Length);
+        UpdateConstants(newTree, tmp, updateVariableWeights);
+      } else
+        UpdateConstants(newTree, c, updateVariableWeights);
+
+      return newTree;
+    }
+
+    private static void UpdateConstants(ISymbolicExpressionTree tree, double[] constants, bool updateVariableWeights) {
+      int i = 0;
+      foreach (var node in tree.Root.IterateNodesPrefix().OfType<SymbolicExpressionTreeTerminalNode>()) {
+        ConstantTreeNode constantTreeNode = node as ConstantTreeNode;
+        VariableTreeNodeBase variableTreeNodeBase = node as VariableTreeNodeBase;
+        FactorVariableTreeNode factorVarTreeNode = node as FactorVariableTreeNode;
+        if (constantTreeNode != null)
+          constantTreeNode.Value = constants[i++];
+        else if (updateVariableWeights && variableTreeNodeBase != null)
+          variableTreeNodeBase.Weight = constants[i++];
+        else if (factorVarTreeNode != null) {
+          for (int j = 0; j < factorVarTreeNode.Weights.Length; j++)
+            factorVarTreeNode.Weights[j] = constants[i++];
+        }
+      }
+    }
+
+    private static alglib.ndimensional_pfunc CreatePFunc(TreeToAutoDiffTermConverter.ParametricFunction func) {
+      return (double[] c, double[] x, ref double fx, object o) => {
+        fx = func(c, x);
+        var counter = (EvaluationsCounter)o;
+        counter.FunctionEvaluations++;
+      };
+    }
+
+    private static alglib.ndimensional_pgrad CreatePGrad(TreeToAutoDiffTermConverter.ParametricFunctionGradient func_grad) {
+      return (double[] c, double[] x, ref double fx, double[] grad, object o) => {
+        var tuple = func_grad(c, x);
+        fx = tuple.Item2;
+        Array.Copy(tuple.Item1, grad, grad.Length);
+        var counter = (EvaluationsCounter)o;
+        counter.GradientEvaluations++;
+      };
+    }
+
+    public static bool CanOptimizeConstants(ISymbolicExpressionTree tree) {
+      return TreeToAutoDiffTermConverter.IsCompatible(tree);
+    }
+  }
+}
Index: /branches/3040_VectorBasedGP/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SingleObjective/Evaluators/SymbolicRegressionConstantOptimizationEvaluator.cs
===================================================================
--- /branches/3040_VectorBasedGP/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SingleObjective/Evaluators/SymbolicRegressionConstantOptimizationEvaluator.cs	(revision 17471)
+++ /branches/3040_VectorBasedGP/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SingleObjective/Evaluators/SymbolicRegressionConstantOptimizationEvaluator.cs	(revision 17472)
@@ -20,7 +20,6 @@
 #endregion
 
-using System;
 using System.Collections.Generic;
-using System.Linq;
+using System.Threading;
 using HEAL.Attic;
 using HeuristicLab.Common;
@@ -33,7 +32,6 @@
 namespace HeuristicLab.Problems.DataAnalysis.Symbolic.Regression {
   [Item("Constant Optimization Evaluator", "Calculates Pearson R² of a symbolic regression solution and optimizes the constant used.")]
-  [StorableType("24B68851-036D-4446-BD6F-3823E9028FF4")]
-  public class SymbolicRegressionConstantOptimizationEvaluator : SymbolicRegressionSingleObjectiveEvaluator {
-    private const string ConstantOptimizationIterationsParameterName = "ConstantOptimizationIterations";
+  [StorableType("9F3A528C-DF9B-4D8F-8611-314E169A3B34")]
+  public abstract class SymbolicRegressionConstantOptimizationEvaluator : SymbolicRegressionSingleObjectiveEvaluator {
     private const string ConstantOptimizationImprovementParameterName = "ConstantOptimizationImprovement";
     private const string ConstantOptimizationProbabilityParameterName = "ConstantOptimizationProbability";
@@ -46,7 +44,5 @@
     private const string CountEvaluationsParameterName = "Count Function and Gradient Evaluations";
 
-    public IFixedValueParameter<IntValue> ConstantOptimizationIterationsParameter {
-      get { return (IFixedValueParameter<IntValue>)Parameters[ConstantOptimizationIterationsParameterName]; }
-    }
+
     public IFixedValueParameter<DoubleValue> ConstantOptimizationImprovementParameter {
       get { return (IFixedValueParameter<DoubleValue>)Parameters[ConstantOptimizationImprovementParameterName]; }
@@ -76,7 +72,4 @@
 
 
-    public IntValue ConstantOptimizationIterations {
-      get { return ConstantOptimizationIterationsParameter.Value; }
-    }
     public DoubleValue ConstantOptimizationImprovement {
       get { return ConstantOptimizationImprovementParameter.Value; }
@@ -112,7 +105,6 @@
       : base(original, cloner) {
     }
-    public SymbolicRegressionConstantOptimizationEvaluator()
+    protected SymbolicRegressionConstantOptimizationEvaluator()
       : base() {
-      Parameters.Add(new FixedValueParameter<IntValue>(ConstantOptimizationIterationsParameterName, "Determines how many iterations should be calculated while optimizing the constant of a symbolic expression tree (0 indicates other or default stopping criterion).", new IntValue(10)));
       Parameters.Add(new FixedValueParameter<DoubleValue>(ConstantOptimizationImprovementParameterName, "Determines the relative improvement which must be achieved in the constant optimization to continue with it (0 indicates other or default stopping criterion).", new DoubleValue(0)) { Hidden = true });
       Parameters.Add(new FixedValueParameter<PercentValue>(ConstantOptimizationProbabilityParameterName, "Determines the probability that the constants are optimized", new PercentValue(1)));
@@ -124,8 +116,4 @@
       Parameters.Add(new ResultParameter<IntValue>(FunctionEvaluationsResultParameterName, "The number of function evaluations performed by the constants optimization evaluator", "Results", new IntValue()));
       Parameters.Add(new ResultParameter<IntValue>(GradientEvaluationsResultParameterName, "The number of gradient evaluations performed by the constants optimization evaluator", "Results", new IntValue()));
-    }
-
-    public override IDeepCloneable Clone(Cloner cloner) {
-      return new SymbolicRegressionConstantOptimizationEvaluator(this, cloner);
     }
 
@@ -148,17 +136,28 @@
     private static readonly object locker = new object();
     public override IOperation InstrumentedApply() {
+      var originalTree = SymbolicExpressionTreeParameter.ActualValue;
       var solution = SymbolicExpressionTreeParameter.ActualValue;
-      double quality;
+      var problemData = ProblemDataParameter.ActualValue;
+
       if (RandomParameter.ActualValue.NextDouble() < ConstantOptimizationProbability.Value) {
         IEnumerable<int> constantOptimizationRows = GenerateRowsToEvaluate(ConstantOptimizationRowsPercentage.Value);
-        var counter = new EvaluationsCounter();
-        quality = OptimizeConstants(SymbolicDataAnalysisTreeInterpreterParameter.ActualValue, solution, ProblemDataParameter.ActualValue,
-           constantOptimizationRows, ApplyLinearScalingParameter.ActualValue.Value, ConstantOptimizationIterations.Value, updateVariableWeights: UpdateVariableWeights, lowerEstimationLimit: EstimationLimitsParameter.ActualValue.Lower, upperEstimationLimit: EstimationLimitsParameter.ActualValue.Upper, updateConstantsInTree: UpdateConstantsInTree, counter: counter);
+        EvaluationsCounter counter = null;
+        if (CountEvaluations) counter = new EvaluationsCounter();
+
+        var optimizedTree = OptimizeConstants(originalTree, problemData, constantOptimizationRows, counter: counter);
+
+        double quality = SymbolicRegressionSingleObjectivePearsonRSquaredEvaluator.Calculate(
+          SymbolicDataAnalysisTreeInterpreterParameter.ActualValue, optimizedTree,
+          EstimationLimitsParameter.ActualValue.Lower, EstimationLimitsParameter.ActualValue.Upper, ProblemDataParameter.ActualValue, constantOptimizationRows, ApplyLinearScalingParameter.ActualValue.Value);
 
         if (ConstantOptimizationRowsPercentage.Value != RelativeNumberOfEvaluatedSamplesParameter.ActualValue.Value) {
           var evaluationRows = GenerateRowsToEvaluate();
-          quality = SymbolicRegressionSingleObjectivePearsonRSquaredEvaluator.Calculate(SymbolicDataAnalysisTreeInterpreterParameter.ActualValue, solution, EstimationLimitsParameter.ActualValue.Lower, EstimationLimitsParameter.ActualValue.Upper, ProblemDataParameter.ActualValue, evaluationRows, ApplyLinearScalingParameter.ActualValue.Value);
+          quality = SymbolicRegressionSingleObjectivePearsonRSquaredEvaluator.Calculate(
+            SymbolicDataAnalysisTreeInterpreterParameter.ActualValue, solution,
+            EstimationLimitsParameter.ActualValue.Lower, EstimationLimitsParameter.ActualValue.Upper, ProblemDataParameter.ActualValue, evaluationRows, ApplyLinearScalingParameter.ActualValue.Value);
         }
 
+        SymbolicExpressionTreeParameter.ActualValue = optimizedTree;
+        QualityParameter.ActualValue = new DoubleValue(quality);
         if (CountEvaluations) {
           lock (locker) {
@@ -170,7 +169,9 @@
       } else {
         var evaluationRows = GenerateRowsToEvaluate();
-        quality = SymbolicRegressionSingleObjectivePearsonRSquaredEvaluator.Calculate(SymbolicDataAnalysisTreeInterpreterParameter.ActualValue, solution, EstimationLimitsParameter.ActualValue.Lower, EstimationLimitsParameter.ActualValue.Upper, ProblemDataParameter.ActualValue, evaluationRows, ApplyLinearScalingParameter.ActualValue.Value);
+        double quality = SymbolicRegressionSingleObjectivePearsonRSquaredEvaluator.Calculate(
+          SymbolicDataAnalysisTreeInterpreterParameter.ActualValue, solution,
+          EstimationLimitsParameter.ActualValue.Lower, EstimationLimitsParameter.ActualValue.Upper, ProblemDataParameter.ActualValue, evaluationRows, ApplyLinearScalingParameter.ActualValue.Value);
+        QualityParameter.ActualValue = new DoubleValue(quality);
       }
-      QualityParameter.ActualValue = new DoubleValue(quality);
 
       return base.InstrumentedApply();
@@ -198,146 +199,12 @@
     }
 
+    protected abstract ISymbolicExpressionTree OptimizeConstants(
+      ISymbolicExpressionTree tree, IRegressionProblemData problemData, IEnumerable<int> rows,
+      CancellationToken cancellationToken = default(CancellationToken), EvaluationsCounter counter = null);
+
     public class EvaluationsCounter {
       public int FunctionEvaluations = 0;
       public int GradientEvaluations = 0;
     }
-
-    public static double OptimizeConstants(ISymbolicDataAnalysisExpressionTreeInterpreter interpreter,
-      ISymbolicExpressionTree tree, IRegressionProblemData problemData, IEnumerable<int> rows, bool applyLinearScaling,
-      int maxIterations, bool updateVariableWeights = true,
-      double lowerEstimationLimit = double.MinValue, double upperEstimationLimit = double.MaxValue,
-      bool updateConstantsInTree = true, Action<double[], double, object> iterationCallback = null, EvaluationsCounter counter = null) {
-
-      // numeric constants in the tree become variables for constant opt
-      // variables in the tree become parameters (fixed values) for constant opt
-      // for each parameter (variable in the original tree) we store the 
-      // variable name, variable value (for factor vars) and lag as a DataForVariable object.
-      // A dictionary is used to find parameters
-      double[] initialConstants;
-      var parameters = new List<TreeToAutoDiffTermConverter.DataForVariable>();
-
-      TreeToAutoDiffTermConverter.ParametricFunction func;
-      TreeToAutoDiffTermConverter.ParametricFunctionGradient func_grad;
-      if (!TreeToAutoDiffTermConverter.TryConvertToAutoDiff(tree, updateVariableWeights, applyLinearScaling, out parameters, out initialConstants, out func, out func_grad))
-        throw new NotSupportedException("Could not optimize constants of symbolic expression tree due to not supported symbols used in the tree.");
-      if (parameters.Count == 0) return 0.0; // gkronber: constant expressions always have a R² of 0.0 
-      var parameterEntries = parameters.ToArray(); // order of entries must be the same for x
-
-      //extract inital constants
-      double[] c;
-      if (applyLinearScaling) {
-        c = new double[initialConstants.Length + 2];
-        c[0] = 0.0;
-        c[1] = 1.0;
-        Array.Copy(initialConstants, 0, c, 2, initialConstants.Length);
-      } else {
-        c = (double[])initialConstants.Clone();
-      }
-
-      double originalQuality = SymbolicRegressionSingleObjectivePearsonRSquaredEvaluator.Calculate(interpreter, tree, lowerEstimationLimit, upperEstimationLimit, problemData, rows, applyLinearScaling);
-
-      if (counter == null) counter = new EvaluationsCounter();
-      var rowEvaluationsCounter = new EvaluationsCounter();
-
-      alglib.lsfitstate state;
-      alglib.lsfitreport rep;
-      int retVal;
-
-      IDataset ds = problemData.Dataset;
-      double[,] x = new double[rows.Count(), parameters.Count];
-      int row = 0;
-      foreach (var r in rows) {
-        int col = 0;
-        foreach (var info in parameterEntries) {
-          if (ds.VariableHasType<double>(info.variableName)) {
-            x[row, col] = ds.GetDoubleValue(info.variableName, r + info.lag);
-          } else if (ds.VariableHasType<string>(info.variableName)) {
-            x[row, col] = ds.GetStringValue(info.variableName, r) == info.variableValue ? 1 : 0;
-          } else throw new InvalidProgramException("found a variable of unknown type");
-          col++;
-        }
-        row++;
-      }
-      double[] y = ds.GetDoubleValues(problemData.TargetVariable, rows).ToArray();
-      int n = x.GetLength(0);
-      int m = x.GetLength(1);
-      int k = c.Length;
-
-      alglib.ndimensional_pfunc function_cx_1_func = CreatePFunc(func);
-      alglib.ndimensional_pgrad function_cx_1_grad = CreatePGrad(func_grad);
-      alglib.ndimensional_rep xrep = (p, f, obj) => iterationCallback(p, f, obj);
-
-      try {
-        alglib.lsfitcreatefg(x, y, c, n, m, k, false, out state);
-        alglib.lsfitsetcond(state, 0.0, 0.0, maxIterations);
-        alglib.lsfitsetxrep(state, iterationCallback != null);
-        //alglib.lsfitsetgradientcheck(state, 0.001);
-        alglib.lsfitfit(state, function_cx_1_func, function_cx_1_grad, xrep, rowEvaluationsCounter);
-        alglib.lsfitresults(state, out retVal, out c, out rep);
-      } catch (ArithmeticException) {
-        return originalQuality;
-      } catch (alglib.alglibexception) {
-        return originalQuality;
-      }
-
-      counter.FunctionEvaluations += rowEvaluationsCounter.FunctionEvaluations / n;
-      counter.GradientEvaluations += rowEvaluationsCounter.GradientEvaluations / n;
-
-      //retVal == -7  => constant optimization failed due to wrong gradient
-      if (retVal != -7) {
-        if (applyLinearScaling) {
-          var tmp = new double[c.Length - 2];
-          Array.Copy(c, 2, tmp, 0, tmp.Length);
-          UpdateConstants(tree, tmp, updateVariableWeights);
-        } else UpdateConstants(tree, c, updateVariableWeights);
-      }
-      var quality = SymbolicRegressionSingleObjectivePearsonRSquaredEvaluator.Calculate(interpreter, tree, lowerEstimationLimit, upperEstimationLimit, problemData, rows, applyLinearScaling);
-
-      if (!updateConstantsInTree) UpdateConstants(tree, initialConstants, updateVariableWeights);
-
-      if (originalQuality - quality > 0.001 || double.IsNaN(quality)) {
-        UpdateConstants(tree, initialConstants, updateVariableWeights);
-        return originalQuality;
-      }
-      return quality;
-    }
-
-    private static void UpdateConstants(ISymbolicExpressionTree tree, double[] constants, bool updateVariableWeights) {
-      int i = 0;
-      foreach (var node in tree.Root.IterateNodesPrefix().OfType<SymbolicExpressionTreeTerminalNode>()) {
-        ConstantTreeNode constantTreeNode = node as ConstantTreeNode;
-        VariableTreeNodeBase variableTreeNodeBase = node as VariableTreeNodeBase;
-        FactorVariableTreeNode factorVarTreeNode = node as FactorVariableTreeNode;
-        if (constantTreeNode != null)
-          constantTreeNode.Value = constants[i++];
-        else if (updateVariableWeights && variableTreeNodeBase != null)
-          variableTreeNodeBase.Weight = constants[i++];
-        else if (factorVarTreeNode != null) {
-          for (int j = 0; j < factorVarTreeNode.Weights.Length; j++)
-            factorVarTreeNode.Weights[j] = constants[i++];
-        }
-      }
-    }
-
-    private static alglib.ndimensional_pfunc CreatePFunc(TreeToAutoDiffTermConverter.ParametricFunction func) {
-      return (double[] c, double[] x, ref double fx, object o) => {
-        fx = func(c, x);
-        var counter = (EvaluationsCounter)o;
-        counter.FunctionEvaluations++;
-      };
-    }
-
-    private static alglib.ndimensional_pgrad CreatePGrad(TreeToAutoDiffTermConverter.ParametricFunctionGradient func_grad) {
-      return (double[] c, double[] x, ref double fx, double[] grad, object o) => {
-        var tuple = func_grad(c, x);
-        fx = tuple.Item2;
-        Array.Copy(tuple.Item1, grad, grad.Length);
-        var counter = (EvaluationsCounter)o;
-        counter.GradientEvaluations++;
-      };
-    }
-    public static bool CanOptimizeConstants(ISymbolicExpressionTree tree) {
-      return TreeToAutoDiffTermConverter.IsCompatible(tree);
-    }
   }
 }
Index: /branches/3040_VectorBasedGP/HeuristicLab.Problems.DataAnalysis.Symbolic.Views/3.4/InteractiveSymbolicDataAnalysisSolutionSimplifierView.cs
===================================================================
--- /branches/3040_VectorBasedGP/HeuristicLab.Problems.DataAnalysis.Symbolic.Views/3.4/InteractiveSymbolicDataAnalysisSolutionSimplifierView.cs	(revision 17471)
+++ /branches/3040_VectorBasedGP/HeuristicLab.Problems.DataAnalysis.Symbolic.Views/3.4/InteractiveSymbolicDataAnalysisSolutionSimplifierView.cs	(revision 17472)
@@ -230,5 +230,5 @@
     protected abstract void UpdateModel(ISymbolicExpressionTree tree);
 
-    protected virtual ISymbolicExpressionTree OptimizeConstants(ISymbolicExpressionTree tree, IProgress progress) {
+    protected virtual ISymbolicExpressionTree OptimizeConstants(ISymbolicExpressionTree tree, CancellationToken cancellationToken, IProgress progress) {
       return tree;
     }
@@ -325,5 +325,5 @@
         var tree = (ISymbolicExpressionTree)Content.Model.SymbolicExpressionTree.Clone();
 
-        var newTree = await Task.Run(() => OptimizeConstants(tree, progress));
+        var newTree = await Task.Run(() => OptimizeConstants(tree, cancellationTokenSource.Token, progress), cancellationTokenSource.Token);
         try {
           await Task.Delay(300, cancellationTokenSource.Token); // wait for progressbar to finish animation
