3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-23 00:55:31 +00:00
This commit is contained in:
Nikolaj Bjorner 2023-12-29 18:11:40 -08:00
parent 03e012c1d8
commit 78f32401ac
6 changed files with 66 additions and 58 deletions

View file

@ -62,11 +62,6 @@ namespace polysat {
auto& [sc, lit, val] = c.m_constraint_index.back();
auto& vars = sc.vars();
auto idx = c.m_constraint_index.size() - 1;
IF_VERBOSE(10,
verbose_stream() << "undo add watch " << sc << " ";
if (vars.size() > 0) verbose_stream() << "(" << idx << ": " << c.m_watch[vars[0]] << ") ";
if (vars.size() > 1) verbose_stream() << "(" << idx << ": " << c.m_watch[vars[1]] << ") ";
verbose_stream() << "\n");
unsigned n = sc.num_watch();
SASSERT(n <= vars.size());
auto del_watch = [&](unsigned i) {
@ -147,10 +142,6 @@ namespace polysat {
add_watch(idx, vars[0]);
if (j > 1)
add_watch(idx, vars[1]);
IF_VERBOSE(10, verbose_stream() << "add watch " << sc << " " << vars << " ";
if (j > 0) verbose_stream() << "( " << idx << " : " << m_watch[vars[0]] << ") ";
if (j > 1) verbose_stream() << "( " << idx << " : " << m_watch[vars[1]] << ") ";
verbose_stream() << "\n");
s.trail().push(mk_add_watch(*this));
return { idx };
}
@ -166,38 +157,36 @@ namespace polysat {
CTRACE("bv", is_assigned(m_var), display(tout << "v" << m_var << " is assigned\n"););
SASSERT(!is_assigned(m_var));
switch (m_viable.find_viable(m_var, m_value)) {
auto& var_value = m_values[m_var];
switch (m_viable.find_viable(m_var, var_value)) {
case find_t::empty:
viable_conflict(m_var);
return sat::check_result::CR_CONTINUE;
case find_t::singleton: {
auto p = var2pdd(m_var).mk_var(m_var);
auto sc = m_constraints.eq(p, m_value);
TRACE("bv", tout << "check-propagate v" << m_var << " := " << m_value << " " << sc << "\n");
auto sc = m_constraints.eq(p, var_value);
TRACE("bv", tout << "check-propagate v" << m_var << " := " << var_value << " " << sc << "\n");
auto d = s.propagate(sc, m_viable.explain(), "viable-propagate");
propagate_assignment(m_var, m_value, d);
propagate_assignment(m_var, var_value, d);
return sat::check_result::CR_CONTINUE;
}
case find_t::multiple: {
do {
try_again:
dependency d = null_dependency;
lbool value = s.add_eq_literal(m_var, m_value, d);
TRACE("bv", tout << "check-multiple v" << m_var << " := " << m_value << " " << value << "\n");
switch (value) {
case l_true:
propagate_assignment(m_var, m_value, d);
break;
case l_false:
// add m_var != m_value to m_viable but need a constraint index for that.
m_value = mod(m_value + 1, rational::power_of_two(size(m_var)));
goto try_again;
default:
// let core assign equality.
break;
}
}
while (false);
dependency d = null_dependency;
lbool value = s.add_eq_literal(m_var, var_value, d);
TRACE("bv", tout << "check-multiple v" << m_var << " := " << var_value << " " << value << "\n");
switch (value) {
case l_true:
propagate_assignment(m_var, var_value, d);
break;
case l_false:
// disequality is forced into propagation queue.
var_value = mod(var_value + 1, rational::power_of_two(size(m_var)));
propagate();
break;
default:
// let core assign equality.
break;
}
return sat::check_result::CR_CONTINUE;
}
case find_t::resource_out:
@ -211,14 +200,17 @@ namespace polysat {
sat::check_result core::final_check() {
unsigned n = 0;
constraint_id conflict_idx = { UINT_MAX };
// verbose_stream() << "final-check\n";
for (auto idx : m_prop_queue) {
auto [sc, d, value] = m_constraint_index[idx.id];
SASSERT(value != l_undef);
// verbose_stream() << "constraint " << (value == l_true ? sc : ~sc) << "\n";
lbool eval_value = eval(sc);
CTRACE("bv", eval_value == l_undef, sc.display(tout << "eval: ") << " evaluates to " << eval_value << "\n"; display(tout););
SASSERT(eval_value != l_undef);
if (eval_value == value)
continue;
// verbose_stream() << "violated " << sc << " " << d << " " << eval_value << "\n";
if (0 == (m_rand() % (++n)))
conflict_idx = idx;
@ -288,8 +280,9 @@ namespace polysat {
s.set_conflict({dep}, "infeasible assignment");
return;
}
if (sc.is_eq(m_var, m_value))
propagate_assignment(m_var, m_value, dep);
rational var_value;
if (sc.is_eq(m_var, var_value))
propagate_assignment(m_var, var_value, dep);
else
propagate_activation(idx, sc, dep);
}
@ -424,7 +417,7 @@ namespace polysat {
return s.inconsistent();
}
void core::assign_eh(constraint_id index, bool sign, unsigned level) {
void core::assign_eh(constraint_id index, bool sign) {
struct unassign : public trail {
core& c;
unsigned m_index;
@ -434,6 +427,8 @@ namespace polysat {
c.m_prop_queue.pop_back();
}
};
if (m_constraint_index[index.id].value != l_undef)
return;
m_prop_queue.push_back(index);
m_constraint_index[index.id].value = to_lbool(!sign);
s.trail().push(unassign(*this, index.id));
@ -494,7 +489,7 @@ namespace polysat {
void core::add_axiom(signed_constraint sc) {
auto idx = register_constraint(sc, dependency::axiom());
assign_eh(idx, false, 0);
assign_eh(idx, false);
}
signed_constraint core::get_constraint(constraint_id idx) {

View file

@ -69,7 +69,6 @@ namespace polysat {
vector<unsigned_vector> m_watch; // watch lists for variables for constraints on m_prop_queue where they occur
// values to split on
rational m_value;
pvar m_var = 0;
dd::pdd_manager& sz2pdd(unsigned sz) const;
@ -99,7 +98,7 @@ namespace polysat {
sat::check_result check();
constraint_id register_constraint(signed_constraint& sc, dependency d);
bool propagate();
void assign_eh(constraint_id idx, bool sign, unsigned level);
void assign_eh(constraint_id idx, bool sign);
pvar next_var() { return m_var_queue.next_var(); }
pdd value(rational const& v, unsigned sz);

View file

@ -107,20 +107,28 @@ namespace polysat {
m_num_bits = c.size(v);
m_fixed_bits.reset(v);
init_overlaps(v);
rational const& max_value = c.var2pdd(v).max_value();
val1 = 0;
bool start_at0 = val1 == 0;
lbool r = next_viable(val1);
TRACE("bv", display_state(tout); display(tout << "next viable v" << v << " " << val1 << " " << r << "\n"));
if (r == l_false && !start_at0) {
val1 = 0;
r = next_viable(val1);
}
if (r != l_true)
return r;
if (val1 == max_value) {
val2 = val1;
return l_true;
if (val1 == c.var2pdd(v).max_value()) {
if (start_at0) {
val2 = val1;
return l_true;
}
else
val2 = 0;
}
val2 = val1 + 1;
else
val2 = val1 + 1;
r = next_viable(val2);

View file

@ -178,13 +178,15 @@ namespace polysat {
}
};
void solver::mk_atom(sat::bool_var bv, signed_constraint& sc) {
if (get_bv2a(bv))
return;
solver::atom* solver::mk_atom(sat::bool_var bv, signed_constraint& sc) {
auto a = get_bv2a(bv);
if (a)
return a;
auto index = m_core.register_constraint(sc, dependency(bv));
auto a = new (get_region()) atom(bv, index);
a = new (get_region()) atom(bv, index);
insert_bv2a(bv, a);
ctx.push(mk_atom_trail(bv, *this));
return a;
}
void solver::internalize_binary_predicate(app* e, std::function<polysat::signed_constraint(pdd, pdd)> const& fn) {
@ -759,6 +761,7 @@ namespace polysat {
public:
undo_add_eq(solver& s, unsigned i) : s(s), index(i) {}
void undo() override {
SASSERT(index == s.m_eqs.back().index());
s.m_eq2constraint.remove(index);
s.m_eqs.pop_back();
}
@ -769,10 +772,8 @@ namespace polysat {
constraint_id idx;
if (m_eq2constraint.find(r.index(), idx))
return idx;
auto sc = m_core.eq(p, q);
TRACE("bv", tout << "new eq " << sc << "\n");
auto sc = m_core.eq(p, q);
idx = m_core.register_constraint(sc, d);
m_eq2constraint.insert(r.index(), idx);
m_eqs.push_back(r);
ctx.push(undo_add_eq(*this, r.index()));

View file

@ -114,7 +114,7 @@ namespace polysat {
if (!a)
return;
force_push();
m_core.assign_eh(a->m_index, l.sign(), s().lvl(l));
m_core.assign_eh(a->m_index, l.sign());
}
void solver::set_conflict(dependency_vector const& deps, char const* hint_info) {
@ -193,10 +193,15 @@ namespace polysat {
pdd p = m_core.var(pvar);
pdd q = m_core.value(val, m_core.size(pvar));
auto sc = m_core.eq(p, q);
mk_atom(eq.var(), sc);
s().set_phase(eq);
ctx.mark_relevant(eq);
d = dependency(eq.var());
auto value = s().value(eq);
if (!get_bv2a(eq.var())) {
auto a = mk_atom(eq.var(), sc);
if (value == l_false)
m_core.assign_eh(a->m_index, true);
}
return s().value(eq);
}
@ -213,7 +218,7 @@ namespace polysat {
pdd q = var2pdd(v2);
auto d = dependency(v1, v2);
constraint_id id = eq_constraint(p, q, d);
m_core.assign_eh(id, false, s().scope_lvl());
m_core.assign_eh(id, false);
}
@ -228,7 +233,7 @@ namespace polysat {
auto d = dependency(eq.var());
auto id = eq_constraint(p, q, d);
TRACE("bv", tout << eq << " := " << s().value(eq) << " @" << s().scope_lvl() << "\n");
m_core.assign_eh(id, true, s().lvl(eq));
m_core.assign_eh(id, true);
}
// Core uses the propagate callback to add unit propagations to the trail.

View file

@ -103,7 +103,7 @@ namespace polysat {
void erase_bv2a(bool_var bv) { m_bool_var2atom[bv] = nullptr; }
atom* get_bv2a(bool_var bv) const { return m_bool_var2atom.get(bv, nullptr); }
class mk_atom_trail;
void mk_atom(sat::bool_var bv, signed_constraint& sc);
atom* mk_atom(sat::bool_var bv, signed_constraint& sc);
void set_bit_eh(theory_var v, literal l, unsigned idx);
void init_bits(expr* e, expr_ref_vector const & bits);
void mk_bits(theory_var v);