3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-24 01:25:31 +00:00

tune axioms for derivatives

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2020-05-25 12:41:30 -07:00
parent 97b480ded3
commit 4e01d5b5c1
8 changed files with 207 additions and 65 deletions

View file

@ -239,6 +239,60 @@ bool arith_rewriter::is_bound(expr * arg1, expr * arg2, op_kind kind, expr_ref &
return false;
}
bool arith_rewriter::is_non_negative(expr* e) {
seq_util seq(m());
if (seq.str.is_length(e))
return true;
// TBD: check for even power
return false;
}
/**
* perform static analysis on arg1 to determine a non-negative lower bound.
* a + b + r1 <= r2 -> false if r1 > r2 and a >= 0, b >= 0
* a + b + r1 >= r2 -> false if r1 < r2 and a <= 0, b <= 0
*/
bool arith_rewriter::is_separated(expr* arg1, expr* arg2, op_kind kind, expr_ref& result) {
if (kind != LE && kind != GE)
return false;
rational bound(0), r1, r2;
expr_ref narg(m());
bool has_bound = true;
if (!m_util.is_numeral(arg2, r2))
return false;
auto update_bound = [&](expr* arg) {
if (m_util.is_numeral(arg, r1)) {
bound += r1;
return;
}
if (kind == LE && is_non_negative(arg))
return;
if (kind == GE && is_neg_poly(arg, narg) && is_non_negative(narg))
return;
has_bound = false;
};
if (m_util.is_add(arg1)) {
for (expr* arg : *to_app(arg1)) {
update_bound(arg);
}
}
else {
update_bound(arg1);
}
if (!has_bound)
return false;
if (kind == LE && r1 > r2) {
result = m().mk_false();
return true;
}
if (kind == GE && r1 < r2) {
result = m().mk_false();
return true;
}
return false;
}
bool arith_rewriter::elim_to_real_var(expr * var, expr_ref & new_var) {
numeral val;
if (m_util.is_numeral(var, val)) {
@ -427,6 +481,8 @@ br_status arith_rewriter::mk_le_ge_eq_core(expr * arg1, expr * arg2, op_kind kin
ANUM_LE_GE_EQ();
}
}
if (is_separated(arg1, arg2, kind, result))
return BR_DONE;
if (is_bound(arg1, arg2, kind, result))
return BR_DONE;
if (is_bound(arg2, arg1, inv(kind), result))

View file

@ -64,6 +64,8 @@ class arith_rewriter : public poly_rewriter<arith_rewriter_core> {
enum op_kind { LE, GE, EQ };
static op_kind inv(op_kind k) { return k == LE ? GE : (k == GE ? LE : EQ); }
bool is_bound(expr * arg1, expr * arg2, op_kind kind, expr_ref & result);
bool is_separated(expr * arg1, expr * arg2, op_kind kind, expr_ref & result);
bool is_non_negative(expr* e);
br_status mk_le_ge_eq_core(expr * arg1, expr * arg2, op_kind kind, expr_ref & result);
bool elim_to_real_var(expr * var, expr_ref & new_var);

View file

@ -2079,7 +2079,7 @@ expr_ref seq_rewriter::kleene_predicate(expr* cond, sort* seq_sort) {
expr_ref seq_rewriter::is_nullable(expr* r) {
SASSERT(m_util.is_re(r));
expr* r1 = nullptr, *r2 = nullptr;
expr* r1 = nullptr, *r2 = nullptr, *cond = nullptr;
unsigned lo = 0, hi = 0;
expr_ref result(m());
if (re().is_concat(r, r1, r2) ||
@ -2120,6 +2120,9 @@ expr_ref seq_rewriter::is_nullable(expr* r) {
expr* emptystr = m_util.str.mk_empty(seq_sort);
result = m().mk_eq(emptystr, r1);
}
else if (m().is_ite(r, cond, r1, r2)) {
result = m().mk_ite(cond, is_nullable(r1), is_nullable(r2));
}
else {
sort* seq_sort = nullptr;
VERIFY(m_util.is_re(r, seq_sort));
@ -2663,8 +2666,15 @@ br_status seq_rewriter::mk_re_opt(expr* a, expr_ref& result) {
}
bool seq_rewriter::has_cofactor(expr* r, expr_ref& cond, expr_ref& th, expr_ref& el) {
if (m().is_ite(r)) {
cond = to_app(r)->get_arg(0);
th = to_app(r)->get_arg(1);
el = to_app(r)->get_arg(2);
return true;
}
expr_ref_vector trail(m()), args_th(m()), args_el(m());
expr* c = nullptr, *tt = nullptr, *ee = nullptr;
cond = nullptr;
obj_map<expr,expr*> cache_th, cache_el;
expr_mark no_cofactor, visited;
ptr_vector<expr> todo;

View file

@ -233,6 +233,7 @@ public:
br_status mk_app_core(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result);
br_status mk_eq_core(expr * lhs, expr * rhs, expr_ref & result);
br_status mk_bool_app(func_decl* f, unsigned n, expr* const* args, expr_ref& result);
bool reduce_eq(expr* l, expr* r, expr_ref_pair_vector& new_eqs, bool& change);
@ -242,8 +243,6 @@ public:
void add_seqs(expr_ref_vector const& ls, expr_ref_vector const& rs, expr_ref_pair_vector& new_eqs);
br_status mk_bool_app(func_decl* f, unsigned n, expr* const* args, expr_ref& result);
expr_ref derivative(expr* hd, expr* r);
expr_ref is_nullable(expr* r);