Closed CodiBurley closed 7 years ago
Z3 does not keep a symbol or function table, but only an AST table. This is however not accessible from the outside. Instead I would recommend to simply walk the expression that was read from the SMT2 file to collect the function symbols that appear in it; technically, this is only a tiny bit less efficient than walking the internal AST table. For instance, something like the following function lets us find all the predicates (func_decls with Boolean range):
void collect_fds(expr & e, vector<func_decl> & fds) {
if (e.is_app()) {
func_decl fd = e.decl();
if (fd.range().is_bool())
fds.push_back(fd);
for (unsigned i = 0; i < e.num_args(); i++)
collect_fds(e.arg(i), fds);
}
else if (e.is_quantifier())
collect_fds(e.body(), fds);
}
and we could use that like so:
Z3_ast ast = Z3_parse_smtlib2_file(c, filename.c_str(), 0, 0, 0, 0, 0, 0);
expr e(c, ast);
vector<func_decl> my_fds;
collect_fds(e, my_fds);
We also recently added
c.parse_file(filename.c_str())
to avoid the more awkward Z3_parse_smtlib2_file call.
@wintersteiger Thank you, this describes how I could get function declarations and such very well. Is there an easy way you know of to utilize the constructors and accessors created by the declare-datatypes command?
(declare-datatypes () ((Person (person (name String)))))
You can access all this information from the func_decl parameters, but it is very low level so essentially a nonstarter. The file datatype_decl_plugin describes the format and implements helper functions you would have to replicate.
Is your issue resolved?
Sorry for the delayed response.
@NikolajBjorner I took your advice and looked into reimplementing some of the helper functions in datatype_decl_plugin. In particular I looked into reimplementing
func_decl * datatype_util::get_constructor(sort * ty, unsigned c_id)
.
Im running into issues with this call
(func_decl * d = m_manager.mk_func_decl(m_family_id, OP_DT_CONSTRUCTOR, 2, p, domain.size(), domain.c_ptr());
) inside get_constructor. I think that this function is what does the work in regards to getting a reference to the constructor function for the datatype that I declare in an smt2 and load in using the api. I'm having problems with it because I do not have access to the ast_manager m_manager or any ast manager that I know of, through the api. I tried replacing this in some way with just a call to Z3_mk_func_decl but that did not seem to get an actual reference to the function and instead just created a new function declaration.
I really appreciate your help so far, Thanks!
I am so sorry for miss-leading you. There are in fact API methods for accessing constructors. You should be able to just use these to access the relevant information.
unsigned Z3_API Z3_get_datatype_sort_num_constructors(
Z3_context c, Z3_sort t);
Z3_func_decl Z3_API Z3_get_datatype_sort_constructor(
Z3_context c, Z3_sort t, unsigned idx);
Z3_func_decl Z3_API Z3_get_datatype_sort_constructor_accessor(Z3_context c,
Z3_sort t,
unsigned idx_c,
unsigned idx_a);
They are a bit esotheric, so they havent' found their way into the C++ API, but it should be fairly straight-forward to write wrappers for them so they are convenient from C++.
@NikolajBjorner No worries at all. These functions work great for me, does exactly what I was looking for. I'll go ahead and close this issue. Thanks for the help!
I'm am trying to load in an smt2 file using the C++/C API for z3 (v4.5.1), and then add assertions using the API, with datatypes and functions that were declared in the smt2 file.
Here is an example of what I do to load a file into a solver:
So how do I use what was defined in the smt2 file, using the C or C++ API? (If possible). I would like to make more assertions, get a model, and then evaluate, using the functions and data types defined in the smt2 file. Here are the contents of the smt2 file if anyone is interested: