mirror of
https://github.com/Z3Prover/z3
synced 2025-06-06 14:13:23 +00:00
add inequality propagation
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
parent
7b3eaf75ce
commit
c1365b6ba8
3 changed files with 178 additions and 47 deletions
|
@ -53,10 +53,24 @@ namespace polysat {
|
||||||
virtual void add_le(var_t v, var_t w, unsigned dep) = 0;
|
virtual void add_le(var_t v, var_t w, unsigned dep) = 0;
|
||||||
virtual void add_lt(var_t v, var_t w, unsigned dep) = 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 bool inconsistent() const = 0;
|
||||||
virtual unsigned_vector const& get_unsat_core() const = 0;
|
virtual unsigned_vector const& get_unsat_core() const = 0;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ineq {
|
||||||
|
var_t v = UINT_MAX;
|
||||||
|
var_t w = UINT_MAX;
|
||||||
|
bool strict = false;
|
||||||
|
bool is_active = true;
|
||||||
|
unsigned dep = UINT_MAX;
|
||||||
|
ineq(var_t v, var_t w, unsigned dep, bool s) :
|
||||||
|
v(v), w(w), strict(s), dep(dep) {}
|
||||||
|
|
||||||
|
std::ostream& display(std::ostream& out) const {
|
||||||
|
return out << "v" << v << (strict ? " < v" : " <= v") << w;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
template<typename Ext>
|
template<typename Ext>
|
||||||
class fixplex : public fixplex_base {
|
class fixplex : public fixplex_base {
|
||||||
|
@ -143,19 +157,10 @@ namespace polysat {
|
||||||
fix_entry():x(null_var), r(0) {}
|
fix_entry():x(null_var), r(0) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ineq {
|
|
||||||
var_t v = null_var;
|
|
||||||
var_t w = null_var;
|
|
||||||
bool strict = false;
|
|
||||||
bool is_active = true;
|
|
||||||
unsigned dep = UINT_MAX;
|
|
||||||
ineq(var_t v, var_t w, unsigned dep, bool s):
|
|
||||||
v(v), w(w), strict(s), dep(dep) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
enum trail_i {
|
enum trail_i {
|
||||||
inc_level_i,
|
inc_level_i,
|
||||||
set_bound_i,
|
set_bound_i,
|
||||||
|
set_inconsistent_i,
|
||||||
add_ineq_i,
|
add_ineq_i,
|
||||||
add_row_i
|
add_row_i
|
||||||
};
|
};
|
||||||
|
@ -175,6 +180,7 @@ namespace polysat {
|
||||||
random_gen m_random;
|
random_gen m_random;
|
||||||
uint_set m_left_basis;
|
uint_set m_left_basis;
|
||||||
unsigned_vector m_unsat_core;
|
unsigned_vector m_unsat_core;
|
||||||
|
bool m_inconsistent = false;
|
||||||
unsigned_vector m_base_vars;
|
unsigned_vector m_base_vars;
|
||||||
stats m_stats;
|
stats m_stats;
|
||||||
vector<stashed_bound> m_stashed_bounds;
|
vector<stashed_bound> m_stashed_bounds;
|
||||||
|
@ -200,6 +206,7 @@ namespace polysat {
|
||||||
|
|
||||||
void push() override;
|
void push() override;
|
||||||
void pop(unsigned n) override;
|
void pop(unsigned n) override;
|
||||||
|
bool inconsistent() const override { return m_inconsistent; }
|
||||||
|
|
||||||
lbool make_feasible() override;
|
lbool make_feasible() override;
|
||||||
void add_row(var_t base, unsigned num_vars, var_t const* vars, rational const* coeffs) override;
|
void add_row(var_t base, unsigned num_vars, var_t const* vars, rational const* coeffs) override;
|
||||||
|
@ -226,6 +233,10 @@ namespace polysat {
|
||||||
unsigned get_num_vars() const { return m_vars.size(); }
|
unsigned get_num_vars() const { return m_vars.size(); }
|
||||||
void reset();
|
void reset();
|
||||||
lbool propagate_bounds();
|
lbool propagate_bounds();
|
||||||
|
|
||||||
|
svector<std::pair<unsigned, ineq>> stack;
|
||||||
|
uint_set on_stack;
|
||||||
|
lbool propagate_ineqs(ineq const& i0);
|
||||||
void propagate_eqs();
|
void propagate_eqs();
|
||||||
vector<var_eq> const& var_eqs() const { return m_var_eqs; }
|
vector<var_eq> const& var_eqs() const { return m_var_eqs; }
|
||||||
void reset_eqs() { m_var_eqs.reset(); }
|
void reset_eqs() { m_var_eqs.reset(); }
|
||||||
|
@ -251,8 +262,8 @@ namespace polysat {
|
||||||
void get_offset_eqs(row const& r);
|
void get_offset_eqs(row const& r);
|
||||||
void fixed_var_eh(row const& r, var_t x);
|
void fixed_var_eh(row const& r, var_t x);
|
||||||
void eq_eh(var_t x, var_t y, row const& r1, row const& r2);
|
void eq_eh(var_t x, var_t y, row const& r1, row const& r2);
|
||||||
lbool propagate_bounds(row const& r);
|
bool propagate_row(row const& r);
|
||||||
bool propagate_bounds(ineq const& i);
|
bool propagate_ineq(ineq const& i);
|
||||||
bool propagate_strict_bounds(ineq const& i);
|
bool propagate_strict_bounds(ineq const& i);
|
||||||
bool propagate_non_strict_bounds(ineq const& i);
|
bool propagate_non_strict_bounds(ineq const& i);
|
||||||
bool new_bound(row const& r, var_t x, mod_interval<numeral> const& range);
|
bool new_bound(row const& r, var_t x, mod_interval<numeral> const& range);
|
||||||
|
@ -404,6 +415,7 @@ namespace polysat {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
typedef _scoped_numeral<manager> scoped_numeral;
|
typedef _scoped_numeral<manager> scoped_numeral;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef generic_uint_ext<uint64_t> uint64_ext;
|
typedef generic_uint_ext<uint64_t> uint64_ext;
|
||||||
|
@ -415,5 +427,11 @@ namespace polysat {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline std::ostream& operator<<(std::ostream& out, ineq const& i) {
|
||||||
|
return i.display(out);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -96,6 +96,11 @@ namespace polysat {
|
||||||
case trail_i::add_ineq_i:
|
case trail_i::add_ineq_i:
|
||||||
restore_ineq();
|
restore_ineq();
|
||||||
break;
|
break;
|
||||||
|
case trail_i::set_inconsistent_i:
|
||||||
|
SASSERT(m_inconsistent);
|
||||||
|
m_inconsistent = false;
|
||||||
|
m_unsat_core.reset();
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
|
@ -126,6 +131,8 @@ namespace polysat {
|
||||||
|
|
||||||
template<typename Ext>
|
template<typename Ext>
|
||||||
lbool fixplex<Ext>::make_feasible() {
|
lbool fixplex<Ext>::make_feasible() {
|
||||||
|
if (m_inconsistent)
|
||||||
|
return l_false;
|
||||||
++m_stats.m_num_checks;
|
++m_stats.m_num_checks;
|
||||||
m_left_basis.reset();
|
m_left_basis.reset();
|
||||||
unsigned num_iterations = 0;
|
unsigned num_iterations = 0;
|
||||||
|
@ -537,11 +544,13 @@ namespace polysat {
|
||||||
auto hi0 = m_vars[v].hi;
|
auto hi0 = m_vars[v].hi;
|
||||||
m_stashed_bounds.push_back(stashed_bound(v, m_vars[v]));
|
m_stashed_bounds.push_back(stashed_bound(v, m_vars[v]));
|
||||||
m_trail.push_back(trail_i::set_bound_i);
|
m_trail.push_back(trail_i::set_bound_i);
|
||||||
|
// std::cout << "new bound " << x << " " << m_vars[x] << " " << mod_interval<numeral>(l, h) << " -> ";
|
||||||
m_vars[v] &= mod_interval(l, h);
|
m_vars[v] &= mod_interval(l, h);
|
||||||
if (lo0 != m_vars[v].lo)
|
if (lo0 != m_vars[v].lo)
|
||||||
m_vars[v].m_lo_dep = dep;
|
m_vars[v].m_lo_dep = dep;
|
||||||
if (hi0 != m_vars[v].hi)
|
if (hi0 != m_vars[v].hi)
|
||||||
m_vars[v].m_hi_dep = dep;
|
m_vars[v].m_hi_dep = dep;
|
||||||
|
// std::cout << m_vars[x] << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Ext>
|
template<typename Ext>
|
||||||
|
@ -646,11 +655,12 @@ namespace polysat {
|
||||||
*/
|
*/
|
||||||
template<typename Ext>
|
template<typename Ext>
|
||||||
bool fixplex<Ext>::ineqs_are_violated() {
|
bool fixplex<Ext>::ineqs_are_violated() {
|
||||||
|
lbool r;
|
||||||
for (unsigned i = 0; i < m_ineqs_to_check.size(); ++i) {
|
for (unsigned i = 0; i < m_ineqs_to_check.size(); ++i) {
|
||||||
unsigned idx = m_ineqs_to_check[i];
|
unsigned idx = m_ineqs_to_check[i];
|
||||||
if (idx >= m_ineqs.size())
|
if (idx >= m_ineqs.size())
|
||||||
continue;
|
continue;
|
||||||
if (!propagate_bounds(m_ineqs[idx]))
|
if (r = propagate_ineqs(m_ineqs[idx]), r == l_false)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -860,7 +870,6 @@ namespace polysat {
|
||||||
*/
|
*/
|
||||||
template<typename Ext>
|
template<typename Ext>
|
||||||
void fixplex<Ext>::set_infeasible_base(var_t v) {
|
void fixplex<Ext>::set_infeasible_base(var_t v) {
|
||||||
m_unsat_core.reset();
|
|
||||||
SASSERT(is_base(v));
|
SASSERT(is_base(v));
|
||||||
auto row = base2row(v);
|
auto row = base2row(v);
|
||||||
ptr_vector<u_dependency> todo;
|
ptr_vector<u_dependency> todo;
|
||||||
|
@ -869,7 +878,12 @@ namespace polysat {
|
||||||
todo.push_back(m_vars[v].m_lo_dep);
|
todo.push_back(m_vars[v].m_lo_dep);
|
||||||
todo.push_back(m_vars[v].m_hi_dep);
|
todo.push_back(m_vars[v].m_hi_dep);
|
||||||
}
|
}
|
||||||
|
SASSERT(!m_inconsistent);
|
||||||
|
SASSERT(m_unsat_core.empty());
|
||||||
|
m_inconsistent = true;
|
||||||
|
m_trail.push_back(trail_i::set_inconsistent_i);
|
||||||
m_deps.linearize(todo, m_unsat_core);
|
m_deps.linearize(todo, m_unsat_core);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1115,15 +1129,87 @@ namespace polysat {
|
||||||
template<typename Ext>
|
template<typename Ext>
|
||||||
lbool fixplex<Ext>::propagate_bounds() {
|
lbool fixplex<Ext>::propagate_bounds() {
|
||||||
lbool r = l_true;
|
lbool r = l_true;
|
||||||
for (unsigned i = 0; r == l_true && i < m_rows.size(); ++i)
|
for (unsigned i = 0; i < m_rows.size(); ++i)
|
||||||
r = propagate_bounds(row(i));
|
if (!propagate_row(row(i)))
|
||||||
if (r != l_true)
|
return l_false;
|
||||||
|
for (auto ineq : m_ineqs)
|
||||||
|
if (r = propagate_ineqs(ineq), r != l_true)
|
||||||
return r;
|
return r;
|
||||||
for (auto ineq : m_ineqs) {
|
return l_true;
|
||||||
if (!propagate_bounds(ineq))
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// DFS search propagating inequalities
|
||||||
|
// TBDs:
|
||||||
|
// - manage on_stack: which variables? (not source of root inequality)
|
||||||
|
// - propagate other direction?
|
||||||
|
// - re-propagate if lower bound for w gets increased in stack?
|
||||||
|
// - combine with row propagation?
|
||||||
|
// - search for shorter cycles? conflicts with literals asserted at lower (glue) levels?
|
||||||
|
// - statistics
|
||||||
|
// use diff-logic propagation instead?
|
||||||
|
// - use heap based on potential
|
||||||
|
// - update gamma without overflow issues
|
||||||
|
//
|
||||||
|
|
||||||
|
template<typename Ext>
|
||||||
|
lbool fixplex<Ext>::propagate_ineqs(ineq const& i0) {
|
||||||
|
numeral old_lo = m_vars[i0.w].lo;
|
||||||
|
if (!propagate_ineq(i0))
|
||||||
|
return l_false;
|
||||||
|
if (old_lo == m_vars[i0.w].lo)
|
||||||
|
return l_true;
|
||||||
|
on_stack.reset();
|
||||||
|
stack.reset();
|
||||||
|
stack.push_back(std::make_pair(0, i0));
|
||||||
|
on_stack.insert(i0.v);
|
||||||
|
while (!stack.empty()) {
|
||||||
|
if (!m_limit.inc())
|
||||||
|
return l_undef;
|
||||||
|
auto [ineq_out, i] = stack.back();
|
||||||
|
auto const& ineqs = m_var2ineqs[i.w];
|
||||||
|
for (; ineq_out < ineqs.size(); ++ineq_out) {
|
||||||
|
auto& i_out = m_ineqs[ineqs[ineq_out]];
|
||||||
|
if (i.w != i_out.v)
|
||||||
|
continue;
|
||||||
|
old_lo = m_vars[i_out.w].lo;
|
||||||
|
if (!propagate_ineq(i_out))
|
||||||
|
return l_false;
|
||||||
|
bool is_onstack = on_stack.contains(i_out.w);
|
||||||
|
if (old_lo != m_vars[i_out.w].lo && !is_onstack) {
|
||||||
|
on_stack.insert(i_out.w);
|
||||||
|
stack.back().first = ineq_out + 1;
|
||||||
|
stack.push_back(std::make_pair(0, i_out));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is_onstack) {
|
||||||
|
on_stack.insert(i_out.w);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool strict = i_out.strict, found = false;
|
||||||
|
unsigned j = stack.size();
|
||||||
|
for (; !found && j-- > 0; ) {
|
||||||
|
ineq i2 = stack[j].second;
|
||||||
|
strict |= i2.strict;
|
||||||
|
if (i2.v == i_out.w)
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
if (strict && found) {
|
||||||
|
auto* d = mk_leaf(i_out.dep);
|
||||||
|
for (; j < stack.size(); ++j)
|
||||||
|
d = m_deps.mk_join(d, mk_leaf(stack[j].second.dep));
|
||||||
|
conflict(d);
|
||||||
return l_false;
|
return l_false;
|
||||||
}
|
}
|
||||||
return r;
|
}
|
||||||
|
if (ineq_out == ineqs.size()) {
|
||||||
|
on_stack.remove(i.w);
|
||||||
|
stack.pop_back();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return l_true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1136,7 +1222,7 @@ namespace polysat {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
template<typename Ext>
|
template<typename Ext>
|
||||||
lbool fixplex<Ext>::propagate_bounds(row const& r) {
|
bool fixplex<Ext>::propagate_row(row const& r) {
|
||||||
mod_interval<numeral> range(0, 1);
|
mod_interval<numeral> range(0, 1);
|
||||||
numeral free_c = 0;
|
numeral free_c = 0;
|
||||||
var_t free_v = null_var;
|
var_t free_v = null_var;
|
||||||
|
@ -1152,12 +1238,12 @@ namespace polysat {
|
||||||
}
|
}
|
||||||
range += m_vars[v] * c;
|
range += m_vars[v] * c;
|
||||||
if (range.is_free())
|
if (range.is_free())
|
||||||
return l_true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (free_v != null_var) {
|
if (free_v != null_var) {
|
||||||
range = (-range) * free_c;
|
range = (-range) * free_c;
|
||||||
lbool res = new_bound(r, free_v, range) ? l_true : l_false;
|
bool res = new_bound(r, free_v, range);
|
||||||
SASSERT(in_bounds(free_v));
|
SASSERT(in_bounds(free_v));
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
@ -1165,7 +1251,7 @@ namespace polysat {
|
||||||
var_t v = e.var();
|
var_t v = e.var();
|
||||||
SASSERT(!is_free(v));
|
SASSERT(!is_free(v));
|
||||||
auto range1 = range - m_vars[v] * e.coeff();
|
auto range1 = range - m_vars[v] * e.coeff();
|
||||||
lbool res = new_bound(r, v, range1) ? l_true : l_false;
|
bool res = new_bound(r, v, range1);
|
||||||
if (res != l_true)
|
if (res != l_true)
|
||||||
return res;
|
return res;
|
||||||
// SASSERT(in_bounds(v));
|
// SASSERT(in_bounds(v));
|
||||||
|
@ -1180,6 +1266,8 @@ namespace polysat {
|
||||||
auto* vlo = m_vars[v].m_lo_dep, *vhi = m_vars[v].m_hi_dep;
|
auto* vlo = m_vars[v].m_lo_dep, *vhi = m_vars[v].m_hi_dep;
|
||||||
auto* wlo = m_vars[w].m_lo_dep, *whi = m_vars[w].m_hi_dep;
|
auto* wlo = m_vars[w].m_lo_dep, *whi = m_vars[w].m_hi_dep;
|
||||||
|
|
||||||
|
if (v == w)
|
||||||
|
return conflict(i, nullptr), false;
|
||||||
if (lo(w) == 0 && !new_bound(i, w, lo(w) + 1, lo(w), wlo))
|
if (lo(w) == 0 && !new_bound(i, w, lo(w) + 1, lo(w), wlo))
|
||||||
return false;
|
return false;
|
||||||
if (hi(w) == 1 && !new_bound(i, w, lo(w), hi(w) - 1, whi))
|
if (hi(w) == 1 && !new_bound(i, w, lo(w), hi(w) - 1, whi))
|
||||||
|
@ -1214,9 +1302,9 @@ namespace polysat {
|
||||||
|
|
||||||
// manual patch
|
// manual patch
|
||||||
if (is_fixed(w) && lo(w) == 0)
|
if (is_fixed(w) && lo(w) == 0)
|
||||||
return conflict(wlo, whi), false;
|
return conflict(i, wlo, whi), false;
|
||||||
if (is_fixed(v) && hi(v) == 0)
|
if (is_fixed(v) && hi(v) == 0)
|
||||||
return conflict(vlo, vhi), false;
|
return conflict(i, vlo, vhi), false;
|
||||||
if (!is_free(w) && (lo(w) <= hi(w) || hi(w) == 0) && (lo(v) < hi(v) || hi(v) == 0) && !new_bound(i, v, lo(v), hi(w) - 1, vlo, wlo, whi))
|
if (!is_free(w) && (lo(w) <= hi(w) || hi(w) == 0) && (lo(v) < hi(v) || hi(v) == 0) && !new_bound(i, v, lo(v), hi(w) - 1, vlo, wlo, whi))
|
||||||
return false;
|
return false;
|
||||||
if (!is_free(v) && (lo(w) <= hi(w) || hi(w) == 0) && (lo(v) < hi(v) || hi(v) == 0) && !new_bound(i, w, lo(v) + 1, hi(w), vlo, vhi, whi))
|
if (!is_free(v) && (lo(w) <= hi(w) || hi(w) == 0) && (lo(v) < hi(v) || hi(v) == 0) && !new_bound(i, w, lo(v) + 1, hi(w), vlo, vhi, whi))
|
||||||
|
@ -1234,7 +1322,7 @@ namespace polysat {
|
||||||
if (hi(w) <= lo(v) && (lo(v) < hi(v) || hi(v) == 0) && !new_bound(i, w, lo(w), 0, vlo, vhi, wlo, whi))
|
if (hi(w) <= lo(v) && (lo(v) < hi(v) || hi(v) == 0) && !new_bound(i, w, lo(w), 0, vlo, vhi, wlo, whi))
|
||||||
return false;
|
return false;
|
||||||
if (lo(w) < hi(w) && hi(w) <= lo(v) && (lo(v) < hi(v) || hi(v) == 0))
|
if (lo(w) < hi(w) && hi(w) <= lo(v) && (lo(v) < hi(v) || hi(v) == 0))
|
||||||
return conflict(vlo, vhi, wlo, whi), false;
|
return conflict(i, vlo, vhi, wlo, whi), false;
|
||||||
// if (!is_free(w) && hi(v) < lo(v) && lo(w) != 0 && (lo(w) <= hi(w) || hi(w) == 0) && !new_bound(i, v, lo(w) - 1, hi(v), vlo, vhi, wlo, whi))
|
// if (!is_free(w) && hi(v) < lo(v) && lo(w) != 0 && (lo(w) <= hi(w) || hi(w) == 0) && !new_bound(i, v, lo(w) - 1, hi(v), vlo, vhi, wlo, whi))
|
||||||
// return false;
|
// return false;
|
||||||
|
|
||||||
|
@ -1245,7 +1333,7 @@ namespace polysat {
|
||||||
if (lo(w) == 0 && !new_bound(i, w, lo(w) + 1, lo(w), wlo))
|
if (lo(w) == 0 && !new_bound(i, w, lo(w) + 1, lo(w), wlo))
|
||||||
return false;
|
return false;
|
||||||
if (is_fixed(v) && hi(w) <= hi(v) && lo(w) <= hi(w) && !(is_free(w)))
|
if (is_fixed(v) && hi(w) <= hi(v) && lo(w) <= hi(w) && !(is_free(w)))
|
||||||
return conflict(wlo, whi, vhi, vlo), false;
|
return conflict(i, wlo, whi, vhi, vlo), false;
|
||||||
if (lo(w) <= lo(v) && lo(v) <= hi(v) && !new_bound(i, w, lo(v) + 1, lo(v), wlo, vhi, vlo))
|
if (lo(w) <= lo(v) && lo(v) <= hi(v) && !new_bound(i, w, lo(v) + 1, lo(v), wlo, vhi, vlo))
|
||||||
return false;
|
return false;
|
||||||
if (hi(w) <= hi(v) && lo(w) <= hi(w) && !(is_free(w)) && !new_bound(i, v, lo(v), hi(v) - 1, wlo, whi, vhi))
|
if (hi(w) <= hi(v) && lo(w) <= hi(w) && !(is_free(w)) && !new_bound(i, v, lo(v), hi(v) - 1, wlo, whi, vhi))
|
||||||
|
@ -1263,7 +1351,7 @@ namespace polysat {
|
||||||
if (hi(w) <= lo(v) && lo(w) <= hi(w) && !(is_free(w)) && !new_bound(i, v, lo(v) + 1, hi(w) - 1, wlo, whi, vlo))
|
if (hi(w) <= lo(v) && lo(w) <= hi(w) && !(is_free(w)) && !new_bound(i, v, lo(v) + 1, hi(w) - 1, wlo, whi, vlo))
|
||||||
return false;
|
return false;
|
||||||
if (is_fixed(w) && hi(v) == 0 && lo(w) <= lo(v))
|
if (is_fixed(w) && hi(v) == 0 && lo(w) <= lo(v))
|
||||||
return conflict(wlo, whi, vhi, vlo), false;
|
return conflict(i, wlo, whi, vhi, vlo), false;
|
||||||
if (hi(v) == 0 && lo(w) <= lo(v) && !new_bound(i, w, lo(v) + 1, hi(v), wlo, vhi, vlo))
|
if (hi(v) == 0 && lo(w) <= lo(v) && !new_bound(i, w, lo(v) + 1, hi(v), wlo, vhi, vlo))
|
||||||
return false;
|
return false;
|
||||||
if (hi(v) == 0 && !(is_free(v)) && !new_bound(i, v, lo(v), hi(v) - 1, vhi))
|
if (hi(v) == 0 && !(is_free(v)) && !new_bound(i, v, lo(v), hi(v) - 1, vhi))
|
||||||
|
@ -1290,7 +1378,7 @@ namespace polysat {
|
||||||
if (hi(w) < lo(w) && hi(w) <= lo(v) && lo(v) < hi(v) && !new_bound(i, w, lo(w), 0, vlo, vhi, wlo, whi))
|
if (hi(w) < lo(w) && hi(w) <= lo(v) && lo(v) < hi(v) && !new_bound(i, w, lo(w), 0, vlo, vhi, wlo, whi))
|
||||||
return false;
|
return false;
|
||||||
if (lo(w) < hi(w) && hi(w) <= lo(v) && (lo(v) < hi(v) || hi(v) == 0))
|
if (lo(w) < hi(w) && hi(w) <= lo(v) && (lo(v) < hi(v) || hi(v) == 0))
|
||||||
return conflict(vlo, vhi, wlo, whi), false;
|
return conflict(i, vlo, vhi, wlo, whi), false;
|
||||||
|
|
||||||
// automatically generated code.
|
// automatically generated code.
|
||||||
// see scripts/fixplex.py for script
|
// see scripts/fixplex.py for script
|
||||||
|
@ -1366,7 +1454,7 @@ namespace polysat {
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Ext>
|
template<typename Ext>
|
||||||
bool fixplex<Ext>::propagate_bounds(ineq const& i) {
|
bool fixplex<Ext>::propagate_ineq(ineq const& i) {
|
||||||
if (i.strict)
|
if (i.strict)
|
||||||
return propagate_strict_bounds(i);
|
return propagate_strict_bounds(i);
|
||||||
else
|
else
|
||||||
|
@ -1382,6 +1470,9 @@ namespace polysat {
|
||||||
void fixplex<Ext>::conflict(u_dependency* a) {
|
void fixplex<Ext>::conflict(u_dependency* a) {
|
||||||
m_unsat_core.reset();
|
m_unsat_core.reset();
|
||||||
m_deps.linearize(a, m_unsat_core);
|
m_deps.linearize(a, m_unsat_core);
|
||||||
|
SASSERT(!m_inconsistent);
|
||||||
|
m_inconsistent = true;
|
||||||
|
m_trail.push_back(trail_i::set_inconsistent_i);
|
||||||
TRACE("polysat", tout << "core: " << m_unsat_core << "\n";);
|
TRACE("polysat", tout << "core: " << m_unsat_core << "\n";);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1400,9 +1491,7 @@ namespace polysat {
|
||||||
bool fixplex<Ext>::new_bound(ineq const& i, var_t x, numeral const& l, numeral const& h, u_dependency* a, u_dependency* b, u_dependency* c, u_dependency* d) {
|
bool fixplex<Ext>::new_bound(ineq const& i, var_t x, numeral const& l, numeral const& h, u_dependency* a, u_dependency* b, u_dependency* c, u_dependency* d) {
|
||||||
bool was_fixed = lo(x) + 1 == hi(x);
|
bool was_fixed = lo(x) + 1 == hi(x);
|
||||||
u_dependency* dep = m_deps.mk_join(mk_leaf(i.dep), m_deps.mk_join(a, m_deps.mk_join(b, m_deps.mk_join(c, d))));
|
u_dependency* dep = m_deps.mk_join(mk_leaf(i.dep), m_deps.mk_join(a, m_deps.mk_join(b, m_deps.mk_join(c, d))));
|
||||||
// std::cout << "new bound " << x << " " << m_vars[x] << " " << mod_interval<numeral>(l, h) << " -> ";
|
|
||||||
update_bounds(x, l, h, dep);
|
update_bounds(x, l, h, dep);
|
||||||
// std::cout << m_vars[x] << "\n";
|
|
||||||
if (m_vars[x].is_empty())
|
if (m_vars[x].is_empty())
|
||||||
return conflict(m_vars[x].m_lo_dep, m_vars[x].m_hi_dep), false;
|
return conflict(m_vars[x].m_lo_dep, m_vars[x].m_hi_dep), false;
|
||||||
else if (!was_fixed && lo(x) + 1 == hi(x)) {
|
else if (!was_fixed && lo(x) + 1 == hi(x)) {
|
||||||
|
@ -1435,12 +1524,8 @@ namespace polysat {
|
||||||
if (vi.m_is_base) out << "b:" << vi.m_base2row << " " << pp(m_rows[vi.m_base2row].m_value) << " ";
|
if (vi.m_is_base) out << "b:" << vi.m_base2row << " " << pp(m_rows[vi.m_base2row].m_value) << " ";
|
||||||
out << "\n";
|
out << "\n";
|
||||||
}
|
}
|
||||||
for (auto const& i : m_ineqs) {
|
for (ineq const& i : m_ineqs)
|
||||||
if (i.strict)
|
out << i << "\n";
|
||||||
out << "v" << i.v << " < v" << i.w << "\n";
|
|
||||||
else
|
|
||||||
out << "v" << i.v << " <= v" << i.w << "\n";
|
|
||||||
}
|
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -131,13 +131,40 @@ namespace polysat {
|
||||||
std::cout << 29 << " " << e.mul_inverse(29) << " " << 29*e.mul_inverse(29) << "\n";
|
std::cout << 29 << " " << e.mul_inverse(29) << " " << 29*e.mul_inverse(29) << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_ineq1() {
|
static void test_ineq_propagation1() {
|
||||||
std::cout << "ineq1\n";
|
std::cout << "ineq propagation 1\n";
|
||||||
scoped_fp fp;
|
scoped_fp fp;
|
||||||
var_t x = 0, y = 1;
|
var_t x = 0, y = 1;
|
||||||
fp.add_lt(x, y, 1);
|
fp.add_lt(x, y, 1);
|
||||||
fp.add_le(y, x, 2);
|
fp.add_le(y, x, 2);
|
||||||
fp.run();
|
fp.run();
|
||||||
|
std::cout << "core:" << fp.get_unsat_core() << "\n";
|
||||||
|
SASSERT(fp.get_unsat_core().contains(1));
|
||||||
|
SASSERT(fp.get_unsat_core().contains(2));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_ineq_propagation2() {
|
||||||
|
std::cout << "ineq propagation 2\n";
|
||||||
|
scoped_fp fp;
|
||||||
|
var_t x = 0, y = 1, z = 2, u = 3, v = 4;
|
||||||
|
fp.add_le(x, y, 1);
|
||||||
|
fp.add_le(y, z, 2);
|
||||||
|
fp.add_le(z, u, 3);
|
||||||
|
fp.add_le(u, v, 4);
|
||||||
|
fp.add_le(v, x, 5);
|
||||||
|
fp.run();
|
||||||
|
for (unsigned i = 0; i < 4; ++i) {
|
||||||
|
SASSERT(!fp.inconsistent());
|
||||||
|
fp.push();
|
||||||
|
fp.add_lt(i, i + 1, 6);
|
||||||
|
fp.run();
|
||||||
|
SASSERT(fp.inconsistent());
|
||||||
|
std::cout << "core:" << fp.get_unsat_core() << "\n";
|
||||||
|
for (unsigned j = 1; j < 5; ++j)
|
||||||
|
SASSERT((j != i + 1) == fp.get_unsat_core().contains(j));
|
||||||
|
fp.get_unsat_core().contains(6);
|
||||||
|
fp.pop(1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_ineqs() {
|
static void test_ineqs() {
|
||||||
|
@ -344,7 +371,8 @@ namespace polysat {
|
||||||
|
|
||||||
void tst_fixplex() {
|
void tst_fixplex() {
|
||||||
|
|
||||||
polysat::test_ineq1();
|
polysat::test_ineq_propagation1();
|
||||||
|
polysat::test_ineq_propagation2();
|
||||||
polysat::test_ineqs();
|
polysat::test_ineqs();
|
||||||
|
|
||||||
polysat::test1();
|
polysat::test1();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue