mirror of
https://github.com/Z3Prover/z3
synced 2025-04-24 01:25:31 +00:00
Fix UP's decide callback (#6707)
* Query Boolean Assignment in the UP * UP's decide ref arguments => next_split * Fixed wrapper * More fixes
This commit is contained in:
parent
d59bf55539
commit
82667bd86b
18 changed files with 174 additions and 169 deletions
|
@ -128,7 +128,7 @@ namespace bv {
|
|||
/**
|
||||
\brief Find an unassigned bit for m_wpos[v], if such bit cannot be found invoke fixed_var_eh
|
||||
*/
|
||||
void solver::find_wpos(theory_var v) {
|
||||
bool solver::find_wpos(theory_var v) {
|
||||
literal_vector const& bits = m_bits[v];
|
||||
unsigned sz = bits.size();
|
||||
unsigned& wpos = m_wpos[v];
|
||||
|
@ -137,11 +137,12 @@ namespace bv {
|
|||
if (s().value(bits[idx]) == l_undef) {
|
||||
wpos = idx;
|
||||
TRACE("bv", tout << "moved wpos of v" << v << " to " << wpos << "\n";);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
TRACE("bv", tout << "v" << v << " is a fixed variable.\n";);
|
||||
fixed_var_eh(v);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -853,7 +854,17 @@ namespace bv {
|
|||
values[n->get_root_id()] = bv.mk_numeral(val, m_bits[v].size());
|
||||
}
|
||||
|
||||
trail_stack& solver::get_trail_stack() {
|
||||
sat::bool_var solver::get_bit(unsigned bit, euf::enode *n) const {
|
||||
theory_var v = n->get_th_var(get_id());
|
||||
if (v == euf::null_theory_var)
|
||||
return sat::null_bool_var;
|
||||
auto &bits = m_bits[v];
|
||||
if (bit >= bits.size())
|
||||
return sat::null_bool_var;
|
||||
return bits[bit].var();
|
||||
}
|
||||
|
||||
trail_stack &solver::get_trail_stack() {
|
||||
return ctx.get_trail_stack();
|
||||
}
|
||||
|
||||
|
|
|
@ -321,7 +321,7 @@ namespace bv {
|
|||
|
||||
// solving
|
||||
theory_var find(theory_var v) const { return m_find.find(v); }
|
||||
void find_wpos(theory_var v);
|
||||
bool find_wpos(theory_var v);
|
||||
void find_new_diseq_axioms(atom& a, theory_var v, unsigned idx);
|
||||
void mk_new_diseq_axiom(theory_var v1, theory_var v2, unsigned idx);
|
||||
bool get_fixed_value(theory_var v, numeral& result) const;
|
||||
|
@ -334,7 +334,6 @@ namespace bv {
|
|||
numeral const& power2(unsigned i) const;
|
||||
sat::literal mk_true();
|
||||
|
||||
|
||||
// invariants
|
||||
bool check_zero_one_bits(theory_var v);
|
||||
void check_missing_propagation() const;
|
||||
|
@ -391,6 +390,7 @@ namespace bv {
|
|||
euf::theory_var mk_var(euf::enode* n) override;
|
||||
void apply_sort_cnstr(euf::enode * n, sort * s) override;
|
||||
|
||||
bool_var get_bit(unsigned bit, euf::enode* n) const;
|
||||
|
||||
void merge_eh(theory_var, theory_var, theory_var v1, theory_var v2);
|
||||
void after_merge_eh(theory_var r1, theory_var r2, theory_var v1, theory_var v2) { SASSERT(check_zero_one_bits(r1)); }
|
||||
|
|
|
@ -15,8 +15,9 @@ Author:
|
|||
|
||||
--*/
|
||||
|
||||
#include "sat/smt/user_solver.h"
|
||||
#include "sat/smt/bv_solver.h"
|
||||
#include "sat/smt/euf_solver.h"
|
||||
#include "sat/smt/user_solver.h"
|
||||
|
||||
namespace user_solver {
|
||||
|
||||
|
@ -39,7 +40,7 @@ namespace user_solver {
|
|||
expr_ref r(m);
|
||||
sat::literal_vector explain;
|
||||
if (ctx.is_fixed(n, r, explain))
|
||||
m_prop.push_back(prop_info(explain, v, r));
|
||||
m_prop.push_back(prop_info(explain, v, r));
|
||||
}
|
||||
|
||||
void solver::propagate_cb(
|
||||
|
@ -56,17 +57,21 @@ namespace user_solver {
|
|||
void solver::register_cb(expr* e) {
|
||||
add_expr(e);
|
||||
}
|
||||
|
||||
void solver::next_split_cb(expr* e, unsigned idx, lbool phase) {
|
||||
|
||||
bool solver::next_split_cb(expr* e, unsigned idx, lbool phase) {
|
||||
if (e == nullptr) {
|
||||
m_next_split_expr = nullptr;
|
||||
return;
|
||||
m_next_split_var = sat::null_bool_var;
|
||||
return true;
|
||||
}
|
||||
force_push();
|
||||
ctx.internalize(e);
|
||||
m_next_split_expr = e;
|
||||
m_next_split_idx = idx;
|
||||
sat::bool_var var = enode_to_bool(ctx.get_enode(e), idx);
|
||||
m_next_split_phase = phase;
|
||||
if (var == sat::null_bool_var || s().value(var) != l_undef)
|
||||
return false;
|
||||
m_next_split_var = var;
|
||||
m_next_split_phase = phase;
|
||||
return true;
|
||||
}
|
||||
|
||||
sat::check_result solver::check() {
|
||||
|
@ -84,39 +89,41 @@ namespace user_solver {
|
|||
m_id2justification.setx(v, sat::literal_vector(num_lits, jlits), sat::literal_vector());
|
||||
m_fixed_eh(m_user_context, this, var2expr(v), value);
|
||||
}
|
||||
|
||||
|
||||
bool solver::decide(sat::bool_var& var, lbool& phase) {
|
||||
|
||||
|
||||
if (!m_decide_eh)
|
||||
return false;
|
||||
|
||||
|
||||
euf::enode* original_enode = bool_var2enode(var);
|
||||
|
||||
|
||||
if (!original_enode || !is_attached_to_var(original_enode))
|
||||
return false;
|
||||
|
||||
|
||||
unsigned new_bit = 0; // ignored; currently no bv-support
|
||||
expr* e = original_enode->get_expr();
|
||||
|
||||
m_decide_eh(m_user_context, this, &e, &new_bit, &phase);
|
||||
|
||||
euf::enode* new_enode = ctx.get_enode(e);
|
||||
|
||||
if (original_enode == new_enode || new_enode->bool_var() == sat::null_bool_var)
|
||||
|
||||
m_decide_eh(m_user_context, this, e, new_bit, phase);
|
||||
sat::bool_var new_var;
|
||||
if (!get_case_split(new_var, phase) || new_var == var)
|
||||
// The user did not interfere
|
||||
return false;
|
||||
|
||||
var = new_enode->bool_var();
|
||||
var = new_var;
|
||||
|
||||
// check if the new variable is unassigned
|
||||
if (s().value(var) != l_undef)
|
||||
throw default_exception("expression in \"decide\" is already assigned");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool solver::get_case_split(sat::bool_var& var, lbool& phase){
|
||||
if (!m_next_split_expr)
|
||||
|
||||
bool solver::get_case_split(sat::bool_var& var, lbool& phase) {
|
||||
if (m_next_split_var == sat::null_bool_var)
|
||||
return false;
|
||||
|
||||
euf::enode* n = ctx.get_enode(m_next_split_expr);
|
||||
var = n->bool_var();
|
||||
|
||||
var = m_next_split_var;
|
||||
phase = m_next_split_phase;
|
||||
m_next_split_expr = nullptr;
|
||||
m_next_split_var = sat::null_bool_var;
|
||||
m_next_split_phase = l_undef;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -134,14 +141,14 @@ namespace user_solver {
|
|||
m_id2justification.setx(v, lits, sat::literal_vector());
|
||||
m_fixed_eh(m_user_context, this, var2expr(v), lit.sign() ? m.mk_false() : m.mk_true());
|
||||
}
|
||||
|
||||
|
||||
void solver::new_eq_eh(euf::th_eq const& eq) {
|
||||
if (!m_eq_eh)
|
||||
return;
|
||||
force_push();
|
||||
m_eq_eh(m_user_context, this, var2expr(eq.v1()), var2expr(eq.v2()));
|
||||
}
|
||||
|
||||
|
||||
void solver::new_diseq_eh(euf::th_eq const& de) {
|
||||
if (!m_diseq_eh)
|
||||
return;
|
||||
|
@ -188,7 +195,7 @@ namespace user_solver {
|
|||
propagate_consequence(prop);
|
||||
else
|
||||
propagate_new_fixed(prop);
|
||||
}
|
||||
}
|
||||
return np < m_stats.m_num_propagations;
|
||||
}
|
||||
|
||||
|
@ -208,7 +215,7 @@ namespace user_solver {
|
|||
auto& j = justification::from_index(idx);
|
||||
auto const& prop = m_prop[j.m_propagation_index];
|
||||
for (unsigned id : prop.m_ids)
|
||||
r.append(m_id2justification[id]);
|
||||
r.append(m_id2justification[id]);
|
||||
for (auto const& p : prop.m_eqs)
|
||||
ctx.add_antecedent(probing, expr2enode(p.first), expr2enode(p.second));
|
||||
}
|
||||
|
@ -243,7 +250,7 @@ namespace user_solver {
|
|||
}
|
||||
|
||||
std::ostream& solver::display_constraint(std::ostream& out, sat::ext_constraint_idx idx) const {
|
||||
return display_justification(out, idx);
|
||||
return display_justification(out, idx);
|
||||
}
|
||||
|
||||
euf::th_solver* solver::clone(euf::solver& dst_ctx) {
|
||||
|
@ -278,26 +285,35 @@ namespace user_solver {
|
|||
return true;
|
||||
}
|
||||
m_stack.push_back(sat::eframe(e));
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool solver::visited(expr* e) {
|
||||
euf::enode* n = expr2enode(e);
|
||||
return n && n->is_attached_to(get_id());
|
||||
return n && n->is_attached_to(get_id());
|
||||
}
|
||||
|
||||
|
||||
bool solver::post_visit(expr* e, bool sign, bool root) {
|
||||
euf::enode* n = expr2enode(e);
|
||||
SASSERT(!n || !n->is_attached_to(get_id()));
|
||||
if (!n)
|
||||
n = mk_enode(e, false);
|
||||
if (!n)
|
||||
n = mk_enode(e, false);
|
||||
add_expr(e);
|
||||
if (m_created_eh)
|
||||
m_created_eh(m_user_context, this, e);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
sat::bool_var solver::enode_to_bool(euf::enode* n, unsigned idx) {
|
||||
if (n->bool_var() != sat::null_bool_var) {
|
||||
// expression is a boolean
|
||||
return n->bool_var();
|
||||
}
|
||||
// expression is a bit-vector
|
||||
bv_util bv(m);
|
||||
th_solver* th = ctx.fid2solver(bv.get_fid());
|
||||
return ((bv::solver*) th)->get_bit(idx, n);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -75,9 +75,8 @@ namespace user_solver {
|
|||
euf::enode_pair_vector m_eqs;
|
||||
unsigned_vector m_fixed_ids;
|
||||
stats m_stats;
|
||||
expr* m_next_split_expr = nullptr;
|
||||
unsigned m_next_split_idx;
|
||||
lbool m_next_split_phase;
|
||||
sat::bool_var m_next_split_var = sat::null_bool_var;
|
||||
lbool m_next_split_phase = l_undef;
|
||||
|
||||
struct justification {
|
||||
unsigned m_propagation_index { 0 };
|
||||
|
@ -104,6 +103,8 @@ namespace user_solver {
|
|||
bool visited(expr* e) override;
|
||||
bool post_visit(expr* e, bool sign, bool root) override;
|
||||
|
||||
sat::bool_var enode_to_bool(euf::enode* n, unsigned idx);
|
||||
|
||||
public:
|
||||
solver(euf::solver& ctx);
|
||||
|
||||
|
@ -136,7 +137,7 @@ namespace user_solver {
|
|||
|
||||
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;
|
||||
bool next_split_cb(expr* e, unsigned idx, lbool phase) override;
|
||||
|
||||
void new_fixed_eh(euf::theory_var v, expr* value, unsigned num_lits, sat::literal const* jlits);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue