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 14502)
+++ branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Importer/SymbolicExpressionImporter.cs	(revision 14534)
@@ -35,5 +35,5 @@
     private const string INVOKESTART = "CALL";
     private const string TIMELAGSTART = "LAG";
-    private Dictionary<string, Symbol> knownSymbols = new Dictionary<string, Symbol>() 
+    private Dictionary<string, Symbol> knownSymbols = new Dictionary<string, Symbol>()
       {
         {"+", new Addition()},
@@ -45,4 +45,6 @@
         {"POW", new Power()},
         {"ROOT", new Root()},
+        {"SQR", new Square()},
+        {"SQRT", new SquareRoot()},
         {"SIN",new Sine()},
         {"COS", new Cosine()},
@@ -74,4 +76,6 @@
         {"PROG", new ProgramRootSymbol()},
         {"MAIN", new StartSymbol()},
+        {"FACTOR", new FactorVariable() },
+        {"BINARYFACTOR", new BinaryFactorVariable()}
       };
 
@@ -82,4 +86,6 @@
     TimeLag timeLag = new TimeLag();
     Integral integral = new Integral();
+    FactorVariable factorVar = new FactorVariable();
+    BinaryFactorVariable binFactorVar = new BinaryFactorVariable();
 
     ProgramRootSymbol programRootSymbol = new ProgramRootSymbol();
@@ -91,5 +97,5 @@
       ISymbolicExpressionTreeNode start = startSymbol.CreateTreeNode();
       ISymbolicExpressionTreeNode mainBranch = ParseSexp(new Queue<Token>(GetTokenStream(str)));
-      if (mainBranch.Symbol is ProgramRootSymbol) {
+      if(mainBranch.Symbol is ProgramRootSymbol) {
         // when a root symbol was parsed => use main branch as root
         root = mainBranch;
@@ -111,33 +117,37 @@
 
     private ISymbolicExpressionTreeNode ParseSexp(Queue<Token> tokens) {
-      if (tokens.Peek().Symbol == TokenSymbol.LPAR) {
+      if(tokens.Peek().Symbol == TokenSymbol.LPAR) {
         ISymbolicExpressionTreeNode tree;
         Expect(Token.LPAR, tokens);
-        if (tokens.Peek().StringValue.StartsWith(VARSTART)) {
+        if(tokens.Peek().StringValue.StartsWith(VARSTART)) {
           tree = ParseVariable(tokens);
-        } else if (tokens.Peek().StringValue.StartsWith(LAGGEDVARSTART)) {
+        } else if(tokens.Peek().StringValue.StartsWith(LAGGEDVARSTART)) {
           tree = ParseLaggedVariable(tokens);
-        } else if (tokens.Peek().StringValue.StartsWith(TIMELAGSTART)) {
+        } else if(tokens.Peek().StringValue.StartsWith(TIMELAGSTART)) {
           tree = ParseTimeLag(tokens);
           tree.AddSubtree(ParseSexp(tokens));
-        } else if (tokens.Peek().StringValue.StartsWith(INTEGRALSTART)) {
+        } else if(tokens.Peek().StringValue.StartsWith(INTEGRALSTART)) {
           tree = ParseIntegral(tokens);
           tree.AddSubtree(ParseSexp(tokens));
-        } else if (tokens.Peek().StringValue.StartsWith(DEFUNSTART)) {
+        } else if(tokens.Peek().StringValue.StartsWith(DEFUNSTART)) {
           tree = ParseDefun(tokens);
-          while (!tokens.Peek().Equals(Token.RPAR)) {
+          while(!tokens.Peek().Equals(Token.RPAR)) {
             tree.AddSubtree(ParseSexp(tokens));
           }
-        } else if (tokens.Peek().StringValue.StartsWith(ARGSTART)) {
+        } else if(tokens.Peek().StringValue.StartsWith(ARGSTART)) {
           tree = ParseArgument(tokens);
-        } else if (tokens.Peek().StringValue.StartsWith(INVOKESTART)) {
+        } else if(tokens.Peek().StringValue.StartsWith(INVOKESTART)) {
           tree = ParseInvoke(tokens);
-          while (!tokens.Peek().Equals(Token.RPAR)) {
+          while(!tokens.Peek().Equals(Token.RPAR)) {
             tree.AddSubtree(ParseSexp(tokens));
           }
+        } else if(tokens.Peek().StringValue.StartsWith("FACTOR")) {
+          tree = ParseFactor(tokens);
+        } else if(tokens.Peek().StringValue.StartsWith("BINARYFACTOR")) {
+          tree = ParseBinaryFactor(tokens);
         } else {
           Token curToken = tokens.Dequeue();
           tree = CreateTree(curToken);
-          while (!tokens.Peek().Equals(Token.RPAR)) {
+          while(!tokens.Peek().Equals(Token.RPAR)) {
             tree.AddSubtree(ParseSexp(tokens));
           }
@@ -145,5 +155,5 @@
         Expect(Token.RPAR, tokens);
         return tree;
-      } else if (tokens.Peek().Symbol == TokenSymbol.NUMBER) {
+      } else if(tokens.Peek().Symbol == TokenSymbol.NUMBER) {
         ConstantTreeNode t = (ConstantTreeNode)constant.CreateTreeNode();
         t.Value = tokens.Dequeue().DoubleValue;
@@ -201,4 +211,45 @@
     }
 
+    private ISymbolicExpressionTreeNode ParseFactor(Queue<Token> tokens) {
+      Token tok = tokens.Dequeue();
+      Debug.Assert(tok.StringValue == "FACTOR");
+      FactorVariableTreeNode t = (FactorVariableTreeNode)(new FactorVariable()).CreateTreeNode(); // create a new symbol each time on purpose
+      var varNameTok = tokens.Dequeue();
+      Debug.Assert(tok.Symbol == TokenSymbol.SYMB);
+      t.VariableName = varNameTok.StringValue;
+
+      var weights = new List<double>();
+      while(tokens.Peek().Symbol == TokenSymbol.NUMBER) {
+        weights.Add(tokens.Dequeue().DoubleValue);
+      }
+
+      t.Weights = weights.ToArray();
+
+      // 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()) };
+      return t;
+    }
+
+    private ISymbolicExpressionTreeNode ParseBinaryFactor(Queue<Token> tokens) {
+      Token tok = tokens.Dequeue();
+      Debug.Assert(tok.StringValue == "BINFACTOR");
+      var t = (BinaryFactorVariableTreeNode)binFactorVar.CreateTreeNode();
+      var varNameTok = tokens.Dequeue();
+      Debug.Assert(tok.Symbol == TokenSymbol.SYMB);
+      t.VariableName = varNameTok.StringValue;
+
+      var varValTok = tokens.Dequeue();
+      Debug.Assert(tok.Symbol == TokenSymbol.SYMB);
+      t.VariableValue = varNameTok.StringValue;
+
+      var weightTok = tokens.Dequeue();
+      Debug.Assert(tok.Symbol == TokenSymbol.NUMBER);
+      t.Weight = weightTok.DoubleValue;
+
+      return t;
+    }
+
+
     private ISymbolicExpressionTreeNode ParseLaggedVariable(Queue<Token> tokens) {
       Token varTok = tokens.Dequeue();
@@ -212,5 +263,5 @@
 
     private ISymbolicExpressionTreeNode CreateTree(Token token) {
-      if (token.Symbol != TokenSymbol.SYMB) throw new FormatException("Expected function symbol, but got: " + token.StringValue);
+      if(token.Symbol != TokenSymbol.SYMB) throw new FormatException("Expected function symbol, but got: " + token.StringValue);
       return knownSymbols[token.StringValue].CreateTreeNode();
     }
@@ -218,5 +269,5 @@
     private void Expect(Token token, Queue<Token> tokens) {
       Token cur = tokens.Dequeue();
-      if (!token.Equals(cur)) throw new FormatException("Expected: " + token.StringValue + ", but got: " + cur.StringValue);
+      if(!token.Equals(cur)) throw new FormatException("Expected: " + token.StringValue + ", but got: " + cur.StringValue);
     }
   }
Index: branches/symbreg-factors-2650/HeuristicLab.Tests/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4/SymbolicDataAnalysisExpressionTreeSimplifierTest.cs
===================================================================
--- branches/symbreg-factors-2650/HeuristicLab.Tests/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4/SymbolicDataAnalysisExpressionTreeSimplifierTest.cs	(revision 14502)
+++ branches/symbreg-factors-2650/HeuristicLab.Tests/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4/SymbolicDataAnalysisExpressionTreeSimplifierTest.cs	(revision 14534)
@@ -19,9 +19,7 @@
  */
 #endregion
-
 using System;
-using System.Collections.Generic;
+using System.Globalization;
 using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
-using HeuristicLab.Problems.DataAnalysis.Symbolic;
 using Microsoft.VisualStudio.TestTools.UnitTesting;
 
@@ -39,316 +37,182 @@
       SymbolicExpressionTreeStringFormatter formatter = new SymbolicExpressionTreeStringFormatter();
       #region single argument arithmetics
-      {
-        var actualTree = simplifier.Simplify(importer.Import("(+ 1.0)"));
-        var expectedTree = importer.Import("1.0");
-        Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
-      }
-      {
-        var actualTree = simplifier.Simplify(importer.Import("(+ (variable 2.0 a))"));
-        var expectedTree = importer.Import("(variable 2.0 a)");
-        Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
-      }
-      {
-        var actualTree = simplifier.Simplify(importer.Import("(- 1.0)"));
-        var expectedTree = importer.Import("-1.0");
-        Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
-      }
-      {
-        var actualTree = simplifier.Simplify(importer.Import("(- (variable 2.0 a))"));
-        var expectedTree = importer.Import("(variable -2.0 a)");
-        Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
-      }
-      {
-        var actualTree = simplifier.Simplify(importer.Import("(* 2.0)"));
-        var expectedTree = importer.Import("2.0");
-        Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
-      }
-      {
-        var actualTree = simplifier.Simplify(importer.Import("(* (variable 2.0 a))"));
-        var expectedTree = importer.Import("(variable 2.0 a)");
-        Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
-      }
-      {
-        var actualTree = simplifier.Simplify(importer.Import("(/ 2.0)"));
-        var expectedTree = importer.Import("0.5");
-        Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
-      }
-      {
-        var actualTree = simplifier.Simplify(importer.Import("(/ (variable 2.0 a))"));
-        var expectedTree = importer.Import("(/ 1.0 (variable 2.0 a))");
-        Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
-      }
-      #endregion
+
+      AssertEqualAfterSimplification("(+ 1.0)", "1.0");
+      AssertEqualAfterSimplification("(- 1.0)", "-1.0");
+      AssertEqualAfterSimplification("(- (variable 2.0 a))", "(variable -2.0 a)");
+      AssertEqualAfterSimplification("(* 2.0)", "2.0");
+      AssertEqualAfterSimplification("(* (variable 2.0 a))", "(variable 2.0 a)");
+      AssertEqualAfterSimplification("(/ 2.0)", "0.5");
+      AssertEqualAfterSimplification("(/ (variable 2.0 a))", "(/ 1.0 (variable 2.0 a))");
+      #endregion
+
       #region aggregation of constants into factors
-      {
-        var actualTree = simplifier.Simplify(importer.Import("(* 2.0 (variable 2.0 a))"));
-        var expectedTree = importer.Import("(variable 4.0 a)");
-        Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
-      }
-      {
-        var actualTree = simplifier.Simplify(importer.Import("(/ (variable 2.0 a) 2.0)"));
-        var expectedTree = importer.Import("(variable 1.0 a)");
-        Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
-      }
-      {
-        var actualTree = simplifier.Simplify(importer.Import("(/ (variable 2.0 a) (* 2.0 2.0))"));
-        var expectedTree = importer.Import("(variable 0.5 a)");
-        Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
-      }
-      #endregion
+      AssertEqualAfterSimplification("(* 2.0 (variable 2.0 a))", "(variable 4.0 a)");
+      AssertEqualAfterSimplification("(/ (variable 2.0 a) 2.0)", "(variable 1.0 a)");
+      AssertEqualAfterSimplification("(/ (variable 2.0 a) (* 2.0 2.0))", "(variable 0.5 a)");
+      #endregion
+
       #region constant and variable folding
-      {
-        var actualTree = simplifier.Simplify(importer.Import("(+ 1.0 2.0)"));
-        var expectedTree = importer.Import("3.0");
-        Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
-      }
-      {
-        var actualTree = simplifier.Simplify(importer.Import("(+ (variable 2.0 a) (variable 2.0 a))"));
-        var expectedTree = importer.Import("(variable 4.0 a)");
-        Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
-      }
-      {
-        var actualTree = simplifier.Simplify(importer.Import("(- (variable 2.0 a) (variable 1.0 a))"));
-        var expectedTree = importer.Import("(variable 1.0 a)");
-        Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
-      }
-      {
-        var actualTree = simplifier.Simplify(importer.Import("(* (variable 2.0 a) (variable 2.0 a))"));
-        var expectedTree = importer.Import("(* (* (variable 1.0 a) (variable 1.0 a)) 4.0)");
-        Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
-      }
-      {
-        var actualTree = simplifier.Simplify(importer.Import("(/ (variable 1.0 a) (variable 2.0 a))"));
-        var expectedTree = importer.Import("0.5");
-        Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
-      }
-      #endregion
+      AssertEqualAfterSimplification("(+ 1.0 2.0)", "3.0");
+      AssertEqualAfterSimplification("(+ (variable 2.0 a) (variable 2.0 a))", "(variable 4.0 a)");
+      AssertEqualAfterSimplification("(- (variable 2.0 a) (variable 1.0 a))", "(variable 1.0 a)");
+      AssertEqualAfterSimplification("(* (variable 2.0 a) (variable 2.0 a))", "(* (* (variable 1.0 a) (variable 1.0 a)) 4.0)");
+      AssertEqualAfterSimplification("(/ (variable 1.0 a) (variable 2.0 a))", "0.5");
+      #endregion
+
       #region logarithm rules
-      {
-        // cancellation
-        var actualTree = simplifier.Simplify(importer.Import("(log (exp (variable 2.0 a)))"));
-        var expectedTree = importer.Import("(variable 2.0 a)");
-        Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
-      }
-      {
-        // must not transform logs in this way as we do not know wether both variables are positive
-        var actualTree = simplifier.Simplify(importer.Import("(log (* (variable 1.0 a) (variable 1.0 b)))"));
-        var expectedTree = importer.Import("(log (* (variable 1.0 a) (variable 1.0 b)))");
-        Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
-      }
-      {
-        // must not transform logs in this way as we do not know wether both variables are positive
-        var actualTree = simplifier.Simplify(importer.Import("(log (/ (variable 1.0 a) (variable 1.0 b)))"));
-        var expectedTree = importer.Import("(log (/ (variable 1.0 a) (variable 1.0 b)))");
-        Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
-      }
-      #endregion
+
+      // cancellation
+      AssertEqualAfterSimplification("(log (exp (variable 2.0 a)))", "(variable 2.0 a)");
+      // must not transform logs in this way as we do not know wether both variables are positive
+      AssertEqualAfterSimplification("(log (* (variable 1.0 a) (variable 1.0 b)))", "(log (* (variable 1.0 a) (variable 1.0 b)))");
+      // must not transform logs in this way as we do not know wether both variables are positive
+      AssertEqualAfterSimplification("(log (/ (variable 1.0 a) (variable 1.0 b)))", "(log (/ (variable 1.0 a) (variable 1.0 b)))");
+      #endregion
+
       #region exponentiation rules
-      {
-        // cancellation
-        var actualTree = simplifier.Simplify(importer.Import("(exp (log (variable 2.0 a)))"));
-        var expectedTree = importer.Import("(variable 2.0 a)");
-        Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
-      }
-      {
-        // exp transformation
-        var actualTree = simplifier.Simplify(importer.Import("(exp (+ (variable 2.0 a) (variable 3.0 b)))"));
-        var expectedTree = importer.Import("(* (exp (variable 2.0 a)) (exp (variable 3.0 b)))");
-        Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
-      }
-      {
-        // exp transformation
-        var actualTree = simplifier.Simplify(importer.Import("(exp (- (variable 2.0 a) (variable 3.0 b)))"));
-        var expectedTree = importer.Import("(* (exp (variable 2.0 a)) (exp (variable -3.0 b)))");
-        Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
-      }
-      {
-        // exp transformation
-        var actualTree = simplifier.Simplify(importer.Import("(exp (- (variable 2.0 a) (* (variable 3.0 b) (variable 4.0 c))))"));
-        var expectedTree = importer.Import("(* (exp (variable 2.0 a)) (exp (* (variable 1.0 b) (variable 1.0 c) -12.0)))");
-        Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
-      }
-      {
-        // exp transformation
-        var actualTree = simplifier.Simplify(importer.Import("(exp (- (variable 2.0 a) (* (variable 3.0 b) (cos (variable 4.0 c)))))"));
-        var expectedTree = importer.Import("(* (exp (variable 2.0 a)) (exp (* (variable 1.0 b) (cos (variable 4.0 c)) -3.0)))");
-        Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
-      }
-      #endregion
+      // cancellation
+      AssertEqualAfterSimplification("(exp (log (variable 2.0 a)))", "(variable 2.0 a)");
+      // exp transformation
+      AssertEqualAfterSimplification("(exp (+ (variable 2.0 a) (variable 3.0 b)))", "(* (exp (variable 2.0 a)) (exp (variable 3.0 b)))");
+      // exp transformation
+      AssertEqualAfterSimplification("(exp (- (variable 2.0 a) (variable 3.0 b)))", "(* (exp (variable 2.0 a)) (exp (variable -3.0 b)))");
+      // exp transformation
+      AssertEqualAfterSimplification("(exp (- (variable 2.0 a) (* (variable 3.0 b) (variable 4.0 c))))", "(* (exp (variable 2.0 a)) (exp (* (variable 1.0 b) (variable 1.0 c) -12.0)))");
+      // exp transformation
+      AssertEqualAfterSimplification("(exp (- (variable 2.0 a) (* (variable 3.0 b) (cos (variable 4.0 c)))))", "(* (exp (variable 2.0 a)) (exp (* (variable 1.0 b) (cos (variable 4.0 c)) -3.0)))");
+      #endregion
+
       #region power rules
-      {
-        // cancellation
-        var actualTree = simplifier.Simplify(importer.Import("(pow (variable 2.0 a) 0.0)"));
-        var expectedTree = importer.Import("1.0");
-        Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
-      }
-      {
-        // fixed point
-        var actualTree = simplifier.Simplify(importer.Import("(pow (variable 2.0 a) 1.0)"));
-        var expectedTree = importer.Import("(variable 2.0 a)");
-        Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
-      }
-      {
-        // inversion fixed point
-        var actualTree = simplifier.Simplify(importer.Import("(pow (variable 2.0 a) -1.0)"));
-        var expectedTree = importer.Import("(/ 1.0 (variable 2.0 a))");
-        Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
-      }
-      {
-        // inversion 
-        var actualTree = simplifier.Simplify(importer.Import("(pow (variable 2.0 a) -2.0)"));
-        var expectedTree = importer.Import("(/ 1.0 (pow (variable 2.0 a) 2.0))");
-        Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
-      }
-      {
-        // constant folding
-        var actualTree = simplifier.Simplify(importer.Import("(pow 3.0 2.0)"));
-        var expectedTree = importer.Import("9.0");
-        Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
-      }
-      #endregion
+
+      // cancellation
+      AssertEqualAfterSimplification("(pow (variable 2.0 a) 0.0)", "1.0");
+      // fixed point
+      AssertEqualAfterSimplification("(pow (variable 2.0 a) 1.0)", "(variable 2.0 a)");
+      // inversion fixed point
+      AssertEqualAfterSimplification("(pow (variable 2.0 a) -1.0)", "(/ 1.0 (variable 2.0 a))");
+      // inversion 
+      AssertEqualAfterSimplification("(pow (variable 2.0 a) -2.0)", "(/ 1.0 (pow (variable 2.0 a) 2.0))");
+      // constant folding
+      AssertEqualAfterSimplification("(pow 3.0 2.0)", "9.0");
+      #endregion
+
       #region root rules
-      {
-        // cancellation
-        var actualTree = simplifier.Simplify(importer.Import("(root (variable 2.0 a) 0.0)"));
-        var expectedTree = importer.Import("1.0");
-        Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
-      }
-      {
-        // fixed point
-        var actualTree = simplifier.Simplify(importer.Import("(root (variable 2.0 a) 1.0)"));
-        var expectedTree = importer.Import("(variable 2.0 a)");
-        Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
-      }
-      {
-        // inversion fixed point
-        var actualTree = simplifier.Simplify(importer.Import("(root (variable 2.0 a) -1.0)"));
-        var expectedTree = importer.Import("(/ 1.0 (variable 2.0 a))");
-        Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
-      }
-      {
-        // inversion
-        var actualTree = simplifier.Simplify(importer.Import("(root (variable 2.0 a) -2.0)"));
-        var expectedTree = importer.Import("(/ 1.0 (root (variable 2.0 a) 2.0))");
-        Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
-      }
-      {
-        // constant folding
-        var actualTree = simplifier.Simplify(importer.Import("(root 9.0 2.0)"));
-        var expectedTree = importer.Import("3.0");
-        Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
-      }
-      #endregion
+      // cancellation
+      AssertEqualAfterSimplification("(root (variable 2.0 a) 0.0)", "1.0");
+      // fixed point
+      AssertEqualAfterSimplification("(root (variable 2.0 a) 1.0)", "(variable 2.0 a)");
+      // inversion fixed point
+      AssertEqualAfterSimplification("(root (variable 2.0 a) -1.0)", "(/ 1.0 (variable 2.0 a))");
+      // inversion
+      AssertEqualAfterSimplification("(root (variable 2.0 a) -2.0)", "(/ 1.0 (root (variable 2.0 a) 2.0))");
+      // constant folding
+      AssertEqualAfterSimplification("(root 9.0 2.0)", "3.0");
+      #endregion
+
       #region boolean operations
-      {
-        // always true and
-        var actualTree = simplifier.Simplify(importer.Import("(and 1.0 2.0)"));
-        var expectedTree = importer.Import("1.0");
-        Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
-      }
-      {
-        // always false and
-        var actualTree = simplifier.Simplify(importer.Import("(and 1.0 -2.0)"));
-        var expectedTree = importer.Import("-1.0");
-        Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
-      }
-      {
-        // always true or
-        var actualTree = simplifier.Simplify(importer.Import("(or -1.0 2.0)"));
-        var expectedTree = importer.Import("1.0");
-        Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
-      }
-      {
-        // always false or
-        var actualTree = simplifier.Simplify(importer.Import("(or -1.0 -2.0)"));
-        var expectedTree = importer.Import("-1.0");
-        Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
-      }
-      {
-        // constant not 
-        var actualTree = simplifier.Simplify(importer.Import("(not -2.0)"));
-        var expectedTree = importer.Import("1.0");
-        Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
-      }
-      {
-        // constant not 
-        var actualTree = simplifier.Simplify(importer.Import("(not 2.0)"));
-        var expectedTree = importer.Import("-1.0");
-        Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
-      }
-      {
-        // constant not 
-        var actualTree = simplifier.Simplify(importer.Import("(not 0.0)"));
-        var expectedTree = importer.Import("1.0");
-        Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
-      }
-      {
-        // nested nots
-        var actualTree = simplifier.Simplify(importer.Import("(not (not 1.0))"));
-        var expectedTree = importer.Import("1.0");
-        Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
-      }
-      {
-        // not of non-Boolean argument
-        var actualTree = simplifier.Simplify(importer.Import("(not (variable 1.0 a))"));
-        var expectedTree = importer.Import("(not (> (variable 1.0 a) 0.0))");
-        Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
-      }
-      {
-        // not Boolean argument
-        var actualTree = simplifier.Simplify(importer.Import("(not (and (> (variable 1.0 a) 0.0) (> (variable 1.0 a) 0.0)))"));
-        var expectedTree = importer.Import("(not (and (> (variable 1.0 a) 0.0) (> (variable 1.0 a) 0.0)))");
-        Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
-      }
-      #endregion
+      // always true and
+      AssertEqualAfterSimplification("(and 1.0 2.0)", "1.0");
+      // always false and
+      AssertEqualAfterSimplification("(and 1.0 -2.0)", "-1.0");
+      // always true or
+      AssertEqualAfterSimplification("(or -1.0 2.0)", "1.0");
+      // always false or
+      AssertEqualAfterSimplification("(or -1.0 -2.0)", "-1.0");
+      // constant not 
+      AssertEqualAfterSimplification("(not -2.0)", "1.0");
+      // constant not 
+      AssertEqualAfterSimplification("(not 2.0)", "-1.0");
+      // constant not 
+      AssertEqualAfterSimplification("(not 0.0)", "1.0");
+      // nested nots
+      AssertEqualAfterSimplification("(not (not 1.0))", "1.0");
+      // not of non-Boolean argument
+      AssertEqualAfterSimplification("(not (variable 1.0 a))", "(not (> (variable 1.0 a) 0.0))");
+      // not Boolean argument
+      AssertEqualAfterSimplification("(not (and (> (variable 1.0 a) 0.0) (> (variable 1.0 a) 0.0)))", "(not (and (> (variable 1.0 a) 0.0) (> (variable 1.0 a) 0.0)))");
+      #endregion
+
       #region conditionals
-      {
-        // always false
-        var actualTree = simplifier.Simplify(importer.Import("(if -1.0 (variable 2.0 a) (variable 3.0 a))"));
-        var expectedTree = importer.Import("(variable 3.0 a)");
-        Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
-      }
-      {
-        // always true
-        var actualTree = simplifier.Simplify(importer.Import("(if 1.0 (variable 2.0 a) (variable 3.0 a))"));
-        var expectedTree = importer.Import("(variable 2.0 a)");
-        Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
-      }
-      {
-        // always false (0.0)
-        var actualTree = simplifier.Simplify(importer.Import("(if 0.0 (variable 2.0 a) (variable 3.0 a))"));
-        var expectedTree = importer.Import("(variable 3.0 a)");
-        Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
-      }
-      {
-        // complex constant condition (always false)
-        var actualTree = simplifier.Simplify(importer.Import("(if (* 1.0 -2.0) (variable 2.0 a) (variable 3.0 a))"));
-        var expectedTree = importer.Import("(variable 3.0 a)");
-        Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
-      }
-      {
-        // complex constant condition (always false)
-        var actualTree = simplifier.Simplify(importer.Import("(if (/ (variable 1.0 a) (variable -2.0 a)) (variable 2.0 a) (variable 3.0 a))"));
-        var expectedTree = importer.Import("(variable 3.0 a)");
-        Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
-      }
-      {
-        // insertion of relational operator
-        var actualTree = simplifier.Simplify(importer.Import("(if (variable 1.0 a) (variable 2.0 a) (variable 3.0 a))"));
-        var expectedTree = importer.Import("(if (> (variable 1.0 a) 0.0) (variable 2.0 a) (variable 3.0 a))");
-        Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
-      }
+      // always false
+      AssertEqualAfterSimplification("(if -1.0 (variable 2.0 a) (variable 3.0 a))", "(variable 3.0 a)");
+      // always true
+      AssertEqualAfterSimplification("(if 1.0 (variable 2.0 a) (variable 3.0 a))", "(variable 2.0 a)");
+      // always false (0.0)
+      AssertEqualAfterSimplification("(if 0.0 (variable 2.0 a) (variable 3.0 a))", "(variable 3.0 a)");
+      // complex constant condition (always false)
+      AssertEqualAfterSimplification("(if (* 1.0 -2.0) (variable 2.0 a) (variable 3.0 a))", "(variable 3.0 a)");
+      // complex constant condition (always false)
+      AssertEqualAfterSimplification("(if (/ (variable 1.0 a) (variable -2.0 a)) (variable 2.0 a) (variable 3.0 a))", "(variable 3.0 a)");
+      // insertion of relational operator
+      AssertEqualAfterSimplification("(if (variable 1.0 a) (variable 2.0 a) (variable 3.0 a))", "(if (> (variable 1.0 a) 0.0) (variable 2.0 a) (variable 3.0 a))");
+      #endregion
+
+      #region factor variables
+      AssertEqualAfterSimplification("(factor a 1.0)", "(factor a 1.0)");
+      // factor folding
+      AssertEqualAfterSimplification("(+ (factor a 1.0 1.0) (factor a 2.0 3.0))", "(factor a 3.0 4.0)");
+      AssertEqualAfterSimplification("(- (factor a 1.0 1.0) (factor a 2.0 3.0))", "(factor a -1.0 -2.0)");
+      AssertEqualAfterSimplification("(* (factor a 2.0 2.0) (factor a 2.0 3.0))", "(factor a 4.0 6.0)");
+      AssertEqualAfterSimplification("(/ (factor a 2.0 5.0))", "(factor a 0.5 0.2)");
+      AssertEqualAfterSimplification("(/ (factor a 4.0 6.0) (factor a 2.0 3.0))", "(factor a 2.0 2.0)");
+      AssertEqualAfterSimplification("(+ 3.0 (factor a 4.0 6.0))", "(factor a 7.0 9.0)");
+      AssertEqualAfterSimplification("(+ (factor a 4.0 6.0) 3.0)", "(factor a 7.0 9.0)");
+      AssertEqualAfterSimplification("(* 2.0 (factor a 4.0 6.0))", "(factor a 8.0 12.0)");
+      AssertEqualAfterSimplification("(* (factor a 4.0 6.0) 2.0)", "(factor a 8.0 12.0)");
+      AssertEqualAfterSimplification("(* (factor a 4.0 6.0) (variable 2.0 a))", "(* (factor a 4.0 6.0) (variable 2.0 a))");   // not possible
+      AssertEqualAfterSimplification(
+        "(log (factor a 10.0 100.0))",
+        string.Format(CultureInfo.InvariantCulture, "(factor a {0} {1})", Math.Log(10.0), Math.Log(100.0)));
+      AssertEqualAfterSimplification(
+        "(exp (factor a 2.0 3.0))",
+        string.Format(CultureInfo.InvariantCulture, "(factor a {0} {1})", Math.Exp(2.0), Math.Exp(3.0)));
+      AssertEqualAfterSimplification("(sqrt (factor a 9.0 16.0))", "(factor a 3.0 4.0))");
+      AssertEqualAfterSimplification("(sqr (factor a 2.0 3.0))", "(factor a 4.0 9.0))");
+      AssertEqualAfterSimplification("(root (factor a 8.0 27.0) 3)", "(factor a 2.0 3.0))");
+      AssertEqualAfterSimplification("(power (factor a 2.0 3.0) 3)", "(factor a 8.0 27.0))");
+
+      AssertEqualAfterSimplification("(sin (factor a 1.0 2.0) )",
+        string.Format(CultureInfo.InvariantCulture, "(factor a {0} {1}))", Math.Sin(1.0), Math.Sin(2.0)));
+      AssertEqualAfterSimplification("(cos (factor a 1.0 2.0) )",
+        string.Format(CultureInfo.InvariantCulture, "(factor a {0} {1}))", Math.Cos(1.0), Math.Cos(2.0)));
+      AssertEqualAfterSimplification("(tan (factor a 1.0 2.0) )",
+        string.Format(CultureInfo.InvariantCulture, "(factor a {0} {1}))", Math.Tan(1.0), Math.Tan(2.0)));
+
+
+      AssertEqualAfterSimplification("(binfactor a val 1.0)", "(binfactor a val 1.0)");
+      // binfactor folding
+      AssertEqualAfterSimplification("(+ (binfactor a val 1.0) (binfactor a val 2.0))", "(binfactor a val 3.0)");
+      AssertEqualAfterSimplification("(+ (binfactor a val0 1.0) (binfactor a val1 2.0))", "(+ (binfactor a val0 1.0) (binfactor a val1 2.0))"); // cannot be simplified (different vals)
+      AssertEqualAfterSimplification("(+ (binfactor a val 1.0) (binfactor b val 2.0))", "(+ (binfactor a val 1.0) (binfactor b val 2.0))"); // cannot be simplified (different vars)
+      AssertEqualAfterSimplification("(- (binfactor a val 1.0) (binfactor a val 2.0))", "(binfactor a val -1.0)");
+      AssertEqualAfterSimplification("(* (binfactor a val 2.0) (binfactor a val 3.0))", "(binfactor a val 6.0)");
+      AssertEqualAfterSimplification("(/ (binfactor a val 6.0) (binfactor a val 3.0))", "(binfactor a val 2.0)");
+      AssertEqualAfterSimplification("(/ (binfactor a val 4.0))", "(binfactor a val 0.25)");
+
+      AssertEqualAfterSimplification("(+ 3.0 (binfactor a val 4.0 ))", "(binfactor a val 7.0 )");
+      AssertEqualAfterSimplification("(+ (binfactor a val 4.0 ) 3.0)", "(binfactor a val 7.0 )");
+      AssertEqualAfterSimplification("(* 2.0 (binfactor a val 4.0))", "(binfactor a val 8.0 )");
+      AssertEqualAfterSimplification("(* (binfactor a val 4.0) 2.0)", "(binfactor a val 8.0 )");
+
+      // TODO same set of functions as for factor symbols
+
+      // combination of factor and binfactor
+      // TODO: should we support this?
+      AssertEqualAfterSimplification("(+ (binfactor a x0 2.0) (factor a 2.0 3.0))", "(factor a 4.0 3.0)");
       #endregion
     }
 
-    private void AssertEqualEnumerations(IEnumerable<double> expected, IEnumerable<double> actual) {
-      var expectedEnumerator = expected.GetEnumerator();
-      var actualEnumerator = actual.GetEnumerator();
-      while (expectedEnumerator.MoveNext() & actualEnumerator.MoveNext()) {
-        Assert.AreEqual(expectedEnumerator.Current, actualEnumerator.Current, Math.Abs(1E-6 * expectedEnumerator.Current));
-      }
-      if (expectedEnumerator.MoveNext() | actualEnumerator.MoveNext())
-        Assert.Fail("Number of elements in enumerations do not match");
+
+    private void AssertEqualAfterSimplification(string original, string expected) {
+      var simplifier = new SymbolicDataAnalysisExpressionTreeSimplifier();
+      var formatter = new SymbolicExpressionTreeStringFormatter();
+      var importer = new SymbolicExpressionImporter();
+      var actualTree = simplifier.Simplify(importer.Import(original));
+      var expectedTree = importer.Import(expected);
+      Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
+
     }
   }
 }
+
