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 14233)
+++ /branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/FactorVariable.cs	(revision 14233)
@@ -0,0 +1,145 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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 {
+  // TODO: handle correctly in all interpreters and formatters
+  // TODO: view for factor variables (configuration of actually allowed factors)
+  // TODO: handle correctly in variable impacts view
+  // TODO: handle correctly in Non-linear regression (infix parser and infix formatter)
+  // TODO: support in all analyzers which handle variable symbols specifically
+  // TODO: handle correctly in gradient views
+  // TODO: handle correctly in ERC view (create linear regression model)
+  // TODO: handle correctly in classification - solution comparison
+  // TODO: allow factor variables in decision trees (and therefore GBT)?
+  // TODO: support in more algs?
+  // TODO: support in more views?
+  [StorableClass]
+  [Item("FactorVariable", "Represents a categorical variable (comparable to factors as in R).")]
+  public class FactorVariable : Symbol {
+    #region Properties
+    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);
+      }
+    }
+
+    private 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));
+        }
+      }
+    }
+
+
+    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
+
+    [StorableConstructor]
+    protected FactorVariable(bool deserializing)
+      : base(deserializing) {
+      variableNames = new List<string>();
+      allVariableNames = new List<string>();
+      variableValues = new Dictionary<string, List<string>>();
+    }
+    protected FactorVariable(FactorVariable original, Cloner cloner)
+      : base(original, cloner) {
+      variableNames = new List<string>(original.variableNames);
+      allVariableNames = new List<string>(original.allVariableNames);
+      variableValues =
+        original.variableValues.ToDictionary(kvp => kvp.Key, kvp => new List<string>(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) {
+      variableNames = new List<string>();
+      allVariableNames = new List<string>();
+      variableValues = new Dictionary<string, List<string>>();
+    }
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      if (allVariableNames == null || (allVariableNames.Count == 0 && variableNames.Count > 0)) {
+        allVariableNames = variableNames;
+      }
+    }
+    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];
+    }
+  }
+}
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 14233)
+++ /branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/FactorVariableTreeNode.cs	(revision 14233)
@@ -0,0 +1,83 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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 class FactorVariableTreeNode : SymbolicExpressionTreeTerminalNode {
+    public new FactorVariable Symbol {
+      get { return (FactorVariable)base.Symbol; }
+    }
+    [Storable]
+    private string variableName;
+    public string VariableName {
+      get { return variableName; }
+      set { variableName = value; }
+    }
+
+    [Storable]
+    private string variableValue;
+    public string VariableValue {
+      get { return variableValue; }
+      set { variableValue = value; }
+    }
+
+    [StorableConstructor]
+    protected FactorVariableTreeNode(bool deserializing) : base(deserializing) { }
+    protected FactorVariableTreeNode(FactorVariableTreeNode original, Cloner cloner)
+      : base(original, cloner) {
+      variableName = original.variableName;
+      variableValue = original.variableValue;
+    }
+    protected FactorVariableTreeNode() { }
+    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);
+      variableValue = Symbol.GetVariableValues(VariableName).SampleRandom(random);
+    }
+
+    public override void ShakeLocalParameters(IRandom random, double shakingFactor) {
+      base.ShakeLocalParameters(random, shakingFactor);
+      if (random.NextDouble() < 0.2) {
+        variableName = Symbol.VariableNames.SampleRandom(random);
+      }
+      variableValue = Symbol.GetVariableValues(VariableName).SampleRandom(random);
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new FactorVariableTreeNode(this, cloner);
+    }
+
+    public override string ToString() {
+      return variableName + " = " + variableValue;
+    }
+  }
+}
