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(
row const& r_y,
row const& r_z,
numeral const& c,
col_iterator const& z_col,
unsigned tz_b,
numeral const& old_value_y);
};

View file

@ -172,7 +172,6 @@ namespace polysat {
}
}
SASSERT(well_formed());
std::cout << "non-integral: " << m_num_non_integral << "\n";
if (ineqs_are_violated())
return l_false;
if (ineqs_are_satisfied() && m_num_non_integral == 0)
@ -257,9 +256,8 @@ namespace polysat {
for (auto col : M.col_entries(v)) {
if (r.id() == col.get_row().id())
continue;
numeral c = col.get_row_entry().coeff();
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 true;
@ -365,17 +363,12 @@ namespace polysat {
numeral new_value = m_vars[x].closest_value(value(x));
numeral b;
var_t y = select_pivot_core(x, new_value, b);
if (y == null_var) {
if (is_infeasible_row(x))
return l_false;
else
return l_undef;
}
pivot(x, y, b, new_value);
return l_true;
if (y != null_var)
return pivot(x, y, b, new_value), l_true;
else if (is_infeasible_row(x))
return l_false;
else
return l_undef;
}
template<typename Ext>
@ -600,6 +593,13 @@ namespace polysat {
template<typename Ext>
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(w);
unsigned idx = m_ineqs.size();
@ -683,7 +683,6 @@ namespace polysat {
return false;
}
/**
* 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.
@ -799,17 +798,17 @@ namespace polysat {
*/
template<typename Ext>
void fixplex<Ext>::pivot(var_t x, var_t y, numeral const& b, numeral const& new_value) {
++m_stats.m_num_pivots;
TRACE("fixplex", tout << "pivot " << x << " " << y << "\n";);
++m_stats.m_num_pivots;
SASSERT(is_base(x));
SASSERT(!is_base(y));
var_info& xI = m_vars[x];
var_info& yI = m_vars[y];
unsigned rx = xI.m_base2row;
auto& row_x = m_rows[rx];
row r_x(rx);
numeral const& a = row_x.m_base_coeff;
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_value = row_x.m_value - b * old_value_y + a * new_value;
row_x.m_base_coeff = b;
@ -819,20 +818,18 @@ namespace polysat {
xI.m_is_base = false;
xI.m_value = new_value;
touch_var(x);
row r_x(rx);
add_patch(y);
SASSERT(well_formed_row(r_x));
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();
unsigned rz = r_z.id();
if (rz == rx)
continue;
TRACE("fixplex,", display_row(tout << "eliminate ", r_z, false) << "\n";);
numeral c = col.get_row_entry().coeff();
VERIFY(eliminate_var(r_x, r_z, c, tz_b, old_value_y));
VERIFY(eliminate_var(r_x, col, tz_b, old_value_y));
TRACE("fixplex,", display_row(tout << "eliminated ", r_z, false) << "\n";);
add_patch(row2base(r_z));
}
@ -841,37 +838,34 @@ namespace polysat {
/**
* r_y - row where y is base variable
* r_z - row that contains y with z base variable, z != y
* c - coefficient of y in r_z
* z_col - column iterator that contains row where z is base variable.
* 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)
*
* 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).
*/
template<typename Ext>
bool fixplex<Ext>::eliminate_var(
row const& r_y,
row const& r_z,
numeral const& c,
col_iterator const& z_col,
unsigned tz_b,
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);
auto z = row2base(r_z);
auto& row_z = m_rows[r_z.id()];
auto z = row2base(r_z);
unsigned tz_c = m.trailing_zeros(c);
numeral b1, c1;
if (tz_b <= tz_c) {
b1 = b >> tz_b;
c1 = 0 - (c >> tz_b);
}
else {
b1 = b >> tz_c;
c1 = 0 - (c >> tz_c);
}
unsigned tz = std::min(tz_b, tz_c);
numeral b1 = b >> tz;
numeral c1 = 0 - (c >> tz);
M.mul(r_z, b1);
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_base_coeff *= b1;
set_base_value(z);

View file

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