feat(library/congr_lemma_manager): add new kind of congr_arg
This commit is contained in:
parent
67d49aabd9
commit
d0fe59ef8a
4 changed files with 55 additions and 16 deletions
|
@ -192,6 +192,7 @@ static optional<ext_congr_lemma> to_ext_congr_lemma(name const & R, expr const &
|
||||||
Rcs.resize(lhs_args.size(), optional<name>());
|
Rcs.resize(lhs_args.size(), optional<name>());
|
||||||
r_hyps.resize(lhs_args.size(), none_expr());
|
r_hyps.resize(lhs_args.size(), none_expr());
|
||||||
// Set Fixed args
|
// Set Fixed args
|
||||||
|
// TODO(Leo): handle FixedNoParam case?
|
||||||
for (unsigned i = 0; i < lhs_args.size(); i++) {
|
for (unsigned i = 0; i < lhs_args.size(); i++) {
|
||||||
if (lhs_args[i] == rhs_args[i])
|
if (lhs_args[i] == rhs_args[i])
|
||||||
kinds[i] = congr_arg_kind::Fixed;
|
kinds[i] = congr_arg_kind::Fixed;
|
||||||
|
@ -241,6 +242,9 @@ static optional<ext_congr_lemma> to_ext_congr_lemma(name const & R, expr const &
|
||||||
return optional<ext_congr_lemma>();
|
return optional<ext_congr_lemma>();
|
||||||
}
|
}
|
||||||
switch (kinds[i]) {
|
switch (kinds[i]) {
|
||||||
|
case congr_arg_kind::FixedNoParam:
|
||||||
|
// TODO(Leo): revise this code
|
||||||
|
break;
|
||||||
case congr_arg_kind::Fixed:
|
case congr_arg_kind::Fixed:
|
||||||
break;
|
break;
|
||||||
case congr_arg_kind::Eq: {
|
case congr_arg_kind::Eq: {
|
||||||
|
@ -431,6 +435,7 @@ int congruence_closure::congr_key_cmp::operator()(congr_key const & k1, congr_ke
|
||||||
if (r != 0) return r;
|
if (r != 0) return r;
|
||||||
break;
|
break;
|
||||||
case congr_arg_kind::Fixed:
|
case congr_arg_kind::Fixed:
|
||||||
|
case congr_arg_kind::FixedNoParam:
|
||||||
r = expr_quick_cmp()(args1[i], args2[i]);
|
r = expr_quick_cmp()(args1[i], args2[i]);
|
||||||
if (r != 0) return r;
|
if (r != 0) return r;
|
||||||
break;
|
break;
|
||||||
|
@ -491,6 +496,7 @@ auto congruence_closure::mk_congr_key(ext_congr_lemma const & lemma, expr const
|
||||||
h = hash(h, get_root(*head(*it1), args[i]).hash());
|
h = hash(h, get_root(*head(*it1), args[i]).hash());
|
||||||
break;
|
break;
|
||||||
case congr_arg_kind::Fixed:
|
case congr_arg_kind::Fixed:
|
||||||
|
case congr_arg_kind::FixedNoParam:
|
||||||
h = hash(h, args[i].hash());
|
h = hash(h, args[i].hash());
|
||||||
break;
|
break;
|
||||||
case congr_arg_kind::Cast:
|
case congr_arg_kind::Cast:
|
||||||
|
@ -967,6 +973,8 @@ expr congruence_closure::mk_congr_proof_core(name const & R, expr const & lhs, e
|
||||||
case congr_arg_kind::Fixed:
|
case congr_arg_kind::Fixed:
|
||||||
lemma_args.push_back(lhs_args[i]);
|
lemma_args.push_back(lhs_args[i]);
|
||||||
break;
|
break;
|
||||||
|
case congr_arg_kind::FixedNoParam:
|
||||||
|
break;
|
||||||
case congr_arg_kind::Cast:
|
case congr_arg_kind::Cast:
|
||||||
lemma_args.push_back(lhs_args[i]);
|
lemma_args.push_back(lhs_args[i]);
|
||||||
lemma_args.push_back(rhs_args[i]);
|
lemma_args.push_back(rhs_args[i]);
|
||||||
|
|
|
@ -277,22 +277,26 @@ optional<result> simplifier::cache_lookup(expr const & e) {
|
||||||
|
|
||||||
unsigned i = 0;
|
unsigned i = 0;
|
||||||
for_each(congr_lemma->get_arg_kinds(), [&](congr_arg_kind const & ckind) {
|
for_each(congr_lemma->get_arg_kinds(), [&](congr_arg_kind const & ckind) {
|
||||||
if (ckind != congr_arg_kind::Cast) {
|
lean_assert(ckind == congr_arg_kind::Cast || new_args[i] == old_args[i]);
|
||||||
lean_assert(new_args[i] == old_args[i]);
|
|
||||||
}
|
|
||||||
proof = mk_app(proof, new_args[i]);
|
|
||||||
type = instantiate(binding_body(type), new_args[i]);
|
|
||||||
expr rfl;
|
expr rfl;
|
||||||
switch (ckind) {
|
switch (ckind) {
|
||||||
case congr_arg_kind::Fixed:
|
case congr_arg_kind::Fixed:
|
||||||
|
proof = mk_app(proof, new_args[i]);
|
||||||
|
type = instantiate(binding_body(type), new_args[i]);
|
||||||
|
break;
|
||||||
|
case congr_arg_kind::FixedNoParam:
|
||||||
break;
|
break;
|
||||||
case congr_arg_kind::Eq:
|
case congr_arg_kind::Eq:
|
||||||
|
proof = mk_app(proof, new_args[i]);
|
||||||
|
type = instantiate(binding_body(type), new_args[i]);
|
||||||
rfl = get_app_builder().mk_eq_refl(old_args[i]);
|
rfl = get_app_builder().mk_eq_refl(old_args[i]);
|
||||||
proof = mk_app(proof, old_args[i], rfl);
|
proof = mk_app(proof, old_args[i], rfl);
|
||||||
type = instantiate(binding_body(type), old_args[i]);
|
type = instantiate(binding_body(type), old_args[i]);
|
||||||
type = instantiate(binding_body(type), rfl);
|
type = instantiate(binding_body(type), rfl);
|
||||||
break;
|
break;
|
||||||
case congr_arg_kind::Cast:
|
case congr_arg_kind::Cast:
|
||||||
|
proof = mk_app(proof, new_args[i]);
|
||||||
|
type = instantiate(binding_body(type), new_args[i]);
|
||||||
proof = mk_app(proof, old_args[i]);
|
proof = mk_app(proof, old_args[i]);
|
||||||
type = instantiate(binding_body(type), old_args[i]);
|
type = instantiate(binding_body(type), old_args[i]);
|
||||||
break;
|
break;
|
||||||
|
@ -807,17 +811,30 @@ optional<result> simplifier::synth_congr(expr const & e, F && simp) {
|
||||||
bool has_cast = false;
|
bool has_cast = false;
|
||||||
buffer<expr> locals;
|
buffer<expr> locals;
|
||||||
for_each(congr_lemma->get_arg_kinds(), [&](congr_arg_kind const & ckind) {
|
for_each(congr_lemma->get_arg_kinds(), [&](congr_arg_kind const & ckind) {
|
||||||
|
switch (ckind) {
|
||||||
|
case congr_arg_kind::Fixed:
|
||||||
proof = mk_app(proof, args[i]);
|
proof = mk_app(proof, args[i]);
|
||||||
type = instantiate(binding_body(type), args[i]);
|
type = instantiate(binding_body(type), args[i]);
|
||||||
if (ckind == congr_arg_kind::Eq) {
|
break;
|
||||||
|
case congr_arg_kind::FixedNoParam:
|
||||||
|
break;
|
||||||
|
case congr_arg_kind::Eq:
|
||||||
|
proof = mk_app(proof, args[i]);
|
||||||
|
type = instantiate(binding_body(type), args[i]);
|
||||||
|
{
|
||||||
result r_arg = simp(args[i]);
|
result r_arg = simp(args[i]);
|
||||||
if (r_arg.has_proof()) has_proof = true;
|
if (r_arg.has_proof()) has_proof = true;
|
||||||
r_arg = finalize(r_arg);
|
r_arg = finalize(r_arg);
|
||||||
proof = mk_app(proof, r_arg.get_new(), r_arg.get_proof());
|
proof = mk_app(proof, r_arg.get_new(), r_arg.get_proof());
|
||||||
type = instantiate(binding_body(type), r_arg.get_new());
|
type = instantiate(binding_body(type), r_arg.get_new());
|
||||||
type = instantiate(binding_body(type), r_arg.get_proof());
|
type = instantiate(binding_body(type), r_arg.get_proof());
|
||||||
} else if (ckind == congr_arg_kind::Cast) {
|
}
|
||||||
|
break;
|
||||||
|
case congr_arg_kind::Cast:
|
||||||
|
proof = mk_app(proof, args[i]);
|
||||||
|
type = instantiate(binding_body(type), args[i]);
|
||||||
has_cast = true;
|
has_cast = true;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
i++;
|
i++;
|
||||||
});
|
});
|
||||||
|
|
|
@ -199,6 +199,9 @@ struct congr_lemma_manager::imp {
|
||||||
rhss.push_back(lhs);
|
rhss.push_back(lhs);
|
||||||
eqs.push_back(none_expr());
|
eqs.push_back(none_expr());
|
||||||
break;
|
break;
|
||||||
|
case congr_arg_kind::FixedNoParam:
|
||||||
|
lean_unreachable(); // TODO(Leo): not implemented yet
|
||||||
|
break;
|
||||||
case congr_arg_kind::Cast: {
|
case congr_arg_kind::Cast: {
|
||||||
expr rhs_type = mlocal_type(lhs);
|
expr rhs_type = mlocal_type(lhs);
|
||||||
rhs_type = instantiate_rev(abstract_locals(rhs_type, lhss.size()-1, lhss.data()), rhss.size(), rhss.data());
|
rhs_type = instantiate_rev(abstract_locals(rhs_type, lhss.size()-1, lhss.data()), rhss.size(), rhss.data());
|
||||||
|
@ -274,6 +277,9 @@ struct congr_lemma_manager::imp {
|
||||||
rhss.push_back(rhs);
|
rhss.push_back(rhs);
|
||||||
eqs.push_back(none_expr());
|
eqs.push_back(none_expr());
|
||||||
break;
|
break;
|
||||||
|
case congr_arg_kind::FixedNoParam:
|
||||||
|
lean_unreachable(); // TODO(Leo): not implemented yet
|
||||||
|
break;
|
||||||
case congr_arg_kind::Cast: {
|
case congr_arg_kind::Cast: {
|
||||||
rhs = m_ctx.mk_tmp_local(binding_name(fn_type2), binding_domain(fn_type2));
|
rhs = m_ctx.mk_tmp_local(binding_name(fn_type2), binding_domain(fn_type2));
|
||||||
rhss.push_back(rhs);
|
rhss.push_back(rhs);
|
||||||
|
|
|
@ -10,7 +10,15 @@ Author: Leonardo de Moura
|
||||||
#include "library/fun_info_manager.h"
|
#include "library/fun_info_manager.h"
|
||||||
|
|
||||||
namespace lean {
|
namespace lean {
|
||||||
enum class congr_arg_kind { Fixed, Eq, Cast };
|
enum class congr_arg_kind {
|
||||||
|
Fixed, /* It is a parameter for the congruence lemma, the parit occurs in the left and right hand sides. */
|
||||||
|
FixedNoParam, /* It is not a parameter for the congruence lemma, the lemma was specialized for this parameter.
|
||||||
|
This only happens if the parameter is a subsingleton/proposition, and other parameters depend on it. */
|
||||||
|
Eq, /* The lemma contains three parameters for this kind of argument a_i, b_i and (eq_i : a_i = b_i).
|
||||||
|
a_i and b_i represent the left and right hand sides, and eq_i is a proof for their equality. */
|
||||||
|
Cast /* congr-simp lemma contains only one parameter for this kind of argument, and congr-lemmas contains two.
|
||||||
|
They correspond to arguments that are subsingletons/propositions. */
|
||||||
|
};
|
||||||
|
|
||||||
class congr_lemma {
|
class congr_lemma {
|
||||||
expr m_type;
|
expr m_type;
|
||||||
|
|
Loading…
Reference in a new issue