z3-z3-4.12.6.src.model.model_core.cpp Maven / Gradle / Ivy
/*++
Copyright (c) 2011 Microsoft Corporation
Module Name:
model_core.cpp
Abstract:
Base class for models.
Author:
Leonardo de Moura (leonardo) 2011-04-30.
Revision History:
--*/
#include "model/model_core.h"
#include "ast/ast_pp.h"
model_core::~model_core() {
for (auto & kv : m_interp) {
m.dec_ref(kv.m_key);
m.dec_ref(kv.m_value.second);
}
for (auto & kv : m_finterp) {
m.dec_ref(kv.m_key);
dealloc(kv.m_value);
}
}
bool model_core::eval(func_decl* f, expr_ref & r) const {
if (f->get_arity() == 0) {
r = get_const_interp(f);
return r != 0;
}
else {
func_interp * fi = get_func_interp(f);
if (fi != nullptr) {
r = fi->get_interp();
return r != 0;
}
return false;
}
}
void model_core::register_decl(func_decl * d, expr * v) {
if (d->get_arity() > 0) {
func_interp* fi = alloc(func_interp, m, d->get_arity());
fi->set_else(v);
register_decl(d, fi);
return;
}
TRACE("model", tout << "register " << d->get_name() << "\n";
if (v) tout << mk_pp(v, m) << "\n";
);
i_expr v0(0, nullptr);
auto& value = m_interp.insert_if_not_there(d, v0);
if (value == v0) {
// new entry
m.inc_ref(d);
m.inc_ref(v);
value.second = v;
value.first = m_const_decls.size();
m_decls.push_back(d);
m_const_decls.push_back(d);
}
else {
// replacing entry
m.inc_ref(v);
m.dec_ref(value.second);
value.second = v;
}
}
void model_core::register_decl(func_decl * d, func_interp * fi) {
func_interp* old_fi = update_func_interp(d, fi);
dealloc(old_fi);
}
func_interp* model_core::update_func_interp(func_decl* d, func_interp* fi) {
TRACE("model_verbose", tout << "register " << d->get_name() << "\n";);
SASSERT(d->get_arity() > 0);
SASSERT(&fi->m() == &m);
func_interp* old_fi = nullptr;
auto& value = m_finterp.insert_if_not_there(d, nullptr);
if (value == nullptr) {
// new entry
m_decls.push_back(d);
m_func_decls.push_back(d);
m.inc_ref(d);
value = fi;
}
else {
// replacing entry
old_fi = value;
value = fi;
}
return old_fi;
}
void model_core::unregister_decl(func_decl * d) {
decl2expr::obj_map_entry * ec = m_interp.find_core(d);
if (ec) {
auto k = ec->get_data().m_key;
auto v = ec->get_data().m_value;
m_const_decls[v.first] = m_const_decls.back();
m_interp[m_const_decls.back()].first = v.first;
m_const_decls.pop_back();
m_interp.remove(d);
m_decls.erase(d);
m.dec_ref(k);
m.dec_ref(v.second);
return;
}
decl2finterp::obj_map_entry * ef = m_finterp.find_core(d);
if (ef) {
auto k = ef->get_data().m_key;
auto v = ef->get_data().m_value;
m_finterp.remove(d);
m_func_decls.erase(d);
m_decls.erase(d);
m.dec_ref(k);
dealloc(v);
}
}
void model_core::add_lambda_defs() {
unsigned sz = get_num_decls();
for (unsigned i = sz; i-- > 0; ) {
func_decl* f = get_decl(i);
quantifier* q = m.is_lambda_def(f);
if (!q)
continue;
if (f->get_arity() > 0) {
func_interp* fi = alloc(func_interp, m, f->get_arity());
fi->set_else(q);
register_decl(f, fi);
}
else
register_decl(f, q);
}
}