3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-23 09:05:31 +00:00

updates to seq and bug fixes (#4056)

* na

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>

* fix #4037

* nicer output for skolem functions

* more overhaul of seq, some bug fixes

* na

* added offset_eq file

* na

* fix #4044

* fix #4040

* fix #4045

* updated ignore

* new rewrites for indexof based on #4036

* add shortcuts

* updated ne solver for seq, fix #4025

* use pair vectors for equalities that are reduced by seq_rewriter

* use erase_and_swap

* remove unit-walk

* na

* add check for #3200

* nits

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>

* name a type

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>

* remove fp check

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>

* remove unsound axiom instantiation for non-contains

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>

* fix rewrites

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>

* fix #4053

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>

* fix #4052

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2020-04-22 13:18:55 -07:00 committed by GitHub
parent 53c14bd554
commit 95a78b2450
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
39 changed files with 1516 additions and 1654 deletions

View file

@ -33,7 +33,6 @@ z3_add_component(sat
sat_scc.cpp
sat_simplifier.cpp
sat_solver.cpp
sat_unit_walk.cpp
sat_watched.cpp
sat_xor_finder.cpp
COMPONENT_DEPENDENCIES

View file

@ -1865,7 +1865,7 @@ namespace sat {
}
ba_solver::ba_solver()
: m_solver(nullptr), m_lookahead(nullptr), m_unit_walk(nullptr),
: m_solver(nullptr), m_lookahead(nullptr),
m_constraint_id(0), m_ba(*this), m_sort(m_ba) {
TRACE("ba", tout << this << "\n";);
m_num_propagations_since_pop = 0;

View file

@ -24,7 +24,6 @@ Revision History:
#include "sat/sat_extension.h"
#include "sat/sat_solver.h"
#include "sat/sat_lookahead.h"
#include "sat/sat_unit_walk.h"
#include "sat/sat_big.h"
#include "util/small_object_allocator.h"
#include "util/scoped_ptr_vector.h"
@ -230,7 +229,6 @@ namespace sat {
solver* m_solver;
lookahead* m_lookahead;
unit_walk* m_unit_walk;
stats m_stats;
small_object_allocator m_allocator;
@ -445,23 +443,20 @@ namespace sat {
inline lbool value(model const& m, literal l) const { return l.sign() ? ~m[l.var()] : m[l.var()]; }
inline bool is_false(literal lit) const { return l_false == value(lit); }
inline unsigned lvl(literal lit) const { return m_lookahead || m_unit_walk ? 0 : m_solver->lvl(lit); }
inline unsigned lvl(bool_var v) const { return m_lookahead || m_unit_walk ? 0 : m_solver->lvl(v); }
inline unsigned lvl(literal lit) const { return m_lookahead ? 0 : m_solver->lvl(lit); }
inline unsigned lvl(bool_var v) const { return m_lookahead ? 0 : m_solver->lvl(v); }
inline bool inconsistent() const {
if (m_lookahead) return m_lookahead->inconsistent();
if (m_unit_walk) return m_unit_walk->inconsistent();
return m_solver->inconsistent();
}
inline watch_list& get_wlist(literal l) { return m_lookahead ? m_lookahead->get_wlist(l) : m_solver->get_wlist(l); }
inline watch_list const& get_wlist(literal l) const { return m_lookahead ? m_lookahead->get_wlist(l) : m_solver->get_wlist(l); }
inline void assign(literal l, justification j) {
if (m_lookahead) m_lookahead->assign(l);
else if (m_unit_walk) m_unit_walk->assign(l);
else m_solver->assign(l, j);
}
inline void set_conflict(justification j, literal l) {
if (m_lookahead) m_lookahead->set_conflict();
else if (m_unit_walk) m_unit_walk->set_conflict();
else m_solver->set_conflict(j, l);
}
inline config const& get_config() const { return m_lookahead ? m_lookahead->get_config() : m_solver->get_config(); }
@ -544,7 +539,6 @@ namespace sat {
~ba_solver() override;
void set_solver(solver* s) override { m_solver = s; }
void set_lookahead(lookahead* l) override { m_lookahead = l; }
void set_unit_walk(unit_walk* u) override { m_unit_walk = u; }
void add_at_least(bool_var v, literal_vector const& lits, unsigned k);
void add_pb_ge(bool_var v, svector<wliteral> const& wlits, unsigned k);
void add_xr(literal_vector const& lits);

View file

@ -98,8 +98,6 @@ namespace sat {
else
m_local_search_mode = local_search_mode::wsat;
m_local_search_dbg_flips = p.local_search_dbg_flips();
m_unit_walk = p.unit_walk();
m_unit_walk_threads = p.unit_walk_threads();
m_binspr = p.binspr();
m_binspr = false; // prevent adventurous users from trying feature that isn't ready
m_anf_simplify = p.anf();

View file

@ -117,8 +117,6 @@ namespace sat {
bool m_local_search;
local_search_mode m_local_search_mode;
bool m_local_search_dbg_flips;
unsigned m_unit_walk_threads;
bool m_unit_walk;
bool m_binspr;
bool m_cut_simplify;
unsigned m_cut_delay;

View file

@ -52,7 +52,6 @@ namespace sat {
virtual ~extension() {}
virtual void set_solver(solver* s) = 0;
virtual void set_lookahead(lookahead* s) = 0;
virtual void set_unit_walk(unit_walk* u) = 0;
virtual bool propagate(literal l, ext_constraint_idx idx) = 0;
virtual double get_reward(literal l, ext_constraint_idx idx, literal_occs_fun& occs) const = 0;
virtual void get_antecedents(literal l, ext_justification_idx idx, literal_vector & r) = 0;

View file

@ -67,8 +67,6 @@ def_module_params('sat',
('local_search_threads', UINT, 0, 'number of local search threads to find satisfiable solution'),
('local_search_mode', SYMBOL, 'wsat', 'local search algorithm, either default wsat or qsat'),
('local_search_dbg_flips', BOOL, False, 'write debug information for number of flips'),
('unit_walk', BOOL, False, 'use unit-walk search instead of CDCL'),
('unit_walk_threads', UINT, 0, 'number of unit-walk search threads to find satisfiable solution'),
('binspr', BOOL, False, 'enable SPR inferences of binary propagation redundant clauses. This inprocessing step eliminates models'),
('anf', BOOL, False, 'enable ANF based simplification in-processing'),
('anf.delay', UINT, 2, 'delay ANF simplification by in-processing round'),

View file

@ -27,7 +27,6 @@ Revision History:
#include "sat/sat_solver.h"
#include "sat/sat_integrity_checker.h"
#include "sat/sat_lookahead.h"
#include "sat/sat_unit_walk.h"
#include "sat/sat_ddfw.h"
#include "sat/sat_prob.h"
#include "sat/sat_anf_simplifier.h"
@ -1194,7 +1193,7 @@ namespace sat {
return do_local_search(num_lits, lits);
}
if ((m_config.m_num_threads > 1 || m_config.m_local_search_threads > 0 ||
m_config.m_ddfw_threads > 0 || m_config.m_unit_walk_threads > 0) && !m_par) {
m_config.m_ddfw_threads > 0) && !m_par) {
SASSERT(scope_lvl() == 0);
return check_par(num_lits, lits);
}
@ -1214,10 +1213,6 @@ namespace sat {
if (check_inconsistent()) return l_false;
if (m_config.m_force_cleanup) do_cleanup(true);
if (m_config.m_unit_walk) {
return do_unit_walk();
}
if (m_config.m_gc_burst) {
// force gc
m_conflicts_since_gc = m_gc_threshold + 1;
@ -1326,19 +1321,6 @@ namespace sat {
return invoke_local_search(num_lits, lits);
}
lbool solver::do_unit_walk() {
unit_walk srch(*this);
lbool r = srch();
if (r == l_true) {
m_model.reset();
for (bool_var v = 0; v < num_vars(); ++v) {
m_model.push_back(m_assignment[literal(v,false).index()]);
}
m_model_is_current = true;
}
return r;
}
lbool solver::check_par(unsigned num_lits, literal const* lits) {
if (!rlimit().inc()) {
return l_undef;
@ -1347,9 +1329,8 @@ namespace sat {
scoped_ptr_vector<solver> uw;
int num_extra_solvers = m_config.m_num_threads - 1;
int num_local_search = static_cast<int>(m_config.m_local_search_threads);
int num_unit_walk = static_cast<int>(m_config.m_unit_walk_threads);
int num_ddfw = m_ext ? 0 : static_cast<int>(m_config.m_ddfw_threads);
int num_threads = num_extra_solvers + 1 + num_local_search + num_unit_walk + num_ddfw;
int num_threads = num_extra_solvers + 1 + num_local_search + num_ddfw;
for (int i = 0; i < num_local_search; ++i) {
local_search* l = alloc(local_search);
l->updt_params(m_params);
@ -1357,6 +1338,8 @@ namespace sat {
l->set_seed(m_config.m_random_seed + i);
ls.push_back(l);
}
vector<reslimit> lims(num_ddfw);
// set up ddfw search
for (int i = 0; i < num_ddfw; ++i) {
ddfw* d = alloc(ddfw);
@ -1365,23 +1348,11 @@ namespace sat {
d->add(*this);
ls.push_back(d);
}
// set up unit walk
vector<reslimit> lims(num_unit_walk + num_ddfw);
for (int i = 0; i < num_unit_walk; ++i) {
solver* s = alloc(solver, m_params, lims[i]);
s->copy(*this);
s->m_config.m_unit_walk = true;
uw.push_back(s);
}
int local_search_offset = num_extra_solvers;
int unit_walk_offset = num_extra_solvers + num_local_search + num_ddfw;
int main_solver_offset = unit_walk_offset + num_unit_walk;
int main_solver_offset = num_extra_solvers + num_local_search + num_ddfw;
#define IS_AUX_SOLVER(i) (0 <= i && i < num_extra_solvers)
#define IS_LOCAL_SEARCH(i) (local_search_offset <= i && i < unit_walk_offset)
#define IS_UNIT_WALK(i) (unit_walk_offset <= i && i < main_solver_offset)
#define IS_LOCAL_SEARCH(i) (local_search_offset <= i && i < main_solver_offset)
#define IS_MAIN_SOLVER(i) (i == main_solver_offset)
sat::parallel par(*this);
@ -1413,9 +1384,6 @@ namespace sat {
else if (IS_LOCAL_SEARCH(i)) {
r = ls[i-local_search_offset]->check(num_lits, lits, &par);
}
else if (IS_UNIT_WALK(i)) {
r = uw[i-unit_walk_offset]->check(num_lits, lits);
}
else {
r = check(num_lits, lits);
}
@ -1484,9 +1452,6 @@ namespace sat {
if (result == l_true && IS_LOCAL_SEARCH(finished_id)) {
set_model(ls[finished_id - local_search_offset]->get_model(), true);
}
if (result == l_true && IS_UNIT_WALK(finished_id)) {
set_model(uw[finished_id - unit_walk_offset]->get_model(), true);
}
if (!canceled) {
rlimit().reset_cancel();
}

View file

@ -1,514 +0,0 @@
/*++
Copyright (c) 2017 Microsoft Corporation
Module Name:
sat_unit_walk.cpp
Abstract:
unit walk local search procedure.
A variant of UnitWalk. Hirsch and Kojevinkov, SAT 2001.
This version uses a trail to reset assignments and integrates directly with the
watch list structure. Thus, assignments are not delayed and we avoid treating
pending units as a multi-set.
It uses standard DPLL approach for backracking, flipping the last decision literal that
lead to a conflict. It restarts after evern 100 conflicts.
It does not attempt to add conflict clauses
It can receive conflict clauses from a concurrent CDCL solver
The phase of variables is optionally sticky between rounds. We use a decay rate
to compute stickiness of a variable.
Author:
Nikolaj Bjorner (nbjorner) 2017-12-15.
Revision History:
2018-11-5:
change reinitialization to use local search with limited timeouts to find phase and ordering of variables.
--*/
#include "sat/sat_unit_walk.h"
#include "util/luby.h"
namespace sat {
bool_var unit_walk::var_priority::peek(solver& s) {
while (m_head < m_vars.size()) {
bool_var v = m_vars[m_head];
unsigned idx = literal(v, false).index();
if (s.m_assignment[idx] == l_undef) {
// IF_VERBOSE(0, verbose_stream() << "pop " << v << "\n");
return v;
}
++m_head;
}
for (bool_var v : m_vars) {
if (s.m_assignment[literal(v, false).index()] == l_undef) {
IF_VERBOSE(0, verbose_stream() << "unassigned: " << v << "\n");
}
}
IF_VERBOSE(0, verbose_stream() << "#vars: " << m_vars.size() << "\n");
IF_VERBOSE(0, verbose_stream() << "(sat.unit-walk sat)\n");
return null_bool_var;
}
void unit_walk::var_priority::set_vars(solver& s) {
m_vars.reset();
s.pop_to_base_level();
for (unsigned v = 0; v < s.num_vars(); ++v) {
if (!s.was_eliminated(v) && s.value(v) == l_undef) {
add(v);
}
}
IF_VERBOSE(0, verbose_stream() << "num vars " << m_vars.size() << "\n";);
}
bool_var unit_walk::var_priority::next(solver& s) {
bool_var v = peek(s);
++m_head;
return v;
}
unit_walk::unit_walk(solver& s):
s(s) {
m_max_conflicts = 10000;
m_flips = 0;
}
class scoped_set_unit_walk {
solver& s;
public:
scoped_set_unit_walk(unit_walk* u, solver& s): s(s) {
if (s.get_extension()) s.get_extension()->set_unit_walk(u);
}
~scoped_set_unit_walk() {
if (s.get_extension()) s.get_extension()->set_unit_walk(nullptr);
}
};
lbool unit_walk::operator()() {
m_inconsistent = false;
scoped_set_unit_walk _scoped_set(this, s);
if (init_runs())
return l_true;
init_propagation();
init_phase();
lbool st = l_undef;
while (s.rlimit().inc() && st == l_undef) {
if (inconsistent() && !m_decisions.empty()) do_pop();
else if (inconsistent()) st = l_false;
else if (should_restart()) restart();
else if (should_backjump()) st = do_backjump();
else st = decide();
}
log_status();
return st;
}
void unit_walk::do_pop() {
update_max_trail();
++s.m_stats.m_conflict;
pop();
propagate();
}
lbool unit_walk::decide() {
bool_var v = pqueue().next(s);
if (v == null_bool_var) {
return l_true;
}
literal lit(v, !m_phase[v]);
++s.m_stats.m_decision;
m_decisions.push_back(lit);
pqueue().push();
assign(lit);
propagate();
return l_undef;
}
bool unit_walk::should_backjump() {
return
s.m_stats.m_conflict >= m_max_conflicts && m_decisions.size() > 20;
}
lbool unit_walk::do_backjump() {
unsigned backjump_level = m_decisions.size(); // - (m_decisions.size()/20);
lbool st = update_priority(backjump_level);
switch (st) {
case l_true: return l_true;
case l_false: break; // TBD
default: break;
}
if (refresh_solver())
return l_true;
return l_undef;
}
void unit_walk::pop() {
SASSERT (!m_decisions.empty());
literal dlit = m_decisions.back();
pop_decision();
assign(~dlit);
}
void unit_walk::pop_decision() {
SASSERT (!m_decisions.empty());
literal dlit = m_decisions.back();
literal lit;
do {
SASSERT(!m_trail.empty());
lit = m_trail.back();
s.m_assignment[lit.index()] = l_undef;
s.m_assignment[(~lit).index()] = l_undef;
m_trail.pop_back();
}
while (lit != dlit);
m_qhead = m_trail.size();
m_decisions.pop_back();
pqueue().pop();
m_inconsistent = false;
}
bool unit_walk::init_runs() {
m_luby_index = 0;
m_restart_threshold = 1000;
m_max_trail = 0;
m_trail.reset();
m_decisions.reset();
m_phase.resize(s.num_vars());
m_phase_tf.resize(s.num_vars(), ema(1e-5));
pqueue().reset();
pqueue().set_vars(s);
for (unsigned v = 0; v < s.num_vars(); ++v) {
m_phase_tf[v].update(50);
}
m_ls.import(s, true);
m_rand.set_seed(s.rand()());
return l_true == update_priority(0);
}
lbool unit_walk::do_local_search(unsigned num_rounds) {
unsigned prefix_length = (0*m_trail.size())/10;
for (unsigned v = 0; v < s.num_vars(); ++v) {
m_ls.set_bias(v, m_phase_tf[v] >= 50 ? l_true : l_false);
}
for (literal lit : m_trail) {
m_ls.set_bias(lit.var(), lit.sign() ? l_false : l_true);
}
m_ls.rlimit().push(num_rounds);
lbool is_sat = m_ls.check(prefix_length, m_trail.c_ptr(), nullptr);
m_ls.rlimit().pop();
return is_sat;
}
lbool unit_walk::update_priority(unsigned level) {
while (m_decisions.size() > level) {
pop_decision();
}
IF_VERBOSE(1, verbose_stream() << "(sat.unit-walk :update-priority " << m_decisions.size() << ")\n");
unsigned num_rounds = 50;
log_status();
lbool is_sat = do_local_search(num_rounds);
switch (is_sat) {
case l_true:
for (unsigned v = 0; v < s.num_vars(); ++v) {
s.m_assignment[v] = m_ls.get_model()[v];
}
return l_true;
case l_false:
if (m_decisions.empty()) {
return l_false;
}
else {
pop();
return l_undef;
}
default:
update_pqueue();
return l_undef;
}
}
/**
* \brief Reshuffle variables in the priority queue using the break counts from local search.
*/
struct compare_break {
local_search& ls;
compare_break(local_search& ls): ls(ls) {}
int operator()(bool_var v, bool_var w) const {
return ls.get_priority(v) > ls.get_priority(w);
}
};
void unit_walk::update_pqueue() {
compare_break cb(m_ls);
std::sort(pqueue().begin(), pqueue().end(), cb);
for (bool_var v : pqueue()) {
m_phase_tf[v].update(m_ls.cur_solution(v) ? 100 : 0);
m_phase[v] = l_true == m_ls.cur_solution(v);
}
pqueue().rewind();
}
void unit_walk::init_phase() {
for (bool_var v : pqueue()) {
m_phase[v] = s.m_phase[v];
}
}
bool unit_walk::refresh_solver() {
m_max_conflicts += m_conflict_offset ;
m_conflict_offset += 10000;
if (s.m_par && s.m_par->copy_solver(s)) {
IF_VERBOSE(1, verbose_stream() << "(sat.unit-walk fresh copy)\n";);
if (s.get_extension()) s.get_extension()->set_unit_walk(this);
if (init_runs())
return true;
init_phase();
}
return false;
}
bool unit_walk::should_restart() {
if (s.m_stats.m_conflict >= m_restart_threshold) {
m_restart_threshold = s.get_config().m_restart_initial * get_luby(m_luby_index);
++m_luby_index;
return true;
}
return false;
}
void unit_walk::restart() {
while (!m_decisions.empty()) {
pop_decision();
}
}
void unit_walk::update_max_trail() {
if (m_max_trail == 0 || m_trail.size() > m_max_trail) {
m_max_trail = m_trail.size();
m_restart_threshold += 10000;
m_max_conflicts = s.m_stats.m_conflict + 20000;
log_status();
}
}
void unit_walk::init_propagation() {
if (s.m_par && s.m_par->copy_solver(s)) {
IF_VERBOSE(1, verbose_stream() << "(sat.unit-walk fresh copy)\n";);
if (s.get_extension()) s.get_extension()->set_unit_walk(this);
init_runs();
init_phase();
}
for (literal lit : m_trail) {
s.m_assignment[lit.index()] = l_undef;
s.m_assignment[(~lit).index()] = l_undef;
}
m_flips = 0;
m_trail.reset();
s.m_stats.m_conflict = 0;
m_conflict_offset = 10000;
m_decisions.reset();
m_qhead = 0;
m_inconsistent = false;
}
void unit_walk::propagate() {
while (m_qhead < m_trail.size() && !inconsistent()) {
propagate(m_trail[m_qhead++]);
}
}
std::ostream& unit_walk::display(std::ostream& out) const {
unsigned i = 0;
out << "num decisions: " << m_decisions.size() << "\n";
for (literal lit : m_trail) {
if (i < m_decisions.size() && m_decisions[i] == lit) {
out << "d " << i << ": ";
++i;
}
out << lit << "\n";
}
s.display(verbose_stream());
return out;
}
void unit_walk::propagate(literal l) {
++s.m_stats.m_propagate;
literal not_l = ~l;
literal l1, l2;
lbool val1, val2;
bool keep;
watch_list & wlist = s.get_wlist(l);
watch_list::iterator it = wlist.begin();
watch_list::iterator it2 = it;
watch_list::iterator end = wlist.end();
for (; it != end; ++it) {
switch (it->get_kind()) {
case watched::BINARY:
l1 = it->get_literal();
switch (value(l1)) {
case l_false:
conflict_cleanup(it, it2, wlist);
set_conflict(l,l1);
return;
case l_undef:
assign(l1);
break;
case l_true:
break; // skip
}
*it2 = *it;
it2++;
break;
case watched::TERNARY:
l1 = it->get_literal1();
l2 = it->get_literal2();
val1 = value(l1);
val2 = value(l2);
if (val1 == l_false && val2 == l_undef) {
assign(l2);
}
else if (val1 == l_undef && val2 == l_false) {
assign(l1);
}
else if (val1 == l_false && val2 == l_false) {
conflict_cleanup(it, it2, wlist);
set_conflict(l,l1,l2);
return;
}
*it2 = *it;
it2++;
break;
case watched::CLAUSE: {
if (value(it->get_blocked_literal()) == l_true) {
*it2 = *it;
it2++;
break;
}
clause_offset cls_off = it->get_clause_offset();
clause & c = s.get_clause(cls_off);
if (c[0] == not_l)
std::swap(c[0], c[1]);
if (c[1] != not_l) {
*it2 = *it;
it2++;
break;
}
if (value(c[0]) == l_true) {
it2->set_clause(c[0], cls_off);
it2++;
break;
}
SASSERT(c[1] == not_l);
literal * l_it = c.begin() + 2;
literal * l_end = c.end();
for (; l_it != l_end; ++l_it) {
if (value(*l_it) != l_false) {
c[1] = *l_it;
*l_it = not_l;
s.get_wlist((~c[1]).index()).push_back(watched(c[0], cls_off));
goto end_clause_case;
}
}
SASSERT(value(c[0]) == l_false || value(c[0]) == l_undef);
if (value(c[0]) == l_false) {
c.mark_used();
conflict_cleanup(it, it2, wlist);
set_conflict(c);
return;
}
else {
*it2 = *it;
it2++;
assign(c[0]);
}
end_clause_case:
break;
}
case watched::EXT_CONSTRAINT:
SASSERT(s.get_extension());
keep = s.get_extension()->propagate(l, it->get_ext_constraint_idx());
if (inconsistent()) {
if (!keep) {
++it;
}
set_conflict(l, l);
conflict_cleanup(it, it2, wlist);
return;
}
if (keep) {
*it2 = *it;
it2++;
}
break;
default:
UNREACHABLE();
break;
}
}
wlist.set_end(it2);
}
void unit_walk::assign(literal lit) {
VERIFY(value(lit) == l_undef);
s.m_assignment[lit.index()] = l_true;
s.m_assignment[(~lit).index()] = l_false;
m_trail.push_back(lit);
if (s.get_extension() && s.is_external(lit.var())) {
s.get_extension()->asserted(lit);
}
if (m_phase[lit.var()] == lit.sign()) {
++m_flips;
flip_phase(lit);
m_phase_tf[lit.var()].update(m_phase[lit.var()] ? 100 : 0);
}
}
void unit_walk::flip_phase(literal l) {
bool_var v = l.var();
m_phase[v] = !m_phase[v];
}
void unit_walk::log_status() {
IF_VERBOSE(1, verbose_stream()
<< "(sat.unit-walk"
<< " :trail " << m_trail.size()
<< " :depth " << m_decisions.size()
<< " :decisions " << s.m_stats.m_decision
<< " :propagations " << s.m_stats.m_propagate
<< " :conflicts " << s.m_stats.m_conflict
<< ")\n";);
}
void unit_walk::set_conflict(literal l1, literal l2) {
set_conflict();
}
void unit_walk::set_conflict(literal l1, literal l2, literal l3) {
set_conflict();
}
void unit_walk::set_conflict(clause const& c) {
set_conflict();
}
void unit_walk::set_conflict() {
m_inconsistent = true;
}
};

View file

@ -1,112 +0,0 @@
/*++
Copyright (c) 2017 Microsoft Corporation
Module Name:
sat_unit_walk.h
Abstract:
unit walk local search procedure.
Author:
Nikolaj Bjorner (nbjorner) 2017-12-15.
Revision History:
--*/
#ifndef SAT_UNIT_WALK_H_
#define SAT_UNIT_WALK_H_
#include "sat/sat_solver.h"
#include "sat/sat_local_search.h"
#include "util/ema.h"
namespace sat {
class unit_walk {
#if 0
struct double2 {
double t, f;
};
#endif
class var_priority {
svector<bool_var> m_vars;
unsigned_vector m_lim;
unsigned m_head;
public:
var_priority() { m_head = 0; }
void reset() { m_lim.reset(); m_head = 0;}
void rewind() { for (unsigned& l : m_lim) l = 0; m_head = 0;}
void add(bool_var v) { m_vars.push_back(v); }
bool_var next(solver& s);
bool_var peek(solver& s);
void set_vars(solver& s);
void push() { m_lim.push_back(m_head); }
void pop() { m_head = m_lim.back(); m_lim.pop_back(); }
bool empty() const { return m_lim.empty(); }
bool_var const* begin() const { return m_vars.begin(); }
bool_var const* end() const { return m_vars.end(); }
bool_var* begin() { return m_vars.begin(); }
bool_var* end() { return m_vars.end(); }
};
solver& s;
local_search m_ls;
random_gen m_rand;
bool_vector m_phase;
svector<ema> m_phase_tf;
var_priority m_priorities;
unsigned m_luby_index;
unsigned m_restart_threshold;
// settings
unsigned m_max_conflicts;
unsigned m_flips;
unsigned m_max_trail;
unsigned m_qhead;
literal_vector m_trail;
bool m_inconsistent;
literal_vector m_decisions;
unsigned m_conflict_offset;
svector<lbool> m_model;
bool should_restart();
void do_pop();
bool should_backjump();
lbool do_backjump();
lbool do_local_search(unsigned num_rounds);
lbool decide();
void restart();
void pop();
void pop_decision();
bool init_runs();
lbool update_priority(unsigned level);
void update_pqueue();
void init_phase();
void init_propagation();
bool refresh_solver();
void update_max_trail();
void flip_phase(literal l);
void propagate();
void propagate(literal lit);
void set_conflict(literal l1, literal l2);
void set_conflict(literal l1, literal l2, literal l3);
void set_conflict(clause const& c);
inline lbool value(literal lit) { return s.value(lit); }
void log_status();
var_priority& pqueue() { return m_priorities; }
public:
unit_walk(solver& s);
lbool operator()();
std::ostream& display(std::ostream& out) const;
bool inconsistent() const { return m_inconsistent; }
void set_conflict();
void assign(literal lit);
};
};
#endif