mirror of
https://github.com/Z3Prover/z3
synced 2025-07-18 02:16:40 +00:00
Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
This commit is contained in:
parent
8b10e13251
commit
825b72719c
2 changed files with 189 additions and 173 deletions
|
@ -9,7 +9,7 @@ Abstract:
|
||||||
|
|
||||||
SAT simplification procedures that use a "full" occurrence list:
|
SAT simplification procedures that use a "full" occurrence list:
|
||||||
Subsumption, Blocked Clause Removal, Variable Elimination, ...
|
Subsumption, Blocked Clause Removal, Variable Elimination, ...
|
||||||
|
|
||||||
|
|
||||||
Author:
|
Author:
|
||||||
|
|
||||||
|
@ -54,21 +54,21 @@ namespace sat {
|
||||||
m_use_list[l2.index()].erase(c);
|
m_use_list[l2.index()].erase(c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
simplifier::simplifier(solver & _s, params_ref const & p):
|
simplifier::simplifier(solver & _s, params_ref const & p):
|
||||||
s(_s),
|
s(_s),
|
||||||
m_num_calls(0) {
|
m_num_calls(0) {
|
||||||
updt_params(p);
|
updt_params(p);
|
||||||
reset_statistics();
|
reset_statistics();
|
||||||
}
|
}
|
||||||
|
|
||||||
simplifier::~simplifier() {
|
simplifier::~simplifier() {
|
||||||
}
|
}
|
||||||
|
|
||||||
inline watch_list & simplifier::get_wlist(literal l) { return s.get_wlist(l); }
|
inline watch_list & simplifier::get_wlist(literal l) { return s.get_wlist(l); }
|
||||||
|
|
||||||
inline watch_list const & simplifier::get_wlist(literal l) const { return s.get_wlist(l); }
|
inline watch_list const & simplifier::get_wlist(literal l) const { return s.get_wlist(l); }
|
||||||
|
|
||||||
inline bool simplifier::is_external(bool_var v) const { return s.is_external(v); }
|
inline bool simplifier::is_external(bool_var v) const { return s.is_external(v); }
|
||||||
|
|
||||||
inline bool simplifier::was_eliminated(bool_var v) const { return s.was_eliminated(v); }
|
inline bool simplifier::was_eliminated(bool_var v) const { return s.was_eliminated(v); }
|
||||||
|
@ -78,7 +78,7 @@ namespace sat {
|
||||||
lbool simplifier::value(literal l) const { return s.value(l); }
|
lbool simplifier::value(literal l) const { return s.value(l); }
|
||||||
|
|
||||||
inline void simplifier::checkpoint() { s.checkpoint(); }
|
inline void simplifier::checkpoint() { s.checkpoint(); }
|
||||||
|
|
||||||
void simplifier::register_clauses(clause_vector & cs) {
|
void simplifier::register_clauses(clause_vector & cs) {
|
||||||
std::stable_sort(cs.begin(), cs.end(), size_lt());
|
std::stable_sort(cs.begin(), cs.end(), size_lt());
|
||||||
clause_vector::iterator it = cs.begin();
|
clause_vector::iterator it = cs.begin();
|
||||||
|
@ -117,7 +117,7 @@ namespace sat {
|
||||||
SASSERT(s.get_wlist(~l1).contains(watched(l2, learned)));
|
SASSERT(s.get_wlist(~l1).contains(watched(l2, learned)));
|
||||||
s.get_wlist(~l1).erase(watched(l2, learned));
|
s.get_wlist(~l1).erase(watched(l2, learned));
|
||||||
}
|
}
|
||||||
|
|
||||||
void simplifier::init_visited() {
|
void simplifier::init_visited() {
|
||||||
m_visited.reset();
|
m_visited.reset();
|
||||||
m_visited.resize(2*s.num_vars(), false);
|
m_visited.resize(2*s.num_vars(), false);
|
||||||
|
@ -155,7 +155,7 @@ namespace sat {
|
||||||
|
|
||||||
if (!learned && (m_elim_blocked_clauses || m_elim_blocked_clauses_at == m_num_calls))
|
if (!learned && (m_elim_blocked_clauses || m_elim_blocked_clauses_at == m_num_calls))
|
||||||
elim_blocked_clauses();
|
elim_blocked_clauses();
|
||||||
|
|
||||||
if (!learned)
|
if (!learned)
|
||||||
m_num_calls++;
|
m_num_calls++;
|
||||||
|
|
||||||
|
@ -180,6 +180,7 @@ namespace sat {
|
||||||
bool vars_eliminated = m_num_elim_vars > old_num_elim_vars;
|
bool vars_eliminated = m_num_elim_vars > old_num_elim_vars;
|
||||||
|
|
||||||
if (!m_need_cleanup) {
|
if (!m_need_cleanup) {
|
||||||
|
TRACE("after_simplifier", tout << "skipping cleanup...\n";);
|
||||||
if (vars_eliminated) {
|
if (vars_eliminated) {
|
||||||
// must remove learned clauses with eliminated variables
|
// must remove learned clauses with eliminated variables
|
||||||
cleanup_clauses(s.m_learned, true, true, learned_in_use_lists);
|
cleanup_clauses(s.m_learned, true, true, learned_in_use_lists);
|
||||||
|
@ -189,6 +190,7 @@ namespace sat {
|
||||||
free_memory();
|
free_memory();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
TRACE("after_simplifier", tout << "cleanning watches...\n";);
|
||||||
cleanup_watches();
|
cleanup_watches();
|
||||||
cleanup_clauses(s.m_learned, true, vars_eliminated, learned_in_use_lists);
|
cleanup_clauses(s.m_learned, true, vars_eliminated, learned_in_use_lists);
|
||||||
cleanup_clauses(s.m_clauses, false, vars_eliminated, true);
|
cleanup_clauses(s.m_clauses, false, vars_eliminated, true);
|
||||||
|
@ -234,7 +236,7 @@ namespace sat {
|
||||||
s.del_clause(c);
|
s.del_clause(c);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (learned && vars_eliminated) {
|
if (learned && vars_eliminated) {
|
||||||
unsigned sz = c.size();
|
unsigned sz = c.size();
|
||||||
unsigned i;
|
unsigned i;
|
||||||
|
@ -293,7 +295,7 @@ namespace sat {
|
||||||
mark_visited(c[i]);
|
mark_visited(c[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void simplifier::unmark_all(clause const & c) {
|
void simplifier::unmark_all(clause const & c) {
|
||||||
unsigned sz = c.size();
|
unsigned sz = c.size();
|
||||||
for (unsigned i = 0; i < sz; i++)
|
for (unsigned i = 0; i < sz; i++)
|
||||||
|
@ -325,7 +327,7 @@ namespace sat {
|
||||||
*/
|
*/
|
||||||
bool simplifier::subsumes1(clause const & c1, clause const & c2, literal & l) {
|
bool simplifier::subsumes1(clause const & c1, clause const & c2, literal & l) {
|
||||||
unsigned sz2 = c2.size();
|
unsigned sz2 = c2.size();
|
||||||
for (unsigned i = 0; i < sz2; i++)
|
for (unsigned i = 0; i < sz2; i++)
|
||||||
mark_visited(c2[i]);
|
mark_visited(c2[i]);
|
||||||
|
|
||||||
bool r = true;
|
bool r = true;
|
||||||
|
@ -344,7 +346,7 @@ namespace sat {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (unsigned i = 0; i < sz2; i++)
|
for (unsigned i = 0; i < sz2; i++)
|
||||||
unmark_visited(c2[i]);
|
unmark_visited(c2[i]);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
@ -353,7 +355,7 @@ namespace sat {
|
||||||
\brief Return the clauses subsumed by c1 and the clauses that can be subsumed resolved using c1.
|
\brief Return the clauses subsumed by c1 and the clauses that can be subsumed resolved using c1.
|
||||||
The collections is populated using the use list of target.
|
The collections is populated using the use list of target.
|
||||||
*/
|
*/
|
||||||
void simplifier::collect_subsumed1_core(clause const & c1, clause_vector & out, literal_vector & out_lits,
|
void simplifier::collect_subsumed1_core(clause const & c1, clause_vector & out, literal_vector & out_lits,
|
||||||
literal target) {
|
literal target) {
|
||||||
clause_use_list const & cs = m_use_list.get(target);
|
clause_use_list const & cs = m_use_list.get(target);
|
||||||
clause_use_list::iterator it = cs.mk_iterator();
|
clause_use_list::iterator it = cs.mk_iterator();
|
||||||
|
@ -362,7 +364,7 @@ namespace sat {
|
||||||
CTRACE("resolution_bug", c2.was_removed(), tout << "clause has been removed:\n" << c2 << "\n";);
|
CTRACE("resolution_bug", c2.was_removed(), tout << "clause has been removed:\n" << c2 << "\n";);
|
||||||
SASSERT(!c2.was_removed());
|
SASSERT(!c2.was_removed());
|
||||||
if (&c2 != &c1 &&
|
if (&c2 != &c1 &&
|
||||||
c1.size() <= c2.size() &&
|
c1.size() <= c2.size() &&
|
||||||
approx_subset(c1.approx(), c2.approx())) {
|
approx_subset(c1.approx(), c2.approx())) {
|
||||||
m_sub_counter -= c1.size() + c2.size();
|
m_sub_counter -= c1.size() + c2.size();
|
||||||
literal l;
|
literal l;
|
||||||
|
@ -373,7 +375,7 @@ namespace sat {
|
||||||
}
|
}
|
||||||
it.next();
|
it.next();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
\brief Return the clauses subsumed by c1 and the clauses that can be subsumed resolved using c1.
|
\brief Return the clauses subsumed by c1 and the clauses that can be subsumed resolved using c1.
|
||||||
|
@ -400,7 +402,7 @@ namespace sat {
|
||||||
if (*l_it == null_literal) {
|
if (*l_it == null_literal) {
|
||||||
// c2 was subsumed
|
// c2 was subsumed
|
||||||
if (c1.is_learned() && !c2.is_learned())
|
if (c1.is_learned() && !c2.is_learned())
|
||||||
c1.unset_learned();
|
c1.unset_learned();
|
||||||
TRACE("subsumption", tout << c1 << " subsumed " << c2 << "\n";);
|
TRACE("subsumption", tout << c1 << " subsumed " << c2 << "\n";);
|
||||||
remove_clause(c2);
|
remove_clause(c2);
|
||||||
m_num_subsumed++;
|
m_num_subsumed++;
|
||||||
|
@ -447,9 +449,9 @@ namespace sat {
|
||||||
*/
|
*/
|
||||||
bool simplifier::subsumes0(clause const & c1, clause const & c2) {
|
bool simplifier::subsumes0(clause const & c1, clause const & c2) {
|
||||||
unsigned sz2 = c2.size();
|
unsigned sz2 = c2.size();
|
||||||
for (unsigned i = 0; i < sz2; i++)
|
for (unsigned i = 0; i < sz2; i++)
|
||||||
mark_visited(c2[i]);
|
mark_visited(c2[i]);
|
||||||
|
|
||||||
bool r = true;
|
bool r = true;
|
||||||
unsigned sz1 = c1.size();
|
unsigned sz1 = c1.size();
|
||||||
for (unsigned i = 0; i < sz1; i++) {
|
for (unsigned i = 0; i < sz1; i++) {
|
||||||
|
@ -459,12 +461,12 @@ namespace sat {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (unsigned i = 0; i < sz2; i++)
|
for (unsigned i = 0; i < sz2; i++)
|
||||||
unmark_visited(c2[i]);
|
unmark_visited(c2[i]);
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
\brief Collect the clauses subsumed by c1 (using the occurrence list of target).
|
\brief Collect the clauses subsumed by c1 (using the occurrence list of target).
|
||||||
*/
|
*/
|
||||||
|
@ -475,7 +477,7 @@ namespace sat {
|
||||||
clause & c2 = it.curr();
|
clause & c2 = it.curr();
|
||||||
SASSERT(!c2.was_removed());
|
SASSERT(!c2.was_removed());
|
||||||
if (&c2 != &c1 &&
|
if (&c2 != &c1 &&
|
||||||
c1.size() <= c2.size() &&
|
c1.size() <= c2.size() &&
|
||||||
approx_subset(c1.approx(), c2.approx())) {
|
approx_subset(c1.approx(), c2.approx())) {
|
||||||
m_sub_counter -= c1.size() + c2.size();
|
m_sub_counter -= c1.size() + c2.size();
|
||||||
if (subsumes0(c1, c2)) {
|
if (subsumes0(c1, c2)) {
|
||||||
|
@ -485,7 +487,7 @@ namespace sat {
|
||||||
it.next();
|
it.next();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
\brief Collect the clauses subsumed by c1
|
\brief Collect the clauses subsumed by c1
|
||||||
*/
|
*/
|
||||||
|
@ -493,8 +495,8 @@ namespace sat {
|
||||||
literal l = get_min_occ_var0(c1);
|
literal l = get_min_occ_var0(c1);
|
||||||
collect_subsumed0_core(c1, out, l);
|
collect_subsumed0_core(c1, out, l);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
\brief Perform backward subsumption using c1.
|
\brief Perform backward subsumption using c1.
|
||||||
*/
|
*/
|
||||||
|
@ -507,16 +509,16 @@ namespace sat {
|
||||||
clause & c2 = *(*it);
|
clause & c2 = *(*it);
|
||||||
// c2 was subsumed
|
// c2 was subsumed
|
||||||
if (c1.is_learned() && !c2.is_learned())
|
if (c1.is_learned() && !c2.is_learned())
|
||||||
c1.unset_learned();
|
c1.unset_learned();
|
||||||
TRACE("subsumption", tout << c1 << " subsumed " << c2 << "\n";);
|
TRACE("subsumption", tout << c1 << " subsumed " << c2 << "\n";);
|
||||||
remove_clause(c2);
|
remove_clause(c2);
|
||||||
m_num_subsumed++;
|
m_num_subsumed++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
\brief Eliminate false literals from c, and update occurrence lists
|
\brief Eliminate false literals from c, and update occurrence lists
|
||||||
|
|
||||||
Return true if the clause is satisfied
|
Return true if the clause is satisfied
|
||||||
*/
|
*/
|
||||||
bool simplifier::cleanup_clause(clause & c, bool in_use_list) {
|
bool simplifier::cleanup_clause(clause & c, bool in_use_list) {
|
||||||
|
@ -666,7 +668,7 @@ namespace sat {
|
||||||
back_subsumption1(c);
|
back_subsumption1(c);
|
||||||
if (w.is_learned() && !c.is_learned()) {
|
if (w.is_learned() && !c.is_learned()) {
|
||||||
SASSERT(wlist[j] == w);
|
SASSERT(wlist[j] == w);
|
||||||
TRACE("mark_not_learned_bug",
|
TRACE("mark_not_learned_bug",
|
||||||
tout << "marking as not learned: " << l2 << " " << wlist[j].is_learned() << "\n";);
|
tout << "marking as not learned: " << l2 << " " << wlist[j].is_learned() << "\n";);
|
||||||
wlist[j].mark_not_learned();
|
wlist[j].mark_not_learned();
|
||||||
mark_as_not_learned_core(get_wlist(~l2), l);
|
mark_as_not_learned_core(get_wlist(~l2), l);
|
||||||
|
@ -735,7 +737,7 @@ namespace sat {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (it2->get_literal() == last_lit) {
|
if (it2->get_literal() == last_lit) {
|
||||||
TRACE("subsumption", tout << "eliminating: " << ~to_literal(l_idx)
|
TRACE("subsumption", tout << "eliminating: " << ~to_literal(l_idx)
|
||||||
<< " " << it2->get_literal() << "\n";);
|
<< " " << it2->get_literal() << "\n";);
|
||||||
elim++;
|
elim++;
|
||||||
}
|
}
|
||||||
|
@ -762,12 +764,12 @@ namespace sat {
|
||||||
m_num_sub_res(s.m_num_sub_res) {
|
m_num_sub_res(s.m_num_sub_res) {
|
||||||
m_watch.start();
|
m_watch.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
~subsumption_report() {
|
~subsumption_report() {
|
||||||
m_watch.stop();
|
m_watch.stop();
|
||||||
IF_VERBOSE(SAT_VB_LVL,
|
IF_VERBOSE(SAT_VB_LVL,
|
||||||
verbose_stream() << " (sat-subsumer :subsumed "
|
verbose_stream() << " (sat-subsumer :subsumed "
|
||||||
<< (m_simplifier.m_num_subsumed - m_num_subsumed)
|
<< (m_simplifier.m_num_subsumed - m_num_subsumed)
|
||||||
<< " :subsumption-resolution " << (m_simplifier.m_num_sub_res - m_num_sub_res)
|
<< " :subsumption-resolution " << (m_simplifier.m_num_sub_res - m_num_sub_res)
|
||||||
<< " :threshold " << m_simplifier.m_sub_counter
|
<< " :threshold " << m_simplifier.m_sub_counter
|
||||||
<< mem_stat()
|
<< mem_stat()
|
||||||
|
@ -847,12 +849,12 @@ namespace sat {
|
||||||
vector<watch_list> const & m_watches;
|
vector<watch_list> const & m_watches;
|
||||||
public:
|
public:
|
||||||
literal_lt(use_list const & l, vector<watch_list> const & ws):m_use_list(l), m_watches(ws) {}
|
literal_lt(use_list const & l, vector<watch_list> const & ws):m_use_list(l), m_watches(ws) {}
|
||||||
|
|
||||||
unsigned weight(unsigned l_idx) const {
|
unsigned weight(unsigned l_idx) const {
|
||||||
return 2*m_use_list.get(~to_literal(l_idx)).size() + m_watches[l_idx].size();
|
return 2*m_use_list.get(~to_literal(l_idx)).size() + m_watches[l_idx].size();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator()(unsigned l_idx1, unsigned l_idx2) const {
|
bool operator()(unsigned l_idx1, unsigned l_idx2) const {
|
||||||
return weight(l_idx1) < weight(l_idx2);
|
return weight(l_idx1) < weight(l_idx2);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -861,9 +863,9 @@ namespace sat {
|
||||||
heap<literal_lt> m_queue;
|
heap<literal_lt> m_queue;
|
||||||
public:
|
public:
|
||||||
queue(use_list const & l, vector<watch_list> const & ws):m_queue(128, literal_lt(l, ws)) {}
|
queue(use_list const & l, vector<watch_list> const & ws):m_queue(128, literal_lt(l, ws)) {}
|
||||||
void insert(literal l) {
|
void insert(literal l) {
|
||||||
unsigned idx = l.index();
|
unsigned idx = l.index();
|
||||||
m_queue.reserve(idx + 1);
|
m_queue.reserve(idx + 1);
|
||||||
SASSERT(!m_queue.contains(idx));
|
SASSERT(!m_queue.contains(idx));
|
||||||
m_queue.insert(idx);
|
m_queue.insert(idx);
|
||||||
}
|
}
|
||||||
|
@ -877,14 +879,14 @@ namespace sat {
|
||||||
literal next() { SASSERT(!empty()); return to_literal(m_queue.erase_min()); }
|
literal next() { SASSERT(!empty()); return to_literal(m_queue.erase_min()); }
|
||||||
bool empty() const { return m_queue.empty(); }
|
bool empty() const { return m_queue.empty(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
simplifier & s;
|
simplifier & s;
|
||||||
int m_counter;
|
int m_counter;
|
||||||
model_converter & mc;
|
model_converter & mc;
|
||||||
queue m_queue;
|
queue m_queue;
|
||||||
clause_vector m_to_remove;
|
clause_vector m_to_remove;
|
||||||
|
|
||||||
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),
|
||||||
m_counter(limit),
|
m_counter(limit),
|
||||||
|
@ -946,7 +948,7 @@ namespace sat {
|
||||||
clause_vector::iterator it = m_to_remove.begin();
|
clause_vector::iterator it = m_to_remove.begin();
|
||||||
clause_vector::iterator end = m_to_remove.end();
|
clause_vector::iterator end = m_to_remove.end();
|
||||||
for (; it != end; ++it) {
|
for (; it != end; ++it) {
|
||||||
s.remove_clause(*(*it));
|
s.remove_clause(*(*it));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
|
@ -1025,12 +1027,12 @@ namespace sat {
|
||||||
m_num_blocked_clauses(s.m_num_blocked_clauses) {
|
m_num_blocked_clauses(s.m_num_blocked_clauses) {
|
||||||
m_watch.start();
|
m_watch.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
~blocked_cls_report() {
|
~blocked_cls_report() {
|
||||||
m_watch.stop();
|
m_watch.stop();
|
||||||
IF_VERBOSE(SAT_VB_LVL,
|
IF_VERBOSE(SAT_VB_LVL,
|
||||||
verbose_stream() << " (sat-blocked-clauses :elim-blocked-clauses "
|
verbose_stream() << " (sat-blocked-clauses :elim-blocked-clauses "
|
||||||
<< (m_simplifier.m_num_blocked_clauses - m_num_blocked_clauses)
|
<< (m_simplifier.m_num_blocked_clauses - m_num_blocked_clauses)
|
||||||
<< mem_stat()
|
<< mem_stat()
|
||||||
<< " :time " << std::fixed << std::setprecision(2) << m_watch.get_seconds() << ")\n";);
|
<< " :time " << std::fixed << std::setprecision(2) << m_watch.get_seconds() << ")\n";);
|
||||||
}
|
}
|
||||||
|
@ -1062,8 +1064,8 @@ namespace sat {
|
||||||
unsigned num_neg = m_use_list.get(neg_l).size();
|
unsigned num_neg = m_use_list.get(neg_l).size();
|
||||||
unsigned num_bin_pos = get_num_non_learned_bin(pos_l);
|
unsigned num_bin_pos = get_num_non_learned_bin(pos_l);
|
||||||
unsigned num_bin_neg = get_num_non_learned_bin(neg_l);
|
unsigned num_bin_neg = get_num_non_learned_bin(neg_l);
|
||||||
unsigned cost = 2 * num_pos * num_neg + num_pos * num_bin_neg + num_neg * num_bin_pos;
|
unsigned cost = 2 * num_pos * num_neg + num_pos * num_bin_neg + num_neg * num_bin_pos;
|
||||||
CTRACE("elim_vars_detail", cost == 0, tout << v << " num_pos: " << num_pos << " num_neg: " << num_neg << " num_bin_pos: " << num_bin_pos
|
CTRACE("elim_vars_detail", cost == 0, tout << v << " num_pos: " << num_pos << " num_neg: " << num_neg << " num_bin_pos: " << num_bin_pos
|
||||||
<< " num_bin_neg: " << num_bin_neg << " cost: " << cost << "\n";);
|
<< " num_bin_neg: " << num_bin_neg << " cost: " << cost << "\n";);
|
||||||
return cost;
|
return cost;
|
||||||
}
|
}
|
||||||
|
@ -1071,7 +1073,7 @@ namespace sat {
|
||||||
typedef std::pair<bool_var, unsigned> bool_var_and_cost;
|
typedef std::pair<bool_var, unsigned> bool_var_and_cost;
|
||||||
|
|
||||||
struct bool_var_and_cost_lt {
|
struct bool_var_and_cost_lt {
|
||||||
bool operator()(bool_var_and_cost const & p1, bool_var_and_cost const & p2) const { return p1.second < p2.second; }
|
bool operator()(bool_var_and_cost const & p1, bool_var_and_cost const & p2) const { return p1.second < p2.second; }
|
||||||
};
|
};
|
||||||
|
|
||||||
void simplifier::order_vars_for_elim(bool_var_vector & r) {
|
void simplifier::order_vars_for_elim(bool_var_vector & r) {
|
||||||
|
@ -1104,7 +1106,7 @@ namespace sat {
|
||||||
r.push_back(it2->first);
|
r.push_back(it2->first);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
\brief Collect clauses and binary clauses containing l.
|
\brief Collect clauses and binary clauses containing l.
|
||||||
*/
|
*/
|
||||||
|
@ -1116,7 +1118,7 @@ namespace sat {
|
||||||
SASSERT(r.back().size() == it.curr().size());
|
SASSERT(r.back().size() == it.curr().size());
|
||||||
it.next();
|
it.next();
|
||||||
}
|
}
|
||||||
|
|
||||||
watch_list & wlist = get_wlist(~l);
|
watch_list & wlist = get_wlist(~l);
|
||||||
watch_list::iterator it2 = wlist.begin();
|
watch_list::iterator it2 = wlist.begin();
|
||||||
watch_list::iterator end2 = wlist.end();
|
watch_list::iterator end2 = wlist.end();
|
||||||
|
@ -1129,7 +1131,7 @@ namespace sat {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
\brief Resolve clauses c1 and c2.
|
\brief Resolve clauses c1 and c2.
|
||||||
c1 must contain l.
|
c1 must contain l.
|
||||||
c2 must contain ~l.
|
c2 must contain ~l.
|
||||||
Store result in r.
|
Store result in r.
|
||||||
|
@ -1149,7 +1151,7 @@ namespace sat {
|
||||||
m_visited[l2.index()] = true;
|
m_visited[l2.index()] = true;
|
||||||
r.push_back(l2);
|
r.push_back(l2);
|
||||||
}
|
}
|
||||||
|
|
||||||
literal not_l = ~l;
|
literal not_l = ~l;
|
||||||
sz = c2.size();
|
sz = c2.size();
|
||||||
m_elim_counter -= sz;
|
m_elim_counter -= sz;
|
||||||
|
@ -1164,7 +1166,7 @@ namespace sat {
|
||||||
if (!m_visited[l2.index()])
|
if (!m_visited[l2.index()])
|
||||||
r.push_back(l2);
|
r.push_back(l2);
|
||||||
}
|
}
|
||||||
|
|
||||||
sz = c1.size();
|
sz = c1.size();
|
||||||
for (unsigned i = 0; i < sz; i++) {
|
for (unsigned i = 0; i < sz; i++) {
|
||||||
literal l2 = c1[i];
|
literal l2 = c1[i];
|
||||||
|
@ -1200,7 +1202,7 @@ namespace sat {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
CTRACE("resolve_bug", it2 == end2,
|
CTRACE("resolve_bug", it2 == end2,
|
||||||
tout << ~l1 << " -> ";
|
tout << ~l1 << " -> ";
|
||||||
display(tout, s.m_cls_allocator, wlist1); tout << "\n" << ~l2 << " -> ";
|
display(tout, s.m_cls_allocator, wlist1); tout << "\n" << ~l2 << " -> ";
|
||||||
display(tout, s.m_cls_allocator, wlist2); tout << "\n";);
|
display(tout, s.m_cls_allocator, wlist2); tout << "\n";);
|
||||||
|
@ -1262,7 +1264,7 @@ namespace sat {
|
||||||
TRACE("resolution_bug", tout << "processing: " << v << "\n";);
|
TRACE("resolution_bug", tout << "processing: " << v << "\n";);
|
||||||
if (value(v) != l_undef)
|
if (value(v) != l_undef)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
literal pos_l(v, false);
|
literal pos_l(v, false);
|
||||||
literal neg_l(v, true);
|
literal neg_l(v, true);
|
||||||
unsigned num_bin_pos = get_num_non_learned_bin(pos_l);
|
unsigned num_bin_pos = get_num_non_learned_bin(pos_l);
|
||||||
|
@ -1274,12 +1276,12 @@ namespace sat {
|
||||||
m_elim_counter -= num_pos + num_neg;
|
m_elim_counter -= num_pos + num_neg;
|
||||||
|
|
||||||
TRACE("resolution", tout << v << " num_pos: " << num_pos << " neg_pos: " << num_neg << "\n";);
|
TRACE("resolution", tout << v << " num_pos: " << num_pos << " neg_pos: " << num_neg << "\n";);
|
||||||
|
|
||||||
if (num_pos >= m_res_occ_cutoff && num_neg >= m_res_occ_cutoff)
|
if (num_pos >= m_res_occ_cutoff && num_neg >= m_res_occ_cutoff)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
unsigned before_lits = num_bin_pos*2 + num_bin_neg*2;
|
unsigned before_lits = num_bin_pos*2 + num_bin_neg*2;
|
||||||
|
|
||||||
{
|
{
|
||||||
clause_use_list::iterator it = pos_occs.mk_iterator();
|
clause_use_list::iterator it = pos_occs.mk_iterator();
|
||||||
while (!it.at_end()) {
|
while (!it.at_end()) {
|
||||||
|
@ -1287,7 +1289,7 @@ namespace sat {
|
||||||
it.next();
|
it.next();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
clause_use_list::iterator it2 = neg_occs.mk_iterator();
|
clause_use_list::iterator it2 = neg_occs.mk_iterator();
|
||||||
while (!it2.at_end()) {
|
while (!it2.at_end()) {
|
||||||
|
@ -1297,23 +1299,23 @@ namespace sat {
|
||||||
}
|
}
|
||||||
|
|
||||||
TRACE("resolution", tout << v << " num_pos: " << num_pos << " neg_pos: " << num_neg << " before_lits: " << before_lits << "\n";);
|
TRACE("resolution", tout << v << " num_pos: " << num_pos << " neg_pos: " << num_neg << " before_lits: " << before_lits << "\n";);
|
||||||
|
|
||||||
if (num_pos >= m_res_occ_cutoff3 && num_neg >= m_res_occ_cutoff3 && before_lits > m_res_lit_cutoff3 && s.m_clauses.size() > m_res_cls_cutoff2)
|
if (num_pos >= m_res_occ_cutoff3 && num_neg >= m_res_occ_cutoff3 && before_lits > m_res_lit_cutoff3 && s.m_clauses.size() > m_res_cls_cutoff2)
|
||||||
return false;
|
return false;
|
||||||
if (num_pos >= m_res_occ_cutoff2 && num_neg >= m_res_occ_cutoff2 && before_lits > m_res_lit_cutoff2 &&
|
if (num_pos >= m_res_occ_cutoff2 && num_neg >= m_res_occ_cutoff2 && before_lits > m_res_lit_cutoff2 &&
|
||||||
s.m_clauses.size() > m_res_cls_cutoff1 && s.m_clauses.size() <= m_res_cls_cutoff2)
|
s.m_clauses.size() > m_res_cls_cutoff1 && s.m_clauses.size() <= m_res_cls_cutoff2)
|
||||||
return false;
|
return false;
|
||||||
if (num_pos >= m_res_occ_cutoff1 && num_neg >= m_res_occ_cutoff1 && before_lits > m_res_lit_cutoff1 &&
|
if (num_pos >= m_res_occ_cutoff1 && num_neg >= m_res_occ_cutoff1 && before_lits > m_res_lit_cutoff1 &&
|
||||||
s.m_clauses.size() <= m_res_cls_cutoff1)
|
s.m_clauses.size() <= m_res_cls_cutoff1)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
m_pos_cls.reset();
|
m_pos_cls.reset();
|
||||||
m_neg_cls.reset();
|
m_neg_cls.reset();
|
||||||
collect_clauses(pos_l, m_pos_cls);
|
collect_clauses(pos_l, m_pos_cls);
|
||||||
collect_clauses(neg_l, m_neg_cls);
|
collect_clauses(neg_l, m_neg_cls);
|
||||||
|
|
||||||
m_elim_counter -= num_pos * num_neg + before_lits;
|
m_elim_counter -= num_pos * num_neg + before_lits;
|
||||||
|
|
||||||
TRACE("resolution_detail", tout << "collecting number of after_clauses\n";);
|
TRACE("resolution_detail", tout << "collecting number of after_clauses\n";);
|
||||||
unsigned before_clauses = num_pos + num_neg;
|
unsigned before_clauses = num_pos + num_neg;
|
||||||
unsigned after_clauses = 0;
|
unsigned after_clauses = 0;
|
||||||
|
@ -1350,7 +1352,7 @@ namespace sat {
|
||||||
neg_occs.reset();
|
neg_occs.reset();
|
||||||
|
|
||||||
m_elim_counter -= num_pos * num_neg + before_lits;
|
m_elim_counter -= num_pos * num_neg + before_lits;
|
||||||
|
|
||||||
it1 = m_pos_cls.begin();
|
it1 = m_pos_cls.begin();
|
||||||
end1 = m_pos_cls.end();
|
end1 = m_pos_cls.end();
|
||||||
for (; it1 != end1; ++it1) {
|
for (; it1 != end1; ++it1) {
|
||||||
|
@ -1393,7 +1395,7 @@ namespace sat {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1406,10 +1408,10 @@ namespace sat {
|
||||||
m_num_elim_vars(s.m_num_elim_vars) {
|
m_num_elim_vars(s.m_num_elim_vars) {
|
||||||
m_watch.start();
|
m_watch.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
~elim_var_report() {
|
~elim_var_report() {
|
||||||
m_watch.stop();
|
m_watch.stop();
|
||||||
IF_VERBOSE(SAT_VB_LVL,
|
IF_VERBOSE(SAT_VB_LVL,
|
||||||
verbose_stream() << " (sat-resolution :elim-bool-vars "
|
verbose_stream() << " (sat-resolution :elim-bool-vars "
|
||||||
<< (m_simplifier.m_num_elim_vars - m_num_elim_vars)
|
<< (m_simplifier.m_num_elim_vars - m_num_elim_vars)
|
||||||
<< " :threshold " << m_simplifier.m_elim_counter
|
<< " :threshold " << m_simplifier.m_elim_counter
|
||||||
|
@ -1417,12 +1419,12 @@ namespace sat {
|
||||||
<< " :time " << std::fixed << std::setprecision(2) << m_watch.get_seconds() << ")\n";);
|
<< " :time " << std::fixed << std::setprecision(2) << m_watch.get_seconds() << ")\n";);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
void simplifier::elim_vars() {
|
void simplifier::elim_vars() {
|
||||||
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);
|
||||||
|
|
||||||
bool_var_vector::iterator it = vars.begin();
|
bool_var_vector::iterator it = vars.begin();
|
||||||
bool_var_vector::iterator end = vars.end();
|
bool_var_vector::iterator end = vars.end();
|
||||||
for (; it != end; ++it) {
|
for (; it != end; ++it) {
|
||||||
|
@ -1463,7 +1465,7 @@ namespace sat {
|
||||||
void simplifier::collect_param_descrs(param_descrs & r) {
|
void simplifier::collect_param_descrs(param_descrs & r) {
|
||||||
sat_simplifier_params::collect_param_descrs(r);
|
sat_simplifier_params::collect_param_descrs(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
void simplifier::collect_statistics(statistics & st) {
|
void simplifier::collect_statistics(statistics & st) {
|
||||||
st.update("subsumed", m_num_subsumed);
|
st.update("subsumed", m_num_subsumed);
|
||||||
st.update("subsumption resolution", m_num_sub_res);
|
st.update("subsumption resolution", m_num_sub_res);
|
||||||
|
@ -1471,7 +1473,7 @@ namespace sat {
|
||||||
st.update("elim bool vars", m_num_elim_vars);
|
st.update("elim bool vars", m_num_elim_vars);
|
||||||
st.update("elim blocked clauses", m_num_blocked_clauses);
|
st.update("elim blocked clauses", m_num_blocked_clauses);
|
||||||
}
|
}
|
||||||
|
|
||||||
void simplifier::reset_statistics() {
|
void simplifier::reset_statistics() {
|
||||||
m_num_blocked_clauses = 0;
|
m_num_blocked_clauses = 0;
|
||||||
m_num_subsumed = 0;
|
m_num_subsumed = 0;
|
||||||
|
|
|
@ -27,7 +27,7 @@ Revision History:
|
||||||
// define to create a copy of the solver before starting the search
|
// define to create a copy of the solver before starting the search
|
||||||
// useful for checking models
|
// useful for checking models
|
||||||
// #define CLONE_BEFORE_SOLVING
|
// #define CLONE_BEFORE_SOLVING
|
||||||
|
|
||||||
namespace sat {
|
namespace sat {
|
||||||
|
|
||||||
solver::solver(params_ref const & p, extension * ext):
|
solver::solver(params_ref const & p, extension * ext):
|
||||||
|
@ -103,7 +103,7 @@ namespace sat {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------
|
// -----------------------
|
||||||
//
|
//
|
||||||
// Variable & Clause creation
|
// Variable & Clause creation
|
||||||
|
@ -312,7 +312,7 @@ namespace sat {
|
||||||
/**
|
/**
|
||||||
\brief Select a watch literal starting the search at the given position.
|
\brief Select a watch literal starting the search at the given position.
|
||||||
This method is only used for clauses created during the search.
|
This method is only used for clauses created during the search.
|
||||||
|
|
||||||
I use the following rules to select a watch literal.
|
I use the following rules to select a watch literal.
|
||||||
|
|
||||||
1- select a literal l in idx >= starting_at such that value(l) = l_true,
|
1- select a literal l in idx >= starting_at such that value(l) = l_true,
|
||||||
|
@ -329,7 +329,7 @@ namespace sat {
|
||||||
lvl(l) >= lvl(l')
|
lvl(l) >= lvl(l')
|
||||||
|
|
||||||
Without rule 3, boolean propagation is incomplete, that is, it may miss possible propagations.
|
Without rule 3, boolean propagation is incomplete, that is, it may miss possible propagations.
|
||||||
|
|
||||||
\remark The method select_lemma_watch_lit is used to select the watch literal for regular learned clauses.
|
\remark The method select_lemma_watch_lit is used to select the watch literal for regular learned clauses.
|
||||||
*/
|
*/
|
||||||
unsigned solver::select_watch_lit(clause const & cls, unsigned starting_at) const {
|
unsigned solver::select_watch_lit(clause const & cls, unsigned starting_at) const {
|
||||||
|
@ -443,7 +443,7 @@ namespace sat {
|
||||||
erase_clause_watch(get_wlist(~c[0]), cls_off);
|
erase_clause_watch(get_wlist(~c[0]), cls_off);
|
||||||
erase_clause_watch(get_wlist(~c[1]), cls_off);
|
erase_clause_watch(get_wlist(~c[1]), cls_off);
|
||||||
}
|
}
|
||||||
|
|
||||||
void solver::dettach_ter_clause(clause & c) {
|
void solver::dettach_ter_clause(clause & c) {
|
||||||
erase_ternary_watch(get_wlist(~c[0]), c[1], c[2]);
|
erase_ternary_watch(get_wlist(~c[0]), c[1], c[2]);
|
||||||
erase_ternary_watch(get_wlist(~c[1]), c[0], c[2]);
|
erase_ternary_watch(get_wlist(~c[1]), c[0], c[2]);
|
||||||
|
@ -498,10 +498,10 @@ namespace sat {
|
||||||
unsigned sz = c.size();
|
unsigned sz = c.size();
|
||||||
for (unsigned i = 0; i < sz; i++) {
|
for (unsigned i = 0; i < sz; i++) {
|
||||||
switch (value(c[i])) {
|
switch (value(c[i])) {
|
||||||
case l_true:
|
case l_true:
|
||||||
return l_true;
|
return l_true;
|
||||||
case l_undef:
|
case l_undef:
|
||||||
found_undef = true;
|
found_undef = true;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -515,7 +515,7 @@ namespace sat {
|
||||||
// Propagation
|
// Propagation
|
||||||
//
|
//
|
||||||
// -----------------------
|
// -----------------------
|
||||||
|
|
||||||
bool solver::propagate_core(bool update) {
|
bool solver::propagate_core(bool update) {
|
||||||
if (m_inconsistent)
|
if (m_inconsistent)
|
||||||
return false;
|
return false;
|
||||||
|
@ -545,7 +545,7 @@ namespace sat {
|
||||||
}
|
}
|
||||||
for (; it != end; ++it) {
|
for (; it != end; ++it) {
|
||||||
switch (it->get_kind()) {
|
switch (it->get_kind()) {
|
||||||
case watched::BINARY:
|
case watched::BINARY:
|
||||||
l1 = it->get_literal();
|
l1 = it->get_literal();
|
||||||
switch (value(l1)) {
|
switch (value(l1)) {
|
||||||
case l_false:
|
case l_false:
|
||||||
|
@ -585,12 +585,26 @@ namespace sat {
|
||||||
break;
|
break;
|
||||||
case watched::CLAUSE: {
|
case watched::CLAUSE: {
|
||||||
if (value(it->get_blocked_literal()) == l_true) {
|
if (value(it->get_blocked_literal()) == l_true) {
|
||||||
|
TRACE("propagate_clause_bug", tout << "blocked literal " << it->get_blocked_literal() << "\n";
|
||||||
|
clause_offset cls_off = it->get_clause_offset();
|
||||||
|
clause & c = *(m_cls_allocator.get_clause(cls_off));
|
||||||
|
tout << c << "\n";);
|
||||||
*it2 = *it;
|
*it2 = *it;
|
||||||
it2++;
|
it2++;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
clause_offset cls_off = it->get_clause_offset();
|
clause_offset cls_off = it->get_clause_offset();
|
||||||
clause & c = *(m_cls_allocator.get_clause(cls_off));
|
clause & c = *(m_cls_allocator.get_clause(cls_off));
|
||||||
|
TRACE("propagate_clause_bug", tout << "processing... " << c << "\nwas_removed: " << c.was_removed() << "\n";);
|
||||||
|
if (c.was_removed()) {
|
||||||
|
// Remark: this method may be invoked when the watch lists are not in a consistent state,
|
||||||
|
// and may contain dead/removed clauses.
|
||||||
|
// See: sat_simplifier.cpp
|
||||||
|
// So, we must check whether the clause was marked for deletion, and ignore it.
|
||||||
|
*it2 = *it;
|
||||||
|
it2++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
if (c[0] == not_l)
|
if (c[0] == not_l)
|
||||||
std::swap(c[0], c[1]);
|
std::swap(c[0], c[1]);
|
||||||
CTRACE("propagate_bug", c[1] != not_l, tout << "l: " << l << " " << c << "\n";);
|
CTRACE("propagate_bug", c[1] != not_l, tout << "l: " << l << " " << c << "\n";);
|
||||||
|
@ -693,7 +707,7 @@ namespace sat {
|
||||||
m_conflicts_since_restart = 0;
|
m_conflicts_since_restart = 0;
|
||||||
m_restart_threshold = m_config.m_restart_initial;
|
m_restart_threshold = m_config.m_restart_initial;
|
||||||
}
|
}
|
||||||
|
|
||||||
// iff3_finder(*this)();
|
// iff3_finder(*this)();
|
||||||
simplify_problem();
|
simplify_problem();
|
||||||
|
|
||||||
|
@ -704,10 +718,10 @@ namespace sat {
|
||||||
IF_VERBOSE(SAT_VB_LVL, verbose_stream() << "\"abort: max-conflicts = 0\"\n";);
|
IF_VERBOSE(SAT_VB_LVL, verbose_stream() << "\"abort: max-conflicts = 0\"\n";);
|
||||||
return l_undef;
|
return l_undef;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
SASSERT(!inconsistent());
|
SASSERT(!inconsistent());
|
||||||
|
|
||||||
lbool r = bounded_search();
|
lbool r = bounded_search();
|
||||||
if (r != l_undef)
|
if (r != l_undef)
|
||||||
return r;
|
return r;
|
||||||
|
@ -716,7 +730,7 @@ namespace sat {
|
||||||
IF_VERBOSE(SAT_VB_LVL, verbose_stream() << "\"abort: max-conflicts = " << m_conflicts << "\"\n";);
|
IF_VERBOSE(SAT_VB_LVL, verbose_stream() << "\"abort: max-conflicts = " << m_conflicts << "\"\n";);
|
||||||
return l_undef;
|
return l_undef;
|
||||||
}
|
}
|
||||||
|
|
||||||
restart();
|
restart();
|
||||||
if (m_conflicts >= m_next_simplify) {
|
if (m_conflicts >= m_next_simplify) {
|
||||||
simplify_problem();
|
simplify_problem();
|
||||||
|
@ -734,7 +748,7 @@ namespace sat {
|
||||||
|
|
||||||
bool_var solver::next_var() {
|
bool_var solver::next_var() {
|
||||||
bool_var next;
|
bool_var next;
|
||||||
|
|
||||||
if (m_rand() < static_cast<int>(m_config.m_random_freq * random_gen::max_value())) {
|
if (m_rand() < static_cast<int>(m_config.m_random_freq * random_gen::max_value())) {
|
||||||
if (num_vars() == 0)
|
if (num_vars() == 0)
|
||||||
return null_bool_var;
|
return null_bool_var;
|
||||||
|
@ -743,16 +757,16 @@ namespace sat {
|
||||||
if (value(next) == l_undef && !was_eliminated(next))
|
if (value(next) == l_undef && !was_eliminated(next))
|
||||||
return next;
|
return next;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (!m_case_split_queue.empty()) {
|
while (!m_case_split_queue.empty()) {
|
||||||
next = m_case_split_queue.next_var();
|
next = m_case_split_queue.next_var();
|
||||||
if (value(next) == l_undef && !was_eliminated(next))
|
if (value(next) == l_undef && !was_eliminated(next))
|
||||||
return next;
|
return next;
|
||||||
}
|
}
|
||||||
|
|
||||||
return null_bool_var;
|
return null_bool_var;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool solver::decide() {
|
bool solver::decide() {
|
||||||
bool_var next = next_var();
|
bool_var next = next_var();
|
||||||
if (next == null_bool_var)
|
if (next == null_bool_var)
|
||||||
|
@ -760,7 +774,7 @@ namespace sat {
|
||||||
push();
|
push();
|
||||||
m_stats.m_decision++;
|
m_stats.m_decision++;
|
||||||
lbool phase = m_ext ? m_ext->get_phase(next) : l_undef;
|
lbool phase = m_ext ? m_ext->get_phase(next) : l_undef;
|
||||||
|
|
||||||
if (phase == l_undef) {
|
if (phase == l_undef) {
|
||||||
switch (m_config.m_phase) {
|
switch (m_config.m_phase) {
|
||||||
case PS_ALWAYS_TRUE:
|
case PS_ALWAYS_TRUE:
|
||||||
|
@ -784,7 +798,7 @@ namespace sat {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SASSERT(phase != l_undef);
|
SASSERT(phase != l_undef);
|
||||||
literal next_lit(next, phase == l_false);
|
literal next_lit(next, phase == l_false);
|
||||||
assign(next_lit, justification());
|
assign(next_lit, justification());
|
||||||
|
@ -807,23 +821,23 @@ namespace sat {
|
||||||
return l_undef;
|
return l_undef;
|
||||||
if (scope_lvl() == 0) {
|
if (scope_lvl() == 0) {
|
||||||
cleanup(); // cleaner may propagate frozen clauses
|
cleanup(); // cleaner may propagate frozen clauses
|
||||||
if (inconsistent())
|
if (inconsistent())
|
||||||
return l_false;
|
return l_false;
|
||||||
gc();
|
gc();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
gc();
|
gc();
|
||||||
|
|
||||||
if (!decide()) {
|
if (!decide()) {
|
||||||
if (m_ext) {
|
if (m_ext) {
|
||||||
switch (m_ext->check()) {
|
switch (m_ext->check()) {
|
||||||
case CR_DONE:
|
case CR_DONE:
|
||||||
mk_model();
|
mk_model();
|
||||||
return l_true;
|
return l_true;
|
||||||
case CR_CONTINUE:
|
case CR_CONTINUE:
|
||||||
break;
|
break;
|
||||||
case CR_GIVEUP:
|
case CR_GIVEUP:
|
||||||
throw abort_solver();
|
throw abort_solver();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -849,23 +863,23 @@ namespace sat {
|
||||||
m_stopwatch.reset();
|
m_stopwatch.reset();
|
||||||
m_stopwatch.start();
|
m_stopwatch.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
\brief Apply all simplifications.
|
\brief Apply all simplifications.
|
||||||
*/
|
*/
|
||||||
void solver::simplify_problem() {
|
void solver::simplify_problem() {
|
||||||
SASSERT(scope_lvl() == 0);
|
SASSERT(scope_lvl() == 0);
|
||||||
|
|
||||||
m_cleaner();
|
m_cleaner();
|
||||||
CASSERT("sat_simplify_bug", check_invariant());
|
CASSERT("sat_simplify_bug", check_invariant());
|
||||||
|
|
||||||
m_scc();
|
m_scc();
|
||||||
CASSERT("sat_simplify_bug", check_invariant());
|
CASSERT("sat_simplify_bug", check_invariant());
|
||||||
|
|
||||||
m_simplifier(false);
|
m_simplifier(false);
|
||||||
CASSERT("sat_simplify_bug", check_invariant());
|
CASSERT("sat_simplify_bug", check_invariant());
|
||||||
CASSERT("sat_missed_prop", check_missed_propagation());
|
CASSERT("sat_missed_prop", check_missed_propagation());
|
||||||
|
|
||||||
if (!m_learned.empty()) {
|
if (!m_learned.empty()) {
|
||||||
m_simplifier(true);
|
m_simplifier(true);
|
||||||
CASSERT("sat_missed_prop", check_missed_propagation());
|
CASSERT("sat_missed_prop", check_missed_propagation());
|
||||||
|
@ -878,11 +892,11 @@ namespace sat {
|
||||||
m_probing();
|
m_probing();
|
||||||
CASSERT("sat_missed_prop", check_missed_propagation());
|
CASSERT("sat_missed_prop", check_missed_propagation());
|
||||||
CASSERT("sat_simplify_bug", check_invariant());
|
CASSERT("sat_simplify_bug", check_invariant());
|
||||||
|
|
||||||
m_asymm_branch();
|
m_asymm_branch();
|
||||||
CASSERT("sat_missed_prop", check_missed_propagation());
|
CASSERT("sat_missed_prop", check_missed_propagation());
|
||||||
CASSERT("sat_simplify_bug", check_invariant());
|
CASSERT("sat_simplify_bug", check_invariant());
|
||||||
|
|
||||||
if (m_ext) {
|
if (m_ext) {
|
||||||
m_ext->clauses_modifed();
|
m_ext->clauses_modifed();
|
||||||
m_ext->simplify();
|
m_ext->simplify();
|
||||||
|
@ -956,7 +970,7 @@ namespace sat {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!m_mc.check_model(m))
|
if (!m_mc.check_model(m))
|
||||||
ok = false;
|
ok = false;
|
||||||
CTRACE("sat_model_bug", !ok, tout << m << "\n";);
|
CTRACE("sat_model_bug", !ok, tout << m << "\n";);
|
||||||
return ok;
|
return ok;
|
||||||
|
@ -964,9 +978,9 @@ namespace sat {
|
||||||
|
|
||||||
void solver::restart() {
|
void solver::restart() {
|
||||||
m_stats.m_restart++;
|
m_stats.m_restart++;
|
||||||
IF_VERBOSE(1,
|
IF_VERBOSE(1,
|
||||||
verbose_stream() << "(sat-restart :conflicts " << m_stats.m_conflict << " :decisions " << m_stats.m_decision
|
verbose_stream() << "(sat-restart :conflicts " << m_stats.m_conflict << " :decisions " << m_stats.m_decision
|
||||||
<< " :restarts " << m_stats.m_restart << mk_stat(*this)
|
<< " :restarts " << m_stats.m_restart << mk_stat(*this)
|
||||||
<< " :time " << std::fixed << std::setprecision(2) << m_stopwatch.get_current_seconds() << ")\n";);
|
<< " :time " << std::fixed << std::setprecision(2) << m_stopwatch.get_current_seconds() << ")\n";);
|
||||||
IF_VERBOSE(30, display_status(verbose_stream()););
|
IF_VERBOSE(30, display_status(verbose_stream()););
|
||||||
pop(scope_lvl());
|
pop(scope_lvl());
|
||||||
|
@ -991,9 +1005,9 @@ namespace sat {
|
||||||
// GC
|
// GC
|
||||||
//
|
//
|
||||||
// -----------------------
|
// -----------------------
|
||||||
|
|
||||||
void solver::gc() {
|
void solver::gc() {
|
||||||
if (m_conflicts_since_gc <= m_gc_threshold)
|
if (m_conflicts_since_gc <= m_gc_threshold)
|
||||||
return;
|
return;
|
||||||
CASSERT("sat_gc_bug", check_invariant());
|
CASSERT("sat_gc_bug", check_invariant());
|
||||||
switch (m_config.m_gc_strategy) {
|
switch (m_config.m_gc_strategy) {
|
||||||
|
@ -1073,7 +1087,7 @@ namespace sat {
|
||||||
std::stable_sort(m_learned.begin(), m_learned.end(), glue_lt());
|
std::stable_sort(m_learned.begin(), m_learned.end(), glue_lt());
|
||||||
gc_half("glue");
|
gc_half("glue");
|
||||||
}
|
}
|
||||||
|
|
||||||
void solver::gc_psm() {
|
void solver::gc_psm() {
|
||||||
save_psm();
|
save_psm();
|
||||||
std::stable_sort(m_learned.begin(), m_learned.end(), psm_lt());
|
std::stable_sort(m_learned.begin(), m_learned.end(), psm_lt());
|
||||||
|
@ -1134,8 +1148,8 @@ namespace sat {
|
||||||
void solver::gc_dyn_psm() {
|
void solver::gc_dyn_psm() {
|
||||||
// To do gc at scope_lvl() > 0, I will need to use the reinitialization stack, or live with the fact
|
// To do gc at scope_lvl() > 0, I will need to use the reinitialization stack, or live with the fact
|
||||||
// that I may miss some propagations for reactivated clauses.
|
// that I may miss some propagations for reactivated clauses.
|
||||||
SASSERT(scope_lvl() == 0);
|
SASSERT(scope_lvl() == 0);
|
||||||
// compute
|
// compute
|
||||||
// d_tk
|
// d_tk
|
||||||
unsigned h = 0;
|
unsigned h = 0;
|
||||||
unsigned V_tk = 0;
|
unsigned V_tk = 0;
|
||||||
|
@ -1152,7 +1166,7 @@ namespace sat {
|
||||||
double d_tk = V_tk == 0 ? static_cast<double>(num_vars() + 1) : static_cast<double>(h)/static_cast<double>(V_tk);
|
double d_tk = V_tk == 0 ? static_cast<double>(num_vars() + 1) : static_cast<double>(h)/static_cast<double>(V_tk);
|
||||||
if (d_tk < m_min_d_tk)
|
if (d_tk < m_min_d_tk)
|
||||||
m_min_d_tk = d_tk;
|
m_min_d_tk = d_tk;
|
||||||
TRACE("sat_frozen", tout << "m_min_d_tk: " << m_min_d_tk << "\n";);
|
TRACE("sat_frozen", tout << "m_min_d_tk: " << m_min_d_tk << "\n";);
|
||||||
unsigned frozen = 0;
|
unsigned frozen = 0;
|
||||||
unsigned deleted = 0;
|
unsigned deleted = 0;
|
||||||
unsigned activated = 0;
|
unsigned activated = 0;
|
||||||
|
@ -1218,15 +1232,15 @@ namespace sat {
|
||||||
++it2;
|
++it2;
|
||||||
}
|
}
|
||||||
m_learned.set_end(it2);
|
m_learned.set_end(it2);
|
||||||
IF_VERBOSE(SAT_VB_LVL, verbose_stream() << "(sat-gc :d_tk " << d_tk << " :min-d_tk " << m_min_d_tk <<
|
IF_VERBOSE(SAT_VB_LVL, verbose_stream() << "(sat-gc :d_tk " << d_tk << " :min-d_tk " << m_min_d_tk <<
|
||||||
" :frozen " << frozen << " :activated " << activated << " :deleted " << deleted << ")\n";);
|
" :frozen " << frozen << " :activated " << activated << " :deleted " << deleted << ")\n";);
|
||||||
}
|
}
|
||||||
|
|
||||||
// return true if should keep the clause, and false if we should delete it.
|
// return true if should keep the clause, and false if we should delete it.
|
||||||
bool solver::activate_frozen_clause(clause & c) {
|
bool solver::activate_frozen_clause(clause & c) {
|
||||||
TRACE("sat_gc", tout << "reactivating:\n" << c << "\n";);
|
TRACE("sat_gc", tout << "reactivating:\n" << c << "\n";);
|
||||||
SASSERT(scope_lvl() == 0);
|
SASSERT(scope_lvl() == 0);
|
||||||
// do some cleanup
|
// do some cleanup
|
||||||
unsigned sz = c.size();
|
unsigned sz = c.size();
|
||||||
unsigned j = 0;
|
unsigned j = 0;
|
||||||
for (unsigned i = 0; i < sz; i++) {
|
for (unsigned i = 0; i < sz; i++) {
|
||||||
|
@ -1292,7 +1306,7 @@ namespace sat {
|
||||||
bool r = resolve_conflict_core();
|
bool r = resolve_conflict_core();
|
||||||
CASSERT("sat_check_marks", check_marks());
|
CASSERT("sat_check_marks", check_marks());
|
||||||
// after pop, clauses are reinitialized, this may trigger another conflict.
|
// after pop, clauses are reinitialized, this may trigger another conflict.
|
||||||
if (!r)
|
if (!r)
|
||||||
return false;
|
return false;
|
||||||
if (!inconsistent())
|
if (!inconsistent())
|
||||||
return true;
|
return true;
|
||||||
|
@ -1311,7 +1325,7 @@ namespace sat {
|
||||||
if (m_conflict_lvl == 0)
|
if (m_conflict_lvl == 0)
|
||||||
return false;
|
return false;
|
||||||
m_lemma.reset();
|
m_lemma.reset();
|
||||||
|
|
||||||
forget_phase_of_vars(m_conflict_lvl);
|
forget_phase_of_vars(m_conflict_lvl);
|
||||||
|
|
||||||
unsigned idx = skip_literals_above_conflict_level();
|
unsigned idx = skip_literals_above_conflict_level();
|
||||||
|
@ -1326,7 +1340,7 @@ namespace sat {
|
||||||
|
|
||||||
literal consequent = m_not_l;
|
literal consequent = m_not_l;
|
||||||
justification js = m_conflict;
|
justification js = m_conflict;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
TRACE("sat_conflict_detail", tout << "processing consequent: " << consequent << "\n";
|
TRACE("sat_conflict_detail", tout << "processing consequent: " << consequent << "\n";
|
||||||
tout << "num_marks: " << num_marks << ", js kind: " << js.get_kind() << "\n";);
|
tout << "num_marks: " << num_marks << ", js kind: " << js.get_kind() << "\n";);
|
||||||
|
@ -1362,7 +1376,7 @@ namespace sat {
|
||||||
fill_ext_antecedents(consequent, js);
|
fill_ext_antecedents(consequent, js);
|
||||||
literal_vector::iterator it = m_ext_antecedents.begin();
|
literal_vector::iterator it = m_ext_antecedents.begin();
|
||||||
literal_vector::iterator end = m_ext_antecedents.end();
|
literal_vector::iterator end = m_ext_antecedents.end();
|
||||||
for (; it != end; ++it)
|
for (; it != end; ++it)
|
||||||
process_antecedent(*it, num_marks);
|
process_antecedent(*it, num_marks);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1370,10 +1384,10 @@ namespace sat {
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
literal l = m_trail[idx];
|
literal l = m_trail[idx];
|
||||||
if (is_marked(l.var()))
|
if (is_marked(l.var()))
|
||||||
break;
|
break;
|
||||||
SASSERT(idx > 0);
|
SASSERT(idx > 0);
|
||||||
idx--;
|
idx--;
|
||||||
|
@ -1386,9 +1400,9 @@ namespace sat {
|
||||||
idx--;
|
idx--;
|
||||||
num_marks--;
|
num_marks--;
|
||||||
reset_mark(c_var);
|
reset_mark(c_var);
|
||||||
}
|
}
|
||||||
while (num_marks > 0);
|
while (num_marks > 0);
|
||||||
|
|
||||||
m_lemma[0] = ~consequent;
|
m_lemma[0] = ~consequent;
|
||||||
TRACE("sat_lemma", tout << "new lemma size: " << m_lemma.size() << "\n" << m_lemma << "\n";);
|
TRACE("sat_lemma", tout << "new lemma size: " << m_lemma.size() << "\n" << m_lemma << "\n";);
|
||||||
|
|
||||||
|
@ -1401,7 +1415,7 @@ namespace sat {
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
reset_lemma_var_marks();
|
reset_lemma_var_marks();
|
||||||
|
|
||||||
literal_vector::iterator it = m_lemma.begin();
|
literal_vector::iterator it = m_lemma.begin();
|
||||||
literal_vector::iterator end = m_lemma.end();
|
literal_vector::iterator end = m_lemma.end();
|
||||||
unsigned new_scope_lvl = 0;
|
unsigned new_scope_lvl = 0;
|
||||||
|
@ -1432,10 +1446,10 @@ namespace sat {
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
unsigned r = 0;
|
unsigned r = 0;
|
||||||
|
|
||||||
if (consequent != null_literal)
|
if (consequent != null_literal)
|
||||||
r = lvl(consequent);
|
r = lvl(consequent);
|
||||||
|
|
||||||
switch (js.get_kind()) {
|
switch (js.get_kind()) {
|
||||||
case justification::NONE:
|
case justification::NONE:
|
||||||
break;
|
break;
|
||||||
|
@ -1468,7 +1482,7 @@ namespace sat {
|
||||||
fill_ext_antecedents(consequent, js);
|
fill_ext_antecedents(consequent, js);
|
||||||
literal_vector::iterator it = m_ext_antecedents.begin();
|
literal_vector::iterator it = m_ext_antecedents.begin();
|
||||||
literal_vector::iterator end = m_ext_antecedents.end();
|
literal_vector::iterator end = m_ext_antecedents.end();
|
||||||
for (; it != end; ++it)
|
for (; it != end; ++it)
|
||||||
r = std::max(r, lvl(*it));
|
r = std::max(r, lvl(*it));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1497,7 +1511,7 @@ namespace sat {
|
||||||
}
|
}
|
||||||
return idx;
|
return idx;
|
||||||
}
|
}
|
||||||
|
|
||||||
void solver::process_antecedent(literal antecedent, unsigned & num_marks) {
|
void solver::process_antecedent(literal antecedent, unsigned & num_marks) {
|
||||||
bool_var var = antecedent.var();
|
bool_var var = antecedent.var();
|
||||||
unsigned var_lvl = lvl(var);
|
unsigned var_lvl = lvl(var);
|
||||||
|
@ -1511,7 +1525,7 @@ namespace sat {
|
||||||
m_lemma.push_back(~antecedent);
|
m_lemma.push_back(~antecedent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
\brief js is an external justification. Collect its antecedents and store at m_ext_antecedents.
|
\brief js is an external justification. Collect its antecedents and store at m_ext_antecedents.
|
||||||
*/
|
*/
|
||||||
|
@ -1578,7 +1592,7 @@ namespace sat {
|
||||||
unsigned var_lvl = lvl(var);
|
unsigned var_lvl = lvl(var);
|
||||||
if (!is_marked(var) && var_lvl > 0) {
|
if (!is_marked(var) && var_lvl > 0) {
|
||||||
if (m_lvl_set.may_contain(var_lvl)) {
|
if (m_lvl_set.may_contain(var_lvl)) {
|
||||||
mark(var);
|
mark(var);
|
||||||
m_unmark.push_back(var);
|
m_unmark.push_back(var);
|
||||||
m_lemma_min_stack.push_back(var);
|
m_lemma_min_stack.push_back(var);
|
||||||
}
|
}
|
||||||
|
@ -1590,17 +1604,17 @@ namespace sat {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
\brief Return true if lit is implied by other marked literals
|
\brief Return true if lit is implied by other marked literals
|
||||||
and/or literals assigned at the base level.
|
and/or literals assigned at the base level.
|
||||||
The set lvl_set is used as an optimization.
|
The set lvl_set is used as an optimization.
|
||||||
The idea is to stop the recursive search with a failure
|
The idea is to stop the recursive search with a failure
|
||||||
as soon as we find a literal assigned in a level that is not in lvl_set.
|
as soon as we find a literal assigned in a level that is not in lvl_set.
|
||||||
*/
|
*/
|
||||||
bool solver::implied_by_marked(literal lit) {
|
bool solver::implied_by_marked(literal lit) {
|
||||||
m_lemma_min_stack.reset(); // avoid recursive function
|
m_lemma_min_stack.reset(); // avoid recursive function
|
||||||
m_lemma_min_stack.push_back(lit.var());
|
m_lemma_min_stack.push_back(lit.var());
|
||||||
unsigned old_size = m_unmark.size();
|
unsigned old_size = m_unmark.size();
|
||||||
|
|
||||||
while (!m_lemma_min_stack.empty()) {
|
while (!m_lemma_min_stack.empty()) {
|
||||||
bool_var var = m_lemma_min_stack.back();
|
bool_var var = m_lemma_min_stack.back();
|
||||||
m_lemma_min_stack.pop_back();
|
m_lemma_min_stack.pop_back();
|
||||||
|
@ -1701,7 +1715,7 @@ namespace sat {
|
||||||
void solver::minimize_lemma() {
|
void solver::minimize_lemma() {
|
||||||
m_unmark.reset();
|
m_unmark.reset();
|
||||||
updt_lemma_lvl_set();
|
updt_lemma_lvl_set();
|
||||||
|
|
||||||
unsigned sz = m_lemma.size();
|
unsigned sz = m_lemma.size();
|
||||||
unsigned i = 1; // the first literal is the FUIP
|
unsigned i = 1; // the first literal is the FUIP
|
||||||
unsigned j = 1;
|
unsigned j = 1;
|
||||||
|
@ -1717,12 +1731,12 @@ namespace sat {
|
||||||
j++;
|
j++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
reset_unmark(0);
|
reset_unmark(0);
|
||||||
m_lemma.shrink(j);
|
m_lemma.shrink(j);
|
||||||
m_stats.m_minimized_lits += sz - j;
|
m_stats.m_minimized_lits += sz - j;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
\brief Reset the mark of the variables in the current lemma.
|
\brief Reset the mark of the variables in the current lemma.
|
||||||
*/
|
*/
|
||||||
|
@ -1742,17 +1756,17 @@ namespace sat {
|
||||||
Only binary and ternary clauses are used.
|
Only binary and ternary clauses are used.
|
||||||
*/
|
*/
|
||||||
void solver::dyn_sub_res() {
|
void solver::dyn_sub_res() {
|
||||||
unsigned sz = m_lemma.size();
|
unsigned sz = m_lemma.size();
|
||||||
for (unsigned i = 0; i < sz; i++) {
|
for (unsigned i = 0; i < sz; i++) {
|
||||||
mark_lit(m_lemma[i]);
|
mark_lit(m_lemma[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
literal l0 = m_lemma[0];
|
literal l0 = m_lemma[0];
|
||||||
// l0 is the FUIP, and we never remove the FUIP.
|
// l0 is the FUIP, and we never remove the FUIP.
|
||||||
//
|
//
|
||||||
// In the following loop, we use unmark_lit(l) to remove a
|
// In the following loop, we use unmark_lit(l) to remove a
|
||||||
// literal from m_lemma.
|
// literal from m_lemma.
|
||||||
|
|
||||||
for (unsigned i = 0; i < sz; i++) {
|
for (unsigned i = 0; i < sz; i++) {
|
||||||
literal l = m_lemma[i];
|
literal l = m_lemma[i];
|
||||||
if (!is_marked_lit(l))
|
if (!is_marked_lit(l))
|
||||||
|
@ -1764,8 +1778,8 @@ namespace sat {
|
||||||
for (; it != end; ++it) {
|
for (; it != end; ++it) {
|
||||||
// In this for-loop, the conditions l0 != ~l2 and l0 != ~l3
|
// In this for-loop, the conditions l0 != ~l2 and l0 != ~l3
|
||||||
// are not really needed if the solver does not miss unit propagations.
|
// are not really needed if the solver does not miss unit propagations.
|
||||||
// However, we add them anyway because we don't want to rely on this
|
// However, we add them anyway because we don't want to rely on this
|
||||||
// property of the propagator.
|
// property of the propagator.
|
||||||
// For example, if this property is relaxed in the future, then the code
|
// For example, if this property is relaxed in the future, then the code
|
||||||
// without the conditions l0 != ~l2 and l0 != ~l3 may remove the FUIP
|
// without the conditions l0 != ~l2 and l0 != ~l3 may remove the FUIP
|
||||||
if (it->is_binary_clause()) {
|
if (it->is_binary_clause()) {
|
||||||
|
@ -1811,10 +1825,10 @@ namespace sat {
|
||||||
// p1 \/ ~p2
|
// p1 \/ ~p2
|
||||||
// p2 \/ ~p3
|
// p2 \/ ~p3
|
||||||
// p3 \/ ~p4
|
// p3 \/ ~p4
|
||||||
// q1 \/ q2 \/ p1 \/ p2 \/ p3 \/ p4 \/ l2
|
// q1 \/ q2 \/ p1 \/ p2 \/ p3 \/ p4 \/ l2
|
||||||
// q1 \/ ~q2 \/ p1 \/ p2 \/ p3 \/ p4 \/ l2
|
// q1 \/ ~q2 \/ p1 \/ p2 \/ p3 \/ p4 \/ l2
|
||||||
// ~q1 \/ q2 \/ p1 \/ p2 \/ p3 \/ p4 \/ l2
|
// ~q1 \/ q2 \/ p1 \/ p2 \/ p3 \/ p4 \/ l2
|
||||||
// ~q1 \/ ~q2 \/ p1 \/ p2 \/ p3 \/ p4 \/ l2
|
// ~q1 \/ ~q2 \/ p1 \/ p2 \/ p3 \/ p4 \/ l2
|
||||||
// ...
|
// ...
|
||||||
//
|
//
|
||||||
// 2. Now suppose we learned the lemma
|
// 2. Now suppose we learned the lemma
|
||||||
|
@ -1825,15 +1839,15 @@ namespace sat {
|
||||||
// That is, l \/ l2 is an implied clause. Note that probing does not add
|
// That is, l \/ l2 is an implied clause. Note that probing does not add
|
||||||
// this clause to the clause database (there are too many).
|
// this clause to the clause database (there are too many).
|
||||||
//
|
//
|
||||||
// 4. Lemma (*) is deleted (garbage collected).
|
// 4. Lemma (*) is deleted (garbage collected).
|
||||||
//
|
//
|
||||||
// 5. l is decided to be false, p1, p2, p3 and p4 are propagated using BCP,
|
// 5. l is decided to be false, p1, p2, p3 and p4 are propagated using BCP,
|
||||||
// but l2 is not since the lemma (*) was deleted.
|
// but l2 is not since the lemma (*) was deleted.
|
||||||
//
|
//
|
||||||
// Probing module still "knows" that l \/ l2 is valid binary clause
|
// Probing module still "knows" that l \/ l2 is valid binary clause
|
||||||
//
|
//
|
||||||
// 6. A new lemma is created where ~l2 is the FUIP and the lemma also contains l.
|
// 6. A new lemma is created where ~l2 is the FUIP and the lemma also contains l.
|
||||||
// If we remove l0 != ~l2 may try to delete the FUIP.
|
// If we remove l0 != ~l2 may try to delete the FUIP.
|
||||||
if (is_marked_lit(~l2) && l0 != ~l2) {
|
if (is_marked_lit(~l2) && l0 != ~l2) {
|
||||||
// eliminate ~l2 from lemma because we have the clause l \/ l2
|
// eliminate ~l2 from lemma because we have the clause l \/ l2
|
||||||
unmark_lit(~l2);
|
unmark_lit(~l2);
|
||||||
|
@ -1844,7 +1858,7 @@ namespace sat {
|
||||||
|
|
||||||
// can't eliminat FUIP
|
// can't eliminat FUIP
|
||||||
SASSERT(is_marked_lit(m_lemma[0]));
|
SASSERT(is_marked_lit(m_lemma[0]));
|
||||||
|
|
||||||
unsigned j = 0;
|
unsigned j = 0;
|
||||||
for (unsigned i = 0; i < sz; i++) {
|
for (unsigned i = 0; i < sz; i++) {
|
||||||
literal l = m_lemma[i];
|
literal l = m_lemma[i];
|
||||||
|
@ -1856,7 +1870,7 @@ namespace sat {
|
||||||
}
|
}
|
||||||
|
|
||||||
m_stats.m_dyn_sub_res += sz - j;
|
m_stats.m_dyn_sub_res += sz - j;
|
||||||
|
|
||||||
SASSERT(j >= 1);
|
SASSERT(j >= 1);
|
||||||
m_lemma.shrink(j);
|
m_lemma.shrink(j);
|
||||||
}
|
}
|
||||||
|
@ -1949,7 +1963,7 @@ namespace sat {
|
||||||
// Misc
|
// Misc
|
||||||
//
|
//
|
||||||
// -----------------------
|
// -----------------------
|
||||||
|
|
||||||
void solver::updt_params(params_ref const & p) {
|
void solver::updt_params(params_ref const & p) {
|
||||||
m_params = p;
|
m_params = p;
|
||||||
m_config.updt_params(p);
|
m_config.updt_params(p);
|
||||||
|
@ -1971,7 +1985,7 @@ namespace sat {
|
||||||
void solver::set_cancel(bool f) {
|
void solver::set_cancel(bool f) {
|
||||||
m_cancel = f;
|
m_cancel = f;
|
||||||
}
|
}
|
||||||
|
|
||||||
void solver::collect_statistics(statistics & st) {
|
void solver::collect_statistics(statistics & st) {
|
||||||
m_stats.collect_statistics(st);
|
m_stats.collect_statistics(st);
|
||||||
m_cleaner.collect_statistics(st);
|
m_cleaner.collect_statistics(st);
|
||||||
|
@ -2067,7 +2081,7 @@ namespace sat {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void solver::display_units(std::ostream & out) const {
|
void solver::display_units(std::ostream & out) const {
|
||||||
unsigned end = scope_lvl() == 0 ? m_trail.size() : m_scopes[0].m_trail_lim;
|
unsigned end = scope_lvl() == 0 ? m_trail.size() : m_scopes[0].m_trail_lim;
|
||||||
for (unsigned i = 0; i < end; i++) {
|
for (unsigned i = 0; i < end; i++) {
|
||||||
|
@ -2221,26 +2235,26 @@ namespace sat {
|
||||||
// Simplification
|
// Simplification
|
||||||
//
|
//
|
||||||
// -----------------------
|
// -----------------------
|
||||||
void solver::cleanup() {
|
void solver::cleanup() {
|
||||||
if (scope_lvl() > 0 || inconsistent())
|
if (scope_lvl() > 0 || inconsistent())
|
||||||
return;
|
return;
|
||||||
if (m_cleaner() && m_ext)
|
if (m_cleaner() && m_ext)
|
||||||
m_ext->clauses_modifed();
|
m_ext->clauses_modifed();
|
||||||
}
|
}
|
||||||
|
|
||||||
void solver::simplify(bool learned) {
|
void solver::simplify(bool learned) {
|
||||||
if (scope_lvl() > 0 || inconsistent())
|
if (scope_lvl() > 0 || inconsistent())
|
||||||
return;
|
return;
|
||||||
m_simplifier(learned);
|
m_simplifier(learned);
|
||||||
m_simplifier.free_memory();
|
m_simplifier.free_memory();
|
||||||
if (m_ext)
|
if (m_ext)
|
||||||
m_ext->clauses_modifed();
|
m_ext->clauses_modifed();
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned solver::scc_bin() {
|
unsigned solver::scc_bin() {
|
||||||
if (scope_lvl() > 0 || inconsistent())
|
if (scope_lvl() > 0 || inconsistent())
|
||||||
return 0;
|
return 0;
|
||||||
unsigned r = m_scc();
|
unsigned r = m_scc();
|
||||||
if (r > 0 && m_ext)
|
if (r > 0 && m_ext)
|
||||||
m_ext->clauses_modifed();
|
m_ext->clauses_modifed();
|
||||||
return r;
|
return r;
|
||||||
|
@ -2314,10 +2328,10 @@ namespace sat {
|
||||||
out << " :inconsistent " << (m_inconsistent ? "true" : "false") << "\n";
|
out << " :inconsistent " << (m_inconsistent ? "true" : "false") << "\n";
|
||||||
out << " :vars " << num_vars() << "\n";
|
out << " :vars " << num_vars() << "\n";
|
||||||
out << " :elim-vars " << num_elim << "\n";
|
out << " :elim-vars " << num_elim << "\n";
|
||||||
out << " :lits " << num_lits << "\n";
|
out << " :lits " << num_lits << "\n";
|
||||||
out << " :assigned " << m_trail.size() << "\n";
|
out << " :assigned " << m_trail.size() << "\n";
|
||||||
out << " :binary-clauses " << num_bin << "\n";
|
out << " :binary-clauses " << num_bin << "\n";
|
||||||
out << " :ternary-clauses " << num_ter << "\n";
|
out << " :ternary-clauses " << num_ter << "\n";
|
||||||
out << " :clauses " << num_cls << "\n";
|
out << " :clauses " << num_cls << "\n";
|
||||||
out << " :del-clause " << m_stats.m_del_clause << "\n";
|
out << " :del-clause " << m_stats.m_del_clause << "\n";
|
||||||
out << " :avg-clause-size " << (total_cls == 0 ? 0.0 : static_cast<double>(num_lits) / static_cast<double>(total_cls)) << "\n";
|
out << " :avg-clause-size " << (total_cls == 0 ? 0.0 : static_cast<double>(num_lits) / static_cast<double>(total_cls)) << "\n";
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue