Пример #1
0
action_result assert_cc_action(hypothesis_idx hidx) {
    if (!get_config().m_cc)
        return action_result::failed();
    congruence_closure & cc = get_cc();
    if (has_expr_metavar(curr_state().get_hypothesis_decl(hidx).get_type()))
        return action_result::failed();
    cc.add(hidx);
    // cc.display();
    if (cc.is_inconsistent()) {
        try {
            app_builder & b  = get_app_builder();
            expr false_proof = *cc.get_inconsistency_proof();
            trace_action("contradiction by congruence closure");
            return action_result(b.mk_false_rec(curr_state().get_target(), false_proof));
        } catch (app_builder_exception &) {
            return action_result::failed();
        }
    } else {
        expr const & target = curr_state().get_target();
        name R; expr lhs, rhs;
        if (is_relation_app(target, R, lhs, rhs) && cc.is_eqv(R, lhs, rhs)) {
            expr proof = *cc.get_eqv_proof(R, lhs, rhs);
            trace_action("equivalence by congruence closure");
            return action_result(proof);
        } else if (is_prop(target) && !is_false(target) && cc.proved(target)) {
            expr proof = *cc.get_proof(target);
            trace_action("equivalent to true by congruence closure");
            return action_result(proof);
        } else {
            return action_result::new_branch();
        }
    }
}
 virtual action_result resolve(expr const & pr) const override {
     try {
         expr it   = pr;
         bool skip = true;
         for (unsigned i = 0; i < m_num_new_eqs; i++) {
             if (!is_lambda(it)) {
                 break;
                 skip = false;
             }
             it = binding_body(it);
         }
         if (skip && closed(it)) {
             // new eq hypotheses were not used
             return action_result::solved(it);
         }
         state & s = curr_state();
         app_builder & b = get_app_builder();
         hypothesis const & h = s.get_hypothesis_decl(href_index(m_eq_href));
         expr type = h.get_type();
         expr lhs, rhs;
         lean_verify(is_eq(type, lhs, rhs));
         name nc_name(m_I_name, "no_confusion");
         expr new_pr = mk_app(b.mk_app(nc_name, {m_target, lhs, rhs, m_eq_href}), pr);
         return action_result::solved(new_pr);
     } catch (app_builder_exception &) {
         return action_result::failed();
     }
 }
action_result no_confusion_action(hypothesis_idx hidx) {
    try {
        state & s       = curr_state();
        app_builder & b = get_app_builder();
        hypothesis const & h = s.get_hypothesis_decl(hidx);
        expr type = h.get_type();
        expr lhs, rhs;
        if (!is_eq(type, lhs, rhs))
            return action_result::failed();
        lhs = whnf(lhs);
        rhs = whnf(rhs);
        optional<name> c1 = is_constructor_app(env(), lhs);
        optional<name> c2 = is_constructor_app(env(), rhs);
        if (!c1 || !c2)
            return action_result::failed();
        expr A = whnf(infer_type(lhs));
        expr I = get_app_fn(A);
        if (!is_constant(I) || !inductive::is_inductive_decl(env(), const_name(I)))
            return action_result::failed();
        name nct_name(const_name(I), "no_confusion_type");
        if (!env().find(nct_name))
            return action_result::failed();
        expr target  = s.get_target();
        expr nct     = whnf(b.mk_app(nct_name, target, lhs, rhs));
        if (c1 == c2) {
            if (!is_pi(nct))
                return action_result::failed();
            if (s.has_target_forward_deps(hidx)) {
                // TODO(Leo): we currently do not handle this case.
                // To avoid non-termination we remove the given hypothesis, if there
                // forward dependencies, we would also have to remove them.
                // Remark: this is a low priority refinement since it will not happen
                // very often in practice.
                return action_result::failed();
            }
            unsigned num_params  = *inductive::get_num_params(env(), const_name(I));
            unsigned cnstr_arity = get_arity(env().get(*c1).get_type());
            lean_assert(cnstr_arity >= num_params);
            unsigned num_new_eqs = cnstr_arity - num_params;
            s.push_proof_step(new no_confusion_proof_step_cell(const_name(I), target, h.get_self(), num_new_eqs));
            s.set_target(binding_domain(nct));
            s.del_hypothesis(hidx);
            trace_action("no_confusion");
            return action_result::new_branch();
        } else {
            name nc_name(const_name(I), "no_confusion");
            expr pr = b.mk_app(nc_name, {target, lhs, rhs, h.get_self()});
            trace_action("no_confusion");
            return action_result::solved(pr);
        }
    } catch (app_builder_exception &) {
        return action_result::failed();
    }
}
action_result by_contradiction_action() {
    state &  s  = curr_state();
    expr target = whnf(s.get_target());
    if (!is_prop(target)) return action_result::failed();
    if (blast::is_false(target)) return action_result::failed();
    expr not_target;
    if (is_not(target, not_target)) {
        s.set_target(mk_arrow(not_target, mk_constant(get_false_name())));
        return intros_action(1);
    }
    blast_tmp_type_context tmp_tctx;
    optional<expr> target_decidable = tmp_tctx->mk_class_instance(mk_app(mk_constant(get_decidable_name()), target));
    if (!target_decidable) return action_result::failed();
    expr href = s.mk_hypothesis(get_app_builder().mk_not(target));
    auto pcell = new by_contradiction_proof_step_cell(href);
    s.push_proof_step(pcell);
    s.set_target(mk_constant(get_false_name()));
    trace_action("by_contradiction");
    return action_result::new_branch();
}
Пример #5
0
result simplifier::finalize(result const & r) {
    if (r.has_proof()) return r;
    expr pf = get_app_builder().mk_refl(m_rel, r.get_new());
    return result(r.get_new(), pf);
}