Example #1
0
    def testExport(self):
        """Basic case."""
        pt1 = ProofTerm.assume(Eq(x, y))
        pt2 = ProofTerm.assume(Eq(y, z))
        pt3 = pt1.transitive(pt2)

        prf = pt3.export()
        self.assertEqual(len(prf.items), 3)
        self.assertEqual(theory.check_proof(prf), pt3.th)
Example #2
0
def encode(t):
    """Given a propositional formula t, compute its Tseitin encoding.

    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.

    """
    # Mapping from subterms to newly introduced variables
    subterm_dict = dict()
    for i, subt in enumerate(logic_subterms(t)):
        subterm_dict[subt] = Var('x' + str(i + 1), BoolType)

    # Collect list of equations
    eqs = []
    for subt in subterm_dict:
        r = subterm_dict[subt]
        if not is_logical(subt):
            eqs.append(Eq(r, subt))
        elif subt.is_not():
            r1 = subterm_dict[subt.arg]
            eqs.append(Eq(r, Not(r1)))
        else:
            r1 = subterm_dict[subt.arg1]
            r2 = subterm_dict[subt.arg]
            eqs.append(Eq(r, subt.head(r1, r2)))

    # Form the proof term
    eq_pts = [ProofTerm.assume(eq) for eq in eqs]
    encode_pt = ProofTerm.assume(t)
    for eq_pt in eq_pts:
        encode_pt = encode_pt.on_prop(top_conv(rewr_conv(eq_pt, sym=True)))
    for eq_pt in eq_pts:
        if is_logical(eq_pt.rhs):
            encode_pt = logic.apply_theorem('conjI', eq_pt, encode_pt)

    # Rewrite using Tseitin rules
    encode_thms = [
        'encode_conj', 'encode_disj', 'encode_imp', 'encode_eq', 'encode_not'
    ]

    for th in encode_thms:
        encode_pt = encode_pt.on_prop(top_conv(rewr_conv(th)))

    # Normalize the conjuncts
    return encode_pt.on_prop(logic.conj_norm())
Example #3
0
    def testIntro(self):
        basic.load_theory('logic_base')
        macro = logic.intros_macro()

        Ta = TVar('a')
        x = Var('x', Ta)
        P = Var('P', TFun(Ta, BoolType))
        C = Var('C', BoolType)
        ex_P = Exists(x, P(x))
        pt1 = ProofTerm.assume(ex_P)
        pt2 = ProofTerm.variable('x', Ta)
        pt3 = ProofTerm.assume(P(x))
        pt4 = ProofTerm.sorry(Thm([P(x)], C))
        pt4 = ProofTerm('intros', args=[ex_P], prevs=[pt1, pt2, pt3, pt4])
        prf = pt4.export()
        self.assertEqual(theory.check_proof(prf), Thm([ex_P], C))
Example #4
0
    def testNormAbsoluteValue(self):
        test_data = [
            ("abs x", ["x >= 0"], "x"),
            ("abs x", ["x Mem real_closed_interval 0 1"], "x"),
            ("abs x", ["x Mem real_closed_interval (-1) 0"], "-1 * x"),
            ("abs (sin x)", ["x Mem real_closed_interval 0 (pi / 2)"],
             "sin x"),
            ("abs (sin x)", ["x Mem real_closed_interval (-pi / 2) 0"],
             "-1 * sin x"),
            ("abs (log x)", ["x Mem real_open_interval (exp (-1)) 1"],
             "-1 * log x"),
        ]

        vars = {'x': 'real'}
        context.set_context('interval_arith', vars=vars)
        for t, conds, res in test_data:
            conds_pt = [
                ProofTerm.assume(parser.parse_term(cond)) for cond in conds
            ]
            cv = auto.auto_conv(conds_pt)
            test_conv(self,
                      'interval_arith',
                      cv,
                      vars=vars,
                      t=t,
                      t_res=res,
                      assms=conds)
Example #5
0
    def get_proof_term(self, goal, pts):
        dct = dict()

        def traverse_A(pt):
            # Given proof term showing a conjunction, put proof terms
            # showing atoms of the conjunction in dct.
            if pt.prop.is_conj():
                traverse_A(apply_theorem('conjD1', pt))
                traverse_A(apply_theorem('conjD2', pt))
            else:
                dct[pt.prop] = pt

        def traverse_C(t):
            # Return proof term with conclusion t
            if t.is_conj():
                left = traverse_C(t.arg1)
                right = traverse_C(t.arg)
                return apply_theorem('conjI', left, right)
            else:
                assert t in dct.keys(), 'imp_conj_macro'
                return dct[t]

        A = goal.arg1
        traverse_A(ProofTerm.assume(A))
        return traverse_C(goal.arg).implies_intr(A)
Example #6
0
    def testRewriteIntWithAsserstion(self):
        test_data = [(
            "¬(¬(¬(¬P8 ∨ ¬(F20 + -1 * F18 ≤ 0)) ∨ ¬(P8 ∨ ¬(F4 + -1 * F2 ≤ 0))) ∨ ¬(¬(P8 ∨ ¬(F6 + -1 * F4 ≤ 0)) ∨ \
            ¬(¬P8 ∨ ¬(F22 + -1 * F20 ≤ 0))) ∨ ¬(¬(P8 ∨ ¬(F2 + -1 * F0 ≤ 0)) ∨ ¬(¬P8 ∨ ¬(F18 + -1 * F16 ≤ 0))))\
            ⟷ ¬(¬(F2 + -1 * F0 ≤ 0) ∨ ¬(F6 + -1 * F4 ≤ 0) ∨ ¬(F4 + -1 * F2 ≤ 0))",
            ("P8", "P8 ⟷ false"))]

        context.set_context('smt',
                            vars={
                                "P8": "bool",
                                "F20": "int",
                                "F18": "int",
                                "P8": "bool",
                                "F4": "int",
                                "F2": "int",
                                "F6": "int",
                                "F22": "int",
                                "F20": "int",
                                "F2": "int",
                                "F16": "int",
                                "F0": "int"
                            })
        for tm, ast in test_data:
            tm = parse_term(tm)
            var, prop = [parse_term(i) for i in ast]
            proofrec.atoms.clear()
            proofrec.atoms[var] = ProofTerm.assume(prop)
            proofrec._rewrite(tm)
Example #7
0
    def get_proof_term(self, goal, prevs=None):
        elems = goal.strip_disj()

        disjs = [tm.arg for tm in elems[:-1]]
        disj_pts = [ProofTerm.assume(disj) for disj in disjs]
        pt0 = disj_pts[0]
        for pt1 in disj_pts[1:]:
            if pt1.lhs == pt0.rhs:
                pt0 = pt0.transitive(pt1)
            elif pt1.lhs == pt0.lhs:
                pt0 = pt0.symmetric().transitive(pt1)
            elif pt1.rhs == pt0.lhs:
                pt0 = pt0.symmetric().transitive(pt1.symmetric())
            elif pt1.rhs == pt0.rhs:
                pt0 = pt0.transitive(pt1.symmetric())

            else:
                print(pt0.prop)
                print(pt1.prop)
                raise NotImplementedError

        if pt0.symmetric().prop == elems[-1]:
            pt0 = pt0.symmetric()

        assert pt0.prop == elems[-1], "%s \n %s" % (str(
            pt0.prop), str(goal.strip_disj()[-1]))

        return ProofTerm("imp_to_or", elems[:-1] + [goal], prevs=[pt0])
Example #8
0
    def testGetBoundsProof(self):
        test_data = [
            ("x + 3", "[0, 1]", "[3, 4]"),
            ("x + 3", "(0, 1)", "(3, 4)"),
            ("3 + x", "(0, 1)", "(3, 4)"),
            ("x + x", "(0, 1)", "(0, 2)"),
            ("-x", "[0, 2]", "[-2, 0]"),
            ("-x", "(1, 3)", "(-3, -1)"),
            ("-x", "(-1, 1)", "(-1, 1)"),
            ("x - 3", "[0, 1]", "[-3, -2]"),
            ("3 - x", "(0, 1)", "(2, 3)"),
            ("2 * x", "[0, 1]", "[0, 2]"),
            ("1 / x", "[1, 2]", "[1/2, 1]"),
            ("x ^ 2", "[1, 2]", "[1, 4]"),
            ("x ^ 2", "(-1, 0)", "(0, 1)"),
            ("x ^ 3", "(-1, 0)", "(-1, 0)"),
            ("sin(x)", "(0, pi/2)", "(0, 1)"),
            ("sin(x)", "(-pi/2, 0)", "(-1, 0)"),
            ("cos(x)", "(0, pi/2)", "(0, 1)"),
            ("cos(x)", "(-pi/2, pi/2)", "(0, 1]"),
            ("x ^ (1/2)", "(0, 4)", "(0, 2)"),
            ("log(x)", "(1, exp(2))", "(0, 2)"),
        ]

        context.set_context('interval_arith')
        for s, i1, i2 in test_data:
            t = expr_to_holpy(parse_expr(s))
            cond = hol_set.mk_mem(term.Var('x', RealType),
                                  interval_to_holpy(parse_interval(i1)))
            var_range = {'x': ProofTerm.assume(cond)}
            res = hol_set.mk_mem(t, interval_to_holpy(parse_interval(i2)))
            pt = get_bounds_proof(t, var_range)
            self.assertEqual(pt.prop, res)
Example #9
0
    def testCombineFractionConv(self):
        test_data = [
            ('1 / (x + 1) + 1 / (x - 1)',
             'x Mem real_open_interval (-1/2) (1/2)',
             '2 * x / ((x + 1) * (x - 1))'),
            ("2 + 1 / (x + 1)", 'x Mem real_open_interval 0 1',
             '(3 + 2 * x) / (x + 1)'),
            ("(x + 1) ^ -(1::real)", 'x Mem real_open_interval 0 1',
             '1 / (x + 1)'),
            ("2 * (x * (x + 1) ^ -(1::real))", 'x Mem real_open_interval 0 1',
             '2 * x / (x + 1)'),
            ("2 - 1 / (x + 1)", 'x Mem real_open_interval 0 1',
             '(1 + 2 * x) / (x + 1)'),
            ("x ^ (1/2)", "x Mem real_open_interval 0 1", "x ^ (1/2) / 1"),
            ("x ^ -(1/2)", "x Mem real_open_interval 0 1", "1 / (x ^ (1/2))"),
            ("x ^ -(2::real)", "x Mem real_open_interval 0 1",
             "1 / (x ^ (2::nat))"),
        ]

        vars = {'x': 'real'}
        context.set_context('interval_arith', vars=vars)
        for s, cond, res in test_data:
            s = parser.parse_term(s)
            res = parser.parse_term(res)
            cond_t = parser.parse_term(cond)
            cv = proof.combine_fraction([ProofTerm.assume(cond_t)])
            test_conv(self,
                      'interval_arith',
                      cv,
                      vars=vars,
                      t=s,
                      t_res=res,
                      assms=[cond])
Example #10
0
    def get_proof_term(self, goal):
        th = theory.get_theorem(self.th_name)

        assum = th.assums[0]
        cond = self.cond
        if cond is None:
            # Find cond by matching with goal.hyps one by one
            for hyp in goal.hyps:
                try:
                    inst = matcher.first_order_match(th.assums[0], hyp,
                                                     self.inst)
                    cond = hyp
                    break
                except matcher.MatchException:
                    pass

        if cond is None:
            raise TacticException('elim: cannot match assumption')

        try:
            inst = matcher.first_order_match(th.concl, goal.prop, inst)
        except matcher.MatchException:
            raise TacticException('elim: matching failed')

        if any(v.name not in inst for v in th.prop.get_svars()):
            raise TacticException('elim: not all variables are matched')

        pt = ProofTerm.theorem(self.th_name).substitution(inst).on_prop(
            beta_norm_conv())
        pt = pt.implies_elim(ProofTerm.assume(cond))
        for assum in pt.assums:
            pt = pt.implies_elim(ProofTerm.sorry(Thm(goal.hyps, assum)))
        return pt
Example #11
0
    def __init__(self, t):
        assert tseitin.is_logical(t), "%s is not a logical term." % str(t)
        if not is_cnf(t):
            self.encode_pt = tseitin.encode(t)
        else:
            self.encode_pt = ProofTerm.assume(t)
        self.f = self.encode_pt.prop

        # Index the vars occur in cnf term
        self.vars = set()
        self.var_index = dict()
        self.index_var = dict()
        cnf_list = []
        clauses = self.f.strip_conj()
        i = 1

        for clause in clauses:
            literals = clause.strip_disj()
            c = []
            for lit in literals:
                atom = get_atom(lit)
                if atom not in self.var_index:
                    self.var_index[atom] = i
                    self.index_var[i] = atom
                    i += 1
                index = self.var_index[atom]
                if atom != lit:
                    c.append(-index)
                else:
                    c.append(index)
            cnf_list.append(tuple(c))

        self.cnf_list = tuple(cnf_list)

        # Indicate the cnf is whether SAT
        self.state = None

        # Dictionary from index to clause
        self.clause_pt = {
            i: ProofTerm.assume(c)
            for i, c in enumerate(self.f.strip_conj())
        }

        self.conflict_pt = None
Example #12
0
    def testNormRealDerivative(self):
        test_data = [
            # Differentiable everywhere
            ("real_derivative (%x. x) x", [], "(1::real)"),
            ("real_derivative (%x. 3) x", [], "(0::real)"),
            ("real_derivative (%x. 3 * x) x", [], "(3::real)"),
            ("real_derivative (%x. x ^ (2::nat)) x", [], "2 * x"),
            ("real_derivative (%x. x ^ (3::nat)) x", [], "3 * x ^ (2::nat)"),
            ("real_derivative (%x. (x + 1) ^ (3::nat)) x", [],
             "3 + 6 * x + 3 * x ^ (2::nat)"),
            ("real_derivative (%x. exp x) x", [], "exp x"),
            ("real_derivative (%x. exp (x ^ (2::nat))) x", [],
             "2 * (exp (x ^ (2::nat)) * x)"),
            # ("real_derivative (%x. exp (exp x)) x", [], "exp (x + exp x)"),
            ("real_derivative (%x. sin x) x", [], "cos x"),
            ("real_derivative (%x. cos x) x", [], "-1 * sin x"),
            ("real_derivative (%x. sin x * cos x) x", [],
             "(cos x) ^ (2::nat) + -1 * (sin x) ^ (2::nat)"),

            # Differentiable with conditions
            ("real_derivative (%x. 1 / x) x", ["x Mem real_open_interval 0 1"],
             "-1 * x ^ -(2::real)"),
            ("real_derivative (%x. 1 / (x ^ (2::nat) + 1)) x",
             ["x Mem real_open_interval (-1) 1"],
             "-2 * (x * (1 + 2 * x ^ (2::nat) + x ^ (4::nat)) ^ -(1::real))"),
            ("real_derivative (%x. log x) x", ["x Mem real_open_interval 0 1"],
             "x ^ -(1::real)"),
            ("real_derivative (%x. log (sin x)) x",
             ["x Mem real_open_interval 0 1"], "cos x * (sin x) ^ -(1::real)"),
            ("real_derivative (%x. sqrt x) x",
             ["x Mem real_open_interval 0 1"], "1 / 2 * x ^ -(1 / 2)"),
            ("real_derivative (%x. sqrt (x ^ (2::nat) + 1)) x",
             ["x Mem real_open_interval (-1) 1"
              ], "x * (1 + x ^ (2::nat)) ^ -(1 / 2)"),

            # Real power
            ("real_derivative (%x. x ^ (1 / 3)) x",
             ["x Mem real_open_interval 0 1"], "1 / 3 * x ^ -(2 / 3)"),
            ("real_derivative (%x. 2 ^ x) x",
             ["x Mem real_open_interval (-1) 1"], "log 2 * 2 ^ x"),
        ]

        vars = {'x': 'real'}
        context.set_context('interval_arith', vars=vars)
        for t, conds, res in test_data:
            conds_pt = [
                ProofTerm.assume(parser.parse_term(cond)) for cond in conds
            ]
            cv = auto.auto_conv(conds_pt)
            test_conv(self,
                      'interval_arith',
                      cv,
                      vars=vars,
                      t=t,
                      t_res=res,
                      assms=conds)
Example #13
0
def vcg(T, goal):
    """Compute the verification conditions for the goal. Here the
    goal is of the form Valid P c Q. The function returns a proof term
    showing [] |- Valid P c Q.
    
    """
    P, c, Q = goal.args
    pt = compute_wp(T, c, Q)
    entail_P = ProofTerm.assume(Entail(T)(P, pt.prop.args[0]))
    return apply_theorem("pre_rule", entail_P, pt)
Example #14
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])
Example #15
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)
Example #16
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])
Example #17
0
    def testThLemmaIntMulti(self):
        test_data = [(('¬(x ≤ 3)', 'x ≤ 4'), '0 = -4 + x'),
                     (('x ≥ 0', 'x ≤ 0'), '1 = 1 + x'),
                     (('x ≥ 0', '¬(x ≥ 1)'), '1 = 1 + x')]

        context.set_context('smt', vars={'x': 'int'})

        for assms, res in test_data:
            assms = [ProofTerm.assume(parse_term(assm)) for assm in assms]
            res = parse_term(res)
            self.assertEqual(proofrec.th_lemma([*assms, res]).prop, res)
Example #18
0
    def get_proof_term(self, args, pts):
        new_names = get_forall_names(args)
        vars, As, C = strip_all_implies(args, new_names)
        assert C in As, "trivial_macro"

        pt = ProofTerm.assume(C)
        for A in reversed(As):
            pt = pt.implies_intr(A)
        for v in reversed(vars):
            pt = pt.forall_intr(v)
        return pt
Example #19
0
    def get_proof_term(self, goal, *, args=None, prevs=None):
        if args is None:
            var_names = []
        else:
            var_names = args

        vars, As, C = logic.strip_all_implies(goal.prop, var_names, svar=False)

        pt = ProofTerm.sorry(Thm(list(goal.hyps) + As, C))
        ptAs = [ProofTerm.assume(A) for A in As]
        ptVars = [ProofTerm.variable(var.name, var.T) for var in vars]
        return ProofTerm('intros', None, ptVars + ptAs + [pt])
Example #20
0
    def get_proof(self):
        invC = Const("inv", TFun(gcl.stateT, BoolType))
        transC = Const("trans", TFun(gcl.stateT, gcl.stateT, BoolType))
        s1 = Var("s1", gcl.stateT)
        s2 = Var("s2", gcl.stateT)
        prop = Thm([], Implies(invC(s1), transC(s1, s2), invC(s2)))
        # print(printer.print_thm(prop))

        trans_pt = ProofTerm.assume(transC(s1, s2))
        # print(printer.print_thm(trans_pt.th))
        P = Implies(invC(s1), invC(s2))
        ind_pt = apply_theorem("trans_cases", inst=Inst(a1=s1, a2=s2, P=P))
        # print(printer.print_thm(ind_pt.th))

        ind_As, ind_C = ind_pt.prop.strip_implies()
        for ind_A in ind_As[1:-1]:
            # print("ind_A: ", ind_A)
            vars, As, C = logic.strip_all_implies(ind_A, ["s", "k"])
            # for A in As:
            #     print("A: ", A)
            # print("C: ", C)
            eq1 = ProofTerm.assume(As[0])
            eq2 = ProofTerm.assume(As[1])
            guard = ProofTerm.assume(As[2])
            inv_pre = ProofTerm.assume(As[3]).on_arg(rewr_conv(eq1)).on_prop(
                rewr_conv("inv_def"))
            C_goal = ProofTerm.assume(C).on_arg(rewr_conv(eq2)).on_prop(
                rewr_conv("inv_def"))
Example #21
0
    def __init__(self, vars, assms):
        self.vars = vars
        self.assms = assms
        self.updates = []
        self.queue = queue.PriorityQueue()

        # Add the initial assumptions to the queue
        for assm in self.assms:
            self.queue.put(
                Update(0, '$INIT', [], FactItem(ProofTerm.assume(assm))))

        # Overall count of number of steps
        self.step_count = 0
Example #22
0
    def testGetBoundsProofSplit(self):
        test_data = [
            ("x ^ 2", "[-1, 1]", "[0, 1]"),
            ("x ^ 2", "(-1, 1)", "[0, 1)"),
            ("2 + -1 * x ^ 2", "(-1, 1)", "(1, 2]"),
        ]

        context.set_context('interval_arith')
        for s, i1, i2 in test_data:
            t = expr_to_holpy(parse_expr(s))
            cond = hol_set.mk_mem(term.Var('x', RealType),
                                  interval_to_holpy(parse_interval(i1)))
            var_range = {'x': ProofTerm.assume(cond)}
            res = hol_set.mk_mem(t, interval_to_holpy(parse_interval(i2)))
            pt = get_bounds_proof(t, var_range)
            self.assertEqual(pt.prop, res)
Example #23
0
    def testInequalityMacro(self):
        test_data = [
            ("x < 2", "x Mem real_closed_interval 0 1"),
            ("x > 0", "x Mem real_closed_interval 1 2"),
            ("-1 + x >= 0", "x Mem real_closed_interval 1 2"),
            ("1 + -(x ^ (2::nat)) > 0",
             "x Mem real_open_interval (1 / 2 * 2 ^ (1 / 2)) 1"),
            ("1 + x > 0", "x Mem real_open_interval (-1 / 2) (1 / 2)"),
        ]

        context.set_context('interval_arith', vars={'x': 'real'})
        macro = IntervalInequalityMacro()
        for goal, cond in test_data:
            goal = parser.parse_term(goal)
            cond = parser.parse_term(cond)
            pt = macro.get_proof_term(goal, [ProofTerm.assume(cond)])
            self.assertEqual(pt.prop, goal)
Example #24
0
    def testCombineAtomConv(self):
        test_data = [
            ("x ^ (2::nat) * x ^ (3::nat)", [], "x ^ (5::nat)"),
            ("x ^ (2::nat) * x ^ (1 / 2)", ["x > 0"], "x ^ (5 / 2)"),
            ("x * x", [], "x ^ (2::nat)"),
            ("x * (x ^ (2::nat))", [], "x ^ (3::nat)"),
            ("x * (x ^ (1 / 2))", ["x > 0"], "x ^ (3 / 2)"),
            ("x ^ (1 / 2) * x ^ (1 / 2)", ["x > 0"], "x"),
            ("x ^ (1 / 2) * x ^ (3 / 2)", ["x > 0"], "x ^ (2::nat)"),
            ("x * x ^ (-(1::real))", ["x > 0"], "(1::real)"),
            ("x ^ (1 / 2) * x ^ -(1 / 2)", ["x > 0"], "(1::real)"),
        ]

        vars = {'x': 'real'}
        context.set_context('realintegral', vars=vars)
        for t, conds, res in test_data:
            conds_pt = [ProofTerm.assume(parser.parse_term(cond)) for cond in conds]
            cv = real.combine_atom(conds_pt)
            test_conv(self, 'realintegral', cv, vars=vars, t=t, t_res=res, assms=conds)
Example #25
0
    def testNormMultMonomials(self):
        test_data = [
            ("x * y", [], "x * y"),
            ("(1 / 2 * x) * (1 / 2 * y)", [], "1 / 4 * (x * y)"),
            ("x * (1 / 2 * y)", [], "1 / 2 * (x * y)"),
            ("(1 / 2 * x) * y", [], "1 / 2 * (x * y)"),
            ("(1 / 2 * x) * (2 * y)", [], "x * y"),
            ("(x * y) * (x * y)", [], "x ^ (2::nat) * y ^ (2::nat)"),
            ("(x * y) * (1 / 2 * x ^ (-(1::real)))", ["x > 0"], "1 / 2 * y"),
            ("(x * y) * (x ^ (-(1::real)) * y ^ (-(1::real)))", ["x > 0", "y > 0"], "(1::real)"),
            ("(1 / 2) * x", [], "1 / 2 * x"),
            ("(1 / 2) * (1 / 2 * x)", [], "1 / 4 * x"),
            ("(1 / 2) * (2 * x)", [], "x"),
            ("0 * x", [], "(0::real)"),
        ]

        vars = {'x': 'real', 'y': 'real'}
        context.set_context('realintegral', vars=vars)
        for t, conds, res in test_data:
            conds_pt = [ProofTerm.assume(parser.parse_term(cond)) for cond in conds]
            cv = real.norm_mult_monomials(conds_pt)
            test_conv(self, 'realintegral', cv, vars=vars, t=t, t_res=res, assms=conds)
Example #26
0
File: real.py Project: bzhan/holpy
    def handle_geq_stage1(self, pts):
        if not pts:
            return None, None, None

        # ⊢ min(min(...(min(x_1, x_2), x_3)...), x_n-1), x_n) > 0
        min_pos_pt = functools.reduce(
            lambda pt1, pt2: logic.apply_theorem("min_greater_0", pt1, pt2),
            pts[1:], pts[0])

        # ⊢ 0 < 2
        two_pos_pt = ProofTerm("real_compare", Real(0) < Real(2))

        # ⊢ min(...) / 2 > 0
        min_divides_two_pos = logic.apply_theorem(
            "real_lt_div", min_pos_pt.on_prop(rewr_conv("real_ge_to_le")),
            two_pos_pt).on_prop(rewr_conv("real_ge_to_le", sym=True))

        # ⊢ 2 ≥ 1
        two_larger_one = ProofTerm("real_compare", Real(2) >= Real(1))

        # ⊢ min(...) ≥ min(...) / 2
        larger_half_pt = logic.apply_theorem("real_divides_larger_1",
                                             two_larger_one, min_pos_pt)

        # ⊢ min(...) / 2 = δ_1
        delta_1 = Var("δ_1", RealType)
        pt_delta1_eq = ProofTerm.assume(Eq(larger_half_pt.prop.arg, delta_1))

        # ⊢ min(...) ≥ δ_1
        larger_half_pt_delta = larger_half_pt.on_prop(
            top_conv(replace_conv(pt_delta1_eq)))

        # ⊢ δ_1 > 0
        delta_1_pos = min_divides_two_pos.on_prop(
            arg1_conv(replace_conv(pt_delta1_eq)))

        return larger_half_pt_delta, delta_1_pos, pt_delta1_eq
