feat(library/relation_manager): cache information about binary relations
This commit is contained in:
parent
c2faa0fe98
commit
907d017cbf
2 changed files with 72 additions and 0 deletions
|
@ -8,8 +8,10 @@ Author: Leonardo de Moura
|
||||||
#include "util/optional.h"
|
#include "util/optional.h"
|
||||||
#include "util/name.h"
|
#include "util/name.h"
|
||||||
#include "util/rb_map.h"
|
#include "util/rb_map.h"
|
||||||
|
#include "util/sstream.h"
|
||||||
#include "library/constants.h"
|
#include "library/constants.h"
|
||||||
#include "library/scoped_ext.h"
|
#include "library/scoped_ext.h"
|
||||||
|
#include "library/relation_manager.h"
|
||||||
|
|
||||||
namespace lean {
|
namespace lean {
|
||||||
// Check whether e is of the form (f ...) where f is a constant. If it is return f.
|
// Check whether e is of the form (f ...) where f is a constant. If it is return f.
|
||||||
|
@ -48,12 +50,49 @@ struct rel_state {
|
||||||
typedef name_map<std::tuple<name, unsigned, unsigned>> subst_table;
|
typedef name_map<std::tuple<name, unsigned, unsigned>> subst_table;
|
||||||
typedef name_map<std::tuple<name, unsigned, unsigned>> symm_table;
|
typedef name_map<std::tuple<name, unsigned, unsigned>> symm_table;
|
||||||
typedef rb_map<name_pair, std::tuple<name, name, unsigned>, name_pair_quick_cmp> trans_table;
|
typedef rb_map<name_pair, std::tuple<name, name, unsigned>, name_pair_quick_cmp> trans_table;
|
||||||
|
typedef name_map<relation_info> rop_table;
|
||||||
trans_table m_trans_table;
|
trans_table m_trans_table;
|
||||||
refl_table m_refl_table;
|
refl_table m_refl_table;
|
||||||
subst_table m_subst_table;
|
subst_table m_subst_table;
|
||||||
symm_table m_symm_table;
|
symm_table m_symm_table;
|
||||||
|
rop_table m_rop_table;
|
||||||
rel_state() {}
|
rel_state() {}
|
||||||
|
|
||||||
|
bool is_equivalence(name const & rop) const {
|
||||||
|
return m_trans_table.contains(mk_pair(rop, rop)) && m_refl_table.contains(rop) && m_symm_table.contains(rop);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void throw_invalid_relation(name const & rop) {
|
||||||
|
throw exception(sstream() << "invalid binary relation declaration, relation '" << rop
|
||||||
|
<< "' must have two explicit parameters");
|
||||||
|
}
|
||||||
|
|
||||||
|
void register_rop(environment const & env, name const & rop) {
|
||||||
|
if (m_rop_table.contains(rop))
|
||||||
|
return;
|
||||||
|
declaration const & d = env.get(rop);
|
||||||
|
optional<unsigned> lhs_pos;
|
||||||
|
optional<unsigned> rhs_pos;
|
||||||
|
unsigned i = 0;
|
||||||
|
expr type = d.get_type();
|
||||||
|
while (is_pi(type)) {
|
||||||
|
if (is_explicit(binding_info(type))) {
|
||||||
|
if (!lhs_pos)
|
||||||
|
lhs_pos = i;
|
||||||
|
else if (!rhs_pos)
|
||||||
|
rhs_pos = i;
|
||||||
|
else
|
||||||
|
throw_invalid_relation(rop);
|
||||||
|
}
|
||||||
|
type = binding_body(type);
|
||||||
|
}
|
||||||
|
if (lhs_pos && rhs_pos) {
|
||||||
|
m_rop_table.insert(rop, relation_info(i, *lhs_pos, *rhs_pos));
|
||||||
|
} else {
|
||||||
|
throw_invalid_relation(rop);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void add_subst(environment const & env, name const & subst) {
|
void add_subst(environment const & env, name const & subst) {
|
||||||
buffer<expr> arg_types;
|
buffer<expr> arg_types;
|
||||||
auto p = extract_arg_types_core(env, subst, arg_types);
|
auto p = extract_arg_types_core(env, subst, arg_types);
|
||||||
|
@ -75,6 +114,7 @@ struct rel_state {
|
||||||
if (nargs < 1)
|
if (nargs < 1)
|
||||||
throw exception("invalid reflexivity rule, it must have at least 1 argument");
|
throw exception("invalid reflexivity rule, it must have at least 1 argument");
|
||||||
name const & rop = get_fn_const(r_type, "invalid reflexivity rule, result type must be an operator application");
|
name const & rop = get_fn_const(r_type, "invalid reflexivity rule, result type must be an operator application");
|
||||||
|
register_rop(env, rop);
|
||||||
m_refl_table.insert(rop, std::make_tuple(refl, nargs, nunivs));
|
m_refl_table.insert(rop, std::make_tuple(refl, nargs, nunivs));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,6 +127,7 @@ struct rel_state {
|
||||||
name const & rop = get_fn_const(r_type, "invalid transitivity rule, result type must be an operator application");
|
name const & rop = get_fn_const(r_type, "invalid transitivity rule, result type must be an operator application");
|
||||||
name const & op1 = get_fn_const(arg_types[nargs-2], "invalid transitivity rule, penultimate argument must be an operator application");
|
name const & op1 = get_fn_const(arg_types[nargs-2], "invalid transitivity rule, penultimate argument must be an operator application");
|
||||||
name const & op2 = get_fn_const(arg_types[nargs-1], "invalid transitivity rule, last argument must be an operator application");
|
name const & op2 = get_fn_const(arg_types[nargs-1], "invalid transitivity rule, last argument must be an operator application");
|
||||||
|
register_rop(env, rop);
|
||||||
m_trans_table.insert(name_pair(op1, op2), std::make_tuple(trans, rop, nargs));
|
m_trans_table.insert(name_pair(op1, op2), std::make_tuple(trans, rop, nargs));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,6 +140,7 @@ struct rel_state {
|
||||||
if (nargs < 1)
|
if (nargs < 1)
|
||||||
throw exception("invalid symmetry rule, it must have at least 1 argument");
|
throw exception("invalid symmetry rule, it must have at least 1 argument");
|
||||||
name const & rop = get_fn_const(r_type, "invalid symmetry rule, result type must be an operator application");
|
name const & rop = get_fn_const(r_type, "invalid symmetry rule, result type must be an operator application");
|
||||||
|
register_rop(env, rop);
|
||||||
m_symm_table.insert(rop, std::make_tuple(symm, nargs, nunivs));
|
m_symm_table.insert(rop, std::make_tuple(symm, nargs, nunivs));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -204,6 +246,14 @@ optional<name> get_trans_info(environment const & env, name const & op) {
|
||||||
return optional<name>();
|
return optional<name>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool is_equivalence(environment const & env, name const & rop) {
|
||||||
|
return rel_ext::get_state(env).is_equivalence(rop);
|
||||||
|
}
|
||||||
|
|
||||||
|
relation_info const * get_relation_info(environment const & env, name const & rop) {
|
||||||
|
return rel_ext::get_state(env).m_rop_table.find(rop);
|
||||||
|
}
|
||||||
|
|
||||||
void initialize_relation_manager() {
|
void initialize_relation_manager() {
|
||||||
g_rel_name = new name("rel");
|
g_rel_name = new name("rel");
|
||||||
g_key = new std::string("rel");
|
g_key = new std::string("rel");
|
||||||
|
|
|
@ -8,6 +8,28 @@ Author: Leonardo de Moura
|
||||||
#include "kernel/environment.h"
|
#include "kernel/environment.h"
|
||||||
|
|
||||||
namespace lean {
|
namespace lean {
|
||||||
|
struct relation_info {
|
||||||
|
unsigned m_arity;
|
||||||
|
unsigned m_lhs_pos;
|
||||||
|
unsigned m_rhs_pos;
|
||||||
|
public:
|
||||||
|
relation_info() {}
|
||||||
|
relation_info(unsigned arity, unsigned lhs, unsigned rhs):
|
||||||
|
m_arity(arity), m_lhs_pos(lhs), m_rhs_pos(rhs) {
|
||||||
|
lean_assert(m_lhs_pos < m_arity);
|
||||||
|
lean_assert(m_rhs_pos < m_arity);
|
||||||
|
}
|
||||||
|
unsigned get_arity() const { return m_arity; }
|
||||||
|
unsigned get_lhs_pos() const { return m_lhs_pos; }
|
||||||
|
unsigned get_rhs_pos() const { return m_rhs_pos; }
|
||||||
|
};
|
||||||
|
|
||||||
|
/** \brief Return true if \c rop is a registered equivalence relation in the given manager */
|
||||||
|
bool is_equivalence(environment const & env, name const & rop);
|
||||||
|
|
||||||
|
/** \brief If \c rop is a registered relation, then return a non-null pointer to the associated information */
|
||||||
|
relation_info const * get_relation_info(environment const & env, name const & rop);
|
||||||
|
|
||||||
environment add_subst(environment const & env, name const & n, bool persistent = true);
|
environment add_subst(environment const & env, name const & n, bool persistent = true);
|
||||||
environment add_refl(environment const & env, name const & n, bool persistent = true);
|
environment add_refl(environment const & env, name const & n, bool persistent = true);
|
||||||
environment add_symm(environment const & env, name const & n, bool persistent = true);
|
environment add_symm(environment const & env, name const & n, bool persistent = true);
|
||||||
|
|
Loading…
Reference in a new issue