Skip to content

Commit 584eee2

Browse files
fixing #2448 and #2445 and #2443
Signed-off-by: Nikolaj Bjorner <[email protected]>
1 parent c448033 commit 584eee2

File tree

6 files changed

+43
-57
lines changed

6 files changed

+43
-57
lines changed

src/ast/rewriter/seq_rewriter.cpp

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -478,11 +478,12 @@ br_status seq_rewriter::mk_app_core(func_decl * f, unsigned num_args, expr * con
478478
SASSERT(num_args == 2);
479479
st = mk_seq_at(args[0], args[1], result);
480480
break;
481-
#if 1
482481
case OP_SEQ_NTH:
483482
SASSERT(num_args == 2);
484483
return mk_seq_nth(args[0], args[1], result);
485-
#endif
484+
case OP_SEQ_NTH_I:
485+
SASSERT(num_args == 2);
486+
return mk_seq_nth_i(args[0], args[1], result);
486487
case OP_SEQ_PREFIX:
487488
SASSERT(num_args == 2);
488489
st = mk_seq_prefix(args[0], args[1], result);
@@ -991,6 +992,16 @@ br_status seq_rewriter::mk_seq_at(expr* a, expr* b, expr_ref& result) {
991992
}
992993

993994
br_status seq_rewriter::mk_seq_nth(expr* a, expr* b, expr_ref& result) {
995+
expr* es[2] = { a, b};
996+
expr* la = m_util.str.mk_length(a);
997+
result = m().mk_ite(m().mk_and(m_autil.mk_le(m_autil.mk_int(0), b), m_autil.mk_lt(b, la)),
998+
m().mk_app(m_util.get_family_id(), OP_SEQ_NTH_I, 2, es),
999+
m().mk_app(m_util.get_family_id(), OP_SEQ_NTH_U, 2, es));
1000+
return BR_REWRITE_FULL;
1001+
}
1002+
1003+
1004+
br_status seq_rewriter::mk_seq_nth_i(expr* a, expr* b, expr_ref& result) {
9941005
zstring c;
9951006
rational r;
9961007
if (!m_autil.is_numeral(b, r) || !r.is_unsigned()) {

src/ast/rewriter/seq_rewriter.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ class seq_rewriter {
115115
br_status mk_seq_contains(expr* a, expr* b, expr_ref& result);
116116
br_status mk_seq_at(expr* a, expr* b, expr_ref& result);
117117
br_status mk_seq_nth(expr* a, expr* b, expr_ref& result);
118+
br_status mk_seq_nth_i(expr* a, expr* b, expr_ref& result);
118119
br_status mk_seq_index(expr* a, expr* b, expr* c, expr_ref& result);
119120
br_status mk_seq_last_index(expr* a, expr* b, expr_ref& result);
120121
br_status mk_seq_replace(expr* a, expr* b, expr* c, expr_ref& result);

src/ast/seq_decl_plugin.cpp

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -559,6 +559,8 @@ void seq_decl_plugin::init() {
559559
m_sigs[OP_SEQ_LAST_INDEX] = alloc(psig, m, "seq.last_indexof", 1, 2, seqAseqA, intT);
560560
m_sigs[OP_SEQ_AT] = alloc(psig, m, "seq.at", 1, 2, seqAintT, seqA);
561561
m_sigs[OP_SEQ_NTH] = alloc(psig, m, "seq.nth", 1, 2, seqAintT, A);
562+
m_sigs[OP_SEQ_NTH_I] = alloc(psig, m, "seq.nth_i", 1, 2, seqAintT, A);
563+
m_sigs[OP_SEQ_NTH_U] = alloc(psig, m, "seq.nth_u", 1, 2, seqAintT, A);
562564
m_sigs[OP_SEQ_LENGTH] = alloc(psig, m, "seq.len", 1, 1, &seqA, intT);
563565
m_sigs[OP_RE_PLUS] = alloc(psig, m, "re.+", 1, 1, &reA, reA);
564566
m_sigs[OP_RE_STAR] = alloc(psig, m, "re.*", 1, 1, &reA, reA);
@@ -852,6 +854,8 @@ func_decl * seq_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters,
852854
return mk_str_fun(k, arity, domain, range, OP_SEQ_AT);
853855

854856
case OP_SEQ_NTH:
857+
case OP_SEQ_NTH_I:
858+
case OP_SEQ_NTH_U:
855859
match(*m_sigs[k], arity, domain, range, rng);
856860
return m.mk_func_decl(m_sigs[k]->m_name, arity, domain, rng, func_decl_info(m_family_id, k));
857861

@@ -1035,14 +1039,14 @@ bool seq_util::str::is_string(expr const* n, zstring& s) const {
10351039
}
10361040
}
10371041

1038-
bool seq_util::str::is_nth(expr const* n, expr*& s, unsigned& idx) const {
1042+
bool seq_util::str::is_nth_i(expr const* n, expr*& s, unsigned& idx) const {
10391043
expr* i = nullptr;
1040-
if (!is_nth(n, s, i)) return false;
1044+
if (!is_nth_i(n, s, i)) return false;
10411045
return arith_util(m).is_unsigned(i, idx);
10421046
}
10431047

1044-
app* seq_util::str::mk_nth(expr* s, unsigned i) const {
1045-
return mk_nth(s, arith_util(m).mk_int(i));
1048+
app* seq_util::str::mk_nth_i(expr* s, unsigned i) const {
1049+
return mk_nth_i(s, arith_util(m).mk_int(i));
10461050
}
10471051

10481052
void seq_util::str::get_concat(expr* e, expr_ref_vector& es) const {

src/ast/seq_decl_plugin.h

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ enum seq_op_kind {
4141
OP_SEQ_REPLACE,
4242
OP_SEQ_AT,
4343
OP_SEQ_NTH,
44+
OP_SEQ_NTH_I,
45+
OP_SEQ_NTH_U,
4446
OP_SEQ_LENGTH,
4547
OP_SEQ_INDEX,
4648
OP_SEQ_LAST_INDEX,
@@ -259,8 +261,8 @@ class seq_util {
259261
expr* mk_concat(expr_ref_vector const& es) const { return mk_concat(es.size(), es.c_ptr()); }
260262
app* mk_length(expr* a) const { return m.mk_app(m_fid, OP_SEQ_LENGTH, 1, &a); }
261263
app* mk_at(expr* s, expr* i) const { expr* es[2] = { s, i }; return m.mk_app(m_fid, OP_SEQ_AT, 2, es); }
262-
app* mk_nth(expr* s, expr* i) const { expr* es[2] = { s, i }; return m.mk_app(m_fid, OP_SEQ_NTH, 2, es); }
263-
app* mk_nth(expr* s, unsigned i) const;
264+
app* mk_nth_i(expr* s, expr* i) const { expr* es[2] = { s, i }; return m.mk_app(m_fid, OP_SEQ_NTH_I, 2, es); }
265+
app* mk_nth_i(expr* s, unsigned i) const;
264266

265267
app* mk_substr(expr* a, expr* b, expr* c) const { expr* es[3] = { a, b, c }; return m.mk_app(m_fid, OP_SEQ_EXTRACT, 3, es); }
266268
app* mk_contains(expr* a, expr* b) const { expr* es[2] = { a, b }; return m.mk_app(m_fid, OP_SEQ_CONTAINS, 2, es); }
@@ -277,7 +279,8 @@ class seq_util {
277279
app* mk_lex_le(expr* a, expr* b) const { expr* es[2] = { a, b }; return m.mk_app(m_fid, OP_STRING_LE, 2, es); }
278280

279281

280-
bool is_nth(func_decl* f) const { return is_decl_of(f, m_fid, OP_SEQ_NTH); }
282+
bool is_nth_i(func_decl* f) const { return is_decl_of(f, m_fid, OP_SEQ_NTH_I); }
283+
bool is_nth_u(func_decl* f) const { return is_decl_of(f, m_fid, OP_SEQ_NTH_U); }
281284

282285
bool is_string(expr const * n) const { return is_app_of(n, m_fid, OP_STRING_CONST); }
283286
bool is_string(expr const* n, symbol& s) const {
@@ -292,8 +295,9 @@ class seq_util {
292295
bool is_extract(expr const* n) const { return is_app_of(n, m_fid, OP_SEQ_EXTRACT); }
293296
bool is_contains(expr const* n) const { return is_app_of(n, m_fid, OP_SEQ_CONTAINS); }
294297
bool is_at(expr const* n) const { return is_app_of(n, m_fid, OP_SEQ_AT); }
295-
bool is_nth(expr const* n) const { return is_app_of(n, m_fid, OP_SEQ_NTH); }
296-
bool is_nth(expr const* n, expr*& s, unsigned& idx) const;
298+
bool is_nth_i(expr const* n) const { return is_app_of(n, m_fid, OP_SEQ_NTH_I); }
299+
bool is_nth_u(expr const* n) const { return is_app_of(n, m_fid, OP_SEQ_NTH_U); }
300+
bool is_nth_i(expr const* n, expr*& s, unsigned& idx) const;
297301
bool is_index(expr const* n) const { return is_app_of(n, m_fid, OP_SEQ_INDEX); }
298302
bool is_last_index(expr const* n) const { return is_app_of(n, m_fid, OP_SEQ_LAST_INDEX); }
299303
bool is_replace(expr const* n) const { return is_app_of(n, m_fid, OP_SEQ_REPLACE); }
@@ -321,7 +325,8 @@ class seq_util {
321325
MATCH_TERNARY(is_extract);
322326
MATCH_BINARY(is_contains);
323327
MATCH_BINARY(is_at);
324-
MATCH_BINARY(is_nth);
328+
MATCH_BINARY(is_nth_i);
329+
MATCH_BINARY(is_nth_u);
325330
MATCH_BINARY(is_index);
326331
MATCH_TERNARY(is_index);
327332
MATCH_BINARY(is_last_index);

src/smt/theory_seq.cpp

Lines changed: 9 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,6 @@ theory_seq::theory_seq(ast_manager& m, theory_seq_params const & params):
274274
m_overlap(m),
275275
m_overlap2(m),
276276
m_len_prop_lvl(-1),
277-
m_internal_nth_es(m),
278277
m_factory(nullptr),
279278
m_exclude(m),
280279
m_axioms(m),
@@ -1985,16 +1984,9 @@ bool theory_seq::propagate_is_conc(expr* e, expr* conc) {
19851984

19861985
bool theory_seq::is_unit_nth(expr* e) const {
19871986
expr *s = nullptr;
1988-
return m_util.str.is_unit(e, s) && is_nth(s);
1987+
return m_util.str.is_unit(e, s) && m_util.str.is_nth_i(s);
19891988
}
19901989

1991-
bool theory_seq::is_nth(expr* e) const {
1992-
return m_util.str.is_nth(e);
1993-
}
1994-
1995-
bool theory_seq::is_nth(expr* e, expr*& e1, expr*& e2) const {
1996-
return m_util.str.is_nth(e, e1, e2);
1997-
}
19981990

19991991
bool theory_seq::is_tail(expr* e, expr*& s, unsigned& idx) const {
20001992
rational r;
@@ -2017,14 +2009,8 @@ bool theory_seq::is_post(expr* e, expr*& s, expr*& i) {
20172009
return is_skolem(m_post, e) && (s = to_app(e)->get_arg(0), i = to_app(e)->get_arg(1), true);
20182010
}
20192011

2020-
2021-
20222012
expr_ref theory_seq::mk_nth(expr* s, expr* idx) {
2023-
expr_ref result(m_util.str.mk_nth(s, idx), m);
2024-
if (!m_internal_nth_table.contains(result)) {
2025-
m_internal_nth_table.insert(result);
2026-
m_internal_nth_es.push_back(result);
2027-
}
2013+
expr_ref result(m_util.str.mk_nth_i(s, idx), m);
20282014
return result;
20292015
}
20302016

@@ -2445,7 +2431,7 @@ bool theory_seq::solve_nth_eq(expr_ref_vector const& ls, expr_ref_vector const&
24452431
for (unsigned i = 0; i < rs.size(); ++i) {
24462432
unsigned k = 0;
24472433
expr* ru = nullptr, *r = nullptr;
2448-
if (m_util.str.is_unit(rs.get(i), ru) && m_util.str.is_nth(ru, r, k) && k == i && r == l) {
2434+
if (m_util.str.is_unit(rs.get(i), ru) && m_util.str.is_nth_i(ru, r, k) && k == i && r == l) {
24492435
continue;
24502436
}
24512437
return false;
@@ -2461,10 +2447,6 @@ bool theory_seq::solve_unit_eq(expr_ref_vector const& l, expr_ref_vector const&
24612447
if (r.size() == 1 && is_var(r[0]) && !occurs(r[0], l) && add_solution(r[0], mk_concat(l, m.get_sort(r[0])), deps)) {
24622448
return true;
24632449
}
2464-
// if (l.size() == 1 && r.size() == 1 && l[0] != r[0] && is_nth(l[0]) && add_solution(l[0], r[0], deps))
2465-
// return true;
2466-
// if (l.size() == 1 && r.size() == 1 && l[0] != r[0] && is_nth(r[0]) && add_solution(r[0], l[0], deps))
2467-
// return true;
24682450

24692451
return false;
24702452
}
@@ -2493,10 +2475,6 @@ bool theory_seq::solve_unit_eq(expr* l, expr* r, dependency* deps) {
24932475
if (is_var(r) && !occurs(r, l) && add_solution(r, l, deps)) {
24942476
return true;
24952477
}
2496-
// if (is_nth(l) && !occurs(l, r) && add_solution(l, r, deps))
2497-
// return true;
2498-
// if (is_nth(r) && !occurs(r, l) && add_solution(r, l, deps))
2499-
// return true;
25002478

25012479
return false;
25022480
}
@@ -2529,7 +2507,7 @@ bool theory_seq::occurs(expr* a, expr* b) {
25292507
else if (m_util.str.is_unit(b, e1)) {
25302508
m_todo.push_back(e1);
25312509
}
2532-
else if (m_util.str.is_nth(b, e1, e2)) {
2510+
else if (m_util.str.is_nth_i(b, e1, e2)) {
25332511
m_todo.push_back(e1);
25342512
}
25352513
}
@@ -4440,7 +4418,7 @@ void theory_seq::deque_axiom(expr* n) {
44404418
else if (m_util.str.is_at(n)) {
44414419
add_at_axiom(n);
44424420
}
4443-
else if (m_util.str.is_nth(n)) {
4421+
else if (m_util.str.is_nth_i(n)) {
44444422
add_nth_axiom(n);
44454423
}
44464424
else if (m_util.str.is_string(n)) {
@@ -5207,12 +5185,12 @@ void theory_seq::add_nth_axiom(expr* e) {
52075185
expr* s = nullptr, *i = nullptr;
52085186
rational n;
52095187
zstring str;
5210-
VERIFY(m_util.str.is_nth(e, s, i));
5188+
VERIFY(m_util.str.is_nth_i(e, s, i));
52115189
if (m_util.str.is_string(s, str) && m_autil.is_numeral(i, n) && n.is_unsigned() && n.get_unsigned() < str.length()) {
52125190
app_ref ch(m_util.str.mk_char(str[n.get_unsigned()]), m);
52135191
add_axiom(mk_eq(ch, e, false));
52145192
}
5215-
else if (!m_internal_nth_table.contains(e)) {
5193+
else {
52165194
expr_ref zero(m_autil.mk_int(0), m);
52175195
literal i_ge_0 = mk_simplified_literal(m_autil.mk_ge(i, zero));
52185196
literal i_ge_len_s = mk_simplified_literal(m_autil.mk_ge(mk_sub(i, mk_len(s)), zero));
@@ -5563,7 +5541,7 @@ void theory_seq::assign_eh(bool_var v, bool is_true) {
55635541
else if (m_util.str.is_lt(e) || m_util.str.is_le(e)) {
55645542
m_lts.push_back(e);
55655543
}
5566-
else if (is_nth(e)) {
5544+
else if (m_util.str.is_nth_i(e)) {
55675545
// no-op
55685546
}
55695547
else {
@@ -5693,7 +5671,6 @@ void theory_seq::push_scope_eh() {
56935671
m_nqs.push_scope();
56945672
m_ncs.push_scope();
56955673
m_lts.push_scope();
5696-
m_internal_nth_lim.push_back(m_internal_nth_es.size());
56975674
}
56985675

56995676
void theory_seq::pop_scope_eh(unsigned num_scopes) {
@@ -5715,12 +5692,6 @@ void theory_seq::pop_scope_eh(unsigned num_scopes) {
57155692
m_len_prop_lvl = ctx.get_scope_level();
57165693
m_len_offset.reset();
57175694
}
5718-
unsigned old_sz = m_internal_nth_lim[m_internal_nth_lim.size() - num_scopes];
5719-
for (unsigned i = m_internal_nth_es.size(); i-- > old_sz; ) {
5720-
m_internal_nth_table.erase(m_internal_nth_es.get(i));
5721-
}
5722-
m_internal_nth_es.shrink(old_sz);
5723-
m_internal_nth_lim.shrink(m_internal_nth_lim.size() - num_scopes);
57245695
}
57255696

57265697
void theory_seq::restart_eh() {
@@ -5731,7 +5702,7 @@ void theory_seq::relevant_eh(app* n) {
57315702
m_util.str.is_replace(n) ||
57325703
m_util.str.is_extract(n) ||
57335704
m_util.str.is_at(n) ||
5734-
m_util.str.is_nth(n) ||
5705+
m_util.str.is_nth_i(n) ||
57355706
m_util.str.is_empty(n) ||
57365707
m_util.str.is_string(n) ||
57375708
m_util.str.is_itos(n) ||

src/smt/theory_seq.h

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -338,10 +338,6 @@ namespace smt {
338338
obj_map<enode, obj_map<enode, int>> m_len_offset;
339339
int m_len_prop_lvl;
340340

341-
obj_hashtable<expr> m_internal_nth_table;
342-
expr_ref_vector m_internal_nth_es;
343-
unsigned_vector m_internal_nth_lim;
344-
345341
seq_factory* m_factory; // value factory
346342
exclusion_table m_exclude; // set of asserted disequalities.
347343
expr_ref_vector m_axioms; // list of axioms to add.
@@ -399,7 +395,7 @@ namespace smt {
399395
void add_theory_assumptions(expr_ref_vector & assumptions) override;
400396
theory* mk_fresh(context* new_ctx) override { return alloc(theory_seq, new_ctx->get_manager(), m_params); }
401397
char const * get_name() const override { return "seq"; }
402-
bool include_func_interp(func_decl* f) override { return false; } // m_util.str.is_nth(f); }
398+
bool include_func_interp(func_decl* f) override { return m_util.str.is_nth_u(f); }
403399
theory_var mk_var(enode* n) override;
404400
void apply_sort_cnstr(enode* n, sort* s) override;
405401
void display(std::ostream & out) const override;
@@ -532,8 +528,6 @@ namespace smt {
532528
bool is_var(expr* b) const;
533529
bool add_solution(expr* l, expr* r, dependency* dep);
534530
bool is_unit_nth(expr* a) const;
535-
bool is_nth(expr* a) const;
536-
bool is_nth(expr* a, expr*& e1, expr*& e2) const;
537531
bool is_tail(expr* a, expr*& s, unsigned& idx) const;
538532
bool is_eq(expr* e, expr*& a, expr*& b) const;
539533
bool is_pre(expr* e, expr*& s, expr*& i);

0 commit comments

Comments
 (0)