Index: branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Importer/SymbolicExpressionImporter.cs
===================================================================
--- branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Importer/SymbolicExpressionImporter.cs	(revision 14716)
+++ branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Importer/SymbolicExpressionImporter.cs	(revision 14717)
@@ -228,5 +228,8 @@
       // create a set of (virtual) values to match the number of weights
       t.Symbol.VariableNames = new string[] { t.VariableName };
-      t.Symbol.VariableValues = new KeyValuePair<string, List<string>>[] { new KeyValuePair<string, List<string>>(t.VariableName, weights.Select((_, i) => "X" + i).ToList()) };
+      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;
     }
Index: branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisProblem.cs
===================================================================
--- branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisProblem.cs	(revision 14716)
+++ branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisProblem.cs	(revision 14717)
@@ -159,5 +159,5 @@
     [StorableHook(HookType.AfterDeserialization)]
     private void AfterDeserialization() {
-      if (!Parameters.ContainsKey(ApplyLinearScalingParameterName)) {
+      if(!Parameters.ContainsKey(ApplyLinearScalingParameterName)) {
         Parameters.Add(new FixedValueParameter<BoolValue>(ApplyLinearScalingParameterName, ApplyLinearScalingParameterDescription, new BoolValue(false)));
         ApplyLinearScalingParameter.Hidden = true;
@@ -165,5 +165,5 @@
         //it is assumed that for all symbolic regression algorithms linear scaling was set to true
         //there is no possibility to determine the previous value of the parameter as it was stored in the evaluator
-        if (GetType().Name.Contains("SymbolicRegression"))
+        if(GetType().Name.Contains("SymbolicRegression"))
           ApplyLinearScaling.Value = true;
       }
@@ -213,12 +213,12 @@
       grammar.MaximumFunctionArguments = MaximumFunctionArguments.Value;
       grammar.MaximumFunctionDefinitions = MaximumFunctionDefinitions.Value;
-      foreach (var varSymbol in grammar.Symbols.OfType<HeuristicLab.Problems.DataAnalysis.Symbolic.VariableBase>()) {
-        if (!varSymbol.Fixed) {
+      foreach(var varSymbol in grammar.Symbols.OfType<HeuristicLab.Problems.DataAnalysis.Symbolic.VariableBase>()) {
+        if(!varSymbol.Fixed) {
           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 factorSymbol in grammar.Symbols.OfType<BinaryFactorVariable>()) {
-        if (!factorSymbol.Fixed) {
+      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));
@@ -226,10 +226,14 @@
             .ToDictionary(varName => varName, varName => ds.GetStringValues(varName).Distinct().ToList());
         }
-      } foreach (var factorSymbol in grammar.Symbols.OfType<FactorVariable>()) {
-        if (!factorSymbol.Fixed) {
+      }
+      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());
+            .ToDictionary(varName => varName,
+            varName => ds.GetStringValues(varName).Distinct()
+            .Select((n, i) => Tuple.Create(n, i))
+            .ToDictionary(tup => tup.Item1, tup => tup.Item2));
         }
       }
@@ -276,5 +280,5 @@
 
     private void MaximumSymbolicExpressionTreeDepth_ValueChanged(object sender, EventArgs e) {
-      if (MaximumSymbolicExpressionTreeDepth != null && MaximumSymbolicExpressionTreeDepth.Value < 3)
+      if(MaximumSymbolicExpressionTreeDepth != null && MaximumSymbolicExpressionTreeDepth.Value < 3)
         MaximumSymbolicExpressionTreeDepth.Value = 3;
     }
@@ -304,5 +308,5 @@
 
       var handler = ProblemDataChanged;
-      if (handler != null) handler(this, EventArgs.Empty);
+      if(handler != null) handler(this, EventArgs.Empty);
 
       OnReset();
@@ -313,16 +317,16 @@
       var operators = Parameters.OfType<IValueParameter>().Select(p => p.Value).OfType<IOperator>().Union(Operators).ToList();
 
-      foreach (var op in operators.OfType<ISymbolicExpressionTreeGrammarBasedOperator>()) {
+      foreach(var op in operators.OfType<ISymbolicExpressionTreeGrammarBasedOperator>()) {
         op.SymbolicExpressionTreeGrammarParameter.ActualName = SymbolicExpressionTreeGrammarParameter.Name;
       }
-      foreach (var op in operators.OfType<ISymbolicExpressionTreeSizeConstraintOperator>()) {
+      foreach(var op in operators.OfType<ISymbolicExpressionTreeSizeConstraintOperator>()) {
         op.MaximumSymbolicExpressionTreeDepthParameter.ActualName = MaximumSymbolicExpressionTreeDepthParameter.Name;
         op.MaximumSymbolicExpressionTreeLengthParameter.ActualName = MaximumSymbolicExpressionTreeLengthParameter.Name;
       }
-      foreach (var op in operators.OfType<ISymbolicExpressionTreeArchitectureAlteringOperator>()) {
+      foreach(var op in operators.OfType<ISymbolicExpressionTreeArchitectureAlteringOperator>()) {
         op.MaximumFunctionArgumentsParameter.ActualName = MaximumFunctionArgumentsParameter.Name;
         op.MaximumFunctionDefinitionsParameter.ActualName = MaximumFunctionDefinitionsParameter.Name;
       }
-      foreach (var op in operators.OfType<ISymbolicDataAnalysisEvaluator<T>>()) {
+      foreach(var op in operators.OfType<ISymbolicDataAnalysisEvaluator<T>>()) {
         op.ProblemDataParameter.ActualName = ProblemDataParameterName;
         op.SymbolicExpressionTreeParameter.ActualName = SolutionCreator.SymbolicExpressionTreeParameter.ActualName;
@@ -331,31 +335,31 @@
         op.ApplyLinearScalingParameter.ActualName = ApplyLinearScalingParameter.Name;
       }
-      foreach (var op in operators.OfType<ISymbolicExpressionTreeCrossover>()) {
+      foreach(var op in operators.OfType<ISymbolicExpressionTreeCrossover>()) {
         op.ParentsParameter.ActualName = SolutionCreator.SymbolicExpressionTreeParameter.ActualName;
         op.SymbolicExpressionTreeParameter.ActualName = SolutionCreator.SymbolicExpressionTreeParameter.ActualName;
       }
-      foreach (var op in operators.OfType<ISymbolicExpressionTreeManipulator>()) {
-        op.SymbolicExpressionTreeParameter.ActualName = SolutionCreator.SymbolicExpressionTreeParameter.ActualName;
-      }
-      foreach (var op in operators.OfType<ISymbolicExpressionTreeAnalyzer>()) {
-        op.SymbolicExpressionTreeParameter.ActualName = SolutionCreator.SymbolicExpressionTreeParameter.ActualName;
-      }
-      foreach (var op in operators.OfType<ISymbolicDataAnalysisSingleObjectiveAnalyzer>()) {
+      foreach(var op in operators.OfType<ISymbolicExpressionTreeManipulator>()) {
+        op.SymbolicExpressionTreeParameter.ActualName = SolutionCreator.SymbolicExpressionTreeParameter.ActualName;
+      }
+      foreach(var op in operators.OfType<ISymbolicExpressionTreeAnalyzer>()) {
+        op.SymbolicExpressionTreeParameter.ActualName = SolutionCreator.SymbolicExpressionTreeParameter.ActualName;
+      }
+      foreach(var op in operators.OfType<ISymbolicDataAnalysisSingleObjectiveAnalyzer>()) {
         op.ApplyLinearScalingParameter.ActualName = ApplyLinearScalingParameter.Name;
       }
-      foreach (var op in operators.OfType<ISymbolicDataAnalysisMultiObjectiveAnalyzer>()) {
+      foreach(var op in operators.OfType<ISymbolicDataAnalysisMultiObjectiveAnalyzer>()) {
         op.ApplyLinearScalingParameter.ActualName = ApplyLinearScalingParameter.Name;
       }
-      foreach (var op in operators.OfType<ISymbolicDataAnalysisAnalyzer>()) {
-        op.SymbolicExpressionTreeParameter.ActualName = SolutionCreator.SymbolicExpressionTreeParameter.ActualName;
-      }
-      foreach (var op in operators.OfType<ISymbolicDataAnalysisValidationAnalyzer<U, T>>()) {
+      foreach(var op in operators.OfType<ISymbolicDataAnalysisAnalyzer>()) {
+        op.SymbolicExpressionTreeParameter.ActualName = SolutionCreator.SymbolicExpressionTreeParameter.ActualName;
+      }
+      foreach(var op in operators.OfType<ISymbolicDataAnalysisValidationAnalyzer<U, T>>()) {
         op.RelativeNumberOfEvaluatedSamplesParameter.ActualName = RelativeNumberOfEvaluatedSamplesParameter.Name;
         op.ValidationPartitionParameter.ActualName = ValidationPartitionParameter.Name;
       }
-      foreach (var op in operators.OfType<ISymbolicDataAnalysisInterpreterOperator>()) {
+      foreach(var op in operators.OfType<ISymbolicDataAnalysisInterpreterOperator>()) {
         op.SymbolicDataAnalysisTreeInterpreterParameter.ActualName = SymbolicExpressionTreeInterpreterParameter.Name;
       }
-      foreach (var op in operators.OfType<ISymbolicDataAnalysisExpressionCrossover<T>>()) {
+      foreach(var op in operators.OfType<ISymbolicDataAnalysisExpressionCrossover<T>>()) {
         op.EvaluationPartitionParameter.ActualName = FitnessCalculationPartitionParameter.Name;
         op.ProblemDataParameter.ActualName = ProblemDataParameter.Name;
Index: branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/FactorVariable.cs
===================================================================
--- branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/FactorVariable.cs	(revision 14716)
+++ branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/FactorVariable.cs	(revision 14717)
@@ -31,13 +31,13 @@
   [Item("FactorVariable", "Represents a categorical variable (comparable to factors as in R).")]
   public class FactorVariable : VariableBase {
-    private readonly Dictionary<string, List<string>> variableValues;
+    private readonly Dictionary<string, Dictionary<string, int>> variableValues; // for each variable value also store a zero-based index
     [Storable]
-    public IEnumerable<KeyValuePair<string, List<string>>> VariableValues {
+    public IEnumerable<KeyValuePair<string, Dictionary<string, int>>> VariableValues {
       get { return variableValues; }
       set {
-        if (value == null) throw new ArgumentNullException();
+        if(value == null) throw new ArgumentNullException();
         variableValues.Clear();
-        foreach (var kvp in value) {
-          variableValues.Add(kvp.Key, new List<string>(kvp.Value));
+        foreach(var kvp in value) {
+          variableValues.Add(kvp.Key, new Dictionary<string, int>(kvp.Value));
         }
       }
@@ -47,15 +47,15 @@
     protected FactorVariable(bool deserializing)
       : base(deserializing) {
-      variableValues = new Dictionary<string, List<string>>();
+      variableValues = new Dictionary<string, Dictionary<string, int>>();
     }
     protected FactorVariable(FactorVariable original, Cloner cloner)
       : base(original, cloner) {
       variableValues =
-        original.variableValues.ToDictionary(kvp => kvp.Key, kvp => new List<string>(kvp.Value));
+        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, List<string>>();
+      variableValues = new Dictionary<string, Dictionary<string,int>>();
     }
 
@@ -69,5 +69,9 @@
 
     public IEnumerable<string> GetVariableValues(string variableName) {
-      return variableValues[variableName];
+      return variableValues[variableName].Keys;
+    }
+
+    public int GetIndexForValue(string variableName, string variableValue) {
+      return variableValues[variableName][variableValue];
     }
   }
Index: branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/FactorVariableTreeNode.cs
===================================================================
--- branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/FactorVariableTreeNode.cs	(revision 14716)
+++ branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/FactorVariableTreeNode.cs	(revision 14717)
@@ -21,4 +21,5 @@
 
 using System;
+using System.Collections.Generic;
 using System.Linq;
 using HeuristicLab.Common;
@@ -51,5 +52,5 @@
       : base(original, cloner) {
       variableName = original.variableName;
-      if (original.weights != null) {
+      if(original.weights != null) {
         this.weights = new double[original.Weights.Length];
         Array.Copy(original.Weights, weights, weights.Length);
@@ -74,7 +75,7 @@
 
     public override void ShakeLocalParameters(IRandom random, double shakingFactor) {
-      if (random.NextDouble() < 0.2) {
+      if(random.NextDouble() < 0.2) {
         VariableName = Symbol.VariableNames.SampleRandom(random);
-        if (weights.Length != Symbol.GetVariableValues(VariableName).Count()) {
+        if(weights.Length != Symbol.GetVariableValues(VariableName).Count()) {
           // if the length of the weight array does not match => re-initialize weights
           weights =
@@ -87,5 +88,5 @@
         var idx = random.Next(weights.Length);
         // 50% additive & 50% multiplicative
-        if (random.NextDouble() < 0.5) {
+        if(random.NextDouble() < 0.5) {
           double x = NormalDistributedRandom.NextDouble(random, Symbol.WeightManipulatorMu,
             Symbol.WeightManipulatorSigma);
@@ -103,12 +104,5 @@
 
     public double GetValue(string cat) {
-      // TODO: perf
-      var s = Symbol;
-      int idx = 0;
-      foreach (var val in s.GetVariableValues(VariableName)) {
-        if (cat == val) return weights[idx];
-        idx++;
-      }
-      throw new ArgumentOutOfRangeException("Found unknown value " + cat + " for variable " + VariableName);
+      return weights[Symbol.GetIndexForValue(VariableName, cat)];
     }
 