Example #27
0
def compute_wp(T, c, Q):
    """Compute the weakest precondition for the given command
    and postcondition. Here c is the program and Q is the postcondition.
    The computation is by case analysis on the form of c. The function
    returns a proof term showing [...] |- Valid P c Q, where P is the
    computed precondition, and [...] contains the additional subgoals.

    """
    if c.is_const("Skip"):  # Skip
        return apply_theorem("skip_rule", concl=Valid(T)(Q, c, Q))
    elif c.is_comb("Assign", 2):  # Assign a b
        a, b = c.args
        s = Var("s", T)
        P2 = Lambda(s, Q(function.mk_fun_upd(s, a, b(s).beta_conv())))
        return apply_theorem("assign_rule",
                             inst=Inst(b=b),
                             concl=Valid(T)(P2, c, Q))
    elif c.is_comb("Seq", 2):  # Seq c1 c2
        c1, c2 = c.args
        wp1 = compute_wp(T, c2, Q)  # Valid Q' c2 Q
        wp2 = compute_wp(T, c1, wp1.prop.args[0])  # Valid Q'' c1 Q'
        return apply_theorem("seq_rule", wp2, wp1)
    elif c.is_comb("Cond", 3):  # Cond b c1 c2
        b, c1, c2 = c.args
        wp1 = compute_wp(T, c1, Q)
        wp2 = compute_wp(T, c2, Q)
        res = apply_theorem("if_rule", wp1, wp2, inst=Inst(b=b))
        return res
    elif c.is_comb("While", 3):  # While b I c
        _, I, _ = c.args
        pt = apply_theorem("while_rule", concl=Valid(T)(I, c, Q))
        pt0 = ProofTerm.assume(pt.assums[0])
        pt1 = vcg(T, pt.assums[1])
        return pt.implies_elim(pt0, pt1)
    else:
        raise NotImplementedError
Example #28
0
File: real.py Project: bzhan/holpy
    def handle_leq_stage1(self, pts):
        if not pts:
            return None, None, None
        # ⊢ max(max(...(max(x_1, x_2), x_3)...), x_n-1), x_n) < 0
        max_pos_pt = functools.reduce(
            lambda pt1, pt2: logic.apply_theorem("max_less_0", pt1, pt2),
            pts[1:], pts[0])

        # ⊢ 0 < 2
        two_pos_pt = ProofTerm("real_compare", Real(2) > Real(0))

        # ⊢ max(...) / 2 < 0
        max_divides_two_pos = logic.apply_theorem("real_neg_div_pos",
                                                  max_pos_pt, two_pos_pt)

        # ⊢ 2 ≥ 1
        two_larger_one = ProofTerm("real_compare", Real(2) >= Real(1))

        # ⊢ max(...) ≤ max(...) / 2
        less_half_pt = logic.apply_theorem("real_neg_divides_larger_1",
                                           two_larger_one, max_pos_pt)

        # ⊢ max(...) / 2 = -δ
        delta_2 = Var("δ_2", RealType)
        pt_delta_eq = ProofTerm.assume(Eq(less_half_pt.prop.arg, -delta_2))

        # ⊢ δ > 0
        delta_pos_pt = max_divides_two_pos.on_prop(
            rewr_conv("real_le_gt"), top_conv(replace_conv(pt_delta_eq)),
            auto.auto_conv())

        # max(...) ≤ -δ
        less_half_pt_delta = less_half_pt.on_prop(
            arg_conv(replace_conv(pt_delta_eq)))

        return less_half_pt_delta, delta_pos_pt, pt_delta_eq
Example #29
0
def test_macro(self,
               thy_name,
               macro,
               *,
               vars=None,
               assms=None,
               res=None,
               args="",
               failed=None,
               limit=None,
               eval_only=False):
    context.set_context(thy_name, vars=vars, limit=limit)

    macro = theory.global_macros[macro]
    assms = [parser.parse_term(assm)
             for assm in assms] if assms is not None else []
    prev_ths = [Thm([assm], assm) for assm in assms]
    prevs = [ProofTerm.assume(assm) for assm in assms]
    args = parser.parse_args(macro.sig, args)

    if failed is not None:
        self.assertRaises(failed, macro.eval, args, prev_ths)
        if not eval_only:
            self.assertRaises(failed, macro.get_proof_term, args, prevs)
        return

    res = parser.parse_term(res)

    # Check the eval function
    self.assertEqual(macro.eval(args, prev_ths), Thm(assms, res))

    # Check the proof term
    if not eval_only:
        pt = macro.get_proof_term(args, prevs)
        prf = pt.export()
        self.assertEqual(theory.check_proof(prf), Thm(assms, res))
Example #30
0
def get_nat_power_bounds(pt, n):
    """Given theorem of the form t Mem I, obtain a theorem of
    the form t ^ n Mem J.

    """
    a, b = get_mem_bounds(pt)
    if not n.is_number():
        raise NotImplementedError
    if eval_hol_expr(a) >= 0 and is_mem_closed(pt):
        pt = apply_theorem('nat_power_interval_pos_closed',
                           auto.auto_solve(real_nonneg(a)),
                           pt,
                           inst=Inst(n=n))
    elif eval_hol_expr(a) >= 0 and is_mem_open(pt):
        pt = apply_theorem('nat_power_interval_pos_open',
                           auto.auto_solve(real_nonneg(a)),
                           pt,
                           inst=Inst(n=n))
    elif eval_hol_expr(a) >= 0 and is_mem_lopen(pt):
        pt = apply_theorem('nat_power_interval_pos_lopen',
                           auto.auto_solve(real_nonneg(a)),
                           pt,
                           inst=Inst(n=n))
    elif eval_hol_expr(a) >= 0 and is_mem_ropen(pt):
        pt = apply_theorem('nat_power_interval_pos_ropen',
                           auto.auto_solve(real_nonneg(a)),
                           pt,
                           inst=Inst(n=n))
    elif eval_hol_expr(b) <= 0 and is_mem_closed(pt):
        int_n = n.dest_number()
        if int_n % 2 == 0:
            even_pt = nat_as_even(int_n)
            pt = apply_theorem('nat_power_interval_neg_even_closed',
                               auto.auto_solve(real_nonpos(b)), even_pt, pt)
        else:
            odd_pt = nat_as_odd(int_n)
            pt = apply_theorem('nat_power_interval_neg_odd_closed',
                               auto.auto_solve(real_nonpos(b)), odd_pt, pt)
    elif eval_hol_expr(b) <= 0 and is_mem_open(pt):
        int_n = n.dest_number()
        if int_n % 2 == 0:
            even_pt = nat_as_even(int_n)
            pt = apply_theorem('nat_power_interval_neg_even_open',
                               auto.auto_solve(real_nonpos(b)), even_pt, pt)
        else:
            odd_pt = nat_as_odd(int_n)
            pt = apply_theorem('nat_power_interval_neg_odd_open',
                               auto.auto_solve(real_nonpos(b)), odd_pt, pt)
    elif is_mem_closed(pt):
        # Closed interval containing 0
        t = pt.prop.arg1
        assm1 = hol_set.mk_mem(t, real.closed_interval(a, Real(0)))
        assm2 = hol_set.mk_mem(t, real.closed_interval(Real(0), b))
        pt1 = get_nat_power_bounds(ProofTerm.assume(assm1),
                                   n).implies_intr(assm1)
        pt2 = get_nat_power_bounds(ProofTerm.assume(assm2),
                                   n).implies_intr(assm2)
        x = Var('x', RealType)
        pt = apply_theorem('split_interval_closed',
                           auto.auto_solve(real.less_eq(a, Real(0))),
                           auto.auto_solve(real.less_eq(Real(0), b)),
                           pt1,
                           pt2,
                           pt,
                           inst=Inst(x=t, f=Lambda(x, x**n)))
        subset_pt = interval_union_subset(pt.prop.arg)
        pt = apply_theorem('subsetE', subset_pt, pt)
    elif is_mem_open(pt):
        # Open interval containing 0
        t = pt.prop.arg1
        assm1 = hol_set.mk_mem(t, real.open_interval(a, Real(0)))
        assm2 = hol_set.mk_mem(t, real.ropen_interval(Real(0), b))
        pt1 = get_nat_power_bounds(ProofTerm.assume(assm1),
                                   n).implies_intr(assm1)
        pt2 = get_nat_power_bounds(ProofTerm.assume(assm2),
                                   n).implies_intr(assm2)
        x = Var('x', RealType)
        pt = apply_theorem('split_interval_open',
                           auto.auto_solve(real.less_eq(a, Real(0))),
                           auto.auto_solve(real.less_eq(Real(0), b)),
                           pt1,
                           pt2,
                           pt,
                           inst=Inst(x=t, f=Lambda(x, x**n)))
        subset_pt = interval_union_subset(pt.prop.arg)
        pt = apply_theorem('subsetE', subset_pt, pt)
    else:
        raise NotImplementedError
    return norm_mem_interval(pt)