public void TestRegularLookaheadComposition2()
        {
            Z3Provider Z = new Z3Provider();
            var        A = (Z.TT.MkRankedAlphabet("A", Z.IntSort, new string[] { "zeroA", "oneA", "twoA" }, new int[] { 0, 1, 2 }));
            var        B = (Z.TT.MkRankedAlphabet("B", Z.IntSort, new string[] { "zeroB", "oneB", "twoB" }, new int[] { 0, 1, 2 }));
            var        C = (Z.TT.MkRankedAlphabet("C", Z.IntSort, new string[] { "zeroC", "oneC", "twoC" }, new int[] { 0, 1, 2 }));

            var _0 = Z.MkInt(0);
            var _1 = Z.MkInt(1);
            var _2 = Z.MkInt(2);

            var AB_r0 = Z.TT.MkTreeRule(A, B, 0, "oneA", Z.MkEq(_0, A.AttrVar), B.MkTree("oneB", Z.MkAdd(_1, A.AttrVar), A.MkTrans(B, 1, 1)), new int[][] { new int[] { 1 } });
            var AB_r1 = Z.TT.MkTreeRule(A, B, 1, "oneA", Z.MkEq(_1, A.AttrVar), B.MkTree("oneB", Z.MkAdd(_1, A.AttrVar), A.MkTrans(B, 0, 1)), new int[][] { new int[] { 0 } });
            var AB_r2 = Z.TT.MkTreeRule(A, B, 1, "oneA", Z.MkEq(_2, A.AttrVar), B.MkTree("zeroB", Z.MkAdd(_1, A.AttrVar)));

            //just accept the input if the attribute is 1 and delete the child subtree
            var BC_r0 = Z.TT.MkTreeRule(B, C, 0, "oneB", Z.MkEq(_1, B.AttrVar), C.MkTree("zeroC", B.AttrVar));

            var AB = Z.TT.MkTreeAutomaton(0, A, B, new TreeRule[] { AB_r0, AB_r1, AB_r2 });
            var BC = Z.TT.MkTreeAutomaton(0, B, C, new TreeRule[] { BC_r0 });

            var AC = TreeTransducer.ComposeR(AB, BC);

            Assert.AreEqual <int>(4, AC.RuleCount);
        }
        public void TestRegularLookaheadComposition3()
        {
            Z3Provider Z = new Z3Provider();
            var        A = (Z.TT.MkRankedAlphabet("A", Z.IntSort, new string[] { "z", "u", "b" }, new int[] { 0, 1, 2 }));
            var        B = (Z.TT.MkRankedAlphabet("B", Z.IntSort, new string[] { "z", "u", "b" }, new int[] { 0, 1, 2 }));
            var        C = (Z.TT.MkRankedAlphabet("C", Z.IntSort, new string[] { "z", "u", "b" }, new int[] { 0, 1, 2 }));

            var _0 = Z.MkInt(0);
            var _1 = Z.MkInt(1);
            var _2 = Z.MkInt(2);
            var _7 = Z.MkInt(7);

            var AB_r0 = Z.TT.MkTreeRule(A, B, 0, "u", Z.MkLe(_0, A.AttrVar), B.MkTree("u", Z.MkAdd(_1, A.AttrVar), A.MkTrans(B, 1, 1)), new int[][] { new int[] { 3, 1 } });
            var AB_r1 = Z.TT.MkTreeRule(A, B, 1, "u", Z.MkLe(_1, A.AttrVar), B.MkTree("u", Z.MkAdd(_1, A.AttrVar), A.MkTrans(B, 0, 1)), new int[][] { new int[] { 2, 0 } });
            var AB_r2 = Z.TT.MkTreeRule(A, B, 1, "u", Z.MkEq(_2, A.AttrVar), B.MkTree("z", Z.MkAdd(_1, A.AttrVar)));

            var AB_q2  = Z.TT.MkTreeRule(A, B, 2, "u", Z.MkGe(_0, A.AttrVar), null, new int[][] { new int[] { 3 } });
            var AB_q3a = Z.TT.MkTreeRule(A, B, 3, "u", Z.MkGe(_1, A.AttrVar), null, new int[][] { new int[] { 2 } });
            var AB_q3b = Z.TT.MkTreeRule(A, B, 3, "u", Z.MkEq(_2, A.AttrVar), null);

            //just accept the input if the attribute is 1, delete the child subtree and return zeroC(1)
            var BC_r0 = Z.TT.MkTreeRule(B, C, 0, "u", Z.MkEq(_1, B.AttrVar), C.MkTree("z", Z.MkAdd(_7, B.AttrVar)));

            var AB = Z.TT.MkTreeAutomaton(0, A, B, new TreeRule[] { AB_r0, AB_r1, AB_r2, AB_q2, AB_q3a, AB_q3b });
            var BC = Z.TT.MkTreeAutomaton(0, B, C, new TreeRule[] { BC_r0 });

            var AC = TreeTransducer.ComposeR(AB, BC);

            Assert.AreEqual <int>(5, AC.RuleCount);
        }
        public void TestRegularLookaheadComposition1()
        {
            Z3Provider Z = new Z3Provider();
            var        A = (Z.TT.MkRankedAlphabet("A", Z.IntSort, new string[] { "zeroA", "oneA", "twoA" }, new int[] { 0, 1, 2 }));
            var        B = (Z.TT.MkRankedAlphabet("B", Z.IntSort, new string[] { "zeroB", "oneB", "twoB" }, new int[] { 0, 1, 2 }));
            var        C = (Z.TT.MkRankedAlphabet("C", Z.IntSort, new string[] { "zeroC", "oneC", "twoC" }, new int[] { 0, 1, 2 }));

            //(two (plus 1 x0) (one (plus 1 x0) (q x1)) (one (plus 2 x0) (q x2)))
            var b = Z.MkApp(B["twoB"],
                            Z.MkAdd(Z.MkInt(1), A.AttrVar),
                            B.MkTree("oneB", Z.MkAdd(Z.MkInt(1), A.AttrVar), A.MkTrans(B, 0, 1)),
                            B.MkTree("oneB", Z.MkAdd(Z.MkInt(2), A.AttrVar), A.MkTrans(B, 0, 2)));

            //(two (plus 1 x0) (zero x0) (one (plus 100 x0) (q x2)))
            var b2 = Z.MkApp(B["twoB"],
                             Z.MkAdd(Z.MkInt(1), A.AttrVar),
                             B.MkTree("zeroB", A.AttrVar),
                             B.MkTree("oneB", Z.MkAdd(Z.MkInt(9), A.AttrVar), A.MkTrans(B, 0, 2)));

            var rule0 = Z.TT.MkTreeRule(A, B, 0, "zeroA", Z.True, B.MkTree("zeroB", A.AttrVar));
            var rule1 = Z.TT.MkTreeRule(A, B, 0, "twoA", Z.MkGt(A.AttrVar, Z.MkInt(0)), b);
            var rule2 = Z.TT.MkTreeRule(A, B, 0, "twoA", Z.MkGt(A.AttrVar, Z.MkInt(0)), b2);
            var rule3 = Z.TT.MkTreeRule(A, B, 0, "oneA", Z.MkGt(A.AttrVar, Z.MkInt(0)), B.MkTree("oneB", A.AttrVar, A.MkTrans(B, 0, 1)));

            var trans1 = Z.TT.MkTreeAutomaton(0, A, B, new TreeRule[] { rule0, rule1, rule2, rule3 });

            //(two x0 (one (plus 1 x0) (p x1)) (one (plus 2 x0) (p x2)))
            var a = A.MkTree("twoA", C.AttrVar,
                             A.MkTree("oneA", Z.MkAdd(Z.MkInt(1), C.AttrVar), C.MkTrans(A, 1, 1)),
                             A.MkTree("oneA", Z.MkAdd(Z.MkInt(2), C.AttrVar), C.MkTrans(A, 1, 2)));

            var a2 = A.MkTree("zeroA", C.AttrVar);

            var rule4 = Z.TT.MkTreeRule(C, A, 1, "twoC", Z.MkGt(C.AttrVar, Z.MkInt(-2)), a);
            var rule5 = Z.TT.MkTreeRule(C, A, 1, "zeroC", Z.MkGt(C.AttrVar, Z.MkInt(-3)), a2);

            var trans2 = Z.TT.MkTreeAutomaton(1, C, A, new TreeRule[] { rule4, rule5 });

            var trans12 = TreeTransducer.ComposeR(trans2, trans1);

            var rulesOut = trans12.GetRules(trans12.Root, C["twoC"]);

            Assert.AreEqual <int>(2, rulesOut.Count);

            var rulesOut2 = trans12.GetRules(trans12.Root, C["zeroC"]);

            Assert.AreEqual <int>(1, rulesOut2.Count);

            var tin = C.MkTree("twoC", Z.MkInt(55), C.MkTree("zeroC", Z.MkInt(66)), C.MkTree("zeroC", Z.MkInt(77)));
            var res = trans12[tin];

            Assert.AreEqual <int>(2, res.Length);
            Assert.AreEqual <int>(3, trans12.RuleCount);
        }