3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-13 04:28:17 +00:00
Signed-off-by: Miguel Angelo Da Terra Neves <t-mineve@microsoft.com>
This commit is contained in:
Miguel Angelo Da Terra Neves 2017-12-13 11:15:03 -08:00
commit 51fc54fdd1
23 changed files with 537 additions and 356 deletions

View file

@ -4,6 +4,7 @@ z3_add_component(sat
dimacs.cpp
sat_asymm_branch.cpp
sat_bdd.cpp
sat_big.cpp
sat_clause.cpp
sat_clause_set.cpp
sat_clause_use_list.cpp

View file

@ -3158,12 +3158,9 @@ namespace sat {
if (w.is_binary_clause() && is_marked(w.get_literal())) {
++m_stats.m_num_bin_subsumes;
// IF_VERBOSE(10, verbose_stream() << c1 << " subsumes (" << lit << " " << w.get_literal() << ")\n";);
if (w.is_learned()) {
if (!w.is_learned()) {
c1.set_learned(false);
}
else if (w.is_blocked()) {
w.set_unblocked();
}
}
else {
if (it != it2) {

View file

@ -19,7 +19,7 @@ Revision History:
#include "sat/sat_asymm_branch.h"
#include "sat/sat_asymm_branch_params.hpp"
#include "sat/sat_solver.h"
#include "sat/sat_scc.h"
#include "sat/sat_big.h"
#include "util/stopwatch.h"
#include "util/trace.h"
@ -42,9 +42,13 @@ namespace sat {
asymm_branch & m_asymm_branch;
stopwatch m_watch;
unsigned m_elim_literals;
unsigned m_elim_learned_literals;
unsigned m_hidden_tautologies;
report(asymm_branch & a):
m_asymm_branch(a),
m_elim_literals(a.m_elim_literals) {
m_elim_literals(a.m_elim_literals),
m_elim_learned_literals(a.m_elim_learned_literals),
m_hidden_tautologies(a.m_hidden_tautologies) {
m_watch.start();
}
@ -53,13 +57,36 @@ namespace sat {
IF_VERBOSE(SAT_VB_LVL,
verbose_stream() << " (sat-asymm-branch :elim-literals "
<< (m_asymm_branch.m_elim_literals - m_elim_literals)
<< " :elim-learned-literals " << (m_asymm_branch.m_elim_learned_literals - m_elim_learned_literals)
<< " :hidden-tautologies " << (m_asymm_branch.m_hidden_tautologies - m_hidden_tautologies)
<< " :cost " << m_asymm_branch.m_counter
<< mem_stat()
<< " :time " << std::fixed << std::setprecision(2) << m_watch.get_seconds() << ")\n";);
}
};
void asymm_branch::process(scc* scc, clause_vector& clauses) {
bool asymm_branch::process(big* big) {
unsigned elim0 = m_elim_literals;
unsigned eliml0 = m_elim_learned_literals;
for (unsigned i = 0; i < m_asymm_branch_rounds; ++i) {
unsigned elim = m_elim_literals;
if (big) big->init_big(s, true);
process(big, s.m_clauses);
process(big, s.m_learned);
s.propagate(false);
if (s.m_inconsistent)
break;
//std::cout << "elim: " << m_elim_literals - elim << "\n";
if (m_elim_literals == elim)
break;
}
//std::cout << "elim-literals: " << m_elim_literals - elim0 << "\n";
//std::cout << "elim-learned-literals: " << m_elim_learned_literals - eliml0 << "\n";
return m_elim_literals > elim0;
}
void asymm_branch::process(big* big, clause_vector& clauses) {
int64 limit = -m_asymm_branch_limit;
std::stable_sort(clauses.begin(), clauses.end(), clause_size_lt());
m_counter -= clauses.size();
@ -83,7 +110,7 @@ namespace sat {
}
s.checkpoint();
clause & c = *(*it);
if (scc ? !process_sampled(*scc, c) : !process(c)) {
if (big ? !process_sampled(*big, c) : !process(c)) {
continue; // clause was removed
}
*it2 = *it;
@ -119,25 +146,23 @@ namespace sat {
TRACE("asymm_branch_detail", s.display(tout););
report rpt(*this);
svector<char> saved_phase(s.m_phase);
if (m_asymm_branch) {
m_counter = 0;
process(nullptr, s.m_clauses);
m_counter = -m_counter;
}
if (m_asymm_branch_sampled) {
scc scc(s, m_params);
while (true) {
unsigned elim = m_elim_literals;
scc.init_big(true);
process(&scc, s.m_clauses);
process(&scc, s.m_learned);
s.propagate(false);
if (s.m_inconsistent)
break;
if (m_elim_literals == elim)
break;
bool change = true;
unsigned counter = 0;
while (change && counter < 2) {
++counter;
change = false;
if (m_asymm_branch_sampled) {
big big;
if (process(&big)) change = true;
}
if (m_asymm_branch) {
m_counter = 0;
if (process(nullptr)) change = true;
m_counter = -m_counter;
}
}
s.m_phase = saved_phase;
m_asymm_branch_limit *= 2;
if (m_asymm_branch_limit > UINT_MAX)
@ -163,35 +188,40 @@ namespace sat {
}
struct asymm_branch::compare_left {
scc& s;
compare_left(scc& s): s(s) {}
big& s;
compare_left(big& s): s(s) {}
bool operator()(literal u, literal v) const {
return s.get_left(u) < s.get_left(v);
}
};
void asymm_branch::sort(scc& scc, clause const& c) {
void asymm_branch::sort(big& big, clause const& c) {
sort(big, c.begin(), c.end());
}
void asymm_branch::sort(big& big, literal const* begin, literal const* end) {
m_pos.reset(); m_neg.reset();
for (literal l : c) {
for (; begin != end; ++begin) {
literal l = *begin;
m_pos.push_back(l);
m_neg.push_back(~l);
}
compare_left cmp(scc);
compare_left cmp(big);
std::sort(m_pos.begin(), m_pos.end(), cmp);
std::sort(m_neg.begin(), m_neg.end(), cmp);
}
bool asymm_branch::uhte(scc& scc, clause & c) {
bool asymm_branch::uhte(big& big, clause & c) {
unsigned pindex = 0, nindex = 0;
literal lpos = m_pos[pindex++];
literal lneg = m_neg[nindex++];
while (true) {
if (scc.get_left(lneg) > scc.get_left(lpos)) {
if (big.get_left(lneg) > big.get_left(lpos)) {
if (pindex == m_pos.size()) return false;
lpos = m_pos[pindex++];
}
else if (scc.get_right(lneg) < scc.get_right(lpos) ||
(m_pos.size() == 2 && (lpos == ~lneg || scc.get_parent(lpos) == lneg))) {
else if (big.get_right(lneg) < big.get_right(lpos) ||
(m_pos.size() == 2 && (lpos == ~lneg || big.get_parent(lpos) == lneg))) {
if (nindex == m_neg.size()) return false;
lneg = m_neg[nindex++];
}
@ -202,25 +232,44 @@ namespace sat {
return false;
}
bool asymm_branch::uhle(scoped_detach& scoped_d, scc& scc, clause & c) {
int right = scc.get_right(m_pos.back());
m_to_delete.reset();
for (unsigned i = m_pos.size() - 1; i-- > 0; ) {
literal lit = m_pos[i];
int right2 = scc.get_right(lit);
if (right2 > right) {
// lit => last, so lit can be deleted
m_to_delete.push_back(lit);
void asymm_branch::minimize(big& big, literal_vector& lemma) {
big.ensure_big(s, true);
sort(big, lemma.begin(), lemma.end());
uhle(big);
if (!m_to_delete.empty()) {
unsigned j = 0;
for (unsigned i = 0; i < lemma.size(); ++i) {
literal l = lemma[i];
if (!m_to_delete.contains(l)) {
lemma[j++] = l;
}
}
else {
right = right2;
// std::cout << lemma.size() << " -> " << j << "\n";
lemma.shrink(j);
}
}
void asymm_branch::uhle(big& big) {
m_to_delete.reset();
if (m_to_delete.empty()) {
int right = big.get_right(m_pos.back());
for (unsigned i = m_pos.size() - 1; i-- > 0; ) {
literal lit = m_pos[i];
int right2 = big.get_right(lit);
if (right2 > right) {
// lit => last, so lit can be deleted
m_to_delete.push_back(lit);
}
else {
right = right2;
}
}
}
if (m_to_delete.empty()) {
right = scc.get_right(m_neg[0]);
int right = big.get_right(m_neg[0]);
for (unsigned i = 1; i < m_neg.size(); ++i) {
literal lit = m_neg[i];
int right2 = scc.get_right(lit);
int right2 = big.get_right(lit);
if (right > right2) {
// ~first => ~lit
m_to_delete.push_back(~lit);
@ -230,6 +279,10 @@ namespace sat {
}
}
}
}
bool asymm_branch::uhle(scoped_detach& scoped_d, big& big, clause & c) {
uhle(big);
if (!m_to_delete.empty()) {
unsigned j = 0;
for (unsigned i = 0; i < c.size(); ++i) {
@ -299,10 +352,13 @@ namespace sat {
return re_attach(scoped_d, c, new_sz);
}
bool asymm_branch::re_attach(scoped_detach& scoped_d, clause& c, unsigned new_sz) {
m_elim_literals += c.size() - new_sz;
switch(new_sz) {
case 0:
bool asymm_branch::re_attach(scoped_detach& scoped_d, clause& c, unsigned new_sz) {
m_elim_literals += c.size() - new_sz;
if (c.is_learned()) {
m_elim_learned_literals += c.size() - new_sz;
}
switch(new_sz) {
case 0:
s.set_conflict(justification());
return false;
case 1:
@ -314,7 +370,7 @@ namespace sat {
return false; // check_missed_propagation() may fail, since m_clauses is not in a consistent state.
case 2:
SASSERT(s.value(c[0]) == l_undef && s.value(c[1]) == l_undef);
s.mk_bin_clause(c[0], c[1], false);
s.mk_bin_clause(c[0], c[1], c.is_learned());
scoped_d.del_clause();
SASSERT(s.m_qhead == s.m_trail.size());
return false;
@ -327,16 +383,17 @@ namespace sat {
}
}
bool asymm_branch::process_sampled(scc& scc, clause & c) {
bool asymm_branch::process_sampled(big& big, clause & c) {
scoped_detach scoped_d(s, c);
sort(scc, c);
sort(big, c);
#if 0
if (uhte(scc, c)) {
if (uhte(big, c)) {
++m_hidden_tautologies;
scoped_d.del_clause();
return false;
}
#endif
return uhle(scoped_d, scc, c);
return uhle(scoped_d, big, c);
}
bool asymm_branch::process(clause & c) {
@ -368,7 +425,7 @@ namespace sat {
// clause must not be used for propagation
scoped_detach scoped_d(s, c);
unsigned new_sz = c.size();
unsigned flip_position = 2 + m_rand(c.size() - 2); // don't flip on the watch literals.
unsigned flip_position = m_rand(c.size());
bool found_conflict = flip_literal_at(c, flip_position, new_sz);
SASSERT(!s.inconsistent());
SASSERT(s.scope_lvl() == 0);
@ -386,11 +443,12 @@ namespace sat {
void asymm_branch::updt_params(params_ref const & _p) {
sat_asymm_branch_params p(_p);
m_asymm_branch = p.asymm_branch();
m_asymm_branch_delay = p.asymm_branch_delay();
m_asymm_branch = p.asymm_branch();
m_asymm_branch_rounds = p.asymm_branch_rounds();
m_asymm_branch_delay = p.asymm_branch_delay();
m_asymm_branch_sampled = p.asymm_branch_sampled();
m_asymm_branch_limit = p.asymm_branch_limit();
m_asymm_branch_all = p.asymm_branch_all();
m_asymm_branch_limit = p.asymm_branch_limit();
m_asymm_branch_all = p.asymm_branch_all();
if (m_asymm_branch_limit > UINT_MAX)
m_asymm_branch_limit = UINT_MAX;
}
@ -401,10 +459,13 @@ namespace sat {
void asymm_branch::collect_statistics(statistics & st) const {
st.update("elim literals", m_elim_literals);
st.update("hidden tautologies", m_hidden_tautologies);
}
void asymm_branch::reset_statistics() {
m_elim_literals = 0;
m_elim_learned_literals = 0;
m_hidden_tautologies = 0;
}
};

View file

@ -20,7 +20,7 @@ Revision History:
#define SAT_ASYMM_BRANCH_H_
#include "sat/sat_types.h"
#include "sat/sat_scc.h"
#include "sat/sat_big.h"
#include "util/statistics.h"
#include "util/params.h"
@ -39,6 +39,7 @@ namespace sat {
// config
bool m_asymm_branch;
unsigned m_asymm_branch_rounds;
unsigned m_asymm_branch_delay;
bool m_asymm_branch_sampled;
bool m_asymm_branch_propagate;
@ -47,25 +48,32 @@ namespace sat {
// stats
unsigned m_elim_literals;
unsigned m_elim_learned_literals;
unsigned m_hidden_tautologies;
literal_vector m_pos, m_neg; // literals (complements of literals) in clauses sorted by discovery time (m_left in scc).
literal_vector m_pos, m_neg; // literals (complements of literals) in clauses sorted by discovery time (m_left in BIG).
literal_vector m_to_delete;
struct compare_left;
void sort(scc & scc, clause const& c);
void sort(big& big, literal const* begin, literal const* end);
void sort(big & big, clause const& c);
bool uhle(scoped_detach& scoped_d, scc & scc, clause & c);
bool uhle(scoped_detach& scoped_d, big & big, clause & c);
bool uhte(scc & scc, clause & c);
void uhle(big & big);
bool uhte(big & big, clause & c);
bool re_attach(scoped_detach& scoped_d, clause& c, unsigned new_sz);
bool process(big* big);
bool process(clause & c);
bool process_sampled(scc& scc, clause & c);
bool process_sampled(big& big, clause & c);
void process(scc* scc, clause_vector & c);
void process(big* big, clause_vector & c);
bool process_all(clause & c);
@ -86,6 +94,8 @@ namespace sat {
void collect_statistics(statistics & st) const;
void reset_statistics();
void minimize(big& big, literal_vector& lemma);
void init_search() { m_calls = 0; }
inline void dec(unsigned c) { m_counter -= c; }

View file

@ -2,6 +2,7 @@ def_module_params(module_name='sat',
class_name='sat_asymm_branch_params',
export=True,
params=(('asymm_branch', BOOL, True, 'asymmetric branching'),
('asymm_branch.rounds', UINT, 10, 'maximal number of rounds to run asymmetric branch simplifications if progress is made'),
('asymm_branch.delay', UINT, 1, 'number of simplification rounds to wait until invoking asymmetric branch simplification'),
('asymm_branch.sampled', BOOL, False, 'use sampling based asymmetric branching based on binary implication graph'),
('asymm_branch.limit', UINT, 100000000, 'approx. maximum number of literals visited during asymmetric branching'),

133
src/sat/sat_big.cpp Normal file
View file

@ -0,0 +1,133 @@
/*++
Copyright (c) 2011 Microsoft Corporation
Module Name:
sat_big.cpp
Abstract:
binary implication graph structure.
Author:
Nikolaj Bjorner (nbjorner) 2017-12-13.
Revision History:
--*/
#include "sat/sat_big.h"
#include "sat/sat_solver.h"
namespace sat {
big::big() {}
void big::init_big(solver& s, bool learned) {
m_num_vars = s.num_vars();
unsigned num_lits = m_num_vars * 2;
m_dag.reset();
m_roots.reset();
m_dag.resize(num_lits, 0);
m_roots.resize(num_lits, true);
literal_vector lits;
SASSERT(num_lits == m_dag.size() && num_lits == m_roots.size());
for (unsigned l_idx = 0; l_idx < num_lits; l_idx++) {
literal u = to_literal(l_idx);
if (s.was_eliminated(u.var()))
continue;
auto& edges = m_dag[l_idx];
for (watched const& w : s.get_wlist(l_idx)) {
if (learned ? w.is_binary_clause() : w.is_binary_non_learned_clause()) {
literal v = w.get_literal();
m_roots[v.index()] = false;
edges.push_back(v);
}
}
shuffle<literal>(edges.size(), edges.c_ptr(), m_rand);
}
init_dfs_num(learned);
}
struct big::pframe {
literal m_parent;
literal m_child;
pframe(literal p, literal c):
m_parent(p), m_child(c) {}
literal child() const { return m_child; }
literal parent() const { return m_parent; }
};
void big::init_dfs_num(bool learned) {
unsigned num_lits = m_num_vars * 2;
m_left.reset();
m_right.reset();
m_root.reset();
m_parent.reset();
m_left.resize(num_lits, 0);
m_right.resize(num_lits, -1);
m_root.resize(num_lits, null_literal);
m_parent.resize(num_lits, null_literal);
for (unsigned i = 0; i < num_lits; ++i) {
m_root[i] = to_literal(i);
m_parent[i] = to_literal(i);
}
svector<pframe> todo;
// retrieve literals that have no predecessors
for (unsigned l_idx = 0; l_idx < num_lits; l_idx++) {
literal u(to_literal(l_idx));
if (m_roots[u.index()]) {
todo.push_back(pframe(null_literal, u));
}
}
shuffle<pframe>(todo.size(), todo.c_ptr(), m_rand);
int dfs_num = 0;
while (!todo.empty()) {
literal u = todo.back().child();
if (m_left[u.index()] > 0) {
// already visited
if (m_right[u.index()] < 0) {
m_right[u.index()] = ++dfs_num;
}
todo.pop_back();
}
else {
SASSERT(m_left[u.index()] == 0);
m_left[u.index()] = ++dfs_num;
literal p = todo.back().parent();
if (p != null_literal) {
m_root[u.index()] = m_root[p.index()];
m_parent[u.index()] = p;
}
for (literal v : m_dag[u.index()]) {
if (m_left[v.index()] == 0) {
todo.push_back(pframe(u, v));
}
}
}
}
for (unsigned i = 0; i < num_lits; ++i) {
if (m_right[i] < 0) {
VERIFY(m_left[i] == 0);
m_left[i] = ++dfs_num;
m_right[i] = ++dfs_num;
}
}
for (unsigned i = 0; i < num_lits; ++i) {
VERIFY(m_left[i] < m_right[i]);
}
}
void big::display(std::ostream& out) const {
unsigned idx = 0;
for (auto& next : m_dag) {
if (!next.empty()) {
out << to_literal(idx) << " : " << m_left[idx] << ":" << m_right[idx] << " -> " << next << "\n";
}
++idx;
}
}
};

55
src/sat/sat_big.h Normal file
View file

@ -0,0 +1,55 @@
/*++
Copyright (c) 2017 Microsoft Corporation
Module Name:
sat_big.h
Abstract:
binary implication graph structure.
Author:
Nikolaj Bjorner (nbjorner) 2017-12-13.
Revision History:
--*/
#ifndef SAT_BIG_H_
#define SAT_BIG_H_
#include "sat/sat_types.h"
#include "util/statistics.h"
#include "util/params.h"
namespace sat {
class solver;
class big {
random_gen m_rand;
unsigned m_num_vars;
vector<literal_vector> m_dag;
svector<bool> m_roots;
svector<int> m_left, m_right;
literal_vector m_root, m_parent;
void init_dfs_num(bool learned);
struct pframe;
public:
big();
void init_big(solver& s, bool learned);
void ensure_big(solver& s, bool learned) { if (m_left.empty()) init_big(s, learned); }
int get_left(literal l) const { return m_left[l.index()]; }
int get_right(literal l) const { return m_right[l.index()]; }
literal get_parent(literal l) const { return m_parent[l.index()]; }
literal get_root(literal l) const { return m_root[l.index()]; }
bool reaches(literal u, literal v) const { return m_left[u.index()] < m_left[v.index()] && m_right[v.index()] < m_right[u.index()]; }
bool connected(literal u, literal v) const { return reaches(u, v) || reaches(~v, ~u); }
void display(std::ostream& out) const;
};
};
#endif

View file

@ -85,9 +85,9 @@ namespace sat{
// eliminate variable
simp.m_pos_cls.reset();
simp.m_neg_cls.reset();
simp.collect_clauses(pos_l, simp.m_pos_cls, false);
simp.collect_clauses(neg_l, simp.m_neg_cls, false);
//VERIFY(!s.is_external(v));
simp.collect_clauses(pos_l, simp.m_pos_cls);
simp.collect_clauses(neg_l, simp.m_neg_cls);
VERIFY(!simp.is_external(v));
model_converter::entry & mc_entry = s.m_mc.mk(model_converter::ELIM_VAR, v);
simp.save_clauses(mc_entry, simp.m_pos_cls);
simp.save_clauses(mc_entry, simp.m_neg_cls);
@ -295,7 +295,7 @@ namespace sat{
bool elim_vars::mark_literals(literal lit) {
watch_list& wl = simp.get_wlist(lit);
for (watched const& w : wl) {
if (w.is_binary_unblocked_clause()) {
if (w.is_binary_non_learned_clause()) {
mark_var(w.get_literal().var());
}
}
@ -321,7 +321,7 @@ namespace sat{
bdd result = m.mk_true();
watch_list& wl = simp.get_wlist(~lit);
for (watched const& w : wl) {
if (w.is_binary_unblocked_clause()) {
if (w.is_binary_non_learned_clause()) {
result &= (mk_literal(lit) || mk_literal(w.get_literal()));
}
}

View file

@ -34,13 +34,11 @@ namespace sat {
// for nary clauses
static bool contains_watched(watch_list const & wlist, clause const & c, clause_offset cls_off) {
watch_list::const_iterator it = wlist.begin();
watch_list::const_iterator end = wlist.end();
for (; it != end; ++it) {
if (it->is_clause()) {
if (it->get_clause_offset() == cls_off) {
for (watched const& w : wlist) {
if (w.is_clause()) {
if (w.get_clause_offset() == cls_off) {
// the blocked literal must be in the clause.
SASSERT(c.contains(it->get_blocked_literal()));
SASSERT(c.contains(w.get_blocked_literal()));
return true;
}
}
@ -96,13 +94,13 @@ namespace sat {
}
// the first two literals must be watched.
VERIFY(contains_watched(s.get_wlist(~c[0]), c, s.get_offset(c)));
VERIFY(contains_watched(s.get_wlist(~c[0]), c, s.get_offset(c)));
VERIFY(contains_watched(s.get_wlist(~c[1]), c, s.get_offset(c)));
}
return true;
}
bool integrity_checker::check_clauses(clause * const * begin, clause * const * end) const {
bool integrity_checker::check_clauses(clause * const * begin, clause * const * end) const {
for (clause * const * it = begin; it != end; ++it) {
SASSERT(check_clause(*(*it)));
}
@ -152,49 +150,54 @@ namespace sat {
return true;
}
bool integrity_checker::check_watches(literal l) const {
return check_watches(l, s.get_wlist(~l));
}
bool integrity_checker::check_watches(literal l, watch_list const& wlist) const {
for (watched const& w : wlist) {
switch (w.get_kind()) {
case watched::BINARY:
SASSERT(!s.was_eliminated(w.get_literal().var()));
CTRACE("sat_watched_bug", !s.get_wlist(~(w.get_literal())).contains(watched(l, w.is_learned())),
tout << "l: " << l << " l2: " << w.get_literal() << "\n";
tout << "was_eliminated1: " << s.was_eliminated(l.var());
tout << " was_eliminated2: " << s.was_eliminated(w.get_literal().var());
tout << " learned: " << w.is_learned() << "\n";
sat::display_watch_list(tout, s.m_cls_allocator, wlist);
tout << "\n";
sat::display_watch_list(tout, s.m_cls_allocator, s.get_wlist(~(w.get_literal())));
tout << "\n";);
VERIFY(find_binary_watch(s.get_wlist(~(w.get_literal())), l));
break;
case watched::TERNARY:
VERIFY(!s.was_eliminated(w.get_literal1().var()));
VERIFY(!s.was_eliminated(w.get_literal2().var()));
VERIFY(w.get_literal1().index() < w.get_literal2().index());
break;
case watched::CLAUSE:
SASSERT(!s.m_cls_allocator.get_clause(w.get_clause_offset())->was_removed());
break;
default:
break;
}
}
return true;
}
bool integrity_checker::check_watches() const {
DEBUG_CODE(
vector<watch_list>::const_iterator it = s.m_watches.begin();
vector<watch_list>::const_iterator end = s.m_watches.end();
for (unsigned l_idx = 0; it != end; ++it, ++l_idx) {
literal l = ~to_literal(l_idx);
watch_list const & wlist = *it;
unsigned l_idx = 0;
for (watch_list const& wlist : s.m_watches) {
literal l = ~to_literal(l_idx++);
CTRACE("sat_bug",
s.was_eliminated(l.var()) && !wlist.empty(),
tout << "l: " << l << "\n";
s.display_watches(tout);
s.display(tout););
SASSERT(!s.was_eliminated(l.var()) || wlist.empty());
watch_list::const_iterator it2 = wlist.begin();
watch_list::const_iterator end2 = wlist.end();
for (; it2 != end2; ++it2) {
switch (it2->get_kind()) {
case watched::BINARY:
SASSERT(!s.was_eliminated(it2->get_literal().var()));
CTRACE("sat_watched_bug", !s.get_wlist(~(it2->get_literal())).contains(watched(l, it2->is_learned())),
tout << "l: " << l << " l2: " << it2->get_literal() << "\n";
tout << "was_eliminated1: " << s.was_eliminated(l.var());
tout << " was_eliminated2: " << s.was_eliminated(it2->get_literal().var());
tout << " learned: " << it2->is_learned() << "\n";
sat::display_watch_list(tout, s.m_cls_allocator, wlist);
tout << "\n";
sat::display_watch_list(tout, s.m_cls_allocator, s.get_wlist(~(it2->get_literal())));
tout << "\n";);
SASSERT(s.get_wlist(~(it2->get_literal())).contains(watched(l, it2->is_learned())));
break;
case watched::TERNARY:
SASSERT(!s.was_eliminated(it2->get_literal1().var()));
SASSERT(!s.was_eliminated(it2->get_literal2().var()));
SASSERT(it2->get_literal1().index() < it2->get_literal2().index());
break;
case watched::CLAUSE:
SASSERT(!s.m_cls_allocator.get_clause(it2->get_clause_offset())->was_removed());
break;
default:
break;
}
}
});
if (!check_watches(l, wlist))
return false;
}
return true;
}
@ -211,16 +214,12 @@ namespace sat {
bool integrity_checker::check_disjoint_clauses() const {
uint_set ids;
clause_vector::const_iterator it = s.m_clauses.begin();
clause_vector::const_iterator end = s.m_clauses.end();
for (; it != end; ++it) {
ids.insert((*it)->id());
for (clause* cp : s.m_clauses) {
ids.insert(cp->id());
}
it = s.m_learned.begin();
end = s.m_learned.end();
for (; it != end; ++it) {
if (ids.contains((*it)->id())) {
TRACE("sat", tout << "Repeated clause: " << (*it)->id() << "\n";);
for (clause* cp : s.m_learned) {
if (ids.contains(cp->id())) {
TRACE("sat", tout << "Repeated clause: " << cp->id() << "\n";);
return false;
}
}

View file

@ -21,6 +21,7 @@ Revision History:
#define SAT_INTEGRITY_CHECKER_H_
#include "sat/sat_types.h"
#include "sat/sat_watched.h"
namespace sat {
class integrity_checker {
@ -35,6 +36,8 @@ namespace sat {
bool check_assignment() const;
bool check_bool_vars() const;
bool check_watches() const;
bool check_watches(literal l, watch_list const& wlist) const;
bool check_watches(literal l) const;
bool check_reinit_stack() const;
bool check_disjoint_clauses() const;
bool operator()() const;

View file

@ -302,7 +302,7 @@ namespace sat {
literal l1 = ~to_literal(l_idx);
watch_list const & wlist = s.m_watches[l_idx];
for (watched const& w : wlist) {
if (!w.is_binary_unblocked_clause())
if (!w.is_binary_non_learned_clause())
continue;
literal l2 = w.get_literal();
if (l1.index() > l2.index())

View file

@ -2372,8 +2372,8 @@ namespace sat {
}
}
scc scc(m_s, m_s.m_params);
scc.init_big(true);
big big;
big.init_big(m_s, true);
svector<std::pair<literal, literal>> candidates;
unsigned_vector bin_size(num_lits);
@ -2390,14 +2390,14 @@ namespace sat {
if (v == get_parent(v) &&
!m_s.was_eliminated(v.var()) &&
!imp.contains(std::make_pair(u.index(), v.index())) &&
!scc.reaches(u, v)) {
!big.connected(u, v)) {
candidates.push_back(std::make_pair(u, v));
}
}
}
for (unsigned count = 0; count < 5; ++count) {
scc.init_big(true);
big.init_big(m_s, true);
unsigned k = 0;
union_find_default_ctx ufctx;
union_find<union_find_default_ctx> uf(ufctx);
@ -2405,7 +2405,7 @@ namespace sat {
for (unsigned j = 0; j < candidates.size(); ++j) {
literal u = candidates[j].first;
literal v = candidates[j].second;
if (!scc.reaches(u, v)) {
if (!big.connected(u, v)) {
if (uf.find(u.index()) != uf.find(v.index())) {
++num_bins;
uf.merge(u.index(), v.index());

View file

@ -45,6 +45,7 @@ def_module_params('sat',
('lookahead.cube.psat.var_exp', DOUBLE, 1, 'free variable exponent for PSAT cutoff'),
('lookahead.cube.psat.clause_base', DOUBLE, 2, 'clause base for PSAT cutoff'),
('lookahead.cube.psat.trigger', DOUBLE, 5, 'trigger value to create lookahead cubes for PSAT cutoff. Used when lookahead.cube.cutoff is psat'),
('lookahead_search', BOOL, False, 'use lookahead solver'),
('lookahead.preselect', BOOL, False, 'use pre-selection of subset of variables for branching'),
('lookahead_simplify', BOOL, False, 'use lookahead solver during simplification'),
('lookahead_simplify.bca', BOOL, False, 'add learned binary clauses as part of lookahead simplification'),

View file

@ -234,102 +234,10 @@ namespace sat {
return to_elim.size();
}
void scc::init_big(bool learned) {
unsigned num_lits = m_solver.num_vars() * 2;
m_dag.reset();
m_roots.reset();
m_dag.resize(num_lits, 0);
m_roots.resize(num_lits, true);
SASSERT(num_lits == m_dag.size() && num_lits == m_roots.size());
for (unsigned l_idx = 0; l_idx < num_lits; l_idx++) {
literal u = to_literal(l_idx);
if (m_solver.was_eliminated(u.var()))
continue;
auto& edges = m_dag[l_idx];
for (watched const& w : m_solver.m_watches[l_idx]) {
if (learned ? w.is_binary_clause() : w.is_binary_unblocked_clause()) {
literal v = w.get_literal();
m_roots[v.index()] = false;
edges.push_back(v);
}
}
shuffle<literal>(edges.size(), edges.c_ptr(), m_rand);
}
init_dfs_num(learned);
}
struct scc::pframe {
literal m_parent;
literal m_child;
pframe(literal p, literal c):
m_parent(p), m_child(c) {}
literal child() const { return m_child; }
literal parent() const { return m_parent; }
};
void scc::init_dfs_num(bool learned) {
unsigned num_lits = m_solver.num_vars() * 2;
m_left.reset();
m_right.reset();
m_root.reset();
m_parent.reset();
m_left.resize(num_lits, 0);
m_right.resize(num_lits, -1);
m_root.resize(num_lits, null_literal);
m_parent.resize(num_lits, null_literal);
for (unsigned i = 0; i < num_lits; ++i) {
m_root[i] = to_literal(i);
m_parent[i] = to_literal(i);
}
svector<pframe> todo;
// retrieve literals that have no predecessors
for (unsigned l_idx = 0; l_idx < num_lits; l_idx++) {
literal u(to_literal(l_idx));
if (m_roots[u.index()]) {
todo.push_back(pframe(null_literal, u));
}
}
shuffle<pframe>(todo.size(), todo.c_ptr(), m_rand);
int dfs_num = 0;
while (!todo.empty()) {
literal u = todo.back().child();
if (m_left[u.index()] > 0) {
// already visited
if (m_right[u.index()] < 0) {
m_right[u.index()] = ++dfs_num;
}
todo.pop_back();
}
else {
SASSERT(m_left[u.index()] == 0);
m_left[u.index()] = ++dfs_num;
literal p = todo.back().parent();
if (p != null_literal) {
m_root[u.index()] = m_root[p.index()];
m_parent[u.index()] = p;
}
for (literal v : m_dag[u.index()]) {
if (m_left[v.index()] == 0) {
todo.push_back(pframe(u, v));
}
}
}
}
for (unsigned i = 0; i < num_lits; ++i) {
if (m_right[i] < 0) {
VERIFY(m_left[i] == 0);
m_left[i] = ++dfs_num;
m_right[i] = ++dfs_num;
}
}
for (unsigned i = 0; i < num_lits; ++i) {
VERIFY(m_left[i] < m_right[i]);
}
}
unsigned scc::reduce_tr(bool learned) {
unsigned num_lits = m_solver.num_vars() * 2;
init_big(learned);
unsigned idx = 0;
unsigned elim = m_num_elim_bin;
for (watch_list & wlist : m_solver.m_watches) {
@ -343,6 +251,7 @@ namespace sat {
literal v = w.get_literal();
if (reaches(u, v) && u != get_parent(v)) {
++m_num_elim_bin;
m_solver.get_wlist(~v).erase(watched(~u, w.is_learned()));
}
else {
*itprev = *it;

View file

@ -19,9 +19,10 @@ Revision History:
#ifndef SAT_SCC_H_
#define SAT_SCC_H_
#include "sat/sat_types.h"
#include "util/statistics.h"
#include "util/params.h"
#include "sat/sat_types.h"
#include "sat/sat_big.h"
namespace sat {
class solver;
@ -35,24 +36,12 @@ namespace sat {
// stats
unsigned m_num_elim;
unsigned m_num_elim_bin;
random_gen m_rand;
// BIG state:
vector<literal_vector> m_dag;
svector<bool> m_roots;
svector<int> m_left, m_right;
literal_vector m_root, m_parent;
big m_big;
void reduce_tr();
unsigned reduce_tr(bool learned);
void init_dfs_num(bool learned);
struct pframe;
bool reaches_aux(literal u, literal v) const { return m_left[u.index()] < m_left[v.index()] && m_right[v.index()] < m_right[u.index()]; }
public:
scc(solver & s, params_ref const & p);
@ -67,13 +56,16 @@ namespace sat {
/*
\brief create binary implication graph and associated data-structures to check transitivity.
*/
void init_big(bool learned);
void ensure_big(bool learned) { if (m_left.empty()) init_big(learned); }
int get_left(literal l) const { return m_left[l.index()]; }
int get_right(literal l) const { return m_right[l.index()]; }
literal get_parent(literal l) const { return m_parent[l.index()]; }
literal get_root(literal l) const { return m_root[l.index()]; }
bool reaches(literal u, literal v) const { return reaches_aux(u, v) || reaches_aux(~v, ~u); }
void init_big(bool learned) { m_big.init_big(m_solver, learned); }
void ensure_big(bool learned) { m_big.ensure_big(m_solver, learned); }
int get_left(literal l) const { return m_big.get_left(l); }
int get_right(literal l) const { return m_big.get_right(l); }
literal get_parent(literal l) const { return m_big.get_parent(l); }
literal get_root(literal l) const { return m_big.get_root(l); }
bool reaches(literal u, literal v) const { return m_big.reaches(u, v); }
bool connected(literal u, literal v) const {
return m_big.connected(u, v);
}
};
};

View file

@ -22,6 +22,7 @@ Revision History:
#include "sat/sat_simplifier_params.hpp"
#include "sat/sat_solver.h"
#include "sat/sat_elim_vars.h"
#include "sat/sat_integrity_checker.h"
#include "util/stopwatch.h"
#include "util/trace.h"
@ -99,16 +100,16 @@ namespace sat {
(m_elim_blocked_clauses || m_elim_blocked_clauses_at == m_num_calls || cce_enabled());
}
bool simplifier::acce_enabled() const {
return !m_incremental_mode && !s.tracking_assumptions() && !m_learned_in_use_lists && m_num_calls >= m_bce_delay && m_acce;
return !s.m_ext && !m_incremental_mode && !s.tracking_assumptions() && !m_learned_in_use_lists && m_num_calls >= m_bce_delay && m_acce;
}
bool simplifier::cce_enabled() const {
return !m_incremental_mode && !s.tracking_assumptions() && !m_learned_in_use_lists && m_num_calls >= m_bce_delay && (m_cce || acce_enabled());
return !s.m_ext && !m_incremental_mode && !s.tracking_assumptions() && !m_learned_in_use_lists && m_num_calls >= m_bce_delay && (m_cce || acce_enabled());
}
bool simplifier::abce_enabled() const {
return !m_incremental_mode && !s.tracking_assumptions() && !m_learned_in_use_lists && m_num_calls >= m_bce_delay && m_abce;
return !s.m_ext && !m_incremental_mode && !s.tracking_assumptions() && !m_learned_in_use_lists && m_num_calls >= m_bce_delay && m_abce;
}
bool simplifier::bca_enabled() const {
return !m_incremental_mode && !s.tracking_assumptions() && m_bca && m_learned_in_use_lists && single_threaded();
return !s.m_ext && !m_incremental_mode && !s.tracking_assumptions() && m_bca && m_learned_in_use_lists && single_threaded();
}
bool simplifier::elim_vars_bdd_enabled() const {
return !m_incremental_mode && !s.tracking_assumptions() && m_elim_vars_bdd && m_num_calls >= m_elim_vars_bdd_delay && single_threaded();
@ -164,23 +165,11 @@ namespace sat {
}
inline void simplifier::remove_bin_clause_half(literal l1, literal l2, bool learned) {
SASSERT(get_wlist(~l1).contains(watched(l2, 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));
}
inline void simplifier::block_bin_clause_half(literal l1, literal l2) {
SASSERT(get_wlist(~l1).contains(watched(l2, false)));
for (watched & w : get_wlist(~l1)) {
if (w.get_literal() == l2) {
w.set_blocked();
break;
}
}
m_sub_bin_todo.erase(bin_clause(l1, l2, false));
}
void simplifier::init_visited() {
m_visited.reset();
m_visited.resize(2*s.num_vars(), false);
@ -213,6 +202,9 @@ namespace sat {
void simplifier::operator()(bool learned) {
integrity_checker si(s);
si.check_watches();
if (s.inconsistent())
return;
if (!m_subsumption && !bce_enabled() && !bca_enabled() && !elim_vars_enabled())
@ -239,6 +231,7 @@ namespace sat {
if (bce_enabled() || abce_enabled() || bca_enabled()) {
elim_blocked_clauses();
}
si.check_watches();
if (!learned) {
m_num_calls++;
@ -260,7 +253,7 @@ namespace sat {
if (s.inconsistent())
return;
if (!learned && elim_vars_enabled())
elim_vars();
elim_vars();
if (s.inconsistent())
return;
if (!m_subsumption || m_sub_counter < 0)
@ -276,12 +269,14 @@ namespace sat {
cleanup_clauses(s.m_learned, true, vars_eliminated, m_learned_in_use_lists);
cleanup_clauses(s.m_clauses, false, vars_eliminated, true);
}
si.check_watches();
CASSERT("sat_solver", s.check_invariant());
TRACE("after_simplifier", s.display(tout); tout << "model_converter:\n"; s.m_mc.display(tout););
finalize();
si.check_watches();
}
/**
@ -736,7 +731,7 @@ namespace sat {
// should not traverse wlist using iterators, since back_subsumption1 may add new binary clauses there
for (unsigned j = 0; j < wlist.size(); j++) {
watched w = wlist[j];
if (w.is_binary_unblocked_clause()) {
if (w.is_binary_non_learned_clause()) {
literal l2 = w.get_literal();
if (l.index() < l2.index()) {
m_dummy.set(l, l2, w.is_learned());
@ -744,9 +739,9 @@ namespace sat {
back_subsumption1(c);
if (w.is_learned() && !c.is_learned()) {
SASSERT(wlist[j] == w);
TRACE("mark_not_learned_bug",
TRACE("set_not_learned_bug",
tout << "marking as not learned: " << l2 << " " << wlist[j].is_learned() << "\n";);
wlist[j].mark_not_learned();
wlist[j].set_not_learned();
mark_as_not_learned_core(get_wlist(~l2), l);
}
if (s.inconsistent())
@ -763,7 +758,7 @@ namespace sat {
void simplifier::mark_as_not_learned_core(watch_list & wlist, literal l2) {
for (watched & w : wlist) {
if (w.is_binary_clause() && w.get_literal() == l2 && w.is_learned()) {
w.mark_not_learned();
w.set_not_learned();
return;
}
}
@ -983,14 +978,20 @@ namespace sat {
}
void operator()() {
integrity_checker si(s.s);
si.check_watches();
if (s.bce_enabled())
block_clauses();
si.check_watches();
if (s.abce_enabled())
cce<false>();
si.check_watches();
if (s.cce_enabled())
cce<true>();
si.check_watches();
if (s.bca_enabled())
bca();
si.check_watches();
}
void block_clauses() {
@ -1013,12 +1014,14 @@ namespace sat {
void process(literal l) {
TRACE("blocked_clause", tout << "processing: " << l << "\n";);
model_converter::entry * new_entry = 0;
if (!process_var(l.var())) {
return;
}
integrity_checker si(s.s);
//si.check_watches();
process_clauses(l);
process_binary(l);
//si.check_watches();
}
void process_binary(literal l) {
@ -1029,11 +1032,9 @@ namespace sat {
watch_list::iterator it2 = it;
watch_list::iterator end = wlist.end();
#define INC() if (!s.m_retain_blocked_clauses) { *it2 = *it; it2++; }
for (; it != end; ++it) {
if (!it->is_binary_clause() || it->is_blocked()) {
INC();
if (!it->is_binary_non_learned_clause()) {
*it2 = *it; it2++;
continue;
}
literal l2 = it->get_literal();
@ -1043,11 +1044,11 @@ namespace sat {
s.m_num_blocked_clauses++;
}
else {
INC();
*it2 = *it; it2++;
}
s.unmark_visited(l2);
}
if (!s.m_retain_blocked_clauses) wlist.set_end(it2);
wlist.set_end(it2);
}
void process_clauses(literal l) {
@ -1094,7 +1095,7 @@ namespace sat {
for (watched & w : s.get_wlist(l)) {
// when adding a blocked clause, then all non-learned clauses have to be considered for the
// resolution intersection.
bool process_bin = adding ? w.is_binary_clause() : w.is_binary_unblocked_clause();
bool process_bin = adding ? w.is_binary_clause() : w.is_binary_non_learned_clause();
if (process_bin) {
literal lit = w.get_literal();
if (s.is_marked(~lit) && lit != ~l) {
@ -1146,7 +1147,7 @@ namespace sat {
bool check_abce_tautology(literal l) {
if (!process_var(l.var())) return false;
for (watched & w : s.get_wlist(l)) {
if (w.is_binary_unblocked_clause()) {
if (w.is_binary_non_learned_clause()) {
literal lit = w.get_literal();
if (!s.is_marked(~lit) || lit == ~l) return false;
}
@ -1176,7 +1177,7 @@ namespace sat {
for (; m_ala_qhead < m_covered_clause.size(); ++m_ala_qhead) {
literal l = m_covered_clause[m_ala_qhead];
for (watched & w : s.get_wlist(~l)) {
if (w.is_binary_unblocked_clause()) {
if (w.is_binary_non_learned_clause()) {
literal lit = w.get_literal();
if (!s.is_marked(lit) && !s.is_marked(~lit)) {
m_covered_clause.push_back(~lit);
@ -1318,8 +1319,9 @@ namespace sat {
watch_list::iterator end = wlist.end();
model_converter::kind k;
for (; it != end; ++it) {
if (!it->is_binary_clause() || it->is_blocked()) {
INC();
if (!it->is_binary_non_learned_clause()) {
*it2 = *it;
it2++;
continue;
}
literal l2 = it->get_literal();
@ -1328,10 +1330,11 @@ namespace sat {
s.m_num_covered_clauses++;
}
else {
INC();
*it2 = *it;
it2++;
}
}
if (!s.m_retain_blocked_clauses) wlist.set_end(it2);
wlist.set_end(it2);
}
@ -1382,24 +1385,18 @@ namespace sat {
void prepare_block_binary(watch_list::iterator it, literal l1, literal blocked, model_converter::entry*& new_entry, model_converter::kind k) {
SASSERT(!s.is_external(blocked));
//VERIFY(!s.is_external(blocked));
if (new_entry == 0)
new_entry = &(mc.mk(k, blocked.var()));
literal l2 = it->get_literal();
TRACE("blocked_clause", tout << "new blocked clause: " << l2 << " " << l1 << "\n";);
if (s.m_retain_blocked_clauses && !it->is_learned()) {
s.block_bin_clause_half(l2, l1);
s.block_bin_clause_half(l1, l2);
}
else {
s.remove_bin_clause_half(l2, l1, it->is_learned());
}
s.remove_bin_clause_half(l2, l1, it->is_learned());
m_queue.decreased(~l2);
}
void block_binary(watch_list::iterator it, literal l, model_converter::entry *& new_entry) {
literal l2 = it->get_literal();
prepare_block_binary(it, l, l, new_entry, model_converter::BLOCK_LIT);
mc.insert(*new_entry, l, it->get_literal());
mc.insert(*new_entry, l, l2);
}
void block_covered_binary(watch_list::iterator it, literal l, literal blocked, model_converter::kind k) {
@ -1431,19 +1428,12 @@ namespace sat {
}
for (literal l2 : m_intersection) {
l2.neg();
bool found = false;
for (watched w : s.get_wlist(~l)) {
found = w.is_binary_clause() && l2 == w.get_literal();
if (found) break;
}
if (!found) {
watched* w = find_binary_watch(s.get_wlist(~l), l2);
if (!w) {
IF_VERBOSE(100, verbose_stream() << "bca " << l << " " << l2 << "\n";);
watched w1(l2, false);
w1.set_blocked();
watched w2(l, false);
w2.set_blocked();
s.get_wlist(~l).push_back(w1);
s.get_wlist(~l2).push_back(w2);
s.get_wlist(~l).push_back(watched(l2, true));
VERIFY(!find_binary_watch(s.get_wlist(~l2), l));
s.get_wlist(~l2).push_back(watched(l, true));
++s.m_num_bca;
}
}
@ -1453,7 +1443,7 @@ namespace sat {
watch_list & wlist = s.get_wlist(l);
m_counter -= wlist.size();
for (auto const& w : wlist) {
if (w.is_binary_unblocked_clause() &&
if (w.is_binary_non_learned_clause() &&
!s.is_marked(~w.get_literal()))
return false;
}
@ -1525,7 +1515,7 @@ namespace sat {
unsigned r = 0;
watch_list const & wlist = get_wlist(~l);
for (auto & w : wlist) {
if (w.is_binary_unblocked_clause())
if (w.is_binary_non_learned_clause())
r++;
}
return r;
@ -1574,10 +1564,10 @@ namespace sat {
/**
\brief Collect clauses and binary clauses containing l.
*/
void simplifier::collect_clauses(literal l, clause_wrapper_vector & r, bool include_blocked) {
void simplifier::collect_clauses(literal l, clause_wrapper_vector & r) {
clause_use_list const & cs = m_use_list.get(l);
for (auto it = cs.mk_iterator(); !it.at_end(); it.next()) {
if (!it.curr().is_blocked() || include_blocked) {
if (!it.curr().is_blocked()) {
r.push_back(clause_wrapper(it.curr()));
SASSERT(r.back().size() == it.curr().size());
}
@ -1585,7 +1575,7 @@ namespace sat {
watch_list & wlist = get_wlist(~l);
for (auto & w : wlist) {
if (include_blocked ? w.is_binary_non_learned_clause() : w.is_binary_unblocked_clause()) {
if (w.is_binary_non_learned_clause()) {
r.push_back(clause_wrapper(l, w.get_literal()));
SASSERT(r.back().size() == 2);
}
@ -1643,27 +1633,26 @@ namespace sat {
}
void simplifier::add_non_learned_binary_clause(literal l1, literal l2) {
watched* w;
watch_list & wlist1 = get_wlist(~l1);
watch_list & wlist2 = get_wlist(~l2);
bool found = false;
for (watched& w : wlist1) {
if (w.is_binary_clause() && w.get_literal() == l2) {
if (w.is_learned()) w.mark_not_learned();
found = true;
break;
}
w = find_binary_watch(wlist1, l2);
if (w) {
if (w->is_learned())
w->set_not_learned();
}
else {
wlist1.push_back(watched(l2, false));
}
if (!found) wlist1.push_back(watched(l2, false));
found = false;
for (watched& w : wlist2) {
if (w.is_binary_clause() && w.get_literal() == l1) {
if (w.is_learned()) w.mark_not_learned();
found = true;
break;
}
w = find_binary_watch(wlist2, l1);
if (w) {
if (w->is_learned())
w->set_not_learned();
}
else {
wlist2.push_back(watched(l1, false));
}
if (!found) wlist2.push_back(watched(l1, false));
}
/**
@ -1755,8 +1744,8 @@ namespace sat {
m_pos_cls.reset();
m_neg_cls.reset();
collect_clauses(pos_l, m_pos_cls, false);
collect_clauses(neg_l, m_neg_cls, false);
collect_clauses(pos_l, m_pos_cls);
collect_clauses(neg_l, m_neg_cls);
TRACE("resolution_detail", tout << "collecting number of after_clauses\n";);
unsigned before_clauses = num_pos + num_neg;

View file

@ -132,7 +132,6 @@ namespace sat {
void remove_clause(clause & c);
void remove_clause(clause & c, literal l);
void block_clause(clause & c);
void block_bin_clause_half(literal l1, literal l2);
void unblock_clause(clause & c);
void remove_bin_clause_half(literal l1, literal l2, bool learned);
@ -185,7 +184,7 @@ namespace sat {
unsigned get_num_unblocked_bin(literal l) const;
unsigned get_to_elim_cost(bool_var v) const;
void order_vars_for_elim(bool_var_vector & r);
void collect_clauses(literal l, clause_wrapper_vector & r, bool include_blocked);
void collect_clauses(literal l, clause_wrapper_vector & r);
clause_wrapper_vector m_pos_cls;
clause_wrapper_vector m_neg_cls;
literal_vector m_new_cls;

View file

@ -137,10 +137,6 @@ namespace sat {
watched w1(l2, wi.is_learned());
watched w2(l, wi.is_learned());
if (wi.is_blocked()) {
w1.set_blocked();
w2.set_blocked();
}
m_watches[(~l).index()].push_back(w1);
m_watches[(~l2).index()].push_back(w2);
}
@ -315,6 +311,19 @@ namespace sat {
}
void solver::mk_bin_clause(literal l1, literal l2, bool learned) {
watched* w0 = find_binary_watch(get_wlist(~l1), l2);
if (w0) {
if (w0->is_learned() && !learned) {
w0->set_not_learned();
}
w0 = find_binary_watch(get_wlist(~l2), l1);
}
if (w0) {
if (w0->is_learned() && !learned) {
w0->set_not_learned();
}
return;
}
if (m_config.m_drat)
m_drat.add(l1, l2, learned);
if (propagate_bin_clause(l1, l2)) {
@ -324,8 +333,8 @@ namespace sat {
m_clauses_to_reinit.push_back(clause_wrapper(l1, l2));
}
m_stats.m_mk_bin_clause++;
m_watches[(~l1).index()].push_back(watched(l2, learned));
m_watches[(~l2).index()].push_back(watched(l1, learned));
get_wlist(~l1).push_back(watched(l2, learned));
get_wlist(~l2).push_back(watched(l1, learned));
}
bool solver::propagate_bin_clause(literal l1, literal l2) {
@ -1419,6 +1428,8 @@ namespace sat {
if (m_conflicts_since_init < m_next_simplify) {
return;
}
integrity_checker si(*this);
si.check_watches();
m_simplifications++;
IF_VERBOSE(2, verbose_stream() << "(sat.simplify :simplifications " << m_simplifications << ")\n";);
@ -1430,26 +1441,26 @@ namespace sat {
m_cleaner();
CASSERT("sat_simplify_bug", check_invariant());
si.check_watches();
m_scc();
CASSERT("sat_simplify_bug", check_invariant());
si.check_watches();
m_simplifier(false);
CASSERT("sat_simplify_bug", check_invariant());
CASSERT("sat_missed_prop", check_missed_propagation());
si.check_watches();
if (!m_learned.empty()) {
m_simplifier(true);
CASSERT("sat_missed_prop", check_missed_propagation());
CASSERT("sat_simplify_bug", check_invariant());
}
if (m_config.m_lookahead_simplify) {
lookahead lh(*this);
lh.simplify();
lh.collect_statistics(m_aux_stats);
}
sort_watch_lits();
CASSERT("sat_simplify_bug", check_invariant());
@ -1575,7 +1586,7 @@ namespace sat {
literal l = ~to_literal(l_idx);
if (value_at(l, m) != l_true) {
for (watched const& w : wlist) {
if (!w.is_binary_unblocked_clause())
if (!w.is_binary_non_learned_clause())
continue;
literal l2 = w.get_literal();
if (value_at(l2, m) != l_true) {

View file

@ -169,6 +169,7 @@ namespace sat {
friend class cleaner;
friend class simplifier;
friend class scc;
friend class big;
friend class elim_eqs;
friend class asymm_branch;
friend class probing;

View file

@ -40,6 +40,38 @@ namespace sat {
return false;
}
watched* find_binary_watch(watch_list & wlist, literal l) {
for (watched& w : wlist) {
if (w.is_binary_clause() && w.get_literal() == l) return &w;
}
return nullptr;
}
watched const* find_binary_watch(watch_list const& wlist, literal l) {
for (watched const& w : wlist) {
if (w.is_binary_clause() && w.get_literal() == l) return &w;
}
return nullptr;
}
void erase_binary_watch(watch_list& wlist, literal l) {
watch_list::iterator it = wlist.begin(), end = wlist.end();
watch_list::iterator it2 = it;
bool found = false;
for (; it != end; ++it) {
if (it->is_binary_clause() && it->get_literal() == l && !found) {
found = true;
}
else {
*it2 = *it;
++it2;
}
}
wlist.set_end(it2);
VERIFY(found);
}
std::ostream& display_watch_list(std::ostream & out, clause_allocator const & ca, watch_list const & wlist) {
bool first = true;
for (watched const& w : wlist) {

View file

@ -50,7 +50,7 @@ namespace sat {
SASSERT(is_binary_clause());
SASSERT(get_literal() == l);
SASSERT(is_learned() == learned);
SASSERT(learned || is_binary_unblocked_clause());
SASSERT(learned || is_binary_non_learned_clause());
}
watched(literal l1, literal l2) {
@ -88,15 +88,12 @@ namespace sat {
void set_literal(literal l) { SASSERT(is_binary_clause()); m_val1 = l.to_uint(); }
bool is_learned() const { SASSERT(is_binary_clause()); return (m_val2 >> 2) == 1; }
bool is_binary_unblocked_clause() const { return m_val2 == 0; }
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(); }
void mark_not_learned() { SASSERT(is_learned()); m_val2 = static_cast<unsigned>(BINARY); SASSERT(!is_learned()); }
void set_blocked() { SASSERT(is_binary_clause()); SASSERT(!is_learned()); m_val2 |= (1 << 3); }
bool is_blocked() const { SASSERT(is_binary_clause()); return 0 != (m_val2 & (1 << 3)); }
void set_unblocked() { SASSERT(is_binary_clause()); SASSERT(is_blocked()); m_val2 &= ~(1u << 3u); }
void set_not_learned() { SASSERT(is_learned()); m_val2 = static_cast<unsigned>(BINARY); SASSERT(!is_learned()); }
void set_learned() { SASSERT(!is_learned()); m_val2 = static_cast<unsigned>(BINARY) + (1u << 2); SASSERT(is_learned()); }
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); }
@ -135,6 +132,8 @@ namespace sat {
typedef vector<watched> watch_list;
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);
inline void erase_ternary_watch(watch_list & wlist, literal l1, literal l2) { wlist.erase(watched(l1, l2)); }

View file

@ -180,12 +180,6 @@ public:
m_solver2->assert_expr(t, a);
}
virtual void assert_lemma(expr* t) {
m_solver1->assert_lemma(t);
if (m_solver2_initialized)
m_solver2->assert_lemma(t);
}
virtual void push() {
switch_inc_mode();
m_solver1->push();

View file

@ -104,12 +104,6 @@ public:
virtual void assert_expr_core(expr * t, expr * a) = 0;
/**
\brief Add a lemma to the assertion stack. A lemma is assumed to be a consequence of already
asserted formulas. The solver is free to ignore lemmas.
*/
virtual void assert_lemma(expr * t) {}
/**
\brief Create a backtracking point.
*/