Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisAlleleFrequencyAnalyzer.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisAlleleFrequencyAnalyzer.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisAlleleFrequencyAnalyzer.cs	(revision 15973)
@@ -1,5 +1,5 @@
 #region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
@@ -89,6 +89,12 @@
       var varTreeNode = tree as VariableTreeNode;
       var constTreeNode = tree as ConstantTreeNode;
+      var factorVarTreeNode = tree as FactorVariableTreeNode;
+      var binFactorVarTreeNode = tree as BinaryFactorVariableTreeNode;
       if (varTreeNode != null) {
         builder.Append("(var " + varTreeNode.VariableName);
+      } else if (factorVarTreeNode != null) {
+        builder.Append("(factor " + factorVarTreeNode.VariableName);
+      } else if (binFactorVarTreeNode != null) {
+        builder.Append("(factor " + binFactorVarTreeNode.VariableName + "=" + binFactorVarTreeNode.VariableValue);
       } else if (constTreeNode != null) {
         builder.Append("(const");
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisAnalyzer.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisAnalyzer.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisAnalyzer.cs	(revision 15973)
@@ -1,5 +1,5 @@
 #region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisBottomUpDiversityAnalyzer.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisBottomUpDiversityAnalyzer.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisBottomUpDiversityAnalyzer.cs	(revision 15973)
@@ -1,5 +1,5 @@
 ﻿#region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisMultiObjectiveAnalyzer.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisMultiObjectiveAnalyzer.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisMultiObjectiveAnalyzer.cs	(revision 15973)
@@ -1,5 +1,5 @@
 #region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisMultiObjectiveTrainingBestSolutionAnalyzer.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisMultiObjectiveTrainingBestSolutionAnalyzer.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisMultiObjectiveTrainingBestSolutionAnalyzer.cs	(revision 15973)
@@ -1,5 +1,5 @@
 #region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisMultiObjectiveValidationAnalyzer.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisMultiObjectiveValidationAnalyzer.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisMultiObjectiveValidationAnalyzer.cs	(revision 15973)
@@ -1,5 +1,5 @@
 #region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisMultiObjectiveValidationBestSolutionAnalyzer.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisMultiObjectiveValidationBestSolutionAnalyzer.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisMultiObjectiveValidationBestSolutionAnalyzer.cs	(revision 15973)
@@ -1,5 +1,5 @@
 #region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisSingleObjectiveAnalyzer.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisSingleObjectiveAnalyzer.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisSingleObjectiveAnalyzer.cs	(revision 15973)
@@ -1,5 +1,5 @@
 #region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisSingleObjectivePruningAnalyzer.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisSingleObjectivePruningAnalyzer.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisSingleObjectivePruningAnalyzer.cs	(revision 15973)
@@ -2,5 +2,5 @@
 
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisSingleObjectiveTrainingBestSolutionAnalyzer.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisSingleObjectiveTrainingBestSolutionAnalyzer.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisSingleObjectiveTrainingBestSolutionAnalyzer.cs	(revision 15973)
@@ -1,5 +1,5 @@
 #region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
@@ -35,13 +35,13 @@
   [Item("SymbolicDataAnalysisSingleObjectiveTrainingBestSolutionAnalyzer", "An operator that analyzes the training best symbolic data analysis solution for single objective symbolic data analysis problems.")]
   [StorableClass]
-  public abstract class SymbolicDataAnalysisSingleObjectiveTrainingBestSolutionAnalyzer<T> : SymbolicDataAnalysisSingleObjectiveAnalyzer, IIterationBasedOperator
-
-    where T : class, ISymbolicDataAnalysisSolution {
+  public abstract class SymbolicDataAnalysisSingleObjectiveTrainingBestSolutionAnalyzer<T> : SymbolicDataAnalysisSingleObjectiveAnalyzer, IIterationBasedOperator where T : class, ISymbolicDataAnalysisSolution {
     private const string TrainingBestSolutionParameterName = "Best training solution";
     private const string TrainingBestSolutionQualityParameterName = "Best training solution quality";
     private const string TrainingBestSolutionGenerationParameterName = "Best training solution generation";
+    private const string TrainingBestSolutionsHistoryParameterName = "Best training solutions history";
     private const string UpdateAlwaysParameterName = "Always update best solution";
     private const string IterationsParameterName = "Iterations";
     private const string MaximumIterationsParameterName = "Maximum Iterations";
+    private const string StoreHistoryParameterName = "Store History";
 
     #region parameter properties
@@ -55,4 +55,7 @@
       get { return (ILookupParameter<IntValue>)Parameters[TrainingBestSolutionGenerationParameterName]; }
     }
+    public ILookupParameter<ItemList<T>> TrainingBestSolutionsHistoryParameter {
+      get { return (ILookupParameter<ItemList<T>>)Parameters[TrainingBestSolutionsHistoryParameterName]; }
+    }
     public IFixedValueParameter<BoolValue> UpdateAlwaysParameter {
       get { return (IFixedValueParameter<BoolValue>)Parameters[UpdateAlwaysParameterName]; }
@@ -63,4 +66,8 @@
     public IValueLookupParameter<IntValue> MaximumIterationsParameter {
       get { return (IValueLookupParameter<IntValue>)Parameters[MaximumIterationsParameterName]; }
+    }
+
+    public IFixedValueParameter<BoolValue> StoreHistoryParameter {
+      get { return (IFixedValueParameter<BoolValue>)Parameters[StoreHistoryParameterName]; }
     }
     #endregion
@@ -74,8 +81,15 @@
       set { TrainingBestSolutionQualityParameter.ActualValue = value; }
     }
-    public BoolValue UpdateAlways {
-      get { return UpdateAlwaysParameter.Value; }
+    public bool UpdateAlways {
+      get { return UpdateAlwaysParameter.Value.Value; }
+      set { UpdateAlwaysParameter.Value.Value = value; }
+    }
+
+    public bool StoreHistory {
+      get { return StoreHistoryParameter.Value.Value; }
+      set { StoreHistoryParameter.Value.Value = value; }
     }
     #endregion
+
 
     [StorableConstructor]
@@ -84,5 +98,5 @@
     public SymbolicDataAnalysisSingleObjectiveTrainingBestSolutionAnalyzer()
       : base() {
-      Parameters.Add(new LookupParameter<T>(TrainingBestSolutionParameterName, "The training best symbolic data analyis solution."));
+      Parameters.Add(new LookupParameter<T>(TrainingBestSolutionParameterName, "The best training symbolic data analyis solution."));
       Parameters.Add(new LookupParameter<DoubleValue>(TrainingBestSolutionQualityParameterName, "The quality of the training best symbolic data analysis solution."));
       Parameters.Add(new LookupParameter<IntValue>(TrainingBestSolutionGenerationParameterName, "The generation in which the best training solution was found."));
@@ -90,4 +104,6 @@
       Parameters.Add(new LookupParameter<IntValue>(IterationsParameterName, "The number of performed iterations."));
       Parameters.Add(new ValueLookupParameter<IntValue>(MaximumIterationsParameterName, "The maximum number of performed iterations.") { Hidden = true });
+      Parameters.Add(new FixedValueParameter<BoolValue>(StoreHistoryParameterName, "Flag that determines whether all encountered best solutions should be stored as results.", new BoolValue(false)));
+      Parameters.Add(new LookupParameter<ItemList<T>>(TrainingBestSolutionsHistoryParameterName, "The history of the best training symbolic data analysis solutions."));
       UpdateAlwaysParameter.Hidden = true;
     }
@@ -105,7 +121,27 @@
       if (!Parameters.ContainsKey(MaximumIterationsParameterName))
         Parameters.Add(new ValueLookupParameter<IntValue>(MaximumIterationsParameterName, "The maximum number of performed iterations.") { Hidden = true });
+      if (!Parameters.ContainsKey(StoreHistoryParameterName))
+        Parameters.Add(new FixedValueParameter<BoolValue>(StoreHistoryParameterName, "Flag that determines whether all encountered best solutions should be stored as results.", new BoolValue(false)));
+      if (!Parameters.ContainsKey(TrainingBestSolutionsHistoryParameterName))
+        Parameters.Add(new LookupParameter<ItemList<T>>(TrainingBestSolutionsHistoryParameterName, "The history of the best training symbolic data analysis solutions."));
     }
 
     public override IOperation Apply() {
+      var results = ResultCollection;
+      #region create results
+      if (!results.ContainsKey(TrainingBestSolutionParameter.Name))
+        results.Add(new Result(TrainingBestSolutionParameter.Name, TrainingBestSolutionParameter.Description, typeof(T)));
+      if (!results.ContainsKey(TrainingBestSolutionQualityParameter.Name))
+        results.Add(new Result(TrainingBestSolutionQualityParameter.Name, TrainingBestSolutionQualityParameter.Description, typeof(DoubleValue)));
+      if (!results.ContainsKey(TrainingBestSolutionGenerationParameter.Name) && IterationsParameter.ActualValue != null)
+        results.Add(new Result(TrainingBestSolutionGenerationParameter.Name, TrainingBestSolutionGenerationParameter.Description, typeof(IntValue)));
+      if (StoreHistory && !results.ContainsKey(TrainingBestSolutionsHistoryParameter.Name)) {
+
+        results.Add(new Result(TrainingBestSolutionsHistoryParameter.Name, TrainingBestSolutionsHistoryParameter.Description, typeof(ItemList<T>)));
+        TrainingBestSolutionsHistoryParameter.ActualValue = new ItemList<T>();
+        results[TrainingBestSolutionsHistoryParameter.Name].Value = TrainingBestSolutionsHistoryParameter.ActualValue;
+      }
+      #endregion
+
       #region find best tree
       double bestQuality = Maximization.Value ? double.NegativeInfinity : double.PositiveInfinity;
@@ -121,6 +157,5 @@
       #endregion
 
-      var results = ResultCollection;
-      if (bestTree != null && (UpdateAlways.Value || TrainingBestSolutionQuality == null ||
+      if (bestTree != null && (UpdateAlways || TrainingBestSolutionQuality == null ||
         IsBetter(bestQuality, TrainingBestSolutionQuality.Value, Maximization.Value))) {
         TrainingBestSolution = CreateSolution(bestTree, bestQuality);
@@ -129,15 +164,11 @@
           TrainingBestSolutionGenerationParameter.ActualValue = new IntValue(IterationsParameter.ActualValue.Value);
 
-        if (!results.ContainsKey(TrainingBestSolutionParameter.Name)) {
-          results.Add(new Result(TrainingBestSolutionParameter.Name, TrainingBestSolutionParameter.Description, TrainingBestSolution));
-          results.Add(new Result(TrainingBestSolutionQualityParameter.Name, TrainingBestSolutionQualityParameter.Description, TrainingBestSolutionQuality));
-          if (TrainingBestSolutionGenerationParameter.ActualValue != null)
-            results.Add(new Result(TrainingBestSolutionGenerationParameter.Name, TrainingBestSolutionGenerationParameter.Description, TrainingBestSolutionGenerationParameter.ActualValue));
-        } else {
-          results[TrainingBestSolutionParameter.Name].Value = TrainingBestSolution;
-          results[TrainingBestSolutionQualityParameter.Name].Value = TrainingBestSolutionQuality;
-          if (TrainingBestSolutionGenerationParameter.ActualValue != null)
-            results[TrainingBestSolutionGenerationParameter.Name].Value = TrainingBestSolutionGenerationParameter.ActualValue;
+        results[TrainingBestSolutionParameter.Name].Value = TrainingBestSolution;
+        results[TrainingBestSolutionQualityParameter.Name].Value = TrainingBestSolutionQuality;
+        if (TrainingBestSolutionGenerationParameter.ActualValue != null)
+          results[TrainingBestSolutionGenerationParameter.Name].Value = TrainingBestSolutionGenerationParameter.ActualValue;
 
+        if (StoreHistory) {
+          TrainingBestSolutionsHistoryParameter.ActualValue.Add(TrainingBestSolution);
         }
       }
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisSingleObjectiveTrainingParetoBestSolutionAnalyzer.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisSingleObjectiveTrainingParetoBestSolutionAnalyzer.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisSingleObjectiveTrainingParetoBestSolutionAnalyzer.cs	(revision 15973)
@@ -1,5 +1,5 @@
 #region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisSingleObjectiveValidationAnalyzer.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisSingleObjectiveValidationAnalyzer.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisSingleObjectiveValidationAnalyzer.cs	(revision 15973)
@@ -1,5 +1,5 @@
 #region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisSingleObjectiveValidationBestSolutionAnalyzer.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisSingleObjectiveValidationBestSolutionAnalyzer.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisSingleObjectiveValidationBestSolutionAnalyzer.cs	(revision 15973)
@@ -1,5 +1,5 @@
 #region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisSingleObjectiveValidationParetoBestSolutionAnalyzer.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisSingleObjectiveValidationParetoBestSolutionAnalyzer.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisSingleObjectiveValidationParetoBestSolutionAnalyzer.cs	(revision 15973)
@@ -1,5 +1,5 @@
 #region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisVariableFrequencyAnalyzer.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisVariableFrequencyAnalyzer.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisVariableFrequencyAnalyzer.cs	(revision 15973)
@@ -1,5 +1,5 @@
 #region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
@@ -22,4 +22,5 @@
 using System;
 using System.Collections.Generic;
+using System.Globalization;
 using System.Linq;
 using HeuristicLab.Analysis;
@@ -41,4 +42,5 @@
     private const string VariableFrequenciesParameterName = "VariableFrequencies";
     private const string AggregateLaggedVariablesParameterName = "AggregateLaggedVariables";
+    private const string AggregateFactorVariablesParameterName = "AggregateFactorVariables";
     private const string VariableImpactsParameterName = "VariableImpacts";
 
@@ -52,4 +54,7 @@
     public IValueLookupParameter<BoolValue> AggregateLaggedVariablesParameter {
       get { return (IValueLookupParameter<BoolValue>)Parameters[AggregateLaggedVariablesParameterName]; }
+    }
+    public IValueLookupParameter<BoolValue> AggregateFactorVariablesParameter {
+      get { return (IValueLookupParameter<BoolValue>)Parameters[AggregateFactorVariablesParameterName]; }
     }
     #endregion
@@ -59,4 +64,8 @@
       set { AggregateLaggedVariablesParameter.Value = value; }
     }
+    public BoolValue AggregateFactorVariables {
+      get { return AggregateFactorVariablesParameter.ActualValue; }
+      set { AggregateFactorVariablesParameter.Value = value; }
+    }
     #endregion
     [StorableConstructor]
@@ -70,4 +79,15 @@
       Parameters.Add(new LookupParameter<DoubleMatrix>(VariableImpactsParameterName, "The relative variable relevance calculated as the average relative variable frequency over the whole run."));
       Parameters.Add(new ValueLookupParameter<BoolValue>(AggregateLaggedVariablesParameterName, "Switch that determines whether all references to a variable should be aggregated regardless of time-offsets. Turn off to analyze all variable references with different time offsets separately.", new BoolValue(true)));
+      Parameters.Add(new ValueLookupParameter<BoolValue>(AggregateFactorVariablesParameterName, "Switch that determines whether all references to factor variables should be aggregated regardless of the value. Turn off to analyze all factor variable references with different values separately.", new BoolValue(true)));
+    }
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      // BackwardsCompatibility3.3
+      #region Backwards compatible code, remove with 3.4
+      if (!Parameters.ContainsKey(AggregateFactorVariablesParameterName)) {
+        Parameters.Add(new ValueLookupParameter<BoolValue>(AggregateFactorVariablesParameterName, "Switch that determines whether all references to factor variables should be aggregated regardless of the value. Turn off to analyze all factor variable references with different values separately.", new BoolValue(true)));
+      }
+      #endregion
     }
 
@@ -93,5 +113,5 @@
       int numberOfValues = datatable.Rows.Select(r => r.Values.Count).DefaultIfEmpty().First();
 
-      foreach (var pair in SymbolicDataAnalysisVariableFrequencyAnalyzer.CalculateVariableFrequencies(expressions, AggregateLaggedVariables.Value)) {
+      foreach (var pair in CalculateVariableFrequencies(expressions, AggregateLaggedVariables.Value, AggregateFactorVariables.Value)) {
         if (!datatable.Rows.ContainsKey(pair.Key)) {
           // initialize a new row for the variable and pad with zeros
@@ -128,8 +148,9 @@
     }
 
-    public static IEnumerable<KeyValuePair<string, double>> CalculateVariableFrequencies(IEnumerable<ISymbolicExpressionTree> trees, bool aggregateLaggedVariables = true) {
+    public static IEnumerable<KeyValuePair<string, double>> CalculateVariableFrequencies(IEnumerable<ISymbolicExpressionTree> trees,
+      bool aggregateLaggedVariables = true, bool aggregateFactorVariables = true) {
 
       var variableFrequencies = trees
-        .SelectMany(t => GetVariableReferences(t, aggregateLaggedVariables))
+        .SelectMany(t => GetVariableReferences(t, aggregateLaggedVariables, aggregateFactorVariables))
         .GroupBy(pair => pair.Key, pair => pair.Value)
         .ToDictionary(g => g.Key, g => (double)g.Sum());
@@ -141,49 +162,61 @@
     }
 
-    private static IEnumerable<KeyValuePair<string, int>> GetVariableReferences(ISymbolicExpressionTree tree, bool aggregateLaggedVariables = true) {
+    private static IEnumerable<KeyValuePair<string, int>> GetVariableReferences(ISymbolicExpressionTree tree,
+      bool aggregateLaggedVariables = true, bool aggregateFactorVariables = true) {
       Dictionary<string, int> references = new Dictionary<string, int>();
       if (aggregateLaggedVariables) {
         tree.Root.ForEachNodePrefix(node => {
-          if (node.Symbol is Variable) {
-            var varNode = node as VariableTreeNode;
-            IncReferenceCount(references, varNode.VariableName);
-          } else if (node.Symbol is VariableCondition) {
-            var varCondNode = node as VariableConditionTreeNode;
-            IncReferenceCount(references, varCondNode.VariableName);
+          if (node is IVariableTreeNode) {
+            var factorNode = node as BinaryFactorVariableTreeNode;
+            if (factorNode != null && !aggregateFactorVariables) {
+              IncReferenceCount(references, factorNode.VariableName + "=" + factorNode.VariableValue);
+            } else {
+              var varNode = node as IVariableTreeNode;
+              IncReferenceCount(references, varNode.VariableName);
+            }
           }
         });
       } else {
-        GetVariableReferences(references, tree.Root, 0);
+        GetVariableReferences(references, tree.Root, 0, aggregateFactorVariables);
       }
       return references;
     }
 
-    private static void GetVariableReferences(Dictionary<string, int> references, ISymbolicExpressionTreeNode node, int currentLag) {
-      if (node.Symbol is LaggedVariable) {
-        var laggedVarNode = node as LaggedVariableTreeNode;
-        IncReferenceCount(references, laggedVarNode.VariableName, currentLag + laggedVarNode.Lag);
-      } else if (node.Symbol is Variable) {
-        var varNode = node as VariableTreeNode;
-        IncReferenceCount(references, varNode.VariableName, currentLag);
-      } else if (node.Symbol is VariableCondition) {
-        var varCondNode = node as VariableConditionTreeNode;
-        IncReferenceCount(references, varCondNode.VariableName, currentLag);
-        GetVariableReferences(references, node.GetSubtree(0), currentLag);
-        GetVariableReferences(references, node.GetSubtree(1), currentLag);
+    private static void GetVariableReferences(Dictionary<string, int> references, ISymbolicExpressionTreeNode node, int currentLag, bool aggregateFactorVariables) {
+      if (node is IVariableTreeNode) {
+        var laggedVarTreeNode = node as LaggedVariableTreeNode;
+        var binFactorVariableTreeNode = node as BinaryFactorVariableTreeNode;
+        var varConditionTreeNode = node as VariableConditionTreeNode;
+        if (laggedVarTreeNode != null) {
+          IncReferenceCount(references, laggedVarTreeNode.VariableName, currentLag + laggedVarTreeNode.Lag);
+        } else if (binFactorVariableTreeNode != null) {
+          if (aggregateFactorVariables) {
+            IncReferenceCount(references, binFactorVariableTreeNode.VariableName, currentLag);
+          } else {
+            IncReferenceCount(references, binFactorVariableTreeNode.VariableName + "=" + binFactorVariableTreeNode.VariableValue, currentLag);
+          }
+        } else if (varConditionTreeNode != null) {
+          IncReferenceCount(references, varConditionTreeNode.VariableName, currentLag);
+          GetVariableReferences(references, node.GetSubtree(0), currentLag, aggregateFactorVariables);
+          GetVariableReferences(references, node.GetSubtree(1), currentLag, aggregateFactorVariables);
+        } else {
+          var varNode = node as IVariableTreeNode;
+          IncReferenceCount(references, varNode.VariableName, currentLag);
+        }
       } else if (node.Symbol is Integral) {
         var laggedNode = node as LaggedTreeNode;
         for (int l = laggedNode.Lag; l <= 0; l++) {
-          GetVariableReferences(references, node.GetSubtree(0), currentLag + l);
+          GetVariableReferences(references, node.GetSubtree(0), currentLag + l, aggregateFactorVariables);
         }
       } else if (node.Symbol is Derivative) {
         for (int l = -4; l <= 0; l++) {
-          GetVariableReferences(references, node.GetSubtree(0), currentLag + l);
+          GetVariableReferences(references, node.GetSubtree(0), currentLag + l, aggregateFactorVariables);
         }
       } else if (node.Symbol is TimeLag) {
         var laggedNode = node as LaggedTreeNode;
-        GetVariableReferences(references, node.GetSubtree(0), currentLag + laggedNode.Lag);
+        GetVariableReferences(references, node.GetSubtree(0), currentLag + laggedNode.Lag, aggregateFactorVariables);
       } else {
         foreach (var subtree in node.Subtrees) {
-          GetVariableReferences(references, subtree, currentLag);
+          GetVariableReferences(references, subtree, currentLag, aggregateFactorVariables);
         }
       }
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Converters/LinearModelToTreeConverter.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Converters/LinearModelToTreeConverter.cs	(revision 15973)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Converters/LinearModelToTreeConverter.cs	(revision 15973)
@@ -0,0 +1,126 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
+  public static class LinearModelToTreeConverter {
+    public static ISymbolicExpressionTree CreateTree(string[] variableNames, double[] coefficients,
+      double @const = 0) {
+      return CreateTree(variableNames, new int[variableNames.Length], coefficients, @const);
+    }
+
+    public static ISymbolicExpressionTree CreateTree(
+      IEnumerable<KeyValuePair<string, IEnumerable<string>>> factors, double[] factorCoefficients,
+      string[] variableNames, double[] coefficients,
+      double @const = 0) {
+      if (factorCoefficients.Length == 0 && coefficients.Length == 0) throw new ArgumentException();
+      ISymbolicExpressionTree p1 = null;
+      if (coefficients.Length > 0) {
+        p1 = CreateTree(variableNames, new int[variableNames.Length], coefficients, @const);
+        if (factorCoefficients.Length == 0)
+          return p1;
+      }
+      if (factorCoefficients.Length > 0) {
+        var p2 = CreateTree(factors, factorCoefficients);
+        if (p1 == null) return p2;
+
+        // combine
+        ISymbolicExpressionTreeNode add = p1.Root.GetSubtree(0).GetSubtree(0);
+        foreach (var binFactorNode in p2.IterateNodesPrefix().OfType<BinaryFactorVariableTreeNode>())
+          add.AddSubtree(binFactorNode);
+        return p1;
+      }
+      throw new ArgumentException();
+    }
+
+    public static ISymbolicExpressionTree CreateTree(string[] variableNames, int[] lags, double[] coefficients,
+      double @const = 0) {
+      if (variableNames.Length == 0 ||
+        variableNames.Length != coefficients.Length ||
+        variableNames.Length != lags.Length)
+        throw new ArgumentException("The length of the variable names, lags, and coefficients vectors must match");
+
+      ISymbolicExpressionTree tree = new SymbolicExpressionTree(new ProgramRootSymbol().CreateTreeNode());
+      ISymbolicExpressionTreeNode startNode = new StartSymbol().CreateTreeNode();
+      tree.Root.AddSubtree(startNode);
+      ISymbolicExpressionTreeNode addition = new Addition().CreateTreeNode();
+      startNode.AddSubtree(addition);
+
+      for (int i = 0; i < variableNames.Length; i++) {
+        if (lags[i] == 0) {
+          VariableTreeNode vNode = (VariableTreeNode)new Variable().CreateTreeNode();
+          vNode.VariableName = variableNames[i];
+          vNode.Weight = coefficients[i];
+          addition.AddSubtree(vNode);
+        } else {
+          LaggedVariableTreeNode vNode = (LaggedVariableTreeNode)new LaggedVariable().CreateTreeNode();
+          vNode.VariableName = variableNames[i];
+          vNode.Weight = coefficients[i];
+          vNode.Lag = lags[i];
+          addition.AddSubtree(vNode);
+        }
+      }
+
+      if (!@const.IsAlmost(0.0)) {
+        ConstantTreeNode cNode = (ConstantTreeNode)new Constant().CreateTreeNode();
+        cNode.Value = @const;
+        addition.AddSubtree(cNode);
+      }
+      return tree;
+    }
+
+    public static ISymbolicExpressionTree CreateTree(IEnumerable<KeyValuePair<string, IEnumerable<string>>> factors,
+      double[] factorCoefficients,
+      double @const = 0) {
+
+      ISymbolicExpressionTree tree = new SymbolicExpressionTree(new ProgramRootSymbol().CreateTreeNode());
+      ISymbolicExpressionTreeNode startNode = new StartSymbol().CreateTreeNode();
+      tree.Root.AddSubtree(startNode);
+      ISymbolicExpressionTreeNode addition = new Addition().CreateTreeNode();
+      startNode.AddSubtree(addition);
+
+      int i = 0;
+      foreach (var factor in factors) {
+        var varName = factor.Key;
+        foreach (var factorValue in factor.Value) {
+          var node = (BinaryFactorVariableTreeNode)new BinaryFactorVariable().CreateTreeNode();
+          node.VariableValue = factorValue;
+          node.VariableName = varName;
+          node.Weight = factorCoefficients[i];
+          addition.AddSubtree(node);
+          i++;
+        }
+      }
+
+      if (!@const.IsAlmost(0.0)) {
+        ConstantTreeNode cNode = (ConstantTreeNode)new Constant().CreateTreeNode();
+        cNode.Value = @const;
+        addition.AddSubtree(cNode);
+      }
+      return tree;
+    }
+  }
+}
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Converters/TreeSimplifier.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Converters/TreeSimplifier.cs	(revision 15973)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Converters/TreeSimplifier.cs	(revision 15973)
@@ -0,0 +1,1340 @@
+﻿#region License Information
+
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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 static readonly Addition addSymbol = new Addition();
+    private static readonly Multiplication mulSymbol = new Multiplication();
+    private static readonly Division divSymbol = new Division();
+    private static readonly Constant constSymbol = new Constant();
+    private static readonly Logarithm logSymbol = new Logarithm();
+    private static readonly Exponential expSymbol = new Exponential();
+    private static readonly Root rootSymbol = new Root();
+    private static readonly Square sqrSymbol = new Square();
+    private static readonly SquareRoot sqrtSymbol = new SquareRoot();
+    private static readonly Power powSymbol = new Power();
+    private static readonly Sine sineSymbol = new Sine();
+    private static readonly Cosine cosineSymbol = new Cosine();
+    private static readonly Tangent tanSymbol = new Tangent();
+    private static readonly IfThenElse ifThenElseSymbol = new IfThenElse();
+    private static readonly And andSymbol = new And();
+    private static readonly Or orSymbol = new Or();
+    private static readonly Not notSymbol = new Not();
+    private static readonly GreaterThan gtSymbol = new GreaterThan();
+    private static readonly LessThan ltSymbol = new LessThan();
+    private static readonly Integral integralSymbol = new Integral();
+    private static readonly LaggedVariable laggedVariableSymbol = new LaggedVariable();
+    private static readonly TimeLag timeLagSymbol = new TimeLag();
+
+    [Obsolete("Use static method TreeSimplifier.Simplify instead")]
+    public TreeSimplifier() { }
+
+    public static ISymbolicExpressionTree Simplify(ISymbolicExpressionTree originalTree) {
+      var clone = (ISymbolicExpressionTreeNode)originalTree.Root.Clone();
+      // macro expand (initially no argument trees)
+      var macroExpandedTree = MacroExpand(clone, clone.GetSubtree(0), new List<ISymbolicExpressionTreeNode>());
+      ISymbolicExpressionTreeNode rootNode = (new ProgramRootSymbol()).CreateTreeNode();
+      rootNode.AddSubtree(GetSimplifiedTree(macroExpandedTree));
+
+#if DEBUG
+      // check that each node is only referenced once
+      var nodes = rootNode.IterateNodesPrefix().ToArray();
+      foreach (var n in nodes) if (nodes.Count(ni => ni == n) > 1) throw new InvalidOperationException();
+#endif
+      return new SymbolicExpressionTree(rootNode);
+    }
+
+    // the argumentTrees list contains already expanded trees used as arguments for invocations
+    private static 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 static 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 static bool IsDivision(ISymbolicExpressionTreeNode node) {
+      return node.Symbol is Division;
+    }
+
+    private static bool IsMultiplication(ISymbolicExpressionTreeNode node) {
+      return node.Symbol is Multiplication;
+    }
+
+    private static bool IsSubtraction(ISymbolicExpressionTreeNode node) {
+      return node.Symbol is Subtraction;
+    }
+
+    private static bool IsAddition(ISymbolicExpressionTreeNode node) {
+      return node.Symbol is Addition;
+    }
+
+    private static bool IsAverage(ISymbolicExpressionTreeNode node) {
+      return node.Symbol is Average;
+    }
+
+    // exponential
+    private static bool IsLog(ISymbolicExpressionTreeNode node) {
+      return node.Symbol is Logarithm;
+    }
+
+    private static bool IsExp(ISymbolicExpressionTreeNode node) {
+      return node.Symbol is Exponential;
+    }
+
+    private static bool IsRoot(ISymbolicExpressionTreeNode node) {
+      return node.Symbol is Root;
+    }
+
+    private static bool IsSquare(ISymbolicExpressionTreeNode node) {
+      return node.Symbol is Square;
+    }
+
+    private static bool IsSquareRoot(ISymbolicExpressionTreeNode node) {
+      return node.Symbol is SquareRoot;
+    }
+
+    private static bool IsPower(ISymbolicExpressionTreeNode node) {
+      return node.Symbol is Power;
+    }
+
+    // trigonometric
+    private static bool IsSine(ISymbolicExpressionTreeNode node) {
+      return node.Symbol is Sine;
+    }
+
+    private static bool IsCosine(ISymbolicExpressionTreeNode node) {
+      return node.Symbol is Cosine;
+    }
+
+    private static bool IsTangent(ISymbolicExpressionTreeNode node) {
+      return node.Symbol is Tangent;
+    }
+
+    // boolean
+    private static bool IsIfThenElse(ISymbolicExpressionTreeNode node) {
+      return node.Symbol is IfThenElse;
+    }
+
+    private static bool IsAnd(ISymbolicExpressionTreeNode node) {
+      return node.Symbol is And;
+    }
+
+    private static bool IsOr(ISymbolicExpressionTreeNode node) {
+      return node.Symbol is Or;
+    }
+
+    private static bool IsNot(ISymbolicExpressionTreeNode node) {
+      return node.Symbol is Not;
+    }
+
+    // comparison
+    private static bool IsGreaterThan(ISymbolicExpressionTreeNode node) {
+      return node.Symbol is GreaterThan;
+    }
+
+    private static bool IsLessThan(ISymbolicExpressionTreeNode node) {
+      return node.Symbol is LessThan;
+    }
+
+    private static bool IsBoolean(ISymbolicExpressionTreeNode node) {
+      return
+        node.Symbol is GreaterThan ||
+        node.Symbol is LessThan ||
+        node.Symbol is And ||
+        node.Symbol is Or;
+    }
+
+    // terminals
+    private static bool IsVariable(ISymbolicExpressionTreeNode node) {
+      return node.Symbol is Variable;
+    }
+
+    private static bool IsVariableBase(ISymbolicExpressionTreeNode node) {
+      return node is VariableTreeNodeBase;
+    }
+
+    private static bool IsFactor(ISymbolicExpressionTreeNode node) {
+      return node is FactorVariableTreeNode;
+    }
+
+    private static bool IsBinFactor(ISymbolicExpressionTreeNode node) {
+      return node is BinaryFactorVariableTreeNode;
+    }
+
+    private static bool IsConstant(ISymbolicExpressionTreeNode node) {
+      return node.Symbol is Constant;
+    }
+
+    // dynamic
+    private static bool IsTimeLag(ISymbolicExpressionTreeNode node) {
+      return node.Symbol is TimeLag;
+    }
+
+    private static bool IsIntegral(ISymbolicExpressionTreeNode node) {
+      return node.Symbol is Integral;
+    }
+
+    #endregion
+
+    /// <summary>
+    /// Creates a new simplified tree
+    /// </summary>
+    /// <param name="original"></param>
+    /// <returns></returns>
+    public static ISymbolicExpressionTreeNode GetSimplifiedTree(ISymbolicExpressionTreeNode original) {
+      if (IsConstant(original) || IsVariableBase(original)) {
+        return (ISymbolicExpressionTreeNode)original.Clone();
+      } else if (IsAddition(original)) {
+        return SimplifyAddition(original);
+      } else if (IsSubtraction(original)) {
+        return SimplifySubtraction(original);
+      } else if (IsMultiplication(original)) {
+        return SimplifyMultiplication(original);
+      } else if (IsDivision(original)) {
+        return SimplifyDivision(original);
+      } else if (IsAverage(original)) {
+        return SimplifyAverage(original);
+      } else if (IsLog(original)) {
+        return SimplifyLog(original);
+      } else if (IsExp(original)) {
+        return SimplifyExp(original);
+      } else if (IsSquare(original)) {
+        return SimplifySquare(original);
+      } else if (IsSquareRoot(original)) {
+        return SimplifySquareRoot(original);
+      } else if (IsPower(original)) {
+        return SimplifyPower(original);
+      } else if (IsRoot(original)) {
+        return SimplifyRoot(original);
+      } else if (IsSine(original)) {
+        return SimplifySine(original);
+      } else if (IsCosine(original)) {
+        return SimplifyCosine(original);
+      } else if (IsTangent(original)) {
+        return SimplifyTangent(original);
+      } else if (IsIfThenElse(original)) {
+        return SimplifyIfThenElse(original);
+      } else if (IsGreaterThan(original)) {
+        return SimplifyGreaterThan(original);
+      } else if (IsLessThan(original)) {
+        return SimplifyLessThan(original);
+      } else if (IsAnd(original)) {
+        return SimplifyAnd(original);
+      } else if (IsOr(original)) {
+        return SimplifyOr(original);
+      } else if (IsNot(original)) {
+        return SimplifyNot(original);
+      } else if (IsTimeLag(original)) {
+        return SimplifyTimeLag(original);
+      } else if (IsIntegral(original)) {
+        return SimplifyIntegral(original);
+      } else {
+        return SimplifyAny(original);
+      }
+    }
+
+    #region specific simplification routines
+
+    private static 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 static ISymbolicExpressionTreeNode SimplifyConstantExpression(ISymbolicExpressionTreeNode original) {
+      // not yet implemented
+      return original;
+    }
+
+    private static 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 static 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 static ISymbolicExpressionTreeNode SimplifyMultiplication(ISymbolicExpressionTreeNode original) {
+      if (original.Subtrees.Count() == 1) {
+        return GetSimplifiedTree(original.GetSubtree(0));
+      } else {
+        return original.Subtrees
+          .Select(GetSimplifiedTree)
+          .Aggregate(MakeProduct);
+      }
+    }
+
+    private static 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 static 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 static ISymbolicExpressionTreeNode SimplifyNot(ISymbolicExpressionTreeNode original) {
+      return MakeNot(GetSimplifiedTree(original.GetSubtree(0)));
+    }
+
+    private static ISymbolicExpressionTreeNode SimplifyOr(ISymbolicExpressionTreeNode original) {
+      return original.Subtrees
+        .Select(GetSimplifiedTree)
+        .Aggregate(MakeOr);
+    }
+
+    private static ISymbolicExpressionTreeNode SimplifyAnd(ISymbolicExpressionTreeNode original) {
+      return original.Subtrees
+        .Select(GetSimplifiedTree)
+        .Aggregate(MakeAnd);
+    }
+
+    private static ISymbolicExpressionTreeNode SimplifyLessThan(ISymbolicExpressionTreeNode original) {
+      return MakeLessThan(GetSimplifiedTree(original.GetSubtree(0)), GetSimplifiedTree(original.GetSubtree(1)));
+    }
+
+    private static ISymbolicExpressionTreeNode SimplifyGreaterThan(ISymbolicExpressionTreeNode original) {
+      return MakeGreaterThan(GetSimplifiedTree(original.GetSubtree(0)), GetSimplifiedTree(original.GetSubtree(1)));
+    }
+
+    private static ISymbolicExpressionTreeNode SimplifyIfThenElse(ISymbolicExpressionTreeNode original) {
+      return MakeIfThenElse(GetSimplifiedTree(original.GetSubtree(0)), GetSimplifiedTree(original.GetSubtree(1)),
+        GetSimplifiedTree(original.GetSubtree(2)));
+    }
+
+    private static ISymbolicExpressionTreeNode SimplifyTangent(ISymbolicExpressionTreeNode original) {
+      return MakeTangent(GetSimplifiedTree(original.GetSubtree(0)));
+    }
+
+    private static ISymbolicExpressionTreeNode SimplifyCosine(ISymbolicExpressionTreeNode original) {
+      return MakeCosine(GetSimplifiedTree(original.GetSubtree(0)));
+    }
+
+    private static ISymbolicExpressionTreeNode SimplifySine(ISymbolicExpressionTreeNode original) {
+      return MakeSine(GetSimplifiedTree(original.GetSubtree(0)));
+    }
+
+    private static ISymbolicExpressionTreeNode SimplifyExp(ISymbolicExpressionTreeNode original) {
+      return MakeExp(GetSimplifiedTree(original.GetSubtree(0)));
+    }
+
+    private static ISymbolicExpressionTreeNode SimplifySquare(ISymbolicExpressionTreeNode original) {
+      return MakeSquare(GetSimplifiedTree(original.GetSubtree(0)));
+    }
+
+    private static ISymbolicExpressionTreeNode SimplifySquareRoot(ISymbolicExpressionTreeNode original) {
+      return MakeSquareRoot(GetSimplifiedTree(original.GetSubtree(0)));
+    }
+
+    private static ISymbolicExpressionTreeNode SimplifyLog(ISymbolicExpressionTreeNode original) {
+      return MakeLog(GetSimplifiedTree(original.GetSubtree(0)));
+    }
+
+    private static ISymbolicExpressionTreeNode SimplifyRoot(ISymbolicExpressionTreeNode original) {
+      return MakeRoot(GetSimplifiedTree(original.GetSubtree(0)), GetSimplifiedTree(original.GetSubtree(1)));
+    }
+
+    private static ISymbolicExpressionTreeNode SimplifyPower(ISymbolicExpressionTreeNode original) {
+      return MakePower(GetSimplifiedTree(original.GetSubtree(0)), GetSimplifiedTree(original.GetSubtree(1)));
+    }
+
+    private static 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 static 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 static 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 static 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 static 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 static 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 static 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 static 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 static 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 static 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 static ISymbolicExpressionTreeNode MakeSine(ISymbolicExpressionTreeNode node) {
+      if (IsConstant(node)) {
+        var constT = node as ConstantTreeNode;
+        return MakeConstant(Math.Sin(constT.Value));
+      } else if (IsFactor(node)) {
+        var factor = node as FactorVariableTreeNode;
+        return MakeFactor(factor.Symbol, factor.VariableName, factor.Weights.Select(Math.Sin));
+      } else if (IsBinFactor(node)) {
+        var binFactor = node as BinaryFactorVariableTreeNode;
+        return MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Sin(binFactor.Weight));
+      } else {
+        var sineNode = sineSymbol.CreateTreeNode();
+        sineNode.AddSubtree(node);
+        return sineNode;
+      }
+    }
+
+    private static ISymbolicExpressionTreeNode MakeTangent(ISymbolicExpressionTreeNode node) {
+      if (IsConstant(node)) {
+        var constT = node as ConstantTreeNode;
+        return MakeConstant(Math.Tan(constT.Value));
+      } else if (IsFactor(node)) {
+        var factor = node as FactorVariableTreeNode;
+        return MakeFactor(factor.Symbol, factor.VariableName, factor.Weights.Select(Math.Tan));
+      } else if (IsBinFactor(node)) {
+        var binFactor = node as BinaryFactorVariableTreeNode;
+        return MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Tan(binFactor.Weight));
+      } else {
+        var tanNode = tanSymbol.CreateTreeNode();
+        tanNode.AddSubtree(node);
+        return tanNode;
+      }
+    }
+
+    private static ISymbolicExpressionTreeNode MakeCosine(ISymbolicExpressionTreeNode node) {
+      if (IsConstant(node)) {
+        var constT = node as ConstantTreeNode;
+        return MakeConstant(Math.Cos(constT.Value));
+      } else if (IsFactor(node)) {
+        var factor = node as FactorVariableTreeNode;
+        return MakeFactor(factor.Symbol, factor.VariableName, factor.Weights.Select(Math.Cos));
+      } else if (IsBinFactor(node)) {
+        var binFactor = node as BinaryFactorVariableTreeNode;
+        // cos(0) = 1 see similar case for Exp(binfactor)
+        return MakeSum(MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Cos(binFactor.Weight) - 1),
+          MakeConstant(1.0));
+      } else {
+        var cosNode = cosineSymbol.CreateTreeNode();
+        cosNode.AddSubtree(node);
+        return cosNode;
+      }
+    }
+
+    private static ISymbolicExpressionTreeNode MakeExp(ISymbolicExpressionTreeNode node) {
+      if (IsConstant(node)) {
+        var constT = node as ConstantTreeNode;
+        return MakeConstant(Math.Exp(constT.Value));
+      } else if (IsFactor(node)) {
+        var factNode = node as FactorVariableTreeNode;
+        return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => Math.Exp(w)));
+      } else if (IsBinFactor(node)) {
+        // exp( binfactor w val=a) = if(val=a) exp(w) else exp(0) = binfactor( (exp(w) - 1) val a) + 1
+        var binFactor = node as BinaryFactorVariableTreeNode;
+        return
+          MakeSum(MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Exp(binFactor.Weight) - 1), MakeConstant(1.0));
+      } else if (IsLog(node)) {
+        return node.GetSubtree(0);
+      } else if (IsAddition(node)) {
+        return node.Subtrees.Select(s => MakeExp(s)).Aggregate((s, t) => MakeProduct(s, t));
+      } else if (IsSubtraction(node)) {
+        return node.Subtrees.Select(s => MakeExp(s)).Aggregate((s, t) => MakeProduct(s, Negate(t)));
+      } else {
+        var expNode = expSymbol.CreateTreeNode();
+        expNode.AddSubtree(node);
+        return expNode;
+      }
+    }
+    private static ISymbolicExpressionTreeNode MakeLog(ISymbolicExpressionTreeNode node) {
+      if (IsConstant(node)) {
+        var constT = node as ConstantTreeNode;
+        return MakeConstant(Math.Log(constT.Value));
+      } else if (IsFactor(node)) {
+        var factNode = node as FactorVariableTreeNode;
+        return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => Math.Log(w)));
+      } else if (IsExp(node)) {
+        return node.GetSubtree(0);
+      } else if (IsSquareRoot(node)) {
+        return MakeFraction(MakeLog(node.GetSubtree(0)), MakeConstant(2.0));
+      } else {
+        var logNode = logSymbol.CreateTreeNode();
+        logNode.AddSubtree(node);
+        return logNode;
+      }
+    }
+
+    private static ISymbolicExpressionTreeNode MakeSquare(ISymbolicExpressionTreeNode node) {
+      if (IsConstant(node)) {
+        var constT = node as ConstantTreeNode;
+        return MakeConstant(constT.Value * constT.Value);
+      } else if (IsFactor(node)) {
+        var factNode = node as FactorVariableTreeNode;
+        return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => w * w));
+      } else if (IsBinFactor(node)) {
+        var binFactor = node as BinaryFactorVariableTreeNode;
+        return MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, binFactor.Weight * binFactor.Weight);
+      } else if (IsSquareRoot(node)) {
+        return node.GetSubtree(0);
+      } else {
+        var sqrNode = sqrSymbol.CreateTreeNode();
+        sqrNode.AddSubtree(node);
+        return sqrNode;
+      }
+    }
+
+    private static ISymbolicExpressionTreeNode MakeSquareRoot(ISymbolicExpressionTreeNode node) {
+      if (IsConstant(node)) {
+        var constT = node as ConstantTreeNode;
+        return MakeConstant(Math.Sqrt(constT.Value));
+      } else if (IsFactor(node)) {
+        var factNode = node as FactorVariableTreeNode;
+        return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => Math.Sqrt(w)));
+      } else if (IsBinFactor(node)) {
+        var binFactor = node as BinaryFactorVariableTreeNode;
+        return MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Sqrt(binFactor.Weight));
+      } else if (IsSquare(node)) {
+        return node.GetSubtree(0);
+      } else {
+        var sqrtNode = sqrtSymbol.CreateTreeNode();
+        sqrtNode.AddSubtree(node);
+        return sqrtNode;
+      }
+    }
+
+    private static ISymbolicExpressionTreeNode MakeRoot(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) {
+      if (IsConstant(a) && IsConstant(b)) {
+        var constA = a as ConstantTreeNode;
+        var constB = b as ConstantTreeNode;
+        return MakeConstant(Math.Pow(constA.Value, 1.0 / Math.Round(constB.Value)));
+      } else if (IsFactor(a) && IsConstant(b)) {
+        var factNode = a as FactorVariableTreeNode;
+        var constNode = b as ConstantTreeNode;
+        return MakeFactor(factNode.Symbol, factNode.VariableName,
+          factNode.Weights.Select(w => Math.Pow(w, 1.0 / Math.Round(constNode.Value))));
+      } else if (IsBinFactor(a) && IsConstant(b)) {
+        var binFactor = a as BinaryFactorVariableTreeNode;
+        var constNode = b as ConstantTreeNode;
+        return MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Pow(binFactor.Weight, 1.0 / Math.Round(constNode.Value)));
+      } else if (IsConstant(a) && IsFactor(b)) {
+        var constNode = a as ConstantTreeNode;
+        var factNode = b as FactorVariableTreeNode;
+        return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => Math.Pow(constNode.Value, 1.0 / Math.Round(w))));
+      } else if (IsConstant(a) && IsBinFactor(b)) {
+        var constNode = a as ConstantTreeNode;
+        var factNode = b as BinaryFactorVariableTreeNode;
+        return MakeBinFactor(factNode.Symbol, factNode.VariableName, factNode.VariableValue, Math.Pow(constNode.Value, 1.0 / Math.Round(factNode.Weight)));
+      } else if (IsFactor(a) && IsFactor(b) && AreSameTypeAndVariable(a, b)) {
+        var node0 = a as FactorVariableTreeNode;
+        var node1 = b as FactorVariableTreeNode;
+        return MakeFactor(node0.Symbol, node0.VariableName, node0.Weights.Zip(node1.Weights, (u, v) => Math.Pow(u, 1.0 / Math.Round(v))));
+      } else if (IsConstant(b)) {
+        var constB = b as ConstantTreeNode;
+        var constBValue = Math.Round(constB.Value);
+        if (constBValue.IsAlmost(1.0)) {
+          return a;
+        } else if (constBValue.IsAlmost(0.0)) {
+          return MakeConstant(1.0);
+        } else if (constBValue.IsAlmost(-1.0)) {
+          return MakeFraction(MakeConstant(1.0), a);
+        } else if (constBValue < 0) {
+          var rootNode = rootSymbol.CreateTreeNode();
+          rootNode.AddSubtree(a);
+          rootNode.AddSubtree(MakeConstant(-1.0 * constBValue));
+          return MakeFraction(MakeConstant(1.0), rootNode);
+        } else {
+          var rootNode = rootSymbol.CreateTreeNode();
+          rootNode.AddSubtree(a);
+          rootNode.AddSubtree(MakeConstant(constBValue));
+          return rootNode;
+        }
+      } else {
+        var rootNode = rootSymbol.CreateTreeNode();
+        rootNode.AddSubtree(a);
+        rootNode.AddSubtree(b);
+        return rootNode;
+      }
+    }
+
+
+    private static ISymbolicExpressionTreeNode MakePower(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) {
+      if (IsConstant(a) && IsConstant(b)) {
+        var constA = a as ConstantTreeNode;
+        var constB = b as ConstantTreeNode;
+        return MakeConstant(Math.Pow(constA.Value, Math.Round(constB.Value)));
+      } else if (IsFactor(a) && IsConstant(b)) {
+        var factNode = a as FactorVariableTreeNode;
+        var constNode = b as ConstantTreeNode;
+        return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => Math.Pow(w, Math.Round(constNode.Value))));
+      } else if (IsBinFactor(a) && IsConstant(b)) {
+        var binFactor = a as BinaryFactorVariableTreeNode;
+        var constNode = b as ConstantTreeNode;
+        return MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Pow(binFactor.Weight, Math.Round(constNode.Value)));
+      } else if (IsConstant(a) && IsFactor(b)) {
+        var constNode = a as ConstantTreeNode;
+        var factNode = b as FactorVariableTreeNode;
+        return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => Math.Pow(constNode.Value, Math.Round(w))));
+      } else if (IsConstant(a) && IsBinFactor(b)) {
+        var constNode = a as ConstantTreeNode;
+        var factNode = b as BinaryFactorVariableTreeNode;
+        return MakeBinFactor(factNode.Symbol, factNode.VariableName, factNode.VariableValue, Math.Pow(constNode.Value, Math.Round(factNode.Weight)));
+      } else if (IsFactor(a) && IsFactor(b) && AreSameTypeAndVariable(a, b)) {
+        var node0 = a as FactorVariableTreeNode;
+        var node1 = b as FactorVariableTreeNode;
+        return MakeFactor(node0.Symbol, node0.VariableName, node0.Weights.Zip(node1.Weights, (u, v) => Math.Pow(u, Math.Round(v))));
+      } else if (IsConstant(b)) {
+        var constB = b as ConstantTreeNode;
+        double exponent = Math.Round(constB.Value);
+        if (exponent.IsAlmost(0.0)) {
+          return MakeConstant(1.0);
+        } else if (exponent.IsAlmost(1.0)) {
+          return a;
+        } else if (exponent.IsAlmost(-1.0)) {
+          return MakeFraction(MakeConstant(1.0), a);
+        } else if (exponent < 0) {
+          var powNode = powSymbol.CreateTreeNode();
+          powNode.AddSubtree(a);
+          powNode.AddSubtree(MakeConstant(-1.0 * exponent));
+          return MakeFraction(MakeConstant(1.0), powNode);
+        } else {
+          var powNode = powSymbol.CreateTreeNode();
+          powNode.AddSubtree(a);
+          powNode.AddSubtree(MakeConstant(exponent));
+          return powNode;
+        }
+      } else {
+        var powNode = powSymbol.CreateTreeNode();
+        powNode.AddSubtree(a);
+        powNode.AddSubtree(b);
+        return powNode;
+      }
+    }
+
+
+    // MakeFraction, MakeProduct and MakeSum take two already simplified trees and create a new simplified tree
+    private static ISymbolicExpressionTreeNode MakeFraction(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) {
+      if (IsConstant(a) && IsConstant(b)) {
+        // fold constants
+        return MakeConstant(((ConstantTreeNode)a).Value / ((ConstantTreeNode)b).Value);
+      } else if ((IsConstant(a) && !((ConstantTreeNode)a).Value.IsAlmost(1.0))) {
+        return MakeFraction(MakeConstant(1.0), MakeProduct(b, Invert(a)));
+      } else if (IsVariableBase(a) && IsConstant(b)) {
+        // merge constant values into variable weights
+        var constB = ((ConstantTreeNode)b).Value;
+        ((VariableTreeNodeBase)a).Weight /= constB;
+        return a;
+      } else if (IsFactor(a) && IsConstant(b)) {
+        var factNode = a as FactorVariableTreeNode;
+        var constNode = b as ConstantTreeNode;
+        return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => w / constNode.Value));
+      } else if (IsBinFactor(a) && IsConstant(b)) {
+        var factNode = a as BinaryFactorVariableTreeNode;
+        var constNode = b as ConstantTreeNode;
+        return MakeBinFactor(factNode.Symbol, factNode.VariableName, factNode.VariableValue, factNode.Weight / constNode.Value);
+      } else if (IsFactor(a) && IsFactor(b) && AreSameTypeAndVariable(a, b)) {
+        var node0 = a as FactorVariableTreeNode;
+        var node1 = b as FactorVariableTreeNode;
+        return MakeFactor(node0.Symbol, node0.VariableName, node0.Weights.Zip(node1.Weights, (u, v) => u / v));
+      } else if (IsFactor(a) && IsBinFactor(b) && ((IVariableTreeNode)a).VariableName == ((IVariableTreeNode)b).VariableName) {
+        var node0 = a as FactorVariableTreeNode;
+        var node1 = b as BinaryFactorVariableTreeNode;
+        var varValues = node0.Symbol.GetVariableValues(node0.VariableName).ToArray();
+        var wi = Array.IndexOf(varValues, node1.VariableValue);
+        if (wi < 0) throw new ArgumentException();
+        var newWeighs = new double[varValues.Length];
+        node0.Weights.CopyTo(newWeighs, 0);
+        for (int i = 0; i < newWeighs.Length; i++)
+          if (wi == i) newWeighs[i] /= node1.Weight;
+          else newWeighs[i] /= 0.0;
+        return MakeFactor(node0.Symbol, node0.VariableName, newWeighs);
+      } else if (IsFactor(a)) {
+        return MakeFraction(MakeConstant(1.0), MakeProduct(b, Invert(a)));
+      } else if (IsVariableBase(a) && IsVariableBase(b) && AreSameTypeAndVariable(a, b) && !IsBinFactor(b)) {
+        // cancel variables (not allowed for bin factors because of division by zero)
+        var aVar = a as VariableTreeNode;
+        var bVar = b as VariableTreeNode;
+        return MakeConstant(aVar.Weight / bVar.Weight);
+      } else if (IsAddition(a) && IsConstant(b)) {
+        return a.Subtrees
+          .Select(x => GetSimplifiedTree(x))
+          .Select(x => MakeFraction(x, GetSimplifiedTree(b)))
+          .Aggregate((c, d) => MakeSum(c, d));
+      } else if (IsMultiplication(a) && IsConstant(b)) {
+        return MakeProduct(a, Invert(b));
+      } else if (IsDivision(a) && IsConstant(b)) {
+        // (a1 / a2) / c => (a1 / (a2 * c))
+        return MakeFraction(a.GetSubtree(0), MakeProduct(a.GetSubtree(1), b));
+      } else if (IsDivision(a) && IsDivision(b)) {
+        // (a1 / a2) / (b1 / b2) => 
+        return MakeFraction(MakeProduct(a.GetSubtree(0), b.GetSubtree(1)), MakeProduct(a.GetSubtree(1), b.GetSubtree(0)));
+      } else if (IsDivision(a)) {
+        // (a1 / a2) / b => (a1 / (a2 * b))
+        return MakeFraction(a.GetSubtree(0), MakeProduct(a.GetSubtree(1), b));
+      } else if (IsDivision(b)) {
+        // a / (b1 / b2) => (a * b2) / b1
+        return MakeFraction(MakeProduct(a, b.GetSubtree(1)), b.GetSubtree(0));
+      } else {
+        var div = divSymbol.CreateTreeNode();
+        div.AddSubtree(a);
+        div.AddSubtree(b);
+        return div;
+      }
+    }
+
+    private static ISymbolicExpressionTreeNode MakeSum(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) {
+      if (IsConstant(a) && IsConstant(b)) {
+        // fold constants
+        ((ConstantTreeNode)a).Value += ((ConstantTreeNode)b).Value;
+        return a;
+      } else if (IsConstant(a)) {
+        // c + x => x + c
+        // b is not constant => make sure constant is on the right
+        return MakeSum(b, a);
+      } else if (IsConstant(b) && ((ConstantTreeNode)b).Value.IsAlmost(0.0)) {
+        // x + 0 => x
+        return a;
+      } else if (IsFactor(a) && IsConstant(b)) {
+        var factNode = a as FactorVariableTreeNode;
+        var constNode = b as ConstantTreeNode;
+        return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select((w) => w + constNode.Value));
+      } else if (IsFactor(a) && IsFactor(b) && AreSameTypeAndVariable(a, b)) {
+        var node0 = a as FactorVariableTreeNode;
+        var node1 = b as FactorVariableTreeNode;
+        return MakeFactor(node0.Symbol, node0.VariableName, node0.Weights.Zip(node1.Weights, (u, v) => u + v));
+      } else if (IsBinFactor(a) && IsFactor(b)) {
+        return MakeSum(b, a);
+      } else if (IsFactor(a) && IsBinFactor(b) &&
+        ((IVariableTreeNode)a).VariableName == ((IVariableTreeNode)b).VariableName) {
+        var node0 = a as FactorVariableTreeNode;
+        var node1 = b as BinaryFactorVariableTreeNode;
+        var varValues = node0.Symbol.GetVariableValues(node0.VariableName).ToArray();
+        var wi = Array.IndexOf(varValues, node1.VariableValue);
+        if (wi < 0) throw new ArgumentException();
+        var newWeighs = new double[varValues.Length];
+        node0.Weights.CopyTo(newWeighs, 0);
+        newWeighs[wi] += node1.Weight;
+        return MakeFactor(node0.Symbol, node0.VariableName, newWeighs);
+      } else if (IsAddition(a) && IsAddition(b)) {
+        // merge additions
+        var add = addSymbol.CreateTreeNode();
+        // add all sub trees except for the last
+        for (int i = 0; i < a.Subtrees.Count() - 1; i++) add.AddSubtree(a.GetSubtree(i));
+        for (int i = 0; i < b.Subtrees.Count() - 1; i++) add.AddSubtree(b.GetSubtree(i));
+        if (IsConstant(a.Subtrees.Last()) && IsConstant(b.Subtrees.Last())) {
+          add.AddSubtree(MakeSum(a.Subtrees.Last(), b.Subtrees.Last()));
+        } else if (IsConstant(a.Subtrees.Last())) {
+          add.AddSubtree(b.Subtrees.Last());
+          add.AddSubtree(a.Subtrees.Last());
+        } else {
+          add.AddSubtree(a.Subtrees.Last());
+          add.AddSubtree(b.Subtrees.Last());
+        }
+        MergeVariablesInSum(add);
+        if (add.Subtrees.Count() == 1) {
+          return add.GetSubtree(0);
+        } else {
+          return add;
+        }
+      } else if (IsAddition(b)) {
+        return MakeSum(b, a);
+      } else if (IsAddition(a) && IsConstant(b)) {
+        // a is an addition and b is a constant => append b to a and make sure the constants are merged
+        var add = addSymbol.CreateTreeNode();
+        // add all sub trees except for the last
+        for (int i = 0; i < a.Subtrees.Count() - 1; i++) add.AddSubtree(a.GetSubtree(i));
+        if (IsConstant(a.Subtrees.Last()))
+          add.AddSubtree(MakeSum(a.Subtrees.Last(), b));
+        else {
+          add.AddSubtree(a.Subtrees.Last());
+          add.AddSubtree(b);
+        }
+        return add;
+      } else if (IsAddition(a)) {
+        // a is already an addition => append b
+        var add = addSymbol.CreateTreeNode();
+        add.AddSubtree(b);
+        foreach (var subtree in a.Subtrees) {
+          add.AddSubtree(subtree);
+        }
+        MergeVariablesInSum(add);
+        if (add.Subtrees.Count() == 1) {
+          return add.GetSubtree(0);
+        } else {
+          return add;
+        }
+      } else {
+        var add = addSymbol.CreateTreeNode();
+        add.AddSubtree(a);
+        add.AddSubtree(b);
+        MergeVariablesInSum(add);
+        if (add.Subtrees.Count() == 1) {
+          return add.GetSubtree(0);
+        } else {
+          return add;
+        }
+      }
+    }
+
+    // makes sure variable symbols in sums are combined
+    private static void MergeVariablesInSum(ISymbolicExpressionTreeNode sum) {
+      var subtrees = new List<ISymbolicExpressionTreeNode>(sum.Subtrees);
+      while (sum.Subtrees.Any()) sum.RemoveSubtree(0);
+      var groupedVarNodes = from node in subtrees.OfType<IVariableTreeNode>()
+                            where node.SubtreeCount == 0
+                            group node by GroupId(node) into g
+                            select g;
+      var constant = (from node in subtrees.OfType<ConstantTreeNode>()
+                      select node.Value).DefaultIfEmpty(0.0).Sum();
+      var unchangedSubtrees = subtrees.Where(t => t.SubtreeCount > 0 || !(t is IVariableTreeNode) && !(t is ConstantTreeNode));
+
+      foreach (var variableNodeGroup in groupedVarNodes) {
+        var firstNode = variableNodeGroup.First();
+        if (firstNode is VariableTreeNodeBase) {
+          var representative = firstNode as VariableTreeNodeBase;
+          var weightSum = variableNodeGroup.Cast<VariableTreeNodeBase>().Select(t => t.Weight).Sum();
+          representative.Weight = weightSum;
+          sum.AddSubtree(representative);
+        } else if (firstNode is FactorVariableTreeNode) {
+          var representative = firstNode as FactorVariableTreeNode;
+          foreach (var node in variableNodeGroup.Skip(1).Cast<FactorVariableTreeNode>()) {
+            for (int j = 0; j < representative.Weights.Length; j++) {
+              representative.Weights[j] += node.Weights[j];
+            }
+          }
+          sum.AddSubtree(representative);
+        }
+      }
+      foreach (var unchangedSubtree in unchangedSubtrees)
+        sum.AddSubtree(unchangedSubtree);
+      if (!constant.IsAlmost(0.0)) {
+        sum.AddSubtree(MakeConstant(constant));
+      }
+    }
+
+    // nodes referencing variables can be grouped if they have
+    private static string GroupId(IVariableTreeNode node) {
+      var binaryFactorNode = node as BinaryFactorVariableTreeNode;
+      var factorNode = node as FactorVariableTreeNode;
+      var variableNode = node as VariableTreeNode;
+      var laggedVarNode = node as LaggedVariableTreeNode;
+      if (variableNode != null) {
+        return "var " + variableNode.VariableName;
+      } else if (binaryFactorNode != null) {
+        return "binfactor " + binaryFactorNode.VariableName + " " + binaryFactorNode.VariableValue;
+      } else if (factorNode != null) {
+        return "factor " + factorNode.VariableName;
+      } else if (laggedVarNode != null) {
+        return "lagged " + laggedVarNode.VariableName + " " + laggedVarNode.Lag;
+      } else {
+        throw new NotSupportedException();
+      }
+    }
+
+
+    private static ISymbolicExpressionTreeNode MakeProduct(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) {
+      if (IsConstant(a) && IsConstant(b)) {
+        // fold constants
+        return MakeConstant(((ConstantTreeNode)a).Value * ((ConstantTreeNode)b).Value);
+      } else if (IsConstant(a)) {
+        // a * $ => $ * a
+        return MakeProduct(b, a);
+      } else if (IsFactor(a) && IsFactor(b) && AreSameTypeAndVariable(a, b)) {
+        var node0 = a as FactorVariableTreeNode;
+        var node1 = b as FactorVariableTreeNode;
+        return MakeFactor(node0.Symbol, node0.VariableName, node0.Weights.Zip(node1.Weights, (u, v) => u * v));
+      } else if (IsBinFactor(a) && IsBinFactor(b) && AreSameTypeAndVariable(a, b)) {
+        var node0 = a as BinaryFactorVariableTreeNode;
+        var node1 = b as BinaryFactorVariableTreeNode;
+        return MakeBinFactor(node0.Symbol, node0.VariableName, node0.VariableValue, node0.Weight * node1.Weight);
+      } else if (IsFactor(a) && IsConstant(b)) {
+        var node0 = a as FactorVariableTreeNode;
+        var node1 = b as ConstantTreeNode;
+        return MakeFactor(node0.Symbol, node0.VariableName, node0.Weights.Select(w => w * node1.Value));
+      } else if (IsBinFactor(a) && IsConstant(b)) {
+        var node0 = a as BinaryFactorVariableTreeNode;
+        var node1 = b as ConstantTreeNode;
+        return MakeBinFactor(node0.Symbol, node0.VariableName, node0.VariableValue, node0.Weight * node1.Value);
+      } else if (IsBinFactor(a) && IsFactor(b)) {
+        return MakeProduct(b, a);
+      } else if (IsFactor(a) && IsBinFactor(b) &&
+        ((IVariableTreeNode)a).VariableName == ((IVariableTreeNode)b).VariableName) {
+        var node0 = a as FactorVariableTreeNode;
+        var node1 = b as BinaryFactorVariableTreeNode;
+        var varValues = node0.Symbol.GetVariableValues(node0.VariableName).ToArray();
+        var wi = Array.IndexOf(varValues, node1.VariableValue);
+        if (wi < 0) throw new ArgumentException();
+        return MakeBinFactor(node1.Symbol, node1.VariableName, node1.VariableValue, node1.Weight * node0.Weights[wi]);
+      } else if (IsConstant(b) && ((ConstantTreeNode)b).Value.IsAlmost(1.0)) {
+        // $ * 1.0 => $
+        return a;
+      } else if (IsConstant(b) && IsVariableBase(a)) {
+        // multiply constants into variables weights
+        ((VariableTreeNodeBase)a).Weight *= ((ConstantTreeNode)b).Value;
+        return a;
+      } else if (IsConstant(b) && IsAddition(a) ||
+          IsFactor(b) && IsAddition(a) ||
+          IsBinFactor(b) && IsAddition(a)) {
+        // multiply constants into additions
+        return a.Subtrees.Select(x => MakeProduct(GetSimplifiedTree(x), GetSimplifiedTree(b))).Aggregate((c, d) => MakeSum(c, d));
+      } else if (IsDivision(a) && IsDivision(b)) {
+        // (a1 / a2) * (b1 / b2) => (a1 * b1) / (a2 * b2)
+        return MakeFraction(MakeProduct(a.GetSubtree(0), b.GetSubtree(0)), MakeProduct(a.GetSubtree(1), b.GetSubtree(1)));
+      } else if (IsDivision(a)) {
+        // (a1 / a2) * b => (a1 * b) / a2
+        return MakeFraction(MakeProduct(a.GetSubtree(0), b), a.GetSubtree(1));
+      } else if (IsDivision(b)) {
+        // a * (b1 / b2) => (b1 * a) / b2
+        return MakeFraction(MakeProduct(b.GetSubtree(0), a), b.GetSubtree(1));
+      } else if (IsMultiplication(a) && IsMultiplication(b)) {
+        // merge multiplications (make sure constants are merged)
+        var mul = mulSymbol.CreateTreeNode();
+        for (int i = 0; i < a.Subtrees.Count(); i++) mul.AddSubtree(a.GetSubtree(i));
+        for (int i = 0; i < b.Subtrees.Count(); i++) mul.AddSubtree(b.GetSubtree(i));
+        MergeVariablesAndConstantsInProduct(mul);
+        return mul;
+      } else if (IsMultiplication(b)) {
+        return MakeProduct(b, a);
+      } else if (IsMultiplication(a)) {
+        // a is already an multiplication => append b
+        a.AddSubtree(GetSimplifiedTree(b));
+        MergeVariablesAndConstantsInProduct(a);
+        return a;
+      } else {
+        var mul = mulSymbol.CreateTreeNode();
+        mul.AddSubtree(a);
+        mul.AddSubtree(b);
+        MergeVariablesAndConstantsInProduct(mul);
+        return mul;
+      }
+    }
+
+    #endregion
+
+    #region helper functions
+
+    private static 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 static 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 static bool AreSameTypeAndVariable(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) {
+      return GroupId((IVariableTreeNode)a) == GroupId((IVariableTreeNode)b);
+    }
+
+    // helper to combine the constant factors in products and to combine variables (powers of 2, 3...)
+    private static void MergeVariablesAndConstantsInProduct(ISymbolicExpressionTreeNode prod) {
+      var subtrees = new List<ISymbolicExpressionTreeNode>(prod.Subtrees);
+      while (prod.Subtrees.Any()) prod.RemoveSubtree(0);
+      var groupedVarNodes = from node in subtrees.OfType<IVariableTreeNode>()
+                            where node.SubtreeCount == 0
+                            group node by GroupId(node) into g
+                            orderby g.Count()
+                            select g;
+      var constantProduct = (from node in subtrees.OfType<VariableTreeNodeBase>()
+                             select node.Weight)
+        .Concat(from node in subtrees.OfType<ConstantTreeNode>()
+                select node.Value)
+        .DefaultIfEmpty(1.0)
+        .Aggregate((c1, c2) => c1 * c2);
+
+      var unchangedSubtrees = from tree in subtrees
+                              where tree.SubtreeCount > 0 || !(tree is IVariableTreeNode) && !(tree is ConstantTreeNode)
+                              select tree;
+
+      foreach (var variableNodeGroup in groupedVarNodes) {
+        var firstNode = variableNodeGroup.First();
+        if (firstNode is VariableTreeNodeBase) {
+          var representative = (VariableTreeNodeBase)firstNode;
+          representative.Weight = 1.0;
+          if (variableNodeGroup.Count() > 1) {
+            var poly = mulSymbol.CreateTreeNode();
+            for (int p = 0; p < variableNodeGroup.Count(); p++) {
+              poly.AddSubtree((ISymbolicExpressionTreeNode)representative.Clone());
+            }
+            prod.AddSubtree(poly);
+          } else {
+            prod.AddSubtree(representative);
+          }
+        } else if (firstNode is FactorVariableTreeNode) {
+          var representative = (FactorVariableTreeNode)firstNode;
+          foreach (var node in variableNodeGroup.Skip(1).Cast<FactorVariableTreeNode>()) {
+            for (int j = 0; j < representative.Weights.Length; j++) {
+              representative.Weights[j] *= node.Weights[j];
+            }
+          }
+          for (int j = 0; j < representative.Weights.Length; j++) {
+            representative.Weights[j] *= constantProduct;
+          }
+          constantProduct = 1.0;
+          // if the product already contains a factor it is not necessary to multiply a constant below
+          prod.AddSubtree(representative);
+        }
+      }
+
+      foreach (var unchangedSubtree in unchangedSubtrees)
+        prod.AddSubtree(unchangedSubtree);
+
+      if (!constantProduct.IsAlmost(1.0)) {
+        prod.AddSubtree(MakeConstant(constantProduct));
+      }
+    }
+
+
+    /// <summary>
+    /// x => x * -1
+    /// Is only used in cases where it is not necessary to create new tree nodes. Manipulates x directly.
+    /// </summary>
+    /// <param name="x"></param>
+    /// <returns>-x</returns>
+    private static ISymbolicExpressionTreeNode Negate(ISymbolicExpressionTreeNode x) {
+      if (IsConstant(x)) {
+        ((ConstantTreeNode)x).Value *= -1;
+      } else if (IsVariableBase(x)) {
+        var variableTree = (VariableTreeNodeBase)x;
+        variableTree.Weight *= -1.0;
+      } else if (IsFactor(x)) {
+        var factorNode = (FactorVariableTreeNode)x;
+        for (int i = 0; i < factorNode.Weights.Length; i++) factorNode.Weights[i] *= -1;
+      } else if (IsBinFactor(x)) {
+        var factorNode = (BinaryFactorVariableTreeNode)x;
+        factorNode.Weight *= -1;
+      } else if (IsAddition(x)) {
+        // (x0 + x1 + .. + xn) * -1 => (-x0 + -x1 + .. + -xn)        
+        var subtrees = new List<ISymbolicExpressionTreeNode>(x.Subtrees);
+        while (x.Subtrees.Any()) x.RemoveSubtree(0);
+        foreach (var subtree in subtrees) {
+          x.AddSubtree(Negate(subtree));
+        }
+      } else if (IsMultiplication(x) || IsDivision(x)) {
+        // x0 * x1 * .. * xn * -1 => x0 * x1 * .. * -xn
+        var lastSubTree = x.Subtrees.Last();
+        x.RemoveSubtree(x.SubtreeCount - 1);
+        x.AddSubtree(Negate(lastSubTree)); // last is maybe a constant, prefer to negate the constant
+      } else {
+        // any other function
+        return MakeProduct(x, MakeConstant(-1));
+      }
+      return x;
+    }
+
+    /// <summary>
+    /// x => 1/x
+    /// Must create new tree nodes
+    /// </summary>
+    /// <param name="x"></param>
+    /// <returns></returns>
+    private static ISymbolicExpressionTreeNode Invert(ISymbolicExpressionTreeNode x) {
+      if (IsConstant(x)) {
+        return MakeConstant(1.0 / ((ConstantTreeNode)x).Value);
+      } else if (IsFactor(x)) {
+        var factorNode = (FactorVariableTreeNode)x;
+        return MakeFactor(factorNode.Symbol, factorNode.VariableName, factorNode.Weights.Select(w => 1.0 / w));
+      } else if (IsDivision(x)) {
+        return MakeFraction(x.GetSubtree(1), x.GetSubtree(0));
+      } else {
+        // any other function
+        return MakeFraction(MakeConstant(1), x);
+      }
+    }
+
+    private static ISymbolicExpressionTreeNode MakeConstant(double value) {
+      ConstantTreeNode constantTreeNode = (ConstantTreeNode)(constSymbol.CreateTreeNode());
+      constantTreeNode.Value = value;
+      return constantTreeNode;
+    }
+
+    private static ISymbolicExpressionTreeNode MakeFactor(FactorVariable sy, string variableName, IEnumerable<double> weights) {
+      var tree = (FactorVariableTreeNode)sy.CreateTreeNode();
+      tree.VariableName = variableName;
+      tree.Weights = weights.ToArray();
+      return tree;
+    }
+    private static ISymbolicExpressionTreeNode MakeBinFactor(BinaryFactorVariable sy, string variableName, string variableValue, double weight) {
+      var tree = (BinaryFactorVariableTreeNode)sy.CreateTreeNode();
+      tree.VariableName = variableName;
+      tree.VariableValue = variableValue;
+      tree.Weight = weight;
+      return tree;
+    }
+
+
+    #endregion
+  }
+}
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Converters/TreeToAutoDiffTermConverter.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Converters/TreeToAutoDiffTermConverter.cs	(revision 15973)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Converters/TreeToAutoDiffTermConverter.cs	(revision 15973)
@@ -0,0 +1,327 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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 System.Runtime.Serialization;
+using AutoDiff;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
+  public class TreeToAutoDiffTermConverter {
+    public delegate double ParametricFunction(double[] vars, double[] @params);
+
+    public delegate Tuple<double[], double> ParametricFunctionGradient(double[] vars, double[] @params);
+
+    #region helper class
+    public class DataForVariable {
+      public readonly string variableName;
+      public readonly string variableValue; // for factor vars
+      public readonly int lag;
+
+      public DataForVariable(string varName, string varValue, int lag) {
+        this.variableName = varName;
+        this.variableValue = varValue;
+        this.lag = lag;
+      }
+
+      public override bool Equals(object obj) {
+        var other = obj as DataForVariable;
+        if (other == null) return false;
+        return other.variableName.Equals(this.variableName) &&
+               other.variableValue.Equals(this.variableValue) &&
+               other.lag == this.lag;
+      }
+
+      public override int GetHashCode() {
+        return variableName.GetHashCode() ^ variableValue.GetHashCode() ^ lag;
+      }
+    }
+    #endregion
+
+    #region derivations of functions
+    // create function factory for arctangent
+    private static readonly Func<Term, UnaryFunc> arctan = UnaryFunc.Factory(
+      eval: Math.Atan,
+      diff: x => 1 / (1 + x * x));
+
+    private static readonly Func<Term, UnaryFunc> sin = UnaryFunc.Factory(
+      eval: Math.Sin,
+      diff: Math.Cos);
+
+    private static readonly Func<Term, UnaryFunc> cos = UnaryFunc.Factory(
+      eval: Math.Cos,
+      diff: x => -Math.Sin(x));
+
+    private static readonly Func<Term, UnaryFunc> tan = UnaryFunc.Factory(
+      eval: Math.Tan,
+      diff: x => 1 + Math.Tan(x) * Math.Tan(x));
+
+    private static readonly Func<Term, UnaryFunc> erf = UnaryFunc.Factory(
+      eval: alglib.errorfunction,
+      diff: x => 2.0 * Math.Exp(-(x * x)) / Math.Sqrt(Math.PI));
+
+    private static readonly Func<Term, UnaryFunc> norm = UnaryFunc.Factory(
+      eval: alglib.normaldistribution,
+      diff: x => -(Math.Exp(-(x * x)) * Math.Sqrt(Math.Exp(x * x)) * x) / Math.Sqrt(2 * Math.PI));
+
+    #endregion
+
+    public static bool TryConvertToAutoDiff(ISymbolicExpressionTree tree, bool makeVariableWeightsVariable, bool addLinearScalingTerms,
+      out List<DataForVariable> parameters, out double[] initialConstants,
+      out ParametricFunction func,
+      out ParametricFunctionGradient func_grad) {
+
+      // use a transformator object which holds the state (variable list, parameter list, ...) for recursive transformation of the tree
+      var transformator = new TreeToAutoDiffTermConverter(makeVariableWeightsVariable, addLinearScalingTerms);
+      AutoDiff.Term term;
+      try {
+        term = transformator.ConvertToAutoDiff(tree.Root.GetSubtree(0));
+        var parameterEntries = transformator.parameters.ToArray(); // guarantee same order for keys and values
+        var compiledTerm = term.Compile(transformator.variables.ToArray(),
+          parameterEntries.Select(kvp => kvp.Value).ToArray());
+        parameters = new List<DataForVariable>(parameterEntries.Select(kvp => kvp.Key));
+        initialConstants = transformator.initialConstants.ToArray();
+        func = (vars, @params) => compiledTerm.Evaluate(vars, @params);
+        func_grad = (vars, @params) => compiledTerm.Differentiate(vars, @params);
+        return true;
+      } catch (ConversionException) {
+        func = null;
+        func_grad = null;
+        parameters = null;
+        initialConstants = null;
+      }
+      return false;
+    }
+
+    // state for recursive transformation of trees 
+    private readonly
+    List<double> initialConstants;
+    private readonly Dictionary<DataForVariable, AutoDiff.Variable> parameters;
+    private readonly List<AutoDiff.Variable> variables;
+    private readonly bool makeVariableWeightsVariable;
+    private readonly bool addLinearScalingTerms;
+
+    private TreeToAutoDiffTermConverter(bool makeVariableWeightsVariable, bool addLinearScalingTerms) {
+      this.makeVariableWeightsVariable = makeVariableWeightsVariable;
+      this.addLinearScalingTerms = addLinearScalingTerms;
+      this.initialConstants = new List<double>();
+      this.parameters = new Dictionary<DataForVariable, AutoDiff.Variable>();
+      this.variables = new List<AutoDiff.Variable>();
+    }
+
+    private AutoDiff.Term ConvertToAutoDiff(ISymbolicExpressionTreeNode node) {
+      if (node.Symbol is Constant) {
+        initialConstants.Add(((ConstantTreeNode)node).Value);
+        var var = new AutoDiff.Variable();
+        variables.Add(var);
+        return var;
+      }
+      if (node.Symbol is Variable || node.Symbol is BinaryFactorVariable) {
+        var varNode = node as VariableTreeNodeBase;
+        var factorVarNode = node as BinaryFactorVariableTreeNode;
+        // factor variable values are only 0 or 1 and set in x accordingly
+        var varValue = factorVarNode != null ? factorVarNode.VariableValue : string.Empty;
+        var par = FindOrCreateParameter(parameters, varNode.VariableName, varValue);
+
+        if (makeVariableWeightsVariable) {
+          initialConstants.Add(varNode.Weight);
+          var w = new AutoDiff.Variable();
+          variables.Add(w);
+          return AutoDiff.TermBuilder.Product(w, par);
+        } else {
+          return varNode.Weight * par;
+        }
+      }
+      if (node.Symbol is FactorVariable) {
+        var factorVarNode = node as FactorVariableTreeNode;
+        var products = new List<Term>();
+        foreach (var variableValue in factorVarNode.Symbol.GetVariableValues(factorVarNode.VariableName)) {
+          var par = FindOrCreateParameter(parameters, factorVarNode.VariableName, variableValue);
+
+          initialConstants.Add(factorVarNode.GetValue(variableValue));
+          var wVar = new AutoDiff.Variable();
+          variables.Add(wVar);
+
+          products.Add(AutoDiff.TermBuilder.Product(wVar, par));
+        }
+        return AutoDiff.TermBuilder.Sum(products);
+      }
+      if (node.Symbol is LaggedVariable) {
+        var varNode = node as LaggedVariableTreeNode;
+        var par = FindOrCreateParameter(parameters, varNode.VariableName, string.Empty, varNode.Lag);
+
+        if (makeVariableWeightsVariable) {
+          initialConstants.Add(varNode.Weight);
+          var w = new AutoDiff.Variable();
+          variables.Add(w);
+          return AutoDiff.TermBuilder.Product(w, par);
+        } else {
+          return varNode.Weight * par;
+        }
+      }
+      if (node.Symbol is Addition) {
+        List<AutoDiff.Term> terms = new List<Term>();
+        foreach (var subTree in node.Subtrees) {
+          terms.Add(ConvertToAutoDiff(subTree));
+        }
+        return AutoDiff.TermBuilder.Sum(terms);
+      }
+      if (node.Symbol is Subtraction) {
+        List<AutoDiff.Term> terms = new List<Term>();
+        for (int i = 0; i < node.SubtreeCount; i++) {
+          AutoDiff.Term t = ConvertToAutoDiff(node.GetSubtree(i));
+          if (i > 0) t = -t;
+          terms.Add(t);
+        }
+        if (terms.Count == 1) return -terms[0];
+        else return AutoDiff.TermBuilder.Sum(terms);
+      }
+      if (node.Symbol is Multiplication) {
+        List<AutoDiff.Term> terms = new List<Term>();
+        foreach (var subTree in node.Subtrees) {
+          terms.Add(ConvertToAutoDiff(subTree));
+        }
+        if (terms.Count == 1) return terms[0];
+        else return terms.Aggregate((a, b) => new AutoDiff.Product(a, b));
+      }
+      if (node.Symbol is Division) {
+        List<AutoDiff.Term> terms = new List<Term>();
+        foreach (var subTree in node.Subtrees) {
+          terms.Add(ConvertToAutoDiff(subTree));
+        }
+        if (terms.Count == 1) return 1.0 / terms[0];
+        else return terms.Aggregate((a, b) => new AutoDiff.Product(a, 1.0 / b));
+      }
+      if (node.Symbol is Logarithm) {
+        return AutoDiff.TermBuilder.Log(
+          ConvertToAutoDiff(node.GetSubtree(0)));
+      }
+      if (node.Symbol is Exponential) {
+        return AutoDiff.TermBuilder.Exp(
+          ConvertToAutoDiff(node.GetSubtree(0)));
+      }
+      if (node.Symbol is Square) {
+        return AutoDiff.TermBuilder.Power(
+          ConvertToAutoDiff(node.GetSubtree(0)), 2.0);
+      }
+      if (node.Symbol is SquareRoot) {
+        return AutoDiff.TermBuilder.Power(
+          ConvertToAutoDiff(node.GetSubtree(0)), 0.5);
+      }
+      if (node.Symbol is Sine) {
+        return sin(
+          ConvertToAutoDiff(node.GetSubtree(0)));
+      }
+      if (node.Symbol is Cosine) {
+        return cos(
+          ConvertToAutoDiff(node.GetSubtree(0)));
+      }
+      if (node.Symbol is Tangent) {
+        return tan(
+          ConvertToAutoDiff(node.GetSubtree(0)));
+      }
+      if (node.Symbol is Erf) {
+        return erf(
+          ConvertToAutoDiff(node.GetSubtree(0)));
+      }
+      if (node.Symbol is Norm) {
+        return norm(
+          ConvertToAutoDiff(node.GetSubtree(0)));
+      }
+      if (node.Symbol is StartSymbol) {
+        if (addLinearScalingTerms) {
+          // scaling variables α, β are given at the beginning of the parameter vector
+          var alpha = new AutoDiff.Variable();
+          var beta = new AutoDiff.Variable();
+          variables.Add(beta);
+          variables.Add(alpha);
+          var t = ConvertToAutoDiff(node.GetSubtree(0));
+          return t * alpha + beta;
+        } else return ConvertToAutoDiff(node.GetSubtree(0));
+      }
+      throw new ConversionException();
+    }
+
+
+    // for each factor variable value we need a parameter which represents a binary indicator for that variable & value combination
+    // each binary indicator is only necessary once. So we only create a parameter if this combination is not yet available
+    private static Term FindOrCreateParameter(Dictionary<DataForVariable, AutoDiff.Variable> parameters,
+      string varName, string varValue = "", int lag = 0) {
+      var data = new DataForVariable(varName, varValue, lag);
+
+      AutoDiff.Variable par = null;
+      if (!parameters.TryGetValue(data, out par)) {
+        // not found -> create new parameter and entries in names and values lists
+        par = new AutoDiff.Variable();
+        parameters.Add(data, par);
+      }
+      return par;
+    }
+
+    public static bool IsCompatible(ISymbolicExpressionTree tree) {
+      var containsUnknownSymbol = (
+        from n in tree.Root.GetSubtree(0).IterateNodesPrefix()
+        where
+          !(n.Symbol is Variable) &&
+          !(n.Symbol is BinaryFactorVariable) &&
+          !(n.Symbol is FactorVariable) &&
+          !(n.Symbol is LaggedVariable) &&
+          !(n.Symbol is Constant) &&
+          !(n.Symbol is Addition) &&
+          !(n.Symbol is Subtraction) &&
+          !(n.Symbol is Multiplication) &&
+          !(n.Symbol is Division) &&
+          !(n.Symbol is Logarithm) &&
+          !(n.Symbol is Exponential) &&
+          !(n.Symbol is SquareRoot) &&
+          !(n.Symbol is Square) &&
+          !(n.Symbol is Sine) &&
+          !(n.Symbol is Cosine) &&
+          !(n.Symbol is Tangent) &&
+          !(n.Symbol is Erf) &&
+          !(n.Symbol is Norm) &&
+          !(n.Symbol is StartSymbol)
+        select n).Any();
+      return !containsUnknownSymbol;
+    }
+    #region exception class
+    [Serializable]
+    public class ConversionException : Exception {
+
+      public ConversionException() {
+      }
+
+      public ConversionException(string message) : base(message) {
+      }
+
+      public ConversionException(string message, Exception inner) : base(message, inner) {
+      }
+
+      protected ConversionException(
+        SerializationInfo info,
+        StreamingContext context) : base(info, context) {
+      }
+    }
+    #endregion
+  }
+}
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Creators/MultiSymbolicDataAnalysisExpressionCreator.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Creators/MultiSymbolicDataAnalysisExpressionCreator.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Creators/MultiSymbolicDataAnalysisExpressionCreator.cs	(revision 15973)
@@ -1,5 +1,5 @@
 ﻿#region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Creators/SymbolicDataAnalysisExpressionFullTreeCreator.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Creators/SymbolicDataAnalysisExpressionFullTreeCreator.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Creators/SymbolicDataAnalysisExpressionFullTreeCreator.cs	(revision 15973)
@@ -1,5 +1,5 @@
 #region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Creators/SymbolicDataAnalysisExpressionGrowTreeCreator.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Creators/SymbolicDataAnalysisExpressionGrowTreeCreator.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Creators/SymbolicDataAnalysisExpressionGrowTreeCreator.cs	(revision 15973)
@@ -1,5 +1,5 @@
 #region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Creators/SymbolicDataAnalysisExpressionRampedHalfAndHalfTreeCreator.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Creators/SymbolicDataAnalysisExpressionRampedHalfAndHalfTreeCreator.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Creators/SymbolicDataAnalysisExpressionRampedHalfAndHalfTreeCreator.cs	(revision 15973)
@@ -1,5 +1,5 @@
 #region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Creators/SymbolicDataAnalysisExpressionTreeCreator.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Creators/SymbolicDataAnalysisExpressionTreeCreator.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Creators/SymbolicDataAnalysisExpressionTreeCreator.cs	(revision 15973)
@@ -1,5 +1,5 @@
 ﻿#region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Crossovers/MultiSymbolicDataAnalysisExpressionCrossover.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Crossovers/MultiSymbolicDataAnalysisExpressionCrossover.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Crossovers/MultiSymbolicDataAnalysisExpressionCrossover.cs	(revision 15973)
@@ -1,5 +1,5 @@
 ﻿#region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Crossovers/SymbolicDataAnalysisExpressionContextAwareCrossover.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Crossovers/SymbolicDataAnalysisExpressionContextAwareCrossover.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Crossovers/SymbolicDataAnalysisExpressionContextAwareCrossover.cs	(revision 15973)
@@ -1,5 +1,5 @@
 #region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Crossovers/SymbolicDataAnalysisExpressionCrossover.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Crossovers/SymbolicDataAnalysisExpressionCrossover.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Crossovers/SymbolicDataAnalysisExpressionCrossover.cs	(revision 15973)
@@ -1,5 +1,5 @@
 #region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Crossovers/SymbolicDataAnalysisExpressionDepthConstrainedCrossover.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Crossovers/SymbolicDataAnalysisExpressionDepthConstrainedCrossover.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Crossovers/SymbolicDataAnalysisExpressionDepthConstrainedCrossover.cs	(revision 15973)
@@ -1,5 +1,5 @@
 #region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Crossovers/SymbolicDataAnalysisExpressionDeterministicBestCrossover.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Crossovers/SymbolicDataAnalysisExpressionDeterministicBestCrossover.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Crossovers/SymbolicDataAnalysisExpressionDeterministicBestCrossover.cs	(revision 15973)
@@ -1,5 +1,5 @@
 #region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Crossovers/SymbolicDataAnalysisExpressionProbabilisticFunctionalCrossover.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Crossovers/SymbolicDataAnalysisExpressionProbabilisticFunctionalCrossover.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Crossovers/SymbolicDataAnalysisExpressionProbabilisticFunctionalCrossover.cs	(revision 15973)
@@ -1,5 +1,5 @@
 #region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Crossovers/SymbolicDataAnalysisExpressionSemanticSimilarityCrossover.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Crossovers/SymbolicDataAnalysisExpressionSemanticSimilarityCrossover.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Crossovers/SymbolicDataAnalysisExpressionSemanticSimilarityCrossover.cs	(revision 15973)
@@ -1,5 +1,5 @@
 #region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Evaluators/SymbolicDataAnalysisEvaluator.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Evaluators/SymbolicDataAnalysisEvaluator.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Evaluators/SymbolicDataAnalysisEvaluator.cs	(revision 15973)
@@ -1,5 +1,5 @@
 ﻿#region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
@@ -93,13 +93,13 @@
     public SymbolicDataAnalysisEvaluator()
       : base() {
-      Parameters.Add(new ValueLookupParameter<IRandom>(RandomParameterName, "The random generator to use."));
-      Parameters.Add(new LookupParameter<ISymbolicDataAnalysisExpressionTreeInterpreter>(SymbolicDataAnalysisTreeInterpreterParameterName, "The interpreter that should be used to calculate the output values of the symbolic data analysis tree."));
-      Parameters.Add(new LookupParameter<ISymbolicExpressionTree>(SymbolicExpressionTreeParameterName, "The symbolic data analysis solution encoded as a symbolic expression tree."));
-      Parameters.Add(new ValueLookupParameter<T>(ProblemDataParameterName, "The problem data on which the symbolic data analysis solution should be evaluated."));
-      Parameters.Add(new ValueLookupParameter<IntRange>(EvaluationPartitionParameterName, "The start index of the dataset partition on which the symbolic data analysis solution should be evaluated."));
-      Parameters.Add(new ValueLookupParameter<DoubleLimit>(EstimationLimitsParameterName, "The upper and lower limit that should be used as cut off value for the output values of symbolic data analysis trees."));
-      Parameters.Add(new ValueLookupParameter<PercentValue>(RelativeNumberOfEvaluatedSamplesParameterName, "The relative number of samples of the dataset partition, which should be randomly chosen for evaluation between the start and end index."));
-      Parameters.Add(new LookupParameter<BoolValue>(ApplyLinearScalingParameterName, "Flag that indicates if the individual should be linearly scaled before evaluating."));
-      Parameters.Add(new ValueLookupParameter<StringValue>(ValidRowIndicatorParameterName, "An indicator variable in the data set that specifies which rows should be evaluated (those for which the indicator <> 0) (optional)."));
+      Parameters.Add(new ValueLookupParameter<IRandom>(RandomParameterName, "The random generator to use.") { Hidden = true });
+      Parameters.Add(new LookupParameter<ISymbolicDataAnalysisExpressionTreeInterpreter>(SymbolicDataAnalysisTreeInterpreterParameterName, "The interpreter that should be used to calculate the output values of the symbolic data analysis tree.") { Hidden = true });
+      Parameters.Add(new LookupParameter<ISymbolicExpressionTree>(SymbolicExpressionTreeParameterName, "The symbolic data analysis solution encoded as a symbolic expression tree.") { Hidden = true });
+      Parameters.Add(new ValueLookupParameter<T>(ProblemDataParameterName, "The problem data on which the symbolic data analysis solution should be evaluated.") { Hidden = true });
+      Parameters.Add(new ValueLookupParameter<IntRange>(EvaluationPartitionParameterName, "The start index of the dataset partition on which the symbolic data analysis solution should be evaluated.") { Hidden = true });
+      Parameters.Add(new ValueLookupParameter<DoubleLimit>(EstimationLimitsParameterName, "The upper and lower limit that should be used as cut off value for the output values of symbolic data analysis trees.") { Hidden = true });
+      Parameters.Add(new ValueLookupParameter<PercentValue>(RelativeNumberOfEvaluatedSamplesParameterName, "The relative number of samples of the dataset partition, which should be randomly chosen for evaluation between the start and end index.") { Hidden = true });
+      Parameters.Add(new LookupParameter<BoolValue>(ApplyLinearScalingParameterName, "Flag that indicates if the individual should be linearly scaled before evaluating.") { Hidden = true });
+      Parameters.Add(new ValueLookupParameter<StringValue>(ValidRowIndicatorParameterName, "An indicator variable in the data set that specifies which rows should be evaluated (those for which the indicator <> 0) (optional).") { Hidden = true });
     }
 
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Evaluators/SymbolicDataAnalysisMultiObjectiveEvaluator.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Evaluators/SymbolicDataAnalysisMultiObjectiveEvaluator.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Evaluators/SymbolicDataAnalysisMultiObjectiveEvaluator.cs	(revision 15973)
@@ -1,5 +1,5 @@
 ﻿#region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Evaluators/SymbolicDataAnalysisSingleObjectiveEvaluator.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Evaluators/SymbolicDataAnalysisSingleObjectiveEvaluator.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Evaluators/SymbolicDataAnalysisSingleObjectiveEvaluator.cs	(revision 15973)
@@ -1,5 +1,5 @@
 ﻿#region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/InfixExpressionFormatter.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/InfixExpressionFormatter.cs	(revision 15973)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/InfixExpressionFormatter.cs	(revision 15973)
@@ -0,0 +1,192 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Globalization;
+using System.Linq;
+using System.Text;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
+  /// <summary>
+  /// Formats mathematical expressions in infix form. E.g. x1 * (3.0 * x2 + x3)
+  /// </summary>
+  [StorableClass]
+  [Item("Infix Symbolic Expression Tree Formatter", "A string formatter that converts symbolic expression trees to infix expressions.")]
+
+  public sealed class InfixExpressionFormatter : NamedItem, ISymbolicExpressionTreeStringFormatter {
+
+
+    [StorableConstructor]
+    private InfixExpressionFormatter(bool deserializing) : base(deserializing) { }
+    private InfixExpressionFormatter(InfixExpressionFormatter original, Cloner cloner) : base(original, cloner) { }
+    public InfixExpressionFormatter()
+      : base() {
+      Name = ItemName;
+      Description = ItemDescription;
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new InfixExpressionFormatter(this, cloner);
+    }
+
+    public string Format(ISymbolicExpressionTree symbolicExpressionTree) {
+      // skip root and start symbols
+      StringBuilder strBuilder = new StringBuilder();
+      FormatRecursively(symbolicExpressionTree.Root.GetSubtree(0).GetSubtree(0), strBuilder);
+      return strBuilder.ToString();
+    }
+
+    private void FormatRecursively(ISymbolicExpressionTreeNode node, StringBuilder strBuilder) {
+      if (node.SubtreeCount > 1) {
+        var token = GetToken(node.Symbol);
+        if (token == "+" || token == "-" || token == "OR" || token == "XOR") {
+          strBuilder.Append("(");
+          FormatRecursively(node.Subtrees.First(), strBuilder);
+
+          foreach (var subtree in node.Subtrees.Skip(1)) {
+            strBuilder.Append(" ").Append(token).Append(" ");
+            FormatRecursively(subtree, strBuilder);
+          }
+          strBuilder.Append(")");
+
+        } else if (token == "*" || token == "/" || token == "AND") {
+          strBuilder.Append("(");
+          FormatRecursively(node.Subtrees.First(), strBuilder);
+
+          foreach (var subtree in node.Subtrees.Skip(1)) {
+            strBuilder.Append(" ").Append(token).Append(" ");
+            FormatRecursively(subtree, strBuilder);
+          }
+          strBuilder.Append(")");
+        } else {
+          // function with multiple arguments
+          strBuilder.Append(token).Append("(");
+          FormatRecursively(node.Subtrees.First(), strBuilder);
+          foreach (var subtree in node.Subtrees.Skip(1)) {
+            strBuilder.Append(", ");
+            FormatRecursively(subtree, strBuilder);
+          }
+          strBuilder.Append(")");
+        }
+      } else if (node.SubtreeCount == 1) {
+        var token = GetToken(node.Symbol);
+        if (token == "-" || token == "NOT") {
+          strBuilder.Append("(").Append(token).Append("(");
+          FormatRecursively(node.GetSubtree(0), strBuilder);
+          strBuilder.Append("))");
+        } else if (token == "/") {
+          strBuilder.Append("1/");
+          FormatRecursively(node.GetSubtree(0), strBuilder);
+        } else if (token == "+" || token == "*") {
+          FormatRecursively(node.GetSubtree(0), strBuilder);
+        } else {
+          // function with only one argument
+          strBuilder.Append(token).Append("(");
+          FormatRecursively(node.GetSubtree(0), strBuilder);
+          strBuilder.Append(")");
+        }
+      } else {
+        // no subtrees
+        if (node.Symbol is LaggedVariable) {
+          var varNode = node as LaggedVariableTreeNode;
+          if (!varNode.Weight.IsAlmost(1.0)) {
+            strBuilder.Append("(");
+            strBuilder.AppendFormat(CultureInfo.InvariantCulture, "{0}", varNode.Weight);
+            strBuilder.Append("*");
+          }
+          strBuilder.Append("LAG(");
+          if (varNode.VariableName.Contains("'")) {
+            strBuilder.AppendFormat("\"{0}\"", varNode.VariableName);
+          } else {
+            strBuilder.AppendFormat("'{0}'", varNode.VariableName);
+          }
+          strBuilder.Append(", ")
+            .AppendFormat(CultureInfo.InvariantCulture, "{0}", varNode.Lag)
+            .Append(")");
+        } else if (node.Symbol is Variable) {
+          var varNode = node as VariableTreeNode;
+          if (!varNode.Weight.IsAlmost(1.0)) {
+            strBuilder.Append("(");
+            strBuilder.AppendFormat(CultureInfo.InvariantCulture, "{0}", varNode.Weight);
+            strBuilder.Append("*");
+          }
+          if (varNode.VariableName.Contains("'")) {
+            strBuilder.AppendFormat("\"{0}\"", varNode.VariableName);
+          } else {
+            strBuilder.AppendFormat("'{0}'", varNode.VariableName);
+          }
+          if (!varNode.Weight.IsAlmost(1.0)) {
+            strBuilder.Append(")");
+          }
+        } else if (node.Symbol is FactorVariable) {
+          var factorNode = node as FactorVariableTreeNode;
+          if (factorNode.VariableName.Contains("'")) {
+            strBuilder.AppendFormat("\"{0}\"", factorNode.VariableName);
+          } else {
+            strBuilder.AppendFormat("'{0}'", factorNode.VariableName);
+          }
+          strBuilder.AppendFormat("[{0}]",
+            string.Join(", ", factorNode.Weights.Select(w => w.ToString(CultureInfo.InvariantCulture))));
+        } else if (node.Symbol is BinaryFactorVariable) {
+          var factorNode = node as BinaryFactorVariableTreeNode;
+          if (!factorNode.Weight.IsAlmost(1.0)) {
+            strBuilder.Append("(");
+            strBuilder.AppendFormat(CultureInfo.InvariantCulture, "{0}", factorNode.Weight);
+            strBuilder.Append("*");
+          }
+          if (factorNode.VariableName.Contains("'")) {
+            strBuilder.AppendFormat("\"{0}\"", factorNode.VariableName);
+          } else {
+            strBuilder.AppendFormat("'{0}'", factorNode.VariableName);
+          }
+          strBuilder.Append(" = ");
+          if (factorNode.VariableValue.Contains("'")) {
+            strBuilder.AppendFormat("\"{0}\"", factorNode.VariableValue);
+          } else {
+            strBuilder.AppendFormat("'{0}'", factorNode.VariableValue);
+          }
+
+          if (!factorNode.Weight.IsAlmost(1.0)) {
+            strBuilder.Append(")");
+          }
+
+        } else if (node.Symbol is Constant) {
+          var constNode = node as ConstantTreeNode;
+          if (constNode.Value >= 0.0)
+            strBuilder.AppendFormat(CultureInfo.InvariantCulture, "{0}", constNode.Value);
+          else
+            strBuilder.AppendFormat(CultureInfo.InvariantCulture, "({0})", constNode.Value); // (-1
+        }
+      }
+    }
+
+    private string GetToken(ISymbol symbol) {
+      var tok = InfixExpressionParser.knownSymbols.GetBySecond(symbol).SingleOrDefault();
+      if (tok == null)
+        throw new ArgumentException(string.Format("Unknown symbol {0} found.", symbol.Name));
+      return tok;
+    }
+  }
+}
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/SymbolicDataAnalysisExpressionCSharpFormatter.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/SymbolicDataAnalysisExpressionCSharpFormatter.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/SymbolicDataAnalysisExpressionCSharpFormatter.cs	(revision 15973)
@@ -1,5 +1,5 @@
 ﻿#region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
@@ -25,4 +25,5 @@
 using System.Linq;
 using System.Text;
+using System.Text.RegularExpressions;
 using HeuristicLab.Common;
 using HeuristicLab.Core;
@@ -53,4 +54,42 @@
       GenerateFooter(strBuilder);
       return strBuilder.ToString();
+    }
+
+    private string VariableName2Identifier(string name) {     
+      /*
+       * identifier-start-character:
+       *    letter-character
+       *    _ (the underscore character U+005F)
+       *  identifier-part-characters:
+       *    identifier-part-character
+       *    identifier-part-characters   identifier-part-character
+       *  identifier-part-character:
+       *    letter-character
+       *    decimal-digit-character
+       *    connecting-character
+       *    combining-character
+       *    formatting-character
+       *  letter-character:
+       *    A Unicode character of classes Lu, Ll, Lt, Lm, Lo, or Nl 
+       *    A unicode-escape-sequence representing a character of classes Lu, Ll, Lt, Lm, Lo, or Nl
+       *  combining-character:
+       *    A Unicode character of classes Mn or Mc 
+       *    A unicode-escape-sequence representing a character of classes Mn or Mc
+       *  decimal-digit-character:
+       *    A Unicode character of the class Nd 
+       *    A unicode-escape-sequence representing a character of the class Nd
+       *  connecting-character:
+       *    A Unicode character of the class Pc 
+       *    A unicode-escape-sequence representing a character of the class Pc
+       *  formatting-character:
+       *    A Unicode character of the class Cf 
+       *    A unicode-escape-sequence representing a character of the class Cf
+       */
+
+      var invalidIdentifierStarts = new Regex(@"[^_\p{Lu}\p{Ll}\p{Lt}\p{Lm}\p{Lo}\p{Nl}]");
+      var invalidIdentifierParts = new Regex(@"[^\p{Lu}\p{Ll}\p{Lt}\p{Lm}\p{Lo}\p{Nl}\p{Mn}\p{Mc}\p{Nd}\p{Pc}\p{Cf}]");
+      return "@" +
+        (invalidIdentifierStarts.IsMatch(name.Substring(0, 1)) ? "_" : "") + // prepend '_' if necessary
+        invalidIdentifierParts.Replace(name, "_");
     }
 
@@ -106,12 +145,27 @@
         if (node is VariableTreeNode) {
           var varNode = node as VariableTreeNode;
-          strBuilder.AppendFormat("{0} * {1}", varNode.VariableName, varNode.Weight.ToString("g17", CultureInfo.InvariantCulture));
+          strBuilder.AppendFormat("{0} * {1}", VariableName2Identifier(varNode.VariableName), varNode.Weight.ToString("g17", CultureInfo.InvariantCulture));
         } else if (node is ConstantTreeNode) {
           var constNode = node as ConstantTreeNode;
           strBuilder.Append(constNode.Value.ToString("g17", CultureInfo.InvariantCulture));
+        } else if (node.Symbol is FactorVariable) {
+          var factorNode = node as FactorVariableTreeNode;
+          FormatFactor(factorNode, strBuilder);
+        } else if (node.Symbol is BinaryFactorVariable) {
+          var binFactorNode = node as BinaryFactorVariableTreeNode;
+          FormatBinaryFactor(binFactorNode, strBuilder);
         } else {
           throw new NotSupportedException("Formatting of symbol: " + node.Symbol + " not supported for C# symbolic expression tree formatter.");
         }
       }
+    }
+
+    private void FormatFactor(FactorVariableTreeNode node, StringBuilder strBuilder) {
+      strBuilder.AppendFormat("EvaluateFactor({0}, new [] {{ {1} }}, new [] {{ {2} }})", VariableName2Identifier(node.VariableName),
+        string.Join(",", node.Symbol.GetVariableValues(node.VariableName).Select(name => "\"" + name + "\"")), string.Join(",", node.Weights.Select(v => v.ToString(CultureInfo.InvariantCulture))));
+    }
+
+    private void FormatBinaryFactor(BinaryFactorVariableTreeNode node, StringBuilder strBuilder) {
+      strBuilder.AppendFormat(CultureInfo.InvariantCulture, "EvaluateBinaryFactor({0}, \"{1}\", {2})", VariableName2Identifier(node.VariableName), node.VariableValue, node.Weight);
     }
 
@@ -182,13 +236,27 @@
       GenerateAverageSource(strBuilder);
       GenerateIfThenElseSource(strBuilder);
+      GenerateFactorSource(strBuilder);
+      GenerateBinaryFactorSource(strBuilder);
       strBuilder.Append(Environment.NewLine + "public static double Evaluate (");
 
-      HashSet<string> varNames = new HashSet<string>();
-      foreach (var node in symbolicExpressionTree.IterateNodesPostfix().Where(x => x is VariableTreeNode)) {
-        varNames.Add(((VariableTreeNode)node).VariableName);
-      }
-
-      var orderedNames = varNames.OrderBy(n => n, new NaturalStringComparer()).Select(n => "double " + n);
+      // here we don't have access to problemData to determine the type for each variable (double/string) therefore we must distinguish based on the symbol type
+      HashSet<string> doubleVarNames = new HashSet<string>();
+      foreach (var node in symbolicExpressionTree.IterateNodesPostfix().Where(x => x is VariableTreeNode || x is VariableConditionTreeNode)) {
+        doubleVarNames.Add(((IVariableTreeNode)node).VariableName);
+      }
+
+      HashSet<string> stringVarNames = new HashSet<string>();
+      foreach (var node in symbolicExpressionTree.IterateNodesPostfix().Where(x => x is BinaryFactorVariableTreeNode || x is FactorVariableTreeNode)) {
+        stringVarNames.Add(((IVariableTreeNode)node).VariableName);
+      }
+
+      var orderedNames = stringVarNames.OrderBy(n => n, new NaturalStringComparer()).Select(n => "string " + VariableName2Identifier(n) + " /* " + n + " */");
       strBuilder.Append(string.Join(", ", orderedNames));
+
+      if (stringVarNames.Any() && doubleVarNames.Any())
+        strBuilder.AppendLine(",");
+      orderedNames = doubleVarNames.OrderBy(n => n, new NaturalStringComparer()).Select(n => "double " + VariableName2Identifier(n) + " /* " + n + " */");
+      strBuilder.Append(string.Join(", ", orderedNames));
+
 
       strBuilder.AppendLine(") {");
@@ -198,4 +266,5 @@
     private void GenerateFooter(StringBuilder strBuilder) {
       strBuilder.AppendLine(";");
+
       strBuilder.AppendLine("return result;");
       strBuilder.AppendLine("}");
@@ -215,4 +284,19 @@
       strBuilder.AppendLine("}");
     }
+
+    private void GenerateFactorSource(StringBuilder strBuilder) {
+      strBuilder.AppendLine("private static double EvaluateFactor(string factorValue, string[] factorValues, double[] constants) {");
+      strBuilder.AppendLine("   for(int i=0;i<factorValues.Length;i++) " +
+                            "      if(factorValues[i] == factorValue) return constants[i];" +
+                            "   throw new ArgumentException();");
+      strBuilder.AppendLine("}");
+    }
+
+    private void GenerateBinaryFactorSource(StringBuilder strBuilder) {
+      strBuilder.AppendLine("private static double EvaluateBinaryFactor(string factorValue, string targetValue, double weight) {");
+      strBuilder.AppendLine("  return factorValue == targetValue ? weight : 0.0;");
+      strBuilder.AppendLine("}");
+    }
+
   }
 }
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/SymbolicDataAnalysisExpressionExcelFormatter.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/SymbolicDataAnalysisExpressionExcelFormatter.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/SymbolicDataAnalysisExpressionExcelFormatter.cs	(revision 15973)
@@ -1,5 +1,5 @@
 ﻿#region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
@@ -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) + columnName;
         dividend = (int)((dividend - modulo) / 26);
       }
@@ -60,10 +60,10 @@
     private readonly Dictionary<string, string> variableNameMapping = new Dictionary<string, string>();
     private int currentVariableIndex = 0;
