feat(library/norm_num): use type_context

This commit is contained in:
Daniel Selsam 2015-11-16 14:09:34 -08:00
parent 770ca546be
commit 550cac6065
5 changed files with 69 additions and 38 deletions

View file

@ -18,6 +18,7 @@
#include "library/simplifier/ceqv.h" #include "library/simplifier/ceqv.h"
#include "library/app_builder.h" #include "library/app_builder.h"
#include "library/num.h" #include "library/num.h"
#include "library/norm_num.h"
#include "util/flet.h" #include "util/flet.h"
#include "util/pair.h" #include "util/pair.h"
#include "util/sexpr/option_declarations.h" #include "util/sexpr/option_declarations.h"
@ -48,6 +49,9 @@
#ifndef LEAN_DEFAULT_SIMPLIFY_FUSE #ifndef LEAN_DEFAULT_SIMPLIFY_FUSE
#define LEAN_DEFAULT_SIMPLIFY_FUSE false #define LEAN_DEFAULT_SIMPLIFY_FUSE false
#endif #endif
#ifndef LEAN_DEFAULT_SIMPLIFY_NUMERALS
#define LEAN_DEFAULT_SIMPLIFY_NUMERALS true
#endif
namespace lean { namespace lean {
namespace blast { namespace blast {
@ -71,6 +75,7 @@ static name * g_simplify_contextual = nullptr;
static name * g_simplify_expand_macros = nullptr; static name * g_simplify_expand_macros = nullptr;
static name * g_simplify_trace = nullptr; static name * g_simplify_trace = nullptr;
static name * g_simplify_fuse = nullptr; static name * g_simplify_fuse = nullptr;
static name * g_simplify_numerals = nullptr;
unsigned get_simplify_max_steps() { unsigned get_simplify_max_steps() {
return ios().get_options().get_unsigned(*g_simplify_max_steps, LEAN_DEFAULT_SIMPLIFY_MAX_STEPS); return ios().get_options().get_unsigned(*g_simplify_max_steps, LEAN_DEFAULT_SIMPLIFY_MAX_STEPS);
@ -104,6 +109,10 @@ bool get_simplify_fuse() {
return ios().get_options().get_bool(*g_simplify_fuse, LEAN_DEFAULT_SIMPLIFY_FUSE); return ios().get_options().get_bool(*g_simplify_fuse, LEAN_DEFAULT_SIMPLIFY_FUSE);
} }
bool get_simplify_numerals() {
return ios().get_options().get_bool(*g_simplify_numerals, LEAN_DEFAULT_SIMPLIFY_NUMERALS);
}
/* Miscellaneous helpers */ /* Miscellaneous helpers */
static bool is_add_app(expr const & e) { static bool is_add_app(expr const & e) {
@ -141,6 +150,7 @@ class simplifier {
bool m_expand_macros{get_simplify_expand_macros()}; bool m_expand_macros{get_simplify_expand_macros()};
bool m_trace{get_simplify_trace()}; bool m_trace{get_simplify_trace()};
bool m_fuse{get_simplify_fuse()}; bool m_fuse{get_simplify_fuse()};
bool m_numerals{get_simplify_numerals()};
/* Cache */ /* Cache */
struct key { struct key {
@ -205,6 +215,7 @@ class simplifier {
result simplify_pi(expr const & e); result simplify_pi(expr const & e);
result simplify_app(expr const & e); result simplify_app(expr const & e);
result simplify_fun(expr const & e); result simplify_fun(expr const & e);
optional<result> simplify_numeral(expr const & e);
/* Proving */ /* Proving */
optional<expr> prove(expr const & thm); optional<expr> prove(expr const & thm);
@ -364,6 +375,11 @@ result simplifier::simplify(expr const & e, bool is_root) {
if (auto it = cache_lookup(e)) return *it; if (auto it = cache_lookup(e)) return *it;
} }
if (m_numerals) {
// TODO(dhs): cache these?
if (auto r = simplify_numeral(e)) return *r;
}
result r(e); result r(e);
if (m_top_down) r = join(r, rewrite(whnf(r.get_new()))); if (m_top_down) r = join(r, rewrite(whnf(r.get_new())));
@ -501,6 +517,22 @@ result simplifier::simplify_fun(expr const & e) {
return congr_funs(r_f, args); return congr_funs(r_f, args);
} }
optional<result> simplifier::simplify_numeral(expr const & e) {
if (is_num(e)) {
return optional<result>(result(e));
}
else if (is_add_app(e) || is_mul_app(e)) {
buffer<expr> args;
get_app_args(e, args);
if (is_num(args[2]) && is_num(args[3])){
expr_pair r = mk_norm_num(*m_tmp_tctx, e);
return optional<result>(result(r.first, r.second));
}
}
// TODO(dhs): simplify division and substraction as well
return optional<result>();
}
/* Proving */ /* Proving */
optional<expr> simplifier::prove(expr const & thm) { optional<expr> simplifier::prove(expr const & thm) {
@ -984,6 +1016,7 @@ void initialize_simplifier() {
g_simplify_expand_macros = new name{"simplify", "expand_macros"}; g_simplify_expand_macros = new name{"simplify", "expand_macros"};
g_simplify_trace = new name{"simplify", "trace"}; g_simplify_trace = new name{"simplify", "trace"};
g_simplify_fuse = new name{"simplify", "fuse"}; g_simplify_fuse = new name{"simplify", "fuse"};
g_simplify_numerals = new name{"simplify", "numerals"};
register_unsigned_option(*g_simplify_max_steps, LEAN_DEFAULT_SIMPLIFY_MAX_STEPS, register_unsigned_option(*g_simplify_max_steps, LEAN_DEFAULT_SIMPLIFY_MAX_STEPS,
"(simplify) max allowed steps in simplification"); "(simplify) max allowed steps in simplification");
@ -1001,9 +1034,12 @@ void initialize_simplifier() {
"(simplify) trace"); "(simplify) trace");
register_bool_option(*g_simplify_fuse, LEAN_DEFAULT_SIMPLIFY_FUSE, register_bool_option(*g_simplify_fuse, LEAN_DEFAULT_SIMPLIFY_FUSE,
"(simplify) fuse addition in distrib structures"); "(simplify) fuse addition in distrib structures");
register_bool_option(*g_simplify_numerals, LEAN_DEFAULT_SIMPLIFY_NUMERALS,
"(simplify) simplify (+, *, -, /) over numerals");
} }
void finalize_simplifier() { void finalize_simplifier() {
delete g_simplify_numerals;
delete g_simplify_fuse; delete g_simplify_fuse;
delete g_simplify_trace; delete g_simplify_trace;
delete g_simplify_expand_macros; delete g_simplify_expand_macros;

View file

@ -126,7 +126,7 @@ expr norm_num_context::mk_has_add(expr const & e) {
return instances[l_name]; return instances[l_name];
} }
expr t = mk_app(mk_constant(l_name, m_lvls), e); expr t = mk_app(mk_constant(l_name, m_lvls), e);
optional<expr> inst = mk_class_instance(m_env, m_ctx, t); optional<expr> inst = m_type_ctx.mk_class_instance(t);
if (inst) { if (inst) {
instances[l_name] = *inst; instances[l_name] = *inst;
return *inst; return *inst;
@ -141,7 +141,7 @@ expr norm_num_context::mk_has_mul(expr const & e) {
return instances[l_name]; return instances[l_name];
} }
expr t = mk_app(mk_constant(l_name, m_lvls), e); expr t = mk_app(mk_constant(l_name, m_lvls), e);
optional<expr> inst = mk_class_instance(m_env, m_ctx, t); optional<expr> inst = m_type_ctx.mk_class_instance(t);
if (inst) { if (inst) {
instances[l_name] = *inst; instances[l_name] = *inst;
return *inst; return *inst;
@ -156,7 +156,7 @@ expr norm_num_context::mk_has_one(expr const & e) {
return instances[l_name]; return instances[l_name];
} }
expr t = mk_app(mk_constant(l_name, m_lvls), e); expr t = mk_app(mk_constant(l_name, m_lvls), e);
optional<expr> inst = mk_class_instance(m_env, m_ctx, t); optional<expr> inst = m_type_ctx.mk_class_instance(t);
if (inst) { if (inst) {
instances[l_name] = *inst; instances[l_name] = *inst;
return *inst; return *inst;
@ -171,7 +171,7 @@ expr norm_num_context::mk_has_zero(expr const & e) {
return instances[l_name]; return instances[l_name];
} }
expr t = mk_app(mk_constant(l_name, m_lvls), e); expr t = mk_app(mk_constant(l_name, m_lvls), e);
optional<expr> inst = mk_class_instance(m_env, m_ctx, t); optional<expr> inst = m_type_ctx.mk_class_instance(t);
if (inst) { if (inst) {
instances[l_name] = *inst; instances[l_name] = *inst;
return *inst; return *inst;
@ -186,7 +186,7 @@ expr norm_num_context::mk_add_monoid(expr const & e) {
return instances[l_name]; return instances[l_name];
} }
expr t = mk_app(mk_constant(l_name, m_lvls), e); expr t = mk_app(mk_constant(l_name, m_lvls), e);
optional<expr> inst = mk_class_instance(m_env, m_ctx, t); optional<expr> inst = m_type_ctx.mk_class_instance(t);
if (inst) { if (inst) {
instances[l_name] = *inst; instances[l_name] = *inst;
return *inst; return *inst;
@ -201,7 +201,7 @@ expr norm_num_context::mk_monoid(expr const & e) {
return instances[l_name]; return instances[l_name];
} }
expr t = mk_app(mk_constant(l_name, m_lvls), e); expr t = mk_app(mk_constant(l_name, m_lvls), e);
optional<expr> inst = mk_class_instance(m_env, m_ctx, t); optional<expr> inst = m_type_ctx.mk_class_instance(t);
if (inst) { if (inst) {
instances[l_name] = *inst; instances[l_name] = *inst;
return *inst; return *inst;
@ -212,7 +212,7 @@ expr norm_num_context::mk_monoid(expr const & e) {
expr norm_num_context::mk_field(expr const & e) { expr norm_num_context::mk_field(expr const & e) {
expr t = mk_app(mk_constant(*g_field, m_lvls), e); expr t = mk_app(mk_constant(*g_field, m_lvls), e);
optional<expr> inst = mk_class_instance(m_env, m_ctx, t); optional<expr> inst = m_type_ctx.mk_class_instance(t);
if (inst) { if (inst) {
return *inst; return *inst;
} else { } else {
@ -226,7 +226,7 @@ expr norm_num_context::mk_add_comm(expr const & e) {
return instances[l_name]; return instances[l_name];
} }
expr t = mk_app(mk_constant(l_name, m_lvls), e); expr t = mk_app(mk_constant(l_name, m_lvls), e);
optional<expr> inst = mk_class_instance(m_env, m_ctx, t); optional<expr> inst = m_type_ctx.mk_class_instance(t);
if (inst) { if (inst) {
instances[l_name] = *inst; instances[l_name] = *inst;
return *inst; return *inst;
@ -241,7 +241,7 @@ expr norm_num_context::mk_add_group(expr const & e) {
return instances[l_name]; return instances[l_name];
} }
expr t = mk_app(mk_constant(l_name, m_lvls), e); expr t = mk_app(mk_constant(l_name, m_lvls), e);
optional<expr> inst = mk_class_instance(m_env, m_ctx, t); optional<expr> inst = m_type_ctx.mk_class_instance(t);
if (inst) { if (inst) {
instances[l_name] = *inst; instances[l_name] = *inst;
return *inst; return *inst;
@ -256,7 +256,7 @@ expr norm_num_context::mk_has_distrib(expr const & e) {
return instances[l_name]; return instances[l_name];
} }
expr t = mk_app(mk_constant(l_name, m_lvls), e); expr t = mk_app(mk_constant(l_name, m_lvls), e);
optional<expr> inst = mk_class_instance(m_env, m_ctx, t); optional<expr> inst = m_type_ctx.mk_class_instance(t);
if (inst) { if (inst) {
instances[l_name] = *inst; instances[l_name] = *inst;
return *inst; return *inst;
@ -271,7 +271,7 @@ expr norm_num_context::mk_mul_zero_class(expr const & e) {
return instances[l_name]; return instances[l_name];
} }
expr t = mk_app(mk_constant(l_name, m_lvls), e); expr t = mk_app(mk_constant(l_name, m_lvls), e);
optional<expr> inst = mk_class_instance(m_env, m_ctx, t); optional<expr> inst = m_type_ctx.mk_class_instance(t);
if (inst) { if (inst) {
instances[l_name] = *inst; instances[l_name] = *inst;
return *inst; return *inst;
@ -286,7 +286,7 @@ expr norm_num_context::mk_semiring(expr const & e) {
return instances[l_name]; return instances[l_name];
} }
expr t = mk_app(mk_constant(l_name, m_lvls), e); expr t = mk_app(mk_constant(l_name, m_lvls), e);
optional<expr> inst = mk_class_instance(m_env, m_ctx, t); optional<expr> inst = m_type_ctx.mk_class_instance(t);
if (inst) { if (inst) {
instances[l_name] = *inst; instances[l_name] = *inst;
return *inst; return *inst;
@ -301,7 +301,7 @@ expr norm_num_context::mk_has_neg(expr const & e) {
return instances[l_name]; return instances[l_name];
} }
expr t = mk_app(mk_constant(l_name, m_lvls), e); expr t = mk_app(mk_constant(l_name, m_lvls), e);
optional<expr> inst = mk_class_instance(m_env, m_ctx, t); optional<expr> inst = m_type_ctx.mk_class_instance(t);
if (inst) { if (inst) {
instances[l_name] = *inst; instances[l_name] = *inst;
return *inst; return *inst;
@ -316,7 +316,7 @@ expr norm_num_context::mk_has_sub(expr const & e) {
return instances[l_name]; return instances[l_name];
} }
expr t = mk_app(mk_constant(l_name, m_lvls), e); expr t = mk_app(mk_constant(l_name, m_lvls), e);
optional<expr> inst = mk_class_instance(m_env, m_ctx, t); optional<expr> inst = m_type_ctx.mk_class_instance(t);
if (inst) { if (inst) {
instances[l_name] = *inst; instances[l_name] = *inst;
return *inst; return *inst;
@ -331,7 +331,7 @@ expr norm_num_context::mk_has_div(expr const & e) {
return instances[l_name]; return instances[l_name];
} }
expr t = mk_app(mk_constant(l_name, m_lvls), e); expr t = mk_app(mk_constant(l_name, m_lvls), e);
optional<expr> inst = mk_class_instance(m_env, m_ctx, t); optional<expr> inst = m_type_ctx.mk_class_instance(t);
if (inst) { if (inst) {
instances[l_name] = *inst; instances[l_name] = *inst;
return *inst; return *inst;
@ -346,7 +346,7 @@ expr norm_num_context::mk_add_comm_group(expr const & e) {
return instances[l_name]; return instances[l_name];
} }
expr t = mk_app(mk_constant(l_name, m_lvls), e); expr t = mk_app(mk_constant(l_name, m_lvls), e);
optional<expr> inst = mk_class_instance(m_env, m_ctx, t); optional<expr> inst = m_type_ctx.mk_class_instance(t);
if (inst) { if (inst) {
instances[l_name] = *inst; instances[l_name] = *inst;
return *inst; return *inst;
@ -361,7 +361,7 @@ expr norm_num_context::mk_ring(expr const & e) {
return instances[l_name]; return instances[l_name];
} }
expr t = mk_app(mk_constant(l_name, m_lvls), e); expr t = mk_app(mk_constant(l_name, m_lvls), e);
optional<expr> inst = mk_class_instance(m_env, m_ctx, t); optional<expr> inst = m_type_ctx.mk_class_instance(t);
if (inst) { if (inst) {
instances[l_name] = *inst; instances[l_name] = *inst;
return *inst; return *inst;
@ -376,7 +376,7 @@ expr norm_num_context::mk_lin_ord_ring(expr const & e) {
return instances[l_name]; return instances[l_name];
} }
expr t = mk_app(mk_constant(l_name, m_lvls), e); expr t = mk_app(mk_constant(l_name, m_lvls), e);
optional<expr> inst = mk_class_instance(m_env, m_ctx, t); optional<expr> inst = m_type_ctx.mk_class_instance(t);
if (inst) { if (inst) {
instances[l_name] = *inst; instances[l_name] = *inst;
return *inst; return *inst;
@ -391,7 +391,7 @@ expr norm_num_context::mk_lin_ord_semiring(expr const & e) {
return instances[l_name]; return instances[l_name];
} }
expr t = mk_app(mk_constant(l_name, m_lvls), e); expr t = mk_app(mk_constant(l_name, m_lvls), e);
optional<expr> inst = mk_class_instance(m_env, m_ctx, t); optional<expr> inst = m_type_ctx.mk_class_instance(t);
if (inst) { if (inst) {
instances[l_name] = *inst; instances[l_name] = *inst;
return *inst; return *inst;
@ -406,7 +406,7 @@ expr norm_num_context::mk_wk_order(expr const & e) {
return instances[l_name]; return instances[l_name];
} }
expr t = mk_app(mk_constant(l_name, m_lvls), e); expr t = mk_app(mk_constant(l_name, m_lvls), e);
optional<expr> inst = mk_class_instance(m_env, m_ctx, t); optional<expr> inst = m_type_ctx.mk_class_instance(t);
if (inst) { if (inst) {
instances[l_name] = *inst; instances[l_name] = *inst;
return *inst; return *inst;

View file

@ -5,7 +5,7 @@ Author: Robert Y. Lewis
*/ */
#pragma once #pragma once
#include "kernel/environment.h" #include "kernel/environment.h"
#include "library/local_context.h" #include "library/type_context.h"
#include "library/num.h" #include "library/num.h"
#include "library/class_instance_resolution.h" #include "library/class_instance_resolution.h"
#include "util/numerics/mpq.h" #include "util/numerics/mpq.h"
@ -21,8 +21,7 @@ struct hash_name {
}; };
class norm_num_context { class norm_num_context {
environment m_env; type_context & m_type_ctx;
local_context m_ctx;
levels m_lvls; levels m_lvls;
pair<expr, expr> mk_norm_add(expr const &, expr const &); pair<expr, expr> mk_norm_add(expr const &, expr const &);
pair<expr, expr> mk_norm_add1(expr const &); pair<expr, expr> mk_norm_add1(expr const &);
@ -72,7 +71,7 @@ class norm_num_context {
std::unordered_map<name, expr, hash_name> instances; std::unordered_map<name, expr, hash_name> instances;
public: public:
norm_num_context(environment const & env, local_context const & ctx):m_env(env), m_ctx(ctx) {} norm_num_context(type_context & type_ctx): m_type_ctx(type_ctx) {}
bool is_numeral(expr const & e) const; bool is_numeral(expr const & e) const;
bool is_neg_app(expr const &) const; bool is_neg_app(expr const &) const;
@ -89,20 +88,20 @@ public:
inline bool is_neg(expr const & e); inline bool is_neg(expr const & e);
inline bool is_numeral(environment const & env, expr const & e) { inline bool is_numeral(type_context & type_ctx, expr const & e) {
return norm_num_context(env, local_context()).is_numeral(e); return norm_num_context(type_ctx).is_numeral(e);
} }
inline pair<expr, expr> mk_norm_num(environment const & env, local_context const & ctx, expr const & e) { inline pair<expr, expr> mk_norm_num(type_context & type_ctx, expr const & e) {
return norm_num_context(env, ctx).mk_norm(e); return norm_num_context(type_ctx).mk_norm(e);
} }
inline mpz num_of_expr(environment const & env, local_context const & ctx, expr const & e) { inline mpz num_of_expr(type_context & type_ctx, expr const & e) {
return norm_num_context(env, ctx).num_of_expr(e); return norm_num_context(type_ctx).num_of_expr(e);
} }
inline mpq mpq_of_expr(environment const & env, local_context const & ctx, expr const & e) { inline mpq mpq_of_expr(type_context & type_ctx, expr const & e) {
return norm_num_context(env, ctx).mpq_of_expr(e); return norm_num_context(type_ctx).mpq_of_expr(e);
} }
void initialize_norm_num(); void initialize_norm_num();

View file

@ -6,5 +6,4 @@ expr_to_tactic.cpp location.cpp rewrite_tactic.cpp util.cpp
init_module.cpp change_tactic.cpp check_expr_tactic.cpp let_tactic.cpp init_module.cpp change_tactic.cpp check_expr_tactic.cpp let_tactic.cpp
contradiction_tactic.cpp exfalso_tactic.cpp constructor_tactic.cpp contradiction_tactic.cpp exfalso_tactic.cpp constructor_tactic.cpp
injection_tactic.cpp congruence_tactic.cpp relation_tactics.cpp injection_tactic.cpp congruence_tactic.cpp relation_tactics.cpp
induction_tactic.cpp subst_tactic.cpp unfold_rec.cpp with_options_tactic.cpp induction_tactic.cpp subst_tactic.cpp unfold_rec.cpp with_options_tactic.cpp)
norm_num_tactic.cpp)

View file

@ -32,7 +32,6 @@ Author: Leonardo de Moura
#include "library/tactic/subst_tactic.h" #include "library/tactic/subst_tactic.h"
#include "library/tactic/location.h" #include "library/tactic/location.h"
#include "library/tactic/with_options_tactic.h" #include "library/tactic/with_options_tactic.h"
#include "library/tactic/norm_num_tactic.h"
namespace lean { namespace lean {
void initialize_tactic_module() { void initialize_tactic_module() {
@ -63,11 +62,9 @@ void initialize_tactic_module() {
initialize_subst_tactic(); initialize_subst_tactic();
initialize_location(); initialize_location();
initialize_with_options_tactic(); initialize_with_options_tactic();
initialize_norm_num_tactic();
} }
void finalize_tactic_module() { void finalize_tactic_module() {
finalize_norm_num_tactic();
finalize_with_options_tactic(); finalize_with_options_tactic();
finalize_location(); finalize_location();
finalize_subst_tactic(); finalize_subst_tactic();