mirror of
https://github.com/Z3Prover/z3
synced 2025-04-23 09:05:31 +00:00
na
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
commit
dcdbbfb925
144 changed files with 1528 additions and 517 deletions
|
@ -1050,6 +1050,12 @@ public:
|
|||
*/
|
||||
virtual bool is_value(app * a) const { return false; }
|
||||
|
||||
|
||||
/**
|
||||
\brief return true if the expression can be used as a model value.
|
||||
*/
|
||||
virtual bool is_model_value(app* a) const { return is_value(a); }
|
||||
|
||||
/**
|
||||
\brief Return true if \c a is a unique plugin value.
|
||||
The following property should hold for unique theory values:
|
||||
|
|
|
@ -717,6 +717,8 @@ namespace datatype {
|
|||
todo.pop_back();
|
||||
continue;
|
||||
}
|
||||
if (!is_declared(s))
|
||||
return true;
|
||||
already_found.insert(datatype_name(s), GRAY);
|
||||
def const& d = get_def(s);
|
||||
bool can_process = true;
|
||||
|
|
|
@ -65,7 +65,7 @@ bool has_skolem_functions(expr * n) {
|
|||
}
|
||||
|
||||
subterms::subterms(expr_ref_vector const& es, bool include_bound): m_include_bound(include_bound), m_es(es) {}
|
||||
subterms::subterms(expr_ref const& e, bool include_bound) : m_include_bound(include_bound), m_es(e.m()) { m_es.push_back(e); }
|
||||
subterms::subterms(expr_ref const& e, bool include_bound) : m_include_bound(include_bound), m_es(e.m()) {if (e) m_es.push_back(e); }
|
||||
subterms::iterator subterms::begin() { return iterator(*this, true); }
|
||||
subterms::iterator subterms::end() { return iterator(*this, false); }
|
||||
subterms::iterator::iterator(subterms& f, bool start): m_include_bound(f.m_include_bound), m_es(f.m_es) {
|
||||
|
@ -112,7 +112,7 @@ bool subterms::iterator::operator!=(iterator const& other) const {
|
|||
|
||||
|
||||
subterms_postorder::subterms_postorder(expr_ref_vector const& es): m_es(es) {}
|
||||
subterms_postorder::subterms_postorder(expr_ref const& e) : m_es(e.m()) { m_es.push_back(e); }
|
||||
subterms_postorder::subterms_postorder(expr_ref const& e) : m_es(e.m()) { if (e) m_es.push_back(e); }
|
||||
subterms_postorder::iterator subterms_postorder::begin() { return iterator(*this, true); }
|
||||
subterms_postorder::iterator subterms_postorder::end() { return iterator(*this, false); }
|
||||
subterms_postorder::iterator::iterator(subterms_postorder& f, bool start): m_es(f.m_es) {
|
||||
|
|
|
@ -855,6 +855,16 @@ br_status bv_rewriter::mk_bv_shl(expr * arg1, expr * arg2, expr_ref & result) {
|
|||
return BR_REWRITE2;
|
||||
}
|
||||
|
||||
expr* x = nullptr, *y = nullptr;
|
||||
if (m_util.is_bv_shl(arg1, x, y)) {
|
||||
expr_ref sum(m_util.mk_bv_add(y, arg2), m());
|
||||
expr_ref cond(m_util.mk_ule(y, sum), m());
|
||||
result = m().mk_ite(cond,
|
||||
m_util.mk_bv_shl(x, sum),
|
||||
mk_numeral(0, bv_size));
|
||||
return BR_REWRITE3;
|
||||
}
|
||||
|
||||
return BR_FAILED;
|
||||
}
|
||||
|
||||
|
@ -1436,18 +1446,34 @@ br_status bv_rewriter::mk_bv2int(expr * arg, expr_ref & result) {
|
|||
|
||||
|
||||
bool bv_rewriter::is_mul_no_overflow(expr* e) {
|
||||
if (!m_util.is_bv_mul(e)) return false;
|
||||
if (!m_util.is_bv_mul(e))
|
||||
return false;
|
||||
unsigned sz = get_bv_size(e);
|
||||
unsigned sum = 0;
|
||||
for (expr* x : *to_app(e)) sum += sz-num_leading_zero_bits(x);
|
||||
return sum < sz;
|
||||
for (expr* x : *to_app(e))
|
||||
sum += sz - num_leading_zero_bits(x);
|
||||
if (sum > sz + 1)
|
||||
return false;
|
||||
if (sum <= sz)
|
||||
return true;
|
||||
rational v;
|
||||
unsigned shift;
|
||||
for (expr* x : *to_app(e))
|
||||
if (m_util.is_numeral(x, v) && v.is_power_of_two(shift))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool bv_rewriter::is_add_no_overflow(expr* e) {
|
||||
if (!is_add(e)) return false;
|
||||
for (expr* x : *to_app(e)) {
|
||||
if (0 == num_leading_zero_bits(x)) return false;
|
||||
}
|
||||
if (!is_add(e))
|
||||
return false;
|
||||
unsigned num_args = to_app(e)->get_num_args();
|
||||
if (num_args <= 1)
|
||||
return true;
|
||||
num_args -= 2;
|
||||
for (expr* x : *to_app(e))
|
||||
if (num_args >= num_leading_zero_bits(x))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -205,10 +205,12 @@ namespace seq {
|
|||
drop_last_axiom(e, s);
|
||||
return;
|
||||
}
|
||||
#if 1
|
||||
if (is_extract_prefix(s, _i, _l)) {
|
||||
extract_prefix_axiom(e, s, l);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
if (is_extract_suffix(s, _i, _l)) {
|
||||
extract_suffix_axiom(e, s, i);
|
||||
return;
|
||||
|
@ -325,8 +327,7 @@ namespace seq {
|
|||
0 <= l <= len(s) => len(e) = l
|
||||
len(s) < l => e = s
|
||||
*/
|
||||
void axioms::extract_prefix_axiom(expr* e, expr* s, expr* l) {
|
||||
|
||||
void axioms::extract_prefix_axiom(expr* e, expr* s, expr* l) {
|
||||
TRACE("seq", tout << "prefix " << mk_bounded_pp(e, m, 2) << " " << mk_bounded_pp(s, m, 2) << " " << mk_bounded_pp(l, m, 2) << "\n";);
|
||||
expr_ref le = mk_len(e);
|
||||
expr_ref ls = mk_len(s);
|
||||
|
@ -1029,6 +1030,29 @@ namespace seq {
|
|||
add_clause(le, emp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assume that r has the property that if r accepts string p
|
||||
* then r does *not* accept any suffix of p. It is conceptually easy to
|
||||
* convert a deterministic automaton for a regex to a suffix blocking acceptor
|
||||
* by removing outgoing edges from accepting states and redirecting them
|
||||
* to a sink. Alternative, introduce a different string membership predicate that is
|
||||
* prefix sensitive.
|
||||
*
|
||||
* Let e = replace_re(s, r, t)
|
||||
* Then a claim is that the following axioms suffice to encode str.replace_re
|
||||
*
|
||||
* s = "" => e = t
|
||||
* r = "" => e = s + t
|
||||
* s not in .*r.* => e = t
|
||||
* s = x + y + [z] + u & y + [z] in r & x + y not in .*r.* => e = x + t + u
|
||||
*/
|
||||
void axioms::replace_re_axiom(expr* e) {
|
||||
expr* s = nullptr, *r = nullptr, *t = nullptr;
|
||||
VERIFY(seq.str.is_replace_re(e, s, r, t));
|
||||
NOT_IMPLEMENTED_YET();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Unit is injective:
|
||||
|
@ -1170,4 +1194,5 @@ namespace seq {
|
|||
return bound_tracker;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -106,6 +106,7 @@ namespace seq {
|
|||
void unit_axiom(expr* n);
|
||||
void length_axiom(expr* n);
|
||||
void unroll_not_contains(expr* e);
|
||||
void replace_re_axiom(expr* e);
|
||||
|
||||
expr_ref length_limit(expr* s, unsigned k);
|
||||
expr_ref is_digit(expr* ch);
|
||||
|
|
|
@ -33,6 +33,7 @@ skolem::skolem(ast_manager& m, th_rewriter& rw):
|
|||
m_aut_step = "aut.step";
|
||||
m_pre = "seq.pre"; // (seq.pre s l): prefix of string s of length l
|
||||
m_post = "seq.post"; // (seq.post s l): suffix of string s of length k, based on extract starting at index i of length l
|
||||
m_postp = "seq.postp";
|
||||
m_eq = "seq.eq";
|
||||
m_max_unfolding = "seq.max_unfolding";
|
||||
m_length_limit = "seq.length_limit";
|
||||
|
|
|
@ -37,7 +37,8 @@ namespace seq {
|
|||
symbol m_aut_step; // regex unfolding state
|
||||
symbol m_accept; // regex
|
||||
symbol m_is_empty, m_is_non_empty; // regex emptiness check
|
||||
symbol m_pre, m_post; // inverse of at: (pre s i) + (at s i) + (post s i) = s if 0 <= i < (len s)
|
||||
symbol m_pre, m_post; // inverse of at: (pre s i) + (at s i) + (post s i) = s if 0 <= i < (len s)
|
||||
symbol m_postp;
|
||||
symbol m_eq; // equality atom
|
||||
symbol m_max_unfolding, m_length_limit;
|
||||
|
||||
|
@ -84,6 +85,7 @@ namespace seq {
|
|||
|
||||
expr_ref mk_tail(expr* s, expr* i) { return mk(m_tail, s, i); }
|
||||
expr_ref mk_post(expr* s, expr* i) { return mk(m_post, s, i); }
|
||||
expr_ref mk_postp(expr* s, expr* i) { return mk(m_postp, s, i); }
|
||||
expr_ref mk_ite(expr* c, expr* t, expr* e) { return mk(symbol("seq.if"), c, t, e, nullptr, t->get_sort()); }
|
||||
expr_ref mk_last(expr* s);
|
||||
expr_ref mk_first(expr* s);
|
||||
|
|
|
@ -705,6 +705,17 @@ bool seq_decl_plugin::is_value(app* e) const {
|
|||
}
|
||||
}
|
||||
|
||||
bool seq_decl_plugin::is_model_value(app* e) const {
|
||||
if (is_app_of(e, m_family_id, OP_SEQ_EMPTY))
|
||||
return true;
|
||||
if (is_app_of(e, m_family_id, OP_STRING_CONST))
|
||||
return true;
|
||||
if (is_app_of(e, m_family_id, OP_SEQ_UNIT) &&
|
||||
m_manager->is_value(e->get_arg(0)))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool seq_decl_plugin::are_equal(app* a, app* b) const {
|
||||
if (a == b) return true;
|
||||
// handle concatenations
|
||||
|
|
|
@ -179,6 +179,8 @@ public:
|
|||
|
||||
bool is_value(app * e) const override;
|
||||
|
||||
bool is_model_value(app* e) const override;
|
||||
|
||||
bool is_unique_value(app * e) const override;
|
||||
|
||||
bool are_equal(app* a, app* b) const override;
|
||||
|
|
|
@ -406,12 +406,25 @@ void static_features::process(expr * e, bool form_ctx, bool or_and_ctx, bool ite
|
|||
}
|
||||
|
||||
if (stack_depth > m_max_stack_depth) {
|
||||
for (expr* arg : subterms::ground(expr_ref(e, m)))
|
||||
if (get_depth(arg) <= 3 || is_quantifier(arg))
|
||||
process(arg, form_ctx, or_and_ctx, ite_ctx, stack_depth - 10);
|
||||
ptr_vector<expr> todo;
|
||||
todo.push_back(e);
|
||||
for (unsigned i = 0; i < todo.size(); ++i) {
|
||||
e = todo[i];
|
||||
if (is_marked(e))
|
||||
continue;
|
||||
if (is_basic_expr(e)) {
|
||||
mark(e);
|
||||
todo.append(to_app(e)->get_num_args(), to_app(e)->get_args());
|
||||
}
|
||||
else {
|
||||
process(e, form_ctx, or_and_ctx, ite_ctx, stack_depth - 10);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
mark(e);
|
||||
|
||||
update_core(e);
|
||||
|
||||
if (is_quantifier(e)) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue