Esempio n. 1
0
def interval_union_subset(t):
    """Given t of the form I1 Un I2, return a theorem of the form
    I1 Un I2 SUB I.

    """
    assert t.is_comb('union', 2), "interval_union_subset"

    I1, I2 = t.args
    a, b = I1.args
    c, d = I2.args
    if is_closed_interval(I1) and is_closed_interval(I2):
        pt = apply_theorem('closed_interval_union',
                           inst=Inst(a=a, b=b, c=c, d=d))
        return pt.on_prop(
            arg_conv(
                then_conv(arg1_conv(const_min_conv()),
                          arg_conv(const_max_conv()))))
    elif is_open_interval(I1) and is_ropen_interval(I2):
        if eval_hol_expr(c) <= eval_hol_expr(a):
            pt = apply_theorem('open_ropen_interval_union1',
                               auto.auto_solve(real.less_eq(c, a)),
                               inst=Inst(b=b, d=d))
        else:
            pt = apply_theorem('open_ropen_interval_union2',
                               auto.auto_solve(real.less(a, c)),
                               inst=Inst(b=b, d=d))
        return pt.on_prop(arg_conv(arg_conv(const_max_conv())))
    else:
        raise NotImplementedError

    return pt
Esempio n. 2
0
def first_order_match_list(pats, ts, inst=None):
    """First-order matching of a list of pattern-term pairs.
    
    inst : optinal Inst
        Existing instantiation. Default to empty instantiation.
    
    """
    if inst is None:
        inst = Inst()
    else:
        inst = copy(inst)

    if len(pats) == 0:
        return inst

    if len(pats) == 1:
        return first_order_match(pats[0], ts[0], inst)

    if is_pattern(pats[0], list(inst.keys())):
        inst = first_order_match(pats[0], ts[0], inst)
        inst = first_order_match_list(pats[1:], ts[1:], inst)
        return inst
    else:
        inst = first_order_match_list(pats[1:], ts[1:], inst)
        inst = first_order_match(pats[0], ts[0], inst)
        return inst
Esempio n. 3
0
def eval_Sem(c, st):
    """Evaluates the effect of program c on state st."""
    T = st.get_type()
    if c.is_const("Skip"):
        return apply_theorem("Sem_Skip", inst=Inst(s=st))
    elif c.is_comb("Assign", 2):
        a, b = c.args
        Ta = a.get_type()
        Tb = b.get_type().range_type()
        pt = apply_theorem("Sem_Assign", inst=Inst(a=a, b=b, s=st))
        return pt.on_arg(arg_conv(norm_cv))
    elif c.is_comb("Seq", 2):
        c1, c2 = c.args
        pt1 = eval_Sem(c1, st)
        pt2 = eval_Sem(c2, pt1.prop.arg)
        pt = apply_theorem("Sem_seq", pt1, pt2)
        return pt.on_arg(function.fun_upd_norm_one_conv())
    elif c.is_comb("Cond", 3):
        b, c1, c2 = c.args
        b_st = beta_norm(b(st))
        b_eval = norm_cond_cv.get_proof_term(b_st)
        if b_eval.prop.arg == true:
            b_res = b_eval.on_prop(rewr_conv("eq_true", sym=True))
            pt1 = eval_Sem(c1, st)
            return apply_theorem("Sem_if1",
                                 b_res,
                                 pt1,
                                 concl=Sem(T)(c, st, pt1.prop.arg))
        else:
            b_res = b_eval.on_prop(rewr_conv("eq_false", sym=True))
            pt2 = eval_Sem(c2, st)
            return apply_theorem("Sem_if2",
                                 b_res,
                                 pt2,
                                 concl=Sem(T)(c, st, pt2.prop.arg))
    elif c.is_comb("While", 3):
        b, inv, body = c.args
        b_st = beta_norm(b(st))
        b_eval = norm_cond_cv.get_proof_term(b_st)
        if b_eval.prop.arg == true:
            b_res = b_eval.on_prop(rewr_conv("eq_true", sym=True))
            pt1 = eval_Sem(body, st)
            pt2 = eval_Sem(c, pt1.prop.arg)
            pt = apply_theorem("Sem_while_loop",
                               b_res,
                               pt1,
                               pt2,
                               concl=Sem(T)(c, st, pt2.prop.arg),
                               inst=Inst(s3=pt1.prop.arg))
            return pt.on_arg(function.fun_upd_norm_one_conv())
        else:
            b_res = b_eval.on_prop(rewr_conv("eq_false", sym=True))
            return apply_theorem("Sem_while_skip",
                                 b_res,
                                 concl=Sem(T)(c, st, st))
    else:
        raise NotImplementedError
Esempio n. 4
0
    def run_test(self, thy_name, pat, t, *, vars=None, svars=None, tyinst=None, inst=None, failed=None):
        context.set_context(thy_name, vars=vars, svars=svars)

        pat, t = Term(pat), Term(t)
        inst = Inst((nm, Term(s)) for nm, s in inst.items()) if inst is not None else Inst()
        if tyinst is not None:
            inst.tyinst = TyInst((nm, Type(s)) for nm, s in tyinst.items())

        if failed is not None:
            self.assertRaises(failed, first_order_match, pat, t)
            return

        self.assertEqual(first_order_match(pat, t), inst)
