3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-06-27 08:28:44 +00:00

use clause structure for nary

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2017-10-10 11:49:31 -07:00
parent a0cd6e0fca
commit 8b32c15ac9
4 changed files with 455 additions and 18 deletions

View file

@ -312,10 +312,11 @@ namespace sat {
}
bool lookahead::is_unsat() const {
bool all_false = true;
bool first = true;
// check if there is a clause whose literals are false.
// every clause is terminated by a null-literal.
#if OLD_NARY
bool all_false = true;
bool first = true;
for (unsigned l_idx : m_nary_literals) {
literal l = to_literal(l_idx);
if (first) {
@ -332,6 +333,15 @@ namespace sat {
all_false &= is_false(l);
}
}
#else
for (nary* n : m_nary_clauses) {
bool all_false = true;
for (literal l : *n) {
all_false &= is_false(l);
}
if (all_false) return true;
}
#endif
// check if there is a ternary whose literals are false.
for (unsigned idx = 0; idx < m_ternary.size(); ++idx) {
literal lit = to_literal(idx);
@ -366,10 +376,11 @@ namespace sat {
}
}
}
bool no_true = true;
bool first = true;
// check if there is a clause whose literals are false.
// every clause is terminated by a null-literal.
#if OLD_NARY
bool no_true = true;
bool first = true;
for (unsigned l_idx : m_nary_literals) {
literal l = to_literal(l_idx);
if (first) {
@ -385,6 +396,15 @@ namespace sat {
no_true &= !is_true(l);
}
}
#else
for (nary * n : m_nary_clauses) {
bool no_true = true;
for (literal l : *n) {
no_true &= !is_true(l);
}
if (no_true) return false;
}
#endif
// check if there is a ternary whose literals are false.
for (unsigned idx = 0; idx < m_ternary.size(); ++idx) {
literal lit = to_literal(idx);
@ -457,6 +477,7 @@ namespace sat {
sum += (literal_occs(b.m_u) + literal_occs(b.m_v)) / 8.0;
}
sz = m_nary_count[(~l).index()];
#if OLD_NARY
for (unsigned idx : m_nary[(~l).index()]) {
if (sz-- == 0) break;
literal lit;
@ -470,6 +491,9 @@ namespace sat {
unsigned len = m_nary_literals[idx];
sum += pow(0.5, len) * to_add / len;
}
#else
#endif
return sum;
}
@ -488,10 +512,17 @@ namespace sat {
}
sum += 0.25 * m_ternary_count[(~l).index()];
unsigned sz = m_nary_count[(~l).index()];
#if OLD_NARY
for (unsigned cls_idx : m_nary[(~l).index()]) {
if (sz-- == 0) break;
sum += pow(0.5, m_nary_literals[cls_idx]);
}
#else
for (nary * n : m_nary[(~l).index()]) {
if (sz-- == 0) break;
sum += pow(0.5, n->size());
}
#endif
return sum;
}
@ -866,8 +897,13 @@ namespace sat {
m_ternary.push_back(svector<binary>());
m_ternary_count.push_back(0);
m_ternary_count.push_back(0);
#if OLD_NARY
m_nary.push_back(unsigned_vector());
m_nary.push_back(unsigned_vector());
#else
m_nary.push_back(ptr_vector<nary>());
m_nary.push_back(ptr_vector<nary>());
#endif
m_nary_count.push_back(0);
m_nary_count.push_back(0);
m_bstamp.push_back(0);
@ -1254,8 +1290,10 @@ namespace sat {
// new n-ary clause managment
void lookahead::add_clause(clause const& c) {
SASSERT(c.size() > 3);
#if OLD_NARY
unsigned sz = c.size();
SASSERT(sz > 3);
unsigned idx = m_nary_literals.size();
m_nary_literals.push_back(sz);
for (literal l : c) {
@ -1264,7 +1302,15 @@ namespace sat {
m_nary[l.index()].push_back(idx);
SASSERT(m_nary_count[l.index()] == m_nary[l.index()].size());
}
m_nary_literals.push_back(null_literal.index());
m_nary_literals.push_back(null_literal.index());
#else
void * mem = m_allocator.allocate(nary::get_obj_size(c.size()));
nary * n = new (mem) nary(c.size(), c.begin());
m_nary_clauses.push_back(n);
for (literal l : c) {
m_nary[l.index()].push_back(n);
}
#endif
}
@ -1274,6 +1320,7 @@ namespace sat {
literal lit;
SASSERT(m_search_mode == lookahead_mode::searching);
#if OLD_NARY
for (unsigned idx : m_nary[(~l).index()]) {
if (sz-- == 0) break;
unsigned len = --m_nary_literals[idx];
@ -1323,12 +1370,69 @@ namespace sat {
}
}
}
#else
for (nary * n : m_nary[(~l).index()]) {
if (sz-- == 0) break;
unsigned len = n->dec_size();
if (m_inconsistent) continue;
if (len <= 1) continue; // already processed
// find the two unassigned literals, if any
if (len == 2) {
literal l1 = null_literal;
literal l2 = null_literal;
bool found_true = false;
for (literal lit : *n) {
if (!is_fixed(lit)) {
if (l1 == null_literal) {
l1 = lit;
}
else {
SASSERT(l2 == null_literal);
l2 = lit;
break;
}
}
else if (is_true(lit)) {
n->set_head(lit);
found_true = true;
break;
}
}
if (found_true) {
// skip, the clause will be removed when propagating on 'lit'
}
else if (l1 == null_literal) {
set_conflict();
}
else if (l2 == null_literal) {
// clause may get revisited during propagation, when l2 is true in this clause.
// m_removed_clauses.push_back(std::make_pair(~l, idx));
// remove_clause_at(~l, idx);
propagated(l1);
}
else {
// extract binary clause. A unary or empty clause may get revisited,
// but we skip it then because it is already handled as a binary clause.
// m_removed_clauses.push_back(std::make_pair(~l, idx)); // need to restore this clause.
// remove_clause_at(~l, idx);
try_add_binary(l1, l2);
}
}
}
#endif
// clauses where l is positive:
sz = m_nary_count[l.index()];
#if OLD_NARY
for (unsigned idx : m_nary[l.index()]) {
if (sz-- == 0) break;
remove_clause_at(l, idx);
}
#else
for (nary* n : m_nary[l.index()]) {
if (sz-- == 0) break;
remove_clause_at(l, *n);
}
#endif
}
void lookahead::propagate_clauses_lookahead(literal l) {
@ -1338,6 +1442,7 @@ namespace sat {
SASSERT(m_search_mode == lookahead_mode::lookahead1 ||
m_search_mode == lookahead_mode::lookahead2);
#if OLD_NARY
for (unsigned idx : m_nary[(~l).index()]) {
if (sz-- == 0) break;
literal l1 = null_literal;
@ -1404,9 +1509,75 @@ namespace sat {
}
}
}
#else
for (nary* n : m_nary[(~l).index()]) {
if (sz-- == 0) break;
literal l1 = null_literal;
literal l2 = null_literal;
bool found_true = false;
unsigned nonfixed = 0;
for (literal lit : *n) {
if (!is_fixed(lit)) {
++nonfixed;
if (l1 == null_literal) {
l1 = lit;
}
else if (l2 == null_literal) {
l2 = lit;
}
}
else if (is_true(lit)) {
found_true = true;
break;
}
}
if (found_true) {
// skip, the clause will be removed when propagating on 'lit'
}
else if (l1 == null_literal) {
set_conflict();
return;
}
else if (l2 == null_literal) {
propagated(l1);
}
else if (m_search_mode == lookahead_mode::lookahead2) {
continue;
}
else {
SASSERT(nonfixed >= 2);
SASSERT(m_search_mode == lookahead_mode::lookahead1);
switch (m_config.m_reward_type) {
case heule_schur_reward: {
double to_add = 0;
for (literal lit : *n) {
if (!is_fixed(lit)) {
to_add += literal_occs(lit);
}
}
m_lookahead_reward += pow(0.5, nonfixed) * to_add / nonfixed;
break;
}
case heule_unit_reward:
m_lookahead_reward += pow(0.5, nonfixed);
break;
case ternary_reward:
if (nonfixed == 2) {
m_lookahead_reward += (*m_heur)[l1.index()] * (*m_heur)[l2.index()];
}
else {
m_lookahead_reward += (double)0.001;
}
break;
case unit_literal_reward:
break;
}
}
}
#endif
}
#if OLD_NARY
void lookahead::remove_clause_at(literal l, unsigned clause_idx) {
unsigned j = clause_idx;
literal lit;
@ -1429,21 +1600,50 @@ namespace sat {
}
UNREACHABLE();
}
#else
void lookahead::remove_clause_at(literal l, nary& n) {
for (literal lit : n) {
if (lit != l) {
remove_clause(lit, n);
}
}
}
void lookahead::remove_clause(literal l, nary& n) {
ptr_vector<nary>& pclauses = m_nary[l.index()];
unsigned sz = m_nary_count[l.index()]--;
for (unsigned i = sz; i > 0; ) {
--i;
if (&n == pclauses[i]) {
std::swap(pclauses[i], pclauses[sz-1]);
return;
}
}
UNREACHABLE();
}
#endif
void lookahead::restore_clauses(literal l) {
SASSERT(m_search_mode == lookahead_mode::searching);
// increase the length of clauses where l is negative
unsigned sz = m_nary_count[(~l).index()];
#if OLD_NARY
for (unsigned idx : m_nary[(~l).index()]) {
if (sz-- == 0) break;
++m_nary_literals[idx];
}
#else
for (nary* n : m_nary[(~l).index()]) {
if (sz-- == 0) break;
n->inc_size();
}
#endif
// add idx back to clause list where l is positive
// add them back in the same order as they were inserted
// in this way we can check that the clauses are the same.
sz = m_nary_count[l.index()];
#if OLD_NARY
unsigned_vector const& pclauses = m_nary[l.index()];
for (unsigned i = sz; i > 0; ) {
--i;
@ -1456,6 +1656,17 @@ namespace sat {
}
}
}
#else
ptr_vector<nary>& pclauses = m_nary[l.index()];
for (unsigned i = sz; i-- > 0; ) {
for (literal lit : *pclauses[i]) {
if (lit != l) {
// SASSERT(m_nary[lit.index()] == pclauses[i]);
m_nary_count[lit.index()]++;
}
}
}
#endif
}
void lookahead::propagate_clauses(literal l) {
@ -1527,7 +1738,7 @@ namespace sat {
// Sum_{ clause C that contains ~l } 1
double lookahead::literal_occs(literal l) {
double result = m_binary[l.index()].size();
unsigned_vector const& nclauses = m_nary[(~l).index()];
// unsigned_vector const& nclauses = m_nary[(~l).index()];
result += m_nary_count[(~l).index()];
result += m_ternary_count[(~l).index()];
return result;
@ -1684,7 +1895,7 @@ namespace sat {
return false;
#if 0
// no propagations are allowed to reduce clauses.
for (clause * cp : m_full_watches[l.index()]) {
for (nary * cp : m_nary[(~l).index()]) {
clause& c = *cp;
unsigned sz = c.size();
bool found = false;
@ -2026,6 +2237,7 @@ namespace sat {
}
}
#if OLD_NARY
for (unsigned l_idx : m_nary_literals) {
literal l = to_literal(l_idx);
if (first) {
@ -2041,6 +2253,12 @@ namespace sat {
out << l << " ";
}
}
#else
for (nary * n : m_nary_clauses) {
for (literal l : *n) out << l << " ";
out << "\n";
}
#endif
return out;
}