3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-06-06 06:03:23 +00:00

adding deps

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2021-08-04 14:02:32 -07:00
parent 91ac15d716
commit be9f172cc0
7 changed files with 268 additions and 194 deletions

View file

@ -70,12 +70,8 @@ inline std::ostream& operator<<(std::ostream& out, u256 const& u) {
inline bool operator<(uint64_t n, u256 const& y) { return y > n; } inline bool operator<(uint64_t n, u256 const& y) { return y > n; }
inline bool operator<=(uint64_t n, u256 const& y) { return y >= n; } inline bool operator<=(uint64_t n, u256 const& y) { return y >= n; }
inline bool operator>(uint64_t n, u256 const& y) { return y < n; } inline bool operator>(uint64_t n, u256 const& y) { return y < n; }
inline unsigned trailing_zeros(u256 const& n) { inline unsigned trailing_zeros(u256 const& n) { return n.trailing_zeros(); }
NOT_IMPLEMENTED_YET();
return 0; inline u256 operator-(uint64_t n, u256 const& y) { return u256(n) - y; }
}
inline u256 operator-(uint64_t n, u256 const& y) {
u256 x(n);
return x - y;
}
inline bool operator>=(uint64_t n, u256 const& y) { return y <= n; } inline bool operator>=(uint64_t n, u256 const& y) { return y <= n; }
inline rational to_rational(u256 const& x) { return x.to_rational(); }

View file

@ -27,6 +27,8 @@ Author:
#include "util/lbool.h" #include "util/lbool.h"
#include "util/uint_set.h" #include "util/uint_set.h"
inline rational to_rational(uint64_t n) { return rational(n, rational::ui64()); }
namespace polysat { namespace polysat {
typedef unsigned var_t; typedef unsigned var_t;
@ -38,12 +40,14 @@ namespace polysat {
virtual void del_row(var_t base_var) = 0; virtual void del_row(var_t base_var) = 0;
virtual std::ostream& display(std::ostream& out) const = 0; virtual std::ostream& display(std::ostream& out) const = 0;
virtual void collect_statistics(::statistics & st) const = 0; virtual void collect_statistics(::statistics & st) const = 0;
virtual void set_bounds(var_t v, rational const& lo, rational const& hi) = 0; virtual void set_bounds(var_t v, rational const& lo, rational const& hi, unsigned dep) = 0;
virtual void set_value(var_t v, rational const& val) = 0; virtual void set_value(var_t v, rational const& val, unsigned dep) = 0;
virtual rational get_value(var_t v) = 0;
virtual void restore_bound() = 0; virtual void restore_bound() = 0;
virtual void add_le(var_t v, var_t w) = 0; virtual void add_le(var_t v, var_t w, unsigned dep) = 0;
virtual void add_lt(var_t v, var_t w) = 0; virtual void add_lt(var_t v, var_t w, unsigned dep) = 0;
virtual void restore_ineq() = 0; virtual void restore_ineq() = 0;
virtual void get_infeasible_deps(unsigned_vector& deps) = 0;
}; };
@ -92,7 +96,9 @@ namespace polysat {
struct var_info : public mod_interval<numeral> { struct var_info : public mod_interval<numeral> {
unsigned m_base2row:29; unsigned m_base2row:29;
unsigned m_is_base:1; unsigned m_is_base:1;
numeral m_value { 0 }; numeral m_value = 0;
unsigned m_lo_dep = UINT_MAX;
unsigned m_hi_dep = UINT_MAX;
var_info(): var_info():
m_base2row(0), m_base2row(0),
m_is_base(false) m_is_base(false)
@ -115,10 +121,10 @@ namespace polysat {
numeral m_base_coeff; numeral m_base_coeff;
}; };
struct stashed_bound : mod_interval<numeral> { struct stashed_bound : var_info {
var_t m_var; var_t m_var;
stashed_bound(var_t v, mod_interval<numeral> const& i): stashed_bound(var_t v, var_info const& i):
mod_interval<numeral>(i), var_info(i),
m_var(v) m_var(v)
{} {}
}; };
@ -131,12 +137,13 @@ namespace polysat {
}; };
struct ineq { struct ineq {
var_t v { null_var }; var_t v = null_var;
var_t w { null_var }; var_t w = null_var;
bool strict { false }; bool strict = false;
bool is_active { true }; bool is_active = true;
ineq(var_t v, var_t w, bool s): unsigned dep = UINT_MAX;
v(v), w(w), strict(s) {} ineq(var_t v, var_t w, unsigned dep, bool s):
v(v), w(w), strict(s), dep(dep) {}
}; };
static const var_t null_var = UINT_MAX; static const var_t null_var = UINT_MAX;
@ -179,14 +186,15 @@ namespace polysat {
std::ostream& display(std::ostream& out) const override; std::ostream& display(std::ostream& out) const override;
void collect_statistics(::statistics & st) const override; void collect_statistics(::statistics & st) const override;
void del_row(var_t base_var) override; void del_row(var_t base_var) override;
void set_bounds(var_t v, rational const& lo, rational const& hi) override; void set_bounds(var_t v, rational const& lo, rational const& hi, unsigned dep) override;
void set_value(var_t v, rational const& val) override; void set_value(var_t v, rational const& val, unsigned dep) override;
rational get_value(var_t v) override;
void restore_bound() override; void restore_bound() override;
void add_le(var_t v, var_t w) override { add_ineq(v, w, false); } void add_le(var_t v, var_t w, unsigned dep) override { add_ineq(v, w, dep, false); }
void add_lt(var_t v, var_t w) override { add_ineq(v, w, true); } void add_lt(var_t v, var_t w, unsigned dep) override { add_ineq(v, w, dep, true); }
virtual void restore_ineq() override; virtual void restore_ineq() override;
void set_bounds(var_t v, numeral const& lo, numeral const& hi); void set_bounds(var_t v, numeral const& lo, numeral const& hi, unsigned dep);
void unset_bounds(var_t v) { m_vars[v].set_free(); } void unset_bounds(var_t v) { m_vars[v].set_free(); }
@ -202,10 +210,13 @@ namespace polysat {
void reset_eqs() { m_var_eqs.reset(); } void reset_eqs() { m_var_eqs.reset(); }
void add_row(var_t base, unsigned num_vars, var_t const* vars, numeral const* coeffs); void add_row(var_t base, unsigned num_vars, var_t const* vars, numeral const* coeffs);
row get_infeasible_row();
void get_infeasible_deps(unsigned_vector& deps) override;
private: private:
row get_infeasible_row();
std::ostream& display_row(std::ostream& out, row const& r, bool values = true); std::ostream& display_row(std::ostream& out, row const& r, bool values = true);
var_t get_base_var(row const& r) const { return m_rows[r.id()].m_base; } var_t get_base_var(row const& r) const { return m_rows[r.id()].m_base; }
@ -258,7 +269,7 @@ namespace polysat {
var_t select_error_var(bool least); var_t select_error_var(bool least);
// facilities for handling inequalities // facilities for handling inequalities
void add_ineq(var_t v, var_t w, bool strict); void add_ineq(var_t v, var_t w, unsigned dep, bool strict);
void touch_var(var_t x); void touch_var(var_t x);
lbool check_ineqs(); lbool check_ineqs();
@ -284,7 +295,6 @@ namespace polysat {
numeral const& old_value_y); numeral const& old_value_y);
}; };
template<typename uint_type> template<typename uint_type>
struct generic_uint_ext { struct generic_uint_ext {
typedef uint_type numeral; typedef uint_type numeral;
@ -302,6 +312,7 @@ namespace polysat {
} }
}; };
numeral from_rational(rational const& n) { return static_cast<uint_type>(n.get_uint64()); } numeral from_rational(rational const& n) { return static_cast<uint_type>(n.get_uint64()); }
rational to_rational(numeral const& n) const { return ::to_rational(n); }
void reset() {} void reset() {}
void reset(numeral& n) { n = 0; } void reset(numeral& n) { n = 0; }
void del(numeral const& n) {} void del(numeral const& n) {}

View file

@ -70,16 +70,16 @@ namespace polysat {
template<typename Ext> template<typename Ext>
fixplex<Ext>::~fixplex() { fixplex<Ext>::~fixplex() {
reset(); reset();
} }
template<typename Ext> template<typename Ext>
void fixplex<Ext>::ensure_var(var_t v) { void fixplex<Ext>::ensure_var(var_t v) {
while (v >= m_vars.size()) { while (v >= m_vars.size()) {
M.ensure_var(m_vars.size()); M.ensure_var(m_vars.size());
m_vars.push_back(var_info()); m_vars.push_back(var_info());
} }
if (m_to_patch.get_bounds() <= v) if (m_to_patch.get_bounds() <= v)
m_to_patch.set_bounds(2*v+1); m_to_patch.set_bounds(2 * v + 1);
} }
template<typename Ext> template<typename Ext>
@ -105,7 +105,7 @@ namespace polysat {
SASSERT(well_formed()); SASSERT(well_formed());
while ((v = select_var_to_fix()) != null_var) { while ((v = select_var_to_fix()) != null_var) {
TRACE("polysat", display(tout << "v" << v << "\n");); TRACE("polysat", display(tout << "v" << v << "\n"););
if (!m_limit.inc() || num_iterations > m_max_iterations) if (!m_limit.inc() || num_iterations > m_max_iterations)
return l_undef; return l_undef;
check_blands_rule(v, num_repeated); check_blands_rule(v, num_repeated);
switch (make_var_feasible(v)) { switch (make_var_feasible(v)) {
@ -138,20 +138,20 @@ namespace polysat {
template<typename Ext> template<typename Ext>
void fixplex<Ext>::add_row(var_t base_var, unsigned num_vars, var_t const* vars, numeral const* coeffs) { void fixplex<Ext>::add_row(var_t base_var, unsigned num_vars, var_t const* vars, numeral const* coeffs) {
for (unsigned i = 0; i < num_vars; ++i) for (unsigned i = 0; i < num_vars; ++i)
ensure_var(vars[i]); ensure_var(vars[i]);
m_base_vars.reset(); m_base_vars.reset();
row r = M.mk_row(); row r = M.mk_row();
for (unsigned i = 0; i < num_vars; ++i) for (unsigned i = 0; i < num_vars; ++i)
if (coeffs[i] != 0) if (coeffs[i] != 0)
M.add_var(r, coeffs[i], vars[i]); M.add_var(r, coeffs[i], vars[i]);
numeral base_coeff = 0; numeral base_coeff = 0;
numeral value = 0; numeral value = 0;
for (auto const& e : M.row_entries(r)) { for (auto const& e : M.row_entries(r)) {
var_t v = e.var(); var_t v = e.var();
if (v == base_var) if (v == base_var)
base_coeff = e.coeff(); base_coeff = e.coeff();
else { else {
if (is_base(v)) if (is_base(v))
@ -161,7 +161,7 @@ namespace polysat {
} }
SASSERT(base_coeff != 0); SASSERT(base_coeff != 0);
SASSERT(!is_base(base_var)); SASSERT(!is_base(base_var));
while (m_rows.size() <= r.id()) while (m_rows.size() <= r.id())
m_rows.push_back(row_info()); m_rows.push_back(row_info());
m_rows[r.id()].m_base = base_var; m_rows[r.id()].m_base = base_var;
m_rows[r.id()].m_base_coeff = base_coeff; m_rows[r.id()].m_base_coeff = base_coeff;
@ -189,9 +189,9 @@ namespace polysat {
/** /**
* Eliminate base variable v from all rows except where v is basic. * Eliminate base variable v from all rows except where v is basic.
* Return false if elimination required to multiply a non-basic row with an even number. * Return false if elimination required to multiply a non-basic row with an even number.
* This happens when the parity in the non-basic row is smaller than the parity of v in * This happens when the parity in the non-basic row is smaller than the parity of v in
* the basic row. It is expected to be a corner case and we don't try to solve this * the basic row. It is expected to be a corner case and we don't try to solve this
* inside of fixplex. Instead to deal with the corner case we assume the layer around * inside of fixplex. Instead to deal with the corner case we assume the layer around
* fixplex uses a solution from fixplex as a starting point for a complete search (in polysat). * fixplex uses a solution from fixplex as a starting point for a complete search (in polysat).
*/ */
template<typename Ext> template<typename Ext>
@ -248,14 +248,14 @@ namespace polysat {
var_t old_base = row2base(r); var_t old_base = row2base(r);
numeral new_value; numeral new_value;
var_info& vi = m_vars[old_base]; var_info& vi = m_vars[old_base];
if (!vi.contains(value(old_base))) if (!vi.contains(value(old_base)))
new_value = vi.lo; new_value = vi.lo;
else else
new_value = value(old_base); new_value = value(old_base);
// need to move var such that old_base comes in bound. // need to move var such that old_base comes in bound.
pivot(old_base, var, coeff, new_value); pivot(old_base, var, coeff, new_value);
SASSERT(is_base(var)); SASSERT(is_base(var));
SASSERT(base2row(var).id() == r.id()); SASSERT(base2row(var).id() == r.id());
SASSERT(vi.contains(value(old_base))); SASSERT(vi.contains(value(old_base)));
} }
del_row(r); del_row(r);
@ -288,17 +288,17 @@ namespace polysat {
ri.m_value += delta * c.get_row_entry().coeff(); ri.m_value += delta * c.get_row_entry().coeff();
set_base_value(s); set_base_value(s);
add_patch(s); add_patch(s);
} }
} }
/** /**
* Attempt to improve assigment to make x feasible. * Attempt to improve assigment to make x feasible.
* *
* return l_false if x is base variable of infeasible row * return l_false if x is base variable of infeasible row
* return l_true if it is possible to find an assignment that improves * return l_true if it is possible to find an assignment that improves
* return l_undef if the row could not be used for an improvement * return l_undef if the row could not be used for an improvement
* *
* delta - improvement over previous gap to feasible bound. * delta - improvement over previous gap to feasible bound.
* new_value - the new value to assign to x within its bounds. * new_value - the new value to assign to x within its bounds.
*/ */
@ -320,37 +320,37 @@ namespace polysat {
return l_undef; return l_undef;
} }
pivot(x, y, b, new_value); pivot(x, y, b, new_value);
return l_true; return l_true;
} }
template<typename Ext> template<typename Ext>
var_t fixplex<Ext>::select_pivot(var_t x, numeral const& new_value, numeral & out_b) { var_t fixplex<Ext>::select_pivot(var_t x, numeral const& new_value, numeral& out_b) {
if (m_bland) if (m_bland)
return select_pivot_blands(x, new_value, out_b); return select_pivot_blands(x, new_value, out_b);
return select_pivot_core(x, new_value, out_b); return select_pivot_core(x, new_value, out_b);
} }
/** /**
\brief Select a variable y in the row r defining the base var x, \brief Select a variable y in the row r defining the base var x,
s.t. y can be used to patch the error in x_i. Return null_var s.t. y can be used to patch the error in x_i. Return null_var
if there is no y. Otherwise, return y and store its coefficient if there is no y. Otherwise, return y and store its coefficient
in out_b. in out_b.
The routine gives up if the coefficients of all free variables do not have the minimal The routine gives up if the coefficients of all free variables do not have the minimal
number of trailing zeros. number of trailing zeros.
*/ */
template<typename Ext> template<typename Ext>
var_t fixplex<Ext>::select_pivot_core(var_t x, numeral const& new_value, numeral & out_b) { var_t fixplex<Ext>::select_pivot_core(var_t x, numeral const& new_value, numeral& out_b) {
SASSERT(is_base(x)); SASSERT(is_base(x));
var_t max = get_num_vars(); var_t max = get_num_vars();
var_t result = max; var_t result = max;
row r = base2row(x); row r = base2row(x);
int n = 0; int n = 0;
unsigned best_col_sz = UINT_MAX; unsigned best_col_sz = UINT_MAX;
int best_so_far = INT_MAX; int best_so_far = INT_MAX;
numeral a = row2base_coeff(r); numeral a = row2base_coeff(r);
numeral row_value = row2value(r) + a * new_value; numeral row_value = row2value(r) + a * new_value;
numeral delta_y = 0; numeral delta_y = 0;
@ -358,13 +358,13 @@ namespace polysat {
bool best_in_bounds = false; bool best_in_bounds = false;
for (auto const& r : M.row_entries(r)) { for (auto const& r : M.row_entries(r)) {
var_t y = r.var(); var_t y = r.var();
numeral const & b = r.coeff(); numeral const& b = r.coeff();
if (x == y) if (x == y)
continue; continue;
if (!has_minimal_trailing_zeros(y, b)) if (!has_minimal_trailing_zeros(y, b))
continue; continue;
numeral new_y_value = solve_for(row_value - b*value(y), b); numeral new_y_value = solve_for(row_value - b * value(y), b);
bool _in_bounds = in_bounds(y, new_y_value); bool _in_bounds = in_bounds(y, new_y_value);
if (!_in_bounds) { if (!_in_bounds) {
if (lo(y) - new_y_value < new_y_value - hi(y)) if (lo(y) - new_y_value < new_y_value - hi(y))
@ -372,7 +372,7 @@ namespace polysat {
else else
delta_y = new_y_value - hi(y) - 1; delta_y = new_y_value - hi(y) - 1;
} }
int num = get_num_non_free_dep_vars(y, best_so_far); int num = get_num_non_free_dep_vars(y, best_so_far);
unsigned col_sz = M.column_size(y); unsigned col_sz = M.column_size(y);
bool is_improvement = false, is_plateau = false; bool is_improvement = false, is_plateau = false;
@ -391,23 +391,23 @@ namespace polysat {
is_plateau = true; is_plateau = true;
else if (best_in_bounds && _in_bounds && best_so_far == num && col_sz == best_col_sz) else if (best_in_bounds && _in_bounds && best_so_far == num && col_sz == best_col_sz)
is_plateau = true; is_plateau = true;
if (is_improvement) { if (is_improvement) {
result = y; result = y;
out_b = b; out_b = b;
best_so_far = num; best_so_far = num;
best_col_sz = col_sz; best_col_sz = col_sz;
best_in_bounds = _in_bounds; best_in_bounds = _in_bounds;
delta_best = delta_y; delta_best = delta_y;
n = 1; n = 1;
} }
else if (is_plateau) { else if (is_plateau) {
n++; n++;
if (m_random() % n == 0) { if (m_random() % n == 0) {
result = y; result = y;
out_b = b; out_b = b;
} }
} }
} }
if (result == max) if (result == max)
return null_var; return null_var;
@ -417,18 +417,18 @@ namespace polysat {
} }
template<typename Ext> template<typename Ext>
var_t fixplex<Ext>::select_pivot_blands(var_t x, numeral const& new_value, numeral & out_b) { var_t fixplex<Ext>::select_pivot_blands(var_t x, numeral const& new_value, numeral& out_b) {
SASSERT(is_base(x)); SASSERT(is_base(x));
unsigned max = get_num_vars(); unsigned max = get_num_vars();
var_t result = max; var_t result = max;
row r = base2row(x); row r = base2row(x);
for (auto const& c : M.col_entries(r)) { for (auto const& c : M.col_entries(r)) {
var_t y = c.var(); var_t y = c.var();
if (x == y || y >= result) if (x == y || y >= result)
continue; continue;
numeral const & b = c.coeff(); numeral const& b = c.coeff();
if (can_improve(y, b)) { if (can_improve(y, b)) {
out_b = b; out_b = b;
result = y; result = y;
} }
} }
@ -436,8 +436,8 @@ namespace polysat {
} }
/** /**
* determine whether setting x := new_value * determine whether setting x := new_value
* allows to change the value of y in a direction * allows to change the value of y in a direction
* that reduces or maintains the overall error. * that reduces or maintains the overall error.
*/ */
template<typename Ext> template<typename Ext>
@ -452,30 +452,30 @@ namespace polysat {
/** /**
* Compute delta to add to the value, such that value + delta is either lo(v), or hi(v) - 1 * Compute delta to add to the value, such that value + delta is either lo(v), or hi(v) - 1
* A pre-condition is that value is not in the interval [lo(v),hi(v)[, * A pre-condition is that value is not in the interval [lo(v),hi(v)[,
* and therefore as a consequence lo(v) != hi(v). * and therefore as a consequence lo(v) != hi(v).
*/ */
template<typename Ext> template<typename Ext>
typename fixplex<Ext>::numeral typename fixplex<Ext>::numeral
fixplex<Ext>::value2delta(var_t v, numeral const& value) const { fixplex<Ext>::value2delta(var_t v, numeral const& value) const {
SASSERT(!in_bounds(v)); SASSERT(!in_bounds(v));
SASSERT(lo(v) != hi(v)); SASSERT(lo(v) != hi(v));
if (lo(v) - value < value - hi(v)) if (lo(v) - value < value - hi(v))
return lo(v) - value; return lo(v) - value;
else else
return hi(v) - value - 1; return hi(v) - value - 1;
} }
template<typename Ext> template<typename Ext>
typename fixplex<Ext>::numeral typename fixplex<Ext>::numeral
fixplex<Ext>::value2error(var_t v, numeral const& value) const { fixplex<Ext>::value2error(var_t v, numeral const& value) const {
if (in_bounds(v)) if (in_bounds(v))
return 0; return 0;
SASSERT(lo(v) != hi(v)); SASSERT(lo(v) != hi(v));
if (lo(v) - value < value - hi(v)) if (lo(v) - value < value - hi(v))
return lo(v) - value; return lo(v) - value;
else else
return value - hi(v) - 1; return value - hi(v) - 1;
} }
/** /**
@ -486,46 +486,60 @@ namespace polysat {
* - the variable v is queued to patch if v is basic. * - the variable v is queued to patch if v is basic.
*/ */
template<typename Ext> template<typename Ext>
void fixplex<Ext>::set_bounds(var_t v, numeral const& l, numeral const& h) { void fixplex<Ext>::set_bounds(var_t v, numeral const& l, numeral const& h, unsigned dep) {
m_vars[v] = mod_interval(l, h); auto lo0 = m_vars[v].lo;
auto hi0 = m_vars[v].hi;
m_vars[v] &= mod_interval(l, h);
if (lo0 != m_vars[v].lo)
m_vars[v].m_lo_dep = dep;
if (hi0 != m_vars[v].hi)
m_vars[v].m_hi_dep = dep;
if (in_bounds(v)) if (in_bounds(v))
return; return;
if (is_base(v)) if (is_base(v))
add_patch(v); add_patch(v);
else else
update_value(v, value2delta(v, value(v))); update_value(v, value2delta(v, value(v)));
} }
template<typename Ext> template<typename Ext>
void fixplex<Ext>::set_bounds(var_t v, rational const& _lo, rational const& _hi) { void fixplex<Ext>::set_bounds(var_t v, rational const& _lo, rational const& _hi, unsigned dep) {
numeral lo = m.from_rational(_lo); numeral lo = m.from_rational(_lo);
numeral hi = m.from_rational(_hi); numeral hi = m.from_rational(_hi);
m_stashed_bounds.push_back(stashed_bound(v, m_vars[v])); m_stashed_bounds.push_back(stashed_bound(v, m_vars[v]));
set_bounds(v, lo, hi); set_bounds(v, lo, hi, dep);
} }
template<typename Ext> template<typename Ext>
void fixplex<Ext>::set_value(var_t v, rational const& _val) { void fixplex<Ext>::set_value(var_t v, rational const& _val, unsigned dep) {
numeral val = m.from_rational(_val); numeral val = m.from_rational(_val);
m_stashed_bounds.push_back(stashed_bound(v, m_vars[v])); m_stashed_bounds.push_back(stashed_bound(v, m_vars[v]));
set_bounds(v, val, val + 1); set_bounds(v, val, val + 1, dep);
}
template<typename Ext>
rational fixplex<Ext>::get_value(var_t v) {
return m.to_rational(m_vars[v].m_value);
} }
template<typename Ext> template<typename Ext>
void fixplex<Ext>::restore_bound() { void fixplex<Ext>::restore_bound() {
auto const& b = m_stashed_bounds.back(); auto const& b = m_stashed_bounds.back();
set_bounds(b.m_var, b.lo, b.hi); m_vars[b.m_var].lo = b.lo;
m_vars[b.m_var].hi = b.hi;
m_vars[b.m_var].m_lo_dep = b.m_lo_dep;
m_vars[b.m_var].m_hi_dep = b.m_hi_dep;
m_stashed_bounds.pop_back(); m_stashed_bounds.pop_back();
} }
template<typename Ext> template<typename Ext>
void fixplex<Ext>::add_ineq(var_t v, var_t w, bool strict) { void fixplex<Ext>::add_ineq(var_t v, var_t w, unsigned dep, bool strict) {
unsigned idx = m_ineqs.size(); unsigned idx = m_ineqs.size();
m_var2ineqs.reserve(std::max(v, w) + 1); m_var2ineqs.reserve(std::max(v, w) + 1);
m_var2ineqs[v].push_back(idx); m_var2ineqs[v].push_back(idx);
m_var2ineqs[w].push_back(idx); m_var2ineqs[w].push_back(idx);
m_ineqs_to_check.push_back(idx); m_ineqs_to_check.push_back(idx);
m_ineqs.push_back(ineq(v, w, strict)); m_ineqs.push_back(ineq(v, w, dep, strict));
} }
template<typename Ext> template<typename Ext>
@ -577,7 +591,7 @@ namespace polysat {
m_ineqs_to_check.reset(); m_ineqs_to_check.reset();
m_vars_to_untouch.reset(); m_vars_to_untouch.reset();
return l_true; return l_true;
} }
/** /**
@ -603,15 +617,15 @@ namespace polysat {
* A row is linear infeasible if it can be established * A row is linear infeasible if it can be established
* that none of the available assignments within current * that none of the available assignments within current
* bounds let the row add up to 0. * bounds let the row add up to 0.
* *
* Assume the row is of the form: * Assume the row is of the form:
* ax + by + cz = 0 * ax + by + cz = 0
* with bounds * with bounds
* x : [lo_x, hi_x[, y : [lo_y, hi_y[, z : [lo_z : hi_z[ * x : [lo_x, hi_x[, y : [lo_y, hi_y[, z : [lo_z : hi_z[
* *
* Let range = [lo_x, hi_x[ + [lo_y, hi_y[ + [lo_z : hi_z[ * Let range = [lo_x, hi_x[ + [lo_y, hi_y[ + [lo_z : hi_z[
* Claim. If range does not contain 0, then the row is infeasible. * Claim. If range does not contain 0, then the row is infeasible.
* *
*/ */
template<typename Ext> template<typename Ext>
bool fixplex<Ext>::is_infeasible_row(var_t x) { bool fixplex<Ext>::is_infeasible_row(var_t x) {
@ -624,7 +638,7 @@ namespace polysat {
range += m_vars[v] * c; range += m_vars[v] * c;
if (range.is_free()) if (range.is_free())
return false; return false;
} }
return !range.contains(0); return !range.contains(0);
} }
@ -650,14 +664,14 @@ namespace polysat {
var_t v = e.var(); var_t v = e.var();
auto c = e.coeff(); auto c = e.coeff();
if (is_fixed(v)) if (is_fixed(v))
fixed += value(v)*c; fixed += value(v) * c;
else else
parity = std::min(m.trailing_zeros(c), parity); parity = std::min(m.trailing_zeros(c), parity);
} }
if (m.trailing_zeros(fixed) < parity) if (m.trailing_zeros(fixed) < parity)
return true; return true;
return false; return false;
} }
@ -676,23 +690,23 @@ namespace polysat {
Effect: Effect:
base(r_x) := y base(r_x) := y
value(x) := new_value value(x) := new_value
value(r_x) := value(r_x) - b*value(y) + a*new_value value(r_x) := value(r_x) - b*value(y) + a*new_value
value(y) := -value(r_x) / b value(y) := -value(r_x) / b
base_coeff(r_x) := b base_coeff(r_x) := b
Let r be a row where y has coefficient c != 0. Let r be a row where y has coefficient c != 0.
Assume: trailing_zeros(c) >= trailing_zeros(b) Assume: trailing_zeros(c) >= trailing_zeros(b)
z = base(r) z = base(r)
d = base_coeff(r) d = base_coeff(r)
b1 = (b >> tz(b)) b1 = (b >> tz(b))
c1 = (c >> (tz(c) - tz(b))) c1 = (c >> (tz(c) - tz(b)))
r <- b1 * r - c1 * r_x r <- b1 * r - c1 * r_x
value(r) := b1 * value(r) - b1 * old_value(y) - c1 * value(r_x) value(r) := b1 * value(r) - b1 * old_value(y) - c1 * value(r_x)
value(z) := - value(r) / d value(z) := - value(r) / d
base_coeff(r) := b1 * base_coeff(r) base_coeff(r) := b1 * base_coeff(r)
*/ */
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;
@ -705,7 +719,7 @@ namespace polysat {
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;
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;
yI.m_base2row = rx; yI.m_base2row = rx;
yI.m_is_base = true; yI.m_is_base = true;
@ -718,7 +732,7 @@ namespace polysat {
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 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();
@ -740,12 +754,12 @@ namespace polysat {
* *
* 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, row const& r_z,
numeral const& c, numeral const& c,
unsigned tz_b, unsigned tz_b,
numeral const& old_value_y) { numeral const& old_value_y) {
numeral b = row2base_coeff(r_y); numeral b = row2base_coeff(r_y);
@ -770,7 +784,7 @@ namespace polysat {
return tz_b <= tz_c; return tz_b <= tz_c;
} }
template<typename Ext> template<typename Ext>
bool fixplex<Ext>::is_feasible() const { bool fixplex<Ext>::is_feasible() const {
for (unsigned i = m_vars.size(); i-- > 0; ) for (unsigned i = m_vars.size(); i-- > 0; )
if (!in_bounds(i)) if (!in_bounds(i))
@ -779,12 +793,34 @@ namespace polysat {
} }
template<typename Ext> template<typename Ext>
typename fixplex<Ext>::row typename fixplex<Ext>::row
fixplex<Ext>::get_infeasible_row() { fixplex<Ext>::get_infeasible_row() {
SASSERT(is_base(m_infeasible_var)); SASSERT(is_base(m_infeasible_var));
return base2row(m_infeasible_var); return base2row(m_infeasible_var);
} }
/***
* Extract dependencies for infeasible row.
* A safe approximation is to extract dependencies for all bounds.
*
* Different modes of infeasibility may not be based on a row:
* - inequalities
* - parity constraints between two rows.
*/
template<typename Ext>
void fixplex<Ext>::get_infeasible_deps(unsigned_vector& deps) {
auto row = get_infeasible_row();
for (auto const& e : M.row_entries(row)) {
var_t v = e.var();
auto lo = m_vars[v].m_lo_dep;
auto hi = m_vars[v].m_hi_dep;
if (lo != UINT_MAX)
deps.push_back(lo);
if (hi != UINT_MAX)
deps.push_back(hi);
}
}
/** /**
\brief Return the number of base variables that are non free and are v dependent. \brief Return the number of base variables that are non free and are v dependent.
The function adds 1 to the result if v is non free. The function adds 1 to the result if v is non free.

View file

@ -60,11 +60,16 @@ namespace polysat {
m_rows.pop_back(); m_rows.pop_back();
break; break;
} }
case trail_i::set_active_i:
m_active.pop_back();
break;
default: default:
UNREACHABLE(); UNREACHABLE();
} }
m_trail.pop_back(); m_trail.pop_back();
} }
m_unsat_f = nullptr;
} }
fixplex_base& linear_solver::sz2fixplex(unsigned sz) { fixplex_base& linear_solver::sz2fixplex(unsigned sz) {
@ -78,10 +83,10 @@ namespace polysat {
b = alloc(fixplex<uint64_ext>, s.m_lim); b = alloc(fixplex<uint64_ext>, s.m_lim);
break; break;
case 128: case 128:
NOT_IMPLEMENTED_YET(); NOT_IMPLEMENTED_YET();
break; break;
case 256: case 256:
b = alloc(fixplex<generic_uint_ext<u256>>, s.m_lim); b = alloc(fixplex<generic_uint_ext<u256>>, s.m_lim);
break; break;
default: default:
NOT_IMPLEMENTED_YET(); NOT_IMPLEMENTED_YET();
@ -117,8 +122,16 @@ namespace polysat {
auto pr = std::make_pair(v, v); auto pr = std::make_pair(v, v);
m_bool_var2row.setx(c.bvar(), pr, pr); m_bool_var2row.setx(c.bvar(), pr, pr);
} }
void linear_solver::new_le(ule_constraint& c) {
var_t v = internalize_pdd(c.lhs());
var_t w = internalize_pdd(c.rhs());
auto pr = std::make_pair(v, w);
m_bool_var2row.setx(c.bvar(), pr, pr);
}
void linear_solver::assert_eq(eq_constraint& c) { void linear_solver::assert_eq(bool is_positive, eq_constraint& c) {
unsigned c_dep = constraint_idx2dep(m_active.size() - 1);
var_t v = m_bool_var2row[c.bvar()].first; var_t v = m_bool_var2row[c.bvar()].first;
unsigned sz = c.p().power_of_2(); unsigned sz = c.p().power_of_2();
auto& fp = sz2fixplex(sz); auto& fp = sz2fixplex(sz);
@ -126,17 +139,10 @@ namespace polysat {
m_rows.push_back(std::make_pair(v, sz)); m_rows.push_back(std::make_pair(v, sz));
rational z(0), o(1); rational z(0), o(1);
SASSERT(!c.is_undef()); SASSERT(!c.is_undef());
if (c.is_positive()) if (is_positive)
fp.set_bounds(v, z, z); fp.set_bounds(v, z, z, c_dep);
else else
fp.set_bounds(v, o, z); fp.set_bounds(v, o, z, c_dep);
}
void linear_solver::new_le(ule_constraint& c) {
var_t v = internalize_pdd(c.lhs());
var_t w = internalize_pdd(c.rhs());
auto pr = std::make_pair(v, w);
m_bool_var2row.setx(c.bvar(), pr, pr);
} }
// //
@ -152,44 +158,45 @@ namespace polysat {
// inequality graph (with offsets) // inequality graph (with offsets)
// //
void linear_solver::assert_le(ule_constraint& c) { void linear_solver::assert_le(bool is_positive, ule_constraint& c) {
auto [v, w] = m_bool_var2row[c.bvar()]; auto [v, w] = m_bool_var2row[c.bvar()];
unsigned sz = c.lhs().power_of_2(); unsigned sz = c.lhs().power_of_2();
auto& fp = sz2fixplex(sz); auto& fp = sz2fixplex(sz);
unsigned c_dep = constraint_idx2dep(m_active.size() - 1);
rational z(0); rational z(0);
if (c.rhs().is_val()) { if (c.rhs().is_val()) {
bool is_max_value = false; bool is_max_value = false;
if (c.is_positive()) if (is_positive)
// v <= rhs // v <= rhs
fp.set_bounds(v, z, c.rhs().val()); fp.set_bounds(v, z, c.rhs().val(), c_dep);
else if (is_max_value) else if (is_max_value)
throw default_exception("conflict not implemented"); throw default_exception("conflict not implemented");
else else
// rhs < v // rhs < v
fp.set_bounds(v, c.rhs().val() + 1, z); fp.set_bounds(v, c.rhs().val() + 1, z, c_dep);
m_trail.push_back(trail_i::set_bound_i); m_trail.push_back(trail_i::set_bound_i);
m_rows.push_back(std::make_pair(v, sz)); m_rows.push_back(std::make_pair(v, sz));
return; return;
} }
if (c.lhs().is_val()) { if (c.lhs().is_val()) {
if (c.is_positive()) if (is_positive)
// w >= lhs // w >= lhs
fp.set_bounds(w, c.lhs().val(), z); fp.set_bounds(w, c.lhs().val(), z, c_dep);
else if (c.lhs().val() == 0) else if (c.lhs().val() == 0)
throw default_exception("conflict not implemented"); throw default_exception("conflict not implemented");
else else
// w < lhs // w < lhs
fp.set_bounds(w, z, c.lhs().val() - 1); fp.set_bounds(w, z, c.lhs().val() - 1, c_dep);
m_trail.push_back(trail_i::set_bound_i); m_trail.push_back(trail_i::set_bound_i);
m_rows.push_back(std::make_pair(w, sz)); m_rows.push_back(std::make_pair(w, sz));
return; return;
} }
if (c.is_positive()) if (is_positive)
fp.add_le(v, w); fp.add_le(v, w, c_dep);
else else
fp.add_lt(w, v); fp.add_lt(w, v, c_dep);
m_trail.push_back(trail_i::add_ineq_i); m_trail.push_back(trail_i::add_ineq_i);
m_rows.push_back(std::make_pair(v, sz)); m_rows.push_back(std::make_pair(v, sz));
} }
@ -209,14 +216,16 @@ namespace polysat {
} }
} }
void linear_solver::activate_constraint(constraint& c) { void linear_solver::activate_constraint(bool is_positive, constraint& c) {
m_active.push_back(&c);
m_trail.push_back(trail_i::set_active_i);
SASSERT(!c.is_undef()); SASSERT(!c.is_undef());
switch (c.kind()) { switch (c.kind()) {
case ckind_t::eq_t: case ckind_t::eq_t:
assert_eq(c.to_eq()); assert_eq(is_positive, c.to_eq());
break; break;
case ckind_t::ule_t: case ckind_t::ule_t:
assert_le(c.to_ule()); assert_le(is_positive, c.to_ule());
break; break;
default: default:
UNREACHABLE(); UNREACHABLE();
@ -261,34 +270,37 @@ namespace polysat {
return m_sz2num_vars[sz]++; return m_sz2num_vars[sz]++;
} }
void linear_solver::set_value(pvar v, rational const& value) { void linear_solver::set_value(pvar v, rational const& value, unsigned dep) {
unsigned sz = s.size(v); unsigned sz = s.size(v);
auto& fp = sz2fixplex(sz); auto& fp = sz2fixplex(sz);
var_t w = pvar2var(sz, v); var_t w = pvar2var(sz, v);
m_trail.push_back(trail_i::set_bound_i); m_trail.push_back(trail_i::set_bound_i);
m_rows.push_back(std::make_pair(w, sz)); m_rows.push_back(std::make_pair(w, sz));
fp.set_value(w, value); fp.set_value(w, value, external_dep2dep(dep));
} }
void linear_solver::set_bound(pvar v, rational const& lo, rational const& hi) { void linear_solver::set_bound(pvar v, rational const& lo, rational const& hi, unsigned dep) {
unsigned sz = s.size(v); unsigned sz = s.size(v);
auto& fp = sz2fixplex(sz); auto& fp = sz2fixplex(sz);
var_t w = pvar2var(sz, v); var_t w = pvar2var(sz, v);
m_trail.push_back(trail_i::set_bound_i); m_trail.push_back(trail_i::set_bound_i);
m_rows.push_back(std::make_pair(w, sz)); m_rows.push_back(std::make_pair(w, sz));
fp.set_bounds(w, lo, hi); fp.set_bounds(w, lo, hi, external_dep2dep(dep));
} }
// check integer modular feasibility under current bounds. /**
// and inequalities * check integer modular feasibility under current bounds.
* and inequalities
*/
lbool linear_solver::check() { lbool linear_solver::check() {
lbool res = l_true; lbool res = l_true;
m_unsat_f = nullptr;
for (auto* f : m_fix) { for (auto* f : m_fix) {
if (!f) if (!f)
continue; continue;
lbool r = f->make_feasible(); lbool r = f->make_feasible();
if (r == l_false) { if (r == l_false) {
// m_unsat_f = f; m_unsat_f = f;
return r; return r;
} }
if (r == l_undef) if (r == l_undef)
@ -297,13 +309,25 @@ namespace polysat {
return res; return res;
} }
void linear_solver::unsat_core(unsigned_vector& deps) { void linear_solver::unsat_core(ptr_vector<constraint>& cs, unsigned_vector& deps) {
NOT_IMPLEMENTED_YET(); SASSERT(m_unsat_f);
deps.reset();
cs.reset();
m_unsat_f->get_infeasible_deps(deps);
unsigned j = 0;
for (unsigned dep : deps) {
if (is_constraint_dep(dep))
cs.push_back(m_active[dep2constraint_idx(dep)]);
else
deps[j++] = dep2external_dep(dep);
}
deps.shrink(j);
} }
// current value assigned to (linear) variable according to tableau. // current value assigned to (linear) variable according to tableau.
rational linear_solver::value(pvar v) { rational linear_solver::value(pvar v) {
return rational(0); unsigned sz = s.size(v);
return sz2fixplex(sz).get_value(pvar2var(sz, v));
} }
}; };

View file

@ -43,7 +43,8 @@ namespace polysat {
add_mono_i, add_mono_i,
set_bound_i, set_bound_i,
add_ineq_i, add_ineq_i,
add_row_i add_row_i,
set_active_i
}; };
struct mono_info { struct mono_info {
@ -81,6 +82,7 @@ namespace polysat {
svector<std::pair<var_t, unsigned>> m_rows; svector<std::pair<var_t, unsigned>> m_rows;
unsigned_vector m_var2ext; unsigned_vector m_var2ext;
unsigned_vector m_ext2var; unsigned_vector m_ext2var;
ptr_vector<constraint> m_active;
svector<var_t> m_vars; svector<var_t> m_vars;
vector<rational> m_coeffs; vector<rational> m_coeffs;
@ -90,29 +92,31 @@ namespace polysat {
unsigned_vector m_sz2num_vars; unsigned_vector m_sz2num_vars;
small_object_allocator m_alloc; small_object_allocator m_alloc;
svector<mono_info> m_monomials; svector<mono_info> m_monomials;
fixplex_base* m_unsat_f = nullptr;
fixplex_base& sz2fixplex(unsigned sz); fixplex_base& sz2fixplex(unsigned sz);
void linearize(pdd const& p); void linearize(pdd const& p);
var_t fresh_var(unsigned sz); var_t fresh_var(unsigned sz);
var_t internalize_pdd(pdd const& p); var_t internalize_pdd(pdd const& p);
void new_eq(eq_constraint& eq); void new_eq(eq_constraint& eq);
void new_le(ule_constraint& le); void new_le(ule_constraint& le);
void assert_eq(eq_constraint& eq); void assert_eq(bool is_positive, eq_constraint& eq);
void assert_le(ule_constraint& le); void assert_le(bool is_positive, ule_constraint& le);
// bind monomial to variable. // bind monomial to variable.
var_t mono2var(unsigned sz, unsigned_vector const& m); var_t mono2var(unsigned sz, unsigned_vector const& m);
var_t pvar2var(unsigned sz, pvar v); var_t pvar2var(unsigned sz, pvar v);
unsigned_vector var2mono(unsigned sz, var_t v) { throw default_exception("nyi"); } // unsigned_vector var2mono(unsigned sz, var_t v) { throw default_exception("nyi"); }
//
// TBD trail object for // distinguish constraint and justification dependencies
// removing variables unsigned external_dep2dep(unsigned dep) const { return UINT_MAX - dep; }
// undoing variable bounds bounds unsigned constraint_idx2dep(unsigned idx) const { return idx; }
// removing rows from fixplex bool is_constraint_dep(unsigned dep) const { return dep < UINT_MAX / 2; }
// unsigned dep2constraint_idx(unsigned dep) const { return dep; }
unsigned dep2external_dep(unsigned dep) const { return UINT_MAX - dep; }
public: public:
linear_solver(solver& s): linear_solver(solver& s):
s(s), s(s),
@ -122,13 +126,13 @@ namespace polysat {
void push(); void push();
void pop(unsigned n); void pop(unsigned n);
void new_constraint(constraint& c); void new_constraint(constraint& c);
void set_value(pvar v, rational const& value); void set_value(pvar v, rational const& value, unsigned dep);
void set_bound(pvar v, rational const& lo, rational const& hi); void set_bound(pvar v, rational const& lo, rational const& hi, unsigned dep);
void activate_constraint(constraint& c); void activate_constraint(bool is_positive, constraint& c);
// check integer modular feasibility under current bounds. // check integer modular feasibility under current bounds.
lbool check(); lbool check();
void unsat_core(unsigned_vector& deps); void unsat_core(ptr_vector<constraint>& constraints, unsigned_vector& deps);
// current value assigned to (linear) variable according to tableau. // current value assigned to (linear) variable according to tableau.
rational value(pvar v); rational value(pvar v);

View file

@ -383,7 +383,8 @@ namespace polysat {
m_trail.push_back(trail_instr_t::assign_i); m_trail.push_back(trail_instr_t::assign_i);
m_justification[v] = j; m_justification[v] = j;
#if ENABLE_LINEAR_SOLVER #if ENABLE_LINEAR_SOLVER
m_linear_solver.set_value(v, val); // TODO: convert justification into a format that can be tracked in a depdendency core.
m_linear_solver.set_value(v, val, UINT_MAX);
#endif #endif
} }
@ -942,7 +943,12 @@ namespace polysat {
m_bvars.assign(lit, m_level, reason, lemma); m_bvars.assign(lit, m_level, reason, lemma);
} }
/// Activate constraint immediately /**
* Activate constraint immediately
* Activation and de-activation of constraints follows the scope controlled by push/pop.
* constraints activated within the linear solver are de-activated when the linear
* solver is popped.
*/
void solver::activate_constraint(constraint& c, bool is_true) { void solver::activate_constraint(constraint& c, bool is_true) {
LOG("Activating constraint: " << c << " ; is_true = " << is_true); LOG("Activating constraint: " << c << " ; is_true = " << is_true);
SASSERT(m_bvars.value(c.bvar()) == to_lbool(is_true)); SASSERT(m_bvars.value(c.bvar()) == to_lbool(is_true));
@ -950,18 +956,15 @@ namespace polysat {
add_watch(c); add_watch(c);
c.narrow(*this); c.narrow(*this);
#if ENABLE_LINEAR_SOLVER #if ENABLE_LINEAR_SOLVER
m_linear_solver.activate_constraint(c); m_linear_solver.activate_constraint(c.is_positive(), c);
#endif #endif
} }
/// Deactivate constraint immediately /// Deactivate constraint
void solver::deactivate_constraint(constraint& c) { void solver::deactivate_constraint(constraint& c) {
LOG("Deactivating constraint: " << c); LOG("Deactivating constraint: " << c);
erase_watch(c); erase_watch(c);
c.unassign(); c.unassign();
#if ENABLE_LINEAR_SOLVER
m_linear_solver.deactivate_constraint(c); // TODO add this method to linear solver?
#endif
} }
void solver::backjump(unsigned new_level) { void solver::backjump(unsigned new_level) {

View file

@ -28,7 +28,7 @@ namespace polysat {
var_t ys[3] = { x, y, z }; var_t ys[3] = { x, y, z };
numeral coeffs[3] = { 2, 1, 4 }; numeral coeffs[3] = { 2, 1, 4 };
fp.add_row(x, 3, ys, coeffs); fp.add_row(x, 3, ys, coeffs);
fp.set_bounds(x, 1, 2); fp.set_bounds(x, 1, 2, 0);
fp.run(); fp.run();
} }
@ -38,7 +38,7 @@ namespace polysat {
var_t ys[3] = { x, y, z }; var_t ys[3] = { x, y, z };
numeral coeffs[3] = { 1, 2, 4 }; numeral coeffs[3] = { 1, 2, 4 };
fp.add_row(x, 3, ys, coeffs); fp.add_row(x, 3, ys, coeffs);
fp.set_bounds(x, 3, 4); fp.set_bounds(x, 3, 4, 1);
fp.run(); fp.run();
} }
@ -48,9 +48,9 @@ namespace polysat {
var_t ys[3] = { x, y, z }; var_t ys[3] = { x, y, z };
numeral coeffs[3] = { 1, 1, 1 }; numeral coeffs[3] = { 1, 1, 1 };
fp.add_row(x, 3, ys, coeffs); fp.add_row(x, 3, ys, coeffs);
fp.set_bounds(x, 3, 4); fp.set_bounds(x, 3, 4, 1);
fp.set_bounds(y, 3, 4); fp.set_bounds(y, 3, 4, 2);
fp.set_bounds(z, 3, 4); fp.set_bounds(z, 3, 4, 3);
fp.run(); fp.run();
} }
@ -60,22 +60,22 @@ namespace polysat {
var_t ys[3] = { x, y, z }; var_t ys[3] = { x, y, z };
numeral coeffs[3] = { 1, 1, 1 }; numeral coeffs[3] = { 1, 1, 1 };
fp.add_row(x, 3, ys, coeffs); fp.add_row(x, 3, ys, coeffs);
fp.set_bounds(x, 3, 4); fp.set_bounds(x, 3, 4, 1);
fp.set_bounds(y, 3, 6); fp.set_bounds(y, 3, 6, 2);
fp.run(); fp.run();
fp.propagate_bounds(); fp.propagate_bounds();
fp.reset(); fp.reset();
coeffs[2] = 0ull - 1; coeffs[2] = 0ull - 1;
fp.add_row(x, 3, ys, coeffs); fp.add_row(x, 3, ys, coeffs);
fp.set_bounds(x, 3, 4); fp.set_bounds(x, 3, 4, 1);
fp.set_bounds(y, 3, 6); fp.set_bounds(y, 3, 6, 2);
fp.run(); fp.run();
fp.propagate_bounds(); fp.propagate_bounds();
fp.reset(); fp.reset();
fp.add_row(x, 3, ys, coeffs); fp.add_row(x, 3, ys, coeffs);
fp.set_bounds(x, 3, 4); fp.set_bounds(x, 3, 4, 1);
fp.set_bounds(y, 3, 6); fp.set_bounds(y, 3, 6, 2);
fp.set_bounds(z, 1, 8); fp.set_bounds(z, 1, 8, 3);
fp.run(); fp.run();
fp.propagate_bounds(); fp.propagate_bounds();
fp.reset(); fp.reset();
@ -88,8 +88,8 @@ namespace polysat {
var_t ys[3] = { x, y, z }; var_t ys[3] = { x, y, z };
numeral coeffs[3] = { 1, 1, 1 }; numeral coeffs[3] = { 1, 1, 1 };
fp.add_row(x, 3, ys, coeffs); fp.add_row(x, 3, ys, coeffs);
fp.set_bounds(x, 3, 4); fp.set_bounds(x, 3, 4, 1);
fp.set_bounds(y, 3, 6); fp.set_bounds(y, 3, 6, 2);
var_t ys2[3] = { u, y, z }; var_t ys2[3] = { u, y, z };
fp.add_row(u, 3, ys2, coeffs); fp.add_row(u, 3, ys2, coeffs);
fp.run(); fp.run();
@ -107,7 +107,7 @@ namespace polysat {
numeral coeffs2[3] = { 1, m1, 1 }; numeral coeffs2[3] = { 1, m1, 1 };
fp.add_row(x, 3, ys1, coeffs1); fp.add_row(x, 3, ys1, coeffs1);
fp.add_row(z, 3, ys2, coeffs2); fp.add_row(z, 3, ys2, coeffs2);
fp.set_bounds(u, 1, 2); fp.set_bounds(u, 1, 2, 1);
fp.run(); fp.run();
fp.propagate_eqs(); fp.propagate_eqs();
for (auto e : fp.var_eqs()) for (auto e : fp.var_eqs())