mirror of
https://github.com/Z3Prover/z3
synced 2025-06-05 21:53:23 +00:00
updates to simplifier
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
parent
42749e7b22
commit
ee6cfb8eef
9 changed files with 365 additions and 291 deletions
|
@ -743,7 +743,7 @@ namespace sat {
|
||||||
|
|
||||||
void bdd_manager::gc() {
|
void bdd_manager::gc() {
|
||||||
m_free_nodes.reset();
|
m_free_nodes.reset();
|
||||||
IF_VERBOSE(3, verbose_stream() << "(bdd :gc " << m_nodes.size() << ")\n";);
|
IF_VERBOSE(13, verbose_stream() << "(bdd :gc " << m_nodes.size() << ")\n";);
|
||||||
svector<bool> reachable(m_nodes.size(), false);
|
svector<bool> reachable(m_nodes.size(), false);
|
||||||
for (unsigned i = m_bdd_stack.size(); i-- > 0; ) {
|
for (unsigned i = m_bdd_stack.size(); i-- > 0; ) {
|
||||||
reachable[m_bdd_stack[i]] = true;
|
reachable[m_bdd_stack[i]] = true;
|
||||||
|
|
|
@ -98,6 +98,7 @@ namespace sat {
|
||||||
// apply substitution
|
// apply substitution
|
||||||
for (i = 0; i < sz; i++) {
|
for (i = 0; i < sz; i++) {
|
||||||
c[i] = norm(roots, c[i]);
|
c[i] = norm(roots, c[i]);
|
||||||
|
VERIFY(c[i] == norm(roots, c[i]));
|
||||||
VERIFY(!m_solver.was_eliminated(c[i].var()));
|
VERIFY(!m_solver.was_eliminated(c[i].var()));
|
||||||
}
|
}
|
||||||
std::sort(c.begin(), c.end());
|
std::sort(c.begin(), c.end());
|
||||||
|
|
|
@ -204,7 +204,7 @@ namespace sat {
|
||||||
|
|
||||||
|
|
||||||
void lookahead::pre_select() {
|
void lookahead::pre_select() {
|
||||||
IF_VERBOSE(10, verbose_stream() << "freevars: " << m_freevars.size() << "\n";);
|
IF_VERBOSE(10, verbose_stream() << "(sat-lookahead :freevars " << m_freevars.size() << ")\n";);
|
||||||
m_lookahead.reset();
|
m_lookahead.reset();
|
||||||
for (bool_var x : m_freevars) { // tree lookahead leaves literals fixed in lower truth levels
|
for (bool_var x : m_freevars) { // tree lookahead leaves literals fixed in lower truth levels
|
||||||
literal l(x, false);
|
literal l(x, false);
|
||||||
|
@ -1808,7 +1808,7 @@ namespace sat {
|
||||||
scoped_level _sl(*this, dl_truth);
|
scoped_level _sl(*this, dl_truth);
|
||||||
SASSERT(get_level(m_trail.back()) == dl_truth);
|
SASSERT(get_level(m_trail.back()) == dl_truth);
|
||||||
SASSERT(is_fixed(l));
|
SASSERT(is_fixed(l));
|
||||||
IF_VERBOSE(2, verbose_stream() << "double: " << l << " depth: " << m_trail_lim.size() << "\n";);
|
IF_VERBOSE(2, verbose_stream() << "(sat-lookahead :double " << l << " :depth " << m_trail_lim.size() << ")\n";);
|
||||||
lookahead_backtrack();
|
lookahead_backtrack();
|
||||||
assign(l);
|
assign(l);
|
||||||
propagate();
|
propagate();
|
||||||
|
@ -2211,71 +2211,65 @@ namespace sat {
|
||||||
m_s.propagate_core(false);
|
m_s.propagate_core(false);
|
||||||
m_s.m_simplifier(false);
|
m_s.m_simplifier(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (select(0)) {
|
||||||
|
get_scc();
|
||||||
|
if (!inconsistent()) {
|
||||||
|
normalize_parents();
|
||||||
|
literal_vector roots;
|
||||||
|
bool_var_vector to_elim;
|
||||||
|
for (unsigned i = 0; i < m_num_vars; ++i) {
|
||||||
|
roots.push_back(literal(i, false));
|
||||||
|
}
|
||||||
|
for (auto const& c : m_candidates) {
|
||||||
|
bool_var v = c.m_var;
|
||||||
|
literal q(v, false);
|
||||||
|
literal p = get_parent(q);
|
||||||
|
if (p != null_literal && p.var() != v && !m_s.is_external(v) &&
|
||||||
|
!m_s.was_eliminated(v) && !m_s.was_eliminated(p.var())) {
|
||||||
|
to_elim.push_back(v);
|
||||||
|
roots[v] = p;
|
||||||
|
VERIFY(get_parent(p) == p);
|
||||||
|
VERIFY(get_parent(~p) == ~p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
IF_VERBOSE(1, verbose_stream() << "(sat-lookahead :equivalences " << to_elim.size() << ")\n";);
|
||||||
|
elim_eqs elim(m_s);
|
||||||
|
elim(roots, to_elim);
|
||||||
|
}
|
||||||
|
}
|
||||||
m_lookahead.reset();
|
m_lookahead.reset();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
void lookahead::normalize_parents() {
|
||||||
// there can be two sets of equivalence classes.
|
literal_vector roots;
|
||||||
// example:
|
for (unsigned i = 0; i < m_num_vars; ++i) {
|
||||||
// a -> !b
|
literal lit(i, false);
|
||||||
// b -> !a
|
roots.push_back(lit);
|
||||||
// c -> !a
|
roots.push_back(~lit);
|
||||||
// we pick as root the Boolean variable with the largest value.
|
SASSERT(roots[lit.index()] == lit);
|
||||||
//
|
|
||||||
literal lookahead::get_root(bool_var v) {
|
|
||||||
literal lit(v, false);
|
|
||||||
literal r1 = get_parent(lit);
|
|
||||||
literal r2 = get_parent(literal(r1.var(), false));
|
|
||||||
CTRACE("sat", r1 != get_parent(literal(r2.var(), false)),
|
|
||||||
tout << r1 << " " << r2 << "\n";);
|
|
||||||
SASSERT(r1.var() == get_parent(literal(r2.var(), false)).var());
|
|
||||||
if (r1.var() >= r2.var()) {
|
|
||||||
return r1;
|
|
||||||
}
|
}
|
||||||
else {
|
for (auto const& c : m_candidates) {
|
||||||
return r1.sign() ? ~r2 : r2;
|
bool_var v = c.m_var;
|
||||||
}
|
literal p(v, false);
|
||||||
}
|
literal q = get_parent(p);
|
||||||
|
literal r = ~get_parent(~p);
|
||||||
/**
|
if (q != r) {
|
||||||
\brief extract equivalence classes of variables and simplify clauses using these.
|
if (q.var() < r.var()) {
|
||||||
*/
|
roots[q.index()] = r;
|
||||||
void lookahead::scc() {
|
}
|
||||||
SASSERT(m_prefix == 0);
|
else {
|
||||||
SASSERT(m_watches.empty());
|
roots[r.index()] = q;
|
||||||
m_search_mode = lookahead_mode::searching;
|
|
||||||
scoped_level _sl(*this, c_fixed_truth);
|
|
||||||
init();
|
|
||||||
if (inconsistent()) return;
|
|
||||||
inc_istamp();
|
|
||||||
m_lookahead.reset();
|
|
||||||
if (select(0)) {
|
|
||||||
// extract equivalences
|
|
||||||
get_scc();
|
|
||||||
if (inconsistent()) return;
|
|
||||||
literal_vector roots;
|
|
||||||
bool_var_vector to_elim;
|
|
||||||
for (unsigned i = 0; i < m_num_vars; ++i) {
|
|
||||||
roots.push_back(literal(i, false));
|
|
||||||
}
|
|
||||||
for (unsigned i = 0; i < m_candidates.size(); ++i) {
|
|
||||||
bool_var v = m_candidates[i].m_var;
|
|
||||||
literal p = get_root(v);
|
|
||||||
if (p != null_literal && p.var() != v && !m_s.is_external(v) &&
|
|
||||||
!m_s.was_eliminated(v) && !m_s.was_eliminated(p.var())) {
|
|
||||||
to_elim.push_back(v);
|
|
||||||
roots[v] = p;
|
|
||||||
SASSERT(get_parent(p) == p);
|
|
||||||
set_parent(~p, ~p);
|
|
||||||
SASSERT(get_parent(~p) == ~p);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
IF_VERBOSE(1, verbose_stream() << "(sat-lookahead :equivalences " << to_elim.size() << ")\n";);
|
|
||||||
elim_eqs elim(m_s);
|
|
||||||
elim(roots, to_elim);
|
|
||||||
}
|
}
|
||||||
m_lookahead.reset();
|
for (auto const& c : m_candidates) {
|
||||||
|
literal p(c.m_var, false);
|
||||||
|
literal q = roots[get_parent(p).index()];
|
||||||
|
set_parent(p, q);
|
||||||
|
set_parent(~p, ~q);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::ostream& lookahead::display_summary(std::ostream& out) const {
|
std::ostream& lookahead::display_summary(std::ostream& out) const {
|
||||||
|
|
|
@ -529,6 +529,8 @@ namespace sat {
|
||||||
|
|
||||||
void init_config();
|
void init_config();
|
||||||
|
|
||||||
|
void normalize_parents();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
lookahead(solver& s) :
|
lookahead(solver& s) :
|
||||||
m_s(s),
|
m_s(s),
|
||||||
|
@ -573,21 +575,6 @@ namespace sat {
|
||||||
*/
|
*/
|
||||||
void simplify();
|
void simplify();
|
||||||
|
|
||||||
//
|
|
||||||
// there can be two sets of equivalence classes.
|
|
||||||
// example:
|
|
||||||
// a -> !b
|
|
||||||
// b -> !a
|
|
||||||
// c -> !a
|
|
||||||
// we pick as root the Boolean variable with the largest value.
|
|
||||||
//
|
|
||||||
literal get_root(bool_var v);
|
|
||||||
|
|
||||||
/**
|
|
||||||
\brief extract equivalence classes of variables and simplify clauses using these.
|
|
||||||
*/
|
|
||||||
void scc();
|
|
||||||
|
|
||||||
std::ostream& display(std::ostream& out) const;
|
std::ostream& display(std::ostream& out) const;
|
||||||
std::ostream& display_summary(std::ostream& out) const;
|
std::ostream& display_summary(std::ostream& out) const;
|
||||||
model const& get_model();
|
model const& get_model();
|
||||||
|
|
|
@ -50,6 +50,7 @@ namespace sat {
|
||||||
}
|
}
|
||||||
if (!sat) {
|
if (!sat) {
|
||||||
m[lit.var()] = lit.sign() ? l_false : l_true;
|
m[lit.var()] = lit.sign() ? l_false : l_true;
|
||||||
|
// if (lit.var() == 258007) std::cout << "flip " << lit << " " << m[lit.var()] << " @ " << i << " of " << c << " from overall size " << sz << "\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -69,10 +70,10 @@ namespace sat {
|
||||||
for (literal l : it->m_clauses) {
|
for (literal l : it->m_clauses) {
|
||||||
if (l == null_literal) {
|
if (l == null_literal) {
|
||||||
// end of clause
|
// end of clause
|
||||||
if (!sat) {
|
elim_stack* s = it->m_elim_stack[index];
|
||||||
|
if (!sat) {
|
||||||
m[it->var()] = var_sign ? l_false : l_true;
|
m[it->var()] = var_sign ? l_false : l_true;
|
||||||
}
|
}
|
||||||
elim_stack* s = it->m_elim_stack[index];
|
|
||||||
if (s) {
|
if (s) {
|
||||||
process_stack(m, clause, s->stack());
|
process_stack(m, clause, s->stack());
|
||||||
}
|
}
|
||||||
|
@ -94,6 +95,7 @@ namespace sat {
|
||||||
else if (!sat && v != it->var() && m[v] == l_undef) {
|
else if (!sat && v != it->var() && m[v] == l_undef) {
|
||||||
// clause can be satisfied by assigning v.
|
// clause can be satisfied by assigning v.
|
||||||
m[v] = sign ? l_false : l_true;
|
m[v] = sign ? l_false : l_true;
|
||||||
|
// if (v == 258007) std::cout << "set undef " << v << " to " << m[v] << " in " << clause << "\n";
|
||||||
sat = true;
|
sat = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -121,12 +121,13 @@ namespace sat {
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void simplifier::block_clause(clause & c) {
|
inline void simplifier::block_clause(clause & c) {
|
||||||
#if 1
|
if (m_retain_blocked_clauses) {
|
||||||
remove_clause(c);
|
c.block();
|
||||||
#else
|
m_use_list.block(c);
|
||||||
c.block();
|
}
|
||||||
m_use_list.block(c);
|
else {
|
||||||
#endif
|
remove_clause(c);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void simplifier::unblock_clause(clause & c) {
|
inline void simplifier::unblock_clause(clause & c) {
|
||||||
|
@ -135,9 +136,21 @@ namespace sat {
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void simplifier::remove_bin_clause_half(literal l1, literal l2, bool learned) {
|
inline void simplifier::remove_bin_clause_half(literal l1, literal l2, bool learned) {
|
||||||
SASSERT(s.get_wlist(~l1).contains(watched(l2, learned)));
|
SASSERT(get_wlist(~l1).contains(watched(l2, learned)));
|
||||||
s.get_wlist(~l1).erase(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(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() {
|
void simplifier::init_visited() {
|
||||||
|
@ -173,7 +186,7 @@ namespace sat {
|
||||||
void simplifier::operator()(bool learned) {
|
void simplifier::operator()(bool learned) {
|
||||||
if (s.inconsistent())
|
if (s.inconsistent())
|
||||||
return;
|
return;
|
||||||
if (!m_subsumption && !m_elim_blocked_clauses && !m_resolution)
|
if (!m_subsumption && !bce_enabled() && !bca_enabled() && !elim_vars_enabled())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// solver::scoped_disable_checkpoint _scoped_disable_checkpoint(s);
|
// solver::scoped_disable_checkpoint _scoped_disable_checkpoint(s);
|
||||||
|
@ -195,7 +208,7 @@ namespace sat {
|
||||||
}
|
}
|
||||||
register_clauses(s.m_clauses);
|
register_clauses(s.m_clauses);
|
||||||
|
|
||||||
if (!learned && (m_elim_blocked_clauses || m_elim_blocked_clauses_at == m_num_calls))
|
if (!learned && (bce_enabled() || bca_enabled()))
|
||||||
elim_blocked_clauses();
|
elim_blocked_clauses();
|
||||||
|
|
||||||
if (!learned)
|
if (!learned)
|
||||||
|
@ -205,8 +218,6 @@ namespace sat {
|
||||||
m_elim_counter = m_res_limit;
|
m_elim_counter = m_res_limit;
|
||||||
m_old_num_elim_vars = m_num_elim_vars;
|
m_old_num_elim_vars = m_num_elim_vars;
|
||||||
|
|
||||||
// scoped_finalize _scoped_finalize(*this);
|
|
||||||
|
|
||||||
for (bool_var v = 0; v < s.num_vars(); ++v) {
|
for (bool_var v = 0; v < s.num_vars(); ++v) {
|
||||||
if (!s.m_eliminated[v] && !is_external(v)) {
|
if (!s.m_eliminated[v] && !is_external(v)) {
|
||||||
insert_elim_todo(v);
|
insert_elim_todo(v);
|
||||||
|
@ -218,7 +229,7 @@ namespace sat {
|
||||||
subsume();
|
subsume();
|
||||||
if (s.inconsistent())
|
if (s.inconsistent())
|
||||||
return;
|
return;
|
||||||
if (!learned && m_resolution && s.m_config.m_num_threads == 1)
|
if (!learned && elim_vars_enabled() && s.m_config.m_num_threads == 1)
|
||||||
elim_vars();
|
elim_vars();
|
||||||
if (s.inconsistent())
|
if (s.inconsistent())
|
||||||
return;
|
return;
|
||||||
|
@ -743,11 +754,9 @@ namespace sat {
|
||||||
}
|
}
|
||||||
|
|
||||||
void simplifier::mark_as_not_learned_core(watch_list & wlist, literal l2) {
|
void simplifier::mark_as_not_learned_core(watch_list & wlist, literal l2) {
|
||||||
watch_list::iterator it = wlist.begin();
|
for (watched & w : wlist) {
|
||||||
watch_list::iterator end = wlist.end();
|
if (w.is_binary_clause() && w.get_literal() == l2 && w.is_learned()) {
|
||||||
for (; it != end; ++it) {
|
w.mark_not_learned();
|
||||||
if (it->is_binary_clause() && it->get_literal() == l2 && it->is_learned()) {
|
|
||||||
it->mark_not_learned();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -774,34 +783,31 @@ namespace sat {
|
||||||
\brief Eliminate duplicated binary clauses.
|
\brief Eliminate duplicated binary clauses.
|
||||||
*/
|
*/
|
||||||
void simplifier::elim_dup_bins() {
|
void simplifier::elim_dup_bins() {
|
||||||
vector<watch_list>::iterator it = s.m_watches.begin();
|
|
||||||
vector<watch_list>::iterator end = s.m_watches.end();
|
|
||||||
#ifdef _TRACE
|
#ifdef _TRACE
|
||||||
unsigned l_idx = 0;
|
unsigned l_idx = 0;
|
||||||
#endif
|
#endif
|
||||||
unsigned elim = 0;
|
unsigned elim = 0;
|
||||||
for (; it != end; ++it) {
|
for (watch_list & wlist : s.m_watches) {
|
||||||
checkpoint();
|
checkpoint();
|
||||||
watch_list & wlist = *it;
|
|
||||||
std::stable_sort(wlist.begin(), wlist.end(), bin_lt());
|
std::stable_sort(wlist.begin(), wlist.end(), bin_lt());
|
||||||
literal last_lit = null_literal;
|
literal last_lit = null_literal;
|
||||||
watch_list::iterator it2 = wlist.begin();
|
watch_list::iterator it = wlist.begin();
|
||||||
watch_list::iterator itprev = it2;
|
watch_list::iterator itprev = it;
|
||||||
watch_list::iterator end2 = wlist.end();
|
watch_list::iterator end = wlist.end();
|
||||||
for (; it2 != end2; ++it2) {
|
for (; it != end; ++it) {
|
||||||
if (!it2->is_binary_clause()) {
|
if (!it->is_binary_clause()) {
|
||||||
*itprev = *it2;
|
*itprev = *it;
|
||||||
itprev++;
|
itprev++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (it2->get_literal() == last_lit) {
|
if (it->get_literal() == last_lit) {
|
||||||
TRACE("subsumption", tout << "eliminating: " << ~to_literal(l_idx)
|
TRACE("subsumption", tout << "eliminating: " << ~to_literal(l_idx)
|
||||||
<< " " << it2->get_literal() << "\n";);
|
<< " " << it->get_literal() << "\n";);
|
||||||
elim++;
|
elim++;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
last_lit = it2->get_literal();
|
last_lit = it->get_literal();
|
||||||
*itprev = *it2;
|
*itprev = *it;
|
||||||
itprev++;
|
itprev++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -944,6 +950,11 @@ namespace sat {
|
||||||
queue m_queue;
|
queue m_queue;
|
||||||
clause_vector m_to_remove;
|
clause_vector m_to_remove;
|
||||||
|
|
||||||
|
literal_vector m_covered_clause;
|
||||||
|
literal_vector m_intersection;
|
||||||
|
sat::model_converter::elim_stackv m_elim_stack;
|
||||||
|
unsigned m_ala_qhead;
|
||||||
|
|
||||||
blocked_clause_elim(simplifier & _s, unsigned limit, model_converter & _mc, use_list & l,
|
blocked_clause_elim(simplifier & _s, unsigned limit, model_converter & _mc, use_list & l,
|
||||||
vector<watch_list> & wlist):
|
vector<watch_list> & wlist):
|
||||||
s(_s),
|
s(_s),
|
||||||
|
@ -960,7 +971,25 @@ namespace sat {
|
||||||
return !s.s.is_assumption(v) && !s.was_eliminated(v) && !s.is_external(v);
|
return !s.s.is_assumption(v) && !s.was_eliminated(v) && !s.is_external(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
void insert_queue(unsigned num_vars) {
|
void operator()() {
|
||||||
|
if (s.bce_enabled())
|
||||||
|
block_clauses();
|
||||||
|
if (s.m_cce)
|
||||||
|
cce();
|
||||||
|
if (s.m_bca)
|
||||||
|
bca();
|
||||||
|
}
|
||||||
|
|
||||||
|
void block_clauses() {
|
||||||
|
insert_queue();
|
||||||
|
while (!m_queue.empty() && m_counter >= 0) {
|
||||||
|
s.checkpoint();
|
||||||
|
process(m_queue.next());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void insert_queue() {
|
||||||
|
unsigned num_vars = s.s.num_vars();
|
||||||
for (bool_var v = 0; v < num_vars; v++) {
|
for (bool_var v = 0; v < num_vars; v++) {
|
||||||
if (process_var(v)) {
|
if (process_var(v)) {
|
||||||
insert(literal(v, false));
|
insert(literal(v, false));
|
||||||
|
@ -969,96 +998,82 @@ namespace sat {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void block_clauses(unsigned num_vars) {
|
|
||||||
insert_queue(num_vars);
|
|
||||||
while (!m_queue.empty()) {
|
|
||||||
s.checkpoint();
|
|
||||||
if (m_counter < 0)
|
|
||||||
return;
|
|
||||||
literal l = m_queue.next();
|
|
||||||
process(l);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void operator()(unsigned num_vars) {
|
|
||||||
block_clauses(num_vars);
|
|
||||||
if (s.m_elim_covered_clauses)
|
|
||||||
cce();
|
|
||||||
}
|
|
||||||
|
|
||||||
void process(literal l) {
|
void process(literal l) {
|
||||||
TRACE("blocked_clause", tout << "processing: " << l << "\n";);
|
TRACE("blocked_clause", tout << "processing: " << l << "\n";);
|
||||||
model_converter::entry * new_entry = 0;
|
model_converter::entry * new_entry = 0;
|
||||||
if (!process_var(l.var())) {
|
if (!process_var(l.var())) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
process_clauses(l);
|
||||||
|
process_binary(l);
|
||||||
|
}
|
||||||
|
|
||||||
literal blocked = null_literal;
|
void process_binary(literal l) {
|
||||||
m_to_remove.reset();
|
model_converter::entry* new_entry = 0;
|
||||||
{
|
watch_list & wlist = s.get_wlist(~l);
|
||||||
clause_use_list & occs = s.m_use_list.get(l);
|
m_counter -= wlist.size();
|
||||||
clause_use_list::iterator it = occs.mk_iterator();
|
watch_list::iterator it = wlist.begin();
|
||||||
while (!it.at_end()) {
|
watch_list::iterator it2 = it;
|
||||||
clause & c = it.curr();
|
watch_list::iterator end = wlist.end();
|
||||||
if (c.is_blocked()) continue;
|
|
||||||
m_counter -= c.size();
|
#define INC() if (!s.m_retain_blocked_clauses) { *it2 = *it; it2++; }
|
||||||
SASSERT(c.contains(l));
|
|
||||||
s.mark_all_but(c, l);
|
for (; it != end; ++it) {
|
||||||
if (all_tautology(l)) {
|
if (!it->is_binary_clause() || it->is_blocked()) {
|
||||||
block_clause(c, l, new_entry);
|
INC();
|
||||||
s.m_num_blocked_clauses++;
|
continue;
|
||||||
}
|
|
||||||
s.unmark_all(c);
|
|
||||||
it.next();
|
|
||||||
}
|
}
|
||||||
|
literal l2 = it->get_literal();
|
||||||
|
s.mark_visited(l2);
|
||||||
|
if (all_tautology(l)) {
|
||||||
|
block_binary(it, l, new_entry);
|
||||||
|
s.m_num_blocked_clauses++;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
INC();
|
||||||
|
}
|
||||||
|
s.unmark_visited(l2);
|
||||||
|
}
|
||||||
|
if (!s.m_retain_blocked_clauses) wlist.set_end(it2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void process_clauses(literal l) {
|
||||||
|
model_converter::entry* new_entry = 0;
|
||||||
|
m_to_remove.reset();
|
||||||
|
clause_use_list & occs = s.m_use_list.get(l);
|
||||||
|
clause_use_list::iterator it = occs.mk_iterator();
|
||||||
|
while (!it.at_end()) {
|
||||||
|
clause & c = it.curr();
|
||||||
|
if (c.is_blocked()) continue;
|
||||||
|
m_counter -= c.size();
|
||||||
|
SASSERT(c.contains(l));
|
||||||
|
s.mark_all_but(c, l);
|
||||||
|
if (all_tautology(l)) {
|
||||||
|
block_clause(c, l, new_entry);
|
||||||
|
s.m_num_blocked_clauses++;
|
||||||
|
}
|
||||||
|
s.unmark_all(c);
|
||||||
|
it.next();
|
||||||
}
|
}
|
||||||
for (clause* c : m_to_remove)
|
for (clause* c : m_to_remove)
|
||||||
s.block_clause(*c);
|
s.block_clause(*c);
|
||||||
|
|
||||||
{
|
|
||||||
watch_list & wlist = s.get_wlist(~l);
|
|
||||||
m_counter -= wlist.size();
|
|
||||||
watch_list::iterator it = wlist.begin();
|
|
||||||
watch_list::iterator it2 = it;
|
|
||||||
watch_list::iterator end = wlist.end();
|
|
||||||
for (; it != end; ++it) {
|
|
||||||
if (!it->is_binary_clause() || it->is_blocked()) {
|
|
||||||
*it2 = *it;
|
|
||||||
it2++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
literal l2 = it->get_literal();
|
|
||||||
s.mark_visited(l2);
|
|
||||||
if (all_tautology(l)) {
|
|
||||||
block_binary(it, l, new_entry);
|
|
||||||
s.m_num_blocked_clauses++;
|
|
||||||
}
|
|
||||||
else if (s.m_elim_covered_clauses && cce(l, l2, blocked)) {
|
|
||||||
block_covered_binary(it, l, blocked);
|
|
||||||
s.m_num_covered_clauses++;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
*it2 = *it;
|
|
||||||
it2++;
|
|
||||||
}
|
|
||||||
s.unmark_visited(l2);
|
|
||||||
}
|
|
||||||
wlist.set_end(it2);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// 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.
|
||||||
//
|
//
|
||||||
bool ri(literal l, literal_vector& inter) {
|
bool resolution_intersection(literal l, literal_vector& inter, bool adding) {
|
||||||
if (!process_var(l.var())) return false;
|
if (!process_var(l.var())) return false;
|
||||||
bool first = true;
|
bool first = true;
|
||||||
for (watched & w : s.get_wlist(l)) {
|
for (watched & w : s.get_wlist(l)) {
|
||||||
if (w.is_binary_unblocked_clause()) {
|
// 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_learned()) : w.is_binary_unblocked_clause();
|
||||||
|
if (process_bin) {
|
||||||
literal lit = w.get_literal();
|
literal lit = w.get_literal();
|
||||||
if (s.is_marked(~lit) && lit != ~l) continue;
|
if (s.is_marked(~lit) && lit != ~l) continue;
|
||||||
if (!first) {
|
if (!first || s.is_marked(lit)) {
|
||||||
inter.reset();
|
inter.reset();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -1081,9 +1096,10 @@ namespace sat {
|
||||||
if (!tautology) {
|
if (!tautology) {
|
||||||
if (first) {
|
if (first) {
|
||||||
for (literal lit : c) {
|
for (literal lit : c) {
|
||||||
if (lit != ~l) inter.push_back(lit);
|
if (lit != ~l && !s.is_marked(lit)) inter.push_back(lit);
|
||||||
}
|
}
|
||||||
first = false;
|
first = false;
|
||||||
|
if (inter.empty()) return false;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
unsigned j = 0;
|
unsigned j = 0;
|
||||||
|
@ -1099,11 +1115,6 @@ namespace sat {
|
||||||
return first;
|
return first;
|
||||||
}
|
}
|
||||||
|
|
||||||
literal_vector m_covered_clause;
|
|
||||||
literal_vector m_intersection;
|
|
||||||
sat::model_converter::elim_stackv m_elim_stack;
|
|
||||||
unsigned m_ala_qhead;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* C \/ l l \/ lit
|
* C \/ l l \/ lit
|
||||||
* -------------------
|
* -------------------
|
||||||
|
@ -1113,10 +1124,9 @@ namespace sat {
|
||||||
for (; m_ala_qhead < m_covered_clause.size(); ++m_ala_qhead) {
|
for (; m_ala_qhead < m_covered_clause.size(); ++m_ala_qhead) {
|
||||||
literal l = m_covered_clause[m_ala_qhead];
|
literal l = m_covered_clause[m_ala_qhead];
|
||||||
for (watched & w : s.get_wlist(~l)) {
|
for (watched & w : s.get_wlist(~l)) {
|
||||||
if (w.is_binary_clause()) {
|
if (w.is_binary_unblocked_clause()) {
|
||||||
literal lit = w.get_literal();
|
literal lit = w.get_literal();
|
||||||
if (!s.is_marked(lit) && !s.is_marked(~lit)) {
|
if (!s.is_marked(lit) && !s.is_marked(~lit)) {
|
||||||
//std::cout << "ALA " << ~lit << "\n";
|
|
||||||
m_covered_clause.push_back(~lit);
|
m_covered_clause.push_back(~lit);
|
||||||
s.mark_visited(~lit);
|
s.mark_visited(~lit);
|
||||||
}
|
}
|
||||||
|
@ -1136,7 +1146,7 @@ namespace sat {
|
||||||
bool add_cla(literal& blocked) {
|
bool add_cla(literal& blocked) {
|
||||||
for (unsigned i = 0; i < m_covered_clause.size(); ++i) {
|
for (unsigned i = 0; i < m_covered_clause.size(); ++i) {
|
||||||
m_intersection.reset();
|
m_intersection.reset();
|
||||||
if (ri(m_covered_clause[i], m_intersection)) {
|
if (resolution_intersection(m_covered_clause[i], m_intersection, false)) {
|
||||||
blocked = m_covered_clause[i];
|
blocked = m_covered_clause[i];
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1166,18 +1176,14 @@ 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 1
|
if (s.m_acce && !is_tautology) {
|
||||||
break;
|
sz = m_covered_clause.size();
|
||||||
#else
|
add_ala();
|
||||||
// check for soundness?
|
}
|
||||||
if (is_tautology) break;
|
|
||||||
sz = m_covered_clause.size();
|
|
||||||
add_ala();
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
while (m_covered_clause.size() > sz);
|
while (m_covered_clause.size() > sz && !is_tautology);
|
||||||
for (literal l : m_covered_clause) s.unmark_visited(l);
|
for (literal l : m_covered_clause) s.unmark_visited(l);
|
||||||
if (is_tautology) std::cout << "taut: " << num_iterations << " " << m_covered_clause.size() << " " << m_elim_stack.size() << "\n";
|
// if (is_tautology) std::cout << "taut: " << num_iterations << " " << m_covered_clause.size() << " " << m_elim_stack.size() << "\n";
|
||||||
return is_tautology;
|
return is_tautology;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1196,8 +1202,47 @@ namespace sat {
|
||||||
m_covered_clause.push_back(l2);
|
m_covered_clause.push_back(l2);
|
||||||
return cla(blocked);
|
return cla(blocked);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cce() {
|
void cce() {
|
||||||
|
cce_clauses();
|
||||||
|
cce_binary();
|
||||||
|
}
|
||||||
|
|
||||||
|
void cce_binary() {
|
||||||
|
insert_queue();
|
||||||
|
while (!m_queue.empty() && m_counter >= 0) {
|
||||||
|
s.checkpoint();
|
||||||
|
process_cce_binary(m_queue.next());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void process_cce_binary(literal l) {
|
||||||
|
literal blocked = null_literal;
|
||||||
|
watch_list & wlist = s.get_wlist(~l);
|
||||||
|
m_counter -= wlist.size();
|
||||||
|
watch_list::iterator it = wlist.begin();
|
||||||
|
watch_list::iterator it2 = it;
|
||||||
|
watch_list::iterator end = wlist.end();
|
||||||
|
|
||||||
|
for (; it != end; ++it) {
|
||||||
|
if (!it->is_binary_clause() || it->is_blocked()) {
|
||||||
|
INC();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
literal l2 = it->get_literal();
|
||||||
|
if (cce(l, l2, blocked)) {
|
||||||
|
block_covered_binary(it, l, blocked);
|
||||||
|
s.m_num_covered_clauses++;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
INC();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!s.m_retain_blocked_clauses) wlist.set_end(it2);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void cce_clauses() {
|
||||||
m_to_remove.reset();
|
m_to_remove.reset();
|
||||||
literal blocked;
|
literal blocked;
|
||||||
for (clause* cp : s.s.m_clauses) {
|
for (clause* cp : s.s.m_clauses) {
|
||||||
|
@ -1237,15 +1282,21 @@ 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 l, literal blocked, model_converter::entry *& new_entry) {
|
void prepare_block_binary(watch_list::iterator it, literal l1, literal blocked, model_converter::entry*& new_entry) {
|
||||||
if (new_entry == 0)
|
if (new_entry == 0)
|
||||||
new_entry = &(mc.mk(model_converter::BLOCK_LIT, blocked.var()));
|
new_entry = &(mc.mk(model_converter::BLOCK_LIT, blocked.var()));
|
||||||
literal l2 = it->get_literal();
|
literal l2 = it->get_literal();
|
||||||
TRACE("blocked_clause", tout << "new blocked clause: " << l2 << " " << l << "\n";);
|
TRACE("blocked_clause", tout << "new blocked clause: " << l2 << " " << l1 << "\n";);
|
||||||
s.remove_bin_clause_half(l2, l, it->is_learned());
|
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());
|
||||||
|
}
|
||||||
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(watch_list::iterator it, literal l, model_converter::entry *& new_entry) {
|
||||||
prepare_block_binary(it, l, l, new_entry);
|
prepare_block_binary(it, l, l, new_entry);
|
||||||
mc.insert(*new_entry, l, it->get_literal());
|
mc.insert(*new_entry, l, it->get_literal());
|
||||||
|
@ -1257,6 +1308,47 @@ namespace sat {
|
||||||
mc.insert(*new_entry, m_covered_clause, m_elim_stack);
|
mc.insert(*new_entry, m_covered_clause, m_elim_stack);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void bca() {
|
||||||
|
insert_queue();
|
||||||
|
while (!m_queue.empty() && m_counter >= 0) {
|
||||||
|
s.checkpoint();
|
||||||
|
bca(m_queue.next());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
\brief blocked binary clause addition for literal l
|
||||||
|
Let RI be the resolution intersection with l, e.g, RI are the literals
|
||||||
|
that are in all clauses of the form ~l \/ C.
|
||||||
|
If RI is non-empty, then let l' be a literal in RI.
|
||||||
|
Then the following binary clause is blocked: l \/ ~l'
|
||||||
|
*/
|
||||||
|
void bca(literal l) {
|
||||||
|
m_intersection.reset();
|
||||||
|
if (resolution_intersection(l, m_intersection, true)) {
|
||||||
|
// this literal is pure.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
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) {
|
||||||
|
IF_VERBOSE(100, verbose_stream() << "bca " << l << " " << l2 << "\n";);
|
||||||
|
watched w(l2, false);
|
||||||
|
w.set_blocked();
|
||||||
|
s.get_wlist(~l).push_back(w);
|
||||||
|
w = watched(l, false);
|
||||||
|
w.set_blocked();
|
||||||
|
s.get_wlist(~l2).push_back(w);
|
||||||
|
++s.m_num_bca;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool all_tautology(literal l) {
|
bool all_tautology(literal l) {
|
||||||
watch_list & wlist = s.get_wlist(l);
|
watch_list & wlist = s.get_wlist(l);
|
||||||
m_counter -= wlist.size();
|
m_counter -= wlist.size();
|
||||||
|
@ -1323,7 +1415,7 @@ namespace sat {
|
||||||
TRACE("blocked_clause_bug", tout << "trail: " << s.m_trail.size() << "\n"; s.display_watches(tout); s.display(tout););
|
TRACE("blocked_clause_bug", tout << "trail: " << s.m_trail.size() << "\n"; s.display_watches(tout); s.display(tout););
|
||||||
blocked_cls_report rpt(*this);
|
blocked_cls_report rpt(*this);
|
||||||
blocked_clause_elim elim(*this, m_blocked_clause_limit, s.m_mc, m_use_list, s.m_watches);
|
blocked_clause_elim elim(*this, m_blocked_clause_limit, s.m_mc, m_use_list, s.m_watches);
|
||||||
elim(s.num_vars());
|
elim();
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned simplifier::get_num_unblocked_bin(literal l) const {
|
unsigned simplifier::get_num_unblocked_bin(literal l) const {
|
||||||
|
@ -1422,18 +1514,18 @@ namespace sat {
|
||||||
SASSERT(c2.contains(~l));
|
SASSERT(c2.contains(~l));
|
||||||
bool res = true;
|
bool res = true;
|
||||||
m_elim_counter -= c1.size() + c2.size();
|
m_elim_counter -= c1.size() + c2.size();
|
||||||
unsigned sz = c1.size();
|
unsigned sz1 = c1.size();
|
||||||
for (unsigned i = 0; i < sz; ++i) {
|
for (unsigned i = 0; i < sz1; ++i) {
|
||||||
literal l2 = c1[i];
|
literal l1 = c1[i];
|
||||||
if (l == l2)
|
if (l == l1)
|
||||||
continue;
|
continue;
|
||||||
m_visited[l2.index()] = true;
|
m_visited[l1.index()] = true;
|
||||||
r.push_back(l2);
|
r.push_back(l1);
|
||||||
}
|
}
|
||||||
|
|
||||||
literal not_l = ~l;
|
literal not_l = ~l;
|
||||||
sz = c2.size();
|
unsigned sz2 = c2.size();
|
||||||
for (unsigned i = 0; i < sz; ++i) {
|
for (unsigned i = 0; i < sz2; ++i) {
|
||||||
literal l2 = c2[i];
|
literal l2 = c2[i];
|
||||||
if (not_l == l2)
|
if (not_l == l2)
|
||||||
continue;
|
continue;
|
||||||
|
@ -1445,10 +1537,9 @@ namespace sat {
|
||||||
r.push_back(l2);
|
r.push_back(l2);
|
||||||
}
|
}
|
||||||
|
|
||||||
sz = c1.size();
|
for (unsigned i = 0; i < sz1; ++i) {
|
||||||
for (unsigned i = 0; i < sz; ++i) {
|
literal l1 = c1[i];
|
||||||
literal l2 = c1[i];
|
m_visited[l1.index()] = false;
|
||||||
m_visited[l2.index()] = false;
|
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
@ -1461,31 +1552,27 @@ namespace sat {
|
||||||
}
|
}
|
||||||
|
|
||||||
void simplifier::add_non_learned_binary_clause(literal l1, literal l2) {
|
void simplifier::add_non_learned_binary_clause(literal l1, literal l2) {
|
||||||
watch_list & wlist1 = s.m_watches[(~l1).index()];
|
watch_list & wlist1 = get_wlist(~l1);
|
||||||
watch_list & wlist2 = s.m_watches[(~l2).index()];
|
watch_list & wlist2 = get_wlist(~l2);
|
||||||
watch_list::iterator it1 = wlist1.begin();
|
bool found = false;
|
||||||
watch_list::iterator end1 = wlist1.end();
|
for (watched& w : wlist1) {
|
||||||
for (; it1 != end1; ++it1) {
|
if (w.is_binary_clause() && w.get_literal() == l2) {
|
||||||
if (it1->is_binary_clause() && it1->get_literal() == l2) {
|
if (w.is_learned()) w.mark_not_learned();
|
||||||
*it1 = watched(l2, false);
|
found = true;
|
||||||
watch_list::iterator it2 = wlist2.begin();
|
break;
|
||||||
watch_list::iterator end2 = wlist2.end();
|
|
||||||
for (; it2 != end2; ++it2) {
|
|
||||||
if (it2->is_binary_clause() && it2->get_literal() == l1) {
|
|
||||||
*it2 = watched(l1, false);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
CTRACE("resolve_bug", it2 == end2,
|
|
||||||
tout << ~l1 << " -> ";
|
|
||||||
display_watch_list(tout, s.m_cls_allocator, wlist1); tout << "\n" << ~l2 << " -> ";
|
|
||||||
display_watch_list(tout, s.m_cls_allocator, wlist2); tout << "\n";);
|
|
||||||
SASSERT(it2 != end2);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
wlist1.push_back(watched(l2, false));
|
if (!found) wlist1.push_back(watched(l2, false));
|
||||||
wlist2.push_back(watched(l1, 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!found) wlist2.push_back(watched(l1, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1692,7 +1779,7 @@ namespace sat {
|
||||||
};
|
};
|
||||||
|
|
||||||
void simplifier::elim_vars() {
|
void simplifier::elim_vars() {
|
||||||
if (!m_elim_vars) return;
|
if (!elim_vars_enabled()) return;
|
||||||
elim_var_report rpt(*this);
|
elim_var_report rpt(*this);
|
||||||
bool_var_vector vars;
|
bool_var_vector vars;
|
||||||
order_vars_for_elim(vars);
|
order_vars_for_elim(vars);
|
||||||
|
@ -1704,7 +1791,7 @@ namespace sat {
|
||||||
if (try_eliminate(v)) {
|
if (try_eliminate(v)) {
|
||||||
m_num_elim_vars++;
|
m_num_elim_vars++;
|
||||||
}
|
}
|
||||||
else if (elim_bdd(v)) {
|
else if (elim_vars_bdd_enabled() && elim_bdd(v)) {
|
||||||
m_num_elim_vars++;
|
m_num_elim_vars++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1716,11 +1803,13 @@ namespace sat {
|
||||||
|
|
||||||
void simplifier::updt_params(params_ref const & _p) {
|
void simplifier::updt_params(params_ref const & _p) {
|
||||||
sat_simplifier_params p(_p);
|
sat_simplifier_params p(_p);
|
||||||
m_elim_covered_clauses = p.elim_covered_clauses();
|
m_cce = p.cce();
|
||||||
|
m_acce = p.acce();
|
||||||
|
m_bca = p.bca();
|
||||||
m_elim_blocked_clauses = p.elim_blocked_clauses();
|
m_elim_blocked_clauses = p.elim_blocked_clauses();
|
||||||
m_elim_blocked_clauses_at = p.elim_blocked_clauses_at();
|
m_elim_blocked_clauses_at = p.elim_blocked_clauses_at();
|
||||||
|
m_retain_blocked_clauses = p.retain_blocked_clauses();
|
||||||
m_blocked_clause_limit = p.blocked_clause_limit();
|
m_blocked_clause_limit = p.blocked_clause_limit();
|
||||||
m_resolution = p.resolution();
|
|
||||||
m_res_limit = p.resolution_limit();
|
m_res_limit = p.resolution_limit();
|
||||||
m_res_occ_cutoff = p.resolution_occ_cutoff();
|
m_res_occ_cutoff = p.resolution_occ_cutoff();
|
||||||
m_res_occ_cutoff1 = p.resolution_occ_cutoff_range1();
|
m_res_occ_cutoff1 = p.resolution_occ_cutoff_range1();
|
||||||
|
@ -1735,6 +1824,7 @@ namespace sat {
|
||||||
m_subsumption_limit = p.subsumption_limit();
|
m_subsumption_limit = p.subsumption_limit();
|
||||||
m_elim_vars = p.elim_vars();
|
m_elim_vars = p.elim_vars();
|
||||||
m_elim_vars_bdd = p.elim_vars_bdd();
|
m_elim_vars_bdd = p.elim_vars_bdd();
|
||||||
|
m_elim_vars_bdd_delay = p.elim_vars_bdd_delay();
|
||||||
}
|
}
|
||||||
|
|
||||||
void simplifier::collect_param_descrs(param_descrs & r) {
|
void simplifier::collect_param_descrs(param_descrs & r) {
|
||||||
|
@ -1747,6 +1837,7 @@ namespace sat {
|
||||||
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("elim blocked clauses", m_num_blocked_clauses);
|
||||||
st.update("elim covered clauses", m_num_covered_clauses);
|
st.update("elim covered clauses", m_num_covered_clauses);
|
||||||
|
st.update("blocked clauses added", m_num_bca);
|
||||||
}
|
}
|
||||||
|
|
||||||
void simplifier::reset_statistics() {
|
void simplifier::reset_statistics() {
|
||||||
|
@ -1756,5 +1847,6 @@ namespace sat {
|
||||||
m_num_sub_res = 0;
|
m_num_sub_res = 0;
|
||||||
m_num_elim_lits = 0;
|
m_num_elim_lits = 0;
|
||||||
m_num_elim_vars = 0;
|
m_num_elim_vars = 0;
|
||||||
|
m_num_bca = 0;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -71,9 +71,12 @@ namespace sat {
|
||||||
int m_elim_counter;
|
int m_elim_counter;
|
||||||
|
|
||||||
// config
|
// config
|
||||||
bool m_elim_covered_clauses;
|
bool m_cce; // covered clause elimination
|
||||||
|
bool m_acce; // cce with asymetric literal addition
|
||||||
|
bool m_bca; // blocked (binary) clause addition.
|
||||||
bool m_elim_blocked_clauses;
|
bool m_elim_blocked_clauses;
|
||||||
unsigned m_elim_blocked_clauses_at;
|
unsigned m_elim_blocked_clauses_at;
|
||||||
|
bool m_retain_blocked_clauses;
|
||||||
unsigned m_blocked_clause_limit;
|
unsigned m_blocked_clause_limit;
|
||||||
bool m_resolution;
|
bool m_resolution;
|
||||||
unsigned m_res_limit;
|
unsigned m_res_limit;
|
||||||
|
@ -91,6 +94,7 @@ namespace sat {
|
||||||
unsigned m_subsumption_limit;
|
unsigned m_subsumption_limit;
|
||||||
bool m_elim_vars;
|
bool m_elim_vars;
|
||||||
bool m_elim_vars_bdd;
|
bool m_elim_vars_bdd;
|
||||||
|
unsigned m_elim_vars_bdd_delay;
|
||||||
|
|
||||||
// stats
|
// stats
|
||||||
unsigned m_num_blocked_clauses;
|
unsigned m_num_blocked_clauses;
|
||||||
|
@ -99,6 +103,7 @@ namespace sat {
|
||||||
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;
|
||||||
|
|
||||||
bool m_learned_in_use_lists;
|
bool m_learned_in_use_lists;
|
||||||
unsigned m_old_num_elim_vars;
|
unsigned m_old_num_elim_vars;
|
||||||
|
@ -124,6 +129,7 @@ namespace sat {
|
||||||
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 block_clause(clause & c);
|
||||||
|
void block_bin_clause_half(literal l1, literal l2);
|
||||||
void unblock_clause(clause & c);
|
void unblock_clause(clause & c);
|
||||||
void remove_bin_clause_half(literal l1, literal l2, bool learned);
|
void remove_bin_clause_half(literal l1, literal l2, bool learned);
|
||||||
|
|
||||||
|
@ -163,6 +169,13 @@ namespace sat {
|
||||||
struct blocked_clause_elim;
|
struct blocked_clause_elim;
|
||||||
void elim_blocked_clauses();
|
void elim_blocked_clauses();
|
||||||
|
|
||||||
|
bool bce_enabled() const { return m_elim_blocked_clauses || m_elim_blocked_clauses_at == m_num_calls || cce_enabled(); }
|
||||||
|
bool acce_enabled() const { return m_acce; }
|
||||||
|
bool cce_enabled() const { return m_cce || acce_enabled(); }
|
||||||
|
bool bca_enabled() const { return m_bca; }
|
||||||
|
bool elim_vars_bdd_enabled() const { return m_elim_vars_bdd && m_num_calls >= m_elim_vars_bdd_delay; }
|
||||||
|
bool elim_vars_enabled() const { return m_elim_vars; }
|
||||||
|
|
||||||
unsigned get_num_unblocked_bin(literal l) const;
|
unsigned get_num_unblocked_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);
|
||||||
|
|
|
@ -2,10 +2,12 @@ def_module_params(module_name='sat',
|
||||||
class_name='sat_simplifier_params',
|
class_name='sat_simplifier_params',
|
||||||
export=True,
|
export=True,
|
||||||
params=(('elim_blocked_clauses', BOOL, False, 'eliminate blocked clauses'),
|
params=(('elim_blocked_clauses', BOOL, False, 'eliminate blocked clauses'),
|
||||||
('elim_covered_clauses', BOOL, False, 'eliminate covered clauses'),
|
('cce', BOOL, False, 'eliminate covered clauses'),
|
||||||
|
('acce', BOOL, False, 'eliminate covered clauses using asymmetric added literals'),
|
||||||
('elim_blocked_clauses_at', UINT, 2, 'eliminate blocked clauses only once at the given simplification round'),
|
('elim_blocked_clauses_at', UINT, 2, 'eliminate blocked clauses only once at the given simplification round'),
|
||||||
|
('bca', BOOL, False, 'blocked clause addition - add blocked binary clauses'),
|
||||||
|
('retain_blocked_clauses', BOOL, False, 'retain blocked clauses for propagation, hide them from variable elimination'),
|
||||||
('blocked_clause_limit', UINT, 100000000, 'maximum number of literals visited during blocked clause elimination'),
|
('blocked_clause_limit', UINT, 100000000, 'maximum number of literals visited during blocked clause elimination'),
|
||||||
('resolution', BOOL, True, 'eliminate boolean variables using resolution'),
|
|
||||||
('resolution.limit', UINT, 500000000, 'approx. maximum number of literals visited during variable elimination'),
|
('resolution.limit', UINT, 500000000, 'approx. maximum number of literals visited during variable elimination'),
|
||||||
('resolution.occ_cutoff', UINT, 10, 'first cutoff (on number of positive/negative occurrences) for Boolean variable elimination'),
|
('resolution.occ_cutoff', UINT, 10, 'first cutoff (on number of positive/negative occurrences) for Boolean variable elimination'),
|
||||||
('resolution.occ_cutoff_range1', UINT, 8, 'second cutoff (number of positive/negative occurrences) for Boolean variable elimination, for problems containing less than res_cls_cutoff1 clauses'),
|
('resolution.occ_cutoff_range1', UINT, 8, 'second cutoff (number of positive/negative occurrences) for Boolean variable elimination, for problems containing less than res_cls_cutoff1 clauses'),
|
||||||
|
@ -16,7 +18,8 @@ def_module_params(module_name='sat',
|
||||||
('resolution.lit_cutoff_range3', UINT, 300, 'second cutoff (total number of literals) for Boolean variable elimination, for problems containing more than res_cls_cutoff2'),
|
('resolution.lit_cutoff_range3', UINT, 300, 'second cutoff (total number of literals) for Boolean variable elimination, for problems containing more than res_cls_cutoff2'),
|
||||||
('resolution.cls_cutoff1', UINT, 100000000, 'limit1 - total number of problems clauses for the second cutoff of Boolean variable elimination'),
|
('resolution.cls_cutoff1', UINT, 100000000, 'limit1 - total number of problems clauses for the second cutoff of Boolean variable elimination'),
|
||||||
('resolution.cls_cutoff2', UINT, 700000000, 'limit2 - total number of problems clauses for the second cutoff of Boolean variable elimination'),
|
('resolution.cls_cutoff2', UINT, 700000000, 'limit2 - total number of problems clauses for the second cutoff of Boolean variable elimination'),
|
||||||
('elim_vars', BOOL, True, 'enable variable elimination during simplification'),
|
('elim_vars', BOOL, True, 'enable variable elimination using resolution during simplification'),
|
||||||
('elim_vars_bdd', BOOL, True, 'enable variable elimination using BDD recompilation during simplification'),
|
('elim_vars_bdd', BOOL, True, 'enable variable elimination using BDD recompilation during simplification'),
|
||||||
|
('elim_vars_bdd_delay', UINT, 3, 'delay elimination of variables using BDDs until after simplification round'),
|
||||||
('subsumption', BOOL, True, 'eliminate subsumed clauses'),
|
('subsumption', BOOL, True, 'eliminate subsumed clauses'),
|
||||||
('subsumption.limit', UINT, 100000000, 'approx. maximum number of literals visited during subsumption (and subsumption resolution)')))
|
('subsumption.limit', UINT, 100000000, 'approx. maximum number of literals visited during subsumption (and subsumption resolution)')))
|
||||||
|
|
|
@ -1468,19 +1468,9 @@ namespace sat {
|
||||||
|
|
||||||
|
|
||||||
if (m_config.m_lookahead_simplify) {
|
if (m_config.m_lookahead_simplify) {
|
||||||
{
|
lookahead lh(*this);
|
||||||
lookahead lh(*this);
|
lh.simplify();
|
||||||
lh.simplify();
|
lh.collect_statistics(m_aux_stats);
|
||||||
lh.collect_statistics(m_aux_stats);
|
|
||||||
}
|
|
||||||
#if 0
|
|
||||||
// Buggy
|
|
||||||
{
|
|
||||||
lookahead lh(*this);
|
|
||||||
lh.scc();
|
|
||||||
lh.collect_statistics(m_aux_stats);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1562,7 +1552,7 @@ namespace sat {
|
||||||
TRACE("sat", for (bool_var v = 0; v < num; v++) tout << v << ": " << m_model[v] << "\n";);
|
TRACE("sat", for (bool_var v = 0; v < num; v++) tout << v << ": " << m_model[v] << "\n";);
|
||||||
|
|
||||||
// #ifndef _EXTERNAL_RELEASE
|
// #ifndef _EXTERNAL_RELEASE
|
||||||
IF_VERBOSE(1, verbose_stream() << "\"checking model\"\n";);
|
IF_VERBOSE(10, verbose_stream() << "\"checking model\"\n";);
|
||||||
if (!check_model(m_model))
|
if (!check_model(m_model))
|
||||||
throw solver_exception("check model failed");
|
throw solver_exception("check model failed");
|
||||||
|
|
||||||
|
@ -1576,48 +1566,40 @@ namespace sat {
|
||||||
|
|
||||||
bool solver::check_model(model const & m) const {
|
bool solver::check_model(model const & m) const {
|
||||||
bool ok = true;
|
bool ok = true;
|
||||||
clause_vector const * vs[2] = { &m_clauses, &m_learned };
|
for (clause const* cp : m_clauses) {
|
||||||
for (unsigned i = 0; i < 2; i++) {
|
clause const & c = *cp;
|
||||||
clause_vector const & cs = *(vs[i]);
|
if (!c.satisfied_by(m) && !c.is_blocked()) {
|
||||||
clause_vector::const_iterator it = cs.begin();
|
IF_VERBOSE(0, verbose_stream() << "model check failed: " << c << "\n";);
|
||||||
clause_vector::const_iterator end = cs.end();
|
TRACE("sat", tout << "failed: " << c << "\n";
|
||||||
for (; it != end; ++it) {
|
tout << "assumptions: " << m_assumptions << "\n";
|
||||||
clause const & c = *(*it);
|
tout << "trail: " << m_trail << "\n";
|
||||||
if (!c.satisfied_by(m)) {
|
tout << "model: " << m << "\n";
|
||||||
TRACE("sat", tout << "failed: " << c << "\n";
|
m_mc.display(tout);
|
||||||
tout << "assumptions: " << m_assumptions << "\n";
|
);
|
||||||
tout << "trail: " << m_trail << "\n";
|
ok = false;
|
||||||
tout << "model: " << m << "\n";
|
|
||||||
m_mc.display(tout);
|
|
||||||
);
|
|
||||||
ok = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
vector<watch_list>::const_iterator it = m_watches.begin();
|
unsigned l_idx = 0;
|
||||||
vector<watch_list>::const_iterator end = m_watches.end();
|
for (watch_list const& wlist : m_watches) {
|
||||||
for (unsigned l_idx = 0; it != end; ++it, ++l_idx) {
|
|
||||||
literal l = ~to_literal(l_idx);
|
literal l = ~to_literal(l_idx);
|
||||||
if (value_at(l, m) != l_true) {
|
if (value_at(l, m) != l_true) {
|
||||||
watch_list const & wlist = *it;
|
for (watched const& w : wlist) {
|
||||||
watch_list::const_iterator it2 = wlist.begin();
|
if (!w.is_binary_unblocked_clause())
|
||||||
watch_list::const_iterator end2 = wlist.end();
|
|
||||||
for (; it2 != end2; ++it2) {
|
|
||||||
if (!it2->is_binary_clause())
|
|
||||||
continue;
|
continue;
|
||||||
literal l2 = it2->get_literal();
|
literal l2 = w.get_literal();
|
||||||
if (value_at(l2, m) != l_true) {
|
if (value_at(l2, m) != l_true) {
|
||||||
TRACE("sat", tout << "failed binary: " << l << " " << l2 << " learned: " << it2->is_learned() << "\n";
|
IF_VERBOSE(0, verbose_stream() << "failed binary: " << l << " " << l2 << " " << "\n";);
|
||||||
m_mc.display(tout););
|
TRACE("sat", m_mc.display(tout << "failed binary: " << l << " " << l2 << "\n"););
|
||||||
ok = false;
|
ok = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
++l_idx;
|
||||||
}
|
}
|
||||||
for (unsigned i = 0; i < m_assumptions.size(); ++i) {
|
for (literal l : m_assumptions) {
|
||||||
if (value_at(m_assumptions[i], m) != l_true) {
|
if (value_at(l, m) != l_true) {
|
||||||
TRACE("sat",
|
TRACE("sat",
|
||||||
tout << m_assumptions[i] << " does not model check\n";
|
tout << l << " does not model check\n";
|
||||||
tout << "trail: " << m_trail << "\n";
|
tout << "trail: " << m_trail << "\n";
|
||||||
tout << "model: " << m << "\n";
|
tout << "model: " << m << "\n";
|
||||||
m_mc.display(tout);
|
m_mc.display(tout);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue