Index: /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/GaussianProcess/GaussianProcessModel.cs
===================================================================
--- /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/GaussianProcess/GaussianProcessModel.cs	(revision 15141)
+++ /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/GaussianProcess/GaussianProcessModel.cs	(revision 15142)
@@ -165,6 +165,5 @@
       try {
         CalculateModel(ds, rows, scaleInputs);
-      }
-      catch (alglib.alglibexception ae) {
+      } catch (alglib.alglibexception ae) {
         // wrap exception so that calling code doesn't have to know about alglib implementation
         throw new ArgumentException("There was a problem in the calculation of the Gaussian process model", ae);
@@ -260,7 +259,18 @@
     private static double[,] GetData(IDataset ds, IEnumerable<string> allowedInputs, IEnumerable<int> rows, Scaling scaling) {
       if (scaling != null) {
-        return AlglibUtil.PrepareAndScaleInputMatrix(ds, allowedInputs, rows, scaling);
+        // TODO: completely remove Scaling class
+        List<ITransformation<double>> transformations = new List<ITransformation<double>>();
+
+        foreach (var varName in allowedInputs) {
+          double min;
+          double max;
+          scaling.GetScalingParameters(varName, out min, out max);
+          var add = -min / (max - min);
+          var mult = 1.0 / (max - min);
+          transformations.Add(new LinearTransformation(allowedInputs) { Addend = add, Multiplier = mult });
+        }
+        return ds.ToArray(allowedInputs, transformations, rows);
       } else {
-        return AlglibUtil.PrepareInputMatrix(ds, allowedInputs, rows);
+        return ds.ToArray(allowedInputs, rows);
       }
     }
@@ -334,6 +344,5 @@
         return Enumerable.Range(0, newN)
           .Select(i => ms[i] + Util.ScalarProd(Ks[i], alpha));
-      }
-      catch (alglib.alglibexception ae) {
+      } catch (alglib.alglibexception ae) {
         // wrap exception so that calling code doesn't have to know about alglib implementation
         throw new ArgumentException("There was a problem in the calculation of the Gaussian process model", ae);
@@ -381,6 +390,5 @@
         }
         return kss;
