fix(library/expr_lt): make sure the builtin order is AC-compatible
Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
This commit is contained in:
parent
b2cb49fa1f
commit
0d5e346143
7 changed files with 51 additions and 31 deletions
|
@ -26,6 +26,20 @@ Author: Leonardo de Moura
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace lean {
|
namespace lean {
|
||||||
|
unsigned add_weight(unsigned w1, unsigned w2) {
|
||||||
|
unsigned r = w1 + w2;
|
||||||
|
if (r < w1)
|
||||||
|
r = std::numeric_limits<unsigned>::max(); // overflow
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned inc_weight(unsigned w) {
|
||||||
|
if (w < std::numeric_limits<unsigned>::max())
|
||||||
|
return w+1;
|
||||||
|
else
|
||||||
|
return w;
|
||||||
|
}
|
||||||
|
|
||||||
static expr g_dummy(mk_var(0));
|
static expr g_dummy(mk_var(0));
|
||||||
expr::expr():expr(g_dummy) {}
|
expr::expr():expr(g_dummy) {}
|
||||||
|
|
||||||
|
@ -150,9 +164,9 @@ void expr_local::dealloc(buffer<expr_cell*> & todelete) {
|
||||||
|
|
||||||
// Composite expressions
|
// Composite expressions
|
||||||
expr_composite::expr_composite(expr_kind k, unsigned h, bool has_expr_mv, bool has_univ_mv,
|
expr_composite::expr_composite(expr_kind k, unsigned h, bool has_expr_mv, bool has_univ_mv,
|
||||||
bool has_local, bool has_param_univ, unsigned d, unsigned fv_range):
|
bool has_local, bool has_param_univ, unsigned w, unsigned fv_range):
|
||||||
expr_cell(k, h, has_expr_mv, has_univ_mv, has_local, has_param_univ),
|
expr_cell(k, h, has_expr_mv, has_univ_mv, has_local, has_param_univ),
|
||||||
m_depth(d),
|
m_weight(w),
|
||||||
m_free_var_range(fv_range) {}
|
m_free_var_range(fv_range) {}
|
||||||
|
|
||||||
// Expr applications
|
// Expr applications
|
||||||
|
@ -164,10 +178,10 @@ expr_app::expr_app(expr const & fn, expr const & arg):
|
||||||
fn.has_univ_metavar() || arg.has_univ_metavar(),
|
fn.has_univ_metavar() || arg.has_univ_metavar(),
|
||||||
fn.has_local() || arg.has_local(),
|
fn.has_local() || arg.has_local(),
|
||||||
fn.has_param_univ() || arg.has_param_univ(),
|
fn.has_param_univ() || arg.has_param_univ(),
|
||||||
std::max(get_depth(fn), get_depth(arg)) + 1,
|
inc_weight(add_weight(get_weight(fn), get_weight(arg))),
|
||||||
std::max(get_free_var_range(fn), get_free_var_range(arg))),
|
std::max(get_free_var_range(fn), get_free_var_range(arg))),
|
||||||
m_fn(fn), m_arg(arg) {
|
m_fn(fn), m_arg(arg) {
|
||||||
m_hash = ::lean::hash(m_hash, m_depth);
|
m_hash = ::lean::hash(m_hash, m_weight);
|
||||||
}
|
}
|
||||||
void expr_app::dealloc(buffer<expr_cell*> & todelete) {
|
void expr_app::dealloc(buffer<expr_cell*> & todelete) {
|
||||||
dec_ref(m_fn, todelete);
|
dec_ref(m_fn, todelete);
|
||||||
|
@ -195,11 +209,11 @@ expr_binding::expr_binding(expr_kind k, name const & n, expr const & t, expr con
|
||||||
t.has_univ_metavar() || b.has_univ_metavar(),
|
t.has_univ_metavar() || b.has_univ_metavar(),
|
||||||
t.has_local() || b.has_local(),
|
t.has_local() || b.has_local(),
|
||||||
t.has_param_univ() || b.has_param_univ(),
|
t.has_param_univ() || b.has_param_univ(),
|
||||||
std::max(get_depth(t), get_depth(b)) + 1,
|
inc_weight(add_weight(get_weight(t), get_weight(b))),
|
||||||
std::max(get_free_var_range(t), dec(get_free_var_range(b)))),
|
std::max(get_free_var_range(t), dec(get_free_var_range(b)))),
|
||||||
m_binder(n, t, i),
|
m_binder(n, t, i),
|
||||||
m_body(b) {
|
m_body(b) {
|
||||||
m_hash = ::lean::hash(m_hash, m_depth);
|
m_hash = ::lean::hash(m_hash, m_weight);
|
||||||
lean_assert(k == expr_kind::Lambda || k == expr_kind::Pi);
|
lean_assert(k == expr_kind::Lambda || k == expr_kind::Pi);
|
||||||
}
|
}
|
||||||
void expr_binding::dealloc(buffer<expr_cell*> & todelete) {
|
void expr_binding::dealloc(buffer<expr_cell*> & todelete) {
|
||||||
|
@ -245,13 +259,10 @@ bool macro_definition::operator<(macro_definition const & other) const {
|
||||||
return get_name() < other.get_name();
|
return get_name() < other.get_name();
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned max_depth(unsigned num, expr const * args) {
|
static unsigned add_weight(unsigned num, expr const * args) {
|
||||||
unsigned r = 0;
|
unsigned r = 0;
|
||||||
for (unsigned i = 0; i < num; i++) {
|
for (unsigned i = 0; i < num; i++)
|
||||||
unsigned d = get_depth(args[i]);
|
r = add_weight(r, get_weight(args[i]));
|
||||||
if (d > r)
|
|
||||||
r = d;
|
|
||||||
}
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -272,7 +283,7 @@ expr_macro::expr_macro(macro_definition const & m, unsigned num, expr const * ar
|
||||||
std::any_of(args, args+num, [](expr const & e) { return e.has_univ_metavar(); }),
|
std::any_of(args, args+num, [](expr const & e) { return e.has_univ_metavar(); }),
|
||||||
std::any_of(args, args+num, [](expr const & e) { return e.has_local(); }),
|
std::any_of(args, args+num, [](expr const & e) { return e.has_local(); }),
|
||||||
std::any_of(args, args+num, [](expr const & e) { return e.has_param_univ(); }),
|
std::any_of(args, args+num, [](expr const & e) { return e.has_param_univ(); }),
|
||||||
max_depth(num, args) + 1,
|
inc_weight(add_weight(num, args)),
|
||||||
get_free_var_range(num, args)),
|
get_free_var_range(num, args)),
|
||||||
m_definition(m),
|
m_definition(m),
|
||||||
m_num_args(num) {
|
m_num_args(num) {
|
||||||
|
@ -471,14 +482,14 @@ expr mk_Type() {
|
||||||
expr Prop = mk_Prop();
|
expr Prop = mk_Prop();
|
||||||
expr Type = mk_Type();
|
expr Type = mk_Type();
|
||||||
|
|
||||||
unsigned get_depth(expr const & e) {
|
unsigned get_weight(expr const & e) {
|
||||||
switch (e.kind()) {
|
switch (e.kind()) {
|
||||||
case expr_kind::Var: case expr_kind::Constant: case expr_kind::Sort:
|
case expr_kind::Var: case expr_kind::Constant: case expr_kind::Sort:
|
||||||
case expr_kind::Meta: case expr_kind::Local:
|
case expr_kind::Meta: case expr_kind::Local:
|
||||||
return 1;
|
return 1;
|
||||||
case expr_kind::Lambda: case expr_kind::Pi: case expr_kind::Macro:
|
case expr_kind::Lambda: case expr_kind::Pi: case expr_kind::Macro:
|
||||||
case expr_kind::App:
|
case expr_kind::App:
|
||||||
return static_cast<expr_composite*>(e.raw())->m_depth;
|
return static_cast<expr_composite*>(e.raw())->m_weight;
|
||||||
}
|
}
|
||||||
lean_unreachable(); // LCOV_EXCL_LINE
|
lean_unreachable(); // LCOV_EXCL_LINE
|
||||||
}
|
}
|
||||||
|
|
|
@ -200,13 +200,13 @@ public:
|
||||||
/** \brief Composite expressions */
|
/** \brief Composite expressions */
|
||||||
class expr_composite : public expr_cell {
|
class expr_composite : public expr_cell {
|
||||||
protected:
|
protected:
|
||||||
unsigned m_depth;
|
unsigned m_weight;
|
||||||
unsigned m_free_var_range;
|
unsigned m_free_var_range;
|
||||||
friend unsigned get_depth(expr const & e);
|
friend unsigned get_weight(expr const & e);
|
||||||
friend unsigned get_free_var_range(expr const & e);
|
friend unsigned get_free_var_range(expr const & e);
|
||||||
public:
|
public:
|
||||||
expr_composite(expr_kind k, unsigned h, bool has_expr_mv, bool has_univ_mv, bool has_local,
|
expr_composite(expr_kind k, unsigned h, bool has_expr_mv, bool has_univ_mv, bool has_local,
|
||||||
bool has_param_univ, unsigned d, unsigned fv_range);
|
bool has_param_univ, unsigned w, unsigned fv_range);
|
||||||
};
|
};
|
||||||
|
|
||||||
/** \brief Metavariables and local constants */
|
/** \brief Metavariables and local constants */
|
||||||
|
@ -589,7 +589,7 @@ inline bool has_univ_metavar(expr const & e) { return e.has_univ_metavar(); }
|
||||||
bool has_expr_metavar_strict(expr const & e);
|
bool has_expr_metavar_strict(expr const & e);
|
||||||
inline bool has_local(expr const & e) { return e.has_local(); }
|
inline bool has_local(expr const & e) { return e.has_local(); }
|
||||||
inline bool has_param_univ(expr const & e) { return e.has_param_univ(); }
|
inline bool has_param_univ(expr const & e) { return e.has_param_univ(); }
|
||||||
unsigned get_depth(expr const & e);
|
unsigned get_weight(expr const & e);
|
||||||
/**
|
/**
|
||||||
\brief Return \c R s.t. the de Bruijn index of all free variables
|
\brief Return \c R s.t. the de Bruijn index of all free variables
|
||||||
occurring in \c e is in the interval <tt>[0, R)</tt>.
|
occurring in \c e is in the interval <tt>[0, R)</tt>.
|
||||||
|
|
|
@ -10,10 +10,10 @@ Author: Leonardo de Moura
|
||||||
namespace lean {
|
namespace lean {
|
||||||
bool is_lt(expr const & a, expr const & b, bool use_hash) {
|
bool is_lt(expr const & a, expr const & b, bool use_hash) {
|
||||||
if (is_eqp(a, b)) return false;
|
if (is_eqp(a, b)) return false;
|
||||||
unsigned da = get_depth(a);
|
unsigned wa = get_weight(a);
|
||||||
unsigned db = get_depth(b);
|
unsigned wb = get_weight(b);
|
||||||
if (da < db) return true;
|
if (wa < wb) return true;
|
||||||
if (da > db) return false;
|
if (wa > wb) return false;
|
||||||
if (a.kind() != b.kind()) return a.kind() < b.kind();
|
if (a.kind() != b.kind()) return a.kind() < b.kind();
|
||||||
if (use_hash) {
|
if (use_hash) {
|
||||||
if (a.hash() < b.hash()) return true;
|
if (a.hash() < b.hash()) return true;
|
||||||
|
|
|
@ -581,8 +581,8 @@ static int binding_info(lua_State * L) { return push_binder_info(L, binding_info
|
||||||
|
|
||||||
static int expr_occurs(lua_State * L) { return push_boolean(L, occurs(to_expr(L, 1), to_expr(L, 2))); }
|
static int expr_occurs(lua_State * L) { return push_boolean(L, occurs(to_expr(L, 1), to_expr(L, 2))); }
|
||||||
static int expr_is_eqp(lua_State * L) { return push_boolean(L, is_eqp(to_expr(L, 1), to_expr(L, 2))); }
|
static int expr_is_eqp(lua_State * L) { return push_boolean(L, is_eqp(to_expr(L, 1), to_expr(L, 2))); }
|
||||||
static int expr_hash(lua_State * L) { return push_integer(L, to_expr(L, 1).hash()); }
|
static int expr_hash(lua_State * L) { return push_integer(L, to_expr(L, 1).hash()); }
|
||||||
static int expr_depth(lua_State * L) { return push_integer(L, get_depth(to_expr(L, 1))); }
|
static int expr_weight(lua_State * L) { return push_integer(L, get_weight(to_expr(L, 1))); }
|
||||||
static int expr_is_lt(lua_State * L) {
|
static int expr_is_lt(lua_State * L) {
|
||||||
int nargs = lua_gettop(L);
|
int nargs = lua_gettop(L);
|
||||||
return push_boolean(L, is_lt(to_expr(L, 1), to_expr(L, 2), nargs == 3 && lua_toboolean(L, 3)));
|
return push_boolean(L, is_lt(to_expr(L, 1), to_expr(L, 2), nargs == 3 && lua_toboolean(L, 3)));
|
||||||
|
@ -630,7 +630,7 @@ static const struct luaL_Reg expr_m[] = {
|
||||||
{"fn", safe_function<expr_fn>},
|
{"fn", safe_function<expr_fn>},
|
||||||
{"fields", safe_function<expr_fields>},
|
{"fields", safe_function<expr_fields>},
|
||||||
{"data", safe_function<expr_fields>},
|
{"data", safe_function<expr_fields>},
|
||||||
{"depth", safe_function<expr_depth>},
|
{"weight", safe_function<expr_weight>},
|
||||||
{"binding_name", safe_function<binding_name>},
|
{"binding_name", safe_function<binding_name>},
|
||||||
{"binding_domain", safe_function<binding_domain>},
|
{"binding_domain", safe_function<binding_domain>},
|
||||||
{"binding_body", safe_function<binding_body>},
|
{"binding_body", safe_function<binding_body>},
|
||||||
|
|
|
@ -8,6 +8,7 @@ Author: Leonardo de Moura
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <limits>
|
||||||
#include "util/test.h"
|
#include "util/test.h"
|
||||||
#include "kernel/expr.h"
|
#include "kernel/expr.h"
|
||||||
#include "kernel/expr_sets.h"
|
#include "kernel/expr_sets.h"
|
||||||
|
@ -68,11 +69,11 @@ static expr mk_dag(unsigned depth, bool _closed = false) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tst2() {
|
static void tst2() {
|
||||||
expr r1 = mk_dag(20);
|
expr r1 = mk_dag(40);
|
||||||
expr r2 = mk_dag(20);
|
expr r2 = mk_dag(40);
|
||||||
lean_assert(r1 == r2);
|
lean_assert(r1 == r2);
|
||||||
std::cout << get_depth(r1) << "\n";
|
std::cout << get_weight(r1) << "\n";
|
||||||
lean_assert_eq(get_depth(r1), 41);
|
lean_assert(get_weight(r1) == std::numeric_limits<unsigned>::max());
|
||||||
}
|
}
|
||||||
|
|
||||||
static expr mk_big(expr f, unsigned depth, unsigned val) {
|
static expr mk_big(expr f, unsigned depth, unsigned val) {
|
||||||
|
|
|
@ -95,5 +95,5 @@ assert(a:occurs(f(a)))
|
||||||
enable_expr_caching(false)
|
enable_expr_caching(false)
|
||||||
assert(not f(a):is_eqp(f(a)))
|
assert(not f(a):is_eqp(f(a)))
|
||||||
assert(f(a):arg():is_eqp(a))
|
assert(f(a):arg():is_eqp(a))
|
||||||
assert(f(a):depth() == 2)
|
assert(f(a):weight() == 3)
|
||||||
print(f(a):hash())
|
print(f(a):hash())
|
||||||
|
|
8
tests/lua/order.lua
Normal file
8
tests/lua/order.lua
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
local mul = Const("mul")
|
||||||
|
local div = Const("div")
|
||||||
|
local z = Const("z")
|
||||||
|
local x = Const("x")
|
||||||
|
local y = Const("y")
|
||||||
|
local t1 = mul(z, mul(div(x, y), y))
|
||||||
|
local t2 = mul(div(x, y), mul(z, y))
|
||||||
|
assert(t1 < t2)
|
Loading…
Reference in a new issue