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:
commit
e79f7ca1fd
35 changed files with 1051 additions and 171 deletions
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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";
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue