mirror of
https://github.com/Z3Prover/z3
synced 2025-04-27 10:55:50 +00:00
Add BDD utilities; use them for narrowing/propagation of linear equality constraints (#5192)
* Add a few helper methods for encoding sets of integers as BDDs * Use BDD functions in solver * Add bdd::find_int * Use bdd::find_int in solver * Add narrowing for linear equality constraints * Simplify code for linear propagation * Add test for later * Narrowing can only handle linear constraints with a single variable * Need to push_cjust
This commit is contained in:
parent
e970fe5034
commit
f72e30e539
10 changed files with 208 additions and 104 deletions
|
@ -30,44 +30,23 @@ namespace polysat {
|
|||
}
|
||||
|
||||
bool solver::is_viable(pvar v, rational const& val) {
|
||||
bdd b = m_viable[v];
|
||||
for (unsigned k = size(v); k-- > 0 && !b.is_false(); )
|
||||
b &= val.get_bit(k) ? m_bdd.mk_var(k) : m_bdd.mk_nvar(k);
|
||||
return !b.is_false();
|
||||
return m_viable[v].contains_int(val, size(v));
|
||||
}
|
||||
|
||||
void solver::add_non_viable(pvar v, rational const& val) {
|
||||
LOG("pvar " << v << " /= " << val);
|
||||
TRACE("polysat", tout << "v" << v << " /= " << val << "\n";);
|
||||
bdd value = m_bdd.mk_true();
|
||||
for (unsigned k = size(v); k-- > 0; )
|
||||
value &= val.get_bit(k) ? m_bdd.mk_var(k) : m_bdd.mk_nvar(k);
|
||||
SASSERT((value && !m_viable[v]).is_false());
|
||||
push_viable(v);
|
||||
m_viable[v] &= !value;
|
||||
SASSERT(is_viable(v, val));
|
||||
intersect_viable(v, !m_bdd.mk_int(val, size(v)));
|
||||
}
|
||||
|
||||
lbool solver::find_viable(pvar v, rational & val) {
|
||||
val = 0;
|
||||
bdd viable = m_viable[v];
|
||||
if (viable.is_false())
|
||||
return l_false;
|
||||
bool is_unique = true;
|
||||
unsigned num_vars = 0;
|
||||
while (!viable.is_true()) {
|
||||
++num_vars;
|
||||
if (!viable.lo().is_false() && !viable.hi().is_false())
|
||||
is_unique = false;
|
||||
if (viable.lo().is_false()) {
|
||||
val += rational::power_of_two(viable.var());
|
||||
viable = viable.hi();
|
||||
}
|
||||
else
|
||||
viable = viable.lo();
|
||||
}
|
||||
is_unique &= num_vars == size(v);
|
||||
TRACE("polysat", tout << "v" << v << " := " << val << " unique " << is_unique << "\n";);
|
||||
return is_unique ? l_true : l_undef;
|
||||
void solver::intersect_viable(pvar v, bdd vals) {
|
||||
push_viable(v);
|
||||
m_viable[v] &= vals;
|
||||
}
|
||||
|
||||
dd::find_int_t solver::find_viable(pvar v, rational & val) {
|
||||
return m_viable[v].find_int(size(v), val);
|
||||
}
|
||||
|
||||
|
||||
|
@ -312,15 +291,15 @@ namespace polysat {
|
|||
IF_LOGGING(log_viable(v));
|
||||
rational val;
|
||||
switch (find_viable(v, val)) {
|
||||
case l_false:
|
||||
case dd::find_int_t::empty:
|
||||
LOG("Conflict: no value for pvar " << v);
|
||||
set_conflict(v);
|
||||
break;
|
||||
case l_true:
|
||||
case dd::find_int_t::singleton:
|
||||
LOG("Propagation: pvar " << v << " := " << val << " (due to unique value)");
|
||||
assign_core(v, val, justification::propagation(m_level));
|
||||
break;
|
||||
case l_undef:
|
||||
case dd::find_int_t::multiple:
|
||||
LOG("Decision: pvar " << v << " := " << val);
|
||||
push_level();
|
||||
assign_core(v, val, justification::decision(m_level));
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue