3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-08-26 04:56:03 +00:00

Adding field update feature

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2015-01-03 01:27:52 -08:00
parent a296023823
commit 129e048a1b
10 changed files with 221 additions and 24 deletions

View file

@ -61,6 +61,13 @@ namespace smt {
if (antecedent == null_literal) {
ctx.assign_eq(lhs, ctx.get_enode(rhs), eq_justification::mk_axiom());
}
else if (ctx.get_assignment(antecedent) != l_true) {
literal l(mk_eq(lhs->get_owner(), rhs, true));
ctx.mark_as_relevant(l);
ctx.mark_as_relevant(antecedent);
literal lits[2] = {l, ~antecedent};
ctx.mk_th_axiom(get_id(), 2, lits);
}
else {
SASSERT(ctx.get_assignment(antecedent) == l_true);
region & r = ctx.get_region();
@ -143,6 +150,48 @@ namespace smt {
ctx.set_conflict(ctx.mk_justification(ext_theory_conflict_justification(get_id(), reg, 1, &l, 1, &p)));
}
/**
\brief Given a field update n := { r with field := v } for constructor C, assert the axioms:
(=> (is-C r) (= (acc_j n) (acc_j r))) for acc_j != field
(=> (is-C r) (= (field n) v)) for acc_j != field
(=> (not (is-C r)) (= n r))
*/
void theory_datatype::assert_update_field_axioms(enode * n) {
m_stats.m_assert_update_field++;
SASSERT(is_update_field(n));
context & ctx = get_context();
ast_manager & m = get_manager();
app* own = n->get_owner();
expr* arg1 = own->get_arg(0);
expr* arg2 = own->get_arg(1);
func_decl * upd = n->get_decl();
func_decl * acc = to_func_decl(upd->get_parameter(0).get_ast());
func_decl * con = m_util.get_accessor_constructor(acc);
func_decl * rec = m_util.get_constructor_recognizer(con);
ptr_vector<func_decl> const * accessors = m_util.get_constructor_accessors(con);
ptr_vector<func_decl>::const_iterator it = accessors->begin();
ptr_vector<func_decl>::const_iterator end = accessors->end();
app_ref rec_app(m.mk_app(rec, arg1), m);
ctx.internalize(rec_app, false);
literal is_con(ctx.get_bool_var(rec_app));
for (; it != end; ++it) {
enode* arg;
func_decl * acc1 = *it;
if (acc1 == acc) {
arg = n->get_arg(1);
}
else {
app* acc_app = m.mk_app(acc1, arg1);
ctx.internalize(acc_app, false);
arg = ctx.get_enode(acc_app);
}
app * acc_own = m.mk_app(acc1, own);
assert_eq_axiom(arg, acc_own, is_con);
}
// update_field is identity if 'n' is not created by a matching constructor.
assert_eq_axiom(n, arg1, ~is_con);
}
theory_var theory_datatype::mk_var(enode * n) {
theory_var r = theory::mk_var(n);
theory_var r2 = m_find.mk_var();
@ -150,15 +199,17 @@ namespace smt {
SASSERT(r == static_cast<int>(m_var_data.size()));
m_var_data.push_back(alloc(var_data));
var_data * d = m_var_data[r];
context & ctx = get_context();
ctx.attach_th_var(n, this, r);
if (is_constructor(n)) {
d->m_constructor = n;
get_context().attach_th_var(n, this, r);
assert_accessor_axioms(n);
}
else if (is_update_field(n)) {
assert_update_field_axioms(n);
}
else {
ast_manager & m = get_manager();
context & ctx = get_context();
ctx.attach_th_var(n, this, r);
sort * s = m.get_sort(n->get_owner());
if (m_util.get_datatype_num_constructors(s) == 1) {
func_decl * c = m_util.get_datatype_constructors(s)->get(0);
@ -192,7 +243,7 @@ namespace smt {
ctx.set_var_theory(bv, get_id());
ctx.set_enode_flag(bv, true);
}
if (is_constructor(term)) {
if (is_constructor(term) || is_update_field(term)) {
SASSERT(!is_attached_to_var(e));
// *** We must create a theory variable for each argument that has sort datatype ***
//
@ -478,6 +529,7 @@ namespace smt {
st.update("datatype splits", m_stats.m_splits);
st.update("datatype constructor ax", m_stats.m_assert_cnstr);
st.update("datatype accessor ax", m_stats.m_assert_accessor);
st.update("datatype update ax", m_stats.m_assert_update_field);
}
void theory_datatype::display_var(std::ostream & out, theory_var v) const {

View file

@ -41,7 +41,7 @@ namespace smt {
struct stats {
unsigned m_occurs_check, m_splits;
unsigned m_assert_cnstr, m_assert_accessor;
unsigned m_assert_cnstr, m_assert_accessor, m_assert_update_field;
void reset() { memset(this, 0, sizeof(stats)); }
stats() { reset(); }
};
@ -58,14 +58,17 @@ namespace smt {
bool is_constructor(app * f) const { return m_util.is_constructor(f); }
bool is_recognizer(app * f) const { return m_util.is_recognizer(f); }
bool is_accessor(app * f) const { return m_util.is_accessor(f); }
bool is_update_field(app * f) const { return m_util.is_update_field(f); }
bool is_constructor(enode * n) const { return is_constructor(n->get_owner()); }
bool is_recognizer(enode * n) const { return is_recognizer(n->get_owner()); }
bool is_accessor(enode * n) const { return is_accessor(n->get_owner()); }
bool is_update_field(enode * n) const { return m_util.is_update_field(n->get_owner()); }
void assert_eq_axiom(enode * lhs, expr * rhs, literal antecedent);
void assert_is_constructor_axiom(enode * n, func_decl * c, literal antecedent);
void assert_accessor_axioms(enode * n);
void assert_update_field_axioms(enode * n);
void add_recognizer(theory_var v, enode * recognizer);
void propagate_recognizer(theory_var v, enode * r);
void sign_recognizer_conflict(enode * c, enode * r);