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 17501)
+++ /branches/3040_VectorBasedGP/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression.Views/3.4/InteractiveSymbolicRegressionSolutionSimplifierView.cs	(revision 17502)
@@ -64,22 +64,41 @@
       int reps = 0;
 
-      do {
-        prevResult = result;
-        //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);
-        //  });
-        tree = TensorFlowConstantOptimizationEvaluator.OptimizeTree(tree, regressionProblemData, regressionProblemData.TrainingIndices,
-          applyLinearScaling: true, updateVariableWeights: true, maxIterations: 10, learningRate: 0.001);
-        result = SymbolicRegressionSingleObjectivePearsonRSquaredEvaluator.Calculate(model.Interpreter, tree,
-          model.LowerEstimationLimit, model.UpperEstimationLimit, regressionProblemData, regressionProblemData.TrainingIndices, applyLinearScaling: true);
-        reps++;
-        improvement = result - prevResult;
-      } while (improvement > minimumImprovement && reps < maxRepetitions &&
-               progress.ProgressState != ProgressState.StopRequested &&
-               progress.ProgressState != ProgressState.CancelRequested);
-      return tree;
+      //do {
+      //  prevResult = result;
+      //  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;
+      //} while (improvement > minimumImprovement && reps < maxRepetitions &&
+      //         progress.ProgressState != ProgressState.StopRequested &&
+      //         progress.ProgressState != ProgressState.CancelRequested);
+      //return tree;
+      const int maxIterations = 1000;
+      return TensorFlowConstantOptimizationEvaluator.OptimizeTree(tree, regressionProblemData,
+        regressionProblemData.TrainingIndices,
+        applyLinearScaling: false, updateVariableWeights: true, maxIterations: maxIterations, learningRate: 0.0001,
+        cancellationToken: cancellationToken,
+        progress: new SynchronousProgress<double>(cost => {
+          var newProgress = progress.ProgressValue + (1.0 / (maxIterations + 1));
+          progress.ProgressValue = Math.Min(newProgress, 1.0);
+          progress.Message = $"MSE: {cost}";
+        })
+      );
+    }
+
+    internal class SynchronousProgress<T> : IProgress<T> {
+      private readonly Action<T> callback;
+      public SynchronousProgress(Action<T> callback) {
+        this.callback = callback;
+      }
+      public void Report(T value) {
+        callback(value);
+      }
     }
   }
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 17501)
+++ /branches/3040_VectorBasedGP/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression-3.4.csproj	(revision 17502)
@@ -47,4 +47,5 @@
     <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
     <Prefer32Bit>false</Prefer32Bit>
+    <LangVersion>7</LangVersion>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
@@ -57,4 +58,5 @@
     <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
     <Prefer32Bit>false</Prefer32Bit>
+    <LangVersion>7</LangVersion>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x64' ">
@@ -67,4 +69,5 @@
     <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
     <Prefer32Bit>false</Prefer32Bit>
+    <LangVersion>7</LangVersion>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x64' ">
@@ -77,4 +80,5 @@
     <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
     <Prefer32Bit>false</Prefer32Bit>
+    <LangVersion>7</LangVersion>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
@@ -87,4 +91,5 @@
     <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
     <Prefer32Bit>false</Prefer32Bit>
+    <LangVersion>7</LangVersion>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
@@ -97,4 +102,5 @@
     <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
     <Prefer32Bit>false</Prefer32Bit>
+    <LangVersion>7</LangVersion>
   </PropertyGroup>
   <ItemGroup>
@@ -113,4 +119,5 @@
     </Reference>
     <Reference Include="System.Drawing" />
+    <Reference Include="System.Numerics" />
     <Reference Include="System.Xml.Linq">
       <RequiredTargetFramework>3.5</RequiredTargetFramework>
Index: /branches/3040_VectorBasedGP/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SingleObjective/Evaluators/TensorFlowConstantOptimizationEvaluator.cs
===================================================================
--- /branches/3040_VectorBasedGP/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SingleObjective/Evaluators/TensorFlowConstantOptimizationEvaluator.cs	(revision 17501)
+++ /branches/3040_VectorBasedGP/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SingleObjective/Evaluators/TensorFlowConstantOptimizationEvaluator.cs	(revision 17502)
@@ -20,10 +20,18 @@
 #endregion
 
-#define EXPLICIT_SHAPE
+//#define EXPORT_GRAPH
+//#define LOG_CONSOLE
+//#define LOG_FILE
 
 using System;
 using System.Collections;
 using System.Collections.Generic;
+#if LOG_CONSOLE
 using System.Diagnostics;
+#endif
+#if LOG_FILE
+using System.Globalization;
+using System.IO;
+#endif
 using System.Linq;
 using System.Threading;
@@ -46,5 +54,7 @@
     private const string LearningRateName = "LearningRate";
 
-    #region Parameter Properties
+    private static readonly TF_DataType DataType = tf.float32;
+
+#region Parameter Properties
     public IFixedValueParameter<IntValue> ConstantOptimizationIterationsParameter {
       get { return (IFixedValueParameter<IntValue>)Parameters[MaximumIterationsName]; }
@@ -53,7 +63,7 @@
       get { return (IFixedValueParameter<DoubleValue>)Parameters[LearningRateName]; }
     }
-    #endregion
-
-    #region Properties
+#endregion
+
+#region Properties
     public int ConstantOptimizationIterations {
       get { return ConstantOptimizationIterationsParameter.Value.Value; }
@@ -62,10 +72,10 @@
       get { return LearningRateParameter.Value.Value; }
     }
-    #endregion
+#endregion
 
     public TensorFlowConstantOptimizationEvaluator()
       : base() {
       Parameters.Add(new FixedValueParameter<IntValue>(MaximumIterationsName, "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>(LearningRateName, "", new DoubleValue(0.01)));
+      Parameters.Add(new FixedValueParameter<DoubleValue>(LearningRateName, "", new DoubleValue(0.001)));
     }
 
@@ -87,12 +97,11 @@
         ApplyLinearScalingParameter.ActualValue.Value, UpdateVariableWeights,
         ConstantOptimizationIterations, LearningRate,
-        cancellationToken, counter);
-    }
-
-    public static ISymbolicExpressionTree OptimizeTree(
-      ISymbolicExpressionTree tree,
+        cancellationToken);
+    }
+
+    public static ISymbolicExpressionTree OptimizeTree(ISymbolicExpressionTree tree,
       IRegressionProblemData problemData, IEnumerable<int> rows,
       bool applyLinearScaling, bool updateVariableWeights, int maxIterations, double learningRate,
-      CancellationToken cancellationToken = default(CancellationToken), EvaluationsCounter counter = null) {
+      CancellationToken cancellationToken = default(CancellationToken), IProgress<double> progress = null) {
 
       int numRows = rows.Count();
@@ -114,10 +123,17 @@
         return (ISymbolicExpressionTree)tree.Clone();
 
-#if EXPLICIT_SHAPE
-      var target = tf.placeholder(tf.float64, new TensorShape(numRows, 1), name: problemData.TargetVariable);
-#endif
-      // mse
-      var costs = tf.reduce_sum(tf.square(target - prediction)) / (2.0 * numRows);
-      var optimizer = tf.train.GradientDescentOptimizer((float)learningRate).minimize(costs);
+      var target = tf.placeholder(DataType, new TensorShape(numRows), name: problemData.TargetVariable);
+      // MSE
+      var cost = tf.reduce_mean(tf.square(prediction - target));
+
+      var optimizer = tf.train.AdamOptimizer((float)learningRate);
+      //var optimizer = tf.train.GradientDescentOptimizer((float)learningRate);
+      var optimizationOperation = optimizer.minimize(cost);
+
+#if EXPORT_GRAPH
+      //https://github.com/SciSharp/TensorFlow.NET/wiki/Debugging
+      tf.train.export_meta_graph(@"C:\temp\TFboard\graph.meta", as_text: false,
+        clear_devices: true, clear_extraneous_savers: false, strip_default_attrs: true);
+#endif
 
       // features as feed items
@@ -127,44 +143,97 @@
         var variableName = kvp.Value;
         if (problemData.Dataset.VariableHasType<double>(variableName)) {
-          var data = problemData.Dataset.GetDoubleValues(variableName, rows).ToArray();
-          //if (vectorLength.HasValue) {
-          //  var vectorData = new double[numRows][];
-          //  for (int i = 0; i < numRows; i++)
-          //    vectorData[i] = Enumerable.Repeat(data[i], vectorLength.Value).ToArray();
-          //  variablesFeed.Add(variable, np.array(vectorData));
-          //} else
+          var data = problemData.Dataset.GetDoubleValues(variableName, rows).Select(x => (float)x).ToArray();
           variablesFeed.Add(variable, np.array(data, copy: false).reshape(numRows, 1));
-          //} else if (problemData.Dataset.VariableHasType<string>(variableName)) {
-          //  variablesFeed.Add(variable, problemData.Dataset.GetStringValues(variableName, rows));
         } else if (problemData.Dataset.VariableHasType<DoubleVector>(variableName)) {
-          var data = problemData.Dataset.GetDoubleVectorValues(variableName, rows).Select(x => x.ToArray()).ToArray();
+          var data = problemData.Dataset.GetDoubleVectorValues(variableName, rows).Select(x => x.Select(y => (float)y).ToArray()).ToArray();
           variablesFeed.Add(variable, np.array(data));
         } else
           throw new NotSupportedException($"Type of the variable is not supported: {variableName}");
       }
-      var targetData = problemData.Dataset.GetDoubleValues(problemData.TargetVariable, rows).ToArray();
-      variablesFeed.Add(target, np.array(targetData, copy: false).reshape(numRows, 1));
+      var targetData = problemData.Dataset.GetDoubleValues(problemData.TargetVariable, rows).Select(x => (float)x).ToArray();
+      variablesFeed.Add(target, np.array(targetData, copy: false));
+
 
       List<NDArray> constants;
       using (var session = tf.Session()) {
+
+#if LOG_FILE
+        var directoryName = $"C:\\temp\\TFboard\\logdir\\manual_{DateTime.Now.ToString("yyyyMMddHHmmss")}_{maxIterations}_{learningRate.ToString(CultureInfo.InvariantCulture)}";
+        Directory.CreateDirectory(directoryName);
+        var costsWriter = new StreamWriter(File.Create(Path.Combine(directoryName, "Costs.csv")));
+        var weightsWriter = new StreamWriter(File.Create(Path.Combine(directoryName, "Weights.csv")));
+        var gradientsWriter = new StreamWriter(File.Create(Path.Combine(directoryName, "Gradients.csv")));
+#endif
+
+#if LOG_CONSOLE || LOG_FILE
+        var gradients = optimizer.compute_gradients(cost);
+#endif
+
         session.run(tf.global_variables_initializer());
 
-        // https://github.com/SciSharp/TensorFlow.NET/wiki/Debugging
-        tf.train.export_meta_graph(@"C:\temp\TFboard\graph.meta", as_text: false);
+        progress?.Report(session.run(cost, variablesFeed)[0].GetValue<float>(0));
+
+
+#if LOG_CONSOLE
+        Trace.WriteLine("Costs:");
+        Trace.WriteLine($"MSE: {session.run(cost, variablesFeed)[0].ToString(true)}");
 
         Trace.WriteLine("Weights:");
-        foreach (var v in variables)
+        foreach (var v in variables) {
           Trace.WriteLine($"{v.name}: {session.run(v).ToString(true)}");
+        }
+
+        Trace.WriteLine("Gradients:");
+        foreach (var t in gradients) {
+          Trace.WriteLine($"{t.Item2.name}: {session.run(t.Item1, variablesFeed)[0].ToString(true)}");
+        }
+#endif
+
+#if LOG_FILE
+        costsWriter.WriteLine("MSE");
+        costsWriter.WriteLine(session.run(cost, variablesFeed)[0].GetValue<float>(0).ToString(CultureInfo.InvariantCulture));
+
+        weightsWriter.WriteLine(string.Join(";", variables.Select(v => v.name)));
+        weightsWriter.WriteLine(string.Join(";", variables.Select(v => session.run(v).GetValue<float>(0, 0).ToString(CultureInfo.InvariantCulture))));
+
+        gradientsWriter.WriteLine(string.Join(";", gradients.Select(t => t.Item2.name)));
+        gradientsWriter.WriteLine(string.Join(";", gradients.Select(t => session.run(t.Item1, variablesFeed)[0].GetValue<float>(0, 0).ToString(CultureInfo.InvariantCulture))));
+#endif
 
         for (int i = 0; i < maxIterations; i++) {
-
-          //optimizer.minimize(costs);
-          session.run(optimizer, variablesFeed);
+          if (cancellationToken.IsCancellationRequested)
+            break;
+
+          session.run(optimizationOperation, variablesFeed);
+
+          progress?.Report(session.run(cost, variablesFeed)[0].GetValue<float>(0));
+
+#if LOG_CONSOLE
+          Trace.WriteLine("Costs:");
+          Trace.WriteLine($"MSE: {session.run(cost, variablesFeed)[0].ToString(true)}");
 
           Trace.WriteLine("Weights:");
-          foreach (var v in variables)
+          foreach (var v in variables) {
             Trace.WriteLine($"{v.name}: {session.run(v).ToString(true)}");
-        }
-
+          }
+
+          Trace.WriteLine("Gradients:");
+          foreach (var t in gradients) {
+            Trace.WriteLine($"{t.Item2.name}: {session.run(t.Item1, variablesFeed)[0].ToString(true)}");
+          }
+#endif
+
+#if LOG_FILE
+          costsWriter.WriteLine(session.run(cost, variablesFeed)[0].GetValue<float>(0).ToString(CultureInfo.InvariantCulture));
+          weightsWriter.WriteLine(string.Join(";", variables.Select(v => session.run(v).GetValue<float>(0, 0).ToString(CultureInfo.InvariantCulture))));
+          gradientsWriter.WriteLine(string.Join(";", gradients.Select(t => session.run(t.Item1, variablesFeed)[0].GetValue<float>(0, 0).ToString(CultureInfo.InvariantCulture))));
+#endif
+        }
+
+#if LOG_FILE
+        costsWriter.Close();
+        weightsWriter.Close();
+        gradientsWriter.Close();
+#endif
         constants = variables.Select(v => session.run(v)).ToList();
       }
@@ -182,10 +251,10 @@
       foreach (var node in tree.Root.IterateNodesPrefix().OfType<SymbolicExpressionTreeTerminalNode>()) {
         if (node is ConstantTreeNode constantTreeNode)
-          constantTreeNode.Value = constants[i++].GetDouble(0, 0);
+          constantTreeNode.Value = constants[i++].GetValue<float>(0, 0);
         else if (node is VariableTreeNodeBase variableTreeNodeBase && updateVariableWeights)
-          variableTreeNodeBase.Weight = constants[i++].GetDouble(0, 0);
+          variableTreeNodeBase.Weight = constants[i++].GetValue<float>(0, 0);
         else if (node is FactorVariableTreeNode factorVarTreeNode && updateVariableWeights) {
           for (int j = 0; j < factorVarTreeNode.Weights.Length; j++)
-            factorVarTreeNode.Weights[j] = constants[i++].GetDouble(0, 0);
+            factorVarTreeNode.Weights[j] = constants[i++].GetValue<float>(0, 0);
         }
       }
Index: /branches/3040_VectorBasedGP/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Converters/TreeToTensorConverter.cs
===================================================================
--- /branches/3040_VectorBasedGP/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Converters/TreeToTensorConverter.cs	(revision 17501)
+++ /branches/3040_VectorBasedGP/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Converters/TreeToTensorConverter.cs	(revision 17502)
@@ -29,36 +29,13 @@
 using Tensorflow;
 using static Tensorflow.Binding;
