3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-24 09:35:32 +00:00

working on lookahead

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2017-03-27 04:53:27 +02:00
parent 5ed3200c88
commit 2afd45b3c2
10 changed files with 388 additions and 168 deletions

View file

@ -136,9 +136,9 @@ namespace sat {
TRACE("iff3_finder",
tout << "visiting: " << x << "\n";
tout << "pos:\n";
display(tout, s.m_cls_allocator, pos_wlist);
display_watch_list(tout, s.m_cls_allocator, pos_wlist);
tout << "\nneg:\n";
display(tout, s.m_cls_allocator, neg_wlist);
display_watch_list(tout, s.m_cls_allocator, neg_wlist);
tout << "\n--------------\n";);
// traverse the ternary clauses x \/ l1 \/ l2
bool_var curr_v1 = null_bool_var;

View file

@ -68,7 +68,7 @@ namespace sat {
if (c.size() == 3) {
CTRACE("sat_ter_watch_bug", !contains_watched(s.get_wlist(~c[0]), c[1], c[2]), tout << c << "\n";
tout << "watch_list:\n";
sat::display(tout, s.m_cls_allocator, s.get_wlist(~c[0]));
sat::display_watch_list(tout, s.m_cls_allocator, s.get_wlist(~c[0]));
tout << "\n";);
VERIFY(contains_watched(s.get_wlist(~c[0]), c[1], c[2]));
VERIFY(contains_watched(s.get_wlist(~c[1]), c[0], c[2]));
@ -176,9 +176,9 @@ namespace sat {
tout << "was_eliminated1: " << s.was_eliminated(l.var());
tout << " was_eliminated2: " << s.was_eliminated(it2->get_literal().var());
tout << " learned: " << it2->is_learned() << "\n";
sat::display(tout, s.m_cls_allocator, wlist);
sat::display_watch_list(tout, s.m_cls_allocator, wlist);
tout << "\n";
sat::display(tout, s.m_cls_allocator, s.get_wlist(~(it2->get_literal())));
sat::display_watch_list(tout, s.m_cls_allocator, s.get_wlist(~(it2->get_literal())));
tout << "\n";);
SASSERT(s.get_wlist(~(it2->get_literal())).contains(watched(l, it2->is_learned())));
break;

View file

@ -21,6 +21,38 @@ Notes:
#define _SAT_LOOKAHEAD_H_
namespace sat {
struct pp_prefix {
uint64 m_prefix;
unsigned m_depth;
pp_prefix(uint64 p, unsigned d) : m_prefix(p), m_depth(d) {}
};
inline std::ostream& operator<<(std::ostream& out, pp_prefix const& p) {
uint64 q = p.m_prefix;
unsigned d = std::min(63u, p.m_depth);
for (unsigned i = 0; i <= d; ++i) {
if (0 != (p.m_prefix & (1ull << i))) out << "1"; else out << "0";
}
return out;
}
enum lookahead_mode {
searching, // normal search
lookahead1, // lookahead mode
lookahead2 // double lookahead
};
inline std::ostream& operator<<(std::ostream& out, lookahead_mode m) {
switch (m) {
case lookahead_mode::searching: return out << "searching";
case lookahead_mode::lookahead1: return out << "lookahead1";
case lookahead_mode::lookahead2: return out << "lookahead2";
default: break;
}
return out;
}
class lookahead {
solver& s;
@ -32,6 +64,7 @@ namespace sat {
unsigned m_min_cutoff;
unsigned m_level_cand;
float m_delta_rho;
unsigned m_dl_max_iterations;
config() {
m_max_hlevel = 50;
@ -40,6 +73,7 @@ namespace sat {
m_min_cutoff = 30;
m_level_cand = 600;
m_delta_rho = (float)0.9995;
m_dl_max_iterations = 32;
}
};
@ -55,28 +89,17 @@ namespace sat {
lit_info(): m_wnb(0), m_double_lookahead(0) {}
};
struct statistics {
struct stats {
unsigned m_propagations;
statistics() { reset(); }
unsigned m_add_binary;
unsigned m_del_binary;
unsigned m_add_ternary;
unsigned m_del_ternary;
unsigned m_decisions;
stats() { reset(); }
void reset() { memset(this, 0, sizeof(*this)); }
};
enum search_mode {
searching, // normal search
lookahead1, // lookahead mode
lookahead2 // double lookahead
};
std::ostream& display(std::ostream& out, search_mode m) const {
switch (m) {
case search_mode::searching: return out << "searching";
case search_mode::lookahead1: return out << "lookahead1";
case search_mode::lookahead2: return out << "lookahead2";
default: break;
}
return out;
}
struct ternary {
ternary(literal u, literal v, literal w): m_u(u), m_v(v), m_w(w) {}
literal m_u, m_v, m_w;
@ -94,8 +117,9 @@ namespace sat {
unsigned_vector m_qhead_lim;
clause_vector m_clauses; // non-binary clauses
clause_vector m_retired_clauses; // clauses that were removed during search
svector<ternary> m_retired_ternary; //
unsigned_vector m_retired_clause_lim;
svector<ternary> m_retired_ternary; // ternary removed during search
unsigned_vector m_retired_ternary_lim;
clause_allocator m_cls_allocator;
bool m_inconsistent;
unsigned_vector m_bstamp; // literal: timestamp for binary implication
@ -110,12 +134,12 @@ namespace sat {
vector<watch_list> m_watches; // literal: watch structure
svector<lit_info> m_lits; // literal: attributes.
float m_weighted_new_binaries; // metric associated with current lookahead1 literal.
unsigned m_prefix; // where we are in search tree
literal_vector m_wstack; // windofall stack that is populated in lookahead1 mode
uint64 m_prefix; // where we are in search tree
svector<prefix> m_vprefix; // var: prefix where variable participates in propagation
indexed_uint_set m_freevars;
svector<search_mode> m_search_modes; // stack of modes
search_mode m_search_mode; // mode of search
statistics m_stats;
lookahead_mode m_search_mode; // mode of search
stats m_stats;
// ---------------------------------------
// truth values
@ -148,15 +172,15 @@ namespace sat {
// skip bit 0 in a bid to reduce details.
void flip_prefix() {
if (m_trail_lim.size() < 32) {
unsigned mask = (1 << m_trail_lim.size());
m_prefix &= mask | (mask - 1);
if (m_trail_lim.size() < 64) {
uint64 mask = (1ull << m_trail_lim.size());
m_prefix = mask | (m_prefix & (mask - 1));
}
}
void prune_prefix() {
if (m_trail_lim.size() < 32) {
m_prefix &= (1 << m_trail_lim.size()) - 1;
if (m_trail_lim.size() < 64) {
m_prefix &= (1ull << m_trail_lim.size()) - 1;
}
}
@ -167,7 +191,7 @@ namespace sat {
if (m_vprefix[x].m_length >= m_trail_lim.size() ||
((p | m_prefix) != m_prefix)) {
m_vprefix[x].m_length = m_trail_lim.size();
m_vprefix[x].m_prefix = m_prefix;
m_vprefix[x].m_prefix = static_cast<unsigned>(m_prefix);
}
}
@ -176,19 +200,23 @@ namespace sat {
unsigned p = m_vprefix[x].m_prefix;
unsigned l = m_vprefix[x].m_length;
if (l > lvl) return false;
if (l == lvl || l >= 32) return m_prefix == p;
return (m_prefix & ((1 << l) - 1)) == p;
if (l == lvl || l >= 31) return m_prefix == p;
unsigned mask = ((1 << l) - 1);
return (m_prefix & mask) == (p & mask);
}
// ----------------------------------------
void add_binary(literal l1, literal l2) {
TRACE("sat", tout << "binary: " << l1 << " " << l2 << "\n";);
TRACE("sat", tout << "binary: " << l1 << " " << l2 << "\n";);
SASSERT(l1 != l2);
SASSERT(~l1 != l2);
// don't add tautologies and don't add already added binaries
if (~l1 == l2) return;
if (!m_binary[(~l1).index()].empty() && m_binary[(~l1).index()].back() == l2) return;
m_binary[(~l1).index()].push_back(l2);
m_binary[(~l2).index()].push_back(l1);
m_binary_trail.push_back((~l1).index());
++m_stats.m_add_binary;
}
void del_binary(unsigned idx) {
@ -197,6 +225,7 @@ namespace sat {
literal l = lits.back();
lits.pop_back();
m_binary[(~l).index()].pop_back();
++m_stats.m_del_binary;
}
// -------------------------------------
@ -247,6 +276,7 @@ namespace sat {
if (!is_fixed(w)) {
if (is_stamped(~w)) {
// u \/ v, ~v \/ w, u \/ ~w => u is unit
TRACE("sat", tout << "tc1: " << u << "\n";);
assign(u);
return false;
}
@ -260,16 +290,18 @@ namespace sat {
\brief main routine for adding a new binary clause dynamically.
*/
void try_add_binary(literal u, literal v) {
SASSERT(m_search_mode == searching);
SASSERT(m_search_mode == lookahead_mode::searching);
SASSERT(u.var() != v.var());
set_bstamps(~u);
if (is_stamped(~v)) {
if (is_stamped(~v)) {
TRACE("sat", tout << "try_add_binary: " << u << "\n";);
assign(u); // u \/ ~v, u \/ v => u is a unit literal
}
else if (!is_stamped(v) && add_tc1(u, v)) {
// u \/ v is not in index
set_bstamps(~v);
if (is_stamped(~u)) {
TRACE("sat", tout << "try_add_binary: " << v << "\n";);
assign(v); // v \/ ~u, u \/ v => v is a unit literal
}
else if (add_tc1(v, u)) {
@ -288,9 +320,10 @@ namespace sat {
m_lookahead.reset();
if (select(scope_lvl())) {
get_scc();
if (inconsistent()) return;
find_heights();
construct_lookahead_table();
}
}
}
struct candidate {
@ -316,6 +349,8 @@ namespace sat {
return false;
}
if (newbies) {
enable_trace("sat");
TRACE("sat", display(tout););
TRACE("sat", tout << sum << "\n";);
}
}
@ -396,6 +431,20 @@ namespace sat {
return out;
}
bool is_unsat() const {
for (unsigned i = 0; i < m_clauses.size(); ++i) {
clause& c = *m_clauses[i];
unsigned j = 0;
for (; j < c.size() && is_false(c[j]); ++j) {}
if (j == c.size()) {
TRACE("sat", tout << c << "\n";);
TRACE("sat", display(tout););
return true;
}
}
return false;
}
bool is_sat() const {
for (bool_var const* it = m_freevars.begin(), * end = m_freevars.end(); it != end; ++it) {
literal l(*it, false);
@ -489,10 +538,14 @@ namespace sat {
case watched::BINARY:
UNREACHABLE();
break;
case watched::TERNARY:
UNREACHABLE();
tsum += h[wit->get_literal1().index()] * h[wit->get_literal2().index()];
case watched::TERNARY: {
literal l1 = wit->get_literal1();
literal l2 = wit->get_literal2();
if (is_undef(l1) && is_undef(l2)) {
tsum += h[l1.index()] * h[l2.index()];
}
break;
}
case watched::CLAUSE: {
clause_offset cls_off = wit->get_clause_offset();
clause & c = *(s.m_cls_allocator.get_clause(cls_off));
@ -552,7 +605,7 @@ namespace sat {
void get_scc() {
init_scc();
for (unsigned i = 0; i < m_candidates.size(); ++i) {
for (unsigned i = 0; i < m_candidates.size() && !inconsistent(); ++i) {
literal lit(m_candidates[i].m_var, false);
if (get_rank(lit) == 0) get_scc(lit);
if (get_rank(~lit) == 0) get_scc(~lit);
@ -644,7 +697,7 @@ namespace sat {
v = u;
}
}
while (v != null_literal);
while (v != null_literal && !inconsistent());
}
void activate_scc(literal l) {
SASSERT(get_rank(l) == 0);
@ -663,7 +716,11 @@ namespace sat {
set_rank(v, UINT_MAX);
set_link(v, m_settled); m_settled = t;
while (t != v) {
SASSERT(t != ~v);
if (t == ~v) {
TRACE("sat", display_scc(tout << "found contradiction during scc search\n"););
set_conflict();
break;
}
set_rank(t, UINT_MAX);
set_parent(t, v);
float t_rating = get_rating(t);
@ -855,10 +912,8 @@ namespace sat {
// clause management
void attach_clause(clause& c) {
if (false && c.size() == 3) { // disable ternary clauses
m_watches[(~c[0]).index()].push_back(watched(c[1], c[2]));
m_watches[(~c[1]).index()].push_back(watched(c[0], c[2]));
m_watches[(~c[2]).index()].push_back(watched(c[0], c[1]));
if (c.size() == 3) {
attach_ternary(c[0], c[1], c[2]);
}
else {
literal block_lit = c[c.size() >> 2];
@ -885,17 +940,26 @@ namespace sat {
}
}
void detach_ternary(literal l1, literal l2, literal l3) {
NOT_IMPLEMENTED_YET();
// there is a clause corresponding to a ternary watch group.
// the clause could be retired / detached.
++m_stats.m_del_ternary;
m_retired_ternary.push_back(ternary(l1, l2, l3));
erase_ternary_watch(get_wlist(~l1), l2, l3);
// implicitly erased: erase_ternary_watch(get_wlist(~l1), l2, l3);
erase_ternary_watch(get_wlist(~l2), l1, l3);
erase_ternary_watch(get_wlist(~l3), l1, l2);
}
void attach_ternary(ternary const& t) {
attach_ternary(t.m_u, t.m_v, t.m_w);
}
void attach_ternary(literal l1, literal l2, literal l3) {
++m_stats.m_add_ternary;
TRACE("sat", tout << l1 << " " << l2 << " " << l3 << "\n";);
m_watches[(~l1).index()].push_back(watched(l2, l3));
m_watches[(~l2).index()].push_back(watched(l1, l3));
m_watches[(~l3).index()].push_back(watched(l1, l2));
}
watch_list& get_wlist(literal l) { return m_watches[l.index()]; }
// ------------------------------------
@ -952,7 +1016,7 @@ namespace sat {
clause& c = *(*it);
clause* c1 = m_cls_allocator.mk_clause(c.size(), c.begin(), false);
m_clauses.push_back(c1);
attach_clause(c);
attach_clause(*c1);
}
// copy units
@ -968,12 +1032,12 @@ namespace sat {
// search
void push(literal lit, unsigned level) {
SASSERT(m_search_mode == lookahead_mode::searching);
m_binary_trail_lim.push_back(m_binary_trail.size());
m_trail_lim.push_back(m_trail.size());
m_retired_clause_lim.push_back(m_retired_clauses.size());
m_retired_ternary_lim.push_back(m_retired_ternary.size());
m_qhead_lim.push_back(m_qhead);
m_search_modes.push_back(m_search_mode);
m_search_mode = searching;
scoped_level _sl(*this, level);
assign(lit);
propagate();
@ -981,12 +1045,8 @@ namespace sat {
void pop() {
m_inconsistent = false;
SASSERT(m_search_mode == lookahead_mode::searching);
// search mode
m_search_mode = m_search_modes.back();
m_search_modes.pop_back();
// not for lookahead.
// m_freevars only for main search
// undo assignments
unsigned old_sz = m_trail_lim.back();
@ -1000,7 +1060,6 @@ namespace sat {
m_trail.shrink(old_sz); // reset assignment.
m_trail_lim.pop_back();
// not for lookahead
// unretire clauses
old_sz = m_retired_clause_lim.back();
for (unsigned i = old_sz; i < m_retired_clauses.size(); ++i) {
@ -1008,11 +1067,16 @@ namespace sat {
}
m_retired_clauses.resize(old_sz);
m_retired_clause_lim.pop_back();
old_sz = m_retired_ternary_lim.back();
for (unsigned i = old_sz; i < m_retired_ternary.size(); ++i) {
attach_ternary(m_retired_ternary[i]);
}
m_retired_ternary.shrink(old_sz);
m_retired_ternary_lim.pop_back();
// m_search_mode == searching
// remove local binary clauses
old_sz = m_binary_trail_lim.back();
old_sz = m_binary_trail_lim.back();
for (unsigned i = m_binary_trail.size(); i > old_sz; ) {
del_binary(m_binary_trail[--i]);
}
@ -1024,11 +1088,39 @@ namespace sat {
m_qhead_lim.pop_back();
}
void push_lookahead2(literal lit) {
bool push_lookahead2(literal lit, unsigned level) {
scoped_level _sl(*this, level);
SASSERT(m_search_mode == lookahead_mode::lookahead1);
m_search_mode = lookahead_mode::lookahead2;
assign(lit);
propagate();
bool unsat = inconsistent();
SASSERT(m_search_mode == lookahead_mode::lookahead2);
m_search_mode = lookahead_mode::lookahead1;
m_inconsistent = false;
return unsat;
}
void pop_lookahead2() {
void push_lookahead1(literal lit, unsigned level) {
SASSERT(m_search_mode == lookahead_mode::searching);
m_search_mode = lookahead_mode::lookahead1;
scoped_level _sl(*this, level);
assign(lit);
propagate();
}
void pop_lookahead1(literal lit) {
bool unsat = inconsistent();
SASSERT(m_search_mode == lookahead_mode::lookahead1);
m_inconsistent = false;
m_search_mode = lookahead_mode::searching;
// convert windfalls to binary clauses.
if (!unsat) {
for (unsigned i = 0; i < m_wstack.size(); ++i) {
add_binary(lit, m_wstack[i]);
}
}
m_wstack.reset();
}
@ -1056,50 +1148,64 @@ namespace sat {
UNREACHABLE();
break;
case watched::TERNARY: {
UNREACHABLE(); // we avoid adding ternary clauses for now.
literal l1 = it->get_literal1();
literal l2 = it->get_literal2();
bool skip = false;
if (is_fixed(l1)) {
if (is_false(l1)) {
if (is_undef(l2)) {
m_stats.m_propagations++;
assign(l2);
propagated(l2);
}
else if (is_false(l2)) {
TRACE("sat", tout << l1 << " " << l2 << " " << l << "\n";);
set_conflict();
}
}
else {
// retire this clause
}
}
else if (is_fixed(l2)) {
if (is_false(l2)) {
m_stats.m_propagations++;
assign(l1);
propagated(l1);
}
else {
// retire this clause
}
}
else {
switch (m_search_mode) {
case searching:
detach_ternary(l, l1, l2);
case lookahead_mode::searching:
detach_ternary(~l, l1, l2);
try_add_binary(l1, l2);
skip = true;
break;
case lookahead1:
case lookahead_mode::lookahead1:
m_weighted_new_binaries += (*m_heur)[l1.index()] * (*m_heur)[l2.index()];
break;
case lookahead2:
break;
}
}
*it2 = *it;
it2++;
if (!skip) {
*it2 = *it;
it2++;
}
break;
}
case watched::CLAUSE: {
clause_offset cls_off = it->get_clause_offset();
clause & c = *(s.m_cls_allocator.get_clause(cls_off));
if (is_true(it->get_blocked_literal())) {
*it2 = *it;
++it2;
break;
}
if (c[0] == ~l)
std::swap(c[0], c[1]);
if (is_true(c[0])) {
it2->set_clause(c[0], cls_off);
*it2 = *it;
it2++;
break;
}
@ -1112,6 +1218,7 @@ namespace sat {
c[1] = *l_it;
*l_it = ~l;
m_watches[(~c[1]).index()].push_back(watched(c[0], cls_off));
TRACE("sat", tout << "move watch from " << l << " to " << c[1] << " for clause " << c << "\n";);
}
}
if (found) {
@ -1123,30 +1230,40 @@ namespace sat {
if (!found && is_undef(c[1]) && is_undef(c[0])) {
TRACE("sat", tout << "got binary " << l << ": " << c << "\n";);
switch (m_search_mode) {
case searching:
case lookahead_mode::searching:
detach_clause(c);
try_add_binary(c[0], c[1]);
break;
case lookahead1:
case lookahead_mode::lookahead1:
m_weighted_new_binaries += (*m_heur)[c[0].index()]* (*m_heur)[c[1].index()];
break;
case lookahead2:
case lookahead_mode::lookahead2:
break;
}
}
else if (found && m_search_mode == lookahead_mode::lookahead1 && m_weighted_new_binaries == 0) {
// leave a trail that some clause was reduced but potentially not an autarky
l_it = c.begin() + 2;
found = false;
for (; l_it != l_end && !found; found = is_true(*l_it), ++l_it) ;
if (!found) {
m_weighted_new_binaries = (float)0.001;
}
}
break;
}
if (is_false(c[0])) {
TRACE("sat", tout << "conflict " << l << ": " << c << "\n";);
set_conflict();
*it2 = *it;
++it2;
}
else {
TRACE("sat", tout << "propagating " << l << ": " << c << "\n";);
SASSERT(is_undef(c[0]));
*it2 = *it;
it2++;
m_stats.m_propagations++;
assign(c[0]);
propagated(c[0]);
}
break;
}
@ -1176,10 +1293,11 @@ namespace sat {
for (; m_qhead < m_trail.size(); ++m_qhead) {
if (inconsistent()) break;
literal l = m_trail[m_qhead];
TRACE("sat", tout << "propagate " << l << "\n";);
propagate_binary(l);
propagate_clauses(l);
}
TRACE("sat", display(tout << scope_lvl() << " " << (inconsistent()?"unsat":"sat") << "\n"););
TRACE("sat_verbose", display(tout << scope_lvl() << " " << (inconsistent()?"unsat":"sat") << "\n"););
}
literal choose() {
@ -1195,28 +1313,43 @@ namespace sat {
}
l = select_literal();
}
SASSERT(inconsistent() || !is_unsat());
return l;
}
void compute_wnb() {
init_wnb();
TRACE("sat", display_lookahead(tout); );
for (unsigned i = 0; !inconsistent() && i < m_lookahead.size(); ++i) {
literal lit = m_lookahead[i].m_lit;
TRACE("sat", tout << "lookahead " << lit << "\n";);
reset_wnb(lit);
push_lookahead1(lit, 2 + m_lookahead[i].m_offset);
bool unsat = inconsistent();
// TBD do_double(lit);
pop_lookahead1();
update_wnb(lit);
if (unsat) {
TRACE("sat", tout << "backtracking and settting " << ~lit << "\n";);
reset_wnb();
assign(~lit);
propagate();
init_wnb();
unsigned base = 2;
bool change = true;
while (change && !inconsistent()) {
change = false;
for (unsigned i = 0; !inconsistent() && i < m_lookahead.size(); ++i) {
literal lit = m_lookahead[i].m_lit;
if (is_fixed_at(lit, c_fixed_truth)) continue;
TRACE("sat", tout << "lookahead " << lit << "\n";);
reset_wnb(lit);
push_lookahead1(lit, base + m_lookahead[i].m_offset);
bool unsat = inconsistent();
// TBD do_double(lit, base);
pop_lookahead1(lit);
if (unsat) {
TRACE("sat", tout << "backtracking and settting " << ~lit << "\n";);
reset_wnb();
assign(~lit);
propagate();
init_wnb();
change = true;
}
else {
update_wnb(lit);
}
SASSERT(inconsistent() || !is_unsat());
}
if (c_fixed_truth - 2 * m_lookahead.size() < base) {
break;
}
base += 2 * m_lookahead.size();
}
reset_wnb();
TRACE("sat", display_lookahead(tout); );
@ -1258,23 +1391,11 @@ namespace sat {
l = diff1 < diff2 ? lit : ~lit;
}
}
// if (count > 1) std::cout << count << "\n";
TRACE("sat", tout << "selected: " << l << "\n";);
return l;
}
void push_lookahead1(literal lit, unsigned level) {
m_search_modes.push_back(m_search_mode);
m_search_mode = lookahead1;
scoped_level _sl(*this, level);
assign(lit);
propagate();
}
void pop_lookahead1() {
m_inconsistent = false;
m_search_mode = m_search_modes.back();
m_search_modes.pop_back();
}
void set_wnb(literal l, float f) { m_lits[l.index()].m_wnb = f; }
void inc_wnb(literal l, float f) { m_lits[l.index()].m_wnb += f; }
@ -1289,8 +1410,35 @@ namespace sat {
}
void update_wnb(literal l) {
if (m_weighted_new_binaries == 0) {
// TBD autarky
if (false && m_weighted_new_binaries == 0) {
return;
//
// all consequences of l can be set to true.
// it is an autarky.
// copy the part of the trail that originates from l
// down to the trail that is associated with the
// current search scope.
//
unsigned index = m_trail.size();
while (m_trail[--index] != l);
m_qhead = m_qhead_lim.back();
unsigned old_sz = m_trail_lim.back();
for (unsigned i = old_sz; i < m_trail.size(); ++i) {
set_undef(m_trail[i]);
}
m_qhead_lim.pop_back();
for (unsigned i = index; i < m_trail.size(); ++i) {
l = m_trail[i];
m_trail[old_sz - index + i] = l;
set_true(l);
m_freevars.remove(l.var());
}
m_trail.shrink(old_sz + m_trail.size() - index);
TRACE("sat", tout << "autarky: " << m_trail << "\n";);
m_trail_lim.pop_back();
propagate();
SASSERT(!inconsistent());
init_wnb();
}
else {
inc_wnb(l, m_weighted_new_binaries);
@ -1300,27 +1448,51 @@ namespace sat {
bool dl_enabled(literal l) const { return m_lits[l.index()].m_double_lookahead != m_istamp_id; }
void dl_disable(literal l) { m_lits[l.index()].m_double_lookahead = m_istamp_id; }
void double_look() {
bool unsat;
for (unsigned i = 0; !inconsistent() && i < m_lookahead.size(); ++i) {
literal lit = m_lookahead[i].m_lit;
if (!is_undef(lit)) continue;
bool is_fixed_at(literal lit, unsigned level) const {
return is_fixed(lit) && (!is_false(lit) || m_stamp[lit.var()] >= level);
}
push_lookahead2(lit);
unsat = inconsistent();
pop_lookahead2();
if (unsat) {
TRACE("sat", tout << "unit: " << ~lit << "\n";);
assign(~lit);
continue;
void double_look(literal l, unsigned& base) {
SASSERT(!inconsistent());
SASSERT(base + 2 * m_lookahead.size() * static_cast<uint64>(m_config.m_dl_max_iterations + 1) < c_fixed_truth);
unsigned dl_truth = base + 2 * m_lookahead.size() * (m_config.m_dl_max_iterations + 1);
m_level = dl_truth;
assign(l);
propagate();
bool change = true;
unsigned num_iterations = 0;
while (change && num_iterations < m_config.m_dl_max_iterations && !inconsistent()) {
change = false;
num_iterations++;
for (unsigned i = 0; !inconsistent() && i < m_lookahead.size(); ++i) {
literal lit = m_lookahead[i].m_lit;
if (is_fixed_at(lit, dl_truth)) continue;
if (push_lookahead2(lit, base + m_lookahead[i].m_offset)) {
TRACE("sat", tout << "unit: " << ~lit << "\n";);
SASSERT(m_level == dl_truth);
assign(~lit);
propagate();
change = true;
}
}
SASSERT(dl_truth - 2 * m_lookahead.size() > base);
base += 2*m_lookahead.size();
}
SASSERT(m_level == dl_truth);
base = dl_truth;
}
push_lookahead2(~lit);
unsat = inconsistent();
pop_lookahead2();
if (unsat) {
TRACE("sat", tout << "unit: " << lit << "\n";);
assign(lit);
void do_double(literal l, unsigned& base) {
if (!inconsistent() && scope_lvl() > 0 && dl_enabled(l)) {
if (get_wnb(l) > m_delta_trigger) {
if (base + 2 * m_lookahead.size() * static_cast<uint64>(m_config.m_dl_max_iterations + 1) < c_fixed_truth) {
double_look(l, base);
m_delta_trigger = get_wnb(l);
dl_disable(l);
}
}
else {
m_delta_trigger *= m_config.m_delta_rho;
}
}
}
@ -1332,54 +1504,61 @@ namespace sat {
unsigned scope_lvl() const { return m_trail_lim.size(); }
void assign(literal l) {
TRACE("sat", tout << "assign: " << l << " := " << value(l) << " @ " << m_level << " "; display(tout, m_search_mode) << "\n";);
SASSERT(m_level > 0);
if (is_undef(l)) {
TRACE("sat", tout << "assign: " << l << " @ " << m_level << " " << m_trail_lim.size() << " " << m_search_mode << "\n";);
set_true(l);
m_trail.push_back(l);
if (m_search_mode == searching) {
if (m_search_mode == lookahead_mode::searching) {
m_stats.m_propagations++;
TRACE("sat", tout << "removing free var v" << l.var() << "\n";);
m_freevars.remove(l.var());
}
}
else if (is_false(l)) {
TRACE("sat", tout << "conflict: " << l << " @ " << m_level << " " << m_search_mode << "\n";);
SASSERT(!is_true(l));
set_conflict();
}
}
void do_double(literal l) {
if (!inconsistent() && scope_lvl() > 0 && dl_enabled(l)) {
if (get_wnb(l) > m_delta_trigger) {
double_look();
m_delta_trigger = get_wnb(l);
dl_disable(l);
}
else {
m_delta_trigger *= m_config.m_delta_rho;
}
void propagated(literal l) {
assign(l);
switch (m_search_mode) {
case lookahead_mode::searching:
break;
case lookahead_mode::lookahead1:
m_wstack.push_back(l);
break;
case lookahead_mode::lookahead2:
break;
}
}
bool backtrack(literal_vector& trail) {
if (trail.empty()) return false;
pop();
flip_prefix();
assign(~trail.back());
propagate();
trail.pop_back();
while (inconsistent()) {
if (trail.empty()) return false;
pop();
flip_prefix();
assign(~trail.back());
trail.pop_back();
propagate();
}
return true;
}
lbool search() {
scoped_level _sl(*this, c_fixed_truth);
literal_vector trail;
m_search_mode = searching;
m_search_mode = lookahead_mode::searching;
while (true) {
TRACE("sat", display(tout););
inc_istamp();
s.checkpoint();
if (inconsistent()) {
if (!backtrack(trail)) return l_false;
continue;
}
literal l = choose();
if (inconsistent()) {
if (!backtrack(trail)) return l_false;
@ -1389,8 +1568,11 @@ namespace sat {
return l_true;
}
TRACE("sat", tout << "choose: " << l << " " << trail << "\n";);
++m_stats.m_decisions;
IF_VERBOSE(1, verbose_stream() << "select " << pp_prefix(m_prefix, m_trail_lim.size()) << ": " << l << " " << m_trail.size() << "\n";);
push(l, c_fixed_truth);
trail.push_back(l);
SASSERT(inconsistent() || !is_unsat());
}
}
@ -1414,7 +1596,7 @@ namespace sat {
std::ostream& display_values(std::ostream& out) const {
for (unsigned i = 0; i < m_trail.size(); ++i) {
literal l = m_trail[i];
out << l << " " << m_stamp[l.var()] << "\n";
out << l << "\n";
}
return out;
}
@ -1437,8 +1619,9 @@ namespace sat {
s(s),
m_level(2),
m_prefix(0) {
scoped_level _sl(*this, c_fixed_truth);
init();
m_search_mode = lookahead_mode::searching;
scoped_level _sl(*this, c_fixed_truth);
init();
}
~lookahead() {
@ -1450,13 +1633,36 @@ namespace sat {
}
std::ostream& display(std::ostream& out) const {
out << std::hex << "Prefix: " << m_prefix << std::dec << "\n";
out << "Prefix: " << pp_prefix(m_prefix, m_trail_lim.size()) << "\n";
out << "Level: " << m_level << "\n";
display_values(out);
display_binary(out);
display_clauses(out);
out << "free vars: ";
for (bool_var const* it = m_freevars.begin(), * end = m_freevars.end(); it != end; ++it) {
out << *it << " ";
}
out << "\n";
for (unsigned i = 0; i < m_watches.size(); ++i) {
watch_list const& wl = m_watches[i];
if (!wl.empty()) {
sat::display_watch_list(out << to_literal(i) << " -> ", m_cls_allocator, wl);
out << "\n";
}
}
return out;
}
void collect_statistics(statistics& st) const {
st.update("bool var", m_vprefix.size());
st.update("clauses", m_clauses.size());
st.update("add binary", m_stats.m_add_binary);
st.update("del binary", m_stats.m_del_binary);
st.update("add ternary", m_stats.m_add_ternary);
st.update("del ternary", m_stats.m_del_ternary);
st.update("propagations", m_stats.m_propagations);
st.update("decisions", m_stats.m_decisions);
}
};
}

View file

@ -1256,8 +1256,8 @@ namespace sat {
}
CTRACE("resolve_bug", it2 == end2,
tout << ~l1 << " -> ";
display(tout, s.m_cls_allocator, wlist1); tout << "\n" << ~l2 << " -> ";
display(tout, s.m_cls_allocator, wlist2); tout << "\n";);
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;
}

View file

@ -2998,7 +2998,7 @@ namespace sat {
watch_list const & wlist = *it;
literal l = to_literal(l_idx);
out << l << ": ";
sat::display(out, m_cls_allocator, wlist);
sat::display_watch_list(out, m_cls_allocator, wlist);
out << "\n";
}
}

View file

@ -104,7 +104,7 @@ namespace sat {
inline bool operator==(literal const & l1, literal const & l2) { return l1.m_val == l2.m_val; }
inline bool operator!=(literal const & l1, literal const & l2) { return l1.m_val != l2.m_val; }
inline std::ostream & operator<<(std::ostream & out, literal l) { out << (l.sign() ? "-" : "") << l.var(); return out; }
inline std::ostream & operator<<(std::ostream & out, literal l) { if (l == null_literal) out << "null"; else out << (l.sign() ? "-" : "") << l.var(); return out; }
typedef svector<literal> literal_vector;
typedef std::pair<literal, literal> literal_pair;

View file

@ -39,7 +39,7 @@ namespace sat {
return false;
}
void display(std::ostream & out, clause_allocator const & ca, watch_list const & wlist) {
void display_watch_list(std::ostream & out, clause_allocator const & ca, watch_list const & wlist) {
watch_list::const_iterator it = wlist.begin();
watch_list::const_iterator end = wlist.end();
for (bool first = true; it != end; ++it) {

View file

@ -130,7 +130,7 @@ namespace sat {
inline void erase_ternary_watch(watch_list & wlist, literal l1, literal l2) { wlist.erase(watched(l1, l2)); }
class clause_allocator;
void display(std::ostream & out, clause_allocator const & ca, watch_list const & wlist);
void display_watch_list(std::ostream & out, clause_allocator const & ca, watch_list const & wlist);
};
#endif