Ejemplo n.º 1
0
 def get_proof_term(self, t):
     assert t.is_equals() or t.is_less_eq() or t.is_less()\
         or t.is_greater_eq() or t.is_greater(), "%s is not an equality term" % t
     pt1 = refl(t)  # a = b <==> a = b
     if t.is_equals():
         pt2 = pt1.on_rhs(rewr_conv('int_sub_move_0_r',
                                    sym=True))  # a = b <==> a - b = 0
         eq_refl = ProofTerm.reflexive(equals(IntType))
     elif t.is_less_eq():
         pt2 = pt1.on_rhs(rewr_conv('int_leq'))
         eq_refl = ProofTerm.reflexive(less_eq(IntType))
     elif t.is_less():
         pt2 = pt1.on_rhs(rewr_conv('int_less'))
         eq_refl = ProofTerm.reflexive(less(IntType))
     elif t.is_greater_eq():
         pt2 = pt1.on_rhs(rewr_conv('int_geq'))
         eq_refl = ProofTerm.reflexive(greater_eq(IntType))
     elif t.is_greater():
         pt2 = pt1.on_rhs(rewr_conv('int_gt'))
         eq_refl = ProofTerm.reflexive(greater(IntType))
     pt3 = simp_full().get_proof_term(
         pt2.prop.arg.arg1)  # a - b = a + (-1) * b
     pt4 = ProofTerm.combination(eq_refl, pt3)
     pt5 = ProofTerm.combination(pt4, refl(Const(
         'zero', IntType)))  # a - b = 0 <==> a + (-1)*b = 0
     return pt2.transitive(pt5)  # a = b <==> a + (-1) * b = 0
Ejemplo n.º 2
0
    def testExport2(self):
        """Repeated theorems."""
        pt1 = ProofTerm.assume(Eq(x, y))
        pt2 = ProofTerm.reflexive(f)
        pt3 = pt2.combination(pt1)  # f x = f y
        pt4 = pt3.combination(pt1)  # f x x = f y y

        prf = pt4.export()
        self.assertEqual(len(prf.items), 4)
        self.assertEqual(theory.check_proof(prf), pt4.th)
Ejemplo n.º 3
0
Archivo: conv.py Proyecto: bzhan/holpy
    def get_proof_term(self, t):
        if not t.is_comb():
            raise ConvException("combination_conv: not a combination")
        pt1 = self.cv1.get_proof_term(t.fun)
        pt2 = self.cv2.get_proof_term(t.arg)

        # Obtain some savings if one of pt1 and pt2 is reflexivity:
        if pt1.th.is_reflexive() and pt2.th.is_reflexive():
            return ProofTerm.reflexive(t)
        else:
            return pt1.combination(pt2)
Ejemplo n.º 4
0
        def get_proofterm(u, v):
            """Get proof term corresponding to u = v."""
            path = explain[(u, v)]
            cur_pos = u
            pt = ProofTerm.reflexive(self.index[u])
            for eq in path:
                # Form the proof term for eq, depending on the two cases.
                if eq[0] == EQ_CONST:
                    _, a, b = eq
                    if (a, b) in self.pts:
                        eq_pt = self.pts[(a, b)]
                    else:
                        eq_pt = ProofTerm.sorry(
                            Thm([], Eq(self.index[a], self.index[b])))
                else:
                    _, ((a1, a2), a), ((b1, b2), b) = eq
                    # We already should have:
                    # - a corresponds to Comb(a1, a2)
                    # - b corresponds to Comb(b1, b2)
                    eq_pt1 = get_proofterm(
                        a1, b1) if a1 != b1 else ProofTerm.reflexive(
                            self.index[a1])
                    eq_pt2 = get_proofterm(
                        a2, b2) if a2 != b2 else ProofTerm.reflexive(
                            self.index[a2])
                    eq_pt = eq_pt1.combination(eq_pt2)

                # Append the equality to the current chain.
                if a == cur_pos:
                    pt = pt.transitive(eq_pt)
                    cur_pos = b
                else:
                    assert b == cur_pos
                    pt = pt.transitive(pt, eq_pt.symmetric())
                    cur_pos = a

            return pt
Ejemplo n.º 5
0
    def get_proof_term(self, goal, prevs=None):
        elems = goal.strip_disj()
        preds, concl = elems[:-1], elems[-1]
        args_pair = [(i, j) for i, j in zip(concl.lhs.strip_comb()[1],
                                            concl.rhs.strip_comb()[1])]
        preds_pair = [(i.arg.lhs, i.arg.rhs) for i in preds]
        fun = concl.lhs.head
        pt0 = ProofTerm.reflexive(fun)
        pt_args_assms = []
        for pair in args_pair:
            r_pair = pair[::-1]
            if pair in args_pair:
                pt_args_assms.append(ProofTerm.assume(Eq(*pair)))
            elif r_pair in args_pair:
                pt_args_assms.append(ProofTerm.assume(Eq(*r_pair)))

        pt1 = functools.reduce(lambda x, y: x.combination(y), pt_args_assms,
                               pt0)
        return ProofTerm("imp_to_or", elems[:-1] + [goal], prevs=[pt1])
Ejemplo n.º 6
0
 def get_proof_term(self, goal, prevs=None):
     """{(not (= x_1 y_1)) ... (not (= x_n y_n)) (not (p x_1 ... x_n)) (p y_1 ... y_n)}
     Special case: (not (= x y)) (not (p x y)) (p y x)
     """
     elems = goal.strip_disj()
     preds, pred_fun, concl = elems[:-2], elems[-2], elems[-1]
     if pred_fun.is_not():
         args_pair = [(i, j) for i, j in zip(pred_fun.arg.strip_comb()[1],
                                             concl.strip_comb()[1])]
     else:
         args_pair = [(i, j) for i, j in zip(pred_fun.strip_comb()[1],
                                             concl.arg.strip_comb()[1])]
     if len(preds) > 1:
         preds_pair = [(i.arg.lhs, i.arg.rhs) for i in preds]
     else:
         preds_pair = [(preds[0].arg.lhs, preds[0].arg.rhs),
                       (preds[0].arg.lhs, preds[0].arg.rhs)]
     if pred_fun.is_not():
         fun = concl.head
     else:
         fun = pred_fun.head
     pt0 = ProofTerm.reflexive(fun)
     pt_args_assms = []
     for arg, pred in zip(args_pair, preds_pair):
         if arg == pred:
             pt_args_assms.append(ProofTerm.assume(Eq(pred[0], pred[1])))
         elif arg[0] == pred[1] and pred[0] == arg[1]:
             pt_args_assms.append(
                 ProofTerm.assume(Eq(pred[0], pred[1])).symmetric())
         else:
             raise NotImplementedError
     pt1 = functools.reduce(lambda x, y: x.combination(y), pt_args_assms,
                            pt0)
     if pred_fun.is_not():
         pt2 = logic.apply_theorem("eq_implies1", pt1).implies_elim(
             ProofTerm.assume(pred_fun.arg))
         return ProofTerm("imp_to_or", elems[:-1] + [goal], prevs=[pt2])
     else:
         pt2 = pt1.on_prop(conv.rewr_conv("neg_iff_both_sides"))
         pt3 = logic.apply_theorem("eq_implies1", pt2).implies_elim(
             ProofTerm.assume(Not(pred_fun)))
         return ProofTerm("imp_to_or", elems[:-1] + [goal], prevs=[pt3])
