3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-08-19 17:50:23 +00:00

remove ternary clause optimization

Removing ternary clause optimization from sat_solver simplifies special case handling of ternary clauses throughout the sat solver and dependent solvers (pb_solver). Benchmarking on QF_BV suggests the ternary clause optimization does not have any effect. While removing ternary clause optimization two bugs in unit propagation were also uncovered: it missed propagations when the only a single undef literal remained in the non-watched literals and it did not update blocked literals in cases where it could in the watch list. These performance bugs were for general clauses, ternary clause propagation did not miss propagations (and don't use blocked literals), but fixing these issues for general clauses appear to have made ternary clause optimization irrelevant based on what was measured.
This commit is contained in:
Nikolaj Bjorner 2022-10-30 03:57:39 -07:00
parent 0da0fa2b27
commit 9fc4015c46
13 changed files with 16 additions and 386 deletions

View file

@ -40,11 +40,7 @@ namespace sat {
class watched {
public:
enum kind {
BINARY = 0,
#if ENABLE_TERNARY
TERNARY,
#endif
CLAUSE, EXT_CONSTRAINT
BINARY = 0, CLAUSE, EXT_CONSTRAINT
};
private:
size_t m_val1;
@ -59,18 +55,6 @@ namespace sat {
SASSERT(learned || is_binary_non_learned_clause());
}
#if ENABLE_TERNARY
watched(literal l1, literal l2) {
SASSERT(l1 != l2);
if (l1.index() > l2.index())
std::swap(l1, l2);
m_val1 = l1.to_uint();
m_val2 = static_cast<unsigned>(TERNARY) + (l2.to_uint() << 2);
SASSERT(is_ternary_clause());
SASSERT(get_literal1() == l1);
SASSERT(get_literal2() == l2);
}
#endif
unsigned val2() const { return m_val2; }
@ -101,11 +85,6 @@ namespace sat {
void set_learned(bool l) { if (l) m_val2 |= 4u; else m_val2 &= ~4u; SASSERT(is_learned() == l); }
#if ENABLE_TERNARY
bool is_ternary_clause() const { return get_kind() == TERNARY; }
literal get_literal1() const { SASSERT(is_ternary_clause()); return to_literal(static_cast<unsigned>(m_val1)); }
literal get_literal2() const { SASSERT(is_ternary_clause()); return to_literal(m_val2 >> 2); }
#endif
bool is_clause() const { return get_kind() == CLAUSE; }
clause_offset get_clause_offset() const { SASSERT(is_clause()); return static_cast<clause_offset>(m_val1); }
@ -124,21 +103,14 @@ namespace sat {
bool operator!=(watched const & w) const { return !operator==(w); }
};
static_assert(0 <= watched::BINARY && watched::BINARY <= 3, "");
#if ENABLE_TERNARY
static_assert(0 <= watched::TERNARY && watched::TERNARY <= 3, "");
#endif
static_assert(0 <= watched::CLAUSE && watched::CLAUSE <= 3, "");
static_assert(0 <= watched::EXT_CONSTRAINT && watched::EXT_CONSTRAINT <= 3, "");
static_assert(0 <= watched::BINARY && watched::BINARY <= 2, "");
static_assert(0 <= watched::CLAUSE && watched::CLAUSE <= 2, "");
static_assert(0 <= watched::EXT_CONSTRAINT && watched::EXT_CONSTRAINT <= 2, "");
struct watched_lt {
bool operator()(watched const & w1, watched const & w2) const {
if (w2.is_binary_clause()) return false;
if (w1.is_binary_clause()) return true;
#if ENABLE_TERNARY
if (w2.is_ternary_clause()) return false;
if (w1.is_ternary_clause()) return true;
#endif
return false;
}
};
@ -148,8 +120,6 @@ namespace sat {
watched* find_binary_watch(watch_list & wlist, literal l);
watched const* find_binary_watch(watch_list const & wlist, literal l);
bool erase_clause_watch(watch_list & wlist, clause_offset c);
void erase_ternary_watch(watch_list & wlist, literal l1, literal l2);
void set_ternary_learned(watch_list& wlist, literal l1, literal l2, bool learned);
class clause_allocator;
std::ostream& display_watch_list(std::ostream & out, clause_allocator const & ca, watch_list const & wlist, extension* ext);