3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-24 01:25:31 +00:00
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2019-05-14 19:05:40 +02:00
parent 4d05a11144
commit 4fcc4d07ae
12 changed files with 139 additions and 49 deletions

View file

@ -535,14 +535,14 @@ namespace smt {
}
void context::internalize_lambda(quantifier * q) {
UNREACHABLE();
#if 0
UNREACHABLE();
#else
TRACE("internalize_quantifier", tout << mk_pp(q, m_manager) << "\n";);
SASSERT(is_lambda(q));
app_ref lam_name(m_manager.mk_fresh_const("lambda", m_manager.get_sort(q)), m_manager);
enode * e = mk_enode(lam_name, true, false, false);
expr_ref eq(m_manager), lam_app(m_manager);
app_ref eq(m_manager), lam_app(m_manager);
expr_ref_vector vars(m_manager);
vars.push_back(lam_name);
unsigned sz = q->get_num_decls();
@ -553,9 +553,11 @@ namespace smt {
lam_app = autil.mk_select(vars.size(), vars.c_ptr());
eq = m_manager.mk_eq(lam_app, q->get_expr());
quantifier_ref fa(m_manager);
expr * patterns[1] = { m_manager.mk_pattern(lam_name) };
expr * patterns[1] = { m_manager.mk_pattern(lam_app) };
fa = m_manager.mk_forall(sz, q->get_decl_sorts(), q->get_decl_names(), eq, 0, m_manager.lambda_def_qid(), symbol::null, 1, patterns);
internalize_quantifier(fa, true);
if (!e_internalized(lam_name)) internalize_uninterpreted(lam_name);
m_app2enode.setx(q->get_id(), get_enode(lam_name), nullptr);
#endif
}
@ -938,7 +940,7 @@ namespace smt {
e->mark_as_interpreted();
TRACE("mk_var_bug", tout << "mk_enode: " << id << "\n";);
TRACE("generation", tout << "mk_enode: " << id << " " << generation << "\n";);
m_app2enode.setx(id, e, 0);
m_app2enode.setx(id, e, nullptr);
m_e_internalized_stack.push_back(n);
m_trail_stack.push_back(&m_mk_enode_trail);
m_enodes.push_back(e);

View file

@ -272,9 +272,7 @@ namespace smt {
}
// traverse all enodes that are associated with fresh values...
unsigned sz = roots.size();
for (unsigned i = 0; i < sz; i++) {
enode * r = roots[i];
for (enode* r : roots) {
model_value_proc * proc = root2proc[r];
SASSERT(proc);
if (!proc->is_fresh())
@ -282,9 +280,7 @@ namespace smt {
process_source(source(r), roots, root2proc, colors, already_traversed, todo, sorted_sources);
}
sz = roots.size();
for (unsigned i = 0; i < sz; i++) {
enode * r = roots[i];
for (enode * r : roots) {
process_source(source(r), roots, root2proc, colors, already_traversed, todo, sorted_sources);
}
}

View file

@ -230,6 +230,7 @@ namespace smt {
m_stats.m_num_extensionality++;
}
bool theory_array::internalize_atom(app * atom, bool) {
return internalize_term(atom);
}
@ -297,12 +298,11 @@ namespace smt {
void theory_array::new_eq_eh(theory_var v1, theory_var v2) {
m_find.merge(v1, v2);
#if 0
if (is_lambda(get_enode(v1)->get_owner()) ||
is_lambda(get_enode(v2)->get_owner())) {
instantiate_extensionality(get_enode(v1), get_enode(v2));
enode* n1 = get_enode(v1), *n2 = get_enode(v2);
if (n1->get_owner()->get_decl()->is_lambda() ||
n2->get_owner()->get_decl()->is_lambda()) {
assert_congruent(n1, n2);
}
#endif
}
void theory_array::new_diseq_eh(theory_var v1, theory_var v2) {

View file

@ -88,6 +88,7 @@ namespace smt {
bool instantiate_axiom2b(enode * select, enode * store);
void instantiate_axiom1(enode * store);
void instantiate_extensionality(enode * a1, enode * a2);
void instantiate_congruent(enode * a1, enode * a2);
bool instantiate_axiom2b_for(theory_var v);
virtual final_check_status assert_delayed_axioms();

View file

@ -300,6 +300,20 @@ namespace smt {
m_extensionality_todo.push_back(std::make_pair(n1, n2));
return true;
}
void theory_array_base::assert_congruent(enode * a1, enode * a2) {
TRACE("array", tout << "congruent: #" << a1->get_owner_id() << " #" << a2->get_owner_id() << "\n";);
SASSERT(is_array_sort(a1));
SASSERT(is_array_sort(a2));
context & ctx = get_context();
if (a1->get_owner_id() > a2->get_owner_id())
std::swap(a1, a2);
enode * nodes[2] = { a1, a2 };
if (!ctx.add_fingerprint(this, 1, 2, nodes))
return; // axiom was already instantiated
m_congruent_todo.push_back(std::make_pair(a1, a2));
}
void theory_array_base::assert_extensionality_core(enode * n1, enode * n2) {
app * e1 = n1->get_owner();
@ -338,8 +352,59 @@ namespace smt {
if (m.has_trace_stream()) m.trace_stream() << "[end-of-instance]\n";
}
/**
\brief assert n1 = n2 => forall vars . (n1 vars) = (n2 vars)
*/
void theory_array_base::assert_congruent_core(enode * n1, enode * n2) {
app * e1 = n1->get_owner();
app * e2 = n2->get_owner();
context & ctx = get_context();
ast_manager & m = get_manager();
sort* s = m.get_sort(e1);
unsigned dimension = get_array_arity(s);
literal n1_eq_n2 = mk_eq(e1, e2, true);
ctx.mark_as_relevant(n1_eq_n2);
expr_ref_vector args1(m), args2(m);
expr_ref f1 = instantiate_lambda(e1);
expr_ref f2 = instantiate_lambda(e2);
args1.push_back(f1);
args2.push_back(f2);
svector<symbol> names;
sort_ref_vector sorts(m);
for (unsigned i = 0; i < dimension; i++) {
sort * srt = get_array_domain(s, i);
sorts.push_back(srt);
names.push_back(symbol(i));
expr * k = m.mk_var(dimension - i - 1, srt);
args1.push_back(k);
args2.push_back(k);
}
expr * sel1 = mk_select(dimension+1, args1.c_ptr());
expr * sel2 = mk_select(dimension+1, args2.c_ptr());
expr * eq = m.mk_eq(sel1, sel2);
expr_ref q(m.mk_forall(dimension, sorts.c_ptr(), names.c_ptr(), eq), m);
ctx.get_rewriter()(q);
if (!ctx.b_internalized(q)) {
ctx.internalize(q, true);
}
literal fa_eq = ctx.get_literal(q);
ctx.mark_as_relevant(fa_eq);
assert_axiom(~n1_eq_n2, fa_eq);
}
expr_ref theory_array_base::instantiate_lambda(app* e) {
ast_manager& m = get_manager();
quantifier * q = m.is_lambda_def(e->get_decl());
expr_ref f(e, m);
if (q) {
var_subst sub(m, false);
f = sub(q, e->get_num_args(), e->get_args());
}
return f;
}
bool theory_array_base::can_propagate() {
return !m_axiom1_todo.empty() || !m_axiom2_todo.empty() || !m_extensionality_todo.empty();
return !m_axiom1_todo.empty() || !m_axiom2_todo.empty() || !m_extensionality_todo.empty() || !m_congruent_todo.empty();
}
void theory_array_base::propagate() {
@ -352,7 +417,10 @@ namespace smt {
m_axiom2_todo.reset();
for (unsigned i = 0; i < m_extensionality_todo.size(); i++)
assert_extensionality_core(m_extensionality_todo[i].first, m_extensionality_todo[i].second);
for (unsigned i = 0; i < m_congruent_todo.size(); i++)
assert_congruent_core(m_congruent_todo[i].first, m_congruent_todo[i].second);
m_extensionality_todo.reset();
m_congruent_todo.reset();
}
}
@ -522,6 +590,7 @@ namespace smt {
m_axiom1_todo.reset();
m_axiom2_todo.reset();
m_extensionality_todo.reset();
m_congruent_todo.reset();
}

View file

@ -66,6 +66,7 @@ namespace smt {
ptr_vector<enode> m_axiom1_todo;
enode_pair_vector m_axiom2_todo;
enode_pair_vector m_extensionality_todo;
enode_pair_vector m_congruent_todo;
scoped_ptr<theory_array_bapa> m_bapa;
void assert_axiom(unsigned num_lits, literal * lits);
@ -79,6 +80,10 @@ namespace smt {
void assert_extensionality_core(enode * a1, enode * a2);
bool assert_extensionality(enode * a1, enode * a2);
expr_ref instantiate_lambda(app* e);
void assert_congruent_core(enode * a1, enode * a2);
void assert_congruent(enode * a1, enode * a2);
// --------------------------------------------------
// Array sort -> extensionality skolems
//

View file

@ -3429,7 +3429,7 @@ public:
}
app_ref mk_obj(theory_var v) {
lp::var_index vi = m_theory_var2var_index[v];
lp::var_index vi = get_var_index(v);
bool is_int = a.is_int(get_enode(v)->get_owner());
if (m_solver->is_term(vi)) {
return mk_term(m_solver->get_term(vi), is_int);