3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-08 10:25:18 +00:00

seq API, tuning

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2016-01-03 17:16:13 -08:00
parent 8e80fb830b
commit a3c4972c85
3 changed files with 237 additions and 14 deletions

View file

@ -205,6 +205,18 @@ namespace z3 {
\brief Return the Bit-vector sort of size \c sz. That is, the sort for bit-vectors of size \c sz.
*/
sort bv_sort(unsigned sz);
/**
\brief Return the sort for ASCII strings.
*/
sort string_sort();
/**
\brief Return a sequence sort over base sort \c s.
*/
sort seq_sort(sort& s);
/**
\brief Return a regular expression sort over sequences \c seq_sort.
*/
sort re_sort(sort& seq_sort);
/**
\brief Return an array sort for arrays from \c d to \c r.
@ -261,6 +273,9 @@ namespace z3 {
expr bv_val(__uint64 n, unsigned sz);
expr bv_val(char const * n, unsigned sz);
expr string_val(char const* s);
expr string_val(std::string const& s);
expr num_val(int n, sort const & s);
/**
@ -425,6 +440,14 @@ namespace z3 {
\brief Return true if this sort is a Relation sort.
*/
bool is_relation() const { return sort_kind() == Z3_RELATION_SORT; }
/**
\brief Return true if this sort is a Sequence sort.
*/
bool is_seq() const { return sort_kind() == Z3_SEQ_SORT; }
/**
\brief Return true if this sort is a regular expression sort.
*/
bool is_re() const { return sort_kind() == Z3_RE_SORT; }
/**
\brief Return true if this sort is a Finite domain sort.
*/
@ -532,6 +555,15 @@ namespace z3 {
\brief Return true if this is a Relation expression.
*/
bool is_relation() const { return get_sort().is_relation(); }
/**
\brief Return true if this is a sequence expression.
*/
bool is_seq() const { return get_sort().is_seq(); }
/**
\brief Return true if this is a regular expression.
*/
bool is_re() const { return get_sort().is_re(); }
/**
\brief Return true if this is a Finite-domain expression.
@ -663,6 +695,7 @@ namespace z3 {
friend expr distinct(expr_vector const& args);
friend expr concat(expr const& a, expr const& b);
friend expr concat(expr_vector const& args);
friend expr operator==(expr const & a, expr const & b);
friend expr operator==(expr const & a, int b);
@ -728,10 +761,50 @@ namespace z3 {
friend expr operator|(int a, expr const & b);
friend expr operator~(expr const & a);
expr extract(unsigned hi, unsigned lo) const { Z3_ast r = Z3_mk_extract(ctx(), hi, lo, *this); return expr(ctx(), r); }
expr extract(unsigned hi, unsigned lo) const { Z3_ast r = Z3_mk_extract(ctx(), hi, lo, *this); ctx().check_error(); return expr(ctx(), r); }
unsigned lo() const { assert (is_app() && Z3_get_decl_num_parameters(ctx(), decl()) == 2); return static_cast<unsigned>(Z3_get_decl_int_parameter(ctx(), decl(), 1)); }
unsigned hi() const { assert (is_app() && Z3_get_decl_num_parameters(ctx(), decl()) == 2); return static_cast<unsigned>(Z3_get_decl_int_parameter(ctx(), decl(), 0)); }
/**
\brief sequence and regular expression operations.
+ is overloaeded as sequence concatenation and regular expression union.
concat is overloaded to handle sequences and regular expressions
*/
expr extract(expr const& offset, expr const& length) const {
check_context(*this, offset); check_context(offset, length);
Z3_ast r = Z3_mk_seq_extract(ctx(), *this, offset, length); check_error(); return expr(ctx(), r);
}
expr replace(expr const& src, expr const& dst) const {
check_context(*this, src); check_context(src, dst);
Z3_ast r = Z3_mk_seq_replace(ctx(), *this, src, dst);
check_error();
return expr(ctx(), r);
}
expr unit() const {
Z3_ast r = Z3_mk_seq_unit(ctx(), *this);
check_error();
return expr(ctx(), r);
}
expr contains(expr const& s) {
check_context(*this, s);
Z3_ast r = Z3_mk_seq_contains(ctx(), *this, s);
check_error();
return expr(ctx(), r);
}
expr at(expr const& index) const {
check_context(*this, index);
Z3_ast r = Z3_mk_seq_at(ctx(), *this, index);
check_error();
return expr(ctx(), r);
}
expr length() const {
Z3_ast r = Z3_mk_seq_length(ctx(), *this);
check_error();
return expr(ctx(), r);
}
/**
\brief Return a simplified version of this expression.
*/
@ -835,6 +908,13 @@ namespace z3 {
else if (a.is_bv() && b.is_bv()) {
r = Z3_mk_bvadd(a.ctx(), a, b);
}
else if (a.is_seq() && b.is_seq()) {
return concat(a, b);
}
else if (a.is_re() && b.is_re()) {
Z3_ast _args[2] = { a, b };
r = Z3_mk_re_union(a.ctx(), 2, _args);
}
else {
// operator is not supported by given arguments.
assert(false);
@ -1219,11 +1299,48 @@ namespace z3 {
inline expr concat(expr const& a, expr const& b) {
check_context(a, b);
Z3_ast r = Z3_mk_concat(a.ctx(), a, b);
Z3_ast r;
if (Z3_is_seq_sort(a.ctx(), a.get_sort())) {
Z3_ast _args[2] = { a, b };
r = Z3_mk_seq_concat(a.ctx(), 2, _args);
}
else if (Z3_is_re_sort(a.ctx(), a.get_sort())) {
Z3_ast _args[2] = { a, b };
r = Z3_mk_re_concat(a.ctx(), 2, _args);
}
else {
r = Z3_mk_concat(a.ctx(), a, b);
}
a.ctx().check_error();
return expr(a.ctx(), r);
}
inline expr concat(expr_vector const& args) {
Z3_ast r;
assert(args.size() > 0);
if (args.size() == 1) {
return args[0];
}
context& ctx = args[0].ctx();
array<Z3_ast> _args(args);
if (Z3_is_seq_sort(ctx, args[0].get_sort())) {
r = Z3_mk_seq_concat(ctx, _args.size(), _args.ptr());
}
else if (Z3_is_re_sort(ctx, args[0].get_sort())) {
r = Z3_mk_re_concat(ctx, _args.size(), _args.ptr());
}
else {
r = _args[args.size()-1];
for (unsigned i = args.size()-1; i > 0; ) {
--i;
r = Z3_mk_concat(ctx, _args[i], r);
ctx.check_error();
}
}
ctx.check_error();
return expr(ctx, r);
}
class func_entry : public object {
Z3_func_entry m_entry;
void init(Z3_func_entry e) {
@ -1762,6 +1879,10 @@ namespace z3 {
inline sort context::int_sort() { Z3_sort s = Z3_mk_int_sort(m_ctx); check_error(); return sort(*this, s); }
inline sort context::real_sort() { Z3_sort s = Z3_mk_real_sort(m_ctx); check_error(); return sort(*this, s); }
inline sort context::bv_sort(unsigned sz) { Z3_sort s = Z3_mk_bv_sort(m_ctx, sz); check_error(); return sort(*this, s); }
inline sort context::string_sort() { Z3_sort s = Z3_mk_string_sort(m_ctx); check_error(); return sort(*this, s); }
inline sort context::seq_sort(sort& s) { Z3_sort r = Z3_mk_seq_sort(m_ctx, s); check_error(); return sort(*this, r); }
inline sort context::re_sort(sort& s) { Z3_sort r = Z3_mk_re_sort(m_ctx, s); check_error(); return sort(*this, r); }
inline sort context::array_sort(sort d, sort r) { Z3_sort s = Z3_mk_array_sort(m_ctx, d, r); check_error(); return sort(*this, s); }
inline sort context::enumeration_sort(char const * name, unsigned n, char const * const * enum_names, func_decl_vector & cs, func_decl_vector & ts) {
array<Z3_symbol> _enum_names(n);
@ -1885,6 +2006,9 @@ namespace z3 {
inline expr context::bv_val(__uint64 n, unsigned sz) { Z3_ast r = Z3_mk_unsigned_int64(m_ctx, n, bv_sort(sz)); check_error(); return expr(*this, r); }
inline expr context::bv_val(char const * n, unsigned sz) { Z3_ast r = Z3_mk_numeral(m_ctx, n, bv_sort(sz)); check_error(); return expr(*this, r); }
inline expr context::string_val(char const* s) { Z3_ast r = Z3_mk_string(m_ctx, s); check_error(); return expr(*this, r); }
inline expr context::string_val(std::string const& s) { Z3_ast r = Z3_mk_string(m_ctx, s.c_str()); check_error(); return expr(*this, r); }
inline expr context::num_val(int n, sort const & s) { Z3_ast r = Z3_mk_int(m_ctx, n, s); check_error(); return expr(*this, r); }
inline expr func_decl::operator()(unsigned n, expr const * args) const {
@ -2017,6 +2141,62 @@ namespace z3 {
d.check_error();
return expr(d.ctx(), r);
}
// sequence and regular expression operations.
// union is +
// concat is overloaded to handle sequences and regular expressions
inline expr empty(sort const& s) {
Z3_ast r = Z3_mk_seq_empty(s.ctx(), s);
s.check_error();
return expr(s.ctx(), r);
}
inline expr suffixof(expr const& a, expr const& b) {
check_context(a, b);
Z3_ast r = Z3_mk_seq_suffix(a.ctx(), a, b);
a.check_error();
return expr(a.ctx(), r);
}
inline expr prefixof(expr const& a, expr const& b) {
check_context(a, b);
Z3_ast r = Z3_mk_seq_prefix(a.ctx(), a, b);
a.check_error();
return expr(a.ctx(), r);
}
inline expr indexof(expr const& s, expr const& substr, expr const& offset) {
check_context(s, substr); check_context(s, offset);
Z3_ast r = Z3_mk_seq_index(s.ctx(), s, substr, offset);
s.check_error();
return expr(s.ctx(), r);
}
inline expr to_re(expr const& s) {
Z3_ast r = Z3_mk_seq_to_re(s.ctx(), s);
s.check_error();
return expr(s.ctx(), r);
}
inline expr in_re(expr const& s, expr const& re) {
check_context(s, re);
Z3_ast r = Z3_mk_seq_in_re(s.ctx(), s, re);
s.check_error();
return expr(s.ctx(), r);
}
inline expr plus(expr const& re) {
Z3_ast r = Z3_mk_re_plus(re.ctx(), re);
re.check_error();
return expr(re.ctx(), r);
}
inline expr option(expr const& re) {
Z3_ast r = Z3_mk_re_option(re.ctx(), re);
re.check_error();
return expr(re.ctx(), r);
}
inline expr star(expr const& re) {
Z3_ast r = Z3_mk_re_star(re.ctx(), re);
re.check_error();
return expr(re.ctx(), r);
}
inline expr interpolant(expr const& a) {
return expr(a.ctx(), Z3_mk_interpolant(a.ctx(), a));
}

View file

@ -292,7 +292,8 @@ public:
// Generalized:
// Src - E -> dst - t -> dst1 => Src - t -> dst1 if dst is final => each Src is final
//
// src - e -> dst - ET -> dst1 => src - ET - dst1 if in_degree(dst) = 1, src != dst
// src - e -> dst - ET -> Dst1 => src - ET -> Dst1 if in_degree(dst) = 1, src != dst
// Src - E -> dst - et -> dst1 => Src - et -> dst1 if out_degree(dst) = 1, src != dst
//
void compress() {
for (unsigned i = 0; i < m_delta.size(); ++i) {
@ -339,24 +340,42 @@ public:
add(mvs1[k]);
}
}
else if (false && 1 == out_degree(dst) && all_epsilon_in(dst) && init() != dst && !is_final_state(dst)) {
//
// Src - E -> dst - et -> dst1 => Src - et -> dst1 if out_degree(dst) = 1, src != dst
//
else if (1 == out_degree(dst) && all_epsilon_in(dst) && init() != dst && !is_final_state(dst)) {
move const& mv = m_delta[dst][0];
T* t = mv.t();
unsigned dst1 = mv.dst();
T* t = mv.t();
unsigned_vector src0s;
moves const& mvs = m_delta_inv[dst];
moves mvs1;
for (unsigned k = 0; k < mvs.size(); ++k) {
SASSERT(mvs[k].is_epsilon());
src0s.push_back(mvs[k].src());
mvs1.push_back(move(m, mvs[k].src(), dst1, t));
}
for (unsigned k = 0; k < src0s.size(); ++k) {
remove(src0s[k], dst, 0);
add(move(m, src0s[i], dst1, t));
for (unsigned k = 0; k < mvs1.size(); ++k) {
remove(mvs1[k].src(), dst, 0);
add(mvs1[k]);
}
remove(dst, dst1, t);
--j;
continue;
}
//
// Src1 - ET -> src - e -> dst => Src1 - ET -> dst if out_degree(src) = 1, src != init()
//
else if (1 == out_degree(src) && init() != src && (!is_final_state(src) || is_final_state(dst))) {
moves const& mvs = m_delta_inv[src];
moves mvs1;
for (unsigned k = 0; k < mvs.size(); ++k) {
mvs1.push_back(move(m, mvs[k].src(), dst, mvs[k].t()));
}
for (unsigned k = 0; k < mvs1.size(); ++k) {
remove(mvs1[k].src(), src, mvs1[k].t());
add(mvs1[k]);
}
}
else {
continue;
}
@ -482,7 +501,7 @@ private:
void remove_dead_states() {
unsigned_vector remap;
for (unsigned i = 0; i < m_delta.size(); ++i) {
}
}

View file

@ -373,14 +373,12 @@ bool theory_seq::propagate_length_coherence(expr* e) {
expr_ref high1(m_autil.mk_le(m_util.str.mk_length(e), m_autil.mk_numeral(hi, true)), m);
expr_ref high2(m_autil.mk_le(m_util.str.mk_length(seq), m_autil.mk_numeral(hi-lo, true)), m);
add_axiom(~mk_literal(high1), mk_literal(high2));
m_trail_stack.push(push_replay(alloc(replay_length_coherence, m, e)));
}
m_trail_stack.push(push_replay(alloc(replay_length_coherence, m, e)));
return true;
}
bool theory_seq::check_length_coherence() {
bool coherent = true;
obj_hashtable<expr>::iterator it = m_length.begin(), end = m_length.end();
for (; it != end; ++it) {
expr* e = *it;
@ -398,7 +396,7 @@ bool theory_seq::check_length_coherence() {
return false;
}
}
return coherent;
return true;
}
/*
@ -890,6 +888,23 @@ void theory_seq::solve_ne(unsigned idx) {
set_conflict(n.m_dep, lits);
SASSERT(m_new_propagation);
}
if (num_undef_lits == 0 && n.m_lhs.size() == 1) {
expr* l = n.m_lhs[0];
expr* r = n.m_rhs[0];
if (m_util.str.is_empty(r)) {
std::swap(l, r);
}
if (m_util.str.is_empty(l) && is_var(r)) {
literal lit = ~mk_eq_empty(r);
if (ctx.get_assignment(lit) == l_true) {
expr_ref head(m), tail(m);
mk_decompose(r, head, tail);
expr_ref conc(m_util.str.mk_concat(head, tail), m);
propagate_is_conc(r, conc);
}
m_new_propagation = true;
}
}
}
@ -2171,6 +2186,15 @@ bool theory_seq::add_accept2step(expr* acc) {
break;
}
}
if (has_undef && mvs.size() == 1) {
literal lit = lits.back();
lits.pop_back();
for (unsigned i = 0; i < lits.size(); ++i) {
lits[i].neg();
}
propagate_lit(0, lits.size(), lits.c_ptr(), lit);
return false;
}
if (has_undef) {
return true;
}