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:
parent
30b0d5ba13
commit
c8fe91d8c5
1 changed files with 111 additions and 38 deletions
|
@ -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);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue