mirror of
https://github.com/Z3Prover/z3
synced 2025-04-24 01:25:31 +00:00
Added function to select the next variable to split on (User-Propagator) (#6096)
* Added function to select the next variable to split on * Fixed typo * Small fixes * uint -> int
This commit is contained in:
parent
f08e3d70a9
commit
2fa60aa43c
17 changed files with 255 additions and 104 deletions
|
@ -1848,24 +1848,30 @@ namespace smt {
|
|||
}
|
||||
}
|
||||
bool_var var;
|
||||
lbool phase = l_undef;
|
||||
m_case_split_queue->next_case_split(var, phase);
|
||||
bool is_pos;
|
||||
bool used_queue = false;
|
||||
|
||||
if (!has_split_candidate(var, is_pos)) {
|
||||
lbool phase = l_undef;
|
||||
m_case_split_queue->next_case_split(var, phase);
|
||||
used_queue = true;
|
||||
if (var == null_bool_var)
|
||||
return false;
|
||||
|
||||
if (var == null_bool_var) {
|
||||
return false;
|
||||
TRACE_CODE({
|
||||
static unsigned counter = 0;
|
||||
counter++;
|
||||
if (counter % 100 == 0) {
|
||||
TRACE("activity_profile",
|
||||
for (unsigned i=0; i<get_num_bool_vars(); i++) {
|
||||
tout << get_activity(i) << " ";
|
||||
}
|
||||
tout << "\n";);
|
||||
}});
|
||||
|
||||
is_pos = guess(var, phase);
|
||||
}
|
||||
|
||||
TRACE_CODE({
|
||||
static unsigned counter = 0;
|
||||
counter++;
|
||||
if (counter % 100 == 0) {
|
||||
TRACE("activity_profile",
|
||||
for (unsigned i=0; i<get_num_bool_vars(); i++) {
|
||||
tout << get_activity(i) << " ";
|
||||
}
|
||||
tout << "\n";);
|
||||
}});
|
||||
|
||||
m_stats.m_num_decisions++;
|
||||
|
||||
push_scope();
|
||||
|
@ -1873,13 +1879,13 @@ namespace smt {
|
|||
|
||||
TRACE("decide_detail", tout << mk_pp(bool_var2expr(var), m) << "\n";);
|
||||
|
||||
bool is_pos = guess(var, phase);
|
||||
literal l(var, false);
|
||||
|
||||
bool_var original_choice = var;
|
||||
|
||||
if (decide_user_interference(var, is_pos)) {
|
||||
m_case_split_queue->unassign_var_eh(original_choice);
|
||||
if (used_queue)
|
||||
m_case_split_queue->unassign_var_eh(original_choice);
|
||||
l = literal(var, false);
|
||||
}
|
||||
|
||||
|
@ -2905,8 +2911,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::has_split_candidate(bool_var& var, bool& is_pos) {
|
||||
if (!m_user_propagator)
|
||||
return false;
|
||||
return m_user_propagator->get_case_split(var, is_pos);
|
||||
}
|
||||
|
||||
bool context::decide_user_interference(bool_var& var, bool& is_pos) {
|
||||
if (!m_user_propagator || !m_user_propagator->has_decide())
|
||||
if (!m_user_propagator)
|
||||
return false;
|
||||
bool_var old = var;
|
||||
m_user_propagator->decide(var, is_pos);
|
||||
|
|
|
@ -1754,6 +1754,8 @@ namespace smt {
|
|||
|
||||
bool watches_fixed(enode* n) const;
|
||||
|
||||
bool has_split_candidate(bool_var& var, bool& is_pos);
|
||||
|
||||
bool decide_user_interference(bool_var& var, bool& is_pos);
|
||||
|
||||
void assign_fixed(enode* n, expr* val, unsigned sz, literal const* explain);
|
||||
|
|
|
@ -102,6 +102,17 @@ void theory_user_propagator::register_cb(expr* e) {
|
|||
add_expr(e, true);
|
||||
}
|
||||
|
||||
void theory_user_propagator::next_split_cb(expr* e, unsigned idx, lbool phase) {
|
||||
if (e == nullptr) { // clear
|
||||
m_next_split_expr = nullptr;
|
||||
return;
|
||||
}
|
||||
ensure_enode(e);
|
||||
m_next_split_expr = e;
|
||||
m_next_split_idx = idx;
|
||||
m_next_split_phase = phase;
|
||||
}
|
||||
|
||||
theory * theory_user_propagator::mk_fresh(context * new_ctx) {
|
||||
auto* th = alloc(theory_user_propagator, *new_ctx);
|
||||
void* ctx;
|
||||
|
@ -156,8 +167,24 @@ void theory_user_propagator::new_fixed_eh(theory_var v, expr* value, unsigned nu
|
|||
}
|
||||
}
|
||||
|
||||
void theory_user_propagator::decide(bool_var& var, bool& is_pos) {
|
||||
bool_var theory_user_propagator::enode_to_bool(enode* n, unsigned bit) {
|
||||
if (n->is_bool()) {
|
||||
// expression is a boolean
|
||||
bool_var new_var = ctx.enode2bool_var(n);
|
||||
if (ctx.get_assignment(new_var) == l_undef)
|
||||
return new_var;
|
||||
return null_bool_var;
|
||||
}
|
||||
// expression is a bit-vector
|
||||
bv_util bv(m);
|
||||
auto th_bv = (theory_bv*)ctx.get_theory(bv.get_fid());
|
||||
return th_bv->get_first_unassigned(bit, n);
|
||||
}
|
||||
|
||||
void theory_user_propagator::decide(bool_var& var, bool& is_pos) {
|
||||
if (!m_decide_eh)
|
||||
return;
|
||||
|
||||
const bool_var_data& d = ctx.get_bdata(var);
|
||||
|
||||
if (!d.is_enode() && !d.is_theory_atom())
|
||||
|
@ -216,25 +243,28 @@ void theory_user_propagator::decide(bool_var& var, bool& is_pos) {
|
|||
return;
|
||||
}
|
||||
|
||||
if (new_enode->is_bool()) {
|
||||
// expression was set to a boolean
|
||||
bool_var new_var = ctx.enode2bool_var(new_enode);
|
||||
if (ctx.get_assignment(new_var) == l_undef) {
|
||||
var = new_var;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// expression was set to a bit-vector
|
||||
auto th_bv = (theory_bv*)ctx.get_theory(bv.get_fid());
|
||||
bool_var new_var = th_bv->get_first_unassigned(new_bit, new_enode);
|
||||
if (new_var != null_bool_var)
|
||||
var = new_var;
|
||||
}
|
||||
// get unassigned variable from enode
|
||||
var = enode_to_bool(new_enode, new_bit);
|
||||
|
||||
// in case the callback did not decide on a truth value -> let Z3 decide
|
||||
is_pos = ctx.guess(var, phase);
|
||||
}
|
||||
|
||||
bool theory_user_propagator::get_case_split(bool_var& var, bool& is_pos){
|
||||
if (!m_next_split_expr)
|
||||
return false;
|
||||
enode* n = ctx.get_enode(m_next_split_expr);
|
||||
|
||||
var = enode_to_bool(n, m_next_split_idx);
|
||||
|
||||
if (var == null_bool_var)
|
||||
return false;
|
||||
|
||||
is_pos = ctx.guess(var, m_next_split_phase);
|
||||
m_next_split_expr = nullptr;
|
||||
return true;
|
||||
}
|
||||
|
||||
void theory_user_propagator::push_scope_eh() {
|
||||
++m_num_scopes;
|
||||
}
|
||||
|
|
|
@ -83,6 +83,9 @@ namespace smt {
|
|||
expr_ref_vector m_to_add;
|
||||
unsigned_vector m_to_add_lim;
|
||||
unsigned m_to_add_qhead = 0;
|
||||
expr* m_next_split_expr = nullptr;
|
||||
unsigned m_next_split_idx;
|
||||
lbool m_next_split_phase;
|
||||
|
||||
expr* var2expr(theory_var v) { return m_var2expr.get(v); }
|
||||
theory_var expr2var(expr* e) { check_defined(e); return m_expr2var[e->get_id()]; }
|
||||
|
@ -95,6 +98,8 @@ namespace smt {
|
|||
|
||||
void propagate_consequence(prop_info const& prop);
|
||||
void propagate_new_fixed(prop_info const& prop);
|
||||
|
||||
bool_var enode_to_bool(enode* n, unsigned bit);
|
||||
|
||||
public:
|
||||
theory_user_propagator(context& ctx);
|
||||
|
@ -125,13 +130,14 @@ namespace smt {
|
|||
void register_decide(user_propagator::decide_eh_t& decide_eh) { m_decide_eh = decide_eh; }
|
||||
|
||||
bool has_fixed() const { return (bool)m_fixed_eh; }
|
||||
bool has_decide() const { return (bool)m_decide_eh; }
|
||||
|
||||
void propagate_cb(unsigned num_fixed, expr* const* fixed_ids, unsigned num_eqs, expr* const* lhs, expr* const* rhs, expr* conseq) override;
|
||||
void register_cb(expr* e) override;
|
||||
void next_split_cb(expr* e, unsigned idx, lbool phase) override;
|
||||
|
||||
void new_fixed_eh(theory_var v, expr* value, unsigned num_lits, literal const* jlits);
|
||||
void decide(bool_var& var, bool& is_pos);
|
||||
bool get_case_split(bool_var& var, bool& is_pos);
|
||||
|
||||
theory * mk_fresh(context * new_ctx) override;
|
||||
bool internalize_atom(app* atom, bool gate_ctx) override;
|
||||
|
@ -154,5 +160,5 @@ namespace smt {
|
|||
bool can_propagate() override;
|
||||
void propagate() override;
|
||||
void display(std::ostream& out) const override {}
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue