Index: branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisVariableFrequencyAnalyzer.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisVariableFrequencyAnalyzer.cs	(revision 14195)
+++ branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisVariableFrequencyAnalyzer.cs	(revision 14232)
@@ -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,5 +162,6 @@
     }
 
-    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) {
@@ -151,13 +173,20 @@
             var varCondNode = node as VariableConditionTreeNode;
             IncReferenceCount(references, varCondNode.VariableName);
+          } else if (node.Symbol is FactorVariable) {
+            var factorNode = node as FactorVariableTreeNode;
+            if (aggregateFactorVariables) {
+              IncReferenceCount(references, factorNode.VariableName);
+            } else {
+              IncReferenceCount(references, factorNode.ToString());
+            }
           }
         });
       } 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) {
+    private static void GetVariableReferences(Dictionary<string, int> references, ISymbolicExpressionTreeNode node, int currentLag, bool aggregateFactorVariables) {
       if (node.Symbol is LaggedVariable) {
         var laggedVarNode = node as LaggedVariableTreeNode;
@@ -166,24 +195,31 @@
         var varNode = node as VariableTreeNode;
         IncReferenceCount(references, varNode.VariableName, currentLag);
+      } else if (node.Symbol is FactorVariable) {
+        var factorNode = node as FactorVariableTreeNode;
+        if (aggregateFactorVariables) {
+          IncReferenceCount(references, factorNode.VariableName, currentLag);
+        } else {
+          IncReferenceCount(references, factorNode.ToString(), 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);
+        GetVariableReferences(references, node.GetSubtree(0), currentLag, aggregateFactorVariables);
+        GetVariableReferences(references, node.GetSubtree(1), currentLag, aggregateFactorVariables);
       } 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/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Grammars/ArithmeticExpressionGrammar.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Grammars/ArithmeticExpressionGrammar.cs	(revision 14195)
+++ branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Grammars/ArithmeticExpressionGrammar.cs	(revision 14232)
@@ -53,6 +53,7 @@
       constant.MaxValue = 20;
       var variableSymbol = new HeuristicLab.Problems.DataAnalysis.Symbolic.Variable();
+      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, factorVariableSymbol };
       var functionSymbols = new List<Symbol>() { add, sub, mul, div };
 
@@ -65,4 +66,5 @@
       SetSubtreeCount(constant, 0, 0);
       SetSubtreeCount(variableSymbol, 0, 0);
+      SetSubtreeCount(factorVariableSymbol, 0, 0);
 
       // allow each symbol as child of the start symbol
Index: branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Grammars/FullFunctionalExpressionGrammar.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Grammars/FullFunctionalExpressionGrammar.cs	(revision 14195)
+++ branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Grammars/FullFunctionalExpressionGrammar.cs	(revision 14232)
@@ -115,4 +115,5 @@
       constant.MaxValue = 20;
       var variableSymbol = new HeuristicLab.Problems.DataAnalysis.Symbolic.Variable();
+      var factorVariable = new FactorVariable();
       var laggedVariable = new LaggedVariable();
       laggedVariable.InitialFrequency = 0.0;
@@ -123,5 +124,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, 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 +131,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, factorVariable, constant, laggedVariable, autoregressiveVariable };
 
       foreach (var symb in allSymbols)
Index: branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Grammars/TypeCoherentExpressionGrammar.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Grammars/TypeCoherentExpressionGrammar.cs	(revision 14195)
+++ branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Grammars/TypeCoherentExpressionGrammar.cs	(revision 14232)
@@ -104,4 +104,5 @@
       constant.MaxValue = 20;
       var variableSymbol = new Variable();
+      var factorVariable = new FactorVariable();
       var laggedVariable = new LaggedVariable();
       var autoregressiveVariable = new AutoregressiveTargetVariable();
@@ -114,5 +115,5 @@
       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, factorVariable });
       var realValuedSymbols = new GroupSymbol(RealValuedSymbolsName, new List<ISymbol>() { arithmeticSymbols, trigonometricSymbols, exponentialAndLogarithmicSymbols, specialFunctions, terminalSymbols });
 
@@ -122,5 +123,5 @@
       var comparisonSymbols = new GroupSymbol(ComparisonsName, new List<ISymbol> { gt, lt });
       var booleanOperationSymbols = new GroupSymbol(BooleanOperatorsName, new List<ISymbol> { and, or, not, xor });
-      var conditionalSymbols = new GroupSymbol(ConditionalSymbolsName, new List<ISymbol> { conditionSymbols, comparisonSymbols, booleanOperationSymbols });
+      var conditionalSymbols = new GroupSymbol(ConditionalSymbolsName, new List<ISymbol> { conditionSymbols, comparisonSymbols, booleanOperationSymbols }); // TODO: factorVariableBool?
 
       var timeSeriesSymbols = new GroupSymbol(TimeSeriesSymbolsName, new List<ISymbol> { timeLag, integral, derivative, laggedVariable, autoregressiveVariable });
Index: branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4.csproj
===================================================================
--- trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4.csproj	(revision 14195)
+++ branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4.csproj	(revision 14232)
@@ -198,4 +198,6 @@
     <Compile Include="Symbols\AiryB.cs" />
     <Compile Include="Symbols\Bessel.cs" />
+    <Compile Include="Symbols\FactorVariable.cs" />
+    <Compile Include="Symbols\FactorVariableTreeNode.cs" />
     <Compile Include="Symbols\Xor.cs" />
     <Compile Include="Symbols\Erf.cs" />
Index: branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/ISymbolicDataAnalysisImpactValuesCalculator.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/ISymbolicDataAnalysisImpactValuesCalculator.cs	(revision 14195)
+++ branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/ISymbolicDataAnalysisImpactValuesCalculator.cs	(revision 14232)
@@ -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/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/OpCodes.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/OpCodes.cs	(revision 14195)
+++ branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/OpCodes.cs	(revision 14232)
@@ -83,4 +83,5 @@
     public const byte Erf = 43;
     public const byte Bessel = 44;
+    public const byte FactorVariable = 46;
 
     private static Dictionary<Type, byte> symbolToOpcode = new Dictionary<Type, byte>() {
@@ -130,5 +131,6 @@
       { typeof(Norm), OpCodes.Norm},
       { typeof(Erf), OpCodes.Erf},
-      { typeof(Bessel), OpCodes.Bessel}   
+      { typeof(Bessel), OpCodes.Bessel},
+      { typeof(FactorVariable), OpCodes.FactorVariable }
     };
 
Index: branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeILEmittingInterpreter.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeILEmittingInterpreter.cs	(revision 14195)
+++ branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeILEmittingInterpreter.cs	(revision 14232)
@@ -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
 
@@ -627,4 +628,38 @@
             return;
           }
+        case OpCodes.FactorVariable: {
+            FactorVariableTreeNode varNode = currentInstr.dynamicNode as FactorVariableTreeNode;
+            il.Emit(System.Reflection.Emit.OpCodes.Ldarg_1); // load columns array
+            il.Emit(System.Reflection.Emit.OpCodes.Ldc_I4, (int)currentInstr.data);
+            // load correct column of the current variable
+            il.Emit(System.Reflection.Emit.OpCodes.Ldelem_Ref);
+            il.Emit(System.Reflection.Emit.OpCodes.Ldarg_0); // rowIndex
+            if (!state.InLaggedContext) {
+              il.Emit(System.Reflection.Emit.OpCodes.Call, listGetValue);
+              il.Emit(System.Reflection.Emit.OpCodes.Ldc_R8, varNode.VariableValue); 
+              il.Emit(System.Reflection.Emit.OpCodes.Call, string_eq);
+              // TODO: convert bool to 1 / 0?
+            } else {
+              var nanResult = il.DefineLabel();
+              var normalResult = il.DefineLabel();
+              il.Emit(System.Reflection.Emit.OpCodes.Dup);
+              il.Emit(System.Reflection.Emit.OpCodes.Ldc_I4_0);
+              il.Emit(System.Reflection.Emit.OpCodes.Blt, nanResult);
+              il.Emit(System.Reflection.Emit.OpCodes.Dup);
+              il.Emit(System.Reflection.Emit.OpCodes.Ldc_I4, ds.Rows);
+              il.Emit(System.Reflection.Emit.OpCodes.Bge, nanResult);
+              il.Emit(System.Reflection.Emit.OpCodes.Call, listGetValue);
+              il.Emit(System.Reflection.Emit.OpCodes.Ldc_R8, varNode.VariableValue);
+              il.Emit(System.Reflection.Emit.OpCodes.Call, string_eq);
+              // TODO: convert bool to 1 / 0?
+              il.Emit(System.Reflection.Emit.OpCodes.Br, normalResult);
+              il.MarkLabel(nanResult);
+              il.Emit(System.Reflection.Emit.OpCodes.Pop); // rowIndex
+              il.Emit(System.Reflection.Emit.OpCodes.Pop); // column reference
+              il.Emit(System.Reflection.Emit.OpCodes.Ldc_R8, double.NaN);
+              il.MarkLabel(normalResult);
+            }
+            return;
+          }
         case OpCodes.LagVariable: {
             var nanResult = il.DefineLabel();
Index: branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeInterpreter.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeInterpreter.cs	(revision 14195)
+++ branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeInterpreter.cs	(revision 14232)
@@ -22,4 +22,5 @@
 using System;
 using System.Collections.Generic;
+using System.Linq;
 using HeuristicLab.Common;
 using HeuristicLab.Core;
@@ -143,4 +144,7 @@
           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.LagVariable) {
           var laggedVariableTreeNode = (LaggedVariableTreeNode)instr.dynamicNode;
@@ -455,4 +459,9 @@
             return ((IList<double>)currentInstr.data)[row] * variableTreeNode.Weight;
           }
+        case OpCodes.FactorVariable: {
+            if (row < 0 || row >= dataset.Rows) return double.NaN;
+            var factorVarTreeNode = currentInstr.dynamicNode as FactorVariableTreeNode;
+            return ((IList<string>)currentInstr.data)[row] == factorVarTreeNode.VariableValue ? 1 : 0;
+          }
         case OpCodes.LagVariable: {
             var laggedVariableTreeNode = (LaggedVariableTreeNode)currentInstr.dynamicNode;
Index: branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeLinearInterpreter.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeLinearInterpreter.cs	(revision 14195)
+++ branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeLinearInterpreter.cs	(revision 14232)
@@ -147,4 +147,10 @@
             var variableTreeNode = (VariableTreeNode)instr.dynamicNode;
             instr.value = ((IList<double>)instr.data)[row] * variableTreeNode.Weight;
+          }
+        } 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 = ((IList<string>)instr.data)[row] == factorTreeNode.VariableValue ? 1 : 0;
           }
         } else if (instr.opCode == OpCodes.LagVariable) {
@@ -392,4 +398,9 @@
             }
             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;
Index: branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisModelComplexityCalculator.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisModelComplexityCalculator.cs	(revision 14195)
+++ branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisModelComplexityCalculator.cs	(revision 14232)
@@ -39,8 +39,9 @@
             return 1;
           }
-        case OpCodes.Variable: {
+        case OpCodes.Variable:
+        case OpCodes.FactorVariable: {
             return 2;
           }
-        case OpCodes.Add: 
+        case OpCodes.Add:
         case OpCodes.Sub: {
             double complexity = 0;
@@ -50,5 +51,5 @@
             return complexity;
           }
-        case OpCodes.Mul: 
+        case OpCodes.Mul:
         case OpCodes.Div: {
             double complexity = 1;
@@ -60,7 +61,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 +76,5 @@
             return complexity * complexity * complexity;
           }
-        case OpCodes.Power:          
+        case OpCodes.Power:
         case OpCodes.Root: {
             double complexity = CalculateComplexity(node.GetSubtree(0));
Index: branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisProblem.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisProblem.cs	(revision 14195)
+++ branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisProblem.cs	(revision 14232)
@@ -208,16 +208,27 @@
 
     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.Variable>()) {
         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>()) {
+      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().ToList());
+        }
+      }
+      foreach (var varSymbol in grammar.Symbols.OfType<HeuristicLab.Problems.DataAnalysis.Symbolic.VariableCondition>()) {
         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;
         }
       }
Index: branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisSolutionImpactValuesCalculator.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisSolutionImpactValuesCalculator.cs	(revision 14195)
+++ branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisSolutionImpactValuesCalculator.cs	(revision 14232)
@@ -21,4 +21,5 @@
 
 using System.Collections.Generic;
+using System.Linq;
 using HeuristicLab.Common;
 using HeuristicLab.Core;
@@ -36,25 +37,31 @@
     [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,
+    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;
+      FactorVariableTreeNode factorNode = node as FactorVariableTreeNode;
+      if (constantNode != null) {
+        yield return constantNode.Value;
+      } else if (factorNode != null) {
+        // valid replacements are either all off or all on
+        yield return 0;
+        yield return 1;
+      } 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();
     }
   }