-using DoubleVector = MathNet.Numerics.LinearAlgebra.Vector<double>;
 
 namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
   public class TreeToTensorConverter {
 
-    #region helper class
-    public class DataForVariable {
-      public readonly string variableName;
-      public readonly string variableValue; // for factor vars
-
-      public DataForVariable(string varName, string varValue) {
-        this.variableName = varName;
-        this.variableValue = varValue;
-      }
-
-      public override bool Equals(object obj) {
-        var other = obj as DataForVariable;
-        if (other == null) return false;
-        return other.variableName.Equals(this.variableName) &&
-               other.variableValue.Equals(this.variableValue);
-      }
-
-      public override int GetHashCode() {
-        return variableName.GetHashCode() ^ variableValue.GetHashCode();
-      }
-    }
-    #endregion
+    private static readonly TF_DataType DataType = tf.float32;
 
     public static bool TryConvert(ISymbolicExpressionTree tree, int numRows, Dictionary<string, int> variableLengths,
       bool makeVariableWeightsVariable, bool addLinearScalingTerms,
-      out Tensor graph, out Dictionary<Tensor, string> parameters, out List<Tensor> variables
-/*, out double[] initialConstants*/) {
+      out Tensor graph, out Dictionary<Tensor, string> parameters, out List<Tensor> variables) {
 
       try {
@@ -66,8 +43,6 @@
         graph = converter.ConvertNode(tree.Root.GetSubtree(0));
 
-        //var parametersEntries = converter.parameters.ToList(); // guarantee same order for keys and values
-        parameters = converter.parameters; // parametersEntries.Select(kvp => kvp.Value).ToList();
+        parameters = converter.parameters;
         variables = converter.variables;
-        //initialConstants = converter.initialConstants.ToArray();
         return true;
       } catch (NotSupportedException) {
@@ -75,5 +50,4 @@
         parameters = null;
         variables = null;
-        //initialConstants = null;
         return false;
       }
@@ -85,5 +59,4 @@
     private readonly bool addLinearScalingTerms;
 
-    //private readonly List<double> initialConstants = new List<double>();
     private readonly Dictionary<Tensor, string> parameters = new Dictionary<Tensor, string>();
     private readonly List<Tensor> variables = new List<Tensor>();
@@ -97,15 +70,9 @@
 
 
-
     private Tensor ConvertNode(ISymbolicExpressionTreeNode node) {
       if (node.Symbol is Constant) {
-        var value = ((ConstantTreeNode)node).Value;
-        //initialConstants.Add(value);
-#if EXPLICIT_SHAPE
-        //var var = (RefVariable)tf.VariableV1(value, name: $"c_{variables.Count}", dtype: tf.float64, shape: new[] { 1, 1 });
+        var value = (float)((ConstantTreeNode)node).Value;
         var value_arr = np.array(value).reshape(1, 1);
-        var var = tf.Variable(value_arr, name: $"c_{variables.Count}", dtype: tf.float64);
-#endif
-        //var var = tf.Variable(value, name: $"c_{variables.Count}", dtype: tf.float64/*, shape: new[] { 1, 1 }*/);
+        var var = tf.Variable(value_arr, name: $"c_{variables.Count}", dtype: DataType);
         variables.Add(var);
         return var;
@@ -118,17 +85,10 @@
         //var varValue = factorVarNode != null ? factorVarNode.VariableValue : string.Empty;
         //var par = FindOrCreateParameter(parameters, varNode.VariableName, varValue);
-#if EXPLICIT_SHAPE
-        var par = tf.placeholder(tf.float64, new TensorShape(numRows, variableLengths[varNode.VariableName]), name: varNode.VariableName);
-#endif
+        var par = tf.placeholder(DataType, new TensorShape(numRows, variableLengths[varNode.VariableName]), name: varNode.VariableName);
         parameters.Add(par, varNode.VariableName);
 
         if (makeVariableWeightsVariable) {
-          //initialConstants.Add(varNode.Weight);
-#if EXPLICIT_SHAPE
-          //var w = (RefVariable)tf.VariableV1(varNode.Weight, name: $"w_{varNode.VariableName}_{variables.Count}", dtype: tf.float64, shape: new[] { 1, 1 });
-          var w_arr = np.array(varNode.Weight).reshape(1, 1);
-          var w = tf.Variable(w_arr, name: $"w_{varNode.VariableName}", dtype: tf.float64);
-#endif
-          //var w = tf.Variable(varNode.Weight, name: $"w_{varNode.VariableName}_{variables.Count}", dtype: tf.float64/*, shape: new[] { 1, 1 }*/);
+          var w_arr = np.array((float)varNode.Weight).reshape(1, 1);
+          var w = tf.Variable(w_arr, name: $"w_{varNode.VariableName}", dtype: DataType);
           variables.Add(w);
           return w * par;
@@ -143,10 +103,10 @@
       //  foreach (var variableValue in factorVarNode.Symbol.GetVariableValues(factorVarNode.VariableName)) {
       //    //var par = FindOrCreateParameter(parameters, factorVarNode.VariableName, variableValue);
-      //    var par = tf.placeholder(tf.float64, new TensorShape(numRows, 1), name: factorVarNode.VariableName);
+      //    var par = tf.placeholder(DataType, new TensorShape(numRows, 1), name: factorVarNode.VariableName);
       //    parameters.Add(par, factorVarNode.VariableName);
 
       //    var value = factorVarNode.GetValue(variableValue);
       //    //initialConstants.Add(value);
-      //    var wVar = (RefVariable)tf.VariableV1(value, name: $"f_{factorVarNode.VariableName}_{variables.Count}", dtype: tf.float64, shape: new[] { 1, 1 });
+      //    var wVar = (RefVariable)tf.VariableV1(value, name: $"f_{factorVarNode.VariableName}_{variables.Count}", dtype: DataType, shape: new[] { 1, 1 });
       //    //var wVar = tf.Variable(value, name: $"f_{factorVarNode.VariableName}_{variables.Count}"/*, shape: new[] { 1, 1 }*/);
       //    variables.Add(wVar);
@@ -159,42 +119,23 @@
 
       if (node.Symbol is Addition) {
-        var terms = new List<Tensor>();
-        foreach (var subTree in node.Subtrees) {
-          terms.Add(ConvertNode(subTree));
-        }
-
+        var terms = node.Subtrees.Select(ConvertNode).ToList();
         return terms.Aggregate((a, b) => a + b);
       }
 
       if (node.Symbol is Subtraction) {
-        var terms = new List<Tensor>();
-        for (int i = 0; i < node.SubtreeCount; i++) {
-          var t = ConvertNode(node.GetSubtree(i));
-          if (i > 0) t = -t;
-          terms.Add(t);
-        }
-
+        var terms = node.Subtrees.Select(ConvertNode).ToList();
         if (terms.Count == 1) return -terms[0];
-        else return terms.Aggregate((a, b) => a + b);
+        return terms.Aggregate((a, b) => a - b);
       }
 
       if (node.Symbol is Multiplication) {
-        var terms = new List<Tensor>();
-        foreach (var subTree in node.Subtrees) {
-          terms.Add(ConvertNode(subTree));
-        }
-
-        if (terms.Count == 1) return terms[0];
-        else return terms.Aggregate((a, b) => a * b);
+        var terms = node.Subtrees.Select(ConvertNode).ToList();
+        return terms.Aggregate((a, b) => a * b);
       }
 
       if (node.Symbol is Division) {
-        var terms = new List<Tensor>();
-        foreach (var subTree in node.Subtrees) {
-          terms.Add(ConvertNode(subTree));
-        }
-
-        if (terms.Count == 1) return 1.0 / terms[0];
-        else return terms.Aggregate((a, b) => a * (1.0 / b));
+        var terms = node.Subtrees.Select(ConvertNode).ToList();
+        if (terms.Count == 1) return 1.0f / terms[0];
+        return terms.Aggregate((a, b) => a / b);
       }
 
@@ -207,5 +148,5 @@
         var x1 = ConvertNode(node.GetSubtree(0));
         var x2 = ConvertNode(node.GetSubtree(1));
-        return x1 / tf.pow(1 + x2 * x2, 0.5);
+        return x1 / tf.pow(1.0f + x2 * x2, 0.5f);
       }
 
@@ -233,10 +174,10 @@
       if (node.Symbol is Cube) {
         return math_ops.pow(
-          ConvertNode(node.GetSubtree(0)), 3.0);
+          ConvertNode(node.GetSubtree(0)), 3.0f);
       }
 
       if (node.Symbol is CubeRoot) {
         return math_ops.pow(
-          ConvertNode(node.GetSubtree(0)), 1.0 / 3.0);
+          ConvertNode(node.GetSubtree(0)), 1.0f / 3.0f);
         // TODO
         // f: x < 0 ? -Math.Pow(-x, 1.0 / 3) : Math.Pow(x, 1.0 / 3),
@@ -281,22 +222,20 @@
 
       if (node.Symbol is StartSymbol) {
+        Tensor prediction;
         if (addLinearScalingTerms) {
           // scaling variables α, β are given at the beginning of the parameter vector
-#if EXPLICIT_SHAPE
-          //var alpha = (RefVariable)tf.VariableV1(1.0, name: $"alpha_{1.0}", dtype: tf.float64, shape: new[] { 1, 1 });
-          //var beta = (RefVariable)tf.VariableV1(0.0, name: $"beta_{0.0}", dtype: tf.float64, shape: new[] { 1, 1 });
-
-          var alpha_arr = np.array(1.0).reshape(1, 1);
-          var alpha = tf.Variable(alpha_arr, name: "alpha", dtype: tf.float64);
-          var beta_arr = np.array(0.0).reshape(1, 1);
-          var beta = tf.Variable(beta_arr, name: "beta", dtype: tf.float64);
-#endif
-          //var alpha = tf.Variable(1.0, name: $"alpha_{1.0}", dtype: tf.float64/*, shape: new[] { 1, 1 }*/);
-          //var beta = tf.Variable(0.0, name: $"beta_{0.0}", dtype: tf.float64/*, shape: new[] { 1, 1 }*/);
+          var alpha_arr = np.array(1.0f).reshape(1, 1);
+          var alpha = tf.Variable(alpha_arr, name: "alpha", dtype: DataType);
+          var beta_arr = np.array(0.0f).reshape(1, 1);
+          var beta = tf.Variable(beta_arr, name: "beta", dtype: DataType);
           variables.Add(alpha);
           variables.Add(beta);
           var t = ConvertNode(node.GetSubtree(0));
-          return t * alpha + beta;
-        } else return ConvertNode(node.GetSubtree(0));
+          prediction = t * alpha + beta;
+        } else {
+          prediction = ConvertNode(node.GetSubtree(0));
+        }
+
+        return tf.reduce_sum(prediction, axis: new[] { 1 });
       }
 
