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:
parent
97b480ded3
commit
4e01d5b5c1
8 changed files with 207 additions and 65 deletions
|
@ -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))
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue