Index: stable/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SingleObjective/Evaluators/SymbolicRegressionConstantOptimizationEvaluator.cs
===================================================================
--- stable/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SingleObjective/Evaluators/SymbolicRegressionConstantOptimizationEvaluator.cs	(revision 15514)
+++ stable/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SingleObjective/Evaluators/SymbolicRegressionConstantOptimizationEvaluator.cs	(revision 15515)
@@ -27,4 +27,5 @@
 using HeuristicLab.Data;
 using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+using HeuristicLab.Optimization;
 using HeuristicLab.Parameters;
 using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
@@ -41,4 +42,8 @@
     private const string UpdateVariableWeightsParameterName = "Update Variable Weights";
 
+    private const string FunctionEvaluationsResultParameterName = "Constants Optimization Function Evaluations";
+    private const string GradientEvaluationsResultParameterName = "Constants Optimization Gradient Evaluations";
+    private const string CountEvaluationsParameterName = "Count Function and Gradient Evaluations";
+
     public IFixedValueParameter<IntValue> ConstantOptimizationIterationsParameter {
       get { return (IFixedValueParameter<IntValue>)Parameters[ConstantOptimizationIterationsParameterName]; }
@@ -58,4 +63,14 @@
     public IFixedValueParameter<BoolValue> UpdateVariableWeightsParameter {
       get { return (IFixedValueParameter<BoolValue>)Parameters[UpdateVariableWeightsParameterName]; }
+    }
+
+    public IResultParameter<IntValue> FunctionEvaluationsResultParameter {
+      get { return (IResultParameter<IntValue>)Parameters[FunctionEvaluationsResultParameterName]; }
+    }
+    public IResultParameter<IntValue> GradientEvaluationsResultParameter {
+      get { return (IResultParameter<IntValue>)Parameters[GradientEvaluationsResultParameterName]; }
+    }
+    public IFixedValueParameter<BoolValue> CountEvaluationsParameter {
+      get { return (IFixedValueParameter<BoolValue>)Parameters[CountEvaluationsParameterName]; }
     }
 
@@ -81,4 +96,9 @@
       get { return UpdateVariableWeightsParameter.Value.Value; }
       set { UpdateVariableWeightsParameter.Value.Value = value; }
+    }
+
+    public bool CountEvaluations {
+      get { return CountEvaluationsParameter.Value.Value; }
+      set { CountEvaluationsParameter.Value.Value = value; }
     }
 
@@ -100,4 +120,8 @@
       Parameters.Add(new FixedValueParameter<BoolValue>(UpdateConstantsInTreeParameterName, "Determines if the constants in the tree should be overwritten by the optimized constants.", new BoolValue(true)) { Hidden = true });
       Parameters.Add(new FixedValueParameter<BoolValue>(UpdateVariableWeightsParameterName, "Determines if the variable weights in the tree should be  optimized.", new BoolValue(true)) { Hidden = true });
+
+      Parameters.Add(new FixedValueParameter<BoolValue>(CountEvaluationsParameterName, "Determines if function and gradient evaluation should be counted.", new BoolValue(false)));
+      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()));
     }
 
@@ -112,6 +136,17 @@
       if (!Parameters.ContainsKey(UpdateVariableWeightsParameterName))
         Parameters.Add(new FixedValueParameter<BoolValue>(UpdateVariableWeightsParameterName, "Determines if the variable weights in the tree should be  optimized.", new BoolValue(true)));
-    }
-
+
+      if (!Parameters.ContainsKey(CountEvaluationsParameterName))
+        Parameters.Add(new FixedValueParameter<BoolValue>(CountEvaluationsParameterName, "Determines if function and gradient evaluation should be counted.", new BoolValue(false)));
+      if (Parameters.ContainsKey(FunctionEvaluationsResultParameterName) && Parameters.ContainsKey(GradientEvaluationsResultParameterName))
+        CountEvaluations = true;
+
+      if (!Parameters.ContainsKey(FunctionEvaluationsResultParameterName))
+        Parameters.Add(new ResultParameter<IntValue>(FunctionEvaluationsResultParameterName, "The number of function evaluations performed by the constants optimization evaluator", "Results", new IntValue()));
+      if (!Parameters.ContainsKey(GradientEvaluationsResultParameterName))
+        Parameters.Add(new ResultParameter<IntValue>(GradientEvaluationsResultParameterName, "The number of gradient evaluations performed by the constants optimization evaluator", "Results", new IntValue()));
+    }
+
+    private static readonly object locker = new object();
     public override IOperation InstrumentedApply() {
       var solution = SymbolicExpressionTreeParameter.ActualValue;
@@ -119,6 +154,7 @@
       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);
+           constantOptimizationRows, ApplyLinearScalingParameter.ActualValue.Value, ConstantOptimizationIterations.Value, updateVariableWeights: UpdateVariableWeights, lowerEstimationLimit: EstimationLimitsParameter.ActualValue.Lower, upperEstimationLimit: EstimationLimitsParameter.ActualValue.Upper, updateConstantsInTree: UpdateConstantsInTree, counter: counter);
 
         if (ConstantOptimizationRowsPercentage.Value != RelativeNumberOfEvaluatedSamplesParameter.ActualValue.Value) {
@@ -126,4 +162,12 @@
           quality = SymbolicRegressionSingleObjectivePearsonRSquaredEvaluator.Calculate(SymbolicDataAnalysisTreeInterpreterParameter.ActualValue, solution, EstimationLimitsParameter.ActualValue.Lower, EstimationLimitsParameter.ActualValue.Upper, ProblemDataParameter.ActualValue, evaluationRows, ApplyLinearScalingParameter.ActualValue.Value);
         }
+
+        if (CountEvaluations) {
+          lock (locker) {
+            FunctionEvaluationsResultParameter.ActualValue.Value += counter.FunctionEvaluations;
+            GradientEvaluationsResultParameter.ActualValue.Value += counter.GradientEvaluations;
+          }
+        }
+
       } else {
         var evaluationRows = GenerateRowsToEvaluate();
@@ -139,4 +183,6 @@
       EstimationLimitsParameter.ExecutionContext = context;
       ApplyLinearScalingParameter.ExecutionContext = context;
+      FunctionEvaluationsResultParameter.ExecutionContext = context;
+      GradientEvaluationsResultParameter.ExecutionContext = context;
 
       // Pearson R² evaluator is used on purpose instead of the const-opt evaluator, 
@@ -148,6 +194,13 @@
       EstimationLimitsParameter.ExecutionContext = null;
       ApplyLinearScalingParameter.ExecutionContext = null;
+      FunctionEvaluationsResultParameter.ExecutionContext = null;
+      GradientEvaluationsResultParameter.ExecutionContext = null;
 
       return r2;
+    }
+
+    public class EvaluationsCounter {
+      public int FunctionEvaluations = 0;
+      public int GradientEvaluations = 0;
     }
 
@@ -156,5 +209,5 @@
       int maxIterations, bool updateVariableWeights = true,
       double lowerEstimationLimit = double.MinValue, double upperEstimationLimit = double.MaxValue,
-      bool updateConstantsInTree = true, Action<double[], double, object> iterationCallback = null) {
+      bool updateConstantsInTree = true, Action<double[], double, object> iterationCallback = null, EvaluationsCounter counter = null) {
 
       // numeric constants in the tree become variables for constant opt
@@ -168,19 +221,24 @@
       TreeToAutoDiffTermConverter.ParametricFunction func;
       TreeToAutoDiffTermConverter.ParametricFunctionGradient func_grad;
-      if (!TreeToAutoDiffTermConverter.TryConvertToAutoDiff(tree, updateVariableWeights, out parameters, out initialConstants, out func, out 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 = new double[initialConstants.Length + 2];
-      {
+      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);
-      }
-      double[] originalConstants = (double[])c.Clone();
+      } 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;
@@ -217,21 +275,29 @@
         alglib.lsfitsetxrep(state, iterationCallback != null);
         //alglib.lsfitsetgradientcheck(state, 0.001);
-        alglib.lsfitfit(state, function_cx_1_func, function_cx_1_grad, xrep, null);
+        alglib.lsfitfit(state, function_cx_1_func, function_cx_1_grad, xrep, rowEvaluationsCounter);
         alglib.lsfitresults(state, out retVal, out c, out rep);
-      }
-      catch (ArithmeticException) {
+      } catch (ArithmeticException) {
         return originalQuality;
-      }
-      catch (alglib.alglibexception) {
+      } 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) UpdateConstants(tree, c.Skip(2).ToArray(), updateVariableWeights);
+      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, originalConstants.Skip(2).ToArray(), updateVariableWeights);
+      if (!updateConstantsInTree) UpdateConstants(tree, initialConstants, updateVariableWeights);
+
       if (originalQuality - quality > 0.001 || double.IsNaN(quality)) {
-        UpdateConstants(tree, originalConstants.Skip(2).ToArray(), updateVariableWeights);
+        UpdateConstants(tree, initialConstants, updateVariableWeights);
         return originalQuality;
       }
