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 11027)
+++ trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4.csproj	(revision 11114)
@@ -132,4 +132,5 @@
     <Compile Include="Matching\SymbolicExpressionTreeNodeComparer.cs" />
     <Compile Include="Matching\SymbolicExpressionTreeNodeSimilarityComparer.cs" />
+    <Compile Include="SymbolicExpressionTreeBacktransformator.cs" />
     <Compile Include="SymbolicDataAnalysisExpressionPruningOperator.cs" />
     <Compile Include="Analyzers\SymbolicDataAnalysisVariableFrequencyAnalyzer.cs" />
@@ -228,4 +229,5 @@
     <Compile Include="Symbols\VariableConditionTreeNode.cs" />
     <Compile Include="Symbols\VariableTreeNode.cs" />
+    <Compile Include="TransformationToSymbolicTreeMapper.cs" />
     <None Include="HeuristicLab.snk" />
     <None Include="Plugin.cs.frame" />
Index: trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicExpressionTreeBacktransformator.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicExpressionTreeBacktransformator.cs	(revision 11114)
+++ trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicExpressionTreeBacktransformator.cs	(revision 11114)
@@ -0,0 +1,97 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2013 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 IDataAnalysisModel Backtransform(IDataAnalysisModel 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/TransformationToSymbolicTreeMapper.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/TransformationToSymbolicTreeMapper.cs	(revision 11114)
+++ trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/TransformationToSymbolicTreeMapper.cs	(revision 11114)
@@ -0,0 +1,294 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2013 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;
+    }
+  }
+}
