feat(kernel/inductive): use nondependent elimination when the datatype is in Bool/Prop

Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
This commit is contained in:
Leonardo de Moura 2014-05-18 15:39:48 -07:00
parent 45252e2229
commit 28b70b4e04
2 changed files with 45 additions and 12 deletions

View file

@ -34,6 +34,7 @@ struct add_inductive_fn {
type_checker m_tc; type_checker m_tc;
level m_elim_level; // extra universe level for eliminator. level m_elim_level; // extra universe level for eliminator.
bool m_dep_elim; // true if using dependent elimination
buffer<expr> m_param_consts; // local constants used to represent global parameters buffer<expr> m_param_consts; // local constants used to represent global parameters
buffer<level> m_it_levels; // the levels for each inductive datatype in m_decls buffer<level> m_it_levels; // the levels for each inductive datatype in m_decls
@ -300,6 +301,14 @@ struct add_inductive_fn {
} }
} }
/** \brief Initialize m_dep_elim flag */
void set_dep_elim() {
if (m_env.impredicative() && is_zero(m_it_levels[0]))
m_dep_elim = false;
else
m_dep_elim = true;
}
/** /**
\brief Given t of the form (I As is) where I is one of the inductive datatypes being defined, \brief Given t of the form (I As is) where I is one of the inductive datatypes being defined,
As are the global parameters, and is the actual indices provided to it. As are the global parameters, and is the actual indices provided to it.
@ -334,10 +343,14 @@ struct add_inductive_fn {
i++; i++;
} }
info.m_major_premise = mk_local(mk_fresh_name(), "n", mk_app(mk_app(m_it_consts[d_idx], m_param_consts), info.m_indices)); info.m_major_premise = mk_local(mk_fresh_name(), "n", mk_app(mk_app(m_it_consts[d_idx], m_param_consts), info.m_indices));
name C("C"); expr C_ty = mk_sort(m_elim_level);
if (m_dep_elim)
C_ty = Pi(info.m_major_premise, C_ty);
C_ty = Pi(info.m_indices, C_ty);
name C_name("C");
if (get_num_its() > 1) if (get_num_its() > 1)
C = name(C).append_after(d_idx+1); C_name = name(C_name).append_after(d_idx+1);
info.m_C = mk_local(mk_fresh_name(), C, Pi(info.m_indices, Pi(info.m_major_premise, mk_sort(m_elim_level)))); info.m_C = mk_local(mk_fresh_name(), C_name, C_ty);
m_elim_info.push_back(info); m_elim_info.push_back(info);
d_idx++; d_idx++;
} }
@ -366,8 +379,11 @@ struct add_inductive_fn {
} }
buffer<expr> it_indices; buffer<expr> it_indices;
unsigned it_idx = get_I_indices(t, it_indices); unsigned it_idx = get_I_indices(t, it_indices);
expr intro_app = mk_app(mk_app(mk_app(mk_constant(intro_rule_name(ir), m_levels), m_param_consts), b), u); expr C_app = mk_app(m_elim_info[it_idx].m_C, it_indices);
expr C_app = mk_app(mk_app(m_elim_info[it_idx].m_C, it_indices), intro_app); if (m_dep_elim) {
expr intro_app = mk_app(mk_app(mk_app(mk_constant(intro_rule_name(ir), m_levels), m_param_consts), b), u);
C_app = mk_app(C_app, intro_app);
}
// populate v using u // populate v using u
for (unsigned i = 0; i < u.size(); i++) { for (unsigned i = 0; i < u.size(); i++) {
expr u_i = u[i]; expr u_i = u[i];
@ -380,8 +396,11 @@ struct add_inductive_fn {
} }
buffer<expr> it_indices; buffer<expr> it_indices;
unsigned it_idx = get_I_indices(u_i_ty, it_indices); unsigned it_idx = get_I_indices(u_i_ty, it_indices);
expr u_app = mk_app(u_i, xs); expr C_app = mk_app(m_elim_info[it_idx].m_C, it_indices);
expr C_app = mk_app(mk_app(m_elim_info[it_idx].m_C, it_indices), u_app); if (m_dep_elim) {
expr u_app = mk_app(u_i, xs);
C_app = mk_app(C_app, u_app);
}
expr v_i_ty = Pi(xs, C_app); expr v_i_ty = Pi(xs, C_app);
expr v_i = mk_local(mk_fresh_name(), name("v").append_after(i), v_i_ty); expr v_i = mk_local(mk_fresh_name(), name("v").append_after(i), v_i_ty);
v.push_back(v_i); v.push_back(v_i);
@ -398,7 +417,9 @@ struct add_inductive_fn {
/** \brief Declare elimination rule */ /** \brief Declare elimination rule */
void declare_elim_rule(inductive_decl const & d, unsigned d_idx) { void declare_elim_rule(inductive_decl const & d, unsigned d_idx) {
elim_info const & info = m_elim_info[d_idx]; elim_info const & info = m_elim_info[d_idx];
expr C_app = mk_app(mk_app(info.m_C, info.m_indices), info.m_major_premise); expr C_app = mk_app(info.m_C, info.m_indices);
if (m_dep_elim)
C_app = mk_app(C_app, info.m_major_premise);
expr elim_ty = Pi(info.m_indices, Pi(info.m_major_premise, C_app)); expr elim_ty = Pi(info.m_indices, Pi(info.m_major_premise, C_app));
// abstract all introduction rules // abstract all introduction rules
unsigned i = get_num_its(); unsigned i = get_num_its();
@ -428,6 +449,7 @@ struct add_inductive_fn {
/** \brief Declare the eliminator/recursor for each datatype */ /** \brief Declare the eliminator/recursor for each datatype */
void declare_elim_rules() { void declare_elim_rules() {
set_dep_elim();
mk_elim_level(); mk_elim_level();
mk_elim_info(); mk_elim_info();
unsigned i = 0; unsigned i = 0;

View file

@ -29,7 +29,7 @@ env = add_inductive(env,
-- 1 is the number of parameters. -- 1 is the number of parameters.
-- The Boolean true in {A, U_l, true} is marking that this argument is implicit. -- The Boolean true in {A, U_l, true} is marking that this argument is implicit.
env = add_inductive(env, env = add_inductive(env,
"list", {l}, 1, mk_arrow(U_l, U_l1), "list", {l}, 1, Pi(A, U_l, U_l1),
"nil", Pi({{A, U_l, true}}, list_l(A)), "nil", Pi({{A, U_l, true}}, list_l(A)),
"cons", Pi({{A, U_l, true}}, mk_arrow(A, list_l(A), list_l(A)))) "cons", Pi({{A, U_l, true}}, mk_arrow(A, list_l(A), list_l(A))))
env = add_inductive(env, env = add_inductive(env,
@ -46,17 +46,17 @@ env = add_inductive(env, "false", Bool)
-- Datatype with a single constructor. -- Datatype with a single constructor.
env = add_inductive(env, "true", Bool, "trivial", Const("true")) env = add_inductive(env, "true", Bool, "trivial", Const("true"))
env = add_inductive(env, env = add_inductive(env,
"and", mk_arrow(Bool, Bool, Bool), "and", 2, Pi({{A, Bool}, {B, Bool}}, Bool),
"and_intro", Pi({{A, Bool, true}, {B, Bool, true}}, mk_arrow(A, B, And(A, B)))) "and_intro", Pi({{A, Bool, true}, {B, Bool, true}}, mk_arrow(A, B, And(A, B))))
env = add_inductive(env, env = add_inductive(env,
"or", mk_arrow(Bool, Bool, Bool), "or", 2, Pi({{A, Bool}, {B, Bool}}, Bool),
"or_intro_left", Pi({{A, Bool, true}, {B, Bool, true}}, mk_arrow(A, Or(A, B))), "or_intro_left", Pi({{A, Bool, true}, {B, Bool, true}}, mk_arrow(A, Or(A, B))),
"or_intro_right", Pi({{A, Bool, true}, {B, Bool, true}}, mk_arrow(B, Or(A, B)))) "or_intro_right", Pi({{A, Bool, true}, {B, Bool, true}}, mk_arrow(B, Or(A, B))))
local P = Const("P") local P = Const("P")
local a = Const("a") local a = Const("a")
local exists_l = Const("exists", {l}) local exists_l = Const("exists", {l})
env = add_inductive(env, env = add_inductive(env,
"exists", {l}, 2, Pi({{A, U_l}}, mk_arrow(mk_arrow(A, Bool), Bool)), "exists", {l}, 2, Pi({{A, U_l}, {P, mk_arrow(A, Bool)}}, Bool),
"exists_intro", Pi({{A, U_l, true}, {P, mk_arrow(A, Bool), true}, {a, A}}, mk_arrow(P(a), exists_l(A, P)))) "exists_intro", Pi({{A, U_l, true}, {P, mk_arrow(A, Bool), true}, {a, A}}, mk_arrow(P(a), exists_l(A, P))))
env = add_inductive(env, {l}, 1, env = add_inductive(env, {l}, 1,
@ -73,6 +73,7 @@ display_type(env, Const("vcons", {mk_level_zero()}))
display_type(env, Const("consf", {mk_level_zero()})) display_type(env, Const("consf", {mk_level_zero()}))
display_type(env, Const("forest_rec", {v, u})) display_type(env, Const("forest_rec", {v, u}))
display_type(env, Const("nat_rec", {v})) display_type(env, Const("nat_rec", {v}))
display_type(env, Const("or_rec"))
local Even = Const("Even") local Even = Const("Even")
local Odd = Const("Odd") local Odd = Const("Odd")
@ -89,3 +90,13 @@ env = add_inductive(env,
"flist", {l}, 1, mk_arrow(U_l, U_l1), "flist", {l}, 1, mk_arrow(U_l, U_l1),
"fnil", Pi({{A, U_l, true}}, flist_l(A)), "fnil", Pi({{A, U_l, true}}, flist_l(A)),
"fcons", Pi({{A, U_l, true}}, mk_arrow(A, mk_arrow(Nat, flist_l(A)), flist_l(A)))) "fcons", Pi({{A, U_l, true}}, mk_arrow(A, mk_arrow(Nat, flist_l(A)), flist_l(A))))
local eq_l = Const("eq", {l})
env = add_inductive(env,
"eq", {l}, 2, Pi({{A, U_l}, {a, A}, {b, A}}, Bool),
"refl", Pi({{A, U_l}, {a, A}}, eq_l(A, a, a)))
display_type(env, Const("eq_rec", {v, u}))
display_type(env, Const("exists_rec", {v, u}))
display_type(env, Const("list_rec", {v, u}))
display_type(env, Const("Even_rec"))
display_type(env, Const("Odd_rec"))