mirror of
https://github.com/Z3Prover/z3
synced 2025-04-08 18:31:49 +00:00
working on horn difference logic
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
parent
17f0377c06
commit
0fbdd37e89
|
@ -46,7 +46,7 @@ extern "C" {
|
|||
Z3_TRY;
|
||||
LOG_Z3_mk_int_symbol(c, i);
|
||||
RESET_ERROR_CODE();
|
||||
if (i < 0 || (unsigned)i >= (SIZE_MAX >> PTR_ALIGNMENT)) {
|
||||
if (i < 0 || (size_t)i >= (SIZE_MAX >> PTR_ALIGNMENT)) {
|
||||
SET_ERROR_CODE(Z3_IOB);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -268,6 +268,8 @@ public:
|
|||
bool is_int_real(expr const * n) const { return is_int_real(get_sort(n)); }
|
||||
|
||||
MATCH_UNARY(is_uminus);
|
||||
MATCH_UNARY(is_to_real);
|
||||
MATCH_UNARY(is_to_int);
|
||||
MATCH_BINARY(is_sub);
|
||||
MATCH_BINARY(is_add);
|
||||
MATCH_BINARY(is_mul);
|
||||
|
|
|
@ -1004,7 +1004,6 @@ namespace datalog {
|
|||
symbol is_name(_name.str().c_str());
|
||||
std::stringstream _name2;
|
||||
_name2 << "get_succ#" << i;
|
||||
symbol acc_name(_name2.str().c_str());
|
||||
ptr_vector<accessor_decl> accs;
|
||||
type_ref tr(0);
|
||||
accs.push_back(mk_accessor_decl(name, tr));
|
||||
|
|
|
@ -647,7 +647,6 @@ namespace datalog {
|
|||
}
|
||||
}
|
||||
ast_manager& m = get_manager();
|
||||
datalog::rule_manager& rm = get_rule_manager();
|
||||
contains_pred contains_p(*this);
|
||||
check_pred check_pred(contains_p, get_manager());
|
||||
|
||||
|
|
|
@ -141,7 +141,6 @@ namespace datalog {
|
|||
func_decl_ref_vector const& new_funcs() const { return m_new_funcs; }
|
||||
|
||||
br_status reduce_app(func_decl * f, unsigned num, expr * const * args, expr_ref & result, proof_ref & result_pr) {
|
||||
rule_manager& rm = m_context.get_rule_manager();
|
||||
bool found = false;
|
||||
for (unsigned j = 0; !found && j < num; ++j) {
|
||||
found = m_util.is_mkbv(args[j]);
|
||||
|
|
|
@ -35,6 +35,8 @@ Revision History:
|
|||
#include"dl_mk_karr_invariants.h"
|
||||
#include"expr_safe_replace.h"
|
||||
#include"bool_rewriter.h"
|
||||
#include"dl_mk_backwards.h"
|
||||
#include"dl_mk_loop_counter.h"
|
||||
|
||||
namespace datalog {
|
||||
|
||||
|
@ -199,6 +201,29 @@ namespace datalog {
|
|||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
mk_loop_counter lc(m_ctx);
|
||||
mk_backwards bwd(m_ctx);
|
||||
|
||||
scoped_ptr<rule_set> src_loop = lc(source);
|
||||
TRACE("dl", src_loop->display(tout << "source loop\n"););
|
||||
|
||||
// run propagation forwards, then backwards
|
||||
scoped_ptr<rule_set> src_annot = update_using_propagation(*src_loop, *src_loop);
|
||||
TRACE("dl", src_annot->display(tout << "updated using propagation\n"););
|
||||
|
||||
#if 0
|
||||
// figure out whether to update same rules as used for saturation.
|
||||
scoped_ptr<rule_set> rev_source = bwd(*src_annot);
|
||||
src_annot = update_using_propagation(*src_annot, *rev_source);
|
||||
#endif
|
||||
rule_set* rules = lc.revert(*src_annot);
|
||||
rules->inherit_predicates(source);
|
||||
TRACE("dl", rules->display(tout););
|
||||
return rules;
|
||||
}
|
||||
|
||||
rule_set* mk_karr_invariants::update_using_propagation(rule_set const& src, rule_set const& srcref) {
|
||||
m_inner_ctx.reset();
|
||||
rel_context& rctx = m_inner_ctx.get_rel_context();
|
||||
ptr_vector<func_decl> heads;
|
||||
|
@ -207,24 +232,24 @@ namespace datalog {
|
|||
m_inner_ctx.register_predicate(*fit, false);
|
||||
}
|
||||
m_inner_ctx.ensure_opened();
|
||||
m_inner_ctx.replace_rules(source);
|
||||
m_inner_ctx.replace_rules(srcref);
|
||||
m_inner_ctx.close();
|
||||
rule_set::decl2rules::iterator dit = source.begin_grouped_rules();
|
||||
rule_set::decl2rules::iterator dend = source.end_grouped_rules();
|
||||
rule_set::decl2rules::iterator dit = srcref.begin_grouped_rules();
|
||||
rule_set::decl2rules::iterator dend = srcref.end_grouped_rules();
|
||||
for (; dit != dend; ++dit) {
|
||||
heads.push_back(dit->m_key);
|
||||
}
|
||||
m_inner_ctx.rel_query(heads.size(), heads.c_ptr());
|
||||
|
||||
rule_set* rules = alloc(rule_set, m_ctx);
|
||||
it = source.begin();
|
||||
rule_set* dst = alloc(rule_set, m_ctx);
|
||||
rule_set::iterator it = src.begin(), end = src.end();
|
||||
for (; it != end; ++it) {
|
||||
update_body(rctx, *rules, **it);
|
||||
update_body(rctx, *dst, **it);
|
||||
}
|
||||
if (m_ctx.get_model_converter()) {
|
||||
add_invariant_model_converter* kmc = alloc(add_invariant_model_converter, m);
|
||||
rule_set::decl2rules::iterator git = source.begin_grouped_rules();
|
||||
rule_set::decl2rules::iterator gend = source.end_grouped_rules();
|
||||
rule_set::decl2rules::iterator git = src.begin_grouped_rules();
|
||||
rule_set::decl2rules::iterator gend = src.end_grouped_rules();
|
||||
for (; git != gend; ++git) {
|
||||
func_decl* p = git->m_key;
|
||||
expr_ref fml(m);
|
||||
|
@ -236,9 +261,9 @@ namespace datalog {
|
|||
}
|
||||
m_ctx.add_model_converter(kmc);
|
||||
}
|
||||
TRACE("dl", rules->display(tout););
|
||||
rules->inherit_predicates(source);
|
||||
return rules;
|
||||
|
||||
dst->inherit_predicates(src);
|
||||
return dst;
|
||||
}
|
||||
|
||||
void mk_karr_invariants::update_body(rel_context& rctx, rule_set& rules, rule& r) {
|
||||
|
|
|
@ -56,7 +56,7 @@ namespace datalog {
|
|||
context m_inner_ctx;
|
||||
arith_util a;
|
||||
void update_body(rel_context& rctx, rule_set& result, rule& r);
|
||||
|
||||
rule_set* update_using_propagation(rule_set const& src, rule_set const& srcref);
|
||||
public:
|
||||
mk_karr_invariants(context & ctx, unsigned priority);
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ namespace datalog {
|
|||
|
||||
mk_loop_counter::~mk_loop_counter() { }
|
||||
|
||||
app_ref mk_loop_counter::add_arg(app* fn, unsigned idx) {
|
||||
app_ref mk_loop_counter::add_arg(rule_set const& src, rule_set& dst, app* fn, unsigned idx) {
|
||||
expr_ref_vector args(m);
|
||||
func_decl* new_fn, *old_fn = fn->get_decl();
|
||||
args.append(fn->get_num_args(), fn->get_args());
|
||||
|
@ -46,17 +46,29 @@ namespace datalog {
|
|||
m_old2new.insert(old_fn, new_fn);
|
||||
m_new2old.insert(new_fn, old_fn);
|
||||
m_refs.push_back(new_fn);
|
||||
m_ctx.register_predicate(new_fn, false);
|
||||
if (src.is_output_predicate(old_fn)) {
|
||||
dst.set_output_predicate(new_fn);
|
||||
}
|
||||
}
|
||||
return app_ref(m.mk_app(new_fn, args.size(), args.c_ptr()), m);
|
||||
}
|
||||
|
||||
app_ref mk_loop_counter::del_arg(app* fn) {
|
||||
expr_ref_vector args(m);
|
||||
func_decl* old_fn, *new_fn = fn->get_decl();
|
||||
SASSERT(fn->get_num_args() > 0);
|
||||
args.append(fn->get_num_args()-1, fn->get_args());
|
||||
VERIFY (m_new2old.find(new_fn, old_fn));
|
||||
return app_ref(m.mk_app(old_fn, args.size(), args.c_ptr()), m);
|
||||
}
|
||||
|
||||
rule_set * mk_loop_counter::operator()(rule_set const & source) {
|
||||
m_refs.reset();
|
||||
m_old2new.reset();
|
||||
m_new2old.reset();
|
||||
context& ctx = source.get_context();
|
||||
rule_manager& rm = source.get_rule_manager();
|
||||
rule_set * result = alloc(rule_set, ctx);
|
||||
rule_set * result = alloc(rule_set, m_ctx);
|
||||
unsigned sz = source.get_num_rules();
|
||||
rule_ref new_rule(rm);
|
||||
app_ref_vector tail(m);
|
||||
|
@ -71,16 +83,14 @@ namespace datalog {
|
|||
unsigned utsz = r.get_uninterpreted_tail_size();
|
||||
unsigned tsz = r.get_tail_size();
|
||||
for (unsigned j = 0; j < utsz; ++j, ++cnt) {
|
||||
tail.push_back(add_arg(r.get_tail(j), cnt));
|
||||
tail.push_back(add_arg(source, *result, r.get_tail(j), cnt));
|
||||
neg.push_back(r.is_neg_tail(j));
|
||||
m_ctx.register_predicate(tail.back()->get_decl(), false);
|
||||
}
|
||||
for (unsigned j = utsz; j < tsz; ++j) {
|
||||
tail.push_back(r.get_tail(j));
|
||||
neg.push_back(false);
|
||||
}
|
||||
head = add_arg(r.get_head(), cnt);
|
||||
m_ctx.register_predicate(head->get_decl(), false);
|
||||
head = add_arg(source, *result, r.get_head(), cnt);
|
||||
// set the loop counter to be an increment of the previous
|
||||
bool found = false;
|
||||
unsigned last = head->get_num_args()-1;
|
||||
|
@ -108,9 +118,41 @@ namespace datalog {
|
|||
// model converter: remove references to extra argument.
|
||||
// proof converter: remove references to extra argument as well.
|
||||
|
||||
result->inherit_predicates(source);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
rule_set * mk_loop_counter::revert(rule_set const & source) {
|
||||
context& ctx = source.get_context();
|
||||
rule_manager& rm = source.get_rule_manager();
|
||||
rule_set * result = alloc(rule_set, ctx);
|
||||
unsigned sz = source.get_num_rules();
|
||||
rule_ref new_rule(rm);
|
||||
app_ref_vector tail(m);
|
||||
app_ref head(m);
|
||||
svector<bool> neg;
|
||||
for (unsigned i = 0; i < sz; ++i) {
|
||||
tail.reset();
|
||||
neg.reset();
|
||||
rule & r = *source.get_rule(i);
|
||||
unsigned utsz = r.get_uninterpreted_tail_size();
|
||||
unsigned tsz = r.get_tail_size();
|
||||
for (unsigned j = 0; j < utsz; ++j) {
|
||||
tail.push_back(del_arg(r.get_tail(j)));
|
||||
neg.push_back(r.is_neg_tail(j));
|
||||
}
|
||||
for (unsigned j = utsz; j < tsz; ++j) {
|
||||
tail.push_back(r.get_tail(j));
|
||||
neg.push_back(false);
|
||||
}
|
||||
head = del_arg(r.get_head());
|
||||
new_rule = rm.mk(head, tail.size(), tail.c_ptr(), neg.c_ptr(), r.name(), true);
|
||||
result->add_rule(new_rule);
|
||||
}
|
||||
|
||||
// model converter: ...
|
||||
// proof converter: ...
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
};
|
||||
|
|
|
@ -32,7 +32,8 @@ namespace datalog {
|
|||
obj_map<func_decl, func_decl*> m_new2old;
|
||||
obj_map<func_decl, func_decl*> m_old2new;
|
||||
|
||||
app_ref add_arg(app* fn, unsigned idx);
|
||||
app_ref add_arg(rule_set const& src, rule_set& dst, app* fn, unsigned idx);
|
||||
app_ref del_arg(app* fn);
|
||||
public:
|
||||
mk_loop_counter(context & ctx, unsigned priority = 33000);
|
||||
~mk_loop_counter();
|
||||
|
@ -40,6 +41,8 @@ namespace datalog {
|
|||
rule_set * operator()(rule_set const & source);
|
||||
|
||||
func_decl* get_old(func_decl* f) const { return m_new2old.find(f); }
|
||||
|
||||
rule_set * revert(rule_set const& source);
|
||||
};
|
||||
|
||||
};
|
||||
|
|
|
@ -409,9 +409,10 @@ namespace datalog {
|
|||
}
|
||||
|
||||
void rule_set::reopen() {
|
||||
SASSERT(is_closed());
|
||||
m_stratifier = 0;
|
||||
m_deps.reset();
|
||||
if (is_closed()) {
|
||||
m_stratifier = 0;
|
||||
m_deps.reset();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1643,7 +1643,3 @@ public:
|
|||
|
||||
#endif /* _DIFF_LOGIC_H_ */
|
||||
|
||||
#if 0
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -318,7 +318,7 @@ template<typename Ext>
|
|||
void theory_diff_logic<Ext>::assign_eh(bool_var v, bool is_true) {
|
||||
m_stats.m_num_assertions++;
|
||||
atom * a = 0;
|
||||
m_bool_var2atom.find(v, a);
|
||||
VERIFY (m_bool_var2atom.find(v, a));
|
||||
SASSERT(a);
|
||||
SASSERT(get_context().get_assignment(v) != l_undef);
|
||||
SASSERT((get_context().get_assignment(v) == l_true) == is_true);
|
||||
|
@ -376,13 +376,6 @@ final_check_status theory_diff_logic<Ext>::final_check_eh() {
|
|||
SASSERT(is_consistent());
|
||||
|
||||
|
||||
#if 0
|
||||
TBD:
|
||||
if (propagate_cheap_equalities()) {
|
||||
return FC_CONTINUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (m_non_diff_logic_exprs) {
|
||||
return FC_GIVEUP;
|
||||
}
|
||||
|
|
|
@ -223,6 +223,7 @@ class inf_rational {
|
|||
}
|
||||
|
||||
friend inline inf_rational operator*(const rational & r1, const inf_rational & r2);
|
||||
friend inline inf_rational operator*(const inf_rational & r1, const rational & r2);
|
||||
friend inline inf_rational operator/(const inf_rational & r1, const rational & r2);
|
||||
|
||||
inf_rational & operator++() {
|
||||
|
@ -426,6 +427,10 @@ inline inf_rational operator*(const rational & r1, const inf_rational & r2) {
|
|||
return result;
|
||||
}
|
||||
|
||||
inline inf_rational operator*(const inf_rational & r1, const rational & r2) {
|
||||
return r2 * r1;
|
||||
}
|
||||
|
||||
inline inf_rational operator/(const inf_rational & r1, const rational & r2) {
|
||||
inf_rational result(r1);
|
||||
result.m_first /= r2;
|
||||
|
|
Loading…
Reference in a new issue