GCC Code Coverage Report
Directory: . Exec Total Coverage
File: test/unit/theory/sequences_rewriter_white.cpp Lines: 760 760 100.0 %
Date: 2021-09-10 Branches: 2465 5282 46.7 %

Line Exec Source
1
/******************************************************************************
2
 * Top contributors (to current version):
3
 *   Aina Niemetz, Andres Noetzli, Andrew Reynolds
4
 *
5
 * This file is part of the cvc5 project.
6
 *
7
 * Copyright (c) 2009-2021 by the authors listed in the file AUTHORS
8
 * in the top-level source directory and their institutional affiliations.
9
 * All rights reserved.  See the file COPYING in the top-level source
10
 * directory for licensing information.
11
 * ****************************************************************************
12
 *
13
 * Unit tests for the strings/sequences rewriter.
14
 */
15
16
#include <iostream>
17
#include <memory>
18
#include <vector>
19
20
#include "expr/node.h"
21
#include "expr/node_manager.h"
22
#include "test_smt.h"
23
#include "theory/rewriter.h"
24
#include "theory/strings/arith_entail.h"
25
#include "theory/strings/sequences_rewriter.h"
26
#include "theory/strings/strings_entail.h"
27
#include "theory/strings/strings_rewriter.h"
28
#include "util/rational.h"
29
#include "util/string.h"
30
31
namespace cvc5 {
32
33
using namespace theory;
34
using namespace theory::strings;
35
36
namespace test {
37
38
68
class TestTheoryWhiteSequencesRewriter : public TestSmt
39
{
40
 protected:
41
34
  void SetUp() override
42
  {
43
34
    TestSmt::SetUp();
44
68
    Options opts;
45
34
    d_rewriter = d_smtEngine->getRewriter();
46
34
  }
47
48
  Rewriter* d_rewriter;
49
50
4
  void inNormalForm(Node t)
51
  {
52
8
    Node res_t = d_rewriter->extendedRewrite(t);
53
54
4
    std::cout << std::endl;
55
4
    std::cout << t << " ---> " << res_t << std::endl;
56
4
    ASSERT_EQ(t, res_t);
57
  }
58
59
178
  void sameNormalForm(Node t1, Node t2)
60
  {
61
356
    Node res_t1 = d_rewriter->extendedRewrite(t1);
62
356
    Node res_t2 = d_rewriter->extendedRewrite(t2);
63
64
178
    std::cout << std::endl;
65
178
    std::cout << t1 << " ---> " << res_t1 << std::endl;
66
178
    std::cout << t2 << " ---> " << res_t2 << std::endl;
67
178
    ASSERT_EQ(res_t1, res_t2);
68
  }
69
70
16
  void differentNormalForms(Node t1, Node t2)
71
  {
72
32
    Node res_t1 = d_rewriter->extendedRewrite(t1);
73
32
    Node res_t2 = d_rewriter->extendedRewrite(t2);
74
75
16
    std::cout << std::endl;
76
16
    std::cout << t1 << " ---> " << res_t1 << std::endl;
77
16
    std::cout << t2 << " ---> " << res_t2 << std::endl;
78
16
    ASSERT_NE(res_t1, res_t2);
79
  }
80
};
81
82
26
TEST_F(TestTheoryWhiteSequencesRewriter, check_entail_length_one)
83
{
84
4
  TypeNode intType = d_nodeManager->integerType();
85
4
  TypeNode strType = d_nodeManager->stringType();
86
87
4
  Node a = d_nodeManager->mkConst(::cvc5::String("A"));
88
4
  Node abcd = d_nodeManager->mkConst(::cvc5::String("ABCD"));
89
4
  Node aaad = d_nodeManager->mkConst(::cvc5::String("AAAD"));
90
4
  Node b = d_nodeManager->mkConst(::cvc5::String("B"));
91
4
  Node x = d_nodeManager->mkVar("x", strType);
92
4
  Node y = d_nodeManager->mkVar("y", strType);
93
4
  Node negOne = d_nodeManager->mkConst(Rational(-1));
94
4
  Node zero = d_nodeManager->mkConst(Rational(0));
95
4
  Node one = d_nodeManager->mkConst(Rational(1));
96
4
  Node two = d_nodeManager->mkConst(Rational(2));
97
4
  Node three = d_nodeManager->mkConst(Rational(3));
98
4
  Node i = d_nodeManager->mkVar("i", intType);
99
100
2
  ASSERT_TRUE(StringsEntail::checkLengthOne(a));
101
2
  ASSERT_TRUE(StringsEntail::checkLengthOne(a, true));
102
103
4
  Node substr = d_nodeManager->mkNode(kind::STRING_SUBSTR, x, zero, one);
104
2
  ASSERT_TRUE(StringsEntail::checkLengthOne(substr));
105
2
  ASSERT_FALSE(StringsEntail::checkLengthOne(substr, true));
106
107
2
  substr =
108
8
      d_nodeManager->mkNode(kind::STRING_SUBSTR,
109
4
                            d_nodeManager->mkNode(kind::STRING_CONCAT, a, x),
110
                            zero,
111
                            one);
112
2
  ASSERT_TRUE(StringsEntail::checkLengthOne(substr));
113
2
  ASSERT_TRUE(StringsEntail::checkLengthOne(substr, true));
114
115
2
  substr = d_nodeManager->mkNode(kind::STRING_SUBSTR, x, zero, two);
116
2
  ASSERT_FALSE(StringsEntail::checkLengthOne(substr));
117
2
  ASSERT_FALSE(StringsEntail::checkLengthOne(substr, true));
118
}
119
120
26
TEST_F(TestTheoryWhiteSequencesRewriter, check_entail_arith)
121
{
122
4
  TypeNode intType = d_nodeManager->integerType();
123
4
  TypeNode strType = d_nodeManager->stringType();
124
125
4
  Node z = d_nodeManager->mkVar("z", strType);
126
4
  Node n = d_nodeManager->mkVar("n", intType);
127
4
  Node one = d_nodeManager->mkConst(Rational(1));
128
129
  // 1 >= (str.len (str.substr z n 1)) ---> true
130
  Node substr_z = d_nodeManager->mkNode(
131
      kind::STRING_LENGTH,
132
4
      d_nodeManager->mkNode(kind::STRING_SUBSTR, z, n, one));
133
2
  ASSERT_TRUE(ArithEntail::check(one, substr_z));
134
135
  // (str.len (str.substr z n 1)) >= 1 ---> false
136
2
  ASSERT_FALSE(ArithEntail::check(substr_z, one));
137
}
138
139
26
TEST_F(TestTheoryWhiteSequencesRewriter, check_entail_with_with_assumption)
140
{
141
4
  TypeNode intType = d_nodeManager->integerType();
142
4
  TypeNode strType = d_nodeManager->stringType();
143
144
4
  Node x = d_nodeManager->mkVar("x", intType);
145
4
  Node y = d_nodeManager->mkVar("y", strType);
146
4
  Node z = d_nodeManager->mkVar("z", intType);
147
148
4
  Node zero = d_nodeManager->mkConst(Rational(0));
149
4
  Node one = d_nodeManager->mkConst(Rational(1));
150
151
4
  Node empty = d_nodeManager->mkConst(::cvc5::String(""));
152
4
  Node a = d_nodeManager->mkConst(::cvc5::String("A"));
153
154
4
  Node slen_y = d_nodeManager->mkNode(kind::STRING_LENGTH, y);
155
4
  Node x_plus_slen_y = d_nodeManager->mkNode(kind::PLUS, x, slen_y);
156
  Node x_plus_slen_y_eq_zero = d_rewriter->rewrite(
157
4
      d_nodeManager->mkNode(kind::EQUAL, x_plus_slen_y, zero));
158
159
  // x + (str.len y) = 0 |= 0 >= x --> true
160
2
  ASSERT_TRUE(
161
2
      ArithEntail::checkWithAssumption(x_plus_slen_y_eq_zero, zero, x, false));
162
163
  // x + (str.len y) = 0 |= 0 > x --> false
164
2
  ASSERT_FALSE(
165
2
      ArithEntail::checkWithAssumption(x_plus_slen_y_eq_zero, zero, x, true));
166
167
8
  Node x_plus_slen_y_plus_z_eq_zero = d_rewriter->rewrite(d_nodeManager->mkNode(
168
8
      kind::EQUAL, d_nodeManager->mkNode(kind::PLUS, x_plus_slen_y, z), zero));
169
170
  // x + (str.len y) + z = 0 |= 0 > x --> false
171
2
  ASSERT_FALSE(ArithEntail::checkWithAssumption(
172
2
      x_plus_slen_y_plus_z_eq_zero, zero, x, true));
173
174
  Node x_plus_slen_y_plus_slen_y_eq_zero =
175
8
      d_rewriter->rewrite(d_nodeManager->mkNode(
176
          kind::EQUAL,
177
4
          d_nodeManager->mkNode(kind::PLUS, x_plus_slen_y, slen_y),
178
4
          zero));
179
180
  // x + (str.len y) + (str.len y) = 0 |= 0 >= x --> true
181
2
  ASSERT_TRUE(ArithEntail::checkWithAssumption(
182
2
      x_plus_slen_y_plus_slen_y_eq_zero, zero, x, false));
183
184
4
  Node five = d_nodeManager->mkConst(Rational(5));
185
4
  Node six = d_nodeManager->mkConst(Rational(6));
186
4
  Node x_plus_five = d_nodeManager->mkNode(kind::PLUS, x, five);
187
  Node x_plus_five_lt_six =
188
4
      d_rewriter->rewrite(d_nodeManager->mkNode(kind::LT, x_plus_five, six));
189
190
  // x + 5 < 6 |= 0 >= x --> true
191
2
  ASSERT_TRUE(
192
2
      ArithEntail::checkWithAssumption(x_plus_five_lt_six, zero, x, false));
193
194
  // x + 5 < 6 |= 0 > x --> false
195
2
  ASSERT_TRUE(
196
2
      !ArithEntail::checkWithAssumption(x_plus_five_lt_six, zero, x, true));
197
198
4
  Node neg_x = d_nodeManager->mkNode(kind::UMINUS, x);
199
  Node x_plus_five_lt_five =
200
4
      d_rewriter->rewrite(d_nodeManager->mkNode(kind::LT, x_plus_five, five));
201
202
  // x + 5 < 5 |= -x >= 0 --> true
203
2
  ASSERT_TRUE(ArithEntail::checkWithAssumption(
204
2
      x_plus_five_lt_five, neg_x, zero, false));
205
206
  // x + 5 < 5 |= 0 > x --> true
207
2
  ASSERT_TRUE(
208
2
      ArithEntail::checkWithAssumption(x_plus_five_lt_five, zero, x, false));
209
210
  // 0 < x |= x >= (str.len (int.to.str x))
211
4
  Node assm = d_rewriter->rewrite(d_nodeManager->mkNode(kind::LT, zero, x));
212
2
  ASSERT_TRUE(ArithEntail::checkWithAssumption(
213
      assm,
214
      x,
215
      d_nodeManager->mkNode(kind::STRING_LENGTH,
216
                            d_nodeManager->mkNode(kind::STRING_ITOS, x)),
217
2
      false));
218
}
219
220
26
TEST_F(TestTheoryWhiteSequencesRewriter, rewrite_substr)
221
{
222
4
  TypeNode intType = d_nodeManager->integerType();
223
4
  TypeNode strType = d_nodeManager->stringType();
224
225
4
  Node empty = d_nodeManager->mkConst(::cvc5::String(""));
226
4
  Node a = d_nodeManager->mkConst(::cvc5::String("A"));
227
4
  Node b = d_nodeManager->mkConst(::cvc5::String("B"));
228
4
  Node abcd = d_nodeManager->mkConst(::cvc5::String("ABCD"));
229
4
  Node negone = d_nodeManager->mkConst(Rational(-1));
230
4
  Node zero = d_nodeManager->mkConst(Rational(0));
231
4
  Node one = d_nodeManager->mkConst(Rational(1));
232
4
  Node two = d_nodeManager->mkConst(Rational(2));
233
4
  Node three = d_nodeManager->mkConst(Rational(3));
234
235
4
  Node s = d_nodeManager->mkVar("s", strType);
236
4
  Node s2 = d_nodeManager->mkVar("s2", strType);
237
4
  Node x = d_nodeManager->mkVar("x", intType);
238
4
  Node y = d_nodeManager->mkVar("y", intType);
239
240
  // (str.substr "A" x x) --> ""
241
4
  Node n = d_nodeManager->mkNode(kind::STRING_SUBSTR, a, x, x);
242
4
  Node res = StringsRewriter(nullptr).rewriteSubstr(n);
243
2
  ASSERT_EQ(res, empty);
244
245
  // (str.substr "A" (+ x 1) x) -> ""
246
6
  n = d_nodeManager->mkNode(
247
      kind::STRING_SUBSTR,
248
      a,
249
4
      d_nodeManager->mkNode(kind::PLUS, x, d_nodeManager->mkConst(Rational(1))),
250
      x);
251
2
  res = StringsRewriter(nullptr).rewriteSubstr(n);
252
2
  ASSERT_EQ(res, empty);
253
254
  // (str.substr "A" (+ x (str.len s2)) x) -> ""
255
6
  n = d_nodeManager->mkNode(
256
      kind::STRING_SUBSTR,
257
      a,
258
6
      d_nodeManager->mkNode(
259
4
          kind::PLUS, x, d_nodeManager->mkNode(kind::STRING_LENGTH, s)),
260
      x);
261
2
  res = StringsRewriter(nullptr).rewriteSubstr(n);
262
2
  ASSERT_EQ(res, empty);
263
264
  // (str.substr "A" x y) -> (str.substr "A" x y)
265
2
  n = d_nodeManager->mkNode(kind::STRING_SUBSTR, a, x, y);
266
2
  res = StringsRewriter(nullptr).rewriteSubstr(n);
267
2
  ASSERT_EQ(res, n);
268
269
  // (str.substr "ABCD" (+ x 3) x) -> ""
270
6
  n = d_nodeManager->mkNode(kind::STRING_SUBSTR,
271
                            abcd,
272
4
                            d_nodeManager->mkNode(kind::PLUS, x, three),
273
                            x);
274
2
  res = StringsRewriter(nullptr).rewriteSubstr(n);
275
2
  ASSERT_EQ(res, empty);
276
277
  // (str.substr "ABCD" (+ x 2) x) -> (str.substr "ABCD" (+ x 2) x)
278
6
  n = d_nodeManager->mkNode(
279
4
      kind::STRING_SUBSTR, abcd, d_nodeManager->mkNode(kind::PLUS, x, two), x);
280
2
  res = StringsRewriter(nullptr).rewriteSubstr(n);
281
2
  ASSERT_EQ(res, n);
282
283
  // (str.substr (str.substr s x x) x x) -> ""
284
6
  n = d_nodeManager->mkNode(kind::STRING_SUBSTR,
285
4
                            d_nodeManager->mkNode(kind::STRING_SUBSTR, s, x, x),
286
                            x,
287
                            x);
288
2
  sameNormalForm(n, empty);
289
290
  // Same normal form for:
291
  //
292
  // (str.substr (str.replace "" s "B") x x)
293
  //
294
  // (str.replace "" s (str.substr "B" x x)))
295
  Node lhs = d_nodeManager->mkNode(
296
      kind::STRING_SUBSTR,
297
4
      d_nodeManager->mkNode(kind::STRING_REPLACE, empty, s, b),
298
      x,
299
8
      x);
300
  Node rhs = d_nodeManager->mkNode(
301
      kind::STRING_REPLACE,
302
      empty,
303
      s,
304
4
      d_nodeManager->mkNode(kind::STRING_SUBSTR, b, x, x));
305
2
  sameNormalForm(lhs, rhs);
306
307
  // Same normal form:
308
  //
309
  // (str.substr (str.replace s "A" "B") 0 x)
310
  //
311
  // (str.replace (str.substr s 0 x) "A" "B")
312
  Node substr_repl = d_nodeManager->mkNode(
313
      kind::STRING_SUBSTR,
314
4
      d_nodeManager->mkNode(kind::STRING_REPLACE, s, a, b),
315
      zero,
316
8
      x);
317
  Node repl_substr = d_nodeManager->mkNode(
318
      kind::STRING_REPLACE,
319
4
      d_nodeManager->mkNode(kind::STRING_SUBSTR, s, zero, x),
320
      a,
321
8
      b);
322
2
  sameNormalForm(substr_repl, repl_substr);
323
324
  // Same normal form:
325
  //
326
  // (str.substr (str.replace s (str.substr (str.++ s2 "A") 0 1) "B") 0 x)
327
  //
328
  // (str.replace (str.substr s 0 x) (str.substr (str.++ s2 "A") 0 1) "B")
329
  Node substr_y =
330
      d_nodeManager->mkNode(kind::STRING_SUBSTR,
331
4
                            d_nodeManager->mkNode(kind::STRING_CONCAT, s2, a),
332
                            zero,
333
8
                            one);
334
6
  substr_repl = d_nodeManager->mkNode(
335
      kind::STRING_SUBSTR,
336
4
      d_nodeManager->mkNode(kind::STRING_REPLACE, s, substr_y, b),
337
      zero,
338
      x);
339
6
  repl_substr = d_nodeManager->mkNode(
340
      kind::STRING_REPLACE,
341
4
      d_nodeManager->mkNode(kind::STRING_SUBSTR, s, zero, x),
342
      substr_y,
343
      b);
344
2
  sameNormalForm(substr_repl, repl_substr);
345
346
  // (str.substr (str.int.to.str x) x x) ---> empty
347
  Node substr_itos = d_nodeManager->mkNode(
348
4
      kind::STRING_SUBSTR, d_nodeManager->mkNode(kind::STRING_ITOS, x), x, x);
349
2
  sameNormalForm(substr_itos, empty);
350
351
  // (str.substr s (* (- 1) (str.len s)) 1) ---> empty
352
  Node substr = d_nodeManager->mkNode(
353
      kind::STRING_SUBSTR,
354
      s,
355
6
      d_nodeManager->mkNode(
356
4
          kind::MULT, negone, d_nodeManager->mkNode(kind::STRING_LENGTH, s)),
357
8
      one);
358
2
  sameNormalForm(substr, empty);
359
}
360
361
26
TEST_F(TestTheoryWhiteSequencesRewriter, rewrite_concat)
362
{
363
4
  TypeNode intType = d_nodeManager->integerType();
364
4
  TypeNode strType = d_nodeManager->stringType();
365
366
4
  Node empty = d_nodeManager->mkConst(::cvc5::String(""));
367
4
  Node a = d_nodeManager->mkConst(::cvc5::String("A"));
368
4
  Node zero = d_nodeManager->mkConst(Rational(0));
369
4
  Node three = d_nodeManager->mkConst(Rational(3));
370
371
4
  Node i = d_nodeManager->mkVar("i", intType);
372
4
  Node s = d_nodeManager->mkVar("s", strType);
373
4
  Node x = d_nodeManager->mkVar("x", strType);
374
4
  Node y = d_nodeManager->mkVar("y", strType);
375
376
  // Same normal form for:
377
  //
378
  // (str.++ (str.replace "A" x "") "A")
379
  //
380
  // (str.++ "A" (str.replace "A" x ""))
381
4
  Node repl_a_x_e = d_nodeManager->mkNode(kind::STRING_REPLACE, a, x, empty);
382
4
  Node repl_a = d_nodeManager->mkNode(kind::STRING_CONCAT, repl_a_x_e, a);
383
4
  Node a_repl = d_nodeManager->mkNode(kind::STRING_CONCAT, a, repl_a_x_e);
384
2
  sameNormalForm(repl_a, a_repl);
385
386
  // Same normal form for:
387
  //
388
  // (str.++ y (str.replace "" x (str.substr y 0 3)) (str.substr y 0 3) "A"
389
  // (str.substr y 0 3))
390
  //
391
  // (str.++ y (str.substr y 0 3) (str.replace "" x (str.substr y 0 3)) "A"
392
  // (str.substr y 0 3))
393
4
  Node z = d_nodeManager->mkNode(kind::STRING_SUBSTR, y, zero, three);
394
4
  Node repl_e_x_z = d_nodeManager->mkNode(kind::STRING_REPLACE, empty, x, z);
395
2
  repl_a = d_nodeManager->mkNode(kind::STRING_CONCAT, {y, repl_e_x_z, z, a, z});
396
2
  a_repl = d_nodeManager->mkNode(kind::STRING_CONCAT, {y, z, repl_e_x_z, a, z});
397
2
  sameNormalForm(repl_a, a_repl);
398
399
  // Same normal form for:
400
  //
401
  // (str.++ "A" (str.replace "A" x "") (str.substr "A" 0 i))
402
  //
403
  // (str.++ (str.substr "A" 0 i) (str.replace "A" x "") "A")
404
4
  Node substr_a = d_nodeManager->mkNode(kind::STRING_SUBSTR, a, zero, i);
405
  Node a_substr_repl =
406
4
      d_nodeManager->mkNode(kind::STRING_CONCAT, a, substr_a, repl_a_x_e);
407
  Node substr_repl_a =
408
4
      d_nodeManager->mkNode(kind::STRING_CONCAT, substr_a, repl_a_x_e, a);
409
2
  sameNormalForm(a_substr_repl, substr_repl_a);
410
411
  // Same normal form for:
412
  //
413
  // (str.++ (str.replace "" x (str.substr "A" 0 i)) (str.substr "A" 0 i)
414
  // (str.at "A" i))
415
  //
416
  // (str.++ (str.at "A" i) (str.replace "" x (str.substr "A" 0 i)) (str.substr
417
  // "A" 0 i))
418
4
  Node charat_a = d_nodeManager->mkNode(kind::STRING_CHARAT, a, i);
419
  Node repl_e_x_s =
420
4
      d_nodeManager->mkNode(kind::STRING_REPLACE, empty, x, substr_a);
421
  Node repl_substr_a = d_nodeManager->mkNode(
422
4
      kind::STRING_CONCAT, repl_e_x_s, substr_a, charat_a);
423
  Node a_repl_substr = d_nodeManager->mkNode(
424
4
      kind::STRING_CONCAT, charat_a, repl_e_x_s, substr_a);
425
2
  sameNormalForm(repl_substr_a, a_repl_substr);
426
2
}
427
428
26
TEST_F(TestTheoryWhiteSequencesRewriter, length_preserve_rewrite)
429
{
430
4
  TypeNode intType = d_nodeManager->integerType();
431
4
  TypeNode strType = d_nodeManager->stringType();
432
433
4
  Node empty = d_nodeManager->mkConst(::cvc5::String(""));
434
4
  Node abcd = d_nodeManager->mkConst(::cvc5::String("ABCD"));
435
4
  Node f = d_nodeManager->mkConst(::cvc5::String("F"));
436
4
  Node gh = d_nodeManager->mkConst(::cvc5::String("GH"));
437
4
  Node ij = d_nodeManager->mkConst(::cvc5::String("IJ"));
438
439
4
  Node i = d_nodeManager->mkVar("i", intType);
440
4
  Node s = d_nodeManager->mkVar("s", strType);
441
4
  Node x = d_nodeManager->mkVar("x", strType);
442
4
  Node y = d_nodeManager->mkVar("y", strType);
443
444
  // Same length preserving rewrite for:
445
  //
446
  // (str.++ "ABCD" (str.++ x x))
447
  //
448
  // (str.++ "GH" (str.repl "GH" "IJ") "IJ")
449
  Node concat1 =
450
      d_nodeManager->mkNode(kind::STRING_CONCAT,
451
                            abcd,
452
4
                            d_nodeManager->mkNode(kind::STRING_CONCAT, x, x));
453
  Node concat2 = d_nodeManager->mkNode(
454
      kind::STRING_CONCAT,
455
4
      {gh, x, d_nodeManager->mkNode(kind::STRING_REPLACE, x, gh, ij), ij});
456
4
  Node res_concat1 = SequencesRewriter::lengthPreserveRewrite(concat1);
457
4
  Node res_concat2 = SequencesRewriter::lengthPreserveRewrite(concat2);
458
2
  ASSERT_EQ(res_concat1, res_concat2);
459
}
460
461
26
TEST_F(TestTheoryWhiteSequencesRewriter, rewrite_indexOf)
462
{
463
4
  TypeNode intType = d_nodeManager->integerType();
464
4
  TypeNode strType = d_nodeManager->stringType();
465
466
4
  Node a = d_nodeManager->mkConst(::cvc5::String("A"));
467
4
  Node abcd = d_nodeManager->mkConst(::cvc5::String("ABCD"));
468
4
  Node aaad = d_nodeManager->mkConst(::cvc5::String("AAAD"));
469
4
  Node b = d_nodeManager->mkConst(::cvc5::String("B"));
470
4
  Node c = d_nodeManager->mkConst(::cvc5::String("C"));
471
4
  Node ccc = d_nodeManager->mkConst(::cvc5::String("CCC"));
472
4
  Node x = d_nodeManager->mkVar("x", strType);
473
4
  Node y = d_nodeManager->mkVar("y", strType);
474
4
  Node negOne = d_nodeManager->mkConst(Rational(-1));
475
4
  Node zero = d_nodeManager->mkConst(Rational(0));
476
4
  Node one = d_nodeManager->mkConst(Rational(1));
477
4
  Node two = d_nodeManager->mkConst(Rational(2));
478
4
  Node three = d_nodeManager->mkConst(Rational(3));
479
4
  Node i = d_nodeManager->mkVar("i", intType);
480
4
  Node j = d_nodeManager->mkVar("j", intType);
481
482
  // Same normal form for:
483
  //
484
  // (str.to.int (str.indexof "A" x 1))
485
  //
486
  // (str.to.int (str.indexof "B" x 1))
487
4
  Node a_idof_x = d_nodeManager->mkNode(kind::STRING_INDEXOF, a, x, two);
488
4
  Node itos_a_idof_x = d_nodeManager->mkNode(kind::STRING_ITOS, a_idof_x);
489
4
  Node b_idof_x = d_nodeManager->mkNode(kind::STRING_INDEXOF, b, x, two);
490
4
  Node itos_b_idof_x = d_nodeManager->mkNode(kind::STRING_ITOS, b_idof_x);
491
2
  sameNormalForm(itos_a_idof_x, itos_b_idof_x);
492
493
  // Same normal form for:
494
  //
495
  // (str.indexof (str.++ "ABCD" x) y 3)
496
  //
497
  // (str.indexof (str.++ "AAAD" x) y 3)
498
  Node idof_abcd =
499
      d_nodeManager->mkNode(kind::STRING_INDEXOF,
500
4
                            d_nodeManager->mkNode(kind::STRING_CONCAT, abcd, x),
501
                            y,
502
8
                            three);
503
  Node idof_aaad =
504
      d_nodeManager->mkNode(kind::STRING_INDEXOF,
505
4
                            d_nodeManager->mkNode(kind::STRING_CONCAT, aaad, x),
506
                            y,
507
8
                            three);
508
2
  sameNormalForm(idof_abcd, idof_aaad);
509
510
  // (str.indexof (str.substr x 1 i) "A" i) ---> -1
511
  Node idof_substr = d_nodeManager->mkNode(
512
      kind::STRING_INDEXOF,
513
4
      d_nodeManager->mkNode(kind::STRING_SUBSTR, x, one, i),
514
      a,
515
8
      i);
516
2
  sameNormalForm(idof_substr, negOne);
517
518
  {
519
    // Same normal form for:
520
    //
521
    // (str.indexof (str.++ "B" "C" "A" x y) "A" 0)
522
    //
523
    // (+ 2 (str.indexof (str.++ "A" x y) "A" 0))
524
    Node lhs = d_nodeManager->mkNode(
525
        kind::STRING_INDEXOF,
526
4
        d_nodeManager->mkNode(kind::STRING_CONCAT, {b, c, a, x, y}),
527
        a,
528
8
        zero);
529
    Node rhs = d_nodeManager->mkNode(
530
        kind::PLUS,
531
        two,
532
8
        d_nodeManager->mkNode(
533
            kind::STRING_INDEXOF,
534
4
            d_nodeManager->mkNode(kind::STRING_CONCAT, a, x, y),
535
            a,
536
6
            zero));
537
2
    sameNormalForm(lhs, rhs);
538
  }
539
2
}
540
541
26
TEST_F(TestTheoryWhiteSequencesRewriter, rewrite_replace)
542
{
543
4
  TypeNode intType = d_nodeManager->integerType();
544
4
  TypeNode strType = d_nodeManager->stringType();
545
546
4
  Node empty = d_nodeManager->mkConst(::cvc5::String(""));
547
4
  Node a = d_nodeManager->mkConst(::cvc5::String("A"));
548
4
  Node ab = d_nodeManager->mkConst(::cvc5::String("AB"));
549
4
  Node b = d_nodeManager->mkConst(::cvc5::String("B"));
550
4
  Node c = d_nodeManager->mkConst(::cvc5::String("C"));
551
4
  Node d = d_nodeManager->mkConst(::cvc5::String("D"));
552
4
  Node x = d_nodeManager->mkVar("x", strType);
553
4
  Node y = d_nodeManager->mkVar("y", strType);
554
4
  Node z = d_nodeManager->mkVar("z", strType);
555
4
  Node zero = d_nodeManager->mkConst(Rational(0));
556
4
  Node one = d_nodeManager->mkConst(Rational(1));
557
4
  Node n = d_nodeManager->mkVar("n", intType);
558
559
  // (str.replace (str.replace x "B" x) x "A") -->
560
  //   (str.replace (str.replace x "B" "A") x "A")
561
  Node repl_repl = d_nodeManager->mkNode(
562
      kind::STRING_REPLACE,
563
4
      d_nodeManager->mkNode(kind::STRING_REPLACE, x, b, x),
564
      x,
565
8
      a);
566
  Node repl_repl_short = d_nodeManager->mkNode(
567
      kind::STRING_REPLACE,
568
4
      d_nodeManager->mkNode(kind::STRING_REPLACE, x, b, a),
569
      x,
570
8
      a);
571
2
  sameNormalForm(repl_repl, repl_repl_short);
572
573
  // (str.replace "A" (str.replace "B", x, "C") "D") --> "A"
574
6
  repl_repl = d_nodeManager->mkNode(
575
      kind::STRING_REPLACE,
576
      a,
577
4
      d_nodeManager->mkNode(kind::STRING_REPLACE, b, x, c),
578
      d);
579
2
  sameNormalForm(repl_repl, a);
580
581
  // (str.replace "A" (str.replace "B", x, "A") "D") -/-> "A"
582
6
  repl_repl = d_nodeManager->mkNode(
583
      kind::STRING_REPLACE,
584
      a,
585
4
      d_nodeManager->mkNode(kind::STRING_REPLACE, b, x, a),
586
      d);
587
2
  differentNormalForms(repl_repl, a);
588
589
  // Same normal form for:
590
  //
591
  // (str.replace x (str.++ x y z) y)
592
  //
593
  // (str.replace x (str.++ x y z) z)
594
4
  Node xyz = d_nodeManager->mkNode(kind::STRING_CONCAT, x, y, z);
595
4
  Node repl_x_xyz = d_nodeManager->mkNode(kind::STRING_REPLACE, x, xyz, y);
596
4
  Node repl_x_zyx = d_nodeManager->mkNode(kind::STRING_REPLACE, x, xyz, z);
597
2
  sameNormalForm(repl_x_xyz, repl_x_zyx);
598
599
  // (str.replace "" (str.++ x x) x) --> ""
600
  Node repl_empty_xx =
601
      d_nodeManager->mkNode(kind::STRING_REPLACE,
602
                            empty,
603
4
                            d_nodeManager->mkNode(kind::STRING_CONCAT, x, x),
604
8
                            x);
605
2
  sameNormalForm(repl_empty_xx, empty);
606
607
  // (str.replace "AB" (str.++ x "A") x) --> (str.replace "AB" (str.++ x "A")
608
  // "")
609
  Node repl_ab_xa_x =
610
      d_nodeManager->mkNode(kind::STRING_REPLACE,
611
4
                            d_nodeManager->mkNode(kind::STRING_CONCAT, a, b),
612
4
                            d_nodeManager->mkNode(kind::STRING_CONCAT, x, a),
613
12
                            x);
614
  Node repl_ab_xa_e =
615
      d_nodeManager->mkNode(kind::STRING_REPLACE,
616
4
                            d_nodeManager->mkNode(kind::STRING_CONCAT, a, b),
617
4
                            d_nodeManager->mkNode(kind::STRING_CONCAT, x, a),
618
12
                            empty);
619
2
  sameNormalForm(repl_ab_xa_x, repl_ab_xa_e);
620
621
  // (str.replace "AB" (str.++ x "A") x) -/-> (str.replace "AB" (str.++ "A" x)
622
  // "")
623
  Node repl_ab_ax_e =
624
      d_nodeManager->mkNode(kind::STRING_REPLACE,
625
4
                            d_nodeManager->mkNode(kind::STRING_CONCAT, a, b),
626
4
                            d_nodeManager->mkNode(kind::STRING_CONCAT, a, x),
627
12
                            empty);
628
2
  differentNormalForms(repl_ab_ax_e, repl_ab_xa_e);
629
630
  // (str.replace "" (str.replace y x "A") y) ---> ""
631
6
  repl_repl = d_nodeManager->mkNode(
632
      kind::STRING_REPLACE,
633
      empty,
634
4
      d_nodeManager->mkNode(kind::STRING_REPLACE, y, x, a),
635
      y);
636
2
  sameNormalForm(repl_repl, empty);
637
638
  // (str.replace "" (str.replace x y x) x) ---> ""
639
6
  repl_repl = d_nodeManager->mkNode(
640
      kind::STRING_REPLACE,
641
      empty,
642
4
      d_nodeManager->mkNode(kind::STRING_REPLACE, x, y, x),
643
      x);
644
2
  sameNormalForm(repl_repl, empty);
645
646
  // (str.replace "" (str.substr x 0 1) x) ---> ""
647
6
  repl_repl = d_nodeManager->mkNode(
648
      kind::STRING_REPLACE,
649
      empty,
650
4
      d_nodeManager->mkNode(kind::STRING_SUBSTR, x, zero, one),
651
      x);
652
2
  sameNormalForm(repl_repl, empty);
653
654
  // Same normal form for:
655
  //
656
  // (str.replace "" (str.replace x y x) y)
657
  //
658
  // (str.replace "" x y)
659
6
  repl_repl = d_nodeManager->mkNode(
660
      kind::STRING_REPLACE,
661
      empty,
662
4
      d_nodeManager->mkNode(kind::STRING_REPLACE, x, y, x),
663
      y);
664
4
  Node repl = d_nodeManager->mkNode(kind::STRING_REPLACE, empty, x, y);
665
2
  sameNormalForm(repl_repl, repl);
666
667
  // Same normal form:
668
  //
669
  // (str.replace "B" (str.replace x "A" "B") "B")
670
  //
671
  // (str.replace "B" x "B"))
672
6
  repl_repl = d_nodeManager->mkNode(
673
      kind::STRING_REPLACE,
674
      b,
675
4
      d_nodeManager->mkNode(kind::STRING_REPLACE, x, a, b),
676
      b);
677
2
  repl = d_nodeManager->mkNode(kind::STRING_REPLACE, b, x, b);
678
2
  sameNormalForm(repl_repl, repl);
679
680
  // Different normal forms for:
681
  //
682
  // (str.replace "B" (str.replace "" x "A") "B")
683
  //
684
  // (str.replace "B" x "B")
685
6
  repl_repl = d_nodeManager->mkNode(
686
      kind::STRING_REPLACE,
687
      b,
688
4
      d_nodeManager->mkNode(kind::STRING_REPLACE, empty, x, a),
689
      b);
690
2
  repl = d_nodeManager->mkNode(kind::STRING_REPLACE, b, x, b);
691
2
  differentNormalForms(repl_repl, repl);
692
693
  {
694
    // Same normal form:
695
    //
696
    // (str.replace (str.++ "AB" x) "C" y)
697
    //
698
    // (str.++ "AB" (str.replace x "C" y))
699
    Node lhs =
700
        d_nodeManager->mkNode(kind::STRING_REPLACE,
701
4
                              d_nodeManager->mkNode(kind::STRING_CONCAT, ab, x),
702
                              c,
703
8
                              y);
704
    Node rhs = d_nodeManager->mkNode(
705
        kind::STRING_CONCAT,
706
        ab,
707
4
        d_nodeManager->mkNode(kind::STRING_REPLACE, x, c, y));
708
2
    sameNormalForm(lhs, rhs);
709
  }
710
2
}
711
712
26
TEST_F(TestTheoryWhiteSequencesRewriter, rewrite_replace_re)
713
{
714
4
  TypeNode intType = d_nodeManager->integerType();
715
4
  TypeNode strType = d_nodeManager->stringType();
716
717
4
  std::vector<Node> emptyVec;
718
  Node sigStar = d_nodeManager->mkNode(
719
4
      kind::REGEXP_STAR, d_nodeManager->mkNode(kind::REGEXP_SIGMA, emptyVec));
720
4
  Node foo = d_nodeManager->mkConst(String("FOO"));
721
4
  Node a = d_nodeManager->mkConst(String("A"));
722
4
  Node b = d_nodeManager->mkConst(String("B"));
723
  Node re =
724
      d_nodeManager->mkNode(kind::REGEXP_CONCAT,
725
4
                            d_nodeManager->mkNode(kind::STRING_TO_REGEXP, a),
726
                            sigStar,
727
8
                            d_nodeManager->mkNode(kind::STRING_TO_REGEXP, b));
728
729
  // Same normal form:
730
  //
731
  // (str.replace_re
732
  //   "AZZZB"
733
  //   (re.++ (str.to_re "A") re.all (str.to_re "B"))
734
  //   "FOO")
735
  //
736
  // "FOO"
737
  {
738
    Node t = d_nodeManager->mkNode(kind::STRING_REPLACE_RE,
739
4
                                   d_nodeManager->mkConst(String("AZZZB")),
740
                                   re,
741
8
                                   foo);
742
4
    Node res = d_nodeManager->mkConst(::cvc5::String("FOO"));
743
2
    sameNormalForm(t, res);
744
  }
745
746
  // Same normal form:
747
  //
748
  // (str.replace_re
749
  //   "ZAZZZBZZB"
750
  //   (re.++ (str.to_re "A") re.all (str.to_re "B"))
751
  //   "FOO")
752
  //
753
  // "ZFOOZZB"
754
  {
755
    Node t = d_nodeManager->mkNode(kind::STRING_REPLACE_RE,
756
4
                                   d_nodeManager->mkConst(String("ZAZZZBZZB")),
757
                                   re,
758
8
                                   foo);
759
4
    Node res = d_nodeManager->mkConst(::cvc5::String("ZFOOZZB"));
760
2
    sameNormalForm(t, res);
761
  }
762
763
  // Same normal form:
764
  //
765
  // (str.replace_re
766
  //   "ZAZZZBZAZB"
767
  //   (re.++ (str.to_re "A") re.all (str.to_re "B"))
768
  //   "FOO")
769
  //
770
  // "ZFOOZAZB"
771
  {
772
    Node t = d_nodeManager->mkNode(kind::STRING_REPLACE_RE,
773
4
                                   d_nodeManager->mkConst(String("ZAZZZBZAZB")),
774
                                   re,
775
8
                                   foo);
776
4
    Node res = d_nodeManager->mkConst(::cvc5::String("ZFOOZAZB"));
777
2
    sameNormalForm(t, res);
778
  }
779
780
  // Same normal form:
781
  //
782
  // (str.replace_re
783
  //   "ZZZ"
784
  //   (re.++ (str.to_re "A") re.all (str.to_re "B"))
785
  //   "FOO")
786
  //
787
  // "ZZZ"
788
  {
789
    Node t = d_nodeManager->mkNode(kind::STRING_REPLACE_RE,
790
4
                                   d_nodeManager->mkConst(String("ZZZ")),
791
                                   re,
792
8
                                   foo);
793
4
    Node res = d_nodeManager->mkConst(::cvc5::String("ZZZ"));
794
2
    sameNormalForm(t, res);
795
  }
796
797
  // Same normal form:
798
  //
799
  // (str.replace_re
800
  //   "ZZZ"
801
  //   re.all
802
  //   "FOO")
803
  //
804
  // "FOOZZZ"
805
  {
806
    Node t = d_nodeManager->mkNode(kind::STRING_REPLACE_RE,
807
4
                                   d_nodeManager->mkConst(String("ZZZ")),
808
                                   sigStar,
809
8
                                   foo);
810
4
    Node res = d_nodeManager->mkConst(::cvc5::String("FOOZZZ"));
811
2
    sameNormalForm(t, res);
812
  }
813
814
  // Same normal form:
815
  //
816
  // (str.replace_re
817
  //   ""
818
  //   re.all
819
  //   "FOO")
820
  //
821
  // "FOO"
822
  {
823
    Node t = d_nodeManager->mkNode(kind::STRING_REPLACE_RE,
824
4
                                   d_nodeManager->mkConst(String("")),
825
                                   sigStar,
826
8
                                   foo);
827
4
    Node res = d_nodeManager->mkConst(::cvc5::String("FOO"));
828
2
    sameNormalForm(t, res);
829
  }
830
2
}
831
832
26
TEST_F(TestTheoryWhiteSequencesRewriter, rewrite_replace_all)
833
{
834
4
  TypeNode intType = d_nodeManager->integerType();
835
4
  TypeNode strType = d_nodeManager->stringType();
836
837
4
  std::vector<Node> emptyVec;
838
  Node sigStar = d_nodeManager->mkNode(
839
4
      kind::REGEXP_STAR, d_nodeManager->mkNode(kind::REGEXP_SIGMA, emptyVec));
840
4
  Node foo = d_nodeManager->mkConst(String("FOO"));
841
4
  Node a = d_nodeManager->mkConst(String("A"));
842
4
  Node b = d_nodeManager->mkConst(String("B"));
843
  Node re =
844
      d_nodeManager->mkNode(kind::REGEXP_CONCAT,
845
4
                            d_nodeManager->mkNode(kind::STRING_TO_REGEXP, a),
846
                            sigStar,
847
8
                            d_nodeManager->mkNode(kind::STRING_TO_REGEXP, b));
848
849
  // Same normal form:
850
  //
851
  // (str.replace_re
852
  //   "AZZZB"
853
  //   (re.++ (str.to_re "A") re.all (str.to_re "B"))
854
  //   "FOO")
855
  //
856
  // "FOO"
857
  {
858
    Node t = d_nodeManager->mkNode(kind::STRING_REPLACE_RE_ALL,
859
4
                                   d_nodeManager->mkConst(String("AZZZB")),
860
                                   re,
861
8
                                   foo);
862
4
    Node res = d_nodeManager->mkConst(::cvc5::String("FOO"));
863
2
    sameNormalForm(t, res);
864
  }
865
866
  // Same normal form:
867
  //
868
  // (str.replace_re
869
  //   "ZAZZZBZZB"
870
  //   (re.++ (str.to_re "A") re.all (str.to_re "B"))
871
  //   "FOO")
872
  //
873
  // "ZFOOZZB"
874
  {
875
    Node t = d_nodeManager->mkNode(kind::STRING_REPLACE_RE_ALL,
876
4
                                   d_nodeManager->mkConst(String("ZAZZZBZZB")),
877
                                   re,
878
8
                                   foo);
879
4
    Node res = d_nodeManager->mkConst(::cvc5::String("ZFOOZZB"));
880
2
    sameNormalForm(t, res);
881
  }
882
883
  // Same normal form:
884
  //
885
  // (str.replace_re
886
  //   "ZAZZZBZAZB"
887
  //   (re.++ (str.to_re "A") re.all (str.to_re "B"))
888
  //   "FOO")
889
  //
890
  // "ZFOOZFOO"
891
  {
892
    Node t = d_nodeManager->mkNode(kind::STRING_REPLACE_RE_ALL,
893
4
                                   d_nodeManager->mkConst(String("ZAZZZBZAZB")),
894
                                   re,
895
8
                                   foo);
896
4
    Node res = d_nodeManager->mkConst(::cvc5::String("ZFOOZFOO"));
897
2
    sameNormalForm(t, res);
898
  }
899
900
  // Same normal form:
901
  //
902
  // (str.replace_re
903
  //   "ZZZ"
904
  //   (re.++ (str.to_re "A") re.all (str.to_re "B"))
905
  //   "FOO")
906
  //
907
  // "ZZZ"
908
  {
909
    Node t = d_nodeManager->mkNode(kind::STRING_REPLACE_RE_ALL,
910
4
                                   d_nodeManager->mkConst(String("ZZZ")),
911
                                   re,
912
8
                                   foo);
913
4
    Node res = d_nodeManager->mkConst(::cvc5::String("ZZZ"));
914
2
    sameNormalForm(t, res);
915
  }
916
917
  // Same normal form:
918
  //
919
  // (str.replace_re
920
  //   "ZZZ"
921
  //   re.all
922
  //   "FOO")
923
  //
924
  // "FOOFOOFOO"
925
  {
926
    Node t = d_nodeManager->mkNode(kind::STRING_REPLACE_RE_ALL,
927
4
                                   d_nodeManager->mkConst(String("ZZZ")),
928
                                   sigStar,
929
8
                                   foo);
930
4
    Node res = d_nodeManager->mkConst(::cvc5::String("FOOFOOFOO"));
931
2
    sameNormalForm(t, res);
932
  }
933
934
  // Same normal form:
935
  //
936
  // (str.replace_re
937
  //   ""
938
  //   re.all
939
  //   "FOO")
940
  //
941
  // ""
942
  {
943
    Node t = d_nodeManager->mkNode(kind::STRING_REPLACE_RE_ALL,
944
4
                                   d_nodeManager->mkConst(String("")),
945
                                   sigStar,
946
8
                                   foo);
947
4
    Node res = d_nodeManager->mkConst(::cvc5::String(""));
948
2
    sameNormalForm(t, res);
949
  }
950
2
}
951
952
26
TEST_F(TestTheoryWhiteSequencesRewriter, rewrite_contains)
953
{
954
4
  TypeNode intType = d_nodeManager->integerType();
955
4
  TypeNode strType = d_nodeManager->stringType();
956
957
4
  Node empty = d_nodeManager->mkConst(::cvc5::String(""));
958
4
  Node a = d_nodeManager->mkConst(::cvc5::String("A"));
959
4
  Node ab = d_nodeManager->mkConst(::cvc5::String("AB"));
960
4
  Node b = d_nodeManager->mkConst(::cvc5::String("B"));
961
4
  Node c = d_nodeManager->mkConst(::cvc5::String("C"));
962
4
  Node e = d_nodeManager->mkConst(::cvc5::String("E"));
963
4
  Node h = d_nodeManager->mkConst(::cvc5::String("H"));
964
4
  Node j = d_nodeManager->mkConst(::cvc5::String("J"));
965
4
  Node p = d_nodeManager->mkConst(::cvc5::String("P"));
966
4
  Node abc = d_nodeManager->mkConst(::cvc5::String("ABC"));
967
4
  Node def = d_nodeManager->mkConst(::cvc5::String("DEF"));
968
4
  Node ghi = d_nodeManager->mkConst(::cvc5::String("GHI"));
969
4
  Node x = d_nodeManager->mkVar("x", strType);
970
4
  Node y = d_nodeManager->mkVar("y", strType);
971
4
  Node xy = d_nodeManager->mkNode(kind::STRING_CONCAT, x, y);
972
4
  Node yx = d_nodeManager->mkNode(kind::STRING_CONCAT, y, x);
973
4
  Node z = d_nodeManager->mkVar("z", strType);
974
4
  Node n = d_nodeManager->mkVar("n", intType);
975
4
  Node m = d_nodeManager->mkVar("m", intType);
976
4
  Node one = d_nodeManager->mkConst(Rational(1));
977
4
  Node two = d_nodeManager->mkConst(Rational(2));
978
4
  Node three = d_nodeManager->mkConst(Rational(3));
979
4
  Node four = d_nodeManager->mkConst(Rational(4));
980
4
  Node t = d_nodeManager->mkConst(true);
981
4
  Node f = d_nodeManager->mkConst(false);
982
983
  // Same normal form for:
984
  //
985
  // (str.replace "A" (str.substr x 1 3) y z)
986
  //
987
  // (str.replace "A" (str.substr x 1 4) y z)
988
  Node substr_3 = d_nodeManager->mkNode(
989
      kind::STRING_REPLACE,
990
      a,
991
4
      d_nodeManager->mkNode(kind::STRING_SUBSTR, x, one, three),
992
8
      z);
993
  Node substr_4 = d_nodeManager->mkNode(
994
      kind::STRING_REPLACE,
995
      a,
996
4
      d_nodeManager->mkNode(kind::STRING_SUBSTR, x, one, four),
997
8
      z);
998
2
  sameNormalForm(substr_3, substr_4);
999
1000
  // Same normal form for:
1001
  //
1002
  // (str.replace "A" (str.++ y (str.substr x 1 3)) y z)
1003
  //
1004
  // (str.replace "A" (str.++ y (str.substr x 1 4)) y z)
1005
  Node concat_substr_3 = d_nodeManager->mkNode(
1006
      kind::STRING_REPLACE,
1007
      a,
1008
6
      d_nodeManager->mkNode(
1009
          kind::STRING_CONCAT,
1010
          y,
1011
4
          d_nodeManager->mkNode(kind::STRING_SUBSTR, x, one, three)),
1012
8
      z);
1013
  Node concat_substr_4 = d_nodeManager->mkNode(
1014
      kind::STRING_REPLACE,
1015
      a,
1016
6
      d_nodeManager->mkNode(
1017
          kind::STRING_CONCAT,
1018
          y,
1019
4
          d_nodeManager->mkNode(kind::STRING_SUBSTR, x, one, four)),
1020
8
      z);
1021
2
  sameNormalForm(concat_substr_3, concat_substr_4);
1022
1023
  // (str.contains "A" (str.++ a (str.replace "B", x, "C")) --> false
1024
  Node ctn_repl = d_nodeManager->mkNode(
1025
      kind::STRING_CONTAINS,
1026
      a,
1027
6
      d_nodeManager->mkNode(
1028
          kind::STRING_CONCAT,
1029
          a,
1030
10
          d_nodeManager->mkNode(kind::STRING_REPLACE, b, x, c)));
1031
2
  sameNormalForm(ctn_repl, f);
1032
1033
  // (str.contains x (str.++ x x)) --> (= x "")
1034
  Node x_cnts_x_x = d_nodeManager->mkNode(
1035
4
      kind::STRING_CONTAINS, x, d_nodeManager->mkNode(kind::STRING_CONCAT, x, x));
1036
2
  sameNormalForm(x_cnts_x_x, d_nodeManager->mkNode(kind::EQUAL, x, empty));
1037
1038
  // Same normal form for:
1039
  //
1040
  // (str.contains (str.++ y x) (str.++ x z y))
1041
  //
1042
  // (and (str.contains (str.++ y x) (str.++ x y)) (= z ""))
1043
  Node yx_cnts_xzy = d_nodeManager->mkNode(
1044
      kind::STRING_CONTAINS,
1045
      yx,
1046
4
      d_nodeManager->mkNode(kind::STRING_CONCAT, x, z, y));
1047
  Node yx_cnts_xy =
1048
      d_nodeManager->mkNode(kind::AND,
1049
4
                            d_nodeManager->mkNode(kind::EQUAL, z, empty),
1050
8
                            d_nodeManager->mkNode(kind::STRING_CONTAINS, yx, xy));
1051
2
  sameNormalForm(yx_cnts_xzy, yx_cnts_xy);
1052
1053
  // Same normal form for:
1054
  //
1055
  // (str.contains (str.substr x n (str.len y)) y)
1056
  //
1057
  // (= (str.substr x n (str.len y)) y)
1058
  Node ctn_substr = d_nodeManager->mkNode(
1059
      kind::STRING_CONTAINS,
1060
6
      d_nodeManager->mkNode(kind::STRING_SUBSTR,
1061
                            x,
1062
                            n,
1063
4
                            d_nodeManager->mkNode(kind::STRING_LENGTH, y)),
1064
8
      y);
1065
  Node substr_eq = d_nodeManager->mkNode(
1066
      kind::EQUAL,
1067
6
      d_nodeManager->mkNode(kind::STRING_SUBSTR,
1068
                            x,
1069
                            n,
1070
4
                            d_nodeManager->mkNode(kind::STRING_LENGTH, y)),
1071
8
      y);
1072
2
  sameNormalForm(ctn_substr, substr_eq);
1073
1074
  // Same normal form for:
1075
  //
1076
  // (str.contains x (str.replace y x y))
1077
  //
1078
  // (str.contains x y)
1079
  Node ctn_repl_y_x_y = d_nodeManager->mkNode(
1080
      kind::STRING_CONTAINS,
1081
      x,
1082
4
      d_nodeManager->mkNode(kind::STRING_REPLACE, y, x, y));
1083
4
  Node ctn_x_y = d_nodeManager->mkNode(kind::STRING_CONTAINS, x, y);
1084
2
  sameNormalForm(ctn_repl_y_x_y, ctn_repl_y_x_y);
1085
1086
  // Same normal form for:
1087
  //
1088
  // (str.contains x (str.replace x y x))
1089
  //
1090
  // (= x (str.replace x y x))
1091
  Node ctn_repl_self = d_nodeManager->mkNode(
1092
      kind::STRING_CONTAINS,
1093
      x,
1094
4
      d_nodeManager->mkNode(kind::STRING_REPLACE, x, y, x));
1095
  Node eq_repl = d_nodeManager->mkNode(
1096
4
      kind::EQUAL, x, d_nodeManager->mkNode(kind::STRING_REPLACE, x, y, x));
1097
2
  sameNormalForm(ctn_repl_self, eq_repl);
1098
1099
  // (str.contains x (str.++ "A" (str.replace x y x))) ---> false
1100
  Node ctn_repl_self_f = d_nodeManager->mkNode(
1101
      kind::STRING_CONTAINS,
1102
      x,
1103
6
      d_nodeManager->mkNode(
1104
          kind::STRING_CONCAT,
1105
          a,
1106
10
          d_nodeManager->mkNode(kind::STRING_REPLACE, x, y, x)));
1107
2
  sameNormalForm(ctn_repl_self_f, f);
1108
1109
  // Same normal form for:
1110
  //
1111
  // (str.contains x (str.replace "" x y))
1112
  //
1113
  // (= "" (str.replace "" x y))
1114
  Node ctn_repl_empty = d_nodeManager->mkNode(
1115
      kind::STRING_CONTAINS,
1116
      x,
1117
4
      d_nodeManager->mkNode(kind::STRING_REPLACE, empty, x, y));
1118
  Node eq_repl_empty = d_nodeManager->mkNode(
1119
      kind::EQUAL,
1120
      empty,
1121
4
      d_nodeManager->mkNode(kind::STRING_REPLACE, empty, x, y));
1122
2
  sameNormalForm(ctn_repl_empty, eq_repl_empty);
1123
1124
  // Same normal form for:
1125
  //
1126
  // (str.contains x (str.++ x y))
1127
  //
1128
  // (= "" y)
1129
  Node ctn_x_x_y = d_nodeManager->mkNode(
1130
4
      kind::STRING_CONTAINS, x, d_nodeManager->mkNode(kind::STRING_CONCAT, x, y));
1131
4
  Node eq_emp_y = d_nodeManager->mkNode(kind::EQUAL, empty, y);
1132
2
  sameNormalForm(ctn_x_x_y, eq_emp_y);
1133
1134
  // Same normal form for:
1135
  //
1136
  // (str.contains (str.++ y x) (str.++ x y))
1137
  //
1138
  // (= (str.++ y x) (str.++ x y))
1139
4
  Node ctn_yxxy = d_nodeManager->mkNode(kind::STRING_CONTAINS, yx, xy);
1140
4
  Node eq_yxxy = d_nodeManager->mkNode(kind::EQUAL, yx, xy);
1141
2
  sameNormalForm(ctn_yxxy, eq_yxxy);
1142
1143
  // (str.contains (str.replace x y x) x) ---> true
1144
6
  ctn_repl = d_nodeManager->mkNode(
1145
      kind::STRING_CONTAINS,
1146
4
      d_nodeManager->mkNode(kind::STRING_REPLACE, x, y, x),
1147
      x);
1148
2
  sameNormalForm(ctn_repl, t);
1149
1150
  // (str.contains (str.replace (str.++ x y) z (str.++ y x)) x) ---> true
1151
6
  ctn_repl = d_nodeManager->mkNode(
1152
      kind::STRING_CONTAINS,
1153
4
      d_nodeManager->mkNode(kind::STRING_REPLACE, xy, z, yx),
1154
      x);
1155
2
  sameNormalForm(ctn_repl, t);
1156
1157
  // (str.contains (str.++ z (str.replace (str.++ x y) z (str.++ y x))) x)
1158
  //   ---> true
1159
6
  ctn_repl = d_nodeManager->mkNode(
1160
      kind::STRING_CONTAINS,
1161
6
      d_nodeManager->mkNode(
1162
          kind::STRING_CONCAT,
1163
          z,
1164
4
          d_nodeManager->mkNode(kind::STRING_REPLACE, xy, z, yx)),
1165
      x);
1166
2
  sameNormalForm(ctn_repl, t);
1167
1168
  // Same normal form for:
1169
  //
1170
  // (str.contains (str.replace x y x) y)
1171
  //
1172
  // (str.contains x y)
1173
  Node lhs = d_nodeManager->mkNode(
1174
      kind::STRING_CONTAINS,
1175
4
      d_nodeManager->mkNode(kind::STRING_REPLACE, x, y, x),
1176
8
      y);
1177
4
  Node rhs = d_nodeManager->mkNode(kind::STRING_CONTAINS, x, y);
1178
2
  sameNormalForm(lhs, rhs);
1179
1180
  // Same normal form for:
1181
  //
1182
  // (str.contains (str.replace x y x) "B")
1183
  //
1184
  // (str.contains x "B")
1185
6
  lhs = d_nodeManager->mkNode(
1186
      kind::STRING_CONTAINS,
1187
4
      d_nodeManager->mkNode(kind::STRING_REPLACE, x, y, x),
1188
      b);
1189
2
  rhs = d_nodeManager->mkNode(kind::STRING_CONTAINS, x, b);
1190
2
  sameNormalForm(lhs, rhs);
1191
1192
  // Same normal form for:
1193
  //
1194
  // (str.contains (str.replace x y x) (str.substr z n 1))
1195
  //
1196
  // (str.contains x (str.substr z n 1))
1197
4
  Node substr_z = d_nodeManager->mkNode(kind::STRING_SUBSTR, z, n, one);
1198
6
  lhs = d_nodeManager->mkNode(
1199
      kind::STRING_CONTAINS,
1200
4
      d_nodeManager->mkNode(kind::STRING_REPLACE, x, y, x),
1201
      substr_z);
1202
2
  rhs = d_nodeManager->mkNode(kind::STRING_CONTAINS, x, substr_z);
1203
2
  sameNormalForm(lhs, rhs);
1204
1205
  // Same normal form for:
1206
  //
1207
  // (str.contains (str.replace x y z) z)
1208
  //
1209
  // (str.contains (str.replace x z y) y)
1210
6
  lhs = d_nodeManager->mkNode(
1211
      kind::STRING_CONTAINS,
1212
4
      d_nodeManager->mkNode(kind::STRING_REPLACE, x, y, z),
1213
      z);
1214
6
  rhs = d_nodeManager->mkNode(
1215
      kind::STRING_CONTAINS,
1216
4
      d_nodeManager->mkNode(kind::STRING_REPLACE, x, z, y),
1217
      y);
1218
2
  sameNormalForm(lhs, rhs);
1219
1220
  // Same normal form for:
1221
  //
1222
  // (str.contains (str.replace x "A" "B") "A")
1223
  //
1224
  // (str.contains (str.replace x "A" "") "A")
1225
6
  lhs = d_nodeManager->mkNode(
1226
      kind::STRING_CONTAINS,
1227
4
      d_nodeManager->mkNode(kind::STRING_REPLACE, x, a, b),
1228
      a);
1229
6
  rhs = d_nodeManager->mkNode(
1230
      kind::STRING_CONTAINS,
1231
4
      d_nodeManager->mkNode(kind::STRING_REPLACE, x, a, empty),
1232
      a);
1233
2
  sameNormalForm(lhs, rhs);
1234
1235
  {
1236
    // (str.contains (str.++ x "A") (str.++ "B" x)) ---> false
1237
    Node ctn =
1238
        d_nodeManager->mkNode(kind::STRING_CONTAINS,
1239
4
                              d_nodeManager->mkNode(kind::STRING_CONCAT, x, a),
1240
8
                              d_nodeManager->mkNode(kind::STRING_CONCAT, b, x));
1241
2
    sameNormalForm(ctn, f);
1242
  }
1243
1244
  {
1245
    // Same normal form for:
1246
    //
1247
    // (str.contains (str.replace x "ABC" "DEF") "GHI")
1248
    //
1249
    // (str.contains x "GHI")
1250
6
    lhs = d_nodeManager->mkNode(
1251
        kind::STRING_CONTAINS,
1252
4
        d_nodeManager->mkNode(kind::STRING_REPLACE, x, abc, def),
1253
        ghi);
1254
2
    rhs = d_nodeManager->mkNode(kind::STRING_CONTAINS, x, ghi);
1255
2
    sameNormalForm(lhs, rhs);
1256
  }
1257
1258
  {
1259
    // Different normal forms for:
1260
    //
1261
    // (str.contains (str.replace x "ABC" "DEF") "B")
1262
    //
1263
    // (str.contains x "B")
1264
6
    lhs = d_nodeManager->mkNode(
1265
        kind::STRING_CONTAINS,
1266
4
        d_nodeManager->mkNode(kind::STRING_REPLACE, x, abc, def),
1267
        b);
1268
2
    rhs = d_nodeManager->mkNode(kind::STRING_CONTAINS, x, b);
1269
2
    differentNormalForms(lhs, rhs);
1270
  }
1271
1272
  {
1273
    // Different normal forms for:
1274
    //
1275
    // (str.contains (str.replace x "B" "DEF") "ABC")
1276
    //
1277
    // (str.contains x "ABC")
1278
6
    lhs = d_nodeManager->mkNode(
1279
        kind::STRING_CONTAINS,
1280
4
        d_nodeManager->mkNode(kind::STRING_REPLACE, x, b, def),
1281
        abc);
1282
2
    rhs = d_nodeManager->mkNode(kind::STRING_CONTAINS, x, abc);
1283
2
    differentNormalForms(lhs, rhs);
1284
  }
1285
1286
  {
1287
    // Same normal form for:
1288
    //
1289
    // (str.contains "ABC" (str.at x n))
1290
    //
1291
    // (or (= x "")
1292
    //     (= x "A") (= x "B") (= x "C"))
1293
4
    Node cat = d_nodeManager->mkNode(kind::STRING_CHARAT, x, n);
1294
2
    lhs = d_nodeManager->mkNode(kind::STRING_CONTAINS, abc, cat);
1295
18
    rhs = d_nodeManager->mkNode(kind::OR,
1296
4
                                {d_nodeManager->mkNode(kind::EQUAL, cat, empty),
1297
4
                                 d_nodeManager->mkNode(kind::EQUAL, cat, a),
1298
4
                                 d_nodeManager->mkNode(kind::EQUAL, cat, b),
1299
12
                                 d_nodeManager->mkNode(kind::EQUAL, cat, c)});
1300
2
    sameNormalForm(lhs, rhs);
1301
  }
1302
2
}
1303
1304
26
TEST_F(TestTheoryWhiteSequencesRewriter, infer_eqs_from_contains)
1305
{
1306
4
  TypeNode strType = d_nodeManager->stringType();
1307
1308
4
  Node empty = d_nodeManager->mkConst(::cvc5::String(""));
1309
4
  Node a = d_nodeManager->mkConst(::cvc5::String("A"));
1310
4
  Node b = d_nodeManager->mkConst(::cvc5::String("B"));
1311
4
  Node x = d_nodeManager->mkVar("x", strType);
1312
4
  Node y = d_nodeManager->mkVar("y", strType);
1313
4
  Node xy = d_nodeManager->mkNode(kind::STRING_CONCAT, x, y);
1314
4
  Node f = d_nodeManager->mkConst(false);
1315
1316
  // inferEqsFromContains("", (str.++ x y)) returns something equivalent to
1317
  // (= "" y)
1318
  Node empty_x_y =
1319
      d_nodeManager->mkNode(kind::AND,
1320
4
                            d_nodeManager->mkNode(kind::EQUAL, empty, x),
1321
8
                            d_nodeManager->mkNode(kind::EQUAL, empty, y));
1322
2
  sameNormalForm(StringsEntail::inferEqsFromContains(empty, xy), empty_x_y);
1323
1324
  // inferEqsFromContains(x, (str.++ x y)) returns false
1325
4
  Node bxya = d_nodeManager->mkNode(kind::STRING_CONCAT, {b, y, x, a});
1326
2
  sameNormalForm(StringsEntail::inferEqsFromContains(x, bxya), f);
1327
1328
  // inferEqsFromContains(x, y) returns null
1329
4
  Node n = StringsEntail::inferEqsFromContains(x, y);
1330
2
  ASSERT_TRUE(n.isNull());
1331
1332
  // inferEqsFromContains(x, x) returns something equivalent to (= x x)
1333
4
  Node eq_x_x = d_nodeManager->mkNode(kind::EQUAL, x, x);
1334
2
  sameNormalForm(StringsEntail::inferEqsFromContains(x, x), eq_x_x);
1335
1336
  // inferEqsFromContains((str.replace x "B" "A"), x) returns something
1337
  // equivalent to (= (str.replace x "B" "A") x)
1338
4
  Node repl = d_nodeManager->mkNode(kind::STRING_REPLACE, x, b, a);
1339
4
  Node eq_repl_x = d_nodeManager->mkNode(kind::EQUAL, repl, x);
1340
2
  sameNormalForm(StringsEntail::inferEqsFromContains(repl, x), eq_repl_x);
1341
1342
  // inferEqsFromContains(x, (str.replace x "B" "A")) returns something
1343
  // equivalent to (= (str.replace x "B" "A") x)
1344
4
  Node eq_x_repl = d_nodeManager->mkNode(kind::EQUAL, x, repl);
1345
2
  sameNormalForm(StringsEntail::inferEqsFromContains(x, repl), eq_x_repl);
1346
}
1347
1348
26
TEST_F(TestTheoryWhiteSequencesRewriter, rewrite_prefix_suffix)
1349
{
1350
4
  TypeNode strType = d_nodeManager->stringType();
1351
1352
4
  Node empty = d_nodeManager->mkConst(::cvc5::String(""));
1353
4
  Node a = d_nodeManager->mkConst(::cvc5::String("A"));
1354
4
  Node x = d_nodeManager->mkVar("x", strType);
1355
4
  Node y = d_nodeManager->mkVar("y", strType);
1356
4
  Node xx = d_nodeManager->mkNode(kind::STRING_CONCAT, x, x);
1357
4
  Node xxa = d_nodeManager->mkNode(kind::STRING_CONCAT, x, x, a);
1358
4
  Node xy = d_nodeManager->mkNode(kind::STRING_CONCAT, x, y);
1359
4
  Node f = d_nodeManager->mkConst(false);
1360
1361
  // Same normal form for:
1362
  //
1363
  // (str.prefix (str.++ x y) x)
1364
  //
1365
  // (= y "")
1366
4
  Node p_xy = d_nodeManager->mkNode(kind::STRING_PREFIX, xy, x);
1367
4
  Node empty_y = d_nodeManager->mkNode(kind::EQUAL, y, empty);
1368
2
  sameNormalForm(p_xy, empty_y);
1369
1370
  // Same normal form for:
1371
  //
1372
  // (str.suffix (str.++ x x) x)
1373
  //
1374
  // (= x "")
1375
4
  Node p_xx = d_nodeManager->mkNode(kind::STRING_SUFFIX, xx, x);
1376
4
  Node empty_x = d_nodeManager->mkNode(kind::EQUAL, x, empty);
1377
2
  sameNormalForm(p_xx, empty_x);
1378
1379
  // (str.suffix x (str.++ x x "A")) ---> false
1380
4
  Node p_xxa = d_nodeManager->mkNode(kind::STRING_SUFFIX, xxa, x);
1381
2
  sameNormalForm(p_xxa, f);
1382
2
}
1383
1384
26
TEST_F(TestTheoryWhiteSequencesRewriter, rewrite_equality_ext)
1385
{
1386
4
  TypeNode strType = d_nodeManager->stringType();
1387
4
  TypeNode intType = d_nodeManager->integerType();
1388
1389
4
  Node empty = d_nodeManager->mkConst(::cvc5::String(""));
1390
4
  Node a = d_nodeManager->mkConst(::cvc5::String("A"));
1391
4
  Node aaa = d_nodeManager->mkConst(::cvc5::String("AAA"));
1392
4
  Node b = d_nodeManager->mkConst(::cvc5::String("B"));
1393
4
  Node ba = d_nodeManager->mkConst(::cvc5::String("BA"));
1394
4
  Node w = d_nodeManager->mkVar("w", strType);
1395
4
  Node x = d_nodeManager->mkVar("x", strType);
1396
4
  Node y = d_nodeManager->mkVar("y", strType);
1397
4
  Node z = d_nodeManager->mkVar("z", strType);
1398
4
  Node xxa = d_nodeManager->mkNode(kind::STRING_CONCAT, x, x, a);
1399
4
  Node f = d_nodeManager->mkConst(false);
1400
4
  Node n = d_nodeManager->mkVar("n", intType);
1401
4
  Node zero = d_nodeManager->mkConst(Rational(0));
1402
4
  Node one = d_nodeManager->mkConst(Rational(1));
1403
4
  Node three = d_nodeManager->mkConst(Rational(3));
1404
1405
  // Same normal form for:
1406
  //
1407
  // (= "" (str.replace "" x "B"))
1408
  //
1409
  // (not (= x ""))
1410
  Node empty_repl = d_nodeManager->mkNode(
1411
      kind::EQUAL,
1412
      empty,
1413
4
      d_nodeManager->mkNode(kind::STRING_REPLACE, empty, x, b));
1414
  Node empty_x = d_nodeManager->mkNode(
1415
4
      kind::NOT, d_nodeManager->mkNode(kind::EQUAL, x, empty));
1416
2
  sameNormalForm(empty_repl, empty_x);
1417
1418
  // Same normal form for:
1419
  //
1420
  // (= "" (str.replace x y (str.++ x x "A")))
1421
  //
1422
  // (and (= x "") (not (= y "")))
1423
  Node empty_repl_xaa = d_nodeManager->mkNode(
1424
      kind::EQUAL,
1425
      empty,
1426
4
      d_nodeManager->mkNode(kind::STRING_REPLACE, x, y, xxa));
1427
  Node empty_xy = d_nodeManager->mkNode(
1428
      kind::AND,
1429
4
      d_nodeManager->mkNode(kind::EQUAL, x, empty),
1430
6
      d_nodeManager->mkNode(kind::NOT,
1431
14
                            d_nodeManager->mkNode(kind::EQUAL, y, empty)));
1432
2
  sameNormalForm(empty_repl_xaa, empty_xy);
1433
1434
  // (= "" (str.replace (str.++ x x "A") x y)) ---> false
1435
  Node empty_repl_xxaxy = d_nodeManager->mkNode(
1436
      kind::EQUAL,
1437
      empty,
1438
4
      d_nodeManager->mkNode(kind::STRING_REPLACE, xxa, x, y));
1439
  Node eq_xxa_repl = d_nodeManager->mkNode(
1440
      kind::EQUAL,
1441
      xxa,
1442
4
      d_nodeManager->mkNode(kind::STRING_REPLACE, empty, y, x));
1443
2
  sameNormalForm(empty_repl_xxaxy, f);
1444
1445
  // Same normal form for:
1446
  //
1447
  // (= "" (str.replace "A" x y))
1448
  //
1449
  // (= "A" (str.replace "" y x))
1450
  Node empty_repl_axy = d_nodeManager->mkNode(
1451
4
      kind::EQUAL, empty, d_nodeManager->mkNode(kind::STRING_REPLACE, a, x, y));
1452
  Node eq_a_repl = d_nodeManager->mkNode(
1453
4
      kind::EQUAL, a, d_nodeManager->mkNode(kind::STRING_REPLACE, empty, y, x));
1454
2
  sameNormalForm(empty_repl_axy, eq_a_repl);
1455
1456
  // Same normal form for:
1457
  //
1458
  // (= "" (str.replace x "A" ""))
1459
  //
1460
  // (str.prefix x "A")
1461
  Node empty_repl_a = d_nodeManager->mkNode(
1462
      kind::EQUAL,
1463
      empty,
1464
4
      d_nodeManager->mkNode(kind::STRING_REPLACE, x, a, empty));
1465
4
  Node prefix_a = d_nodeManager->mkNode(kind::STRING_PREFIX, x, a);
1466
2
  sameNormalForm(empty_repl_a, prefix_a);
1467
1468
  // Same normal form for:
1469
  //
1470
  // (= "" (str.substr x 1 2))
1471
  //
1472
  // (<= (str.len x) 1)
1473
  Node empty_substr = d_nodeManager->mkNode(
1474
      kind::EQUAL,
1475
      empty,
1476
4
      d_nodeManager->mkNode(kind::STRING_SUBSTR, x, one, three));
1477
  Node leq_len_x = d_nodeManager->mkNode(
1478
4
      kind::LEQ, d_nodeManager->mkNode(kind::STRING_LENGTH, x), one);
1479
2
  sameNormalForm(empty_substr, leq_len_x);
1480
1481
  // Different normal form for:
1482
  //
1483
  // (= "" (str.substr x 0 n))
1484
  //
1485
  // (<= n 0)
1486
  Node empty_substr_x = d_nodeManager->mkNode(
1487
      kind::EQUAL,
1488
      empty,
1489
4
      d_nodeManager->mkNode(kind::STRING_SUBSTR, x, zero, n));
1490
4
  Node leq_n = d_nodeManager->mkNode(kind::LEQ, n, zero);
1491
2
  differentNormalForms(empty_substr_x, leq_n);
1492
1493
  // Same normal form for:
1494
  //
1495
  // (= "" (str.substr "A" 0 n))
1496
  //
1497
  // (<= n 0)
1498
  Node empty_substr_a = d_nodeManager->mkNode(
1499
      kind::EQUAL,
1500
      empty,
1501
4
      d_nodeManager->mkNode(kind::STRING_SUBSTR, a, zero, n));
1502
2
  sameNormalForm(empty_substr_a, leq_n);
1503
1504
  // Same normal form for:
1505
  //
1506
  // (= (str.++ x x a) (str.replace y (str.++ x x a) y))
1507
  //
1508
  // (= (str.++ x x a) y)
1509
  Node eq_xxa_repl_y = d_nodeManager->mkNode(
1510
4
      kind::EQUAL, xxa, d_nodeManager->mkNode(kind::STRING_REPLACE, y, xxa, y));
1511
4
  Node eq_xxa_y = d_nodeManager->mkNode(kind::EQUAL, xxa, y);
1512
2
  sameNormalForm(eq_xxa_repl_y, eq_xxa_y);
1513
1514
  // (= (str.++ x x a) (str.replace (str.++ x x a) "A" "B")) ---> false
1515
  Node eq_xxa_repl_xxa = d_nodeManager->mkNode(
1516
4
      kind::EQUAL, xxa, d_nodeManager->mkNode(kind::STRING_REPLACE, xxa, a, b));
1517
2
  sameNormalForm(eq_xxa_repl_xxa, f);
1518
1519
  // Same normal form for:
1520
  //
1521
  // (= (str.replace x "A" "B") "")
1522
  //
1523
  // (= x "")
1524
  Node eq_repl = d_nodeManager->mkNode(
1525
4
      kind::EQUAL, d_nodeManager->mkNode(kind::STRING_REPLACE, x, a, b), empty);
1526
4
  Node eq_x = d_nodeManager->mkNode(kind::EQUAL, x, empty);
1527
2
  sameNormalForm(eq_repl, eq_x);
1528
1529
  {
1530
    // Same normal form for:
1531
    //
1532
    // (= (str.replace y "A" "B") "B")
1533
    //
1534
    // (= (str.replace y "B" "A") "A")
1535
    Node lhs = d_nodeManager->mkNode(
1536
4
        kind::EQUAL, d_nodeManager->mkNode(kind::STRING_REPLACE, x, a, b), b);
1537
    Node rhs = d_nodeManager->mkNode(
1538
4
        kind::EQUAL, d_nodeManager->mkNode(kind::STRING_REPLACE, x, b, a), a);
1539
2
    sameNormalForm(lhs, rhs);
1540
  }
1541
1542
  {
1543
    // Same normal form for:
1544
    //
1545
    // (= (str.++ x "A" y) (str.++ "A" "A" (str.substr "AAA" 0 n)))
1546
    //
1547
    // (= (str.++ y x) (str.++ (str.substr "AAA" 0 n) "A"))
1548
    Node lhs = d_nodeManager->mkNode(
1549
        kind::EQUAL,
1550
4
        d_nodeManager->mkNode(kind::STRING_CONCAT, x, a, y),
1551
6
        d_nodeManager->mkNode(
1552
            kind::STRING_CONCAT,
1553
            a,
1554
            a,
1555
14
            d_nodeManager->mkNode(kind::STRING_SUBSTR, aaa, zero, n)));
1556
    Node rhs = d_nodeManager->mkNode(
1557
        kind::EQUAL,
1558
4
        d_nodeManager->mkNode(kind::STRING_CONCAT, x, y),
1559
8
        d_nodeManager->mkNode(
1560
            kind::STRING_CONCAT,
1561
4
            d_nodeManager->mkNode(kind::STRING_SUBSTR, aaa, zero, n),
1562
10
            a));
1563
2
    sameNormalForm(lhs, rhs);
1564
  }
1565
1566
  {
1567
    // Same normal form for:
1568
    //
1569
    // (= (str.++ "A" x) "A")
1570
    //
1571
    // (= x "")
1572
    Node lhs = d_nodeManager->mkNode(
1573
4
        kind::EQUAL, d_nodeManager->mkNode(kind::STRING_CONCAT, a, x), a);
1574
4
    Node rhs = d_nodeManager->mkNode(kind::EQUAL, x, empty);
1575
2
    sameNormalForm(lhs, rhs);
1576
  }
1577
1578
  {
1579
    // (= (str.++ x "A") "") ---> false
1580
    Node eq = d_nodeManager->mkNode(
1581
4
        kind::EQUAL, d_nodeManager->mkNode(kind::STRING_CONCAT, x, a), empty);
1582
2
    sameNormalForm(eq, f);
1583
  }
1584
1585
  {
1586
    // (= (str.++ x "B") "AAA") ---> false
1587
    Node eq = d_nodeManager->mkNode(
1588
4
        kind::EQUAL, d_nodeManager->mkNode(kind::STRING_CONCAT, x, b), aaa);
1589
2
    sameNormalForm(eq, f);
1590
  }
1591
1592
  {
1593
    // (= (str.++ x "AAA") "A") ---> false
1594
    Node eq = d_nodeManager->mkNode(
1595
4
        kind::EQUAL, d_nodeManager->mkNode(kind::STRING_CONCAT, x, aaa), a);
1596
2
    sameNormalForm(eq, f);
1597
  }
1598
1599
  {
1600
    // (= (str.++ "AAA" (str.substr "A" 0 n)) (str.++ x "B")) ---> false
1601
    Node eq = d_nodeManager->mkNode(
1602
        kind::EQUAL,
1603
6
        d_nodeManager->mkNode(
1604
            kind::STRING_CONCAT,
1605
            aaa,
1606
6
            d_nodeManager->mkNode(
1607
                kind::STRING_CONCAT,
1608
                a,
1609
                a,
1610
4
                d_nodeManager->mkNode(kind::STRING_SUBSTR, x, zero, n))),
1611
8
        d_nodeManager->mkNode(kind::STRING_CONCAT, x, b));
1612
2
    sameNormalForm(eq, f);
1613
  }
1614
1615
  {
1616
    // (= (str.++ "A" (int.to.str n)) "A") -/-> false
1617
    Node eq = d_nodeManager->mkNode(
1618
        kind::EQUAL,
1619
6
        d_nodeManager->mkNode(kind::STRING_CONCAT,
1620
                              a,
1621
4
                              d_nodeManager->mkNode(kind::STRING_ITOS, n)),
1622
8
        a);
1623
2
    differentNormalForms(eq, f);
1624
  }
1625
1626
  {
1627
    // (= (str.++ "A" x y) (str.++ x "B" z)) --> false
1628
    Node eq = d_nodeManager->mkNode(
1629
        kind::EQUAL,
1630
4
        d_nodeManager->mkNode(kind::STRING_CONCAT, a, x, y),
1631
8
        d_nodeManager->mkNode(kind::STRING_CONCAT, x, b, z));
1632
2
    sameNormalForm(eq, f);
1633
  }
1634
1635
  {
1636
    // (= (str.++ "B" x y) (str.++ x "AAA" z)) --> false
1637
    Node eq = d_nodeManager->mkNode(
1638
        kind::EQUAL,
1639
4
        d_nodeManager->mkNode(kind::STRING_CONCAT, b, x, y),
1640
8
        d_nodeManager->mkNode(kind::STRING_CONCAT, x, aaa, z));
1641
2
    sameNormalForm(eq, f);
1642
  }
1643
1644
  {
1645
4
    Node xrepl = d_nodeManager->mkNode(kind::STRING_REPLACE, x, a, b);
1646
1647
    // Same normal form for:
1648
    //
1649
    // (= (str.++ "B" (str.replace x "A" "B") z y w)
1650
    //    (str.++ z x "BA" z))
1651
    //
1652
    // (and (= (str.++ "B" (str.replace x "A" "B") z)
1653
    //         (str.++ z x "B"))
1654
    //      (= (str.++ y w) (str.++ "A" z)))
1655
    Node lhs = d_nodeManager->mkNode(
1656
        kind::EQUAL,
1657
4
        d_nodeManager->mkNode(kind::STRING_CONCAT, {b, xrepl, z, y, w}),
1658
8
        d_nodeManager->mkNode(kind::STRING_CONCAT, {z, x, ba, z}));
1659
    Node rhs = d_nodeManager->mkNode(
1660
        kind::AND,
1661
10
        d_nodeManager->mkNode(
1662
            kind::EQUAL,
1663
4
            d_nodeManager->mkNode(kind::STRING_CONCAT, b, xrepl, z),
1664
4
            d_nodeManager->mkNode(kind::STRING_CONCAT, z, x, b)),
1665
10
        d_nodeManager->mkNode(
1666
            kind::EQUAL,
1667
4
            d_nodeManager->mkNode(kind::STRING_CONCAT, y, w),
1668
14
            d_nodeManager->mkNode(kind::STRING_CONCAT, a, z)));
1669
2
    sameNormalForm(lhs, rhs);
1670
  }
1671
2
}
1672
1673
26
TEST_F(TestTheoryWhiteSequencesRewriter, strip_constant_endpoints)
1674
{
1675
4
  TypeNode intType = d_nodeManager->integerType();
1676
4
  TypeNode strType = d_nodeManager->stringType();
1677
1678
4
  Node empty = d_nodeManager->mkConst(::cvc5::String(""));
1679
4
  Node a = d_nodeManager->mkConst(::cvc5::String("A"));
1680
4
  Node ab = d_nodeManager->mkConst(::cvc5::String("AB"));
1681
4
  Node abc = d_nodeManager->mkConst(::cvc5::String("ABC"));
1682
4
  Node abcd = d_nodeManager->mkConst(::cvc5::String("ABCD"));
1683
4
  Node bc = d_nodeManager->mkConst(::cvc5::String("BC"));
1684
4
  Node c = d_nodeManager->mkConst(::cvc5::String("C"));
1685
4
  Node cd = d_nodeManager->mkConst(::cvc5::String("CD"));
1686
4
  Node x = d_nodeManager->mkVar("x", strType);
1687
4
  Node y = d_nodeManager->mkVar("y", strType);
1688
4
  Node n = d_nodeManager->mkVar("n", intType);
1689
1690
  {
1691
    // stripConstantEndpoints({ "" }, { "A" }, {}, {}, 0) ---> false
1692
4
    std::vector<Node> n1 = {empty};
1693
4
    std::vector<Node> n2 = {a};
1694
4
    std::vector<Node> nb;
1695
4
    std::vector<Node> ne;
1696
2
    bool res = StringsEntail::stripConstantEndpoints(n1, n2, nb, ne, 0);
1697
2
    ASSERT_FALSE(res);
1698
  }
1699
1700
  {
1701
    // stripConstantEndpoints({ "A" }, { "A". (int.to.str n) }, {}, {}, 0)
1702
    // ---> false
1703
4
    std::vector<Node> n1 = {a};
1704
4
    std::vector<Node> n2 = {a, d_nodeManager->mkNode(kind::STRING_ITOS, n)};
1705
4
    std::vector<Node> nb;
1706
4
    std::vector<Node> ne;
1707
2
    bool res = StringsEntail::stripConstantEndpoints(n1, n2, nb, ne, 0);
1708
2
    ASSERT_FALSE(res);
1709
  }
1710
1711
  {
1712
    // stripConstantEndpoints({ "ABCD" }, { "C" }, {}, {}, 1)
1713
    // ---> true
1714
    // n1 is updated to { "CD" }
1715
    // nb is updated to { "AB" }
1716
4
    std::vector<Node> n1 = {abcd};
1717
4
    std::vector<Node> n2 = {c};
1718
4
    std::vector<Node> nb;
1719
4
    std::vector<Node> ne;
1720
4
    std::vector<Node> n1r = {cd};
1721
4
    std::vector<Node> nbr = {ab};
1722
2
    bool res = StringsEntail::stripConstantEndpoints(n1, n2, nb, ne, 1);
1723
2
    ASSERT_TRUE(res);
1724
2
    ASSERT_EQ(n1, n1r);
1725
2
    ASSERT_EQ(nb, nbr);
1726
  }
1727
1728
  {
1729
    // stripConstantEndpoints({ "ABC", x }, { "CD" }, {}, {}, 1)
1730
    // ---> true
1731
    // n1 is updated to { "C", x }
1732
    // nb is updated to { "AB" }
1733
4
    std::vector<Node> n1 = {abc, x};
1734
4
    std::vector<Node> n2 = {cd};
1735
4
    std::vector<Node> nb;
1736
4
    std::vector<Node> ne;
1737
4
    std::vector<Node> n1r = {c, x};
1738
4
    std::vector<Node> nbr = {ab};
1739
2
    bool res = StringsEntail::stripConstantEndpoints(n1, n2, nb, ne, 1);
1740
2
    ASSERT_TRUE(res);
1741
2
    ASSERT_EQ(n1, n1r);
1742
2
    ASSERT_EQ(nb, nbr);
1743
  }
1744
1745
  {
1746
    // stripConstantEndpoints({ "ABC" }, { "A" }, {}, {}, -1)
1747
    // ---> true
1748
    // n1 is updated to { "A" }
1749
    // nb is updated to { "BC" }
1750
4
    std::vector<Node> n1 = {abc};
1751
4
    std::vector<Node> n2 = {a};
1752
4
    std::vector<Node> nb;
1753
4
    std::vector<Node> ne;
1754
4
    std::vector<Node> n1r = {a};
1755
4
    std::vector<Node> ner = {bc};
1756
2
    bool res = StringsEntail::stripConstantEndpoints(n1, n2, nb, ne, -1);
1757
2
    ASSERT_TRUE(res);
1758
2
    ASSERT_EQ(n1, n1r);
1759
2
    ASSERT_EQ(ne, ner);
1760
  }
1761
1762
  {
1763
    // stripConstantEndpoints({ x, "ABC" }, { y, "A" }, {}, {}, -1)
1764
    // ---> true
1765
    // n1 is updated to { x, "A" }
1766
    // nb is updated to { "BC" }
1767
4
    std::vector<Node> n1 = {x, abc};
1768
4
    std::vector<Node> n2 = {y, a};
1769
4
    std::vector<Node> nb;
1770
4
    std::vector<Node> ne;
1771
4
    std::vector<Node> n1r = {x, a};
1772
4
    std::vector<Node> ner = {bc};
1773
2
    bool res = StringsEntail::stripConstantEndpoints(n1, n2, nb, ne, -1);
1774
2
    ASSERT_TRUE(res);
1775
2
    ASSERT_EQ(n1, n1r);
1776
2
    ASSERT_EQ(ne, ner);
1777
  }
1778
}
1779
1780
26
TEST_F(TestTheoryWhiteSequencesRewriter, rewrite_membership)
1781
{
1782
4
  TypeNode strType = d_nodeManager->stringType();
1783
1784
4
  std::vector<Node> vec_empty;
1785
4
  Node abc = d_nodeManager->mkConst(::cvc5::String("ABC"));
1786
4
  Node re_abc = d_nodeManager->mkNode(kind::STRING_TO_REGEXP, abc);
1787
4
  Node x = d_nodeManager->mkVar("x", strType);
1788
1789
  {
1790
    // Same normal form for:
1791
    //
1792
    // (str.in.re x (re.++ (re.* re.allchar)
1793
    //                     (re.* re.allchar)
1794
    //                     (str.to.re "ABC")
1795
    //                     (re.* re.allchar)))
1796
    //
1797
    // (str.contains x "ABC")
1798
    Node sig_star = d_nodeManager->mkNode(
1799
        kind::REGEXP_STAR,
1800
4
        d_nodeManager->mkNode(kind::REGEXP_SIGMA, vec_empty));
1801
    Node lhs = d_nodeManager->mkNode(
1802
        kind::STRING_IN_REGEXP,
1803
        x,
1804
6
        d_nodeManager->mkNode(kind::REGEXP_CONCAT,
1805
14
                              {sig_star, sig_star, re_abc, sig_star}));
1806
4
    Node rhs = d_nodeManager->mkNode(kind::STRING_CONTAINS, x, abc);
1807
2
    sameNormalForm(lhs, rhs);
1808
  }
1809
1810
  {
1811
    // Different normal forms for:
1812
    //
1813
    // (str.in.re x (re.++ (re.* re.allchar) (str.to.re "ABC")))
1814
    //
1815
    // (str.contains x "ABC")
1816
    Node sig_star = d_nodeManager->mkNode(
1817
        kind::REGEXP_STAR,
1818
4
        d_nodeManager->mkNode(kind::REGEXP_SIGMA, vec_empty));
1819
    Node lhs = d_nodeManager->mkNode(
1820
        kind::STRING_IN_REGEXP,
1821
        x,
1822
4
        d_nodeManager->mkNode(kind::REGEXP_CONCAT, sig_star, re_abc));
1823
4
    Node rhs = d_nodeManager->mkNode(kind::STRING_CONTAINS, x, abc);
1824
2
    differentNormalForms(lhs, rhs);
1825
  }
1826
2
}
1827
1828
26
TEST_F(TestTheoryWhiteSequencesRewriter, rewrite_regexp_concat)
1829
{
1830
4
  TypeNode strType = d_nodeManager->stringType();
1831
1832
4
  std::vector<Node> emptyArgs;
1833
4
  Node x = d_nodeManager->mkVar("x", strType);
1834
4
  Node y = d_nodeManager->mkVar("y", strType);
1835
  Node allStar = d_nodeManager->mkNode(
1836
4
      kind::REGEXP_STAR, d_nodeManager->mkNode(kind::REGEXP_SIGMA, emptyArgs));
1837
4
  Node xReg = d_nodeManager->mkNode(kind::STRING_TO_REGEXP, x);
1838
4
  Node yReg = d_nodeManager->mkNode(kind::STRING_TO_REGEXP, y);
1839
1840
  {
1841
    // In normal form:
1842
    //
1843
    // (re.++ (re.* re.allchar) (re.union (str.to.re x) (str.to.re y)))
1844
    Node n = d_nodeManager->mkNode(
1845
        kind::REGEXP_CONCAT,
1846
        allStar,
1847
4
        d_nodeManager->mkNode(kind::REGEXP_UNION, xReg, yReg));
1848
2
    inNormalForm(n);
1849
  }
1850
1851
  {
1852
    // In normal form:
1853
    //
1854
    // (re.++ (str.to.re x) (re.* re.allchar))
1855
4
    Node n = d_nodeManager->mkNode(kind::REGEXP_CONCAT, xReg, allStar);
1856
2
    inNormalForm(n);
1857
  }
1858
2
}
1859
}  // namespace test
1860
12087926
}  // namespace cvc5