Index: trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Converters/Convert.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Converters/Convert.cs	(revision 14390)
+++ trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Converters/Convert.cs	(revision 14390)
@@ -0,0 +1,51 @@
+﻿#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 string[] variableNames, out int[] lags, out double[] initialConstants,
+      out TreeToAutoDiffTermConverter.ParametricFunction func,
+      out TreeToAutoDiffTermConverter.ParametricFunctionGradient func_grad) {
+      var success = TreeToAutoDiffTermConverter.TryTransformToAutoDiff(tree, makeVariableWeightsVariable, out variableNames,
+        out lags, 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);
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Converters/LinearModelToTreeConverter.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Converters/LinearModelToTreeConverter.cs	(revision 14390)
+++ trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Converters/LinearModelToTreeConverter.cs	(revision 14390)
@@ -0,0 +1,54 @@
+﻿#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.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) {
+      if (variableNames.Length == 0 ||
+        variableNames.Length != coefficients.Length)
+        throw new ArgumentException("The length of the variable names 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++) {
+        VariableTreeNode vNode = (VariableTreeNode)new Variable().CreateTreeNode();
+        vNode.VariableName = variableNames[i];
+        vNode.Weight = coefficients[i];
+        addition.AddSubtree(vNode);
+      }
+
+      if (!@const.IsAlmost(0.0)) {
+        ConstantTreeNode cNode = (ConstantTreeNode)new Constant().CreateTreeNode();
+        cNode.Value = @const;
+        addition.AddSubtree(cNode);
+      }
+      return tree;
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Converters/TreeSimplifier.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Converters/TreeSimplifier.cs	(revision 14390)
+++ trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Converters/TreeSimplifier.cs	(revision 14390)
@@ -0,0 +1,1056 @@
+﻿#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 Subtraction subSymbol = new Subtraction();
+    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));
+      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 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) || IsVariable(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 {
+        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 {
+        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 {
+        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 (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 MakeSquare(ISymbolicExpressionTreeNode node) {
+      if (IsConstant(node)) {
+        var constT = node as ConstantTreeNode;
+        return MakeConstant(constT.Value * constT.Value);
+      } 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 (IsSquare(node)) {
+        return node.GetSubtree(0);
+      } else {
+        var sqrtNode = sqrtSymbol.CreateTreeNode();
+        sqrtNode.AddSubtree(node);
+        return sqrtNode;
+      }
+    }
+
+    private ISymbolicExpressionTreeNode MakeLog(ISymbolicExpressionTreeNode node) {
+      if (IsConstant(node)) {
+        var constT = node as ConstantTreeNode;
+        return MakeConstant(Math.Log(constT.Value));
+      } 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 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 (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 (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);
+      }
+      if (IsConstant(a) && !((ConstantTreeNode)a).Value.IsAlmost(1.0)) {
+        return MakeFraction(MakeConstant(1.0), MakeProduct(b, Invert(a)));
+      } else if (IsVariable(a) && IsConstant(b)) {
+        // merge constant values into variable weights
+        var constB = ((ConstantTreeNode)b).Value;
+        ((VariableTreeNode)a).Weight /= constB;
+        return a;
+      } else if (IsVariable(a) && IsVariable(b) && AreSameVariable(a, b)) {
+        // cancel variables
+        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, 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 (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
+    // possible improvement: combine sums of products where the products only reference the same variable
+    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<VariableTreeNode>()
+                            let lag = (node is LaggedVariableTreeNode) ? ((LaggedVariableTreeNode)node).Lag : 0
+                            group node by node.VariableName + lag into g
+                            select g;
+      var unchangedSubtrees = subtrees.Where(t => !(t is VariableTreeNode));
+
+      foreach (var variableNodeGroup in groupedVarNodes) {
+        var weightSum = variableNodeGroup.Select(t => t.Weight).Sum();
+        var representative = variableNodeGroup.First();
+        representative.Weight = weightSum;
+        sum.AddSubtree(representative);
+      }
+      foreach (var unchangedSubtree in unchangedSubtrees)
+        sum.AddSubtree(unchangedSubtree);
+    }
+
+
+    private ISymbolicExpressionTreeNode MakeProduct(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) {
+      if (IsConstant(a) && IsConstant(b)) {
+        // fold constants
+        ((ConstantTreeNode)a).Value *= ((ConstantTreeNode)b).Value;
+        return a;
+      } else if (IsConstant(a)) {
+        // a * $ => $ * a
+        return MakeProduct(b, a);
+      } else if (IsConstant(b) && ((ConstantTreeNode)b).Value.IsAlmost(1.0)) {
+        // $ * 1.0 => $
+        return a;
+      } else if (IsConstant(b) && IsVariable(a)) {
+        // multiply constants into variables weights
+        ((VariableTreeNode)a).Weight *= ((ConstantTreeNode)b).Value;
+        return a;
+      } else if (IsConstant(b) && IsAddition(a)) {
+        // multiply constants into additions
+        return a.Subtrees.Select(x => MakeProduct(x, 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(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 AreSameVariable(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) {
+      var aLaggedVar = a as LaggedVariableTreeNode;
+      var bLaggedVar = b as LaggedVariableTreeNode;
+      if (aLaggedVar != null && bLaggedVar != null) {
+        return aLaggedVar.VariableName == bLaggedVar.VariableName &&
+          aLaggedVar.Lag == bLaggedVar.Lag;
+      }
+      var aVar = a as VariableTreeNode;
+      var bVar = b as VariableTreeNode;
+      if (aVar != null && bVar != null) {
+        return aVar.VariableName == bVar.VariableName;
+      }
+      return false;
+    }
+
+    // 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<VariableTreeNode>()
+                            let lag = (node is LaggedVariableTreeNode) ? ((LaggedVariableTreeNode)node).Lag : 0
+                            group node by node.VariableName + lag into g
+                            orderby g.Count()
+                            select g;
+      var constantProduct = (from node in subtrees.OfType<VariableTreeNode>()
+                             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 is VariableTreeNode)
+                              where !(tree is ConstantTreeNode)
+                              select tree;
+
+      foreach (var variableNodeGroup in groupedVarNodes) {
+        var representative = variableNodeGroup.First();
+        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);
+        }
+      }
+
+      foreach (var unchangedSubtree in unchangedSubtrees)
+        prod.AddSubtree(unchangedSubtree);
+
+      if (!constantProduct.IsAlmost(1.0)) {
+        prod.AddSubtree(MakeConstant(constantProduct));
+      }
+    }
+
+
+    /// <summary>
+    /// x => x * -1
+    /// Doesn't create new trees and manipulates x
+    /// </summary>
+    /// <param name="x"></param>
+    /// <returns>-x</returns>
+    private ISymbolicExpressionTreeNode Negate(ISymbolicExpressionTreeNode x) {
+      if (IsConstant(x)) {
+        ((ConstantTreeNode)x).Value *= -1;
+      } else if (IsVariable(x)) {
+        var variableTree = (VariableTreeNode)x;
+        variableTree.Weight *= -1.0;
+      } 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
+    /// Doesn't create new trees and manipulates x
+    /// </summary>
+    /// <param name="x"></param>
+    /// <returns></returns>
+    private ISymbolicExpressionTreeNode Invert(ISymbolicExpressionTreeNode x) {
+      if (IsConstant(x)) {
+        return MakeConstant(1.0 / ((ConstantTreeNode)x).Value);
+      } 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 MakeVariable(double weight, string name) {
+      var tree = (VariableTreeNode)varSymbol.CreateTreeNode();
+      tree.Weight = weight;
+      tree.VariableName = name;
+      return tree;
+    }
+    #endregion
+  }
+}
Index: trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Converters/TreeToAutoDiffTermConverter.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Converters/TreeToAutoDiffTermConverter.cs	(revision 14390)
+++ trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Converters/TreeToAutoDiffTermConverter.cs	(revision 14390)
@@ -0,0 +1,332 @@
+﻿#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 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 string[] variableNames, out int[] lags, 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.TryTransformToAutoDiff(tree.Root.GetSubtree(0), out term);
+      if (success) {
+        var compiledTerm = term.Compile(transformator.variables.ToArray(), transformator.parameters.ToArray());
+        variableNames = transformator.variableNames.ToArray();
+        lags = transformator.lags.ToArray();
+        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;
+        variableNames = null;
+        lags = 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 List<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 List<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) {
+        var varNode = node as VariableTreeNode;
+        var par = new AutoDiff.Variable();
+        parameters.Add(par);
+        variableNames.Add(varNode.VariableName);
+        lags.Add(0);
+
+        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 LaggedVariable) {
+        var varNode = node as LaggedVariableTreeNode;
+        var par = new AutoDiff.Variable();
+        parameters.Add(par);
+        variableNames.Add(varNode.VariableName);
+        lags.Add(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(); // TODO
+        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;
+    }
+
+
+    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: trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/SymbolicDataAnalysisExpressionExcelFormatter.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/SymbolicDataAnalysisExpressionExcelFormatter.cs	(revision 14378)
+++ trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/SymbolicDataAnalysisExpressionExcelFormatter.cs	(revision 14390)
@@ -51,5 +51,5 @@
       while (dividend > 0) {
         int modulo = (dividend - 1) % 26;
-        columnName = Convert.ToChar(65 + modulo).ToString() + columnName;
+        columnName = System.Convert.ToChar(65 + modulo).ToString() + columnName;
         dividend = (int)((dividend - modulo) / 26);
       }
Index: trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4.csproj
===================================================================
--- trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4.csproj	(revision 14378)
+++ trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4.csproj	(revision 14390)
@@ -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" />
@@ -242,8 +246,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: trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisExpressionTreeSimplificationOperator.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisExpressionTreeSimplificationOperator.cs	(revision 14378)
+++ trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisExpressionTreeSimplificationOperator.cs	(revision 14390)
@@ -37,5 +37,5 @@
     }
 
-    private readonly SymbolicDataAnalysisExpressionTreeSimplifier simplifier = new SymbolicDataAnalysisExpressionTreeSimplifier();
+    private readonly TreeSimplifier simplifier = new TreeSimplifier();
 
     [StorableConstructor]
Index: trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Transformations/SymbolicExpressionTreeBacktransformator.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Transformations/SymbolicExpressionTreeBacktransformator.cs	(revision 14390)
+++ trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Transformations/SymbolicExpressionTreeBacktransformator.cs	(revision 14390)
@@ -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: trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Transformations/TransformationToSymbolicTreeMapper.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Transformations/TransformationToSymbolicTreeMapper.cs	(revision 14390)
+++ trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Transformations/TransformationToSymbolicTreeMapper.cs	(revision 14390)
@@ -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;
+    }
+  }
+}
