Exemplo n.º 1
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)
Exemplo n.º 2
0
Arquivo: conv.py Projeto: 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
Exemplo n.º 3
0
Arquivo: conv.py Projeto: 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)
Exemplo n.º 4
0
def is_pattern_list(ts, matched_vars, bd_vars=None):
    """Test whether a list of ts can be matched."""
    if len(ts) == 0:
        return True
    elif len(ts) == 1:
        return is_pattern(ts[0], matched_vars, bd_vars)
    else:
        if is_pattern(ts[0], matched_vars):
            all_vars = list(
                set(matched_vars + [v.name for v in ts[0].get_svars()]))
            return is_pattern_list(ts[1:], all_vars, bd_vars)
        else:
            if not is_pattern_list(ts[1:], matched_vars, bd_vars):
                return False
            all_vars = list(
                set(matched_vars + [v.name for v in term.get_svars(ts[1:])]))
            return is_pattern(ts[0], all_vars, bd_vars)
Exemplo n.º 5
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)