3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-05-10 09:15:47 +00:00

Added decide-callback to user-propagator (#5978)

* Fixed registering expressions in push/pop

* Reused existing function

* Reverted reusing can_propagate

* Added decide-callback to user-propagator

* Refactoring

* Fixed index
This commit is contained in:
Clemens Eisenhofer 2022-04-15 20:07:17 +02:00 committed by GitHub
parent 9ecd4f8406
commit e11496bc65
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 284 additions and 87 deletions

View file

@ -1766,6 +1766,70 @@ namespace smt {
m_bvar_inc *= INV_ACTIVITY_LIMIT;
}
/**
\brief Returns a truth value for the given variable
*/
bool context::guess(bool_var var, lbool phase) {
if (is_quantifier(m_bool_var2expr[var])) {
// Overriding any decision on how to assign the quantifier.
// assigning a quantifier to false is equivalent to make it irrelevant.
phase = l_false;
}
literal l(var, false);
if (phase != l_undef)
return phase == l_true;
bool_var_data & d = m_bdata[var];
if (d.try_true_first())
return true;
switch (m_fparams.m_phase_selection) {
case PS_THEORY:
if (m_phase_cache_on && d.m_phase_available) {
return m_bdata[var].m_phase;
}
if (!m_phase_cache_on && d.is_theory_atom()) {
theory * th = m_theories.get_plugin(d.get_theory());
lbool th_phase = th->get_phase(var);
if (th_phase != l_undef) {
return th_phase == l_true;
}
}
if (track_occs()) {
if (m_lit_occs[l.index()] == 0) {
return false;
}
if (m_lit_occs[(~l).index()] == 0) {
return true;
}
}
return m_phase_default;
case PS_CACHING:
case PS_CACHING_CONSERVATIVE:
case PS_CACHING_CONSERVATIVE2:
if (m_phase_cache_on && d.m_phase_available) {
TRACE("phase_selection", tout << "using cached value, is_pos: " << m_bdata[var].m_phase << ", var: p" << var << "\n";);
return m_bdata[var].m_phase;
}
else {
TRACE("phase_selection", tout << "setting to false\n";);
return m_phase_default;
}
case PS_ALWAYS_FALSE:
return false;
case PS_ALWAYS_TRUE:
return true;
case PS_RANDOM:
return m_random() % 2 == 0;
case PS_OCCURRENCE: {
return m_lit_occs[l.index()] > m_lit_occs[(~l).index()];
}
default:
UNREACHABLE();
return false;
}
}
/**
\brief Execute next case split, return false if there are no
more case splits to be performed.
@ -1807,81 +1871,15 @@ namespace smt {
TRACE("decide", tout << "splitting, lvl: " << m_scope_lvl << "\n";);
TRACE("decide_detail", tout << mk_pp(bool_var2expr(var), m) << "\n";);
bool is_pos;
if (is_quantifier(m_bool_var2expr[var])) {
// Overriding any decision on how to assign the quantifier.
// assigning a quantifier to false is equivalent to make it irrelevant.
phase = l_false;
}
bool is_pos = guess(var, phase);
literal l(var, false);
if (phase != l_undef) {
is_pos = phase == l_true;
}
else {
bool_var_data & d = m_bdata[var];
if (d.try_true_first()) {
is_pos = true;
}
else {
switch (m_fparams.m_phase_selection) {
case PS_THEORY:
if (m_phase_cache_on && d.m_phase_available) {
is_pos = m_bdata[var].m_phase;
break;
}
if (!m_phase_cache_on && d.is_theory_atom()) {
theory * th = m_theories.get_plugin(d.get_theory());
lbool th_phase = th->get_phase(var);
if (th_phase != l_undef) {
is_pos = th_phase == l_true;
break;
}
}
if (track_occs()) {
if (m_lit_occs[l.index()] == 0) {
is_pos = false;
break;
}
if (m_lit_occs[(~l).index()] == 0) {
is_pos = true;
break;
}
}
is_pos = m_phase_default;
break;
case PS_CACHING:
case PS_CACHING_CONSERVATIVE:
case PS_CACHING_CONSERVATIVE2:
if (m_phase_cache_on && d.m_phase_available) {
TRACE("phase_selection", tout << "using cached value, is_pos: " << m_bdata[var].m_phase << ", var: p" << var << "\n";);
is_pos = m_bdata[var].m_phase;
}
else {
TRACE("phase_selection", tout << "setting to false\n";);
is_pos = m_phase_default;
}
break;
case PS_ALWAYS_FALSE:
is_pos = false;
break;
case PS_ALWAYS_TRUE:
is_pos = true;
break;
case PS_RANDOM:
is_pos = (m_random() % 2 == 0);
break;
case PS_OCCURRENCE: {
is_pos = m_lit_occs[l.index()] > m_lit_occs[(~l).index()];
break;
}
default:
is_pos = false;
UNREACHABLE();
}
}
bool_var original_choice = var;
if (decide_user_interference(var, is_pos)) {
m_case_split_queue->unassign_var_eh(original_choice);
l = literal(var, false);
}
if (!is_pos) l.neg();
@ -1889,7 +1887,7 @@ namespace smt {
assign(l, b_justification::mk_axiom(), true);
return true;
}
/**
\brief Update counter that is used to enable/disable phase caching.
*/
@ -2906,6 +2904,14 @@ namespace smt {
return m_user_propagator && m_user_propagator->has_fixed() && n->get_th_var(m_user_propagator->get_family_id()) != null_theory_var;
}
bool context::decide_user_interference(bool_var& var, bool& is_pos) {
if (!m_user_propagator || !m_user_propagator->has_decide())
return false;
bool_var old = var;
m_user_propagator->decide(var, is_pos);
return old != var;
}
void context::assign_fixed(enode* n, expr* val, unsigned sz, literal const* explain) {
theory_var v = n->get_th_var(m_user_propagator->get_family_id());
m_user_propagator->new_fixed_eh(v, val, sz, explain);
@ -3042,7 +3048,8 @@ namespace smt {
}
}
}
} else {
}
else {
literal_vector new_case_split;
for (unsigned i = 0; i < num_lits; ++i) {
literal l = lits[i];