Automata.Z3.Tests.Z3_Z3ContextTests.TupleTest C# (CSharp) Method

TupleTest() private method

private TupleTest ( ) : void
return void
        public void TupleTest()
        {
            Z3Provider z3p = new Z3Provider();
            //create the tuple sort for mouth
            FuncDecl mouth;
            FuncDecl[] mouth_accessors;
            var MOUTH = z3p.MkTupleSort("MOUTH", new string[] { "open", "teeth" }, new Sort[] { z3p.BoolSort, z3p.IntSort }, out mouth, out mouth_accessors);
            Func<Expr,Expr,Expr> mk_mouth = ((o,t) => z3p.MkApp(mouth, o, t));
            Func<Expr,Expr> get_open = (m => z3p.MkApp(mouth_accessors[0], m));
            Func<Expr,Expr> get_teeth = (m => z3p.MkApp(mouth_accessors[1], m));
            //create the tuple sort for nose
            FuncDecl nose;
            FuncDecl[] nose_accessors;
            var NOSE = z3p.MkTupleSort("NOSE", new string[] { "size" }, new Sort[] { z3p.IntSort }, out nose, out nose_accessors);
            Func<Expr,Expr> mk_nose = (s => z3p.MkApp(nose, s));
            Func<Expr,Expr> get_size = (n => z3p.MkApp(nose_accessors[0], n));
            //create the tuple sort for head
            FuncDecl head;
            FuncDecl[] head_accessors;
            var HEAD = z3p.MkTupleSort("HEAD", new string[] { "bald", "nose", "mouth" }, new Sort[] { z3p.BoolSort, NOSE, MOUTH }, out head, out head_accessors);
            Func<Expr,Expr,Expr,Expr> mk_head = ((b,n,m) => z3p.MkApp(head, b,n,m));
            Func<Expr,Expr> get_bald = (h => z3p.MkApp(head_accessors[0], h));
            Func<Expr,Expr> get_nose = (h => z3p.MkApp(head_accessors[1], h));
            Func<Expr,Expr> get_mouth = (h => z3p.MkApp(head_accessors[2], h));
            //------------------------
            // create a transformation "punch" from HEAD tp HEAD that removes k teeth, k is  the second parameter of the transformation
            var punch = z3p.MkFuncDecl("punch", new Sort[]{HEAD, z3p.IntSort}, HEAD);
            var x = z3p.MkVar(0, HEAD);        // <-- this is the input HEAD
            var y = z3p.MkVar(1, z3p.IntSort); // <-- this is the n parameter
            //this is the actual transformation of x that removes one tooth
            var new_mouth = mk_mouth(get_open(get_mouth(x)), z3p.MkSub(get_teeth(get_mouth(x)), y));
            var old_nose = get_nose(x);
            var old_bald = get_bald(x);
            var punch_def = mk_head(old_bald, old_nose,new_mouth);
            var punch_axiom = z3p.MkEqForall(z3p.MkApp(punch, x , y), punch_def, x, y);
            Func<Expr,Expr,Expr> punch_app = ((h,k) => z3p.MkApp(punch, h,k));
            z3p.MainSolver.Assert(punch_axiom);
            //------------------------
            // create a transformation "hit" from HEAD tp HEAD that doubles the size of the nose
            var hit = z3p.MkFuncDecl("hit", HEAD, HEAD);
            var hit_def = mk_head(get_bald(x), mk_nose(z3p.MkMul(z3p.MkInt(2),get_size(get_nose(x)))), get_mouth(x));
            var hit_axiom = z3p.MkEqForall(z3p.MkApp(hit, x), hit_def, x);
            Func<Expr,Expr> hit_app = (h => z3p.MkApp(hit, h));
            z3p.MainSolver.Assert(hit_axiom);
            //-------------------------------
            // Analysis
            var H = z3p.MkConst("H", HEAD);
            var N = z3p.MkConst("N", z3p.IntSort);
            // check that hit and punch commute
            z3p.MainSolver.Push();
            z3p.MainSolver.Assert(z3p.MkNeq(punch_app(hit_app(H), N), hit_app(punch_app(H, N))));
            Status status = z3p.Check(); //here status must be UNSATISFIABLE
            z3p.MainSolver.Pop(); //remove the temporary context
            //check that hit is not idempotent
            z3p.MainSolver.Push();
            z3p.MainSolver.Assert(z3p.MkNeq(hit_app(hit_app(H)), hit_app(H)));
            status = z3p.Check(); //here status must not be UNSATISFIABLE (it is UNKNOWN due to use of axioms)
            var model1 = z3p.Z3S.Model;
            var witness1 = model1.Evaluate(H, true);   //a concrete instance of HEAD that shows when hitting twice is not the same as hitting once
            z3p.MainSolver.Pop();
            //but it is possible that hitting twice does no harm (when nose has size 0)
            z3p.MainSolver.Push();
            z3p.MainSolver.Assert(z3p.MkEq(hit_app(hit_app(H)), hit_app(H)));
            status = z3p.Check();
            var model2 = z3p.Z3S.Model;
            var witness2 = model2.Evaluate(H, true);
            z3p.MainSolver.Pop();
        }