Index: /trunk/sources/HeuristicLab.Problems.DataAnalysis/3.3/Symbolic/SymbolicSimplifier.cs
===================================================================
--- /trunk/sources/HeuristicLab.Problems.DataAnalysis/3.3/Symbolic/SymbolicSimplifier.cs	(revision 5464)
+++ /trunk/sources/HeuristicLab.Problems.DataAnalysis/3.3/Symbolic/SymbolicSimplifier.cs	(revision 5465)
@@ -42,4 +42,6 @@
     private Logarithm logSymbol = new Logarithm();
     private Exponential expSymbol = new Exponential();
+    private Root rootSymbol = new Root();
+    private Power powSymbol = new Power();
     private Sine sineSymbol = new Sine();
     private Cosine cosineSymbol = new Cosine();
@@ -122,4 +124,10 @@
     private bool IsExp(SymbolicExpressionTreeNode node) {
       return node.Symbol is Exponential;
+    }
+    private bool IsRoot(SymbolicExpressionTreeNode node) {
+      return node.Symbol is Root;
+    }
+    private bool IsPower(SymbolicExpressionTreeNode node) {
+      return node.Symbol is Power;
     }
     // trigonometric
@@ -195,4 +203,8 @@
       } else if (IsExp(original)) {
         return SimplifyExp(original);
+      } else if (IsRoot(original)) {
+        return SimplifyRoot(original);
+      } else if (IsPower(original)) {
+        return SimplifyPower(original);
       } else if (IsSine(original)) {
         return SimplifySine(original);
@@ -347,8 +359,12 @@
       return MakeLog(GetSimplifiedTree(original.SubTrees[0]));
     }
-
+    private SymbolicExpressionTreeNode SimplifyRoot(SymbolicExpressionTreeNode original) {
+      return MakeRoot(GetSimplifiedTree(original.SubTrees[0]), GetSimplifiedTree(original.SubTrees[1]));
+    }
+
+    private SymbolicExpressionTreeNode SimplifyPower(SymbolicExpressionTreeNode original) {
+      return MakePower(GetSimplifiedTree(original.SubTrees[0]), GetSimplifiedTree(original.SubTrees[1]));
+    }
     #endregion
-
-
 
     #region low level tree restructuring
@@ -462,5 +478,4 @@
 
     private SymbolicExpressionTreeNode MakeSine(SymbolicExpressionTreeNode node) {
-      // todo implement more transformation rules
       if (IsConstant(node)) {
         var constT = node as ConstantTreeNode;
@@ -473,5 +488,4 @@
     }
     private SymbolicExpressionTreeNode MakeTangent(SymbolicExpressionTreeNode node) {
-      // todo implement more transformation rules
       if (IsConstant(node)) {
         var constT = node as ConstantTreeNode;
@@ -484,5 +498,4 @@
     }
     private SymbolicExpressionTreeNode MakeCosine(SymbolicExpressionTreeNode node) {
-      // todo implement more transformation rules
       if (IsConstant(node)) {
         var constT = node as ConstantTreeNode;
@@ -495,5 +508,4 @@
     }
     private SymbolicExpressionTreeNode MakeExp(SymbolicExpressionTreeNode node) {
-      // todo implement more transformation rules
       if (IsConstant(node)) {
         var constT = node as ConstantTreeNode;
@@ -501,4 +513,8 @@
       } else if (IsLog(node)) {
         return node.SubTrees[0];
+      } else if (IsAddition(node)) {
+        return node.SubTrees.Select(s => MakeExp(s)).Aggregate((s, t) => MakeProduct(s, t));
+      } else if (IsSubtraction(node)) {
+        return node.SubTrees.Select(s => MakeExp(s)).Aggregate((s, t) => MakeProduct(s, Negate(t)));
       } else {
         var expNode = expSymbol.CreateTreeNode();
@@ -508,5 +524,4 @@
     }
     private SymbolicExpressionTreeNode MakeLog(SymbolicExpressionTreeNode node) {
-      // todo implement more transformation rules
       if (IsConstant(node)) {
         var constT = node as ConstantTreeNode;
@@ -526,4 +541,68 @@
         logNode.AddSubTree(node);
         return logNode;
+      }
+    }
+    private SymbolicExpressionTreeNode MakeRoot(SymbolicExpressionTreeNode a, SymbolicExpressionTreeNode b) {
+      if (IsConstant(a) && IsConstant(b)) {
+        var constA = a as ConstantTreeNode;
+        var constB = b as ConstantTreeNode;
+        return MakeConstant(Math.Pow(constA.Value, 1.0 / Math.Round(constB.Value)));
+      } else if (IsConstant(b)) {
+        var constB = b as ConstantTreeNode;
+        var constBValue = Math.Round(constB.Value);
+        if (constBValue.IsAlmost(1.0)) {
+          return a;
+        } else if (constBValue.IsAlmost(0.0)) {
+          return MakeConstant(1.0);
+        } else if (constBValue.IsAlmost(-1.0)) {
+          return MakeFraction(MakeConstant(1.0), a);
+        } else if (constBValue < 0) {
+          var rootNode = rootSymbol.CreateTreeNode();
+          rootNode.AddSubTree(a);
+          rootNode.AddSubTree(MakeConstant(-1.0 * constBValue));
+          return MakeFraction(MakeConstant(1.0), rootNode);
+        } else {
+          var rootNode = rootSymbol.CreateTreeNode();
+          rootNode.AddSubTree(a);
+          rootNode.AddSubTree(MakeConstant(constBValue));
+          return rootNode;
+        }
+      } else {
+        var rootNode = rootSymbol.CreateTreeNode();
+        rootNode.AddSubTree(a);
+        rootNode.AddSubTree(b);
+        return rootNode;
+      }
+    }
+    private SymbolicExpressionTreeNode MakePower(SymbolicExpressionTreeNode a, SymbolicExpressionTreeNode b) {
+      if (IsConstant(a) && IsConstant(b)) {
+        var constA = a as ConstantTreeNode;
+        var constB = b as ConstantTreeNode;
+        return MakeConstant(Math.Pow(constA.Value, Math.Round(constB.Value)));
+      } else if (IsConstant(b)) {
+        var constB = b as ConstantTreeNode;
+        double exponent = Math.Round(constB.Value);
+        if (exponent.IsAlmost(0.0)) {
+          return MakeConstant(1.0);
+        } else if (exponent.IsAlmost(1.0)) {
+          return a;
+        } else if (exponent.IsAlmost(-1.0)) {
+          return MakeFraction(MakeConstant(1.0), a);
+        } else if (exponent < 0) {
+          var powNode = powSymbol.CreateTreeNode();
+          powNode.AddSubTree(a);
+          powNode.AddSubTree(MakeConstant(-1.0 * exponent));
+          return MakeFraction(MakeConstant(1.0), powNode);
+        } else {
+          var powNode = powSymbol.CreateTreeNode();
+          powNode.AddSubTree(a);
+          powNode.AddSubTree(MakeConstant(exponent));
+          return powNode;
+        }
+      } else {
+        var powNode = powSymbol.CreateTreeNode();
+        powNode.AddSubTree(a);
+        powNode.AddSubTree(b);
+        return powNode;
       }
     }
Index: /trunk/sources/HeuristicLab.Problems.DataAnalysis/3.3/Tests/SymbolicExpressionImporter.cs
===================================================================
--- /trunk/sources/HeuristicLab.Problems.DataAnalysis/3.3/Tests/SymbolicExpressionImporter.cs	(revision 5464)
+++ /trunk/sources/HeuristicLab.Problems.DataAnalysis/3.3/Tests/SymbolicExpressionImporter.cs	(revision 5465)
@@ -42,4 +42,6 @@
         {"EXP", new Exponential()},
         {"LOG", new Logarithm()},
+        {"POW", new Power()},
+        {"ROOT", new Root()},
         {"SIN",new Sine()},
         {"COS", new Cosine()},
Index: /trunk/sources/HeuristicLab.Problems.DataAnalysis/3.3/Tests/SymbolicSimplifierTest.cs
===================================================================
--- /trunk/sources/HeuristicLab.Problems.DataAnalysis/3.3/Tests/SymbolicSimplifierTest.cs	(revision 5464)
+++ /trunk/sources/HeuristicLab.Problems.DataAnalysis/3.3/Tests/SymbolicSimplifierTest.cs	(revision 5465)
@@ -170,10 +170,4 @@
       {
         // 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));
-      }
-      {
-        // cancellation
         var actualTree = simplifier.Simplify(importer.Import("(log (exp (variable 2.0 a)))"));
         var expectedTree = importer.Import("(variable 2.0 a)");
@@ -190,4 +184,88 @@
         var actualTree = simplifier.Simplify(importer.Import("(log (/ (variable 2.0 a) (variable 3.0 b)))"));
         var expectedTree = importer.Import("(- (log (variable 2.0 a)) (log (variable 3.0 b)))");
+        Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
+      }
+      #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));
+      }
+      #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
+      #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));
       }
