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:
parent
a7db118ebc
commit
fda5809c89
|
@ -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
|
||||||
|
|
|
@ -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); }
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue