3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-28 19:35:50 +00:00
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2021-08-12 19:40:33 -07:00
parent cdbd121b5e
commit bd2e73014c
3 changed files with 49 additions and 53 deletions

View file

@ -331,8 +331,7 @@ namespace polysat {
bool eliminate_var( bool eliminate_var(
row const& r_y, row const& r_y,
row const& r_z, col_iterator const& z_col,
numeral const& c,
unsigned tz_b, unsigned tz_b,
numeral const& old_value_y); numeral const& old_value_y);
}; };

View file

@ -172,7 +172,6 @@ namespace polysat {
} }
} }
SASSERT(well_formed()); SASSERT(well_formed());
std::cout << "non-integral: " << m_num_non_integral << "\n";
if (ineqs_are_violated()) if (ineqs_are_violated())
return l_false; return l_false;
if (ineqs_are_satisfied() && m_num_non_integral == 0) if (ineqs_are_satisfied() && m_num_non_integral == 0)
@ -257,9 +256,8 @@ namespace polysat {
for (auto col : M.col_entries(v)) { for (auto col : M.col_entries(v)) {
if (r.id() == col.get_row().id()) if (r.id() == col.get_row().id())
continue; continue;
numeral c = col.get_row_entry().coeff();
numeral value_v = value(v); numeral value_v = value(v);
if (!eliminate_var(r, col.get_row(), c, tz_b, value_v)) if (!eliminate_var(r, col, tz_b, value_v))
return false; return false;
} }
return true; return true;
@ -365,17 +363,12 @@ namespace polysat {
numeral new_value = m_vars[x].closest_value(value(x)); numeral new_value = m_vars[x].closest_value(value(x));
numeral b; numeral b;
var_t y = select_pivot_core(x, new_value, b); var_t y = select_pivot_core(x, new_value, b);
if (y != null_var)
if (y == null_var) { return pivot(x, y, b, new_value), l_true;
if (is_infeasible_row(x)) else if (is_infeasible_row(x))
return l_false; return l_false;
else else
return l_undef; return l_undef;
}
pivot(x, y, b, new_value);
return l_true;
} }
template<typename Ext> template<typename Ext>
@ -600,6 +593,13 @@ namespace polysat {
template<typename Ext> template<typename Ext>
void fixplex<Ext>::add_ineq(var_t v, var_t w, unsigned dep, bool strict) { void fixplex<Ext>::add_ineq(var_t v, var_t w, unsigned dep, bool strict) {
if (inconsistent())
return;
if (v == w) {
if (strict)
conflict(mk_leaf(dep));
return;
}
ensure_var(v); ensure_var(v);
ensure_var(w); ensure_var(w);
unsigned idx = m_ineqs.size(); unsigned idx = m_ineqs.size();
@ -683,7 +683,6 @@ namespace polysat {
return false; return false;
} }
/** /**
* Check if the coefficient b of y has the minimal number of trailing zeros. * Check if the coefficient b of y has the minimal number of trailing zeros.
* In other words, the coefficient b is a multiple of the smallest power of 2. * In other words, the coefficient b is a multiple of the smallest power of 2.
@ -799,17 +798,17 @@ namespace polysat {
*/ */
template<typename Ext> template<typename Ext>
void fixplex<Ext>::pivot(var_t x, var_t y, numeral const& b, numeral const& new_value) { void fixplex<Ext>::pivot(var_t x, var_t y, numeral const& b, numeral const& new_value) {
++m_stats.m_num_pivots; ++m_stats.m_num_pivots;
TRACE("fixplex", tout << "pivot " << x << " " << y << "\n";);
SASSERT(is_base(x)); SASSERT(is_base(x));
SASSERT(!is_base(y)); SASSERT(!is_base(y));
var_info& xI = m_vars[x]; var_info& xI = m_vars[x];
var_info& yI = m_vars[y]; var_info& yI = m_vars[y];
unsigned rx = xI.m_base2row; unsigned rx = xI.m_base2row;
auto& row_x = m_rows[rx]; auto& row_x = m_rows[rx];
row r_x(rx);
numeral const& a = row_x.m_base_coeff; numeral const& a = row_x.m_base_coeff;
numeral old_value_y = yI.m_value; numeral old_value_y = yI.m_value;
TRACE("fixplex", display_row(tout << "pivot " << x << " " << y << "\n", r_x););
row_x.m_base = y; row_x.m_base = y;
row_x.m_value = row_x.m_value - b * old_value_y + a * new_value; row_x.m_value = row_x.m_value - b * old_value_y + a * new_value;
row_x.m_base_coeff = b; row_x.m_base_coeff = b;
@ -819,20 +818,18 @@ namespace polysat {
xI.m_is_base = false; xI.m_is_base = false;
xI.m_value = new_value; xI.m_value = new_value;
touch_var(x); touch_var(x);
row r_x(rx);
add_patch(y); add_patch(y);
SASSERT(well_formed_row(r_x)); SASSERT(well_formed_row(r_x));
unsigned tz_b = m.trailing_zeros(b); unsigned tz_b = m.trailing_zeros(b);
for (auto col : M.col_entries(y)) { for (auto const& col : M.col_entries(y)) {
row r_z = col.get_row(); row r_z = col.get_row();
unsigned rz = r_z.id(); unsigned rz = r_z.id();
if (rz == rx) if (rz == rx)
continue; continue;
TRACE("fixplex,", display_row(tout << "eliminate ", r_z, false) << "\n";); TRACE("fixplex,", display_row(tout << "eliminate ", r_z, false) << "\n";);
numeral c = col.get_row_entry().coeff(); VERIFY(eliminate_var(r_x, col, tz_b, old_value_y));
VERIFY(eliminate_var(r_x, r_z, c, tz_b, old_value_y));
TRACE("fixplex,", display_row(tout << "eliminated ", r_z, false) << "\n";); TRACE("fixplex,", display_row(tout << "eliminated ", r_z, false) << "\n";);
add_patch(row2base(r_z)); add_patch(row2base(r_z));
} }
@ -841,37 +838,34 @@ namespace polysat {
/** /**
* r_y - row where y is base variable * r_y - row where y is base variable
* r_z - row that contains y with z base variable, z != y * z_col - column iterator that contains row where z is base variable.
* c - coefficient of y in r_z
* tz_b - number of trailing zeros to coefficient of y in r_y * tz_b - number of trailing zeros to coefficient of y in r_y
* old_value_y - the value of y used to compute row2value(r_z) * old_value_y - the value of y used to compute row2value(r_z)
* *
* Implied variables:
* r_z - row that contains y with z base variable, z != y
* c - coefficient of y in r_z
*
* returns true if elimination preserves equivalence (is lossless). * returns true if elimination preserves equivalence (is lossless).
*/ */
template<typename Ext> template<typename Ext>
bool fixplex<Ext>::eliminate_var( bool fixplex<Ext>::eliminate_var(
row const& r_y, row const& r_y,
row const& r_z, col_iterator const& z_col,
numeral const& c,
unsigned tz_b, unsigned tz_b,
numeral const& old_value_y) { numeral const& old_value_y) {
row const& r_z = z_col.get_row();
numeral c = z_col.get_row_entry().coeff();
numeral b = row2base_coeff(r_y); numeral b = row2base_coeff(r_y);
auto z = row2base(r_z); auto z = row2base(r_z);
auto& row_z = m_rows[r_z.id()];
unsigned tz_c = m.trailing_zeros(c); unsigned tz_c = m.trailing_zeros(c);
numeral b1, c1; unsigned tz = std::min(tz_b, tz_c);
if (tz_b <= tz_c) { numeral b1 = b >> tz;
b1 = b >> tz_b; numeral c1 = 0 - (c >> tz);
c1 = 0 - (c >> tz_b);
}
else {
b1 = b >> tz_c;
c1 = 0 - (c >> tz_c);
}
M.mul(r_z, b1); M.mul(r_z, b1);
M.add(r_z, c1, r_y); M.add(r_z, c1, r_y);
auto& row_z = m_rows[r_z.id()];
row_z.m_value = (b1 * (row2value(r_z) - c * old_value_y)) + c1 * row2value(r_y); row_z.m_value = (b1 * (row2value(r_z) - c * old_value_y)) + c1 * row2value(r_y);
row_z.m_base_coeff *= b1; row_z.m_base_coeff *= b1;
set_base_value(z); set_base_value(z);

View file

@ -32,6 +32,8 @@ namespace simplex {
typedef typename Ext::manager manager; typedef typename Ext::manager manager;
typedef unsigned var_t; typedef unsigned var_t;
struct column;
class row_entry { class row_entry {
friend class sparse_matrix; friend class sparse_matrix;
numeral m_coeff; numeral m_coeff;
@ -85,8 +87,7 @@ namespace simplex {
col_entry(): m_row_id(0), m_row_idx(0) {} col_entry(): m_row_id(0), m_row_idx(0) {}
bool is_dead() const { return (unsigned) m_row_id == dead_id; } bool is_dead() const { return (unsigned) m_row_id == dead_id; }
}; };
struct column;
/** /**
\brief A row contains a base variable and set of \brief A row contains a base variable and set of
@ -110,29 +111,31 @@ namespace simplex {
int get_idx_of(var_t v) const; int get_idx_of(var_t v) const;
}; };
/** /**
\brief A column stores in which rows a variable occurs. \brief A column stores in which rows a variable occurs.
The column may have free/dead entries. The field m_first_free_idx The column may have free/dead entries. The field m_first_free_idx
is a reference to the first free/dead entry. is a reference to the first free/dead entry.
*/ */
struct column { struct column {
svector<col_entry> m_entries; svector<col_entry> m_entries;
unsigned m_size; unsigned m_size;
int m_first_free_idx; int m_first_free_idx;
mutable unsigned m_refs; mutable unsigned m_refs;
column():m_size(0), m_first_free_idx(-1), m_refs(0) {} column() :m_size(0), m_first_free_idx(-1), m_refs(0) {}
unsigned size() const { return m_size; } unsigned size() const { return m_size; }
unsigned num_entries() const { return m_entries.size(); } unsigned num_entries() const { return m_entries.size(); }
void reset(); void reset();
void compress(vector<_row> & rows); void compress(vector<_row>& rows);
void compress_if_needed(vector<_row> & rows); void compress_if_needed(vector<_row>& rows);
//void compress_singleton(vector<_row> & rows, unsigned singleton_pos); //void compress_singleton(vector<_row> & rows, unsigned singleton_pos);
col_entry const * get_first_col_entry() const; col_entry const* get_first_col_entry() const;
col_entry & add_col_entry(int & pos_idx); col_entry& add_col_entry(int& pos_idx);
void del_col_entry(unsigned idx); void del_col_entry(unsigned idx);
}; };
manager& m; manager& m;
vector<_row> m_rows; vector<_row> m_rows;
svector<unsigned> m_dead_rows; // rows to recycle svector<unsigned> m_dead_rows; // rows to recycle
@ -258,7 +261,7 @@ namespace simplex {
row get_row() const { row get_row() const {
return row(col().m_entries[m_curr].m_row_id); return row(col().m_entries[m_curr].m_row_id);
} }
row_entry const& get_row_entry() { row_entry const& get_row_entry() const {
col_entry const& c = col().m_entries[m_curr]; col_entry const& c = col().m_entries[m_curr];
int row_id = c.m_row_id; int row_id = c.m_row_id;
return m_sm.m_rows[row_id].m_entries[c.m_row_idx]; return m_sm.m_rows[row_id].m_entries[c.m_row_idx];