3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-12 12:08:18 +00:00
this time adding inheritance to the recfun plugin so it properly contains the recursive definitions from the source.
This commit is contained in:
Nikolaj Bjorner 2022-07-04 12:42:11 -07:00
parent 6ed2b444b5
commit 0353fc38ff
5 changed files with 86 additions and 17 deletions

View file

@ -10,8 +10,8 @@ Version 4.9.next
- native word level bit-vector solving. - native word level bit-vector solving.
- introduction of simple induction lemmas to handle a limited repertoire of induction proofs. - introduction of simple induction lemmas to handle a limited repertoire of induction proofs.
Version 4.9 Version 4.9.0
=========== =============
- API for incremental parsing of assertions. - API for incremental parsing of assertions.
A description of the feature is given by example here: https://github.com/Z3Prover/z3/commit/815518dc026e900392bf0d08ed859e5ec42d1e43 A description of the feature is given by example here: https://github.com/Z3Prover/z3/commit/815518dc026e900392bf0d08ed859e5ec42d1e43
It also allows incrementality at the level of adding assertions to the It also allows incrementality at the level of adding assertions to the
@ -19,10 +19,21 @@ Version 4.9
- Fold/map for sequences: - Fold/map for sequences:
https://microsoft.github.io/rise4fun/docs/guide/Sequences#map-and-fold https://microsoft.github.io/rise4fun/docs/guide/Sequences#map-and-fold
At this point these functions are only exposed over the SMTLIB2 interface (and not programmatic API) At this point these functions are only exposed over the SMTLIB2 interface (and not programmatic API)
maxdiff/mindiff on arrays are more likely to be deprecated
- User Propagator: - User Propagator:
- Add functions and callbacks for external control over branching - Add functions and callbacks for external control over branching
- A functioning dotnet API for the User Propagator - A functioning dotnet API for the User Propagator
https://github.com/Z3Prover/z3/blob/master/src/api/dotnet/UserPropagator.cs https://github.com/Z3Prover/z3/blob/master/src/api/dotnet/UserPropagator.cs
- Java Script API
- higher level object wrappers are available thanks to Gibbons and Tomalka
- Totalizers and RC2
- The MaxSAT engine now allows to run RC2 with totalizer encoding.
Totalizers are on by default as preliminary tests suggest this solves already 10% more problems on
standard benchmarks. The option rc2.totalizer (which by default is true) is used to control whether to use
totalizer encoding or built-in cardinality constraints.
The default engine is still maxres, so you have to set opt.maxsat_engine=rc2 to
enable the rc2 option at this point. The engines maxres-bin and rc2bin are experimental should not be used
(they are inferior to default options).
Version 4.8.17 Version 4.8.17
============== ==============

View file

@ -67,6 +67,30 @@ namespace recfun {
m_decl = m.mk_func_decl(s, arity, domain, range, info); m_decl = m.mk_func_decl(s, arity, domain, range, info);
} }
def* def::copy(util& dst, ast_translation& tr) {
SASSERT(&dst.m() == &tr.to());
sort_ref_vector domain(tr.to());
sort_ref range(tr(m_range.get()), tr.to());
for (auto* s : m_domain)
domain.push_back(tr(s));
family_id fid = dst.get_family_id();
bool is_generated = m_decl->get_parameter(0).get_int() != 0;
def* r = alloc(def, tr.to(), fid, m_name, domain.size(), domain.data(), range, is_generated);
r->m_rhs = tr(m_rhs.get());
for (auto* v : m_vars)
r->m_vars.push_back(tr(v));
for (auto const& c1 : m_cases) {
r->m_cases.push_back(case_def(tr.to()));
auto& c2 = r->m_cases.back();
c2.m_pred = tr(c1.m_pred.get());
c2.m_guards = tr(c1.m_guards);
c2.m_rhs = tr(c1.m_rhs.get());
c2.m_def = r;
c2.m_immediate = c1.m_immediate;
}
return r;
}
bool def::contains_def(util& u, expr * e) { bool def::contains_def(util& u, expr * e) {
struct def_find_p : public i_expr_pred { struct def_find_p : public i_expr_pred {
util& u; util& u;
@ -415,6 +439,19 @@ namespace recfun {
return promise_def(&u(), d); return promise_def(&u(), d);
} }
void plugin::inherit(decl_plugin* other, ast_translation& tr) {
for (auto [k, v] : static_cast<plugin*>(other)->m_defs) {
func_decl_ref f(tr(k), tr.to());
if (m_defs.contains(f))
continue;
def* d = v->copy(u(), tr);
m_defs.insert(f, d);
for (case_def & c : d->get_cases())
m_case_defs.insert(c.get_decl(), &c);
}
}
promise_def plugin::ensure_def(symbol const& name, unsigned n, sort *const * params, sort * range, bool is_generated) { promise_def plugin::ensure_def(symbol const& name, unsigned n, sort *const * params, sort * range, bool is_generated) {
def* d = u().decl_fun(name, n, params, range, is_generated); def* d = u().decl_fun(name, n, params, range, is_generated);
erase_def(d->get_decl()); erase_def(d->get_decl());

View file

@ -21,6 +21,7 @@ Revision History:
#include "ast/ast.h" #include "ast/ast.h"
#include "ast/ast_pp.h" #include "ast/ast_pp.h"
#include "ast/ast_translation.h"
#include "util/obj_hashtable.h" #include "util/obj_hashtable.h"
namespace recfun { namespace recfun {
@ -62,6 +63,12 @@ namespace recfun {
def * m_def; //<! definition this is a part of def * m_def; //<! definition this is a part of
bool m_immediate; //<! does `rhs` contain no defined_fun/case_pred? bool m_immediate; //<! does `rhs` contain no defined_fun/case_pred?
case_def(ast_manager& m):
m_pred(m),
m_guards(m),
m_rhs(m)
{}
case_def(ast_manager & m, case_def(ast_manager & m,
family_id fid, family_id fid,
def * d, def * d,
@ -132,6 +139,8 @@ namespace recfun {
bool is_fun_macro() const { return m_cases.size() == 1; } bool is_fun_macro() const { return m_cases.size() == 1; }
bool is_fun_defined() const { return !is_fun_macro(); } bool is_fun_defined() const { return !is_fun_macro(); }
def* copy(util& dst, ast_translation& tr);
}; };
// definition to be complete (missing RHS) // definition to be complete (missing RHS)
@ -205,6 +214,8 @@ namespace recfun {
expr_ref redirect_ite(replace& subst, unsigned n, var * const* vars, expr * e); expr_ref redirect_ite(replace& subst, unsigned n, var * const* vars, expr * e);
void inherit(decl_plugin* other, ast_translation& tr) override;
}; };
} }

View file

@ -506,7 +506,7 @@ namespace dt {
return m_nodes; return m_nodes;
} }
ptr_vector<euf::enode> const& solver::get_seq_args(enode* n) { ptr_vector<euf::enode> const& solver::get_seq_args(enode* n, enode*& sibling) {
m_nodes.reset(); m_nodes.reset();
m_todo.reset(); m_todo.reset();
auto add_todo = [&](enode* n) { auto add_todo = [&](enode* n) {
@ -515,9 +515,15 @@ namespace dt {
m_todo.push_back(n); m_todo.push_back(n);
} }
}; };
for (enode* sib : euf::enode_class(n)) for (enode* sib : euf::enode_class(n)) {
add_todo(sib); if (m_sutil.str.is_concat_of_units(sib->get_expr())) {
add_todo(sib);
sibling = sib;
break;
}
}
for (unsigned i = 0; i < m_todo.size(); ++i) { for (unsigned i = 0; i < m_todo.size(); ++i) {
enode* n = m_todo[i]; enode* n = m_todo[i];
@ -551,10 +557,10 @@ namespace dt {
// collect equalities on all children that may have been used. // collect equalities on all children that may have been used.
bool found = false; bool found = false;
auto add = [&](enode* arg) { auto add = [&](enode* seq_arg) {
if (arg->get_root() == child->get_root()) { if (seq_arg->get_root() == child->get_root()) {
if (arg != child) if (seq_arg != child)
m_used_eqs.push_back(enode_pair(arg, child)); m_used_eqs.push_back(enode_pair(seq_arg, child));
found = true; found = true;
} }
}; };
@ -564,11 +570,14 @@ namespace dt {
if (m_autil.is_array(s) && dt.is_datatype(get_array_range(s))) if (m_autil.is_array(s) && dt.is_datatype(get_array_range(s)))
for (enode* aarg : get_array_args(arg)) for (enode* aarg : get_array_args(arg))
add(aarg); add(aarg);
} sort* se;
sort* se; if (m_sutil.is_seq(arg->get_sort(), se) && dt.is_datatype(se)) {
if (m_sutil.is_seq(child->get_sort(), se) && dt.is_datatype(se)) { enode* sibling = nullptr;
for (enode* aarg : get_seq_args(child)) for (enode* seq_arg : get_seq_args(arg, sibling))
add(aarg); add(seq_arg);
if (sibling && sibling != arg)
m_used_eqs.push_back(enode_pair(arg, sibling));
}
} }
VERIFY(found); VERIFY(found);
@ -636,12 +645,13 @@ namespace dt {
// explore `arg` (with parent) // explore `arg` (with parent)
expr* earg = arg->get_expr(); expr* earg = arg->get_expr();
sort* s = earg->get_sort(), *se; sort* s = earg->get_sort(), *se;
enode* sibling;
if (dt.is_datatype(s)) { if (dt.is_datatype(s)) {
m_parent.insert(arg->get_root(), parent); m_parent.insert(arg->get_root(), parent);
oc_push_stack(arg); oc_push_stack(arg);
} }
else if (m_sutil.is_seq(s, se) && dt.is_datatype(se)) { else if (m_sutil.is_seq(s, se) && dt.is_datatype(se)) {
for (enode* sarg : get_seq_args(arg)) for (enode* sarg : get_seq_args(arg, sibling))
if (process_arg(sarg)) if (process_arg(sarg))
return true; return true;
} }

View file

@ -112,7 +112,7 @@ namespace dt {
void oc_push_stack(enode * n); void oc_push_stack(enode * n);
ptr_vector<enode> m_nodes, m_todo; ptr_vector<enode> m_nodes, m_todo;
ptr_vector<enode> const& get_array_args(enode* n); ptr_vector<enode> const& get_array_args(enode* n);
ptr_vector<enode> const& get_seq_args(enode* n); ptr_vector<enode> const& get_seq_args(enode* n, enode*& sibling);
void pop_core(unsigned n) override; void pop_core(unsigned n) override;