3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-06-06 06:03:23 +00:00

add handling for nested terms

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2017-07-24 16:12:46 -07:00
parent 30b0d5ba13
commit c8fe91d8c5

View file

@ -602,8 +602,8 @@ namespace smt {
} }
bool all_zeros(vector<rational> const& v) const { bool all_zeros(vector<rational> const& v) const {
for (unsigned i = 0; i < v.size(); ++i) { for (rational const& r : v) {
if (!v[i].is_zero()) { if (!r.is_zero()) {
return false; return false;
} }
} }
@ -1031,20 +1031,32 @@ namespace smt {
return m_solver->var_is_registered(m_theory_var2var_index[v]); return m_solver->var_is_registered(m_theory_var2var_index[v]);
} }
mutable vector<std::pair<lp::var_index, rational>> m_todo_terms;
lp::impq get_ivalue(theory_var v) const { lp::impq get_ivalue(theory_var v) const {
lp_assert(can_get_ivalue(v)); lp_assert(can_get_ivalue(v));
lp::var_index vi = m_theory_var2var_index[v]; lp::var_index vi = m_theory_var2var_index[v];
if (!m_solver->is_term(vi)) if (!m_solver->is_term(vi))
return m_solver->get_value(vi); return m_solver->get_value(vi);
m_todo_terms.push_back(std::make_pair(vi, rational::one()));
const lp::lar_term& term = m_solver->get_term(vi); lp::impq result(0);
lp::impq result(term.m_v); while (!m_todo_terms.empty()) {
for (const auto & i: term.m_coeffs) { vi = m_todo_terms.back().first;
result += m_solver->get_value(i.first) * i.second; rational coeff = m_todo_terms.back().second;
m_todo_terms.pop_back();
if (m_solver->is_term(vi)) {
const lp::lar_term& term = m_solver->get_term(vi);
result += term.m_v * coeff;
for (const auto & i: term.m_coeffs) {
m_todo_terms.push_back(std::make_pair(i.first, coeff * i.second));
}
}
else {
result += m_solver->get_value(vi) * coeff;
}
} }
return result; return result;
} }
rational get_value(theory_var v) const { rational get_value(theory_var v) const {
if (!can_get_value(v)) return rational::zero(); if (!can_get_value(v)) return rational::zero();
@ -1052,17 +1064,25 @@ namespace smt {
if (m_variable_values.count(vi) > 0) { if (m_variable_values.count(vi) > 0) {
return m_variable_values[vi]; return m_variable_values[vi];
} }
if (m_solver->is_term(vi)) { m_todo_terms.push_back(std::make_pair(vi, rational::one()));
const lp::lar_term& term = m_solver->get_term(vi); rational result(0);
rational result = term.m_v; while (!m_todo_terms.empty()) {
for (auto i = term.m_coeffs.begin(); i != term.m_coeffs.end(); ++i) { lp::var_index wi = m_todo_terms.back().first;
result += m_variable_values[i->first] * i->second; rational coeff = m_todo_terms.back().second;
m_todo_terms.pop_back();
if (m_solver->is_term(wi)) {
const lp::lar_term& term = m_solver->get_term(wi);
result += term.m_v * coeff;
for (auto const& i : term.m_coeffs) {
m_todo_terms.push_back(std::make_pair(i.first, i.second * coeff));
}
}
else {
result += m_variable_values[wi] * coeff;
} }
m_variable_values[vi] = result;
return result;
} }
UNREACHABLE(); m_variable_values[vi] = result;
return m_variable_values[vi]; return result;
} }
void init_variable_values() { void init_variable_values() {
@ -1550,8 +1570,8 @@ namespace smt {
SASSERT(validate_assign(lit)); SASSERT(validate_assign(lit));
if (m_core.size() < small_lemma_size() && m_eqs.empty()) { if (m_core.size() < small_lemma_size() && m_eqs.empty()) {
m_core2.reset(); m_core2.reset();
for (unsigned i = 0; i < m_core.size(); ++i) { for (auto const& c : m_core) {
m_core2.push_back(~m_core[i]); m_core2.push_back(~c);
} }
m_core2.push_back(lit); m_core2.push_back(lit);
justification * js = 0; justification * js = 0;
@ -1926,16 +1946,29 @@ namespace smt {
++m_stats.m_bounds_propagations; ++m_stats.m_bounds_propagations;
} }
svector<lp::var_index> m_todo_vars;
void add_use_lists(lp_api::bound* b) { void add_use_lists(lp_api::bound* b) {
theory_var v = b->get_var(); theory_var v = b->get_var();
lp::var_index vi = get_var_index(v); lp::var_index vi = get_var_index(v);
if (m_solver->is_term(vi)) { if (!m_solver->is_term(vi)) {
return;
}
m_todo_vars.push_back(vi);
while (!m_todo_vars.empty()) {
vi = m_todo_vars.back();
m_todo_vars.pop_back();
lp::lar_term const& term = m_solver->get_term(vi); lp::lar_term const& term = m_solver->get_term(vi);
for (auto i = term.m_coeffs.begin(); i != term.m_coeffs.end(); ++i) { for (auto i = term.m_coeffs.begin(); i != term.m_coeffs.end(); ++i) {
lp::var_index wi = i->first; lp::var_index wi = i->first;
unsigned w = m_var_index2theory_var[wi]; if (m_solver->is_term(wi)) {
m_use_list.reserve(w + 1, ptr_vector<lp_api::bound>()); m_todo_vars.push_back(wi);
m_use_list[w].push_back(b); }
else {
unsigned w = m_var_index2theory_var[wi];
m_use_list.reserve(w + 1, ptr_vector<lp_api::bound>());
m_use_list[w].push_back(b);
}
} }
} }
} }
@ -1943,13 +1976,24 @@ namespace smt {
void del_use_lists(lp_api::bound* b) { void del_use_lists(lp_api::bound* b) {
theory_var v = b->get_var(); theory_var v = b->get_var();
lp::var_index vi = m_theory_var2var_index[v]; lp::var_index vi = m_theory_var2var_index[v];
if (m_solver->is_term(vi)) { if (!m_solver->is_term(vi)) {
return;
}
m_todo_vars.push_back(vi);
while (!m_todo_vars.empty()) {
vi = m_todo_vars.back();
m_todo_vars.pop_back();
lp::lar_term const& term = m_solver->get_term(vi); lp::lar_term const& term = m_solver->get_term(vi);
for (auto i = term.m_coeffs.begin(); i != term.m_coeffs.end(); ++i) { for (auto i = term.m_coeffs.begin(); i != term.m_coeffs.end(); ++i) {
lp::var_index wi = i->first; lp::var_index wi = i->first;
unsigned w = m_var_index2theory_var[wi]; if (m_solver->is_term(wi)) {
SASSERT(m_use_list[w].back() == b); m_todo_vars.push_back(wi);
m_use_list[w].pop_back(); }
else {
unsigned w = m_var_index2theory_var[wi];
SASSERT(m_use_list[w].back() == b);
m_use_list[w].pop_back();
}
} }
} }
} }
@ -2036,6 +2080,9 @@ namespace smt {
lp::constraint_index ci; lp::constraint_index ci;
rational value; rational value;
bool is_strict; bool is_strict;
if (m_solver->is_term(wi)) {
return false;
}
if (coeff.second.is_neg() == is_lub) { if (coeff.second.is_neg() == is_lub) {
// -3*x ... <= lub based on lower bound for x. // -3*x ... <= lub based on lower bound for x.
if (!m_solver->has_lower_bound(wi, ci, value, is_strict)) { if (!m_solver->has_lower_bound(wi, ci, value, is_strict)) {
@ -2381,15 +2428,31 @@ namespace smt {
SASSERT(m_use_nra_model); SASSERT(m_use_nra_model);
lp::var_index vi = m_theory_var2var_index[v]; lp::var_index vi = m_theory_var2var_index[v];
if (m_solver->is_term(vi)) { if (m_solver->is_term(vi)) {
lp::lar_term const& term = m_solver->get_term(vi);
scoped_anum r1(m_nra->am()); m_todo_terms.push_back(std::make_pair(vi, rational::one()));
m_nra->am().set(r, term.m_v.to_mpq());
m_nra->am().set(r, 0);
for (auto const coeff : term.m_coeffs) { while (!m_todo_terms.empty()) {
lp::var_index wi = coeff.first; rational wcoeff = m_todo_terms.back().second;
m_nra->am().set(r1, coeff.second.to_mpq()); lp::var_index wi = m_todo_terms.back().first;
m_nra->am().mul(m_nra->value(wi), r1, r1); m_todo_terms.pop_back();
m_nra->am().add(r1, r, r); lp::lar_term const& term = m_solver->get_term(vi);
scoped_anum r1(m_nra->am());
rational c1 = term.m_v * wcoeff;
m_nra->am().set(r1, c1.to_mpq());
m_nra->am().add(r, r1, r);
for (auto const coeff : term.m_coeffs) {
lp::var_index wi = coeff.first;
c1 = coeff.second * wcoeff;
if (m_solver->is_term(wi)) {
m_todo_terms.push_back(std::make_pair(wi, c1));
}
else {
m_nra->am().set(r1, c1.to_mpq());
m_nra->am().mul(m_nra->value(wi), r1, r1);
m_nra->am().add(r1, r, r);
}
}
} }
return r; return r;
} }
@ -2489,10 +2552,14 @@ namespace smt {
theory_lra::inf_eps maximize(theory_var v, expr_ref& blocker, bool& has_shared) { theory_lra::inf_eps maximize(theory_var v, expr_ref& blocker, bool& has_shared) {
lp::var_index vi = m_theory_var2var_index.get(v, UINT_MAX); lp::var_index vi = m_theory_var2var_index.get(v, UINT_MAX);
vector<std::pair<rational, lp::var_index> > coeffs; vector<std::pair<rational, lp::var_index> > coeffs;
rational coeff; rational coeff(0);
//
// TBD: change API for maximize_term to take a proper term as input.
//
if (m_solver->is_term(vi)) { if (m_solver->is_term(vi)) {
const lp::lar_term& term = m_solver->get_term(vi); const lp::lar_term& term = m_solver->get_term(vi);
for (auto & ti : term.m_coeffs) { for (auto & ti : term.m_coeffs) {
SASSERT(!m_solver->is_term(ti.first));
coeffs.push_back(std::make_pair(ti.second, ti.first)); coeffs.push_back(std::make_pair(ti.second, ti.first));
} }
coeff = term.m_v; coeff = term.m_v;
@ -2550,7 +2617,13 @@ namespace smt {
app_ref mk_term(lp::lar_term const& term, bool is_int) { app_ref mk_term(lp::lar_term const& term, bool is_int) {
expr_ref_vector args(m); expr_ref_vector args(m);
for (auto & ti : term.m_coeffs) { for (auto & ti : term.m_coeffs) {
theory_var w = m_var_index2theory_var[ti.first]; theory_var w;
if (m_solver->is_term(ti.first)) {
w = m_term_index2theory_var[m_solver->adjust_term_index(ti.first)];
}
else {
w = m_var_index2theory_var[ti.first];
}
expr* o = get_enode(w)->get_owner(); expr* o = get_enode(w)->get_owner();
if (ti.second.is_one()) { if (ti.second.is_one()) {
args.push_back(o); args.push_back(o);