Index: branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SingleObjective/Evaluators/SymbolicRegressionConstantOptimizationEvaluator.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SingleObjective/Evaluators/SymbolicRegressionConstantOptimizationEvaluator.cs	(revision 14195)
+++ branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SingleObjective/Evaluators/SymbolicRegressionConstantOptimizationEvaluator.cs	(revision 14232)
@@ -181,13 +181,14 @@
       List<AutoDiff.Variable> parameters = new List<AutoDiff.Variable>();
       List<string> variableNames = new List<string>();
+      List<string> categoricalVariableValues = new List<string>();
 
       AutoDiff.Term func;
-      if (!TryTransformToAutoDiff(tree.Root.GetSubtree(0), variables, parameters, variableNames, updateVariableWeights, out func))
+      if (!TryTransformToAutoDiff(tree.Root.GetSubtree(0), variables, parameters, variableNames, categoricalVariableValues, updateVariableWeights, out func))
         throw new NotSupportedException("Could not optimize constants of symbolic expression tree due to not supported symbols used in the tree.");
-      if (variableNames.Count == 0) return 0.0;
+      if (variableNames.Count == 0) return 0.0; // gkronber: constant expressions always have a R² of 0.0 
 
       AutoDiff.IParametricCompiledTerm compiledFunc = func.Compile(variables.ToArray(), parameters.ToArray());
 
-      List<SymbolicExpressionTreeTerminalNode> terminalNodes = null;
+      List<SymbolicExpressionTreeTerminalNode> terminalNodes = null; // gkronber only used for extraction of initial constants
       if (updateVariableWeights)
         terminalNodes = tree.Root.IterateNodesPrefix().OfType<SymbolicExpressionTreeTerminalNode>().ToList();
@@ -222,5 +223,9 @@
       foreach (var r in rows) {
         for (int col = 0; col < variableNames.Count; col++) {
-          x[row, col] = ds.GetDoubleValue(variableNames[col], r);
+          if (ds.VariableHasType<double>(variableNames[col])) {
+            x[row, col] = ds.GetDoubleValue(variableNames[col], r);
+          } else if (ds.VariableHasType<string>(variableNames[col])) {
+            x[row, col] = ds.GetStringValue(variableNames[col], r) == categoricalVariableValues[col] ? 1 : 0;
+          } else throw new InvalidProgramException("found a variable of unknown type");
         }
         row++;
@@ -286,5 +291,6 @@
     }
 
-    private static bool TryTransformToAutoDiff(ISymbolicExpressionTreeNode node, List<AutoDiff.Variable> variables, List<AutoDiff.Variable> parameters, List<string> variableNames, bool updateVariableWeights, out AutoDiff.Term term) {
+    private static bool TryTransformToAutoDiff(ISymbolicExpressionTreeNode node, List<AutoDiff.Variable> variables, List<AutoDiff.Variable> parameters,
+      List<string> variableNames, List<string> categoricalVariableValues, bool updateVariableWeights, out AutoDiff.Term term) {
       if (node.Symbol is Constant) {
         var var = new AutoDiff.Variable();
@@ -298,4 +304,5 @@
         parameters.Add(par);
         variableNames.Add(varNode.VariableName);
+        categoricalVariableValues.Add(string.Empty);   // as a value as placeholder (variableNames.Length == catVariableValues.Length)
 
         if (updateVariableWeights) {
@@ -308,9 +315,20 @@
         return true;
       }
+      if (node.Symbol is FactorVariable) {
+        // nothing to update in this case (like a variable without a weight)
+        // values are only 0 or 1 and set in x accordingly
+        var factorNode = node as FactorVariableTreeNode;
+        var par = new AutoDiff.Variable();
+        parameters.Add(par);
+        variableNames.Add(factorNode.VariableName);
+        categoricalVariableValues.Add(factorNode.VariableValue);
+        term = par;
+        return true;
+      }
       if (node.Symbol is Addition) {
         List<AutoDiff.Term> terms = new List<Term>();
         foreach (var subTree in node.Subtrees) {
           AutoDiff.Term t;
-          if (!TryTransformToAutoDiff(subTree, variables, parameters, variableNames, updateVariableWeights, out t)) {
+          if (!TryTransformToAutoDiff(subTree, variables, parameters, variableNames, categoricalVariableValues, updateVariableWeights, out t)) {
             term = null;
             return false;
@@ -325,5 +343,5 @@
         for (int i = 0; i < node.SubtreeCount; i++) {
           AutoDiff.Term t;
-          if (!TryTransformToAutoDiff(node.GetSubtree(i), variables, parameters, variableNames, updateVariableWeights, out t)) {
+          if (!TryTransformToAutoDiff(node.GetSubtree(i), variables, parameters, variableNames, categoricalVariableValues, updateVariableWeights, out t)) {
             term = null;
             return false;
@@ -340,5 +358,5 @@
         foreach (var subTree in node.Subtrees) {
           AutoDiff.Term t;
-          if (!TryTransformToAutoDiff(subTree, variables, parameters, variableNames, updateVariableWeights, out t)) {
+          if (!TryTransformToAutoDiff(subTree, variables, parameters, variableNames, categoricalVariableValues, updateVariableWeights, out t)) {
             term = null;
             return false;
@@ -355,5 +373,5 @@
         foreach (var subTree in node.Subtrees) {
           AutoDiff.Term t;
-          if (!TryTransformToAutoDiff(subTree, variables, parameters, variableNames, updateVariableWeights, out t)) {
+          if (!TryTransformToAutoDiff(subTree, variables, parameters, variableNames, categoricalVariableValues, updateVariableWeights, out t)) {
             term = null;
             return false;
@@ -367,5 +385,5 @@
       if (node.Symbol is Logarithm) {
         AutoDiff.Term t;
-        if (!TryTransformToAutoDiff(node.GetSubtree(0), variables, parameters, variableNames, updateVariableWeights, out t)) {
+        if (!TryTransformToAutoDiff(node.GetSubtree(0), variables, parameters, variableNames, categoricalVariableValues, updateVariableWeights, out t)) {
           term = null;
           return false;
@@ -377,5 +395,5 @@
       if (node.Symbol is Exponential) {
         AutoDiff.Term t;
-        if (!TryTransformToAutoDiff(node.GetSubtree(0), variables, parameters, variableNames, updateVariableWeights, out t)) {
+        if (!TryTransformToAutoDiff(node.GetSubtree(0), variables, parameters, variableNames, categoricalVariableValues, updateVariableWeights, out t)) {
           term = null;
           return false;
@@ -387,5 +405,5 @@
       if (node.Symbol is Square) {
         AutoDiff.Term t;
-        if (!TryTransformToAutoDiff(node.GetSubtree(0), variables, parameters, variableNames, updateVariableWeights, out t)) {
+        if (!TryTransformToAutoDiff(node.GetSubtree(0), variables, parameters, variableNames, categoricalVariableValues, updateVariableWeights, out t)) {
           term = null;
           return false;
@@ -397,5 +415,5 @@
       if (node.Symbol is SquareRoot) {
         AutoDiff.Term t;
-        if (!TryTransformToAutoDiff(node.GetSubtree(0), variables, parameters, variableNames, updateVariableWeights, out t)) {
+        if (!TryTransformToAutoDiff(node.GetSubtree(0), variables, parameters, variableNames, categoricalVariableValues, updateVariableWeights, out t)) {
           term = null;
           return false;
@@ -407,5 +425,5 @@
       if (node.Symbol is Sine) {
         AutoDiff.Term t;
-        if (!TryTransformToAutoDiff(node.GetSubtree(0), variables, parameters, variableNames, updateVariableWeights, out t)) {
+        if (!TryTransformToAutoDiff(node.GetSubtree(0), variables, parameters, variableNames, categoricalVariableValues, updateVariableWeights, out t)) {
           term = null;
           return false;
@@ -417,5 +435,5 @@
       if (node.Symbol is Cosine) {
         AutoDiff.Term t;
-        if (!TryTransformToAutoDiff(node.GetSubtree(0), variables, parameters, variableNames, updateVariableWeights, out t)) {
+        if (!TryTransformToAutoDiff(node.GetSubtree(0), variables, parameters, variableNames, categoricalVariableValues, updateVariableWeights, out t)) {
           term = null;
           return false;
@@ -427,5 +445,5 @@
       if (node.Symbol is Tangent) {
         AutoDiff.Term t;
-        if (!TryTransformToAutoDiff(node.GetSubtree(0), variables, parameters, variableNames, updateVariableWeights, out t)) {
+        if (!TryTransformToAutoDiff(node.GetSubtree(0), variables, parameters, variableNames, categoricalVariableValues, updateVariableWeights, out t)) {
           term = null;
           return false;
@@ -437,5 +455,5 @@
       if (node.Symbol is Erf) {
         AutoDiff.Term t;
-        if (!TryTransformToAutoDiff(node.GetSubtree(0), variables, parameters, variableNames, updateVariableWeights, out t)) {
+        if (!TryTransformToAutoDiff(node.GetSubtree(0), variables, parameters, variableNames, categoricalVariableValues, updateVariableWeights, out t)) {
           term = null;
           return false;
@@ -447,5 +465,5 @@
       if (node.Symbol is Norm) {
         AutoDiff.Term t;
-        if (!TryTransformToAutoDiff(node.GetSubtree(0), variables, parameters, variableNames, updateVariableWeights, out t)) {
+        if (!TryTransformToAutoDiff(node.GetSubtree(0), variables, parameters, variableNames, categoricalVariableValues, updateVariableWeights, out t)) {
           term = null;
           return false;
@@ -461,5 +479,5 @@
         variables.Add(alpha);
         AutoDiff.Term branchTerm;
-        if (TryTransformToAutoDiff(node.GetSubtree(0), variables, parameters, variableNames, updateVariableWeights, out branchTerm)) {
+        if (TryTransformToAutoDiff(node.GetSubtree(0), variables, parameters, variableNames, categoricalVariableValues, updateVariableWeights, out branchTerm)) {
           term = branchTerm * alpha + beta;
           return true;
@@ -478,4 +496,5 @@
         where
          !(n.Symbol is Variable) &&
+         !(n.Symbol is FactorVariable) &&
          !(n.Symbol is Constant) &&
          !(n.Symbol is Addition) &&
Index: branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SymbolicRegressionSolutionImpactValuesCalculator.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SymbolicRegressionSolutionImpactValuesCalculator.cs	(revision 14195)
+++ branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SymbolicRegressionSolutionImpactValuesCalculator.cs	(revision 14232)
@@ -41,20 +41,8 @@
     [StorableConstructor]
     protected SymbolicRegressionSolutionImpactValuesCalculator(bool deserializing) : base(deserializing) { }
-    public override double CalculateReplacementValue(ISymbolicDataAnalysisModel model, ISymbolicExpressionTreeNode node, IDataAnalysisProblemData problemData, IEnumerable<int> rows) {
-      var regressionModel = (ISymbolicRegressionModel)model;
-      var regressionProblemData = (IRegressionProblemData)problemData;
-
-      return CalculateReplacementValue(node, regressionModel.SymbolicExpressionTree, regressionModel.Interpreter, regressionProblemData.Dataset, rows);
-    }
-
-    public override double CalculateImpactValue(ISymbolicDataAnalysisModel model, ISymbolicExpressionTreeNode node, IDataAnalysisProblemData problemData, IEnumerable<int> rows, double qualityForImpactsCalculation = double.NaN) {
-      double impactValue, replacementValue, newQualityForImpactsCalculation;
-      CalculateImpactAndReplacementValues(model, node, problemData, rows, out impactValue, out replacementValue, out newQualityForImpactsCalculation, qualityForImpactsCalculation);
-      return impactValue;
-    }
 
     public override void CalculateImpactAndReplacementValues(ISymbolicDataAnalysisModel model, ISymbolicExpressionTreeNode node,
       IDataAnalysisProblemData problemData, IEnumerable<int> rows, out double impactValue, out double replacementValue, out double newQualityForImpactsCalculation,
-      double qualityForImpactsCalculation = Double.NaN) {
+      double qualityForImpactsCalculation = double.NaN) {
       var regressionModel = (ISymbolicRegressionModel)model;
       var regressionProblemData = (IRegressionProblemData)problemData;
@@ -63,10 +51,6 @@
       var targetValues = dataset.GetDoubleValues(regressionProblemData.TargetVariable, rows);
 
-      OnlineCalculatorError errorState;
       if (double.IsNaN(qualityForImpactsCalculation))
         qualityForImpactsCalculation = CalculateQualityForImpacts(regressionModel, regressionProblemData, rows);
-
-      replacementValue = CalculateReplacementValue(regressionModel, node, regressionProblemData, rows);
-      var constantNode = new ConstantTreeNode(new Constant()) { Value = replacementValue };
 
       var cloner = new Cloner();
@@ -76,13 +60,31 @@
       var tempModelParentNode = tempModelNode.Parent;
       int i = tempModelParentNode.IndexOfSubtree(tempModelNode);
-      tempModelParentNode.RemoveSubtree(i);
-      tempModelParentNode.InsertSubtree(i, constantNode);
 
-      var estimatedValues = tempModel.GetEstimatedValues(dataset, rows);
-      double r = OnlinePearsonsRCalculator.Calculate(targetValues, estimatedValues, out errorState);
-      if (errorState != OnlineCalculatorError.None) r = 0.0;
-      newQualityForImpactsCalculation = r * r;
+      double bestReplacementValue = 0.0;
+      double bestImpactValue = double.NegativeInfinity;
+      newQualityForImpactsCalculation = qualityForImpactsCalculation; // initialize
+      // try the potentially reasonable replacement values and use the best one
+      foreach (var repValue in CalculateReplacementValues(node, regressionModel.SymbolicExpressionTree, regressionModel.Interpreter, regressionProblemData.Dataset, regressionProblemData.TrainingIndices)) {
 
-      impactValue = qualityForImpactsCalculation - newQualityForImpactsCalculation;
+        tempModelParentNode.RemoveSubtree(i);
+
+        var constantNode = new ConstantTreeNode(new Constant()) { Value = repValue };
+
+        tempModelParentNode.InsertSubtree(i, constantNode);
+
+        var estimatedValues = tempModel.GetEstimatedValues(dataset, rows);
+        OnlineCalculatorError errorState;
+        double r = OnlinePearsonsRCalculator.Calculate(targetValues, estimatedValues, out errorState);
+        if (errorState != OnlineCalculatorError.None) r = 0.0;
+        newQualityForImpactsCalculation = r * r;
+
+        impactValue = qualityForImpactsCalculation - newQualityForImpactsCalculation;
+        if (impactValue > bestImpactValue) {
+          bestImpactValue = impactValue;
+          bestReplacementValue = repValue;
+        }
+      }
+      replacementValue = bestReplacementValue;
+      impactValue = bestImpactValue;
     }
 
