mirror of
https://github.com/Z3Prover/z3
synced 2025-04-22 08:35:31 +00:00
fix axiomatization for sdiv
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
parent
0ca94b9c2f
commit
477db7d8bd
4 changed files with 39 additions and 9 deletions
|
@ -92,7 +92,7 @@ namespace euf {
|
|||
m_egraph.explain_eq<size_t>(m_explain, &m_explain_cc, a, b);
|
||||
m_egraph.end_explain();
|
||||
// Detect shortcut if equality is explained directly by a theory
|
||||
if (m_explain.size() == 1 && !is_literal(m_explain[0])) {
|
||||
if (m_explain.size() == 1 && is_justification(m_explain[0])) {
|
||||
auto const& [x, y] = th_explain::from_index(get_justification(m_explain[0])).eq_consequent();
|
||||
if (x == a && y == b)
|
||||
continue;
|
||||
|
|
|
@ -427,8 +427,8 @@ namespace polysat {
|
|||
unsigned sz = bv.get_bv_size(x);
|
||||
expr* u = bv.mk_bv_urem(x, y);
|
||||
rational N = rational::power_of_two(bv.get_bv_size(x));
|
||||
expr* signx = bv.mk_ule(bv.mk_numeral(N / 2, sz), x);
|
||||
expr* signy = bv.mk_ule(bv.mk_numeral(N / 2, sz), y);
|
||||
expr_ref signx = mk_ule(bv.mk_numeral(N / 2, sz), x);
|
||||
expr_ref signy = mk_ule(bv.mk_numeral(N / 2, sz), y);
|
||||
sat::literal lsignx = mk_literal(signx);
|
||||
sat::literal lsigny = mk_literal(signy);
|
||||
sat::literal u_eq0 = eq_internalize(u, bv.mk_zero(sz));
|
||||
|
@ -443,6 +443,22 @@ namespace polysat {
|
|||
add_axiom(name, { y_eq0, lsignx, lsigny, eq_internalize(e, u) });
|
||||
}
|
||||
|
||||
expr_ref solver::mk_ite(expr* c, expr* t, expr* e) {
|
||||
expr_ref _c(c, m), _t(t, m), _e(e, m);
|
||||
if (m.is_true(c))
|
||||
return _t;
|
||||
if (m.is_false(c))
|
||||
return _e;
|
||||
return expr_ref(m.mk_ite(c, t, e), m);
|
||||
}
|
||||
|
||||
expr_ref solver::mk_ule(expr* l, expr* r) {
|
||||
expr_ref res(bv.mk_ule(l, r), m);
|
||||
ctx.get_rewriter()(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// d = udiv(abs(x), abs(y))
|
||||
// y = 0, x > 0 -> 1
|
||||
|
@ -455,17 +471,19 @@ namespace polysat {
|
|||
void solver::axiomatize_sdiv(app* e, expr* x, expr* y) {
|
||||
unsigned sz = bv.get_bv_size(x);
|
||||
rational N = rational::power_of_two(bv.get_bv_size(x));
|
||||
expr* signx = bv.mk_ule(bv.mk_numeral(N / 2, sz), x);
|
||||
expr* signy = bv.mk_ule(bv.mk_numeral(N / 2, sz), y);
|
||||
expr* absx = m.mk_ite(signx, bv.mk_bv_sub(bv.mk_numeral(N - 1, sz), x), x);
|
||||
expr* absy = m.mk_ite(signy, bv.mk_bv_sub(bv.mk_numeral(N - 1, sz), y), y);
|
||||
expr_ref signx = mk_ule(bv.mk_numeral(N / 2, sz), x);
|
||||
expr_ref signy = mk_ule(bv.mk_numeral(N / 2, sz), y);
|
||||
expr_ref absx = mk_ite(signx, bv.mk_bv_sub(bv.mk_numeral(N - 1, sz), x), x);
|
||||
expr_ref absy = mk_ite(signy, bv.mk_bv_sub(bv.mk_numeral(N - 1, sz), y), y);
|
||||
expr* d = bv.mk_bv_udiv(absx, absy);
|
||||
sat::literal lsignx = mk_literal(signx);
|
||||
sat::literal lsigny = mk_literal(signy);
|
||||
sat::literal y_eq0 = eq_internalize(y, bv.mk_zero(sz));
|
||||
sat::literal x_eq0 = eq_internalize(x, bv.mk_zero(sz));
|
||||
auto name = "sdiv";
|
||||
add_axiom(name, { ~y_eq0, ~lsignx, eq_internalize(e, bv.mk_numeral(1, sz)) });
|
||||
add_axiom(name, { ~y_eq0, lsignx, eq_internalize(e, bv.mk_numeral(N - 1, sz)) });
|
||||
add_axiom(name, { y_eq0, ~x_eq0, eq_internalize(e, bv.mk_zero(sz)) });
|
||||
add_axiom(name, { y_eq0, lsignx, ~lsigny, eq_internalize(e, bv.mk_bv_neg(d)) });
|
||||
add_axiom(name, { y_eq0, ~lsignx, lsigny, eq_internalize(e, bv.mk_bv_neg(d)) });
|
||||
add_axiom(name, { y_eq0, lsignx, lsigny, eq_internalize(e, d) });
|
||||
|
@ -499,6 +517,7 @@ namespace polysat {
|
|||
euf::enode* rn = expr2enode(rem);
|
||||
auto& m = a.manager();
|
||||
unsigned sz = m.power_of_2();
|
||||
verbose_stream() << "quot-rem " << a << " " << b << "\n";
|
||||
if (b.is_zero()) {
|
||||
// By SMT-LIB specification, b = 0 ==> q = -1, r = a.
|
||||
internalize_set(quot, m.mk_val(m.max_value()));
|
||||
|
|
|
@ -424,13 +424,22 @@ namespace polysat {
|
|||
if (q.is_zero() && p.has_unit(x)) {
|
||||
auto l = pdd2expr(x);
|
||||
auto r = pdd2expr(x - p);
|
||||
result = m.mk_eq(l, r);
|
||||
if (m.are_equal(l, r))
|
||||
result = m.mk_true();
|
||||
else if (m.are_distinct(l, r))
|
||||
result = m.mk_false();
|
||||
else
|
||||
result = m.mk_eq(l, r);
|
||||
}
|
||||
else {
|
||||
auto l = pdd2expr(p);
|
||||
auto r = pdd2expr(q);
|
||||
if (p == q)
|
||||
if (m.are_equal(l, r))
|
||||
result = m.mk_true();
|
||||
else if (m.is_value(l) && m.is_value(r)) {
|
||||
result = bv.mk_ule(l, r);
|
||||
ctx.get_rewriter()(result);
|
||||
}
|
||||
else if (q.is_zero())
|
||||
result = m.mk_eq(l, r);
|
||||
else
|
||||
|
|
|
@ -187,6 +187,8 @@ namespace polysat {
|
|||
void axiomatize_bv2int(app* e, expr* x);
|
||||
void axioms_for_extract(app* e);
|
||||
void axioms_for_concat(app* e);
|
||||
expr_ref mk_ite(expr* c, expr* t, expr* e);
|
||||
expr_ref mk_ule(expr* l, expr* r);
|
||||
expr* rotate_left(app* e, unsigned n, expr* x);
|
||||
unsigned m_delayed_axioms_qhead = 0;
|
||||
ptr_vector<app> m_delayed_axioms;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue