3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-12-01 01:37:13 +00:00

fix crash bugs in sat solver

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2017-11-11 11:25:43 -08:00
parent c522487a86
commit a6da207b65
10 changed files with 133 additions and 43 deletions

View file

@ -201,7 +201,6 @@ namespace sat {
return false;
default:
c.shrink(new_sz);
s.attach_clause(c);
if (s.m_config.m_drat) s.m_drat.add(c, true);
// if (s.m_config.m_drat) s.m_drat.del(c0); // TBD
SASSERT(s.m_qhead == s.m_trail.size());

View file

@ -129,20 +129,23 @@ namespace sat {
}
clause * clause_allocator::get_clause(clause_offset cls_off) const {
#if defined(_AMD64_)
#if 0
// defined(_AMD64_)
if (((cls_off & c_alignment_mask) == c_last_segment)) {
unsigned id = cls_off >> c_cls_alignment;
return const_cast<clause*>(m_last_seg_id2cls[id]);
}
return reinterpret_cast<clause *>(m_segments[cls_off & c_alignment_mask] + (static_cast<size_t>(cls_off) & ~c_alignment_mask));
#else
VERIFY(cls_off == reinterpret_cast<clause_offset>(reinterpret_cast<clause*>(cls_off)));
return reinterpret_cast<clause *>(cls_off);
#endif
}
clause_offset clause_allocator::get_offset(clause const * cls) const {
#if defined(_AMD64_)
#if 0
// defined(_AMD64_)
size_t ptr = reinterpret_cast<size_t>(cls);
SASSERT((ptr & c_alignment_mask) == 0);
@ -163,6 +166,7 @@ namespace sat {
return static_cast<clause_offset>(reinterpret_cast<size_t>(cls)) + i;
}
#else
VERIFY(cls == reinterpret_cast<clause *>(reinterpret_cast<size_t>(cls)));
return reinterpret_cast<size_t>(cls);
#endif
}
@ -178,9 +182,13 @@ namespace sat {
void clause_allocator::del_clause(clause * cls) {
TRACE("sat_clause", tout << "delete: " << cls->id() << " " << *cls << "\n";);
if (cls->id() == 62805 && cls->capacity() == 29) {
std::cout << "delete 62805\n";
for (literal l : *cls) {
std::cout << l << "\n";
}
}
m_id_gen.recycle(cls->id());
#if defined(_AMD64_)
#endif
size_t size = clause::get_obj_size(cls->m_capacity);
cls->~clause();
m_allocator.deallocate(size, cls);

View file

@ -62,6 +62,7 @@ namespace sat {
public:
unsigned id() const { return m_id; }
unsigned size() const { return m_size; }
unsigned capacity() const { return m_capacity; }
literal & operator[](unsigned idx) { SASSERT(idx < m_size); return m_lits[idx]; }
literal const & operator[](unsigned idx) const { SASSERT(idx < m_size); return m_lits[idx]; }
bool is_learned() const { return m_learned; }

View file

@ -48,7 +48,7 @@ namespace sat {
literal get_literal2() const { SASSERT(is_ternary_clause()); return to_literal(m_val2 >> 3); }
bool is_clause() const { return m_val2 == CLAUSE; }
clause_offset get_clause_offset() const { return val1(); }
clause_offset get_clause_offset() const { return m_val1; }
bool is_ext_justification() const { return m_val2 == EXT_JUSTIFICATION; }
ext_justification_idx get_ext_justification_idx() const { return m_val1; }

View file

@ -268,19 +268,12 @@ namespace sat {
bool vars_eliminated = m_num_elim_vars > m_old_num_elim_vars;
if (m_need_cleanup) {
if (m_need_cleanup || vars_eliminated) {
TRACE("after_simplifier", tout << "cleanning watches...\n";);
cleanup_watches();
cleanup_clauses(s.m_learned, true, vars_eliminated, m_learned_in_use_lists);
cleanup_clauses(s.m_clauses, false, vars_eliminated, true);
}
else {
TRACE("after_simplifier", tout << "skipping cleanup...\n";);
if (vars_eliminated) {
// must remove learned clauses with eliminated variables
cleanup_clauses(s.m_learned, true, true, m_learned_in_use_lists);
}
}
CASSERT("sat_solver", s.check_invariant());
TRACE("after_simplifier", s.display(tout); tout << "model_converter:\n"; s.m_mc.display(tout););

View file

@ -417,6 +417,9 @@ namespace sat {
}
unsigned some_idx = c.size() >> 1;
literal block_lit = c[some_idx];
DEBUG_CODE(for (auto const& w : m_watches[(~c[0]).index()]) VERIFY(!w.is_clause() || w.get_clause_offset() != cls_off););
DEBUG_CODE(for (auto const& w : m_watches[(~c[1]).index()]) VERIFY(!w.is_clause() || w.get_clause_offset() != cls_off););
VERIFY(c[0] != c[1]);
m_watches[(~c[0]).index()].push_back(watched(block_lit, cls_off));
m_watches[(~c[1]).index()].push_back(watched(block_lit, cls_off));
return reinit;
@ -563,6 +566,9 @@ namespace sat {
void solver::detach_nary_clause(clause & c) {
clause_offset cls_off = get_offset(c);
if (c.id() == 62805 && c.capacity() == 29) {
std::cout << "detach: " << c[0] << " " << c[1] << " size: " << c.size() << " cap: " << c.capacity() << " id: " << c.id() << "\n";
}
erase_clause_watch(get_wlist(~c[0]), cls_off);
erase_clause_watch(get_wlist(~c[1]), cls_off);
}
@ -753,18 +759,19 @@ namespace sat {
it2++;
break;
}
SASSERT(c[1] == not_l);
if (value(c[0]) == l_true) {
it2->set_clause(c[0], cls_off);
it2++;
break;
}
VERIFY(c[1] == not_l);
literal * l_it = c.begin() + 2;
literal * l_end = c.end();
for (; l_it != l_end; ++l_it) {
if (value(*l_it) != l_false) {
c[1] = *l_it;
*l_it = not_l;
DEBUG_CODE(for (auto const& w : m_watches[(~c[1]).index()]) VERIFY(!w.is_clause() || w.get_clause_offset() != cls_off););
m_watches[(~c[1]).index()].push_back(watched(c[0], cls_off));
goto end_clause_case;
}
@ -1555,7 +1562,7 @@ namespace sat {
if (!check_clauses(m_model)) {
std::cout << "failure checking clauses on transformed model\n";
IF_VERBOSE(0, verbose_stream() << "failure checking clauses on transformed model\n";);
UNREACHABLE();
throw solver_exception("check model failed");
}
@ -3267,29 +3274,24 @@ namespace sat {
for (unsigned i = 0; i < m_trail.size(); i++) {
out << max_weight << " " << dimacs_lit(m_trail[i]) << " 0\n";
}
vector<watch_list>::const_iterator it = m_watches.begin();
vector<watch_list>::const_iterator end = m_watches.end();
for (unsigned l_idx = 0; it != end; ++it, ++l_idx) {
unsigned l_idx = 0;
for (watch_list const& wlist : m_watches) {
literal l = ~to_literal(l_idx);
watch_list const & wlist = *it;
watch_list::const_iterator it2 = wlist.begin();
watch_list::const_iterator end2 = wlist.end();
for (; it2 != end2; ++it2) {
if (it2->is_binary_clause() && l.index() < it2->get_literal().index())
out << max_weight << " " << dimacs_lit(l) << " " << dimacs_lit(it2->get_literal()) << " 0\n";
for (watched const& w : wlist) {
if (w.is_binary_clause() && l.index() < w.get_literal().index())
out << max_weight << " " << dimacs_lit(l) << " " << dimacs_lit(w.get_literal()) << " 0\n";
}
++l_idx;
}
clause_vector const * vs[2] = { &m_clauses, &m_learned };
for (unsigned i = 0; i < 2; i++) {
clause_vector const & cs = *(vs[i]);
clause_vector::const_iterator it = cs.begin();
clause_vector::const_iterator end = cs.end();
for (; it != end; ++it) {
clause const & c = *(*it);
for (clause const* cp : cs) {
clause const & c = *cp;
unsigned clsz = c.size();
out << max_weight << " ";
for (unsigned j = 0; j < clsz; j++)
out << dimacs_lit(c[j]) << " ";
for (literal l : c)
out << dimacs_lit(l) << " ";
out << "0\n";
}
}

View file

@ -109,7 +109,7 @@ namespace sat {
typedef svector<literal> literal_vector;
typedef std::pair<literal, literal> literal_pair;
typedef unsigned clause_offset;
typedef size_t clause_offset;
typedef size_t ext_constraint_idx;
typedef size_t ext_justification_idx;

View file

@ -27,8 +27,9 @@ namespace sat {
for (; it != end; ++it) {
if (it->is_clause() && it->get_clause_offset() == c) {
watch_list::iterator it2 = it;
++it;
++it;
for (; it != end; ++it) {
SASSERT(!((it->is_clause() && it->get_clause_offset() == c)));
*it2 = *it;
++it2;
}
@ -40,27 +41,26 @@ namespace sat {
}
std::ostream& display_watch_list(std::ostream & out, clause_allocator const & ca, watch_list const & wlist) {
watch_list::const_iterator it = wlist.begin();
watch_list::const_iterator end = wlist.end();
for (bool first = true; it != end; ++it) {
bool first = true;
for (watched const& w : wlist) {
if (first)
first = false;
else
out << " ";
switch (it->get_kind()) {
switch (w.get_kind()) {
case watched::BINARY:
out << it->get_literal();
if (it->is_learned())
out << w.get_literal();
if (w.is_learned())
out << "*";
break;
case watched::TERNARY:
out << "(" << it->get_literal1() << " " << it->get_literal2() << ")";
out << "(" << w.get_literal1() << " " << w.get_literal2() << ")";
break;
case watched::CLAUSE:
out << "(" << it->get_blocked_literal() << " " << *(ca.get_clause(it->get_clause_offset())) << ")";
out << "(" << w.get_blocked_literal() << " " << *(ca.get_clause(w.get_clause_offset())) << ")";
break;
case watched::EXT_CONSTRAINT:
out << "ext: " << it->get_ext_constraint_idx();
out << "ext: " << w.get_ext_constraint_idx();
break;
default:
UNREACHABLE();

View file

@ -64,6 +64,8 @@ namespace sat {
SASSERT(get_literal2() == l2);
}
unsigned val2() const { return m_val2; }
watched(literal blocked_lit, clause_offset cls_off):
m_val1(cls_off),
m_val2(static_cast<unsigned>(CLAUSE) + (blocked_lit.to_uint() << 2)) {