Index: branches/2994-AutoDiffForIntervals/HeuristicLab.Algorithms.DataAnalysis.ConstrainedNonlinearRegression/3.4/ConstrainedNonlinearRegression.cs
===================================================================
--- branches/2994-AutoDiffForIntervals/HeuristicLab.Algorithms.DataAnalysis.ConstrainedNonlinearRegression/3.4/ConstrainedNonlinearRegression.cs	(revision 16698)
+++ branches/2994-AutoDiffForIntervals/HeuristicLab.Algorithms.DataAnalysis.ConstrainedNonlinearRegression/3.4/ConstrainedNonlinearRegression.cs	(revision 16727)
@@ -248,12 +248,4 @@
         }
       }
-
-      // var interpreter = new SymbolicDataAnalysisExpressionTreeLinearInterpreter();
-      // 
-      // SymbolicRegressionConstantOptimizationEvaluator.OptimizeConstants(interpreter, tree, problemData, problemData.TrainingIndices,
-      //   applyLinearScaling: applyLinearScaling, maxIterations: maxIterations,
-      //   updateVariableWeights: false, updateConstantsInTree: true);
-
-
       var intervals = problemData.IntervalConstraints;
       var constraintsParser = new IntervalConstraintsParser();
@@ -315,4 +307,5 @@
       }
 
+      // local function
       void UpdateThetaValues(double[] theta) {
         for (int i = 0; i < theta.Length; ++i) {
@@ -321,6 +314,12 @@
       }
 
+      // buffers for calculate_jacobian
+      var target = problemData.TargetVariableTrainingValues.ToArray();
+      var fi_eval = new double[target.Length];
+      var jac_eval = new double[target.Length, thetaValues.Count];
+
       // define the callback used by the alglib optimizer
       // the x argument for this callback represents our theta
+      // local function
       void calculate_jacobian(double[] x, double[] fi, double[,] jac, object obj) {
         UpdateThetaValues(x);
@@ -328,6 +327,5 @@
         var autoDiffEval = new VectorAutoDiffEvaluator();
         autoDiffEval.Evaluate(preparedTree, problemData.Dataset, problemData.TrainingIndices.ToArray(),
-          GetParameterNodes(preparedTree, allThetaNodes), out double[] fi_eval, out double[,] jac_eval);
-        var target = problemData.TargetVariableTrainingValues.ToArray();
+          GetParameterNodes(preparedTree, allThetaNodes), fi_eval, jac_eval);
 
         // calc sum of squared errors and gradient
@@ -336,12 +334,12 @@
         for (int i = 0; i < target.Length; i++) {
           var res = target[i] - fi_eval[i];
-          sse += res * res;
+          sse += 0.5 * res * res;
           for (int j = 0; j < g.Length; j++) {
-            g[j] += -2.0 * res * jac_eval[i, j];
-          }
-        }
-
-        fi[0] = sse;
-        for (int j = 0; j < x.Length; j++) { jac[0, j] = g[j]; }
+            g[j] -= res * jac_eval[i, j];
+          }
+        }
+
+        fi[0] = sse / target.Length;
+        for (int j = 0; j < x.Length; j++) { jac[0, j] = g[j] / target.Length; }
 
         var intervalEvaluator = new IntervalEvaluator();
@@ -358,26 +356,27 @@
       }
 
+
+
       // prepare alglib
       alglib.minnlcstate state;
       alglib.minnlcreport rep;
+      alglib.optguardreport optGuardRep;
       var x0 = thetaValues.ToArray();
 
       alglib.minnlccreate(x0.Length, x0, out state);
-      double epsx = 1e-6;
-      int maxits = 0;
-      alglib.minnlcsetalgoslp(state);
-      alglib.minnlcsetcond(state, 0, maxits);
+      alglib.minnlcsetalgoslp(state);        // SLP is more robust but slower
+      alglib.minnlcsetcond(state, 0, maxIterations);
       var s = Enumerable.Repeat(1d, x0.Length).ToArray();  // scale is set to unit scale
       alglib.minnlcsetscale(state, s);
 
-      // set boundary constraints
-      // var boundaryLower = Enumerable.Repeat(-10d, n).ToArray();
-      // var boundaryUpper = Enumerable.Repeat(10d, n).ToArray();
-      // alglib.minnlcsetbc(state, boundaryLower, boundaryUpper);
       // set non-linear constraints: 0 equality constraints, 1 inequality constraint
       alglib.minnlcsetnlc(state, 0, constraintTrees.Count);
 
+      alglib.minnlcoptguardsmoothness(state);
+      alglib.minnlcoptguardgradient(state, 0.001);
+
       alglib.minnlcoptimize(state, calculate_jacobian, null, null);
       alglib.minnlcresults(state, out double[] xOpt, out rep);
+      alglib.minnlcoptguardresults(state, out optGuardRep);
 
       var interpreter = new SymbolicDataAnalysisExpressionTreeLinearInterpreter();
@@ -416,5 +415,5 @@
             var parent = n.Parent;
             if(thetaNodes[thetaIdx].Any()) {
-              // HACKY: REUSE CONSTANT TREE NODE IN SEVERAL TREES
+              // HACK: REUSE CONSTANT TREE NODE IN SEVERAL TREES
               // we use this trick to allow autodiff over thetas when thetas occurr multiple times in the tree (e.g. in derived trees)
               var constNode = thetaNodes[thetaIdx].First();
@@ -444,21 +443,5 @@
       for (int i = 0; i < nodes.Count; ++i) {
         var node = nodes[i];
-        /*if (node is VariableTreeNode variableTreeNode) {
-          var thetaVar = (VariableTreeNode)new Problems.DataAnalysis.Symbolic.Variable().CreateTreeNode();
-          thetaVar.Weight = 1;
-          thetaVar.VariableName = $"θ{n++}";
-
-          thetaNames.Add(thetaVar.VariableName);
-          thetaValues.Add(variableTreeNode.Weight);
-          variableTreeNode.Weight = 1; // set to unit weight
-
-          var parent = variableTreeNode.Parent;
-          var prod = MakeNode<Multiplication>(thetaVar, variableTreeNode);
-          if (parent != null) {
-            var index = parent.IndexOfSubtree(variableTreeNode);
-            parent.RemoveSubtree(index);
-            parent.InsertSubtree(index, prod);
-          }
-        } else*/ if (node is ConstantTreeNode constantTreeNode) {
+        if (node is ConstantTreeNode constantTreeNode) {
           var thetaVar = (VariableTreeNode)new Problems.DataAnalysis.Symbolic.Variable().CreateTreeNode();
           thetaVar.Weight = 1;