Esempio n. 5
0
 def substitution(self, inst=None, **kwargs):
     if inst is None:
         inst = Inst(**kwargs)
     if inst:
         return ProofTerm("substitution", inst, [self])
     else:
         return self
Esempio n. 6
0
    def get_proof_term(self, args, pts):
        if self.with_inst:
            name, inst = args
        else:
            name = args
            inst = Inst()
        th = theory.get_theorem(name)
        As, C = th.prop.strip_implies()

        assert len(pts) <= len(As), "apply_theorem: too many prevs."

        # First attempt to match type variables
        svars = th.prop.get_svars()
        for v in svars:
            if v.name in inst:
                v.T.match_incr(inst[v.name].get_type(), inst.tyinst)

        pats = As[:len(pts)]
        ts = [pt.prop for pt in pts]
        inst = matcher.first_order_match_list(pats, ts, inst)

        pt = ProofTerm.theorem(name)
        pt = pt.subst_type(inst.tyinst).substitution(inst)
        if pt.prop.beta_norm() != pt.prop:
            pt = pt.on_prop(beta_norm_conv())
        pt = pt.implies_elim(*pts)

        assert len(pt.prop.get_stvars()) == 0, "apply_theorem: unmatched type variables."
        vars = pt.prop.get_svars()
        for v in reversed(vars):
            pt = pt.forall_intr(v)

        return pt
Esempio n. 7
0
    def eval(self, args, prevs):
        if self.with_inst:
            name, inst = args
        else:
            name = args
            inst = Inst()
        th = theory.get_theorem(name)
        As, C = th.prop.strip_implies()

        assert len(prevs) <= len(As), "apply_theorem: too many prevs."

        # First attempt to match type variables
        svars = th.prop.get_svars()
        for v in svars:
            if v.name in inst:
                v.T.match_incr(inst[v.name].get_type(), inst.tyinst)

        pats = As[:len(prevs)]
        ts = [prev_th.prop for prev_th in prevs]
        inst = matcher.first_order_match_list(pats, ts, inst)

        As, C = th.prop.subst_norm(inst).strip_implies()
        new_prop = Implies(*(As[len(prevs):] + [C]))

        prev_hyps = sum([prev.hyps for prev in prevs], ())
        th = Thm(th.hyps + prev_hyps, new_prop)

        assert len(new_prop.get_stvars()) == 0, "apply_theorem: unmatched type variables."
        vars = new_prop.get_svars()
        for v in reversed(vars):
            th = Thm.forall_intr(v, th)
        return th
Esempio n. 8
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"))
Esempio n. 9
0
    def get_proof_term(self, goal, pts):
        """Goal is of the form A_1 | ... | A_m --> B_1 | ...| B_n, where
        {A_1, ..., A_m} is a subset of {B_1, ..., B_n}."""

        # Dictionary from B_i to B_i --> B_1 | ... | B_n
        pts_B = dict()
        
        # Fills up pts_B.
        def traverse_C(pt):
            if pt.prop.arg1.is_disj():
                pt1 = apply_theorem('disjI1', concl=pt.prop.arg1)
                pt2 = apply_theorem('disjI2', concl=pt.prop.arg1)
                traverse_C(apply_theorem('syllogism', pt1, pt))
                traverse_C(apply_theorem('syllogism', pt2, pt))
            else:
                pts_B[pt.prop.arg1] = pt
        
        # Use pts_B to prove the implication
        def traverse_A(t):
            if t.is_disj():
                pt1 = traverse_A(t.arg1)
                pt2 = traverse_A(t.arg)
                return apply_theorem('disjE2', pt1, pt2)
            else:
                assert t in pts_B, "imp_disj: %s not found in conclusion" % t
                return pts_B[t]
            
        triv = apply_theorem('trivial', inst=Inst(A=goal.arg))
        traverse_C(triv)
        return traverse_A(goal.arg1)
Esempio n. 10
0
    def testProofItem(self):
        test_data = [
            (ProofItem(0, "theorem", args="conjD1"), "0: theorem conjD1", {
                'id': 0,
                'th': '',
                'rule': 'theorem',
                'args': 'conjD1',
                'prevs': []
            }),
            (ProofItem(1, "assume", args=A_to_B), "1: assume implies A B", {
                'id': 1,
                'th': '',
                'rule': 'assume',
                'args': 'implies A B',
                'prevs': []
            }),
            (ProofItem(5, "substitution", args=Inst(A=B, B=A),
                       prevs=[4]), "5: substitution {A: B, B: A} from 4", {
                           'id': 5,
                           'th': '',
                           'rule': 'substitution',
                           'args': '{A: B, B: A}',
                           'prevs': [4]
                       }),
            (ProofItem(6, "implies_elim",
                       prevs=[5, 3]), "6: implies_elim from 5, 3", {
                           'id': 6,
                           'th': '',
                           'rule': 'implies_elim',
                           'args': '',
                           'prevs': [5, 3]
                       }),
            (ProofItem(1,
                       "apply_theorem_for",
                       args=("conjD2", Inst(A=B, B=A)),
                       prevs=[0]),
             "1: apply_theorem_for conjD2, {A: B, B: A} from 0", {
                 'id': 1,
                 'th': '',
                 'rule': 'apply_theorem_for',
                 'args': 'conjD2, {A: B, B: A}',
                 'prevs': [0]
             })
        ]

        for item, s, d in test_data:
            self.assertEqual(str(item), s)
Esempio n. 11
0
File: nat.py Progetto: bzhan/holpy
def ineq_one_proof_term(n):
    """Returns the inequality n ~= 1."""
    assert n != 1, "ineq_one_proof_term: n = 1"
    if n == 0:
        return apply_theorem("ineq_sym", ProofTerm.theorem("one_nonzero"))
    elif n % 2 == 0:
        return apply_theorem("bit0_neq_one", inst=Inst(m=Binary(n // 2)))
    else:
        return apply_theorem("bit1_neq_one", ineq_zero_proof_term(n // 2))
Esempio n. 12
0
File: nat.py Progetto: bzhan/holpy
def ineq_zero_proof_term(n):
    """Returns the inequality n ~= 0."""
    assert n != 0, "ineq_zero_proof_term: n = 0"
    if n == 1:
        return ProofTerm.theorem("one_nonzero")
    elif n % 2 == 0:
        return apply_theorem("bit0_nonzero", ineq_zero_proof_term(n // 2))
    else:
        return apply_theorem("bit1_nonzero", inst=Inst(m=Binary(n // 2)))
Esempio n. 13
0
    def get_proof_term(self, goal, *, args=None, prevs=None):
        assert isinstance(args, Term), "inst_exists_goal"

        C = goal.prop
        assert C.is_exists(), "inst_exists_goal: goal is not exists statement"
        argT = args.get_type()
        assert C.arg.var_T == argT, "inst_exists_goal: incorrect type: expect %s, given %s" % (
            str(C.arg.var_T), str(argT))

        return rule().get_proof_term(goal, args=('exI', Inst(P=C.arg, a=args)))
Esempio n. 14
0
    def get_proof_term(self, goal, *, args=None, prevs=None):
        if isinstance(args, tuple):
            th_name, inst = args
        else:
            th_name, inst = args, None
        assert isinstance(th_name, str), "rule: theorem name must be a string"

        if prevs is None:
            prevs = []

        th = theory.get_theorem(th_name)
        As, C = th.assums, th.concl

        # Length of prevs is at most length of As
        assert len(prevs) <= len(As), "rule: too many previous facts"
        if inst is None:
            inst = Inst()

        # Match the conclusion and assumptions. Either the conclusion
        # or the list of assumptions must be a first-order pattern.
        if matcher.is_pattern(C, []):
            inst = matcher.first_order_match(C, goal.prop, inst)
            for pat, prev in zip(As, prevs):
                inst = matcher.first_order_match(pat, prev.prop, inst)
        else:
            for pat, prev in zip(As, prevs):
                inst = matcher.first_order_match(pat, prev.prop, inst)
            inst = matcher.first_order_match(C, goal.prop, inst)

        # Check that every variable in the theorem has an instantiation.
        unmatched_vars = [
            v.name for v in term.get_svars(As + [C]) if v.name not in inst
        ]
        if unmatched_vars:
            raise theory.ParameterQueryException(
                list("param_" + name for name in unmatched_vars))

        # Substitute and normalize
        As, _ = th.prop.subst_norm(inst).strip_implies()
        goal_Alen = len(goal.assums)
        if goal_Alen > 0:
            As = As[:-goal_Alen]

        pts = prevs + [
            ProofTerm.sorry(Thm(goal.hyps, A)) for A in As[len(prevs):]
        ]

        # Determine whether it is necessary to provide instantiation
        # to apply_theorem.
        if set(term.get_svars(th.assums)) != set(th.prop.get_svars()) or \
           set(term.get_stvars(th.assums)) != set(th.prop.get_stvars()) or \
           not matcher.is_pattern_list(th.assums, []):
            return apply_theorem(th_name, *pts, inst=inst)
        else:
            return apply_theorem(th_name, *pts)
Esempio n. 15
0
    def testSubst(self):
        test_data = [
            (SVar('a', Ta), c),
            (c, c),
            (f(SVar('a', Ta)), f(c)),
            (Abs("x", Ta, B0), Abs("x", Ta, B0)),
            (Abs("x", Ta, SVar('a', Ta)), Abs("x", Ta, c)),
        ]

        for t, res in test_data:
            self.assertEqual(t.subst(Inst(a=c)), res)
Esempio n. 16
0
    def apply(self, state, id, data, prevs):
        inst = Inst()
        with context.fresh_context(vars=state.get_vars(id)):
            for key, val in data.items():
                if key.startswith("param_"):
                    inst[key[6:]] = parser.parse_term(val)

        if inst:
            state.apply_tactic(id, tactic.apply_prev(), args=inst, prevs=prevs)
        else:
            state.apply_tactic(id, tactic.apply_prev(), prevs=prevs)
Esempio n. 17
0
 def testRule4(self):
     n = Var("n", NatType)
     self.run_test('nat',
                   tactic.rule(),
                   vars={"n": "nat"},
                   goal="n + 0 = n",
                   args=("nat_induct", Inst(P=Lambda(n, Eq(n + 0, n)),
                                            x=n)),
                   new_goals=[
                       "(0::nat) + 0 = 0",
                       "!n. n + 0 = n --> Suc n + 0 = Suc n"
                   ])
Esempio n. 18
0
    def testCheckProof4(self):
        """Proof of |- x = y --> x = y by instantiating an existing theorem."""
        theory.thy.add_theorem("trivial", Thm([], Implies(A,A)))

        x_eq_y = Eq(x,y)
        prf = Proof()
        prf.add_item(0, "theorem", args="trivial")
        prf.add_item(1, "substitution", args=Inst(A=x_eq_y), prevs=[0])

        rpt = ProofReport()
        th = Thm([], Implies(x_eq_y,x_eq_y))
        self.assertEqual(theory.check_proof(prf, rpt), th)
        self.assertEqual(rpt.steps, 2)
Esempio n. 19
0
File: conv.py Progetto: bzhan/holpy
    def get_proof_term(self, t):
        # If self.eq_pt is not present, produce it from thy, self.pt
        # and self.sym. Decompose into self.As and self.C.
        if self.eq_pt is None:
            if isinstance(self.pt, str):
                self.eq_pt = ProofTerm.theorem(self.pt)
            else:
                self.eq_pt = self.pt

            self.As, self.C = self.eq_pt.prop.strip_implies()

        # The conclusion of eq_pt should be an equality, and the number of
        # assumptions in eq_pt should match number of conditions.
        assert self.C.is_equals(), "rewr_conv: theorem is not an equality."
        if len(self.As) != len(self.conds):
            raise ConvException("rewr_conv: number of conds does not agree")

        inst = Inst()
        ts = [cond.prop for cond in self.conds]
        if not self.sym:
            lhs = self.C.lhs
        else:
            lhs = self.C.rhs
        try:
            inst = matcher.first_order_match_list(self.As, ts, inst)
            inst = matcher.first_order_match(lhs, t, inst)
        except matcher.MatchException:
            raise ConvException("rewr_conv: cannot match left side")

        # Check that every variable in the theorem has an instantiation
        if set(term.get_svars(self.As + [lhs])) != set(
                term.get_svars(self.As + [self.C])):
            raise ConvException("rewr_conv: unmatched vars")

        pt = self.eq_pt
        pt = pt.substitution(inst)
        pt = pt.implies_elim(*self.conds)
        if self.sym:
            pt = pt.symmetric()

        assert pt.th.is_equals(), "rewr_conv: wrong result."

        if pt.th.prop.lhs != t:
            pt = pt.on_prop(beta_norm_conv())

        if pt.th.prop.lhs != t:
            pt = pt.on_prop(eta_conv())

        assert pt.th.prop.lhs == t, "rewr_conv: wrong result. Expected %s, got %s" % (
            str(t), str(pt.th.prop.lhs))
        return pt
Esempio n. 20
0
    def testCheckProof5(self):
        """Empty instantiation."""
        theory.thy.add_theorem("trivial", Thm([], Implies(A,A)))

        x_eq_y = Eq(x,y)
        prf = Proof()
        prf.add_item(0, "theorem", args="trivial")
        prf.add_item(1, "substitution", args=Inst(), prevs=[0])

        rpt = ProofReport()
        th = Thm([], Implies(SVar('A', BoolType), SVar('A', BoolType)))
        self.assertEqual(theory.check_proof(prf, rpt), th)
        self.assertEqual(rpt.steps_stat(), (1, 1, 0))
        self.assertEqual(rpt.th_names, {"trivial"})
Esempio n. 21
0
    def get_proof_term(self, args, pts):
        if not self.with_inst:
            assert len(pts) >= 2, "apply fact: too few prevs"

        pt, pt_prevs = pts[0], pts[1:]

        # First, obtain the patterns
        new_names = get_forall_names(pt.prop)

        new_vars, As, C = strip_all_implies(pt.prop, new_names)
        assert len(pt_prevs) <= len(As), "apply_fact: too many prevs"

        if self.with_inst:
            assert len(args) == len(new_names), "apply_fact_macro: wrong number of args."
            inst = Inst({nm: v for nm, v in zip(new_names, args)})
        else:
            inst = Inst()
            for idx, pt_prev in enumerate(pt_prevs):
                inst = matcher.first_order_match(As[idx], pt_prev.prop, inst)

        pt = pt.subst_type(inst.tyinst)
        for new_var in new_vars:
            if new_var.name in inst:
                pt = pt.forall_elim(inst[new_var.name])
            else:
                pt = pt.forall_elim(new_var)
        if pt.prop.beta_norm() != pt.prop:
            pt = pt.on_prop(beta_norm_conv())
        for prev_pt in pt_prevs:
            if prev_pt.prop != pt.assums[0]:
                prev_pt = prev_pt.on_prop(beta_norm_conv())
            pt = pt.implies_elim(prev_pt)
        for new_var in new_vars:
            if new_var.name not in inst:
                pt = pt.forall_intr(new_var)

        return pt
Esempio n. 22
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
Esempio n. 23
0
File: conv.py Progetto: bzhan/holpy
def has_rewrite(th, t, *, sym=False, conds=None):
    """Returns whether a rewrite is possible on a subterm of t.
    
    This can serve as a pre-check for top_sweep_conv, top_conv, and
    bottom_conv applied to rewr_conv.

    th -- either the name of a theorem, or the theorem itself.
    t -- target of rewriting.
    conds -- optional list of theorems matching assumptions of th.

    """
    if isinstance(th, str):
        th = theory.get_theorem(th)

    if sym:
        th = Thm.symmetric(th)

    As, C = th.prop.strip_implies()

    if conds is None:
        conds = []
    if not C.is_equals() or len(As) != len(conds):
        return False

    if set(term.get_svars(As + [C.lhs])) != set(term.get_svars(As + [C])):
        return False

    ts = [cond.prop for cond in conds]
    inst = Inst()
    try:
        inst = matcher.first_order_match_list(As, ts, inst)
    except matcher.MatchException:
        return False

    def rec(t):
        if not t.is_open() and matcher.can_first_order_match(C.lhs, t, inst):
            return True

        if t.is_comb():
            return rec(t.fun) or rec(t.arg)
        elif t.is_abs():
            _, body = t.dest_abs()
            return rec(body)
        else:
            return False

    return rec(t)
Esempio n. 24
0
    def apply(self, state, id, data, prevs):
        inst = Inst()
        with context.fresh_context(vars=state.get_vars(id)):
            for key, val in data.items():
                if key.startswith("param_"):
                    if val != '':
                        inst[key[6:]] = parser.parse_term(val)

        th = theory.get_theorem(data['theorem'])

        # Check whether to ask for parameters
        As, C = th.prop.strip_implies()
        match_svars = term.get_svars(As[:len(prevs)])
        all_svars = th.prop.get_svars()
        param_svars = [
            v for v in all_svars
            if v not in match_svars and 'param_' + v.name not in data
        ]
        if param_svars:
            raise theory.ParameterQueryException(
                list("param_" + v.name for v in param_svars))

        # First test apply_theorem
        prev_ths = [state.get_proof_item(prev).th for prev in prevs]
        macro = logic.apply_theorem_macro(with_inst=True)
        res_th = macro.eval((data['theorem'], inst), prev_ths)

        state.add_line_before(id, 1)
        if inst:
            state.set_line(id,
                           'apply_theorem_for',
                           args=(data['theorem'], inst),
                           prevs=prevs)
        else:
            state.set_line(id,
                           'apply_theorem',
                           args=data['theorem'],
                           prevs=prevs)

        id2 = id.incr_id(1)
        new_id = state.find_goal(state.get_proof_item(id2).th, id2)
        if new_id is not None:
            state.replace_id(id2, new_id)
Esempio n. 25
0
File: nat.py Progetto: bzhan/holpy
def ineq_proof_term(m, n):
    """Returns the inequality m ~= n."""
    assert m != n, "ineq_proof_term: m = n"
    if n == 0:
        return ineq_zero_proof_term(m)
    elif n == 1:
        return ineq_one_proof_term(m)
    elif m == 0:
        return apply_theorem("ineq_sym", ineq_zero_proof_term(n))
    elif m == 1:
        return apply_theorem("ineq_sym", ineq_one_proof_term(n))
    elif m % 2 == 0 and n % 2 == 0:
        return apply_theorem("bit0_neq", ineq_proof_term(m // 2, n // 2))
    elif m % 2 == 1 and n % 2 == 1:
        return apply_theorem("bit1_neq", ineq_proof_term(m // 2, n // 2))
    elif m % 2 == 0 and n % 2 == 1:
        return apply_theorem("bit0_bit1_neq",
                             inst=Inst(m=Binary(m // 2), n=Binary(n // 2)))
    else:
        return apply_theorem("ineq_sym", ineq_proof_term(n, m))
Esempio n. 26
0
def apply_theorem(th_name, *pts, concl=None, inst=None):
    """Wrapper for apply_theorem and apply_theorem_for macros.

    The function takes optional arguments concl, inst. Matching
    always starts with inst. If conclusion is specified, it is
    matched next. Finally, the assumptions are matched.

    """
    typecheck.checkinstance('apply_theorem', pts, [ProofTerm])
    if concl is None and inst is None:
        # Normal case, can use apply_theorem
        return ProofTerm("apply_theorem", th_name, pts)
    else:
        pt = ProofTerm.theorem(th_name)
        if inst is None:
            inst = Inst()
        if concl is not None:
            inst = matcher.first_order_match(pt.concl, concl, inst)
        for i, prev in enumerate(pts):
            inst = matcher.first_order_match(pt.assums[i], prev.prop, inst)
        return ProofTerm("apply_theorem_for", (th_name, inst), pts)
Esempio n. 27
0
    def get_proof_term(self, goal, *, args=None, prevs=None):
        assert isinstance(prevs, list) and len(prevs) >= 1, "apply_prev"
        pt, prev_pts = prevs[0], prevs[1:]

        # First, obtain the patterns
        new_names = logic.get_forall_names(pt.prop)
        new_vars, As, C = logic.strip_all_implies(pt.prop, new_names)
        assert len(prev_pts) <= len(As), "apply_prev: too many prev_pts"

        if args is None:
            inst = Inst()
        else:
            inst = args
        inst = matcher.first_order_match(C, goal.prop, inst)
        for idx, prev_pt in enumerate(prev_pts):
            inst = matcher.first_order_match(As[idx], prev_pt.prop, inst)

        unmatched_vars = [v for v in new_names if v not in inst]
        if unmatched_vars:
            raise theory.ParameterQueryException(
                list("param_" + name for name in unmatched_vars))

        pt = pt.subst_type(inst.tyinst)
        for new_name in new_names:
            pt = pt.forall_elim(inst[new_name])
        if pt.prop.beta_norm() != pt.prop:
            pt = pt.on_prop(beta_norm_conv())
        inst_As, inst_C = pt.prop.strip_implies()

        inst_arg = [inst[new_name] for new_name in new_names]
        new_goals = [
            ProofTerm.sorry(Thm(goal.hyps, A)) for A in inst_As[len(prev_pts):]
        ]
        if set(new_names).issubset({v.name for v in term.get_vars(As)}) and \
           matcher.is_pattern_list(As, []):
            return ProofTerm('apply_fact', args=None, prevs=prevs + new_goals)
        else:
            return ProofTerm('apply_fact_for',
                             args=inst_arg,
                             prevs=prevs + new_goals)
Esempio n. 28
0
def get_bounds_proof(t, var_range):
    """Given a term t and a mapping from variables to intervals,
    return a theorem for t belonging to an interval.

    t - Term, a HOL expression.
    var_range - dict(str, Thm): mapping from variables x to theorems of
        the form x Mem [a, b] or x Mem (a, b).

    Returns a theorem of the form t Mem [a, b] or t Mem (a, b).

    """
    if t.ty == Term.VAR:
        assert t.name in var_range, "get_bounds_proof: variable %s not found" % t.name
        return var_range[t.name]

    elif t.is_number() or t == real.pi:
        return apply_theorem('const_interval', inst=Inst(x=t))

    elif t.is_plus():
        pt1 = get_bounds_proof(t.arg1, var_range)
        pt2 = get_bounds_proof(t.arg, var_range)
        if is_mem_closed(pt1) and is_mem_closed(pt2):
            pt = apply_theorem('add_interval_closed', pt1, pt2)
        elif is_mem_open(pt1) and is_mem_open(pt2):
            pt = apply_theorem('add_interval_open', pt1, pt2)
        elif is_mem_open(pt1) and is_mem_closed(pt2):
            pt = apply_theorem('add_interval_open_closed', pt1, pt2)
        elif is_mem_closed(pt1) and is_mem_open(pt2):
            pt = apply_theorem('add_interval_closed_open', pt1, pt2)
        elif is_mem_closed(pt1) and is_mem_lopen(pt2):
            pt = apply_theorem('add_interval_closed_lopen', pt1, pt2)
        elif is_mem_closed(pt1) and is_mem_ropen(pt2):
            pt = apply_theorem('add_interval_closed_ropen', pt1, pt2)
        elif is_mem_ropen(pt1) and is_mem_closed(pt2):
            pt = apply_theorem('add_interval_closed_ropen', pt2, pt1)
            pt = pt.on_prop(arg1_conv(rewr_conv('real_add_comm')))
        else:
            raise NotImplementedError('get_bounds: %s, %s' % (pt1, pt2))
        return norm_mem_interval(pt)

    elif t.is_uminus():
        pt = get_bounds_proof(t.arg, var_range)
        if is_mem_closed(pt):
            pt = apply_theorem('neg_interval_closed', pt)
        elif is_mem_open(pt):
            pt = apply_theorem('neg_interval_open', pt)
        else:
            raise NotImplementedError
        return norm_mem_interval(pt)

    elif t.is_minus():
        rewr_t = t.arg1 + (-t.arg)
        pt = get_bounds_proof(rewr_t, var_range)
        return pt.on_prop(arg1_conv(rewr_conv('real_minus_def', sym=True)))

    elif t.is_real_inverse():
        pt = get_bounds_proof(t.arg, var_range)
        a, b = get_mem_bounds(pt)
        if eval_hol_expr(a) > 0 and is_mem_closed(pt):
            pt = apply_theorem('inverse_interval_pos_closed',
                               auto.auto_solve(real_pos(a)), pt)
        else:
            raise NotImplementedError
        return norm_mem_interval(pt)

    elif t.is_times():
        if t.arg1.has_var():
            pt1 = get_bounds_proof(t.arg1, var_range)
            pt2 = get_bounds_proof(t.arg, var_range)
            a, b = get_mem_bounds(pt1)
            c, d = get_mem_bounds(pt2)
            if eval_hol_expr(a) >= 0 and eval_hol_expr(c) >= 0 and is_mem_open(
                    pt1) and is_mem_open(pt2):
                pt = apply_theorem('mult_interval_pos_pos_open',
                                   auto.auto_solve(real_nonneg(a)),
                                   auto.auto_solve(real_nonneg(c)), pt1, pt2)
            elif eval_hol_expr(a) >= 0 and eval_hol_expr(
                    c) >= 0 and is_mem_closed(pt1) and is_mem_closed(pt2):
                pt = apply_theorem('mult_interval_pos_pos_closed',
                                   auto.auto_solve(real_nonneg(a)),
                                   auto.auto_solve(real_nonneg(c)), pt1, pt2)
            elif eval_hol_expr(a) >= 0 and eval_hol_expr(
                    c) >= 0 and is_mem_lopen(pt1) and is_mem_ropen(pt2):
                pt = apply_theorem('mult_interval_pos_pos_lopen_ropen',
                                   auto.auto_solve(real_nonneg(a)),
                                   auto.auto_solve(real_nonneg(c)), pt1, pt2)
            elif eval_hol_expr(b) <= 0 and eval_hol_expr(
                    c) >= 0 and is_mem_open(pt1) and is_mem_open(pt2):
                pt = apply_theorem('mult_interval_neg_pos_open',
                                   auto.auto_solve(real_nonpos(b)),
                                   auto.auto_solve(real_nonneg(c)), pt1, pt2)
            else:
                raise NotImplementedError('get_bounds: %s, %s' % (pt1, pt2))
        else:
            pt = get_bounds_proof(t.arg, var_range)
            a, b = get_mem_bounds(pt)
            c = t.arg1
            nc = eval_hol_expr(c)
            if nc >= 0 and is_mem_closed(pt):
                pt = apply_theorem('mult_interval_pos_closed',
                                   auto.auto_solve(real_nonneg(c)), pt)
            elif nc >= 0 and is_mem_open(pt):
                pt = apply_theorem('mult_interval_pos_open',
                                   auto.auto_solve(real_nonneg(c)), pt)
            elif nc >= 0 and is_mem_lopen(pt):
                pt = apply_theorem('mult_interval_pos_lopen',
                                   auto.auto_solve(real_nonneg(c)), pt)
            elif nc >= 0 and is_mem_ropen(pt):
                pt = apply_theorem('mult_interval_pos_ropen',
                                   auto.auto_solve(real_nonneg(c)), pt)
            elif nc < 0 and is_mem_closed(pt):
                pt = apply_theorem('mult_interval_neg_closed',
                                   auto.auto_solve(real_neg(c)), pt)
            elif nc < 0 and is_mem_open(pt):
                pt = apply_theorem('mult_interval_neg_open',
                                   auto.auto_solve(real_neg(c)), pt)
            elif nc < 0 and is_mem_lopen(pt):
                pt = apply_theorem('mult_interval_neg_lopen',
                                   auto.auto_solve(real_neg(c)), pt)
            elif nc < 0 and is_mem_ropen(pt):
                pt = apply_theorem('mult_interval_neg_ropen',
                                   auto.auto_solve(real_neg(c)), pt)
            else:
                raise NotImplementedError
        return norm_mem_interval(pt)

    elif t.is_divides():
        rewr_t = t.arg1 * (real.inverse(t.arg))
        pt = get_bounds_proof(rewr_t, var_range)
        return pt.on_prop(arg1_conv(rewr_conv('real_divide_def', sym=True)))

    elif t.is_nat_power():
        pt = get_bounds_proof(t.arg1, var_range)
        if not t.arg.is_number():
            raise NotImplementedError
        return get_nat_power_bounds(pt, t.arg)

    elif t.is_real_power():
        pt = get_bounds_proof(t.arg1, var_range)
        a, b = get_mem_bounds(pt)
        if not t.arg.is_number():
            raise NotImplementedError
        p = t.arg.dest_number()
        if p >= 0 and eval_hol_expr(a) >= 0:
            nonneg_p = auto.auto_solve(real_nonneg(t.arg))
            nonneg_a = auto.auto_solve(real_nonneg(a))
            if is_mem_closed(pt):
                pt = apply_theorem('real_power_interval_pos_closed', nonneg_p,
                                   nonneg_a, pt)
            elif is_mem_open(pt):
                pt = apply_theorem('real_power_interval_pos_open', nonneg_p,
                                   nonneg_a, pt)
            else:
                raise NotImplementedError
        elif p < 0:
            neg_p = auto.auto_solve(real_neg(t.arg))
            if is_mem_closed(pt) and eval_hol_expr(a) > 0:
                pos_a = auto.auto_solve(real_pos(a))
                pt = apply_theorem('real_power_interval_neg_closed', neg_p,
                                   pos_a, pt)
            elif is_mem_open(pt):
                nonneg_a = auto.auto_solve(real_nonneg(a))
                pt = apply_theorem('real_power_interval_neg_open', neg_p,
                                   nonneg_a, pt)
            elif is_mem_lopen(pt):
                nonneg_a = auto.auto_solve(real_nonneg(a))
                pt = apply_theorem('real_power_interval_neg_lopen', neg_p,
                                   nonneg_a, pt)
            else:
                print(pt)
                raise NotImplementedError
        else:
            raise NotImplementedError
        return norm_mem_interval(pt)

    elif t.head == real.log:
        pt = get_bounds_proof(t.arg, var_range)
        a, b = get_mem_bounds(pt)
        if eval_hol_expr(a) > 0 and is_mem_closed(pt):
            pt = apply_theorem('log_interval_closed',
                               auto.auto_solve(real_pos(a)), pt)
        elif eval_hol_expr(a) >= 0 and is_mem_open(pt):
            pt = apply_theorem('log_interval_open',
                               auto.auto_solve(real_nonneg(a)), pt)
        else:
            raise NotImplementedError
        return norm_mem_interval(pt)

    elif t.head == real.exp:
        pt = get_bounds_proof(t.arg, var_range)
        if is_mem_closed(pt):
            pt = apply_theorem('exp_interval_closed', pt)
        elif is_mem_open(pt):
            pt = apply_theorem('exp_interval_open', pt)
        else:
            raise NotImplementedError
        return norm_mem_interval(pt)

    elif t.head == real.sin:
        pt = get_bounds_proof(t.arg, var_range)
        a, b = get_mem_bounds(pt)
        if eval_hol_expr(a) >= -math.pi / 2 and eval_hol_expr(
                b) <= math.pi / 2:
            if is_mem_closed(pt):
                pt = apply_theorem(
                    'sin_interval_main_closed',
                    auto.auto_solve(real.greater_eq(a, -real.pi / 2)),
                    auto.auto_solve(real.less_eq(b, real.pi / 2)), pt)
            elif is_mem_open(pt):
                pt = apply_theorem(
                    'sin_interval_main_open',
                    auto.auto_solve(real.greater_eq(a, -real.pi / 2)),
                    auto.auto_solve(real.less_eq(b, real.pi / 2)), pt)
            else:
                raise NotImplementedError
        elif eval_hol_expr(a) >= 0 and eval_hol_expr(b) <= math.pi:
            if is_mem_closed(pt):
                pt = apply_theorem('sin_interval_pos_closed',
                                   auto.auto_solve(real_nonneg(a)),
                                   auto.solve(real.less_eq(b, real.pi)), pt)
            elif is_mem_open(pt):
                pt = apply_theorem('sin_interval_pos_open',
                                   auto.auto_solve(real_nonneg(a)),
                                   auto.solve(real.less_eq(b, real.pi)), pt)
            else:
                raise NotImplementedError
        else:
            raise NotImplementedError
        return norm_mem_interval(pt)

    elif t.head == real.cos:
        pt = get_bounds_proof(t.arg, var_range)
        a, b = get_mem_bounds(pt)
        if eval_hol_expr(a) >= 0 and eval_hol_expr(b) <= math.pi:
            if is_mem_closed(pt):
                pt = apply_theorem('cos_interval_main_closed',
                                   auto.auto_solve(real_nonneg(a)),
                                   auto.auto_solve(real.less_eq(b, real.pi)),
                                   pt)
            elif is_mem_open(pt):
                pt = apply_theorem('cos_interval_main_open',
                                   auto.auto_solve(real_nonneg(a)),
                                   auto.auto_solve(real.less_eq(b, real.pi)),
                                   pt)
            else:
                raise NotImplementedError
        elif eval_hol_expr(a) >= -math.pi / 2 and eval_hol_expr(
                b) <= math.pi / 2:
            if is_mem_closed(pt):
                pt = apply_theorem(
                    'cos_interval_pos_closed',
                    auto.auto_solve(real.greater_eq(a, -real.pi / 2)),
                    auto.auto_solve(real.less_eq(b, real.pi / 2)), pt)
            elif is_mem_open(pt):
                pt = apply_theorem(
                    'cos_interval_pos_open',
                    auto.auto_solve(real.greater_eq(a, -real.pi / 2)),
                    auto.auto_solve(real.less_eq(b, real.pi / 2)), pt)
            else:
                raise NotImplementedError
        else:
            raise NotImplementedError
        return norm_mem_interval(pt)

    elif t.head == real.atn:
        pt = get_bounds_proof(t.arg, var_range)
        if is_mem_closed(pt):
            pt = apply_theorem('atn_interval_closed', pt)
        elif is_mem_open(pt):
            pt = apply_theorem('atn_interval_open', pt)
        else:
            raise NotImplementedError
        return norm_mem_interval(pt)

    else:
        print("Cannot deal with", t)
        raise NotImplementedError
Esempio n. 29
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)
Esempio n. 30
0
def nat_as_odd(n):
    """Obtain theorem of form odd n."""
    assert n % 2 == 1, "nat_as_odd: n is not odd"
    eq_pt = auto.auto_solve(Eq(nat.Suc(Nat(2) * Nat(n // 2)), Nat(n)))
    pt = apply_theorem('odd_double', inst=Inst(n=Nat(n // 2)))
    return pt.on_prop(arg_conv(rewr_conv(eq_pt)))