Esempio n. 1
0
    def testAllConj(self):
        """Proof of (!x. A x & B x) --> (!x. A x) & (!x. B x)."""
        thy = basic.load_theory('logic_base')
        Ta = TVar("a")
        A = Var("A", TFun(Ta, boolT))
        B = Var("B", TFun(Ta, boolT))
        x = Var("x", Ta)
        all_conj = Term.mk_all(x, logic.mk_conj(A(x), B(x)))
        all_A = Term.mk_all(x, A(x))
        all_B = Term.mk_all(x, B(x))
        conj_all = logic.mk_conj(all_A, all_B)

        prf = Proof(all_conj)
        prf.add_item(1, "forall_elim", args=x, prevs=[0])
        prf.add_item(2, "theorem", args="conjD1")
        prf.add_item(3, "substitution", args={"A": A(x), "B": B(x)}, prevs=[2])
        prf.add_item(4, "implies_elim", prevs=[3, 1])
        prf.add_item(5, "forall_intr", args=x, prevs=[4])
        prf.add_item(6, "theorem", args="conjD2")
        prf.add_item(7, "substitution", args={"A": A(x), "B": B(x)}, prevs=[6])
        prf.add_item(8, "implies_elim", prevs=[7, 1])
        prf.add_item(9, "forall_intr", args=x, prevs=[8])
        prf.add_item(10, "theorem", args="conjI")
        prf.add_item(11,
                     "substitution",
                     args={
                         "A": all_A,
                         "B": all_B
                     },
                     prevs=[10])
        prf.add_item(12, "implies_elim", prevs=[11, 5])
        prf.add_item(13, "implies_elim", prevs=[12, 9])
        prf.add_item(14, "implies_intr", args=all_conj, prevs=[13])
        th = Thm.mk_implies(all_conj, conj_all)
        self.assertEqual(thy.check_proof(prf), th)
Esempio n. 2
0
 def testIntroduction3(self):
     Ta = TVar("a")
     A = Var("A", TFun(Ta, boolT))
     B = Var("B", TFun(Ta, boolT))
     x = Var("x", Ta)
     state = ProofState.init_state(thy, [A, B], [], Term.mk_all(x, imp(A(x), B(x))))
     state.introduction(0, ["x"])
     self.assertEqual(state.check_proof(), Thm([], Term.mk_all(x, imp(A(x), B(x)))))
     self.assertEqual(len(state.prf.items), 1)
     self.assertEqual(len(state.prf.items[0].subproof.items), 4)
Esempio n. 3
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)
Esempio n. 4
0
    def forall_intr(x, th):
        """Derivation rule FORALL_INTR:

        A |- t
        ------------
        A |- !x. t    where x does not occur in A.
        """
        if any(hyp.occurs_var(x) for hyp in th.hyps):
            raise InvalidDerivationException("forall_intr")
        elif x.ty != Term.VAR:
            raise InvalidDerivationException("forall_intr")
        else:
            return Thm(th.hyps, Term.mk_all(x, th.prop))
Esempio n. 5
0
    def testAllConjWithMacro(self):
        """Proof of (!x. A x & B x) --> (!x. A x) & (!x. B x), using macros."""
        thy = basic.load_theory('logic_base')
        Ta = TVar("a")
        A = Var("A", TFun(Ta, boolT))
        B = Var("B", TFun(Ta, boolT))
        x = Var("x", Ta)
        all_conj = Term.mk_all(x, logic.mk_conj(A(x), B(x)))
        all_A = Term.mk_all(x, A(x))
        all_B = Term.mk_all(x, B(x))
        conj_all = logic.mk_conj(all_A, all_B)

        prf = Proof(all_conj)
        prf.add_item(1, "forall_elim", args=x, prevs=[0])
        prf.add_item(2, "apply_theorem", args="conjD1", prevs=[1])
        prf.add_item(3, "forall_intr", args=x, prevs=[2])
        prf.add_item(4, "apply_theorem", args="conjD2", prevs=[1])
        prf.add_item(5, "forall_intr", args=x, prevs=[4])
        prf.add_item(6, "apply_theorem", args="conjI", prevs=[3, 5])
        prf.add_item(7, "implies_intr", args=all_conj, prevs=[6])
        th = Thm.mk_implies(all_conj, conj_all)
        self.assertEqual(thy.check_proof(prf), th)
Esempio n. 6
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
Esempio n. 7
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
Esempio n. 8
0
 def testForallElimFail2(self):
     P = Var("P", TFun(Ta, boolT))
     th = Thm([], Term.mk_all(x, P(x)))
     self.assertRaises(InvalidDerivationException, Thm.forall_elim, A, th)
Esempio n. 9
0
 def testForallElim(self):
     P = Var("P", TFun(Ta, boolT))
     th = Thm([], Term.mk_all(x, P(x)))
     self.assertEqual(Thm.forall_elim(y, th), Thm([], P(y)))
Esempio n. 10
0
 def testForallIntr2(self):
     """Also OK if the variable does not appear in theorem."""
     th = Thm.mk_equals(x, y)
     t_res = Term.mk_all(z, Term.mk_equals(x, y))
     self.assertEqual(Thm.forall_intr(z, th), Thm([], t_res))
Esempio n. 11
0
 def testForallIntr(self):
     th = Thm.mk_equals(x, y)
     t_res = Term.mk_all(x, Term.mk_equals(x, y))
     self.assertEqual(Thm.forall_intr(x, th), Thm([], t_res))