z3-z3-4.13.0.src.model.model_smt2_pp.cpp Maven / Gradle / Ivy
The newest version!
/*++
Copyright (c) 2011 Microsoft Corporation
Module Name:
model_smt2_pp.cpp
Abstract:
Pretty printer for models using SMT2 format.
Author:
Leonardo de Moura (leonardo)
Revision History:
--*/
#include
#include "model/model_smt2_pp.h"
#include "ast/ast_smt2_pp.h"
#include "ast/func_decl_dependencies.h"
#include "ast/recfun_decl_plugin.h"
#include "ast/pp.h"
using namespace format_ns;
static void pp_indent(std::ostream & out, unsigned indent) {
for (unsigned i = 0; i < indent; i++)
out << " ";
}
static unsigned pp_symbol(std::ostream & out, symbol const & s) {
if (is_smt2_quoted_symbol(s)) {
std::string str = mk_smt2_quoted_symbol(s);
out << str;
return static_cast(str.length());
}
else if (s.is_numerical()) {
std::string str = s.str();
out << str;
return static_cast(str.length());
}
else {
out << s.bare_str();
return static_cast(strlen(s.bare_str()));
}
}
#define TAB_SZ 2
static void pp_uninterp_sorts(std::ostream & out, ast_printer_context & ctx, model_core const & md, unsigned indent) {
ast_manager & m = ctx.get_ast_manager();
ptr_buffer f_conds;
unsigned num = md.get_num_uninterpreted_sorts();
for (unsigned i = 0; i < num; i++) {
sort * s = md.get_uninterpreted_sort(i);
ptr_vector const & u = md.get_universe(s);
std::ostringstream buffer;
buffer << "universe for ";
ctx.display(buffer, s, 13);
buffer << ":\n";
pp_indent(buffer, TAB_SZ);
for (expr* e : u) {
SASSERT(is_app(e));
app * c = to_app(e);
pp_symbol(buffer, c->get_decl()->get_name());
buffer << " ";
}
buffer << "\n-----------";
std::string buffer_str = std::move(buffer).str();
unsigned len = static_cast(buffer_str.length());
pp_indent(out, indent);
out << ";; ";
for (unsigned i = 0; i < len; i++) {
char c = buffer_str[i];
if (c == '\n') {
out << "\n";
pp_indent(out, indent);
out << ";; ";
}
else {
out << c;
}
}
out << "\n";
pp_indent(out, indent);
out << ";; definitions for universe elements:\n";
for (expr * e : u) {
app * c = to_app(e);
pp_indent(out, indent);
out << "(declare-fun ";
unsigned len = pp_symbol(out, c->get_decl()->get_name());
out << " () ";
ctx.display(out, c->get_decl()->get_range(), indent + len + 16);
out << ")\n";
}
pp_indent(out, indent);
out << ";; cardinality constraint:\n";
f_conds.reset();
format * var = mk_string(m, "x");
for (expr* e : u) {
app * c = to_app(e);
symbol csym = c->get_decl()->get_name();
std::string cname;
if (is_smt2_quoted_symbol(csym))
cname = mk_smt2_quoted_symbol(csym);
else
cname = csym.str();
format * c_args[2] = { var, mk_string(m, cname) };
f_conds.push_back(mk_seq1(m, c_args, c_args+2, f2f(), "="));
}
SASSERT(!f_conds.empty());
format * f_cond;
if (f_conds.size() > 1)
f_cond = mk_seq1(m, f_conds.begin(), f_conds.end(), f2f(), "or");
else
f_cond = f_conds[0];
format_ref f_s(fm(m));
ctx.pp(s, f_s);
format * f_args[2] = { mk_compose(m,
mk_string(m, "((x "),
mk_indent(m, 4, mk_compose(m, f_s.get(), mk_string(m, "))")))),
f_cond };
format_ref f_card(fm(m));
f_card = mk_indent(m, indent, mk_seq1(m, f_args, f_args+2, f2f(), "forall"));
pp_indent(out, indent);
pp(out, f_card, m);
out << "\n";
pp_indent(out, indent);
out << ";; -----------\n";
}
}
static void pp_consts(std::ostream & out, ast_printer_context & ctx, model_core const & md, unsigned indent) {
unsigned num = md.get_num_constants();
for (unsigned i = 0; i < num; i++) {
func_decl * c = md.get_constant(i);
expr * c_i = md.get_const_interp(c);
pp_indent(out, indent);
out << "(define-fun ";
unsigned len = pp_symbol(out, c->get_name());
out << " () ";
ctx.display(out, c->get_range(), indent + len + 16);
out << "\n";
pp_indent(out, indent + TAB_SZ);
ctx.display(out, c_i);
out << ")\n";
}
}
void sort_fun_decls(ast_manager & m, model_core const & md, ptr_buffer & result) {
func_decl_set visited;
ptr_vector todo;
unsigned sz = md.get_num_functions();
for (unsigned i = 0; i < sz; i++) {
func_decl * f = md.get_function(i);
if (visited.contains(f))
continue;
visited.insert(f);
todo.push_back(f);
while (!todo.empty()) {
func_decl * curr = todo.back();
func_interp * curr_i = md.get_func_interp(curr);
SASSERT(curr_i != 0);
if (!curr_i->is_partial()) {
func_decl_set deps;
bool all_visited = true;
collect_func_decls(m, curr_i->get_else(), deps);
for (func_decl * d : deps) {
if (d->get_arity() > 0 && md.has_interpretation(d) && !visited.contains(d)) {
todo.push_back(d);
visited.insert(d);
all_visited = false;
}
}
if (!all_visited)
continue;
}
todo.pop_back();
result.push_back(curr);
}
}
}
static void pp_funs(std::ostream & out, ast_printer_context & ctx, model_core const & md, unsigned indent) {
ast_manager & m = ctx.get_ast_manager();
recfun::util recfun_util(m);
sbuffer var_names;
ptr_buffer f_var_names;
ptr_buffer f_arg_decls;
ptr_buffer f_entries;
ptr_buffer f_entry_conds;
ptr_buffer func_decls;
sort_fun_decls(m, md, func_decls);
for (func_decl * f : func_decls) {
if (recfun_util.is_defined(f) && !recfun_util.is_generated(f))
continue;
if (!m.is_considered_uninterpreted(f))
continue;
func_interp * f_i = md.get_func_interp(f);
SASSERT(f->get_arity() == f_i->get_arity());
format_ref body(fm(m));
var_names.reset();
if (f_i->is_partial()) {
body = mk_string(m, "#unspecified");
for (unsigned j = 0; j < f->get_arity(); j++) {
var_names.push_back(symbol("x!" + std::to_string(j+1)));
}
}
else {
ctx.pp(f_i->get_else(), f->get_arity(), "x", body, var_names);
}
TRACE("model_smt2_pp", for (unsigned i = 0; i < var_names.size(); i++) tout << var_names[i] << "\n";);
f_var_names.reset();
for (auto const& vn : var_names)
f_var_names.push_back(mk_string(m, vn.bare_str()));
f_arg_decls.reset();
for (unsigned i = 0; i < f->get_arity(); i++) {
format_ref f_domain(fm(m));
ctx.pp(f->get_domain(i), f_domain);
format * args[2] = { f_var_names[i], f_domain.get() };
f_arg_decls.push_back(mk_seq5(m, args, args+2, f2f()));
}
format * f_domain = mk_seq5(m, f_arg_decls.begin(), f_arg_decls.end(), f2f());
format_ref f_range(fm(m));
ctx.pp(f->get_range(), f_range);
if (f_i->num_entries() > 0) {
f_entries.reset();
for (unsigned i = 0; i < f_i->num_entries(); i++) {
func_entry const * e = f_i->get_entry(i);
f_entry_conds.reset();
for (unsigned j = 0; j < f->get_arity(); j++) {
format_ref f_arg(fm(m));
ctx.pp(e->get_arg(j), f_arg);
format * eq_args[2] = { f_var_names[j], f_arg.get() };
f_entry_conds.push_back(mk_seq1(m, eq_args, eq_args+2, f2f(), "="));
}
format * f_entry_cond;
SASSERT(!f_entry_conds.empty());
if (f_entry_conds.size() > 1)
f_entry_cond = mk_seq1(m, f_entry_conds.begin(), f_entry_conds.end(), f2f(), "and");
else
f_entry_cond = f_entry_conds[0];
format_ref f_result(fm(m));
ctx.pp(e->get_result(), f_result);
if (i > 0)
f_entries.push_back(mk_line_break(m));
f_entries.push_back(mk_group(m, mk_compose(m,
mk_string(m, "(ite "),
mk_indent(m, 5, f_entry_cond),
mk_indent(m, TAB_SZ, mk_compose(m,
mk_line_break(m),
f_result.get())))));
}
f_entries.push_back(mk_indent(m, TAB_SZ, mk_compose(m,
mk_line_break(m),
body.get())));
for (unsigned i = 0; i < f_i->num_entries(); i++)
f_entries.push_back(mk_string(m, ")"));
body = mk_compose(m, f_entries.size(), f_entries.data());
}
format_ref def(fm(m));
std::string fname;
if (is_smt2_quoted_symbol(f->get_name()))
fname = mk_smt2_quoted_symbol(f->get_name());
else
fname = f->get_name().str();
def = mk_indent(m, indent, mk_compose(m,
mk_compose(m,
mk_string(m, "(define-fun "),
mk_string(m, fname),
mk_string(m, " "),
mk_compose(m,
f_domain,
mk_string(m, " "),
f_range)),
mk_indent(m, TAB_SZ, mk_compose(m,
mk_line_break(m),
body.get(),
mk_string(m, ")")))));
pp_indent(out, indent);
pp(out, def.get(), m);
out << "\n";
}
}
void model_smt2_pp(std::ostream & out, ast_printer_context & ctx, model_core const & m, unsigned indent) {
pp_uninterp_sorts(out, ctx, m, indent);
pp_consts(out, ctx, m, indent);
pp_funs(out, ctx, m, indent);
}
void model_smt2_pp(std::ostream & out, ast_manager & m, model_core const & md, unsigned indent) {
scoped_ptr ctx;
ctx = mk_simple_ast_printer_context(m);
pp_uninterp_sorts(out, *(ctx.get()), md, indent);
pp_consts(out, *(ctx.get()), md, indent);
pp_funs(out, *(ctx.get()), md, indent);
}
std::ostream& operator<<(std::ostream& out, model_core const& m) {
model_smt2_pp(out, m.get_manager(), m, 0);
return out;
}