mirror of
https://github.com/Z3Prover/z3
synced 2025-04-14 21:08:46 +00:00
add handling for nested terms
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
parent
30b0d5ba13
commit
c8fe91d8c5
|
@ -602,8 +602,8 @@ namespace smt {
|
|||
}
|
||||
|
||||
bool all_zeros(vector<rational> const& v) const {
|
||||
for (unsigned i = 0; i < v.size(); ++i) {
|
||||
if (!v[i].is_zero()) {
|
||||
for (rational const& r : v) {
|
||||
if (!r.is_zero()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -1031,20 +1031,32 @@ namespace smt {
|
|||
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_assert(can_get_ivalue(v));
|
||||
lp::var_index vi = m_theory_var2var_index[v];
|
||||
if (!m_solver->is_term(vi))
|
||||
return m_solver->get_value(vi);
|
||||
|
||||
const lp::lar_term& term = m_solver->get_term(vi);
|
||||
lp::impq result(term.m_v);
|
||||
for (const auto & i: term.m_coeffs) {
|
||||
result += m_solver->get_value(i.first) * i.second;
|
||||
m_todo_terms.push_back(std::make_pair(vi, rational::one()));
|
||||
lp::impq result(0);
|
||||
while (!m_todo_terms.empty()) {
|
||||
vi = m_todo_terms.back().first;
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
rational get_value(theory_var v) const {
|
||||
if (!can_get_value(v)) return rational::zero();
|
||||
|
@ -1052,17 +1064,25 @@ namespace smt {
|
|||
if (m_variable_values.count(vi) > 0) {
|
||||
return m_variable_values[vi];
|
||||
}
|
||||
if (m_solver->is_term(vi)) {
|
||||
const lp::lar_term& term = m_solver->get_term(vi);
|
||||
rational result = term.m_v;
|
||||
for (auto i = term.m_coeffs.begin(); i != term.m_coeffs.end(); ++i) {
|
||||
result += m_variable_values[i->first] * i->second;
|
||||
m_todo_terms.push_back(std::make_pair(vi, rational::one()));
|
||||
rational result(0);
|
||||
while (!m_todo_terms.empty()) {
|
||||
lp::var_index wi = m_todo_terms.back().first;
|
||||
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();
|
||||
return m_variable_values[vi];
|
||||
m_variable_values[vi] = result;
|
||||
return result;
|
||||
}
|
||||
|
||||
void init_variable_values() {
|
||||
|
@ -1550,8 +1570,8 @@ namespace smt {
|
|||
SASSERT(validate_assign(lit));
|
||||
if (m_core.size() < small_lemma_size() && m_eqs.empty()) {
|
||||
m_core2.reset();
|
||||
for (unsigned i = 0; i < m_core.size(); ++i) {
|
||||
m_core2.push_back(~m_core[i]);
|
||||
for (auto const& c : m_core) {
|
||||
m_core2.push_back(~c);
|
||||
}
|
||||
m_core2.push_back(lit);
|
||||
justification * js = 0;
|
||||
|
@ -1926,16 +1946,29 @@ namespace smt {
|
|||
++m_stats.m_bounds_propagations;
|
||||
}
|
||||
|
||||
svector<lp::var_index> m_todo_vars;
|
||||
|
||||
void add_use_lists(lp_api::bound* b) {
|
||||
theory_var v = b->get_var();
|
||||
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);
|
||||
for (auto i = term.m_coeffs.begin(); i != term.m_coeffs.end(); ++i) {
|
||||
lp::var_index wi = i->first;
|
||||
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);
|
||||
if (m_solver->is_term(wi)) {
|
||||
m_todo_vars.push_back(wi);
|
||||
}
|
||||
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) {
|
||||
theory_var v = b->get_var();
|
||||
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);
|
||||
for (auto i = term.m_coeffs.begin(); i != term.m_coeffs.end(); ++i) {
|
||||
lp::var_index wi = i->first;
|
||||
unsigned w = m_var_index2theory_var[wi];
|
||||
SASSERT(m_use_list[w].back() == b);
|
||||
m_use_list[w].pop_back();
|
||||
if (m_solver->is_term(wi)) {
|
||||
m_todo_vars.push_back(wi);
|
||||
}
|
||||
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;
|
||||
rational value;
|
||||
bool is_strict;
|
||||
if (m_solver->is_term(wi)) {
|
||||
return false;
|
||||
}
|
||||
if (coeff.second.is_neg() == is_lub) {
|
||||
// -3*x ... <= lub based on lower bound for x.
|
||||
if (!m_solver->has_lower_bound(wi, ci, value, is_strict)) {
|
||||
|
@ -2381,15 +2428,31 @@ namespace smt {
|
|||
SASSERT(m_use_nra_model);
|
||||
lp::var_index vi = m_theory_var2var_index[v];
|
||||
if (m_solver->is_term(vi)) {
|
||||
lp::lar_term const& term = m_solver->get_term(vi);
|
||||
scoped_anum r1(m_nra->am());
|
||||
m_nra->am().set(r, term.m_v.to_mpq());
|
||||
|
||||
for (auto const coeff : term.m_coeffs) {
|
||||
lp::var_index wi = coeff.first;
|
||||
m_nra->am().set(r1, coeff.second.to_mpq());
|
||||
m_nra->am().mul(m_nra->value(wi), r1, r1);
|
||||
m_nra->am().add(r1, r, r);
|
||||
|
||||
m_todo_terms.push_back(std::make_pair(vi, rational::one()));
|
||||
|
||||
m_nra->am().set(r, 0);
|
||||
while (!m_todo_terms.empty()) {
|
||||
rational wcoeff = m_todo_terms.back().second;
|
||||
lp::var_index wi = m_todo_terms.back().first;
|
||||
m_todo_terms.pop_back();
|
||||
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;
|
||||
}
|
||||
|
@ -2489,10 +2552,14 @@ namespace smt {
|
|||
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);
|
||||
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)) {
|
||||
const lp::lar_term& term = m_solver->get_term(vi);
|
||||
for (auto & ti : term.m_coeffs) {
|
||||
SASSERT(!m_solver->is_term(ti.first));
|
||||
coeffs.push_back(std::make_pair(ti.second, ti.first));
|
||||
}
|
||||
coeff = term.m_v;
|
||||
|
@ -2550,7 +2617,13 @@ namespace smt {
|
|||
app_ref mk_term(lp::lar_term const& term, bool is_int) {
|
||||
expr_ref_vector args(m);
|
||||
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();
|
||||
if (ti.second.is_one()) {
|
||||
args.push_back(o);
|
||||
|
|
Loading…
Reference in a new issue