Example #1
0
        private void AssertEqualAfterSimplification(string original, string expected)
        {
            var formatter    = new SymbolicExpressionTreeStringFormatter();
            var importer     = new SymbolicExpressionImporter();
            var actualTree   = TreeSimplifier.Simplify(importer.Import(original));
            var expectedTree = importer.Import(expected);

            Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
        }
        private void TestMatchedNodes(string expr1, string expr2, int expected)
        {
            var t1 = importer.Import(expr1);
            var t2 = importer.Import(expr2);

            var mapping = busCalculator.ComputeBottomUpMapping(t1.Root, t2.Root);
            var c       = mapping.Count;

            if (c != expected)
            {
                throw new Exception("Match count " + c + " is different than expected value " + expected);
            }
        }
        private void Evaluate(ISymbolicDataAnalysisExpressionTreeInterpreter interpreter, Dataset ds, string expr, int index, double expected)
        {
            var importer = new SymbolicExpressionImporter();
            ISymbolicExpressionTree tree = importer.Import(expr);

            double actual = interpreter.GetSymbolicExpressionTreeValues(tree, ds, Enumerable.Range(index, 1)).First();

            Assert.IsFalse(double.IsNaN(actual) && !double.IsNaN(expected));
            Assert.IsFalse(!double.IsNaN(actual) && double.IsNaN(expected));
            if (!double.IsNaN(actual) && !double.IsNaN(expected))
            {
                Assert.AreEqual(expected, actual, 1.0E-12, expr);
            }
        }
    private void Evaluate(ISymbolicDataAnalysisExpressionTreeInterpreter interpreter, Dataset ds, string expr, int index, double expected) {
      var importer = new SymbolicExpressionImporter();
      ISymbolicExpressionTree tree = importer.Import(expr);

      double actual = interpreter.GetSymbolicExpressionTreeValues(tree, ds, Enumerable.Range(index, 1)).First();

      Assert.IsFalse(double.IsNaN(actual) && !double.IsNaN(expected));
      Assert.IsFalse(!double.IsNaN(actual) && double.IsNaN(expected));
      if (!double.IsNaN(actual) && !double.IsNaN(expected))
        Assert.AreEqual(expected, actual, 1.0E-12, expr);
    }
        public void SimplifierAxiomsTest()
        {
            SymbolicExpressionImporter importer = new SymbolicExpressionImporter();
            SymbolicDataAnalysisExpressionTreeSimplifier simplifier = new SymbolicDataAnalysisExpressionTreeSimplifier();
            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
            #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
            #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
            #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
            #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
            #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));
            }
            #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
            #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));
            }
            #endregion
        }