-    private string GetColumnToVariableName(string variabelName) {
-      if (!variableNameMapping.ContainsKey(variabelName)) {
+    private string GetColumnToVariableName(string varName) {
+      if (!variableNameMapping.ContainsKey(varName)) {
         currentVariableIndex++;
-        variableNameMapping.Add(variabelName, GetExcelColumnName(currentVariableIndex));
-      }
-      return string.Format("${0}1", variableNameMapping[variabelName]);
+        variableNameMapping.Add(varName, GetExcelColumnName(currentVariableIndex));
+      }
+      return string.Format("${0}1", variableNameMapping[varName]);
     }
     public string Format(ISymbolicExpressionTree symbolicExpressionTree) {
@@ -71,12 +71,19 @@
     }
 
+
     public string Format(ISymbolicExpressionTree symbolicExpressionTree, IDataset dataset) {
+      if (dataset != null)
+        return FormatWithMapping(symbolicExpressionTree, CalculateVariableMapping(symbolicExpressionTree, dataset));
+      else return FormatWithMapping(symbolicExpressionTree, new Dictionary<string, string>());
+    }
+
+    public string FormatWithMapping(ISymbolicExpressionTree symbolicExpressionTree, Dictionary<string, string> variableNameMapping) {
+      foreach (var kvp in variableNameMapping) this.variableNameMapping.Add(kvp.Key, kvp.Value);
       var stringBuilder = new StringBuilder();
-      if (dataset != null) CalculateVariableMapping(symbolicExpressionTree, dataset);
 
       stringBuilder.Append("=");
       stringBuilder.Append(FormatRecursively(symbolicExpressionTree.Root));
 
-      foreach (var variable in variableNameMapping) {
+      foreach (var variable in this.variableNameMapping) {
         stringBuilder.AppendLine();
         stringBuilder.Append(variable.Key + " = " + variable.Value);
@@ -85,14 +92,14 @@
     }
 
-    private void CalculateVariableMapping(ISymbolicExpressionTree tree, IDataset dataset) {
-      int columnIndex = 0;
+    private Dictionary<string, string> CalculateVariableMapping(ISymbolicExpressionTree tree, IDataset dataset) {
+      var mapping = new Dictionary<string, string>();
       int inputIndex = 0;
-      var usedVariables = tree.IterateNodesPrefix().OfType<VariableTreeNode>().Select(v => v.VariableName).Distinct();
+      var usedVariables = tree.IterateNodesPrefix().OfType<IVariableTreeNode>().Select(v => v.VariableName).Distinct().ToArray();
       foreach (var variable in dataset.VariableNames) {
-        columnIndex++;
         if (!usedVariables.Contains(variable)) continue;
         inputIndex++;
-        variableNameMapping[variable] = GetExcelColumnName(inputIndex);
-      }
+        mapping[variable] = GetExcelColumnName(inputIndex);
+      }
+      return mapping;
     }
 
@@ -190,5 +197,25 @@
         stringBuilder.Append(variableTreeNode.Weight.ToString(CultureInfo.InvariantCulture));
         stringBuilder.Append("*");
-        stringBuilder.Append(GetColumnToVariableName(variableTreeNode.VariableName));// + LagToString(currentLag));
+        stringBuilder.Append(GetColumnToVariableName(variableTreeNode.VariableName));
+      } else if (symbol is BinaryFactorVariable) {
+        var binFactorNode = node as BinaryFactorVariableTreeNode;
+        stringBuilder.AppendFormat("IF({0}=\"{1}\", {2}, 0)",
+          GetColumnToVariableName(binFactorNode.VariableName),
+          binFactorNode.VariableValue,
+          binFactorNode.Weight.ToString(CultureInfo.InvariantCulture)
+          );
+      } else if (symbol is FactorVariable) {
+        var factorNode = node as FactorVariableTreeNode;
+        var values = factorNode.Symbol.GetVariableValues(factorNode.VariableName).ToArray();
+        var w = factorNode.Weights;
+        // create nested if
+        for (int i = 0; i < values.Length; i++) {
+          stringBuilder.AppendFormat("IF({0}=\"{1}\", {2}, ",
+            GetColumnToVariableName(factorNode.VariableName),
+            values[i],
+            w[i].ToString(CultureInfo.InvariantCulture));
+        }
+        stringBuilder.Append("\"\""); // return empty string on unknown value
+        stringBuilder.Append(')', values.Length); // add closing parenthesis
       } else if (symbol is Power) {
         stringBuilder.Append("POWER(");
@@ -213,16 +240,27 @@
       } else if (symbol is VariableCondition) {
         VariableConditionTreeNode variableConditionTreeNode = node as VariableConditionTreeNode;
-        double threshold = variableConditionTreeNode.Threshold;
-        double slope = variableConditionTreeNode.Slope;
-        string p = "(1 / (1 + EXP(-" + slope.ToString(CultureInfo.InvariantCulture) + " * (" + GetColumnToVariableName(variableConditionTreeNode.VariableName) + "-" + threshold.ToString(CultureInfo.InvariantCulture) + "))))";
-        stringBuilder.Append("((");
-        stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
-        stringBuilder.Append("*");
-        stringBuilder.Append(p);
-        stringBuilder.Append(") + (");
-        stringBuilder.Append(FormatRecursively(node.GetSubtree(1)));
-        stringBuilder.Append("*(");
-        stringBuilder.Append("1 - " + p + ")");
-        stringBuilder.Append("))");
+        if (!variableConditionTreeNode.Symbol.IgnoreSlope) {
+          double threshold = variableConditionTreeNode.Threshold;
+          double slope = variableConditionTreeNode.Slope;
+          string p = "(1 / (1 + EXP(-" + slope.ToString(CultureInfo.InvariantCulture) + " * (" +
+                     GetColumnToVariableName(variableConditionTreeNode.VariableName) + "-" +
+                     threshold.ToString(CultureInfo.InvariantCulture) + "))))";
+          stringBuilder.Append("((");
+          stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
+          stringBuilder.Append("*");
+          stringBuilder.Append(p);
+          stringBuilder.Append(") + (");
+          stringBuilder.Append(FormatRecursively(node.GetSubtree(1)));
+          stringBuilder.Append("*(");
+          stringBuilder.Append("1 - " + p + ")");
+          stringBuilder.Append("))");
+        } else {
+          stringBuilder.AppendFormat(CultureInfo.InvariantCulture, "(IF({0} <= {1}, {2}, {3}))",
+            GetColumnToVariableName(variableConditionTreeNode.VariableName),
+            variableConditionTreeNode.Threshold,
+            FormatRecursively(node.GetSubtree(0)),
+            FormatRecursively(node.GetSubtree(1))
+            );
+        }
       } else if (symbol is Xor) {
         stringBuilder.Append("IF(");
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/SymbolicDataAnalysisExpressionLatexFormatter.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/SymbolicDataAnalysisExpressionLatexFormatter.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/SymbolicDataAnalysisExpressionLatexFormatter.cs	(revision 15973)
@@ -1,5 +1,5 @@
 ﻿#region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
@@ -33,7 +33,10 @@
   [StorableClass]
   public sealed class SymbolicDataAnalysisExpressionLatexFormatter : NamedItem, ISymbolicExpressionTreeStringFormatter {
-    private readonly List<double> constants;
+    private readonly List<KeyValuePair<string, double>> constants;
+    private int constIndex;
     private int targetCount;
     private int currentLag;
+    private string targetVariable;
+    private bool containsTimeSeriesSymbol;
 
     [StorableConstructor]
@@ -41,5 +44,8 @@
     private SymbolicDataAnalysisExpressionLatexFormatter(SymbolicDataAnalysisExpressionLatexFormatter original, Cloner cloner)
       : base(original, cloner) {
-      constants = new List<double>(original.constants);
+      constants = new List<KeyValuePair<string, double>>(original.constants);
+      constIndex = original.constIndex;
+      currentLag = original.currentLag;
+      targetCount = original.targetCount;
     }
     public SymbolicDataAnalysisExpressionLatexFormatter()
@@ -47,5 +53,5 @@
       Name = ItemName;
       Description = ItemDescription;
-      constants = new List<double>();
+      constants = new List<KeyValuePair<string, double>>();
     }
 
@@ -55,13 +61,21 @@
 
     public string Format(ISymbolicExpressionTree symbolicExpressionTree) {
+      return Format(symbolicExpressionTree, null);
+    }
+    public string Format(ISymbolicExpressionTree symbolicExpressionTree, string targetVariable) {
       try {
         StringBuilder strBuilder = new StringBuilder();
         constants.Clear();
+        constIndex = 0;
+        this.targetVariable = targetVariable;
+        containsTimeSeriesSymbol = symbolicExpressionTree.IterateNodesBreadth().Any(n => IsTimeSeriesSymbol(n.Symbol));
         strBuilder.AppendLine(FormatRecursively(symbolicExpressionTree.Root));
         return strBuilder.ToString();
-      }
-      catch (NotImplementedException ex) {
+      } catch (NotImplementedException ex) {
         return ex.Message + Environment.NewLine + ex.StackTrace;
       }
+    }
+    static bool IsTimeSeriesSymbol(ISymbol s) {
+      return s is TimeLag || s is Integral || s is Derivative || s is LaggedVariable;
     }
 
@@ -75,5 +89,5 @@
       }
       int i = 1;
-      foreach (SymbolicExpressionTreeNode subTree in node.Subtrees.Skip(1)) {
+      foreach (var subTree in node.Subtrees.Skip(1)) {
         FormatSep(node, strBuilder, i);
         // format the whole subtree
@@ -99,5 +113,5 @@
       } else if (node.Symbol is Division) {
         if (node.SubtreeCount == 1) {
-          strBuilder.Append(@" \cfrac{1");
+          strBuilder.Append(@" \cfrac{1}{");
         } else {
           strBuilder.Append(@" \cfrac{ ");
@@ -166,12 +180,41 @@
         strBuilder.Append(@" \operatorname{if}  \left( ");
       } else if (node.Symbol is Constant) {
-        strBuilder.Append("c_{" + constants.Count + "} ");
+        var constName = "c_{" + constIndex + "}";
+        constIndex++;
         var constNode = node as ConstantTreeNode;
-        constants.Add(constNode.Value);
+        if (constNode.Value.IsAlmost(1.0)) {
+          strBuilder.Append("1 ");
+        } else {
+          strBuilder.Append(constName);
+          constants.Add(new KeyValuePair<string, double>(constName, constNode.Value));
+        }
+
+      } else if (node.Symbol is FactorVariable) {
+        var factorNode = node as FactorVariableTreeNode;
+        var constName = "c_{" + constIndex + "}";
+        strBuilder.Append(constName + " ");
+        foreach (var e in factorNode.Symbol.GetVariableValues(factorNode.VariableName)
+          .Zip(factorNode.Weights, Tuple.Create)) {
+          constants.Add(new KeyValuePair<string, double>("c_{" + constIndex + ", " + EscapeLatexString(factorNode.VariableName) + "=" + EscapeLatexString(e.Item1) + "}", e.Item2));
+        }
+        constIndex++;
+      } else if (node.Symbol is BinaryFactorVariable) {
+        var binFactorNode = node as BinaryFactorVariableTreeNode;
+        if (!binFactorNode.Weight.IsAlmost((1.0))) {
+          var constName = "c_{" + constIndex + "}";
+          strBuilder.Append(constName + "  \\cdot");
+          constants.Add(new KeyValuePair<string, double>(constName, binFactorNode.Weight));
+          constIndex++;
+        }
+        strBuilder.Append("(" + EscapeLatexString(binFactorNode.VariableName));
+        strBuilder.Append(LagToString(currentLag));
+        strBuilder.Append(" = " + EscapeLatexString(binFactorNode.VariableValue) + " )");
       } else if (node.Symbol is LaggedVariable) {
         var laggedVarNode = node as LaggedVariableTreeNode;
         if (!laggedVarNode.Weight.IsAlmost(1.0)) {
-          strBuilder.Append("c_{" + constants.Count + "} \\cdot ");
-          constants.Add(laggedVarNode.Weight);
+          var constName = "c_{" + constIndex + "}";
+          strBuilder.Append(constName + "  \\cdot");
+          constants.Add(new KeyValuePair<string, double>(constName, laggedVarNode.Weight));
+          constIndex++;
         }
         strBuilder.Append(EscapeLatexString(laggedVarNode.VariableName));
@@ -181,6 +224,8 @@
         var varNode = node as VariableTreeNode;
         if (!varNode.Weight.IsAlmost((1.0))) {
-          strBuilder.Append("c_{" + constants.Count + "} \\cdot ");
-          constants.Add(varNode.Weight);
+          var constName = "c_{" + constIndex + "}";
+          strBuilder.Append(constName + "  \\cdot");
+          constants.Add(new KeyValuePair<string, double>(constName, varNode.Weight));
+          constIndex++;
         }
         strBuilder.Append(EscapeLatexString(varNode.VariableName));
@@ -197,5 +242,5 @@
         strBuilder.Append(invokeNode.Symbol.FunctionName + @" \left( ");
       } else if (node.Symbol is StartSymbol) {
-        strBuilder.Append("target_" + (targetCount++) + "(t) & = ");
+        FormatStartSymbol(strBuilder);
       } else if (node.Symbol is Argument) {
         var argSym = node.Symbol as Argument;
@@ -216,8 +261,12 @@
       } else if (node.Symbol is VariableCondition) {
         var conditionTreeNode = node as VariableConditionTreeNode;
-        string p = @"1 /  1 + \exp  - c_{" + constants.Count + "} ";
-        constants.Add(conditionTreeNode.Slope);
-        p += @" \cdot " + EscapeLatexString(conditionTreeNode.VariableName) + LagToString(currentLag) + " - c_{" + constants.Count + @"}   ";
-        constants.Add(conditionTreeNode.Threshold);
+        var constName = "c_{" + constants.Count + "}";
+        string p = @"1 /  1 + \exp  - " + constName + " ";
+        constants.Add(new KeyValuePair<string, double>(constName, conditionTreeNode.Slope));
+        constIndex++;
+        var const2Name = "c_{" + constants.Count + @"}";
+        p += @" \cdot " + EscapeLatexString(conditionTreeNode.VariableName) + LagToString(currentLag) + " - " + const2Name + "   ";
+        constants.Add(new KeyValuePair<string, double>(const2Name, conditionTreeNode.Threshold));
+        constIndex++;
         strBuilder.Append(@" \left( " + p + @"\cdot ");
       } else {
@@ -303,5 +352,5 @@
       } else if (node.Symbol is StartSymbol) {
         strBuilder.Append(@"\\" + Environment.NewLine);
-        strBuilder.Append("target_" + (targetCount++) + "(t) & = ");
+        FormatStartSymbol(strBuilder);
       } else if (node.Symbol is Power) {
         strBuilder.Append(@"\right) ^ { \operatorname{round} \left(");
@@ -310,8 +359,12 @@
       } else if (node.Symbol is VariableCondition) {
         var conditionTreeNode = node as VariableConditionTreeNode;
-        string p = @"1 / \left( 1 + \exp \left( - c_{" + constants.Count + "} ";
-        constants.Add(conditionTreeNode.Slope);
-        p += @" \cdot " + EscapeLatexString(conditionTreeNode.VariableName) + LagToString(currentLag) + " - c_{" + constants.Count + @"} \right) \right) \right)   ";
-        constants.Add(conditionTreeNode.Threshold);
+        var const1Name = "c_{" + constants.Count + "}";
+        string p = @"1 / \left( 1 + \exp \left( - " + const1Name + " ";
+        constants.Add(new KeyValuePair<string, double>(const1Name, conditionTreeNode.Slope));
+        constIndex++;
+        var const2Name = "c_{" + constants.Count + "}";
+        p += @" \cdot " + EscapeLatexString(conditionTreeNode.VariableName) + LagToString(currentLag) + " - " + const2Name + " \right) \right) \right)   ";
+        constants.Add(new KeyValuePair<string, double>(const2Name, conditionTreeNode.Threshold));
+        constIndex++;
         strBuilder.Append(@" +  \left( 1 - " + p + @" \right) \cdot ");
       } else {
@@ -391,4 +444,6 @@
       } else if (node.Symbol is LaggedVariable) {
       } else if (node.Symbol is Variable) {
+      } else if (node.Symbol is FactorVariable) {
+      } else if (node.Symbol is BinaryFactorVariable) {
       } else if (node.Symbol is ProgramRootSymbol) {
         strBuilder
@@ -398,13 +453,11 @@
         // output all constant values
         if (constants.Count > 0) {
-          int i = 0;
           foreach (var constant in constants) {
             // replace "." with ".&" to align decimal points
-            var constStr = string.Format(System.Globalization.NumberFormatInfo.InvariantInfo, "{0:G5}", constant);
+            var constStr = string.Format(System.Globalization.NumberFormatInfo.InvariantInfo, "{0:G5}", constant.Value);
             if (!constStr.Contains(".")) constStr = constStr + ".0";
-            constStr = constStr.Replace(".", "\\negthickspace&.");  // fix problem in rendering of aligned expressions
-            strBuilder.Append("c_{" + i + "}& = & " + constStr);
+            constStr = constStr.Replace(".", "&.");  // fix problem in rendering of aligned expressions
+            strBuilder.Append(constant.Key + "& = & " + constStr);
             strBuilder.Append(@"\\");
-            i++;
           }
         }
@@ -433,4 +486,11 @@
     }
 
+    private void FormatStartSymbol(StringBuilder strBuilder) {
+      strBuilder.Append(targetVariable ?? "target_" + (targetCount++));
+      if (containsTimeSeriesSymbol)
+        strBuilder.Append("(t)");
+      strBuilder.Append(" & = ");
+    }
+
     private string LagToString(int lag) {
       if (lag < 0) {
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/SymbolicDataAnalysisExpressionMATLABFormatter.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/SymbolicDataAnalysisExpressionMATLABFormatter.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/SymbolicDataAnalysisExpressionMATLABFormatter.cs	(revision 15973)
@@ -1,5 +1,5 @@
 ﻿#region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
@@ -21,4 +21,5 @@
 
 using System.Globalization;
+using System.Linq;
 using System.Text;
 using HeuristicLab.Common;
@@ -77,4 +78,26 @@
       stringBuilder.AppendLine("  y = (f0 + 2*f1 - 2*f3 - f4) / 8;");
       stringBuilder.AppendLine("end");
+
+      var factorVariableNames =
+        symbolicExpressionTree.IterateNodesPostfix()
+          .OfType<FactorVariableTreeNode>()
+          .Select(n => n.VariableName)
+          .Distinct();
+
+      foreach (var factorVarName in factorVariableNames) {
+        var factorSymb = symbolicExpressionTree.IterateNodesPostfix()
+          .OfType<FactorVariableTreeNode>()
+          .First(n => n.VariableName == factorVarName)
+          .Symbol;
+        stringBuilder.AppendFormat("function y = switch_{0}(val, v)", factorVarName).AppendLine();
+        var values = factorSymb.GetVariableValues(factorVarName).ToArray();
+        stringBuilder.AppendLine("switch val");
+        for (int i = 0; i < values.Length; i++) {
+          stringBuilder.AppendFormat(CultureInfo.InvariantCulture, "  case \"{0}\" y = v({1})", values[i], i).AppendLine();
+        }
+        stringBuilder.AppendLine("end");
+        stringBuilder.AppendLine();
+      }
+
       return stringBuilder.ToString();
     }
@@ -296,4 +319,14 @@
         stringBuilder.Append("*");
         stringBuilder.Append(variableTreeNode.VariableName + LagToString(currentLag));
+      } else if (symbol is HeuristicLab.Problems.DataAnalysis.Symbolic.FactorVariable) {
+        var factorNode = node as FactorVariableTreeNode;
+        var weights = string.Join(" ", factorNode.Weights.Select(w => w.ToString("G17", CultureInfo.InvariantCulture)));
+        stringBuilder.AppendFormat("switch_{0}(\"{1}\",[{2}])",
+          factorNode.VariableName, factorNode.VariableName, weights)
+          .AppendLine();
+      } else if (symbol is HeuristicLab.Problems.DataAnalysis.Symbolic.BinaryFactorVariable) {
+        var factorNode = node as BinaryFactorVariableTreeNode;
+        stringBuilder.AppendFormat(CultureInfo.InvariantCulture,
+          "((strcmp({0},\"{1}\")==1) * {2:G17})", factorNode.VariableName, factorNode.VariableValue, factorNode.Weight);
       } else if (symbol is Power) {
         stringBuilder.Append("(");
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/SymbolicDataAnalysisExpressionMathematicaFormatter.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/SymbolicDataAnalysisExpressionMathematicaFormatter.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/SymbolicDataAnalysisExpressionMathematicaFormatter.cs	(revision 15973)
@@ -1,5 +1,5 @@
 ﻿#region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
@@ -110,10 +110,25 @@
         }
       } else {
-        if (node is VariableTreeNode) {
+        // terminals
+        if (node.Symbol is Variable) {
           var varNode = node as VariableTreeNode;
           strBuilder.AppendFormat("Times[{0}, {1}]", varNode.VariableName, varNode.Weight.ToString("G17", CultureInfo.InvariantCulture));
-        } else if (node is ConstantTreeNode) {
+        } else if (node.Symbol is Constant) {
           var constNode = node as ConstantTreeNode;
           strBuilder.Append(constNode.Value.ToString("G17", CultureInfo.InvariantCulture));
+        } else if (node.Symbol is FactorVariable) {
+          var factorNode = node as FactorVariableTreeNode;
+          strBuilder.AppendFormat("Switch[{0},", factorNode.VariableName);
+          var varValues = factorNode.Symbol.GetVariableValues(factorNode.VariableName).ToArray();
+          var weights = varValues.Select(factorNode.GetValue).ToArray();
+
+          var weightStr = string.Join(", ",
+            varValues.Zip(weights, (s, d) => string.Format(CultureInfo.InvariantCulture, "\"{0}\", {1:G17}", s, d)));
+          strBuilder.Append(weightStr);
+          strBuilder.Append("]");
+        } else if (node.Symbol is BinaryFactorVariable) {
+          var factorNode = node as BinaryFactorVariableTreeNode;
+          strBuilder.AppendFormat(CultureInfo.InvariantCulture, "If[{0}==\"{1}\",{2:G17},0.0]",
+            factorNode.VariableName, factorNode.VariableValue, factorNode.Weight);
         } else {
           throw new NotSupportedException("Formatting of symbol: " + node.Symbol + " is not supported.");
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/SymbolicDataAnalysisExpressionSmalltalkFormatter.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/SymbolicDataAnalysisExpressionSmalltalkFormatter.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/SymbolicDataAnalysisExpressionSmalltalkFormatter.cs	(revision 15973)
@@ -1,5 +1,5 @@
 ﻿#region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
@@ -115,5 +115,5 @@
         stringBuilder.Append("]");
       } else if (symbol is LaggedVariable) {
-        stringBuilder.Append("lagged variable not implemented");
+        stringBuilder.Append("lagged variables are not supported");
       } else if (symbol is LessThan) {
         stringBuilder.Append("(");
@@ -165,4 +165,6 @@
         stringBuilder.Append("*");
         stringBuilder.Append(variableTreeNode.VariableName);
+      } else if (symbol is BinaryFactorVariable || symbol is FactorVariable) {
+        stringBuilder.Append("factor variables are not supported");
       } else {
         stringBuilder.Append("(");
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/TSQLExpressionFormatter.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/TSQLExpressionFormatter.cs	(revision 15973)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/TSQLExpressionFormatter.cs	(revision 15973)
@@ -0,0 +1,278 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Globalization;
+using System.Linq;
+using System.Text;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
+  internal static class StringBuilderExtensions {
+    internal static void AppendIndented(this StringBuilder strBuilder, int level, string text) {
+      strBuilder.Append(new string(' ', level * 2));
+      strBuilder.Append(text);
+    }
+    internal static void AppendLineIndented(this StringBuilder strBuilder, int level, string text) {
+      strBuilder.Append(new string(' ', level * 2));
+      strBuilder.AppendLine(text);
+    }
+  }
+
+  [Item("TSQL String Formatter", "String formatter for string representations of symbolic data analysis expressions in TSQL syntax.")]
+  [StorableClass]
+  public sealed class TSQLExpressionFormatter : NamedItem, ISymbolicExpressionTreeStringFormatter {
+    [StorableConstructor]
+    private TSQLExpressionFormatter(bool deserializing) : base(deserializing) { }
+    private TSQLExpressionFormatter(TSQLExpressionFormatter original, Cloner cloner) : base(original, cloner) { }
+    public TSQLExpressionFormatter()
+      : base() {
+      Name = ItemName;
+      Description = ItemDescription;
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new TSQLExpressionFormatter(this, cloner);
+    }
+
+    public string Format(ISymbolicExpressionTree symbolicExpressionTree) {
+      // skip root and start symbols
+      StringBuilder strBuilder = new StringBuilder();
+      GenerateHeader(strBuilder, symbolicExpressionTree);
+
+      //generate function body
+      FormatRecursively(1, symbolicExpressionTree.Root.GetSubtree(0).GetSubtree(0), strBuilder);
+
+      GenerateFooter(strBuilder);
+      return strBuilder.ToString();
+    }
+
+    private void GenerateHeader(StringBuilder strBuilder, ISymbolicExpressionTree symbolicExpressionTree) {
+      HashSet<string> floatVarNames = new HashSet<string>();
+      foreach (var node in symbolicExpressionTree.IterateNodesPostfix().Where(x => x is VariableTreeNode || x is VariableConditionTreeNode)) {
+        floatVarNames.Add(((IVariableTreeNode)node).VariableName);
+      }
+      var sortedFloatIdentifiers = floatVarNames.OrderBy(n => n, new NaturalStringComparer()).Select(n => VariableName2Identifier(n)).ToList();
+
+      HashSet<string> varcharVarNames = new HashSet<string>();
+      foreach (var node in symbolicExpressionTree.IterateNodesPostfix().Where(x => x is BinaryFactorVariableTreeNode || x is FactorVariableTreeNode)) {
+        varcharVarNames.Add(((IVariableTreeNode)node).VariableName);
+      }
+      var sortedVarcharIdentifiers = varcharVarNames.OrderBy(n => n, new NaturalStringComparer()).Select(n => VariableName2Identifier(n)).ToList();
+
+      //Generate comment and instructions
+      strBuilder.Append("-- generated. created function can be used like 'SELECT dbo.REGRESSIONMODEL(");
+      strBuilder.Append(string.Join(", ", sortedVarcharIdentifiers));
+      if (varcharVarNames.Any() && floatVarNames.Any())
+        strBuilder.Append(",");
+      strBuilder.Append(string.Join(", ", sortedFloatIdentifiers));
+      strBuilder.AppendLine(")'");
+      strBuilder.AppendLine("-- use the expression after the RETURN statement if you want to incorporate the model in a query without creating a function.");
+
+      //Generate function header
+      strBuilder.Append("CREATE FUNCTION dbo.REGRESSIONMODEL(");
+      strBuilder.Append(string.Join(", ", sortedVarcharIdentifiers.Select(n => string.Format("{0} NVARCHAR(max)",n))));
+      if (varcharVarNames.Any() && floatVarNames.Any())
+        strBuilder.Append(",");
+      strBuilder.Append(string.Join(", ", sortedFloatIdentifiers.Select(n => string.Format("{0} FLOAT",n))));
+      strBuilder.AppendLine(")");
+
+      //start function body
+      strBuilder.AppendLine("RETURNS FLOAT");
+      strBuilder.AppendLine("BEGIN");
+
+      //add variable declaration for convenience
+      strBuilder.AppendLineIndented(1, "-- added variable declaration for convenience");
+      foreach (var name in sortedVarcharIdentifiers)
+        strBuilder.AppendLineIndented(1, string.Format("-- DECLARE {0} NVARCHAR(max) = ''", name));
+      foreach (var name in sortedFloatIdentifiers)
+        strBuilder.AppendLineIndented(1, string.Format("-- DECLARE {0} FLOAT = 0.0", name));
+      strBuilder.AppendLineIndented(1, "-- SELECT");
+      strBuilder.AppendLine("RETURN ");
+    }
+
+    private void FormatRecursively(int level, ISymbolicExpressionTreeNode node, StringBuilder strBuilder) {
+      if (node.Subtrees.Any()) {
+        if (node.Symbol is Addition) {
+          FormatOperator(level, node, "+", strBuilder);
+        } else if (node.Symbol is And) {
+          FormatOperator(level, node, "AND", strBuilder);
+        } else if (node.Symbol is Average) {
+          FormatAverage(level, node, strBuilder);
+        } else if (node.Symbol is Cosine) {
+          FormatFunction(level, node, "COS", strBuilder);
+        } else if (node.Symbol is Division) {
+          FormatDivision(level, node, strBuilder);
+        } else if (node.Symbol is Exponential) {
+          FormatFunction(level, node, "EXP", strBuilder);
+        } else if (node.Symbol is GreaterThan) {
+          FormatOperator(level, node, ">", strBuilder);
+        } else if (node.Symbol is IfThenElse) {
+          FormatIfThenElse(level, node, strBuilder);
+        } else if (node.Symbol is LessThan) {
+          FormatOperator(level, node, "<", strBuilder);
+        } else if (node.Symbol is Logarithm) {
+          FormatFunction(level, node, "LOG", strBuilder);
+        } else if (node.Symbol is Multiplication) {
+          FormatOperator(level, node, "*", strBuilder);
+        } else if (node.Symbol is Not) {
+          FormatOperator(level, node, "NOT LIKE", strBuilder);
+        } else if (node.Symbol is Or) {
+          FormatOperator(level, node, "OR", strBuilder);
+        } else if (node.Symbol is Xor) {
+          throw new NotSupportedException(string.Format("Symbol {0} not yet supported.", node.Symbol.GetType().Name));
+        } else if (node.Symbol is Sine) {
+          FormatFunction(level, node, "SIN", strBuilder);
+        } else if (node.Symbol is Subtraction) {
+          FormatSubtraction(level, node, strBuilder);
+        } else if (node.Symbol is Tangent) {
+          FormatFunction(level, node, "TAN", strBuilder);
+        } else if (node.Symbol is Square) {
+          FormatFunction(level, node, "SQUARE", strBuilder);
+        } else if (node.Symbol is SquareRoot) {
+          FormatFunction(level, node, "SQRT", strBuilder);
+        } else if (node.Symbol is Power) {
+          FormatFunction(level, node, "POWER", strBuilder);
+        } else if (node.Symbol is Root) {
+          FormatRoot(level, node, strBuilder);
+        } else {
+          throw new NotSupportedException("Formatting of symbol: " + node.Symbol + " not supported for TSQL symbolic expression tree formatter.");
+        }
+      } else {
+        if (node is VariableTreeNode) {
+          var varNode = node as VariableTreeNode;
+          strBuilder.AppendFormat("{0} * {1}", VariableName2Identifier(varNode.VariableName), varNode.Weight.ToString("g17", CultureInfo.InvariantCulture));
+        } else if (node is ConstantTreeNode) {
+          var constNode = node as ConstantTreeNode;
+          strBuilder.Append(constNode.Value.ToString("g17", CultureInfo.InvariantCulture));
+        } else if (node.Symbol is FactorVariable) {
+          var factorNode = node as FactorVariableTreeNode;
+          FormatFactor(level, factorNode, strBuilder);
+        } else if (node.Symbol is BinaryFactorVariable) {
+          var binFactorNode = node as BinaryFactorVariableTreeNode;
+          throw new NotSupportedException(string.Format("Symbol {0} not yet supported.", node.Symbol.GetType().Name));
+        } else {
+          throw new NotSupportedException("Formatting of symbol: " + node.Symbol + " not supported for TSQL symbolic expression tree formatter.");
+        }
+      }
+    }
+
+    private void FormatIfThenElse(int level, ISymbolicExpressionTreeNode node, StringBuilder strBuilder) {
+      strBuilder.Append("CASE ISNULL((SELECT 1 WHERE");
+      FormatRecursively(level,node.GetSubtree(0), strBuilder);
+      strBuilder.AppendLine("),0)");
+      strBuilder.AppendIndented(level,"WHEN 1 THEN ");
+      FormatRecursively(level, node.GetSubtree(1), strBuilder);
+      strBuilder.AppendLine();
+      strBuilder.AppendIndented(level, "WHEN 0 THEN ");
+      FormatRecursively(level, node.GetSubtree(2), strBuilder);
+      strBuilder.AppendLine();
+      strBuilder.AppendIndented(level, "END");
+    }
+
+    private void FormatAverage(int level, ISymbolicExpressionTreeNode node, StringBuilder strBuilder) {
+      strBuilder.Append("(");
+      foreach (var child in node.Subtrees) {
+        FormatRecursively(level, child, strBuilder);
+        if (child != node.Subtrees.Last())
+          strBuilder.Append(" + ");
+      }
+      strBuilder.AppendFormat(") / {0}", node.Subtrees.Count());
+    }
+
+    private string VariableName2Identifier(string variableName) {
+      return "@"+variableName.Replace(' ', '_');
+    }
+
+    private void GenerateFooter(StringBuilder strBuilder) {
+      strBuilder.Append(Environment.NewLine);
+      strBuilder.AppendLine("END");
+    }
+
+
+    private void FormatOperator(int level, ISymbolicExpressionTreeNode node, string symbol, StringBuilder strBuilder) {
+      strBuilder.Append("(");
+      foreach (var child in node.Subtrees) {
+        FormatRecursively(level, child, strBuilder);
+        if (child != node.Subtrees.Last())
+          strBuilder.Append(" " + symbol + " ");
+      }
+      strBuilder.Append(")");
+    }
+
+    private void FormatFunction(int level, ISymbolicExpressionTreeNode node, string function, StringBuilder strBuilder) {
+      strBuilder.Append(function + "(");
+      foreach (var child in node.Subtrees) {
+        FormatRecursively(level++, child, strBuilder);
+        if (child != node.Subtrees.Last())
+          strBuilder.Append(", ");
+      }
+      strBuilder.Append(")");
+    }
+
+    private void FormatDivision(int level, ISymbolicExpressionTreeNode node, StringBuilder strBuilder) {
+      if (node.SubtreeCount == 1) {
+        strBuilder.Append("1.0 / ");
+        FormatRecursively(level, node.GetSubtree(0), strBuilder);
+      } else {
+        FormatRecursively(level, node.GetSubtree(0), strBuilder);
+        strBuilder.Append("/ (");
+        for (int i = 1; i < node.SubtreeCount; i++) {
+          if (i > 1) strBuilder.Append(" * ");
+          FormatRecursively(level, node.GetSubtree(i), strBuilder);
+        }
+        strBuilder.Append(")");
+      }
+    }
+
+    private void FormatSubtraction(int level, ISymbolicExpressionTreeNode node, StringBuilder strBuilder) {
+      if (node.SubtreeCount == 1) {
+        strBuilder.Append("-");
+        FormatRecursively(level, node.GetSubtree(0), strBuilder);
+        return;
+      }
+      //Default case: more than 1 child
+      FormatOperator(level, node, "-", strBuilder);
+    }
+
+    private void FormatRoot(int level, ISymbolicExpressionTreeNode node, StringBuilder strBuilder) {
+      strBuilder.AppendLine("POWER(");
+      FormatRecursively(level, node.GetSubtree(0), strBuilder);
+      strBuilder.AppendLineIndented(level, " , 1.0 / (");
+      FormatRecursively(level, node.GetSubtree(1), strBuilder);
+      strBuilder.AppendLineIndented(level, "))");
+    }
+
+    private void FormatFactor(int level, FactorVariableTreeNode node, StringBuilder strBuilder) {
+      strBuilder.AppendLine("( ");
+      strBuilder.AppendLineIndented(level + 1, string.Format("CASE {0}", VariableName2Identifier(node.VariableName)));
+      foreach (var name in node.Symbol.GetVariableValues(node.VariableName)) {
+        strBuilder.AppendLineIndented(level + 2, string.Format("WHEN '{0}' THEN {1}", name, node.GetValue(name).ToString(CultureInfo.InvariantCulture)));
+      }
+      strBuilder.AppendLineIndented(level + 1, "ELSE NULL END");
+      strBuilder.AppendIndented(level, ")");
+    }
+
+  }
+}
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Grammars/ArithmeticExpressionGrammar.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Grammars/ArithmeticExpressionGrammar.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Grammars/ArithmeticExpressionGrammar.cs	(revision 15973)
@@ -1,5 +1,5 @@
 #region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
@@ -53,6 +53,8 @@
       constant.MaxValue = 20;
       var variableSymbol = new HeuristicLab.Problems.DataAnalysis.Symbolic.Variable();
+      var binFactorVariableSymbol = new BinaryFactorVariable();
+      var factorVariableSymbol = new FactorVariable();
 
-      var allSymbols = new List<Symbol>() { add, sub, mul, div, constant, variableSymbol };
+      var allSymbols = new List<Symbol>() { add, sub, mul, div, constant, variableSymbol, binFactorVariableSymbol, factorVariableSymbol};
       var functionSymbols = new List<Symbol>() { add, sub, mul, div };
 
@@ -65,4 +67,6 @@
       SetSubtreeCount(constant, 0, 0);
       SetSubtreeCount(variableSymbol, 0, 0);
+      SetSubtreeCount(binFactorVariableSymbol, 0, 0);
+      SetSubtreeCount(factorVariableSymbol, 0, 0);
 
       // allow each symbol as child of the start symbol
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Grammars/FullFunctionalExpressionGrammar.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Grammars/FullFunctionalExpressionGrammar.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Grammars/FullFunctionalExpressionGrammar.cs	(revision 15973)
@@ -1,5 +1,5 @@
 #region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
@@ -115,4 +115,6 @@
       constant.MaxValue = 20;
       var variableSymbol = new HeuristicLab.Problems.DataAnalysis.Symbolic.Variable();
+      var binFactorVariable = new BinaryFactorVariable();
+      var factorVariable = new FactorVariable();
       var laggedVariable = new LaggedVariable();
       laggedVariable.InitialFrequency = 0.0;
@@ -123,5 +125,5 @@
       var allSymbols = new List<Symbol>() { add, sub, mul, div, mean, sin, cos, tan, log, square, pow, sqrt, root, exp,
         airyA, airyB, bessel, cosineIntegral, dawson, erf, expIntegralEi, fresnelCosineIntegral, fresnelSineIntegral, gamma, hypCosineIntegral, hypSineIntegral, norm, psi, sineIntegral,
-        @if, gt, lt, and, or, not,xor, timeLag, integral, derivative, constant, variableSymbol, laggedVariable,autoregressiveVariable, variableCondition };
+        @if, gt, lt, and, or, not,xor, timeLag, integral, derivative, constant, variableSymbol, binFactorVariable, factorVariable, laggedVariable,autoregressiveVariable, variableCondition };
       var unaryFunctionSymbols = new List<Symbol>() { square, sqrt, sin, cos, tan, log, exp, not, timeLag, integral, derivative,
         airyA, airyB, bessel, cosineIntegral, dawson, erf, expIntegralEi, fresnelCosineIntegral, fresnelSineIntegral, gamma, hypCosineIntegral, hypSineIntegral, norm, psi, sineIntegral
@@ -130,5 +132,5 @@
       var binaryFunctionSymbols = new List<Symbol>() { pow, root, gt, lt, variableCondition };
       var ternarySymbols = new List<Symbol>() { add, sub, mul, div, mean, and, or, xor };
-      var terminalSymbols = new List<Symbol>() { variableSymbol, constant, laggedVariable, autoregressiveVariable };
+      var terminalSymbols = new List<Symbol>() { variableSymbol, binFactorVariable, factorVariable, constant, laggedVariable, autoregressiveVariable };
 
       foreach (var symb in allSymbols)
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Grammars/TypeCoherentExpressionGrammar.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Grammars/TypeCoherentExpressionGrammar.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Grammars/TypeCoherentExpressionGrammar.cs	(revision 15973)
@@ -1,5 +1,5 @@
 #region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
@@ -104,4 +104,6 @@
       constant.MaxValue = 20;
       var variableSymbol = new Variable();
+      var binFactorVariable = new BinaryFactorVariable();
+      var factorVariable = new FactorVariable();
       var laggedVariable = new LaggedVariable();
       var autoregressiveVariable = new AutoregressiveTargetVariable();
@@ -112,7 +114,7 @@
       var trigonometricSymbols = new GroupSymbol(TrigonometricFunctionsName, new List<ISymbol>() { sin, cos, tan });
       var exponentialAndLogarithmicSymbols = new GroupSymbol(ExponentialFunctionsName, new List<ISymbol> { exp, log });
-      var specialFunctions = new GroupSymbol(SpecialFunctionsName, new List<ISymbol> { airyA, airyB, bessel, cosineIntegral, dawson, erf, expIntegralEi, 
+      var specialFunctions = new GroupSymbol(SpecialFunctionsName, new List<ISymbol> { airyA, airyB, bessel, cosineIntegral, dawson, erf, expIntegralEi,
         fresnelCosineIntegral,fresnelSineIntegral,gamma,hypCosineIntegral,hypSineIntegral,norm, psi, sineIntegral});
-      var terminalSymbols = new GroupSymbol(TerminalsName, new List<ISymbol> { constant, variableSymbol });
+      var terminalSymbols = new GroupSymbol(TerminalsName, new List<ISymbol> { constant, variableSymbol, binFactorVariable, factorVariable });
       var realValuedSymbols = new GroupSymbol(RealValuedSymbolsName, new List<ISymbol>() { arithmeticSymbols, trigonometricSymbols, exponentialAndLogarithmicSymbols, specialFunctions, terminalSymbols });
 
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4.csproj
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4.csproj	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4.csproj	(revision 15973)
@@ -103,4 +103,8 @@
       <Private>False</Private>
     </Reference>
+    <Reference Include="AutoDiff-1.0, Version=1.0.0.14388, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL">
+      <HintPath>..\..\bin\AutoDiff-1.0.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
     <Reference Include="System" />
     <Reference Include="System.Core">
@@ -133,13 +137,20 @@
       <SubType>Code</SubType>
     </Compile>
+    <Compile Include="Converters\LinearModelToTreeConverter.cs" />
+    <Compile Include="Converters\TreeSimplifier.cs" />
+    <Compile Include="Converters\TreeToAutoDiffTermConverter.cs" />
+    <Compile Include="Formatters\InfixExpressionFormatter.cs" />
+    <Compile Include="Formatters\TSQLExpressionFormatter.cs" />
     <Compile Include="Formatters\SymbolicDataAnalysisExpressionMathematicaFormatter.cs" />
     <Compile Include="Formatters\SymbolicDataAnalysisExpressionCSharpFormatter.cs" />
+    <Compile Include="Importer\InfixExpressionParser.cs" />
     <Compile Include="Importer\SymbolicExpressionImporter.cs" />
     <Compile Include="Importer\Token.cs" />
     <Compile Include="Interfaces\IModelBacktransformator.cs" />
+    <Compile Include="Interfaces\IVariableTreeNode.cs" />
+    <Compile Include="Interfaces\IVariableSymbol.cs" />
     <Compile Include="Interpreter\SymbolicDataAnalysisExpressionCompiledTreeInterpreter.cs" />
     <Compile Include="SymbolicDataAnalysisExpressionTreeSimplificationOperator.cs" />
     <Compile Include="SymbolicDataAnalysisModelComplexityCalculator.cs" />
-    <Compile Include="SymbolicExpressionTreeBacktransformator.cs" />
     <Compile Include="SymbolicDataAnalysisExpressionPruningOperator.cs" />
     <Compile Include="Analyzers\SymbolicDataAnalysisVariableFrequencyAnalyzer.cs" />
@@ -184,5 +195,4 @@
     <Compile Include="Interfaces\ISymbolicDataAnalysisAnalyzer.cs" />
     <Compile Include="SymbolicDataAnalysisSingleObjectiveProblem.cs" />
-    <Compile Include="SymbolicDataAnalysisExpressionTreeSimplifier.cs" />
     <Compile Include="SymbolicDataAnalysisProblem.cs" />
     <Compile Include="SymbolicDataAnalysisSolutionImpactValuesCalculator.cs" />
@@ -196,4 +206,10 @@
     <Compile Include="Symbols\AiryB.cs" />
     <Compile Include="Symbols\Bessel.cs" />
+    <Compile Include="Symbols\BinaryFactorVariable.cs" />
+    <Compile Include="Symbols\BinaryFactorVariableTreeNode.cs" />
+    <Compile Include="Symbols\FactorVariableTreeNode.cs" />
+    <Compile Include="Symbols\FactorVariable.cs" />
+    <Compile Include="Symbols\VariableBase.cs" />
+    <Compile Include="Symbols\VariableTreeNodeBase.cs" />
     <Compile Include="Symbols\Xor.cs" />
     <Compile Include="Symbols\Erf.cs" />
@@ -238,5 +254,6 @@
     <Compile Include="Symbols\VariableConditionTreeNode.cs" />
     <Compile Include="Symbols\VariableTreeNode.cs" />
-    <Compile Include="TransformationToSymbolicTreeMapper.cs" />
+    <Compile Include="Transformations\SymbolicExpressionTreeBacktransformator.cs" />
+    <Compile Include="Transformations\TransformationToSymbolicTreeMapper.cs" />
     <Compile Include="TreeMatching\SymbolicExpressionTreeBottomUpSimilarityCalculator.cs" />
     <Compile Include="TreeMatching\SymbolicExpressionTreeCanonicalSorter.cs" />
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Importer/InfixExpressionParser.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Importer/InfixExpressionParser.cs	(revision 15973)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Importer/InfixExpressionParser.cs	(revision 15973)
@@ -0,0 +1,505 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Globalization;
+using System.Linq;
+using System.Text;
+using HeuristicLab.Collections;
+using HeuristicLab.Common;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
+  /// <summary>
+  /// Parses mathematical expressions in infix form. E.g. x1 * (3.0 * x2 + x3)
+  /// Identifier format (functions or variables): '_' | letter { '_' | letter | digit }
+  /// Variables names and variable values can be set under quotes "" or '' because variable names might contain spaces. 
+  ///   Variable = ident | " ident " | ' ident ' 
+  /// It is also possible to use functions e.g. log("x1") or real-valued constants e.g. 3.1415 . 
+  /// Variable names are case sensitive. Function names are not case sensitive.
+  /// 
+  /// 
+  /// S             = Expr EOF
+  /// Expr          = ['-' | '+'] Term { '+' Term | '-' Term }
+  /// Term          = Fact { '*' Fact | '/' Fact }
+  /// Fact          = '(' Expr ')' 
+  ///                 | 'LAG' '(' varId ',' ['+' | '-' ] number ')' 
+  ///                 | funcId '(' ArgList ')' 
+  ///                 | VarExpr | number
+  /// ArgList       = Expr { ',' Expr }
+  /// VarExpr       = varId OptFactorPart
+  /// OptFactorPart = [ ('=' varVal | '[' ['+' | '-' ] number {',' ['+' | '-' ] number } ']' ) ]
+  /// varId         =  ident | ' ident ' | " ident "
+  /// varVal        =  ident | ' ident ' | " ident "
+  /// ident         =  '_' | letter { '_' | letter | digit }
+  /// </summary>
+  public sealed class InfixExpressionParser {
+    private enum TokenType { Operator, Identifier, Number, LeftPar, RightPar, LeftBracket, RightBracket, Comma, Eq, End, NA };
+    private class Token {
+      internal double doubleVal;
+      internal string strVal;
+      internal TokenType TokenType;
+    }
+
+    private class SymbolNameComparer : IEqualityComparer<ISymbol>, IComparer<ISymbol> {
+      public int Compare(ISymbol x, ISymbol y) {
+        return x.Name.CompareTo(y.Name);
+      }
+
+      public bool Equals(ISymbol x, ISymbol y) {
+        return Compare(x, y) == 0;
+      }
+
+      public int GetHashCode(ISymbol obj) {
+        return obj.Name.GetHashCode();
+      }
+    }
+    // format name <-> symbol 
+    // the lookup table is also used in the corresponding formatter
+    internal static readonly BidirectionalLookup<string, ISymbol>
+      knownSymbols = new BidirectionalLookup<string, ISymbol>(StringComparer.InvariantCulture, new SymbolNameComparer());
+
+    private Constant constant = new Constant();
+    private Variable variable = new Variable();
+    private BinaryFactorVariable binaryFactorVar = new BinaryFactorVariable();
+    private FactorVariable factorVar = new FactorVariable();
+
+    private ProgramRootSymbol programRootSymbol = new ProgramRootSymbol();
+    private StartSymbol startSymbol = new StartSymbol();
+
+    static InfixExpressionParser() {
+      // populate bidirectional lookup
+      var dict = new Dictionary<string, ISymbol>
+      {
+        { "+", new Addition()},
+        { "/", new Division()},
+        { "*", new Multiplication()},
+        { "-", new Subtraction()},
+        { "EXP", new Exponential()},
+        { "LOG", new Logarithm()},
+        { "POW", new Power()},
+        { "ROOT", new Root()},
+        { "SQR", new Square() },
+        { "SQRT", new SquareRoot() },
+        { "SIN",new Sine()},
+        { "COS", new Cosine()},
+        { "TAN", new Tangent()},
+        { "AIRYA", new AiryA()},
+        { "AIRYB", new AiryB()},
+        { "BESSEL", new Bessel()},
+        { "COSINT", new CosineIntegral()},
+        { "SININT", new SineIntegral()},
+        { "HYPCOSINT", new HyperbolicCosineIntegral()},
+        { "HYPSININT", new HyperbolicSineIntegral()},
+        { "FRESNELSININT", new FresnelSineIntegral()},
+        { "FRESNELCOSINT", new FresnelCosineIntegral()},
+        { "NORM", new Norm()},
+        { "ERF", new Erf()},
+        { "GAMMA", new Gamma()},
+        { "PSI", new Psi()},
+        { "DAWSON", new Dawson()},
+        { "EXPINT", new ExponentialIntegralEi()},
+        { "MEAN", new Average()},
+        { "IF", new IfThenElse()},
+        { "GT", new GreaterThan()},
+        { "LT", new LessThan()},
+        { "AND", new And()},
+        { "OR", new Or()},
+        { "NOT", new Not()},
+        { "XOR", new Xor()},
+        { "DIFF", new Derivative()},
+        { "LAG", new LaggedVariable() },
+      };
+
+
+      foreach (var kvp in dict) {
+        knownSymbols.Add(kvp.Key, kvp.Value);
+      }
+    }
+
+    public ISymbolicExpressionTree Parse(string str) {
+      ISymbolicExpressionTreeNode root = programRootSymbol.CreateTreeNode();
+      ISymbolicExpressionTreeNode start = startSymbol.CreateTreeNode();
+      var allTokens = GetAllTokens(str).ToArray();
+      ISymbolicExpressionTreeNode mainBranch = ParseS(new Queue<Token>(allTokens));
+
+      // only a main branch was given => insert the main branch into the default tree template
+      root.AddSubtree(start);
+      start.AddSubtree(mainBranch);
+      return new SymbolicExpressionTree(root);
+    }
+
+    private IEnumerable<Token> GetAllTokens(string str) {
+      int pos = 0;
+      while (true) {
+        while (pos < str.Length && Char.IsWhiteSpace(str[pos])) pos++;
+        if (pos >= str.Length) {
+          yield return new Token { TokenType = TokenType.End, strVal = "" };
+          yield break;
+        }
+        if (char.IsDigit(str[pos])) {
+          // read number (=> read until white space or operator or comma)
+          var sb = new StringBuilder();
+          sb.Append(str[pos]);
+          pos++;
+          while (pos < str.Length && !char.IsWhiteSpace(str[pos])
+            && (str[pos] != '+' || str[pos - 1] == 'e' || str[pos - 1] == 'E')     // continue reading exponents
+            && (str[pos] != '-' || str[pos - 1] == 'e' || str[pos - 1] == 'E')
+            && str[pos] != '*'
+            && str[pos] != '/'
+            && str[pos] != ')'
+            && str[pos] != ']'
+            && str[pos] != ',') {
+            sb.Append(str[pos]);
+            pos++;
+          }
+          double dblVal;
+          if (double.TryParse(sb.ToString(), NumberStyles.Float, CultureInfo.InvariantCulture, out dblVal))
+            yield return new Token { TokenType = TokenType.Number, strVal = sb.ToString(), doubleVal = dblVal };
+          else yield return new Token { TokenType = TokenType.NA, strVal = sb.ToString() };
+        } else if (char.IsLetter(str[pos]) || str[pos] == '_') {
+          // read ident
+          var sb = new StringBuilder();
+          sb.Append(str[pos]);
+          pos++;
+          while (pos < str.Length &&
+            (char.IsLetter(str[pos]) || str[pos] == '_' || char.IsDigit(str[pos]))) {
+            sb.Append(str[pos]);
+            pos++;
+          }
+          yield return new Token { TokenType = TokenType.Identifier, strVal = sb.ToString() };
+        } else if (str[pos] == '"') {
+          // read to next " 
+          pos++;
+          var sb = new StringBuilder();
+          while (pos < str.Length && str[pos] != '"') {
+            sb.Append(str[pos]);
+            pos++;
+          }
+          if (pos < str.Length && str[pos] == '"') {
+            pos++; // skip "
+            yield return new Token { TokenType = TokenType.Identifier, strVal = sb.ToString() };
+          } else
+            yield return new Token { TokenType = TokenType.NA };
+
+        } else if (str[pos] == '\'') {
+          // read to next '
+          pos++;
+          var sb = new StringBuilder();
+          while (pos < str.Length && str[pos] != '\'') {
+            sb.Append(str[pos]);
+            pos++;
+          }
+          if (pos < str.Length && str[pos] == '\'') {
+            pos++; // skip '
+            yield return new Token { TokenType = TokenType.Identifier, strVal = sb.ToString() };
+          } else
+            yield return new Token { TokenType = TokenType.NA };
+        } else if (str[pos] == '+') {
+          pos++;
+          yield return new Token { TokenType = TokenType.Operator, strVal = "+" };
+        } else if (str[pos] == '-') {
+          pos++;
+          yield return new Token { TokenType = TokenType.Operator, strVal = "-" };
+        } else if (str[pos] == '/') {
+          pos++;
+          yield return new Token { TokenType = TokenType.Operator, strVal = "/" };
+        } else if (str[pos] == '*') {
+          pos++;
+          yield return new Token { TokenType = TokenType.Operator, strVal = "*" };
+        } else if (str[pos] == '(') {
+          pos++;
+          yield return new Token { TokenType = TokenType.LeftPar, strVal = "(" };
+        } else if (str[pos] == ')') {
+          pos++;
+          yield return new Token { TokenType = TokenType.RightPar, strVal = ")" };
+        } else if (str[pos] == '[') {
+          pos++;
+          yield return new Token { TokenType = TokenType.LeftBracket, strVal = "[" };
+        } else if (str[pos] == ']') {
+          pos++;
+          yield return new Token { TokenType = TokenType.RightBracket, strVal = "]" };
+        } else if (str[pos] == '=') {
+          pos++;
+          yield return new Token { TokenType = TokenType.Eq, strVal = "=" };
+        } else if (str[pos] == ',') {
+          pos++;
+          yield return new Token { TokenType = TokenType.Comma, strVal = "," };
+        } else {
+          throw new ArgumentException("Invalid character: " + str[pos]);
+        }
+      }
+    }
+    /// S             = Expr EOF
+    private ISymbolicExpressionTreeNode ParseS(Queue<Token> tokens) {
+      var expr = ParseExpr(tokens);
+
+      var endTok = tokens.Dequeue();
+      if (endTok.TokenType != TokenType.End)
+        throw new ArgumentException(string.Format("Expected end of expression (got {0})", endTok.strVal));
+
+      return expr;
+    }
+
+    /// Expr          = ['-' | '+'] Term { '+' Term | '-' Term }
+    private ISymbolicExpressionTreeNode ParseExpr(Queue<Token> tokens) {
+      var next = tokens.Peek();
+      var posTerms = new List<ISymbolicExpressionTreeNode>();
+      var negTerms = new List<ISymbolicExpressionTreeNode>();
+      bool negateFirstTerm = false;
+      if (next.TokenType == TokenType.Operator && (next.strVal == "+" || next.strVal == "-")) {
+        tokens.Dequeue();
+        if (next.strVal == "-")
+          negateFirstTerm = true;
+      }
+      var t = ParseTerm(tokens);
+      if (negateFirstTerm) negTerms.Add(t);
+      else posTerms.Add(t);
+
+      next = tokens.Peek();
+      while (next.strVal == "+" || next.strVal == "-") {
+        switch (next.strVal) {
+          case "+": {
+              tokens.Dequeue();
+              var term = ParseTerm(tokens);
+              posTerms.Add(term);
+              break;
+            }
+          case "-": {
+              tokens.Dequeue();
+              var term = ParseTerm(tokens);
+              negTerms.Add(term);
+              break;
+            }
+        }
+        next = tokens.Peek();
+      }
+
+      var sum = GetSymbol("+").CreateTreeNode();
+      foreach (var posTerm in posTerms) sum.AddSubtree(posTerm);
+      if (negTerms.Any()) {
+        if (negTerms.Count == 1) {
+          var sub = GetSymbol("-").CreateTreeNode();
+          sub.AddSubtree(negTerms.Single());
+          sum.AddSubtree(sub);
+        } else {
+          var sumNeg = GetSymbol("+").CreateTreeNode();
+          foreach (var negTerm in negTerms) sumNeg.AddSubtree(negTerm);
+
+          var constNode = (ConstantTreeNode)constant.CreateTreeNode();
+          constNode.Value = -1.0;
+          var prod = GetSymbol("*").CreateTreeNode();
+          prod.AddSubtree(constNode);
+          prod.AddSubtree(sumNeg);
+
+          sum.AddSubtree(prod);
+        }
+      }
+      if (sum.SubtreeCount == 1) return sum.Subtrees.First();
+      else return sum;
+    }
+
+    private ISymbol GetSymbol(string tok) {
+      var symb = knownSymbols.GetByFirst(tok).FirstOrDefault();
+      if (symb == null) throw new ArgumentException(string.Format("Unknown token {0} found.", tok));
+      return symb;
+    }
+
+    /// Term          = Fact { '*' Fact | '/' Fact }
+    private ISymbolicExpressionTreeNode ParseTerm(Queue<Token> tokens) {
+      var factors = new List<ISymbolicExpressionTreeNode>();
+      var firstFactor = ParseFact(tokens);
+      factors.Add(firstFactor);
+
+      var next = tokens.Peek();
+      while (next.strVal == "*" || next.strVal == "/") {
+        switch (next.strVal) {
+          case "*": {
+              tokens.Dequeue();
+              var fact = ParseFact(tokens);
+              factors.Add(fact);
+              break;
+            }
+          case "/": {
+              tokens.Dequeue();
+              var invFact = ParseFact(tokens);
+              var divNode = GetSymbol("/").CreateTreeNode(); // 1/x
+              divNode.AddSubtree(invFact);
+              factors.Add(divNode);
+              break;
+            }
+        }
+
+        next = tokens.Peek();
+      }
+      if (factors.Count == 1) return factors.First();
+      else {
+        var prod = GetSymbol("*").CreateTreeNode();
+        foreach (var f in factors) prod.AddSubtree(f);
+        return prod;
+      }
+    }
+
+    /// Fact          = '(' Expr ')' 
+    ///                 | 'LAG' '(' varId ',' ['+' | '-' ] number ')' 
+    ///                 | funcId '(' ArgList ')' 
+    ///                 | VarExpr | number
+    /// ArgList       = Expr { ',' Expr }
+    /// VarExpr       = varId OptFactorPart
+    /// OptFactorPart = [ ('=' varVal | '[' ['+' | '-' ] number {',' ['+' | '-' ] number } ']' ) ]
+    /// varId         =  ident | ' ident ' | " ident "
+    /// varVal        =  ident | ' ident ' | " ident "
+    /// ident         =  '_' | letter { '_' | letter | digit }
+    private ISymbolicExpressionTreeNode ParseFact(Queue<Token> tokens) {
+      var next = tokens.Peek();
+      if (next.TokenType == TokenType.LeftPar) {
+        tokens.Dequeue();
+        var expr = ParseExpr(tokens);
+        var rPar = tokens.Dequeue();
+        if (rPar.TokenType != TokenType.RightPar)
+          throw new ArgumentException("expected )");
+        return expr;
+      } else if (next.TokenType == TokenType.Identifier) {
+        var idTok = tokens.Dequeue();
+        if (tokens.Peek().TokenType == TokenType.LeftPar) {
+          // function identifier or LAG
+          var funcId = idTok.strVal.ToUpperInvariant();
+
+          var funcNode = GetSymbol(funcId).CreateTreeNode();
+          var lPar = tokens.Dequeue();
+          if (lPar.TokenType != TokenType.LeftPar)
+            throw new ArgumentException("expected (");
+
+          // handle 'lag' specifically
+          if (funcNode.Symbol is LaggedVariable) {
+            var varId = tokens.Dequeue();
+            if (varId.TokenType != TokenType.Identifier) throw new ArgumentException("Identifier expected. Format for lagged variables: \"lag(x, -1)\"");
+            var comma = tokens.Dequeue();
+            if (comma.TokenType != TokenType.Comma) throw new ArgumentException("',' expected, Format for lagged variables: \"lag(x, -1)\"");
+            double sign = 1.0;
+            if (tokens.Peek().strVal == "+" || tokens.Peek().strVal == "-") {
+              // read sign
+              var signTok = tokens.Dequeue();
+              if (signTok.strVal == "-") sign = -1.0;
+            }
+            var lagToken = tokens.Dequeue();
+            if (lagToken.TokenType != TokenType.Number) throw new ArgumentException("Number expected, Format for lagged variables: \"lag(x, -1)\"");
+            if (!lagToken.doubleVal.IsAlmost(Math.Round(lagToken.doubleVal)))
+              throw new ArgumentException("Time lags must be integer values");
+            var laggedVarNode = funcNode as LaggedVariableTreeNode;
+            laggedVarNode.VariableName = varId.strVal;
+            laggedVarNode.Lag = (int)Math.Round(sign * lagToken.doubleVal);
+            laggedVarNode.Weight = 1.0;
+          } else {
+            // functions
+            var args = ParseArgList(tokens);
+            // check number of arguments
+            if (funcNode.Symbol.MinimumArity > args.Length || funcNode.Symbol.MaximumArity < args.Length) {
+              throw new ArgumentException(string.Format("Symbol {0} requires between {1} and  {2} arguments.", funcId,
+                funcNode.Symbol.MinimumArity, funcNode.Symbol.MaximumArity));
+            }
+            foreach (var arg in args) funcNode.AddSubtree(arg);
+          }
+
+          var rPar = tokens.Dequeue();
+          if (rPar.TokenType != TokenType.RightPar)
+            throw new ArgumentException("expected )");
+
+          return funcNode;
+        } else {
+          // variable
+          if (tokens.Peek().TokenType == TokenType.Eq) {
+            // binary factor
+            tokens.Dequeue(); // skip Eq
+            var valTok = tokens.Dequeue();
+            if (valTok.TokenType != TokenType.Identifier) throw new ArgumentException("expected identifier");
+            var binFactorNode = (BinaryFactorVariableTreeNode)binaryFactorVar.CreateTreeNode();
+            binFactorNode.Weight = 1.0;
+            binFactorNode.VariableName = idTok.strVal;
+            binFactorNode.VariableValue = valTok.strVal;
+            return binFactorNode;
+          } else if (tokens.Peek().TokenType == TokenType.LeftBracket) {
+            // factor variable
+            var factorVariableNode = (FactorVariableTreeNode)factorVar.CreateTreeNode();
+            factorVariableNode.VariableName = idTok.strVal;
+
+            tokens.Dequeue(); // skip [
+            var weights = new List<double>();
+            // at least one weight is necessary
+            var sign = 1.0;
+            if (tokens.Peek().TokenType == TokenType.Operator) {
+              var opToken = tokens.Dequeue();
+              if (opToken.strVal == "+") sign = 1.0;
+              else if (opToken.strVal == "-") sign = -1.0;
+              else throw new ArgumentException();
+            }
+            if (tokens.Peek().TokenType != TokenType.Number) throw new ArgumentException("number expected");
+            var weightTok = tokens.Dequeue();
+            weights.Add(sign * weightTok.doubleVal);
+            while (tokens.Peek().TokenType == TokenType.Comma) {
+              // skip comma
+              tokens.Dequeue();
+              if (tokens.Peek().TokenType == TokenType.Operator) {
+                var opToken = tokens.Dequeue();
+                if (opToken.strVal == "+") sign = 1.0;
+                else if (opToken.strVal == "-") sign = -1.0;
+                else throw new ArgumentException();
+              }
+              weightTok = tokens.Dequeue();
+              if (weightTok.TokenType != TokenType.Number) throw new ArgumentException("number expected");
+              weights.Add(sign * weightTok.doubleVal);
+            }
+            var rightBracketToken = tokens.Dequeue();
+            if (rightBracketToken.TokenType != TokenType.RightBracket) throw new ArgumentException("closing bracket ] expected");
+            factorVariableNode.Weights = weights.ToArray();
+            return factorVariableNode;
+          } else {
+            // variable
+            var varNode = (VariableTreeNode)variable.CreateTreeNode();
+            varNode.Weight = 1.0;
+            varNode.VariableName = idTok.strVal;
+            return varNode;
+          }
+        }
+      } else if (next.TokenType == TokenType.Number) {
+        var numTok = tokens.Dequeue();
+        var constNode = (ConstantTreeNode)constant.CreateTreeNode();
+        constNode.Value = numTok.doubleVal;
+        return constNode;
+      } else {
+        throw new ArgumentException(string.Format("unexpected token in expression {0}", next.strVal));
+      }
+    }
+
+    // ArgList = Expr { ',' Expr }
+    private ISymbolicExpressionTreeNode[] ParseArgList(Queue<Token> tokens) {
+      var exprList = new List<ISymbolicExpressionTreeNode>();
+      exprList.Add(ParseExpr(tokens));
+      while (tokens.Peek().TokenType != TokenType.RightPar) {
+        var comma = tokens.Dequeue();
+        if (comma.TokenType != TokenType.Comma) throw new ArgumentException("expected ',' ");
+        exprList.Add(ParseExpr(tokens));
+      }
+      return exprList.ToArray();
+    }
+  }
+}
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Importer/SymbolicExpressionImporter.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Importer/SymbolicExpressionImporter.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Importer/SymbolicExpressionImporter.cs	(revision 15973)
@@ -1,5 +1,5 @@
 #region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
@@ -35,5 +35,5 @@
     private const string INVOKESTART = "CALL";
     private const string TIMELAGSTART = "LAG";
-    private Dictionary<string, Symbol> knownSymbols = new Dictionary<string, Symbol>() 
+    private Dictionary<string, Symbol> knownSymbols = new Dictionary<string, Symbol>()
       {
         {"+", new Addition()},
@@ -45,4 +45,6 @@
         {"POW", new Power()},
         {"ROOT", new Root()},
+        {"SQR", new Square()},
+        {"SQRT", new SquareRoot()},
         {"SIN",new Sine()},
         {"COS", new Cosine()},
@@ -74,4 +76,6 @@
         {"PROG", new ProgramRootSymbol()},
         {"MAIN", new StartSymbol()},
+        {"FACTOR", new FactorVariable() },
+        {"BINFACTOR", new BinaryFactorVariable()}
       };
 
@@ -82,4 +86,6 @@
     TimeLag timeLag = new TimeLag();
     Integral integral = new Integral();
+    FactorVariable factorVar = new FactorVariable();
+    BinaryFactorVariable binFactorVar = new BinaryFactorVariable();
 
     ProgramRootSymbol programRootSymbol = new ProgramRootSymbol();
@@ -136,4 +142,8 @@
             tree.AddSubtree(ParseSexp(tokens));
           }
+        } else if (tokens.Peek().StringValue.StartsWith("FACTOR")) {
+          tree = ParseFactor(tokens);
+        } else if (tokens.Peek().StringValue.StartsWith("BINFACTOR")) {
+          tree = ParseBinaryFactor(tokens);
         } else {
           Token curToken = tokens.Dequeue();
@@ -201,4 +211,48 @@
     }
 
+    private ISymbolicExpressionTreeNode ParseFactor(Queue<Token> tokens) {
+      Token tok = tokens.Dequeue();
+      Debug.Assert(tok.StringValue == "FACTOR");
+      FactorVariableTreeNode t = (FactorVariableTreeNode)(new FactorVariable()).CreateTreeNode(); // create a new symbol each time on purpose
+      var varNameTok = tokens.Dequeue();
+      Debug.Assert(tok.Symbol == TokenSymbol.SYMB);
+      t.VariableName = varNameTok.StringValue;
+
+      var weights = new List<double>();
+      while (tokens.Peek().Symbol == TokenSymbol.NUMBER) {
+        weights.Add(tokens.Dequeue().DoubleValue);
+      }
+
+      t.Weights = weights.ToArray();
+
+      // create a set of (virtual) values to match the number of weights
+      t.Symbol.VariableNames = new string[] { t.VariableName };
+      t.Symbol.VariableValues = new[]
+      { new KeyValuePair<string, Dictionary<string,int>>(
+        t.VariableName,
+        weights.Select((_, i) => Tuple.Create(_,i)).ToDictionary(tup=>"X" + tup.Item2, tup=>tup.Item2)) };
+      return t;
+    }
+
+    private ISymbolicExpressionTreeNode ParseBinaryFactor(Queue<Token> tokens) {
+      Token tok = tokens.Dequeue();
+      Debug.Assert(tok.StringValue == "BINFACTOR");
+      var t = (BinaryFactorVariableTreeNode)binFactorVar.CreateTreeNode();
+      var varNameTok = tokens.Dequeue();
+      Debug.Assert(varNameTok.Symbol == TokenSymbol.SYMB);
+      t.VariableName = varNameTok.StringValue;
+
+      var varValTok = tokens.Dequeue();
+      Debug.Assert(varValTok.Symbol == TokenSymbol.SYMB);
+      t.VariableValue = varValTok.StringValue;
+
+      var weightTok = tokens.Dequeue();
+      Debug.Assert(weightTok.Symbol == TokenSymbol.NUMBER);
+      t.Weight = weightTok.DoubleValue;
+
+      return t;
+    }
+
+
     private ISymbolicExpressionTreeNode ParseLaggedVariable(Queue<Token> tokens) {
       Token varTok = tokens.Dequeue();
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Importer/Token.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Importer/Token.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Importer/Token.cs	(revision 15973)
@@ -1,5 +1,5 @@
 #region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/IModelBacktransformator.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/IModelBacktransformator.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/IModelBacktransformator.cs	(revision 15973)
@@ -1,5 +1,5 @@
 ﻿#region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/ISymbolicDataAnalysisAnalyzer.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/ISymbolicDataAnalysisAnalyzer.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/ISymbolicDataAnalysisAnalyzer.cs	(revision 15973)
@@ -1,5 +1,5 @@
 ﻿#region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/ISymbolicDataAnalysisBoundedOperator.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/ISymbolicDataAnalysisBoundedOperator.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/ISymbolicDataAnalysisBoundedOperator.cs	(revision 15973)
@@ -1,5 +1,5 @@
 ﻿#region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/ISymbolicDataAnalysisEvaluator.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/ISymbolicDataAnalysisEvaluator.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/ISymbolicDataAnalysisEvaluator.cs	(revision 15973)
@@ -1,5 +1,5 @@
 ﻿#region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/ISymbolicDataAnalysisExpressionCrossover.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/ISymbolicDataAnalysisExpressionCrossover.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/ISymbolicDataAnalysisExpressionCrossover.cs	(revision 15973)
@@ -1,5 +1,5 @@
 ﻿#region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/ISymbolicDataAnalysisExpressionTreeInterpreter.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/ISymbolicDataAnalysisExpressionTreeInterpreter.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/ISymbolicDataAnalysisExpressionTreeInterpreter.cs	(revision 15973)
@@ -1,5 +1,5 @@
 ﻿#region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/ISymbolicDataAnalysisGrammar.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/ISymbolicDataAnalysisGrammar.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/ISymbolicDataAnalysisGrammar.cs	(revision 15973)
@@ -1,5 +1,5 @@
 ﻿#region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/ISymbolicDataAnalysisImpactValuesCalculator.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/ISymbolicDataAnalysisImpactValuesCalculator.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/ISymbolicDataAnalysisImpactValuesCalculator.cs	(revision 15973)
@@ -5,6 +5,4 @@
 namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
   public interface ISymbolicDataAnalysisSolutionImpactValuesCalculator : IItem {
-    double CalculateReplacementValue(ISymbolicDataAnalysisModel model, ISymbolicExpressionTreeNode node, IDataAnalysisProblemData problemData, IEnumerable<int> rows);
-    double CalculateImpactValue(ISymbolicDataAnalysisModel model, ISymbolicExpressionTreeNode node, IDataAnalysisProblemData problemData, IEnumerable<int> rows, double qualityForImpactsCalculation = double.NaN);
     void CalculateImpactAndReplacementValues(ISymbolicDataAnalysisModel model, ISymbolicExpressionTreeNode node, IDataAnalysisProblemData problemData,
       IEnumerable<int> rows, out double impactValue, out double replacementValue, out double newQualityForImpactsCalculation, double qualityForImpactsCalculation = double.NaN);
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/ISymbolicDataAnalysisInterpreterOperator.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/ISymbolicDataAnalysisInterpreterOperator.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/ISymbolicDataAnalysisInterpreterOperator.cs	(revision 15973)
@@ -1,5 +1,5 @@
 ﻿#region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/ISymbolicDataAnalysisModel.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/ISymbolicDataAnalysisModel.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/ISymbolicDataAnalysisModel.cs	(revision 15973)
@@ -1,5 +1,5 @@
 ﻿#region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/ISymbolicDataAnalysisMultiObjectiveAnalyzer.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/ISymbolicDataAnalysisMultiObjectiveAnalyzer.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/ISymbolicDataAnalysisMultiObjectiveAnalyzer.cs	(revision 15973)
@@ -1,5 +1,5 @@
 ﻿#region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/ISymbolicDataAnalysisMultiObjectiveEvaluator.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/ISymbolicDataAnalysisMultiObjectiveEvaluator.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/ISymbolicDataAnalysisMultiObjectiveEvaluator.cs	(revision 15973)
@@ -1,5 +1,5 @@
 ﻿#region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/ISymbolicDataAnalysisProblem.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/ISymbolicDataAnalysisProblem.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/ISymbolicDataAnalysisProblem.cs	(revision 15973)
@@ -1,5 +1,5 @@
 ﻿#region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/ISymbolicDataAnalysisSingleObjectiveAnalyzer.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/ISymbolicDataAnalysisSingleObjectiveAnalyzer.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/ISymbolicDataAnalysisSingleObjectiveAnalyzer.cs	(revision 15973)
@@ -1,5 +1,5 @@
 ﻿#region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/ISymbolicDataAnalysisSingleObjectiveEvaluator.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/ISymbolicDataAnalysisSingleObjectiveEvaluator.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/ISymbolicDataAnalysisSingleObjectiveEvaluator.cs	(revision 15973)
@@ -1,5 +1,5 @@
 ﻿#region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/ISymbolicDataAnalysisSolution.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/ISymbolicDataAnalysisSolution.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/ISymbolicDataAnalysisSolution.cs	(revision 15973)
@@ -1,5 +1,5 @@
 ﻿#region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/ISymbolicDataAnalysisSolutionCreator.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/ISymbolicDataAnalysisSolutionCreator.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/ISymbolicDataAnalysisSolutionCreator.cs	(revision 15973)
@@ -1,5 +1,5 @@
 ﻿#region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/ISymbolicDataAnalysisValidationAnalyzer.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/ISymbolicDataAnalysisValidationAnalyzer.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/ISymbolicDataAnalysisValidationAnalyzer.cs	(revision 15973)
@@ -1,5 +1,5 @@
 ﻿#region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/IVariableSymbol.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/IVariableSymbol.cs	(revision 15973)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/IVariableSymbol.cs	(revision 15973)
@@ -0,0 +1,30 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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 HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
+
+  /// <summary>
+  /// Any symbol that references a variable (includes terminal as well as non-terminal symbols)
+  /// </summary>
+  public interface IVariableSymbol : ISymbol {
+  }
+}
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/IVariableTreeNode.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/IVariableTreeNode.cs	(revision 15973)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/IVariableTreeNode.cs	(revision 15973)
@@ -0,0 +1,30 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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 HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
+  /// <summary>
+  /// Any tree node that references a variable 
+  /// </summary>
+  public interface IVariableTreeNode : ISymbolicExpressionTreeNode {
+    string VariableName { get; }
+  }
+}
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/InterpreterState.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/InterpreterState.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/InterpreterState.cs	(revision 15973)
@@ -1,5 +1,5 @@
 ﻿#region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/OpCodes.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/OpCodes.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/OpCodes.cs	(revision 15973)
@@ -1,5 +1,5 @@
 ﻿#region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
@@ -83,4 +83,7 @@
     public const byte Erf = 43;
     public const byte Bessel = 44;
+    public const byte FactorVariable = 46;
+    public const byte BinaryFactorVariable = 47;
+
 
     private static Dictionary<Type, byte> symbolToOpcode = new Dictionary<Type, byte>() {
@@ -130,5 +133,7 @@
       { typeof(Norm), OpCodes.Norm},
       { typeof(Erf), OpCodes.Erf},
-      { typeof(Bessel), OpCodes.Bessel}   
+      { typeof(Bessel), OpCodes.Bessel},
+      { typeof(FactorVariable), OpCodes.FactorVariable },
+      { typeof(BinaryFactorVariable), OpCodes.BinaryFactorVariable }
     };
 
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionCompiledTreeInterpreter.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionCompiledTreeInterpreter.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionCompiledTreeInterpreter.cs	(revision 15973)
@@ -1,5 +1,5 @@
 ﻿#region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
@@ -614,4 +614,5 @@
         case OpCodes.VariableCondition: {
             var variableConditionTreeNode = (VariableConditionTreeNode)node;
+            if (variableConditionTreeNode.Symbol.IgnoreSlope) throw new NotSupportedException("Strict variable conditionals are not supported");
             var variableName = variableConditionTreeNode.VariableName;
             var indexExpr = Expression.Constant(variableIndices[variableName]);
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeILEmittingInterpreter.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeILEmittingInterpreter.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeILEmittingInterpreter.cs	(revision 15973)
@@ -1,5 +1,5 @@
 ﻿#region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
@@ -66,4 +66,5 @@
     private static MethodInfo erf = thisType.GetMethod("Erf", new Type[] { typeof(double) });
     private static MethodInfo bessel = thisType.GetMethod("Bessel", new Type[] { typeof(double) });
+    private static MethodInfo string_eq = typeof(string).GetMethod("Equals", new Type[] { typeof(string) });
     #endregion
 
@@ -259,5 +260,5 @@
               il.Emit(System.Reflection.Emit.OpCodes.Add);
             }
-            il.Emit(System.Reflection.Emit.OpCodes.Ldc_I4, nArgs);
+            il.Emit(System.Reflection.Emit.OpCodes.Ldc_R8, (double)nArgs);
             il.Emit(System.Reflection.Emit.OpCodes.Div);
             return;
@@ -457,4 +458,5 @@
             il.Emit(System.Reflection.Emit.OpCodes.Ldc_I4_0); // > 0
             il.Emit(System.Reflection.Emit.OpCodes.Cgt);
+            il.Emit(System.Reflection.Emit.OpCodes.Conv_R8); // convert to float64
             il.Emit(System.Reflection.Emit.OpCodes.Ldc_R8, 2.0); // * 2
             il.Emit(System.Reflection.Emit.OpCodes.Mul);
@@ -475,4 +477,6 @@
               il.Emit(System.Reflection.Emit.OpCodes.Xor);
             }
+            il.Emit(System.Reflection.Emit.OpCodes.Conv_R8); // convert to float64
+
             il.Emit(System.Reflection.Emit.OpCodes.Ldc_R8, 2.0); // * 2
             il.Emit(System.Reflection.Emit.OpCodes.Mul);
@@ -486,4 +490,5 @@
 
             il.Emit(System.Reflection.Emit.OpCodes.Cgt); // 1 (>) / 0 (otherwise)
+            il.Emit(System.Reflection.Emit.OpCodes.Conv_R8); // convert to float64
             il.Emit(System.Reflection.Emit.OpCodes.Ldc_R8, 2.0); // * 2
             il.Emit(System.Reflection.Emit.OpCodes.Mul);
@@ -496,4 +501,5 @@
             CompileInstructions(il, state, ds);
             il.Emit(System.Reflection.Emit.OpCodes.Clt);
+            il.Emit(System.Reflection.Emit.OpCodes.Conv_R8); // convert to float64
             il.Emit(System.Reflection.Emit.OpCodes.Ldc_R8, 2.0); // * 2
             il.Emit(System.Reflection.Emit.OpCodes.Mul);
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeInterpreter.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeInterpreter.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeInterpreter.cs	(revision 15973)
@@ -1,5 +1,5 @@
 ﻿#region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
@@ -22,4 +22,5 @@
 using System;
 using System.Collections.Generic;
+using System.Linq;
 using HeuristicLab.Common;
 using HeuristicLab.Core;
@@ -143,4 +144,10 @@
           var variableTreeNode = (VariableTreeNode)instr.dynamicNode;
           instr.data = dataset.GetReadOnlyDoubleValues(variableTreeNode.VariableName);
+        } else if (instr.opCode == OpCodes.FactorVariable) {
+          var factorTreeNode = instr.dynamicNode as FactorVariableTreeNode;
+          instr.data = dataset.GetReadOnlyStringValues(factorTreeNode.VariableName);
+        } else if (instr.opCode == OpCodes.BinaryFactorVariable) {
+          var factorTreeNode = instr.dynamicNode as BinaryFactorVariableTreeNode;
+          instr.data = dataset.GetReadOnlyStringValues(factorTreeNode.VariableName);
         } else if (instr.opCode == OpCodes.LagVariable) {
           var laggedVariableTreeNode = (LaggedVariableTreeNode)instr.dynamicNode;
@@ -455,4 +462,14 @@
             return ((IList<double>)currentInstr.data)[row] * variableTreeNode.Weight;
           }
+        case OpCodes.BinaryFactorVariable: {
+            if (row < 0 || row >= dataset.Rows) return double.NaN;
+            var factorVarTreeNode = currentInstr.dynamicNode as BinaryFactorVariableTreeNode;
+            return ((IList<string>)currentInstr.data)[row] == factorVarTreeNode.VariableValue ? factorVarTreeNode.Weight : 0;
+          }
+        case OpCodes.FactorVariable: {
+            if (row < 0 || row >= dataset.Rows) return double.NaN;
+            var factorVarTreeNode = currentInstr.dynamicNode as FactorVariableTreeNode;
+            return factorVarTreeNode.GetValue(((IList<string>)currentInstr.data)[row]);
+          }
         case OpCodes.LagVariable: {
             var laggedVariableTreeNode = (LaggedVariableTreeNode)currentInstr.dynamicNode;
@@ -471,12 +488,25 @@
             if (row < 0 || row >= dataset.Rows) return double.NaN;
             var variableConditionTreeNode = (VariableConditionTreeNode)currentInstr.dynamicNode;
-            double variableValue = ((IList<double>)currentInstr.data)[row];
-            double x = variableValue - variableConditionTreeNode.Threshold;
-            double p = 1 / (1 + Math.Exp(-variableConditionTreeNode.Slope * x));
-
-            double trueBranch = Evaluate(dataset, ref row, state);
-            double falseBranch = Evaluate(dataset, ref row, state);
-
-            return trueBranch * p + falseBranch * (1 - p);
+            if (!variableConditionTreeNode.Symbol.IgnoreSlope) {
+              double variableValue = ((IList<double>)currentInstr.data)[row];
+              double x = variableValue - variableConditionTreeNode.Threshold;
+              double p = 1 / (1 + Math.Exp(-variableConditionTreeNode.Slope * x));
+
+              double trueBranch = Evaluate(dataset, ref row, state);
+              double falseBranch = Evaluate(dataset, ref row, state);
+
+              return trueBranch * p + falseBranch * (1 - p);
+            } else {
+              // strict threshold
+              double variableValue = ((IList<double>)currentInstr.data)[row];
+              if (variableValue <= variableConditionTreeNode.Threshold) {
+                var left = Evaluate(dataset, ref row, state);
+                state.SkipInstructions();
+                return left;
+              } else {
+                state.SkipInstructions();
+                return Evaluate(dataset, ref row, state);
+              }
+            }
           }
         default:
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeLinearInterpreter.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeLinearInterpreter.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeLinearInterpreter.cs	(revision 15973)
@@ -1,5 +1,5 @@
 ﻿#region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
@@ -38,5 +38,5 @@
     private const string EvaluatedSolutionsParameterName = "EvaluatedSolutions";
 
-    private SymbolicDataAnalysisExpressionTreeInterpreter interpreter;
+    private readonly SymbolicDataAnalysisExpressionTreeInterpreter interpreter;
 
     public override bool CanChangeName {
@@ -72,4 +72,5 @@
     private SymbolicDataAnalysisExpressionTreeLinearInterpreter(bool deserializing)
       : base(deserializing) {
+      interpreter = new SymbolicDataAnalysisExpressionTreeInterpreter();
     }
 
@@ -125,4 +126,5 @@
     private readonly object syncRoot = new object();
     public IEnumerable<double> GetSymbolicExpressionTreeValues(ISymbolicExpressionTree tree, IDataset dataset, IEnumerable<int> rows) {
+      if (!rows.Any()) return Enumerable.Empty<double>();
       if (CheckExpressionsWithIntervalArithmetic)
         throw new NotSupportedException("Interval arithmetic is not yet supported in the symbolic data analysis interpreter.");
@@ -147,4 +149,16 @@
             var variableTreeNode = (VariableTreeNode)instr.dynamicNode;
             instr.value = ((IList<double>)instr.data)[row] * variableTreeNode.Weight;
+          }
+        } else if (instr.opCode == OpCodes.BinaryFactorVariable) {
+          if (row < 0 || row >= dataset.Rows) instr.value = double.NaN;
+          else {
+            var factorTreeNode = instr.dynamicNode as BinaryFactorVariableTreeNode;
+            instr.value = ((IList<string>)instr.data)[row] == factorTreeNode.VariableValue ? factorTreeNode.Weight : 0;
+          }
+        } else if (instr.opCode == OpCodes.FactorVariable) {
+          if (row < 0 || row >= dataset.Rows) instr.value = double.NaN;
+          else {
+            var factorTreeNode = instr.dynamicNode as FactorVariableTreeNode;
+            instr.value = factorTreeNode.GetValue(((IList<string>)instr.data)[row]);
           }
         } else if (instr.opCode == OpCodes.LagVariable) {
@@ -158,12 +172,21 @@
           if (row < 0 || row >= dataset.Rows) instr.value = double.NaN;
           var variableConditionTreeNode = (VariableConditionTreeNode)instr.dynamicNode;
-          double variableValue = ((IList<double>)instr.data)[row];
-          double x = variableValue - variableConditionTreeNode.Threshold;
-          double p = 1 / (1 + Math.Exp(-variableConditionTreeNode.Slope * x));
-
-          double trueBranch = code[instr.childIndex].value;
-          double falseBranch = code[instr.childIndex + 1].value;
-
-          instr.value = trueBranch * p + falseBranch * (1 - p);
+          if (!variableConditionTreeNode.Symbol.IgnoreSlope) {
+            double variableValue = ((IList<double>)instr.data)[row];
+            double x = variableValue - variableConditionTreeNode.Threshold;
+            double p = 1 / (1 + Math.Exp(-variableConditionTreeNode.Slope * x));
+
+            double trueBranch = code[instr.childIndex].value;
+            double falseBranch = code[instr.childIndex + 1].value;
+
+            instr.value = trueBranch * p + falseBranch * (1 - p);
+          } else {
+            double variableValue = ((IList<double>)instr.data)[row];
+            if (variableValue <= variableConditionTreeNode.Threshold) {
+              instr.value = code[instr.childIndex].value;
+            } else {
+              instr.value = code[instr.childIndex + 1].value;
+            }
+          }
         } else if (instr.opCode == OpCodes.Add) {
           double s = code[instr.childIndex].value;
@@ -392,4 +415,14 @@
             }
             break;
+          case OpCodes.BinaryFactorVariable: {
+              var factorVariableTreeNode = instr.dynamicNode as BinaryFactorVariableTreeNode;
+              instr.data = dataset.GetReadOnlyStringValues(factorVariableTreeNode.VariableName);
+            }
+            break;
+          case OpCodes.FactorVariable: {
+              var factorVariableTreeNode = instr.dynamicNode as FactorVariableTreeNode;
+              instr.data = dataset.GetReadOnlyStringValues(factorVariableTreeNode.VariableName);
+            }
+            break;
           case OpCodes.LagVariable: {
               var laggedVariableTreeNode = (LaggedVariableTreeNode)instr.dynamicNode;
@@ -410,6 +443,6 @@
               for (int j = 1; j != seq.Length; ++j)
                 seq[j].skip = true;
-            }
-            break;
+              break;
+            }
         }
         #endregion
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Plugin.cs.frame
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Plugin.cs.frame	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Plugin.cs.frame	(revision 15973)
@@ -1,5 +1,5 @@
 #region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
@@ -26,7 +26,8 @@
 
 namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
-  [Plugin("HeuristicLab.Problems.DataAnalysis.Symbolic","Provides base classes for symbolic data analysis tasks.", "3.4.9.$WCREV$")]
+  [Plugin("HeuristicLab.Problems.DataAnalysis.Symbolic","Provides base classes for symbolic data analysis tasks.", "3.4.11.$WCREV$")]
   [PluginFile("HeuristicLab.Problems.DataAnalysis.Symbolic-3.4.dll", PluginFileType.Assembly)]
   [PluginDependency("HeuristicLab.ALGLIB", "3.7.0")]
+  [PluginDependency("HeuristicLab.AutoDiff", "1.0")]
   [PluginDependency("HeuristicLab.Analysis", "3.3")]
   [PluginDependency("HeuristicLab.Collections", "3.3")]
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Properties/AssemblyInfo.cs.frame
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Properties/AssemblyInfo.cs.frame	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Properties/AssemblyInfo.cs.frame	(revision 15973)
@@ -1,5 +1,5 @@
 #region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
@@ -31,5 +31,5 @@
 [assembly: AssemblyCompany("")]
 [assembly: AssemblyProduct("HeuristicLab")]
-[assembly: AssemblyCopyright("(c) 2002-2015 HEAL")]
+[assembly: AssemblyCopyright("(c) 2002-2018 HEAL")]
 [assembly: AssemblyTrademark("")]
 [assembly: AssemblyCulture("")]
@@ -53,3 +53,3 @@
 // by using the '*' as shown below:
 [assembly: AssemblyVersion("3.4.0.0")]
-[assembly: AssemblyFileVersion("3.4.9.$WCREV$")]
+[assembly: AssemblyFileVersion("3.4.11.$WCREV$")]
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisExpressionPruningOperator.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisExpressionPruningOperator.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisExpressionPruningOperator.cs	(revision 15973)
@@ -2,5 +2,5 @@
 
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisExpressionTreeSimplificationOperator.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisExpressionTreeSimplificationOperator.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisExpressionTreeSimplificationOperator.cs	(revision 15973)
@@ -1,5 +1,5 @@
 ﻿#region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
@@ -37,6 +37,4 @@
     }
 
-    private readonly SymbolicDataAnalysisExpressionTreeSimplifier simplifier = new SymbolicDataAnalysisExpressionTreeSimplifier();
-
     [StorableConstructor]
     protected SymbolicDataAnalysisExpressionTreeSimplificationOperator(bool deserializing) : base(deserializing) { }
@@ -53,6 +51,6 @@
     public override IOperation Apply() {
       var tree = SymbolicExpressionTreeParameter.ActualValue;
-      var simplifiedTree = simplifier.Simplify(tree);
-      simplifiedTree = simplifier.Simplify(simplifiedTree);
+      var simplifiedTree = TreeSimplifier.Simplify(tree);
+      simplifiedTree = TreeSimplifier.Simplify(simplifiedTree);
       SymbolicExpressionTreeParameter.ActualValue = simplifiedTree;
 
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisExpressionTreeSimplifier.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisExpressionTreeSimplifier.cs	(revision 15651)
+++ 	(revision )
@@ -1,1055 +1,0 @@
-﻿#region License Information
-/* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
- *
- * This file is part of HeuristicLab.
- *
- * HeuristicLab is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * HeuristicLab is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
- */
-#endregion
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using HeuristicLab.Common;
-using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
-
-namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
-  /// <summary>
-  /// Simplifier for symbolic expressions
-  /// </summary>
-  public class SymbolicDataAnalysisExpressionTreeSimplifier {
-    private Addition addSymbol = new Addition();
-    private 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: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisModel.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisModel.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisModel.cs	(revision 15973)
@@ -1,5 +1,5 @@
 #region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
@@ -21,5 +21,7 @@
 
 using System;
+using System.Collections.Generic;
 using System.Drawing;
+using System.Linq;
 using HeuristicLab.Common;
 using HeuristicLab.Core;
@@ -56,4 +58,17 @@
       get { return interpreter; }
     }
+
+    public IEnumerable<string> VariablesUsedForPrediction {
+      get {
+        var variables =
+          SymbolicExpressionTree.IterateNodesPrefix()
+            .OfType<IVariableTreeNode>()
+            .Select(x => x.VariableName)
+            .Distinct();
+
+        return variables.OrderBy(x => x);
+      }
+    }
+
     #endregion
 
@@ -160,4 +175,5 @@
     }
     #endregion
+
   }
 }
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisModelComplexityCalculator.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisModelComplexityCalculator.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisModelComplexityCalculator.cs	(revision 15973)
@@ -2,5 +2,5 @@
 
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
@@ -39,8 +39,10 @@
             return 1;
           }
-        case OpCodes.Variable: {
+        case OpCodes.Variable:
+        case OpCodes.BinaryFactorVariable:
+        case OpCodes.FactorVariable: {
             return 2;
           }
-        case OpCodes.Add: 
+        case OpCodes.Add:
         case OpCodes.Sub: {
             double complexity = 0;
@@ -50,5 +52,5 @@
             return complexity;
           }
-        case OpCodes.Mul: 
+        case OpCodes.Mul:
         case OpCodes.Div: {
             double complexity = 1;
@@ -60,7 +62,7 @@
           }
         case OpCodes.Sin:
-        case OpCodes.Cos: 
+        case OpCodes.Cos:
         case OpCodes.Tan:
-        case OpCodes.Exp: 
+        case OpCodes.Exp:
         case OpCodes.Log: {
             double complexity = CalculateComplexity(node.GetSubtree(0));
@@ -75,5 +77,5 @@
             return complexity * complexity * complexity;
           }
-        case OpCodes.Power:          
+        case OpCodes.Power:
         case OpCodes.Root: {
             double complexity = CalculateComplexity(node.GetSubtree(0));
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisMultiObjectiveProblem.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisMultiObjectiveProblem.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisMultiObjectiveProblem.cs	(revision 15973)
@@ -1,5 +1,5 @@
 ﻿#region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisProblem.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisProblem.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisProblem.cs	(revision 15973)
@@ -1,5 +1,5 @@
 ﻿#region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
@@ -21,4 +21,5 @@
 
 using System;
+using System.Collections.Generic;
 using System.Drawing;
 using System.Linq;
@@ -208,29 +209,54 @@
 
     protected virtual void UpdateGrammar() {
-      SymbolicExpressionTreeGrammar.MaximumFunctionArguments = MaximumFunctionArguments.Value;
-      SymbolicExpressionTreeGrammar.MaximumFunctionDefinitions = MaximumFunctionDefinitions.Value;
-      foreach (var varSymbol in SymbolicExpressionTreeGrammar.Symbols.OfType<HeuristicLab.Problems.DataAnalysis.Symbolic.Variable>()) {
+      var problemData = ProblemData;
+      var ds = problemData.Dataset;
+      var grammar = SymbolicExpressionTreeGrammar;
+      grammar.MaximumFunctionArguments = MaximumFunctionArguments.Value;
+      grammar.MaximumFunctionDefinitions = MaximumFunctionDefinitions.Value;
+      foreach (var varSymbol in grammar.Symbols.OfType<HeuristicLab.Problems.DataAnalysis.Symbolic.VariableBase>()) {
         if (!varSymbol.Fixed) {
-          varSymbol.AllVariableNames = ProblemData.InputVariables.Select(x => x.Value);
-          varSymbol.VariableNames = ProblemData.AllowedInputVariables;
+          varSymbol.AllVariableNames = problemData.InputVariables.Select(x => x.Value).Where(x => ds.VariableHasType<double>(x));
+          varSymbol.VariableNames = problemData.AllowedInputVariables.Where(x => ds.VariableHasType<double>(x));
         }
       }
-      foreach (var varSymbol in SymbolicExpressionTreeGrammar.Symbols.OfType<HeuristicLab.Problems.DataAnalysis.Symbolic.VariableCondition>()) {
-        if (!varSymbol.Fixed) {
-          varSymbol.AllVariableNames = ProblemData.InputVariables.Select(x => x.Value);
-          varSymbol.VariableNames = ProblemData.AllowedInputVariables;
+      foreach (var factorSymbol in grammar.Symbols.OfType<BinaryFactorVariable>()) {
+        if (!factorSymbol.Fixed) {
+          factorSymbol.AllVariableNames = problemData.InputVariables.Select(x => x.Value).Where(x => ds.VariableHasType<string>(x));
+          factorSymbol.VariableNames = problemData.AllowedInputVariables.Where(x => ds.VariableHasType<string>(x));
+          factorSymbol.VariableValues = factorSymbol.VariableNames
+            .ToDictionary(varName => varName, varName => ds.GetStringValues(varName).Distinct().ToList());
         }
       }
+      foreach (var factorSymbol in grammar.Symbols.OfType<FactorVariable>()) {
+        if (!factorSymbol.Fixed) {
+          factorSymbol.AllVariableNames = problemData.InputVariables.Select(x => x.Value).Where(x => ds.VariableHasType<string>(x));
+          factorSymbol.VariableNames = problemData.AllowedInputVariables.Where(x => ds.VariableHasType<string>(x));
+          factorSymbol.VariableValues = factorSymbol.VariableNames
+            .ToDictionary(varName => varName,
+            varName => ds.GetStringValues(varName).Distinct()
+            .Select((n, i) => Tuple.Create(n, i))
+            .ToDictionary(tup => tup.Item1, tup => tup.Item2));
+        }
+      }
     }
 
     private void InitializeOperators() {
-      Operators.AddRange(ApplicationManager.Manager.GetInstances<ISymbolicExpressionTreeOperator>());
-      Operators.AddRange(ApplicationManager.Manager.GetInstances<ISymbolicDataAnalysisExpressionCrossover<T>>());
-      Operators.Add(new SymbolicExpressionSymbolFrequencyAnalyzer());
-      Operators.Add(new SymbolicDataAnalysisVariableFrequencyAnalyzer());
-      Operators.Add(new MinAverageMaxSymbolicExpressionTreeLengthAnalyzer());
-      Operators.Add(new SymbolicExpressionTreeLengthAnalyzer());
-      Operators.Add(new SymbolicExpressionTreeBottomUpSimilarityCalculator());
-      Operators.Add(new SymbolicDataAnalysisBottomUpDiversityAnalyzer(Operators.OfType<SymbolicExpressionTreeBottomUpSimilarityCalculator>().First()));
+      var operators = new HashSet<IItem>(new TypeEqualityComparer<IItem>());
+      operators.Add(new SubtreeCrossover());
+      operators.Add(new MultiSymbolicExpressionTreeManipulator());
+
+      foreach (var op in ApplicationManager.Manager.GetInstances<ISymbolicExpressionTreeOperator>())
+        operators.Add(op);
+      foreach (var op in ApplicationManager.Manager.GetInstances<ISymbolicDataAnalysisExpressionCrossover<T>>())
+        operators.Add(op);
+
+      operators.Add(new SymbolicExpressionSymbolFrequencyAnalyzer());
+      operators.Add(new SymbolicDataAnalysisVariableFrequencyAnalyzer());
+      operators.Add(new MinAverageMaxSymbolicExpressionTreeLengthAnalyzer());
+      operators.Add(new SymbolicExpressionTreeLengthAnalyzer());
+      operators.Add(new SymbolicExpressionTreeBottomUpSimilarityCalculator());
+      operators.Add(new SymbolicDataAnalysisBottomUpDiversityAnalyzer(operators.OfType<SymbolicExpressionTreeBottomUpSimilarityCalculator>().First()));
+
+      Operators.AddRange(operators);
       ParameterizeOperators();
     }
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisSingleObjectiveProblem.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisSingleObjectiveProblem.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisSingleObjectiveProblem.cs	(revision 15973)
@@ -1,5 +1,5 @@
 ﻿#region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
@@ -73,5 +73,5 @@
     }
 
-    public SymbolicDataAnalysisSingleObjectiveProblem(T problemData, U evaluator, V solutionCreator)
+    protected SymbolicDataAnalysisSingleObjectiveProblem(T problemData, U evaluator, V solutionCreator)
       : base(problemData, evaluator, solutionCreator) {
       Parameters.Add(new FixedValueParameter<BoolValue>(MaximizationParameterName, "Set to false if the problem should be minimized."));
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisSolutionImpactValuesCalculator.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisSolutionImpactValuesCalculator.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisSolutionImpactValuesCalculator.cs	(revision 15973)
@@ -1,5 +1,5 @@
 ﻿#region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
@@ -21,4 +21,5 @@
 
 using System.Collections.Generic;
+using System.Linq;
 using HeuristicLab.Common;
 using HeuristicLab.Core;
@@ -31,30 +32,78 @@
   public abstract class SymbolicDataAnalysisSolutionImpactValuesCalculator : Item, ISymbolicDataAnalysisSolutionImpactValuesCalculator {
     protected SymbolicDataAnalysisSolutionImpactValuesCalculator() { }
-
     protected SymbolicDataAnalysisSolutionImpactValuesCalculator(SymbolicDataAnalysisSolutionImpactValuesCalculator original, Cloner cloner)
       : base(original, cloner) { }
     [StorableConstructor]
     protected SymbolicDataAnalysisSolutionImpactValuesCalculator(bool deserializing) : base(deserializing) { }
-    public abstract double CalculateReplacementValue(ISymbolicDataAnalysisModel model, ISymbolicExpressionTreeNode node, IDataAnalysisProblemData problemData, IEnumerable<int> rows);
-    public abstract double CalculateImpactValue(ISymbolicDataAnalysisModel model, ISymbolicExpressionTreeNode node, IDataAnalysisProblemData problemData, IEnumerable<int> rows, double qualityForImpactsCalculation = double.NaN);
-    public abstract void CalculateImpactAndReplacementValues(ISymbolicDataAnalysisModel model, ISymbolicExpressionTreeNode node, IDataAnalysisProblemData problemData, IEnumerable<int> rows, out double impactValue, out double replacementValue, out double newQualityForImpactsCalculation, double qualityForImpactsCalculation = double.NaN);
 
-    protected static double CalculateReplacementValue(ISymbolicExpressionTreeNode node, ISymbolicExpressionTree sourceTree, ISymbolicDataAnalysisExpressionTreeInterpreter interpreter,
+    public virtual void CalculateImpactAndReplacementValues(ISymbolicDataAnalysisModel model, ISymbolicExpressionTreeNode node, IDataAnalysisProblemData problemData, IEnumerable<int> rows,
+        out double impactValue, out double replacementValue, out double newQualityForImpactsCalculation,
+        double qualityForImpactsCalculation = double.NaN) {
+
+      var cloner = new Cloner();
+      var tempModel = cloner.Clone(model);
+
+      if (double.IsNaN(qualityForImpactsCalculation)) {
+        qualityForImpactsCalculation = CalculateQualityForImpacts(tempModel, problemData, rows);
+      }
+
+      var tempModelNode = (ISymbolicExpressionTreeNode)cloner.GetClone(node);
+      var tempModelParentNode = tempModelNode.Parent;
+      int i = tempModelParentNode.IndexOfSubtree(tempModelNode);
+
+      double bestReplacementValue = 0.0;
+      double bestImpactValue = double.PositiveInfinity;
+      newQualityForImpactsCalculation = qualityForImpactsCalculation; // initialize
+      // try the potentially reasonable replacement values and use the best one
+      foreach (var repValue in CalculateReplacementValues(node, model.SymbolicExpressionTree, model.Interpreter, problemData.Dataset, rows)) {
+        tempModelParentNode.RemoveSubtree(i);
+
+        var constantNode = new ConstantTreeNode(new Constant()) { Value = repValue };
+        tempModelParentNode.InsertSubtree(i, constantNode);
+
+        newQualityForImpactsCalculation = CalculateQualityForImpacts(tempModel, problemData, rows);
+
+        impactValue = qualityForImpactsCalculation - newQualityForImpactsCalculation;
+        if (impactValue < bestImpactValue) {
+          bestImpactValue = impactValue;
+          bestReplacementValue = repValue;
+        }
+      }
+
+      replacementValue = bestReplacementValue;
+      impactValue = bestImpactValue;
+    }
+
+    protected abstract double CalculateQualityForImpacts(ISymbolicDataAnalysisModel model, IDataAnalysisProblemData problemData, IEnumerable<int> rows);
+
+    protected IEnumerable<double> CalculateReplacementValues(ISymbolicExpressionTreeNode node, ISymbolicExpressionTree sourceTree, ISymbolicDataAnalysisExpressionTreeInterpreter interpreter,
       IDataset dataset, IEnumerable<int> rows) {
       //optimization: constant nodes return always the same value
       ConstantTreeNode constantNode = node as ConstantTreeNode;
-      if (constantNode != null) return constantNode.Value;
+      BinaryFactorVariableTreeNode binaryFactorNode = node as BinaryFactorVariableTreeNode;
+      FactorVariableTreeNode factorNode = node as FactorVariableTreeNode;
+      if (constantNode != null) {
+        yield return constantNode.Value;
+      } else if (binaryFactorNode != null) {
+        // valid replacements are either all off or all on
+        yield return 0;
+        yield return 1;
+      } else if (factorNode != null) {
+        foreach (var w in factorNode.Weights) yield return w;
+        yield return 0.0;
+      } else {
+        var rootSymbol = new ProgramRootSymbol().CreateTreeNode();
+        var startSymbol = new StartSymbol().CreateTreeNode();
+        rootSymbol.AddSubtree(startSymbol);
+        startSymbol.AddSubtree((ISymbolicExpressionTreeNode)node.Clone());
 
-      var rootSymbol = new ProgramRootSymbol().CreateTreeNode();
-      var startSymbol = new StartSymbol().CreateTreeNode();
-      rootSymbol.AddSubtree(startSymbol);
-      startSymbol.AddSubtree((ISymbolicExpressionTreeNode)node.Clone());
-
-      var tempTree = new SymbolicExpressionTree(rootSymbol);
-      // clone ADFs of source tree
-      for (int i = 1; i < sourceTree.Root.SubtreeCount; i++) {
-        tempTree.Root.AddSubtree((ISymbolicExpressionTreeNode)sourceTree.Root.GetSubtree(i).Clone());
+        var tempTree = new SymbolicExpressionTree(rootSymbol);
+        // clone ADFs of source tree
+        for (int i = 1; i < sourceTree.Root.SubtreeCount; i++) {
+          tempTree.Root.AddSubtree((ISymbolicExpressionTreeNode)sourceTree.Root.GetSubtree(i).Clone());
+        }
+        yield return interpreter.GetSymbolicExpressionTreeValues(tempTree, dataset, rows).Median();
+        yield return interpreter.GetSymbolicExpressionTreeValues(tempTree, dataset, rows).Average(); // TODO perf
       }
-      return interpreter.GetSymbolicExpressionTreeValues(tempTree, dataset, rows).Median();
     }
   }
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicExpressionTreeBacktransformator.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicExpressionTreeBacktransformator.cs	(revision 15651)
+++ 	(revision )
@@ -1,97 +1,0 @@
-﻿#region License Information
-/* HeuristicLab
- * Copyright (C) 2002-2015 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: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Addition.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Addition.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Addition.cs	(revision 15973)
@@ -1,5 +1,5 @@
 #region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/AiryA.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/AiryA.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/AiryA.cs	(revision 15973)
@@ -1,5 +1,5 @@
 #region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/AiryB.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/AiryB.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/AiryB.cs	(revision 15973)
@@ -1,5 +1,5 @@
 #region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/And.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/And.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/And.cs	(revision 15973)
@@ -1,5 +1,5 @@
 #region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/AutoregressiveVariable.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/AutoregressiveVariable.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/AutoregressiveVariable.cs	(revision 15973)
@@ -1,5 +1,5 @@
 #region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Average.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Average.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Average.cs	(revision 15973)
@@ -1,5 +1,5 @@
 #region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Bessel.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Bessel.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Bessel.cs	(revision 15973)
@@ -1,5 +1,5 @@
 #region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/BinaryFactorVariable.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/BinaryFactorVariable.cs	(revision 15973)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/BinaryFactorVariable.cs	(revision 15973)
@@ -0,0 +1,76 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Core;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
+  [StorableClass]
+  [Item("BinaryFactorVariable", "Represents a categorical variable (comparable to factors as in R) and it's value.")]
+  public sealed class BinaryFactorVariable : VariableBase {
+
+    private readonly Dictionary<string, List<string>> variableValues;
+
+    [Storable]
+    public IEnumerable<KeyValuePair<string, List<string>>> VariableValues {
+      get { return variableValues; }
+      set {
+        if (value == null) throw new ArgumentNullException();
+        variableValues.Clear();
+        foreach (var kvp in value) {
+          variableValues.Add(kvp.Key, new List<string>(kvp.Value));
+        }
+      }
+    }
+
+    [StorableConstructor]
+    private BinaryFactorVariable(bool deserializing)
+      : base(deserializing) {
+      variableValues = new Dictionary<string, List<string>>();
+    }
+    private BinaryFactorVariable(BinaryFactorVariable original, Cloner cloner)
+      : base(original, cloner) {
+      variableValues =
+        original.variableValues.ToDictionary(kvp => kvp.Key, kvp => new List<string>(kvp.Value));
+    }
+    public BinaryFactorVariable() : this("BinaryFactorVariable", "Represents a categorical variable (comparable to factors as in R) and it's value.") { }
+    public BinaryFactorVariable(string name, string description)
+      : base(name, description) {
+      variableValues = new Dictionary<string, List<string>>();
+    }
+
+    public override ISymbolicExpressionTreeNode CreateTreeNode() {
+      return new BinaryFactorVariableTreeNode(this);
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new BinaryFactorVariable(this, cloner);
+    }
+
+    public IEnumerable<string> GetVariableValues(string variableName) {
+      return variableValues[variableName];
+    }
+  }
+}
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/BinaryFactorVariableTreeNode.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/BinaryFactorVariableTreeNode.cs	(revision 15973)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/BinaryFactorVariableTreeNode.cs	(revision 15973)
@@ -0,0 +1,84 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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 HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Random;
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
+  [StorableClass]
+  public sealed class BinaryFactorVariableTreeNode : VariableTreeNodeBase {
+    public new BinaryFactorVariable Symbol {
+      get { return (BinaryFactorVariable)base.Symbol; }
+    }
+
+    [Storable]
+    private string variableValue;
+    public string VariableValue {
+      get { return variableValue; }
+      set { variableValue = value; }
+    }
+
+    [StorableConstructor]
+    private BinaryFactorVariableTreeNode(bool deserializing) : base(deserializing) { }
+    private BinaryFactorVariableTreeNode(BinaryFactorVariableTreeNode original, Cloner cloner)
+      : base(original, cloner) {
+      variableValue = original.variableValue;
+    }
+    public BinaryFactorVariableTreeNode(BinaryFactorVariable variableSymbol) : base(variableSymbol) { }
+
+    public override bool HasLocalParameters {
+      get { return true; }
+    }
+
+    public override void ResetLocalParameters(IRandom random) {
+      base.ResetLocalParameters(random);
+      variableValue = Symbol.GetVariableValues(VariableName).SampleRandom(random);
+    }
+
+    public override void ShakeLocalParameters(IRandom random, double shakingFactor) {
+      // 50% additive & 50% multiplicative (override of functionality of base class because of a BUG)
+      if (random.NextDouble() < 0.5) {
+        double x = NormalDistributedRandom.NextDouble(random, Symbol.WeightManipulatorMu, Symbol.WeightManipulatorSigma);
+        Weight = Weight + x * shakingFactor;
+      } else {
+        double x = NormalDistributedRandom.NextDouble(random, 1.0, Symbol.MultiplicativeWeightManipulatorSigma);
+        Weight = Weight * x;
+      }
+      if (random.NextDouble() < Symbol.VariableChangeProbability) {
+        var oldName = VariableName;
+        VariableName = Symbol.VariableNames.SampleRandom(random);
+        // reinitialize weights if variable has changed (similar to FactorVariableTreeNode)
+        if (oldName != VariableName)
+          Weight = NormalDistributedRandom.NextDouble(random, Symbol.WeightMu, Symbol.WeightSigma);
+      }
+      variableValue = Symbol.GetVariableValues(VariableName).SampleRandom(random);
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new BinaryFactorVariableTreeNode(this, cloner);
+    }
+
+    public override string ToString() {
+      return base.ToString() + " = " + variableValue;
+    }
+  }
+}
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Constant.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Constant.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Constant.cs	(revision 15973)
@@ -1,5 +1,5 @@
 #region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/ConstantTreeNode.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/ConstantTreeNode.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/ConstantTreeNode.cs	(revision 15973)
@@ -1,5 +1,5 @@
 #region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Cosine.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Cosine.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Cosine.cs	(revision 15973)
@@ -1,5 +1,5 @@
 #region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/CosineIntegral.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/CosineIntegral.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/CosineIntegral.cs	(revision 15973)
@@ -1,5 +1,5 @@
 #region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Dawson.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Dawson.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Dawson.cs	(revision 15973)
@@ -1,5 +1,5 @@
 #region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Derivative.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Derivative.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Derivative.cs	(revision 15973)
@@ -1,5 +1,5 @@
 #region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Division.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Division.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Division.cs	(revision 15973)
@@ -1,5 +1,5 @@
 #region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Erf.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Erf.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Erf.cs	(revision 15973)
@@ -1,5 +1,5 @@
 #region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Exponential.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Exponential.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Exponential.cs	(revision 15973)
@@ -1,5 +1,5 @@
 #region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/ExponentialIntegralEi.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/ExponentialIntegralEi.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/ExponentialIntegralEi.cs	(revision 15973)
@@ -1,5 +1,5 @@
 #region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/FactorVariable.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/FactorVariable.cs	(revision 15973)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/FactorVariable.cs	(revision 15973)
@@ -0,0 +1,78 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Core;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
+  [StorableClass]
+  [Item("FactorVariable", "Represents a categorical variable (comparable to factors as in R).")]
+  public sealed class FactorVariable : VariableBase {
+    private readonly Dictionary<string, Dictionary<string, int>> variableValues; // for each variable value also store a zero-based index
+    [Storable]
+    public IEnumerable<KeyValuePair<string, Dictionary<string, int>>> VariableValues {
+      get { return variableValues; }
+      set {
+        if(value == null) throw new ArgumentNullException();
+        variableValues.Clear();
+        foreach(var kvp in value) {
+          variableValues.Add(kvp.Key, new Dictionary<string, int>(kvp.Value));
+        }
+      }
+    }
+
+    [StorableConstructor]
+    private FactorVariable(bool deserializing)
+      : base(deserializing) {
+      variableValues = new Dictionary<string, Dictionary<string, int>>();
+    }
+    private FactorVariable(FactorVariable original, Cloner cloner)
+      : base(original, cloner) {
+      variableValues =
+        original.variableValues.ToDictionary(kvp => kvp.Key, kvp => new Dictionary<string, int>(kvp.Value));
+    }
+    public FactorVariable() : this("FactorVariable", "Represents a categorical variable (comparable to factors as in R).") { }
+    public FactorVariable(string name, string description)
+      : base(name, description) {
+      variableValues = new Dictionary<string, Dictionary<string,int>>();
+    }
+
+    public override ISymbolicExpressionTreeNode CreateTreeNode() {
+      return new FactorVariableTreeNode(this);
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new FactorVariable(this, cloner);
+    }
+
+    public IEnumerable<string> GetVariableValues(string variableName) {
+      return variableValues[variableName].Keys;
+    }
+
+    public int GetIndexForValue(string variableName, string variableValue) {
+      return variableValues[variableName][variableValue];
+    }
+  }
+}
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/FactorVariableTreeNode.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/FactorVariableTreeNode.cs	(revision 15973)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/FactorVariableTreeNode.cs	(revision 15973)
@@ -0,0 +1,116 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Core;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Random;
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
+  [StorableClass]
+  public sealed class FactorVariableTreeNode : SymbolicExpressionTreeTerminalNode, IVariableTreeNode {
+    public new FactorVariable Symbol {
+      get { return (FactorVariable)base.Symbol; }
+    }
+    [Storable]
+    private double[] weights;
+    public double[] Weights {
+      get { return weights; }
+      set { weights = value; }
+    }
+    [Storable]
+    private string variableName;
+    public string VariableName {
+      get { return variableName; }
+      set { variableName = value; }
+    }
+
+    [StorableConstructor]
+    private FactorVariableTreeNode(bool deserializing) : base(deserializing) { }
+    private FactorVariableTreeNode(FactorVariableTreeNode original, Cloner cloner)
+      : base(original, cloner) {
+      variableName = original.variableName;
+      if (original.weights != null) {
+        this.weights = new double[original.Weights.Length];
+        Array.Copy(original.Weights, weights, weights.Length);
+      }
+    }
+
+    public FactorVariableTreeNode(FactorVariable variableSymbol)
+      : base(variableSymbol) {
+    }
+
+    public override bool HasLocalParameters {
+      get { return true; }
+    }
+
+    public override void ResetLocalParameters(IRandom random) {
+      base.ResetLocalParameters(random);
+      variableName = Symbol.VariableNames.SampleRandom(random);
+      weights =
+        Symbol.GetVariableValues(variableName)
+        .Select(_ => NormalDistributedRandom.NextDouble(random, 0, 1)).ToArray();
+    }
+
+    public override void ShakeLocalParameters(IRandom random, double shakingFactor) {
+      // mutate only one randomly selected weight
+      var idx = random.Next(weights.Length);
+      // 50% additive & 50% multiplicative
+      if (random.NextDouble() < 0.5) {
+        double x = NormalDistributedRandom.NextDouble(random, Symbol.WeightManipulatorMu,
+          Symbol.WeightManipulatorSigma);
+        weights[idx] = weights[idx] + x * shakingFactor;
+      } else {
+        double x = NormalDistributedRandom.NextDouble(random, 1.0, Symbol.MultiplicativeWeightManipulatorSigma);
+        weights[idx] = weights[idx] * x;
+      }
+      if (random.NextDouble() < Symbol.VariableChangeProbability) {
+        VariableName = Symbol.VariableNames.SampleRandom(random);
+        if (weights.Length != Symbol.GetVariableValues(VariableName).Count()) {
+          // if the length of the weight array does not match => re-initialize weights
+          weights =
+            Symbol.GetVariableValues(variableName)
+              .Select(_ => NormalDistributedRandom.NextDouble(random, 0, 1))
+              .ToArray();
+        }
+      }
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new FactorVariableTreeNode(this, cloner);
+    }
+
+    public double GetValue(string cat) {
+      return weights[Symbol.GetIndexForValue(VariableName, cat)];
+    }
+
+    public override string ToString() {
+      var weightStr = string.Join("; ",
+        Symbol.GetVariableValues(VariableName).Select(value => value + ": " + GetValue(value).ToString("E4")));
+      return VariableName + " (factor) "
+        + "[" + weightStr + "]";
+    }
+  }
+}
+
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/FresnelCosineIntegral.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/FresnelCosineIntegral.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/FresnelCosineIntegral.cs	(revision 15973)
@@ -1,5 +1,5 @@
 #region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/FresnelSineIntegral.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/FresnelSineIntegral.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/FresnelSineIntegral.cs	(revision 15973)
@@ -1,5 +1,5 @@
 #region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Gamma.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Gamma.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Gamma.cs	(revision 15973)
@@ -1,5 +1,5 @@
 #region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/GreaterThan.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/GreaterThan.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/GreaterThan.cs	(revision 15973)
@@ -1,5 +1,5 @@
 #region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/HyperbolicCosineIntegral.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/HyperbolicCosineIntegral.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/HyperbolicCosineIntegral.cs	(revision 15973)
@@ -1,5 +1,5 @@
 #region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/HyperbolicSineIntegral.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/HyperbolicSineIntegral.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/HyperbolicSineIntegral.cs	(revision 15973)
@@ -1,5 +1,5 @@
 #region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/ILaggedTreeNode.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/ILaggedTreeNode.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/ILaggedTreeNode.cs	(revision 15973)
@@ -1,5 +1,5 @@
 ﻿#region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/IfThenElse.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/IfThenElse.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/IfThenElse.cs	(revision 15973)
@@ -1,5 +1,5 @@
 #region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Integral.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Integral.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Integral.cs	(revision 15973)
@@ -1,5 +1,5 @@
 #region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/LaggedSymbol.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/LaggedSymbol.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/LaggedSymbol.cs	(revision 15973)
@@ -1,5 +1,5 @@
 ﻿#region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/LaggedTreeNode.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/LaggedTreeNode.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/LaggedTreeNode.cs	(revision 15973)
@@ -1,5 +1,5 @@
 #region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/LaggedVariable.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/LaggedVariable.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/LaggedVariable.cs	(revision 15973)
@@ -1,5 +1,5 @@
 #region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
@@ -27,5 +27,5 @@
   [StorableClass]
   [Item("LaggedVariable", "Represents a variable value with a time offset.")]
-  public class LaggedVariable : Variable {
+  public class LaggedVariable : VariableBase {
     [Storable]
     private int minLag;
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/LaggedVariableTreeNode.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/LaggedVariableTreeNode.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/LaggedVariableTreeNode.cs	(revision 15973)
@@ -1,5 +1,5 @@
 #region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
@@ -26,5 +26,5 @@
 namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
   [StorableClass]
-  public sealed class LaggedVariableTreeNode : VariableTreeNode, ILaggedTreeNode {
+  public sealed class LaggedVariableTreeNode : VariableTreeNodeBase, ILaggedTreeNode {
     public new LaggedVariable Symbol {
       get { return (LaggedVariable)base.Symbol; }
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/LessThan.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/LessThan.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/LessThan.cs	(revision 15973)
@@ -1,5 +1,5 @@
 #region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Logarithm.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Logarithm.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Logarithm.cs	(revision 15973)
@@ -1,5 +1,5 @@
 #region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Multiplication.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Multiplication.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Multiplication.cs	(revision 15973)
@@ -1,5 +1,5 @@
 #region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Norm.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Norm.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Norm.cs	(revision 15973)
@@ -1,5 +1,5 @@
 #region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Not.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Not.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Not.cs	(revision 15973)
@@ -1,5 +1,5 @@
 #region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Or.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Or.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Or.cs	(revision 15973)
@@ -1,5 +1,5 @@
 #region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Power.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Power.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Power.cs	(revision 15973)
@@ -1,5 +1,5 @@
 #region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Psi.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Psi.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Psi.cs	(revision 15973)
@@ -1,5 +1,5 @@
 #region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Root.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Root.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Root.cs	(revision 15973)
@@ -1,5 +1,5 @@
 #region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Sine.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Sine.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Sine.cs	(revision 15973)
@@ -1,5 +1,5 @@
 #region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/SineIntegral.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/SineIntegral.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/SineIntegral.cs	(revision 15973)
@@ -1,5 +1,5 @@
 #region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Square.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Square.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Square.cs	(revision 15973)
@@ -1,5 +1,5 @@
 #region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/SquareRoot.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/SquareRoot.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/SquareRoot.cs	(revision 15973)
@@ -1,5 +1,5 @@
 #region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Subtraction.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Subtraction.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Subtraction.cs	(revision 15973)
@@ -1,5 +1,5 @@
 #region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Tangent.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Tangent.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Tangent.cs	(revision 15973)
@@ -1,5 +1,5 @@
 #region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/TimeLag.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/TimeLag.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/TimeLag.cs	(revision 15973)
@@ -1,5 +1,5 @@
 ﻿#region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Variable.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Variable.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Variable.cs	(revision 15973)
@@ -1,5 +1,5 @@
 #region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
@@ -20,6 +20,4 @@
 #endregion
 
-using System;
-using System.Collections.Generic;
 using HeuristicLab.Common;
 using HeuristicLab.Core;
@@ -29,143 +27,15 @@
   [StorableClass]
   [Item("Variable", "Represents a variable value.")]
-  public class Variable : Symbol {
-    #region Properties
-    [Storable]
-    private double weightMu;
-    public double WeightMu {
-      get { return weightMu; }
-      set {
-        if (value != weightMu) {
-          weightMu = value;
-          OnChanged(EventArgs.Empty);
-        }
-      }
-    }
-    [Storable]
-    private double weightSigma;
-    public double WeightSigma {
-      get { return weightSigma; }
-      set {
-        if (weightSigma < 0.0) throw new ArgumentException("Negative sigma is not allowed.");
-        if (value != weightSigma) {
-          weightSigma = value;
-          OnChanged(EventArgs.Empty);
-        }
-      }
-    }
-    [Storable]
-    private double weightManipulatorMu;
-    public double WeightManipulatorMu {
-      get { return weightManipulatorMu; }
-      set {
-        if (value != weightManipulatorMu) {
-          weightManipulatorMu = value;
-          OnChanged(EventArgs.Empty);
-        }
-      }
-    }
-    [Storable]
-    private double weightManipulatorSigma;
-    public double WeightManipulatorSigma {
-      get { return weightManipulatorSigma; }
-      set {
-        if (weightManipulatorSigma < 0.0) throw new ArgumentException("Negative sigma is not allowed.");
-        if (value != weightManipulatorSigma) {
-          weightManipulatorSigma = value;
-          OnChanged(EventArgs.Empty);
-        }
-      }
-    }
-    [Storable(DefaultValue = 0.0)]
-    private double multiplicativeWeightManipulatorSigma;
-    public double MultiplicativeWeightManipulatorSigma {
-      get { return multiplicativeWeightManipulatorSigma; }
-      set {
-        if (multiplicativeWeightManipulatorSigma < 0.0) throw new ArgumentException("Negative sigma is not allowed.");
-        if (value != multiplicativeWeightManipulatorSigma) {
-          multiplicativeWeightManipulatorSigma = value;
-          OnChanged(EventArgs.Empty);
-        }
-      }
-    }
-    private List<string> variableNames;
-    [Storable]
-    public IEnumerable<string> VariableNames {
-      get { return variableNames; }
-      set {
-        if (value == null) throw new ArgumentNullException();
-        variableNames.Clear();
-        variableNames.AddRange(value);
-        OnChanged(EventArgs.Empty);
-      }
-    }
-
-    private List<string> allVariableNames;
-    [Storable]
-    public IEnumerable<string> AllVariableNames {
-      get { return allVariableNames; }
-      set {
-        if (value == null) throw new ArgumentNullException();
-        allVariableNames.Clear();
-        allVariableNames.AddRange(value);
-      }
-    }
-
-    public override bool Enabled {
-      get {
-        if (variableNames.Count == 0) return false;
-        return base.Enabled;
-      }
-      set {
-        if (variableNames.Count == 0) base.Enabled = false;
-        else base.Enabled = value;
-      }
-    }
-
-    private const int minimumArity = 0;
-    private const int maximumArity = 0;
-
-    public override int MinimumArity {
-      get { return minimumArity; }
-    }
-    public override int MaximumArity {
-      get { return maximumArity; }
-    }
-    #endregion
-
-    [StorableHook(HookType.AfterDeserialization)]
-    private void AfterDeserialization() {
-      if (allVariableNames == null || (allVariableNames.Count == 0 && variableNames.Count > 0)) {
-        allVariableNames = variableNames;
-      }
-    }
+  public sealed class Variable : VariableBase {
 
     [StorableConstructor]
-    protected Variable(bool deserializing)
+    private Variable(bool deserializing)
       : base(deserializing) {
-      variableNames = new List<string>();
-      allVariableNames = new List<string>();
     }
-    protected Variable(Variable original, Cloner cloner)
+    private Variable(Variable original, Cloner cloner)
       : base(original, cloner) {
-      weightMu = original.weightMu;
-      weightSigma = original.weightSigma;
-      variableNames = new List<string>(original.variableNames);
-      allVariableNames = new List<string>(original.allVariableNames);
-      weightManipulatorMu = original.weightManipulatorMu;
-      weightManipulatorSigma = original.weightManipulatorSigma;
-      multiplicativeWeightManipulatorSigma = original.multiplicativeWeightManipulatorSigma;
     }
-    public Variable() : this("Variable", "Represents a variable value.") { }
-    public Variable(string name, string description)
-      : base(name, description) {
-      weightMu = 1.0;
-      weightSigma = 1.0;
-      weightManipulatorMu = 0.0;
-      weightManipulatorSigma = 0.05;
-      multiplicativeWeightManipulatorSigma = 0.03;
-      variableNames = new List<string>();
-      allVariableNames = new List<string>();
-    }
+    public Variable() : base("Variable", "Represents a variable value.") { }
+    public Variable(string name, string description) : base(name, description) { }
 
     public override ISymbolicExpressionTreeNode CreateTreeNode() {
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/VariableBase.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/VariableBase.cs	(revision 15973)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/VariableBase.cs	(revision 15973)
@@ -0,0 +1,182 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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 HeuristicLab.Common;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
+  [StorableClass]
+  public abstract class VariableBase : Symbol, IVariableSymbol {
+    #region Properties
+    [Storable]
+    private double weightMu;
+    public double WeightMu {
+      get { return weightMu; }
+      set {
+        if (value != weightMu) {
+          weightMu = value;
+          OnChanged(EventArgs.Empty);
+        }
+      }
+    }
+    [Storable]
+    private double weightSigma;
+    public double WeightSigma {
+      get { return weightSigma; }
+      set {
+        if (weightSigma < 0.0) throw new ArgumentException("Negative sigma is not allowed.");
+        if (value != weightSigma) {
+          weightSigma = value;
+          OnChanged(EventArgs.Empty);
+        }
+      }
+    }
+    [Storable]
+    private double weightManipulatorMu;
+    public double WeightManipulatorMu {
+      get { return weightManipulatorMu; }
+      set {
+        if (value != weightManipulatorMu) {
+          weightManipulatorMu = value;
+          OnChanged(EventArgs.Empty);
+        }
+      }
+    }
+    [Storable]
+    private double weightManipulatorSigma;
+    public double WeightManipulatorSigma {
+      get { return weightManipulatorSigma; }
+      set {
+        if (weightManipulatorSigma < 0.0) throw new ArgumentException("Negative sigma is not allowed.");
+        if (value != weightManipulatorSigma) {
+          weightManipulatorSigma = value;
+          OnChanged(EventArgs.Empty);
+        }
+      }
+    }
+    [Storable(DefaultValue = 0.0)]
+    private double multiplicativeWeightManipulatorSigma;
+    public double MultiplicativeWeightManipulatorSigma {
+      get { return multiplicativeWeightManipulatorSigma; }
+      set {
+        if (multiplicativeWeightManipulatorSigma < 0.0) throw new ArgumentException("Negative sigma is not allowed.");
+        if (value != multiplicativeWeightManipulatorSigma) {
+          multiplicativeWeightManipulatorSigma = value;
+          OnChanged(EventArgs.Empty);
+        }
+      }
+    }
+
+    [Storable(DefaultValue = 1.0)]
+    private double variableChangeProbability;
+
+    public double VariableChangeProbability {
+      get { return variableChangeProbability; }
+      set {
+        if (value < 0 || value > 1.0) throw new ArgumentException("Variable change probability must lie in the interval [0..1]");
+        variableChangeProbability = value;
+      }
+    }
+
+    private List<string> variableNames;
+    [Storable]
+    public IEnumerable<string> VariableNames {
+      get { return variableNames; }
+      set {
+        if (value == null) throw new ArgumentNullException();
+        variableNames.Clear();
+        variableNames.AddRange(value);
+        OnChanged(EventArgs.Empty);
+      }
+    }
+
+    private List<string> allVariableNames;
+    [Storable]
+    public IEnumerable<string> AllVariableNames {
+      get { return allVariableNames; }
+      set {
+        if (value == null) throw new ArgumentNullException();
+        allVariableNames.Clear();
+        allVariableNames.AddRange(value);
+      }
+    }
+
+    public override bool Enabled {
+      get {
+        if (variableNames.Count == 0) return false;
+        return base.Enabled;
+      }
+      set {
+        if (variableNames.Count == 0) base.Enabled = false;
+        else base.Enabled = value;
+      }
+    }
+
+    private const int minimumArity = 0;
+    private const int maximumArity = 0;
+
+    public override int MinimumArity {
+      get { return minimumArity; }
+    }
+    public override int MaximumArity {
+      get { return maximumArity; }
+    }
+    #endregion
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      if (allVariableNames == null || (allVariableNames.Count == 0 && variableNames.Count > 0)) {
+        allVariableNames = variableNames;
+      }
+    }
+
+    [StorableConstructor]
+    protected VariableBase(bool deserializing)
+      : base(deserializing) {
+      variableNames = new List<string>();
+      allVariableNames = new List<string>();
+    }
+    protected VariableBase(VariableBase original, Cloner cloner)
+      : base(original, cloner) {
+      weightMu = original.weightMu;
+      weightSigma = original.weightSigma;
+      variableNames = new List<string>(original.variableNames);
+      allVariableNames = new List<string>(original.allVariableNames);
+      weightManipulatorMu = original.weightManipulatorMu;
+      weightManipulatorSigma = original.weightManipulatorSigma;
+      multiplicativeWeightManipulatorSigma = original.multiplicativeWeightManipulatorSigma;
+      variableChangeProbability = original.variableChangeProbability;
+    }
+    protected VariableBase(string name, string description)
+      : base(name, description) {
+      weightMu = 1.0;
+      weightSigma = 1.0;
+      weightManipulatorMu = 0.0;
+      weightManipulatorSigma = 0.05;
+      multiplicativeWeightManipulatorSigma = 0.03;
+      variableChangeProbability = 0.2;
+      variableNames = new List<string>();
+      allVariableNames = new List<string>();
+    }
+  }
+}
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/VariableCondition.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/VariableCondition.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/VariableCondition.cs	(revision 15973)
@@ -1,5 +1,5 @@
 ﻿#region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
@@ -30,5 +30,5 @@
   [StorableClass]
   [Item("Variable Condition", "Represents a condition that tests a given variable against a specified threshold.")]
-  public sealed class VariableCondition : Symbol {
+  public sealed class VariableCondition : Symbol, IVariableSymbol {
     #region properties
     [Storable]
@@ -100,5 +100,4 @@
         allVariableNames.Clear();
         allVariableNames.AddRange(value);
-        VariableNames = value;
       }
     }
@@ -150,4 +149,14 @@
         }
       }
+    }
+
+    /// <summary>
+    /// Flag to indicate if the interpreter should ignore the slope parameter (introduced for representation of expression trees)
+    /// </summary>
+    [Storable]
+    private bool ignoreSlope;
+    public bool IgnoreSlope {
+      get { return ignoreSlope; }
+      set { ignoreSlope = value; }
     }
 
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/VariableConditionTreeNode.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/VariableConditionTreeNode.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/VariableConditionTreeNode.cs	(revision 15973)
@@ -1,5 +1,5 @@
 ﻿#region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
@@ -29,5 +29,5 @@
 namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
   [StorableClass]
-  public sealed class VariableConditionTreeNode : SymbolicExpressionTreeNode {
+  public sealed class VariableConditionTreeNode : SymbolicExpressionTreeNode, IVariableTreeNode {
     #region properties
     public new VariableCondition Symbol {
@@ -96,9 +96,10 @@
 
     public override string ToString() {
-      if (slope.IsAlmost(0.0))
+      if (slope.IsAlmost(0.0) || Symbol.IgnoreSlope) {
+        return variableName + " < " + threshold.ToString("E4");
+      } else {
         return variableName + " > " + threshold.ToString("E4") + Environment.NewLine +
-          "slope: " + slope.ToString("E4");
-      else
-        return variableName + " > " + threshold.ToString("E4");
+               "slope: " + slope.ToString("E4");
+      }
     }
   }
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/VariableTreeNode.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/VariableTreeNode.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/VariableTreeNode.cs	(revision 15973)
@@ -1,5 +1,5 @@
 #region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
@@ -21,73 +21,22 @@
 
 using HeuristicLab.Common;
-using HeuristicLab.Core;
-using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
 using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
-using HeuristicLab.Random;
 namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
   [StorableClass]
-  public class VariableTreeNode : SymbolicExpressionTreeTerminalNode {
+  public sealed class VariableTreeNode : VariableTreeNodeBase {
     public new Variable Symbol {
       get { return (Variable)base.Symbol; }
     }
-    [Storable]
-    private double weight;
-    public double Weight {
-      get { return weight; }
-      set { weight = value; }
+    [StorableConstructor]
+    private VariableTreeNode(bool deserializing) : base(deserializing) { }
+    private VariableTreeNode(VariableTreeNode original, Cloner cloner)
+      : base(original, cloner) {
     }
-    [Storable]
-    private string variableName;
-    public string VariableName {
-      get { return variableName; }
-      set { variableName = value; }
-    }
-
-    [StorableConstructor]
-    protected VariableTreeNode(bool deserializing) : base(deserializing) { }
-    protected VariableTreeNode(VariableTreeNode original, Cloner cloner)
-      : base(original, cloner) {
-      weight = original.weight;
-      variableName = original.variableName;
-    }
-    protected VariableTreeNode() { }
+    private VariableTreeNode() { }
     public VariableTreeNode(Variable variableSymbol) : base(variableSymbol) { }
-
-    public override bool HasLocalParameters {
-      get { return true; }
-    }
-
-    public override void ResetLocalParameters(IRandom random) {
-      base.ResetLocalParameters(random);
-      weight = NormalDistributedRandom.NextDouble(random, Symbol.WeightMu, Symbol.WeightSigma);
-
-#pragma warning disable 612, 618
-      variableName = Symbol.VariableNames.SelectRandom(random);
-#pragma warning restore 612, 618
-    }
-
-    public override void ShakeLocalParameters(IRandom random, double shakingFactor) {
-      base.ShakeLocalParameters(random, shakingFactor);
-      // 50% additive & 50% multiplicative
-      if (random.NextDouble() < 0) {
-        double x = NormalDistributedRandom.NextDouble(random, Symbol.WeightManipulatorMu, Symbol.WeightManipulatorSigma);
-        weight = weight + x * shakingFactor;
-      } else {
-        double x = NormalDistributedRandom.NextDouble(random, 1.0, Symbol.MultiplicativeWeightManipulatorSigma);
-        weight = weight * x;
-      }
-#pragma warning disable 612, 618
-      variableName = Symbol.VariableNames.SelectRandom(random);
-#pragma warning restore 612, 618
-    }
 
     public override IDeepCloneable Clone(Cloner cloner) {
       return new VariableTreeNode(this, cloner);
     }
-
-    public override string ToString() {
-      if (weight.IsAlmost(1.0)) return variableName;
-      else return weight.ToString("E4") + " " + variableName;
-    }
   }
 }
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/VariableTreeNodeBase.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/VariableTreeNodeBase.cs	(revision 15973)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/VariableTreeNodeBase.cs	(revision 15973)
@@ -0,0 +1,103 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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 HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Random;
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
+  [StorableClass]
+  public abstract class VariableTreeNodeBase : SymbolicExpressionTreeTerminalNode, IVariableTreeNode {
+    public new VariableBase Symbol {
+      get { return (VariableBase)base.Symbol; }
+    }
+    [Storable]
+    private double weight;
+    public double Weight {
+      get { return weight; }
+      set { weight = value; }
+    }
+    [Storable]
+    private string variableName;
+    public string VariableName {
+      get { return variableName; }
+      set { variableName = value; }
+    }
+
+    [StorableConstructor]
+    protected VariableTreeNodeBase(bool deserializing) : base(deserializing) { }
+    protected VariableTreeNodeBase(VariableTreeNodeBase original, Cloner cloner)
+      : base(original, cloner) {
+      weight = original.weight;
+      variableName = original.variableName;
+    }
+    protected VariableTreeNodeBase() { }
+    protected VariableTreeNodeBase(VariableBase variableSymbol) : base(variableSymbol) { }
+
+    public override bool HasLocalParameters {
+      get { return true; }
+    }
+
+    public override void ResetLocalParameters(IRandom random) {
+      base.ResetLocalParameters(random);
+      weight = NormalDistributedRandom.NextDouble(random, Symbol.WeightMu, Symbol.WeightSigma);
+
+#pragma warning disable 612, 618
+      variableName = Symbol.VariableNames.SelectRandom(random);
+#pragma warning restore 612, 618
+    }
+
+    public override void ShakeLocalParameters(IRandom random, double shakingFactor) {
+      base.ShakeLocalParameters(random, shakingFactor);
+
+      // 50% additive & 50% multiplicative (TODO: BUG in if statement below -> fix in HL 4.0!)
+      if (random.NextDouble() < 0) {
+        double x = NormalDistributedRandom.NextDouble(random, Symbol.WeightManipulatorMu, Symbol.WeightManipulatorSigma);
+        weight = weight + x * shakingFactor;
+      } else {
+        double x = NormalDistributedRandom.NextDouble(random, 1.0, Symbol.MultiplicativeWeightManipulatorSigma);
+        weight = weight * x;
+      }
+
+      if (Symbol.VariableChangeProbability >= 1.0) {
+        // old behaviour for backwards compatibility
+        #region Backwards compatible code, remove with 3.4
+#pragma warning disable 612, 618
+        variableName = Symbol.VariableNames.SelectRandom(random);
+#pragma warning restore 612, 618
+        #endregion
+      } else if (random.NextDouble() < Symbol.VariableChangeProbability) {
+        var oldName = variableName;
+        variableName = Symbol.VariableNames.SampleRandom(random);
+        if (oldName != variableName) {
+          // re-initialize weight if the variable is changed
+          weight = NormalDistributedRandom.NextDouble(random, Symbol.WeightMu, Symbol.WeightSigma);
+        }
+      }
+    }
+
+    public override string ToString() {
+      if (weight.IsAlmost(1.0)) return variableName;
+      else return weight.ToString("E4") + " " + variableName;
+    }
+  }
+}
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Xor.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Xor.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Xor.cs	(revision 15973)
@@ -1,5 +1,5 @@
 #region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/TransformationToSymbolicTreeMapper.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/TransformationToSymbolicTreeMapper.cs	(revision 15651)
+++ 	(revision )
@@ -1,294 +1,0 @@
-﻿#region License Information
-/* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
- *
- * This file is part of HeuristicLab.
- *
- * HeuristicLab is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * HeuristicLab is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
- */
-#endregion
-
-using System;
-using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
-
-namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
-  public class TransformationToSymbolicTreeMapper : ITransformationMapper<ISymbolicExpressionTreeNode> {
-    private ITransformation transformation;
-    private string column;
-
-    #region ITransformationMapper<ISymbolicExpressionTree> Members
-
-    public ISymbolicExpressionTreeNode GenerateModel(ITransformation transformation) {
-      InitComponents(transformation);
-
-      if (transformation is LinearTransformation) {
-        return GenerateModelForLinearTransformation();
-      } else if (transformation is ExponentialTransformation) {
-        return GenerateModelForExponentialTransformation();
-      } else if (transformation is LogarithmicTransformation) {
-        return GenerateModelForLogarithmicTransformation();
-      } else if (transformation is PowerTransformation) {
-        return GenerateModelForPowerTransformation();
-      } else if (transformation is ReciprocalTransformation) {
-        return GenerateModelForReciprocalTransformation();
-      } else if (transformation is ShiftStandardDistributionTransformation) {
-        return GenerateModelForShiftStandardDistributionTransformation();
-      } else if (transformation is CopyColumnTransformation) {
-        return GenerateTreeNodeForCopyColumnTransformation();
-      }
-      throw new NotImplementedException();
-    }
-
-    public ISymbolicExpressionTreeNode GenerateInverseModel(ITransformation transformation) {
-      InitComponents(transformation);
-
-      if (transformation is LinearTransformation) {
-        return GenerateInverseModelForLinearTransformation();
-      } else if (transformation is ExponentialTransformation) {
-        return GenerateInverseModelForExponentialTransformation();
-      } else if (transformation is LogarithmicTransformation) {
-        return GenerateInverseModelForLogarithmicTransformation();
-      } else if (transformation is PowerTransformation) {
-        return GenerateInverseModelForPowerTransformation();
-      } else if (transformation is ReciprocalTransformation) {
-        return GenerateInverseModelForReciprocalTransformation();
-      } else if (transformation is ShiftStandardDistributionTransformation) {
-        GenerateInverseModelForShiftStandardDistributionTransformation();
-      } else if (transformation is CopyColumnTransformation) {
-        return GenerateTreeNodeForCopyColumnTransformation();
-      }
-
-      throw new NotImplementedException();
-    }
-
-    #endregion
-
-    // helper
-
-    private ISymbolicExpressionTreeNode GenerateModelForLinearTransformation() {
-      var linearTransformation = (LinearTransformation)transformation;
-      var kValue = linearTransformation.Multiplier;
-      var dValue = linearTransformation.Addend;
-
-      // k * x
-      var multiplicationNode = new Multiplication().CreateTreeNode();
-      var kNode = CreateConstantTreeNode("k", kValue);
-      var xNode = CreateVariableTreeNode(column, "x");
-      multiplicationNode.AddSubtree(kNode);
-      multiplicationNode.AddSubtree(xNode);
-
-      // ( k * x ) + d
-      var additionNode = new Addition().CreateTreeNode();
-      var dNode = CreateConstantTreeNode("d", dValue);
-      additionNode.AddSubtree(multiplicationNode);
-      additionNode.AddSubtree(dNode);
-
-      return additionNode;
-    }
-
-    private ISymbolicExpressionTreeNode GenerateInverseModelForLinearTransformation() {
-      var linearTransformation = (LinearTransformation)transformation;
-      var kValue = linearTransformation.Multiplier;
-      var dValue = linearTransformation.Addend;
-
-      // x - d
-      var substractionNode = new Subtraction().CreateTreeNode();
-      var dNode = CreateConstantTreeNode("d", dValue);
-      var xNode = CreateVariableTreeNode(column, "x");
-      substractionNode.AddSubtree(xNode);
-      substractionNode.AddSubtree(dNode);
-
-      // ( x - d ) / k
-      var divisionNode = new Division().CreateTreeNode();
-      var kNode = CreateConstantTreeNode("k", kValue);
-      divisionNode.AddSubtree(substractionNode);
-      divisionNode.AddSubtree(kNode);
-
-      return divisionNode;
-    }
-
-
-    private ISymbolicExpressionTreeNode GenerateModelForExponentialTransformation() {
-      var exponentialTransformation = (ExponentialTransformation)transformation;
-      var bValue = exponentialTransformation.Base;
-
-      return GenTreePow_b_x(bValue);
-    }
-
-    private ISymbolicExpressionTreeNode GenerateInverseModelForExponentialTransformation() {
-      var exponentialTransformation = (ExponentialTransformation)transformation;
-      var bValue = exponentialTransformation.Base;
-
-      return GenTreeLog_x_b(bValue);
-    }
-
-
-    private ISymbolicExpressionTreeNode GenerateModelForLogarithmicTransformation() {
-      var logarithmicTransformation = (LogarithmicTransformation)transformation;
-      var bValue = logarithmicTransformation.Base;
-
-      return GenTreeLog_x_b(bValue);
-    }
-
-    private ISymbolicExpressionTreeNode GenerateInverseModelForLogarithmicTransformation() {
-      var logarithmicTransformation = (LogarithmicTransformation)transformation;
-      var bValue = logarithmicTransformation.Base;
-
-      return GenTreePow_b_x(bValue);
-    }
-
-
-    private ISymbolicExpressionTreeNode GenerateModelForPowerTransformation() {
-      var powerTransformation = (PowerTransformation)transformation;
-      var expValue = powerTransformation.Exponent;
-
-      // x ^ exp
-      var powerNode = new Power().CreateTreeNode();
-      var xNode = CreateVariableTreeNode(column, "x");
-      var expNode = CreateConstantTreeNode("exp", expValue);
-      powerNode.AddSubtree(xNode);
-      powerNode.AddSubtree(expNode);
-
-      return powerNode;
-    }
-
-    private ISymbolicExpressionTreeNode GenerateInverseModelForPowerTransformation() {
-      var powerTransformation = (PowerTransformation)transformation;
-      var expValue = powerTransformation.Exponent;
-
-      // rt(x, b)
-      var rootNode = new Root().CreateTreeNode();
-      var xNode = CreateVariableTreeNode(column, "x");
-      var bNode = CreateConstantTreeNode("b", expValue);
-      rootNode.AddSubtree(xNode);
-      rootNode.AddSubtree(bNode);
-
-      return rootNode;
-    }
-
-
-    private ISymbolicExpressionTreeNode GenerateModelForReciprocalTransformation() {
-      return GenTreeDiv_1_x();
-    }
-
-    private ISymbolicExpressionTreeNode GenerateInverseModelForReciprocalTransformation() {
-      return GenTreeDiv_1_x();
-    }
-
-
-    private ISymbolicExpressionTreeNode GenerateModelForShiftStandardDistributionTransformation() {
-      var shiftStandardDistributionTransformation = (ShiftStandardDistributionTransformation)transformation;
-      var m_orgValue = shiftStandardDistributionTransformation.OriginalMean;
-      var s_orgValue = shiftStandardDistributionTransformation.OriginalStandardDeviation;
-      var m_tarValue = shiftStandardDistributionTransformation.Mean;
-      var s_tarValue = shiftStandardDistributionTransformation.StandardDeviation;
-
-      return GenTreeShiftStdDist(column, m_orgValue, s_orgValue, m_tarValue, s_tarValue);
-    }
-
-    private ISymbolicExpressionTreeNode GenerateInverseModelForShiftStandardDistributionTransformation() {
-      var shiftStandardDistributionTransformation = (ShiftStandardDistributionTransformation)transformation;
-      var m_orgValue = shiftStandardDistributionTransformation.OriginalMean;
-      var s_orgValue = shiftStandardDistributionTransformation.OriginalStandardDeviation;
-      var m_tarValue = shiftStandardDistributionTransformation.Mean;
-      var s_tarValue = shiftStandardDistributionTransformation.StandardDeviation;
-
-      return GenTreeShiftStdDist(column, m_tarValue, s_tarValue, m_orgValue, s_orgValue);
-    }
-
-    private ISymbolicExpressionTreeNode GenerateTreeNodeForCopyColumnTransformation() {
-      var copyColumnTransformation = (CopyColumnTransformation)transformation;
-      var copiedColumnName = copyColumnTransformation.CopiedColumnName;
-
-      return CreateVariableTreeNode(copiedColumnName, copiedColumnName + "(original)");
-    }
-
-    // helper's helper:
-
-    private ISymbolicExpressionTreeNode GenTreeLog_x_b(double b) {
-      // log(x, b)
-      var logNode = new Logarithm().CreateTreeNode();
-      var bNode = CreateConstantTreeNode("b", b);
-      var xNode = CreateVariableTreeNode(column, "x");
-      logNode.AddSubtree(xNode);
-      logNode.AddSubtree(bNode);
-
-      return logNode;
-    }
-
-    private ISymbolicExpressionTreeNode GenTreePow_b_x(double b) {
-      // b ^ x
-      var powerNode = new Power().CreateTreeNode();
-      var bNode = CreateConstantTreeNode("b", b);
-      var xNode = CreateVariableTreeNode(column, "x");
-      powerNode.AddSubtree(bNode);
-      powerNode.AddSubtree(xNode);
-
-      return powerNode;
-    }
-
-    private ISymbolicExpressionTreeNode GenTreeDiv_1_x() {
-      // 1 / x
-      var divNode = new Division().CreateTreeNode();
-      var oneNode = CreateConstantTreeNode("1", 1.0);
-      var xNode = CreateVariableTreeNode(column, "x");
-      divNode.AddSubtree(oneNode);
-      divNode.AddSubtree(xNode);
-
-      return divNode;
-    }
-
-    private ISymbolicExpressionTreeNode GenTreeShiftStdDist(string variable, double m_org, double s_org, double m_tar, double s_tar) {
-      // x - m_org
-      var substractionNode = new Subtraction().CreateTreeNode();
-      var xNode = CreateVariableTreeNode(variable, "x");
-      var m_orgNode = CreateConstantTreeNode("m_org", m_org);
-      substractionNode.AddSubtree(xNode);
-      substractionNode.AddSubtree(m_orgNode);
-
-      // (x - m_org) / s_org
-      var divisionNode = new Division().CreateTreeNode();
-      var s_orgNode = CreateConstantTreeNode("s_org", s_org);
-      divisionNode.AddSubtree(substractionNode);
-      divisionNode.AddSubtree(s_orgNode);
-
-      // ((x - m_org) / s_org ) * s_tar
-      var multiplicationNode = new Multiplication().CreateTreeNode();
-      var s_tarNode = CreateConstantTreeNode("s_tar", s_tar);
-      multiplicationNode.AddSubtree(divisionNode);
-      multiplicationNode.AddSubtree(s_tarNode);
-
-      // ((x - m_org) / s_org ) * s_tar + m_tar
-      var additionNode = new Addition().CreateTreeNode();
-      var m_tarNode = CreateConstantTreeNode("m_tar", m_tar);
-      additionNode.AddSubtree(multiplicationNode);
-      additionNode.AddSubtree(m_tarNode);
-
-      return additionNode;
-    }
-
-    private ConstantTreeNode CreateConstantTreeNode(string description, double value) {
-      return new ConstantTreeNode(new Constant()) { Value = value };
-    }
-
-    private VariableTreeNode CreateVariableTreeNode(string name, string description) {
-      return new VariableTreeNode(new Variable(name, description)) { VariableName = name, Weight = 1.0 };
-    }
-
-    private void InitComponents(ITransformation transformation) {
-      this.transformation = transformation;
-      column = transformation.Column;
-    }
-  }
-}
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Transformations/SymbolicExpressionTreeBacktransformator.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Transformations/SymbolicExpressionTreeBacktransformator.cs	(revision 15973)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Transformations/SymbolicExpressionTreeBacktransformator.cs	(revision 15973)
@@ -0,0 +1,97 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Transformations/TransformationToSymbolicTreeMapper.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Transformations/TransformationToSymbolicTreeMapper.cs	(revision 15973)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Transformations/TransformationToSymbolicTreeMapper.cs	(revision 15973)
@@ -0,0 +1,294 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
+  public class TransformationToSymbolicTreeMapper : ITransformationMapper<ISymbolicExpressionTreeNode> {
+    private ITransformation transformation;
+    private string column;
+
+    #region ITransformationMapper<ISymbolicExpressionTree> Members
+
+    public ISymbolicExpressionTreeNode GenerateModel(ITransformation transformation) {
+      InitComponents(transformation);
+
+      if (transformation is LinearTransformation) {
+        return GenerateModelForLinearTransformation();
+      } else if (transformation is ExponentialTransformation) {
+        return GenerateModelForExponentialTransformation();
+      } else if (transformation is LogarithmicTransformation) {
+        return GenerateModelForLogarithmicTransformation();
+      } else if (transformation is PowerTransformation) {
+        return GenerateModelForPowerTransformation();
+      } else if (transformation is ReciprocalTransformation) {
+        return GenerateModelForReciprocalTransformation();
+      } else if (transformation is ShiftStandardDistributionTransformation) {
+        return GenerateModelForShiftStandardDistributionTransformation();
+      } else if (transformation is CopyColumnTransformation) {
+        return GenerateTreeNodeForCopyColumnTransformation();
+      }
+      throw new NotImplementedException();
+    }
+
+    public ISymbolicExpressionTreeNode GenerateInverseModel(ITransformation transformation) {
+      InitComponents(transformation);
+
+      if (transformation is LinearTransformation) {
+        return GenerateInverseModelForLinearTransformation();
+      } else if (transformation is ExponentialTransformation) {
+        return GenerateInverseModelForExponentialTransformation();
+      } else if (transformation is LogarithmicTransformation) {
+        return GenerateInverseModelForLogarithmicTransformation();
+      } else if (transformation is PowerTransformation) {
+        return GenerateInverseModelForPowerTransformation();
+      } else if (transformation is ReciprocalTransformation) {
+        return GenerateInverseModelForReciprocalTransformation();
+      } else if (transformation is ShiftStandardDistributionTransformation) {
+        GenerateInverseModelForShiftStandardDistributionTransformation();
+      } else if (transformation is CopyColumnTransformation) {
+        return GenerateTreeNodeForCopyColumnTransformation();
+      }
+
+      throw new NotImplementedException();
+    }
+
+    #endregion
+
+    // helper
+
+    private ISymbolicExpressionTreeNode GenerateModelForLinearTransformation() {
+      var linearTransformation = (LinearTransformation)transformation;
+      var kValue = linearTransformation.Multiplier;
+      var dValue = linearTransformation.Addend;
+
+      // k * x
+      var multiplicationNode = new Multiplication().CreateTreeNode();
+      var kNode = CreateConstantTreeNode("k", kValue);
+      var xNode = CreateVariableTreeNode(column, "x");
+      multiplicationNode.AddSubtree(kNode);
+      multiplicationNode.AddSubtree(xNode);
+
+      // ( k * x ) + d
+      var additionNode = new Addition().CreateTreeNode();
+      var dNode = CreateConstantTreeNode("d", dValue);
+      additionNode.AddSubtree(multiplicationNode);
+      additionNode.AddSubtree(dNode);
+
+      return additionNode;
+    }
+
+    private ISymbolicExpressionTreeNode GenerateInverseModelForLinearTransformation() {
+      var linearTransformation = (LinearTransformation)transformation;
+      var kValue = linearTransformation.Multiplier;
+      var dValue = linearTransformation.Addend;
+
+      // x - d
+      var substractionNode = new Subtraction().CreateTreeNode();
+      var dNode = CreateConstantTreeNode("d", dValue);
+      var xNode = CreateVariableTreeNode(column, "x");
+      substractionNode.AddSubtree(xNode);
+      substractionNode.AddSubtree(dNode);
+
+      // ( x - d ) / k
+      var divisionNode = new Division().CreateTreeNode();
+      var kNode = CreateConstantTreeNode("k", kValue);
+      divisionNode.AddSubtree(substractionNode);
+      divisionNode.AddSubtree(kNode);
+
+      return divisionNode;
+    }
+
+
+    private ISymbolicExpressionTreeNode GenerateModelForExponentialTransformation() {
+      var exponentialTransformation = (ExponentialTransformation)transformation;
+      var bValue = exponentialTransformation.Base;
+
+      return GenTreePow_b_x(bValue);
+    }
+
+    private ISymbolicExpressionTreeNode GenerateInverseModelForExponentialTransformation() {
+      var exponentialTransformation = (ExponentialTransformation)transformation;
+      var bValue = exponentialTransformation.Base;
+
+      return GenTreeLog_x_b(bValue);
+    }
+
+
+    private ISymbolicExpressionTreeNode GenerateModelForLogarithmicTransformation() {
+      var logarithmicTransformation = (LogarithmicTransformation)transformation;
+      var bValue = logarithmicTransformation.Base;
+
+      return GenTreeLog_x_b(bValue);
+    }
+
+    private ISymbolicExpressionTreeNode GenerateInverseModelForLogarithmicTransformation() {
+      var logarithmicTransformation = (LogarithmicTransformation)transformation;
+      var bValue = logarithmicTransformation.Base;
+
+      return GenTreePow_b_x(bValue);
+    }
+
+
+    private ISymbolicExpressionTreeNode GenerateModelForPowerTransformation() {
+      var powerTransformation = (PowerTransformation)transformation;
+      var expValue = powerTransformation.Exponent;
+
+      // x ^ exp
+      var powerNode = new Power().CreateTreeNode();
+      var xNode = CreateVariableTreeNode(column, "x");
+      var expNode = CreateConstantTreeNode("exp", expValue);
+      powerNode.AddSubtree(xNode);
+      powerNode.AddSubtree(expNode);
+
+      return powerNode;
+    }
+
+    private ISymbolicExpressionTreeNode GenerateInverseModelForPowerTransformation() {
+      var powerTransformation = (PowerTransformation)transformation;
+      var expValue = powerTransformation.Exponent;
+
+      // rt(x, b)
+      var rootNode = new Root().CreateTreeNode();
+      var xNode = CreateVariableTreeNode(column, "x");
+      var bNode = CreateConstantTreeNode("b", expValue);
+      rootNode.AddSubtree(xNode);
+      rootNode.AddSubtree(bNode);
+
+      return rootNode;
+    }
+
+
+    private ISymbolicExpressionTreeNode GenerateModelForReciprocalTransformation() {
+      return GenTreeDiv_1_x();
+    }
+
+    private ISymbolicExpressionTreeNode GenerateInverseModelForReciprocalTransformation() {
+      return GenTreeDiv_1_x();
+    }
+
+
+    private ISymbolicExpressionTreeNode GenerateModelForShiftStandardDistributionTransformation() {
+      var shiftStandardDistributionTransformation = (ShiftStandardDistributionTransformation)transformation;
+      var m_orgValue = shiftStandardDistributionTransformation.OriginalMean;
+      var s_orgValue = shiftStandardDistributionTransformation.OriginalStandardDeviation;
+      var m_tarValue = shiftStandardDistributionTransformation.Mean;
+      var s_tarValue = shiftStandardDistributionTransformation.StandardDeviation;
+
+      return GenTreeShiftStdDist(column, m_orgValue, s_orgValue, m_tarValue, s_tarValue);
+    }
+
+    private ISymbolicExpressionTreeNode GenerateInverseModelForShiftStandardDistributionTransformation() {
+      var shiftStandardDistributionTransformation = (ShiftStandardDistributionTransformation)transformation;
+      var m_orgValue = shiftStandardDistributionTransformation.OriginalMean;
+      var s_orgValue = shiftStandardDistributionTransformation.OriginalStandardDeviation;
+      var m_tarValue = shiftStandardDistributionTransformation.Mean;
+      var s_tarValue = shiftStandardDistributionTransformation.StandardDeviation;
+
+      return GenTreeShiftStdDist(column, m_tarValue, s_tarValue, m_orgValue, s_orgValue);
+    }
+
+    private ISymbolicExpressionTreeNode GenerateTreeNodeForCopyColumnTransformation() {
+      var copyColumnTransformation = (CopyColumnTransformation)transformation;
+      var copiedColumnName = copyColumnTransformation.CopiedColumnName;
+
+      return CreateVariableTreeNode(copiedColumnName, copiedColumnName + "(original)");
+    }
+
+    // helper's helper:
+
+    private ISymbolicExpressionTreeNode GenTreeLog_x_b(double b) {
+      // log(x, b)
+      var logNode = new Logarithm().CreateTreeNode();
+      var bNode = CreateConstantTreeNode("b", b);
+      var xNode = CreateVariableTreeNode(column, "x");
+      logNode.AddSubtree(xNode);
+      logNode.AddSubtree(bNode);
+
+      return logNode;
+    }
+
+    private ISymbolicExpressionTreeNode GenTreePow_b_x(double b) {
+      // b ^ x
+      var powerNode = new Power().CreateTreeNode();
+      var bNode = CreateConstantTreeNode("b", b);
+      var xNode = CreateVariableTreeNode(column, "x");
+      powerNode.AddSubtree(bNode);
+      powerNode.AddSubtree(xNode);
+
+      return powerNode;
+    }
+
+    private ISymbolicExpressionTreeNode GenTreeDiv_1_x() {
+      // 1 / x
+      var divNode = new Division().CreateTreeNode();
+      var oneNode = CreateConstantTreeNode("1", 1.0);
+      var xNode = CreateVariableTreeNode(column, "x");
+      divNode.AddSubtree(oneNode);
+      divNode.AddSubtree(xNode);
+
+      return divNode;
+    }
+
+    private ISymbolicExpressionTreeNode GenTreeShiftStdDist(string variable, double m_org, double s_org, double m_tar, double s_tar) {
+      // x - m_org
+      var substractionNode = new Subtraction().CreateTreeNode();
+      var xNode = CreateVariableTreeNode(variable, "x");
+      var m_orgNode = CreateConstantTreeNode("m_org", m_org);
+      substractionNode.AddSubtree(xNode);
+      substractionNode.AddSubtree(m_orgNode);
+
+      // (x - m_org) / s_org
+      var divisionNode = new Division().CreateTreeNode();
+      var s_orgNode = CreateConstantTreeNode("s_org", s_org);
+      divisionNode.AddSubtree(substractionNode);
+      divisionNode.AddSubtree(s_orgNode);
+
+      // ((x - m_org) / s_org ) * s_tar
+      var multiplicationNode = new Multiplication().CreateTreeNode();
+      var s_tarNode = CreateConstantTreeNode("s_tar", s_tar);
+      multiplicationNode.AddSubtree(divisionNode);
+      multiplicationNode.AddSubtree(s_tarNode);
+
+      // ((x - m_org) / s_org ) * s_tar + m_tar
+      var additionNode = new Addition().CreateTreeNode();
+      var m_tarNode = CreateConstantTreeNode("m_tar", m_tar);
+      additionNode.AddSubtree(multiplicationNode);
+      additionNode.AddSubtree(m_tarNode);
+
+      return additionNode;
+    }
+
+    private ConstantTreeNode CreateConstantTreeNode(string description, double value) {
+      return new ConstantTreeNode(new Constant()) { Value = value };
+    }
+
+    private VariableTreeNode CreateVariableTreeNode(string name, string description) {
+      return new VariableTreeNode(new Variable(name, description)) { VariableName = name, Weight = 1.0 };
+    }
+
+    private void InitComponents(ITransformation transformation) {
+      this.transformation = transformation;
+      column = transformation.Column;
+    }
+  }
+}
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/TreeMatching/SymbolicExpressionTreeBottomUpSimilarityCalculator.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/TreeMatching/SymbolicExpressionTreeBottomUpSimilarityCalculator.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/TreeMatching/SymbolicExpressionTreeBottomUpSimilarityCalculator.cs	(revision 15973)
@@ -1,5 +1,5 @@
 ﻿#region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/TreeMatching/SymbolicExpressionTreeMatching.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/TreeMatching/SymbolicExpressionTreeMatching.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/TreeMatching/SymbolicExpressionTreeMatching.cs	(revision 15973)
@@ -2,5 +2,5 @@
 
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/TreeMatching/SymbolicExpressionTreeMaxCommonSubtreeSimilarityCalculator.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/TreeMatching/SymbolicExpressionTreeMaxCommonSubtreeSimilarityCalculator.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/TreeMatching/SymbolicExpressionTreeMaxCommonSubtreeSimilarityCalculator.cs	(revision 15973)
@@ -1,5 +1,5 @@
 ﻿#region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/TreeMatching/SymbolicExpressionTreeNodeComparer.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/TreeMatching/SymbolicExpressionTreeNodeComparer.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/TreeMatching/SymbolicExpressionTreeNodeComparer.cs	(revision 15973)
@@ -1,5 +1,5 @@
 ﻿#region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/TreeMatching/SymbolicExpressionTreeNodeEqualityComparer.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/TreeMatching/SymbolicExpressionTreeNodeEqualityComparer.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/TreeMatching/SymbolicExpressionTreeNodeEqualityComparer.cs	(revision 15973)
@@ -1,5 +1,5 @@
 ﻿#region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
Index: branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/TreeMatching/SymbolicExpressionTreePhenotypicSimilarityCalculator.cs
===================================================================
--- branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/TreeMatching/SymbolicExpressionTreePhenotypicSimilarityCalculator.cs	(revision 15651)
+++ branches/2522_RefactorPluginInfrastructure/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/TreeMatching/SymbolicExpressionTreePhenotypicSimilarityCalculator.cs	(revision 15973)
@@ -1,5 +1,5 @@
 ﻿#region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
