Index: branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisAlleleFrequencyAnalyzer.cs
===================================================================
--- branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisAlleleFrequencyAnalyzer.cs	(revision 14574)
+++ branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisAlleleFrequencyAnalyzer.cs	(revision 14878)
@@ -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/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisSingleObjectiveTrainingBestSolutionAnalyzer.cs
===================================================================
--- branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisSingleObjectiveTrainingBestSolutionAnalyzer.cs	(revision 14574)
+++ branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisSingleObjectiveTrainingBestSolutionAnalyzer.cs	(revision 14878)
@@ -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/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisVariableFrequencyAnalyzer.cs
===================================================================
--- branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisVariableFrequencyAnalyzer.cs	(revision 14574)
+++ branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisVariableFrequencyAnalyzer.cs	(revision 14878)
@@ -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);
         }
       }
