Beispiel #1
0
    def testInductList(self):
        Ta = TVar("a")
        Tlista = Type("list", Ta)
        list_ext = induct.add_induct_type(
            "list", ["a"], [("nil", Tlista, []), ("cons", TFun(Ta, Tlista, Tlista), ["x", "xs"])])

        nil = Const("nil", Tlista)
        cons = Const("cons", TFun(Ta, Tlista, Tlista))
        x = Var("x", Ta)
        xs = Var("xs", Tlista)
        x2 = Var("x'", Ta)
        xs2 = Var("xs'", Tlista)
        P = Var("P", TFun(Tlista, boolT))
        xlist = Var("x", Tlista)

        res = [
            AxType("list", 1),
            AxConstant("nil", Tlista),
            AxConstant("cons", TFun(Ta, Tlista, Tlista)),
            Theorem("list_nil_cons_neq", Thm([], logic.neg(eq(nil, cons(x, xs))))),
            Theorem("list_cons_inject", Thm([], imp(eq(cons(x, xs), cons(x2, xs2)), conj(eq(x, x2), eq(xs, xs2))))),
            Theorem("list_induct", Thm([], imp(P(nil), all(x, all(xs, imp(P(xs), P(cons(x, xs))))), P(xlist)))),
            Attribute("list_induct", "var_induct")
        ]
        self.assertEqual(list_ext.data, res)
Beispiel #2
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)
Beispiel #3
0
 def testEvalSem5(self):
     com = While(abs(s, logic.neg(eq(s(zero), nat.to_binary(3)))),
                 assn_true, incr_one)
     st = mk_const_fun(natT, zero)
     st2 = fun_upd_of_seq(0, 3)
     goal = Sem(com, st, st2)
     prf = hoare.eval_Sem_macro().get_proof_term(thy, goal, []).export()
     rpt = ProofReport()
     self.assertEqual(thy.check_proof(prf, rpt), Thm([], goal))
Beispiel #4
0
    def testPelletier(self):
        with open('prover/tests/pelletier.json', 'r', encoding='utf-8') as f:
            f_data = json.load(f)

        for problem in f_data:
            ctxt = parser.parse_vars(thy, problem['vars'])
            prop = parser.parse_term(thy, ctxt, problem['prop'])
            cnf, _ = encode.encode(logic.neg(prop))
            self.assertIsNone(sat.solve_cnf(cnf))
Beispiel #5
0
    def testEvalSem4(self):
        com = Cond(abs(s, logic.neg(eq(s(zero), one))), incr_one, Skip)
        st = mk_const_fun(natT, zero)
        st2 = fun_upd_of_seq(0, 1)
        goal = Sem(com, st, st2)
        prf = hoare.eval_Sem_macro().get_proof_term(thy, goal, []).export()
        self.assertEqual(thy.check_proof(prf), Thm([], goal))

        goal = Sem(com, st2, st2)
        prf = hoare.eval_Sem_macro().get_proof_term(thy, goal, []).export()
        self.assertEqual(thy.check_proof(prf), Thm([], goal))
Beispiel #6
0
    def testNatIneqMacro(self):
        test_data = [
            (0, 1), (1, 0),
            (0, 2), (2, 0),
            (1, 2), (2, 1),
            (1, 3), (3, 1),
            (2, 3), (3, 2),
            (10, 13), (17, 19), (22, 24),
        ]

        macro = nat.nat_const_ineq_macro()
        for m, n in test_data:
            goal = logic.neg(Term.mk_equals(nat.to_binary(m), nat.to_binary(n)))
            prf = macro.get_proof_term(thy, goal, []).export()
            self.assertEqual(thy.check_proof(prf), Thm([], goal))
Beispiel #7
0
 def convert(t):
     if t.head in var_map:
         if len(t.args) == 0:
             return s(Ident(to_binary(var_map[t.head])))
         elif len(t.args) == 1:
             return s(Para(Ident(to_binary(var_map[t.head])), t.arg))
         else:
             raise NotImplementedError
     elif t.is_equals():
         return Term.mk_equals(convert(t.arg1), convert(t.arg))
     elif logic.is_neg(t):
         return logic.neg(convert(t.arg))
     elif logic.is_conj(t):
         return logic.conj(convert(t.arg1), convert(t.arg))
     elif logic.is_disj(t):
         return logic.disj(convert(t.arg1), convert(t.arg))
     elif t.get_type() == boolT:
         return BoolV(t)
     elif t.get_type() == natT:
         return NatV(t)
     else:
         raise NotImplementedError
Beispiel #8
0
    def testInductNat(self):
        nat = Type("nat")
        nat_ext = induct.add_induct_type(
            "nat", [], [("zero", nat, []), ("Suc", TFun(nat, nat), ["n"])])
        
        zero = Const("zero", nat)
        S = Const("Suc", TFun(nat, nat))
        n = Var("n", nat)
        n2 = Var("n'", nat)
        x = Var("x", nat)
        P = Var("P", TFun(nat, boolT))

        res = [
            AxType("nat", 0),
            AxConstant("zero", nat),
            AxConstant("Suc", TFun(nat, nat)),
            Theorem("nat_zero_Suc_neq", Thm([], logic.neg(eq(zero, S(n))))),
            Theorem("nat_Suc_inject", Thm([], imp(eq(S(n), S(n2)), eq(n, n2)))),
            Theorem("nat_induct", Thm([], imp(P(zero), all(n, imp(P(n), P(S(n)))), P(x)))),
            Attribute("nat_induct", "var_induct")
        ]

        self.assertEqual(nat_ext.data, res)
Beispiel #9
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
Beispiel #10
0
 def neg(self, t):
     return logic.neg(t)
Beispiel #11
0
def encode(t):
    """Convert a holpy term into an equisatisfiable CNF. The result
    is a pair (cnf, prop), where cnf is the CNF form, and prop is
    a theorem stating that t, together with equality assumptions,
    imply the statement in CNF.

    """
    # Find the list of logical subterms, remove duplicates.
    subterms = logic_subterms(t)
    subterms = list(OrderedDict.fromkeys(subterms))
    subterms_dict = dict()
    for i, st in enumerate(subterms):
        subterms_dict[st] = i

    # The subterm at index i corresponds to variable x(i+1).
    def get_var(i):
        return Var("x" + str(i + 1), boolT)

    # Obtain the results:
    # eqs -- list of equality assumptions
    # clauses -- list of clauses
    eqs = []
    clauses = []
    for i, st in enumerate(subterms):
        l = get_var(i)
        if st.is_implies() or st.is_equals() or logic.is_conj(
                st) or logic.is_disj(st):
            r1 = get_var(subterms_dict[st.arg1])
            r2 = get_var(subterms_dict[st.arg])
            f = st.head
            eqs.append(Term.mk_equals(l, f(r1, r2)))
            if st.is_implies():
                clauses.extend(encode_eq_imp(l, r1, r2))
            elif st.is_equals():
                clauses.extend(encode_eq_eq(l, r1, r2))
            elif logic.is_conj(st):
                clauses.extend(encode_eq_conj(l, r1, r2))
            else:  # st.is_disj()
                clauses.extend(encode_eq_disj(l, r1, r2))
        elif logic.is_neg(st):
            r = get_var(subterms_dict[st.arg])
            eqs.append(Term.mk_equals(l, logic.neg(r)))
            clauses.extend(encode_eq_neg(l, r))
        else:
            eqs.append(Term.mk_equals(l, st))

    clauses.append(get_var(len(subterms) - 1))

    # Final proposition: under the equality assumptions and the original
    # term t, can derive the conjunction of the clauses.
    th = Thm(eqs + [t], logic.mk_conj(*clauses))

    # Final CNF: for each clause, get the list of disjuncts.
    cnf = []

    def literal(t):
        if logic.is_neg(t):
            return (t.arg.name, False)
        else:
            return (t.name, True)

    for clause in clauses:
        cnf.append(list(literal(t) for t in logic.strip_disj(clause)))

    return cnf, th
Beispiel #12
0
 def ineq_cond(self, e1, e2):
     return logic.neg(Term.mk_equals(e1, e2))
Beispiel #13
0
def nat_const_ineq(thy, a, b):
    goal = logic.neg(Term.mk_equals(a, b))
    return ProofTermDeriv("nat_const_ineq", thy, goal, [])