Exemple #1
0
def logic_subterms(t):
    """Returns the list of logical subterms for a term t."""
    if t.is_implies() or t.is_equals() or logic.is_conj(t) or logic.is_disj(t):
        return logic_subterms(t.arg1) + logic_subterms(t.arg) + [t]
    elif logic.is_neg(t):
        return logic_subterms(t.arg) + [t]
    else:
        return [t]
Exemple #2
0
 def traverse_A(pt):
     # Given proof term showing a conjunction, put proof terms
     # showing atoms of the conjunction in dct.
     if is_conj(pt.prop):
         traverse_A(apply_theorem(thy, 'conjD1', pt))
         traverse_A(apply_theorem(thy, 'conjD2', pt))
     else:
         dct[pt.prop] = pt
Exemple #3
0
 def traverse_C(t):
     # Return proof term with conclusion t
     if is_conj(t):
         left = traverse_C(t.arg1)
         right = traverse_C(t.arg)
         return apply_theorem(thy, 'conjI', left, right)
     else:
         assert t in dct.keys(), 'imp_conj_macro'
         return dct[t]
Exemple #4
0
def get_encode_proof(th):
    """Given resulting theorem for an encoding, obtain the proof
    of the theorem.

    The theorem is structured as follows:

    Each of the assumptions, except the last, is an equality, where
    the right side is either an atom or a logical operation between
    atoms. We call these assumptions As.

    The last assumption is the original formula. We call it F.

    The conclusion is in CNF. Each clause except the last is an
    expansion of one of As. The last clause is obtained by performing
    substitutions of As on F.

    """
    As, F = th.hyps[:-1], th.hyps[-1]

    # Obtain the assumptions
    ptAs = [ProofTerm.assume(A) for A in As]
    ptF = ProofTerm.assume(F)

    # Obtain the expansion of each As to a non-atomic term.
    pts = []
    for ptA in ptAs:
        rhs = ptA.prop.rhs
        if logic.is_conj(rhs):
            pts.append(ptA.on_prop(thy, rewr_conv("encode_conj")))
        elif logic.is_disj(rhs):
            pts.append(ptA.on_prop(thy, rewr_conv("encode_disj")))
        elif rhs.is_implies():
            pts.append(ptA.on_prop(thy, rewr_conv("encode_imp")))
        elif rhs.is_equals():
            pts.append(ptA.on_prop(thy, rewr_conv("encode_eq")))
        elif logic.is_neg(rhs):
            pts.append(ptA.on_prop(thy, rewr_conv("encode_not")))

    # Obtain the rewrite of the original formula.
    cvs = [
        top_conv(rewr_conv(ProofTerm.symmetric(ptA), match_vars=False))
        for ptA in ptAs
    ]
    cv = every_conv(*cvs)

    pts.append(ptF.on_prop(thy, cv))

    pt = pts[0]
    for pt2 in pts[1:]:
        pt = logic_macro.apply_theorem(thy, 'conjI', pt, pt2)

    return pt.on_prop(thy, logic.norm_conj_assoc())
Exemple #5
0
def convert(t):
    """Convert term t to Z3 input."""
    if t.is_var():
        T = t.get_type()
        if T == nat.natT:
            return z3.Int(t.name)
        elif T == TFun(nat.natT, nat.natT):
            return z3.Function(t.name, z3.IntSort(), z3.IntSort())
        elif T == TFun(nat.natT, boolT):
            return z3.Function(t.name, z3.IntSort(), z3.BoolSort())
        elif T == boolT:
            return z3.Bool(t.name)
        else:
            print("convert: unsupported type " + repr(T))
            raise NotImplementedError
    elif t.is_all():
        if t.arg.var_T == nat.natT:
            v = Var(t.arg.var_name, nat.natT)
            z3_v = z3.Int(t.arg.var_name)
            return z3.ForAll([z3_v], convert(t.arg.subst_bound(v)))
        else:
            raise NotImplementedError
    elif t.is_implies():
        return z3.Implies(convert(t.arg1), convert(t.arg))
    elif t.is_equals():
        return convert(t.arg1) == convert(t.arg)
    elif logic.is_conj(t):
        return z3.And(convert(t.arg1), convert(t.arg))
    elif logic.is_disj(t):
        return z3.Or(convert(t.arg1), convert(t.arg))
    elif logic.is_neg(t):
        return z3.Not(convert(t.arg))
    elif nat.is_plus(t):
        return convert(t.arg1) + convert(t.arg)
    elif nat.is_times(t):
        return convert(t.arg1) * convert(t.arg)
    elif nat.is_binary(t):
        return nat.from_binary(t)
    elif t.is_comb():
        return convert(t.fun)(convert(t.arg))
    elif t.is_const():
        if t == logic.true:
            return z3.BoolVal(True)
        elif t == logic.false:
            return z3.BoolVal(False)
        else:
            print("convert: unsupported constant " + repr(t))
            raise NotImplementedError
    else:
        print("convert: unsupported operation " + repr(t))
        raise NotImplementedError
Exemple #6
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
Exemple #7
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
Exemple #8
0
 def strip(t):
     if is_conj(t):
         return strip(t.arg1).union(strip(t.arg))
     else:
         return {t}