mirror of
https://github.com/Z3Prover/z3
synced 2025-06-19 12:23:38 +00:00
bugfixes
This commit is contained in:
parent
03e012c1d8
commit
78f32401ac
6 changed files with 66 additions and 58 deletions
|
@ -62,11 +62,6 @@ namespace polysat {
|
||||||
auto& [sc, lit, val] = c.m_constraint_index.back();
|
auto& [sc, lit, val] = c.m_constraint_index.back();
|
||||||
auto& vars = sc.vars();
|
auto& vars = sc.vars();
|
||||||
auto idx = c.m_constraint_index.size() - 1;
|
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();
|
unsigned n = sc.num_watch();
|
||||||
SASSERT(n <= vars.size());
|
SASSERT(n <= vars.size());
|
||||||
auto del_watch = [&](unsigned i) {
|
auto del_watch = [&](unsigned i) {
|
||||||
|
@ -147,10 +142,6 @@ namespace polysat {
|
||||||
add_watch(idx, vars[0]);
|
add_watch(idx, vars[0]);
|
||||||
if (j > 1)
|
if (j > 1)
|
||||||
add_watch(idx, vars[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));
|
s.trail().push(mk_add_watch(*this));
|
||||||
return { idx };
|
return { idx };
|
||||||
}
|
}
|
||||||
|
@ -166,38 +157,36 @@ namespace polysat {
|
||||||
CTRACE("bv", is_assigned(m_var), display(tout << "v" << m_var << " is assigned\n"););
|
CTRACE("bv", is_assigned(m_var), display(tout << "v" << m_var << " is assigned\n"););
|
||||||
SASSERT(!is_assigned(m_var));
|
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:
|
case find_t::empty:
|
||||||
viable_conflict(m_var);
|
viable_conflict(m_var);
|
||||||
return sat::check_result::CR_CONTINUE;
|
return sat::check_result::CR_CONTINUE;
|
||||||
case find_t::singleton: {
|
case find_t::singleton: {
|
||||||
auto p = var2pdd(m_var).mk_var(m_var);
|
auto p = var2pdd(m_var).mk_var(m_var);
|
||||||
auto sc = m_constraints.eq(p, m_value);
|
auto sc = m_constraints.eq(p, var_value);
|
||||||
TRACE("bv", tout << "check-propagate v" << m_var << " := " << m_value << " " << sc << "\n");
|
TRACE("bv", tout << "check-propagate v" << m_var << " := " << var_value << " " << sc << "\n");
|
||||||
auto d = s.propagate(sc, m_viable.explain(), "viable-propagate");
|
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;
|
return sat::check_result::CR_CONTINUE;
|
||||||
}
|
}
|
||||||
case find_t::multiple: {
|
case find_t::multiple: {
|
||||||
do {
|
|
||||||
try_again:
|
|
||||||
dependency d = null_dependency;
|
dependency d = null_dependency;
|
||||||
lbool value = s.add_eq_literal(m_var, m_value, d);
|
lbool value = s.add_eq_literal(m_var, var_value, d);
|
||||||
TRACE("bv", tout << "check-multiple v" << m_var << " := " << m_value << " " << value << "\n");
|
TRACE("bv", tout << "check-multiple v" << m_var << " := " << var_value << " " << value << "\n");
|
||||||
switch (value) {
|
switch (value) {
|
||||||
case l_true:
|
case l_true:
|
||||||
propagate_assignment(m_var, m_value, d);
|
propagate_assignment(m_var, var_value, d);
|
||||||
break;
|
break;
|
||||||
case l_false:
|
case l_false:
|
||||||
// add m_var != m_value to m_viable but need a constraint index for that.
|
// disequality is forced into propagation queue.
|
||||||
m_value = mod(m_value + 1, rational::power_of_two(size(m_var)));
|
var_value = mod(var_value + 1, rational::power_of_two(size(m_var)));
|
||||||
goto try_again;
|
propagate();
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
// let core assign equality.
|
// let core assign equality.
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
while (false);
|
|
||||||
return sat::check_result::CR_CONTINUE;
|
return sat::check_result::CR_CONTINUE;
|
||||||
}
|
}
|
||||||
case find_t::resource_out:
|
case find_t::resource_out:
|
||||||
|
@ -211,14 +200,17 @@ namespace polysat {
|
||||||
sat::check_result core::final_check() {
|
sat::check_result core::final_check() {
|
||||||
unsigned n = 0;
|
unsigned n = 0;
|
||||||
constraint_id conflict_idx = { UINT_MAX };
|
constraint_id conflict_idx = { UINT_MAX };
|
||||||
|
// verbose_stream() << "final-check\n";
|
||||||
for (auto idx : m_prop_queue) {
|
for (auto idx : m_prop_queue) {
|
||||||
auto [sc, d, value] = m_constraint_index[idx.id];
|
auto [sc, d, value] = m_constraint_index[idx.id];
|
||||||
SASSERT(value != l_undef);
|
SASSERT(value != l_undef);
|
||||||
|
// verbose_stream() << "constraint " << (value == l_true ? sc : ~sc) << "\n";
|
||||||
lbool eval_value = eval(sc);
|
lbool eval_value = eval(sc);
|
||||||
CTRACE("bv", eval_value == l_undef, sc.display(tout << "eval: ") << " evaluates to " << eval_value << "\n"; display(tout););
|
CTRACE("bv", eval_value == l_undef, sc.display(tout << "eval: ") << " evaluates to " << eval_value << "\n"; display(tout););
|
||||||
SASSERT(eval_value != l_undef);
|
SASSERT(eval_value != l_undef);
|
||||||
if (eval_value == value)
|
if (eval_value == value)
|
||||||
continue;
|
continue;
|
||||||
|
// verbose_stream() << "violated " << sc << " " << d << " " << eval_value << "\n";
|
||||||
if (0 == (m_rand() % (++n)))
|
if (0 == (m_rand() % (++n)))
|
||||||
conflict_idx = idx;
|
conflict_idx = idx;
|
||||||
|
|
||||||
|
@ -288,8 +280,9 @@ namespace polysat {
|
||||||
s.set_conflict({dep}, "infeasible assignment");
|
s.set_conflict({dep}, "infeasible assignment");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (sc.is_eq(m_var, m_value))
|
rational var_value;
|
||||||
propagate_assignment(m_var, m_value, dep);
|
if (sc.is_eq(m_var, var_value))
|
||||||
|
propagate_assignment(m_var, var_value, dep);
|
||||||
else
|
else
|
||||||
propagate_activation(idx, sc, dep);
|
propagate_activation(idx, sc, dep);
|
||||||
}
|
}
|
||||||
|
@ -424,7 +417,7 @@ namespace polysat {
|
||||||
return s.inconsistent();
|
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 {
|
struct unassign : public trail {
|
||||||
core& c;
|
core& c;
|
||||||
unsigned m_index;
|
unsigned m_index;
|
||||||
|
@ -434,6 +427,8 @@ namespace polysat {
|
||||||
c.m_prop_queue.pop_back();
|
c.m_prop_queue.pop_back();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
if (m_constraint_index[index.id].value != l_undef)
|
||||||
|
return;
|
||||||
m_prop_queue.push_back(index);
|
m_prop_queue.push_back(index);
|
||||||
m_constraint_index[index.id].value = to_lbool(!sign);
|
m_constraint_index[index.id].value = to_lbool(!sign);
|
||||||
s.trail().push(unassign(*this, index.id));
|
s.trail().push(unassign(*this, index.id));
|
||||||
|
@ -494,7 +489,7 @@ namespace polysat {
|
||||||
|
|
||||||
void core::add_axiom(signed_constraint sc) {
|
void core::add_axiom(signed_constraint sc) {
|
||||||
auto idx = register_constraint(sc, dependency::axiom());
|
auto idx = register_constraint(sc, dependency::axiom());
|
||||||
assign_eh(idx, false, 0);
|
assign_eh(idx, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
signed_constraint core::get_constraint(constraint_id idx) {
|
signed_constraint core::get_constraint(constraint_id idx) {
|
||||||
|
|
|
@ -69,7 +69,6 @@ namespace polysat {
|
||||||
vector<unsigned_vector> m_watch; // watch lists for variables for constraints on m_prop_queue where they occur
|
vector<unsigned_vector> m_watch; // watch lists for variables for constraints on m_prop_queue where they occur
|
||||||
|
|
||||||
// values to split on
|
// values to split on
|
||||||
rational m_value;
|
|
||||||
pvar m_var = 0;
|
pvar m_var = 0;
|
||||||
|
|
||||||
dd::pdd_manager& sz2pdd(unsigned sz) const;
|
dd::pdd_manager& sz2pdd(unsigned sz) const;
|
||||||
|
@ -99,7 +98,7 @@ namespace polysat {
|
||||||
sat::check_result check();
|
sat::check_result check();
|
||||||
constraint_id register_constraint(signed_constraint& sc, dependency d);
|
constraint_id register_constraint(signed_constraint& sc, dependency d);
|
||||||
bool propagate();
|
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(); }
|
pvar next_var() { return m_var_queue.next_var(); }
|
||||||
|
|
||||||
pdd value(rational const& v, unsigned sz);
|
pdd value(rational const& v, unsigned sz);
|
||||||
|
|
|
@ -107,19 +107,27 @@ namespace polysat {
|
||||||
m_num_bits = c.size(v);
|
m_num_bits = c.size(v);
|
||||||
m_fixed_bits.reset(v);
|
m_fixed_bits.reset(v);
|
||||||
init_overlaps(v);
|
init_overlaps(v);
|
||||||
|
bool start_at0 = val1 == 0;
|
||||||
|
|
||||||
rational const& max_value = c.var2pdd(v).max_value();
|
|
||||||
|
|
||||||
val1 = 0;
|
|
||||||
lbool r = next_viable(val1);
|
lbool r = next_viable(val1);
|
||||||
TRACE("bv", display_state(tout); display(tout << "next viable v" << v << " " << val1 << " " << r << "\n"));
|
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)
|
if (r != l_true)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
if (val1 == max_value) {
|
if (val1 == c.var2pdd(v).max_value()) {
|
||||||
|
if (start_at0) {
|
||||||
val2 = val1;
|
val2 = val1;
|
||||||
return l_true;
|
return l_true;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
val2 = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
val2 = val1 + 1;
|
val2 = val1 + 1;
|
||||||
|
|
||||||
r = next_viable(val2);
|
r = next_viable(val2);
|
||||||
|
|
|
@ -178,13 +178,15 @@ namespace polysat {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
void solver::mk_atom(sat::bool_var bv, signed_constraint& sc) {
|
solver::atom* solver::mk_atom(sat::bool_var bv, signed_constraint& sc) {
|
||||||
if (get_bv2a(bv))
|
auto a = get_bv2a(bv);
|
||||||
return;
|
if (a)
|
||||||
|
return a;
|
||||||
auto index = m_core.register_constraint(sc, dependency(bv));
|
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);
|
insert_bv2a(bv, a);
|
||||||
ctx.push(mk_atom_trail(bv, *this));
|
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) {
|
void solver::internalize_binary_predicate(app* e, std::function<polysat::signed_constraint(pdd, pdd)> const& fn) {
|
||||||
|
@ -759,6 +761,7 @@ namespace polysat {
|
||||||
public:
|
public:
|
||||||
undo_add_eq(solver& s, unsigned i) : s(s), index(i) {}
|
undo_add_eq(solver& s, unsigned i) : s(s), index(i) {}
|
||||||
void undo() override {
|
void undo() override {
|
||||||
|
SASSERT(index == s.m_eqs.back().index());
|
||||||
s.m_eq2constraint.remove(index);
|
s.m_eq2constraint.remove(index);
|
||||||
s.m_eqs.pop_back();
|
s.m_eqs.pop_back();
|
||||||
}
|
}
|
||||||
|
@ -770,9 +773,7 @@ namespace polysat {
|
||||||
if (m_eq2constraint.find(r.index(), idx))
|
if (m_eq2constraint.find(r.index(), idx))
|
||||||
return idx;
|
return idx;
|
||||||
auto sc = m_core.eq(p, q);
|
auto sc = m_core.eq(p, q);
|
||||||
TRACE("bv", tout << "new eq " << sc << "\n");
|
|
||||||
idx = m_core.register_constraint(sc, d);
|
idx = m_core.register_constraint(sc, d);
|
||||||
|
|
||||||
m_eq2constraint.insert(r.index(), idx);
|
m_eq2constraint.insert(r.index(), idx);
|
||||||
m_eqs.push_back(r);
|
m_eqs.push_back(r);
|
||||||
ctx.push(undo_add_eq(*this, r.index()));
|
ctx.push(undo_add_eq(*this, r.index()));
|
||||||
|
|
|
@ -114,7 +114,7 @@ namespace polysat {
|
||||||
if (!a)
|
if (!a)
|
||||||
return;
|
return;
|
||||||
force_push();
|
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) {
|
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 p = m_core.var(pvar);
|
||||||
pdd q = m_core.value(val, m_core.size(pvar));
|
pdd q = m_core.value(val, m_core.size(pvar));
|
||||||
auto sc = m_core.eq(p, q);
|
auto sc = m_core.eq(p, q);
|
||||||
mk_atom(eq.var(), sc);
|
|
||||||
s().set_phase(eq);
|
s().set_phase(eq);
|
||||||
ctx.mark_relevant(eq);
|
ctx.mark_relevant(eq);
|
||||||
d = dependency(eq.var());
|
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);
|
return s().value(eq);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -213,7 +218,7 @@ namespace polysat {
|
||||||
pdd q = var2pdd(v2);
|
pdd q = var2pdd(v2);
|
||||||
auto d = dependency(v1, v2);
|
auto d = dependency(v1, v2);
|
||||||
constraint_id id = eq_constraint(p, q, d);
|
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 d = dependency(eq.var());
|
||||||
auto id = eq_constraint(p, q, d);
|
auto id = eq_constraint(p, q, d);
|
||||||
TRACE("bv", tout << eq << " := " << s().value(eq) << " @" << s().scope_lvl() << "\n");
|
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.
|
// Core uses the propagate callback to add unit propagations to the trail.
|
||||||
|
|
|
@ -103,7 +103,7 @@ namespace polysat {
|
||||||
void erase_bv2a(bool_var bv) { m_bool_var2atom[bv] = nullptr; }
|
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); }
|
atom* get_bv2a(bool_var bv) const { return m_bool_var2atom.get(bv, nullptr); }
|
||||||
class mk_atom_trail;
|
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 set_bit_eh(theory_var v, literal l, unsigned idx);
|
||||||
void init_bits(expr* e, expr_ref_vector const & bits);
|
void init_bits(expr* e, expr_ref_vector const & bits);
|
||||||
void mk_bits(theory_var v);
|
void mk_bits(theory_var v);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue