3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-23 09:05:31 +00:00

Merge pull request #2150 from Nils-Becker/master

Logging Support for Theory Solvers
This commit is contained in:
Nikolaj Bjorner 2019-02-27 17:06:31 +01:00 committed by GitHub
commit e79f7ca1fd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
35 changed files with 1051 additions and 171 deletions

View file

@ -89,7 +89,14 @@ app * arith_decl_plugin::mk_numeral(algebraic_numbers::anum const & val, bool is
parameter p(idx, true);
SASSERT(p.is_external());
func_decl * decl = m_manager->mk_const_decl(m_rootv_sym, m_real_decl, func_decl_info(m_family_id, OP_IRRATIONAL_ALGEBRAIC_NUM, 1, &p));
return m_manager->mk_const(decl);
app * r = m_manager->mk_const(decl);
if (log_constant_meaning_prelude(r)) {
am().display_root_smt2(m_manager->trace_stream(), val);
m_manager->trace_stream() << "\n";
}
return r;
}
}
@ -415,6 +422,10 @@ app * arith_decl_plugin::mk_numeral(rational const & val, bool is_int) {
r = m_manager->mk_const(m_manager->mk_const_decl(m_intv_sym, m_int_decl, func_decl_info(m_family_id, OP_NUM, 2, p)));
m_manager->inc_ref(r);
m_small_ints.setx(u_val, r, 0);
if (log_constant_meaning_prelude(r)) {
m_manager->trace_stream() << u_val << "\n";
}
}
return r;
}
@ -425,6 +436,10 @@ app * arith_decl_plugin::mk_numeral(rational const & val, bool is_int) {
r = m_manager->mk_const(m_manager->mk_const_decl(m_realv_sym, m_real_decl, func_decl_info(m_family_id, OP_NUM, 2, p)));
m_manager->inc_ref(r);
m_small_reals.setx(u_val, r, 0);
if (log_constant_meaning_prelude(r)) {
m_manager->trace_stream() << u_val << "\n";
}
}
return r;
}
@ -436,7 +451,14 @@ app * arith_decl_plugin::mk_numeral(rational const & val, bool is_int) {
decl = m_manager->mk_const_decl(m_intv_sym, m_int_decl, func_decl_info(m_family_id, OP_NUM, 2, p));
else
decl = m_manager->mk_const_decl(m_realv_sym, m_real_decl, func_decl_info(m_family_id, OP_NUM, 2, p));
return m_manager->mk_const(decl);
app * r = m_manager->mk_const(decl);
if (log_constant_meaning_prelude(r)) {
val.display_smt2(m_manager->trace_stream());
m_manager->trace_stream() << "\n";
}
return r;
}
func_decl * arith_decl_plugin::mk_num_decl(unsigned num_parameters, parameter const * parameters, unsigned arity) {

View file

@ -28,6 +28,7 @@ Revision History:
#include "ast/ast_smt2_pp.h"
#include "ast/array_decl_plugin.h"
#include "ast/ast_translation.h"
#include "util/z3_version.h"
// -----------------------------------
@ -662,6 +663,23 @@ ast* ast_table::pop_erase() {
//
// -----------------------------------
/**
\brief Checks wether a log is being generated and, if necessary, adds the beginning of an "[attach-meaning]" line
to that log. The theory solver should add some description of the meaning of the term in terms of the theory's
internal reasoning to the end of the line and insert a line break.
\param a the term that should be described.
\return true if a log is being generated, false otherwise.
*/
bool decl_plugin::log_constant_meaning_prelude(app * a) {
if (m_manager->has_trace_stream()) {
m_manager->trace_stream() << "[attach-meaning] #" << a->get_id() << " " << m_manager->get_family_name(m_family_id).str() << " ";
return true;
}
return false;
}
func_decl * decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters, parameter const * parameters,
unsigned num_args, expr * const * args, sort * range) {
ptr_buffer<sort> sorts;
@ -1347,6 +1365,7 @@ ast_manager::ast_manager(proof_gen_mode m, char const * trace_file, bool is_form
if (trace_file) {
m_trace_stream = alloc(std::fstream, trace_file, std::ios_base::out);
m_trace_stream_owner = true;
*m_trace_stream << "[tool-version] Z3 " << Z3_MAJOR_VERSION << "." << Z3_MINOR_VERSION << "." << Z3_BUILD_NUMBER << "\n";
}
if (!is_format_manager)
@ -2183,7 +2202,14 @@ app * ast_manager::mk_app_core(func_decl * decl, unsigned num_args, expr * const
}
if (m_trace_stream && r == new_node) {
*m_trace_stream << "[mk-app] #" << r->get_id() << " ";
if (is_proof(r)) {
if (decl == mk_func_decl(m_basic_family_id, PR_UNDEF, 0, nullptr, 0, static_cast<expr * const *>(nullptr)))
return r;
*m_trace_stream << "[mk-proof] #";
} else {
*m_trace_stream << "[mk-app] #";
}
*m_trace_stream << r->get_id() << " ";
if (r->get_num_args() == 0 && r->get_decl()->get_name() == "int") {
ast_ll_pp(*m_trace_stream, *this, r);
}
@ -2329,7 +2355,7 @@ var * ast_manager::mk_var(unsigned idx, sort * s) {
var * r = register_node(new_node);
if (m_trace_stream && r == new_node) {
*m_trace_stream << "[mk-var] #" << r->get_id() << "\n";
*m_trace_stream << "[mk-var] #" << r->get_id() << " " << idx << "\n";
}
return r;
}
@ -2458,6 +2484,11 @@ quantifier * ast_manager::mk_quantifier(quantifier_kind k, unsigned num_decls, s
if (m_trace_stream && r == new_node) {
trace_quant(*m_trace_stream, r);
*m_trace_stream << "[attach-var-names] #" << r->get_id();
for (unsigned i = 0; i < num_decls; ++i) {
*m_trace_stream << " (|" << decl_names[num_decls - i - 1].str() << "| ; |" << decl_sorts[num_decls - i -1]->get_name().str() << "|)";
}
*m_trace_stream << "\n";
}
return r;

View file

@ -998,6 +998,17 @@ protected:
virtual void inherit(decl_plugin* other_p, ast_translation& ) { }
/**
\brief Checks wether a log is being generated and, if necessary, adds the beginning of an "[attach-meaning]" line
to that log. The theory solver should add some description of the meaning of the term in terms of the theory's
internal reasoning to the end of the line and insert a line break.
\param a the term that should be described.
\return true if a log is being generated, false otherwise.
*/
bool log_constant_meaning_prelude(app * a);
friend class ast_manager;
public:

View file

@ -868,7 +868,21 @@ app * bv_util::mk_numeral(rational const & val, sort* s) const {
app * bv_util::mk_numeral(rational const & val, unsigned bv_size) const {
parameter p[2] = { parameter(val), parameter(static_cast<int>(bv_size)) };
return m_manager.mk_app(get_fid(), OP_BV_NUM, 2, p, 0, nullptr);
app * r = m_manager.mk_app(get_fid(), OP_BV_NUM, 2, p, 0, nullptr);
if (m_plugin->log_constant_meaning_prelude(r)) {
if (bv_size % 4 == 0) {
m_manager.trace_stream() << "#x";
val.display_hex(m_manager.trace_stream(), bv_size);
m_manager.trace_stream() << "\n";
} else {
m_manager.trace_stream() << "#b";
val.display_bin(m_manager.trace_stream(), bv_size);
m_manager.trace_stream() << "\n";
}
}
return r;
}
sort * bv_util::mk_sort(unsigned bv_size) {

View file

@ -126,6 +126,7 @@ inline func_decl * get_div0_decl(ast_manager & m, func_decl * decl) {
}
class bv_decl_plugin : public decl_plugin {
friend class bv_util;
protected:
symbol m_bv_sym;
symbol m_concat_sym;
@ -432,7 +433,53 @@ public:
app * mk_bvsmul_no_udfl(expr* m, expr* n) { return m_manager.mk_app(get_fid(), OP_BSMUL_NO_UDFL, n, m); }
app * mk_bvumul_no_ovfl(expr* m, expr* n) { return m_manager.mk_app(get_fid(), OP_BUMUL_NO_OVFL, n, m); }
app * mk_bv(unsigned n, expr* const* es) { return m_manager.mk_app(get_fid(), OP_MKBV, n, es); }
private:
void log_bv_from_exprs(app * r, unsigned n, expr* const* es) {
if (m_manager.has_trace_stream()) {
for (unsigned i = 0; i < n; ++i) {
if (!m_manager.is_true(es[i]) && !m_manager.is_false(es[i]))
return;
}
if (m_plugin->log_constant_meaning_prelude(r)) {
if (n % 4 == 0) {
m_manager.trace_stream() << " #x";
m_manager.trace_stream() << std::hex;
uint8_t hexDigit = 0;
unsigned curLength = (4 - n % 4) % 4;
for (unsigned i = 0; i < n; ++i) {
hexDigit <<= 1;
++curLength;
if (m_manager.is_true(es[i])) {
hexDigit |= 1;
}
if (curLength == 4) {
m_manager.trace_stream() << hexDigit;
hexDigit = 0;
}
}
m_manager.trace_stream() << std::dec;
} else {
m_manager.trace_stream() << " #b";
for (unsigned i = 0; i < n; ++i) {
m_manager.trace_stream() << (m_manager.is_true(es[i]) ? 1 : 0);
}
}
m_manager.trace_stream() << ")\n";
}
}
}
public:
app * mk_bv(unsigned n, expr* const* es) {
app * r = m_manager.mk_app(get_fid(), OP_MKBV, n, es);
log_bv_from_exprs(r, n, es);
return r;
}
};

View file

@ -453,6 +453,48 @@ namespace datatype {
}
}
void plugin::log_axiom_definitions(symbol const& s, sort * new_sort) {
symbol const& family_name = m_manager->get_family_name(get_family_id());
for (constructor const* c : *m_defs[s]) {
func_decl_ref f = c->instantiate(new_sort);
const unsigned num_args = f->get_arity();
if (num_args == 0) continue;
for (unsigned i = 0; i < num_args; ++i) {
m_manager->trace_stream() << "[mk-var] " << family_name << "#" << m_id_counter << " " << i << "\n";
++m_id_counter;
}
const unsigned constructor_id = m_id_counter;
m_manager->trace_stream() << "[mk-app] " << family_name << "#" << constructor_id << " " << f->get_name();
for (unsigned i = 0; i < num_args; ++i) {
m_manager->trace_stream() << " " << family_name << "#" << constructor_id - num_args + i;
}
m_manager->trace_stream() << "\n";
++m_id_counter;
m_manager->trace_stream() << "[mk-app] " << family_name << "#" << m_id_counter << " pattern " << family_name << "#" << constructor_id << "\n";
++m_id_counter;
m_axiom_bases.insert(f->get_name(), constructor_id + 4);
std::ostringstream var_sorts;
for (accessor const* a : *c) {
var_sorts << " (;" << a->range()->get_name() << ")";
}
std::string var_description = var_sorts.str();
unsigned i = 0;
for (accessor const* a : *c) {
func_decl_ref acc = a->instantiate(new_sort);
m_manager->trace_stream() << "[mk-app] " << family_name << "#" << m_id_counter << " " << acc->get_name() << " " << family_name << "#" << constructor_id << "\n";
++m_id_counter;
m_manager->trace_stream() << "[mk-app] " << family_name << "#" << m_id_counter << " = " << family_name << "#" << constructor_id - num_args + i
<< " " << family_name << "#" << m_id_counter - 1 << "\n";
++m_id_counter;
m_manager->trace_stream() << "[mk-quant] " << family_name << "#" << m_id_counter << " constructor_accessor_axiom " << family_name << "#" << constructor_id + 1
<< " " << family_name << "#" << m_id_counter - 1 << "\n";
m_manager->trace_stream() << "[attach-var-names] " << family_name << "#" << m_id_counter << var_description << "\n";
++m_id_counter;
++i;
}
}
}
bool plugin::mk_datatypes(unsigned num_datatypes, def * const * datatypes, unsigned num_params, sort* const* sort_params, sort_ref_vector & new_sorts) {
begin_def_block();
for (unsigned i = 0; i < num_datatypes; ++i) {
@ -470,6 +512,9 @@ namespace datatype {
sort_ref_vector ps(*m_manager);
for (symbol const& s : m_def_block) {
new_sorts.push_back(m_defs[s]->instantiate(ps));
if (m_manager->has_trace_stream()) {
log_axiom_definitions(s, new_sorts.back());
}
}
return true;
}

View file

@ -206,13 +206,17 @@ namespace datatype {
class plugin : public decl_plugin {
mutable scoped_ptr<util> m_util;
map<symbol, def*, symbol_hash_proc, symbol_eq_proc> m_defs;
map<symbol, unsigned, symbol_hash_proc, symbol_eq_proc> m_axiom_bases;
unsigned m_id_counter;
svector<symbol> m_def_block;
unsigned m_class_id;
void inherit(decl_plugin* other_p, ast_translation& tr) override;
void log_axiom_definitions(symbol const& s, sort * new_sort);
public:
plugin(): m_class_id(0) {}
plugin(): m_id_counter(0), m_class_id(0) {}
~plugin() override;
void finalize() override;
@ -247,6 +251,7 @@ namespace datatype {
def const& get_def(sort* s) const { return *(m_defs[datatype_name(s)]); }
def& get_def(symbol const& s) { return *(m_defs[s]); }
bool is_declared(sort* s) const { return m_defs.contains(datatype_name(s)); }
unsigned get_axiom_base_id(symbol const& s) { return m_axiom_bases[s]; }
util & u() const;
private:

View file

@ -92,7 +92,14 @@ func_decl * fpa_decl_plugin::mk_numeral_decl(mpf const & v) {
}
app * fpa_decl_plugin::mk_numeral(mpf const & v) {
return m_manager->mk_const(mk_numeral_decl(v));
app * r = m_manager->mk_const(mk_numeral_decl(v));
if (log_constant_meaning_prelude(r)) {
m_fm.display_smt2(m_manager->trace_stream(), v, false);
m_manager->trace_stream() << "\n";
}
return r;
}
bool fpa_decl_plugin::is_numeral(expr * n, mpf & val) {

View file

@ -562,6 +562,29 @@ struct th_rewriter_cfg : public default_rewriter_cfg {
br_status reduce_app(func_decl * f, unsigned num, expr * const * args, expr_ref & result, proof_ref & result_pr) {
result_pr = nullptr;
br_status st = reduce_app_core(f, num, args, result);
if (st != BR_FAILED && m().has_trace_stream()) {
family_id fid = f->get_family_id();
if (fid == m_b_rw.get_fid()) {
decl_kind k = f->get_decl_kind();
if (k == OP_EQ) {
SASSERT(num == 2);
fid = m().get_sort(args[0])->get_family_id();
}
else if (k == OP_ITE) {
SASSERT(num == 3);
fid = m().get_sort(args[1])->get_family_id();
}
}
app_ref tmp(m());
tmp = m().mk_app(f, num, args);
m().trace_stream() << "[inst-discovered] theory-solving " << static_cast<void *>(nullptr) << " " << m().get_family_name(fid) << "# ; #" << tmp->get_id() << "\n";
tmp = m().mk_eq(tmp, result);
m().trace_stream() << "[instance] " << static_cast<void *>(nullptr) << " #" << tmp->get_id() << "\n";
m().trace_stream() << "[attach-enode] #" << tmp->get_id() << " 0\n";
m().trace_stream() << "[end-of-instance]\n";
}
if (st != BR_DONE && st != BR_FAILED) {
CTRACE("th_rewriter_step", st != BR_FAILED,
tout << f->get_name() << "\n";