mirror of
https://github.com/Z3Prover/z3
synced 2025-04-08 10:25:18 +00:00
walk/gsat
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
parent
1e32f1fbb5
commit
d819784500
|
@ -34,7 +34,7 @@ project(Z3 C CXX)
|
|||
set(Z3_VERSION_MAJOR 4)
|
||||
set(Z3_VERSION_MINOR 5)
|
||||
set(Z3_VERSION_PATCH 1)
|
||||
set(Z3_VERSION_TWEAK 0)
|
||||
set(Z3_VERSION_TWEAK 0303)
|
||||
set(Z3_FULL_VERSION 0)
|
||||
set(Z3_VERSION "${Z3_VERSION_MAJOR}.${Z3_VERSION_MINOR}.${Z3_VERSION_PATCH}.${Z3_VERSION_TWEAK}")
|
||||
message(STATUS "Z3 version ${Z3_VERSION}")
|
||||
|
|
|
@ -187,6 +187,13 @@ namespace sat {
|
|||
}
|
||||
}
|
||||
|
||||
void local_search::verify_unsat_stack() const {
|
||||
for (unsigned i = 0; i < m_unsat_stack.size(); ++i) {
|
||||
constraint const& c = m_constraints[m_unsat_stack[i]];
|
||||
SASSERT(c.m_k < constraint_value(c));
|
||||
}
|
||||
}
|
||||
|
||||
unsigned local_search::constraint_value(constraint const& c) const {
|
||||
unsigned value = 0;
|
||||
for (unsigned i = 0; i < c.size(); ++i) {
|
||||
|
@ -226,7 +233,6 @@ namespace sat {
|
|||
local_search::local_search(solver& s) :
|
||||
m_par(0) {
|
||||
|
||||
std::cout << "Parameter1: " << s.m_config.m_local_search_parameter1 << "\n";
|
||||
m_vars.reserve(s.num_vars());
|
||||
|
||||
// copy units
|
||||
|
@ -322,15 +328,28 @@ namespace sat {
|
|||
lbool local_search::check() {
|
||||
return check(0, 0);
|
||||
}
|
||||
|
||||
lbool local_search::check(unsigned sz, literal const* assumptions, parallel* p) {
|
||||
flet<parallel*> _p(m_par, p);
|
||||
m_model.reset();
|
||||
unsigned num_constraints = m_constraints.size();
|
||||
for (unsigned i = 0; i < sz; ++i) {
|
||||
add_clause(1, assumptions + i);
|
||||
|
||||
void local_search::walksat() {
|
||||
reinit();
|
||||
timer timer;
|
||||
timer.start();
|
||||
unsigned step = 0, total_steps = 0, max_steps = (1 << 20);
|
||||
for (unsigned tries = 1; !m_unsat_stack.empty() && m_limit.inc(); ++tries) {
|
||||
for (step = 0; step < max_steps && !m_unsat_stack.empty(); ++step) {
|
||||
pick_flip_walksat();
|
||||
}
|
||||
total_steps += step;
|
||||
if (tries % 10 == 0) {
|
||||
IF_VERBOSE(1, verbose_stream() << "(sat-local-search"
|
||||
<< " :tries " << tries
|
||||
<< " :steps " << total_steps
|
||||
<< " :unsat " << m_unsat_stack.size()
|
||||
<< " :time " << timer.get_seconds() << ")\n";);
|
||||
}
|
||||
}
|
||||
init();
|
||||
}
|
||||
|
||||
void local_search::gsat() {
|
||||
reinit();
|
||||
bool reach_known_best_value = false;
|
||||
bool_var flipvar;
|
||||
|
@ -347,8 +366,8 @@ namespace sat {
|
|||
break;
|
||||
}
|
||||
}
|
||||
flipvar = pick_var();
|
||||
flip(flipvar);
|
||||
flipvar = pick_var_gsat();
|
||||
flip_gsat(flipvar);
|
||||
m_vars[flipvar].m_time_stamp = step;
|
||||
}
|
||||
IF_VERBOSE(1, if (tries % 10 == 0)
|
||||
|
@ -363,6 +382,26 @@ namespace sat {
|
|||
m_par->get_phase(*this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lbool local_search::check(unsigned sz, literal const* assumptions, parallel* p) {
|
||||
flet<parallel*> _p(m_par, p);
|
||||
m_model.reset();
|
||||
unsigned num_constraints = m_constraints.size();
|
||||
for (unsigned i = 0; i < sz; ++i) {
|
||||
add_clause(1, assumptions + i);
|
||||
}
|
||||
init();
|
||||
|
||||
switch (m_config.mode()) {
|
||||
case local_search_mode::gsat:
|
||||
gsat();
|
||||
break;
|
||||
case local_search_mode::wsat:
|
||||
walksat();
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
// remove unit clauses from assumptions.
|
||||
m_constraints.shrink(num_constraints);
|
||||
|
@ -398,7 +437,111 @@ namespace sat {
|
|||
m_unsat_stack.push_back(c);
|
||||
}
|
||||
|
||||
void local_search::flip(bool_var flipvar)
|
||||
void local_search::pick_flip_walksat() {
|
||||
m_good_vars.reset();
|
||||
bool_var v;
|
||||
constraint const& c = m_constraints[m_unsat_stack[m_rand() % m_unsat_stack.size()]];
|
||||
SASSERT(c.m_k < constraint_value(c));
|
||||
if (m_rand() % 100 < 5) {
|
||||
// display(std::cout, c);
|
||||
unsigned best_bsb = 0;
|
||||
// find the first one, to fast break the rest
|
||||
unsigned i = 0;
|
||||
while (true) {
|
||||
v = c[i].var();
|
||||
if (is_true(c[i])) {
|
||||
bool tt = cur_solution(v);
|
||||
int_vector const& falsep = m_vars[v].m_watch[!tt];
|
||||
for (unsigned j = 0; j < falsep.size(); ++j) {
|
||||
unsigned ci = falsep[j];
|
||||
if (constraint_slack(ci) < 0)
|
||||
++best_bsb;
|
||||
else if (constraint_slack(ci) == 0)
|
||||
// >= unsat_stack_fill_pointer is enough
|
||||
best_bsb += m_constraints.size();
|
||||
}
|
||||
break;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
m_good_vars.push_back(v);
|
||||
for (++i; i < c.size(); ++i) {
|
||||
v = c[i].var();
|
||||
if (is_true(c[i])) {
|
||||
bool found = false;
|
||||
unsigned bsb = 0;
|
||||
bool tt = cur_solution(v);
|
||||
int_vector const& falsep = m_vars[v].m_watch[!tt];
|
||||
for (unsigned j = 0; j < falsep.size() && !found; ++j) {
|
||||
unsigned ci = falsep[j];
|
||||
if (constraint_slack(ci) < 0) {
|
||||
if (bsb == best_bsb) {
|
||||
found = true;
|
||||
}
|
||||
else {
|
||||
++bsb;
|
||||
}
|
||||
}
|
||||
else if (constraint_slack(ci) == 0) {
|
||||
// >= unsat_stack_fill_pointer is enough
|
||||
bsb += m_constraints.size();
|
||||
if (bsb > best_bsb) {
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
if (bsb < best_bsb) {
|
||||
best_bsb = bsb;
|
||||
m_good_vars.reset();
|
||||
m_good_vars.push_back(v);
|
||||
}
|
||||
else {// if (bb == best_bb)
|
||||
m_good_vars.push_back(v);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (unsigned i = 0; i < c.size(); ++i) {
|
||||
if (is_true(c[i]))
|
||||
m_good_vars.push_back(c[i].var());
|
||||
}
|
||||
}
|
||||
SASSERT(!m_good_vars.empty());
|
||||
//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) {
|
||||
m_vars[flipvar].m_value = !cur_solution(flipvar);
|
||||
|
||||
bool flip_is_true = cur_solution(flipvar);
|
||||
int_vector& truep = m_vars[flipvar].m_watch[flip_is_true];
|
||||
int_vector& falsep = m_vars[flipvar].m_watch[!flip_is_true];
|
||||
|
||||
for (unsigned i = 0; i < truep.size(); ++i) {
|
||||
unsigned ci = truep[i];
|
||||
constraint& c = m_constraints[ci];
|
||||
--c.m_slack;
|
||||
if (c.m_slack == -1) { // from 0 to -1: sat -> unsat
|
||||
unsat(ci);
|
||||
}
|
||||
}
|
||||
for (unsigned i = 0; i < falsep.size(); ++i) {
|
||||
unsigned ci = falsep[i];
|
||||
constraint& c = m_constraints[ci];
|
||||
++c.m_slack;
|
||||
if (c.m_slack == 0) { // from -1 to 0: unsat -> sat
|
||||
sat(ci);
|
||||
}
|
||||
}
|
||||
|
||||
// verify_unsat_stack();
|
||||
}
|
||||
|
||||
void local_search::flip_gsat(bool_var flipvar)
|
||||
{
|
||||
// already changed truth value!!!!
|
||||
m_vars[flipvar].m_value = !cur_solution(flipvar);
|
||||
|
@ -558,7 +701,7 @@ namespace sat {
|
|||
(time_stamp(v) < time_stamp(best_var))))))));
|
||||
}
|
||||
|
||||
bool_var local_search::pick_var() {
|
||||
bool_var local_search::pick_var_gsat() {
|
||||
bool_var best_var = m_vars.size()-1; // sentinel variable
|
||||
// SAT Mode
|
||||
if (m_unsat_stack.empty()) {
|
||||
|
@ -613,7 +756,6 @@ namespace sat {
|
|||
|
||||
TRACE("sat",
|
||||
tout << "seed:\t" << m_config.seed() << '\n';
|
||||
tout << "cutoff time:\t" << m_config.cutoff_time() << '\n';
|
||||
tout << "strategy id:\t" << m_config.strategy_id() << '\n';
|
||||
tout << "best_known_value:\t" << m_config.best_known_value() << '\n';
|
||||
tout << "max_steps:\t" << max_steps << '\n';
|
||||
|
@ -622,7 +764,12 @@ namespace sat {
|
|||
|
||||
void local_search::print_info(std::ostream& out) {
|
||||
for (unsigned v = 0; v < num_vars(); ++v) {
|
||||
out << "v" << v << "\t" << m_vars[v].m_neighbors.size() << '\t' << cur_solution(v) << '\t' << conf_change(v) << '\t' << score(v) << '\t' << slack_score(v) << '\n';
|
||||
out << "v" << v << "\t"
|
||||
<< m_vars[v].m_neighbors.size() << '\t'
|
||||
<< cur_solution(v) << '\t'
|
||||
<< conf_change(v) << '\t'
|
||||
<< score(v) << '\t'
|
||||
<< slack_score(v) << '\n';
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -27,25 +27,33 @@ namespace sat {
|
|||
|
||||
class parallel;
|
||||
|
||||
enum local_search_mode {
|
||||
gsat,
|
||||
wsat
|
||||
};
|
||||
|
||||
class local_search_config {
|
||||
unsigned m_seed;
|
||||
unsigned m_strategy_id;
|
||||
int m_best_known_value;
|
||||
local_search_mode m_mode;
|
||||
public:
|
||||
local_search_config()
|
||||
{
|
||||
local_search_config() {
|
||||
m_seed = 0;
|
||||
m_strategy_id = 0;
|
||||
m_best_known_value = INT_MAX;
|
||||
m_mode = local_search_mode::wsat;
|
||||
}
|
||||
|
||||
unsigned seed() const { return m_seed; }
|
||||
unsigned strategy_id() const { return m_strategy_id; }
|
||||
unsigned best_known_value() const { return m_best_known_value; }
|
||||
local_search_mode mode() const { return m_mode; }
|
||||
|
||||
void set_seed(unsigned s) { m_seed = s; }
|
||||
void set_strategy_id(unsigned i) { m_strategy_id = i; }
|
||||
void set_best_known_value(unsigned v) { m_best_known_value = v; }
|
||||
void set_mode(local_search_mode m) { m_mode = m; }
|
||||
};
|
||||
|
||||
|
||||
|
@ -131,7 +139,8 @@ namespace sat {
|
|||
|
||||
unsigned num_constraints() const { return m_constraints.size(); } // constraint index from 1 to num_constraint
|
||||
|
||||
|
||||
|
||||
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;
|
||||
|
||||
|
@ -142,6 +151,8 @@ namespace sat {
|
|||
// configuration changed decreasing variables (score>0 and conf_change==true)
|
||||
int_vector goodvar_stack;
|
||||
|
||||
svector<bool_var> m_good_vars; // candidate variables to flip on.
|
||||
|
||||
// information about solution
|
||||
int objective_value; // the objective function value corresponds to the current solution
|
||||
bool_vector best_solution; // !var: the best solution so far
|
||||
|
@ -167,9 +178,17 @@ namespace sat {
|
|||
void init_scores();
|
||||
void init_goodvars();
|
||||
|
||||
bool_var pick_var();
|
||||
bool_var pick_var_gsat();
|
||||
|
||||
void flip(bool_var v);
|
||||
void flip_gsat(bool_var v);
|
||||
|
||||
void pick_flip_walksat();
|
||||
|
||||
void flip_walksat(bool_var v);
|
||||
|
||||
void walksat();
|
||||
|
||||
void gsat();
|
||||
|
||||
void unsat(unsigned c);
|
||||
|
||||
|
@ -187,6 +206,8 @@ namespace sat {
|
|||
|
||||
void verify_solution() const;
|
||||
|
||||
void verify_unsat_stack() const;
|
||||
|
||||
void verify_constraint(constraint const& c) const;
|
||||
|
||||
unsigned constraint_value(constraint const& c) const;
|
||||
|
|
Loading…
Reference in a new issue