3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-06-19 04:13:38 +00:00
This commit is contained in:
Nikolaj Bjorner 2018-01-31 11:10:54 -08:00
commit a639452553
16 changed files with 256 additions and 286 deletions

View file

@ -2798,7 +2798,7 @@ namespace sat {
} }
unsigned ba_solver::get_num_unblocked_bin(literal l) { unsigned ba_solver::get_num_unblocked_bin(literal l) {
return s().m_simplifier.get_num_unblocked_bin(l); return s().m_simplifier.num_nonlearned_bin(l);
} }
/* /*

View file

@ -60,7 +60,7 @@ namespace sat {
verbose_stream() verbose_stream()
<< " (sat-asymm-branch :elim-literals " << (num_total - num_learned) << " (sat-asymm-branch :elim-literals " << (num_total - num_learned)
<< " :elim-learned-literals " << num_learned << " :elim-learned-literals " << num_learned
<< " :hidden-tautologies " << (m_asymm_branch.m_hidden_tautologies - m_hidden_tautologies) << " :hte " << (m_asymm_branch.m_hidden_tautologies - m_hidden_tautologies)
<< " :cost " << m_asymm_branch.m_counter << " :cost " << m_asymm_branch.m_counter
<< mem_stat() << mem_stat()
<< " :time " << std::fixed << std::setprecision(2) << m_watch.get_seconds() << ")\n";); << " :time " << std::fixed << std::setprecision(2) << m_watch.get_seconds() << ")\n";);
@ -124,13 +124,13 @@ namespace sat {
break; break;
} }
SASSERT(s.m_qhead == s.m_trail.size()); SASSERT(s.m_qhead == s.m_trail.size());
if (m_counter < limit || s.inconsistent()) { clause & c = *(*it);
if (m_counter < limit || s.inconsistent() || c.was_removed()) {
*it2 = *it; *it2 = *it;
++it2; ++it2;
continue; continue;
} }
s.checkpoint(); s.checkpoint();
clause & c = *(*it);
if (big ? !process_sampled(*big, c) : !process(c)) { if (big ? !process_sampled(*big, c) : !process(c)) {
continue; // clause was removed continue; // clause was removed
} }
@ -431,7 +431,8 @@ namespace sat {
bool asymm_branch::process_sampled(big& big, clause & c) { bool asymm_branch::process_sampled(big& big, clause & c) {
scoped_detach scoped_d(s, c); scoped_detach scoped_d(s, c);
sort(big, c); sort(big, c);
if ((c.is_learned() || !big.learned()) && uhte(big, c)) { if (!big.learned() && !c.is_learned() && uhte(big, c)) {
// TBD: mark clause as learned.
++m_hidden_tautologies; ++m_hidden_tautologies;
scoped_d.del_clause(); scoped_d.del_clause();
return false; return false;
@ -501,7 +502,7 @@ namespace sat {
void asymm_branch::collect_statistics(statistics & st) const { void asymm_branch::collect_statistics(statistics & st) const {
st.update("elim literals", m_elim_literals); st.update("elim literals", m_elim_literals);
st.update("hidden tautologies", m_hidden_tautologies); st.update("hte", m_hidden_tautologies);
} }
void asymm_branch::reset_statistics() { void asymm_branch::reset_statistics() {

View file

@ -87,6 +87,15 @@ namespace sat {
mark_strengthened(); mark_strengthened();
} }
void clause::shrink(unsigned num_lits) {
SASSERT(num_lits <= m_size);
if (num_lits < m_size) {
m_size = num_lits;
mark_strengthened();
}
}
bool clause::satisfied_by(model const & m) const { bool clause::satisfied_by(model const & m) const {
for (literal l : *this) { for (literal l : *this) {
if (l.sign()) { if (l.sign()) {

View file

@ -66,7 +66,7 @@ namespace sat {
literal const & operator[](unsigned idx) const { 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; } bool is_learned() const { return m_learned; }
void set_learned(bool l) { SASSERT(is_learned() != l); m_learned = l; } void set_learned(bool l) { SASSERT(is_learned() != l); m_learned = l; }
void shrink(unsigned num_lits) { SASSERT(num_lits <= m_size); if (num_lits < m_size) { m_size = num_lits; mark_strengthened(); } } void shrink(unsigned num_lits);
bool strengthened() const { return m_strengthened; } bool strengthened() const { return m_strengthened; }
void mark_strengthened() { m_strengthened = true; update_approx(); } void mark_strengthened() { m_strengthened = true; update_approx(); }
void unmark_strengthened() { m_strengthened = false; } void unmark_strengthened() { m_strengthened = false; }

View file

@ -145,10 +145,7 @@ namespace sat {
*it2 = *it; *it2 = *it;
it2++; it2++;
if (!c.frozen()) { if (!c.frozen()) {
if (new_sz == 3) s.attach_clause(c);
s.attach_ter_clause(c);
else
s.attach_nary_clause(c);
} }
if (s.m_config.m_drat) { if (s.m_config.m_drat) {
// for optimization, could also report deletion // for optimization, could also report deletion

View file

@ -37,9 +37,9 @@ namespace sat{
literal pos_l(v, false); literal pos_l(v, false);
literal neg_l(v, true); literal neg_l(v, true);
unsigned num_bin_pos = simp.get_num_unblocked_bin(pos_l); unsigned num_bin_pos = simp.num_nonlearned_bin(pos_l);
if (num_bin_pos > m_max_literals) return false; if (num_bin_pos > m_max_literals) return false;
unsigned num_bin_neg = simp.get_num_unblocked_bin(neg_l); unsigned num_bin_neg = simp.num_nonlearned_bin(neg_l);
if (num_bin_neg > m_max_literals) return false; if (num_bin_neg > m_max_literals) return false;
clause_use_list & pos_occs = simp.m_use_list.get(pos_l); clause_use_list & pos_occs = simp.m_use_list.get(pos_l);
clause_use_list & neg_occs = simp.m_use_list.get(neg_l); clause_use_list & neg_occs = simp.m_use_list.get(neg_l);

View file

@ -73,7 +73,7 @@ namespace sat {
It assumes wlist have been sorted using iff3_lt It assumes wlist have been sorted using iff3_lt
*/ */
static bool contains(watch_list const & wlist, literal l1, literal l2) { static bool contains(watch_list const & wlist, literal l1, literal l2) {
watched k(l1, l2, false); watched k(l1, l2);
if (wlist.size() < SMALL_WLIST) if (wlist.size() < SMALL_WLIST)
return wlist.contains(k); return wlist.contains(k);
iff3_lt lt; iff3_lt lt;

View file

@ -28,8 +28,8 @@ namespace sat {
} }
// for ternary clauses // for ternary clauses
static bool contains_watched(watch_list const & wlist, literal l1, literal l2, bool learned) { static bool contains_watched(watch_list const & wlist, literal l1, literal l2) {
return wlist.contains(watched(l1, l2, learned)); return wlist.contains(watched(l1, l2));
} }
// for nary clauses // for nary clauses
@ -68,9 +68,9 @@ namespace sat {
tout << "watch_list:\n"; tout << "watch_list:\n";
sat::display_watch_list(tout, s.m_cls_allocator, s.get_wlist(~c[0])); sat::display_watch_list(tout, s.m_cls_allocator, s.get_wlist(~c[0]));
tout << "\n";); tout << "\n";);
VERIFY(contains_watched(s.get_wlist(~c[0]), c[1], c[2], c.is_learned())); VERIFY(contains_watched(s.get_wlist(~c[0]), c[1], c[2]));
VERIFY(contains_watched(s.get_wlist(~c[1]), c[0], c[2], c.is_learned())); VERIFY(contains_watched(s.get_wlist(~c[1]), c[0], c[2]));
VERIFY(contains_watched(s.get_wlist(~c[2]), c[0], c[1], c.is_learned())); VERIFY(contains_watched(s.get_wlist(~c[2]), c[0], c[1]));
} }
else { else {
if (s.value(c[0]) == l_false || s.value(c[1]) == l_false) { if (s.value(c[0]) == l_false || s.value(c[1]) == l_false) {

View file

@ -2306,6 +2306,7 @@ namespace sat {
roots[v] = p; roots[v] = p;
VERIFY(get_parent(p) == p); VERIFY(get_parent(p) == p);
VERIFY(get_parent(~p) == ~p); VERIFY(get_parent(~p) == ~p);
IF_VERBOSE(0, verbose_stream() << p << " " << q << "\n";);
} }
} }
IF_VERBOSE(1, verbose_stream() << "(sat-lookahead :equivalences " << to_elim.size() << ")\n";); IF_VERBOSE(1, verbose_stream() << "(sat-lookahead :equivalences " << to_elim.size() << ")\n";);

View file

@ -148,27 +148,17 @@ namespace sat {
m_use_list.erase(c, l); m_use_list.erase(c, l);
} }
inline void simplifier::block_clause(clause & c) { inline void simplifier::set_learned(clause & c) {
if (m_retain_blocked_clauses) {
m_need_cleanup = true; m_need_cleanup = true;
s.set_learned(c, true); s.set_learned(c, true);
m_use_list.block(c); m_use_list.block(c);
} }
else {
remove_clause(c);
}
} inline void simplifier::set_learned(literal l1, literal l2) {
m_sub_bin_todo.erase(bin_clause(l1, l2, false));
inline void simplifier::unblock_clause(clause & c) { m_sub_bin_todo.erase(bin_clause(l2, l1, false));
s.set_learned(c, false); m_sub_bin_todo.push_back(bin_clause(l1, l2, true));
m_use_list.unblock(c); m_sub_bin_todo.push_back(bin_clause(l2, l1, true));
}
inline void simplifier::remove_bin_clause_half(literal l1, literal l2, bool learned) {
get_wlist(~l1).erase(watched(l2, learned));
m_sub_bin_todo.erase(bin_clause(l1, l2, learned));
m_sub_bin_todo.erase(bin_clause(l2, l1, learned));
} }
void simplifier::init_visited() { void simplifier::init_visited() {
@ -308,13 +298,16 @@ namespace sat {
clause_vector::iterator it = cs.begin(); clause_vector::iterator it = cs.begin();
clause_vector::iterator it2 = it; clause_vector::iterator it2 = it;
clause_vector::iterator end = cs.end(); clause_vector::iterator end = cs.end();
unsigned nm = 0;
for (; it != end; ++it) { for (; it != end; ++it) {
clause & c = *(*it); clause & c = *(*it);
if (learned && !c.is_learned()) { if (learned && !c.is_learned()) {
s.m_clauses.push_back(&c); s.m_clauses.push_back(&c);
++nm;
} }
else if (!learned && c.is_learned()) { else if (!learned && c.is_learned()) {
s.m_learned.push_back(&c); s.m_learned.push_back(&c);
++nm;
} }
else { else {
*it2 = *it; *it2 = *it;
@ -373,19 +366,10 @@ namespace sat {
s.del_clause(c); s.del_clause(c);
continue; continue;
} }
// clause became a learned clause
if (!learned && c.is_learned()) {
SASSERT(!c.frozen());
s.m_learned.push_back(&c);
continue;
}
*it2 = *it; *it2 = *it;
it2++; it2++;
if (!c.frozen()) { if (!c.frozen()) {
if (sz == 3) s.attach_clause(c);
s.attach_ter_clause(c);
else
s.attach_nary_clause(c);
if (s.m_config.m_drat) { if (s.m_config.m_drat) {
s.m_drat.add(c, true); s.m_drat.add(c, true);
} }
@ -895,6 +879,7 @@ namespace sat {
break; break;
clause & c = m_sub_todo.erase(); clause & c = m_sub_todo.erase();
c.unmark_strengthened(); c.unmark_strengthened();
m_sub_counter--; m_sub_counter--;
TRACE("subsumption", tout << "next: " << c << "\n";); TRACE("subsumption", tout << "next: " << c << "\n";);
@ -944,21 +929,23 @@ namespace sat {
}; };
class clause_ante { class clause_ante {
bool m_from_ri;
literal m_lit1; literal m_lit1;
literal m_lit2; literal m_lit2;
clause* m_clause; clause* m_clause;
public: public:
clause_ante(): clause_ante():
m_lit1(null_literal), m_lit2(null_literal), m_clause(nullptr) {} m_from_ri(false), m_lit1(null_literal), m_lit2(null_literal), m_clause(nullptr) {}
clause_ante(literal l1): clause_ante(literal l1, bool from_ri):
m_lit1(l1), m_lit2(null_literal), m_clause(nullptr) {} m_from_ri(from_ri), m_lit1(l1), m_lit2(null_literal), m_clause(nullptr) {}
clause_ante(literal l1, literal l2): clause_ante(literal l1, literal l2):
m_lit1(l1), m_lit2(l2), m_clause(nullptr) {} m_from_ri(false), m_lit1(l1), m_lit2(l2), m_clause(nullptr) {}
clause_ante(clause& c): clause_ante(clause& c):
m_lit1(null_literal), m_lit2(null_literal), m_clause(&c) {} m_from_ri(false), m_lit1(null_literal), m_lit2(null_literal), m_clause(&c) {}
literal lit1() const { return m_lit1; } literal lit1() const { return m_lit1; }
literal lit2() const { return m_lit2; } literal lit2() const { return m_lit2; }
clause* cls() const { return m_clause; } clause* cls() const { return m_clause; }
bool from_ri() const { return m_from_ri; }
bool operator==(clause_ante const& a) const { bool operator==(clause_ante const& a) const {
return a.m_lit1 == m_lit1 && a.m_lit2 == m_lit2 && a.m_clause == m_clause; return a.m_lit1 == m_lit1 && a.m_lit2 == m_lit2 && a.m_clause == m_clause;
} }
@ -990,13 +977,12 @@ namespace sat {
int m_counter; int m_counter;
model_converter & mc; model_converter & mc;
queue m_queue; queue m_queue;
clause_vector m_to_remove;
literal_vector m_covered_clause; literal_vector m_covered_clause; // covered clause
svector<clause_ante> m_covered_antecedent; svector<clause_ante> m_covered_antecedent; // explainations for literals in covered clause
literal_vector m_intersection; literal_vector m_intersection; // current resolution intersection
literal_vector m_tautology; // literals that are used in blocking tautology
literal_vector m_new_intersection; literal_vector m_new_intersection;
literal_vector m_blocked_binary;
svector<bool> m_in_intersection; svector<bool> m_in_intersection;
sat::model_converter::elim_stackv m_elim_stack; sat::model_converter::elim_stackv m_elim_stack;
unsigned m_ala_qhead; unsigned m_ala_qhead;
@ -1080,43 +1066,27 @@ namespace sat {
} }
void process_binary(literal l) { void process_binary(literal l) {
m_blocked_binary.reset();
model_converter::entry* new_entry = 0; model_converter::entry* new_entry = 0;
watch_list & wlist = s.get_wlist(~l); watch_list & wlist = s.get_wlist(~l);
m_counter -= wlist.size(); m_counter -= wlist.size();
watch_list::iterator it = wlist.begin(); for (watched& w : wlist) {
watch_list::iterator it2 = it; if (!w.is_binary_non_learned_clause()) {
watch_list::iterator end = wlist.end();
for (; it != end; ++it) {
if (!it->is_binary_non_learned_clause()) {
*it2 = *it; it2++;
continue; continue;
} }
literal l2 = it->get_literal(); literal l2 = w.get_literal();
s.mark_visited(l2); s.mark_visited(l2);
if (all_tautology(l)) { if (all_tautology(l)) {
block_binary(it, l, new_entry); block_binary(w, l, new_entry);
s.m_num_blocked_clauses++; w.set_learned(true);
m_blocked_binary.push_back(l2); s.s.set_learned1(l2, l, true);
} s.m_num_bce++;
else {
*it2 = *it; it2++;
} }
s.unmark_visited(l2); s.unmark_visited(l2);
} }
wlist.set_end(it2);
if (s.m_retain_blocked_clauses && !m_blocked_binary.empty()) {
IF_VERBOSE(0, verbose_stream() << "retaining " << m_blocked_binary.size() << " binary clauses\n";);
for (literal lit2 : m_blocked_binary) {
s.s.mk_bin_clause(l, lit2, true);
}
}
} }
void process_clauses(literal l) { void process_clauses(literal l) {
model_converter::entry* new_entry = 0; model_converter::entry* new_entry = 0;
m_to_remove.reset();
clause_use_list & occs = s.m_use_list.get(l); clause_use_list & occs = s.m_use_list.get(l);
clause_use_list::iterator it = occs.mk_iterator(); clause_use_list::iterator it = occs.mk_iterator();
for (; !it.at_end(); it.next()) { for (; !it.at_end(); it.next()) {
@ -1127,12 +1097,11 @@ namespace sat {
s.mark_all_but(c, l); s.mark_all_but(c, l);
if (all_tautology(l)) { if (all_tautology(l)) {
block_clause(c, l, new_entry); block_clause(c, l, new_entry);
s.m_num_blocked_clauses++; s.m_num_bce++;
s.set_learned(c);
} }
s.unmark_all(c); s.unmark_all(c);
} }
for (clause* c : m_to_remove)
s.block_clause(*c);
} }
void reset_intersection() { void reset_intersection() {
@ -1145,8 +1114,6 @@ namespace sat {
m_in_intersection[lit.index()] = true; m_in_intersection[lit.index()] = true;
} }
// //
// Resolve intersection // Resolve intersection
// Find literals that are in the intersection of all resolvents with l. // Find literals that are in the intersection of all resolvents with l.
@ -1155,6 +1122,7 @@ namespace sat {
if (!process_var(l.var())) return false; if (!process_var(l.var())) return false;
bool first = true; bool first = true;
reset_intersection(); reset_intersection();
m_tautology.reset();
for (watched & w : s.get_wlist(l)) { for (watched & w : s.get_wlist(l)) {
// when adding a blocked clause, then all non-learned clauses have to be considered for the // when adding a blocked clause, then all non-learned clauses have to be considered for the
// resolution intersection. // resolution intersection.
@ -1162,6 +1130,7 @@ namespace sat {
if (process_bin) { if (process_bin) {
literal lit = w.get_literal(); literal lit = w.get_literal();
if (s.is_marked(~lit) && lit != ~l) { if (s.is_marked(~lit) && lit != ~l) {
m_tautology.push_back(~lit);
continue; // tautology continue; // tautology
} }
if (!first || s.is_marked(lit)) { if (!first || s.is_marked(lit)) {
@ -1178,8 +1147,10 @@ namespace sat {
bool tautology = false; bool tautology = false;
clause & c = it.curr(); clause & c = it.curr();
if (c.is_learned() && !adding) continue; if (c.is_learned() && !adding) continue;
if (c.was_removed()) continue;
for (literal lit : c) { for (literal lit : c) {
if (s.is_marked(~lit) && lit != ~l) { if (s.is_marked(~lit) && lit != ~l) {
m_tautology.push_back(~lit);
tautology = true; tautology = true;
break; break;
} }
@ -1204,25 +1175,30 @@ namespace sat {
return false; return false;
} }
} }
// if (first) IF_VERBOSE(0, verbose_stream() << "taut: " << m_tautology << "\n";);
return first; return first;
} }
bool check_abce_tautology(literal l) { bool check_abce_tautology(literal l) {
m_tautology.reset();
if (!process_var(l.var())) return false; if (!process_var(l.var())) return false;
for (watched & w : s.get_wlist(l)) { for (watched & w : s.get_wlist(l)) {
if (w.is_binary_non_learned_clause()) { if (w.is_binary_non_learned_clause()) {
literal lit = w.get_literal(); literal lit = w.get_literal();
if (!s.is_marked(~lit) || lit == ~l) return false; VERIFY(lit != ~l);
if (!s.is_marked(~lit)) return false;
m_tautology.push_back(~lit);
} }
} }
clause_use_list & neg_occs = s.m_use_list.get(~l); clause_use_list & neg_occs = s.m_use_list.get(~l);
for (auto it = neg_occs.mk_iterator(); !it.at_end(); it.next()) { for (auto it = neg_occs.mk_iterator(); !it.at_end(); it.next()) {
clause & c = it.curr(); clause & c = it.curr();
if (c.is_learned()) continue; if (c.is_learned() || c.was_removed()) continue;
bool tautology = false; bool tautology = false;
for (literal lit : c) { for (literal lit : c) {
if (s.is_marked(~lit) && lit != ~l) { if (s.is_marked(~lit) && lit != ~l) {
tautology = true; tautology = true;
m_tautology.push_back(~lit);
break; break;
} }
} }
@ -1237,53 +1213,65 @@ namespace sat {
(m_clause[0] == l2 && m_clause[1] == l1)); (m_clause[0] == l2 && m_clause[1] == l1));
} }
bool revisit_ternary(literal l1, literal l2, literal l3) const {
return m_clause.size() == 3 &&
((m_clause[0] == l1 && m_clause[1] == l2 && m_clause[2] == l3) ||
(m_clause[0] == l2 && m_clause[1] == l1 && m_clause[2] == l3) ||
(m_clause[0] == l2 && m_clause[1] == l3 && m_clause[2] == l1) ||
(m_clause[0] == l1 && m_clause[1] == l3 && m_clause[2] == l2) ||
(m_clause[0] == l3 && m_clause[1] == l1 && m_clause[2] == l2) ||
(m_clause[0] == l3 && m_clause[1] == l2 && m_clause[2] == l1));
}
bool revisit_clause(clause const& c) const { bool revisit_clause(clause const& c) const {
return !m_clause.is_binary() && (m_clause.get_clause() == &c); return !m_clause.is_binary() && (m_clause.get_clause() == &c);
} }
/**
\brief idx is the index of the blocked literal.
m_tautology contains literals that were used to establish that the current members of m_covered_clause is blocked.
This routine removes literals that were not relevant to establishing it was blocked.
*/
void minimize_covered_clause(unsigned idx) { void minimize_covered_clause(unsigned idx) {
IF_VERBOSE(0, verbose_stream() << "minimize: " << m_covered_clause << " @ " << idx << "\n";); // IF_VERBOSE(0, verbose_stream() << "minimize: " << m_covered_clause << " @ " << idx << "\n" << "tautology: " << m_tautology << "\n";);
for (literal l : m_tautology) VERIFY(s.is_marked(l));
for (literal l : m_covered_clause) s.unmark_visited(l); for (literal l : m_covered_clause) s.unmark_visited(l);
for (literal l : m_tautology) s.mark_visited(l);
s.mark_visited(m_covered_clause[idx]); s.mark_visited(m_covered_clause[idx]);
for (unsigned i = 0; i < m_covered_clause.size(); ++i) {
literal lit = m_covered_clause[i];
if (m_covered_antecedent[i] == clause_ante()) s.mark_visited(lit);
if (s.is_marked(lit)) idx = i;
}
for (unsigned i = idx; i > 0; --i) { for (unsigned i = idx; i > 0; --i) {
literal lit = m_covered_clause[i]; literal lit = m_covered_clause[i];
if (!s.is_marked(lit)) continue; if (!s.is_marked(lit)) continue;
clause_ante const& ante = m_covered_antecedent[i]; clause_ante const& ante = m_covered_antecedent[i];
if (ante.cls()) { if (ante.cls()) {
for (literal l : *ante.cls()) { for (literal l : *ante.cls()) {
IF_VERBOSE(0, verbose_stream() << "clause ante: " << l << "\n";);
if (l != ~lit) s.mark_visited(l); if (l != ~lit) s.mark_visited(l);
} }
} }
if (ante.lit1() != null_literal) { if (ante.lit1() != null_literal) {
IF_VERBOSE(0, verbose_stream() << "ante1: " << ante.lit1() << "\n";);
s.mark_visited(ante.lit1()); s.mark_visited(ante.lit1());
} }
if (ante.lit2() != null_literal) { if (ante.lit2() != null_literal) {
IF_VERBOSE(0, verbose_stream() << "ante2: " << ante.lit2() << "\n";);
s.mark_visited(ante.lit2()); s.mark_visited(ante.lit2());
} }
} }
unsigned j = 0; unsigned j = 0;
literal blocked = null_literal;
for (unsigned i = 0; i <= idx; ++i) { for (unsigned i = 0; i <= idx; ++i) {
literal lit = m_covered_clause[i]; literal lit = m_covered_clause[i];
if (s.is_marked(lit) || m_covered_antecedent[i] == clause_ante()) { if (s.is_marked(lit)) {
//
// Record that the resolving literal for
// resolution intersection can be flipped.
//
clause_ante const& ante = m_covered_antecedent[i];
if (ante.from_ri() && blocked != ante.lit1()) {
blocked = ante.lit1();
m_elim_stack.push_back(std::make_pair(j, blocked));
}
m_covered_clause[j++] = lit; m_covered_clause[j++] = lit;
s.unmark_visited(lit); s.unmark_visited(lit);
} }
} }
for (literal l : m_covered_clause) VERIFY(!s.is_marked(l));
// unsigned sz0 = m_covered_clause.size();
m_covered_clause.resize(j); m_covered_clause.resize(j);
IF_VERBOSE(0, verbose_stream() << "reduced: " << m_covered_clause << "\n";); VERIFY(j >= m_clause.size());
// IF_VERBOSE(0, verbose_stream() << "reduced from size " << sz0 << " to " << m_covered_clause << "\n" << m_clause << "\n";);
} }
/* /*
@ -1308,42 +1296,20 @@ namespace sat {
literal lit = w.get_literal(); literal lit = w.get_literal();
if (revisit_binary(l, lit)) continue; if (revisit_binary(l, lit)) continue;
if (s.is_marked(lit)) { if (s.is_marked(lit)) {
IF_VERBOSE(0, verbose_stream() << "ATE: " << m_covered_clause << " binary: " << l << " " << lit << "\n";);
return true; return true;
} }
if (!s.is_marked(~lit)) { if (!s.is_marked(~lit)) {
IF_VERBOSE(0, verbose_stream() << "ALA: " << m_covered_clause << " binary " << l << " " << lit << " " << (~lit) << "\n";);
m_covered_clause.push_back(~lit); m_covered_clause.push_back(~lit);
m_covered_antecedent.push_back(clause_ante(l)); m_covered_antecedent.push_back(clause_ante(l, false));
s.mark_visited(~lit); s.mark_visited(~lit);
} }
} }
else if (w.is_ternary_clause() && !w.is_learned()) {
literal lit1 = w.get_literal1();
literal lit2 = w.get_literal2();
if (revisit_ternary(l, lit1, lit2)) continue;
if (s.is_marked(lit1) && s.is_marked(lit2)) {
IF_VERBOSE(0, verbose_stream() << "ATE: " << m_covered_clause << " ternary: " << l << " " << lit1 << " " << lit2 << "\n";);
return true;
} }
if (s.is_marked(lit1) && !s.is_marked(~lit2)) { clause_use_list & pos_occs = s.m_use_list.get(l);
IF_VERBOSE(0, verbose_stream() << "ALA: " << m_covered_clause << " ternary " << l << " " << lit1 << " " << lit2 << " " << (~lit2) << "\n";); clause_use_list::iterator it = pos_occs.mk_iterator();
m_covered_clause.push_back(~lit2); for (; !it.at_end(); it.next()) {
m_covered_antecedent.push_back(clause_ante(l, lit1)); clause & c = it.curr();
s.mark_visited(~lit2); if (c.is_learned() || c.was_removed()) continue;
continue;
}
if (s.is_marked(lit2) && !s.is_marked(~lit1)) {
IF_VERBOSE(0, verbose_stream() << "ALA: " << m_covered_clause << " ternay " << l << " " << lit1 << " " << lit2 << " " << (~lit1) << "\n";);
m_covered_clause.push_back(~lit1);
m_covered_antecedent.push_back(clause_ante(l, lit2));
s.mark_visited(~lit1);
continue;
}
}
else if (w.is_clause()) {
clause & c = s.s.get_clause(w.get_clause_offset());
if (c.is_learned()) continue;
if (revisit_clause(c)) continue; if (revisit_clause(c)) continue;
literal lit1 = null_literal; literal lit1 = null_literal;
bool ok = true; bool ok = true;
@ -1360,16 +1326,13 @@ namespace sat {
} }
if (!ok) continue; if (!ok) continue;
if (lit1 == null_literal) { if (lit1 == null_literal) {
IF_VERBOSE(0, verbose_stream() << "ATE: " << m_covered_clause << " clause " << c << "\n";);
return true; return true;
} }
IF_VERBOSE(0, verbose_stream() << "ALA: " << m_covered_clause << " clause " << c << " " << (~lit1) << "\n";);
m_covered_clause.push_back(~lit1); m_covered_clause.push_back(~lit1);
m_covered_antecedent.push_back(clause_ante(c)); m_covered_antecedent.push_back(clause_ante(c));
s.mark_visited(~lit1); s.mark_visited(~lit1);
} }
} }
}
return false; return false;
} }
@ -1389,14 +1352,11 @@ namespace sat {
minimize_covered_clause(i); minimize_covered_clause(i);
return true; return true;
} }
if (!m_intersection.empty()) {
m_elim_stack.push_back(std::make_pair(m_covered_clause.size(), m_covered_clause[i]));
}
for (literal l : m_intersection) { for (literal l : m_intersection) {
if (!s.is_marked(l)) { if (!s.is_marked(l)) {
s.mark_visited(l); s.mark_visited(l);
m_covered_clause.push_back(l); m_covered_clause.push_back(l);
m_covered_antecedent.push_back(clause_ante(lit)); m_covered_antecedent.push_back(clause_ante(lit, true));
} }
} }
} }
@ -1430,10 +1390,9 @@ namespace sat {
for (literal l : m_covered_clause) s.unmark_visited(l); for (literal l : m_covered_clause) s.unmark_visited(l);
return at_t; return at_t;
} }
for (unsigned i = 0; !is_tautology && i < sz0; ++i) { for (unsigned i = 0; i < sz0; ++i) {
if (check_abce_tautology(m_covered_clause[i])) { if (check_abce_tautology(m_covered_clause[i])) {
blocked = m_covered_clause[i]; blocked = m_covered_clause[i];
minimize_covered_clause(i);
is_tautology = true; is_tautology = true;
break; break;
} }
@ -1456,7 +1415,6 @@ namespace sat {
is_tautology = add_cla(blocked); is_tautology = add_cla(blocked);
} }
while (m_covered_clause.size() > sz && !is_tautology); while (m_covered_clause.size() > sz && !is_tautology);
if (above_threshold(sz0)) break;
if (et == acce_t && !is_tautology) { if (et == acce_t && !is_tautology) {
sz = m_covered_clause.size(); sz = m_covered_clause.size();
if (add_ala()) { if (add_ala()) {
@ -1465,11 +1423,11 @@ namespace sat {
} }
k = model_converter::ACCE; k = model_converter::ACCE;
} }
if (above_threshold(sz0)) break;
} }
while (m_covered_clause.size() > sz && !is_tautology); while (m_covered_clause.size() > sz && !is_tautology);
// if (is_tautology) std::cout << num_iterations << " " << m_covered_clause.size() << " " << sz0 << " " << is_tautology << " " << m_elim_stack.size() << "\n";
for (literal l : m_covered_clause) s.unmark_visited(l); for (literal l : m_covered_clause) s.unmark_visited(l);
return (is_tautology && !above_threshold(sz0)) ? bc_t : no_t; return is_tautology ? bc_t : no_t;
} }
// perform covered clause elimination. // perform covered clause elimination.
@ -1484,6 +1442,7 @@ namespace sat {
m_covered_clause.push_back(l); m_covered_clause.push_back(l);
m_covered_antecedent.push_back(clause_ante()); m_covered_antecedent.push_back(clause_ante());
} }
// shuffle<literal>(s.s.m_rand, m_covered_clause);
return cla<et>(blocked, k); return cla<et>(blocked, k);
} }
@ -1516,81 +1475,68 @@ namespace sat {
template<elim_type et> template<elim_type et>
void process_cce_binary(literal l) { void process_cce_binary(literal l) {
m_blocked_binary.reset();
literal blocked = null_literal; literal blocked = null_literal;
watch_list & wlist = s.get_wlist(~l); watch_list & wlist = s.get_wlist(~l);
m_counter -= wlist.size(); m_counter -= wlist.size();
watch_list::iterator it = wlist.begin();
watch_list::iterator it2 = it;
watch_list::iterator end = wlist.end();
model_converter::kind k; model_converter::kind k;
for (; it != end; ++it) { for (watched & w : wlist) {
if (!it->is_binary_non_learned_clause()) { if (!w.is_binary_non_learned_clause()) continue;
*it2 = *it; literal l2 = w.get_literal();
it2++;
continue;
}
literal l2 = it->get_literal();
switch (cce<et>(l, l2, blocked, k)) { switch (cce<et>(l, l2, blocked, k)) {
case bc_t: case bc_t:
block_covered_binary(it, l, blocked, k); inc_bc<et>();
s.m_num_covered_clauses++; block_covered_binary(w, l, blocked, k);
m_blocked_binary.push_back(l2); w.set_learned(true);
s.s.set_learned1(l2, l, true);
break; break;
case at_t: case at_t:
s.m_num_ate++; s.m_num_ate++;
m_blocked_binary.push_back(l2); w.set_learned(true);
s.s.set_learned1(l2, l, true);
break; break;
case no_t: case no_t:
*it2 = *it;
it2++;
break; break;
} }
} }
wlist.set_end(it2);
if (s.m_retain_blocked_clauses && !m_blocked_binary.empty()) {
IF_VERBOSE(0, verbose_stream() << "retaining " << m_blocked_binary.size() << " binary clauses\n";);
for (literal lit2 : m_blocked_binary) {
s.s.mk_bin_clause(l, lit2, true);
} }
}
}
template<elim_type et> template<elim_type et>
void cce_clauses() { void cce_clauses() {
m_to_remove.reset();
literal blocked; literal blocked;
model_converter::kind k; model_converter::kind k;
for (clause* cp : s.s.m_clauses) { for (clause* cp : s.s.m_clauses) {
clause& c = *cp; clause& c = *cp;
if (!c.was_removed() && !c.is_learned()) { if (c.was_removed() || c.is_learned()) continue;
switch (cce<et>(c, blocked, k)) { switch (cce<et>(c, blocked, k)) {
case bc_t: case bc_t:
inc_bc<et>();
block_covered_clause(c, blocked, k); block_covered_clause(c, blocked, k);
s.m_num_covered_clauses++; s.set_learned(c);
break; break;
case at_t: case at_t:
m_to_remove.push_back(&c); s.m_num_ate++;
s.set_learned(c);
break; break;
case no_t: case no_t:
break; break;
} }
} }
} }
for (clause* c : m_to_remove) {
s.block_clause(*c);
}
m_to_remove.reset();
}
template<elim_type et>
void inc_bc() {
switch (et) {
case cce_t: s.m_num_cce++; break;
case acce_t: s.m_num_acce++; break;
case abce_t: s.m_num_abce++; break;
}
}
void prepare_block_clause(clause& c, literal l, model_converter::entry*& new_entry, model_converter::kind k) { void prepare_block_clause(clause& c, literal l, model_converter::entry*& new_entry, model_converter::kind k) {
TRACE("blocked_clause", tout << "new blocked clause: " << c << "\n";); TRACE("blocked_clause", tout << "new blocked clause: " << c << "\n";);
VERIFY(!s.is_external(l)); VERIFY(!s.is_external(l));
if (new_entry == 0) if (new_entry == 0)
new_entry = &(mc.mk(k, l.var())); new_entry = &(mc.mk(k, l.var()));
m_to_remove.push_back(&c);
for (literal lit : c) { for (literal lit : c) {
if (lit != l && process_var(lit.var())) { if (lit != l && process_var(lit.var())) {
m_queue.decreased(~lit); m_queue.decreased(~lit);
@ -1611,25 +1557,25 @@ namespace sat {
mc.insert(*new_entry, m_covered_clause, m_elim_stack); mc.insert(*new_entry, m_covered_clause, m_elim_stack);
} }
void prepare_block_binary(watch_list::iterator it, literal l1, literal blocked, model_converter::entry*& new_entry, model_converter::kind k) { void prepare_block_binary(watched const& w, literal l1, literal blocked, model_converter::entry*& new_entry, model_converter::kind k) {
SASSERT(!s.is_external(blocked)); SASSERT(!s.is_external(blocked));
if (new_entry == 0) if (new_entry == 0)
new_entry = &(mc.mk(k, blocked.var())); new_entry = &(mc.mk(k, blocked.var()));
literal l2 = it->get_literal(); literal l2 = w.get_literal();
TRACE("blocked_clause", tout << "new blocked clause: " << l2 << " " << l1 << "\n";); TRACE("blocked_clause", tout << "new blocked clause: " << l2 << " " << l1 << "\n";);
s.remove_bin_clause_half(l2, l1, it->is_learned()); s.set_learned(l1, l2);
m_queue.decreased(~l2); m_queue.decreased(~l2);
} }
void block_binary(watch_list::iterator it, literal l, model_converter::entry *& new_entry) { void block_binary(watched const& w, literal l, model_converter::entry *& new_entry) {
literal l2 = it->get_literal(); literal l2 = w.get_literal();
prepare_block_binary(it, l, l, new_entry, model_converter::BLOCK_LIT); prepare_block_binary(w, l, l, new_entry, model_converter::BLOCK_LIT);
mc.insert(*new_entry, l, l2); mc.insert(*new_entry, l, l2);
} }
void block_covered_binary(watch_list::iterator it, literal l, literal blocked, model_converter::kind k) { void block_covered_binary(watched const& w, literal l, literal blocked, model_converter::kind k) {
model_converter::entry * new_entry = 0; model_converter::entry * new_entry = 0;
prepare_block_binary(it, l, blocked, new_entry, k); prepare_block_binary(w, l, blocked, new_entry, k);
mc.insert(*new_entry, m_covered_clause, m_elim_stack); mc.insert(*new_entry, m_covered_clause, m_elim_stack);
} }
@ -1681,6 +1627,7 @@ namespace sat {
for (; !it.at_end(); it.next()) { for (; !it.at_end(); it.next()) {
clause & c = it.curr(); clause & c = it.curr();
if (c.is_learned()) continue; if (c.is_learned()) continue;
if (c.was_removed()) continue;
m_counter -= c.size(); m_counter -= c.size();
unsigned sz = c.size(); unsigned sz = c.size();
unsigned i; unsigned i;
@ -1707,33 +1654,40 @@ namespace sat {
struct simplifier::blocked_cls_report { struct simplifier::blocked_cls_report {
simplifier & m_simplifier; simplifier & m_simplifier;
stopwatch m_watch; stopwatch m_watch;
unsigned m_num_blocked_clauses; unsigned m_num_bce;
unsigned m_num_covered_clauses; unsigned m_num_cce;
unsigned m_num_acce;
unsigned m_num_abce;
unsigned m_num_ate; unsigned m_num_ate;
unsigned m_num_added_clauses; unsigned m_num_bca;
blocked_cls_report(simplifier & s): blocked_cls_report(simplifier & s):
m_simplifier(s), m_simplifier(s),
m_num_blocked_clauses(s.m_num_blocked_clauses), m_num_bce(s.m_num_bce),
m_num_covered_clauses(s.m_num_covered_clauses), m_num_cce(s.m_num_cce),
m_num_acce(s.m_num_acce),
m_num_abce(s.m_num_abce),
m_num_ate(s.m_num_ate), m_num_ate(s.m_num_ate),
m_num_added_clauses(s.m_num_bca) { m_num_bca(s.m_num_bca) {
m_watch.start(); m_watch.start();
} }
~blocked_cls_report() { ~blocked_cls_report() {
m_watch.stop(); m_watch.stop();
IF_VERBOSE(SAT_VB_LVL, IF_VERBOSE(SAT_VB_LVL,
verbose_stream() << " (sat-blocked-clauses :elim-blocked-clauses " verbose_stream() << " (sat-blocked-clauses";
<< (m_simplifier.m_num_blocked_clauses - m_num_blocked_clauses) report(m_simplifier.m_num_ate, m_num_ate, " :ate ");
<< " :elim-covered-clauses " report(m_simplifier.m_num_bce, m_num_bce, " :bce ");
<< (m_simplifier.m_num_covered_clauses - m_num_covered_clauses) report(m_simplifier.m_num_abce, m_num_abce, " :abce ");
<< " :added-clauses " report(m_simplifier.m_num_cce, m_num_cce, " :cce ");
<< (m_simplifier.m_num_bca - m_num_added_clauses) report(m_simplifier.m_num_bca, m_num_bca, " :bca ");
<< " :ate " report(m_simplifier.m_num_acce, m_num_acce, " :acce ");
<< (m_simplifier.m_num_ate - m_num_ate) verbose_stream() << mem_stat()
<< mem_stat()
<< " :time " << std::fixed << std::setprecision(2) << m_watch.get_seconds() << ")\n";); << " :time " << std::fixed << std::setprecision(2) << m_watch.get_seconds() << ")\n";);
} }
void report(unsigned n, unsigned m, char const* s) {
if (n > m) verbose_stream() << s << (n - m);
}
}; };
void simplifier::elim_blocked_clauses() { void simplifier::elim_blocked_clauses() {
@ -1743,7 +1697,7 @@ namespace sat {
elim(); elim();
} }
unsigned simplifier::get_num_unblocked_bin(literal l) const { unsigned simplifier::num_nonlearned_bin(literal l) const {
unsigned r = 0; unsigned r = 0;
watch_list const & wlist = get_wlist(~l); watch_list const & wlist = get_wlist(~l);
for (auto & w : wlist) { for (auto & w : wlist) {
@ -1758,8 +1712,8 @@ namespace sat {
literal neg_l(v, true); literal neg_l(v, true);
unsigned num_pos = m_use_list.get(pos_l).size(); unsigned num_pos = m_use_list.get(pos_l).size();
unsigned num_neg = m_use_list.get(neg_l).size(); unsigned num_neg = m_use_list.get(neg_l).size();
unsigned num_bin_pos = get_num_unblocked_bin(pos_l); unsigned num_bin_pos = num_nonlearned_bin(pos_l);
unsigned num_bin_neg = get_num_unblocked_bin(neg_l); unsigned num_bin_neg = num_nonlearned_bin(neg_l);
unsigned cost = 2 * num_pos * num_neg + num_pos * num_bin_neg + num_neg * num_bin_pos; unsigned cost = 2 * num_pos * num_neg + num_pos * num_bin_neg + num_neg * num_bin_pos;
CTRACE("elim_vars_detail", cost == 0, tout << v << " num_pos: " << num_pos << " num_neg: " << num_neg << " num_bin_pos: " << num_bin_pos CTRACE("elim_vars_detail", cost == 0, tout << v << " num_pos: " << num_pos << " num_neg: " << num_neg << " num_bin_pos: " << num_bin_pos
<< " num_bin_neg: " << num_bin_neg << " cost: " << cost << "\n";); << " num_bin_neg: " << num_bin_neg << " cost: " << cost << "\n";);
@ -1799,9 +1753,10 @@ namespace sat {
void simplifier::collect_clauses(literal l, clause_wrapper_vector & r) { void simplifier::collect_clauses(literal l, clause_wrapper_vector & r) {
clause_use_list const & cs = m_use_list.get(l); clause_use_list const & cs = m_use_list.get(l);
for (auto it = cs.mk_iterator(); !it.at_end(); it.next()) { for (auto it = cs.mk_iterator(); !it.at_end(); it.next()) {
if (!it.curr().is_learned()) { clause& c = it.curr();
r.push_back(clause_wrapper(it.curr())); if (!c.is_learned() && !c.was_removed()) {
SASSERT(r.back().size() == it.curr().size()); r.push_back(clause_wrapper(c));
SASSERT(r.back().size() == c.size());
} }
} }
@ -1939,8 +1894,8 @@ namespace sat {
literal pos_l(v, false); literal pos_l(v, false);
literal neg_l(v, true); literal neg_l(v, true);
unsigned num_bin_pos = get_num_unblocked_bin(pos_l); unsigned num_bin_pos = num_nonlearned_bin(pos_l);
unsigned num_bin_neg = get_num_unblocked_bin(neg_l); unsigned num_bin_neg = num_nonlearned_bin(neg_l);
clause_use_list & pos_occs = m_use_list.get(pos_l); clause_use_list & pos_occs = m_use_list.get(pos_l);
clause_use_list & neg_occs = m_use_list.get(neg_l); clause_use_list & neg_occs = m_use_list.get(neg_l);
unsigned num_pos = pos_occs.num_irredundant() + num_bin_pos; unsigned num_pos = pos_occs.num_irredundant() + num_bin_pos;
@ -2146,15 +2101,19 @@ namespace sat {
st.update("subsumed", m_num_subsumed); st.update("subsumed", m_num_subsumed);
st.update("subsumption resolution", m_num_sub_res); st.update("subsumption resolution", m_num_sub_res);
st.update("elim literals", m_num_elim_lits); st.update("elim literals", m_num_elim_lits);
st.update("elim blocked clauses", m_num_blocked_clauses); st.update("bce", m_num_bce);
st.update("elim covered clauses", m_num_covered_clauses); st.update("cce", m_num_cce);
st.update("blocked clauses added", m_num_bca); st.update("acce", m_num_acce);
st.update("asymmetric tautologies eliminated", m_num_ate); st.update("abce", m_num_abce);
st.update("bca", m_num_bca);
st.update("ate", m_num_ate);
} }
void simplifier::reset_statistics() { void simplifier::reset_statistics() {
m_num_blocked_clauses = 0; m_num_bce = 0;
m_num_covered_clauses = 0; m_num_cce = 0;
m_num_acce = 0;
m_num_abce = 0;
m_num_subsumed = 0; m_num_subsumed = 0;
m_num_sub_res = 0; m_num_sub_res = 0;
m_num_elim_lits = 0; m_num_elim_lits = 0;

View file

@ -100,14 +100,16 @@ namespace sat {
unsigned m_elim_vars_bdd_delay; unsigned m_elim_vars_bdd_delay;
// stats // stats
unsigned m_num_blocked_clauses; unsigned m_num_bce;
unsigned m_num_covered_clauses; unsigned m_num_cce;
unsigned m_num_acce;
unsigned m_num_abce;
unsigned m_num_bca;
unsigned m_num_ate;
unsigned m_num_subsumed; unsigned m_num_subsumed;
unsigned m_num_elim_vars; unsigned m_num_elim_vars;
unsigned m_num_sub_res; unsigned m_num_sub_res;
unsigned m_num_elim_lits; unsigned m_num_elim_lits;
unsigned m_num_bca;
unsigned m_num_ate;
bool m_learned_in_use_lists; bool m_learned_in_use_lists;
unsigned m_old_num_elim_vars; unsigned m_old_num_elim_vars;
@ -132,9 +134,8 @@ namespace sat {
void remove_clause_core(clause & c); void remove_clause_core(clause & c);
void remove_clause(clause & c); void remove_clause(clause & c);
void remove_clause(clause & c, literal l); void remove_clause(clause & c, literal l);
void block_clause(clause & c); void set_learned(clause & c);
void unblock_clause(clause & c); void set_learned(literal l1, literal l2);
void remove_bin_clause_half(literal l1, literal l2, bool learned);
bool_var get_min_occ_var(clause const & c) const; bool_var get_min_occ_var(clause const & c) const;
bool subsumes1(clause const & c1, clause const & c2, literal & l); bool subsumes1(clause const & c1, clause const & c2, literal & l);
@ -183,7 +184,7 @@ namespace sat {
bool elim_vars_bdd_enabled() const; bool elim_vars_bdd_enabled() const;
bool elim_vars_enabled() const; bool elim_vars_enabled() const;
unsigned get_num_unblocked_bin(literal l) const; unsigned num_nonlearned_bin(literal l) const;
unsigned get_to_elim_cost(bool_var v) const; unsigned get_to_elim_cost(bool_var v) const;
void order_vars_for_elim(bool_var_vector & r); void order_vars_for_elim(bool_var_vector & r);
void collect_clauses(literal l, clause_wrapper_vector & r); void collect_clauses(literal l, clause_wrapper_vector & r);

View file

@ -396,9 +396,9 @@ namespace sat {
bool solver::attach_ter_clause(clause & c) { bool solver::attach_ter_clause(clause & c) {
bool reinit = false; bool reinit = false;
m_watches[(~c[0]).index()].push_back(watched(c[1], c[2], c.is_learned())); m_watches[(~c[0]).index()].push_back(watched(c[1], c[2]));
m_watches[(~c[1]).index()].push_back(watched(c[0], c[2], c.is_learned())); m_watches[(~c[1]).index()].push_back(watched(c[0], c[2]));
m_watches[(~c[2]).index()].push_back(watched(c[0], c[1], c.is_learned())); m_watches[(~c[2]).index()].push_back(watched(c[0], c[1]));
if (!at_base_lvl()) { if (!at_base_lvl()) {
if (value(c[1]) == l_false && value(c[2]) == l_false) { if (value(c[1]) == l_false && value(c[2]) == l_false) {
m_stats.m_ter_propagate++; m_stats.m_ter_propagate++;
@ -482,17 +482,23 @@ namespace sat {
} }
void solver::set_learned(clause& c, bool learned) { void solver::set_learned(clause& c, bool learned) {
if (c.is_learned() == learned) if (c.is_learned() != learned)
return;
if (c.size() == 3) {
set_ternary_learned(get_wlist(~c[0]), c[1], c[2], learned);
set_ternary_learned(get_wlist(~c[1]), c[0], c[2], learned);
set_ternary_learned(get_wlist(~c[2]), c[0], c[1], learned);
}
c.set_learned(learned); c.set_learned(learned);
} }
void solver::set_learned1(literal l1, literal l2, bool learned) {
for (watched& w : get_wlist(~l1)) {
if (w.is_binary_clause() && l2 == w.get_literal() && !w.is_learned()) {
w.set_learned(learned);
break;
}
}
}
void solver::set_learned(literal l1, literal l2, bool learned) {
set_learned1(l1, l2, learned);
set_learned1(l2, l1, learned);
}
/** /**
\brief Select a watch literal starting the search at the given position. \brief Select a watch literal starting the search at the given position.

View file

@ -234,6 +234,8 @@ namespace sat {
void attach_clause(clause & c, bool & reinit); void attach_clause(clause & c, bool & reinit);
void attach_clause(clause & c) { bool reinit; attach_clause(c, reinit); } void attach_clause(clause & c) { bool reinit; attach_clause(c, reinit); }
void set_learned(clause& c, bool learned); void set_learned(clause& c, bool learned);
void set_learned(literal l1, literal l2, bool learned);
void set_learned1(literal l1, literal l2, bool learned);
class scoped_disable_checkpoint { class scoped_disable_checkpoint {
solver& s; solver& s;
public: public:

View file

@ -71,29 +71,23 @@ namespace sat {
} }
void erase_ternary_watch(watch_list& wlist, literal l1, literal l2) { void erase_ternary_watch(watch_list& wlist, literal l1, literal l2) {
watched w(l1, l2);
watch_list::iterator it = wlist.begin(), end = wlist.end(); watch_list::iterator it = wlist.begin(), end = wlist.end();
watch_list::iterator it2 = it; watch_list::iterator it2 = it;
bool found = false; bool found = false;
for (; it != end; ++it) { for (; it != end; ++it) {
if (it->is_ternary_clause() && it->get_literal1() == l1 && it->get_literal2() == l2) { if (!found && w == *it) {
found = true; found = true;
continue;
} }
else {
*it2 = *it; *it2 = *it;
++it2; ++it2;
} }
}
wlist.set_end(it2); wlist.set_end(it2);
VERIFY(found); VERIFY(found);
} }
void set_ternary_learned(watch_list& wlist, literal l1, literal l2, bool learned) {
for (watched& w : wlist) {
if (w.is_ternary_clause() && w.get_literal1() == l1 && w.get_literal2() == l2) {
w.set_learned(learned);
}
}
}
void conflict_cleanup(watch_list::iterator it, watch_list::iterator it2, watch_list& wlist) { void conflict_cleanup(watch_list::iterator it, watch_list::iterator it2, watch_list& wlist) {
watch_list::iterator end = wlist.end(); watch_list::iterator end = wlist.end();
for (; it != end; ++it, ++it2) for (; it != end; ++it, ++it2)

View file

@ -53,12 +53,12 @@ namespace sat {
SASSERT(learned || is_binary_non_learned_clause()); SASSERT(learned || is_binary_non_learned_clause());
} }
watched(literal l1, literal l2, bool learned) { watched(literal l1, literal l2) {
SASSERT(l1 != l2); SASSERT(l1 != l2);
if (l1.index() > l2.index()) if (l1.index() > l2.index())
std::swap(l1, l2); std::swap(l1, l2);
m_val1 = l1.to_uint(); m_val1 = l1.to_uint();
m_val2 = static_cast<unsigned>(TERNARY) + (static_cast<unsigned>(learned) << 2) + (l2.to_uint() << 3); m_val2 = static_cast<unsigned>(TERNARY) + (l2.to_uint() << 2);
SASSERT(is_ternary_clause()); SASSERT(is_ternary_clause());
SASSERT(get_literal1() == l1); SASSERT(get_literal1() == l1);
SASSERT(get_literal2() == l2); SASSERT(get_literal2() == l2);
@ -87,16 +87,16 @@ namespace sat {
bool is_binary_clause() const { return get_kind() == BINARY; } bool is_binary_clause() const { return get_kind() == BINARY; }
literal get_literal() const { SASSERT(is_binary_clause()); return to_literal(static_cast<unsigned>(m_val1)); } literal get_literal() const { SASSERT(is_binary_clause()); return to_literal(static_cast<unsigned>(m_val1)); }
void set_literal(literal l) { SASSERT(is_binary_clause()); m_val1 = l.to_uint(); } void set_literal(literal l) { SASSERT(is_binary_clause()); m_val1 = l.to_uint(); }
bool is_learned() const { SASSERT(is_binary_clause() || is_ternary_clause()); return ((m_val2 >> 2) & 1) == 1; } bool is_learned() const { SASSERT(is_binary_clause()); return ((m_val2 >> 2) & 1) == 1; }
bool is_binary_learned_clause() const { return is_binary_clause() && is_learned(); } bool is_binary_learned_clause() const { return is_binary_clause() && is_learned(); }
bool is_binary_non_learned_clause() const { return is_binary_clause() && !is_learned(); } bool is_binary_non_learned_clause() const { return is_binary_clause() && !is_learned(); }
void set_learned(bool l) { SASSERT(is_learned() != l); if (l) m_val2 |= 4; else m_val2 &= 3; SASSERT(is_learned() == l); } void set_learned(bool l) { if (l) m_val2 |= 4u; else m_val2 &= ~4u; SASSERT(is_learned() == l); }
bool is_ternary_clause() const { return get_kind() == 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_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 >> 3); } literal get_literal2() const { SASSERT(is_ternary_clause()); return to_literal(m_val2 >> 2); }
bool is_clause() const { return get_kind() == CLAUSE; } bool is_clause() const { return get_kind() == CLAUSE; }
clause_offset get_clause_offset() const { SASSERT(is_clause()); return static_cast<clause_offset>(m_val1); } clause_offset get_clause_offset() const { SASSERT(is_clause()); return static_cast<clause_offset>(m_val1); }