Ejemplo n.º 7
0
    def solve(self):
        """
        Call zChaff solver, return the proof term.
        """
        # First write the cnf to a .cnf file.
        s = 'p cnf ' + str(self.var_num) + ' ' + str(self.clause_num)
        for clause in self.cnf_list:
            s += '\n' + ' '.join(str(l) for l in clause) + ' 0'
        with open('./sat/x.cnf', 'w') as f:
            f.write(s)

        # then call zChaff to get the proof trace
        p = subprocess.Popen('.\\sat\\binaries\\zchaff.exe .\\sat\\x.cnf',
                             stdout=subprocess.PIPE,
                             stderr=subprocess.PIPE)

        stdout, stderr = p.communicate()
        result = stdout.decode('utf-8').split('\n')[-2]
        assert result == "RESULT:\tUNSAT\r"

        # proof reconstruct
        first = []
        second = []
        third = []
        with open('.\\resolve_trace', 'r') as f:
            lines = f.readlines()
            for l in lines:
                if l.startswith('CL'):
                    first.append(Resolvent(l))
                elif l.startswith('VAR'):
                    second.append(ImpliedVarValue(l))
                else:
                    third.append(Conflict(l))

        for j, f in enumerate(first):
            res_cls = f.rsl
            pt = self.clause_pt[res_cls[0]]
            for i in range(len(res_cls) - 1):
                pt = resolution(pt, self.clause_pt[res_cls[i + 1]])
            self.clause_pt[len(self.clause_pt)] = pt

        second = sorted(second, key=lambda x: x.level)

        # dictionary from var index to its true value
        var_pt = {}
        for s in second:
            cls_pt = self.clause_pt[s.act]
            pts = []
            lits = [floor(l / 2) for l in s.lits if floor(l / 2) != s.var]
            if not lits:
                var_pt[s.var] = cls_pt
                continue
            exist_var_pt = [var_pt[l] for l in lits]
            exact_var = self.index_var[s.var] if s.value == 1 else Not(
                self.index_var[s.var])
            prevs = [cls_pt] + exist_var_pt
            var_pt[s.var] = DisjForceMacro().get_proof_term(prevs, exact_var)

        conflict_cls = third[0]
        literal_pt = [var_pt[floor(i / 2)] for i in conflict_cls.lits]
        self.conflict_pt = DisjFalseMacro().get_proof_term(
            self.clause_pt[conflict_cls.cls], literal_pt)

        # return the theorem
        pt1, pt2 = self.encode_pt, self.conflict_pt
        while pt1.prop.is_conj():
            pt_left = apply_theorem('conjD1', pt1)
            pt2 = pt2.implies_intr(pt_left.prop).implies_elim(
                pt_left)  # remove one clause from assumption
            pt1 = apply_theorem('conjD2', pt1)
        pt2 = pt2.implies_intr(pt1.prop).implies_elim(
            pt1)  # remove last clause from assumption

        # Clear definition of new variables from antecedent
        eqs = [t for t in pt2.hyps if t.is_equals()]
        eqs = list(reversed(sorted(eqs, key=lambda t: int(t.lhs().name[1:]))))

        for eq in eqs:
            pt2 = pt2.implies_intr(eq).forall_intr(eq.lhs).forall_elim(eq.rhs) \
                    .implies_elim(ProofTerm.reflexive(eq.rhs))

        return apply_theorem('negI', pt2.implies_intr(pt2.hyps[0])).on_prop(
            rewr_conv('double_neg'))
Ejemplo n.º 8
0
Archivo: real.py Proyecto: bzhan/holpy
    def get_proof_term(self, args, prevs=None):
        """
        Let x_i denotes greater comparison, x__i denotes less comparison,
        for the greater comparison, find the smallest number x_min = min(x_1, ..., x_n), since x_min is positive, 
        x_min/2 > 0 ==> x_min >= x_min / 2 ==> x_1, ..., x_n >= x_min / 2 ==> ∃δ. δ > 0 ∧ x_1 >= δ ∧ ... ∧ x_n >= δ.
        for the less comparison, find the largest number x_max = max(x__1, ..., x__n), since x_max is negative, x_max < 
        x_max/2 ==> x__1, ..., x__n <= x_max/2;
        let δ = min(x_min/2, -x_max/2), then all x_i >= δ as well as all x__i <= -δ.
        """
        def need_convert(tm):
            return False if real_eval(tm.arg) != 0 else True

        original_ineq_pts = [ProofTerm.assume(ineq) for ineq in args]

        # record the ineq which rhs is not 0
        need_convert_pt = {arg for arg in args if need_convert(arg)}

        # record the args order
        order_args = {args[i].arg1: i for i in range(len(args))}

        # convert all ineqs to x_i > 0 or x_i < 0
        normal_ineq_pts = [
            pt.on_prop(norm_real_ineq_conv()) if pt.prop.arg != Real(0) else pt
            for pt in original_ineq_pts
        ]

        # dividing less comparison and greater comparison
        greater_ineq_pts = [
            pt for pt in normal_ineq_pts if pt.prop.is_greater()
        ]
        less_ineq_pts = [pt for pt in normal_ineq_pts if pt.prop.is_less()]

        # stage 1: get the max(min) pos bound
        # ⊢ min(...) ≥ δ_1, δ_1 > 0
        # ⊢ max(...) ≤ δ_2, δ_2 < 0
        pt_lower_bound, lower_bound_pos_pt, pt_assert_delta1 = self.handle_geq_stage1(
            greater_ineq_pts)
        pt_upper_bound, upper_bound_neg_pt, pt_assert_delta2 = self.handle_leq_stage1(
            less_ineq_pts)

        delta_1 = Var("δ_1", RealType)
        delta_2 = Var("δ_2", RealType)

        # generate the relaxed inequations
        if pt_lower_bound is None:  # all comparisons are ≤
            pts = self.handle_leq_stage2(pt_upper_bound, less_ineq_pts,
                                         delta_2)
            bound_pt = upper_bound_neg_pt
            delta = delta_2
            pt_asserts = [pt_assert_delta2]
        elif pt_upper_bound is None:  # all comparisons are ≥
            pts = self.handle_geq_stage2(pt_lower_bound, greater_ineq_pts,
                                         delta_1)
            bound_pt = lower_bound_pos_pt
            delta = delta_1
            pt_asserts = [pt_assert_delta1]
        else:  # have both ≥ and ≤
            # ⊢ δ_1 ≥ min(δ_1, δ_2)
            pt_min_lower_bound = logic.apply_theorem("real_greater_min",
                                                     inst=matcher.Inst(
                                                         x=delta_1, y=delta_2))
            # ⊢ -δ_2 ≤ max(-δ_2, -δ_1)
            pt_max_upper_bound = logic.apply_theorem("real_less_max",
                                                     inst=matcher.Inst(
                                                         x=-delta_2,
                                                         y=-delta_1))
            # ⊢ max(-δ_2, -δ_1) = -min(δ_1, δ_2)
            pt_max_min = logic.apply_theorem("max_min",
                                             inst=matcher.Inst(x=delta_1,
                                                               y=delta_2))
            # ⊢ min(...) ≥ min(δ_1, δ_2)
            pt_new_lower_bound = logic.apply_theorem("real_geq_trans",
                                                     pt_lower_bound,
                                                     pt_min_lower_bound)
            # ⊢ -δ_2 ≤ -min(δ_1, δ_2)
            pt_max_upper_bound_1 = pt_max_upper_bound.on_prop(
                arg_conv(replace_conv(pt_max_min)))
            # ⊢ max(...) ≤ -min(δ_1, δ_2)
            pt_new_upper_bound = logic.apply_theorem("real_le_trans",
                                                     pt_upper_bound,
                                                     pt_max_upper_bound_1)
            # ⊢ min(δ_1, δ_2) > 0
            pt_new_lower_bound_pos = logic.apply_theorem(
                "min_pos", lower_bound_pos_pt, upper_bound_neg_pt)
            # ⊢ min(δ_1, δ_2) = δ
            delta = Var("δ", RealType)
            pt_delta_eq = ProofTerm.assume(
                Eq(pt_min_lower_bound.prop.arg, delta))
            pt_asserts = [pt_delta_eq, pt_assert_delta1, pt_assert_delta2]
            # ⊢ min(...) ≥ δ
            pt_new_lower_bound_delta = pt_new_lower_bound.on_prop(
                arg_conv(replace_conv(pt_delta_eq)))
            # ⊢ max(...) ≤ -δ
            pt_new_upper_bound_delta = pt_new_upper_bound.on_prop(
                top_conv(replace_conv(pt_delta_eq)))
            # use new bound
            pts_leq = self.handle_leq_stage2(pt_new_upper_bound_delta,
                                             less_ineq_pts, delta)
            pts_geq = self.handle_geq_stage2(pt_new_lower_bound_delta,
                                             greater_ineq_pts, delta)
            pts = pts_leq + pts_geq
            bound_pt = pt_new_lower_bound_pos.on_prop(
                arg1_conv(replace_conv(pt_delta_eq)))

        # sort_pts = sorted(pts, key=lambda pt: order_args[pt.prop.arg1])

        pt_conj = functools.reduce(
            lambda x, y: logic.apply_theorem("conjI", y, x),
            reversed([bound_pt] + pts))

        # get ⊢∃δ. δ > 0 ∧ x_1 >= δ ∧ ... ∧ x_n >= δ
        th = ProofTerm.theorem("exI")
        inst = matcher.first_order_match(th.prop.arg,
                                         Exists(delta, pt_conj.prop))
        pt_conj_exists = logic.apply_theorem("exI", pt_conj, inst=inst)
        pt_final = pt_conj_exists
        for pt_subst in pt_asserts:
            lhs, rhs = pt_subst.prop.args
            if not rhs.is_uminus():
                pt_final = pt_final.implies_intr(pt_subst.prop).forall_intr(rhs).\
                            forall_elim(lhs).implies_elim(ProofTerm.reflexive(lhs))
            else:
                pt_final = pt_final.implies_intr(pt_subst.prop).forall_intr(rhs.arg).\
                    forall_elim(-lhs).on_prop(top_conv(rewr_conv("real_neg_neg"))).implies_elim(ProofTerm.reflexive(lhs))
        return pt_final