mirror of
https://github.com/Z3Prover/z3
synced 2025-06-22 05:43:39 +00:00
tune cardinality solver for cache misses
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
parent
4831c45ad8
commit
61ade5e6cb
12 changed files with 85 additions and 33 deletions
|
@ -119,20 +119,37 @@ namespace sat {
|
||||||
if (m_var_infos.size() <= static_cast<unsigned>(lit.var())) {
|
if (m_var_infos.size() <= static_cast<unsigned>(lit.var())) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ptr_vector<card>* cards = m_var_infos[lit.var()].m_lit_watch[lit.sign()];
|
ptr_vector<card>*& cards = m_var_infos[lit.var()].m_lit_watch[lit.sign()];
|
||||||
if (cards) {
|
if (cards) {
|
||||||
remove(*cards, c);
|
if (remove(*cards, c)) {
|
||||||
|
std::cout << "Empty: " << cards->empty() << "\n";
|
||||||
|
cards = set_tag_empty(cards);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void card_extension::remove(ptr_vector<card>& cards, card* c) {
|
ptr_vector<card_extension::card>* card_extension::set_tag_empty(ptr_vector<card>* c) {
|
||||||
for (unsigned j = 0; j < cards.size(); ++j) {
|
return TAG(ptr_vector<card>*, c, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool card_extension::is_tag_empty(ptr_vector<card>* c) {
|
||||||
|
return !c || GET_TAG(c) == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr_vector<card_extension::card>* card_extension::set_tag_non_empty(ptr_vector<card>* c) {
|
||||||
|
return UNTAG(ptr_vector<card>*, c);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool card_extension::remove(ptr_vector<card>& cards, card* c) {
|
||||||
|
unsigned sz = cards.size();
|
||||||
|
for (unsigned j = 0; j < sz; ++j) {
|
||||||
if (cards[j] == c) {
|
if (cards[j] == c) {
|
||||||
std::swap(cards[j], cards[cards.size()-1]);
|
std::swap(cards[j], cards[sz-1]);
|
||||||
cards.pop_back();
|
cards.pop_back();
|
||||||
break;
|
return sz == 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void card_extension::assign(card& c, literal lit) {
|
void card_extension::assign(card& c, literal lit) {
|
||||||
|
@ -171,6 +188,10 @@ namespace sat {
|
||||||
cards = alloc(ptr_vector<card>);
|
cards = alloc(ptr_vector<card>);
|
||||||
m_var_infos[lit.var()].m_lit_watch[lit.sign()] = cards;
|
m_var_infos[lit.var()].m_lit_watch[lit.sign()] = cards;
|
||||||
}
|
}
|
||||||
|
else if (is_tag_empty(cards)) {
|
||||||
|
cards = set_tag_non_empty(cards);
|
||||||
|
m_var_infos[lit.var()].m_lit_watch[lit.sign()] = cards;
|
||||||
|
}
|
||||||
TRACE("sat_verbose", tout << "insert: " << lit.var() << " " << lit.sign() << "\n";);
|
TRACE("sat_verbose", tout << "insert: " << lit.var() << " " << lit.sign() << "\n";);
|
||||||
cards->push_back(&c);
|
cards->push_back(&c);
|
||||||
}
|
}
|
||||||
|
@ -617,13 +638,16 @@ namespace sat {
|
||||||
|
|
||||||
void card_extension::asserted(literal l) {
|
void card_extension::asserted(literal l) {
|
||||||
bool_var v = l.var();
|
bool_var v = l.var();
|
||||||
|
if (s().inconsistent()) return;
|
||||||
if (v >= m_var_infos.size()) return;
|
if (v >= m_var_infos.size()) return;
|
||||||
var_info& vinfo = m_var_infos[v];
|
var_info& vinfo = m_var_infos[v];
|
||||||
ptr_vector<card>* cards = vinfo.m_lit_watch[!l.sign()];
|
ptr_vector<card>* cards = vinfo.m_lit_watch[!l.sign()];
|
||||||
//TRACE("sat", tout << "retrieve: " << v << " " << !l.sign() << "\n";);
|
//TRACE("sat", tout << "retrieve: " << v << " " << !l.sign() << "\n";);
|
||||||
//TRACE("sat", tout << "asserted: " << l << " " << (cards ? "non-empty" : "empty") << "\n";);
|
//TRACE("sat", tout << "asserted: " << l << " " << (cards ? "non-empty" : "empty") << "\n";);
|
||||||
if (cards != 0 && !cards->empty() && !s().inconsistent()) {
|
static unsigned is_empty = 0, non_empty = 0;
|
||||||
ptr_vector<card>::iterator it = cards->begin(), it2 = it, end = cards->end();
|
if (!is_tag_empty(cards)) {
|
||||||
|
ptr_vector<card>::iterator begin = cards->begin();
|
||||||
|
ptr_vector<card>::iterator it = begin, it2 = it, end = cards->end();
|
||||||
for (; it != end; ++it) {
|
for (; it != end; ++it) {
|
||||||
card& c = *(*it);
|
card& c = *(*it);
|
||||||
if (value(c.lit()) != l_true) {
|
if (value(c.lit()) != l_true) {
|
||||||
|
@ -648,6 +672,9 @@ namespace sat {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cards->set_end(it2);
|
cards->set_end(it2);
|
||||||
|
if (cards->empty()) {
|
||||||
|
m_var_infos[v].m_lit_watch[!l.sign()] = set_tag_empty(cards);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
card* crd = vinfo.m_card;
|
card* crd = vinfo.m_card;
|
||||||
|
|
|
@ -71,11 +71,14 @@ namespace sat {
|
||||||
}
|
}
|
||||||
void reset() {
|
void reset() {
|
||||||
dealloc(m_card);
|
dealloc(m_card);
|
||||||
dealloc(m_lit_watch[0]);
|
dealloc(card_extension::set_tag_non_empty(m_lit_watch[0]));
|
||||||
dealloc(m_lit_watch[1]);
|
dealloc(card_extension::set_tag_non_empty(m_lit_watch[1]));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
ptr_vector<card>* set_tag_empty(ptr_vector<card>* c);
|
||||||
|
bool is_tag_empty(ptr_vector<card>* c);
|
||||||
|
static ptr_vector<card>* set_tag_non_empty(ptr_vector<card>* c);
|
||||||
|
|
||||||
solver* m_solver;
|
solver* m_solver;
|
||||||
stats m_stats;
|
stats m_stats;
|
||||||
|
@ -113,7 +116,7 @@ namespace sat {
|
||||||
inline unsigned lvl(bool_var v) const { return m_solver->lvl(v); }
|
inline unsigned lvl(bool_var v) const { return m_solver->lvl(v); }
|
||||||
|
|
||||||
void unwatch_literal(literal w, card* c);
|
void unwatch_literal(literal w, card* c);
|
||||||
void remove(ptr_vector<card>& cards, card* c);
|
bool remove(ptr_vector<card>& cards, card* c);
|
||||||
|
|
||||||
void normalize_active_coeffs();
|
void normalize_active_coeffs();
|
||||||
void inc_coeff(literal l, int offset);
|
void inc_coeff(literal l, int offset);
|
||||||
|
|
|
@ -142,12 +142,17 @@ namespace sat {
|
||||||
c.shrink(new_sz);
|
c.shrink(new_sz);
|
||||||
*it2 = *it;
|
*it2 = *it;
|
||||||
it2++;
|
it2++;
|
||||||
if (!c.frozen()) {
|
if (!c.frozen()) {
|
||||||
if (new_sz == 3)
|
if (new_sz == 3)
|
||||||
s.attach_ter_clause(c);
|
s.attach_ter_clause(c);
|
||||||
else
|
else
|
||||||
s.attach_nary_clause(c);
|
s.attach_nary_clause(c);
|
||||||
}
|
}
|
||||||
|
if (s.m_config.m_drat) {
|
||||||
|
// for optimization, could also report deletion
|
||||||
|
// of previous version of clause.
|
||||||
|
s.m_drat.add(c, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -117,7 +117,7 @@ namespace sat {
|
||||||
if (i == 1 + num_threads/2) {
|
if (i == 1 + num_threads/2) {
|
||||||
s.m_params.set_sym("phase", symbol("random"));
|
s.m_params.set_sym("phase", symbol("random"));
|
||||||
}
|
}
|
||||||
m_solvers[i] = alloc(sat::solver, s.m_params, m_limits[i], 0);
|
m_solvers[i] = alloc(sat::solver, s.m_params, m_limits[i]);
|
||||||
m_solvers[i]->copy(s);
|
m_solvers[i]->copy(s);
|
||||||
m_solvers[i]->set_par(this, i);
|
m_solvers[i]->set_par(this, i);
|
||||||
m_scoped_rlimit.push_child(&m_solvers[i]->rlimit());
|
m_scoped_rlimit.push_child(&m_solvers[i]->rlimit());
|
||||||
|
|
|
@ -304,6 +304,9 @@ namespace sat {
|
||||||
s.attach_ter_clause(c);
|
s.attach_ter_clause(c);
|
||||||
else
|
else
|
||||||
s.attach_nary_clause(c);
|
s.attach_nary_clause(c);
|
||||||
|
if (s.m_config.m_drat) {
|
||||||
|
s.m_drat.add(c, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cs.set_end(it2);
|
cs.set_end(it2);
|
||||||
|
|
|
@ -31,10 +31,9 @@ Revision History:
|
||||||
|
|
||||||
namespace sat {
|
namespace sat {
|
||||||
|
|
||||||
solver::solver(params_ref const & p, reslimit& l, extension * ext):
|
solver::solver(params_ref const & p, reslimit& l):
|
||||||
m_rlimit(l),
|
m_rlimit(l),
|
||||||
m_config(p),
|
m_config(p),
|
||||||
m_ext(ext),
|
|
||||||
m_par(0),
|
m_par(0),
|
||||||
m_par_syncing_clauses(false),
|
m_par_syncing_clauses(false),
|
||||||
m_par_id(0),
|
m_par_id(0),
|
||||||
|
@ -59,7 +58,6 @@ namespace sat {
|
||||||
m_conflicts = 0;
|
m_conflicts = 0;
|
||||||
m_next_simplify = 0;
|
m_next_simplify = 0;
|
||||||
m_num_checkpoints = 0;
|
m_num_checkpoints = 0;
|
||||||
if (m_ext) m_ext->set_solver(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
solver::~solver() {
|
solver::~solver() {
|
||||||
|
@ -77,6 +75,11 @@ namespace sat {
|
||||||
++m_stats.m_non_learned_generation;
|
++m_stats.m_non_learned_generation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void solver::set_extension(extension* ext) {
|
||||||
|
m_ext = ext;
|
||||||
|
if (ext) ext->set_solver(this);
|
||||||
|
}
|
||||||
|
|
||||||
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(m_mc.empty() && src.m_mc.empty());
|
||||||
|
@ -771,7 +774,7 @@ namespace sat {
|
||||||
flet<bool> _searching(m_searching, true);
|
flet<bool> _searching(m_searching, true);
|
||||||
#ifdef CLONE_BEFORE_SOLVING
|
#ifdef CLONE_BEFORE_SOLVING
|
||||||
if (m_mc.empty()) {
|
if (m_mc.empty()) {
|
||||||
m_clone = alloc(solver, m_params, 0 /* do not clone extension */);
|
m_clone = alloc(solver, m_params);
|
||||||
SASSERT(m_clone);
|
SASSERT(m_clone);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -156,7 +156,7 @@ namespace sat {
|
||||||
friend class par;
|
friend class par;
|
||||||
friend struct mk_stat;
|
friend struct mk_stat;
|
||||||
public:
|
public:
|
||||||
solver(params_ref const & p, reslimit& l, extension * ext);
|
solver(params_ref const & p, reslimit& l);
|
||||||
~solver();
|
~solver();
|
||||||
|
|
||||||
// -----------------------
|
// -----------------------
|
||||||
|
@ -264,6 +264,7 @@ namespace sat {
|
||||||
bool canceled() { return !m_rlimit.inc(); }
|
bool canceled() { return !m_rlimit.inc(); }
|
||||||
config const& get_config() { return m_config; }
|
config const& get_config() { return m_config; }
|
||||||
extension* get_extension() const { return m_ext.get(); }
|
extension* get_extension() const { return m_ext.get(); }
|
||||||
|
void set_extension(extension* e);
|
||||||
typedef std::pair<literal, literal> bin_clause;
|
typedef std::pair<literal, literal> bin_clause;
|
||||||
protected:
|
protected:
|
||||||
watch_list & get_wlist(literal l) { return m_watches[l.index()]; }
|
watch_list & get_wlist(literal l) { return m_watches[l.index()]; }
|
||||||
|
|
|
@ -72,7 +72,7 @@ class inc_sat_solver : public solver {
|
||||||
public:
|
public:
|
||||||
inc_sat_solver(ast_manager& m, params_ref const& p):
|
inc_sat_solver(ast_manager& m, params_ref const& p):
|
||||||
m(m),
|
m(m),
|
||||||
m_solver(p, m.limit(), alloc(sat::card_extension)),
|
m_solver(p, m.limit()),
|
||||||
m_params(p), m_optimize_model(false),
|
m_params(p), m_optimize_model(false),
|
||||||
m_fmls(m),
|
m_fmls(m),
|
||||||
m_asmsf(m),
|
m_asmsf(m),
|
||||||
|
|
|
@ -78,11 +78,6 @@ struct goal2sat::imp {
|
||||||
m_default_external(default_external) {
|
m_default_external(default_external) {
|
||||||
updt_params(p);
|
updt_params(p);
|
||||||
m_true = sat::null_bool_var;
|
m_true = sat::null_bool_var;
|
||||||
sat::extension* e = m_solver.get_extension();
|
|
||||||
if (e) {
|
|
||||||
sat::card_extension* ce = dynamic_cast<sat::card_extension*>(e);
|
|
||||||
m_ext = ce;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void updt_params(params_ref const & p) {
|
void updt_params(params_ref const & p) {
|
||||||
|
@ -158,7 +153,8 @@ struct goal2sat::imp {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool convert_app(app* t, bool root, bool sign) {
|
bool convert_app(app* t, bool root, bool sign) {
|
||||||
if (m_ext && t->get_family_id() == pb.get_family_id()) {
|
if (t->get_family_id() == pb.get_family_id()) {
|
||||||
|
ensure_extension();
|
||||||
m_frame_stack.push_back(frame(to_app(t), root, sign, 0));
|
m_frame_stack.push_back(frame(to_app(t), root, sign, 0));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -465,6 +461,20 @@ struct goal2sat::imp {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ensure_extension() {
|
||||||
|
if (!m_ext) {
|
||||||
|
sat::extension* ext = m_solver.get_extension();
|
||||||
|
if (ext) {
|
||||||
|
m_ext = dynamic_cast<sat::card_extension*>(ext);
|
||||||
|
SASSERT(m_ext);
|
||||||
|
}
|
||||||
|
if (!m_ext) {
|
||||||
|
m_ext = alloc(sat::card_extension);
|
||||||
|
m_solver.set_extension(m_ext);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void convert(app * t, bool root, bool sign) {
|
void convert(app * t, bool root, bool sign) {
|
||||||
if (t->get_family_id() == m.get_basic_family_id()) {
|
if (t->get_family_id() == m.get_basic_family_id()) {
|
||||||
switch (to_app(t)->get_decl_kind()) {
|
switch (to_app(t)->get_decl_kind()) {
|
||||||
|
@ -485,7 +495,8 @@ struct goal2sat::imp {
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (m_ext && t->get_family_id() == pb.get_family_id()) {
|
else if (t->get_family_id() == pb.get_family_id()) {
|
||||||
|
ensure_extension();
|
||||||
switch (t->get_decl_kind()) {
|
switch (t->get_decl_kind()) {
|
||||||
case OP_AT_MOST_K:
|
case OP_AT_MOST_K:
|
||||||
convert_at_most_k(t, pb.get_k(t), root, sign);
|
convert_at_most_k(t, pb.get_k(t), root, sign);
|
||||||
|
|
|
@ -34,7 +34,7 @@ class sat_tactic : public tactic {
|
||||||
|
|
||||||
imp(ast_manager & _m, params_ref const & p):
|
imp(ast_manager & _m, params_ref const & p):
|
||||||
m(_m),
|
m(_m),
|
||||||
m_solver(p, m.limit(), 0),
|
m_solver(p, m.limit()),
|
||||||
m_params(p) {
|
m_params(p) {
|
||||||
SASSERT(!m.proofs_enabled());
|
SASSERT(!m.proofs_enabled());
|
||||||
}
|
}
|
||||||
|
|
|
@ -126,7 +126,6 @@ static void track_clauses(sat::solver const& src,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
unsigned read_dimacs(char const * file_name) {
|
unsigned read_dimacs(char const * file_name) {
|
||||||
g_start_time = clock();
|
g_start_time = clock();
|
||||||
register_on_timeout_proc(on_timeout);
|
register_on_timeout_proc(on_timeout);
|
||||||
|
@ -134,7 +133,7 @@ unsigned read_dimacs(char const * file_name) {
|
||||||
params_ref p = gparams::get_module("sat");
|
params_ref p = gparams::get_module("sat");
|
||||||
p.set_bool("produce_models", true);
|
p.set_bool("produce_models", true);
|
||||||
reslimit limit;
|
reslimit limit;
|
||||||
sat::solver solver(p, limit, 0);
|
sat::solver solver(p, limit);
|
||||||
g_solver = &solver;
|
g_solver = &solver;
|
||||||
|
|
||||||
if (file_name) {
|
if (file_name) {
|
||||||
|
@ -152,7 +151,7 @@ unsigned read_dimacs(char const * file_name) {
|
||||||
|
|
||||||
lbool r;
|
lbool r;
|
||||||
vector<sat::literal_vector> tracking_clauses;
|
vector<sat::literal_vector> tracking_clauses;
|
||||||
sat::solver solver2(p, limit, 0);
|
sat::solver solver2(p, limit);
|
||||||
if (p.get_bool("dimacs.core", false)) {
|
if (p.get_bool("dimacs.core", false)) {
|
||||||
g_solver = &solver2;
|
g_solver = &solver2;
|
||||||
sat::literal_vector assumptions;
|
sat::literal_vector assumptions;
|
||||||
|
|
|
@ -59,7 +59,7 @@ static void init_vars(sat::solver& s) {
|
||||||
static void check_coherence(sat::solver& s1, trail_t& t) {
|
static void check_coherence(sat::solver& s1, trail_t& t) {
|
||||||
params_ref p;
|
params_ref p;
|
||||||
reslimit rlim;
|
reslimit rlim;
|
||||||
sat::solver s2(p, rlim, 0);
|
sat::solver s2(p, rlim);
|
||||||
init_vars(s2);
|
init_vars(s2);
|
||||||
sat::literal_vector cls;
|
sat::literal_vector cls;
|
||||||
for (unsigned i = 0; i < t.size(); ++i) {
|
for (unsigned i = 0; i < t.size(); ++i) {
|
||||||
|
@ -85,7 +85,7 @@ void tst_sat_user_scope() {
|
||||||
trail_t trail;
|
trail_t trail;
|
||||||
params_ref p;
|
params_ref p;
|
||||||
reslimit rlim;
|
reslimit rlim;
|
||||||
sat::solver s(p, rlim, 0); // incremental solver
|
sat::solver s(p, rlim); // incremental solver
|
||||||
init_vars(s);
|
init_vars(s);
|
||||||
while (true) {
|
while (true) {
|
||||||
for (unsigned i = 0; i < s_num_frames; ++i) {
|
for (unsigned i = 0; i < s_num_frames; ++i) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue