Ejemplo n.º 1
0
    def get_proof_term(self, thy, goal, *, args=None, prevs=None):
        assert isinstance(args, Term), "cases"

        As = goal.hyps
        C = goal.prop
        goal1 = ProofTerm.sorry(Thm(goal.hyps, Term.mk_implies(args, C)))
        goal2 = ProofTerm.sorry(
            Thm(goal.hyps, Term.mk_implies(logic.neg(args), C)))
        return apply_theorem(thy, 'classical_cases', goal1, goal2)
Ejemplo n.º 2
0
    def get_proof(self):
        invC = Const("inv", TFun(gcl.stateT, boolT))
        transC = Const("trans", TFun(gcl.stateT, gcl.stateT, boolT))
        s1 = Var("s1", gcl.stateT)
        s2 = Var("s2", gcl.stateT)
        prop = Thm.mk_implies(invC(s1), transC(s1, s2), invC(s2))
        # print(printer.print_thm(self.thy, prop))

        trans_pt = ProofTerm.assume(transC(s1, s2))
        # print(printer.print_thm(self.thy, trans_pt.th))
        P = Term.mk_implies(invC(s1), invC(s2))
        ind_pt = apply_theorem(self.thy,
                               "trans_cases",
                               inst={
                                   "a1": s1,
                                   "a2": s2,
                                   "P": P
                               })
        # print(printer.print_thm(self.thy, ind_pt.th))

        ind_As, ind_C = ind_pt.prop.strip_implies()
        for ind_A in ind_As[1:-1]:
            # print("ind_A: ", printer.print_term(self.thy, ind_A))
            vars, As, C = logic.strip_all_implies(ind_A, ["s", "k"])
            # for A in As:
            #     print("A: ", printer.print_term(self.thy, A))
            # print("C: ", printer.print_term(self.thy, C))
            eq1 = ProofTerm.assume(As[0])
            eq2 = ProofTerm.assume(As[1])
            guard = ProofTerm.assume(As[2])
            inv_pre = ProofTerm.assume(As[3]).on_arg(self.thy, rewr_conv(eq1)) \
                                             .on_prop(self.thy, rewr_conv("inv_def"))
            C_goal = ProofTerm.assume(C).on_arg(self.thy, rewr_conv(eq2)) \
                                        .on_prop(self.thy, rewr_conv("inv_def"))
Ejemplo n.º 3
0
    def testInferType(self):
        test_data = [
            # A1 --> A2
            (Const("implies", None)(Var("A1", None), Var("A2", None)),
             Term.mk_implies(Var("A1", boolT), Var("A2", boolT))),
            # A1 = A2
            (Const("equals", None)(Var("A1", boolT), Var("A2", None)),
             Term.mk_equals(Var("A1", boolT), Var("A2", boolT))),
            # a = b
            (Const("equals", None)(Var("a", None), Var("b", None)),
             Const("equals", TFun(Ta, Ta, boolT))(Var("a", Ta), Var("b", Ta))),
            # %x. P x
            (Abs("x", None,
                 Var("P", None)(Bound(0))),
             Abs("x", Ta,
                 Var("P", TFun(Ta, boolT))(Bound(0)))),
            # %x y. x = y
            (Abs("x", Ta,
                 Abs("y", None,
                     Const("equals", None)(Bound(1), Bound(0)))),
             Abs(
                 "x", Ta,
                 Abs("y", Ta,
                     Const("equals", TFun(Ta, Ta, boolT))(Bound(1),
                                                          Bound(0))))),
            # [a]
            (Const("cons", None)(Var("a", None), Const("nil", None)),
             list.cons(Ta)(Var("a", Ta), Const("nil", listT(Ta)))),
        ]

        for t, res in test_data:
            self.assertEqual(type_infer(thy, ctxt, t), res)
Ejemplo n.º 4
0
    def implies_intr(A, th):
        """Derivation rule IMPLIES_INTR:

        A |- B
        ------------
        |- A --> B
        """
        return Thm(tuple(t for t in th.hyps if t != A),
                   Term.mk_implies(A, th.prop))
