3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-06-02 12:21:21 +00:00
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2018-10-30 17:23:31 -05:00
commit 719bc5cd5d
11 changed files with 87 additions and 26 deletions

View file

@ -1557,6 +1557,16 @@ std::ostream& ast_manager::display(std::ostream& out, parameter const& p) {
} }
std::ostream& ast_manager::display(std::ostream& out, parameter const& p) {
switch (p.get_kind()) {
case parameter::PARAM_AST:
return out << mk_pp(p.get_ast(), *this);
default:
return p.display(out);
}
return out;
}
void ast_manager::copy_families_plugins(ast_manager const & from) { void ast_manager::copy_families_plugins(ast_manager const & from) {
TRACE("copy_families_plugins", TRACE("copy_families_plugins",
tout << "target:\n"; tout << "target:\n";

View file

@ -2586,6 +2586,16 @@ public:
void operator()(AST * n) { m_manager.inc_ref(n); } void operator()(AST * n) { m_manager.inc_ref(n); }
}; };
struct parameter_pp {
parameter const& p;
ast_manager& m;
parameter_pp(parameter const& p, ast_manager& m): p(p), m(m) {}
};
inline std::ostream& operator<<(std::ostream& out, parameter_pp const& pp) {
return pp.m.display(out, pp.p);
}
#endif /* AST_H_ */ #endif /* AST_H_ */

View file

@ -859,10 +859,6 @@ br_status seq_rewriter::mk_seq_replace(expr* a, expr* b, expr* c, expr_ref& resu
result = m_util.str.mk_concat(c, a); result = m_util.str.mk_concat(c, a);
return BR_REWRITE1; return BR_REWRITE1;
} }
if (m_util.str.is_string(a, s1) && s1.length() == 0) {
result = a;
return BR_DONE;
}
return BR_FAILED; return BR_FAILED;
} }

View file

@ -86,6 +86,7 @@ namespace sat {
m_local_search_mode = local_search_mode::gsat; m_local_search_mode = local_search_mode::gsat;
else else
m_local_search_mode = local_search_mode::wsat; m_local_search_mode = local_search_mode::wsat;
m_local_search_dbg_flips = p.local_search_dbg_flips();
m_unit_walk = p.unit_walk(); m_unit_walk = p.unit_walk();
m_unit_walk_threads = p.unit_walk_threads(); m_unit_walk_threads = p.unit_walk_threads();
m_lookahead_simplify = p.lookahead_simplify(); m_lookahead_simplify = p.lookahead_simplify();

View file

@ -115,6 +115,7 @@ namespace sat {
unsigned m_local_search_threads; unsigned m_local_search_threads;
bool m_local_search; bool m_local_search;
local_search_mode m_local_search_mode; local_search_mode m_local_search_mode;
bool m_local_search_dbg_flips;
unsigned m_unit_walk_threads; unsigned m_unit_walk_threads;
bool m_unit_walk; bool m_unit_walk;
bool m_lookahead_simplify; bool m_lookahead_simplify;

View file

@ -553,6 +553,7 @@ namespace sat {
PROGRESS(tries, total_flips); 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) {
++m_stats.m_num_restarts;
for (step = 0; step < m_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();
if (m_unsat_stack.size() < m_best_unsat) { if (m_unsat_stack.size() < m_best_unsat) {
@ -622,7 +623,6 @@ namespace sat {
break; break;
} }
// remove unit clauses from assumptions. // remove unit clauses from assumptions.
m_constraints.shrink(num_constraints() - sz); m_constraints.shrink(num_constraints() - sz);
@ -779,8 +779,11 @@ namespace sat {
} }
void local_search::flip_walksat(bool_var flipvar) { void local_search::flip_walksat(bool_var flipvar) {
++m_stats.m_num_flips;
VERIFY(!is_unit(flipvar)); VERIFY(!is_unit(flipvar));
m_vars[flipvar].m_value = !cur_solution(flipvar); m_vars[flipvar].m_value = !cur_solution(flipvar);
m_vars[flipvar].m_flips++;
m_vars[flipvar].m_slow_break.update(abs(m_vars[flipvar].m_slack_score));
bool flip_is_true = cur_solution(flipvar); bool flip_is_true = cur_solution(flipvar);
coeff_vector const& truep = m_vars[flipvar].m_watch[flip_is_true]; coeff_vector const& truep = m_vars[flipvar].m_watch[flip_is_true];
@ -1062,6 +1065,19 @@ namespace sat {
return out << "v" << v << " := " << (vi.m_value?"true":"false") << " bias: " << vi.m_bias << "\n"; return out << "v" << v << " := " << (vi.m_value?"true":"false") << " bias: " << vi.m_bias << "\n";
} }
void local_search::collect_statistics(statistics& st) const {
if (m_config.dbg_flips()) {
unsigned i = 0;
for (var_info const& vi : m_vars) {
IF_VERBOSE(0, verbose_stream() << "flips: " << i << " " << vi.m_flips << " " << vi.m_slow_break << "\n");
++i;
}
}
st.update("local-search-flips", m_stats.m_num_flips);
st.update("local-search-restarts", m_stats.m_num_restarts);
}
bool local_search::check_goodvar() { bool local_search::check_goodvar() {
unsigned g = 0; unsigned g = 0;
for (unsigned v = 0; v < num_vars(); ++v) { for (unsigned v = 0; v < num_vars(); ++v) {

View file

@ -23,6 +23,8 @@
#include "sat/sat_types.h" #include "sat/sat_types.h"
#include "sat/sat_config.h" #include "sat/sat_config.h"
#include "util/rlimit.h" #include "util/rlimit.h"
#include "util/ema.h"
#include "util/statistics.h"
namespace sat { namespace sat {
@ -33,18 +35,21 @@ namespace sat {
int m_best_known_value; int m_best_known_value;
local_search_mode m_mode; local_search_mode m_mode;
bool m_phase_sticky; bool m_phase_sticky;
bool m_dbg_flips;
public: public:
local_search_config() { local_search_config() {
m_random_seed = 0; m_random_seed = 0;
m_best_known_value = INT_MAX; m_best_known_value = INT_MAX;
m_mode = local_search_mode::wsat; m_mode = local_search_mode::wsat;
m_phase_sticky = false; m_phase_sticky = false;
m_dbg_flips = false;
} }
unsigned random_seed() const { return m_random_seed; } unsigned random_seed() const { return m_random_seed; }
unsigned best_known_value() const { return m_best_known_value; } unsigned best_known_value() const { return m_best_known_value; }
local_search_mode mode() const { return m_mode; } local_search_mode mode() const { return m_mode; }
bool phase_sticky() const { return m_phase_sticky; } bool phase_sticky() const { return m_phase_sticky; }
bool dbg_flips() const { return m_dbg_flips; }
void set_random_seed(unsigned s) { m_random_seed = s; } void set_random_seed(unsigned s) { m_random_seed = s; }
void set_best_known_value(unsigned v) { m_best_known_value = v; } void set_best_known_value(unsigned v) { m_best_known_value = v; }
@ -53,6 +58,7 @@ namespace sat {
m_mode = cfg.m_local_search_mode; m_mode = cfg.m_local_search_mode;
m_random_seed = cfg.m_random_seed; m_random_seed = cfg.m_random_seed;
m_phase_sticky = cfg.m_phase_sticky; m_phase_sticky = cfg.m_phase_sticky;
m_dbg_flips = cfg.m_local_search_dbg_flips;
} }
}; };
@ -74,6 +80,13 @@ namespace sat {
int coefficient; // non-zero integer int coefficient; // non-zero integer
ob_term(bool_var v, int c): var_id(v), coefficient(c) {} ob_term(bool_var v, int c): var_id(v), coefficient(c) {}
}; };
struct stats {
unsigned m_num_flips;
unsigned m_num_restarts;
void reset() { memset(this, 0, sizeof(*this)); }
stats() { reset(); }
};
struct var_info { struct var_info {
bool m_value; // current solution bool m_value; // current solution
@ -89,6 +102,8 @@ namespace sat {
bool_var_vector m_neighbors; // neighborhood variables bool_var_vector m_neighbors; // neighborhood variables
coeff_vector m_watch[2]; coeff_vector m_watch[2];
literal_vector m_bin[2]; literal_vector m_bin[2];
unsigned m_flips;
ema m_slow_break;
var_info(): var_info():
m_value(true), m_value(true),
m_bias(50), m_bias(50),
@ -97,7 +112,9 @@ namespace sat {
m_in_goodvar_stack(false), m_in_goodvar_stack(false),
m_score(0), m_score(0),
m_slack_score(0), m_slack_score(0),
m_cscc(0) m_cscc(0),
m_flips(0),
m_slow_break(1e-5)
{} {}
}; };
@ -115,6 +132,8 @@ namespace sat {
literal const* end() const { return m_literals.end(); } literal const* end() const { return m_literals.end(); }
}; };
stats m_stats;
local_search_config m_config; local_search_config m_config;
// objective function: maximize // objective function: maximize
@ -145,7 +164,6 @@ namespace sat {
inline void set_best_unsat(); inline void set_best_unsat();
/* TBD: other scores */ /* TBD: other scores */
vector<constraint> m_constraints; vector<constraint> m_constraints;
@ -293,6 +311,8 @@ namespace sat {
model& get_model() { return m_model; } model& get_model() { return m_model; }
void collect_statistics(statistics& st) const;
}; };
} }

View file

@ -50,6 +50,7 @@ def_module_params('sat',
('local_search', BOOL, False, 'use local search instead of CDCL'), ('local_search', BOOL, False, 'use local search instead of CDCL'),
('local_search_threads', UINT, 0, 'number of local search threads to find satisfiable solution'), ('local_search_threads', UINT, 0, 'number of local search threads to find satisfiable solution'),
('local_search_mode', SYMBOL, 'wsat', 'local search algorithm, either default wsat or qsat'), ('local_search_mode', SYMBOL, 'wsat', 'local search algorithm, either default wsat or qsat'),
('local_search_dbg_flips', BOOL, False, 'write debug information for number of flips'),
('unit_walk', BOOL, False, 'use unit-walk search instead of CDCL'), ('unit_walk', BOOL, False, 'use unit-walk search instead of CDCL'),
('unit_walk_threads', UINT, 0, 'number of unit-walk search threads to find satisfiable solution'), ('unit_walk_threads', UINT, 0, 'number of unit-walk search threads to find satisfiable solution'),
('lookahead.cube.cutoff', SYMBOL, 'depth', 'cutoff type used to create lookahead cubes: depth, freevars, psat, adaptive_freevars, adaptive_psat'), ('lookahead.cube.cutoff', SYMBOL, 'depth', 'cutoff type used to create lookahead cubes: depth, freevars, psat, adaptive_freevars, adaptive_psat'),

View file

@ -68,6 +68,7 @@ namespace sat {
m_simplifications = 0; m_simplifications = 0;
m_ext = nullptr; m_ext = nullptr;
m_cuber = nullptr; m_cuber = nullptr;
m_local_search = nullptr;
m_mc.set_solver(this); m_mc.set_solver(this);
} }
@ -758,9 +759,9 @@ namespace sat {
m_not_l = not_l; m_not_l = not_l;
} }
void solver::assign_core(literal l, justification j) { void solver::assign_core(literal l, unsigned lvl, justification j) {
SASSERT(value(l) == l_undef); SASSERT(value(l) == l_undef);
TRACE("sat_assign_core", tout << l << " " << j << " level: " << scope_lvl() << "\n";); TRACE("sat_assign_core", tout << l << " " << j << " level: " << lvl << "\n";);
if (at_base_lvl()) { if (at_base_lvl()) {
if (m_config.m_drat) m_drat.add(l, !j.is_none()); if (m_config.m_drat) m_drat.add(l, !j.is_none());
j = justification(); // erase justification for level 0 j = justification(); // erase justification for level 0
@ -768,7 +769,7 @@ namespace sat {
m_assignment[l.index()] = l_true; m_assignment[l.index()] = l_true;
m_assignment[(~l).index()] = l_false; m_assignment[(~l).index()] = l_false;
bool_var v = l.var(); bool_var v = l.var();
m_level[v] = scope_lvl(); m_level[v] = lvl;
m_justification[v] = j; m_justification[v] = j;
m_phase[v] = static_cast<phase>(l.sign()); m_phase[v] = static_cast<phase>(l.sign());
m_assigned_since_gc[v] = true; m_assigned_since_gc[v] = true;
@ -876,7 +877,7 @@ namespace sat {
return false; return false;
case l_undef: case l_undef:
m_stats.m_bin_propagate++; m_stats.m_bin_propagate++;
assign_core(l1, justification(not_l)); assign_core(l1, scope_lvl(), justification(not_l));
break; break;
case l_true: case l_true:
break; // skip break; // skip
@ -891,11 +892,11 @@ namespace sat {
val2 = value(l2); val2 = value(l2);
if (val1 == l_false && val2 == l_undef) { if (val1 == l_false && val2 == l_undef) {
m_stats.m_ter_propagate++; m_stats.m_ter_propagate++;
assign_core(l2, justification(l1, not_l)); assign_core(l2, scope_lvl(), justification(l1, not_l));
} }
else if (val1 == l_undef && val2 == l_false) { else if (val1 == l_undef && val2 == l_false) {
m_stats.m_ter_propagate++; m_stats.m_ter_propagate++;
assign_core(l1, justification(l2, not_l)); assign_core(l1, scope_lvl(), justification(l2, not_l));
} }
else if (val1 == l_false && val2 == l_false) { else if (val1 == l_false && val2 == l_false) {
CONFLICT_CLEANUP(); CONFLICT_CLEANUP();
@ -958,7 +959,7 @@ namespace sat {
it2++; it2++;
m_stats.m_propagate++; m_stats.m_propagate++;
c.mark_used(); c.mark_used();
assign_core(c[0], justification(cls_off)); assign_core(c[0], scope_lvl(), justification(cls_off));
#ifdef UPDATE_GLUE #ifdef UPDATE_GLUE
if (update && c.is_learned() && c.glue() > 2) { if (update && c.is_learned() && c.glue() > 2) {
unsigned glue; unsigned glue;
@ -1036,7 +1037,7 @@ namespace sat {
literal l(v, false); literal l(v, false);
if (mdl[v] != l_true) l.neg(); if (mdl[v] != l_true) l.neg();
push(); push();
assign_core(l, justification()); assign_core(l, scope_lvl(), justification());
} }
mk_model(); mk_model();
break; break;
@ -1154,13 +1155,16 @@ namespace sat {
lbool solver::do_local_search(unsigned num_lits, literal const* lits) { lbool solver::do_local_search(unsigned num_lits, literal const* lits) {
scoped_limits scoped_rl(rlimit()); scoped_limits scoped_rl(rlimit());
local_search srch; SASSERT(!m_local_search);
m_local_search = alloc(local_search);
local_search& srch = *m_local_search;
srch.config().set_config(m_config); srch.config().set_config(m_config);
srch.import(*this, false); srch.import(*this, false);
scoped_rl.push_child(&srch.rlimit()); scoped_rl.push_child(&srch.rlimit());
lbool r = srch.check(num_lits, lits, nullptr); lbool r = srch.check(num_lits, lits, nullptr);
m_model = srch.get_model(); m_model = srch.get_model();
// srch.collect_statistics(m_aux_stats); m_local_search = nullptr;
dealloc(&srch);
return r; return r;
} }
@ -3373,6 +3377,7 @@ namespace sat {
m_asymm_branch.collect_statistics(st); m_asymm_branch.collect_statistics(st);
m_probing.collect_statistics(st); m_probing.collect_statistics(st);
if (m_ext) m_ext->collect_statistics(st); if (m_ext) m_ext->collect_statistics(st);
if (m_local_search) m_local_search->collect_statistics(st);
st.copy(m_aux_stats); st.copy(m_aux_stats);
} }

View file

@ -163,6 +163,7 @@ namespace sat {
bool m_par_syncing_clauses; bool m_par_syncing_clauses;
class lookahead* m_cuber; class lookahead* m_cuber;
class local_search* m_local_search;
statistics m_aux_stats; statistics m_aux_stats;
@ -305,11 +306,11 @@ namespace sat {
TRACE("sat_assign", tout << l << " previous value: " << value(l) << "\n";); TRACE("sat_assign", tout << l << " previous value: " << value(l) << "\n";);
switch (value(l)) { switch (value(l)) {
case l_false: set_conflict(j, ~l); break; case l_false: set_conflict(j, ~l); break;
case l_undef: assign_core(l, j); break; case l_undef: assign_core(l, scope_lvl(), j); break;
case l_true: return; case l_true: return;
} }
} }
void assign_core(literal l, justification jst); void assign_core(literal l, unsigned lvl, justification jst);
void set_conflict(justification c, literal not_l); void set_conflict(justification c, literal not_l);
void set_conflict(justification c) { set_conflict(c, null_literal); } void set_conflict(justification c) { set_conflict(c, null_literal); }
lbool status(clause const & c) const; lbool status(clause const & c) const;

View file

@ -178,21 +178,21 @@ unsigned read_dimacs(char const * file_name) {
std::cerr << "(error \"failed to open file '" << file_name << "'\")" << std::endl; std::cerr << "(error \"failed to open file '" << file_name << "'\")" << std::endl;
exit(ERR_OPEN_FILE); exit(ERR_OPEN_FILE);
} }
parse_dimacs(in, solver); parse_dimacs(in, *g_solver);
} }
else { else {
parse_dimacs(std::cin, solver); parse_dimacs(std::cin, *g_solver);
} }
IF_VERBOSE(20, solver.display_status(verbose_stream());); IF_VERBOSE(20, g_solver->display_status(verbose_stream()););
lbool r; lbool r;
vector<sat::literal_vector> tracking_clauses; vector<sat::literal_vector> tracking_clauses;
sat::solver solver2(p, limit); sat::solver solver2( p, limit);
if (p.get_bool("dimacs.core", false)) { if (p.get_bool("dimacs.core", false)) {
g_solver = &solver2;
sat::literal_vector assumptions; sat::literal_vector assumptions;
track_clauses(solver, solver2, assumptions, tracking_clauses); track_clauses(solver, solver2, assumptions, tracking_clauses);
r = g_solver->check(assumptions.size(), assumptions.c_ptr()); g_solver = &solver2;
r = solver2.check(assumptions.size(), assumptions.c_ptr());
} }
else { else {
r = g_solver->check(); r = g_solver->check();