mirror of
https://github.com/Z3Prover/z3
synced 2025-04-24 01:25:31 +00:00
add lrb/chb and experiment with them
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
commit
e0a86ccc1a
28 changed files with 459 additions and 281 deletions
|
@ -126,6 +126,27 @@ namespace sat {
|
|||
m_drat_file = p.drat_file();
|
||||
m_drat = (m_drat_check || m_drat_file != symbol("")) && p.threads() == 1;
|
||||
m_dyn_sub_res = p.dyn_sub_res();
|
||||
|
||||
// Parameters used in Liang, Ganesh, Poupart, Czarnecki AAAI 2016.
|
||||
m_branching_heuristic = BH_VSIDS;
|
||||
if (p.branching_heuristic() == symbol("vsids")) {
|
||||
m_branching_heuristic = BH_VSIDS;
|
||||
}
|
||||
else if (p.branching_heuristic() == symbol("chb")) {
|
||||
m_branching_heuristic = BH_CHB;
|
||||
}
|
||||
else if (p.branching_heuristic() == symbol("lrb")) {
|
||||
m_branching_heuristic = BH_LRB;
|
||||
}
|
||||
else {
|
||||
throw sat_param_exception("invalid branching heuristic: accepted heuristics are 'vsids', 'lrb' or 'chb'");
|
||||
}
|
||||
m_anti_exploration = m_branching_heuristic != BH_VSIDS;
|
||||
m_step_size_init = 0.40;
|
||||
m_step_size_dec = 0.000001;
|
||||
m_step_size_min = 0.06;
|
||||
m_reward_multiplier = 0.9;
|
||||
m_reward_offset = 1000000.0;
|
||||
}
|
||||
|
||||
void config::collect_param_descrs(param_descrs & r) {
|
||||
|
|
|
@ -44,6 +44,12 @@ namespace sat {
|
|||
GC_PSM_GLUE
|
||||
};
|
||||
|
||||
enum branching_heuristic {
|
||||
BH_VSIDS,
|
||||
BH_CHB,
|
||||
BH_LRB
|
||||
};
|
||||
|
||||
struct config {
|
||||
unsigned long long m_max_memory;
|
||||
phase_selection m_phase;
|
||||
|
@ -95,6 +101,14 @@ namespace sat {
|
|||
symbol m_glue_psm;
|
||||
symbol m_psm_glue;
|
||||
|
||||
// branching heuristic settings.
|
||||
branching_heuristic m_branching_heuristic;
|
||||
bool m_anti_exploration;
|
||||
double m_step_size_init;
|
||||
double m_step_size_dec;
|
||||
double m_step_size_min;
|
||||
double m_reward_multiplier;
|
||||
double m_reward_offset;
|
||||
config(params_ref const & p);
|
||||
void updt_params(params_ref const & p);
|
||||
static void collect_param_descrs(param_descrs & d);
|
||||
|
|
|
@ -9,6 +9,7 @@ def_module_params('sat',
|
|||
('restart.initial', UINT, 100, 'initial restart (number of conflicts)'),
|
||||
('restart.max', UINT, UINT_MAX, 'maximal number of restarts.'),
|
||||
('restart.factor', DOUBLE, 1.5, 'restart increment factor for geometric strategy'),
|
||||
('branching.heuristic', SYMBOL, 'vsids', 'branching heuristic vsids, lrb or chb'),
|
||||
('random_freq', DOUBLE, 0.01, 'frequency of random case splits'),
|
||||
('random_seed', UINT, 0, 'random seed'),
|
||||
('burst_search', UINT, 100, 'number of conflicts before first global simplification'),
|
||||
|
@ -21,8 +22,7 @@ def_module_params('sat',
|
|||
('minimize_lemmas', BOOL, True, 'minimize learned clauses'),
|
||||
('dyn_sub_res', BOOL, True, 'dynamic subsumption resolution for minimizing learned clauses'),
|
||||
('core.minimize', BOOL, False, 'minimize computed core'),
|
||||
('core.minimize_partial', BOOL, False, 'apply partial (cheap) core minimization'),
|
||||
('threads', UINT, 1, 'number of parallel threads to use'),
|
||||
('core.minimize_partial', BOOL, False, 'apply partial (cheap) core minimization'), ('threads', UINT, 1, 'number of parallel threads to use'),
|
||||
('dimacs.core', BOOL, False, 'extract core from DIMACS benchmarks'),
|
||||
('drat.file', SYMBOL, '', 'file to dump DRAT proofs'),
|
||||
('drat.check', BOOL, False, 'build up internal proof and check'),
|
||||
|
|
|
@ -174,6 +174,11 @@ namespace sat {
|
|||
m_phase.push_back(PHASE_NOT_AVAILABLE);
|
||||
m_prev_phase.push_back(PHASE_NOT_AVAILABLE);
|
||||
m_assigned_since_gc.push_back(false);
|
||||
m_last_conflict.push_back(0);
|
||||
m_last_propagation.push_back(0);
|
||||
m_participated.push_back(0);
|
||||
m_canceled.push_back(0);
|
||||
m_reasoned.push_back(0);
|
||||
m_case_split_queue.mk_var_eh(v);
|
||||
m_simplifier.insert_elim_todo(v);
|
||||
SASSERT(!was_eliminated(v));
|
||||
|
@ -580,6 +585,29 @@ namespace sat {
|
|||
if (m_ext && m_external[v])
|
||||
m_ext->asserted(l);
|
||||
|
||||
switch (m_config.m_branching_heuristic) {
|
||||
case BH_VSIDS:
|
||||
break;
|
||||
case BH_CHB:
|
||||
m_last_propagation[v] = m_stats.m_conflict;
|
||||
break;
|
||||
case BH_LRB:
|
||||
m_participated[v] = 0;
|
||||
m_reasoned[v] = 0;
|
||||
break;
|
||||
}
|
||||
if (m_config.m_anti_exploration) {
|
||||
uint64 age = m_stats.m_conflict - m_canceled[v];
|
||||
if (age > 0) {
|
||||
double decay = pow(0.95, age);
|
||||
m_activity[v] = static_cast<unsigned>(m_activity[v] * decay);
|
||||
// NB. MapleSAT does not update canceled.
|
||||
m_canceled[v] = m_stats.m_conflict;
|
||||
m_case_split_queue.activity_changed_eh(v, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
SASSERT(!l.sign() || m_phase[v] == NEG_PHASE);
|
||||
SASSERT(l.sign() || m_phase[v] == POS_PHASE);
|
||||
|
||||
|
@ -771,7 +799,11 @@ namespace sat {
|
|||
}
|
||||
|
||||
bool solver::propagate(bool update) {
|
||||
unsigned qhead = m_qhead;
|
||||
bool r = propagate_core(update);
|
||||
if (m_config.m_branching_heuristic == BH_CHB) {
|
||||
update_chb_activity(r, qhead);
|
||||
}
|
||||
CASSERT("sat_propagate", check_invariant());
|
||||
CASSERT("sat_missed_prop", check_missed_propagation());
|
||||
return r;
|
||||
|
@ -1064,6 +1096,18 @@ namespace sat {
|
|||
}
|
||||
|
||||
while (!m_case_split_queue.empty()) {
|
||||
if (m_config.m_anti_exploration) {
|
||||
next = m_case_split_queue.min_var();
|
||||
auto age = m_stats.m_conflict - m_canceled[next];
|
||||
while (age > 0) {
|
||||
double decay = pow(0.95, age);
|
||||
m_activity[next] = static_cast<unsigned>(m_activity[next] * pow(0.95, age));
|
||||
m_case_split_queue.activity_changed_eh(next, false);
|
||||
m_canceled[next] = m_stats.m_conflict;
|
||||
next = m_case_split_queue.min_var();
|
||||
age = m_stats.m_conflict - m_canceled[next];
|
||||
}
|
||||
}
|
||||
next = m_case_split_queue.next_var();
|
||||
if (value(next) == l_undef && !was_eliminated(next))
|
||||
return next;
|
||||
|
@ -1828,6 +1872,9 @@ namespace sat {
|
|||
m_conflicts_since_restart++;
|
||||
m_conflicts_since_gc++;
|
||||
m_stats.m_conflict++;
|
||||
if (m_step_size > m_config.m_step_size_min) {
|
||||
m_step_size -= m_config.m_step_size_dec;
|
||||
}
|
||||
|
||||
m_conflict_lvl = get_max_lvl(m_not_l, m_conflict);
|
||||
TRACE("sat", tout << "conflict detected at level " << m_conflict_lvl << " for ";
|
||||
|
@ -2175,7 +2222,16 @@ namespace sat {
|
|||
SASSERT(var < num_vars());
|
||||
if (!is_marked(var) && var_lvl > 0) {
|
||||
mark(var);
|
||||
inc_activity(var);
|
||||
switch (m_config.m_branching_heuristic) {
|
||||
case BH_VSIDS:
|
||||
inc_activity(var);
|
||||
break;
|
||||
case BH_CHB:
|
||||
m_last_conflict[var] = m_stats.m_conflict;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (var_lvl == m_conflict_lvl)
|
||||
num_marks++;
|
||||
else
|
||||
|
@ -2431,6 +2487,9 @@ namespace sat {
|
|||
\brief Reset the mark of the variables in the current lemma.
|
||||
*/
|
||||
void solver::reset_lemma_var_marks() {
|
||||
if (m_config.m_branching_heuristic == BH_LRB) {
|
||||
update_lrb_reasoned();
|
||||
}
|
||||
literal_vector::iterator it = m_lemma.begin();
|
||||
literal_vector::iterator end = m_lemma.end();
|
||||
SASSERT(!is_marked((*it).var()));
|
||||
|
@ -2441,6 +2500,58 @@ namespace sat {
|
|||
}
|
||||
}
|
||||
|
||||
void solver::update_lrb_reasoned() {
|
||||
unsigned sz = m_lemma.size();
|
||||
SASSERT(!is_marked(m_lemma[0].var()));
|
||||
mark(m_lemma[0].var());
|
||||
for (unsigned i = m_lemma.size(); i > 0; ) {
|
||||
--i;
|
||||
justification js = m_justification[m_lemma[i].var()];
|
||||
switch (js.get_kind()) {
|
||||
case justification::NONE:
|
||||
break;
|
||||
case justification::BINARY:
|
||||
update_lrb_reasoned(js.get_literal());
|
||||
break;
|
||||
case justification::TERNARY:
|
||||
update_lrb_reasoned(js.get_literal1());
|
||||
update_lrb_reasoned(js.get_literal2());
|
||||
break;
|
||||
case justification::CLAUSE: {
|
||||
clause & c = *(m_cls_allocator.get_clause(js.get_clause_offset()));
|
||||
for (unsigned i = 0; i < c.size(); ++i) {
|
||||
update_lrb_reasoned(c[i]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case justification::EXT_JUSTIFICATION: {
|
||||
fill_ext_antecedents(m_lemma[i], js);
|
||||
literal_vector::iterator it = m_ext_antecedents.begin();
|
||||
literal_vector::iterator end = m_ext_antecedents.end();
|
||||
for (; it != end; ++it) {
|
||||
update_lrb_reasoned(*it);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
reset_mark(m_lemma[0].var());
|
||||
for (unsigned i = m_lemma.size(); i > sz; ) {
|
||||
--i;
|
||||
reset_mark(m_lemma[i].var());
|
||||
}
|
||||
m_lemma.shrink(sz);
|
||||
}
|
||||
|
||||
void solver::update_lrb_reasoned(literal lit) {
|
||||
bool_var v = lit.var();
|
||||
if (!is_marked(v)) {
|
||||
mark(v);
|
||||
m_reasoned[v]++;
|
||||
m_lemma.push_back(lit);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Apply dynamic subsumption resolution to new lemma.
|
||||
Only binary and ternary clauses are used.
|
||||
|
@ -2617,6 +2728,18 @@ namespace sat {
|
|||
bool_var v = l.var();
|
||||
SASSERT(value(v) == l_undef);
|
||||
m_case_split_queue.unassign_var_eh(v);
|
||||
if (m_config.m_branching_heuristic == BH_LRB) {
|
||||
uint64 interval = m_stats.m_conflict - m_last_propagation[v];
|
||||
if (interval > 0) {
|
||||
auto activity = m_activity[v];
|
||||
auto reward = (m_config.m_reward_offset * (m_participated[v] + m_reasoned[v])) / interval;
|
||||
m_activity[v] = static_cast<unsigned>(m_step_size * reward + ((1 - m_step_size) * activity));
|
||||
m_case_split_queue.activity_changed_eh(v, m_activity[v] > activity);
|
||||
}
|
||||
}
|
||||
if (m_config.m_anti_exploration) {
|
||||
m_canceled[v] = m_stats.m_conflict;
|
||||
}
|
||||
}
|
||||
m_trail.shrink(old_sz);
|
||||
m_qhead = old_sz;
|
||||
|
@ -2799,6 +2922,8 @@ namespace sat {
|
|||
m_probing.updt_params(p);
|
||||
m_scc.updt_params(p);
|
||||
m_rand.set_seed(m_config.m_random_seed);
|
||||
|
||||
m_step_size = m_config.m_step_size_init;
|
||||
}
|
||||
|
||||
void solver::collect_param_descrs(param_descrs & d) {
|
||||
|
@ -2836,6 +2961,7 @@ namespace sat {
|
|||
// -----------------------
|
||||
|
||||
void solver::rescale_activity() {
|
||||
SASSERT(m_config.m_branching_heuristic == BH_VSIDS);
|
||||
svector<unsigned>::iterator it = m_activity.begin();
|
||||
svector<unsigned>::iterator end = m_activity.end();
|
||||
for (; it != end; ++it) {
|
||||
|
@ -2844,6 +2970,18 @@ namespace sat {
|
|||
m_activity_inc >>= 14;
|
||||
}
|
||||
|
||||
void solver::update_chb_activity(bool is_sat, unsigned qhead) {
|
||||
SASSERT(m_config.m_branching_heuristic == BH_CHB);
|
||||
double multiplier = m_config.m_reward_offset * (is_sat ? m_config.m_reward_multiplier : 1.0);
|
||||
for (unsigned i = qhead; i < m_trail.size(); ++i) {
|
||||
auto v = m_trail[i].var();
|
||||
auto reward = multiplier / (m_stats.m_conflict - m_last_conflict[v] + 1);
|
||||
auto activity = m_activity[v];
|
||||
m_activity[v] = static_cast<unsigned>(m_step_size * reward + ((1.0 - m_step_size) * activity));
|
||||
m_case_split_queue.activity_changed_eh(v, m_activity[v] > activity);
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------
|
||||
//
|
||||
// Iterators
|
||||
|
|
|
@ -110,8 +110,17 @@ namespace sat {
|
|||
svector<char> m_eliminated;
|
||||
svector<char> m_external;
|
||||
svector<unsigned> m_level;
|
||||
// branch variable selection:
|
||||
svector<unsigned> m_activity;
|
||||
unsigned m_activity_inc;
|
||||
svector<uint64> m_last_conflict;
|
||||
svector<uint64> m_last_propagation;
|
||||
svector<uint64> m_participated;
|
||||
svector<uint64> m_canceled;
|
||||
svector<uint64> m_reasoned;
|
||||
int m_action;
|
||||
double m_step_size;
|
||||
// phase
|
||||
svector<char> m_phase;
|
||||
svector<char> m_prev_phase;
|
||||
svector<char> m_assigned_since_gc;
|
||||
|
@ -555,6 +564,12 @@ namespace sat {
|
|||
private:
|
||||
void rescale_activity();
|
||||
|
||||
void update_chb_activity(bool is_sat, unsigned qhead);
|
||||
|
||||
void update_lrb_reasoned();
|
||||
|
||||
void update_lrb_reasoned(literal lit);
|
||||
|
||||
// -----------------------
|
||||
//
|
||||
// Iterators
|
||||
|
|
|
@ -39,6 +39,15 @@ namespace sat {
|
|||
m_queue.decreased(v);
|
||||
}
|
||||
|
||||
void activity_changed_eh(bool_var v, bool up) {
|
||||
if (m_queue.contains(v)) {
|
||||
if (up)
|
||||
m_queue.decreased(v);
|
||||
else
|
||||
m_queue.increased(v);
|
||||
}
|
||||
}
|
||||
|
||||
void mk_var_eh(bool_var v) {
|
||||
m_queue.reserve(v+1);
|
||||
m_queue.insert(v);
|
||||
|
@ -61,6 +70,8 @@ namespace sat {
|
|||
bool empty() const { return m_queue.empty(); }
|
||||
|
||||
bool_var next_var() { SASSERT(!empty()); return m_queue.erase_min(); }
|
||||
|
||||
bool_var min_var() { SASSERT(!empty()); return m_queue.min_value(); }
|
||||
};
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue