3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-11 19:53:34 +00:00

fix regression in model generation for UFLRA

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2018-09-25 10:00:13 -07:00
parent b4b9da9d8b
commit af41255a9d

View file

@ -218,6 +218,8 @@ class theory_lra::imp {
mutable std::unordered_map<lp::var_index, rational> m_variable_values; // current model
lp::var_index m_one_var;
lp::var_index m_zero_var;
lp::var_index m_rone_var;
lp::var_index m_rzero_var;
enum constraint_source {
inequality_source,
@ -333,11 +335,11 @@ class theory_lra::imp {
}
}
void add_const(int c, lp::var_index& var) {
lp::var_index add_const(int c, lp::var_index& var, bool is_int) {
if (var != UINT_MAX) {
return;
return var;
}
app_ref cnst(a.mk_int(c), m);
app_ref cnst(a.mk_numeral(rational(c), is_int), m);
TRACE("arith", tout << "add " << cnst << "\n";);
enode* e = mk_enode(cnst);
theory_var v = mk_var(cnst);
@ -347,16 +349,15 @@ class theory_lra::imp {
m_var_trail.push_back(v);
add_def_constraint(m_solver->add_var_bound(var, lp::GE, rational(c)));
add_def_constraint(m_solver->add_var_bound(var, lp::LE, rational(c)));
return var;
}
lp::var_index get_one() {
add_const(1, m_one_var);
return m_one_var;
lp::var_index get_one(bool is_int) {
return add_const(1, is_int ? m_one_var : m_rone_var, is_int);
}
lp::var_index get_zero() {
add_const(0, m_zero_var);
return m_zero_var;
lp::var_index get_zero(bool is_int) {
return add_const(0, is_int ? m_zero_var : m_rzero_var, is_int);
}
@ -577,6 +578,7 @@ class theory_lra::imp {
}
enode * mk_enode(app * n) {
TRACE("arith", tout << expr_ref(n, m) << "\n";);
if (ctx().e_internalized(n)) {
return get_enode(n);
}
@ -777,6 +779,7 @@ class theory_lra::imp {
}
theory_var internalize_def(app* term, scoped_internalize_state& st) {
TRACE("arith", tout << expr_ref(term, m) << "\n";);
if (ctx().e_internalized(term)) {
IF_VERBOSE(0, verbose_stream() << "repeated term\n";);
return mk_var(term, false);
@ -807,10 +810,10 @@ class theory_lra::imp {
return st.vars()[0];
}
else if (is_one(st)) {
return get_one();
return get_one(a.is_int(term));
}
else if (is_zero(st)) {
return get_zero();
return get_zero(a.is_int(term));
}
else {
init_left_side(st);
@ -820,7 +823,7 @@ class theory_lra::imp {
if (vi == UINT_MAX) {
rational const& offset = st.offset();
if (!offset.is_zero()) {
m_left_side.push_back(std::make_pair(offset, get_one()));
m_left_side.push_back(std::make_pair(offset, get_one(a.is_int(term))));
}
SASSERT(!m_left_side.empty());
vi = m_solver->add_term(m_left_side);
@ -854,6 +857,8 @@ public:
m_internalize_head(0),
m_one_var(UINT_MAX),
m_zero_var(UINT_MAX),
m_rone_var(UINT_MAX),
m_rzero_var(UINT_MAX),
m_not_handled(nullptr),
m_asserted_qhead(0),
m_assume_eq_head(0),
@ -925,16 +930,18 @@ public:
}
return true;
}
bool is_arith(enode* n) {
return n && n->get_th_var(get_id()) != null_theory_var;
}
void internalize_eq_eh(app * atom, bool_var) {
TRACE("arith_verbose", tout << mk_pp(atom, m) << "\n";);
expr* lhs = nullptr, *rhs = nullptr;
VERIFY(m.is_eq(atom, lhs, rhs));
enode * n1 = get_enode(lhs);
enode * n2 = get_enode(rhs);
if (n1->get_th_var(get_id()) != null_theory_var &&
n2->get_th_var(get_id()) != null_theory_var &&
n1 != n2) {
TRACE("arith_verbose", tout << mk_pp(atom, m) << "\n";);
if (is_arith(n1) && is_arith(n2) && n1 != n2) {
m_arith_eq_adapter.mk_axioms(n1, n2);
}
}
@ -1301,6 +1308,7 @@ public:
void init_variable_values() {
reset_variable_values();
if (!m.canceled() && m_solver.get() && th.get_num_vars() > 0) {
TRACE("arith", tout << "update variable values\n";);
m_solver->get_model(m_variable_values);
}
}
@ -3002,6 +3010,7 @@ public:
if (!can_get_bound(v)) return false;
lp::var_index vi = m_theory_var2var_index[v];
if (m_solver->has_value(vi, val)) {
TRACE("arith", tout << expr_ref(n->get_owner(), m) << " := " << val << "\n";);
if (is_int(n) && !val.is_int()) return false;
return true;
}