@@ -259,4 +325,6 @@
       return (double[] c, double[] x, ref double fx, object o) => {
         fx = func(c, x);
+        var counter = (EvaluationsCounter)o;
+        counter.FunctionEvaluations++;
       };
     }
@@ -264,7 +332,9 @@
     private static alglib.ndimensional_pgrad CreatePGrad(TreeToAutoDiffTermConverter.ParametricFunctionGradient func_grad) {
       return (double[] c, double[] x, ref double fx, double[] grad, object o) => {
-        var tupel = func_grad(c, x);
-        fx = tupel.Item2;
-        Array.Copy(tupel.Item1, grad, grad.Length);
+        var tuple = func_grad(c, x);
+        fx = tuple.Item2;
+        Array.Copy(tuple.Item1, grad, grad.Length);
+        var counter = (EvaluationsCounter)o;
+        counter.GradientEvaluations++;
       };
     }
Index: stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Converters/TreeToAutoDiffTermConverter.cs
===================================================================
--- stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Converters/TreeToAutoDiffTermConverter.cs	(revision 15514)
+++ stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Converters/TreeToAutoDiffTermConverter.cs	(revision 15515)
@@ -87,5 +87,5 @@
     #endregion
 
-    public static bool TryConvertToAutoDiff(ISymbolicExpressionTree tree, bool makeVariableWeightsVariable,
+    public static bool TryConvertToAutoDiff(ISymbolicExpressionTree tree, bool makeVariableWeightsVariable, bool addLinearScalingTerms,
       out List<DataForVariable> parameters, out double[] initialConstants,
       out ParametricFunction func,
@@ -93,5 +93,5 @@
 
       // use a transformator object which holds the state (variable list, parameter list, ...) for recursive transformation of the tree
-      var transformator = new TreeToAutoDiffTermConverter(makeVariableWeightsVariable);
+      var transformator = new TreeToAutoDiffTermConverter(makeVariableWeightsVariable, addLinearScalingTerms);
       AutoDiff.Term term;
       try {
@@ -120,7 +120,9 @@
     private readonly List<AutoDiff.Variable> variables;
     private readonly bool makeVariableWeightsVariable;
-
-    private TreeToAutoDiffTermConverter(bool makeVariableWeightsVariable) {
+    private readonly bool addLinearScalingTerms;
+
+    private TreeToAutoDiffTermConverter(bool makeVariableWeightsVariable, bool addLinearScalingTerms) {
       this.makeVariableWeightsVariable = makeVariableWeightsVariable;
+      this.addLinearScalingTerms = addLinearScalingTerms;
       this.initialConstants = new List<double>();
       this.parameters = new Dictionary<DataForVariable, AutoDiff.Variable>();
@@ -248,9 +250,13 @@
       }
       if (node.Symbol is StartSymbol) {
-        var alpha = new AutoDiff.Variable();
-        var beta = new AutoDiff.Variable();
-        variables.Add(beta);
-        variables.Add(alpha);
-        return ConvertToAutoDiff(node.GetSubtree(0)) * alpha + beta;
+        if (addLinearScalingTerms) {
+          // scaling variables α, β are given at the beginning of the parameter vector
+          var alpha = new AutoDiff.Variable();
+          var beta = new AutoDiff.Variable();
+          variables.Add(beta);
+          variables.Add(alpha);
+          var t = ConvertToAutoDiff(node.GetSubtree(0));
+          return t * alpha + beta;
+        } else return ConvertToAutoDiff(node.GetSubtree(0));
       }
       throw new ConversionException();
