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