3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-15 13:28:47 +00:00

local search updates

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2017-03-05 14:40:58 -08:00
parent a7db118ebc
commit fda5809c89
7 changed files with 364 additions and 249 deletions

View file

@ -1,21 +1,21 @@
/*++ /*++
Copyright (c) 2017 Microsoft Corporation Copyright (c) 2017 Microsoft Corporation
Module Name: Module Name:
sat_local_search.cpp sat_local_search.cpp
Abstract: Abstract:
Local search module for cardinality clauses. Local search module for cardinality clauses.
Author: Author:
Sixue Liu 2017-2-21 Sixue Liu 2017-2-21
Notes: Notes:
--*/ --*/
#include "sat_local_search.h" #include "sat_local_search.h"
#include "sat_solver.h" #include "sat_solver.h"
@ -27,10 +27,18 @@ namespace sat {
void local_search::init() { void local_search::init() {
for (unsigned i = 0; i < m_assumptions.size(); ++i) {
add_clause(1, m_assumptions.c_ptr() + i);
}
// add sentinel variable. // add sentinel variable.
m_vars.push_back(var_info()); m_vars.push_back(var_info());
best_solution.resize(num_vars() + 1, false); for (unsigned v = 0; v < num_vars(); ++v) {
m_vars[v].m_value = (0 == (m_rand() % 2));
}
m_best_solution.resize(num_vars() + 1, false);
m_index_in_unsat_stack.resize(num_constraints(), 0); m_index_in_unsat_stack.resize(num_constraints(), 0);
coefficient_in_ob_constraint.resize(num_vars() + 1, 0); coefficient_in_ob_constraint.resize(num_vars() + 1, 0);
@ -58,13 +66,12 @@ namespace sat {
set_parameters(); set_parameters();
} }
void local_search::reinit() {
reinit_orig();
}
void local_search::init_cur_solution() { void local_search::init_cur_solution() {
for (unsigned v = 0; v < num_vars(); ++v) { for (unsigned v = 0; v < num_vars(); ++v) {
m_vars[v].m_value = ((unsigned)(m_rand() % 100) < m_vars[v].m_bias); // use bias half the time.
if (m_rand() % 100 < 50) {
m_vars[v].m_value = ((unsigned)(m_rand() % 100) < m_vars[v].m_bias);
}
} }
} }
@ -114,16 +121,16 @@ namespace sat {
// init goodvars // init goodvars
void local_search::init_goodvars() { void local_search::init_goodvars() {
goodvar_stack.reset(); m_goodvar_stack.reset();
for (unsigned v = 0; v < num_vars(); ++v) { for (unsigned v = 0; v < num_vars(); ++v) {
if (score(v) > 0) { // && conf_change[v] == true if (score(v) > 0) { // && conf_change[v] == true
m_vars[v].m_in_goodvar_stack = true; m_vars[v].m_in_goodvar_stack = true;
goodvar_stack.push_back(v); m_goodvar_stack.push_back(v);
} }
} }
} }
void local_search::reinit_orig() { void local_search::reinit() {
for (unsigned i = 0; i < m_constraints.size(); ++i) { for (unsigned i = 0; i < m_constraints.size(); ++i) {
constraint& c = m_constraints[i]; constraint& c = m_constraints[i];
c.m_slack = c.m_k; c.m_slack = c.m_k;
@ -132,7 +139,7 @@ namespace sat {
// init unsat stack // init unsat stack
m_unsat_stack.reset(); m_unsat_stack.reset();
// init solution: random now // init solution using the bias
init_cur_solution(); init_cur_solution();
// init varibale information // init varibale information
@ -142,7 +149,7 @@ namespace sat {
m_vars.back().m_conf_change = false; m_vars.back().m_conf_change = false;
m_vars.back().m_slack_score = INT_MIN; m_vars.back().m_slack_score = INT_MIN;
m_vars.back().m_cscc = 0; m_vars.back().m_cscc = 0;
m_vars.back().m_time_stamp = max_steps + 1; m_vars.back().m_time_stamp = m_max_steps + 1;
for (unsigned i = 0; i < num_vars(); ++i) { for (unsigned i = 0; i < num_vars(); ++i) {
m_vars[i].m_time_stamp = 0; m_vars[i].m_time_stamp = 0;
m_vars[i].m_cscc = 1; m_vars[i].m_cscc = 1;
@ -158,18 +165,18 @@ namespace sat {
void local_search::calculate_and_update_ob() { void local_search::calculate_and_update_ob() {
unsigned i, v; unsigned i, v;
objective_value = 0; int objective_value = 0;
for (i = 0; i < ob_constraint.size(); ++i) { for (i = 0; i < ob_constraint.size(); ++i) {
v = ob_constraint[i].var_id; v = ob_constraint[i].var_id;
if (cur_solution(v)) if (cur_solution(v))
objective_value += ob_constraint[i].coefficient; objective_value += ob_constraint[i].coefficient;
} }
if (objective_value > best_objective_value) { if (objective_value > m_best_objective_value) {
best_solution.reset(); m_best_solution.reset();
for (unsigned v = 0; v < num_vars(); ++v) { for (unsigned v = 0; v < num_vars(); ++v) {
best_solution.push_back(cur_solution(v)); m_best_solution.push_back(cur_solution(v));
} }
best_objective_value = objective_value; m_best_objective_value = objective_value;
} }
} }
@ -230,8 +237,13 @@ namespace sat {
} }
} }
local_search::local_search(solver& s) : local_search::local_search() :
m_par(0) { m_par(0) {
}
void local_search::import(solver& s, bool _init) {
m_vars.reset();
m_constraints.reset();
m_vars.reserve(s.num_vars()); m_vars.reserve(s.num_vars());
@ -268,6 +280,7 @@ namespace sat {
clause& c = *(*it); clause& c = *(*it);
add_clause(c.size(), c.begin()); add_clause(c.size(), c.begin());
} }
m_num_non_binary_clauses = s.m_clauses.size();
// copy cardinality clauses // copy cardinality clauses
card_extension* ext = dynamic_cast<card_extension*>(s.get_extension()); card_extension* ext = dynamic_cast<card_extension*>(s.get_extension());
@ -316,6 +329,9 @@ namespace sat {
// //
SASSERT(ext->m_xors.empty()); SASSERT(ext->m_xors.empty());
} }
if (_init) {
init();
}
} }
local_search::~local_search() { local_search::~local_search() {
@ -329,30 +345,32 @@ namespace sat {
return check(0, 0); return check(0, 0);
} }
#define PROGRESS(tries, total_steps) \ #define PROGRESS(tries, flips) \
if (tries % 10 == 0 || m_unsat_stack.empty()) { \ if (tries % 10 == 0 || m_unsat_stack.empty()) { \
IF_VERBOSE(1, verbose_stream() << "(sat-local-search" \ IF_VERBOSE(1, verbose_stream() << "(sat-local-search" \
<< " :tries " << tries \ << " :flips " << flips \
<< " :steps " << total_steps \
<< " :unsat " << m_unsat_stack.size() \ << " :unsat " << m_unsat_stack.size() \
<< " :time " << timer.get_seconds() << ")\n";); \ << " :time " << (timer.get_seconds() < 0.001 ? 0.0 : timer.get_seconds()) << ")\n";); \
} }
void local_search::walksat() { void local_search::walksat() {
reinit(); reinit();
timer timer; timer timer;
timer.start(); timer.start();
unsigned step = 0, total_steps = 0, max_steps = (1 << 17), tries = 0; unsigned step = 0, total_flips = 0, tries = 0;
PROGRESS(tries, total_steps); PROGRESS(tries, total_flips);
for (tries = 1; !m_unsat_stack.empty() && m_limit.inc(); ++tries) { for (tries = 1; !m_unsat_stack.empty() && m_limit.inc(); ++tries) {
for (step = 0; step < max_steps && !m_unsat_stack.empty(); ++step) { for (step = 0; step < m_max_steps && !m_unsat_stack.empty(); ++step) {
pick_flip_walksat(); pick_flip_walksat();
} }
total_steps += step; total_flips += step;
PROGRESS(tries, total_steps); PROGRESS(tries, total_flips);
if (m_par && tries % 30 == 0) {
m_par->get_phase(*this);
reinit();
}
} }
PROGRESS(tries, total_steps);
} }
void local_search::gsat() { void local_search::gsat() {
@ -361,14 +379,14 @@ namespace sat {
bool_var flipvar; bool_var flipvar;
timer timer; timer timer;
timer.start(); timer.start();
unsigned tries, step = 0, total_steps = 0; unsigned tries, step = 0, total_flips = 0;
for (tries = 1; m_limit.inc() && !m_unsat_stack.empty(); ++tries) { for (tries = 1; m_limit.inc() && !m_unsat_stack.empty(); ++tries) {
reinit(); reinit();
for (step = 1; step <= max_steps; ) { for (step = 1; step <= m_max_steps; ) {
// feasible // feasible
if (m_unsat_stack.empty()) { if (m_unsat_stack.empty()) {
calculate_and_update_ob(); calculate_and_update_ob();
if (best_objective_value >= best_known_value) { if (m_best_objective_value >= m_best_known_value) {
break; break;
} }
} }
@ -376,24 +394,21 @@ namespace sat {
flip_gsat(flipvar); flip_gsat(flipvar);
m_vars[flipvar].m_time_stamp = step++; m_vars[flipvar].m_time_stamp = step++;
} }
total_steps += step; total_flips += step;
PROGRESS(tries, total_steps); PROGRESS(tries, total_flips);
// tell the SAT solvers about the phase of variables. // tell the SAT solvers about the phase of variables.
if (m_par && tries % 10 == 0) { if (m_par && tries % 10 == 0) {
m_par->get_phase(*this); m_par->get_phase(*this);
} }
} }
PROGRESS(tries, total_steps);
} }
lbool local_search::check(unsigned sz, literal const* assumptions, parallel* p) { lbool local_search::check(unsigned sz, literal const* assumptions, parallel* p) {
flet<parallel*> _p(m_par, p); flet<parallel*> _p(m_par, p);
m_model.reset(); m_model.reset();
unsigned num_constraints = m_constraints.size(); m_assumptions.reset();
for (unsigned i = 0; i < sz; ++i) { m_assumptions.append(sz, assumptions);
add_clause(1, assumptions + i);
}
init(); init();
switch (m_config.mode()) { switch (m_config.mode()) {
@ -407,7 +422,7 @@ namespace sat {
// remove unit clauses from assumptions. // remove unit clauses from assumptions.
m_constraints.shrink(num_constraints); m_constraints.shrink(num_constraints() - sz);
TRACE("sat", display(tout);); TRACE("sat", display(tout););
@ -441,7 +456,8 @@ namespace sat {
} }
void local_search::pick_flip_walksat() { void local_search::pick_flip_walksat() {
m_good_vars.reset(); bool_var best_var = null_bool_var;
unsigned n = 1;
bool_var v = null_bool_var; bool_var v = null_bool_var;
unsigned num_unsat = m_unsat_stack.size(); unsigned num_unsat = m_unsat_stack.size();
constraint const& c = m_constraints[m_unsat_stack[m_rand() % m_unsat_stack.size()]]; constraint const& c = m_constraints[m_unsat_stack[m_rand() % m_unsat_stack.size()]];
@ -454,7 +470,7 @@ namespace sat {
literal l; literal l;
for (; !is_true(*cit); ++cit) { SASSERT(cit != cend); } for (; !is_true(*cit); ++cit) { SASSERT(cit != cend); }
l = *cit; l = *cit;
v = l.var(); best_var = v = l.var();
bool tt = cur_solution(v); bool tt = cur_solution(v);
int_vector const& falsep = m_vars[v].m_watch[!tt]; int_vector const& falsep = m_vars[v].m_watch[!tt];
int_vector::const_iterator it = falsep.begin(), end = falsep.end(); int_vector::const_iterator it = falsep.begin(), end = falsep.end();
@ -465,7 +481,6 @@ namespace sat {
else if (slack == 0) else if (slack == 0)
best_bsb += num_unsat; best_bsb += num_unsat;
} }
m_good_vars.push_back(v);
++cit; ++cit;
for (; cit != cend; ++cit) { for (; cit != cend; ++cit) {
l = *cit; l = *cit;
@ -494,11 +509,14 @@ namespace sat {
if (it == end) { if (it == end) {
if (bsb < best_bsb) { if (bsb < best_bsb) {
best_bsb = bsb; best_bsb = bsb;
m_good_vars.reset(); best_var = v;
m_good_vars.push_back(v); n = 1;
} }
else {// if (bb == best_bb) else {// if (bb == best_bb)
m_good_vars.push_back(v); ++n;
if (m_rand() % n == 0) {
best_var = v;
}
} }
} }
} }
@ -506,32 +524,36 @@ namespace sat {
} }
else { else {
for (unsigned i = 0; i < c.size(); ++i) { for (unsigned i = 0; i < c.size(); ++i) {
if (is_true(c[i])) if (is_true(c[i])) {
m_good_vars.push_back(c[i].var()); if (m_rand() % n == 0) {
best_var = c[i].var();
}
++n;
}
} }
} }
SASSERT(!m_good_vars.empty()); flip_walksat(best_var);
//std::cout << m_good_vars.size() << "\n";
flip_walksat(m_good_vars[m_rand() % m_good_vars.size()]);
} }
void local_search::flip_walksat(bool_var flipvar) { void local_search::flip_walksat(bool_var flipvar) {
m_vars[flipvar].m_value = !cur_solution(flipvar); m_vars[flipvar].m_value = !cur_solution(flipvar);
bool flip_is_true = cur_solution(flipvar); bool flip_is_true = cur_solution(flipvar);
int_vector& truep = m_vars[flipvar].m_watch[flip_is_true]; int_vector const& truep = m_vars[flipvar].m_watch[flip_is_true];
int_vector& falsep = m_vars[flipvar].m_watch[!flip_is_true]; int_vector const& falsep = m_vars[flipvar].m_watch[!flip_is_true];
for (unsigned i = 0; i < truep.size(); ++i) { int_vector::const_iterator it = truep.begin(), end = truep.end();
unsigned ci = truep[i]; for (; it != end; ++it) {
unsigned ci = *it;
constraint& c = m_constraints[ci]; constraint& c = m_constraints[ci];
--c.m_slack; --c.m_slack;
if (c.m_slack == -1) { // from 0 to -1: sat -> unsat if (c.m_slack == -1) { // from 0 to -1: sat -> unsat
unsat(ci); unsat(ci);
} }
} }
for (unsigned i = 0; i < falsep.size(); ++i) { it = falsep.begin(), end = falsep.end();
unsigned ci = falsep[i]; for (; it != end; ++it) {
unsigned ci = *it;
constraint& c = m_constraints[ci]; constraint& c = m_constraints[ci];
++c.m_slack; ++c.m_slack;
if (c.m_slack == 0) { // from -1 to 0: unsat -> sat if (c.m_slack == 0) { // from -1 to 0: unsat -> sat
@ -647,12 +669,12 @@ namespace sat {
/* update CCD */ /* update CCD */
// remove the vars no longer goodvar in goodvar stack // remove the vars no longer goodvar in goodvar stack
for (unsigned i = goodvar_stack.size(); i > 0;) { for (unsigned i = m_goodvar_stack.size(); i > 0;) {
--i; --i;
v = goodvar_stack[i]; v = m_goodvar_stack[i];
if (score(v) <= 0) { if (score(v) <= 0) {
goodvar_stack[i] = goodvar_stack.back(); m_goodvar_stack[i] = m_goodvar_stack.back();
goodvar_stack.pop_back(); m_goodvar_stack.pop_back();
m_vars[v].m_in_goodvar_stack = false; m_vars[v].m_in_goodvar_stack = false;
} }
} }
@ -664,7 +686,7 @@ namespace sat {
v = vi.m_neighbors[i]; v = vi.m_neighbors[i];
m_vars[v].m_conf_change = true; m_vars[v].m_conf_change = true;
if (score(v) > 0 && !already_in_goodvar_stack(v)) { if (score(v) > 0 && !already_in_goodvar_stack(v)) {
goodvar_stack.push_back(v); m_goodvar_stack.push_back(v);
m_vars[v].m_in_goodvar_stack = true; m_vars[v].m_in_goodvar_stack = true;
} }
} }
@ -717,11 +739,11 @@ namespace sat {
// Unsat Mode: CCD > RD // Unsat Mode: CCD > RD
// CCD mode // CCD mode
if (!goodvar_stack.empty()) { if (!m_goodvar_stack.empty()) {
//++ccd; //++ccd;
best_var = goodvar_stack[0]; best_var = m_goodvar_stack[0];
for (unsigned i = 1; i < goodvar_stack.size(); ++i) { for (unsigned i = 1; i < m_goodvar_stack.size(); ++i) {
bool_var v = goodvar_stack[i]; bool_var v = m_goodvar_stack[i];
if (tie_breaker_ccd(v, best_var)) if (tie_breaker_ccd(v, best_var))
best_var = v; best_var = v;
} }
@ -742,24 +764,26 @@ namespace sat {
} }
void local_search::set_parameters() { void local_search::set_parameters() {
SASSERT(s_id == 0);
m_rand.set_seed(m_config.seed()); m_rand.set_seed(m_config.seed());
//srand(m_config.seed()); //srand(m_config.seed());
s_id = m_config.strategy_id(); s_id = m_config.strategy_id();
best_known_value = m_config.best_known_value(); m_best_known_value = m_config.best_known_value();
if (s_id == 0) switch (m_config.mode()) {
max_steps = 2 * (num_vars() - 1); case local_search_mode::gsat:
else { m_max_steps = 2 * num_vars();
std::cout << "Invalid strategy id!" << std::endl; break;
exit(-1); case local_search_mode::wsat:
m_max_steps = std::min(static_cast<unsigned>(20 * num_vars()), static_cast<unsigned>(1 << 17)); // cut steps off at 100K
break;
} }
TRACE("sat", TRACE("sat",
tout << "seed:\t" << m_config.seed() << '\n'; tout << "seed:\t" << m_config.seed() << '\n';
tout << "strategy id:\t" << m_config.strategy_id() << '\n'; tout << "strategy id:\t" << m_config.strategy_id() << '\n';
tout << "best_known_value:\t" << m_config.best_known_value() << '\n'; tout << "best_known_value:\t" << m_config.best_known_value() << '\n';
tout << "max_steps:\t" << max_steps << '\n'; tout << "max_steps:\t" << m_max_steps << '\n';
); );
} }
@ -808,10 +832,10 @@ namespace sat {
std::cout << "3\n"; std::cout << "3\n";
} }
} }
if (g == goodvar_stack.size()) if (g == m_goodvar_stack.size())
return true; return true;
else { else {
if (g < goodvar_stack.size()) if (g < m_goodvar_stack.size())
std::cout << "1\n"; std::cout << "1\n";
else else
std::cout << "2\n"; // delete too many std::cout << "2\n"; // delete too many

View file

@ -134,6 +134,10 @@ namespace sat {
vector<constraint> m_constraints; vector<constraint> m_constraints;
literal_vector m_assumptions;
unsigned m_num_non_binary_clauses;
inline bool is_pos(literal t) const { return !t.sign(); } inline bool is_pos(literal t) const { return !t.sign(); }
inline bool is_true(bool_var v) const { return cur_solution(v); } inline bool is_true(bool_var v) const { return cur_solution(v); }
inline bool is_true(literal l) const { return cur_solution(l.var()) != l.sign(); } inline bool is_true(literal l) const { return cur_solution(l.var()) != l.sign(); }
@ -143,26 +147,23 @@ namespace sat {
unsigned constraint_slack(unsigned ci) const { return m_constraints[ci].m_slack; } unsigned constraint_slack(unsigned ci) const { return m_constraints[ci].m_slack; }
// int_vector nb_slack; // constraint_k - ob_var(same in ob) - none_ob_true_terms_count. if < 0: some ob var might be flipped to false, result in an ob decreasing
// bool_vector has_true_ob_terms;
// unsat constraint stack // unsat constraint stack
int_vector m_unsat_stack; // store all the unsat constraits unsigned_vector m_unsat_stack; // store all the unsat constraits
int_vector m_index_in_unsat_stack; // which position is a contraint in the unsat_stack unsigned_vector m_index_in_unsat_stack; // which position is a contraint in the unsat_stack
// configuration changed decreasing variables (score>0 and conf_change==true) // configuration changed decreasing variables (score>0 and conf_change==true)
int_vector goodvar_stack; bool_var_vector m_goodvar_stack;
svector<bool_var> m_good_vars; // candidate variables to flip on.
// information about solution // information about solution
int objective_value; // the objective function value corresponds to the current solution int m_objective_value; // the objective function value corresponds to the current solution
bool_vector best_solution; // !var: the best solution so far bool_vector m_best_solution; // !var: the best solution so far
int best_objective_value = -1; // the objective value corresponds to the best solution so far int m_best_objective_value = -1; // the objective value corresponds to the best solution so far
// for non-known instance, set as maximal // for non-known instance, set as maximal
int best_known_value = INT_MAX; // best known value for this instance int m_best_known_value = INT_MAX; // best known value for this instance
unsigned max_steps = 2000000000; // < 2147483647 unsigned m_max_steps = (1 << 30);
// for tuning // for tuning
int s_id = 0; // strategy id int s_id = 0; // strategy id
@ -228,9 +229,10 @@ namespace sat {
void display(std::ostream& out, unsigned v, var_info const& vi) const; void display(std::ostream& out, unsigned v, var_info const& vi) const;
public: public:
local_search(solver& s); local_search();
reslimit& rlimit() { return m_limit; } reslimit& rlimit() { return m_limit; }
@ -248,6 +250,10 @@ namespace sat {
unsigned num_vars() const { return m_vars.size() - 1; } // var index from 1 to num_vars unsigned num_vars() const { return m_vars.size() - 1; } // var index from 1 to num_vars
unsigned num_non_binary_clauses() const { return m_num_non_binary_clauses; }
void import(solver& s, bool init);
void set_phase(bool_var v, lbool f); void set_phase(bool_var v, lbool f);
bool get_phase(bool_var v) const { return is_true(v); } bool get_phase(bool_var v) const { return is_true(v); }

View file

@ -77,8 +77,6 @@ namespace sat {
literal_vector m_trail; // trail of units literal_vector m_trail; // trail of units
unsigned_vector m_trail_lim; unsigned_vector m_trail_lim;
literal_vector m_units; // units learned during lookahead
unsigned_vector m_units_lim;
vector<literal_vector> m_binary; // literal: binary clauses vector<literal_vector> m_binary; // literal: binary clauses
unsigned_vector m_binary_trail; // trail of added binary clauses unsigned_vector m_binary_trail; // trail of added binary clauses
unsigned_vector m_binary_trail_lim; unsigned_vector m_binary_trail_lim;
@ -96,7 +94,9 @@ namespace sat {
svector<float> m_rating; // var: pre-selection rating svector<float> m_rating; // var: pre-selection rating
unsigned m_bstamp_id; // unique id for binary implication. unsigned m_bstamp_id; // unique id for binary implication.
unsigned m_istamp_id; // unique id for managing double lookaheads unsigned m_istamp_id; // unique id for managing double lookaheads
char_vector m_assignment; // literal: assignment unsigned_vector m_stamp; // var: timestamp with truth value
unsigned m_level; // current level, = 2 * m_trail_lim.size()
const unsigned c_fixed_truth = UINT_MAX - 1;
vector<watch_list> m_watches; // literal: watch structure vector<watch_list> m_watches; // literal: watch structure
svector<lit_info> m_lits; // literal: attributes. svector<lit_info> m_lits; // literal: attributes.
float m_weighted_new_binaries; // metric associated with current lookahead1 literal. float m_weighted_new_binaries; // metric associated with current lookahead1 literal.
@ -106,6 +106,33 @@ namespace sat {
search_mode m_search_mode; // mode of search search_mode m_search_mode; // mode of search
statistics m_stats; statistics m_stats;
// ---------------------------------------
// truth values
inline bool is_fixed(literal l) const { return m_stamp[l.var()] >= m_level; }
inline bool is_undef(literal l) const { return !is_fixed(l); }
inline bool is_undef(bool_var v) const { return m_stamp[v] < m_level; }
inline bool is_false(literal l) const { return is_fixed(l) && (bool)((m_stamp[l.var()] & 0x1) ^ l.sign()); } // even iff l.sign()
inline bool is_true(literal l) const { return is_fixed(l) && !(bool)((m_stamp[l.var()] & 0x1) ^ l.sign()); }
inline void set_true(literal l) { m_stamp[l.var()] = m_level + l.sign(); }
inline void set_undef(literal l) { m_stamp[l.var()] = 0; }
// set the level within a scope of the search.
class scoped_level {
lookahead& m_parent;
unsigned m_save;
public:
scoped_level(lookahead& p, unsigned l):
m_parent(p), m_save(p.m_level) {
p.m_level = l;
}
~scoped_level() {
m_parent.m_level = m_save;
}
};
// ----------------------------------------
void add_binary(literal l1, literal l2) { void add_binary(literal l1, literal l2) {
SASSERT(l1 != l2); SASSERT(l1 != l2);
SASSERT(~l1 != l2); SASSERT(~l1 != l2);
@ -182,6 +209,7 @@ namespace sat {
\brief main routine for adding a new binary clause dynamically. \brief main routine for adding a new binary clause dynamically.
*/ */
void try_add_binary(literal u, literal v) { void try_add_binary(literal u, literal v) {
SASSERT(m_search_mode == searching);
SASSERT(u.var() != v.var()); SASSERT(u.var() != v.var());
set_bstamps(~u); set_bstamps(~u);
if (is_stamped(~v)) { if (is_stamped(~v)) {
@ -292,7 +320,7 @@ namespace sat {
m_candidates.reset(); m_candidates.reset();
float sum = 0; float sum = 0;
for (bool_var const* it = m_freevars.begin(), * end = m_freevars.end(); it != end; ++it) { for (bool_var const* it = m_freevars.begin(), * end = m_freevars.end(); it != end; ++it) {
SASSERT(l_undef == value(*it)); SASSERT(is_undef(*it));
bool_var x = *it; bool_var x = *it;
if (!newbies) { if (!newbies) {
// TBD filter out candidates based on prefix strings or similar method // TBD filter out candidates based on prefix strings or similar method
@ -376,20 +404,13 @@ namespace sat {
float sum = 0, tsum = 0; float sum = 0, tsum = 0;
literal_vector::iterator it = m_binary[l.index()].begin(), end = m_binary[l.index()].end(); literal_vector::iterator it = m_binary[l.index()].begin(), end = m_binary[l.index()].end();
for (; it != end; ++it) { for (; it != end; ++it) {
if (is_free(*it)) sum += h[it->index()]; if (is_undef(*it)) sum += h[it->index()];
} }
// TBD walk ternary clauses. // TBD walk ternary clauses.
sum = (float)(0.1 + afactor*sum + sqfactor*tsum); sum = (float)(0.1 + afactor*sum + sqfactor*tsum);
return std::min(m_config.m_max_score, sum); return std::min(m_config.m_max_score, sum);
} }
bool is_free(literal l) const {
return !is_unit(l);
}
bool is_unit(literal l) const {
return false; // TBD track variables that are units
}
// ------------------------------------ // ------------------------------------
// Implication graph // Implication graph
// Compute implication ordering and strongly connected components. // Compute implication ordering and strongly connected components.
@ -638,7 +659,7 @@ namespace sat {
} }
SASSERT(2*m_lookahead.size() == offset); SASSERT(2*m_lookahead.size() == offset);
TRACE("sat", for (unsigned i = 0; i < m_lookahead.size(); ++i) TRACE("sat", for (unsigned i = 0; i < m_lookahead.size(); ++i)
tout << m_lookahead[i].m_lit << " : " << m_lookahead[i].m_offset << "\n";); tout << m_lookahead[i].m_lit << " : " << m_lookahead[i].m_offset << "\n";);
} }
// ------------------------------------ // ------------------------------------
@ -655,8 +676,8 @@ namespace sat {
clause_offset cls_off = m_cls_allocator.get_offset(&c); clause_offset cls_off = m_cls_allocator.get_offset(&c);
m_watches[(~c[0]).index()].push_back(watched(block_lit, cls_off)); m_watches[(~c[0]).index()].push_back(watched(block_lit, cls_off));
m_watches[(~c[1]).index()].push_back(watched(block_lit, cls_off)); m_watches[(~c[1]).index()].push_back(watched(block_lit, cls_off));
SASSERT(value(c[0]) == l_undef); SASSERT(is_undef(c[0]));
SASSERT(value(c[1]) == l_undef); SASSERT(is_undef(c[1]));
} }
} }
@ -668,6 +689,9 @@ namespace sat {
} }
void detach_ternary(literal l1, literal l2, literal l3) { 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_retired_ternary.push_back(ternary(l1, l2, l3)); m_retired_ternary.push_back(ternary(l1, l2, l3));
erase_ternary_watch(get_wlist(~l1), l2, l3); erase_ternary_watch(get_wlist(~l1), l2, l3);
erase_ternary_watch(get_wlist(~l2), l1, l3); erase_ternary_watch(get_wlist(~l2), l1, l3);
@ -680,8 +704,6 @@ namespace sat {
// initialization // initialization
void init_var(bool_var v) { void init_var(bool_var v) {
m_assignment.push_back(l_undef);
m_assignment.push_back(l_undef);
m_binary.push_back(literal_vector()); m_binary.push_back(literal_vector());
m_binary.push_back(literal_vector()); m_binary.push_back(literal_vector());
m_watches.push_back(watch_list()); m_watches.push_back(watch_list());
@ -738,7 +760,6 @@ namespace sat {
unsigned trail_sz = s.init_trail_size(); unsigned trail_sz = s.init_trail_size();
for (unsigned i = 0; i < trail_sz; ++i) { for (unsigned i = 0; i < trail_sz; ++i) {
literal l = s.m_trail[i]; literal l = s.m_trail[i];
m_units.push_back(l);
assign(l); assign(l);
} }
} }
@ -746,15 +767,15 @@ namespace sat {
// ------------------------------------ // ------------------------------------
// search // search
void push(literal lit, search_mode mode) { void push(literal lit, unsigned level) {
m_binary_trail_lim.push_back(m_binary_trail.size()); m_binary_trail_lim.push_back(m_binary_trail.size());
m_units_lim.push_back(m_units.size());
m_trail_lim.push_back(m_trail.size()); m_trail_lim.push_back(m_trail.size());
m_retired_clause_lim.push_back(m_retired_clauses.size()); m_retired_clause_lim.push_back(m_retired_clauses.size());
m_qhead_lim.push_back(m_qhead); m_qhead_lim.push_back(m_qhead);
m_trail.push_back(lit); m_trail.push_back(lit);
m_search_modes.push_back(m_search_mode); m_search_modes.push_back(m_search_mode);
m_search_mode = mode; m_search_mode = searching;
scoped_level _sl(*this, level);
assign(lit); assign(lit);
propagate(); propagate();
} }
@ -766,6 +787,7 @@ namespace sat {
m_search_mode = m_search_modes.back(); m_search_mode = m_search_modes.back();
m_search_modes.pop_back(); m_search_modes.pop_back();
// not for lookahead
// unretire clauses // unretire clauses
unsigned rsz = m_retired_clause_lim.back(); unsigned rsz = m_retired_clause_lim.back();
for (unsigned i = rsz; i < m_retired_clauses.size(); ++i) { for (unsigned i = rsz; i < m_retired_clauses.size(); ++i) {
@ -774,6 +796,7 @@ namespace sat {
m_retired_clauses.resize(rsz); m_retired_clauses.resize(rsz);
m_retired_clause_lim.pop_back(); m_retired_clause_lim.pop_back();
// m_search_mode == searching
// remove local binary clauses // remove local binary clauses
unsigned old_sz = m_binary_trail_lim.back(); unsigned old_sz = m_binary_trail_lim.back();
m_binary_trail_lim.pop_back(); m_binary_trail_lim.pop_back();
@ -781,30 +804,31 @@ namespace sat {
del_binary(m_binary_trail[i]); del_binary(m_binary_trail[i]);
} }
// not for lookahead.
// m_freevars only for main search
// undo assignments // undo assignments
for (unsigned i = m_trail.size(); i > m_trail_lim.size(); ) { for (unsigned i = m_trail.size(); i > m_trail_lim.size(); ) {
--i; --i;
literal l = m_trail[i]; literal l = m_trail[i];
set_undef(l);
m_freevars.insert(l.var()); m_freevars.insert(l.var());
m_assignment[l.index()] = l_undef;
m_assignment[(~l).index()] = l_undef;
} }
m_trail.shrink(m_trail_lim.size()); // reset assignment. m_trail.shrink(m_trail_lim.size()); // reset assignment.
m_trail_lim.pop_back(); m_trail_lim.pop_back();
// add implied binary clauses
unsigned new_unit_sz = m_units_lim.back();
for (unsigned i = new_unit_sz; i < m_units.size(); ++i) {
try_add_binary(~m_trail.back(), m_units[i]);
}
m_units.shrink(new_unit_sz);
m_units_lim.pop_back();
// reset propagation queue // reset propagation queue
m_qhead_lim.pop_back(); m_qhead_lim.pop_back();
m_qhead = m_qhead_lim.back(); m_qhead = m_qhead_lim.back();
} }
void push_lookahead2(literal lit) {
}
void pop_lookahead2() {
}
float mix_diff(float l, float r) const { return l + r + (1 << 10) * l * r; } float mix_diff(float l, float r) const { return l + r + (1 << 10) * l * r; }
clause const& get_clause(watch_list::iterator it) const { clause const& get_clause(watch_list::iterator it) const {
@ -813,14 +837,13 @@ namespace sat {
} }
bool is_nary_propagation(clause const& c, literal l) const { bool is_nary_propagation(clause const& c, literal l) const {
bool r = c.size() > 2 && ((c[0] == l && value(c[1]) == l_false) || (c[1] == l && value(c[0]) == l_false)); bool r = c.size() > 2 && ((c[0] == l && is_false(c[1])) || (c[1] == l && is_false(c[0])));
DEBUG_CODE(if (r) for (unsigned j = 2; j < c.size(); ++j) SASSERT(value(c[j]) == l_false);); DEBUG_CODE(if (r) for (unsigned j = 2; j < c.size(); ++j) SASSERT(is_false(c[j])););
return r; return r;
} }
void propagate_clauses(literal l) { void propagate_clauses(literal l) {
SASSERT(value(l) == l_true); SASSERT(is_true(l));
SASSERT(value(~l) == l_false);
if (inconsistent()) return; if (inconsistent()) return;
watch_list& wlist = m_watches[l.index()]; watch_list& wlist = m_watches[l.index()];
watch_list::iterator it = wlist.begin(), it2 = it, end = wlist.end(); watch_list::iterator it = wlist.begin(), it2 = it, end = wlist.end();
@ -833,20 +856,24 @@ namespace sat {
UNREACHABLE(); // we avoid adding ternary clauses for now. UNREACHABLE(); // we avoid adding ternary clauses for now.
literal l1 = it->get_literal1(); literal l1 = it->get_literal1();
literal l2 = it->get_literal2(); literal l2 = it->get_literal2();
lbool val1 = value(l1); if (is_fixed(l1)) {
lbool val2 = value(l2); if (is_false(l1)) {
if (val1 == l_false && val2 == l_undef) { if (is_undef(l2)) {
m_stats.m_propagations++; m_stats.m_propagations++;
assign(l2); assign(l2);
}
else if (is_false(l2)) {
set_conflict();
}
}
} }
else if (val1 == l_undef && val2 == l_false) { else if (is_fixed(l2)) {
m_stats.m_propagations++; if (is_false(l2)) {
assign(l1); m_stats.m_propagations++;
assign(l1);
}
} }
else if (val1 == l_false && val2 == l_false) { else {
set_conflict();
}
else if (val1 == l_undef && val2 == l_undef) {
switch (m_search_mode) { switch (m_search_mode) {
case searching: case searching:
detach_ternary(l, l1, l2); detach_ternary(l, l1, l2);
@ -866,10 +893,10 @@ namespace sat {
case watched::CLAUSE: { case watched::CLAUSE: {
clause_offset cls_off = it->get_clause_offset(); clause_offset cls_off = it->get_clause_offset();
clause & c = *(s.m_cls_allocator.get_clause(cls_off)); clause & c = *(s.m_cls_allocator.get_clause(cls_off));
TRACE("propagate_clause_bug", tout << "processing... " << c << "\nwas_removed: " << c.was_removed() << "\n";); TRACE("sat", tout << "propagating " << c << "\n";);
if (c[0] == ~l) if (c[0] == ~l)
std::swap(c[0], c[1]); std::swap(c[0], c[1]);
if (value(c[0]) == l_true) { if (is_true(c[0])) {
it2->set_clause(c[0], cls_off); it2->set_clause(c[0], cls_off);
it2++; it2++;
break; break;
@ -878,7 +905,7 @@ namespace sat {
literal * l_end = c.end(); literal * l_end = c.end();
bool found = false; bool found = false;
for (; l_it != l_end && !found; ++l_it) { for (; l_it != l_end && !found; ++l_it) {
if (value(*l_it) != l_false) { if (!is_false(*l_it)) {
found = true; found = true;
c[1] = *l_it; c[1] = *l_it;
*l_it = ~l; *l_it = ~l;
@ -888,10 +915,10 @@ namespace sat {
if (found) { if (found) {
found = false; found = false;
for (; l_it != l_end && !found; ++l_it) { for (; l_it != l_end && !found; ++l_it) {
found = value(*l_it) != l_false; found = !is_false(*l_it);
} }
// normal clause was converted to a binary clause. // normal clause was converted to a binary clause.
if (!found && value(c[1]) == l_undef && value(c[0]) == l_undef) { if (!found && is_undef(c[1]) && is_undef(c[0])) {
switch (m_search_mode) { switch (m_search_mode) {
case searching: case searching:
detach_clause(c); detach_clause(c);
@ -906,11 +933,11 @@ namespace sat {
} }
break; break;
} }
if (value(c[0]) == l_false) { if (is_false(c[0])) {
set_conflict(); set_conflict();
} }
else { else {
SASSERT(value(c[0]) == l_undef); SASSERT(is_undef(c[0]));
*it2 = *it; *it2 = *it;
it2++; it2++;
m_stats.m_propagations++; m_stats.m_propagations++;
@ -929,14 +956,7 @@ namespace sat {
for (; it != end; ++it, ++it2) { for (; it != end; ++it, ++it2) {
*it2 = *it; *it2 = *it;
} }
wlist.set_end(it2); wlist.set_end(it2);
//
// TBD: count binary clauses created by propagation.
// They used to be in the watch list of l.index(),
// both new literals in watch list should be unassigned.
//
} }
void propagate_binary(literal l) { void propagate_binary(literal l) {
@ -958,78 +978,100 @@ namespace sat {
} }
literal choose() { literal choose() {
literal l; literal l = null_literal;
while (!choose1(l)) {}; while (l == null_literal) {
pre_select();
if (m_lookahead.empty()) {
break;
}
compute_wnb();
if (inconsistent()) {
break;
}
l = select_literal();
}
return l; return l;
} }
// TBD: void compute_wnb() {
// Handle scope properly for nested implications. init_wnb();
// Suppose u -> v, and u -> w and we process v first, then the
// consequences of v should remain when processing u.
// March and sat11.w solve this by introducing timestamps on truth values.
// regular push/pop doesn't really work here: we basically need a traversal of the
// lookahead tree and push/pop according to that (or adapt timestamps)
//
bool choose1(literal& l) {
pre_select();
l = null_literal;
if (m_lookahead.empty()) {
return true;
}
float h = 0;
unsigned count = 1;
for (unsigned i = 0; !inconsistent() && i < m_lookahead.size(); ++i) { for (unsigned i = 0; !inconsistent() && i < m_lookahead.size(); ++i) {
literal lit = m_lookahead[i].m_lit; literal lit = m_lookahead[i].m_lit;
if (value(lit) != l_undef) { if (!is_undef(lit)) {
continue; continue;
} }
SASSERT(value(lit) == l_undef);
SASSERT(!inconsistent());
reset_wnb(lit); reset_wnb(lit);
push(lit, lookahead1); push_lookahead1(lit, 2 + m_lookahead[i].m_offset);
do_double(lit); bool unsat = inconsistent();
if (inconsistent()) { // TBD do_double(lit);
pop(); pop_lookahead1();
update_wnb(lit);
if (unsat) {
reset_wnb();
assign(~lit); assign(~lit);
propagate(); propagate();
continue; init_wnb();
} }
update_wnb(lit); }
float diff1 = m_weighted_new_binaries; reset_wnb();
pop(); }
reset_wnb(~lit);
push(~lit, lookahead1);
do_double(~lit);
if (inconsistent()) {
pop();
assign(lit);
propagate();
continue;
}
update_wnb(~lit);
float diff2 = m_weighted_new_binaries;
pop();
void init_wnb() {
m_qhead_lim.push_back(m_qhead);
m_trail_lim.push_back(m_trail.size());
}
void reset_wnb() {
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_trail.shrink(old_sz);
m_trail_lim.pop_back();
m_qhead_lim.pop_back();
}
literal select_literal() {
literal l = null_literal;
float h = 0;
unsigned count = 1;
for (unsigned i = 0; i < m_lookahead.size(); ++i) {
literal lit = m_lookahead[i].m_lit;
if (lit.sign() || !is_undef(lit)) {
continue;
}
float diff1 = get_wnb(lit), diff2 = get_wnb(~lit);
float mixd = mix_diff(diff1, diff2); float mixd = mix_diff(diff1, diff2);
if (mixd == h) ++count;
if (mixd > h || (mixd == h && s.m_rand(count) == 0)) { if (mixd > h || (mixd == h && s.m_rand(count) == 0)) {
CTRACE("sat", l != null_literal, tout << lit << " diff1: " << diff1 << " diff2: " << diff2 << "\n";); CTRACE("sat", l != null_literal, tout << lit << " " << mixd << "\n";);
if (mixd > h) count = 1; else ++count; if (mixd > h) count = 1;
h = mixd; h = mixd;
l = diff1 < diff2 ? lit : ~lit; l = diff1 < diff2 ? lit : ~lit;
} }
} }
return l != null_literal || inconsistent(); 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() {
SASSERT(!inconsistent());
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 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; } void inc_wnb(literal l, float f) { m_lits[l.index()].m_wnb += f; }
float get_wnb(literal l) const { return m_lits[l.index()].m_wnb; } float get_wnb(literal l) const { return m_lits[l.index()].m_wnb; }
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 reset_wnb(literal l) { void reset_wnb(literal l) {
m_weighted_new_binaries = 0; m_weighted_new_binaries = 0;
@ -1048,24 +1090,27 @@ 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() { void double_look() {
bool unsat; bool unsat;
for (unsigned i = 0; !inconsistent() && i < m_lookahead.size(); ++i) { for (unsigned i = 0; !inconsistent() && i < m_lookahead.size(); ++i) {
literal lit = m_lookahead[i].m_lit; literal lit = m_lookahead[i].m_lit;
if (value(lit) != l_undef) continue; if (!is_undef(lit)) continue;
push(lit, lookahead2); push_lookahead2(lit);
unsat = inconsistent(); unsat = inconsistent();
pop(); pop_lookahead2();
if (unsat) { if (unsat) {
TRACE("sat", tout << "unit: " << ~lit << "\n";); TRACE("sat", tout << "unit: " << ~lit << "\n";);
assign(~lit); assign(~lit);
continue; continue;
} }
push(~lit, lookahead2); push_lookahead2(~lit);
unsat = inconsistent(); unsat = inconsistent();
pop(); pop_lookahead2();
if (unsat) { if (unsat) {
TRACE("sat", tout << "unit: " << lit << "\n";); TRACE("sat", tout << "unit: " << lit << "\n";);
assign(lit); assign(lit);
@ -1073,31 +1118,25 @@ namespace sat {
} }
} }
bool is_fixed(literal l) const { return value(l) != l_undef; }
bool is_contrary(literal l) const { return value(l) == l_false; }
bool is_true(literal l) const { return value(l) == l_true; }
void set_conflict() { m_inconsistent = true; } void set_conflict() { m_inconsistent = true; }
lbool value(literal l) const { return static_cast<lbool>(m_assignment[l.index()]); } bool inconsistent() { return m_inconsistent; }
lbool value(bool_var v) const { return value(literal(v, false)); }
unsigned scope_lvl() const { return m_trail_lim.size(); } unsigned scope_lvl() const { return m_trail_lim.size(); }
void assign(literal l) { void assign(literal l) {
switch (value(l)) { if (is_undef(l)) {
case l_true: set_true(l);
break;
case l_false:
set_conflict();
break;
default:
m_assignment[l.index()] = l.sign() ? l_false : l_true;
m_assignment[(~l).index()] = l.sign() ? l_false : l_true;
m_trail.push_back(l); m_trail.push_back(l);
m_freevars.remove(l.var()); if (m_search_mode == searching) {
break; m_freevars.remove(l.var());
}
}
else if (is_false(l)) {
set_conflict();
} }
} }
bool inconsistent() { return m_inconsistent; }
void do_double(literal l) { void do_double(literal l) {
if (!inconsistent() && scope_lvl() > 0 && dl_enabled(l)) { if (!inconsistent() && scope_lvl() > 0 && dl_enabled(l)) {
@ -1115,7 +1154,8 @@ namespace sat {
bool backtrack(literal_vector& trail) { bool backtrack(literal_vector& trail) {
if (trail.empty()) return false; if (trail.empty()) return false;
pop(); pop();
assign(~trail.back()); assign(~trail.back());
propagate();
trail.pop_back(); trail.pop_back();
return true; return true;
} }
@ -1124,6 +1164,7 @@ namespace sat {
literal_vector trail; literal_vector trail;
m_search_mode = searching; m_search_mode = searching;
while (true) { while (true) {
TRACE("sat", display(tout););
inc_istamp(); inc_istamp();
s.checkpoint(); s.checkpoint();
literal l = choose(); literal l = choose();
@ -1135,19 +1176,55 @@ namespace sat {
return l_true; return l_true;
} }
TRACE("sat", tout << "choose: " << l << " " << trail << "\n";); TRACE("sat", tout << "choose: " << l << " " << trail << "\n";);
push(l, searching); push(l, c_fixed_truth);
trail.push_back(l); trail.push_back(l);
} }
} }
std::ostream& display_binary(std::ostream& out) const {
for (unsigned i = 0; i < m_binary.size(); ++i) {
literal_vector const& lits = m_binary[i];
if (!lits.empty()) {
out << to_literal(i) << " -> " << lits << "\n";
}
}
return out;
}
std::ostream& display_clauses(std::ostream& out) const {
for (unsigned i = 0; i < m_clauses.size(); ++i) {
out << *m_clauses[i] << "\n";
}
return out;
}
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";
}
return out;
}
public: public:
lookahead(solver& s) : s(s) { lookahead(solver& s) :
s(s),
m_level(0) {
scoped_level _sl(*this, c_fixed_truth);
init(); init();
} }
lbool check() { lbool check() {
return search(); return search();
} }
std::ostream& display(std::ostream& out) const {
display_values(out);
display_binary(out);
display_clauses(out);
return out;
}
}; };
} }

View file

@ -139,9 +139,6 @@ namespace sat {
} }
} }
limit = m_units.size(); limit = m_units.size();
_get_phase(s);
_set_phase(s);
} }
} }
@ -228,6 +225,12 @@ namespace sat {
break; break;
} }
} }
if (90 * m_num_clauses > 100 * s.m_clauses.size() && !m_solver_copy) {
// time to update local search with new clauses.
IF_VERBOSE(1, verbose_stream() << "(sat-parallel refresh local search " << m_num_clauses << " -> " << s.m_clauses.size() << ")\n";);
m_solver_copy = alloc(solver, s.m_params, s.rlimit());
m_solver_copy->copy(s);
}
} }
} }
@ -261,10 +264,16 @@ namespace sat {
void parallel::get_phase(local_search& s) { void parallel::get_phase(local_search& s) {
#pragma omp critical (par_solver) #pragma omp critical (par_solver)
{ {
if (m_solver_copy) {
s.import(*m_solver_copy.get(), true);
m_solver_copy = 0;
}
for (unsigned i = 0; i < m_phase.size(); ++i) { for (unsigned i = 0; i < m_phase.size(); ++i) {
s.set_phase(i, m_phase[i]); s.set_phase(i, m_phase[i]);
m_phase[i] = l_undef;
} }
m_phase.reserve(s.num_vars(), l_undef); m_phase.reserve(s.num_vars(), l_undef);
m_num_clauses = s.num_non_binary_clauses();
} }
} }
@ -275,6 +284,7 @@ namespace sat {
for (unsigned i = 0; i < s.num_vars(); ++i) { for (unsigned i = 0; i < s.num_vars(); ++i) {
m_phase[i] = s.get_phase(i) ? l_true : l_false; m_phase[i] = s.get_phase(i) ? l_true : l_false;
} }
m_num_clauses = s.num_non_binary_clauses();
} }
} }

View file

@ -60,7 +60,11 @@ namespace sat {
index_set m_unit_set; index_set m_unit_set;
literal_vector m_lits; literal_vector m_lits;
vector_pool m_pool; vector_pool m_pool;
svector<lbool> m_phase;
// for exchange with local search:
svector<lbool> m_phase;
unsigned m_num_clauses;
scoped_ptr<solver> m_solver_copy;
scoped_limits m_scoped_rlimit; scoped_limits m_scoped_rlimit;
vector<reslimit> m_limits; vector<reslimit> m_limits;

View file

@ -82,15 +82,15 @@ namespace sat {
void solver::copy(solver const & src) { void solver::copy(solver const & src) {
pop_to_base_level(); pop_to_base_level();
SASSERT(m_mc.empty() && src.m_mc.empty());
SASSERT(at_search_lvl());
// create new vars // create new vars
if (num_vars() < src.num_vars()) { if (num_vars() < src.num_vars()) {
for (bool_var v = num_vars(); v < src.num_vars(); v++) { for (bool_var v = num_vars(); v < src.num_vars(); v++) {
SASSERT(!src.was_eliminated(v));
bool ext = src.m_external[v] != 0; bool ext = src.m_external[v] != 0;
bool dvar = src.m_decision[v] != 0; bool dvar = src.m_decision[v] != 0;
VERIFY(v == mk_var(ext, dvar)); VERIFY(v == mk_var(ext, dvar));
if (src.was_eliminated(v)) {
m_eliminated[v] = true;
}
} }
} }
// //
@ -854,19 +854,14 @@ namespace sat {
ERROR_EX ERROR_EX
}; };
local_search& solver::init_local_search() {
if (!m_local_search) {
m_local_search = alloc(local_search, *this);
}
return *m_local_search.get();
}
lbool solver::check_par(unsigned num_lits, literal const* lits) { lbool solver::check_par(unsigned num_lits, literal const* lits) {
bool use_local_search = m_config.m_local_search; bool use_local_search = m_config.m_local_search;
scoped_ptr<local_search> ls;
if (use_local_search) { if (use_local_search) {
m_local_search = alloc(local_search, *this); ls = alloc(local_search);
m_local_search->config().set_seed(m_config.m_random_seed); ls->config().set_seed(m_config.m_random_seed);
ls->import(*this, false);
} }
int num_threads = static_cast<int>(m_config.m_num_threads) + (use_local_search ? 1 : 0); int num_threads = static_cast<int>(m_config.m_num_threads) + (use_local_search ? 1 : 0);
int num_extra_solvers = num_threads - 1 - (use_local_search ? 1 : 0); int num_extra_solvers = num_threads - 1 - (use_local_search ? 1 : 0);
@ -890,7 +885,7 @@ namespace sat {
r = par.get_solver(i).check(num_lits, lits); r = par.get_solver(i).check(num_lits, lits);
} }
else if (IS_LOCAL_SEARCH(i)) { else if (IS_LOCAL_SEARCH(i)) {
r = m_local_search->check(num_lits, lits, &par); r = ls->check(num_lits, lits, &par);
} }
else { else {
r = check(num_lits, lits); r = check(num_lits, lits);
@ -905,8 +900,8 @@ namespace sat {
} }
} }
if (first) { if (first) {
if (m_local_search) { if (ls) {
m_local_search->rlimit().cancel(); ls->rlimit().cancel();
} }
for (int j = 0; j < num_extra_solvers; ++j) { for (int j = 0; j < num_extra_solvers; ++j) {
if (i != j) { if (i != j) {
@ -942,13 +937,13 @@ namespace sat {
m_core.append(par.get_solver(finished_id).get_core()); m_core.append(par.get_solver(finished_id).get_core());
} }
if (result == l_true && finished_id != -1 && IS_LOCAL_SEARCH(finished_id)) { if (result == l_true && finished_id != -1 && IS_LOCAL_SEARCH(finished_id)) {
set_model(m_local_search->get_model()); set_model(ls->get_model());
} }
if (!canceled) { if (!canceled) {
rlimit().reset_cancel(); rlimit().reset_cancel();
} }
set_par(0, 0); set_par(0, 0);
m_local_search = 0; ls = 0;
if (finished_id == -1) { if (finished_id == -1) {
switch (ex_kind) { switch (ex_kind) {
case ERROR_EX: throw z3_error(error_code); case ERROR_EX: throw z3_error(error_code);

View file

@ -90,7 +90,6 @@ namespace sat {
probing m_probing; probing m_probing;
mus m_mus; // MUS for minimal core extraction mus m_mus; // MUS for minimal core extraction
drat m_drat; // DRAT for generating proofs drat m_drat; // DRAT for generating proofs
scoped_ptr<local_search> m_local_search;
bool m_inconsistent; bool m_inconsistent;
bool m_searching; bool m_searching;
// A conflict is usually a single justification. That is, a justification // A conflict is usually a single justification. That is, a justification