Ejemplo n.º 5
0
 def testPrintThmHighlight(self):
     """Test printing of theorems with highlight."""
     # 0, 1, 2, 3 = NORMAL, BOUND, VAR, TVAR
     A = Var('A', boolT)
     B = Var('B', boolT)
     A_to_B = Term.mk_implies(A, B)
     th = Thm([A, A_to_B], B)
     res = printer.print_thm(thy, th, highlight=True)
     self.assertEqual(res, [('A',2),(', ',0),('A',2),(' --> ',0),('B',2),(' ',0),('|-',0),(' ',0),('B',2)])
Ejemplo n.º 6
0
    def testCheckProof(self):
        """Proof of [A, A --> B] |- B."""
        A_to_B = Term.mk_implies(A, B)
        prf = Proof(A_to_B, A)
        prf.add_item(2, "implies_elim", prevs=[0, 1])

        rpt = ProofReport()
        self.assertEqual(thy.check_proof(prf, rpt), Thm([A_to_B, A], B))
        self.assertEqual(rpt.steps, 3)
Ejemplo n.º 7
0
 def testIntros(self):
     Ta = TVar('a')
     x = Var('x', Ta)
     P = Var('P', TFun(Ta, boolT))
     Q = Var('Q', TFun(Ta, boolT))
     goal = Thm([], Term.mk_all(x, Term.mk_implies(P(x), Q(x))))
     intros_tac = tactic.intros()
     pt = intros_tac.get_proof_term(thy, ProofTerm.sorry(goal), args=['x'])
     prf = pt.export()
     self.assertEqual(thy.check_proof(prf), goal)
Ejemplo n.º 8
0
    def testCheckTerm(self):
        test_data = [
            x,
            Term.mk_equals(x, y),
            Term.mk_equals(f, f),
            Term.mk_implies(A, B),
            Abs("x", Ta, Term.mk_equals(x, y)),
        ]

        for t in test_data:
            self.assertEqual(thy.check_term(t), None)
Ejemplo n.º 9
0
def add_induct_predicate(name, T, props):
    """Add the given inductive predicate.

    The inductive predicate is specified by the name and type of
    the predicate, and a list of introduction rules, where each
    introduction rule must be given a name.

    """
    exts = TheoryExtension()
    exts.add_extension(AxConstant(name, T))

    for th_name, prop in props:
        exts.add_extension(Theorem(th_name, Thm([], prop)))
        exts.add_extension(Attribute(th_name, "hint_backward"))

    # Case rule
    Targs, _ = T.strip_type()
    vars = []
    for i, Targ in enumerate(Targs):
        vars.append(Var("_a" + str(i + 1), Targ))

    P = Var("P", boolT)
    pred = Const(name, T)
    assum0 = pred(*vars)
    assums = []
    for th_name, prop in props:
        As, C = prop.strip_implies()
        assert C.head == pred, "add_induct_predicate: wrong form of prop."
        eq_assums = [
            Term.mk_equals(var, arg) for var, arg in zip(vars, C.args)
        ]
        assum = Term.mk_implies(*(eq_assums + As), P)
        prop_vars = term.get_vars(prop)
        for var in reversed(term.get_vars(prop)):
            assum = Term.mk_all(var, assum)
        assums.append(assum)

    prop = Term.mk_implies(*([assum0] + assums + [P]))
    exts.add_extension(Theorem(name + "_cases", Thm([], prop)))

    return exts
Ejemplo n.º 10
0
 def testRewrConvWithAssum(self):
     x = Const("x", natT)
     y = Const("y", natT)
     x_eq_y = Term.mk_equals(x, y)
     th = Thm([], Term.mk_implies(x_eq_y, x_eq_y))
     cv = arg_conv(rewr_conv(ProofTerm.atom(0, th)))
     f = Const("f", TFun(natT, natT))
     res = Thm([x_eq_y], Term.mk_equals(f(x), f(y)))
     self.assertEqual(cv.eval(thy, f(x)), res)
     prf = Proof()
     prf.add_item(0, "sorry", th=th)
     cv.get_proof_term(thy, f(x)).export(prf=prf)
     self.assertEqual(thy.check_proof(prf), res)
Ejemplo n.º 11
0
    def add_semantics(self):
        """Add the semantics of the system in GCL."""
        transC = Const("trans", TFun(gcl.stateT, gcl.stateT, boolT))
        s = Var("s", gcl.stateT)
        props = []
        for i, (_, guard, assign) in enumerate(self.rules):
            t = gcl.convert_term(self.var_map, s, guard)
            t2 = gcl.mk_assign(self.var_map, s, assign)
            props.append(
                ("trans_rule" + str(i), Term.mk_implies(t, transC(s, t2))))

        exts = induct.add_induct_predicate("trans",
                                           TFun(gcl.stateT, gcl.stateT, boolT),
                                           props)
        self.thy.unchecked_extend(exts)
Ejemplo n.º 12
0
    def eval(self, thy, args, prevs):
        tyinst, inst = dict(), dict()
        if self.with_inst:
            name, tyinst, inst = args
        else:
            name = args
        th = thy.get_theorem(name)

        if not self.with_inst:
            As = th.assums
            assert len(prevs) <= len(
                As), "apply_theorem_macro: too many prevs."
            for idx, prev_th in enumerate(prevs):
                matcher.first_order_match_incr(As[idx], prev_th.prop,
                                               (tyinst, inst))

        As, C = logic.subst_norm(th.prop, (tyinst, inst)).strip_implies()
        new_prop = Term.mk_implies(*(As[len(prevs):] + [C]))

        prev_hyps = sum([prev.hyps for prev in prevs], ())
        return Thm(th.hyps + prev_hyps, new_prop)
Ejemplo n.º 13
0
    def testInductPredicate(self):
        nat = Type("nat")
        even = Const("even", TFun(nat, boolT))
        zero = Const("zero", nat)
        Suc = Const("Suc", TFun(nat, nat))
        n = Var("n", nat)
        prop_zero = even(zero)
        prop_Suc = Term.mk_implies(even(n), even(Suc(Suc(n))))
        data = [("even_zero", prop_zero), ("even_Suc", prop_Suc)]
        even_ext = induct.add_induct_predicate("even", TFun(nat, boolT), data)
        a1 = Var("_a1", nat)
        P = Var("P", boolT)

        res = [
            AxConstant("even", TFun(nat, boolT)),
            Theorem("even_zero", Thm([], even(zero))),
            Attribute("even_zero", "hint_backward"),
            Theorem("even_Suc", Thm.mk_implies(even(n), even(Suc(Suc(n))))),
            Attribute("even_Suc", "hint_backward"),
            Theorem("even_cases", Thm.mk_implies(even(a1), imp(eq(a1,zero), P), all(n, imp(eq(a1,Suc(Suc(n))), even(n), P)), P))
        ]
        self.assertEqual(even_ext.data, res)
Ejemplo n.º 14
0
 def testEqualIntrFail3(self):
     th1 = Thm([], Term.mk_implies(A, B))
     th2 = Thm([], Term.mk_implies(A, B))
     self.assertRaises(InvalidDerivationException, Thm.equal_intr, th1, th2)
Ejemplo n.º 15
0
 def testImpliesElimFail2(self):
     th1 = Thm([], Term.mk_implies(A, B))
     th2 = Thm([], B)
     self.assertRaises(InvalidDerivationException, Thm.implies_elim, th1,
                       th2)
Ejemplo n.º 16
0
 def testImpliesElim2(self):
     th1 = Thm([B], Term.mk_implies(A, B))
     th2 = Thm([B], A)
     self.assertEqual(Thm.implies_elim(th1, th2), Thm([B], B))
Ejemplo n.º 17
0
 def mk_implies(*args):
     """Returns the theorem s1 --> ... --> sn --> t."""
     return Thm([], Term.mk_implies(*args))
Ejemplo n.º 18
0
 def testEqualIntr(self):
     th1 = Thm([A], Term.mk_implies(A, B))
     th2 = Thm([B], Term.mk_implies(B, A))
     self.assertEqual(Thm.equal_intr(th1, th2),
                      Thm([A, B], Term.mk_equals(A, B)))
Ejemplo n.º 19
0
    def get_subgoal(self, inv_id, rule_id, case_id, hint):
        """Obtain the subgoal for the given case and hint.

        inv_id: index of the invariant to be shown at the end of the
                transition.
        rule_id: index of the transition rule.
        case_id: index of the case. The cases are as follows:
            - 0 to n-1: parameter in rule equals i'th parameter in inv.
            - n: parameter in rule does not equal any parameter in inv.
        hint: either:
            - GUARD: invariant is implied by the guard.
            - PRE: invariant is implied by the same invariant in the
                   previous state.
            - INV, i, inst:
                Invariant is implied by the guard and a different
                invariant i in the previous state. inst is a list specifying
                how to instantiate the invariant.

        """
        rule_var, guard, assigns = self.rules[rule_id]
        inv_vars, inv = self.invs[inv_id]
        assert case_id >= 0 and case_id <= len(inv_vars), \
               "get_subgoal: unexpected case_id."

        # Obtain invariant on the updated state.
        def subst(t):
            if t.is_comb() and t.fun in self.vars and t.arg in inv_vars:
                # Substitution for a parameterized variable
                if case_id < len(inv_vars) and inv_vars[case_id] == t.arg and \
                   t.fun(rule_var) in assigns:
                    return assigns[t.fun(rule_var)]
                elif t.fun in assigns:
                    return assigns[t.fun](t.arg)
                else:
                    return t
            elif t.is_var():
                # Substitution for a non-parameterized variable
                if t in assigns:
                    return assigns[t]
                else:
                    return t
            elif t.is_const():
                return t
            elif t.is_comb():
                return subst(t.fun)(subst(t.arg))
            else:
                raise NotImplementedError

        inv_after = subst(inv)
        if hint == GUARD:
            return Term.mk_implies(guard, inv_after)
        elif hint == PRE:
            return Term.mk_implies(inv, inv_after)
        else:
            hint_ty, hint_inv_id, subst_vars = hint
            if hint_ty == INV:
                inv_vars, inv = self.invs[hint_inv_id]
                inv_var_nms = [v.name for v in inv_vars]
                subst = dict((nm, Var(subst_var, natT))
                             for nm, subst_var in zip(inv_var_nms, subst_vars))
                inv_subst = inv.subst(subst)
                return Term.mk_implies(inv_subst, guard, inv_after)
Ejemplo n.º 20
0
 def imp(self, s, t):
     return Term.mk_implies(s, t)
Ejemplo n.º 21
0
 def testEqualElimFail(self):
     th1 = Thm([A], Term.mk_implies(A, B))
     th2 = Thm([B], A)
     self.assertRaises(InvalidDerivationException, Thm.equal_elim, th1, th2)
Ejemplo n.º 22
0
def add_induct_type(name, targs, constrs):
    """Add the given inductive type to the theory.
    
    The inductive type is specified by name, arity (as list of default
    names of type arguments), and a list of constructors (triple
    consisting of name of the constant, type of the constant, and a
    list of suggested names of the arguments).

    For example, the natural numbers is specified by:
    (nat, [], [(0, nat, []), (Suc, nat => nat, ["n"])]).

    List type is specified by:
    (list, ["a"], [(nil, 'a list, []), (cons, 'a => 'a list => 'a list, ["x", "xs"])]).

    """
    exts = TheoryExtension()

    # Add to type and term signature.
    exts.add_extension(AxType(name, len(targs)))
    for cname, cT, _ in constrs:
        exts.add_extension(AxConstant(cname, cT))

    # Add non-equality theorems.
    for (cname1, cT1, vars1), (cname2, cT2,
                               vars2) in itertools.combinations(constrs, 2):
        # For each A x_1 ... x_m and B y_1 ... y_n, get the theorem
        # ~ A x_1 ... x_m = B y_1 ... y_n.
        argT1, _ = cT1.strip_type()
        argT2, _ = cT2.strip_type()
        lhs_vars = [Var(nm, T) for nm, T in zip(vars1, argT1)]
        rhs_vars = [Var(nm, T) for nm, T in zip(vars2, argT2)]
        A = Const(cname1, cT1)
        B = Const(cname2, cT2)
        lhs = A(*lhs_vars)
        rhs = B(*rhs_vars)
        neq = logic.neg(Term.mk_equals(lhs, rhs))
        th_name = name + "_" + cname1 + "_" + cname2 + "_neq"
        exts.add_extension(Theorem(th_name, Thm([], neq)))

    # Add injectivity theorems.
    for cname, cT, vars in constrs:
        # For each A x_1 ... x_m with m > 0, get the theorem
        # A x_1 ... x_m = A x_1' ... x_m' --> x_1 = x_1' & ... & x_m = x_m'
        if vars:
            argT, _ = cT.strip_type()
            lhs_vars = [Var(nm, T) for nm, T in zip(vars, argT)]
            rhs_vars = [Var(nm + "'", T) for nm, T in zip(vars, argT)]
            A = Const(cname, cT)
            assum = Term.mk_equals(A(*lhs_vars), A(*rhs_vars))
            concls = [
                Term.mk_equals(var1, var2)
                for var1, var2 in zip(lhs_vars, rhs_vars)
            ]
            concl = logic.mk_conj(*concls) if len(concls) > 1 else concls[0]
            th_name = name + "_" + cname + "_inject"
            exts.add_extension(Theorem(th_name, Thm.mk_implies(assum, concl)))

    # Add the inductive theorem.
    tvars = [TVar(targ) for targ in targs]
    T = Type(name, *tvars)
    var_P = Var("P", TFun(T, boolT))
    ind_assums = []
    for cname, cT, vars in constrs:
        A = Const(cname, cT)
        argT, _ = cT.strip_type()
        args = [Var(nm, T2) for nm, T2 in zip(vars, argT)]
        C = var_P(A(*args))
        As = [var_P(Var(nm, T2)) for nm, T2 in zip(vars, argT) if T2 == T]
        ind_assum = Term.mk_implies(*(As + [C]))
        for arg in reversed(args):
            ind_assum = Term.mk_all(arg, ind_assum)
        ind_assums.append(ind_assum)
    ind_concl = var_P(Var("x", T))
    th_name = name + "_induct"
    exts.add_extension(
        Theorem(th_name, Thm.mk_implies(*(ind_assums + [ind_concl]))))
    exts.add_extension(Attribute(th_name, "var_induct"))

    return exts
Ejemplo n.º 23
0
 def testAbstractOverFail4(self):
     th = Thm([], Term.mk_implies(x, y))
     self.assertRaises(InvalidDerivationException, Thm.abstraction, x, th)
Ejemplo n.º 24
0
 def testImpliesIntr3(self):
     th = Thm([], B)
     self.assertEqual(Thm.implies_intr(A, th), Thm([],
                                                   Term.mk_implies(A, B)))
Ejemplo n.º 25
0
# Author: Bohua Zhan

import unittest

from kernel.type import boolT
from kernel.term import Term, Var
from kernel.thm import Thm
from kernel.proof import ProofItem, Proof

A = Var("A", boolT)
B = Var("B", boolT)
A_to_B = Term.mk_implies(A, B)


class ProofTest(unittest.TestCase):
    def testProofItem(self):
        test_data = [
            (ProofItem(0, "theorem", args="conjD1"), "0: theorem conjD1", {
                'id': 0,
                'th': '',
                'rule': 'theorem',
                'args': 'conjD1',
                'prevs': []
            }),
            (ProofItem(1, "assume", args=A_to_B), "1: assume implies A B", {
                'id': 1,
                'th': '',
                'rule': 'assume',
                'args': 'implies A B',
                'prevs': []
            }),