-      }
-      catch (alglib.alglibexception ae) {
+      } catch (alglib.alglibexception ae) {
         // wrap exception so that calling code doesn't have to know about alglib implementation
         throw new ArgumentException("There was a problem in the calculation of the Gaussian process model", ae);
Index: /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/HeuristicLab.Algorithms.DataAnalysis-3.4.csproj
===================================================================
--- /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/HeuristicLab.Algorithms.DataAnalysis-3.4.csproj	(revision 15141)
+++ /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/HeuristicLab.Algorithms.DataAnalysis-3.4.csproj	(revision 15142)
@@ -246,6 +246,4 @@
       <SubType>Code</SubType>
     </Compile>
-    <Compile Include="Linear\AlglibUtil.cs" />
-    <Compile Include="Linear\Scaling.cs" />
     <Compile Include="Linear\LinearDiscriminantAnalysis.cs" />
     <Compile Include="Linear\LinearRegression.cs">
@@ -255,4 +253,5 @@
     <Compile Include="Linear\MultinomialLogitClassificationSolution.cs" />
     <Compile Include="Linear\MultinomialLogitModel.cs" />
+    <Compile Include="Linear\Scaling.cs" />
     <Compile Include="Nca\Initialization\INcaInitializer.cs" />
     <Compile Include="Nca\Initialization\LdaInitializer.cs" />
Index: able/HeuristicLab.Algorithms.DataAnalysis/3.4/Linear/AlglibUtil.cs
===================================================================
--- /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/Linear/AlglibUtil.cs	(revision 15141)
+++ 	(revision )
@@ -1,132 +1,0 @@
-﻿#region License Information
-/* HeuristicLab
- * Copyright (C) 2002-2016 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 HeuristicLab.Problems.DataAnalysis;
-
-namespace HeuristicLab.Algorithms.DataAnalysis {
-  public static class AlglibUtil {
-    public static double[,] PrepareInputMatrix(IDataset dataset, IEnumerable<string> variables, IEnumerable<int> rows) {
-      // check input variables. Only double variables are allowed.
-      var invalidInputs =
-        variables.Where(name => !dataset.VariableHasType<double>(name));
-      if (invalidInputs.Any())
-        throw new NotSupportedException("Unsupported inputs: " + string.Join(", ", invalidInputs));
-
-      List<int> rowsList = rows.ToList();
-      double[,] matrix = new double[rowsList.Count, variables.Count()];
-
-      int col = 0;
-      foreach (string column in variables) {
-        var values = dataset.GetDoubleValues(column, rows);
-        int row = 0;
-        foreach (var value in values) {
-          matrix[row, col] = value;
-          row++;
-        }
-        col++;
-      }
-
-      return matrix;
-    }
-
-    public static double[,] PrepareAndScaleInputMatrix(IDataset dataset, IEnumerable<string> variables, IEnumerable<int> rows, Scaling scaling) {
-      // check input variables. Only double variables are allowed.
-      var invalidInputs =
-        variables.Where(name => !dataset.VariableHasType<double>(name));
-      if (invalidInputs.Any())
-        throw new NotSupportedException("Unsupported inputs: " + string.Join(", ", invalidInputs));
-
-      List<string> variablesList = variables.ToList();
-      List<int> rowsList = rows.ToList();
-
-      double[,] matrix = new double[rowsList.Count, variablesList.Count];
-
-      int col = 0;
-      foreach (string column in variables) {
-        var values = scaling.GetScaledValues(dataset, column, rows);
-        int row = 0;
-        foreach (var value in values) {
-          matrix[row, col] = value;
-          row++;
-        }
-        col++;
-      }
-
-      return matrix;
-    }
-
-    /// <summary>
-    /// Prepares a binary data matrix from a number of factors and specified factor values
-    /// </summary>
-    /// <param name="dataset">A dataset that contains the variable values</param>
-    /// <param name="factorVariables">An enumerable of categorical variables (factors). For each variable an enumerable of values must be specified.</param>
-    /// <param name="rows">An enumerable of row indices for the dataset</param>
-    /// <returns></returns>
-    /// <remarks>Factor variables (categorical variables) are split up into multiple binary variables one for each specified value.</remarks>
-    public static double[,] PrepareInputMatrix(
-      IDataset dataset,
-      IEnumerable<KeyValuePair<string, IEnumerable<string>>> factorVariables,
-      IEnumerable<int> rows) {
-      // check input variables. Only string variables are allowed.
-      var invalidInputs =
-        factorVariables.Select(kvp => kvp.Key).Where(name => !dataset.VariableHasType<string>(name));
-      if (invalidInputs.Any())
-        throw new NotSupportedException("Unsupported inputs: " + string.Join(", ", invalidInputs));
-
-      int numBinaryColumns = factorVariables.Sum(kvp => kvp.Value.Count());
-
-      List<int> rowsList = rows.ToList();
-      double[,] matrix = new double[rowsList.Count, numBinaryColumns];
-
-      int col = 0;
-      foreach (var kvp in factorVariables) {
-        var varName = kvp.Key;
-        var cats = kvp.Value;
-        if (!cats.Any()) continue;
-        foreach (var cat in cats) {
-          var values = dataset.GetStringValues(varName, rows);
-          int row = 0;
-          foreach (var value in values) {
-            matrix[row, col] = value == cat ? 1 : 0;
-            row++;
-          }
-          col++;
-        }
-      }
-      return matrix;
-    }
-
-    public static IEnumerable<KeyValuePair<string, IEnumerable<string>>> GetFactorVariableValues(IDataset ds, IEnumerable<string> factorVariables, IEnumerable<int> rows) {
-      return from factor in factorVariables
-             let distinctValues = ds.GetStringValues(factor, rows).Distinct().ToArray()
-             // 1 distinct value => skip (constant)
-             // 2 distinct values => only take one of the two values
-             // >=3 distinct values => create a binary value for each value
-             let reducedValues = distinctValues.Length <= 2
-               ? distinctValues.Take(distinctValues.Length - 1)
-               : distinctValues
-             select new KeyValuePair<string, IEnumerable<string>>(factor, reducedValues);
-    }
-  }
-}
Index: /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/Linear/LinearDiscriminantAnalysis.cs
===================================================================
--- /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/Linear/LinearDiscriminantAnalysis.cs	(revision 15141)
+++ /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/Linear/LinearDiscriminantAnalysis.cs	(revision 15142)
@@ -73,8 +73,8 @@
       var doubleVariableNames = allowedInputVariables.Where(dataset.VariableHasType<double>).ToArray();
       var factorVariableNames = allowedInputVariables.Where(dataset.VariableHasType<string>).ToArray();
-      double[,] inputMatrix = AlglibUtil.PrepareInputMatrix(dataset, doubleVariableNames.Concat(new string[] { targetVariable }), rows);
+      double[,] inputMatrix = dataset.ToArray(doubleVariableNames.Concat(new string[] { targetVariable }), rows);
 
-      var factorVariables = AlglibUtil.GetFactorVariableValues(dataset, factorVariableNames, rows);
-      double[,] factorMatrix = AlglibUtil.PrepareInputMatrix(dataset, factorVariables, rows);
+      var factorVariables = dataset.GetFactorVariableValues(factorVariableNames, rows);
+      var factorMatrix = dataset.ToArray(factorVariables, rows);
 
       inputMatrix = factorMatrix.HorzCat(inputMatrix);
@@ -94,30 +94,7 @@
       if (info < 1) throw new ArgumentException("Error in calculation of linear discriminant analysis solution");
 
-      ISymbolicExpressionTree tree = new SymbolicExpressionTree(new ProgramRootSymbol().CreateTreeNode());
-      ISymbolicExpressionTreeNode startNode = new StartSymbol().CreateTreeNode();
-      tree.Root.AddSubtree(startNode);
-      ISymbolicExpressionTreeNode addition = new Addition().CreateTreeNode();
-      startNode.AddSubtree(addition);
-
-      int col = 0;
-      foreach (var kvp in factorVariables) {
-        var varName = kvp.Key;
-        foreach (var cat in kvp.Value) {
-          BinaryFactorVariableTreeNode vNode =
-            (BinaryFactorVariableTreeNode)new HeuristicLab.Problems.DataAnalysis.Symbolic.BinaryFactorVariable().CreateTreeNode();
-          vNode.VariableName = varName;
-          vNode.VariableValue = cat;
-          vNode.Weight = w[col];
-          addition.AddSubtree(vNode);
-          col++;
-        }
-      }
-      foreach (string column in doubleVariableNames) {
-        VariableTreeNode vNode = (VariableTreeNode)new HeuristicLab.Problems.DataAnalysis.Symbolic.Variable().CreateTreeNode();
-        vNode.VariableName = column;
-        vNode.Weight = w[col];
-        addition.AddSubtree(vNode);
-        col++;
-      }
+      var nFactorCoeff = factorMatrix.GetLength(1);
+      var tree = LinearModelToTreeConverter.CreateTree(factorVariables, w.Take(nFactorCoeff).ToArray(),
+        doubleVariableNames, w.Skip(nFactorCoeff).Take(doubleVariableNames.Length).ToArray());
 
       var model = CreateDiscriminantFunctionModel(tree, new SymbolicDataAnalysisExpressionTreeLinearInterpreter(), problemData, rows);
Index: /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/Linear/LinearRegression.cs
===================================================================
--- /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/Linear/LinearRegression.cs	(revision 15141)
+++ /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/Linear/LinearRegression.cs	(revision 15142)
@@ -76,7 +76,7 @@
       var doubleVariables = allowedInputVariables.Where(dataset.VariableHasType<double>);
       var factorVariableNames = allowedInputVariables.Where(dataset.VariableHasType<string>);
-      var factorVariables = AlglibUtil.GetFactorVariableValues(dataset, factorVariableNames, rows);
-      double[,] binaryMatrix = AlglibUtil.PrepareInputMatrix(dataset, factorVariables, rows);
-      double[,] doubleVarMatrix = AlglibUtil.PrepareInputMatrix(dataset, doubleVariables.Concat(new string[] { targetVariable }), rows);
+      var factorVariables = dataset.GetFactorVariableValues(factorVariableNames, rows);
+      double[,] binaryMatrix = dataset.ToArray(factorVariables, rows);
+      double[,] doubleVarMatrix = dataset.ToArray(doubleVariables.Concat(new string[] { targetVariable }), rows);
       var inputMatrix = binaryMatrix.HorzCat(doubleVarMatrix);
 
@@ -98,35 +98,10 @@
       alglib.lrunpack(lm, out coefficients, out nFeatures);
 
-      ISymbolicExpressionTree tree = new SymbolicExpressionTree(new ProgramRootSymbol().CreateTreeNode());
-      ISymbolicExpressionTreeNode startNode = new StartSymbol().CreateTreeNode();
-      tree.Root.AddSubtree(startNode);
-      ISymbolicExpressionTreeNode addition = new Addition().CreateTreeNode();
-      startNode.AddSubtree(addition);
-
-      int col = 0;
-      foreach (var kvp in factorVariables) {
-        var varName = kvp.Key;
-        foreach (var cat in kvp.Value) {
-          BinaryFactorVariableTreeNode vNode =
-            (BinaryFactorVariableTreeNode)new HeuristicLab.Problems.DataAnalysis.Symbolic.BinaryFactorVariable().CreateTreeNode();
-          vNode.VariableName = varName;
-          vNode.VariableValue = cat;
-          vNode.Weight = coefficients[col];
-          addition.AddSubtree(vNode);
-          col++;
-        }
-      }
-      foreach (string column in doubleVariables) {
-        VariableTreeNode vNode = (VariableTreeNode)new HeuristicLab.Problems.DataAnalysis.Symbolic.Variable().CreateTreeNode();
-        vNode.VariableName = column;
-        vNode.Weight = coefficients[col];
-        addition.AddSubtree(vNode);
-        col++;
-      }
-
-      ConstantTreeNode cNode = (ConstantTreeNode)new Constant().CreateTreeNode();
-      cNode.Value = coefficients[coefficients.Length - 1];
-      addition.AddSubtree(cNode);
-
+      int nFactorCoeff = binaryMatrix.GetLength(1);
+      int nVarCoeff = doubleVariables.Count();
+      var tree = LinearModelToTreeConverter.CreateTree(factorVariables, coefficients.Take(nFactorCoeff).ToArray(),
+        doubleVariables.ToArray(), coefficients.Skip(nFactorCoeff).Take(nVarCoeff).ToArray(), 
+        @const: coefficients[nFeatures]);
+      
       SymbolicRegressionSolution solution = new SymbolicRegressionSolution(new SymbolicRegressionModel(problemData.TargetVariable, tree, new SymbolicDataAnalysisExpressionTreeLinearInterpreter()), (IRegressionProblemData)problemData.Clone());
       solution.Model.Name = "Linear Regression Model";
Index: /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/Linear/MultinomialLogitClassification.cs
===================================================================
--- /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/Linear/MultinomialLogitClassification.cs	(revision 15141)
+++ /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/Linear/MultinomialLogitClassification.cs	(revision 15142)
@@ -72,8 +72,8 @@
       var factorVariableNames = problemData.AllowedInputVariables.Where(dataset.VariableHasType<string>);
       IEnumerable<int> rows = problemData.TrainingIndices;
-      double[,] inputMatrix = AlglibUtil.PrepareInputMatrix(dataset, doubleVariableNames.Concat(new string[] { targetVariable }), rows);
+      double[,] inputMatrix = dataset.ToArray(doubleVariableNames.Concat(new string[] { targetVariable }), rows);
 
-      var factorVariableValues = AlglibUtil.GetFactorVariableValues(dataset, factorVariableNames, rows);
-      var factorMatrix = AlglibUtil.PrepareInputMatrix(dataset, factorVariableValues, rows);
+      var factorVariableValues = dataset.GetFactorVariableValues(factorVariableNames, rows);
+      var factorMatrix = dataset.ToArray(factorVariableValues, rows);
       inputMatrix = factorMatrix.HorzCat(inputMatrix);
 
Index: /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/Linear/MultinomialLogitModel.cs
===================================================================
--- /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/Linear/MultinomialLogitModel.cs	(revision 15141)
+++ /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/Linear/MultinomialLogitModel.cs	(revision 15142)
@@ -97,6 +97,6 @@
     public override IEnumerable<double> GetEstimatedClassValues(IDataset dataset, IEnumerable<int> rows) {
 
-      double[,] inputData = AlglibUtil.PrepareInputMatrix(dataset, allowedInputVariables, rows);
-      double[,] factorData = AlglibUtil.PrepareInputMatrix(dataset, factorVariables, rows);
+      double[,] inputData = dataset.ToArray(allowedInputVariables, rows);
+      double[,] factorData = dataset.ToArray(factorVariables, rows);
 
       inputData = factorData.HorzCat(inputData);
Index: /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/Linear/Scaling.cs
===================================================================
--- /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/Linear/Scaling.cs	(revision 15141)
+++ /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/Linear/Scaling.cs	(revision 15142)
@@ -29,4 +29,5 @@
 
 namespace HeuristicLab.Algorithms.DataAnalysis {
+  [Obsolete("Use transformation classes in Problems.DataAnalysis instead")]
   [StorableClass]
   [Item(Name = "Scaling", Description = "Contains information about scaling of variables for data-analysis algorithms.")]
Index: /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/Nca/Initialization/LdaInitializer.cs
===================================================================
--- /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/Nca/Initialization/LdaInitializer.cs	(revision 15141)
+++ /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/Nca/Initialization/LdaInitializer.cs	(revision 15142)
@@ -44,7 +44,7 @@
       var attributes = data.AllowedInputVariables.Count();
 
-      var ldaDs = AlglibUtil.PrepareInputMatrix(data.Dataset,
-                                                data.AllowedInputVariables.Concat(data.TargetVariable.ToEnumerable()),
-                                                data.TrainingIndices);
+      var ldaDs = data.Dataset.ToArray(
+                                       data.AllowedInputVariables.Concat(data.TargetVariable.ToEnumerable()),
+                                       data.TrainingIndices);
 
       // map class values to sequential natural numbers (required by alglib)
Index: /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/Nca/Initialization/PcaInitializer.cs
===================================================================
--- /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/Nca/Initialization/PcaInitializer.cs	(revision 15141)
+++ /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/Nca/Initialization/PcaInitializer.cs	(revision 15142)
@@ -44,5 +44,5 @@
       var attributes = data.AllowedInputVariables.Count();
 
-      var pcaDs = AlglibUtil.PrepareInputMatrix(data.Dataset, data.AllowedInputVariables, data.TrainingIndices);
+      var pcaDs = data.Dataset.ToArray(data.AllowedInputVariables, data.TrainingIndices);
 
       int info;
Index: /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/Nca/NcaGradientCalculator.cs
===================================================================
--- /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/Nca/NcaGradientCalculator.cs	(revision 15141)
+++ /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/Nca/NcaGradientCalculator.cs	(revision 15142)
@@ -99,6 +99,6 @@
       }
 
-      var data = AlglibUtil.PrepareInputMatrix(problemData.Dataset, problemData.AllowedInputVariables,
-                                               problemData.TrainingIndices);
+      var data = problemData.Dataset.ToArray(problemData.AllowedInputVariables,
+                                             problemData.TrainingIndices);
       var classes = problemData.Dataset.GetDoubleValues(problemData.TargetVariable, problemData.TrainingIndices).ToArray();
 
Index: /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/Nca/NcaModel.cs
===================================================================
--- /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/Nca/NcaModel.cs	(revision 15141)
+++ /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/Nca/NcaModel.cs	(revision 15142)
@@ -86,5 +86,5 @@
 
     public double[,] Reduce(IDataset dataset, IEnumerable<int> rows) {
-      var data = AlglibUtil.PrepareInputMatrix(dataset, allowedInputVariables, rows);
+      var data = dataset.ToArray(allowedInputVariables, rows);
 
       var targets = dataset.GetDoubleValues(TargetVariable, rows).ToArray();
Index: /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/NearestNeighbour/NearestNeighbourModel.cs
===================================================================
--- /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/NearestNeighbour/NearestNeighbourModel.cs	(revision 15141)
+++ /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/NearestNeighbour/NearestNeighbourModel.cs	(revision 15142)
@@ -119,5 +119,5 @@
       if (IsCompatibilityLoaded) {
         // no scaling
-        inputMatrix = AlglibUtil.PrepareInputMatrix(dataset,
+        inputMatrix = dataset.ToArray(
           this.allowedInputVariables.Concat(new string[] { targetVariable }),
           rows);
@@ -167,15 +167,9 @@
 
     private static double[,] CreateScaledData(IDataset dataset, IEnumerable<string> variables, IEnumerable<int> rows, double[] offsets, double[] factors) {
-      var x = new double[rows.Count(), variables.Count()];
-      var colIdx = 0;
-      foreach (var variableName in variables) {
-        var rowIdx = 0;
-        foreach (var val in dataset.GetDoubleValues(variableName, rows)) {
-          x[rowIdx, colIdx] = (val + offsets[colIdx]) * factors[colIdx];
-          rowIdx++;
-        }
-        colIdx++;
-      }
-      return x;
+      var transforms =
+        variables.Select(
+          (_, colIdx) =>
+            new LinearTransformation(variables) { Addend = offsets[colIdx] * factors[colIdx], Multiplier = factors[colIdx] });
+      return dataset.ToArray(variables, transforms, rows);
     }
 
@@ -187,5 +181,5 @@
       double[,] inputData;
       if (IsCompatibilityLoaded) {
-        inputData = AlglibUtil.PrepareInputMatrix(dataset, allowedInputVariables, rows);
+        inputData = dataset.ToArray(allowedInputVariables, rows);
       } else {
         inputData = CreateScaledData(dataset, allowedInputVariables, rows, offsets, weights);
@@ -223,5 +217,5 @@
       double[,] inputData;
       if (IsCompatibilityLoaded) {
-        inputData = AlglibUtil.PrepareInputMatrix(dataset, allowedInputVariables, rows);
+        inputData = dataset.ToArray(allowedInputVariables, rows);
       } else {
         inputData = CreateScaledData(dataset, allowedInputVariables, rows, offsets, weights);
Index: /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/NeuralNetwork/NeuralNetworkClassification.cs
===================================================================
--- /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/NeuralNetwork/NeuralNetworkClassification.cs	(revision 15141)
+++ /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/NeuralNetwork/NeuralNetworkClassification.cs	(revision 15142)
@@ -184,5 +184,5 @@
       IEnumerable<string> allowedInputVariables = problemData.AllowedInputVariables;
       IEnumerable<int> rows = problemData.TrainingIndices;
-      double[,] inputMatrix = AlglibUtil.PrepareInputMatrix(dataset, allowedInputVariables.Concat(new string[] { targetVariable }), rows);
+      double[,] inputMatrix = dataset.ToArray(allowedInputVariables.Concat(new string[] { targetVariable }), rows);
       if (inputMatrix.Cast<double>().Any(x => double.IsNaN(x) || double.IsInfinity(x)))
         throw new NotSupportedException("Neural network classification does not support NaN or infinity values in the input dataset.");
Index: /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/NeuralNetwork/NeuralNetworkEnsembleClassification.cs
===================================================================
--- /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/NeuralNetwork/NeuralNetworkEnsembleClassification.cs	(revision 15141)
+++ /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/NeuralNetwork/NeuralNetworkEnsembleClassification.cs	(revision 15142)
@@ -125,7 +125,7 @@
     public NeuralNetworkEnsembleClassification()
       : base() {
-      var validHiddenLayerValues = new ItemSet<IntValue>(new IntValue[] { 
-        (IntValue)new IntValue(0).AsReadOnly(), 
-        (IntValue)new IntValue(1).AsReadOnly(), 
+      var validHiddenLayerValues = new ItemSet<IntValue>(new IntValue[] {
+        (IntValue)new IntValue(0).AsReadOnly(),
+        (IntValue)new IntValue(1).AsReadOnly(),
         (IntValue)new IntValue(2).AsReadOnly() });
       var selectedHiddenLayerValue = (from v in validHiddenLayerValues
@@ -170,5 +170,5 @@
       IEnumerable<string> allowedInputVariables = problemData.AllowedInputVariables;
       IEnumerable<int> rows = problemData.TrainingIndices;
-      double[,] inputMatrix = AlglibUtil.PrepareInputMatrix(dataset, allowedInputVariables.Concat(new string[] { targetVariable }), rows);
+      double[,] inputMatrix = dataset.ToArray(allowedInputVariables.Concat(new string[] { targetVariable }), rows);
       if (inputMatrix.Cast<double>().Any(x => double.IsNaN(x) || double.IsInfinity(x)))
         throw new NotSupportedException("Neural network ensemble classification does not support NaN or infinity values in the input dataset.");
Index: /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/NeuralNetwork/NeuralNetworkEnsembleModel.cs
===================================================================
--- /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/NeuralNetwork/NeuralNetworkEnsembleModel.cs	(revision 15141)
+++ /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/NeuralNetwork/NeuralNetworkEnsembleModel.cs	(revision 15142)
@@ -91,5 +91,5 @@
 
     public IEnumerable<double> GetEstimatedValues(IDataset dataset, IEnumerable<int> rows) {
-      double[,] inputData = AlglibUtil.PrepareInputMatrix(dataset, allowedInputVariables, rows);
+      double[,] inputData = dataset.ToArray(allowedInputVariables, rows);
 
       int n = inputData.GetLength(0);
@@ -108,5 +108,5 @@
 
     public override IEnumerable<double> GetEstimatedClassValues(IDataset dataset, IEnumerable<int> rows) {
-      double[,] inputData = AlglibUtil.PrepareInputMatrix(dataset, allowedInputVariables, rows);
+      double[,] inputData = dataset.ToArray(allowedInputVariables, rows);
 
       int n = inputData.GetLength(0);
Index: /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/NeuralNetwork/NeuralNetworkEnsembleRegression.cs
===================================================================
--- /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/NeuralNetwork/NeuralNetworkEnsembleRegression.cs	(revision 15141)
+++ /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/NeuralNetwork/NeuralNetworkEnsembleRegression.cs	(revision 15142)
@@ -169,5 +169,5 @@
       IEnumerable<string> allowedInputVariables = problemData.AllowedInputVariables;
       IEnumerable<int> rows = problemData.TrainingIndices;
-      double[,] inputMatrix = AlglibUtil.PrepareInputMatrix(dataset, allowedInputVariables.Concat(new string[] { targetVariable }), rows);
+      double[,] inputMatrix = dataset.ToArray(allowedInputVariables.Concat(new string[] { targetVariable }), rows);
       if (inputMatrix.Cast<double>().Any(x => double.IsNaN(x) || double.IsInfinity(x)))
         throw new NotSupportedException("Neural network ensemble regression does not support NaN or infinity values in the input dataset.");
Index: /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/NeuralNetwork/NeuralNetworkModel.cs
===================================================================
--- /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/NeuralNetwork/NeuralNetworkModel.cs	(revision 15141)
+++ /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/NeuralNetwork/NeuralNetworkModel.cs	(revision 15142)
@@ -95,5 +95,5 @@
 
     public IEnumerable<double> GetEstimatedValues(IDataset dataset, IEnumerable<int> rows) {
-      double[,] inputData = AlglibUtil.PrepareInputMatrix(dataset, allowedInputVariables, rows);
+      double[,] inputData = dataset.ToArray(allowedInputVariables, rows);
 
       int n = inputData.GetLength(0);
@@ -112,5 +112,5 @@
 
     public override IEnumerable<double> GetEstimatedClassValues(IDataset dataset, IEnumerable<int> rows) {
-      double[,] inputData = AlglibUtil.PrepareInputMatrix(dataset, allowedInputVariables, rows);
+      double[,] inputData = dataset.ToArray( allowedInputVariables, rows);
 
       int n = inputData.GetLength(0);
Index: /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/NeuralNetwork/NeuralNetworkRegression.cs
===================================================================
--- /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/NeuralNetwork/NeuralNetworkRegression.cs	(revision 15141)
+++ /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/NeuralNetwork/NeuralNetworkRegression.cs	(revision 15142)
@@ -185,5 +185,5 @@
       IEnumerable<string> allowedInputVariables = problemData.AllowedInputVariables;
       IEnumerable<int> rows = problemData.TrainingIndices;
-      double[,] inputMatrix = AlglibUtil.PrepareInputMatrix(dataset, allowedInputVariables.Concat(new string[] { targetVariable }), rows);
+      double[,] inputMatrix = dataset.ToArray(allowedInputVariables.Concat(new string[] { targetVariable }), rows);
       if (inputMatrix.Cast<double>().Any(x => double.IsNaN(x) || double.IsInfinity(x)))
         throw new NotSupportedException("Neural network regression does not support NaN or infinity values in the input dataset.");
Index: /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/RandomForest/RandomForestModel.cs
===================================================================
--- /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/RandomForest/RandomForestModel.cs	(revision 15141)
+++ /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/RandomForest/RandomForestModel.cs	(revision 15142)
@@ -139,5 +139,5 @@
 
     public IEnumerable<double> GetEstimatedValues(IDataset dataset, IEnumerable<int> rows) {
-      double[,] inputData = AlglibUtil.PrepareInputMatrix(dataset, AllowedInputVariables, rows);
+      double[,] inputData = dataset.ToArray(AllowedInputVariables, rows);
       AssertInputMatrix(inputData);
 
@@ -157,5 +157,5 @@
 
     public IEnumerable<double> GetEstimatedVariances(IDataset dataset, IEnumerable<int> rows) {
-      double[,] inputData = AlglibUtil.PrepareInputMatrix(dataset, AllowedInputVariables, rows);
+      double[,] inputData = dataset.ToArray(AllowedInputVariables, rows);
       AssertInputMatrix(inputData);
 
@@ -175,5 +175,5 @@
 
     public override IEnumerable<double> GetEstimatedClassValues(IDataset dataset, IEnumerable<int> rows) {
-      double[,] inputData = AlglibUtil.PrepareInputMatrix(dataset, AllowedInputVariables, rows);
+      double[,] inputData = dataset.ToArray(AllowedInputVariables, rows);
       AssertInputMatrix(inputData);
 
@@ -294,5 +294,5 @@
       out double rmsError, out double outOfBagRmsError, out double avgRelError, out double outOfBagAvgRelError) {
       var variables = problemData.AllowedInputVariables.Concat(new string[] { problemData.TargetVariable });
-      double[,] inputMatrix = AlglibUtil.PrepareInputMatrix(problemData.Dataset, variables, trainingIndices);
+      double[,] inputMatrix = problemData.Dataset.ToArray(variables, trainingIndices);
 
       alglib.dfreport rep;
@@ -316,5 +316,5 @@
 
       var variables = problemData.AllowedInputVariables.Concat(new string[] { problemData.TargetVariable });
-      double[,] inputMatrix = AlglibUtil.PrepareInputMatrix(problemData.Dataset, variables, trainingIndices);
+      double[,] inputMatrix = problemData.Dataset.ToArray(variables, trainingIndices);
 
       var classValues = problemData.ClassValues.ToArray();
Index: /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/TimeSeries/AutoregressiveModeling.cs
===================================================================
--- /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/TimeSeries/AutoregressiveModeling.cs	(revision 15141)
+++ /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/TimeSeries/AutoregressiveModeling.cs	(revision 15142)
@@ -115,22 +115,10 @@
       alglib.lrunpack(lm, out coefficients, out nFeatures);
 
-
-      ISymbolicExpressionTree tree = new SymbolicExpressionTree(new ProgramRootSymbol().CreateTreeNode());
-      ISymbolicExpressionTreeNode startNode = new StartSymbol().CreateTreeNode();
-      tree.Root.AddSubtree(startNode);
-      ISymbolicExpressionTreeNode addition = new Addition().CreateTreeNode();
-      startNode.AddSubtree(addition);
-
-      for (int i = 0; i < timeOffset; i++) {
-        LaggedVariableTreeNode node = (LaggedVariableTreeNode)new LaggedVariable().CreateTreeNode();
-        node.VariableName = targetVariable;
-        node.Weight = coefficients[i];
-        node.Lag = (i + 1) * -1;
-        addition.AddSubtree(node);
-      }
-
-      ConstantTreeNode cNode = (ConstantTreeNode)new Constant().CreateTreeNode();
-      cNode.Value = coefficients[coefficients.Length - 1];
-      addition.AddSubtree(cNode);
+      var tree = LinearModelToTreeConverter.CreateTree(
+        variableNames: Enumerable.Repeat(problemData.TargetVariable, nFeatures).ToArray(),
+        lags: Enumerable.Range(0, timeOffset).Select(i => (i + 1) * -1).ToArray(),
+        coefficients: coefficients.Take(nFeatures).ToArray(),
+        @const: coefficients[nFeatures]
+        );
 
       var interpreter = new SymbolicTimeSeriesPrognosisExpressionTreeInterpreter(problemData.TargetVariable);
Index: /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/kMeans/KMeansClustering.cs
===================================================================
--- /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/kMeans/KMeansClustering.cs	(revision 15141)
+++ /stable/HeuristicLab.Algorithms.DataAnalysis/3.4/kMeans/KMeansClustering.cs	(revision 15142)
@@ -90,5 +90,5 @@
       double[,] centers;
       int[] xyc;
-      double[,] inputMatrix = AlglibUtil.PrepareInputMatrix(dataset, allowedInputVariables, rows);
+      double[,] inputMatrix = dataset.ToArray(allowedInputVariables, rows);
       if (inputMatrix.Cast<double>().Any(x => double.IsNaN(x) || double.IsInfinity(x)))
         throw new NotSupportedException("k-Means clustering does not support NaN or infinity values in the input dataset.");
Index: /stable/HeuristicLab.Common/3.3/EnumerableExtensions.cs
===================================================================
--- /stable/HeuristicLab.Common/3.3/EnumerableExtensions.cs	(revision 15141)
+++ /stable/HeuristicLab.Common/3.3/EnumerableExtensions.cs	(revision 15142)
@@ -88,4 +88,12 @@
     }
 
+    public static IEnumerable<T> TakeEvery<T>(this IEnumerable<T> xs, int nth) {
+      int i = 0;
+      foreach (var x in xs) {
+        if (i % nth == 0) yield return x;
+        i++;
+      }
+    }
+
     /// <summary>
     /// Compute the n-ary cartesian product of arbitrarily many sequences: http://blogs.msdn.com/b/ericlippert/archive/2010/06/28/computing-a-cartesian-product-with-linq.aspx
Index: /stable/HeuristicLab.DataPreprocessing/3.4/PreprocessingTransformator.cs
===================================================================
--- /stable/HeuristicLab.DataPreprocessing/3.4/PreprocessingTransformator.cs	(revision 15141)
+++ /stable/HeuristicLab.DataPreprocessing/3.4/PreprocessingTransformator.cs	(revision 15142)
@@ -113,5 +113,5 @@
       // don't apply when the check fails
       if (success)
-        return transformation.Apply(data);
+        return transformation.ConfigureAndApply(data);
       else
         return data;
Index: /stable/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression.Views/3.4/SymbolicRegressionSolutionErrorCharacteristicsCurveView.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression.Views/3.4/SymbolicRegressionSolutionErrorCharacteristicsCurveView.cs	(revision 15141)
+++ /stable/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression.Views/3.4/SymbolicRegressionSolutionErrorCharacteristicsCurveView.cs	(revision 15142)
@@ -48,7 +48,5 @@
       if (!problemData.TrainingIndices.Any()) return null; // don't create an LR model if the problem does not have a training set (e.g. loaded into an existing model)
 
-      var usedVariables = Content.Model.SymbolicExpressionTree.IterateNodesPostfix()
-        .OfType<IVariableTreeNode>()
-        .Select(node => node.VariableName).ToArray();
+      var usedVariables = Content.Model.VariablesUsedForPrediction;
 
       var usedDoubleVariables = usedVariables
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 15141)
+++ /stable/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SingleObjective/Evaluators/SymbolicRegressionConstantOptimizationEvaluator.cs	(revision 15142)
@@ -164,9 +164,9 @@
       // A dictionary is used to find parameters
       double[] initialConstants;
-      var parameters = new List<TreeToAutoDiffTermTransformator.DataForVariable>();
-
-      TreeToAutoDiffTermTransformator.ParametricFunction func;
-      TreeToAutoDiffTermTransformator.ParametricFunctionGradient func_grad;
-      if (!TreeToAutoDiffTermTransformator.TryTransformToAutoDiff(tree, updateVariableWeights, out parameters, out initialConstants, out func, out func_grad))
+      var parameters = new List<TreeToAutoDiffTermConverter.DataForVariable>();
+
+      TreeToAutoDiffTermConverter.ParametricFunction func;
+      TreeToAutoDiffTermConverter.ParametricFunctionGradient func_grad;
+      if (!TreeToAutoDiffTermConverter.TryConvertToAutoDiff(tree, updateVariableWeights, 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 
@@ -175,5 +175,5 @@
 
       //extract inital constants
-      double[] c = new double[initialConstants.Length];
+      double[] c = new double[initialConstants.Length + 2];
       {
         c[0] = 0.0;
@@ -254,5 +254,5 @@
     }
 
-    private static alglib.ndimensional_pfunc CreatePFunc(TreeToAutoDiffTermTransformator.ParametricFunction func) {
+    private static alglib.ndimensional_pfunc CreatePFunc(TreeToAutoDiffTermConverter.ParametricFunction func) {
       return (double[] c, double[] x, ref double fx, object o) => {
         fx = func(c, x);
@@ -260,5 +260,5 @@
     }
 
-    private static alglib.ndimensional_pgrad CreatePGrad(TreeToAutoDiffTermTransformator.ParametricFunctionGradient func_grad) {
+    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);
@@ -268,5 +268,5 @@
     }
     public static bool CanOptimizeConstants(ISymbolicExpressionTree tree) {
-      return TreeToAutoDiffTermTransformator.IsCompatible(tree);
+      return TreeToAutoDiffTermConverter.IsCompatible(tree);
     }
   }
Index: /stable/HeuristicLab.Problems.DataAnalysis.Symbolic.Views/3.4/InteractiveSymbolicDataAnalysisSolutionSimplifierView.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis.Symbolic.Views/3.4/InteractiveSymbolicDataAnalysisSolutionSimplifierView.cs	(revision 15141)
+++ /stable/HeuristicLab.Problems.DataAnalysis.Symbolic.Views/3.4/InteractiveSymbolicDataAnalysisSolutionSimplifierView.cs	(revision 15142)
@@ -266,5 +266,5 @@
 
     private void btnSimplify_Click(object sender, EventArgs e) {
-      var simplifier = new SymbolicDataAnalysisExpressionTreeSimplifier();
+      var simplifier = new TreeSimplifier();
       var simplifiedExpressionTree = simplifier.Simplify(Content.Model.SymbolicExpressionTree);
       UpdateModel(simplifiedExpressionTree);
Index: /stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Converters/Convert.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Converters/Convert.cs	(revision 15142)
+++ /stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Converters/Convert.cs	(revision 15142)
@@ -0,0 +1,55 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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 AutoDiff;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
+
+  ///  static class which provides methods for all converters for trees for convenience 
+  public static class Convert {
+    public static void ConvertToAutoDiff(ISymbolicExpressionTree tree, bool makeVariableWeightsVariable,
+      out List<TreeToAutoDiffTermConverter.DataForVariable> parameters, out double[] initialConstants,
+      out TreeToAutoDiffTermConverter.ParametricFunction func,
+      out TreeToAutoDiffTermConverter.ParametricFunctionGradient func_grad) {
+      var success = TreeToAutoDiffTermConverter.TryConvertToAutoDiff(tree, makeVariableWeightsVariable, out parameters, 
+        out initialConstants, out func, out func_grad);
+      if (!success) throw new ArgumentException("Cannot convert tree to AutoDiff term.");
+    }
+
+    public static ISymbolicExpressionTree Simplify(ISymbolicExpressionTree tree) {
+      var simplifier = new TreeSimplifier();
+      return simplifier.Simplify(tree);
+    }
+
+    public static ISymbolicExpressionTree CreateLinearModel(string[] variableNames, double[] coefficients,
+      double @const = 0) {
+      return LinearModelToTreeConverter.CreateTree(variableNames, coefficients, @const);
+    }
+    public static ISymbolicExpressionTree CreateLinearModel(string[] variableNames, int[] lags, double[] coefficients,
+      double @const = 0) {
+      return LinearModelToTreeConverter.CreateTree(variableNames, coefficients, @const);
+    }
+  }
+}
Index: /stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Converters/LinearModelToTreeConverter.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Converters/LinearModelToTreeConverter.cs	(revision 15142)
+++ /stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Converters/LinearModelToTreeConverter.cs	(revision 15142)
@@ -0,0 +1,126 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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 HeuristicLab.Common;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
+  public static class LinearModelToTreeConverter {
+    public static ISymbolicExpressionTree CreateTree(string[] variableNames, double[] coefficients,
+      double @const = 0) {
+      return CreateTree(variableNames, new int[variableNames.Length], coefficients, @const);
+    }
+
+    public static ISymbolicExpressionTree CreateTree(
+      IEnumerable<KeyValuePair<string, IEnumerable<string>>> factors, double[] factorCoefficients,
+      string[] variableNames, double[] coefficients,
+      double @const = 0) {
+      if (factorCoefficients.Length == 0 && coefficients.Length == 0) throw new ArgumentException();
+      ISymbolicExpressionTree p1 = null;
+      if (coefficients.Length > 0) {
+        p1 = CreateTree(variableNames, new int[variableNames.Length], coefficients, @const);
+        if (factorCoefficients.Length == 0)
+          return p1;
+      }
+      if (factorCoefficients.Length > 0) {
+        var p2 = CreateTree(factors, factorCoefficients);
+        if (p1 == null) return p2;
+
+        // combine
+        ISymbolicExpressionTreeNode add = p1.Root.GetSubtree(0).GetSubtree(0);
+        foreach (var binFactorNode in p2.IterateNodesPrefix().OfType<BinaryFactorVariableTreeNode>())
+          add.AddSubtree(binFactorNode);
+        return p1;
+      }
+      throw new ArgumentException();
+    }
+
+    public static ISymbolicExpressionTree CreateTree(string[] variableNames, int[] lags, double[] coefficients,
+      double @const = 0) {
+      if (variableNames.Length == 0 ||
+        variableNames.Length != coefficients.Length ||
+        variableNames.Length != lags.Length)
+        throw new ArgumentException("The length of the variable names, lags, and coefficients vectors must match");
+
+      ISymbolicExpressionTree tree = new SymbolicExpressionTree(new ProgramRootSymbol().CreateTreeNode());
+      ISymbolicExpressionTreeNode startNode = new StartSymbol().CreateTreeNode();
+      tree.Root.AddSubtree(startNode);
+      ISymbolicExpressionTreeNode addition = new Addition().CreateTreeNode();
+      startNode.AddSubtree(addition);
+
+      for (int i = 0; i < variableNames.Length; i++) {
+        if (lags[i] == 0) {
+          VariableTreeNode vNode = (VariableTreeNode)new Variable().CreateTreeNode();
+          vNode.VariableName = variableNames[i];
+          vNode.Weight = coefficients[i];
+          addition.AddSubtree(vNode);
+        } else {
+          LaggedVariableTreeNode vNode = (LaggedVariableTreeNode)new LaggedVariable().CreateTreeNode();
+          vNode.VariableName = variableNames[i];
+          vNode.Weight = coefficients[i];
+          vNode.Lag = lags[i];
+          addition.AddSubtree(vNode);
+        }
+      }
+
+      if (!@const.IsAlmost(0.0)) {
+        ConstantTreeNode cNode = (ConstantTreeNode)new Constant().CreateTreeNode();
+        cNode.Value = @const;
+        addition.AddSubtree(cNode);
+      }
+      return tree;
+    }
+
+    public static ISymbolicExpressionTree CreateTree(IEnumerable<KeyValuePair<string, IEnumerable<string>>> factors,
+      double[] factorCoefficients,
+      double @const = 0) {
+
+      ISymbolicExpressionTree tree = new SymbolicExpressionTree(new ProgramRootSymbol().CreateTreeNode());
+      ISymbolicExpressionTreeNode startNode = new StartSymbol().CreateTreeNode();
+      tree.Root.AddSubtree(startNode);
+      ISymbolicExpressionTreeNode addition = new Addition().CreateTreeNode();
+      startNode.AddSubtree(addition);
+
+      int i = 0;
+      foreach (var factor in factors) {
+        var varName = factor.Key;
+        foreach (var factorValue in factor.Value) {
+          var node = (BinaryFactorVariableTreeNode)new BinaryFactorVariable().CreateTreeNode();
+          node.VariableValue = factorValue;
+          node.VariableName = varName;
+          node.Weight = factorCoefficients[i];
+          addition.AddSubtree(node);
+          i++;
+        }
+      }
+
+      if (!@const.IsAlmost(0.0)) {
+        ConstantTreeNode cNode = (ConstantTreeNode)new Constant().CreateTreeNode();
+        cNode.Value = @const;
+        addition.AddSubtree(cNode);
+      }
+      return tree;
+    }
+  }
+}
Index: /stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Converters/TreeSimplifier.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Converters/TreeSimplifier.cs	(revision 15142)
+++ /stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Converters/TreeSimplifier.cs	(revision 15142)
@@ -0,0 +1,1341 @@
+﻿#region License Information
+
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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 HeuristicLab.Common;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
+  /// <summary>
+  /// Simplifier for symbolic expressions
+  /// </summary>
+  public class TreeSimplifier {
+    private Addition addSymbol = new Addition();
+    private Multiplication mulSymbol = new Multiplication();
+    private Division divSymbol = new Division();
+    private Constant constSymbol = new Constant();
+    private Variable varSymbol = new Variable();
+    private Logarithm logSymbol = new Logarithm();
+    private Exponential expSymbol = new Exponential();
+    private Root rootSymbol = new Root();
+    private Square sqrSymbol = new Square();
+    private SquareRoot sqrtSymbol = new SquareRoot();
+    private Power powSymbol = new Power();
+    private Sine sineSymbol = new Sine();
+    private Cosine cosineSymbol = new Cosine();
+    private Tangent tanSymbol = new Tangent();
+    private IfThenElse ifThenElseSymbol = new IfThenElse();
+    private And andSymbol = new And();
+    private Or orSymbol = new Or();
+    private Not notSymbol = new Not();
+    private GreaterThan gtSymbol = new GreaterThan();
+    private LessThan ltSymbol = new LessThan();
+    private Integral integralSymbol = new Integral();
+    private LaggedVariable laggedVariableSymbol = new LaggedVariable();
+    private TimeLag timeLagSymbol = new TimeLag();
+
+    public ISymbolicExpressionTree Simplify(ISymbolicExpressionTree originalTree) {
+      var clone = (ISymbolicExpressionTreeNode)originalTree.Root.Clone();
+      // macro expand (initially no argument trees)
+      var macroExpandedTree = MacroExpand(clone, clone.GetSubtree(0), new List<ISymbolicExpressionTreeNode>());
+      ISymbolicExpressionTreeNode rootNode = (new ProgramRootSymbol()).CreateTreeNode();
+      rootNode.AddSubtree(GetSimplifiedTree(macroExpandedTree));
+
+#if DEBUG
+      // check that each node is only referenced once
+      var nodes = rootNode.IterateNodesPrefix().ToArray();
+      foreach(var n in nodes) if(nodes.Count(ni => ni == n) > 1) throw new InvalidOperationException();
+#endif
+      return new SymbolicExpressionTree(rootNode);
+    }
+
+    // the argumentTrees list contains already expanded trees used as arguments for invocations
+    private ISymbolicExpressionTreeNode MacroExpand(ISymbolicExpressionTreeNode root, ISymbolicExpressionTreeNode node,
+      IList<ISymbolicExpressionTreeNode> argumentTrees) {
+      List<ISymbolicExpressionTreeNode> subtrees = new List<ISymbolicExpressionTreeNode>(node.Subtrees);
+      while (node.SubtreeCount > 0) node.RemoveSubtree(0);
+      if (node.Symbol is InvokeFunction) {
+        var invokeSym = node.Symbol as InvokeFunction;
+        var defunNode = FindFunctionDefinition(root, invokeSym.FunctionName);
+        var macroExpandedArguments = new List<ISymbolicExpressionTreeNode>();
+        foreach (var subtree in subtrees) {
+          macroExpandedArguments.Add(MacroExpand(root, subtree, argumentTrees));
+        }
+        return MacroExpand(root, defunNode, macroExpandedArguments);
+      } else if (node.Symbol is Argument) {
+        var argSym = node.Symbol as Argument;
+        // return the correct argument sub-tree (already macro-expanded)
+        return (SymbolicExpressionTreeNode)argumentTrees[argSym.ArgumentIndex].Clone();
+      } else {
+        // recursive application
+        foreach (var subtree in subtrees) {
+          node.AddSubtree(MacroExpand(root, subtree, argumentTrees));
+        }
+        return node;
+      }
+    }
+
+    private ISymbolicExpressionTreeNode FindFunctionDefinition(ISymbolicExpressionTreeNode root, string functionName) {
+      foreach (var subtree in root.Subtrees.OfType<DefunTreeNode>()) {
+        if (subtree.FunctionName == functionName) return subtree.GetSubtree(0);
+      }
+
+      throw new ArgumentException("Definition of function " + functionName + " not found.");
+    }
+
+    #region symbol predicates
+
+    // arithmetic
+    private bool IsDivision(ISymbolicExpressionTreeNode node) {
+      return node.Symbol is Division;
+    }
+
+    private bool IsMultiplication(ISymbolicExpressionTreeNode node) {
+      return node.Symbol is Multiplication;
+    }
+
+    private bool IsSubtraction(ISymbolicExpressionTreeNode node) {
+      return node.Symbol is Subtraction;
+    }
+
+    private bool IsAddition(ISymbolicExpressionTreeNode node) {
+      return node.Symbol is Addition;
+    }
+
+    private bool IsAverage(ISymbolicExpressionTreeNode node) {
+      return node.Symbol is Average;
+    }
+
+    // exponential
+    private bool IsLog(ISymbolicExpressionTreeNode node) {
+      return node.Symbol is Logarithm;
+    }
+
+    private bool IsExp(ISymbolicExpressionTreeNode node) {
+      return node.Symbol is Exponential;
+    }
+
+    private bool IsRoot(ISymbolicExpressionTreeNode node) {
+      return node.Symbol is Root;
+    }
+
+    private bool IsSquare(ISymbolicExpressionTreeNode node) {
+      return node.Symbol is Square;
+    }
+
+    private bool IsSquareRoot(ISymbolicExpressionTreeNode node) {
+      return node.Symbol is SquareRoot;
+    }
+
+    private bool IsPower(ISymbolicExpressionTreeNode node) {
+      return node.Symbol is Power;
+    }
+
+    // trigonometric
+    private bool IsSine(ISymbolicExpressionTreeNode node) {
+      return node.Symbol is Sine;
+    }
+
+    private bool IsCosine(ISymbolicExpressionTreeNode node) {
+      return node.Symbol is Cosine;
+    }
+
+    private bool IsTangent(ISymbolicExpressionTreeNode node) {
+      return node.Symbol is Tangent;
+    }
+
+    // boolean
+    private bool IsIfThenElse(ISymbolicExpressionTreeNode node) {
+      return node.Symbol is IfThenElse;
+    }
+
+    private bool IsAnd(ISymbolicExpressionTreeNode node) {
+      return node.Symbol is And;
+    }
+
+    private bool IsOr(ISymbolicExpressionTreeNode node) {
+      return node.Symbol is Or;
+    }
+
+    private bool IsNot(ISymbolicExpressionTreeNode node) {
+      return node.Symbol is Not;
+    }
+
+    // comparison
+    private bool IsGreaterThan(ISymbolicExpressionTreeNode node) {
+      return node.Symbol is GreaterThan;
+    }
+
+    private bool IsLessThan(ISymbolicExpressionTreeNode node) {
+      return node.Symbol is LessThan;
+    }
+
+    private bool IsBoolean(ISymbolicExpressionTreeNode node) {
+      return
+        node.Symbol is GreaterThan ||
+        node.Symbol is LessThan ||
+        node.Symbol is And ||
+        node.Symbol is Or;
+    }
+
+    // terminals
+    private bool IsVariable(ISymbolicExpressionTreeNode node) {
+      return node.Symbol is Variable;
+    }
+
+    private bool IsVariableBase(ISymbolicExpressionTreeNode node) {
+      return node is VariableTreeNodeBase;
+    }
+
+    private bool IsFactor(ISymbolicExpressionTreeNode node) {
+      return node is FactorVariableTreeNode;
+    }
+
+    private bool IsBinFactor(ISymbolicExpressionTreeNode node) {
+      return node is BinaryFactorVariableTreeNode;
+    }
+
+    private bool IsConstant(ISymbolicExpressionTreeNode node) {
+      return node.Symbol is Constant;
+    }
+
+    // dynamic
+    private bool IsTimeLag(ISymbolicExpressionTreeNode node) {
+      return node.Symbol is TimeLag;
+    }
+
+    private bool IsIntegral(ISymbolicExpressionTreeNode node) {
+      return node.Symbol is Integral;
+    }
+
+    #endregion
+
+    /// <summary>
+    /// Creates a new simplified tree
+    /// </summary>
+    /// <param name="original"></param>
+    /// <returns></returns>
+    public ISymbolicExpressionTreeNode GetSimplifiedTree(ISymbolicExpressionTreeNode original) {
+      if (IsConstant(original) || IsVariableBase(original)) {
+        return (ISymbolicExpressionTreeNode)original.Clone();
+      } else if (IsAddition(original)) {
+        return SimplifyAddition(original);
+      } else if (IsSubtraction(original)) {
+        return SimplifySubtraction(original);
+      } else if (IsMultiplication(original)) {
+        return SimplifyMultiplication(original);
+      } else if (IsDivision(original)) {
+        return SimplifyDivision(original);
+      } else if (IsAverage(original)) {
+        return SimplifyAverage(original);
+      } else if (IsLog(original)) {
+        return SimplifyLog(original);
+      } else if (IsExp(original)) {
+        return SimplifyExp(original);
+      } else if (IsSquare(original)) {
+        return SimplifySquare(original);
+      } else if (IsSquareRoot(original)) {
+        return SimplifySquareRoot(original);
+      } else if (IsPower(original)) {
+        return SimplifyPower(original);
+      } else if (IsRoot(original)) {
+        return SimplifyRoot(original);
+      } else if (IsSine(original)) {
+        return SimplifySine(original);
+      } else if (IsCosine(original)) {
+        return SimplifyCosine(original);
+      } else if (IsTangent(original)) {
+        return SimplifyTangent(original);
+      } else if (IsIfThenElse(original)) {
+        return SimplifyIfThenElse(original);
+      } else if (IsGreaterThan(original)) {
+        return SimplifyGreaterThan(original);
+      } else if (IsLessThan(original)) {
+        return SimplifyLessThan(original);
+      } else if (IsAnd(original)) {
+        return SimplifyAnd(original);
+      } else if (IsOr(original)) {
+        return SimplifyOr(original);
+      } else if (IsNot(original)) {
+        return SimplifyNot(original);
+      } else if (IsTimeLag(original)) {
+        return SimplifyTimeLag(original);
+      } else if (IsIntegral(original)) {
+        return SimplifyIntegral(original);
+      } else {
+        return SimplifyAny(original);
+      }
+    }
+
+    #region specific simplification routines
+
+    private ISymbolicExpressionTreeNode SimplifyAny(ISymbolicExpressionTreeNode original) {
+      // can't simplify this function but simplify all subtrees 
+      List<ISymbolicExpressionTreeNode> subtrees = new List<ISymbolicExpressionTreeNode>(original.Subtrees);
+      while (original.Subtrees.Count() > 0) original.RemoveSubtree(0);
+      var clone = (SymbolicExpressionTreeNode)original.Clone();
+      List<ISymbolicExpressionTreeNode> simplifiedSubtrees = new List<ISymbolicExpressionTreeNode>();
+      foreach (var subtree in subtrees) {
+        simplifiedSubtrees.Add(GetSimplifiedTree(subtree));
+        original.AddSubtree(subtree);
+      }
+      foreach (var simplifiedSubtree in simplifiedSubtrees) {
+        clone.AddSubtree(simplifiedSubtree);
+      }
+      if (simplifiedSubtrees.TrueForAll(t => IsConstant(t))) {
+        SimplifyConstantExpression(clone);
+      }
+      return clone;
+    }
+
+    private ISymbolicExpressionTreeNode SimplifyConstantExpression(ISymbolicExpressionTreeNode original) {
+      // not yet implemented
+      return original;
+    }
+
+    private ISymbolicExpressionTreeNode SimplifyAverage(ISymbolicExpressionTreeNode original) {
+      if (original.Subtrees.Count() == 1) {
+        return GetSimplifiedTree(original.GetSubtree(0));
+      } else {
+        // simplify expressions x0..xn
+        // make sum(x0..xn) / n
+        var sum = original.Subtrees
+          .Select(GetSimplifiedTree)
+          .Aggregate(MakeSum);
+        return MakeFraction(sum, MakeConstant(original.Subtrees.Count()));
+      }
+    }
+
+    private ISymbolicExpressionTreeNode SimplifyDivision(ISymbolicExpressionTreeNode original) {
+      if (original.Subtrees.Count() == 1) {
+        return Invert(GetSimplifiedTree(original.GetSubtree(0)));
+      } else {
+        // simplify expressions x0..xn
+        // make multiplication (x0 * 1/(x1 * x1 * .. * xn))
+        var first = original.GetSubtree(0);
+        var second = original.GetSubtree(1);
+        var remaining = original.Subtrees.Skip(2);
+        return
+          MakeProduct(GetSimplifiedTree(first),
+            Invert(remaining.Aggregate(GetSimplifiedTree(second), (a, b) => MakeProduct(a, GetSimplifiedTree(b)))));
+      }
+    }
+
+    private ISymbolicExpressionTreeNode SimplifyMultiplication(ISymbolicExpressionTreeNode original) {
+      if (original.Subtrees.Count() == 1) {
+        return GetSimplifiedTree(original.GetSubtree(0));
+      } else {
+        return original.Subtrees
+          .Select(GetSimplifiedTree)
+          .Aggregate(MakeProduct);
+      }
+    }
+
+    private ISymbolicExpressionTreeNode SimplifySubtraction(ISymbolicExpressionTreeNode original) {
+      if (original.Subtrees.Count() == 1) {
+        return Negate(GetSimplifiedTree(original.GetSubtree(0)));
+      } else {
+        // simplify expressions x0..xn
+        // make addition (x0,-x1..-xn)
+        var first = original.Subtrees.First();
+        var remaining = original.Subtrees.Skip(1);
+        return remaining.Aggregate(GetSimplifiedTree(first), (a, b) => MakeSum(a, Negate(GetSimplifiedTree(b))));
+      }
+    }
+
+    private ISymbolicExpressionTreeNode SimplifyAddition(ISymbolicExpressionTreeNode original) {
+      if (original.Subtrees.Count() == 1) {
+        return GetSimplifiedTree(original.GetSubtree(0));
+      } else {
+        // simplify expression x0..xn
+        // make addition (x0..xn)
+        return original.Subtrees
+          .Select(GetSimplifiedTree)
+          .Aggregate(MakeSum);
+      }
+    }
+
+    private ISymbolicExpressionTreeNode SimplifyNot(ISymbolicExpressionTreeNode original) {
+      return MakeNot(GetSimplifiedTree(original.GetSubtree(0)));
+    }
+
+    private ISymbolicExpressionTreeNode SimplifyOr(ISymbolicExpressionTreeNode original) {
+      return original.Subtrees
+        .Select(GetSimplifiedTree)
+        .Aggregate(MakeOr);
+    }
+
+    private ISymbolicExpressionTreeNode SimplifyAnd(ISymbolicExpressionTreeNode original) {
+      return original.Subtrees
+        .Select(GetSimplifiedTree)
+        .Aggregate(MakeAnd);
+    }
+
+    private ISymbolicExpressionTreeNode SimplifyLessThan(ISymbolicExpressionTreeNode original) {
+      return MakeLessThan(GetSimplifiedTree(original.GetSubtree(0)), GetSimplifiedTree(original.GetSubtree(1)));
+    }
+
+    private ISymbolicExpressionTreeNode SimplifyGreaterThan(ISymbolicExpressionTreeNode original) {
+      return MakeGreaterThan(GetSimplifiedTree(original.GetSubtree(0)), GetSimplifiedTree(original.GetSubtree(1)));
+    }
+
+    private ISymbolicExpressionTreeNode SimplifyIfThenElse(ISymbolicExpressionTreeNode original) {
+      return MakeIfThenElse(GetSimplifiedTree(original.GetSubtree(0)), GetSimplifiedTree(original.GetSubtree(1)),
+        GetSimplifiedTree(original.GetSubtree(2)));
+    }
+
+    private ISymbolicExpressionTreeNode SimplifyTangent(ISymbolicExpressionTreeNode original) {
+      return MakeTangent(GetSimplifiedTree(original.GetSubtree(0)));
+    }
+
+    private ISymbolicExpressionTreeNode SimplifyCosine(ISymbolicExpressionTreeNode original) {
+      return MakeCosine(GetSimplifiedTree(original.GetSubtree(0)));
+    }
+
+    private ISymbolicExpressionTreeNode SimplifySine(ISymbolicExpressionTreeNode original) {
+      return MakeSine(GetSimplifiedTree(original.GetSubtree(0)));
+    }
+
+    private ISymbolicExpressionTreeNode SimplifyExp(ISymbolicExpressionTreeNode original) {
+      return MakeExp(GetSimplifiedTree(original.GetSubtree(0)));
+    }
+
+    private ISymbolicExpressionTreeNode SimplifySquare(ISymbolicExpressionTreeNode original) {
+      return MakeSquare(GetSimplifiedTree(original.GetSubtree(0)));
+    }
+
+    private ISymbolicExpressionTreeNode SimplifySquareRoot(ISymbolicExpressionTreeNode original) {
+      return MakeSquareRoot(GetSimplifiedTree(original.GetSubtree(0)));
+    }
+
+    private ISymbolicExpressionTreeNode SimplifyLog(ISymbolicExpressionTreeNode original) {
+      return MakeLog(GetSimplifiedTree(original.GetSubtree(0)));
+    }
+
+    private ISymbolicExpressionTreeNode SimplifyRoot(ISymbolicExpressionTreeNode original) {
+      return MakeRoot(GetSimplifiedTree(original.GetSubtree(0)), GetSimplifiedTree(original.GetSubtree(1)));
+    }
+
+    private ISymbolicExpressionTreeNode SimplifyPower(ISymbolicExpressionTreeNode original) {
+      return MakePower(GetSimplifiedTree(original.GetSubtree(0)), GetSimplifiedTree(original.GetSubtree(1)));
+    }
+
+    private ISymbolicExpressionTreeNode SimplifyTimeLag(ISymbolicExpressionTreeNode original) {
+      var laggedTreeNode = original as ILaggedTreeNode;
+      var simplifiedSubtree = GetSimplifiedTree(original.GetSubtree(0));
+      if (!ContainsVariableCondition(simplifiedSubtree)) {
+        return AddLagToDynamicNodes(simplifiedSubtree, laggedTreeNode.Lag);
+      } else {
+        return MakeTimeLag(simplifiedSubtree, laggedTreeNode.Lag);
+      }
+    }
+
+    private ISymbolicExpressionTreeNode SimplifyIntegral(ISymbolicExpressionTreeNode original) {
+      var laggedTreeNode = original as ILaggedTreeNode;
+      var simplifiedSubtree = GetSimplifiedTree(original.GetSubtree(0));
+      if (IsConstant(simplifiedSubtree)) {
+        return GetSimplifiedTree(MakeProduct(simplifiedSubtree, MakeConstant(-laggedTreeNode.Lag)));
+      } else {
+        return MakeIntegral(simplifiedSubtree, laggedTreeNode.Lag);
+      }
+    }
+
+    #endregion
+
+    #region low level tree restructuring
+
+    private ISymbolicExpressionTreeNode MakeTimeLag(ISymbolicExpressionTreeNode subtree, int lag) {
+      if (lag == 0) return subtree;
+      if (IsConstant(subtree)) return subtree;
+      var lagNode = (LaggedTreeNode)timeLagSymbol.CreateTreeNode();
+      lagNode.Lag = lag;
+      lagNode.AddSubtree(subtree);
+      return lagNode;
+    }
+
+    private ISymbolicExpressionTreeNode MakeIntegral(ISymbolicExpressionTreeNode subtree, int lag) {
+      if (lag == 0) return subtree;
+      else if (lag == -1 || lag == 1) {
+        return MakeSum(subtree, AddLagToDynamicNodes((ISymbolicExpressionTreeNode)subtree.Clone(), lag));
+      } else {
+        var node = (LaggedTreeNode)integralSymbol.CreateTreeNode();
+        node.Lag = lag;
+        node.AddSubtree(subtree);
+        return node;
+      }
+    }
+
+    private ISymbolicExpressionTreeNode MakeNot(ISymbolicExpressionTreeNode t) {
+      if (IsConstant(t)) {
+        var constNode = t as ConstantTreeNode;
+        if (constNode.Value > 0) return MakeConstant(-1.0);
+        else return MakeConstant(1.0);
+      } else if (IsNot(t)) {
+        return t.GetSubtree(0);
+      } else if (!IsBoolean(t)) {
+        var gtNode = gtSymbol.CreateTreeNode();
+        gtNode.AddSubtree(t);
+        gtNode.AddSubtree(MakeConstant(0.0));
+        var notNode = notSymbol.CreateTreeNode();
+        notNode.AddSubtree(gtNode);
+        return notNode;
+      } else {
+        var notNode = notSymbol.CreateTreeNode();
+        notNode.AddSubtree(t);
+        return notNode;
+      }
+    }
+
+    private ISymbolicExpressionTreeNode MakeOr(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) {
+      if (IsConstant(a) && IsConstant(b)) {
+        var constA = a as ConstantTreeNode;
+        var constB = b as ConstantTreeNode;
+        if (constA.Value > 0.0 || constB.Value > 0.0) {
+          return MakeConstant(1.0);
+        } else {
+          return MakeConstant(-1.0);
+        }
+      } else if (IsConstant(a)) {
+        return MakeOr(b, a);
+      } else if (IsConstant(b)) {
+        var constT = b as ConstantTreeNode;
+        if (constT.Value > 0.0) {
+          // boolean expression is necessarily true
+          return MakeConstant(1.0);
+        } else {
+          // the constant value has no effect on the result of the boolean condition so we can drop the constant term
+          var orNode = orSymbol.CreateTreeNode();
+          orNode.AddSubtree(a);
+          return orNode;
+        }
+      } else {
+        var orNode = orSymbol.CreateTreeNode();
+        orNode.AddSubtree(a);
+        orNode.AddSubtree(b);
+        return orNode;
+      }
+    }
+
+    private ISymbolicExpressionTreeNode MakeAnd(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) {
+      if (IsConstant(a) && IsConstant(b)) {
+        var constA = a as ConstantTreeNode;
+        var constB = b as ConstantTreeNode;
+        if (constA.Value > 0.0 && constB.Value > 0.0) {
+          return MakeConstant(1.0);
+        } else {
+          return MakeConstant(-1.0);
+        }
+      } else if (IsConstant(a)) {
+        return MakeAnd(b, a);
+      } else if (IsConstant(b)) {
+        var constB = b as ConstantTreeNode;
+        if (constB.Value > 0.0) {
+          // the constant value has no effect on the result of the boolean condition so we can drop the constant term
+          var andNode = andSymbol.CreateTreeNode();
+          andNode.AddSubtree(a);
+          return andNode;
+        } else {
+          // boolean expression is necessarily false
+          return MakeConstant(-1.0);
+        }
+      } else {
+        var andNode = andSymbol.CreateTreeNode();
+        andNode.AddSubtree(a);
+        andNode.AddSubtree(b);
+        return andNode;
+      }
+    }
+
+    private ISymbolicExpressionTreeNode MakeLessThan(ISymbolicExpressionTreeNode leftSide,
+      ISymbolicExpressionTreeNode rightSide) {
+      if (IsConstant(leftSide) && IsConstant(rightSide)) {
+        var lsConst = leftSide as ConstantTreeNode;
+        var rsConst = rightSide as ConstantTreeNode;
+        if (lsConst.Value < rsConst.Value) return MakeConstant(1.0);
+        else return MakeConstant(-1.0);
+      } else {
+        var ltNode = ltSymbol.CreateTreeNode();
+        ltNode.AddSubtree(leftSide);
+        ltNode.AddSubtree(rightSide);
+        return ltNode;
+      }
+    }
+
+    private ISymbolicExpressionTreeNode MakeGreaterThan(ISymbolicExpressionTreeNode leftSide,
+      ISymbolicExpressionTreeNode rightSide) {
+      if (IsConstant(leftSide) && IsConstant(rightSide)) {
+        var lsConst = leftSide as ConstantTreeNode;
+        var rsConst = rightSide as ConstantTreeNode;
+        if (lsConst.Value > rsConst.Value) return MakeConstant(1.0);
+        else return MakeConstant(-1.0);
+      } else {
+        var gtNode = gtSymbol.CreateTreeNode();
+        gtNode.AddSubtree(leftSide);
+        gtNode.AddSubtree(rightSide);
+        return gtNode;
+      }
+    }
+
+    private ISymbolicExpressionTreeNode MakeIfThenElse(ISymbolicExpressionTreeNode condition,
+      ISymbolicExpressionTreeNode trueBranch, ISymbolicExpressionTreeNode falseBranch) {
+      if (IsConstant(condition)) {
+        var constT = condition as ConstantTreeNode;
+        if (constT.Value > 0.0) return trueBranch;
+        else return falseBranch;
+      } else {
+        var ifNode = ifThenElseSymbol.CreateTreeNode();
+        if (IsBoolean(condition)) {
+          ifNode.AddSubtree(condition);
+        } else {
+          var gtNode = gtSymbol.CreateTreeNode();
+          gtNode.AddSubtree(condition);
+          gtNode.AddSubtree(MakeConstant(0.0));
+          ifNode.AddSubtree(gtNode);
+        }
+        ifNode.AddSubtree(trueBranch);
+        ifNode.AddSubtree(falseBranch);
+        return ifNode;
+      }
+    }
+
+    private ISymbolicExpressionTreeNode MakeSine(ISymbolicExpressionTreeNode node) {
+      if (IsConstant(node)) {
+        var constT = node as ConstantTreeNode;
+        return MakeConstant(Math.Sin(constT.Value));
+      } else if (IsFactor(node)) {
+        var factor = node as FactorVariableTreeNode;
+        return MakeFactor(factor.Symbol, factor.VariableName, factor.Weights.Select(Math.Sin));
+      } else if (IsBinFactor(node)) {
+        var binFactor = node as BinaryFactorVariableTreeNode;
+        return MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Sin(binFactor.Weight));
+      } else {
+        var sineNode = sineSymbol.CreateTreeNode();
+        sineNode.AddSubtree(node);
+        return sineNode;
+      }
+    }
+
+    private ISymbolicExpressionTreeNode MakeTangent(ISymbolicExpressionTreeNode node) {
+      if (IsConstant(node)) {
+        var constT = node as ConstantTreeNode;
+        return MakeConstant(Math.Tan(constT.Value));
+      } else if (IsFactor(node)) {
+        var factor = node as FactorVariableTreeNode;
+        return MakeFactor(factor.Symbol, factor.VariableName, factor.Weights.Select(Math.Tan));
+      } else if (IsBinFactor(node)) {
+        var binFactor = node as BinaryFactorVariableTreeNode;
+        return MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Tan(binFactor.Weight));
+      } else {
+        var tanNode = tanSymbol.CreateTreeNode();
+        tanNode.AddSubtree(node);
+        return tanNode;
+      }
+    }
+
+    private ISymbolicExpressionTreeNode MakeCosine(ISymbolicExpressionTreeNode node) {
+      if (IsConstant(node)) {
+        var constT = node as ConstantTreeNode;
+        return MakeConstant(Math.Cos(constT.Value));
+      } else if (IsFactor(node)) {
+        var factor = node as FactorVariableTreeNode;
+        return MakeFactor(factor.Symbol, factor.VariableName, factor.Weights.Select(Math.Cos));
+      } else if (IsBinFactor(node)) {
+        var binFactor = node as BinaryFactorVariableTreeNode;
+        // cos(0) = 1 see similar case for Exp(binfactor)
+        return MakeSum(MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Cos(binFactor.Weight) - 1),
+          MakeConstant(1.0));
+      } else {
+        var cosNode = cosineSymbol.CreateTreeNode();
+        cosNode.AddSubtree(node);
+        return cosNode;
+      }
+    }
+
+    private ISymbolicExpressionTreeNode MakeExp(ISymbolicExpressionTreeNode node) {
+      if (IsConstant(node)) {
+        var constT = node as ConstantTreeNode;
+        return MakeConstant(Math.Exp(constT.Value));
+      } else if (IsFactor(node)) {
+        var factNode = node as FactorVariableTreeNode;
+        return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => Math.Exp(w)));
+      } else if (IsBinFactor(node)) {
+        // exp( binfactor w val=a) = if(val=a) exp(w) else exp(0) = binfactor( (exp(w) - 1) val a) + 1
+        var binFactor = node as BinaryFactorVariableTreeNode;
+        return
+          MakeSum(MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Exp(binFactor.Weight) - 1), MakeConstant(1.0));
+      } else if (IsLog(node)) {
+        return node.GetSubtree(0);
+      } else if (IsAddition(node)) {
+        return node.Subtrees.Select(s => MakeExp(s)).Aggregate((s, t) => MakeProduct(s, t));
+      } else if (IsSubtraction(node)) {
+        return node.Subtrees.Select(s => MakeExp(s)).Aggregate((s, t) => MakeProduct(s, Negate(t)));
+      } else {
+        var expNode = expSymbol.CreateTreeNode();
+        expNode.AddSubtree(node);
+        return expNode;
+      }
+    }
+    private ISymbolicExpressionTreeNode MakeLog(ISymbolicExpressionTreeNode node) {
+      if (IsConstant(node)) {
+        var constT = node as ConstantTreeNode;
+        return MakeConstant(Math.Log(constT.Value));
+      } else if (IsFactor(node)) {
+        var factNode = node as FactorVariableTreeNode;
+        return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => Math.Log(w)));
+      } else if (IsExp(node)) {
+        return node.GetSubtree(0);
+      } else if (IsSquareRoot(node)) {
+        return MakeFraction(MakeLog(node.GetSubtree(0)), MakeConstant(2.0));
+      } else {
+        var logNode = logSymbol.CreateTreeNode();
+        logNode.AddSubtree(node);
+        return logNode;
+      }
+    }
+
+    private ISymbolicExpressionTreeNode MakeSquare(ISymbolicExpressionTreeNode node) {
+      if (IsConstant(node)) {
+        var constT = node as ConstantTreeNode;
+        return MakeConstant(constT.Value * constT.Value);
+      } else if (IsFactor(node)) {
+        var factNode = node as FactorVariableTreeNode;
+        return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => w * w));
+      } else if (IsBinFactor(node)) {
+        var binFactor = node as BinaryFactorVariableTreeNode;
+        return MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, binFactor.Weight * binFactor.Weight);
+      } else if (IsSquareRoot(node)) {
+        return node.GetSubtree(0);
+      } else {
+        var sqrNode = sqrSymbol.CreateTreeNode();
+        sqrNode.AddSubtree(node);
+        return sqrNode;
+      }
+    }
+
+    private ISymbolicExpressionTreeNode MakeSquareRoot(ISymbolicExpressionTreeNode node) {
+      if (IsConstant(node)) {
+        var constT = node as ConstantTreeNode;
+        return MakeConstant(Math.Sqrt(constT.Value));
+      } else if (IsFactor(node)) {
+        var factNode = node as FactorVariableTreeNode;
+        return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => Math.Sqrt(w)));
+      } else if (IsBinFactor(node)) {
+        var binFactor = node as BinaryFactorVariableTreeNode;
+        return MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Sqrt(binFactor.Weight));
+      } else if (IsSquare(node)) {
+        return node.GetSubtree(0);
+      } else {
+        var sqrtNode = sqrtSymbol.CreateTreeNode();
+        sqrtNode.AddSubtree(node);
+        return sqrtNode;
+      }
+    }
+
+    private ISymbolicExpressionTreeNode MakeRoot(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) {
+      if (IsConstant(a) && IsConstant(b)) {
+        var constA = a as ConstantTreeNode;
+        var constB = b as ConstantTreeNode;
+        return MakeConstant(Math.Pow(constA.Value, 1.0 / Math.Round(constB.Value)));
+      } else if (IsFactor(a) && IsConstant(b)) {
+        var factNode = a as FactorVariableTreeNode;
+        var constNode = b as ConstantTreeNode;
+        return MakeFactor(factNode.Symbol, factNode.VariableName,
+          factNode.Weights.Select(w => Math.Pow(w, 1.0 / Math.Round(constNode.Value))));
+      } else if (IsBinFactor(a) && IsConstant(b)) {
+        var binFactor = a as BinaryFactorVariableTreeNode;
+        var constNode = b as ConstantTreeNode;
+        return MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Pow(binFactor.Weight, 1.0 / Math.Round(constNode.Value)));
+      } else if (IsConstant(a) && IsFactor(b)) {
+        var constNode = a as ConstantTreeNode;
+        var factNode = b as FactorVariableTreeNode;
+        return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => Math.Pow(constNode.Value, 1.0 / Math.Round(w))));
+      } else if (IsConstant(a) && IsBinFactor(b)) {
+        var constNode = a as ConstantTreeNode;
+        var factNode = b as BinaryFactorVariableTreeNode;
+        return MakeBinFactor(factNode.Symbol, factNode.VariableName, factNode.VariableValue, Math.Pow(constNode.Value, 1.0 / Math.Round(factNode.Weight)));
+      } else if (IsFactor(a) && IsFactor(b) && AreSameTypeAndVariable(a, b)) {
+        var node0 = a as FactorVariableTreeNode;
+        var node1 = b as FactorVariableTreeNode;
+        return MakeFactor(node0.Symbol, node0.VariableName, node0.Weights.Zip(node1.Weights, (u, v) => Math.Pow(u, 1.0 / Math.Round(v))));
+      } else if (IsConstant(b)) {
+        var constB = b as ConstantTreeNode;
+        var constBValue = Math.Round(constB.Value);
+        if (constBValue.IsAlmost(1.0)) {
+          return a;
+        } else if (constBValue.IsAlmost(0.0)) {
+          return MakeConstant(1.0);
+        } else if (constBValue.IsAlmost(-1.0)) {
+          return MakeFraction(MakeConstant(1.0), a);
+        } else if (constBValue < 0) {
+          var rootNode = rootSymbol.CreateTreeNode();
+          rootNode.AddSubtree(a);
+          rootNode.AddSubtree(MakeConstant(-1.0 * constBValue));
+          return MakeFraction(MakeConstant(1.0), rootNode);
+        } else {
+          var rootNode = rootSymbol.CreateTreeNode();
+          rootNode.AddSubtree(a);
+          rootNode.AddSubtree(MakeConstant(constBValue));
+          return rootNode;
+        }
+      } else {
+        var rootNode = rootSymbol.CreateTreeNode();
+        rootNode.AddSubtree(a);
+        rootNode.AddSubtree(b);
+        return rootNode;
+      }
+    }
+
+
+    private ISymbolicExpressionTreeNode MakePower(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) {
+      if (IsConstant(a) && IsConstant(b)) {
+        var constA = a as ConstantTreeNode;
+        var constB = b as ConstantTreeNode;
+        return MakeConstant(Math.Pow(constA.Value, Math.Round(constB.Value)));
+      } else if (IsFactor(a) && IsConstant(b)) {
+        var factNode = a as FactorVariableTreeNode;
+        var constNode = b as ConstantTreeNode;
+        return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => Math.Pow(w, Math.Round(constNode.Value))));
+      } else if (IsBinFactor(a) && IsConstant(b)) {
+        var binFactor = a as BinaryFactorVariableTreeNode;
+        var constNode = b as ConstantTreeNode;
+        return MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Pow(binFactor.Weight, Math.Round(constNode.Value)));
+      } else if (IsConstant(a) && IsFactor(b)) {
+        var constNode = a as ConstantTreeNode;
+        var factNode = b as FactorVariableTreeNode;
+        return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => Math.Pow(constNode.Value, Math.Round(w))));
+      } else if (IsConstant(a) && IsBinFactor(b)) {
+        var constNode = a as ConstantTreeNode;
+        var factNode = b as BinaryFactorVariableTreeNode;
+        return MakeBinFactor(factNode.Symbol, factNode.VariableName, factNode.VariableValue, Math.Pow(constNode.Value, Math.Round(factNode.Weight)));
+      } else if (IsFactor(a) && IsFactor(b) && AreSameTypeAndVariable(a, b)) {
+        var node0 = a as FactorVariableTreeNode;
+        var node1 = b as FactorVariableTreeNode;
+        return MakeFactor(node0.Symbol, node0.VariableName, node0.Weights.Zip(node1.Weights, (u, v) => Math.Pow(u, Math.Round(v))));
+      } else if (IsConstant(b)) {
+        var constB = b as ConstantTreeNode;
+        double exponent = Math.Round(constB.Value);
+        if (exponent.IsAlmost(0.0)) {
+          return MakeConstant(1.0);
+        } else if (exponent.IsAlmost(1.0)) {
+          return a;
+        } else if (exponent.IsAlmost(-1.0)) {
+          return MakeFraction(MakeConstant(1.0), a);
+        } else if (exponent < 0) {
+          var powNode = powSymbol.CreateTreeNode();
+          powNode.AddSubtree(a);
+          powNode.AddSubtree(MakeConstant(-1.0 * exponent));
+          return MakeFraction(MakeConstant(1.0), powNode);
+        } else {
+          var powNode = powSymbol.CreateTreeNode();
+          powNode.AddSubtree(a);
+          powNode.AddSubtree(MakeConstant(exponent));
+          return powNode;
+        }
+      } else {
+        var powNode = powSymbol.CreateTreeNode();
+        powNode.AddSubtree(a);
+        powNode.AddSubtree(b);
+        return powNode;
+      }
+    }
+
+
+    // MakeFraction, MakeProduct and MakeSum take two already simplified trees and create a new simplified tree
+    private ISymbolicExpressionTreeNode MakeFraction(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) {
+      if (IsConstant(a) && IsConstant(b)) {
+        // fold constants
+        return MakeConstant(((ConstantTreeNode)a).Value / ((ConstantTreeNode)b).Value);
+      } else if ((IsConstant(a) && !((ConstantTreeNode)a).Value.IsAlmost(1.0))) {
+        return MakeFraction(MakeConstant(1.0), MakeProduct(b, Invert(a)));
+      } else if (IsVariableBase(a) && IsConstant(b)) {
+        // merge constant values into variable weights
+        var constB = ((ConstantTreeNode)b).Value;
+        ((VariableTreeNodeBase)a).Weight /= constB;
+        return a;
+      } else if (IsFactor(a) && IsConstant(b)) {
+        var factNode = a as FactorVariableTreeNode;
+        var constNode = b as ConstantTreeNode;
+        return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => w / constNode.Value));
+      } else if (IsBinFactor(a) && IsConstant(b)) {
+        var factNode = a as BinaryFactorVariableTreeNode;
+        var constNode = b as ConstantTreeNode;
+        return MakeBinFactor(factNode.Symbol, factNode.VariableName, factNode.VariableValue, factNode.Weight / constNode.Value);
+      } else if (IsFactor(a) && IsFactor(b) && AreSameTypeAndVariable(a, b)) {
+        var node0 = a as FactorVariableTreeNode;
+        var node1 = b as FactorVariableTreeNode;
+        return MakeFactor(node0.Symbol, node0.VariableName, node0.Weights.Zip(node1.Weights, (u, v) => u / v));
+      } else if (IsFactor(a) && IsBinFactor(b) && ((IVariableTreeNode)a).VariableName == ((IVariableTreeNode)b).VariableName) {
+        var node0 = a as FactorVariableTreeNode;
+        var node1 = b as BinaryFactorVariableTreeNode;
+        var varValues = node0.Symbol.GetVariableValues(node0.VariableName).ToArray();
+        var wi = Array.IndexOf(varValues, node1.VariableValue);
+        if (wi < 0) throw new ArgumentException();
+        var newWeighs = new double[varValues.Length];
+        node0.Weights.CopyTo(newWeighs, 0);
+        for (int i = 0; i < newWeighs.Length; i++)
+          if (wi == i) newWeighs[i] /= node1.Weight;
+          else newWeighs[i] /= 0.0;
+        return MakeFactor(node0.Symbol, node0.VariableName, newWeighs);
+      } else if (IsFactor(a)) {
+        return MakeFraction(MakeConstant(1.0), MakeProduct(b, Invert(a)));
+      } else if (IsVariableBase(a) && IsVariableBase(b) && AreSameTypeAndVariable(a, b) && !IsBinFactor(b)) {
+        // cancel variables (not allowed for bin factors because of division by zero)
+        var aVar = a as VariableTreeNode;
+        var bVar = b as VariableTreeNode;
+        return MakeConstant(aVar.Weight / bVar.Weight);
+      } else if (IsAddition(a) && IsConstant(b)) {
+        return a.Subtrees
+          .Select(x => GetSimplifiedTree(x))
+          .Select(x => MakeFraction(x, GetSimplifiedTree(b)))
+          .Aggregate((c, d) => MakeSum(c, d));
+      } else if (IsMultiplication(a) && IsConstant(b)) {
+        return MakeProduct(a, Invert(b));
+      } else if (IsDivision(a) && IsConstant(b)) {
+        // (a1 / a2) / c => (a1 / (a2 * c))
+        return MakeFraction(a.GetSubtree(0), MakeProduct(a.GetSubtree(1), b));
+      } else if (IsDivision(a) && IsDivision(b)) {
+        // (a1 / a2) / (b1 / b2) => 
+        return MakeFraction(MakeProduct(a.GetSubtree(0), b.GetSubtree(1)), MakeProduct(a.GetSubtree(1), b.GetSubtree(0)));
+      } else if (IsDivision(a)) {
+        // (a1 / a2) / b => (a1 / (a2 * b))
+        return MakeFraction(a.GetSubtree(0), MakeProduct(a.GetSubtree(1), b));
+      } else if (IsDivision(b)) {
+        // a / (b1 / b2) => (a * b2) / b1
+        return MakeFraction(MakeProduct(a, b.GetSubtree(1)), b.GetSubtree(0));
+      } else {
+        var div = divSymbol.CreateTreeNode();
+        div.AddSubtree(a);
+        div.AddSubtree(b);
+        return div;
+      }
+    }
+
+    private ISymbolicExpressionTreeNode MakeSum(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) {
+      if (IsConstant(a) && IsConstant(b)) {
+        // fold constants
+        ((ConstantTreeNode)a).Value += ((ConstantTreeNode)b).Value;
+        return a;
+      } else if (IsConstant(a)) {
+        // c + x => x + c
+        // b is not constant => make sure constant is on the right
+        return MakeSum(b, a);
+      } else if (IsConstant(b) && ((ConstantTreeNode)b).Value.IsAlmost(0.0)) {
+        // x + 0 => x
+        return a;
+      } else if (IsFactor(a) && IsConstant(b)) {
+        var factNode = a as FactorVariableTreeNode;
+        var constNode = b as ConstantTreeNode;
+        return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select((w) => w + constNode.Value));
+      } else if (IsFactor(a) && IsFactor(b) && AreSameTypeAndVariable(a, b)) {
+        var node0 = a as FactorVariableTreeNode;
+        var node1 = b as FactorVariableTreeNode;
+        return MakeFactor(node0.Symbol, node0.VariableName, node0.Weights.Zip(node1.Weights, (u, v) => u + v));
+      } else if (IsBinFactor(a) && IsFactor(b)) {
+        return MakeSum(b, a);
+      } else if (IsFactor(a) && IsBinFactor(b) &&
+        ((IVariableTreeNode)a).VariableName == ((IVariableTreeNode)b).VariableName) {
+        var node0 = a as FactorVariableTreeNode;
+        var node1 = b as BinaryFactorVariableTreeNode;
+        var varValues = node0.Symbol.GetVariableValues(node0.VariableName).ToArray();
+        var wi = Array.IndexOf(varValues, node1.VariableValue);
+        if (wi < 0) throw new ArgumentException();
+        var newWeighs = new double[varValues.Length];
+        node0.Weights.CopyTo(newWeighs, 0);
+        newWeighs[wi] += node1.Weight;
+        return MakeFactor(node0.Symbol, node0.VariableName, newWeighs);
+      } else if (IsAddition(a) && IsAddition(b)) {
+        // merge additions
+        var add = addSymbol.CreateTreeNode();
+        // add all sub trees except for the last
+        for (int i = 0; i < a.Subtrees.Count() - 1; i++) add.AddSubtree(a.GetSubtree(i));
+        for (int i = 0; i < b.Subtrees.Count() - 1; i++) add.AddSubtree(b.GetSubtree(i));
+        if (IsConstant(a.Subtrees.Last()) && IsConstant(b.Subtrees.Last())) {
+          add.AddSubtree(MakeSum(a.Subtrees.Last(), b.Subtrees.Last()));
+        } else if (IsConstant(a.Subtrees.Last())) {
+          add.AddSubtree(b.Subtrees.Last());
+          add.AddSubtree(a.Subtrees.Last());
+        } else {
+          add.AddSubtree(a.Subtrees.Last());
+          add.AddSubtree(b.Subtrees.Last());
+        }
+        MergeVariablesInSum(add);
+        if (add.Subtrees.Count() == 1) {
+          return add.GetSubtree(0);
+        } else {
+          return add;
+        }
+      } else if (IsAddition(b)) {
+        return MakeSum(b, a);
+      } else if (IsAddition(a) && IsConstant(b)) {
+        // a is an addition and b is a constant => append b to a and make sure the constants are merged
+        var add = addSymbol.CreateTreeNode();
+        // add all sub trees except for the last
+        for (int i = 0; i < a.Subtrees.Count() - 1; i++) add.AddSubtree(a.GetSubtree(i));
+        if (IsConstant(a.Subtrees.Last()))
+          add.AddSubtree(MakeSum(a.Subtrees.Last(), b));
+        else {
+          add.AddSubtree(a.Subtrees.Last());
+          add.AddSubtree(b);
+        }
+        return add;
+      } else if (IsAddition(a)) {
+        // a is already an addition => append b
+        var add = addSymbol.CreateTreeNode();
+        add.AddSubtree(b);
+        foreach (var subtree in a.Subtrees) {
+          add.AddSubtree(subtree);
+        }
+        MergeVariablesInSum(add);
+        if (add.Subtrees.Count() == 1) {
+          return add.GetSubtree(0);
+        } else {
+          return add;
+        }
+      } else {
+        var add = addSymbol.CreateTreeNode();
+        add.AddSubtree(a);
+        add.AddSubtree(b);
+        MergeVariablesInSum(add);
+        if (add.Subtrees.Count() == 1) {
+          return add.GetSubtree(0);
+        } else {
+          return add;
+        }
+      }
+    }
+
+    // makes sure variable symbols in sums are combined
+    private void MergeVariablesInSum(ISymbolicExpressionTreeNode sum) {
+      var subtrees = new List<ISymbolicExpressionTreeNode>(sum.Subtrees);
+      while (sum.Subtrees.Any()) sum.RemoveSubtree(0);
+      var groupedVarNodes = from node in subtrees.OfType<IVariableTreeNode>()
+                            where node.SubtreeCount == 0
+                            group node by GroupId(node) into g
+                            select g;
+      var constant = (from node in subtrees.OfType<ConstantTreeNode>()
+                      select node.Value).DefaultIfEmpty(0.0).Sum();
+      var unchangedSubtrees = subtrees.Where(t => t.SubtreeCount > 0 || !(t is IVariableTreeNode) && !(t is ConstantTreeNode));
+
+      foreach (var variableNodeGroup in groupedVarNodes) {
+        var firstNode = variableNodeGroup.First();
+        if (firstNode is VariableTreeNodeBase) {
+          var representative = firstNode as VariableTreeNodeBase;
+          var weightSum = variableNodeGroup.Cast<VariableTreeNodeBase>().Select(t => t.Weight).Sum();
+          representative.Weight = weightSum;
+          sum.AddSubtree(representative);
+        } else if (firstNode is FactorVariableTreeNode) {
+          var representative = firstNode as FactorVariableTreeNode;
+          foreach (var node in variableNodeGroup.Skip(1).Cast<FactorVariableTreeNode>()) {
+            for (int j = 0; j < representative.Weights.Length; j++) {
+              representative.Weights[j] += node.Weights[j];
+            }
+          }
+          for (int j = 0; j < representative.Weights.Length; j++) {
+            representative.Weights[j] += constant;
+          }
+          sum.AddSubtree(representative);
+        }
+      }
+      foreach (var unchangedSubtree in unchangedSubtrees)
+        sum.AddSubtree(unchangedSubtree);
+      if (!constant.IsAlmost(0.0)) {
+        sum.AddSubtree(MakeConstant(constant));
+      }
+    }
+
+    // nodes referencing variables can be grouped if they have
+    private string GroupId(IVariableTreeNode node) {
+      var binaryFactorNode = node as BinaryFactorVariableTreeNode;
+      var factorNode = node as FactorVariableTreeNode;
+      var variableNode = node as VariableTreeNode;
+      var laggedVarNode = node as LaggedVariableTreeNode;
+      if (variableNode != null) {
+        return "var " + variableNode.VariableName;
+      } else if (binaryFactorNode != null) {
+        return "binfactor " + binaryFactorNode.VariableName + " " + binaryFactorNode.VariableValue;
+      } else if (factorNode != null) {
+        return "factor " + factorNode.VariableName;
+      } else if (laggedVarNode != null) {
+        return "lagged " + laggedVarNode.VariableName + " " + laggedVarNode.Lag;
+      } else {
+        throw new NotSupportedException();
+      }
+    }
+
+
+    private ISymbolicExpressionTreeNode MakeProduct(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) {
+      if (IsConstant(a) && IsConstant(b)) {
+        // fold constants
+        return MakeConstant(((ConstantTreeNode)a).Value * ((ConstantTreeNode)b).Value);
+      } else if (IsConstant(a)) {
+        // a * $ => $ * a
+        return MakeProduct(b, a);
+      } else if (IsFactor(a) && IsFactor(b) && AreSameTypeAndVariable(a, b)) {
+        var node0 = a as FactorVariableTreeNode;
+        var node1 = b as FactorVariableTreeNode;
+        return MakeFactor(node0.Symbol, node0.VariableName, node0.Weights.Zip(node1.Weights, (u, v) => u * v));
+      } else if (IsBinFactor(a) && IsBinFactor(b) && AreSameTypeAndVariable(a, b)) {
+        var node0 = a as BinaryFactorVariableTreeNode;
+        var node1 = b as BinaryFactorVariableTreeNode;
+        return MakeBinFactor(node0.Symbol, node0.VariableName, node0.VariableValue, node0.Weight * node1.Weight);
+      } else if (IsFactor(a) && IsConstant(b)) {
+        var node0 = a as FactorVariableTreeNode;
+        var node1 = b as ConstantTreeNode;
+        return MakeFactor(node0.Symbol, node0.VariableName, node0.Weights.Select(w => w * node1.Value));
+      } else if (IsBinFactor(a) && IsConstant(b)) {
+        var node0 = a as BinaryFactorVariableTreeNode;
+        var node1 = b as ConstantTreeNode;
+        return MakeBinFactor(node0.Symbol, node0.VariableName, node0.VariableValue, node0.Weight * node1.Value);
+      } else if (IsBinFactor(a) && IsFactor(b)) {
+        return MakeProduct(b, a);
+      } else if (IsFactor(a) && IsBinFactor(b) &&
+        ((IVariableTreeNode)a).VariableName == ((IVariableTreeNode)b).VariableName) {
+        var node0 = a as FactorVariableTreeNode;
+        var node1 = b as BinaryFactorVariableTreeNode;
+        var varValues = node0.Symbol.GetVariableValues(node0.VariableName).ToArray();
+        var wi = Array.IndexOf(varValues, node1.VariableValue);
+        if (wi < 0) throw new ArgumentException();
+        return MakeBinFactor(node1.Symbol, node1.VariableName, node1.VariableValue, node1.Weight * node0.Weights[wi]);
+      } else if (IsConstant(b) && ((ConstantTreeNode)b).Value.IsAlmost(1.0)) {
+        // $ * 1.0 => $
+        return a;
+      } else if (IsConstant(b) && IsVariableBase(a)) {
+        // multiply constants into variables weights
+        ((VariableTreeNodeBase)a).Weight *= ((ConstantTreeNode)b).Value;
+        return a;
+      } else if (IsConstant(b) && IsAddition(a) ||
+          IsFactor(b) && IsAddition(a) ||
+          IsBinFactor(b) && IsAddition(a)) {
+        // multiply constants into additions
+        return a.Subtrees.Select(x => MakeProduct(GetSimplifiedTree(x), GetSimplifiedTree(b))).Aggregate((c, d) => MakeSum(c, d));
+      } else if (IsDivision(a) && IsDivision(b)) {
+        // (a1 / a2) * (b1 / b2) => (a1 * b1) / (a2 * b2)
+        return MakeFraction(MakeProduct(a.GetSubtree(0), b.GetSubtree(0)), MakeProduct(a.GetSubtree(1), b.GetSubtree(1)));
+      } else if (IsDivision(a)) {
+        // (a1 / a2) * b => (a1 * b) / a2
+        return MakeFraction(MakeProduct(a.GetSubtree(0), b), a.GetSubtree(1));
+      } else if (IsDivision(b)) {
+        // a * (b1 / b2) => (b1 * a) / b2
+        return MakeFraction(MakeProduct(b.GetSubtree(0), a), b.GetSubtree(1));
+      } else if (IsMultiplication(a) && IsMultiplication(b)) {
+        // merge multiplications (make sure constants are merged)
+        var mul = mulSymbol.CreateTreeNode();
+        for (int i = 0; i < a.Subtrees.Count(); i++) mul.AddSubtree(a.GetSubtree(i));
+        for (int i = 0; i < b.Subtrees.Count(); i++) mul.AddSubtree(b.GetSubtree(i));
+        MergeVariablesAndConstantsInProduct(mul);
+        return mul;
+      } else if (IsMultiplication(b)) {
+        return MakeProduct(b, a);
+      } else if (IsMultiplication(a)) {
+        // a is already an multiplication => append b
+        a.AddSubtree(GetSimplifiedTree(b));
+        MergeVariablesAndConstantsInProduct(a);
+        return a;
+      } else {
+        var mul = mulSymbol.CreateTreeNode();
+        mul.AddSubtree(a);
+        mul.AddSubtree(b);
+        MergeVariablesAndConstantsInProduct(mul);
+        return mul;
+      }
+    }
+
+    #endregion
+
+    #region helper functions
+
+    private bool ContainsVariableCondition(ISymbolicExpressionTreeNode node) {
+      if (node.Symbol is VariableCondition) return true;
+      foreach (var subtree in node.Subtrees)
+        if (ContainsVariableCondition(subtree)) return true;
+      return false;
+    }
+
+    private ISymbolicExpressionTreeNode AddLagToDynamicNodes(ISymbolicExpressionTreeNode node, int lag) {
+      var laggedTreeNode = node as ILaggedTreeNode;
+      var variableNode = node as VariableTreeNode;
+      var variableConditionNode = node as VariableConditionTreeNode;
+      if (laggedTreeNode != null)
+        laggedTreeNode.Lag += lag;
+      else if (variableNode != null) {
+        var laggedVariableNode = (LaggedVariableTreeNode)laggedVariableSymbol.CreateTreeNode();
+        laggedVariableNode.Lag = lag;
+        laggedVariableNode.VariableName = variableNode.VariableName;
+        return laggedVariableNode;
+      } else if (variableConditionNode != null) {
+        throw new NotSupportedException("Removal of time lags around variable condition symbols is not allowed.");
+      }
+      var subtrees = new List<ISymbolicExpressionTreeNode>(node.Subtrees);
+      while (node.SubtreeCount > 0) node.RemoveSubtree(0);
+      foreach (var subtree in subtrees) {
+        node.AddSubtree(AddLagToDynamicNodes(subtree, lag));
+      }
+      return node;
+    }
+
+    private bool AreSameTypeAndVariable(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) {
+      return GroupId((IVariableTreeNode)a) == GroupId((IVariableTreeNode)b);
+    }
+
+    // helper to combine the constant factors in products and to combine variables (powers of 2, 3...)
+    private void MergeVariablesAndConstantsInProduct(ISymbolicExpressionTreeNode prod) {
+      var subtrees = new List<ISymbolicExpressionTreeNode>(prod.Subtrees);
+      while (prod.Subtrees.Any()) prod.RemoveSubtree(0);
+      var groupedVarNodes = from node in subtrees.OfType<IVariableTreeNode>()
+                            where node.SubtreeCount == 0
+                            group node by GroupId(node) into g
+                            orderby g.Count()
+                            select g;
+      var constantProduct = (from node in subtrees.OfType<VariableTreeNodeBase>()
+                             select node.Weight)
+        .Concat(from node in subtrees.OfType<ConstantTreeNode>()
+                select node.Value)
+        .DefaultIfEmpty(1.0)
+        .Aggregate((c1, c2) => c1 * c2);
+
+      var unchangedSubtrees = from tree in subtrees
+                              where tree.SubtreeCount > 0 || !(tree is IVariableTreeNode) && !(tree is ConstantTreeNode)
+                              select tree;
+
+      foreach (var variableNodeGroup in groupedVarNodes) {
+        var firstNode = variableNodeGroup.First();
+        if (firstNode is VariableTreeNodeBase) {
+          var representative = (VariableTreeNodeBase)firstNode;
+          representative.Weight = 1.0;
+          if (variableNodeGroup.Count() > 1) {
+            var poly = mulSymbol.CreateTreeNode();
+            for (int p = 0; p < variableNodeGroup.Count(); p++) {
+              poly.AddSubtree((ISymbolicExpressionTreeNode)representative.Clone());
+            }
+            prod.AddSubtree(poly);
+          } else {
+            prod.AddSubtree(representative);
+          }
+        } else if (firstNode is FactorVariableTreeNode) {
+          var representative = (FactorVariableTreeNode)firstNode;
+          foreach (var node in variableNodeGroup.Skip(1).Cast<FactorVariableTreeNode>()) {
+            for (int j = 0; j < representative.Weights.Length; j++) {
+              representative.Weights[j] *= node.Weights[j];
+            }
+          }
+          for (int j = 0; j < representative.Weights.Length; j++) {
+            representative.Weights[j] *= constantProduct;
+          }
+          constantProduct = 1.0;
+          // if the product already contains a factor it is not necessary to multiply a constant below
+          prod.AddSubtree(representative);
+        }
+      }
+
+      foreach (var unchangedSubtree in unchangedSubtrees)
+        prod.AddSubtree(unchangedSubtree);
+
+      if (!constantProduct.IsAlmost(1.0)) {
+        prod.AddSubtree(MakeConstant(constantProduct));
+      }
+    }
+
+
+    /// <summary>
+    /// x => x * -1
+    /// Is only used in cases where it is not necessary to create new tree nodes. Manipulates x directly.
+    /// </summary>
+    /// <param name="x"></param>
+    /// <returns>-x</returns>
+    private ISymbolicExpressionTreeNode Negate(ISymbolicExpressionTreeNode x) {
+      if (IsConstant(x)) {
+        ((ConstantTreeNode)x).Value *= -1;
+      } else if (IsVariableBase(x)) {
+        var variableTree = (VariableTreeNodeBase)x;
+        variableTree.Weight *= -1.0;
+      } else if (IsFactor(x)) {
+        var factorNode = (FactorVariableTreeNode)x;
+        for (int i = 0; i < factorNode.Weights.Length; i++) factorNode.Weights[i] *= -1;
+      } else if (IsBinFactor(x)) {
+        var factorNode = (BinaryFactorVariableTreeNode)x;
+        factorNode.Weight *= -1;
+      } else if (IsAddition(x)) {
+        // (x0 + x1 + .. + xn) * -1 => (-x0 + -x1 + .. + -xn)        
+        var subtrees = new List<ISymbolicExpressionTreeNode>(x.Subtrees);
+        while (x.Subtrees.Any()) x.RemoveSubtree(0);
+        foreach (var subtree in subtrees) {
+          x.AddSubtree(Negate(subtree));
+        }
+      } else if (IsMultiplication(x) || IsDivision(x)) {
+        // x0 * x1 * .. * xn * -1 => x0 * x1 * .. * -xn
+        var lastSubTree = x.Subtrees.Last();
+        x.RemoveSubtree(x.SubtreeCount - 1);
+        x.AddSubtree(Negate(lastSubTree)); // last is maybe a constant, prefer to negate the constant
+      } else {
+        // any other function
+        return MakeProduct(x, MakeConstant(-1));
+      }
+      return x;
+    }
+
+    /// <summary>
+    /// x => 1/x
+    /// Must create new tree nodes
+    /// </summary>
+    /// <param name="x"></param>
+    /// <returns></returns>
+    private ISymbolicExpressionTreeNode Invert(ISymbolicExpressionTreeNode x) {
+      if (IsConstant(x)) {
+        return MakeConstant(1.0 / ((ConstantTreeNode)x).Value);
+      } else if (IsFactor(x)) {
+        var factorNode = (FactorVariableTreeNode)x;
+        return MakeFactor(factorNode.Symbol, factorNode.VariableName, factorNode.Weights.Select(w => 1.0 / w));
+      } else if (IsDivision(x)) {
+        return MakeFraction(x.GetSubtree(1), x.GetSubtree(0));
+      } else {
+        // any other function
+        return MakeFraction(MakeConstant(1), x);
+      }
+    }
+
+    private ISymbolicExpressionTreeNode MakeConstant(double value) {
+      ConstantTreeNode constantTreeNode = (ConstantTreeNode)(constSymbol.CreateTreeNode());
+      constantTreeNode.Value = value;
+      return constantTreeNode;
+    }
+
+    private ISymbolicExpressionTreeNode MakeFactor(FactorVariable sy, string variableName, IEnumerable<double> weights) {
+      var tree = (FactorVariableTreeNode)sy.CreateTreeNode();
+      tree.VariableName = variableName;
+      tree.Weights = weights.ToArray();
+      return tree;
+    }
+    private ISymbolicExpressionTreeNode MakeBinFactor(BinaryFactorVariable sy, string variableName, string variableValue, double weight) {
+      var tree = (BinaryFactorVariableTreeNode)sy.CreateTreeNode();
+      tree.VariableName = variableName;
+      tree.VariableValue = variableValue;
+      tree.Weight = weight;
+      return tree;
+    }
+
+
+    #endregion
+  }
+}
Index: /stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Converters/TreeToAutoDiffTermConverter.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Converters/TreeToAutoDiffTermConverter.cs	(revision 15142)
+++ /stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Converters/TreeToAutoDiffTermConverter.cs	(revision 15142)
@@ -0,0 +1,386 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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 AutoDiff;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
+  public class TreeToAutoDiffTermConverter {
+    public delegate double ParametricFunction(double[] vars, double[] @params);
+    public delegate Tuple<double[], double> ParametricFunctionGradient(double[] vars, double[] @params);
+
+    #region helper class
+    public class DataForVariable {
+      public readonly string variableName;
+      public readonly string variableValue; // for factor vars
+      public readonly int lag;
+
+      public DataForVariable(string varName, string varValue, int lag) {
+        this.variableName = varName;
+        this.variableValue = varValue;
+        this.lag = lag;
+      }
+
+      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) &&
+               other.lag == this.lag;
+      }
+
+      public override int GetHashCode() {
+        return variableName.GetHashCode() ^ variableValue.GetHashCode() ^ lag;
+      }
+    }
+    #endregion
+
+    #region derivations of functions
+    // create function factory for arctangent
+    private static readonly Func<Term, UnaryFunc> arctan = UnaryFunc.Factory(
+      eval: Math.Atan,
+      diff: x => 1 / (1 + x * x));
+    private static readonly Func<Term, UnaryFunc> sin = UnaryFunc.Factory(
+      eval: Math.Sin,
+      diff: Math.Cos);
+    private static readonly Func<Term, UnaryFunc> cos = UnaryFunc.Factory(
+       eval: Math.Cos,
+       diff: x => -Math.Sin(x));
+    private static readonly Func<Term, UnaryFunc> tan = UnaryFunc.Factory(
+      eval: Math.Tan,
+      diff: x => 1 + Math.Tan(x) * Math.Tan(x));
+    private static readonly Func<Term, UnaryFunc> erf = UnaryFunc.Factory(
+      eval: alglib.errorfunction,
+      diff: x => 2.0 * Math.Exp(-(x * x)) / Math.Sqrt(Math.PI));
+    private static readonly Func<Term, UnaryFunc> norm = UnaryFunc.Factory(
+      eval: alglib.normaldistribution,
+      diff: x => -(Math.Exp(-(x * x)) * Math.Sqrt(Math.Exp(x * x)) * x) / Math.Sqrt(2 * Math.PI));
+
+    #endregion
+
+    public static bool TryConvertToAutoDiff(ISymbolicExpressionTree tree, bool makeVariableWeightsVariable,
+      out List<DataForVariable> parameters, out double[] initialConstants,
+      out ParametricFunction func,
+      out ParametricFunctionGradient func_grad) {
+
+      // use a transformator object which holds the state (variable list, parameter list, ...) for recursive transformation of the tree
+      var transformator = new TreeToAutoDiffTermConverter(makeVariableWeightsVariable);
+      AutoDiff.Term term;
+      var success = transformator.TryConvertToAutoDiff(tree.Root.GetSubtree(0), out term);
+      if (success) {
+        var parameterEntries = transformator.parameters.ToArray(); // guarantee same order for keys and values
+        var compiledTerm = term.Compile(transformator.variables.ToArray(), parameterEntries.Select(kvp => kvp.Value).ToArray());
+        parameters = new List<DataForVariable>(parameterEntries.Select(kvp => kvp.Key));
+        initialConstants = transformator.initialConstants.ToArray();
+        func = (vars, @params) => compiledTerm.Evaluate(vars, @params);
+        func_grad = (vars, @params) => compiledTerm.Differentiate(vars, @params);
+      } else {
+        func = null;
+        func_grad = null;
+        parameters = null;
+        initialConstants = null;
+      }
+      return success;
+    }
+
+    // state for recursive transformation of trees 
+    private readonly List<string> variableNames;
+    private readonly List<int> lags;
+    private readonly List<double> initialConstants;
+    private readonly Dictionary<DataForVariable, AutoDiff.Variable> parameters;
+    private readonly List<AutoDiff.Variable> variables;
+    private readonly bool makeVariableWeightsVariable;
+
+    private TreeToAutoDiffTermConverter(bool makeVariableWeightsVariable) {
+      this.makeVariableWeightsVariable = makeVariableWeightsVariable;
+      this.variableNames = new List<string>();
+      this.lags = new List<int>();
+      this.initialConstants = new List<double>();
+      this.parameters = new Dictionary<DataForVariable, AutoDiff.Variable>();
+      this.variables = new List<AutoDiff.Variable>();
+    }
+
+    private bool TryConvertToAutoDiff(ISymbolicExpressionTreeNode node, out AutoDiff.Term term) {
+      if (node.Symbol is Constant) {
+        initialConstants.Add(((ConstantTreeNode)node).Value);
+        var var = new AutoDiff.Variable();
+        variables.Add(var);
+        term = var;
+        return true;
+      }
+      if (node.Symbol is Variable || node.Symbol is BinaryFactorVariable) {
+        var varNode = node as VariableTreeNodeBase;
+        var factorVarNode = node as BinaryFactorVariableTreeNode;
+        // factor variable values are only 0 or 1 and set in x accordingly
+        var varValue = factorVarNode != null ? factorVarNode.VariableValue : string.Empty;
+        var par = FindOrCreateParameter(parameters, varNode.VariableName, varValue);
+
+        if (makeVariableWeightsVariable) {
+          initialConstants.Add(varNode.Weight);
+          var w = new AutoDiff.Variable();
+          variables.Add(w);
+          term = AutoDiff.TermBuilder.Product(w, par);
+        } else {
+          term = varNode.Weight * par;
+        }
+        return true;
+      }
+      if (node.Symbol is FactorVariable) {
+        var factorVarNode = node as FactorVariableTreeNode;
+        var products = new List<Term>();
+        foreach (var variableValue in factorVarNode.Symbol.GetVariableValues(factorVarNode.VariableName)) {
+          var par = FindOrCreateParameter(parameters, factorVarNode.VariableName, variableValue);
+
+          initialConstants.Add(factorVarNode.GetValue(variableValue));
+          var wVar = new AutoDiff.Variable();
+          variables.Add(wVar);
+
+          products.Add(AutoDiff.TermBuilder.Product(wVar, par));
+        }
+        term = AutoDiff.TermBuilder.Sum(products);
+        return true;
+      }
+      if (node.Symbol is LaggedVariable) {
+        var varNode = node as LaggedVariableTreeNode;
+        var par = FindOrCreateParameter(parameters, varNode.VariableName, string.Empty, varNode.Lag);
+
+        if (makeVariableWeightsVariable) {
+          initialConstants.Add(varNode.Weight);
+          var w = new AutoDiff.Variable();
+          variables.Add(w);
+          term = AutoDiff.TermBuilder.Product(w, par);
+        } else {
+          term = varNode.Weight * par;
+        }
+        return true;
+      }
+      if (node.Symbol is Addition) {
+        List<AutoDiff.Term> terms = new List<Term>();
+        foreach (var subTree in node.Subtrees) {
+          AutoDiff.Term t;
+          if (!TryConvertToAutoDiff(subTree, out t)) {
+            term = null;
+            return false;
+          }
+          terms.Add(t);
+        }
+        term = AutoDiff.TermBuilder.Sum(terms);
+        return true;
+      }
+      if (node.Symbol is Subtraction) {
+        List<AutoDiff.Term> terms = new List<Term>();
+        for (int i = 0; i < node.SubtreeCount; i++) {
+          AutoDiff.Term t;
+          if (!TryConvertToAutoDiff(node.GetSubtree(i), out t)) {
+            term = null;
+            return false;
+          }
+          if (i > 0) t = -t;
+          terms.Add(t);
+        }
+        if (terms.Count == 1) term = -terms[0];
+        else term = AutoDiff.TermBuilder.Sum(terms);
+        return true;
+      }
+      if (node.Symbol is Multiplication) {
+        List<AutoDiff.Term> terms = new List<Term>();
+        foreach (var subTree in node.Subtrees) {
+          AutoDiff.Term t;
+          if (!TryConvertToAutoDiff(subTree, out t)) {
+            term = null;
+            return false;
+          }
+          terms.Add(t);
+        }
+        if (terms.Count == 1) term = terms[0];
+        else term = terms.Aggregate((a, b) => new AutoDiff.Product(a, b));
+        return true;
+
+      }
+      if (node.Symbol is Division) {
+        List<AutoDiff.Term> terms = new List<Term>();
+        foreach (var subTree in node.Subtrees) {
+          AutoDiff.Term t;
+          if (!TryConvertToAutoDiff(subTree, out t)) {
+            term = null;
+            return false;
+          }
+          terms.Add(t);
+        }
+        if (terms.Count == 1) term = 1.0 / terms[0];
+        else term = terms.Aggregate((a, b) => new AutoDiff.Product(a, 1.0 / b));
+        return true;
+      }
+      if (node.Symbol is Logarithm) {
+        AutoDiff.Term t;
+        if (!TryConvertToAutoDiff(node.GetSubtree(0), out t)) {
+          term = null;
+          return false;
+        } else {
+          term = AutoDiff.TermBuilder.Log(t);
+          return true;
+        }
+      }
+      if (node.Symbol is Exponential) {
+        AutoDiff.Term t;
+        if (!TryConvertToAutoDiff(node.GetSubtree(0), out t)) {
+          term = null;
+          return false;
+        } else {
+          term = AutoDiff.TermBuilder.Exp(t);
+          return true;
+        }
+      }
+      if (node.Symbol is Square) {
+        AutoDiff.Term t;
+        if (!TryConvertToAutoDiff(node.GetSubtree(0), out t)) {
+          term = null;
+          return false;
+        } else {
+          term = AutoDiff.TermBuilder.Power(t, 2.0);
+          return true;
+        }
+      }
+      if (node.Symbol is SquareRoot) {
+        AutoDiff.Term t;
+        if (!TryConvertToAutoDiff(node.GetSubtree(0), out t)) {
+          term = null;
+          return false;
+        } else {
+          term = AutoDiff.TermBuilder.Power(t, 0.5);
+          return true;
+        }
+      }
+      if (node.Symbol is Sine) {
+        AutoDiff.Term t;
+        if (!TryConvertToAutoDiff(node.GetSubtree(0), out t)) {
+          term = null;
+          return false;
+        } else {
+          term = sin(t);
+          return true;
+        }
+      }
+      if (node.Symbol is Cosine) {
+        AutoDiff.Term t;
+        if (!TryConvertToAutoDiff(node.GetSubtree(0), out t)) {
+          term = null;
+          return false;
+        } else {
+          term = cos(t);
+          return true;
+        }
+      }
+      if (node.Symbol is Tangent) {
+        AutoDiff.Term t;
+        if (!TryConvertToAutoDiff(node.GetSubtree(0), out t)) {
+          term = null;
+          return false;
+        } else {
+          term = tan(t);
+          return true;
+        }
+      }
+      if (node.Symbol is Erf) {
+        AutoDiff.Term t;
+        if (!TryConvertToAutoDiff(node.GetSubtree(0), out t)) {
+          term = null;
+          return false;
+        } else {
+          term = erf(t);
+          return true;
+        }
+      }
+      if (node.Symbol is Norm) {
+        AutoDiff.Term t;
+        if (!TryConvertToAutoDiff(node.GetSubtree(0), out t)) {
+          term = null;
+          return false;
+        } else {
+          term = norm(t);
+          return true;
+        }
+      }
+      if (node.Symbol is StartSymbol) {
+        var alpha = new AutoDiff.Variable();
+        var beta = new AutoDiff.Variable();
+        variables.Add(beta);
+        variables.Add(alpha);
+        AutoDiff.Term branchTerm;
+        if (TryConvertToAutoDiff(node.GetSubtree(0), out branchTerm)) {
+          term = branchTerm * alpha + beta;
+          return true;
+        } else {
+          term = null;
+          return false;
+        }
+      }
+      term = null;
+      return false;
+    }
+
+
+    // for each factor variable value we need a parameter which represents a binary indicator for that variable & value combination
+    // each binary indicator is only necessary once. So we only create a parameter if this combination is not yet available
+    private static Term FindOrCreateParameter(Dictionary<DataForVariable, AutoDiff.Variable> parameters,
+      string varName, string varValue = "", int lag = 0) {
+      var data = new DataForVariable(varName, varValue, lag);
+
+      AutoDiff.Variable par = null;
+      if (!parameters.TryGetValue(data, out par)) {
+        // not found -> create new parameter and entries in names and values lists
+        par = new AutoDiff.Variable();
+        parameters.Add(data, par);
+      }
+      return par;
+    }
+
+    public static bool IsCompatible(ISymbolicExpressionTree tree) {
+      var containsUnknownSymbol = (
+        from n in tree.Root.GetSubtree(0).IterateNodesPrefix()
+        where
+        !(n.Symbol is Variable) &&
+        !(n.Symbol is BinaryFactorVariable) &&
+        !(n.Symbol is FactorVariable) &&
+        !(n.Symbol is LaggedVariable) &&
+        !(n.Symbol is Constant) &&
+        !(n.Symbol is Addition) &&
+        !(n.Symbol is Subtraction) &&
+        !(n.Symbol is Multiplication) &&
+        !(n.Symbol is Division) &&
+        !(n.Symbol is Logarithm) &&
+        !(n.Symbol is Exponential) &&
+        !(n.Symbol is SquareRoot) &&
+        !(n.Symbol is Square) &&
+        !(n.Symbol is Sine) &&
+        !(n.Symbol is Cosine) &&
+        !(n.Symbol is Tangent) &&
+        !(n.Symbol is Erf) &&
+        !(n.Symbol is Norm) &&
+        !(n.Symbol is StartSymbol)
+        select n).Any();
+      return !containsUnknownSymbol;
+    }
+  }
+}
Index: /stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/SymbolicDataAnalysisExpressionExcelFormatter.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/SymbolicDataAnalysisExpressionExcelFormatter.cs	(revision 15141)
+++ /stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/SymbolicDataAnalysisExpressionExcelFormatter.cs	(revision 15142)
@@ -51,5 +51,5 @@
       while (dividend > 0) {
         int modulo = (dividend - 1) % 26;
-        columnName = Convert.ToChar(65 + modulo) + columnName;
+        columnName = System.Convert.ToChar(65 + modulo) + columnName;
         dividend = (int)((dividend - modulo) / 26);
       }
Index: /stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4.csproj
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4.csproj	(revision 15141)
+++ /stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4.csproj	(revision 15142)
@@ -137,4 +137,8 @@
       <SubType>Code</SubType>
     </Compile>
+    <Compile Include="Converters\Convert.cs" />
+    <Compile Include="Converters\LinearModelToTreeConverter.cs" />
+    <Compile Include="Converters\TreeSimplifier.cs" />
+    <Compile Include="Converters\TreeToAutoDiffTermConverter.cs" />
     <Compile Include="Formatters\InfixExpressionFormatter.cs" />
     <Compile Include="Formatters\SymbolicDataAnalysisExpressionMathematicaFormatter.cs" />
@@ -250,8 +254,6 @@
     <Compile Include="Symbols\VariableConditionTreeNode.cs" />
     <Compile Include="Symbols\VariableTreeNode.cs" />
-    <Compile Include="Transformation\SymbolicDataAnalysisExpressionTreeSimplifier.cs" />
-    <Compile Include="Transformation\SymbolicExpressionTreeBacktransformator.cs" />
-    <Compile Include="Transformation\TreeToAutoDiffTermTransformator.cs" />
-    <Compile Include="Transformation\TransformationToSymbolicTreeMapper.cs" />
+    <Compile Include="Transformations\SymbolicExpressionTreeBacktransformator.cs" />
+    <Compile Include="Transformations\TransformationToSymbolicTreeMapper.cs" />
     <Compile Include="TreeMatching\SymbolicExpressionTreeBottomUpSimilarityCalculator.cs" />
     <Compile Include="TreeMatching\SymbolicExpressionTreeCanonicalSorter.cs" />
Index: /stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisExpressionTreeSimplificationOperator.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisExpressionTreeSimplificationOperator.cs	(revision 15141)
+++ /stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisExpressionTreeSimplificationOperator.cs	(revision 15142)
@@ -37,5 +37,5 @@
     }
 
-    private readonly SymbolicDataAnalysisExpressionTreeSimplifier simplifier = new SymbolicDataAnalysisExpressionTreeSimplifier();
+    private readonly TreeSimplifier simplifier = new TreeSimplifier();
 
     [StorableConstructor]
Index: able/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Transformation/SymbolicDataAnalysisExpressionTreeSimplifier.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Transformation/SymbolicDataAnalysisExpressionTreeSimplifier.cs	(revision 15141)
+++ 	(revision )
@@ -1,1341 +1,0 @@
-﻿#region License Information
-
-/* HeuristicLab
- * Copyright (C) 2002-2016 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 HeuristicLab.Common;
-using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
-
-namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
-  /// <summary>
-  /// Simplifier for symbolic expressions
-  /// </summary>
-  public class SymbolicDataAnalysisExpressionTreeSimplifier {
-    private Addition addSymbol = new Addition();
-    private Multiplication mulSymbol = new Multiplication();
-    private Division divSymbol = new Division();
-    private Constant constSymbol = new Constant();
-    private Variable varSymbol = new Variable();
-    private Logarithm logSymbol = new Logarithm();
-    private Exponential expSymbol = new Exponential();
-    private Root rootSymbol = new Root();
-    private Square sqrSymbol = new Square();
-    private SquareRoot sqrtSymbol = new SquareRoot();
-    private Power powSymbol = new Power();
-    private Sine sineSymbol = new Sine();
-    private Cosine cosineSymbol = new Cosine();
-    private Tangent tanSymbol = new Tangent();
-    private IfThenElse ifThenElseSymbol = new IfThenElse();
-    private And andSymbol = new And();
-    private Or orSymbol = new Or();
-    private Not notSymbol = new Not();
-    private GreaterThan gtSymbol = new GreaterThan();
-    private LessThan ltSymbol = new LessThan();
-    private Integral integralSymbol = new Integral();
-    private LaggedVariable laggedVariableSymbol = new LaggedVariable();
-    private TimeLag timeLagSymbol = new TimeLag();
-
-    public ISymbolicExpressionTree Simplify(ISymbolicExpressionTree originalTree) {
-      var clone = (ISymbolicExpressionTreeNode)originalTree.Root.Clone();
-      // macro expand (initially no argument trees)
-      var macroExpandedTree = MacroExpand(clone, clone.GetSubtree(0), new List<ISymbolicExpressionTreeNode>());
-      ISymbolicExpressionTreeNode rootNode = (new ProgramRootSymbol()).CreateTreeNode();
-      rootNode.AddSubtree(GetSimplifiedTree(macroExpandedTree));
-
-#if DEBUG
-      // check that each node is only referenced once
-      var nodes = rootNode.IterateNodesPrefix().ToArray();
-      foreach(var n in nodes) if(nodes.Count(ni => ni == n) > 1) throw new InvalidOperationException();
-#endif
-      return new SymbolicExpressionTree(rootNode);
-    }
-
-    // the argumentTrees list contains already expanded trees used as arguments for invocations
-    private ISymbolicExpressionTreeNode MacroExpand(ISymbolicExpressionTreeNode root, ISymbolicExpressionTreeNode node,
-      IList<ISymbolicExpressionTreeNode> argumentTrees) {
-      List<ISymbolicExpressionTreeNode> subtrees = new List<ISymbolicExpressionTreeNode>(node.Subtrees);
-      while (node.SubtreeCount > 0) node.RemoveSubtree(0);
-      if (node.Symbol is InvokeFunction) {
-        var invokeSym = node.Symbol as InvokeFunction;
-        var defunNode = FindFunctionDefinition(root, invokeSym.FunctionName);
-        var macroExpandedArguments = new List<ISymbolicExpressionTreeNode>();
-        foreach (var subtree in subtrees) {
-          macroExpandedArguments.Add(MacroExpand(root, subtree, argumentTrees));
-        }
-        return MacroExpand(root, defunNode, macroExpandedArguments);
-      } else if (node.Symbol is Argument) {
-        var argSym = node.Symbol as Argument;
-        // return the correct argument sub-tree (already macro-expanded)
-        return (SymbolicExpressionTreeNode)argumentTrees[argSym.ArgumentIndex].Clone();
-      } else {
-        // recursive application
-        foreach (var subtree in subtrees) {
-          node.AddSubtree(MacroExpand(root, subtree, argumentTrees));
-        }
-        return node;
-      }
-    }
-
-    private ISymbolicExpressionTreeNode FindFunctionDefinition(ISymbolicExpressionTreeNode root, string functionName) {
-      foreach (var subtree in root.Subtrees.OfType<DefunTreeNode>()) {
-        if (subtree.FunctionName == functionName) return subtree.GetSubtree(0);
-      }
-
-      throw new ArgumentException("Definition of function " + functionName + " not found.");
-    }
-
-    #region symbol predicates
-
-    // arithmetic
-    private bool IsDivision(ISymbolicExpressionTreeNode node) {
-      return node.Symbol is Division;
-    }
-
-    private bool IsMultiplication(ISymbolicExpressionTreeNode node) {
-      return node.Symbol is Multiplication;
-    }
-
-    private bool IsSubtraction(ISymbolicExpressionTreeNode node) {
-      return node.Symbol is Subtraction;
-    }
-
-    private bool IsAddition(ISymbolicExpressionTreeNode node) {
-      return node.Symbol is Addition;
-    }
-
-    private bool IsAverage(ISymbolicExpressionTreeNode node) {
-      return node.Symbol is Average;
-    }
-
-    // exponential
-    private bool IsLog(ISymbolicExpressionTreeNode node) {
-      return node.Symbol is Logarithm;
-    }
-
-    private bool IsExp(ISymbolicExpressionTreeNode node) {
-      return node.Symbol is Exponential;
-    }
-
-    private bool IsRoot(ISymbolicExpressionTreeNode node) {
-      return node.Symbol is Root;
-    }
-
-    private bool IsSquare(ISymbolicExpressionTreeNode node) {
-      return node.Symbol is Square;
-    }
-
-    private bool IsSquareRoot(ISymbolicExpressionTreeNode node) {
-      return node.Symbol is SquareRoot;
-    }
-
-    private bool IsPower(ISymbolicExpressionTreeNode node) {
-      return node.Symbol is Power;
-    }
-
-    // trigonometric
-    private bool IsSine(ISymbolicExpressionTreeNode node) {
-      return node.Symbol is Sine;
-    }
-
-    private bool IsCosine(ISymbolicExpressionTreeNode node) {
-      return node.Symbol is Cosine;
-    }
-
-    private bool IsTangent(ISymbolicExpressionTreeNode node) {
-      return node.Symbol is Tangent;
-    }
-
-    // boolean
-    private bool IsIfThenElse(ISymbolicExpressionTreeNode node) {
-      return node.Symbol is IfThenElse;
-    }
-
-    private bool IsAnd(ISymbolicExpressionTreeNode node) {
-      return node.Symbol is And;
-    }
-
-    private bool IsOr(ISymbolicExpressionTreeNode node) {
-      return node.Symbol is Or;
-    }
-
-    private bool IsNot(ISymbolicExpressionTreeNode node) {
-      return node.Symbol is Not;
-    }
-
-    // comparison
-    private bool IsGreaterThan(ISymbolicExpressionTreeNode node) {
-      return node.Symbol is GreaterThan;
-    }
-
-    private bool IsLessThan(ISymbolicExpressionTreeNode node) {
-      return node.Symbol is LessThan;
-    }
-
-    private bool IsBoolean(ISymbolicExpressionTreeNode node) {
-      return
-        node.Symbol is GreaterThan ||
-        node.Symbol is LessThan ||
-        node.Symbol is And ||
-        node.Symbol is Or;
-    }
-
-    // terminals
-    private bool IsVariable(ISymbolicExpressionTreeNode node) {
-      return node.Symbol is Variable;
-    }
-
-    private bool IsVariableBase(ISymbolicExpressionTreeNode node) {
-      return node is VariableTreeNodeBase;
-    }
-
-    private bool IsFactor(ISymbolicExpressionTreeNode node) {
-      return node is FactorVariableTreeNode;
-    }
-
-    private bool IsBinFactor(ISymbolicExpressionTreeNode node) {
-      return node is BinaryFactorVariableTreeNode;
-    }
-
-    private bool IsConstant(ISymbolicExpressionTreeNode node) {
-      return node.Symbol is Constant;
-    }
-
-    // dynamic
-    private bool IsTimeLag(ISymbolicExpressionTreeNode node) {
-      return node.Symbol is TimeLag;
-    }
-
-    private bool IsIntegral(ISymbolicExpressionTreeNode node) {
-      return node.Symbol is Integral;
-    }
-
-    #endregion
-
-    /// <summary>
-    /// Creates a new simplified tree
-    /// </summary>
-    /// <param name="original"></param>
-    /// <returns></returns>
-    public ISymbolicExpressionTreeNode GetSimplifiedTree(ISymbolicExpressionTreeNode original) {
-      if (IsConstant(original) || IsVariableBase(original)) {
-        return (ISymbolicExpressionTreeNode)original.Clone();
-      } else if (IsAddition(original)) {
-        return SimplifyAddition(original);
-      } else if (IsSubtraction(original)) {
-        return SimplifySubtraction(original);
-      } else if (IsMultiplication(original)) {
-        return SimplifyMultiplication(original);
-      } else if (IsDivision(original)) {
-        return SimplifyDivision(original);
-      } else if (IsAverage(original)) {
-        return SimplifyAverage(original);
-      } else if (IsLog(original)) {
-        return SimplifyLog(original);
-      } else if (IsExp(original)) {
-        return SimplifyExp(original);
-      } else if (IsSquare(original)) {
-        return SimplifySquare(original);
-      } else if (IsSquareRoot(original)) {
-        return SimplifySquareRoot(original);
-      } else if (IsPower(original)) {
-        return SimplifyPower(original);
-      } else if (IsRoot(original)) {
-        return SimplifyRoot(original);
-      } else if (IsSine(original)) {
-        return SimplifySine(original);
-      } else if (IsCosine(original)) {
-        return SimplifyCosine(original);
-      } else if (IsTangent(original)) {
-        return SimplifyTangent(original);
-      } else if (IsIfThenElse(original)) {
-        return SimplifyIfThenElse(original);
-      } else if (IsGreaterThan(original)) {
-        return SimplifyGreaterThan(original);
-      } else if (IsLessThan(original)) {
-        return SimplifyLessThan(original);
-      } else if (IsAnd(original)) {
-        return SimplifyAnd(original);
-      } else if (IsOr(original)) {
-        return SimplifyOr(original);
-      } else if (IsNot(original)) {
-        return SimplifyNot(original);
-      } else if (IsTimeLag(original)) {
-        return SimplifyTimeLag(original);
-      } else if (IsIntegral(original)) {
-        return SimplifyIntegral(original);
-      } else {
-        return SimplifyAny(original);
-      }
-    }
-
-    #region specific simplification routines
-
-    private ISymbolicExpressionTreeNode SimplifyAny(ISymbolicExpressionTreeNode original) {
-      // can't simplify this function but simplify all subtrees 
-      List<ISymbolicExpressionTreeNode> subtrees = new List<ISymbolicExpressionTreeNode>(original.Subtrees);
-      while (original.Subtrees.Count() > 0) original.RemoveSubtree(0);
-      var clone = (SymbolicExpressionTreeNode)original.Clone();
-      List<ISymbolicExpressionTreeNode> simplifiedSubtrees = new List<ISymbolicExpressionTreeNode>();
-      foreach (var subtree in subtrees) {
-        simplifiedSubtrees.Add(GetSimplifiedTree(subtree));
-        original.AddSubtree(subtree);
-      }
-      foreach (var simplifiedSubtree in simplifiedSubtrees) {
-        clone.AddSubtree(simplifiedSubtree);
-      }
-      if (simplifiedSubtrees.TrueForAll(t => IsConstant(t))) {
-        SimplifyConstantExpression(clone);
-      }
-      return clone;
-    }
-
-    private ISymbolicExpressionTreeNode SimplifyConstantExpression(ISymbolicExpressionTreeNode original) {
-      // not yet implemented
-      return original;
-    }
-
-    private ISymbolicExpressionTreeNode SimplifyAverage(ISymbolicExpressionTreeNode original) {
-      if (original.Subtrees.Count() == 1) {
-        return GetSimplifiedTree(original.GetSubtree(0));
-      } else {
-        // simplify expressions x0..xn
-        // make sum(x0..xn) / n
-        var sum = original.Subtrees
-          .Select(GetSimplifiedTree)
-          .Aggregate(MakeSum);
-        return MakeFraction(sum, MakeConstant(original.Subtrees.Count()));
-      }
-    }
-
-    private ISymbolicExpressionTreeNode SimplifyDivision(ISymbolicExpressionTreeNode original) {
-      if (original.Subtrees.Count() == 1) {
-        return Invert(GetSimplifiedTree(original.GetSubtree(0)));
-      } else {
-        // simplify expressions x0..xn
-        // make multiplication (x0 * 1/(x1 * x1 * .. * xn))
-        var first = original.GetSubtree(0);
-        var second = original.GetSubtree(1);
-        var remaining = original.Subtrees.Skip(2);
-        return
-          MakeProduct(GetSimplifiedTree(first),
-            Invert(remaining.Aggregate(GetSimplifiedTree(second), (a, b) => MakeProduct(a, GetSimplifiedTree(b)))));
-      }
-    }
-
-    private ISymbolicExpressionTreeNode SimplifyMultiplication(ISymbolicExpressionTreeNode original) {
-      if (original.Subtrees.Count() == 1) {
-        return GetSimplifiedTree(original.GetSubtree(0));
-      } else {
-        return original.Subtrees
-          .Select(GetSimplifiedTree)
-          .Aggregate(MakeProduct);
-      }
-    }
-
-    private ISymbolicExpressionTreeNode SimplifySubtraction(ISymbolicExpressionTreeNode original) {
-      if (original.Subtrees.Count() == 1) {
-        return Negate(GetSimplifiedTree(original.GetSubtree(0)));
-      } else {
-        // simplify expressions x0..xn
-        // make addition (x0,-x1..-xn)
-        var first = original.Subtrees.First();
-        var remaining = original.Subtrees.Skip(1);
-        return remaining.Aggregate(GetSimplifiedTree(first), (a, b) => MakeSum(a, Negate(GetSimplifiedTree(b))));
-      }
-    }
-
-    private ISymbolicExpressionTreeNode SimplifyAddition(ISymbolicExpressionTreeNode original) {
-      if (original.Subtrees.Count() == 1) {
-        return GetSimplifiedTree(original.GetSubtree(0));
-      } else {
-        // simplify expression x0..xn
-        // make addition (x0..xn)
-        return original.Subtrees
-          .Select(GetSimplifiedTree)
-          .Aggregate(MakeSum);
-      }
-    }
-
-    private ISymbolicExpressionTreeNode SimplifyNot(ISymbolicExpressionTreeNode original) {
-      return MakeNot(GetSimplifiedTree(original.GetSubtree(0)));
-    }
-
-    private ISymbolicExpressionTreeNode SimplifyOr(ISymbolicExpressionTreeNode original) {
-      return original.Subtrees
-        .Select(GetSimplifiedTree)
-        .Aggregate(MakeOr);
-    }
-
-    private ISymbolicExpressionTreeNode SimplifyAnd(ISymbolicExpressionTreeNode original) {
-      return original.Subtrees
-        .Select(GetSimplifiedTree)
-        .Aggregate(MakeAnd);
-    }
-
-    private ISymbolicExpressionTreeNode SimplifyLessThan(ISymbolicExpressionTreeNode original) {
-      return MakeLessThan(GetSimplifiedTree(original.GetSubtree(0)), GetSimplifiedTree(original.GetSubtree(1)));
-    }
-
-    private ISymbolicExpressionTreeNode SimplifyGreaterThan(ISymbolicExpressionTreeNode original) {
-      return MakeGreaterThan(GetSimplifiedTree(original.GetSubtree(0)), GetSimplifiedTree(original.GetSubtree(1)));
-    }
-
-    private ISymbolicExpressionTreeNode SimplifyIfThenElse(ISymbolicExpressionTreeNode original) {
-      return MakeIfThenElse(GetSimplifiedTree(original.GetSubtree(0)), GetSimplifiedTree(original.GetSubtree(1)),
-        GetSimplifiedTree(original.GetSubtree(2)));
-    }
-
-    private ISymbolicExpressionTreeNode SimplifyTangent(ISymbolicExpressionTreeNode original) {
-      return MakeTangent(GetSimplifiedTree(original.GetSubtree(0)));
-    }
-
-    private ISymbolicExpressionTreeNode SimplifyCosine(ISymbolicExpressionTreeNode original) {
-      return MakeCosine(GetSimplifiedTree(original.GetSubtree(0)));
-    }
-
-    private ISymbolicExpressionTreeNode SimplifySine(ISymbolicExpressionTreeNode original) {
-      return MakeSine(GetSimplifiedTree(original.GetSubtree(0)));
-    }
-
-    private ISymbolicExpressionTreeNode SimplifyExp(ISymbolicExpressionTreeNode original) {
-      return MakeExp(GetSimplifiedTree(original.GetSubtree(0)));
-    }
-
-    private ISymbolicExpressionTreeNode SimplifySquare(ISymbolicExpressionTreeNode original) {
-      return MakeSquare(GetSimplifiedTree(original.GetSubtree(0)));
-    }
-
-    private ISymbolicExpressionTreeNode SimplifySquareRoot(ISymbolicExpressionTreeNode original) {
-      return MakeSquareRoot(GetSimplifiedTree(original.GetSubtree(0)));
-    }
-
-    private ISymbolicExpressionTreeNode SimplifyLog(ISymbolicExpressionTreeNode original) {
-      return MakeLog(GetSimplifiedTree(original.GetSubtree(0)));
-    }
-
-    private ISymbolicExpressionTreeNode SimplifyRoot(ISymbolicExpressionTreeNode original) {
-      return MakeRoot(GetSimplifiedTree(original.GetSubtree(0)), GetSimplifiedTree(original.GetSubtree(1)));
-    }
-
-    private ISymbolicExpressionTreeNode SimplifyPower(ISymbolicExpressionTreeNode original) {
-      return MakePower(GetSimplifiedTree(original.GetSubtree(0)), GetSimplifiedTree(original.GetSubtree(1)));
-    }
-
-    private ISymbolicExpressionTreeNode SimplifyTimeLag(ISymbolicExpressionTreeNode original) {
-      var laggedTreeNode = original as ILaggedTreeNode;
-      var simplifiedSubtree = GetSimplifiedTree(original.GetSubtree(0));
-      if (!ContainsVariableCondition(simplifiedSubtree)) {
-        return AddLagToDynamicNodes(simplifiedSubtree, laggedTreeNode.Lag);
-      } else {
-        return MakeTimeLag(simplifiedSubtree, laggedTreeNode.Lag);
-      }
-    }
-
-    private ISymbolicExpressionTreeNode SimplifyIntegral(ISymbolicExpressionTreeNode original) {
-      var laggedTreeNode = original as ILaggedTreeNode;
-      var simplifiedSubtree = GetSimplifiedTree(original.GetSubtree(0));
-      if (IsConstant(simplifiedSubtree)) {
-        return GetSimplifiedTree(MakeProduct(simplifiedSubtree, MakeConstant(-laggedTreeNode.Lag)));
-      } else {
-        return MakeIntegral(simplifiedSubtree, laggedTreeNode.Lag);
-      }
-    }
-
-    #endregion
-
-    #region low level tree restructuring
-
-    private ISymbolicExpressionTreeNode MakeTimeLag(ISymbolicExpressionTreeNode subtree, int lag) {
-      if (lag == 0) return subtree;
-      if (IsConstant(subtree)) return subtree;
-      var lagNode = (LaggedTreeNode)timeLagSymbol.CreateTreeNode();
-      lagNode.Lag = lag;
-      lagNode.AddSubtree(subtree);
-      return lagNode;
-    }
-
-    private ISymbolicExpressionTreeNode MakeIntegral(ISymbolicExpressionTreeNode subtree, int lag) {
-      if (lag == 0) return subtree;
-      else if (lag == -1 || lag == 1) {
-        return MakeSum(subtree, AddLagToDynamicNodes((ISymbolicExpressionTreeNode)subtree.Clone(), lag));
-      } else {
-        var node = (LaggedTreeNode)integralSymbol.CreateTreeNode();
-        node.Lag = lag;
-        node.AddSubtree(subtree);
-        return node;
-      }
-    }
-
-    private ISymbolicExpressionTreeNode MakeNot(ISymbolicExpressionTreeNode t) {
-      if (IsConstant(t)) {
-        var constNode = t as ConstantTreeNode;
-        if (constNode.Value > 0) return MakeConstant(-1.0);
-        else return MakeConstant(1.0);
-      } else if (IsNot(t)) {
-        return t.GetSubtree(0);
-      } else if (!IsBoolean(t)) {
-        var gtNode = gtSymbol.CreateTreeNode();
-        gtNode.AddSubtree(t);
-        gtNode.AddSubtree(MakeConstant(0.0));
-        var notNode = notSymbol.CreateTreeNode();
-        notNode.AddSubtree(gtNode);
-        return notNode;
-      } else {
-        var notNode = notSymbol.CreateTreeNode();
-        notNode.AddSubtree(t);
-        return notNode;
-      }
-    }
-
-    private ISymbolicExpressionTreeNode MakeOr(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) {
-      if (IsConstant(a) && IsConstant(b)) {
-        var constA = a as ConstantTreeNode;
-        var constB = b as ConstantTreeNode;
-        if (constA.Value > 0.0 || constB.Value > 0.0) {
-          return MakeConstant(1.0);
-        } else {
-          return MakeConstant(-1.0);
-        }
-      } else if (IsConstant(a)) {
-        return MakeOr(b, a);
-      } else if (IsConstant(b)) {
-        var constT = b as ConstantTreeNode;
-        if (constT.Value > 0.0) {
-          // boolean expression is necessarily true
-          return MakeConstant(1.0);
-        } else {
-          // the constant value has no effect on the result of the boolean condition so we can drop the constant term
-          var orNode = orSymbol.CreateTreeNode();
-          orNode.AddSubtree(a);
-          return orNode;
-        }
-      } else {
-        var orNode = orSymbol.CreateTreeNode();
-        orNode.AddSubtree(a);
-        orNode.AddSubtree(b);
-        return orNode;
-      }
-    }
-
-    private ISymbolicExpressionTreeNode MakeAnd(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) {
-      if (IsConstant(a) && IsConstant(b)) {
-        var constA = a as ConstantTreeNode;
-        var constB = b as ConstantTreeNode;
-        if (constA.Value > 0.0 && constB.Value > 0.0) {
-          return MakeConstant(1.0);
-        } else {
-          return MakeConstant(-1.0);
-        }
-      } else if (IsConstant(a)) {
-        return MakeAnd(b, a);
-      } else if (IsConstant(b)) {
-        var constB = b as ConstantTreeNode;
-        if (constB.Value > 0.0) {
-          // the constant value has no effect on the result of the boolean condition so we can drop the constant term
-          var andNode = andSymbol.CreateTreeNode();
-          andNode.AddSubtree(a);
-          return andNode;
-        } else {
-          // boolean expression is necessarily false
-          return MakeConstant(-1.0);
-        }
-      } else {
-        var andNode = andSymbol.CreateTreeNode();
-        andNode.AddSubtree(a);
-        andNode.AddSubtree(b);
-        return andNode;
-      }
-    }
-
-    private ISymbolicExpressionTreeNode MakeLessThan(ISymbolicExpressionTreeNode leftSide,
-      ISymbolicExpressionTreeNode rightSide) {
-      if (IsConstant(leftSide) && IsConstant(rightSide)) {
-        var lsConst = leftSide as ConstantTreeNode;
-        var rsConst = rightSide as ConstantTreeNode;
-        if (lsConst.Value < rsConst.Value) return MakeConstant(1.0);
-        else return MakeConstant(-1.0);
-      } else {
-        var ltNode = ltSymbol.CreateTreeNode();
-        ltNode.AddSubtree(leftSide);
-        ltNode.AddSubtree(rightSide);
-        return ltNode;
-      }
-    }
-
-    private ISymbolicExpressionTreeNode MakeGreaterThan(ISymbolicExpressionTreeNode leftSide,
-      ISymbolicExpressionTreeNode rightSide) {
-      if (IsConstant(leftSide) && IsConstant(rightSide)) {
-        var lsConst = leftSide as ConstantTreeNode;
-        var rsConst = rightSide as ConstantTreeNode;
-        if (lsConst.Value > rsConst.Value) return MakeConstant(1.0);
-        else return MakeConstant(-1.0);
-      } else {
-        var gtNode = gtSymbol.CreateTreeNode();
-        gtNode.AddSubtree(leftSide);
-        gtNode.AddSubtree(rightSide);
-        return gtNode;
-      }
-    }
-
-    private ISymbolicExpressionTreeNode MakeIfThenElse(ISymbolicExpressionTreeNode condition,
-      ISymbolicExpressionTreeNode trueBranch, ISymbolicExpressionTreeNode falseBranch) {
-      if (IsConstant(condition)) {
-        var constT = condition as ConstantTreeNode;
-        if (constT.Value > 0.0) return trueBranch;
-        else return falseBranch;
-      } else {
-        var ifNode = ifThenElseSymbol.CreateTreeNode();
-        if (IsBoolean(condition)) {
-          ifNode.AddSubtree(condition);
-        } else {
-          var gtNode = gtSymbol.CreateTreeNode();
-          gtNode.AddSubtree(condition);
-          gtNode.AddSubtree(MakeConstant(0.0));
-          ifNode.AddSubtree(gtNode);
-        }
-        ifNode.AddSubtree(trueBranch);
-        ifNode.AddSubtree(falseBranch);
-        return ifNode;
-      }
-    }
-
-    private ISymbolicExpressionTreeNode MakeSine(ISymbolicExpressionTreeNode node) {
-      if (IsConstant(node)) {
-        var constT = node as ConstantTreeNode;
-        return MakeConstant(Math.Sin(constT.Value));
-      } else if (IsFactor(node)) {
-        var factor = node as FactorVariableTreeNode;
-        return MakeFactor(factor.Symbol, factor.VariableName, factor.Weights.Select(Math.Sin));
-      } else if (IsBinFactor(node)) {
-        var binFactor = node as BinaryFactorVariableTreeNode;
-        return MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Sin(binFactor.Weight));
-      } else {
-        var sineNode = sineSymbol.CreateTreeNode();
-        sineNode.AddSubtree(node);
-        return sineNode;
-      }
-    }
-
-    private ISymbolicExpressionTreeNode MakeTangent(ISymbolicExpressionTreeNode node) {
-      if (IsConstant(node)) {
-        var constT = node as ConstantTreeNode;
-        return MakeConstant(Math.Tan(constT.Value));
-      } else if (IsFactor(node)) {
-        var factor = node as FactorVariableTreeNode;
-        return MakeFactor(factor.Symbol, factor.VariableName, factor.Weights.Select(Math.Tan));
-      } else if (IsBinFactor(node)) {
-        var binFactor = node as BinaryFactorVariableTreeNode;
-        return MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Tan(binFactor.Weight));
-      } else {
-        var tanNode = tanSymbol.CreateTreeNode();
-        tanNode.AddSubtree(node);
-        return tanNode;
-      }
-    }
-
-    private ISymbolicExpressionTreeNode MakeCosine(ISymbolicExpressionTreeNode node) {
-      if (IsConstant(node)) {
-        var constT = node as ConstantTreeNode;
-        return MakeConstant(Math.Cos(constT.Value));
-      } else if (IsFactor(node)) {
-        var factor = node as FactorVariableTreeNode;
-        return MakeFactor(factor.Symbol, factor.VariableName, factor.Weights.Select(Math.Cos));
-      } else if (IsBinFactor(node)) {
-        var binFactor = node as BinaryFactorVariableTreeNode;
-        // cos(0) = 1 see similar case for Exp(binfactor)
-        return MakeSum(MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Cos(binFactor.Weight) - 1),
-          MakeConstant(1.0));
-      } else {
-        var cosNode = cosineSymbol.CreateTreeNode();
-        cosNode.AddSubtree(node);
-        return cosNode;
-      }
-    }
-
-    private ISymbolicExpressionTreeNode MakeExp(ISymbolicExpressionTreeNode node) {
-      if (IsConstant(node)) {
-        var constT = node as ConstantTreeNode;
-        return MakeConstant(Math.Exp(constT.Value));
-      } else if (IsFactor(node)) {
-        var factNode = node as FactorVariableTreeNode;
-        return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => Math.Exp(w)));
-      } else if (IsBinFactor(node)) {
-        // exp( binfactor w val=a) = if(val=a) exp(w) else exp(0) = binfactor( (exp(w) - 1) val a) + 1
-        var binFactor = node as BinaryFactorVariableTreeNode;
-        return
-          MakeSum(MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Exp(binFactor.Weight) - 1), MakeConstant(1.0));
-      } else if (IsLog(node)) {
-        return node.GetSubtree(0);
-      } else if (IsAddition(node)) {
-        return node.Subtrees.Select(s => MakeExp(s)).Aggregate((s, t) => MakeProduct(s, t));
-      } else if (IsSubtraction(node)) {
-        return node.Subtrees.Select(s => MakeExp(s)).Aggregate((s, t) => MakeProduct(s, Negate(t)));
-      } else {
-        var expNode = expSymbol.CreateTreeNode();
-        expNode.AddSubtree(node);
-        return expNode;
-      }
-    }
-    private ISymbolicExpressionTreeNode MakeLog(ISymbolicExpressionTreeNode node) {
-      if (IsConstant(node)) {
-        var constT = node as ConstantTreeNode;
-        return MakeConstant(Math.Log(constT.Value));
-      } else if (IsFactor(node)) {
-        var factNode = node as FactorVariableTreeNode;
-        return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => Math.Log(w)));
-      } else if (IsExp(node)) {
-        return node.GetSubtree(0);
-      } else if (IsSquareRoot(node)) {
-        return MakeFraction(MakeLog(node.GetSubtree(0)), MakeConstant(2.0));
-      } else {
-        var logNode = logSymbol.CreateTreeNode();
-        logNode.AddSubtree(node);
-        return logNode;
-      }
-    }
-
-    private ISymbolicExpressionTreeNode MakeSquare(ISymbolicExpressionTreeNode node) {
-      if (IsConstant(node)) {
-        var constT = node as ConstantTreeNode;
-        return MakeConstant(constT.Value * constT.Value);
-      } else if (IsFactor(node)) {
-        var factNode = node as FactorVariableTreeNode;
-        return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => w * w));
-      } else if (IsBinFactor(node)) {
-        var binFactor = node as BinaryFactorVariableTreeNode;
-        return MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, binFactor.Weight * binFactor.Weight);
-      } else if (IsSquareRoot(node)) {
-        return node.GetSubtree(0);
-      } else {
-        var sqrNode = sqrSymbol.CreateTreeNode();
-        sqrNode.AddSubtree(node);
-        return sqrNode;
-      }
-    }
-
-    private ISymbolicExpressionTreeNode MakeSquareRoot(ISymbolicExpressionTreeNode node) {
-      if (IsConstant(node)) {
-        var constT = node as ConstantTreeNode;
-        return MakeConstant(Math.Sqrt(constT.Value));
-      } else if (IsFactor(node)) {
-        var factNode = node as FactorVariableTreeNode;
-        return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => Math.Sqrt(w)));
-      } else if (IsBinFactor(node)) {
-        var binFactor = node as BinaryFactorVariableTreeNode;
-        return MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Sqrt(binFactor.Weight));
-      } else if (IsSquare(node)) {
-        return node.GetSubtree(0);
-      } else {
-        var sqrtNode = sqrtSymbol.CreateTreeNode();
-        sqrtNode.AddSubtree(node);
-        return sqrtNode;
-      }
-    }
-
-    private ISymbolicExpressionTreeNode MakeRoot(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) {
-      if (IsConstant(a) && IsConstant(b)) {
-        var constA = a as ConstantTreeNode;
-        var constB = b as ConstantTreeNode;
-        return MakeConstant(Math.Pow(constA.Value, 1.0 / Math.Round(constB.Value)));
-      } else if (IsFactor(a) && IsConstant(b)) {
-        var factNode = a as FactorVariableTreeNode;
-        var constNode = b as ConstantTreeNode;
-        return MakeFactor(factNode.Symbol, factNode.VariableName,
-          factNode.Weights.Select(w => Math.Pow(w, 1.0 / Math.Round(constNode.Value))));
-      } else if (IsBinFactor(a) && IsConstant(b)) {
-        var binFactor = a as BinaryFactorVariableTreeNode;
-        var constNode = b as ConstantTreeNode;
-        return MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Pow(binFactor.Weight, 1.0 / Math.Round(constNode.Value)));
-      } else if (IsConstant(a) && IsFactor(b)) {
-        var constNode = a as ConstantTreeNode;
-        var factNode = b as FactorVariableTreeNode;
-        return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => Math.Pow(constNode.Value, 1.0 / Math.Round(w))));
-      } else if (IsConstant(a) && IsBinFactor(b)) {
-        var constNode = a as ConstantTreeNode;
-        var factNode = b as BinaryFactorVariableTreeNode;
-        return MakeBinFactor(factNode.Symbol, factNode.VariableName, factNode.VariableValue, Math.Pow(constNode.Value, 1.0 / Math.Round(factNode.Weight)));
-      } else if (IsFactor(a) && IsFactor(b) && AreSameTypeAndVariable(a, b)) {
-        var node0 = a as FactorVariableTreeNode;
-        var node1 = b as FactorVariableTreeNode;
-        return MakeFactor(node0.Symbol, node0.VariableName, node0.Weights.Zip(node1.Weights, (u, v) => Math.Pow(u, 1.0 / Math.Round(v))));
-      } else if (IsConstant(b)) {
-        var constB = b as ConstantTreeNode;
-        var constBValue = Math.Round(constB.Value);
-        if (constBValue.IsAlmost(1.0)) {
-          return a;
-        } else if (constBValue.IsAlmost(0.0)) {
-          return MakeConstant(1.0);
-        } else if (constBValue.IsAlmost(-1.0)) {
-          return MakeFraction(MakeConstant(1.0), a);
-        } else if (constBValue < 0) {
-          var rootNode = rootSymbol.CreateTreeNode();
-          rootNode.AddSubtree(a);
-          rootNode.AddSubtree(MakeConstant(-1.0 * constBValue));
-          return MakeFraction(MakeConstant(1.0), rootNode);
-        } else {
-          var rootNode = rootSymbol.CreateTreeNode();
-          rootNode.AddSubtree(a);
-          rootNode.AddSubtree(MakeConstant(constBValue));
-          return rootNode;
-        }
-      } else {
-        var rootNode = rootSymbol.CreateTreeNode();
-        rootNode.AddSubtree(a);
-        rootNode.AddSubtree(b);
-        return rootNode;
-      }
-    }
-
-
-    private ISymbolicExpressionTreeNode MakePower(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) {
-      if (IsConstant(a) && IsConstant(b)) {
-        var constA = a as ConstantTreeNode;
-        var constB = b as ConstantTreeNode;
-        return MakeConstant(Math.Pow(constA.Value, Math.Round(constB.Value)));
-      } else if (IsFactor(a) && IsConstant(b)) {
-        var factNode = a as FactorVariableTreeNode;
-        var constNode = b as ConstantTreeNode;
-        return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => Math.Pow(w, Math.Round(constNode.Value))));
-      } else if (IsBinFactor(a) && IsConstant(b)) {
-        var binFactor = a as BinaryFactorVariableTreeNode;
-        var constNode = b as ConstantTreeNode;
-        return MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Pow(binFactor.Weight, Math.Round(constNode.Value)));
-      } else if (IsConstant(a) && IsFactor(b)) {
-        var constNode = a as ConstantTreeNode;
-        var factNode = b as FactorVariableTreeNode;
-        return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => Math.Pow(constNode.Value, Math.Round(w))));
-      } else if (IsConstant(a) && IsBinFactor(b)) {
-        var constNode = a as ConstantTreeNode;
-        var factNode = b as BinaryFactorVariableTreeNode;
-        return MakeBinFactor(factNode.Symbol, factNode.VariableName, factNode.VariableValue, Math.Pow(constNode.Value, Math.Round(factNode.Weight)));
-      } else if (IsFactor(a) && IsFactor(b) && AreSameTypeAndVariable(a, b)) {
-        var node0 = a as FactorVariableTreeNode;
-        var node1 = b as FactorVariableTreeNode;
-        return MakeFactor(node0.Symbol, node0.VariableName, node0.Weights.Zip(node1.Weights, (u, v) => Math.Pow(u, Math.Round(v))));
-      } else if (IsConstant(b)) {
-        var constB = b as ConstantTreeNode;
-        double exponent = Math.Round(constB.Value);
-        if (exponent.IsAlmost(0.0)) {
-          return MakeConstant(1.0);
-        } else if (exponent.IsAlmost(1.0)) {
-          return a;
-        } else if (exponent.IsAlmost(-1.0)) {
-          return MakeFraction(MakeConstant(1.0), a);
-        } else if (exponent < 0) {
-          var powNode = powSymbol.CreateTreeNode();
-          powNode.AddSubtree(a);
-          powNode.AddSubtree(MakeConstant(-1.0 * exponent));
-          return MakeFraction(MakeConstant(1.0), powNode);
-        } else {
-          var powNode = powSymbol.CreateTreeNode();
-          powNode.AddSubtree(a);
-          powNode.AddSubtree(MakeConstant(exponent));
-          return powNode;
-        }
-      } else {
-        var powNode = powSymbol.CreateTreeNode();
-        powNode.AddSubtree(a);
-        powNode.AddSubtree(b);
-        return powNode;
-      }
-    }
-
-
-    // MakeFraction, MakeProduct and MakeSum take two already simplified trees and create a new simplified tree
-    private ISymbolicExpressionTreeNode MakeFraction(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) {
-      if (IsConstant(a) && IsConstant(b)) {
-        // fold constants
-        return MakeConstant(((ConstantTreeNode)a).Value / ((ConstantTreeNode)b).Value);
-      } else if ((IsConstant(a) && !((ConstantTreeNode)a).Value.IsAlmost(1.0))) {
-        return MakeFraction(MakeConstant(1.0), MakeProduct(b, Invert(a)));
-      } else if (IsVariableBase(a) && IsConstant(b)) {
-        // merge constant values into variable weights
-        var constB = ((ConstantTreeNode)b).Value;
-        ((VariableTreeNodeBase)a).Weight /= constB;
-        return a;
-      } else if (IsFactor(a) && IsConstant(b)) {
-        var factNode = a as FactorVariableTreeNode;
-        var constNode = b as ConstantTreeNode;
-        return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => w / constNode.Value));
-      } else if (IsBinFactor(a) && IsConstant(b)) {
-        var factNode = a as BinaryFactorVariableTreeNode;
-        var constNode = b as ConstantTreeNode;
-        return MakeBinFactor(factNode.Symbol, factNode.VariableName, factNode.VariableValue, factNode.Weight / constNode.Value);
-      } else if (IsFactor(a) && IsFactor(b) && AreSameTypeAndVariable(a, b)) {
-        var node0 = a as FactorVariableTreeNode;
-        var node1 = b as FactorVariableTreeNode;
-        return MakeFactor(node0.Symbol, node0.VariableName, node0.Weights.Zip(node1.Weights, (u, v) => u / v));
-      } else if (IsFactor(a) && IsBinFactor(b) && ((IVariableTreeNode)a).VariableName == ((IVariableTreeNode)b).VariableName) {
-        var node0 = a as FactorVariableTreeNode;
-        var node1 = b as BinaryFactorVariableTreeNode;
-        var varValues = node0.Symbol.GetVariableValues(node0.VariableName).ToArray();
-        var wi = Array.IndexOf(varValues, node1.VariableValue);
-        if (wi < 0) throw new ArgumentException();
-        var newWeighs = new double[varValues.Length];
-        node0.Weights.CopyTo(newWeighs, 0);
-        for (int i = 0; i < newWeighs.Length; i++)
-          if (wi == i) newWeighs[i] /= node1.Weight;
-          else newWeighs[i] /= 0.0;
-        return MakeFactor(node0.Symbol, node0.VariableName, newWeighs);
-      } else if (IsFactor(a)) {
-        return MakeFraction(MakeConstant(1.0), MakeProduct(b, Invert(a)));
-      } else if (IsVariableBase(a) && IsVariableBase(b) && AreSameTypeAndVariable(a, b) && !IsBinFactor(b)) {
-        // cancel variables (not allowed for bin factors because of division by zero)
-        var aVar = a as VariableTreeNode;
-        var bVar = b as VariableTreeNode;
-        return MakeConstant(aVar.Weight / bVar.Weight);
-      } else if (IsAddition(a) && IsConstant(b)) {
-        return a.Subtrees
-          .Select(x => GetSimplifiedTree(x))
-          .Select(x => MakeFraction(x, GetSimplifiedTree(b)))
-          .Aggregate((c, d) => MakeSum(c, d));
-      } else if (IsMultiplication(a) && IsConstant(b)) {
-        return MakeProduct(a, Invert(b));
-      } else if (IsDivision(a) && IsConstant(b)) {
-        // (a1 / a2) / c => (a1 / (a2 * c))
-        return MakeFraction(a.GetSubtree(0), MakeProduct(a.GetSubtree(1), b));
-      } else if (IsDivision(a) && IsDivision(b)) {
-        // (a1 / a2) / (b1 / b2) => 
-        return MakeFraction(MakeProduct(a.GetSubtree(0), b.GetSubtree(1)), MakeProduct(a.GetSubtree(1), b.GetSubtree(0)));
-      } else if (IsDivision(a)) {
-        // (a1 / a2) / b => (a1 / (a2 * b))
-        return MakeFraction(a.GetSubtree(0), MakeProduct(a.GetSubtree(1), b));
-      } else if (IsDivision(b)) {
-        // a / (b1 / b2) => (a * b2) / b1
-        return MakeFraction(MakeProduct(a, b.GetSubtree(1)), b.GetSubtree(0));
-      } else {
-        var div = divSymbol.CreateTreeNode();
-        div.AddSubtree(a);
-        div.AddSubtree(b);
-        return div;
-      }
-    }
-
-    private ISymbolicExpressionTreeNode MakeSum(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) {
-      if (IsConstant(a) && IsConstant(b)) {
-        // fold constants
-        ((ConstantTreeNode)a).Value += ((ConstantTreeNode)b).Value;
-        return a;
-      } else if (IsConstant(a)) {
-        // c + x => x + c
-        // b is not constant => make sure constant is on the right
-        return MakeSum(b, a);
-      } else if (IsConstant(b) && ((ConstantTreeNode)b).Value.IsAlmost(0.0)) {
-        // x + 0 => x
-        return a;
-      } else if (IsFactor(a) && IsConstant(b)) {
-        var factNode = a as FactorVariableTreeNode;
-        var constNode = b as ConstantTreeNode;
-        return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select((w) => w + constNode.Value));
-      } else if (IsFactor(a) && IsFactor(b) && AreSameTypeAndVariable(a, b)) {
-        var node0 = a as FactorVariableTreeNode;
-        var node1 = b as FactorVariableTreeNode;
-        return MakeFactor(node0.Symbol, node0.VariableName, node0.Weights.Zip(node1.Weights, (u, v) => u + v));
-      } else if (IsBinFactor(a) && IsFactor(b)) {
-        return MakeSum(b, a);
-      } else if (IsFactor(a) && IsBinFactor(b) &&
-        ((IVariableTreeNode)a).VariableName == ((IVariableTreeNode)b).VariableName) {
-        var node0 = a as FactorVariableTreeNode;
-        var node1 = b as BinaryFactorVariableTreeNode;
-        var varValues = node0.Symbol.GetVariableValues(node0.VariableName).ToArray();
-        var wi = Array.IndexOf(varValues, node1.VariableValue);
-        if (wi < 0) throw new ArgumentException();
-        var newWeighs = new double[varValues.Length];
-        node0.Weights.CopyTo(newWeighs, 0);
-        newWeighs[wi] += node1.Weight;
-        return MakeFactor(node0.Symbol, node0.VariableName, newWeighs);
-      } else if (IsAddition(a) && IsAddition(b)) {
-        // merge additions
-        var add = addSymbol.CreateTreeNode();
-        // add all sub trees except for the last
-        for (int i = 0; i < a.Subtrees.Count() - 1; i++) add.AddSubtree(a.GetSubtree(i));
-        for (int i = 0; i < b.Subtrees.Count() - 1; i++) add.AddSubtree(b.GetSubtree(i));
-        if (IsConstant(a.Subtrees.Last()) && IsConstant(b.Subtrees.Last())) {
-          add.AddSubtree(MakeSum(a.Subtrees.Last(), b.Subtrees.Last()));
-        } else if (IsConstant(a.Subtrees.Last())) {
-          add.AddSubtree(b.Subtrees.Last());
-          add.AddSubtree(a.Subtrees.Last());
-        } else {
-          add.AddSubtree(a.Subtrees.Last());
-          add.AddSubtree(b.Subtrees.Last());
-        }
-        MergeVariablesInSum(add);
-        if (add.Subtrees.Count() == 1) {
-          return add.GetSubtree(0);
-        } else {
-          return add;
-        }
-      } else if (IsAddition(b)) {
-        return MakeSum(b, a);
-      } else if (IsAddition(a) && IsConstant(b)) {
-        // a is an addition and b is a constant => append b to a and make sure the constants are merged
-        var add = addSymbol.CreateTreeNode();
-        // add all sub trees except for the last
-        for (int i = 0; i < a.Subtrees.Count() - 1; i++) add.AddSubtree(a.GetSubtree(i));
-        if (IsConstant(a.Subtrees.Last()))
-          add.AddSubtree(MakeSum(a.Subtrees.Last(), b));
-        else {
-          add.AddSubtree(a.Subtrees.Last());
-          add.AddSubtree(b);
-        }
-        return add;
-      } else if (IsAddition(a)) {
-        // a is already an addition => append b
-        var add = addSymbol.CreateTreeNode();
-        add.AddSubtree(b);
-        foreach (var subtree in a.Subtrees) {
-          add.AddSubtree(subtree);
-        }
-        MergeVariablesInSum(add);
-        if (add.Subtrees.Count() == 1) {
-          return add.GetSubtree(0);
-        } else {
-          return add;
-        }
-      } else {
-        var add = addSymbol.CreateTreeNode();
-        add.AddSubtree(a);
-        add.AddSubtree(b);
-        MergeVariablesInSum(add);
-        if (add.Subtrees.Count() == 1) {
-          return add.GetSubtree(0);
-        } else {
-          return add;
-        }
-      }
-    }
-
-    // makes sure variable symbols in sums are combined
-    private void MergeVariablesInSum(ISymbolicExpressionTreeNode sum) {
-      var subtrees = new List<ISymbolicExpressionTreeNode>(sum.Subtrees);
-      while (sum.Subtrees.Any()) sum.RemoveSubtree(0);
-      var groupedVarNodes = from node in subtrees.OfType<IVariableTreeNode>()
-                            where node.SubtreeCount == 0
-                            group node by GroupId(node) into g
-                            select g;
-      var constant = (from node in subtrees.OfType<ConstantTreeNode>()
-                      select node.Value).DefaultIfEmpty(0.0).Sum();
-      var unchangedSubtrees = subtrees.Where(t => t.SubtreeCount > 0 || !(t is IVariableTreeNode) && !(t is ConstantTreeNode));
-
-      foreach (var variableNodeGroup in groupedVarNodes) {
-        var firstNode = variableNodeGroup.First();
-        if (firstNode is VariableTreeNodeBase) {
-          var representative = firstNode as VariableTreeNodeBase;
-          var weightSum = variableNodeGroup.Cast<VariableTreeNodeBase>().Select(t => t.Weight).Sum();
-          representative.Weight = weightSum;
-          sum.AddSubtree(representative);
-        } else if (firstNode is FactorVariableTreeNode) {
-          var representative = firstNode as FactorVariableTreeNode;
-          foreach (var node in variableNodeGroup.Skip(1).Cast<FactorVariableTreeNode>()) {
-            for (int j = 0; j < representative.Weights.Length; j++) {
-              representative.Weights[j] += node.Weights[j];
-            }
-          }
-          for (int j = 0; j < representative.Weights.Length; j++) {
-            representative.Weights[j] += constant;
-          }
-          sum.AddSubtree(representative);
-        }
-      }
-      foreach (var unchangedSubtree in unchangedSubtrees)
-        sum.AddSubtree(unchangedSubtree);
-      if (!constant.IsAlmost(0.0)) {
-        sum.AddSubtree(MakeConstant(constant));
-      }
-    }
-
-    // nodes referencing variables can be grouped if they have
-    private string GroupId(IVariableTreeNode node) {
-      var binaryFactorNode = node as BinaryFactorVariableTreeNode;
-      var factorNode = node as FactorVariableTreeNode;
-      var variableNode = node as VariableTreeNode;
-      var laggedVarNode = node as LaggedVariableTreeNode;
-      if (variableNode != null) {
-        return "var " + variableNode.VariableName;
-      } else if (binaryFactorNode != null) {
-        return "binfactor " + binaryFactorNode.VariableName + " " + binaryFactorNode.VariableValue;
-      } else if (factorNode != null) {
-        return "factor " + factorNode.VariableName;
-      } else if (laggedVarNode != null) {
-        return "lagged " + laggedVarNode.VariableName + " " + laggedVarNode.Lag;
-      } else {
-        throw new NotSupportedException();
-      }
-    }
-
-
-    private ISymbolicExpressionTreeNode MakeProduct(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) {
-      if (IsConstant(a) && IsConstant(b)) {
-        // fold constants
-        return MakeConstant(((ConstantTreeNode)a).Value * ((ConstantTreeNode)b).Value);
-      } else if (IsConstant(a)) {
-        // a * $ => $ * a
-        return MakeProduct(b, a);
-      } else if (IsFactor(a) && IsFactor(b) && AreSameTypeAndVariable(a, b)) {
-        var node0 = a as FactorVariableTreeNode;
-        var node1 = b as FactorVariableTreeNode;
-        return MakeFactor(node0.Symbol, node0.VariableName, node0.Weights.Zip(node1.Weights, (u, v) => u * v));
-      } else if (IsBinFactor(a) && IsBinFactor(b) && AreSameTypeAndVariable(a, b)) {
-        var node0 = a as BinaryFactorVariableTreeNode;
-        var node1 = b as BinaryFactorVariableTreeNode;
-        return MakeBinFactor(node0.Symbol, node0.VariableName, node0.VariableValue, node0.Weight * node1.Weight);
-      } else if (IsFactor(a) && IsConstant(b)) {
-        var node0 = a as FactorVariableTreeNode;
-        var node1 = b as ConstantTreeNode;
-        return MakeFactor(node0.Symbol, node0.VariableName, node0.Weights.Select(w => w * node1.Value));
-      } else if (IsBinFactor(a) && IsConstant(b)) {
-        var node0 = a as BinaryFactorVariableTreeNode;
-        var node1 = b as ConstantTreeNode;
-        return MakeBinFactor(node0.Symbol, node0.VariableName, node0.VariableValue, node0.Weight * node1.Value);
-      } else if (IsBinFactor(a) && IsFactor(b)) {
-        return MakeProduct(b, a);
-      } else if (IsFactor(a) && IsBinFactor(b) &&
-        ((IVariableTreeNode)a).VariableName == ((IVariableTreeNode)b).VariableName) {
-        var node0 = a as FactorVariableTreeNode;
-        var node1 = b as BinaryFactorVariableTreeNode;
-        var varValues = node0.Symbol.GetVariableValues(node0.VariableName).ToArray();
-        var wi = Array.IndexOf(varValues, node1.VariableValue);
-        if (wi < 0) throw new ArgumentException();
-        return MakeBinFactor(node1.Symbol, node1.VariableName, node1.VariableValue, node1.Weight * node0.Weights[wi]);
-      } else if (IsConstant(b) && ((ConstantTreeNode)b).Value.IsAlmost(1.0)) {
-        // $ * 1.0 => $
-        return a;
-      } else if (IsConstant(b) && IsVariableBase(a)) {
-        // multiply constants into variables weights
-        ((VariableTreeNodeBase)a).Weight *= ((ConstantTreeNode)b).Value;
-        return a;
-      } else if (IsConstant(b) && IsAddition(a) ||
-          IsFactor(b) && IsAddition(a) ||
-          IsBinFactor(b) && IsAddition(a)) {
-        // multiply constants into additions
-        return a.Subtrees.Select(x => MakeProduct(GetSimplifiedTree(x), GetSimplifiedTree(b))).Aggregate((c, d) => MakeSum(c, d));
-      } else if (IsDivision(a) && IsDivision(b)) {
-        // (a1 / a2) * (b1 / b2) => (a1 * b1) / (a2 * b2)
-        return MakeFraction(MakeProduct(a.GetSubtree(0), b.GetSubtree(0)), MakeProduct(a.GetSubtree(1), b.GetSubtree(1)));
-      } else if (IsDivision(a)) {
-        // (a1 / a2) * b => (a1 * b) / a2
-        return MakeFraction(MakeProduct(a.GetSubtree(0), b), a.GetSubtree(1));
-      } else if (IsDivision(b)) {
-        // a * (b1 / b2) => (b1 * a) / b2
-        return MakeFraction(MakeProduct(b.GetSubtree(0), a), b.GetSubtree(1));
-      } else if (IsMultiplication(a) && IsMultiplication(b)) {
-        // merge multiplications (make sure constants are merged)
-        var mul = mulSymbol.CreateTreeNode();
-        for (int i = 0; i < a.Subtrees.Count(); i++) mul.AddSubtree(a.GetSubtree(i));
-        for (int i = 0; i < b.Subtrees.Count(); i++) mul.AddSubtree(b.GetSubtree(i));
-        MergeVariablesAndConstantsInProduct(mul);
-        return mul;
-      } else if (IsMultiplication(b)) {
-        return MakeProduct(b, a);
-      } else if (IsMultiplication(a)) {
-        // a is already an multiplication => append b
-        a.AddSubtree(GetSimplifiedTree(b));
-        MergeVariablesAndConstantsInProduct(a);
-        return a;
-      } else {
-        var mul = mulSymbol.CreateTreeNode();
-        mul.AddSubtree(a);
-        mul.AddSubtree(b);
-        MergeVariablesAndConstantsInProduct(mul);
-        return mul;
-      }
-    }
-
-    #endregion
-
-    #region helper functions
-
-    private bool ContainsVariableCondition(ISymbolicExpressionTreeNode node) {
-      if (node.Symbol is VariableCondition) return true;
-      foreach (var subtree in node.Subtrees)
-        if (ContainsVariableCondition(subtree)) return true;
-      return false;
-    }
-
-    private ISymbolicExpressionTreeNode AddLagToDynamicNodes(ISymbolicExpressionTreeNode node, int lag) {
-      var laggedTreeNode = node as ILaggedTreeNode;
-      var variableNode = node as VariableTreeNode;
-      var variableConditionNode = node as VariableConditionTreeNode;
-      if (laggedTreeNode != null)
-        laggedTreeNode.Lag += lag;
-      else if (variableNode != null) {
-        var laggedVariableNode = (LaggedVariableTreeNode)laggedVariableSymbol.CreateTreeNode();
-        laggedVariableNode.Lag = lag;
-        laggedVariableNode.VariableName = variableNode.VariableName;
-        return laggedVariableNode;
-      } else if (variableConditionNode != null) {
-        throw new NotSupportedException("Removal of time lags around variable condition symbols is not allowed.");
-      }
-      var subtrees = new List<ISymbolicExpressionTreeNode>(node.Subtrees);
-      while (node.SubtreeCount > 0) node.RemoveSubtree(0);
-      foreach (var subtree in subtrees) {
-        node.AddSubtree(AddLagToDynamicNodes(subtree, lag));
-      }
-      return node;
-    }
-
-    private bool AreSameTypeAndVariable(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) {
-      return GroupId((IVariableTreeNode)a) == GroupId((IVariableTreeNode)b);
-    }
-
-    // helper to combine the constant factors in products and to combine variables (powers of 2, 3...)
-    private void MergeVariablesAndConstantsInProduct(ISymbolicExpressionTreeNode prod) {
-      var subtrees = new List<ISymbolicExpressionTreeNode>(prod.Subtrees);
-      while (prod.Subtrees.Any()) prod.RemoveSubtree(0);
-      var groupedVarNodes = from node in subtrees.OfType<IVariableTreeNode>()
-                            where node.SubtreeCount == 0
-                            group node by GroupId(node) into g
-                            orderby g.Count()
-                            select g;
-      var constantProduct = (from node in subtrees.OfType<VariableTreeNodeBase>()
-                             select node.Weight)
-        .Concat(from node in subtrees.OfType<ConstantTreeNode>()
-                select node.Value)
-        .DefaultIfEmpty(1.0)
-        .Aggregate((c1, c2) => c1 * c2);
-
-      var unchangedSubtrees = from tree in subtrees
-                              where tree.SubtreeCount > 0 || !(tree is IVariableTreeNode) && !(tree is ConstantTreeNode)
-                              select tree;
-
-      foreach (var variableNodeGroup in groupedVarNodes) {
-        var firstNode = variableNodeGroup.First();
-        if (firstNode is VariableTreeNodeBase) {
-          var representative = (VariableTreeNodeBase)firstNode;
-          representative.Weight = 1.0;
-          if (variableNodeGroup.Count() > 1) {
-            var poly = mulSymbol.CreateTreeNode();
-            for (int p = 0; p < variableNodeGroup.Count(); p++) {
-              poly.AddSubtree((ISymbolicExpressionTreeNode)representative.Clone());
-            }
-            prod.AddSubtree(poly);
-          } else {
-            prod.AddSubtree(representative);
-          }
-        } else if (firstNode is FactorVariableTreeNode) {
-          var representative = (FactorVariableTreeNode)firstNode;
-          foreach (var node in variableNodeGroup.Skip(1).Cast<FactorVariableTreeNode>()) {
-            for (int j = 0; j < representative.Weights.Length; j++) {
-              representative.Weights[j] *= node.Weights[j];
-            }
-          }
-          for (int j = 0; j < representative.Weights.Length; j++) {
-            representative.Weights[j] *= constantProduct;
-          }
-          constantProduct = 1.0;
-          // if the product already contains a factor it is not necessary to multiply a constant below
-          prod.AddSubtree(representative);
-        }
-      }
-
-      foreach (var unchangedSubtree in unchangedSubtrees)
-        prod.AddSubtree(unchangedSubtree);
-
-      if (!constantProduct.IsAlmost(1.0)) {
-        prod.AddSubtree(MakeConstant(constantProduct));
-      }
-    }
-
-
-    /// <summary>
-    /// x => x * -1
-    /// Is only used in cases where it is not necessary to create new tree nodes. Manipulates x directly.
-    /// </summary>
-    /// <param name="x"></param>
-    /// <returns>-x</returns>
-    private ISymbolicExpressionTreeNode Negate(ISymbolicExpressionTreeNode x) {
-      if (IsConstant(x)) {
-        ((ConstantTreeNode)x).Value *= -1;
-      } else if (IsVariableBase(x)) {
-        var variableTree = (VariableTreeNodeBase)x;
-        variableTree.Weight *= -1.0;
-      } else if (IsFactor(x)) {
-        var factorNode = (FactorVariableTreeNode)x;
-        for (int i = 0; i < factorNode.Weights.Length; i++) factorNode.Weights[i] *= -1;
-      } else if (IsBinFactor(x)) {
-        var factorNode = (BinaryFactorVariableTreeNode)x;
-        factorNode.Weight *= -1;
-      } else if (IsAddition(x)) {
-        // (x0 + x1 + .. + xn) * -1 => (-x0 + -x1 + .. + -xn)        
-        var subtrees = new List<ISymbolicExpressionTreeNode>(x.Subtrees);
-        while (x.Subtrees.Any()) x.RemoveSubtree(0);
-        foreach (var subtree in subtrees) {
-          x.AddSubtree(Negate(subtree));
-        }
-      } else if (IsMultiplication(x) || IsDivision(x)) {
-        // x0 * x1 * .. * xn * -1 => x0 * x1 * .. * -xn
-        var lastSubTree = x.Subtrees.Last();
-        x.RemoveSubtree(x.SubtreeCount - 1);
-        x.AddSubtree(Negate(lastSubTree)); // last is maybe a constant, prefer to negate the constant
-      } else {
-        // any other function
-        return MakeProduct(x, MakeConstant(-1));
-      }
-      return x;
-    }
-
-    /// <summary>
-    /// x => 1/x
-    /// Must create new tree nodes
-    /// </summary>
-    /// <param name="x"></param>
-    /// <returns></returns>
-    private ISymbolicExpressionTreeNode Invert(ISymbolicExpressionTreeNode x) {
-      if (IsConstant(x)) {
-        return MakeConstant(1.0 / ((ConstantTreeNode)x).Value);
-      } else if (IsFactor(x)) {
-        var factorNode = (FactorVariableTreeNode)x;
-        return MakeFactor(factorNode.Symbol, factorNode.VariableName, factorNode.Weights.Select(w => 1.0 / w));
-      } else if (IsDivision(x)) {
-        return MakeFraction(x.GetSubtree(1), x.GetSubtree(0));
-      } else {
-        // any other function
-        return MakeFraction(MakeConstant(1), x);
-      }
-    }
-
-    private ISymbolicExpressionTreeNode MakeConstant(double value) {
-      ConstantTreeNode constantTreeNode = (ConstantTreeNode)(constSymbol.CreateTreeNode());
-      constantTreeNode.Value = value;
-      return constantTreeNode;
-    }
-
-    private ISymbolicExpressionTreeNode MakeFactor(FactorVariable sy, string variableName, IEnumerable<double> weights) {
-      var tree = (FactorVariableTreeNode)sy.CreateTreeNode();
-      tree.VariableName = variableName;
-      tree.Weights = weights.ToArray();
-      return tree;
-    }
-    private ISymbolicExpressionTreeNode MakeBinFactor(BinaryFactorVariable sy, string variableName, string variableValue, double weight) {
-      var tree = (BinaryFactorVariableTreeNode)sy.CreateTreeNode();
-      tree.VariableName = variableName;
-      tree.VariableValue = variableValue;
-      tree.Weight = weight;
-      return tree;
-    }
-
-
-    #endregion
-  }
-}
Index: able/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Transformation/SymbolicExpressionTreeBacktransformator.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Transformation/SymbolicExpressionTreeBacktransformator.cs	(revision 15141)
+++ 	(revision )
@@ -1,97 +1,0 @@
-﻿#region License Information
-/* HeuristicLab
- * Copyright (C) 2002-2016 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.Collections.Generic;
-using System.Linq;
-using HeuristicLab.Common;
-using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
-
-namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
-  public class SymbolicExpressionTreeBacktransformator : IModelBacktransformator {
-    private readonly ITransformationMapper<ISymbolicExpressionTreeNode> transformationMapper;
-
-    public SymbolicExpressionTreeBacktransformator(ITransformationMapper<ISymbolicExpressionTreeNode> transformationMapper) {
-      this.transformationMapper = transformationMapper;
-    }
-
-    public ISymbolicDataAnalysisModel Backtransform(ISymbolicDataAnalysisModel model, IEnumerable<ITransformation> transformations, string targetVariable) {
-      var symbolicModel = (ISymbolicDataAnalysisModel)model.Clone();
-
-      foreach (var transformation in transformations.Reverse()) {
-        ApplyBacktransformation(transformation, symbolicModel.SymbolicExpressionTree, targetVariable);
-      }
-
-      return symbolicModel;
-    }
-
-    private void ApplyBacktransformation(ITransformation transformation, ISymbolicExpressionTree symbolicExpressionTree, string targetVariable) {
-      if (transformation.Column != targetVariable) {
-        var variableNodes = symbolicExpressionTree.IterateNodesBreadth()
-          .OfType<VariableTreeNode>()
-          .Where(n => n.VariableName == transformation.Column);
-        ApplyRegularBacktransformation(transformation, variableNodes);
-      } else if (!(transformation is CopyColumnTransformation)) {
-        ApplyInverseBacktransformation(transformation, symbolicExpressionTree);
-      }
-    }
-
-    private void ApplyRegularBacktransformation(ITransformation transformation, IEnumerable<VariableTreeNode> variableNodes) {
-      foreach (var variableNode in variableNodes) {
-        // generate new subtrees because same subtree cannot be added more than once
-        var transformationTree = transformationMapper.GenerateModel(transformation);
-        SwapVariableWithTree(variableNode, transformationTree);
-      }
-    }
-
-    private void ApplyInverseBacktransformation(ITransformation transformation, ISymbolicExpressionTree symbolicExpressionTree) {
-      var startSymbol = symbolicExpressionTree.Root.GetSubtree(0);
-      var modelTree = startSymbol.GetSubtree(0);
-      startSymbol.RemoveSubtree(0);
-
-      var transformationTree = transformationMapper.GenerateInverseModel(transformation);
-      var variableNode = transformationTree.IterateNodesBreadth()
-        .OfType<VariableTreeNode>()
-        .Single(n => n.VariableName == transformation.Column);
-
-      SwapVariableWithTree(variableNode, modelTree);
-
-      startSymbol.AddSubtree(transformationTree);
-    }
-
-    private void SwapVariableWithTree(VariableTreeNode variableNode, ISymbolicExpressionTreeNode treeNode) {
-      var parent = variableNode.Parent;
-      int index = parent.IndexOfSubtree(variableNode);
-      parent.RemoveSubtree(index);
-
-      if (!variableNode.Weight.IsAlmost(1.0))
-        treeNode = CreateNodeFromWeight(treeNode, variableNode);
-
-      parent.InsertSubtree(index, treeNode);
-    }
-
-    private ISymbolicExpressionTreeNode CreateNodeFromWeight(ISymbolicExpressionTreeNode transformationTree, VariableTreeNode variableNode) {
-      var multiplicationNode = new SymbolicExpressionTreeNode(new Multiplication());
-      multiplicationNode.AddSubtree(new ConstantTreeNode(new Constant()) { Value = variableNode.Weight });
-      multiplicationNode.AddSubtree(transformationTree);
-      return multiplicationNode;
-    }
-  }
-}
Index: able/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Transformation/TransformationToSymbolicTreeMapper.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Transformation/TransformationToSymbolicTreeMapper.cs	(revision 15141)
+++ 	(revision )
@@ -1,294 +1,0 @@
-﻿#region License Information
-/* HeuristicLab
- * Copyright (C) 2002-2016 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 HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
-
-namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
-  public class TransformationToSymbolicTreeMapper : ITransformationMapper<ISymbolicExpressionTreeNode> {
-    private ITransformation transformation;
-    private string column;
-
-    #region ITransformationMapper<ISymbolicExpressionTree> Members
-
-    public ISymbolicExpressionTreeNode GenerateModel(ITransformation transformation) {
-      InitComponents(transformation);
-
-      if (transformation is LinearTransformation) {
-        return GenerateModelForLinearTransformation();
-      } else if (transformation is ExponentialTransformation) {
-        return GenerateModelForExponentialTransformation();
-      } else if (transformation is LogarithmicTransformation) {
-        return GenerateModelForLogarithmicTransformation();
-      } else if (transformation is PowerTransformation) {
-        return GenerateModelForPowerTransformation();
-      } else if (transformation is ReciprocalTransformation) {
-        return GenerateModelForReciprocalTransformation();
-      } else if (transformation is ShiftStandardDistributionTransformation) {
-        return GenerateModelForShiftStandardDistributionTransformation();
-      } else if (transformation is CopyColumnTransformation) {
-        return GenerateTreeNodeForCopyColumnTransformation();
-      }
-      throw new NotImplementedException();
-    }
-
-    public ISymbolicExpressionTreeNode GenerateInverseModel(ITransformation transformation) {
-      InitComponents(transformation);
-
-      if (transformation is LinearTransformation) {
-        return GenerateInverseModelForLinearTransformation();
-      } else if (transformation is ExponentialTransformation) {
-        return GenerateInverseModelForExponentialTransformation();
-      } else if (transformation is LogarithmicTransformation) {
-        return GenerateInverseModelForLogarithmicTransformation();
-      } else if (transformation is PowerTransformation) {
-        return GenerateInverseModelForPowerTransformation();
-      } else if (transformation is ReciprocalTransformation) {
-        return GenerateInverseModelForReciprocalTransformation();
-      } else if (transformation is ShiftStandardDistributionTransformation) {
-        GenerateInverseModelForShiftStandardDistributionTransformation();
-      } else if (transformation is CopyColumnTransformation) {
-        return GenerateTreeNodeForCopyColumnTransformation();
-      }
-
-      throw new NotImplementedException();
-    }
-
-    #endregion
-
-    // helper
-
-    private ISymbolicExpressionTreeNode GenerateModelForLinearTransformation() {
-      var linearTransformation = (LinearTransformation)transformation;
-      var kValue = linearTransformation.Multiplier;
-      var dValue = linearTransformation.Addend;
-
-      // k * x
-      var multiplicationNode = new Multiplication().CreateTreeNode();
-      var kNode = CreateConstantTreeNode("k", kValue);
-      var xNode = CreateVariableTreeNode(column, "x");
-      multiplicationNode.AddSubtree(kNode);
-      multiplicationNode.AddSubtree(xNode);
-
-      // ( k * x ) + d
-      var additionNode = new Addition().CreateTreeNode();
-      var dNode = CreateConstantTreeNode("d", dValue);
-      additionNode.AddSubtree(multiplicationNode);
-      additionNode.AddSubtree(dNode);
-
-      return additionNode;
-    }
-
-    private ISymbolicExpressionTreeNode GenerateInverseModelForLinearTransformation() {
-      var linearTransformation = (LinearTransformation)transformation;
-      var kValue = linearTransformation.Multiplier;
-      var dValue = linearTransformation.Addend;
-
-      // x - d
-      var substractionNode = new Subtraction().CreateTreeNode();
-      var dNode = CreateConstantTreeNode("d", dValue);
-      var xNode = CreateVariableTreeNode(column, "x");
-      substractionNode.AddSubtree(xNode);
-      substractionNode.AddSubtree(dNode);
-
-      // ( x - d ) / k
-      var divisionNode = new Division().CreateTreeNode();
-      var kNode = CreateConstantTreeNode("k", kValue);
-      divisionNode.AddSubtree(substractionNode);
-      divisionNode.AddSubtree(kNode);
-
-      return divisionNode;
-    }
-
-
-    private ISymbolicExpressionTreeNode GenerateModelForExponentialTransformation() {
-      var exponentialTransformation = (ExponentialTransformation)transformation;
-      var bValue = exponentialTransformation.Base;
-
-      return GenTreePow_b_x(bValue);
-    }
-
-    private ISymbolicExpressionTreeNode GenerateInverseModelForExponentialTransformation() {
-      var exponentialTransformation = (ExponentialTransformation)transformation;
-      var bValue = exponentialTransformation.Base;
-
-      return GenTreeLog_x_b(bValue);
-    }
-
-
-    private ISymbolicExpressionTreeNode GenerateModelForLogarithmicTransformation() {
-      var logarithmicTransformation = (LogarithmicTransformation)transformation;
-      var bValue = logarithmicTransformation.Base;
-
-      return GenTreeLog_x_b(bValue);
-    }
-
-    private ISymbolicExpressionTreeNode GenerateInverseModelForLogarithmicTransformation() {
-      var logarithmicTransformation = (LogarithmicTransformation)transformation;
-      var bValue = logarithmicTransformation.Base;
-
-      return GenTreePow_b_x(bValue);
-    }
-
-
-    private ISymbolicExpressionTreeNode GenerateModelForPowerTransformation() {
-      var powerTransformation = (PowerTransformation)transformation;
-      var expValue = powerTransformation.Exponent;
-
-      // x ^ exp
-      var powerNode = new Power().CreateTreeNode();
-      var xNode = CreateVariableTreeNode(column, "x");
-      var expNode = CreateConstantTreeNode("exp", expValue);
-      powerNode.AddSubtree(xNode);
-      powerNode.AddSubtree(expNode);
-
-      return powerNode;
-    }
-
-    private ISymbolicExpressionTreeNode GenerateInverseModelForPowerTransformation() {
-      var powerTransformation = (PowerTransformation)transformation;
-      var expValue = powerTransformation.Exponent;
-
-      // rt(x, b)
-      var rootNode = new Root().CreateTreeNode();
-      var xNode = CreateVariableTreeNode(column, "x");
-      var bNode = CreateConstantTreeNode("b", expValue);
-      rootNode.AddSubtree(xNode);
-      rootNode.AddSubtree(bNode);
-
-      return rootNode;
-    }
-
-
-    private ISymbolicExpressionTreeNode GenerateModelForReciprocalTransformation() {
-      return GenTreeDiv_1_x();
-    }
-
-    private ISymbolicExpressionTreeNode GenerateInverseModelForReciprocalTransformation() {
-      return GenTreeDiv_1_x();
-    }
-
-
-    private ISymbolicExpressionTreeNode GenerateModelForShiftStandardDistributionTransformation() {
-      var shiftStandardDistributionTransformation = (ShiftStandardDistributionTransformation)transformation;
-      var m_orgValue = shiftStandardDistributionTransformation.OriginalMean;
-      var s_orgValue = shiftStandardDistributionTransformation.OriginalStandardDeviation;
-      var m_tarValue = shiftStandardDistributionTransformation.Mean;
-      var s_tarValue = shiftStandardDistributionTransformation.StandardDeviation;
-
-      return GenTreeShiftStdDist(column, m_orgValue, s_orgValue, m_tarValue, s_tarValue);
-    }
-
-    private ISymbolicExpressionTreeNode GenerateInverseModelForShiftStandardDistributionTransformation() {
-      var shiftStandardDistributionTransformation = (ShiftStandardDistributionTransformation)transformation;
-      var m_orgValue = shiftStandardDistributionTransformation.OriginalMean;
-      var s_orgValue = shiftStandardDistributionTransformation.OriginalStandardDeviation;
-      var m_tarValue = shiftStandardDistributionTransformation.Mean;
-      var s_tarValue = shiftStandardDistributionTransformation.StandardDeviation;
-
-      return GenTreeShiftStdDist(column, m_tarValue, s_tarValue, m_orgValue, s_orgValue);
-    }
-
-    private ISymbolicExpressionTreeNode GenerateTreeNodeForCopyColumnTransformation() {
-      var copyColumnTransformation = (CopyColumnTransformation)transformation;
-      var copiedColumnName = copyColumnTransformation.CopiedColumnName;
-
-      return CreateVariableTreeNode(copiedColumnName, copiedColumnName + "(original)");
-    }
-
-    // helper's helper:
-
-    private ISymbolicExpressionTreeNode GenTreeLog_x_b(double b) {
-      // log(x, b)
-      var logNode = new Logarithm().CreateTreeNode();
-      var bNode = CreateConstantTreeNode("b", b);
-      var xNode = CreateVariableTreeNode(column, "x");
-      logNode.AddSubtree(xNode);
-      logNode.AddSubtree(bNode);
-
-      return logNode;
-    }
-
-    private ISymbolicExpressionTreeNode GenTreePow_b_x(double b) {
-      // b ^ x
-      var powerNode = new Power().CreateTreeNode();
-      var bNode = CreateConstantTreeNode("b", b);
-      var xNode = CreateVariableTreeNode(column, "x");
-      powerNode.AddSubtree(bNode);
-      powerNode.AddSubtree(xNode);
-
-      return powerNode;
-    }
-
-    private ISymbolicExpressionTreeNode GenTreeDiv_1_x() {
-      // 1 / x
-      var divNode = new Division().CreateTreeNode();
-      var oneNode = CreateConstantTreeNode("1", 1.0);
-      var xNode = CreateVariableTreeNode(column, "x");
-      divNode.AddSubtree(oneNode);
-      divNode.AddSubtree(xNode);
-
-      return divNode;
-    }
-
-    private ISymbolicExpressionTreeNode GenTreeShiftStdDist(string variable, double m_org, double s_org, double m_tar, double s_tar) {
-      // x - m_org
-      var substractionNode = new Subtraction().CreateTreeNode();
-      var xNode = CreateVariableTreeNode(variable, "x");
-      var m_orgNode = CreateConstantTreeNode("m_org", m_org);
-      substractionNode.AddSubtree(xNode);
-      substractionNode.AddSubtree(m_orgNode);
-
-      // (x - m_org) / s_org
-      var divisionNode = new Division().CreateTreeNode();
-      var s_orgNode = CreateConstantTreeNode("s_org", s_org);
-      divisionNode.AddSubtree(substractionNode);
-      divisionNode.AddSubtree(s_orgNode);
-
-      // ((x - m_org) / s_org ) * s_tar
-      var multiplicationNode = new Multiplication().CreateTreeNode();
-      var s_tarNode = CreateConstantTreeNode("s_tar", s_tar);
-      multiplicationNode.AddSubtree(divisionNode);
-      multiplicationNode.AddSubtree(s_tarNode);
-
-      // ((x - m_org) / s_org ) * s_tar + m_tar
-      var additionNode = new Addition().CreateTreeNode();
-      var m_tarNode = CreateConstantTreeNode("m_tar", m_tar);
-      additionNode.AddSubtree(multiplicationNode);
-      additionNode.AddSubtree(m_tarNode);
-
-      return additionNode;
-    }
-
-    private ConstantTreeNode CreateConstantTreeNode(string description, double value) {
-      return new ConstantTreeNode(new Constant()) { Value = value };
-    }
-
-    private VariableTreeNode CreateVariableTreeNode(string name, string description) {
-      return new VariableTreeNode(new Variable(name, description)) { VariableName = name, Weight = 1.0 };
-    }
-
-    private void InitComponents(ITransformation transformation) {
-      this.transformation = transformation;
-      column = transformation.Column;
-    }
-  }
-}
Index: able/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Transformation/TreeToAutoDiffTermTransformator.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Transformation/TreeToAutoDiffTermTransformator.cs	(revision 15141)
+++ 	(revision )
@@ -1,384 +1,0 @@
-﻿#region License Information
-/* HeuristicLab
- * Copyright (C) 2002-2016 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 AutoDiff;
-using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
-
-namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
-  public class TreeToAutoDiffTermTransformator {
-    public delegate double ParametricFunction(double[] vars, double[] @params);
-    public delegate Tuple<double[], double> ParametricFunctionGradient(double[] vars, double[] @params);
-
-    #region helper class
-    public class DataForVariable {
-      public readonly string variableName;
-      public readonly string variableValue; // for factor vars
-      public readonly int lag;
-
-      public DataForVariable(string varName, string varValue, int lag) {
-        this.variableName = varName;
-        this.variableValue = varValue;
-        this.lag = lag;
-      }
-
-      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) &&
-               other.lag == this.lag;
-      }
-
-      public override int GetHashCode() {
-        return variableName.GetHashCode() ^ variableValue.GetHashCode() ^ lag;
-      }
-    }
-    #endregion
-
-    #region derivations of functions
-    // create function factory for arctangent
-    private static readonly Func<Term, UnaryFunc> arctan = UnaryFunc.Factory(
-      eval: Math.Atan,
-      diff: x => 1 / (1 + x * x));
-    private static readonly Func<Term, UnaryFunc> sin = UnaryFunc.Factory(
-      eval: Math.Sin,
-      diff: Math.Cos);
-    private static readonly Func<Term, UnaryFunc> cos = UnaryFunc.Factory(
-       eval: Math.Cos,
-       diff: x => -Math.Sin(x));
-    private static readonly Func<Term, UnaryFunc> tan = UnaryFunc.Factory(
-      eval: Math.Tan,
-      diff: x => 1 + Math.Tan(x) * Math.Tan(x));
-    private static readonly Func<Term, UnaryFunc> erf = UnaryFunc.Factory(
-      eval: alglib.errorfunction,
-      diff: x => 2.0 * Math.Exp(-(x * x)) / Math.Sqrt(Math.PI));
-    private static readonly Func<Term, UnaryFunc> norm = UnaryFunc.Factory(
-      eval: alglib.normaldistribution,
-      diff: x => -(Math.Exp(-(x * x)) * Math.Sqrt(Math.Exp(x * x)) * x) / Math.Sqrt(2 * Math.PI));
-
-    #endregion
-
-    public static bool TryTransformToAutoDiff(ISymbolicExpressionTree tree, bool makeVariableWeightsVariable,
-      out List<DataForVariable> parameters, out double[] initialConstants,
-      out ParametricFunction func,
-      out ParametricFunctionGradient func_grad) {
-
-      // use a transformator object which holds the state (variable list, parameter list, ...) for recursive transformation of the tree
-      var transformator = new TreeToAutoDiffTermTransformator(makeVariableWeightsVariable);
-      AutoDiff.Term term;
-      var success = transformator.TryTransformToAutoDiff(tree.Root.GetSubtree(0), out term);
-      if (success) {
-        var parameterEntries = transformator.parameters.ToArray(); // guarantee same order for keys and values
-        var compiledTerm = term.Compile(transformator.variables.ToArray(), parameterEntries.Select(kvp => kvp.Value).ToArray());
-        parameters = new List<DataForVariable>(parameterEntries.Select(kvp => kvp.Key));
-        initialConstants = transformator.initialConstants.ToArray();
-        func = (vars, @params) => compiledTerm.Evaluate(vars, @params);
-        func_grad = (vars, @params) => compiledTerm.Differentiate(vars, @params);
-      } else {
-        func = null;
-        func_grad = null;
-        parameters = null;
-        initialConstants = null;
-      }
-      return success;
-    }
-
-    // state for recursive transformation of trees 
-    private readonly List<string> variableNames;
-    private readonly List<int> lags;
-    private readonly List<double> initialConstants;
-    private readonly Dictionary<DataForVariable, AutoDiff.Variable> parameters;
-    private readonly List<AutoDiff.Variable> variables;
-    private readonly bool makeVariableWeightsVariable;
-
-    private TreeToAutoDiffTermTransformator(bool makeVariableWeightsVariable) {
-      this.makeVariableWeightsVariable = makeVariableWeightsVariable;
-      this.variableNames = new List<string>();
-      this.lags = new List<int>();
-      this.initialConstants = new List<double>();
-      this.parameters = new Dictionary<DataForVariable, AutoDiff.Variable>();
-      this.variables = new List<AutoDiff.Variable>();
-    }
-
-    private bool TryTransformToAutoDiff(ISymbolicExpressionTreeNode node, out AutoDiff.Term term) {
-      if (node.Symbol is Constant) {
-        initialConstants.Add(((ConstantTreeNode)node).Value);
-        var var = new AutoDiff.Variable();
-        variables.Add(var);
-        term = var;
-        return true;
-      }
-      if (node.Symbol is Variable || node.Symbol is BinaryFactorVariable) {
-        var varNode = node as VariableTreeNode;
-        var factorVarNode = node as BinaryFactorVariableTreeNode;
-        // factor variable values are only 0 or 1 and set in x accordingly
-        var varValue = factorVarNode != null ? factorVarNode.VariableValue : string.Empty;
-        var par = FindOrCreateParameter(parameters, varNode.VariableName, varValue);
-
-        if (makeVariableWeightsVariable) {
-          initialConstants.Add(varNode.Weight);
-          var w = new AutoDiff.Variable();
-          variables.Add(w);
-          term = AutoDiff.TermBuilder.Product(w, par);
-        } else {
-          term = varNode.Weight * par;
-        }
-        return true;
-      }
-      if (node.Symbol is FactorVariable) {
-        var factorVarNode = node as FactorVariableTreeNode;
-        var products = new List<Term>();
-        foreach (var variableValue in factorVarNode.Symbol.GetVariableValues(factorVarNode.VariableName)) {
-          var par = FindOrCreateParameter(parameters, factorVarNode.VariableName, variableValue);
-
-          initialConstants.Add(factorVarNode.GetValue(variableValue));
-          var wVar = new AutoDiff.Variable();
-          variables.Add(wVar);
-
-          products.Add(AutoDiff.TermBuilder.Product(wVar, par));
-        }
-        term = AutoDiff.TermBuilder.Sum(products);
-        return true;
-      }
-      if (node.Symbol is LaggedVariable) {
-        var varNode = node as LaggedVariableTreeNode;
-        var par = FindOrCreateParameter(parameters, varNode.VariableName, string.Empty, varNode.Lag);
-
-        if (makeVariableWeightsVariable) {
-          initialConstants.Add(varNode.Weight);
-          var w = new AutoDiff.Variable();
-          variables.Add(w);
-          term = AutoDiff.TermBuilder.Product(w, par);
-        } else {
-          term = varNode.Weight * par;
-        }
-        return true;
-      }
-      if (node.Symbol is Addition) {
-        List<AutoDiff.Term> terms = new List<Term>();
-        foreach (var subTree in node.Subtrees) {
-          AutoDiff.Term t;
-          if (!TryTransformToAutoDiff(subTree, out t)) {
-            term = null;
-            return false;
-          }
-          terms.Add(t);
-        }
-        term = AutoDiff.TermBuilder.Sum(terms);
-        return true;
-      }
-      if (node.Symbol is Subtraction) {
-        List<AutoDiff.Term> terms = new List<Term>();
-        for (int i = 0; i < node.SubtreeCount; i++) {
-          AutoDiff.Term t;
-          if (!TryTransformToAutoDiff(node.GetSubtree(i), out t)) {
-            term = null;
-            return false;
-          }
-          if (i > 0) t = -t;
-          terms.Add(t);
-        }
-        if (terms.Count == 1) term = -terms[0];
-        else term = AutoDiff.TermBuilder.Sum(terms);
-        return true;
-      }
-      if (node.Symbol is Multiplication) {
-        List<AutoDiff.Term> terms = new List<Term>();
-        foreach (var subTree in node.Subtrees) {
-          AutoDiff.Term t;
-          if (!TryTransformToAutoDiff(subTree, out t)) {
-            term = null;
-            return false;
-          }
-          terms.Add(t);
-        }
-        if (terms.Count == 1) term = terms[0];
-        else term = terms.Aggregate((a, b) => new AutoDiff.Product(a, b));
-        return true;
-
-      }
-      if (node.Symbol is Division) {
-        List<AutoDiff.Term> terms = new List<Term>();
-        foreach (var subTree in node.Subtrees) {
-          AutoDiff.Term t;
-          if (!TryTransformToAutoDiff(subTree, out t)) {
-            term = null;
-            return false;
-          }
-          terms.Add(t);
-        }
-        if (terms.Count == 1) term = 1.0 / terms[0];
-        else term = terms.Aggregate((a, b) => new AutoDiff.Product(a, 1.0 / b));
-        return true;
-      }
-      if (node.Symbol is Logarithm) {
-        AutoDiff.Term t;
-        if (!TryTransformToAutoDiff(node.GetSubtree(0), out t)) {
-          term = null;
-          return false;
-        } else {
-          term = AutoDiff.TermBuilder.Log(t);
-          return true;
-        }
-      }
-      if (node.Symbol is Exponential) {
-        AutoDiff.Term t;
-        if (!TryTransformToAutoDiff(node.GetSubtree(0), out t)) {
-          term = null;
-          return false;
-        } else {
-          term = AutoDiff.TermBuilder.Exp(t);
-          return true;
-        }
-      }
-      if (node.Symbol is Square) {
-        AutoDiff.Term t;
-        if (!TryTransformToAutoDiff(node.GetSubtree(0), out t)) {
-          term = null;
-          return false;
-        } else {
-          term = AutoDiff.TermBuilder.Power(t, 2.0);
-          return true;
-        }
-      }
-      if (node.Symbol is SquareRoot) {
-        AutoDiff.Term t;
-        if (!TryTransformToAutoDiff(node.GetSubtree(0), out t)) {
-          term = null;
-          return false;
-        } else {
-          term = AutoDiff.TermBuilder.Power(t, 0.5);
-          return true;
-        }
-      }
-      if (node.Symbol is Sine) {
-        AutoDiff.Term t;
-        if (!TryTransformToAutoDiff(node.GetSubtree(0), out t)) {
-          term = null;
-          return false;
-        } else {
-          term = sin(t);
-          return true;
-        }
-      }
-      if (node.Symbol is Cosine) {
-        AutoDiff.Term t;
-        if (!TryTransformToAutoDiff(node.GetSubtree(0), out t)) {
-          term = null;
-          return false;
-        } else {
-          term = cos(t);
-          return true;
-        }
-      }
-      if (node.Symbol is Tangent) {
-        AutoDiff.Term t;
-        if (!TryTransformToAutoDiff(node.GetSubtree(0), out t)) {
-          term = null;
-          return false;
-        } else {
-          term = tan(t);
-          return true;
-        }
-      }
-      if (node.Symbol is Erf) {
-        AutoDiff.Term t;
-        if (!TryTransformToAutoDiff(node.GetSubtree(0), out t)) {
-          term = null;
-          return false;
-        } else {
-          term = erf(t);
-          return true;
-        }
-      }
-      if (node.Symbol is Norm) {
-        AutoDiff.Term t;
-        if (!TryTransformToAutoDiff(node.GetSubtree(0), out t)) {
-          term = null;
-          return false;
-        } else {
-          term = norm(t);
-          return true;
-        }
-      }
-      if (node.Symbol is StartSymbol) {
-        var alpha = new AutoDiff.Variable();
-        var beta = new AutoDiff.Variable();
-        variables.Add(beta);
-        variables.Add(alpha);
-        AutoDiff.Term branchTerm;
-        if (TryTransformToAutoDiff(node.GetSubtree(0), out branchTerm)) {
-          term = branchTerm * alpha + beta;
-          return true;
-        } else {
-          term = null;
-          return false;
-        }
-      }
-      term = null;
-      return false;
-    }
-
-
-    // for each factor variable value we need a parameter which represents a binary indicator for that variable & value combination
-    // each binary indicator is only necessary once. So we only create a parameter if this combination is not yet available
-    private static Term FindOrCreateParameter(Dictionary<DataForVariable, AutoDiff.Variable> parameters,
-      string varName, string varValue = "", int lag = 0) {
-      var data = new DataForVariable(varName, varValue, lag);
-
-      AutoDiff.Variable par = null;
-      if (!parameters.TryGetValue(data, out par)) {
-        // not found -> create new parameter and entries in names and values lists
-        par = new AutoDiff.Variable();
-        parameters.Add(data, par);
-      }
-      return par;
-    }
-
-    public static bool IsCompatible(ISymbolicExpressionTree tree) {
-      var containsUnknownSymbol = (
-        from n in tree.Root.GetSubtree(0).IterateNodesPrefix()
-        where
-        !(n.Symbol is Variable) &&
-        !(n.Symbol is LaggedVariable) &&
-        !(n.Symbol is Constant) &&
-        !(n.Symbol is Addition) &&
-        !(n.Symbol is Subtraction) &&
-        !(n.Symbol is Multiplication) &&
-        !(n.Symbol is Division) &&
-        !(n.Symbol is Logarithm) &&
-        !(n.Symbol is Exponential) &&
-        !(n.Symbol is SquareRoot) &&
-        !(n.Symbol is Square) &&
-        !(n.Symbol is Sine) &&
-        !(n.Symbol is Cosine) &&
-        !(n.Symbol is Tangent) &&
-        !(n.Symbol is Erf) &&
-        !(n.Symbol is Norm) &&
-        !(n.Symbol is StartSymbol)
-        select n).Any();
-      return !containsUnknownSymbol;
-    }
-  }
-}
Index: /stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Transformations/SymbolicExpressionTreeBacktransformator.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Transformations/SymbolicExpressionTreeBacktransformator.cs	(revision 15142)
+++ /stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Transformations/SymbolicExpressionTreeBacktransformator.cs	(revision 15142)
@@ -0,0 +1,97 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
+  public class SymbolicExpressionTreeBacktransformator : IModelBacktransformator {
+    private readonly ITransformationMapper<ISymbolicExpressionTreeNode> transformationMapper;
+
+    public SymbolicExpressionTreeBacktransformator(ITransformationMapper<ISymbolicExpressionTreeNode> transformationMapper) {
+      this.transformationMapper = transformationMapper;
+    }
+
+    public ISymbolicDataAnalysisModel Backtransform(ISymbolicDataAnalysisModel model, IEnumerable<ITransformation> transformations, string targetVariable) {
+      var symbolicModel = (ISymbolicDataAnalysisModel)model.Clone();
+
+      foreach (var transformation in transformations.Reverse()) {
+        ApplyBacktransformation(transformation, symbolicModel.SymbolicExpressionTree, targetVariable);
+      }
+
+      return symbolicModel;
+    }
+
+    private void ApplyBacktransformation(ITransformation transformation, ISymbolicExpressionTree symbolicExpressionTree, string targetVariable) {
+      if (transformation.Column != targetVariable) {
+        var variableNodes = symbolicExpressionTree.IterateNodesBreadth()
+          .OfType<VariableTreeNode>()
+          .Where(n => n.VariableName == transformation.Column);
+        ApplyRegularBacktransformation(transformation, variableNodes);
+      } else if (!(transformation is CopyColumnTransformation)) {
+        ApplyInverseBacktransformation(transformation, symbolicExpressionTree);
+      }
+    }
+
+    private void ApplyRegularBacktransformation(ITransformation transformation, IEnumerable<VariableTreeNode> variableNodes) {
+      foreach (var variableNode in variableNodes) {
+        // generate new subtrees because same subtree cannot be added more than once
+        var transformationTree = transformationMapper.GenerateModel(transformation);
+        SwapVariableWithTree(variableNode, transformationTree);
+      }
+    }
+
+    private void ApplyInverseBacktransformation(ITransformation transformation, ISymbolicExpressionTree symbolicExpressionTree) {
+      var startSymbol = symbolicExpressionTree.Root.GetSubtree(0);
+      var modelTree = startSymbol.GetSubtree(0);
+      startSymbol.RemoveSubtree(0);
+
+      var transformationTree = transformationMapper.GenerateInverseModel(transformation);
+      var variableNode = transformationTree.IterateNodesBreadth()
+        .OfType<VariableTreeNode>()
+        .Single(n => n.VariableName == transformation.Column);
+
+      SwapVariableWithTree(variableNode, modelTree);
+
+      startSymbol.AddSubtree(transformationTree);
+    }
+
+    private void SwapVariableWithTree(VariableTreeNode variableNode, ISymbolicExpressionTreeNode treeNode) {
+      var parent = variableNode.Parent;
+      int index = parent.IndexOfSubtree(variableNode);
+      parent.RemoveSubtree(index);
+
+      if (!variableNode.Weight.IsAlmost(1.0))
+        treeNode = CreateNodeFromWeight(treeNode, variableNode);
+
+      parent.InsertSubtree(index, treeNode);
+    }
+
+    private ISymbolicExpressionTreeNode CreateNodeFromWeight(ISymbolicExpressionTreeNode transformationTree, VariableTreeNode variableNode) {
+      var multiplicationNode = new SymbolicExpressionTreeNode(new Multiplication());
+      multiplicationNode.AddSubtree(new ConstantTreeNode(new Constant()) { Value = variableNode.Weight });
+      multiplicationNode.AddSubtree(transformationTree);
+      return multiplicationNode;
+    }
+  }
+}
Index: /stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Transformations/TransformationToSymbolicTreeMapper.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Transformations/TransformationToSymbolicTreeMapper.cs	(revision 15142)
+++ /stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Transformations/TransformationToSymbolicTreeMapper.cs	(revision 15142)
@@ -0,0 +1,294 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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 HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
+  public class TransformationToSymbolicTreeMapper : ITransformationMapper<ISymbolicExpressionTreeNode> {
+    private ITransformation transformation;
+    private string column;
+
+    #region ITransformationMapper<ISymbolicExpressionTree> Members
+
+    public ISymbolicExpressionTreeNode GenerateModel(ITransformation transformation) {
+      InitComponents(transformation);
+
+      if (transformation is LinearTransformation) {
+        return GenerateModelForLinearTransformation();
+      } else if (transformation is ExponentialTransformation) {
+        return GenerateModelForExponentialTransformation();
+      } else if (transformation is LogarithmicTransformation) {
+        return GenerateModelForLogarithmicTransformation();
+      } else if (transformation is PowerTransformation) {
+        return GenerateModelForPowerTransformation();
+      } else if (transformation is ReciprocalTransformation) {
+        return GenerateModelForReciprocalTransformation();
+      } else if (transformation is ShiftStandardDistributionTransformation) {
+        return GenerateModelForShiftStandardDistributionTransformation();
+      } else if (transformation is CopyColumnTransformation) {
+        return GenerateTreeNodeForCopyColumnTransformation();
+      }
+      throw new NotImplementedException();
+    }
+
+    public ISymbolicExpressionTreeNode GenerateInverseModel(ITransformation transformation) {
+      InitComponents(transformation);
+
+      if (transformation is LinearTransformation) {
+        return GenerateInverseModelForLinearTransformation();
+      } else if (transformation is ExponentialTransformation) {
+        return GenerateInverseModelForExponentialTransformation();
+      } else if (transformation is LogarithmicTransformation) {
+        return GenerateInverseModelForLogarithmicTransformation();
+      } else if (transformation is PowerTransformation) {
+        return GenerateInverseModelForPowerTransformation();
+      } else if (transformation is ReciprocalTransformation) {
+        return GenerateInverseModelForReciprocalTransformation();
+      } else if (transformation is ShiftStandardDistributionTransformation) {
+        GenerateInverseModelForShiftStandardDistributionTransformation();
+      } else if (transformation is CopyColumnTransformation) {
+        return GenerateTreeNodeForCopyColumnTransformation();
+      }
+
+      throw new NotImplementedException();
+    }
+
+    #endregion
+
+    // helper
+
+    private ISymbolicExpressionTreeNode GenerateModelForLinearTransformation() {
+      var linearTransformation = (LinearTransformation)transformation;
+      var kValue = linearTransformation.Multiplier;
+      var dValue = linearTransformation.Addend;
+
+      // k * x
+      var multiplicationNode = new Multiplication().CreateTreeNode();
+      var kNode = CreateConstantTreeNode("k", kValue);
+      var xNode = CreateVariableTreeNode(column, "x");
+      multiplicationNode.AddSubtree(kNode);
+      multiplicationNode.AddSubtree(xNode);
+
+      // ( k * x ) + d
+      var additionNode = new Addition().CreateTreeNode();
+      var dNode = CreateConstantTreeNode("d", dValue);
+      additionNode.AddSubtree(multiplicationNode);
+      additionNode.AddSubtree(dNode);
+
+      return additionNode;
+    }
+
+    private ISymbolicExpressionTreeNode GenerateInverseModelForLinearTransformation() {
+      var linearTransformation = (LinearTransformation)transformation;
+      var kValue = linearTransformation.Multiplier;
+      var dValue = linearTransformation.Addend;
+
+      // x - d
+      var substractionNode = new Subtraction().CreateTreeNode();
+      var dNode = CreateConstantTreeNode("d", dValue);
+      var xNode = CreateVariableTreeNode(column, "x");
+      substractionNode.AddSubtree(xNode);
+      substractionNode.AddSubtree(dNode);
+
+      // ( x - d ) / k
+      var divisionNode = new Division().CreateTreeNode();
+      var kNode = CreateConstantTreeNode("k", kValue);
+      divisionNode.AddSubtree(substractionNode);
+      divisionNode.AddSubtree(kNode);
+
+      return divisionNode;
+    }
+
+
+    private ISymbolicExpressionTreeNode GenerateModelForExponentialTransformation() {
+      var exponentialTransformation = (ExponentialTransformation)transformation;
+      var bValue = exponentialTransformation.Base;
+
+      return GenTreePow_b_x(bValue);
+    }
+
+    private ISymbolicExpressionTreeNode GenerateInverseModelForExponentialTransformation() {
+      var exponentialTransformation = (ExponentialTransformation)transformation;
+      var bValue = exponentialTransformation.Base;
+
+      return GenTreeLog_x_b(bValue);
+    }
+
+
+    private ISymbolicExpressionTreeNode GenerateModelForLogarithmicTransformation() {
+      var logarithmicTransformation = (LogarithmicTransformation)transformation;
+      var bValue = logarithmicTransformation.Base;
+
+      return GenTreeLog_x_b(bValue);
+    }
+
+    private ISymbolicExpressionTreeNode GenerateInverseModelForLogarithmicTransformation() {
+      var logarithmicTransformation = (LogarithmicTransformation)transformation;
+      var bValue = logarithmicTransformation.Base;
+
+      return GenTreePow_b_x(bValue);
+    }
+
+
+    private ISymbolicExpressionTreeNode GenerateModelForPowerTransformation() {
+      var powerTransformation = (PowerTransformation)transformation;
+      var expValue = powerTransformation.Exponent;
+
+      // x ^ exp
+      var powerNode = new Power().CreateTreeNode();
+      var xNode = CreateVariableTreeNode(column, "x");
+      var expNode = CreateConstantTreeNode("exp", expValue);
+      powerNode.AddSubtree(xNode);
+      powerNode.AddSubtree(expNode);
+
+      return powerNode;
+    }
+
+    private ISymbolicExpressionTreeNode GenerateInverseModelForPowerTransformation() {
+      var powerTransformation = (PowerTransformation)transformation;
+      var expValue = powerTransformation.Exponent;
+
+      // rt(x, b)
+      var rootNode = new Root().CreateTreeNode();
+      var xNode = CreateVariableTreeNode(column, "x");
+      var bNode = CreateConstantTreeNode("b", expValue);
+      rootNode.AddSubtree(xNode);
+      rootNode.AddSubtree(bNode);
+
+      return rootNode;
+    }
+
+
+    private ISymbolicExpressionTreeNode GenerateModelForReciprocalTransformation() {
+      return GenTreeDiv_1_x();
+    }
+
+    private ISymbolicExpressionTreeNode GenerateInverseModelForReciprocalTransformation() {
+      return GenTreeDiv_1_x();
+    }
+
+
+    private ISymbolicExpressionTreeNode GenerateModelForShiftStandardDistributionTransformation() {
+      var shiftStandardDistributionTransformation = (ShiftStandardDistributionTransformation)transformation;
+      var m_orgValue = shiftStandardDistributionTransformation.OriginalMean;
+      var s_orgValue = shiftStandardDistributionTransformation.OriginalStandardDeviation;
+      var m_tarValue = shiftStandardDistributionTransformation.Mean;
+      var s_tarValue = shiftStandardDistributionTransformation.StandardDeviation;
+
+      return GenTreeShiftStdDist(column, m_orgValue, s_orgValue, m_tarValue, s_tarValue);
+    }
+
+    private ISymbolicExpressionTreeNode GenerateInverseModelForShiftStandardDistributionTransformation() {
+      var shiftStandardDistributionTransformation = (ShiftStandardDistributionTransformation)transformation;
+      var m_orgValue = shiftStandardDistributionTransformation.OriginalMean;
+      var s_orgValue = shiftStandardDistributionTransformation.OriginalStandardDeviation;
+      var m_tarValue = shiftStandardDistributionTransformation.Mean;
+      var s_tarValue = shiftStandardDistributionTransformation.StandardDeviation;
+
+      return GenTreeShiftStdDist(column, m_tarValue, s_tarValue, m_orgValue, s_orgValue);
+    }
+
+    private ISymbolicExpressionTreeNode GenerateTreeNodeForCopyColumnTransformation() {
+      var copyColumnTransformation = (CopyColumnTransformation)transformation;
+      var copiedColumnName = copyColumnTransformation.CopiedColumnName;
+
+      return CreateVariableTreeNode(copiedColumnName, copiedColumnName + "(original)");
+    }
+
+    // helper's helper:
+
+    private ISymbolicExpressionTreeNode GenTreeLog_x_b(double b) {
+      // log(x, b)
+      var logNode = new Logarithm().CreateTreeNode();
+      var bNode = CreateConstantTreeNode("b", b);
+      var xNode = CreateVariableTreeNode(column, "x");
+      logNode.AddSubtree(xNode);
+      logNode.AddSubtree(bNode);
+
+      return logNode;
+    }
+
+    private ISymbolicExpressionTreeNode GenTreePow_b_x(double b) {
+      // b ^ x
+      var powerNode = new Power().CreateTreeNode();
+      var bNode = CreateConstantTreeNode("b", b);
+      var xNode = CreateVariableTreeNode(column, "x");
+      powerNode.AddSubtree(bNode);
+      powerNode.AddSubtree(xNode);
+
+      return powerNode;
+    }
+
+    private ISymbolicExpressionTreeNode GenTreeDiv_1_x() {
+      // 1 / x
+      var divNode = new Division().CreateTreeNode();
+      var oneNode = CreateConstantTreeNode("1", 1.0);
+      var xNode = CreateVariableTreeNode(column, "x");
+      divNode.AddSubtree(oneNode);
+      divNode.AddSubtree(xNode);
+
+      return divNode;
+    }
+
+    private ISymbolicExpressionTreeNode GenTreeShiftStdDist(string variable, double m_org, double s_org, double m_tar, double s_tar) {
+      // x - m_org
+      var substractionNode = new Subtraction().CreateTreeNode();
+      var xNode = CreateVariableTreeNode(variable, "x");
+      var m_orgNode = CreateConstantTreeNode("m_org", m_org);
+      substractionNode.AddSubtree(xNode);
+      substractionNode.AddSubtree(m_orgNode);
+
+      // (x - m_org) / s_org
+      var divisionNode = new Division().CreateTreeNode();
+      var s_orgNode = CreateConstantTreeNode("s_org", s_org);
+      divisionNode.AddSubtree(substractionNode);
+      divisionNode.AddSubtree(s_orgNode);
+
+      // ((x - m_org) / s_org ) * s_tar
+      var multiplicationNode = new Multiplication().CreateTreeNode();
+      var s_tarNode = CreateConstantTreeNode("s_tar", s_tar);
+      multiplicationNode.AddSubtree(divisionNode);
+      multiplicationNode.AddSubtree(s_tarNode);
+
+      // ((x - m_org) / s_org ) * s_tar + m_tar
+      var additionNode = new Addition().CreateTreeNode();
+      var m_tarNode = CreateConstantTreeNode("m_tar", m_tar);
+      additionNode.AddSubtree(multiplicationNode);
+      additionNode.AddSubtree(m_tarNode);
+
+      return additionNode;
+    }
+
+    private ConstantTreeNode CreateConstantTreeNode(string description, double value) {
+      return new ConstantTreeNode(new Constant()) { Value = value };
+    }
+
+    private VariableTreeNode CreateVariableTreeNode(string name, string description) {
+      return new VariableTreeNode(new Variable(name, description)) { VariableName = name, Weight = 1.0 };
+    }
+
+    private void InitComponents(ITransformation transformation) {
+      this.transformation = transformation;
+      column = transformation.Column;
+    }
+  }
+}
Index: /stable/HeuristicLab.Problems.DataAnalysis/3.4/DatasetExtensions.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis/3.4/DatasetExtensions.cs	(revision 15141)
+++ /stable/HeuristicLab.Problems.DataAnalysis/3.4/DatasetExtensions.cs	(revision 15142)
@@ -20,14 +20,91 @@
 #endregion
 
+using System;
 using System.Collections.Generic;
+using System.Linq;
 
 namespace HeuristicLab.Problems.DataAnalysis {
   public static class DatasetExtensions {
-    public static IEnumerable<T> TakeEvery<T>(this IEnumerable<T> xs, int nth) {
-      int i = 0;
-      foreach (var x in xs) {
-        if (i % nth == 0) yield return x;
-        i++;
+    public static double[,] ToArray(this IDataset dataset, IEnumerable<string> variables, IEnumerable<int> rows) {
+      return ToArray(dataset,
+        variables,
+        transformations: variables.Select(_ => (ITransformation<double>)null), // no transform
+        rows: rows);
+    }
+    public static double[,] ToArray(this IDataset dataset, IEnumerable<string> variables,
+      IEnumerable<ITransformation<double>> transformations, IEnumerable<int> rows) {
+      string[] variablesArr = variables.ToArray();
+      int[] rowsArr = rows.ToArray();
+      ITransformation<double>[] transformArr = transformations.ToArray();
+      if (transformArr.Length != variablesArr.Length)
+        throw new ArgumentException("Number of variables and number of transformations must match.");
+
+      double[,] matrix = new double[rowsArr.Length, variablesArr.Length];
+
+      for (int i = 0; i < variablesArr.Length; i++) {
+        var origValues = dataset.GetDoubleValues(variablesArr[i], rowsArr);
+        var values = transformArr[i] != null ? transformArr[i].Apply(origValues) : origValues;
+        int row = 0;
+        foreach (var value in values) {
+          matrix[row, i] = value;
+          row++;
+        }
       }
+
+      return matrix;
+    }
+
+    /// <summary>
+    /// Prepares a binary data matrix from a number of factors and specified factor values
+    /// </summary>
+    /// <param name="dataset">A dataset that contains the variable values</param>
+    /// <param name="factorVariables">An enumerable of categorical variables (factors). For each variable an enumerable of values must be specified.</param>
+    /// <param name="rows">An enumerable of row indices for the dataset</param>
+    /// <returns></returns>
+    /// <remarks>Factor variables (categorical variables) are split up into multiple binary variables one for each specified value.</remarks>
+    public static double[,] ToArray(
+      this IDataset dataset,
+      IEnumerable<KeyValuePair<string, IEnumerable<string>>> factorVariables,
+      IEnumerable<int> rows) {
+      // check input variables. Only string variables are allowed.
+      var invalidInputs =
+        factorVariables.Select(kvp => kvp.Key).Where(name => !dataset.VariableHasType<string>(name));
+      if (invalidInputs.Any())
+        throw new NotSupportedException("Unsupported inputs: " + string.Join(", ", invalidInputs));
+
+      int numBinaryColumns = factorVariables.Sum(kvp => kvp.Value.Count());
+
+      List<int> rowsList = rows.ToList();
+      double[,] matrix = new double[rowsList.Count, numBinaryColumns];
+
+      int col = 0;
+      foreach (var kvp in factorVariables) {
+        var varName = kvp.Key;
+        var cats = kvp.Value;
+        if (!cats.Any()) continue;
+        foreach (var cat in cats) {
+          var values = dataset.GetStringValues(varName, rows);
+          int row = 0;
+          foreach (var value in values) {
+            matrix[row, col] = value == cat ? 1 : 0;
+            row++;
+          }
+          col++;
+        }
+      }
+      return matrix;
+    }
+
+    public static IEnumerable<KeyValuePair<string, IEnumerable<string>>> GetFactorVariableValues(
+      this IDataset ds, IEnumerable<string> factorVariables, IEnumerable<int> rows) {
+      return from factor in factorVariables
+             let distinctValues = ds.GetStringValues(factor, rows).Distinct().ToArray()
+             // 1 distinct value => skip (constant)
+             // 2 distinct values => only take one of the two values
+             // >=3 distinct values => create a binary value for each value
+             let reducedValues = distinctValues.Length <= 2
+               ? distinctValues.Take(distinctValues.Length - 1)
+               : distinctValues
+             select new KeyValuePair<string, IEnumerable<string>>(factor, reducedValues);
     }
   }
Index: /stable/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/DataAnalysisProblemData.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/DataAnalysisProblemData.cs	(revision 15141)
+++ /stable/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/DataAnalysisProblemData.cs	(revision 15142)
@@ -94,4 +94,9 @@
     }
 
+    public double[,] AllowedInputsTrainingValues {
+      get { return Dataset.ToArray(AllowedInputVariables, TrainingIndices); }
+    }
+
+    public double[,] AllowedInputsTestValues { get { return Dataset.ToArray(AllowedInputVariables, TestIndices); } }
     public IntRange TrainingPartition {
       get { return TrainingPartitionParameter.Value; }
Index: /stable/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Transformations/LinearTransformation.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Transformations/LinearTransformation.cs	(revision 15141)
+++ /stable/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Transformations/LinearTransformation.cs	(revision 15142)
@@ -52,5 +52,5 @@
     public double Multiplier {
       get { return MultiplierParameter.Value.Value; }
-      protected set {
+      set {
         MultiplierParameter.Value.Value = value;
       }
@@ -59,5 +59,5 @@
     public double Addend {
       get { return AddendParameter.Value.Value; }
-      protected set {
+      set {
         AddendParameter.Value.Value = value;
       }
Index: /stable/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Transformations/ShiftStandardDistributionTransformation.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Transformations/ShiftStandardDistributionTransformation.cs	(revision 15141)
+++ /stable/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Transformations/ShiftStandardDistributionTransformation.cs	(revision 15142)
@@ -71,5 +71,4 @@
 
     public override IEnumerable<double> Apply(IEnumerable<double> data) {
-      ConfigureParameters(data);
       if (OriginalStandardDeviation.IsAlmost(0.0)) {
         return data;
@@ -94,5 +93,5 @@
     }
 
-    protected void ConfigureParameters(IEnumerable<double> data) {
+    public override void ConfigureParameters(IEnumerable<double> data) {
       OriginalStandardDeviation = data.StandardDeviation();
       OriginalMean = data.Average();
Index: /stable/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Transformations/ShiftToRangeTransformation.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Transformations/ShiftToRangeTransformation.cs	(revision 15141)
+++ /stable/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Transformations/ShiftToRangeTransformation.cs	(revision 15142)
@@ -44,9 +44,4 @@
     }
 
-    public override IEnumerable<double> Apply(IEnumerable<double> data) {
-      ConfigureParameters(data);
-      return base.Apply(data);
-    }
-
     public override bool Check(IEnumerable<double> data, out string errorMsg) {
       ConfigureParameters(data);
@@ -54,5 +49,5 @@
     }
 
-    protected void ConfigureParameters(IEnumerable<double> data) {
+    public override void ConfigureParameters(IEnumerable<double> data) {
       double originalRangeStart = data.Min();
       double originalRangeEnd = data.Max();
Index: /stable/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Transformations/Transformation.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Transformations/Transformation.cs	(revision 15141)
+++ /stable/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Transformations/Transformation.cs	(revision 15142)
@@ -66,5 +66,13 @@
     protected Transformation(IEnumerable<string> allowedColumns) : base(allowedColumns) { }
 
+    public virtual void ConfigureParameters(IEnumerable<T> data) {
+      // override in transformations with parameters
+    }
+
     public abstract IEnumerable<T> Apply(IEnumerable<T> data);
+    public IEnumerable<T> ConfigureAndApply(IEnumerable<T> data) {
+      ConfigureParameters(data);
+      return Apply(data);
+    }
 
     public abstract bool Check(IEnumerable<T> data, out string errorMsg);
Index: /stable/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/IDataAnalysisProblemData.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/IDataAnalysisProblemData.cs	(revision 15141)
+++ /stable/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/IDataAnalysisProblemData.cs	(revision 15142)
@@ -33,4 +33,7 @@
     IEnumerable<string> AllowedInputVariables { get; }
 
+    double[,] AllowedInputsTrainingValues { get; }
+    double[,] AllowedInputsTestValues { get; }
+
     IntRange TrainingPartition { get; }
     IntRange TestPartition { get; }
Index: /stable/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/ITransformation.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/ITransformation.cs	(revision 15141)
+++ /stable/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/ITransformation.cs	(revision 15142)
@@ -30,4 +30,6 @@
 
   public interface ITransformation<T> : ITransformation {
+    void ConfigureParameters(IEnumerable<T> data);
+    IEnumerable<T> ConfigureAndApply(IEnumerable<T> data);
     IEnumerable<T> Apply(IEnumerable<T> data);
   }
Index: /stable/HeuristicLab.Tests/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4/SymbolicDataAnalysisExpressionTreeSimplifierTest.cs
===================================================================
--- /stable/HeuristicLab.Tests/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4/SymbolicDataAnalysisExpressionTreeSimplifierTest.cs	(revision 15141)
+++ /stable/HeuristicLab.Tests/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4/SymbolicDataAnalysisExpressionTreeSimplifierTest.cs	(revision 15142)
@@ -34,5 +34,5 @@
     public void SimplifierAxiomsTest() {
       SymbolicExpressionImporter importer = new SymbolicExpressionImporter();
-      SymbolicDataAnalysisExpressionTreeSimplifier simplifier = new SymbolicDataAnalysisExpressionTreeSimplifier();
+      TreeSimplifier simplifier = new TreeSimplifier();
       SymbolicExpressionTreeStringFormatter formatter = new SymbolicExpressionTreeStringFormatter();
       #region single argument arithmetics
