@@ -2210,13 +2210,21 @@ br_status seq_rewriter::mk_eq_core(expr * l, expr * r, expr_ref & result) {
2210
2210
return BR_REWRITE3;
2211
2211
}
2212
2212
2213
- void seq_rewriter::remove_empty (expr_ref_vector& es) {
2213
+ void seq_rewriter::remove_empty_and_concats (expr_ref_vector& es) {
2214
2214
unsigned j = 0 ;
2215
+ bool has_concat = false ;
2215
2216
for (expr* e : es) {
2217
+ has_concat |= m_util.str .is_concat (e);
2216
2218
if (!m_util.str .is_empty (e))
2217
2219
es[j++] = e;
2218
2220
}
2219
2221
es.shrink (j);
2222
+ if (has_concat) {
2223
+ expr_ref_vector fs (m ());
2224
+ for (expr* e : es)
2225
+ m_util.str .get_concat (e, fs);
2226
+ es.swap (fs);
2227
+ }
2220
2228
}
2221
2229
2222
2230
void seq_rewriter::remove_leading (unsigned n, expr_ref_vector& es) {
@@ -2229,15 +2237,15 @@ void seq_rewriter::remove_leading(unsigned n, expr_ref_vector& es) {
2229
2237
es.shrink (es.size () - n);
2230
2238
}
2231
2239
2232
- bool seq_rewriter::reduce_back (expr_ref_vector& ls, expr_ref_vector& rs, expr_ref_pair_vector& new_eqs, bool & change ) {
2240
+ bool seq_rewriter::reduce_back (expr_ref_vector& ls, expr_ref_vector& rs, expr_ref_pair_vector& new_eqs) {
2233
2241
expr* a, *b;
2234
2242
zstring s, s1, s2;
2235
2243
while (true ) {
2236
2244
if (ls.empty () || rs.empty ()) {
2237
2245
break ;
2238
2246
}
2239
2247
expr* l = ls.back ();
2240
- expr* r = rs.back ();
2248
+ expr* r = rs.back ();
2241
2249
if (m_util.str .is_unit (r) && m_util.str .is_string (l)) {
2242
2250
std::swap (l, r);
2243
2251
ls.swap (rs);
@@ -2289,12 +2297,11 @@ bool seq_rewriter::reduce_back(expr_ref_vector& ls, expr_ref_vector& rs, expr_re
2289
2297
else {
2290
2298
break ;
2291
2299
}
2292
- change = true ;
2293
2300
}
2294
2301
return true ;
2295
2302
}
2296
2303
2297
- bool seq_rewriter::reduce_front (expr_ref_vector& ls, expr_ref_vector& rs, expr_ref_pair_vector& new_eqs, bool & change ) {
2304
+ bool seq_rewriter::reduce_front (expr_ref_vector& ls, expr_ref_vector& rs, expr_ref_pair_vector& new_eqs) {
2298
2305
expr* a, *b;
2299
2306
zstring s, s1, s2;
2300
2307
unsigned head1 = 0 , head2 = 0 ;
@@ -2364,7 +2371,6 @@ bool seq_rewriter::reduce_front(expr_ref_vector& ls, expr_ref_vector& rs, expr_r
2364
2371
else {
2365
2372
break ;
2366
2373
}
2367
- change = true ;
2368
2374
}
2369
2375
remove_leading (head1, ls);
2370
2376
remove_leading (head2, rs);
@@ -2376,17 +2382,24 @@ bool seq_rewriter::reduce_front(expr_ref_vector& ls, expr_ref_vector& rs, expr_r
2376
2382
- New equalities are inserted into eqs.
2377
2383
- Last remaining equalities that cannot be simplified further are kept in ls, rs
2378
2384
- returns false if equality is unsatisfiable
2385
+ - sets change to true if some simplification occurred
2379
2386
*/
2380
2387
bool seq_rewriter::reduce_eq (expr_ref_vector& ls, expr_ref_vector& rs, expr_ref_pair_vector& eqs, bool & change) {
2381
2388
TRACE (" seq_verbose" , tout << ls << " \n " ; tout << rs << " \n " ;);
2382
- remove_empty (ls);
2383
- remove_empty (rs);
2389
+ unsigned hash_l = ls.hash ();
2390
+ unsigned hash_r = rs.hash ();
2391
+ unsigned sz_eqs = eqs.size ();
2392
+ remove_empty_and_concats (ls);
2393
+ remove_empty_and_concats (rs);
2384
2394
return
2385
- reduce_back (ls, rs, eqs, change) &&
2386
- reduce_front (ls, rs, eqs, change) &&
2387
- reduce_itos (ls, rs, eqs, change) &&
2388
- reduce_by_length (ls, rs, eqs, change) &&
2389
- reduce_subsequence (ls, rs, eqs, change);
2395
+ reduce_back (ls, rs, eqs) &&
2396
+ reduce_front (ls, rs, eqs) &&
2397
+ reduce_itos (ls, rs, eqs) &&
2398
+ reduce_itos (rs, ls, eqs) &&
2399
+ reduce_by_length (ls, rs, eqs) &&
2400
+ reduce_subsequence (ls, rs, eqs) &&
2401
+ (change = (hash_l != ls.hash () || hash_r != rs.hash () || eqs.size () != sz_eqs),
2402
+ true );
2390
2403
}
2391
2404
2392
2405
bool seq_rewriter::reduce_eq (expr* l, expr* r, expr_ref_pair_vector& new_eqs, bool & changed) {
@@ -2552,41 +2565,31 @@ bool seq_rewriter::is_string(unsigned n, expr* const* es, zstring& s) const {
2552
2565
return true ;
2553
2566
}
2554
2567
2555
- bool seq_rewriter::reduce_itos (expr_ref_vector& ls, expr_ref_vector& rs,
2556
- expr_ref_pair_vector& eqs, bool & change) {
2557
- expr* n = nullptr ;
2558
- if (ls.size () == 1 && m_util.str .is_itos (ls.get (0 ), n) &&
2559
- solve_itos (n, rs, eqs)) {
2560
- ls.reset (); rs.reset ();
2561
- change = true ;
2562
- }
2563
- else if (rs.size () == 1 && m_util.str .is_itos (rs.get (0 ), n) &&
2564
- solve_itos (n, ls, eqs)) {
2565
- ls.reset (); rs.reset ();
2566
- change = true ;
2567
- }
2568
- return true ;
2569
- }
2570
-
2571
2568
/* *
2572
2569
* itos(n) = <numeric string> -> n = numeric
2573
2570
*/
2574
2571
2575
- bool seq_rewriter::solve_itos (expr* n, expr_ref_vector const & es, expr_ref_pair_vector& eqs) {
2572
+ bool seq_rewriter::reduce_itos (expr_ref_vector& ls, expr_ref_vector& rs,
2573
+ expr_ref_pair_vector& eqs) {
2574
+ expr* n = nullptr ;
2576
2575
zstring s;
2577
- if (is_string (es.size (), es.c_ptr (), s)) {
2576
+ if (ls.size () == 1 &&
2577
+ m_util.str .is_itos (ls.get (0 ), n) &&
2578
+ is_string (rs.size (), rs.c_ptr (), s)) {
2578
2579
std::string s1 = s.encode ();
2579
2580
rational r (s1.c_str ());
2580
2581
if (s1 == r.to_string ()) {
2581
2582
eqs.push_back (n, m_autil.mk_numeral (r, true ));
2583
+ ls.reset ();
2584
+ rs.reset ();
2582
2585
return true ;
2583
2586
}
2584
- }
2585
- return false ;
2587
+ }
2588
+ return true ;
2586
2589
}
2587
2590
2588
2591
bool seq_rewriter::reduce_by_length (expr_ref_vector& ls, expr_ref_vector& rs,
2589
- expr_ref_pair_vector& eqs, bool & change ) {
2592
+ expr_ref_pair_vector& eqs) {
2590
2593
2591
2594
if (ls.empty () && rs.empty ())
2592
2595
return true ;
@@ -2599,15 +2602,13 @@ bool seq_rewriter::reduce_by_length(expr_ref_vector& ls, expr_ref_vector& rs,
2599
2602
if (bounded2 && len2 < len1)
2600
2603
return false ;
2601
2604
if (bounded1 && len1 == len2 && len1 > 0 ) {
2602
- change = true ;
2603
2605
if (!set_empty (rs.size (), rs.c_ptr (), false , eqs))
2604
2606
return false ;
2605
2607
eqs.push_back (concat_non_empty (ls), concat_non_empty (rs));
2606
2608
ls.reset ();
2607
2609
rs.reset ();
2608
2610
}
2609
2611
else if (bounded2 && len1 == len2 && len1 > 0 ) {
2610
- change = true ;
2611
2612
if (!set_empty (ls.size (), ls.c_ptr (), false , eqs))
2612
2613
return false ;
2613
2614
eqs.push_back (concat_non_empty (ls), concat_non_empty (rs));
@@ -2623,7 +2624,7 @@ bool seq_rewriter::is_epsilon(expr* e) const {
2623
2624
return m_util.re .is_to_re (e, e1 ) && m_util.str .is_empty (e1 );
2624
2625
}
2625
2626
2626
- bool seq_rewriter::reduce_subsequence (expr_ref_vector& ls, expr_ref_vector& rs, expr_ref_pair_vector& eqs, bool & change ) {
2627
+ bool seq_rewriter::reduce_subsequence (expr_ref_vector& ls, expr_ref_vector& rs, expr_ref_pair_vector& eqs) {
2627
2628
2628
2629
if (ls.size () > rs.size ())
2629
2630
ls.swap (rs);
@@ -2663,7 +2664,6 @@ bool seq_rewriter::reduce_subsequence(expr_ref_vector& ls, expr_ref_vector& rs,
2663
2664
if (j == rs.size ()) {
2664
2665
return true ;
2665
2666
}
2666
- change = true ;
2667
2667
rs.shrink (j);
2668
2668
SASSERT (ls.size () == rs.size ());
2669
2669
if (!ls.empty ()) {
0 commit comments