3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-13 12:28:44 +00:00

remove the fresh definition when removing its column

Signed-off-by: Lev Nachmanson <levnach@hotmail.com>
This commit is contained in:
Lev Nachmanson 2025-02-06 16:50:24 -10:00 committed by Lev Nachmanson
parent 17d68c18aa
commit dcd5783232

View file

@ -46,7 +46,8 @@
the i-th entry. the i-th entry.
*/ */
namespace lp { namespace lp {
template <typename T, typename K> bool contains(const T& t, K j) { template <typename T, typename K>
bool contains(const T& t, K j) {
return t.find(j) != t.end(); return t.find(j) != t.end();
} }
@ -54,8 +55,8 @@ namespace lp {
mpq m_coeff; mpq m_coeff;
unsigned m_j; unsigned m_j;
lpvar var() const { return m_j; } lpvar var() const { return m_j; }
const mpq & coeff() const { return m_coeff; } const mpq& coeff() const { return m_coeff; }
mpq & coeff() { return m_coeff; } mpq& coeff() { return m_coeff; }
iv() {} iv() {}
iv(const mpq& v, unsigned j) : m_coeff(v), m_j(j) {} iv(const mpq& v, unsigned j) : m_coeff(v), m_j(j) {}
}; };
@ -75,7 +76,7 @@ namespace lp {
return m_rev_map.find(b)->second; return m_rev_map.find(b)->second;
} }
unsigned size() const {return static_cast<unsigned>(m_map.size());} unsigned size() const { return static_cast<unsigned>(m_map.size()); }
void erase_val(unsigned b) { void erase_val(unsigned b) {
VERIFY(contains(m_rev_map, b) && contains(m_map, m_rev_map[b])); VERIFY(contains(m_rev_map, b) && contains(m_map, m_rev_map[b]));
@ -132,14 +133,12 @@ namespace lp {
} }
}; };
template<typename T> template <typename T>
class bij_map { struct bij_map {
// We store T indexed by 'b' in an std::unordered_map, and use bijection to map from 'a' to 'b'. // We store T indexed by 'b' in an std::unordered_map, and use bijection to map from 'a' to 'b'.
bijection m_bij; bijection m_bij;
std::unordered_map<unsigned, T> m_data; std::unordered_map<unsigned, T> m_data;
public:
// Adds a->b in m_bij, associates val with b. // Adds a->b in m_bij, associates val with b.
void add(unsigned a, unsigned b, const T& val) { void add(unsigned a, unsigned b, const T& val) {
// You might have some method in bijection such as 'insert(a, b)' // You might have some method in bijection such as 'insert(a, b)'
@ -155,7 +154,7 @@ namespace lp {
} }
void erase_by_second_key(unsigned b) { void erase_by_second_key(unsigned b) {
VERIFY(m_bij.has_val(b)); SASSERT(m_bij.has_val(b));
m_bij.erase_val(b); m_bij.erase_val(b);
auto it = m_data.find(b); auto it = m_data.find(b);
VERIFY(it != m_data.end()); VERIFY(it != m_data.end());
@ -163,7 +162,7 @@ namespace lp {
} }
bool has_key(unsigned j) const { return m_bij.has_key(j); } bool has_key(unsigned j) const { return m_bij.has_key(j); }
bool has_second_key(unsigned j) const { return m_bij.has_val(j);} bool has_second_key(unsigned j) const { return m_bij.has_val(j); }
// Get the data by 'a', look up b in m_bij, then read from m_data // Get the data by 'a', look up b in m_bij, then read from m_data
const T& get_by_key(unsigned a) const { const T& get_by_key(unsigned a) const {
unsigned b = m_bij[a]; // relies on operator[](unsigned) from bijection unsigned b = m_bij[a]; // relies on operator[](unsigned) from bijection
@ -246,7 +245,7 @@ namespace lp {
std::ostream& print_S(std::ostream& out) { std::ostream& print_S(std::ostream& out) {
out << "S:\n"; out << "S:\n";
for (const auto & p: m_k2s.m_map) { for (const auto& p : m_k2s.m_map) {
print_entry(p.second, out); print_entry(p.second, out);
} }
return out; return out;
@ -258,11 +257,10 @@ namespace lp {
[](int j) -> std::string { return "x" + std::to_string(j); }, out); [](int j) -> std::string { return "x" + std::to_string(j); }, out);
} }
// used for debug only // used for debug only
std::ostream& print_lar_term_L(const std_vector<iv>& t, std::ostream& out) const { std::ostream& print_lar_term_L(const std_vector<iv>& t, std::ostream& out) const {
vector<std::pair<mpq, unsigned>> tp; vector<std::pair<mpq, unsigned>> tp;
for (const auto & p : t) { for (const auto& p : t) {
tp.push_back(std::make_pair(p.coeff(), p.var())); tp.push_back(std::make_pair(p.coeff(), p.var()));
} }
return print_linear_combination_customized( return print_linear_combination_customized(
@ -343,7 +341,7 @@ namespace lp {
// used for debug only // used for debug only
lar_term to_term() const { lar_term to_term() const {
lar_term r; lar_term r;
for (const auto& p: m_data) { for (const auto& p : m_data) {
r.add_monomial(p.coeff(), p.var()); r.add_monomial(p.coeff(), p.var());
} }
return r; return r;
@ -384,7 +382,7 @@ namespace lp {
int idx = m_index[j]; int idx = m_index[j];
if (idx == -1) { if (idx == -1) {
// Insert a new monomial { a, j } into m_data // Insert a new monomial { a, j } into m_data
m_data.push_back({ a, j }); m_data.push_back({a, j});
m_index[j] = static_cast<int>(m_data.size() - 1); m_index[j] = static_cast<int>(m_data.size() - 1);
} else { } else {
// Accumulate the coefficient // Accumulate the coefficient
@ -417,8 +415,7 @@ namespace lp {
return false; return false;
} }
} }
} } else {
else {
// Check that var() in m_data[idx] matches j // Check that var() in m_data[idx] matches j
if (idx < 0 || static_cast<unsigned>(idx) >= m_data.size()) { if (idx < 0 || static_cast<unsigned>(idx) >= m_data.size()) {
return false; return false;
@ -446,20 +443,19 @@ namespace lp {
return true; return true;
} }
void clear() { void clear() {
for (const auto& p: m_data) { for (const auto& p : m_data) {
m_index[p.var()] = -1; m_index[p.var()] = -1;
} }
m_data.clear(); m_data.clear();
SASSERT(invariant()); SASSERT(invariant());
} }
}; };
term_with_index m_l_terms_workspace; term_with_index m_l_terms_workspace;
term_with_index m_substitution_workspace; term_with_index m_substitution_workspace;
bijection m_k2s; bijection m_k2s;
bij_map<lar_term> m_fresh_k2xt_terms; bij_map<std::pair<lar_term, unsigned>> m_fresh_k2xt_terms;
// m_row2fresh_defs[i] is the set of all fresh variables xt // m_row2fresh_defs[i] is the set of all fresh variables xt
// such that pairs (xt, m_fresh_k2xt_terms[xt]) is a fresh definition introduced for row i // such that pairs (xt, m_fresh_k2xt_terms[xt]) is a fresh definition introduced for row i
// When row i is changed all entries depending on m_fresh_k2xt_terms[xt] should be recalculated, // When row i is changed all entries depending on m_fresh_k2xt_terms[xt] should be recalculated,
@ -472,7 +468,6 @@ namespace lp {
// m_column_to_terms[j] is the set of all k such lra.get_term(k) depends on j // m_column_to_terms[j] is the set of all k such lra.get_term(k) depends on j
std::unordered_map<unsigned, std::unordered_set<unsigned>> m_columns_to_terms; std::unordered_map<unsigned, std::unordered_set<unsigned>> m_columns_to_terms;
unsigned m_conflict_index = -1; // the row index of the conflict unsigned m_conflict_index = -1; // the row index of the conflict
unsigned m_max_of_branching_iterations = 0; unsigned m_max_of_branching_iterations = 0;
unsigned m_number_of_branching_calls; unsigned m_number_of_branching_calls;
@ -513,13 +508,13 @@ namespace lp {
} }
}; };
void undo_add_term_method(const lar_term *t) { void undo_add_term_method(const lar_term* t) {
TRACE("d_undo", tout << "t:"<< t<<", t->j():"<< t->j() << std::endl;); TRACE("d_undo", tout << "t:" << t << ", t->j():" << t->j() << std::endl;);
TRACE("dioph_eq", lra.print_term(*t, tout); tout << ", t->j() =" << t->j() << std::endl;); TRACE("dioph_eq", lra.print_term(*t, tout); tout << ", t->j() =" << t->j() << std::endl;);
if (!contains(m_active_terms, t)) { if (!contains(m_active_terms, t)) {
for (int i = static_cast<int>(m_added_terms.size() - 1); i >= 0; --i) { for (int i = static_cast<int>(m_added_terms.size() - 1); i >= 0; --i) {
if (m_added_terms[i] != t) continue; if (m_added_terms[i] != t) continue;
if ((unsigned)i != m_added_terms.size() -1) if ((unsigned)i != m_added_terms.size() - 1)
m_added_terms[i] = m_added_terms.back(); m_added_terms[i] = m_added_terms.back();
m_added_terms.pop_back(); m_added_terms.pop_back();
break; // all is done since the term has not made it to m_active_terms break; // all is done since the term has not made it to m_active_terms
@ -527,8 +522,8 @@ namespace lp {
return; return;
} }
// deregister the term that has been activated // deregister the term that has been activated
for (const auto & p: t->ext_coeffs()) { for (const auto& p : t->ext_coeffs()) {
TRACE("dio_reg", tout << "derigister p.var():" << p.var() <<"->" << t->j() << std::endl; ); TRACE("dio_reg", tout << "derigister p.var():" << p.var() << "->" << t->j() << std::endl;);
auto it = m_columns_to_terms.find(p.var()); auto it = m_columns_to_terms.find(p.var());
SASSERT(it != m_columns_to_terms.end()); SASSERT(it != m_columns_to_terms.end());
it->second.erase(t->j()); it->second.erase(t->j());
@ -539,22 +534,14 @@ namespace lp {
SASSERT(std::find(m_added_terms.begin(), m_added_terms.end(), t) == m_added_terms.end()); SASSERT(std::find(m_added_terms.begin(), m_added_terms.end(), t) == m_added_terms.end());
SASSERT(contains(m_active_terms, t)); SASSERT(contains(m_active_terms, t));
m_active_terms.erase(t); m_active_terms.erase(t);
TRACE("dioph_eq", TRACE("dioph_eq", tout << "the deleted term column in m_l_matrix" << std::endl; for (auto p : m_l_matrix.column(t->j())) { tout << "p.coeff():" << p.coeff() << ", row " << p.var() << std::endl; } tout << "m_l_matrix has " << m_l_matrix.column_count() << " columns" << std::endl; tout << "and " << m_l_matrix.row_count() << " rows" << std::endl; print_lar_term_L(*t, tout); tout << "; t->j()=" << t->j() << std::endl;);
tout << "the deleted term column in m_l_matrix" << std::endl;
for (auto p: m_l_matrix.column(t->j())) {
tout << "p.coeff():" << p.coeff()<< ", row " << p.var() << std::endl;
}
tout << "m_l_matrix has " << m_l_matrix.column_count() << " columns"<< std::endl;
tout << "and " << m_l_matrix.row_count() << " rows" << std::endl;
print_lar_term_L(*t, tout); tout << "; t->j()=" << t->j() << std::endl;
);
shrink_matrices(); shrink_matrices();
} }
struct undo_add_term : public trail { struct undo_add_term : public trail {
imp& m_s; imp& m_s;
const lar_term* m_t; const lar_term* m_t;
undo_add_term(imp& s, const lar_term *t): m_s(s), m_t(t) {} undo_add_term(imp& s, const lar_term* t) : m_s(s), m_t(t) {}
void undo() { void undo() {
m_s.undo_add_term_method(m_t); m_s.undo_add_term_method(m_t);
@ -569,7 +556,7 @@ namespace lp {
} }
unsigned size() const { unsigned size() const {
return m_q.size(); return (unsigned)m_q.size();
} }
void push(unsigned j) { void push(unsigned j) {
@ -591,7 +578,7 @@ namespace lp {
imp& m_imp; imp& m_imp;
unsigned m_j; // the column that has been added unsigned m_j; // the column that has been added
const mpq m_fixed_val; const mpq m_fixed_val;
undo_fixed_column(imp& s, unsigned j) : m_imp(s), m_j(j) , m_fixed_val(s.lra.get_lower_bound(j).x) { undo_fixed_column(imp& s, unsigned j) : m_imp(s), m_j(j), m_fixed_val(s.lra.get_lower_bound(j).x) {
SASSERT(s.lra.column_is_fixed(j)); SASSERT(s.lra.column_is_fixed(j));
} }
@ -613,18 +600,18 @@ namespace lp {
// change only the rows in m_l_matrix, and update m_e_matrix lazily // change only the rows in m_l_matrix, and update m_e_matrix lazily
unsigned j = m_l_matrix.column_count() - 1; unsigned j = m_l_matrix.column_count() - 1;
make_sure_j_is_in_the_last_row_of_l_matrix(); make_sure_j_is_in_the_last_row_of_l_matrix();
const auto &last_e_row = m_l_matrix.m_rows.back(); const auto& last_e_row = m_l_matrix.m_rows.back();
mpq alpha; mpq alpha;
for (const auto& p: last_e_row) { for (const auto& p : last_e_row) {
if (p.var() == j) { if (p.var() == j) {
alpha = p.coeff(); alpha = p.coeff();
break; break;
} }
} }
unsigned last_row_index= m_l_matrix.row_count() - 1; unsigned last_row_index = m_l_matrix.row_count() - 1;
m_l_matrix.divide_row(last_row_index, alpha); // divide the last row by alpha m_l_matrix.divide_row(last_row_index, alpha); // divide the last row by alpha
auto &column = m_l_matrix.m_columns[j]; auto& column = m_l_matrix.m_columns[j];
int pivot_col_cell_index = -1; int pivot_col_cell_index = -1;
for (unsigned k = 0; k < column.size(); k++) { for (unsigned k = 0; k < column.size(); k++) {
if (column[k].var() == last_row_index) { if (column[k].var() == last_row_index) {
@ -645,7 +632,7 @@ namespace lp {
m_l_matrix.m_rows[c.var()][c.offset()].offset() = pivot_col_cell_index; m_l_matrix.m_rows[c.var()][c.offset()].offset() = pivot_col_cell_index;
} }
while (column.size() > 1) { while (column.size() > 1) {
auto & c = column.back(); auto& c = column.back();
SASSERT(c.var() != last_row_index); SASSERT(c.var() != last_row_index);
m_l_matrix.pivot_row_to_row_given_cell(last_row_index, c, j); m_l_matrix.pivot_row_to_row_given_cell(last_row_index, c, j);
m_changed_rows.insert(c.var()); m_changed_rows.insert(c.var());
@ -654,9 +641,9 @@ namespace lp {
void make_sure_j_is_in_the_last_row_of_l_matrix() { void make_sure_j_is_in_the_last_row_of_l_matrix() {
unsigned j = m_l_matrix.column_count() - 1; unsigned j = m_l_matrix.column_count() - 1;
const auto &last_e_row = m_l_matrix.m_rows.back(); const auto& last_e_row = m_l_matrix.m_rows.back();
mpq alpha; mpq alpha;
for (const auto& p: last_e_row) { for (const auto& p : last_e_row) {
if (p.var() == j) { if (p.var() == j) {
return; return;
} }
@ -671,10 +658,10 @@ namespace lp {
eliminate_last_term_column(); eliminate_last_term_column();
remove_last_row_in_matrix(m_l_matrix); remove_last_row_in_matrix(m_l_matrix);
remove_last_row_in_matrix(m_e_matrix); remove_last_row_in_matrix(m_e_matrix);
while(m_l_matrix.column_count() && m_l_matrix.m_columns.back().size() == 0) { while (m_l_matrix.column_count() && m_l_matrix.m_columns.back().size() == 0) {
m_l_matrix.m_columns.pop_back(); m_l_matrix.m_columns.pop_back();
} }
while(m_e_matrix.column_count() && m_e_matrix.m_columns.back().size() == 0) { while (m_e_matrix.column_count() && m_e_matrix.m_columns.back().size() == 0) {
m_e_matrix.m_columns.pop_back(); m_e_matrix.m_columns.pop_back();
} }
m_var_register.shrink(m_e_matrix.column_count()); m_var_register.shrink(m_e_matrix.column_count());
@ -688,16 +675,15 @@ namespace lp {
m_sum_of_fixed.pop_back(); m_sum_of_fixed.pop_back();
} }
void remove_last_row_in_matrix(static_matrix<mpq, mpq>& m) { void remove_last_row_in_matrix(static_matrix<mpq, mpq>& m) {
auto & last_row = m.m_rows.back(); auto& last_row = m.m_rows.back();
for (unsigned k = static_cast<unsigned>(last_row.size()); k-- > 0;) { for (unsigned k = static_cast<unsigned>(last_row.size()); k-- > 0;) {
m.remove_element(last_row, last_row[k]); m.remove_element(last_row, last_row[k]);
} }
m.m_rows.pop_back(); m.m_rows.pop_back();
} }
void remove_entry_index(std::list<unsigned> & l, unsigned ei) { void remove_entry_index(std::list<unsigned>& l, unsigned ei) {
auto it = std::find(l.begin(), l.end(), ei); auto it = std::find(l.begin(), l.end(), ei);
if (it != l.end()) if (it != l.end())
l.erase(it); l.erase(it);
@ -714,7 +700,7 @@ namespace lp {
std_vector<constraint_index> m_explanation_of_branches; std_vector<constraint_index> m_explanation_of_branches;
void add_term_callback(const lar_term* t) { void add_term_callback(const lar_term* t) {
unsigned j = t->j(); unsigned j = t->j();
TRACE("dioph_eq", tout << "term column t->j():" << j << std::endl; lra.print_term(*t, tout) << std::endl; ); TRACE("dioph_eq", tout << "term column t->j():" << j << std::endl; lra.print_term(*t, tout) << std::endl;);
if (!lra.column_is_int(j)) { if (!lra.column_is_int(j)) {
TRACE("dioph_eq", tout << "ignored a non-integral column" << std::endl;); TRACE("dioph_eq", tout << "ignored a non-integral column" << std::endl;);
return; return;
@ -737,13 +723,13 @@ namespace lp {
return; return;
m_changed_columns.insert(j); m_changed_columns.insert(j);
auto undo = undo_fixed_column(*this, j); auto undo = undo_fixed_column(*this, j);
lra.trail().push(undo) ; lra.trail().push(undo);
} }
public: public:
imp(int_solver& lia, lar_solver& lra) : lia(lia), lra(lra) { imp(int_solver& lia, lar_solver& lra) : lia(lia), lra(lra) {
lra.m_add_term_callback=[this](const lar_term*t){add_term_callback(t);}; lra.m_add_term_callback = [this](const lar_term* t) { add_term_callback(t); };
lra.m_update_column_bound_callback = [this](unsigned j){update_column_bound_callback(j);}; lra.m_update_column_bound_callback = [this](unsigned j) { update_column_bound_callback(j); };
} }
term_o get_term_from_entry(unsigned i) const { term_o get_term_from_entry(unsigned i) const {
term_o t; term_o t;
@ -765,14 +751,13 @@ namespace lp {
void register_columns_to_term(const lar_term& t) { void register_columns_to_term(const lar_term& t) {
TRACE("dioph_eq", tout << "register term:"; lra.print_term(t, tout); tout << ", t.j()=" << t.j() << std::endl;); TRACE("dioph_eq", tout << "register term:"; lra.print_term(t, tout); tout << ", t.j()=" << t.j() << std::endl;);
for (const auto &p: t.ext_coeffs()) { for (const auto& p : t.ext_coeffs()) {
auto it = m_columns_to_terms.find(p.var()); auto it = m_columns_to_terms.find(p.var());
TRACE("dio_reg", tout << "register p.var():" << p.var() <<"->" << t.j() << std::endl; ); TRACE("dio_reg", tout << "register p.var():" << p.var() << "->" << t.j() << std::endl;);
if (it != m_columns_to_terms.end()) { if (it != m_columns_to_terms.end()) {
it->second.insert(t.j()); it->second.insert(t.j());
} } else {
else {
std::unordered_set<unsigned> s; std::unordered_set<unsigned> s;
s.insert(t.j()); s.insert(t.j());
m_columns_to_terms[p.var()] = s; m_columns_to_terms[p.var()] = s;
@ -782,16 +767,16 @@ namespace lp {
// the term has form sum(a_i*x_i) - t.j() = 0, // the term has form sum(a_i*x_i) - t.j() = 0,
void fill_entry(const lar_term& t) { void fill_entry(const lar_term& t) {
TRACE("dioph_eq", print_lar_term_L(t, tout) << std::endl;); TRACE("dioph_eq", print_lar_term_L(t, tout) << std::endl;);
unsigned entry_index = (unsigned) m_e_matrix.row_count(); unsigned entry_index = (unsigned)m_e_matrix.row_count();
m_sum_of_fixed.push_back(mpq(0)); m_sum_of_fixed.push_back(mpq(0));
mpq & e = m_sum_of_fixed.back(); mpq& e = m_sum_of_fixed.back();
SASSERT(m_l_matrix.row_count() == m_e_matrix.row_count()); SASSERT(m_l_matrix.row_count() == m_e_matrix.row_count());
// fill m_l_matrix row // fill m_l_matrix row
m_l_matrix.add_row(); m_l_matrix.add_row();
// todo: consider to compress variables t.j() by using a devoted var_register for term columns // todo: consider to compress variables t.j() by using a devoted var_register for term columns
m_l_matrix.add_columns_up_to(t.j()); m_l_matrix.add_columns_up_to(t.j());
m_l_matrix.add_new_element(entry_index, t.j(), mpq(1)); m_l_matrix.add_new_element(entry_index, t.j(), mpq(1));
// fill E-entry // fill E-entry
m_e_matrix.add_row(); m_e_matrix.add_row();
SASSERT(m_e_matrix.row_count() == m_e_matrix.row_count()); SASSERT(m_e_matrix.row_count() == m_e_matrix.row_count());
@ -814,7 +799,7 @@ namespace lp {
if (ei >= m_e_matrix.row_count()) return; if (ei >= m_e_matrix.row_count()) return;
// q is the queue of variables that can be substituted in ei // q is the queue of variables that can be substituted in ei
protected_queue q; protected_queue q;
for (const auto& p: m_e_matrix.m_rows[ei]) { for (const auto& p : m_e_matrix.m_rows[ei]) {
if (can_substitute(p.var())) if (can_substitute(p.var()))
q.push(p.var()); q.push(p.var());
} }
@ -823,23 +808,24 @@ namespace lp {
SASSERT(entry_invariant(ei)); SASSERT(entry_invariant(ei));
} }
void substitute_on_q_with_entry_in_S(protected_queue& q, unsigned ei, unsigned j, const mpq & alpha) { void substitute_on_q_with_entry_in_S(protected_queue& q, unsigned ei, unsigned j, const mpq& alpha) {
unsigned ei_to_sub = m_k2s[j]; unsigned ei_to_sub = m_k2s[j];
int sign_j = get_sign_in_e_row(ei_to_sub, j); int sign_j = get_sign_in_e_row(ei_to_sub, j);
// we need to eliminate alpha*j in ei's row // we need to eliminate alpha*j in ei's row
add_two_entries(-mpq(sign_j)*alpha, ei_to_sub, ei); add_two_entries(-mpq(sign_j) * alpha, ei_to_sub, ei);
for (const auto& p: m_e_matrix.m_rows[ei]) { for (const auto& p : m_e_matrix.m_rows[ei]) {
unsigned jj = p.var(); unsigned jj = p.var();
if (can_substitute(jj)) if (can_substitute(jj))
q.push(jj); q.push(jj);
} }
} }
void substitute_with_fresh_def(protected_queue& q, unsigned ei, unsigned j, const mpq & alpha) { void substitute_with_fresh_def(protected_queue& q, unsigned ei, unsigned j, const mpq& alpha) {
const lar_term& sub_term = m_fresh_k2xt_terms.get_by_key(j); const lar_term& sub_term = m_fresh_k2xt_terms.get_by_key(j).first;
TRACE("dioph_eq", print_lar_term_L(sub_term, tout) << std::endl;);
SASSERT(sub_term.get_coeff(j).is_one()); SASSERT(sub_term.get_coeff(j).is_one());
// we need to eliminate alpha*j in ei's row // we need to eliminate alpha*j in ei's row
add_term_to_entry(- alpha, sub_term, ei); add_term_to_entry(-alpha, sub_term, ei);
for (const auto& p: m_e_matrix.m_rows[ei]) { for (const auto& p : m_e_matrix.m_rows[ei]) {
unsigned jj = p.var(); unsigned jj = p.var();
if (can_substitute(jj)) if (can_substitute(jj))
q.push(jj); q.push(jj);
@ -847,7 +833,7 @@ namespace lp {
} }
// q is the queue of variables that can be substituted in ei // q is the queue of variables that can be substituted in ei
void substitute_on_q(protected_queue & q, unsigned ei) { void substitute_on_q(protected_queue& q, unsigned ei) {
while (!q.empty()) { while (!q.empty()) {
unsigned j = q.pop_front(); unsigned j = q.pop_front();
mpq alpha = get_coeff_in_e_row(ei, j); mpq alpha = get_coeff_in_e_row(ei, j);
@ -860,23 +846,23 @@ namespace lp {
} }
} }
bool term_is_in_range(const lar_term& t) const { bool term_is_in_range(const lar_term& t) const {
for (const auto & p: t) { for (const auto& p : t) {
if (p.var() >= m_e_matrix.column_count()) if (p.var() >= m_e_matrix.column_count())
return false; return false;
} }
return true; return true;
} }
// adds the term multiplied by coeff to m_e_matrix row i // adds the term multiplied by coeff to m_e_matrix row i
void add_term_to_entry(const mpq& coeff, const lar_term& t, unsigned i ) { void add_term_to_entry(const mpq& coeff, const lar_term& t, unsigned i) {
SASSERT(term_is_in_range(t)); SASSERT(term_is_in_range(t));
m_e_matrix.add_term_to_row(coeff, t, i); m_e_matrix.add_term_to_row(coeff, t, i);
} }
// adds entry i0 multiplied by coeff to entry i1 // adds entry i0 multiplied by coeff to entry i1
void add_two_entries(const mpq& coeff, unsigned i0, unsigned i1 ) { void add_two_entries(const mpq& coeff, unsigned i0, unsigned i1) {
m_e_matrix.add_rows(coeff, i0, i1); m_e_matrix.add_rows(coeff, i0, i1);
m_l_matrix.add_rows(coeff, i0, i1); m_l_matrix.add_rows(coeff, i0, i1);
m_sum_of_fixed[i1] += coeff* m_sum_of_fixed[i0]; m_sum_of_fixed[i1] += coeff * m_sum_of_fixed[i0];
} }
bool all_vars_are_int(const lar_term& term) const { bool all_vars_are_int(const lar_term& term) const {
@ -885,26 +871,24 @@ namespace lp {
return false; return false;
} }
return lia.column_is_int(term.j()); return lia.column_is_int(term.j());
} }
void clear_e_row(unsigned ei) { void clear_e_row(unsigned ei) {
auto & row = m_e_matrix.m_rows[ei]; auto& row = m_e_matrix.m_rows[ei];
while (row.size() > 0) { while (row.size() > 0) {
auto& c = row.back(); auto& c = row.back();
m_e_matrix.remove_element(row, c); m_e_matrix.remove_element(row, c);
} }
} }
void recalculate_entry(unsigned ei) { void recalculate_entry(unsigned ei) {
TRACE("dioph_eq", print_entry(ei, tout) << std::endl;); TRACE("dioph_eq", print_entry(ei, tout) << std::endl;);
mpq &c = m_sum_of_fixed[ei]; mpq& c = m_sum_of_fixed[ei];
c = mpq(0); c = mpq(0);
open_l_term_to_work_vector(ei, c); open_l_term_to_work_vector(ei, c);
clear_e_row(ei); clear_e_row(ei);
mpq denom(1); mpq denom(1);
for (const auto & p: m_substitution_workspace.m_data) { for (const auto& p : m_substitution_workspace.m_data) {
unsigned lj = add_var(p.var()); unsigned lj = add_var(p.var());
m_e_matrix.add_columns_up_to(lj); m_e_matrix.add_columns_up_to(lj);
m_e_matrix.add_new_element(ei, lj, p.coeff()); m_e_matrix.add_new_element(ei, lj, p.coeff());
@ -935,31 +919,48 @@ namespace lp {
for (const auto& p : m_e_matrix.column(this->lar_solver_to_local(j))) { for (const auto& p : m_e_matrix.column(this->lar_solver_to_local(j))) {
m_changed_rows.insert(p.var()); // TODO: is it necessary? m_changed_rows.insert(p.var()); // TODO: is it necessary?
} }
} }
} }
void remove_irrelevant_fresh_defs_for_row(unsigned ei) { void remove_irrelevant_fresh_defs_for_row(unsigned ei) {
auto it = m_row2fresh_defs.find(ei); auto it = m_row2fresh_defs.find(ei);
if (it == m_row2fresh_defs.end()) return; if (it == m_row2fresh_defs.end()) return;
for (unsigned xt: it->second) { for (unsigned xt : it->second) {
if (m_fresh_k2xt_terms.has_second_key(xt))
m_fresh_k2xt_terms.erase_by_second_key(xt); m_fresh_k2xt_terms.erase_by_second_key(xt);
} }
m_row2fresh_defs.erase(it); m_row2fresh_defs.erase(it);
} }
void remove_irrelevant_fresh_defs() { void remove_irrelevant_fresh_defs() {
std_vector<unsigned> xt_to_remove;
std_vector<unsigned> rows_to_remove_the_defs_from;
for (const auto& p : m_fresh_k2xt_terms.m_bij.m_rev_map) {
unsigned xt = p.first;
if (xt >= m_e_matrix.column_count()) {
xt_to_remove.push_back(xt);
rows_to_remove_the_defs_from.push_back(m_fresh_k2xt_terms.get_by_val(xt).second);
}
}
for (unsigned xt : xt_to_remove) {
m_fresh_k2xt_terms.erase_by_second_key(xt);
}
for (unsigned ei : m_changed_rows) { for (unsigned ei : m_changed_rows) {
remove_irrelevant_fresh_defs_for_row(ei); remove_irrelevant_fresh_defs_for_row(ei);
} }
for (unsigned ei : rows_to_remove_the_defs_from) {
remove_irrelevant_fresh_defs_for_row(ei);
}
} }
void process_changed_columns() { void process_changed_columns() {
find_changed_terms_and_more_changed_rows(); find_changed_terms_and_more_changed_rows();
for (unsigned j : m_changed_terms) { for (unsigned j : m_changed_terms) {
if (j >= m_l_matrix.column_count()) continue; if (j >= m_l_matrix.column_count()) continue;
for (const auto & cs: m_l_matrix.column(j)) { for (const auto& cs : m_l_matrix.column(j)) {
m_changed_rows.insert(cs.var()); m_changed_rows.insert(cs.var());
} }
} }
@ -971,7 +972,7 @@ namespace lp {
if (it == m_row2fresh_defs.end()) continue; if (it == m_row2fresh_defs.end()) continue;
for (unsigned xt : it->second) { for (unsigned xt : it->second) {
SASSERT(var_is_fresh(xt)); SASSERT(var_is_fresh(xt));
for (const auto &p :m_e_matrix.m_columns[xt]) { for (const auto& p : m_e_matrix.m_columns[xt]) {
more_changed_rows.push_back(p.var()); more_changed_rows.push_back(p.var());
} }
} }
@ -981,12 +982,9 @@ namespace lp {
m_changed_rows.insert(ei); m_changed_rows.insert(ei);
} }
remove_irrelevant_fresh_defs(); for (unsigned ei : m_changed_rows) {
for(unsigned ei : m_changed_rows) {
if (ei >= m_e_matrix.row_count()) if (ei >= m_e_matrix.row_count())
continue;; continue;
recalculate_entry(ei); recalculate_entry(ei);
if (m_e_matrix.m_columns.back().size() == 0) { if (m_e_matrix.m_columns.back().size() == 0) {
m_e_matrix.m_columns.pop_back(); m_e_matrix.m_columns.pop_back();
@ -997,6 +995,8 @@ namespace lp {
} }
} }
remove_irrelevant_fresh_defs();
eliminate_substituted_in_changed_rows(); eliminate_substituted_in_changed_rows();
m_changed_columns.reset(); m_changed_columns.reset();
SASSERT(m_changed_columns.size() == 0); SASSERT(m_changed_columns.size() == 0);
@ -1006,20 +1006,20 @@ namespace lp {
int get_sign_in_e_row(unsigned ei, unsigned j) const { int get_sign_in_e_row(unsigned ei, unsigned j) const {
const auto& row = m_e_matrix.m_rows[ei]; const auto& row = m_e_matrix.m_rows[ei];
auto it = std::find_if (row.begin(), row.end(), [j](const auto& p) {return p.var() == j;} ); auto it = std::find_if(row.begin(), row.end(), [j](const auto& p) { return p.var() == j; });
SASSERT(it != row.end() && abs(it->coeff()) == mpq(1)); SASSERT(it != row.end() && abs(it->coeff()) == mpq(1));
return it->coeff().is_pos()? 1:-1; return it->coeff().is_pos() ? 1 : -1;
} }
mpq get_coeff_in_e_row (unsigned ei, unsigned j) { mpq get_coeff_in_e_row(unsigned ei, unsigned j) {
const auto& row = m_e_matrix.m_rows[ei]; const auto& row = m_e_matrix.m_rows[ei];
auto it = std::find_if (row.begin(), row.end(), [j](const auto& p) {return p.var() == j;} ); auto it = std::find_if(row.begin(), row.end(), [j](const auto& p) { return p.var() == j; });
if (it == row.end()) return mpq(0); if (it == row.end()) return mpq(0);
return it->coeff(); return it->coeff();
} }
void eliminate_substituted_in_changed_rows() { void eliminate_substituted_in_changed_rows() {
for (unsigned ei: m_changed_rows) for (unsigned ei : m_changed_rows)
subs_entry(ei); subs_entry(ei);
} }
@ -1058,7 +1058,7 @@ namespace lp {
} }
if (belongs_to_f(ei)) { if (belongs_to_f(ei)) {
// see that all vars are substituted // see that all vars are substituted
const auto & row = m_e_matrix.m_rows[ei]; const auto& row = m_e_matrix.m_rows[ei];
for (const auto& p : row) { for (const auto& p : row) {
if (m_k2s.has_key(p.var())) { if (m_k2s.has_key(p.var())) {
/* /*
@ -1078,7 +1078,6 @@ namespace lp {
} }
} }
} }
} }
return true; return true;
} }
@ -1093,7 +1092,7 @@ namespace lp {
m_lra_level = 0; m_lra_level = 0;
process_changed_columns(); process_changed_columns();
for (const lar_term* t: m_added_terms) { for (const lar_term* t : m_added_terms) {
m_active_terms.insert(t); m_active_terms.insert(t);
fill_entry(*t); fill_entry(*t);
register_columns_to_term(*t); register_columns_to_term(*t);
@ -1161,7 +1160,7 @@ namespace lp {
// The function returns true if and only if there is no conflict. In the case of a conflict a branch // The function returns true if and only if there is no conflict. In the case of a conflict a branch
// can be returned as well. // can be returned as well.
bool normalize_e_by_gcd(unsigned ei, mpq& g) { bool normalize_e_by_gcd(unsigned ei, mpq& g) {
mpq & e = m_sum_of_fixed[ei]; mpq& e = m_sum_of_fixed[ei];
TRACE("dioph_eq", print_entry(ei, tout) << std::endl;); TRACE("dioph_eq", print_entry(ei, tout) << std::endl;);
g = gcd_of_coeffs(m_e_matrix.m_rows[ei], false); g = gcd_of_coeffs(m_e_matrix.m_rows[ei], false);
if (g.is_zero() || g.is_one()) { if (g.is_zero() || g.is_one()) {
@ -1196,14 +1195,13 @@ namespace lp {
t.c() = -c.rhs(); t.c() = -c.rhs();
} }
void subs_front_in_indexed_vector_by_fresh(unsigned k, protected_queue& q) {
void subs_front_in_indexed_vector_by_fresh(unsigned k, protected_queue &q) { const lar_term& e = m_fresh_k2xt_terms.get_by_key(k).first;
const lar_term& e = m_fresh_k2xt_terms.get_by_key(k);
TRACE("dioph_eq", tout << "k:" << k << ", in "; TRACE("dioph_eq", tout << "k:" << k << ", in ";
print_term_o(create_term_from_ind_c(), tout) << std::endl; print_term_o(create_term_from_ind_c(), tout) << std::endl;
tout << "subs with e:"; tout << "subs with e:";
print_lar_term_L(e, tout) << std::endl;); print_lar_term_L(e, tout) << std::endl;);
mpq coeff = - m_substitution_workspace[k]; // need to copy since it will be zeroed mpq coeff = -m_substitution_workspace[k]; // need to copy since it will be zeroed
m_substitution_workspace.erase(k); // m_work_vector_1[k] = 0; m_substitution_workspace.erase(k); // m_work_vector_1[k] = 0;
SASSERT(e.get_coeff(k).is_one()); SASSERT(e.get_coeff(k).is_one());
@ -1212,7 +1210,7 @@ namespace lp {
unsigned j = p.var(); unsigned j = p.var();
if (j == k) if (j == k)
continue; continue;
m_substitution_workspace.add(p.coeff()*coeff, j); m_substitution_workspace.add(p.coeff() * coeff, j);
// do we need to add j to the queue? // do we need to add j to the queue?
if (!var_is_fresh(j) && m_substitution_workspace.has(j) && can_substitute(j)) if (!var_is_fresh(j) && m_substitution_workspace.has(j) && can_substitute(j))
q.push(j); q.push(j);
@ -1225,7 +1223,7 @@ namespace lp {
} }
void add_l_row_to_term_with_index(const mpq& coeff, unsigned ei) { void add_l_row_to_term_with_index(const mpq& coeff, unsigned ei) {
for (const auto & p: m_l_matrix.m_rows[ei]) { for (const auto& p : m_l_matrix.m_rows[ei]) {
m_l_terms_workspace.add(coeff * p.coeff(), p.var()); m_l_terms_workspace.add(coeff * p.coeff(), p.var());
} }
} }
@ -1290,7 +1288,7 @@ namespace lp {
lar_term l_term_from_row(unsigned k) const { lar_term l_term_from_row(unsigned k) const {
lar_term ret; lar_term ret;
for (const auto & p: m_l_matrix.m_rows[k]) for (const auto& p : m_l_matrix.m_rows[k])
ret.add_monomial(p.coeff(), p.var()); ret.add_monomial(p.coeff(), p.var());
return ret; return ret;
@ -1357,7 +1355,7 @@ namespace lp {
break; break;
} }
} }
for (unsigned j: cleanup) { for (unsigned j : cleanup) {
m_changed_terms.remove(j); m_changed_terms.remove(j);
} }
return ret; return ret;
@ -1428,25 +1426,8 @@ namespace lp {
// term_to_lar_solver(remove_fresh_vars(create_term_from_ind_c()))) // term_to_lar_solver(remove_fresh_vars(create_term_from_ind_c())))
// enable_trace("dioph_eq"); // enable_trace("dioph_eq");
TRACE("dioph_eq_deb_subs", tout << "after subs\n"; TRACE("dioph_eq_deb_subs", tout << "after subs\n"; print_term_o(create_term_from_ind_c(), tout) << std::endl; tout << "term_to_tighten:"; print_lar_term_L(term_to_tighten, tout) << std::endl; tout << "m_tmp_l:"; print_lar_term_L(m_l_terms_workspace.to_term(), tout) << std::endl; tout << "open_ml:"; print_lar_term_L(open_ml(m_l_terms_workspace.to_term()), tout) << std::endl; tout << "term_to_tighten + open_ml:"; print_term_o(term_to_tighten + open_ml(m_l_terms_workspace.to_term()), tout) << std::endl; term_o ls = fix_vars(term_to_tighten + open_ml(m_l_terms_workspace.to_term())); tout << "ls:"; print_term_o(ls, tout) << std::endl; term_o rs = term_to_lar_solver(remove_fresh_vars(create_term_from_ind_c())); tout << "rs:"; print_term_o(rs, tout) << std::endl; term_o diff = ls - rs; if (!diff.is_empty()) {
print_term_o(create_term_from_ind_c(), tout) << std::endl; tout << "diff:"; print_term_o(diff, tout ) << std::endl; });
tout << "term_to_tighten:";
print_lar_term_L(term_to_tighten, tout) << std::endl;
tout << "m_tmp_l:"; print_lar_term_L(m_l_terms_workspace.to_term(), tout) << std::endl;
tout << "open_ml:";
print_lar_term_L(open_ml(m_l_terms_workspace.to_term()), tout) << std::endl;
tout << "term_to_tighten + open_ml:";
print_term_o(term_to_tighten + open_ml(m_l_terms_workspace.to_term()), tout)
<< std::endl;
term_o ls = fix_vars(term_to_tighten + open_ml(m_l_terms_workspace.to_term()));
tout << "ls:"; print_term_o(ls,tout) << std::endl;
term_o rs = term_to_lar_solver(remove_fresh_vars(create_term_from_ind_c()));
tout << "rs:"; print_term_o(rs, tout ) << std::endl;
term_o diff = ls - rs;
if (!diff.is_empty()) {
tout << "diff:"; print_term_o(diff, tout ) << std::endl;
}
);
SASSERT( SASSERT(
fix_vars(term_to_tighten + open_ml(m_l_terms_workspace.to_term())) == fix_vars(term_to_tighten + open_ml(m_l_terms_workspace.to_term())) ==
@ -1574,7 +1555,8 @@ namespace lp {
return true; return true;
} }
template <typename T> u_dependency* explain_fixed_in_meta_term (const T& t) { template <typename T>
u_dependency* explain_fixed_in_meta_term(const T& t) {
return explain_fixed(open_ml(t)); return explain_fixed(open_ml(t));
} }
@ -1591,7 +1573,8 @@ namespace lp {
} }
lia_move process_f() { lia_move process_f() {
while (rewrite_eqs()) {} while (rewrite_eqs()) {
}
if (m_conflict_index != UINT_MAX) { if (m_conflict_index != UINT_MAX) {
lra.stats().m_dio_rewrite_conflicts++; lra.stats().m_dio_rewrite_conflicts++;
return lia_move::conflict; return lia_move::conflict;
@ -1636,10 +1619,10 @@ namespace lp {
mpq c = m_sum_of_fixed[ei]; mpq c = m_sum_of_fixed[ei];
for (const auto& p : m_e_matrix.m_rows[m_k2s[j]]) { for (const auto& p : m_e_matrix.m_rows[m_k2s[j]]) {
if (p.var() == j) { if (p.var() == j) {
const mpq & j_coeff = p.coeff(); const mpq& j_coeff = p.coeff();
SASSERT(j_coeff.is_one() || j_coeff.is_minus_one()); SASSERT(j_coeff.is_one() || j_coeff.is_minus_one());
c += j_coeff * lra.get_lower_bound(local_to_lar_solver(j)).x; c += j_coeff * lra.get_lower_bound(local_to_lar_solver(j)).x;
TRACE("dio_br", tout << "the value of the vixed var is:" << lra.get_lower_bound(local_to_lar_solver(j)).x<<", m_sum_of_fixed[" << ei << "]:" << m_sum_of_fixed[ei] << ", new free coeff c:" << c << std::endl;); TRACE("dio_br", tout << "the value of the vixed var is:" << lra.get_lower_bound(local_to_lar_solver(j)).x << ", m_sum_of_fixed[" << ei << "]:" << m_sum_of_fixed[ei] << ", new free coeff c:" << c << std::endl;);
continue; continue;
} }
if (g.is_zero()) { if (g.is_zero()) {
@ -1649,7 +1632,7 @@ namespace lp {
} }
if (g.is_one()) return lia_move::undef; if (g.is_one()) return lia_move::undef;
} }
if (!(c/g).is_int()) { if (!(c / g).is_int()) {
return lia_move::conflict; return lia_move::conflict;
} }
return lia_move::undef; return lia_move::undef;
@ -1662,7 +1645,8 @@ namespace lp {
*/ */
if (m_k2s.has_key(j)) { // j is substituted but using an entry if (m_k2s.has_key(j)) { // j is substituted but using an entry
TRACE("dio_br", TRACE("dio_br",
tout << "fixed j:" << j <<", was substited by "; print_entry(m_k2s[j], tout);); tout << "fixed j:" << j << ", was substited by ";
print_entry(m_k2s[j], tout););
if (check_fixing(j) == lia_move::conflict) { if (check_fixing(j) == lia_move::conflict) {
for (auto ci : lra.flatten(explain_fixed_in_meta_term(m_l_matrix.m_rows[m_k2s[j]]))) { for (auto ci : lra.flatten(explain_fixed_in_meta_term(m_l_matrix.m_rows[m_k2s[j]]))) {
m_explanation_of_branches.push_back(ci); m_explanation_of_branches.push_back(ci);
@ -1674,7 +1658,7 @@ namespace lp {
} }
void undo_branching() { void undo_branching() {
while (m_lra_level --) { while (m_lra_level--) {
lra.pop(); lra.pop();
} }
lra.find_feasible_solution(); lra.find_feasible_solution();
@ -1697,14 +1681,14 @@ namespace lp {
} else { } else {
lra.add_var_bound(b.m_j, lconstraint_kind::GE, b.m_rs + mpq(1)); lra.add_var_bound(b.m_j, lconstraint_kind::GE, b.m_rs + mpq(1));
} }
TRACE("dio_br", lra.print_column_info(b.m_j, tout) <<"add bound" << std::endl;); TRACE("dio_br", lra.print_column_info(b.m_j, tout) << "add bound" << std::endl;);
if (lra.column_is_fixed(b.m_j)) { if (lra.column_is_fixed(b.m_j)) {
unsigned local_bj; unsigned local_bj;
if (! m_var_register.external_is_used(b.m_j, local_bj)) if (!m_var_register.external_is_used(b.m_j, local_bj))
return lia_move::undef; return lia_move::undef;
if (fix_var(local_bj) == lia_move::conflict) { if (fix_var(local_bj) == lia_move::conflict) {
TRACE("dio_br", tout << "conflict in fix_var" << std::endl;) ; TRACE("dio_br", tout << "conflict in fix_var" << std::endl;);
return lia_move::conflict; return lia_move::conflict;
} }
} }
@ -1731,7 +1715,6 @@ namespace lp {
if (this->lra.constraints().valid_index(ci)) if (this->lra.constraints().valid_index(ci))
m_infeas_explanation.push_back(ci); m_infeas_explanation.push_back(ci);
} }
} }
lia_move branching_on_undef() { lia_move branching_on_undef() {
@ -1800,7 +1783,7 @@ namespace lp {
} }
unsigned get_number_of_int_inf() const { unsigned get_number_of_int_inf() const {
return (unsigned) std::count_if( return (unsigned)std::count_if(
lra.r_basis().begin(), lra.r_basis().end(), lra.r_basis().begin(), lra.r_basis().end(),
[this](unsigned j) { [this](unsigned j) {
return lia.column_is_int_inf(j); return lia.column_is_int_inf(j);
@ -1826,7 +1809,6 @@ namespace lp {
} }
} }
branch create_branch() { branch create_branch() {
unsigned bj = UINT_MAX; unsigned bj = UINT_MAX;
double score = std::numeric_limits<double>::infinity(); double score = std::numeric_limits<double>::infinity();
@ -1868,11 +1850,11 @@ namespace lp {
bool columns_to_terms_is_correct() const { bool columns_to_terms_is_correct() const {
std::unordered_map<unsigned, std::unordered_set<unsigned>> c2t; std::unordered_map<unsigned, std::unordered_set<unsigned>> c2t;
for (unsigned k = 0; k < lra.terms().size(); k ++ ) { for (unsigned k = 0; k < lra.terms().size(); k++) {
const lar_term* t = lra.terms()[k]; const lar_term* t = lra.terms()[k];
if (!all_vars_are_int(*t)) continue; if (!all_vars_are_int(*t)) continue;
SASSERT(t->j() != UINT_MAX); SASSERT(t->j() != UINT_MAX);
for (const auto& p: (*t).ext_coeffs()) { for (const auto& p : (*t).ext_coeffs()) {
unsigned j = p.var(); unsigned j = p.var();
auto it = c2t.find(j); auto it = c2t.find(j);
if (it == c2t.end()) { if (it == c2t.end()) {
@ -1882,42 +1864,25 @@ namespace lp {
} else { } else {
it->second.insert(t->j()); it->second.insert(t->j());
} }
} }
} }
for (const auto & p : c2t) { for (const auto& p : c2t) {
unsigned j = p.first; unsigned j = p.first;
const auto it = m_columns_to_terms.find(j); const auto it = m_columns_to_terms.find(j);
if (it == m_columns_to_terms.end()) { if (it == m_columns_to_terms.end()) {
TRACE("dioph_eq", tout << "column j" << j << " is not registered" << std::endl; TRACE("dioph_eq", tout << "column j" << j << " is not registered" << std::endl; tout << "the column belongs to the the following terms:"; for (unsigned tj : p.second) { tout << " " << tj; } tout << std::endl;);
tout << "the column belongs to the the following terms:";
for (unsigned tj : p.second) {
tout << " " << tj;
}
tout << std::endl;
);
return false; return false;
} }
if (it->second != p.second) { if (it->second != p.second) {
TRACE("dioph_eq_deb", tout << "m_columns_to_terms[" << j << "] has to be "; TRACE("dioph_eq_deb", tout << "m_columns_to_terms[" << j << "] has to be "; tout << "{"; for (unsigned lll : p.second) { tout << lll << ", "; } tout << "}, \nbut it is {"; for (unsigned lll : it->second) { tout << lll << ", "; }; tout << "}" << std::endl;
tout << "{";
for(unsigned lll : p.second) {
tout << lll << ", ";
}
tout << "}, \nbut it is {";
for (unsigned lll : it->second) {
tout << lll << ", ";
};
tout << "}" << std::endl;
); );
return false; return false;
} }
} }
// reverse inclusion // reverse inclusion
for (const auto & p : m_columns_to_terms) { for (const auto& p : m_columns_to_terms) {
unsigned j = p.first; unsigned j = p.first;
const auto it = c2t.find(j); const auto it = c2t.find(j);
if (it == c2t.end()) { if (it == c2t.end()) {
@ -1941,10 +1906,10 @@ namespace lp {
} }
} }
for (unsigned ei = 0; ei < m_e_matrix.row_count(); ei++ ) { for (unsigned ei = 0; ei < m_e_matrix.row_count(); ei++) {
auto it = m_row2fresh_defs.find(ei); auto it = m_row2fresh_defs.find(ei);
if (it != m_row2fresh_defs.end()) { if (it != m_row2fresh_defs.end()) {
for (unsigned xt: it->second) { for (unsigned xt : it->second) {
if (!m_fresh_k2xt_terms.has_second_key(xt)) if (!m_fresh_k2xt_terms.has_second_key(xt))
return false; return false;
} }
@ -1970,7 +1935,7 @@ namespace lp {
return ret; return ret;
} }
SASSERT(ret == lia_move::undef); SASSERT(ret == lia_move::undef);
m_max_of_branching_iterations = (unsigned)m_max_of_branching_iterations/2; m_max_of_branching_iterations = (unsigned)m_max_of_branching_iterations / 2;
return lia_move::undef; return lia_move::undef;
} }
@ -2021,7 +1986,7 @@ namespace lp {
} }
bool j_sign_is_correct(unsigned ei, unsigned j, int j_sign) { bool j_sign_is_correct(unsigned ei, unsigned j, int j_sign) {
const auto& row = m_e_matrix.m_rows[ei]; const auto& row = m_e_matrix.m_rows[ei];
auto it = std::find_if (row.begin(), row.end(), [j](const auto& p) {return p.var() == j;} ); auto it = std::find_if(row.begin(), row.end(), [j](const auto& p) { return p.var() == j; });
if (it == row.end()) return false; if (it == row.end()) return false;
return (it->coeff() == mpq(1) && j_sign == 1) || return (it->coeff() == mpq(1) && j_sign == 1) ||
(it->coeff() == mpq(-1) && j_sign == -1); (it->coeff() == mpq(-1) && j_sign == -1);
@ -2030,7 +1995,7 @@ namespace lp {
// a coefficient equal to j_sign which is +-1 // a coefficient equal to j_sign which is +-1
void eliminate_var_in_f(unsigned ei, unsigned j, int j_sign) { void eliminate_var_in_f(unsigned ei, unsigned j, int j_sign) {
SASSERT(belongs_to_s(ei)); SASSERT(belongs_to_s(ei));
const auto & e = m_sum_of_fixed[ei]; const auto& e = m_sum_of_fixed[ei];
SASSERT(j_sign_is_correct(ei, j, j_sign)); SASSERT(j_sign_is_correct(ei, j, j_sign));
TRACE("dioph_eq", tout << "eliminate var:" << j << " by using:"; TRACE("dioph_eq", tout << "eliminate var:" << j << " by using:";
print_entry(ei, tout) << std::endl;); print_entry(ei, tout) << std::endl;);
@ -2040,7 +2005,7 @@ namespace lp {
[ei](const auto& cell) { [ei](const auto& cell) {
return cell.var() == ei; return cell.var() == ei;
}); });
unsigned pivot_col_cell_index = (unsigned) std::distance(column.begin(), it); unsigned pivot_col_cell_index = (unsigned)std::distance(column.begin(), it);
if (pivot_col_cell_index != 0) { if (pivot_col_cell_index != 0) {
// swap the pivot column cell with the head cell // swap the pivot column cell with the head cell
auto c = column[0]; auto c = column[0];
@ -2067,8 +2032,8 @@ namespace lp {
print_entry(i, tout) << std::endl;); print_entry(i, tout) << std::endl;);
m_sum_of_fixed[i] -= j_sign * coeff * e; m_sum_of_fixed[i] -= j_sign * coeff * e;
m_e_matrix.pivot_row_to_row_given_cell_with_sign(ei, c, j, j_sign); m_e_matrix.pivot_row_to_row_given_cell_with_sign(ei, c, j, j_sign);
//m_sum_of_fixed[i].m_l -= j_sign * coeff * e.m_l; // m_sum_of_fixed[i].m_l -= j_sign * coeff * e.m_l;
m_l_matrix.add_rows( -j_sign*coeff, ei, i); m_l_matrix.add_rows(-j_sign * coeff, ei, i);
TRACE("dioph_eq", tout << "after pivoting c_row:"; TRACE("dioph_eq", tout << "after pivoting c_row:";
print_entry(i, tout);); print_entry(i, tout););
CTRACE( CTRACE(
@ -2114,7 +2079,7 @@ namespace lp {
bool is_eliminated_from_f(unsigned j) const { bool is_eliminated_from_f(unsigned j) const {
for (unsigned ei = 0; ei < m_e_matrix.row_count(); ei++) { for (unsigned ei = 0; ei < m_e_matrix.row_count(); ei++) {
if (!belongs_to_f(ei)) continue; if (!belongs_to_f(ei)) continue;
const auto &row = m_e_matrix.m_rows[ei]; const auto& row = m_e_matrix.m_rows[ei];
for (const auto& p : row) { for (const auto& p : row) {
if (p.var() == j) { if (p.var() == j) {
return false; return false;
@ -2145,7 +2110,7 @@ namespace lp {
get_sign_in_e_row(ei, j); get_sign_in_e_row(ei, j);
} }
for (const auto &p: m_e_matrix.m_rows[ei]) { for (const auto& p : m_e_matrix.m_rows[ei]) {
if (!p.coeff().is_int()) { if (!p.coeff().is_int()) {
return false; return false;
} }
@ -2155,20 +2120,20 @@ namespace lp {
term_to_lar_solver(remove_fresh_vars(get_term_from_entry(ei))) == term_to_lar_solver(remove_fresh_vars(get_term_from_entry(ei))) ==
fix_vars(open_ml(m_l_matrix.m_rows[ei])); fix_vars(open_ml(m_l_matrix.m_rows[ei]));
CTRACE( "dioph_deb_eq", !ret, CTRACE("dioph_deb_eq", !ret,
{ {
tout << "get_term_from_entry(" << ei << "):"; tout << "get_term_from_entry(" << ei << "):";
print_term_o(get_term_from_entry(ei), tout) << std::endl; print_term_o(get_term_from_entry(ei), tout) << std::endl;
tout << "ls:"; tout << "ls:";
print_term_o(remove_fresh_vars(get_term_from_entry(ei)), tout) print_term_o(remove_fresh_vars(get_term_from_entry(ei)), tout)
<< std::endl; << std::endl;
tout << "e.m_l:"; print_lar_term_L(l_term_from_row(ei), tout) << std::endl; tout << "e.m_l:";
print_lar_term_L(l_term_from_row(ei), tout) << std::endl;
tout << "open_ml(e.m_l):"; tout << "open_ml(e.m_l):";
print_lar_term_L(open_ml(l_term_from_row(ei)), tout) << std::endl; print_lar_term_L(open_ml(l_term_from_row(ei)), tout) << std::endl;
tout << "rs:"; tout << "rs:";
print_term_o(fix_vars(open_ml(m_l_matrix.m_rows[ei])), tout) << std::endl; print_term_o(fix_vars(open_ml(m_l_matrix.m_rows[ei])), tout) << std::endl;
} });
);
return ret; return ret;
} }
@ -2183,7 +2148,7 @@ namespace lp {
} }
while (!q.empty()) { while (!q.empty()) {
unsigned xt = q.pop_front(); // xt is a fresh var unsigned xt = q.pop_front(); // xt is a fresh var
const lar_term& fresh_t = m_fresh_k2xt_terms.get_by_val(xt); const lar_term& fresh_t = m_fresh_k2xt_terms.get_by_val(xt).first;
TRACE("dioph_eq", print_lar_term_L(fresh_t, tout);); TRACE("dioph_eq", print_lar_term_L(fresh_t, tout););
SASSERT(fresh_t.get_coeff(xt).is_minus_one()); SASSERT(fresh_t.get_coeff(xt).is_minus_one());
if (!t.contains(xt)) if (!t.contains(xt))
@ -2196,7 +2161,6 @@ namespace lp {
q.push(p.j()); q.push(p.j());
} }
} }
} }
return t; return t;
} }
@ -2206,7 +2170,8 @@ namespace lp {
return print_lar_term_L(opened_ml, out); return print_lar_term_L(opened_ml, out);
} }
template <typename T> term_o open_ml(const T& ml) const { template <typename T>
term_o open_ml(const T& ml) const {
term_o r; term_o r;
for (const auto& p : ml) { for (const auto& p : ml) {
r += p.coeff() * (lra.get_term(p.var()) - lar_term(p.var())); r += p.coeff() * (lra.get_term(p.var()) - lar_term(p.var()));
@ -2216,11 +2181,11 @@ namespace lp {
void open_l_term_to_work_vector(unsigned ei, mpq& c) { void open_l_term_to_work_vector(unsigned ei, mpq& c) {
m_substitution_workspace.clear(); m_substitution_workspace.clear();
for (const auto & p: m_l_matrix.m_rows[ei]) { for (const auto& p : m_l_matrix.m_rows[ei]) {
const lar_term& t = lra.get_term(p.var()); const lar_term& t = lra.get_term(p.var());
for (const auto & q: t.ext_coeffs()) { for (const auto& q : t.ext_coeffs()) {
if (is_fixed(q.var())) { if (is_fixed(q.var())) {
c += p.coeff()*q.coeff()*lia.lower_bound(q.var()).x; c += p.coeff() * q.coeff() * lia.lower_bound(q.var()).x;
} else { } else {
m_substitution_workspace.add(p.coeff() * q.coeff(), q.var()); m_substitution_workspace.add(p.coeff() * q.coeff(), q.var());
} }
@ -2268,7 +2233,7 @@ namespace lp {
fresh_t.add_monomial(-mpq(1), xt); fresh_t.add_monomial(-mpq(1), xt);
fresh_t.add_monomial(mpq(1), k); fresh_t.add_monomial(mpq(1), k);
for (const auto& i : m_e_matrix.m_rows[h]) { for (const auto& i : m_e_matrix.m_rows[h]) {
const mpq &ai = i.coeff(); const mpq& ai = i.coeff();
if (i.var() == k) if (i.var() == k)
continue; continue;
q = machine_div_rem(ai, ahk, r); q = machine_div_rem(ai, ahk, r);
@ -2276,7 +2241,7 @@ namespace lp {
fresh_t.add_monomial(q, i.var()); fresh_t.add_monomial(q, i.var());
} }
m_fresh_k2xt_terms.add(k, xt, fresh_t); m_fresh_k2xt_terms.add(k, xt, std::make_pair(fresh_t, h));
SASSERT(var_is_fresh(xt)); SASSERT(var_is_fresh(xt));
register_var_in_fresh_defs(h, xt); register_var_in_fresh_defs(h, xt);
eliminate_var_in_f_with_term(fresh_t, k, 1); eliminate_var_in_f_with_term(fresh_t, k, 1);
@ -2297,8 +2262,9 @@ namespace lp {
print_deps(out, explain_fixed_in_meta_term(l_term)); print_deps(out, explain_fixed_in_meta_term(l_term));
out << "}\n"; out << "}\n";
} }
if (belongs_to_f(i)) { out << "in F\n"; } if (belongs_to_f(i)) {
else { out << "in F\n";
} else {
unsigned j = m_k2s.get_key(i); unsigned j = m_k2s.get_key(i);
if (local_to_lar_solver(j) == UINT_MAX) { if (local_to_lar_solver(j) == UINT_MAX) {
out << "FRESH\n"; out << "FRESH\n";
@ -2332,7 +2298,7 @@ namespace lp {
mpq the_smallest_ahk; mpq the_smallest_ahk;
unsigned kh; unsigned kh;
int kh_sign; int kh_sign;
for (unsigned ei=0; ei < m_e_matrix.row_count(); ei++) { for (unsigned ei = 0; ei < m_e_matrix.row_count(); ei++) {
if (belongs_to_s(ei)) continue; if (belongs_to_s(ei)) continue;
if (m_e_matrix.m_rows[ei].size() == 0) { if (m_e_matrix.m_rows[ei].size() == 0) {
if (m_sum_of_fixed[ei].is_zero()) { if (m_sum_of_fixed[ei].is_zero()) {
@ -2355,7 +2321,7 @@ namespace lp {
m_conflict_index = ei; m_conflict_index = ei;
return false; return false;
} }
if (!gcd.is_one()){ if (!gcd.is_one()) {
ahk /= gcd; ahk /= gcd;
if (ahk.is_one()) { if (ahk.is_one()) {
TRACE("dioph_eq", tout << "push to S:\n"; print_entry(ei, tout);); TRACE("dioph_eq", tout << "push to S:\n"; print_entry(ei, tout););
@ -2408,7 +2374,6 @@ namespace lp {
SASSERT(!ret || m_var_register.local_to_external(j) == UINT_MAX); SASSERT(!ret || m_var_register.local_to_external(j) == UINT_MAX);
return ret; return ret;
} }
}; };
// Constructor definition // Constructor definition
dioph_eq::dioph_eq(int_solver& lia) { dioph_eq::dioph_eq(int_solver& lia) {
@ -2427,4 +2392,3 @@ namespace lp {
} }
} // namespace lp } // namespace lp