mirror of
https://github.com/Z3Prover/z3
synced 2025-09-05 09:37:44 +00:00
address divergence in the case of shared theory symbols. Codeplex issue 147, thanks to George Karpenkov
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
commit
08cb8b8de8
74 changed files with 1280 additions and 896 deletions
|
@ -245,6 +245,7 @@ namespace datalog {
|
|||
m_rule_fmls_head = 0;
|
||||
m_rule_fmls.reset();
|
||||
m_rule_names.reset();
|
||||
m_rule_bounds.reset();
|
||||
m_argument_var_names.reset();
|
||||
m_preds.reset();
|
||||
m_preds_by_name.reset();
|
||||
|
@ -440,9 +441,10 @@ namespace datalog {
|
|||
return new_pred;
|
||||
}
|
||||
|
||||
void context::add_rule(expr* rl, symbol const& name) {
|
||||
void context::add_rule(expr* rl, symbol const& name, unsigned bound) {
|
||||
m_rule_fmls.push_back(rl);
|
||||
m_rule_names.push_back(name);
|
||||
m_rule_bounds.push_back(bound);
|
||||
}
|
||||
|
||||
void context::flush_add_rules() {
|
||||
|
@ -859,6 +861,9 @@ namespace datalog {
|
|||
flush_add_rules();
|
||||
break;
|
||||
case DUALITY_ENGINE:
|
||||
// this lets us use duality with SAS 2013 abstraction
|
||||
if(quantify_arrays())
|
||||
flush_add_rules();
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
|
@ -979,12 +984,13 @@ namespace datalog {
|
|||
}
|
||||
}
|
||||
|
||||
void context::get_raw_rule_formulas(expr_ref_vector& rules, svector<symbol>& names){
|
||||
void context::get_raw_rule_formulas(expr_ref_vector& rules, svector<symbol>& names, vector<unsigned> &bounds){
|
||||
for (unsigned i = 0; i < m_rule_fmls.size(); ++i) {
|
||||
expr_ref r = bind_vars(m_rule_fmls[i].get(), true);
|
||||
rules.push_back(r.get());
|
||||
// rules.push_back(m_rule_fmls[i].get());
|
||||
names.push_back(m_rule_names[i]);
|
||||
expr_ref r = bind_vars(m_rule_fmls[i].get(), true);
|
||||
rules.push_back(r.get());
|
||||
// rules.push_back(m_rule_fmls[i].get());
|
||||
names.push_back(m_rule_names[i]);
|
||||
bounds.push_back(m_rule_bounds[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1002,6 +1008,7 @@ namespace datalog {
|
|||
m_rule_names[i] = m_rule_names.back();
|
||||
m_rule_fmls.pop_back();
|
||||
m_rule_names.pop_back();
|
||||
m_rule_bounds.pop_back();
|
||||
--i;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -195,6 +195,7 @@ namespace datalog {
|
|||
unsigned m_rule_fmls_head;
|
||||
expr_ref_vector m_rule_fmls;
|
||||
svector<symbol> m_rule_names;
|
||||
vector<unsigned> m_rule_bounds;
|
||||
expr_ref_vector m_background;
|
||||
model_converter_ref m_mc;
|
||||
proof_converter_ref m_pc;
|
||||
|
@ -372,7 +373,7 @@ namespace datalog {
|
|||
rule_set & get_rules() { flush_add_rules(); return m_rule_set; }
|
||||
|
||||
void get_rules_as_formulas(expr_ref_vector& fmls, expr_ref_vector& qs, svector<symbol>& names);
|
||||
void get_raw_rule_formulas(expr_ref_vector& fmls, svector<symbol>& names);
|
||||
void get_raw_rule_formulas(expr_ref_vector& fmls, svector<symbol>& names, vector<unsigned> &bounds);
|
||||
|
||||
void add_fact(app * head);
|
||||
void add_fact(func_decl * pred, const relation_fact & fact);
|
||||
|
@ -389,7 +390,7 @@ namespace datalog {
|
|||
/**
|
||||
Method exposed from API for adding rules.
|
||||
*/
|
||||
void add_rule(expr* rl, symbol const& name);
|
||||
void add_rule(expr* rl, symbol const& name, unsigned bound = UINT_MAX);
|
||||
|
||||
|
||||
/**
|
||||
|
|
|
@ -142,6 +142,7 @@ def_module_params('fixedpoint',
|
|||
('xform.instantiate_quantifiers', BOOL, False,
|
||||
"instantiate quantified Horn clauses using E-matching heuristic"),
|
||||
('xform.coalesce_rules', BOOL, False, "coalesce rules"),
|
||||
('duality.enable_restarts', BOOL, False, 'DUALITY: enable restarts'),
|
||||
))
|
||||
|
||||
|
||||
|
|
|
@ -37,6 +37,7 @@ Revision History:
|
|||
#include "fixedpoint_params.hpp"
|
||||
#include "used_vars.h"
|
||||
#include "func_decl_dependencies.h"
|
||||
#include "dl_transforms.h"
|
||||
|
||||
// template class symbol_table<family_id>;
|
||||
|
||||
|
@ -155,8 +156,41 @@ lbool dl_interface::query(::expr * query) {
|
|||
|
||||
expr_ref_vector rules(m_ctx.get_manager());
|
||||
svector< ::symbol> names;
|
||||
vector<unsigned> bounds;
|
||||
// m_ctx.get_rules_as_formulas(rules, names);
|
||||
m_ctx.get_raw_rule_formulas(rules, names);
|
||||
|
||||
|
||||
// If using SAS 2013 abstractiion, we need to perform some transforms
|
||||
expr_ref query_ref(m_ctx.get_manager());
|
||||
if(m_ctx.quantify_arrays()){
|
||||
datalog::rule_manager& rm = m_ctx.get_rule_manager();
|
||||
rm.mk_query(query, m_ctx.get_rules());
|
||||
apply_default_transformation(m_ctx);
|
||||
datalog::rule_set &rs = m_ctx.get_rules();
|
||||
if(m_ctx.get_rules().get_output_predicates().empty())
|
||||
query_ref = m_ctx.get_manager().mk_false();
|
||||
else {
|
||||
func_decl_ref query_pred(m_ctx.get_manager());
|
||||
query_pred = m_ctx.get_rules().get_output_predicate();
|
||||
ptr_vector<sort> sorts;
|
||||
unsigned nargs = query_pred.get()->get_arity();
|
||||
expr_ref_vector vars(m_ctx.get_manager());
|
||||
for(unsigned i = 0; i < nargs; i++){
|
||||
::sort *s = query_pred.get()->get_domain(i);
|
||||
vars.push_back(m_ctx.get_manager().mk_var(nargs-1-i,s));
|
||||
}
|
||||
query_ref = m_ctx.get_manager().mk_app(query_pred.get(),nargs,vars.c_ptr());
|
||||
query = query_ref.get();
|
||||
}
|
||||
unsigned nrules = rs.get_num_rules();
|
||||
for(unsigned i = 0; i < nrules; i++){
|
||||
expr_ref f(m_ctx.get_manager());
|
||||
rm.to_formula(*rs.get_rule(i), f);
|
||||
rules.push_back(f);
|
||||
}
|
||||
}
|
||||
else
|
||||
m_ctx.get_raw_rule_formulas(rules, names, bounds);
|
||||
|
||||
// get all the rules as clauses
|
||||
std::vector<expr> &clauses = _d->clauses;
|
||||
|
@ -200,6 +234,7 @@ lbool dl_interface::query(::expr * query) {
|
|||
expr qc = implies(q,_d->ctx.bool_val(false));
|
||||
qc = _d->ctx.make_quant(Forall,b_sorts,b_names,qc);
|
||||
clauses.push_back(qc);
|
||||
bounds.push_back(UINT_MAX);
|
||||
|
||||
// get the background axioms
|
||||
unsigned num_asserts = m_ctx.get_num_assertions();
|
||||
|
@ -243,13 +278,21 @@ lbool dl_interface::query(::expr * query) {
|
|||
expr c = implies(_d->ctx.bool_val(false),f(args));
|
||||
c = _d->ctx.make_quant(Forall,args,c);
|
||||
clauses.push_back(c);
|
||||
bounds.push_back(UINT_MAX);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
unsigned rb = m_ctx.get_params().duality_recursion_bound();
|
||||
std::vector<unsigned> std_bounds;
|
||||
for(unsigned i = 0; i < bounds.size(); i++){
|
||||
unsigned b = bounds[i];
|
||||
if (b == UINT_MAX) b = rb;
|
||||
std_bounds.push_back(b);
|
||||
}
|
||||
|
||||
// creates 1-1 map between clauses and rpfp edges
|
||||
_d->rpfp->FromClauses(clauses);
|
||||
_d->rpfp->FromClauses(clauses,&std_bounds);
|
||||
|
||||
// populate the edge-to-clause map
|
||||
for(unsigned i = 0; i < _d->rpfp->edges.size(); ++i)
|
||||
|
@ -271,11 +314,13 @@ lbool dl_interface::query(::expr * query) {
|
|||
rs->SetOption("stratified_inlining",m_ctx.get_params().duality_stratified_inlining() ? "1" : "0");
|
||||
rs->SetOption("batch_expand",m_ctx.get_params().duality_batch_expand() ? "1" : "0");
|
||||
rs->SetOption("conjecture_file",m_ctx.get_params().duality_conjecture_file());
|
||||
unsigned rb = m_ctx.get_params().duality_recursion_bound();
|
||||
rs->SetOption("enable_restarts",m_ctx.get_params().duality_enable_restarts() ? "1" : "0");
|
||||
#if 0
|
||||
if(rb != UINT_MAX){
|
||||
std::ostringstream os; os << rb;
|
||||
rs->SetOption("recursion_bound", os.str());
|
||||
}
|
||||
#endif
|
||||
|
||||
// Solve!
|
||||
bool ans;
|
||||
|
|
|
@ -100,7 +100,7 @@ struct dl_context {
|
|||
dlctx().set_predicate_representation(pred, num_kinds, kinds);
|
||||
}
|
||||
|
||||
void add_rule(expr * rule, symbol const& name) {
|
||||
void add_rule(expr * rule, symbol const& name, unsigned bound) {
|
||||
init();
|
||||
if (m_collected_cmds) {
|
||||
expr_ref rl = m_context->bind_vars(rule, true);
|
||||
|
@ -110,7 +110,7 @@ struct dl_context {
|
|||
m_trail.push(push_back_vector<dl_context, svector<symbol> >(m_collected_cmds->m_names));
|
||||
}
|
||||
else {
|
||||
m_context->add_rule(rule, name);
|
||||
m_context->add_rule(rule, name, bound);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -151,19 +151,22 @@ class dl_rule_cmd : public cmd {
|
|||
mutable unsigned m_arg_idx;
|
||||
expr* m_t;
|
||||
symbol m_name;
|
||||
unsigned m_bound;
|
||||
public:
|
||||
dl_rule_cmd(dl_context * dl_ctx):
|
||||
cmd("rule"),
|
||||
m_dl_ctx(dl_ctx),
|
||||
m_arg_idx(0),
|
||||
m_t(0) {}
|
||||
virtual char const * get_usage() const { return "(forall (q) (=> (and body) head)) :optional-name"; }
|
||||
m_t(0),
|
||||
m_bound(UINT_MAX) {}
|
||||
virtual char const * get_usage() const { return "(forall (q) (=> (and body) head)) :optional-name :optional-recursion-bound"; }
|
||||
virtual char const * get_descr(cmd_context & ctx) const { return "add a Horn rule."; }
|
||||
virtual unsigned get_arity() const { return VAR_ARITY; }
|
||||
virtual cmd_arg_kind next_arg_kind(cmd_context & ctx) const {
|
||||
switch(m_arg_idx) {
|
||||
case 0: return CPK_EXPR;
|
||||
case 1: return CPK_SYMBOL;
|
||||
case 2: return CPK_UINT;
|
||||
default: return CPK_SYMBOL;
|
||||
}
|
||||
}
|
||||
|
@ -173,13 +176,18 @@ public:
|
|||
}
|
||||
virtual void set_next_arg(cmd_context & ctx, symbol const & s) {
|
||||
m_name = s;
|
||||
m_arg_idx++;
|
||||
}
|
||||
virtual void set_next_arg(cmd_context & ctx, unsigned bound) {
|
||||
m_bound = bound;
|
||||
m_arg_idx++;
|
||||
}
|
||||
virtual void reset(cmd_context & ctx) { m_dl_ctx->reset(); prepare(ctx); }
|
||||
virtual void prepare(cmd_context& ctx) { m_arg_idx = 0; m_name = symbol::null; }
|
||||
virtual void prepare(cmd_context& ctx) { m_arg_idx = 0; m_name = symbol::null; m_bound = UINT_MAX; }
|
||||
virtual void finalize(cmd_context & ctx) {
|
||||
}
|
||||
virtual void execute(cmd_context & ctx) {
|
||||
m_dl_ctx->add_rule(m_t, m_name);
|
||||
m_dl_ctx->add_rule(m_t, m_name, m_bound);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -48,13 +48,6 @@ namespace datalog {
|
|||
transf.register_plugin(alloc(datalog::mk_quantifier_abstraction, ctx, 38000));
|
||||
}
|
||||
transf.register_plugin(alloc(datalog::mk_quantifier_instantiation, ctx, 37000));
|
||||
transf.register_plugin(alloc(datalog::mk_scale, ctx, 36030));
|
||||
if (ctx.get_params().xform_magic()) {
|
||||
transf.register_plugin(alloc(datalog::mk_magic_symbolic, ctx, 36020));
|
||||
}
|
||||
transf.register_plugin(alloc(datalog::mk_karr_invariants, ctx, 36010));
|
||||
transf.register_plugin(alloc(datalog::mk_array_blast, ctx, 36000));
|
||||
transf.register_plugin(alloc(datalog::mk_bit_blast, ctx, 35000));
|
||||
|
||||
transf.register_plugin(alloc(datalog::mk_subsumption_checker, ctx, 35005));
|
||||
transf.register_plugin(alloc(datalog::mk_rule_inliner, ctx, 35000));
|
||||
|
@ -75,9 +68,15 @@ namespace datalog {
|
|||
transf.register_plugin(alloc(datalog::mk_rule_inliner, ctx, 34890));
|
||||
transf.register_plugin(alloc(datalog::mk_subsumption_checker, ctx, 34880));
|
||||
|
||||
|
||||
|
||||
|
||||
transf.register_plugin(alloc(datalog::mk_bit_blast, ctx, 35000));
|
||||
transf.register_plugin(alloc(datalog::mk_karr_invariants, ctx, 36010));
|
||||
transf.register_plugin(alloc(datalog::mk_scale, ctx, 36030));
|
||||
if (!ctx.get_params().xform_quantify_arrays()) {
|
||||
transf.register_plugin(alloc(datalog::mk_array_blast, ctx, 36000));
|
||||
}
|
||||
if (ctx.get_params().xform_magic()) {
|
||||
transf.register_plugin(alloc(datalog::mk_magic_symbolic, ctx, 36020));
|
||||
}
|
||||
ctx.transform_rules(transf);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue