1 /********************* */
2 /*! \file theory_strings_preprocess.cpp
4 ** Original author: Tianyi Liang
5 ** Major contributors: Morgan Deters
6 ** Minor contributors (to current version): none
7 ** This file is part of the CVC4 project.
8 ** Copyright (c) 2009-2013 New York University and The University of Iowa
9 ** See the file COPYING in the top-level source directory for licensing
10 ** information.\endverbatim
12 ** \brief Strings Preprocess
14 ** Strings Preprocess.
17 #include "theory/strings/theory_strings_preprocess.h"
18 #include "expr/kind.h"
19 #include "theory/strings/options.h"
20 #include "smt/logic_exception.h"
26 StringsPreprocess::StringsPreprocess() {
27 std::vector
< TypeNode
> argTypes
;
28 argTypes
.push_back(NodeManager::currentNM()->stringType());
29 argTypes
.push_back(NodeManager::currentNM()->integerType());
32 d_zero
= NodeManager::currentNM()->mkConst( ::CVC4::Rational(0) );
35 void StringsPreprocess::simplifyRegExp( Node s
, Node r
, std::vector
< Node
> &ret
, std::vector
< Node
> &nn
) {
38 case kind::STRING_TO_REGEXP
:
40 Node eq
= NodeManager::currentNM()->mkNode( kind::EQUAL
, s
, r
[0] );
44 case kind::REGEXP_CONCAT
:
46 std::vector
< Node
> cc
;
47 for(unsigned i
=0; i
<r
.getNumChildren(); ++i
) {
48 if(r
[i
].getKind() == kind::STRING_TO_REGEXP
) {
49 cc
.push_back( r
[i
][0] );
51 Node sk
= NodeManager::currentNM()->mkSkolem( "recsym_$$", s
.getType(), "created for regular expression concat" );
52 simplifyRegExp( sk
, r
[i
], ret
, nn
);
56 Node cc_eq
= NodeManager::currentNM()->mkNode( kind::EQUAL
, s
,
57 NodeManager::currentNM()->mkNode( kind::STRING_CONCAT
, cc
) );
58 nn
.push_back( cc_eq
);
63 std::vector
< Node
> c_or
;
64 for(unsigned i
=0; i
<r
.getNumChildren(); ++i
) {
65 simplifyRegExp( s
, r
[i
], c_or
, nn
);
67 Node eq
= NodeManager::currentNM()->mkNode( kind::OR
, c_or
);
71 case kind::REGEXP_INTER
:
72 for(unsigned i
=0; i
<r
.getNumChildren(); ++i
) {
73 simplifyRegExp( s
, r
[i
], ret
, nn
);
76 case kind::REGEXP_STAR
:
78 Node eq
= NodeManager::currentNM()->mkNode( kind::STRING_IN_REGEXP
, s
, r
);
83 //TODO: special sym: sigma, none, all
84 Trace("strings-preprocess") << "Unsupported term: " << r
<< " in simplifyRegExp." << std::endl
;
90 bool StringsPreprocess::checkStarPlus( Node t
) {
91 if( t
.getKind() != kind::REGEXP_STAR
&& t
.getKind() != kind::REGEXP_PLUS
) {
92 for( unsigned i
= 0; i
<t
.getNumChildren(); ++i
) {
93 if( checkStarPlus(t
[i
]) ) return true;
100 int StringsPreprocess::checkFixLenVar( Node t
) {
102 if(t
.getKind() == kind::EQUAL
) {
103 if(t
[0].getType().isInteger() && t
[0].isConst() && t
[1].getKind() == kind::STRING_LENGTH
) {
104 if(t
[1][0].getKind() == kind::VARIABLE
) {
107 } else if(t
[1].getType().isInteger() && t
[1].isConst() && t
[0].getKind() == kind::STRING_LENGTH
) {
108 if(t
[0][0].getKind() == kind::VARIABLE
) {
114 int len
= t
[ret
].getConst
<Rational
>().getNumerator().toUnsignedInt();
119 if(!options::stringExp()) {
124 Node
StringsPreprocess::simplify( Node t
, std::vector
< Node
> &new_nodes
) {
125 std::hash_map
<TNode
, Node
, TNodeHashFunction
>::const_iterator i
= d_cache
.find(t
);
126 if(i
!= d_cache
.end()) {
127 return (*i
).second
.isNull() ? t
: (*i
).second
;
130 Trace("strings-preprocess") << "StringsPreprocess::simplify: " << t
<< std::endl
;
132 /*int c_id = checkFixLenVar(t);
135 int len = t[c_id].getConst<Rational>().getNumerator().toUnsignedInt();
137 Node one = NodeManager::currentNM()->mkConst( ::CVC4::Rational(1) );
138 std::vector< Node > vec;
139 for(int i=0; i<len; i++) {
140 Node num = NodeManager::currentNM()->mkConst( ::CVC4::Rational(i) );
141 //Node sk = NodeManager::currentNM()->mkNode(kind::STRING_CHARAT, t[v_id][0], num);
142 Node sk = NodeManager::currentNM()->mkNode(kind::APPLY_UF, d_ufSubstr, t[v_id][0], num, one);
144 Node cc = one.eqNode(NodeManager::currentNM()->mkNode( kind::STRING_LENGTH, sk ));
145 new_nodes.push_back( cc );
147 Node lem = t[v_id][0].eqNode( NodeManager::currentNM()->mkNode( kind::STRING_CONCAT, vec ) );
148 lem = NodeManager::currentNM()->mkNode( kind::IMPLIES, t, lem );
149 new_nodes.push_back( lem );
153 } else */if( t
.getKind() == kind::STRING_IN_REGEXP
) {
155 Node t0
= simplify( t
[0], new_nodes
);
157 //if(!checkStarPlus( t[1] )) {
159 std::vector
< Node
> ret
;
160 std::vector
< Node
> nn
;
161 simplifyRegExp( t0
, t
[1], ret
, nn
);
162 new_nodes
.insert( new_nodes
.end(), nn
.begin(), nn
.end() );
164 Node n
= ret
.size() == 1 ? ret
[0] : NodeManager::currentNM()->mkNode( kind::AND
, ret
);
165 d_cache
[t
] = (t
== n
) ? Node::null() : n
;
169 // return (t0 == t[0]) ? t : NodeManager::currentNM()->mkNode( kind::STRING_IN_REGEXP, t0, t[1] );
171 } else if( t
.getKind() == kind::STRING_SUBSTR_TOTAL
) {
172 Node lenxgti
= NodeManager::currentNM()->mkNode( kind::GEQ
,
173 NodeManager::currentNM()->mkNode( kind::STRING_LENGTH
, t
[0] ),
174 NodeManager::currentNM()->mkNode( kind::PLUS
, t
[1], t
[2] ) );
175 Node t1geq0
= NodeManager::currentNM()->mkNode(kind::GEQ
, t
[1], d_zero
);
176 Node t2geq0
= NodeManager::currentNM()->mkNode(kind::GEQ
, t
[2], d_zero
);
177 Node cond
= Rewriter::rewrite( NodeManager::currentNM()->mkNode( kind::AND
, lenxgti
, t1geq0
, t2geq0
));
178 Node sk1
= NodeManager::currentNM()->mkSkolem( "ss1_$$", NodeManager::currentNM()->stringType(), "created for charat/substr" );
179 Node sk3
= NodeManager::currentNM()->mkSkolem( "ss3_$$", NodeManager::currentNM()->stringType(), "created for charat/substr" );
180 Node x_eq_123
= t
[0].eqNode( NodeManager::currentNM()->mkNode( kind::STRING_CONCAT
, sk1
, t
, sk3
) );
181 Node len_sk1_eq_i
= t
[1].eqNode( NodeManager::currentNM()->mkNode( kind::STRING_LENGTH
, sk1
) );
182 //Node len_uf_eq_j = t[2].eqNode( NodeManager::currentNM()->mkNode( kind::STRING_LENGTH, uf ) );
183 Node lemma
= Rewriter::rewrite( NodeManager::currentNM()->mkNode( kind::ITE
, cond
,
184 NodeManager::currentNM()->mkNode( kind::AND
, x_eq_123
, len_sk1_eq_i
),
185 t
.eqNode(NodeManager::currentNM()->mkConst( ::CVC4::String("") )) ));
186 new_nodes
.push_back( lemma
);
189 } else if( t
.getKind() == kind::STRING_STRIDOF
) {
190 if(options::stringExp()) {
191 Node sk1
= NodeManager::currentNM()->mkSkolem( "io1_$$", t
[0].getType(), "created for indexof" );
192 Node sk2
= NodeManager::currentNM()->mkSkolem( "io2_$$", t
[0].getType(), "created for indexof" );
193 Node sk3
= NodeManager::currentNM()->mkSkolem( "io3_$$", t
[0].getType(), "created for indexof" );
194 Node sk4
= NodeManager::currentNM()->mkSkolem( "io4_$$", t
[0].getType(), "created for indexof" );
195 Node skk
= NodeManager::currentNM()->mkSkolem( "iok_$$", t
[2].getType(), "created for indexof" );
196 Node eq
= t
[0].eqNode( NodeManager::currentNM()->mkNode( kind::STRING_CONCAT
, sk1
, sk2
, sk3
, sk4
) );
197 new_nodes
.push_back( eq
);
198 Node negone
= NodeManager::currentNM()->mkConst( ::CVC4::Rational(-1) );
199 Node krange
= NodeManager::currentNM()->mkNode( kind::GEQ
, skk
, negone
);
200 new_nodes
.push_back( krange
);
201 krange
= NodeManager::currentNM()->mkNode( kind::GT
,
202 NodeManager::currentNM()->mkNode( kind::STRING_LENGTH
, t
[0] ), skk
);
203 new_nodes
.push_back( krange
);
205 //str.len(s1) < y + str.len(s2)
206 Node c1
= Rewriter::rewrite(NodeManager::currentNM()->mkNode( kind::GT
,
207 NodeManager::currentNM()->mkNode( kind::PLUS
, t
[2], NodeManager::currentNM()->mkNode( kind::STRING_LENGTH
, t
[1] )),
208 NodeManager::currentNM()->mkNode( kind::STRING_LENGTH
, t
[0] )));
210 Node c2
= t
[2].eqNode( NodeManager::currentNM()->mkNode( kind::STRING_LENGTH
, sk1
) );
212 Node c3
= Rewriter::rewrite(NodeManager::currentNM()->mkNode( kind::STRING_STRCTN
,
213 NodeManager::currentNM()->mkNode( kind::STRING_CONCAT
, sk2
, sk3
, sk4
), t
[1] ).negate());
215 Node left
= NodeManager::currentNM()->mkNode( kind::OR
, c1
, NodeManager::currentNM()->mkNode( kind::AND
, c2
, c3
) );
217 Node c4
= t
[1].eqNode( sk3
);
219 Node c5
= NodeManager::currentNM()->mkNode( kind::STRING_STRCTN
, sk2
, t
[1] ).negate();
221 Node c6
= skk
.eqNode( NodeManager::currentNM()->mkNode( kind::STRING_LENGTH
,
222 NodeManager::currentNM()->mkNode( kind::STRING_CONCAT
, sk1
, sk2
)));
224 Node right
= Rewriter::rewrite(NodeManager::currentNM()->mkNode( kind::AND
, c2
, c4
, c5
, c6
));
225 Node cond
= skk
.eqNode( negone
);
226 Node rr
= NodeManager::currentNM()->mkNode( kind::ITE
, cond
, left
, right
);
227 new_nodes
.push_back( rr
);
231 throw LogicException("string indexof not supported in this release");
233 } else if( t
.getKind() == kind::STRING_ITOS
) {
234 if(options::stringExp()) {
235 Node num
= t
[0];//NodeManager::currentNM()->mkNode(kind::ABS, t[0]);
236 Node pret
= NodeManager::currentNM()->mkNode(kind::STRING_ITOS
, num
);
237 Node lenp
= NodeManager::currentNM()->mkNode(kind::STRING_LENGTH
, pret
);
239 Node b1
= NodeManager::currentNM()->mkBoundVar("x", NodeManager::currentNM()->integerType());
240 Node b1v
= NodeManager::currentNM()->mkNode(kind::BOUND_VAR_LIST
, b1
);
241 Node g1
= Rewriter::rewrite( NodeManager::currentNM()->mkNode( kind::AND
, NodeManager::currentNM()->mkNode( kind::GEQ
, b1
, d_zero
),
242 NodeManager::currentNM()->mkNode( kind::GT
, lenp
, b1
) ) );
243 Node one
= NodeManager::currentNM()->mkConst( ::CVC4::Rational(1) );
244 Node nine
= NodeManager::currentNM()->mkConst( ::CVC4::Rational(9) );
245 Node ten
= NodeManager::currentNM()->mkConst( ::CVC4::Rational(10) );
247 std::vector
< TypeNode
> argTypes
;
248 argTypes
.push_back(NodeManager::currentNM()->integerType());
249 Node ufP
= NodeManager::currentNM()->mkSkolem("ufP_$$",
250 NodeManager::currentNM()->mkFunctionType(
251 argTypes
, NodeManager::currentNM()->integerType()),
253 Node ufM
= NodeManager::currentNM()->mkSkolem("ufM_$$",
254 NodeManager::currentNM()->mkFunctionType(
255 argTypes
, NodeManager::currentNM()->integerType()),
258 new_nodes
.push_back( num
.eqNode(NodeManager::currentNM()->mkNode(kind::APPLY_UF
, ufP
, d_zero
)) );
259 new_nodes
.push_back( NodeManager::currentNM()->mkNode(kind::GT
, lenp
, d_zero
) );
261 Node ufx
= NodeManager::currentNM()->mkNode(kind::APPLY_UF
, ufP
, b1
);
262 Node ufx1
= NodeManager::currentNM()->mkNode(kind::APPLY_UF
, ufP
, NodeManager::currentNM()->mkNode(kind::MINUS
,b1
,one
));
263 Node ufMx
= NodeManager::currentNM()->mkNode(kind::APPLY_UF
, ufM
, b1
);
264 Node b1gtz
= NodeManager::currentNM()->mkNode(kind::GT
, b1
, d_zero
);
265 Node cc1
= ufx1
.eqNode( NodeManager::currentNM()->mkNode(kind::PLUS
,
266 NodeManager::currentNM()->mkNode(kind::MULT
, ufx
, ten
),
267 NodeManager::currentNM()->mkNode(kind::APPLY_UF
, ufM
, NodeManager::currentNM()->mkNode(kind::MINUS
,b1
,one
)) ));
268 cc1
= NodeManager::currentNM()->mkNode(kind::IMPLIES
, b1gtz
, cc1
);
269 Node lstx
= lenp
.eqNode(NodeManager::currentNM()->mkNode(kind::PLUS
, b1
, one
));
270 Node cc2
= ufx
.eqNode(ufMx
);
271 cc2
= NodeManager::currentNM()->mkNode(kind::IMPLIES
, lstx
, cc2
);
272 Node cc3
= NodeManager::currentNM()->mkNode(kind::GEQ
, ufMx
, d_zero
);
273 Node cc4
= NodeManager::currentNM()->mkNode(kind::GEQ
, nine
, ufMx
);
275 Node b21
= NodeManager::currentNM()->mkBoundVar("y", NodeManager::currentNM()->stringType());
276 Node b22
= NodeManager::currentNM()->mkBoundVar("z", NodeManager::currentNM()->stringType());
277 Node b2v
= NodeManager::currentNM()->mkNode(kind::BOUND_VAR_LIST
, b21
, b22
);
279 Node c21
= NodeManager::currentNM()->mkNode(kind::STRING_LENGTH
, b21
).eqNode(
280 NodeManager::currentNM()->mkNode(kind::MINUS
, lenp
, NodeManager::currentNM()->mkNode(kind::PLUS
, b1
, one
) ));
282 NodeManager::currentNM()->mkNode(kind::ITE
, ufMx
.eqNode(NodeManager::currentNM()->mkConst(::CVC4::Rational(0))),
283 NodeManager::currentNM()->mkConst(::CVC4::String("0")),
284 NodeManager::currentNM()->mkNode(kind::ITE
, ufMx
.eqNode(NodeManager::currentNM()->mkConst(::CVC4::Rational(1))),
285 NodeManager::currentNM()->mkConst(::CVC4::String("1")),
286 NodeManager::currentNM()->mkNode(kind::ITE
, ufMx
.eqNode(NodeManager::currentNM()->mkConst(::CVC4::Rational(2))),
287 NodeManager::currentNM()->mkConst(::CVC4::String("2")),
288 NodeManager::currentNM()->mkNode(kind::ITE
, ufMx
.eqNode(NodeManager::currentNM()->mkConst(::CVC4::Rational(3))),
289 NodeManager::currentNM()->mkConst(::CVC4::String("3")),
290 NodeManager::currentNM()->mkNode(kind::ITE
, ufMx
.eqNode(NodeManager::currentNM()->mkConst(::CVC4::Rational(4))),
291 NodeManager::currentNM()->mkConst(::CVC4::String("4")),
292 NodeManager::currentNM()->mkNode(kind::ITE
, ufMx
.eqNode(NodeManager::currentNM()->mkConst(::CVC4::Rational(5))),
293 NodeManager::currentNM()->mkConst(::CVC4::String("5")),
294 NodeManager::currentNM()->mkNode(kind::ITE
, ufMx
.eqNode(NodeManager::currentNM()->mkConst(::CVC4::Rational(6))),
295 NodeManager::currentNM()->mkConst(::CVC4::String("6")),
296 NodeManager::currentNM()->mkNode(kind::ITE
, ufMx
.eqNode(NodeManager::currentNM()->mkConst(::CVC4::Rational(7))),
297 NodeManager::currentNM()->mkConst(::CVC4::String("7")),
298 NodeManager::currentNM()->mkNode(kind::ITE
, ufMx
.eqNode(NodeManager::currentNM()->mkConst(::CVC4::Rational(8))),
299 NodeManager::currentNM()->mkConst(::CVC4::String("8")),
300 NodeManager::currentNM()->mkConst(::CVC4::String("9")))))))))));
301 Node c22
= pret
.eqNode( NodeManager::currentNM()->mkNode(kind::STRING_CONCAT
, b21
, ch
, b22
) );
302 Node cc5
= NodeManager::currentNM()->mkNode(kind::EXISTS
, b2v
, NodeManager::currentNM()->mkNode(kind::AND
, c21
, c22
));
303 //Node pos = NodeManager::currentNM()->mkNode(kind::MINUS, lenp, NodeManager::currentNM()->mkNode(kind::PLUS, b1, one));
304 //Node cc5 = ch.eqNode( NodeManager::currentNM()->mkNode(kind::STRING_SUBSTR_TOTAL, pret, pos, one) );
305 Node conc
= Rewriter::rewrite( NodeManager::currentNM()->mkNode(kind::AND
, cc1
, cc2
, cc3
, cc4
, cc5
) );
306 conc
= NodeManager::currentNM()->mkNode( kind::IMPLIES
, g1
, conc
);
307 conc
= NodeManager::currentNM()->mkNode( kind::FORALL
, b1v
, conc
);
308 new_nodes
.push_back( conc
);
310 Node sign = NodeManager::currentNM()->mkNode(kind::ITE,
311 NodeManager::currentNM()->mkNode(kind::GEQ, t[0], d_zero),
312 NodeManager::currentNM()->mkConst(::CVC4::String("")),
313 NodeManager::currentNM()->mkConst(::CVC4::String("-")));
314 conc = t.eqNode( NodeManager::currentNM()->mkNode(kind::STRING_CONCAT, sign, pret) );
315 new_nodes.push_back( conc );*/
320 throw LogicException("string int.to.str not supported in this release");
322 } else if( t
.getKind() == kind::STRING_STOI_TOTAL
) {
323 if(options::stringExp()) {
324 Node one
= NodeManager::currentNM()->mkConst( ::CVC4::Rational(1) );
325 Node nine
= NodeManager::currentNM()->mkConst( ::CVC4::Rational(9) );
326 Node ten
= NodeManager::currentNM()->mkConst( ::CVC4::Rational(10) );
327 std::vector
< TypeNode
> argTypes
;
328 argTypes
.push_back(NodeManager::currentNM()->integerType());
329 Node ufP
= NodeManager::currentNM()->mkSkolem("ufP_$$",
330 NodeManager::currentNM()->mkFunctionType(
331 argTypes
, NodeManager::currentNM()->integerType()),
333 Node ufM
= NodeManager::currentNM()->mkSkolem("ufM_$$",
334 NodeManager::currentNM()->mkFunctionType(
335 argTypes
, NodeManager::currentNM()->integerType()),
338 Node ufP0
= NodeManager::currentNM()->mkNode(kind::APPLY_UF
, ufP
, d_zero
);
339 new_nodes
.push_back(t
.eqNode(ufP0
));
341 Node cc1
= t
[0].eqNode(NodeManager::currentNM()->mkConst(::CVC4::String("")));
342 cc1
= NodeManager::currentNM()->mkNode(kind::AND
, ufP0
.eqNode(d_zero
), cc1
);
344 Node b1
= NodeManager::currentNM()->mkBoundVar("x", NodeManager::currentNM()->integerType());
345 Node z1
= NodeManager::currentNM()->mkBoundVar("z1", NodeManager::currentNM()->stringType());
346 Node z2
= NodeManager::currentNM()->mkBoundVar("z2", NodeManager::currentNM()->stringType());
347 Node z3
= NodeManager::currentNM()->mkBoundVar("z3", NodeManager::currentNM()->stringType());
348 Node b1v
= NodeManager::currentNM()->mkNode(kind::BOUND_VAR_LIST
, b1
, z1
, z2
, z3
);
349 std::vector
< Node
> vec_n
;
350 Node g
= NodeManager::currentNM()->mkNode(kind::GEQ
, b1
, d_zero
);
352 g
= NodeManager::currentNM()->mkNode(kind::GT
, NodeManager::currentNM()->mkNode(kind::STRING_LENGTH
, t
[0]), b1
);
354 g
= b1
.eqNode( NodeManager::currentNM()->mkNode(kind::STRING_LENGTH
, z1
) );
356 g
= one
.eqNode( NodeManager::currentNM()->mkNode(kind::STRING_LENGTH
, z2
) );
358 g
= t
[0].eqNode( NodeManager::currentNM()->mkNode(kind::STRING_CONCAT
, z1
, z2
, z3
) );
360 for(unsigned i
=0; i
<=9; i
++) {
362 ch
[0] = i
+ '0'; ch
[1] = '\0';
363 std::string
stmp(ch
);
364 g
= z2
.eqNode( NodeManager::currentNM()->mkConst(::CVC4::String(stmp
)) ).negate();
367 Node cc2
= Rewriter::rewrite(NodeManager::currentNM()->mkNode(kind::AND
, vec_n
));
368 cc2
= NodeManager::currentNM()->mkNode(kind::EXISTS
, b1v
, cc2
);
369 cc2
= NodeManager::currentNM()->mkNode(kind::AND
, ufP0
.eqNode(d_zero
), cc2
);
371 Node b2
= NodeManager::currentNM()->mkBoundVar("y", NodeManager::currentNM()->integerType());
372 Node b2v
= NodeManager::currentNM()->mkNode(kind::BOUND_VAR_LIST
, b2
);
373 Node g2
= NodeManager::currentNM()->mkNode(kind::AND
,
374 NodeManager::currentNM()->mkNode(kind::GEQ
, b2
, d_zero
),
375 NodeManager::currentNM()->mkNode(kind::GT
, NodeManager::currentNM()->mkNode(kind::STRING_LENGTH
, t
[0]), b2
));
376 Node ufx
= NodeManager::currentNM()->mkNode(kind::APPLY_UF
, ufP
, b2
);
377 Node ufx1
= NodeManager::currentNM()->mkNode(kind::APPLY_UF
, ufP
, NodeManager::currentNM()->mkNode(kind::MINUS
,b2
,one
));
378 Node ufMx
= NodeManager::currentNM()->mkNode(kind::APPLY_UF
, ufM
, b2
);
379 Node w1
= NodeManager::currentNM()->mkBoundVar("w1", NodeManager::currentNM()->stringType());
380 Node w2
= NodeManager::currentNM()->mkBoundVar("w2", NodeManager::currentNM()->stringType());
381 Node b3v
= NodeManager::currentNM()->mkNode(kind::BOUND_VAR_LIST
, w1
, w2
);
382 Node b2gtz
= NodeManager::currentNM()->mkNode(kind::GT
, b2
, d_zero
);
383 Node c3c1
= ufx1
.eqNode( NodeManager::currentNM()->mkNode(kind::PLUS
,
384 NodeManager::currentNM()->mkNode(kind::MULT
, ufx
, ten
),
385 NodeManager::currentNM()->mkNode(kind::APPLY_UF
, ufM
, NodeManager::currentNM()->mkNode(kind::MINUS
,b2
,one
)) ));
386 c3c1
= NodeManager::currentNM()->mkNode(kind::AND
, NodeManager::currentNM()->mkNode(kind::GT
, ufx
, d_zero
), c3c1
);
387 c3c1
= NodeManager::currentNM()->mkNode(kind::IMPLIES
, b2gtz
, c3c1
);
388 Node lstx
= NodeManager::currentNM()->mkNode(kind::STRING_LENGTH
,t
[0]).eqNode(NodeManager::currentNM()->mkNode(kind::PLUS
, b2
, one
));
389 Node c3c2
= ufx
.eqNode(ufMx
);
390 c3c2
= NodeManager::currentNM()->mkNode(kind::IMPLIES
, lstx
, c3c2
);
391 Node c3c3
= NodeManager::currentNM()->mkNode(kind::GEQ
, ufMx
, d_zero
);
392 Node c3c4
= NodeManager::currentNM()->mkNode(kind::GEQ
, nine
, ufMx
);
393 Node rev
= NodeManager::currentNM()->mkNode(kind::STRING_LENGTH
, w1
).eqNode(
394 NodeManager::currentNM()->mkNode(kind::MINUS
, NodeManager::currentNM()->mkNode(kind::STRING_LENGTH
,t
[0]),
395 NodeManager::currentNM()->mkNode(kind::PLUS
, b2
, one
)));
397 NodeManager::currentNM()->mkNode(kind::ITE
, ufMx
.eqNode(NodeManager::currentNM()->mkConst(::CVC4::Rational(0))),
398 NodeManager::currentNM()->mkConst(::CVC4::String("0")),
399 NodeManager::currentNM()->mkNode(kind::ITE
, ufMx
.eqNode(NodeManager::currentNM()->mkConst(::CVC4::Rational(1))),
400 NodeManager::currentNM()->mkConst(::CVC4::String("1")),
401 NodeManager::currentNM()->mkNode(kind::ITE
, ufMx
.eqNode(NodeManager::currentNM()->mkConst(::CVC4::Rational(2))),
402 NodeManager::currentNM()->mkConst(::CVC4::String("2")),
403 NodeManager::currentNM()->mkNode(kind::ITE
, ufMx
.eqNode(NodeManager::currentNM()->mkConst(::CVC4::Rational(3))),
404 NodeManager::currentNM()->mkConst(::CVC4::String("3")),
405 NodeManager::currentNM()->mkNode(kind::ITE
, ufMx
.eqNode(NodeManager::currentNM()->mkConst(::CVC4::Rational(4))),
406 NodeManager::currentNM()->mkConst(::CVC4::String("4")),
407 NodeManager::currentNM()->mkNode(kind::ITE
, ufMx
.eqNode(NodeManager::currentNM()->mkConst(::CVC4::Rational(5))),
408 NodeManager::currentNM()->mkConst(::CVC4::String("5")),
409 NodeManager::currentNM()->mkNode(kind::ITE
, ufMx
.eqNode(NodeManager::currentNM()->mkConst(::CVC4::Rational(6))),
410 NodeManager::currentNM()->mkConst(::CVC4::String("6")),
411 NodeManager::currentNM()->mkNode(kind::ITE
, ufMx
.eqNode(NodeManager::currentNM()->mkConst(::CVC4::Rational(7))),
412 NodeManager::currentNM()->mkConst(::CVC4::String("7")),
413 NodeManager::currentNM()->mkNode(kind::ITE
, ufMx
.eqNode(NodeManager::currentNM()->mkConst(::CVC4::Rational(8))),
414 NodeManager::currentNM()->mkConst(::CVC4::String("8")),
415 NodeManager::currentNM()->mkConst(::CVC4::String("9")))))))))));
416 Node c3c5
= t
[0].eqNode(NodeManager::currentNM()->mkNode(kind::STRING_CONCAT
, w1
, ch
, w2
));
417 c3c5
= NodeManager::currentNM()->mkNode(kind::AND
, rev
, c3c5
);
418 c3c5
= NodeManager::currentNM()->mkNode(kind::EXISTS
, b3v
, c3c5
);
419 Node cc3
= Rewriter::rewrite( NodeManager::currentNM()->mkNode(kind::AND
, c3c1
, c3c2
, c3c3
, c3c4
, c3c5
) );
420 cc3
= NodeManager::currentNM()->mkNode(kind::IMPLIES
, g2
, cc3
);
421 cc3
= NodeManager::currentNM()->mkNode(kind::FORALL
, b2v
, cc3
);
423 Node conc
= NodeManager::currentNM()->mkNode(kind::OR
, cc1
, cc2
, cc3
);
424 new_nodes
.push_back( conc
);
428 throw LogicException("string int.to.str not supported in this release");
430 } else if( t
.getKind() == kind::STRING_STRREPL
) {
431 if(options::stringExp()) {
435 Node sk1
= NodeManager::currentNM()->mkSkolem( "rp1_$$", t
[0].getType(), "created for replace" );
436 Node sk2
= NodeManager::currentNM()->mkSkolem( "rp2_$$", t
[0].getType(), "created for replace" );
437 Node skw
= NodeManager::currentNM()->mkSkolem( "rpw_$$", t
[0].getType(), "created for replace" );
438 Node cond
= NodeManager::currentNM()->mkNode( kind::STRING_STRCTN
, x
, y
);
439 Node c1
= x
.eqNode( NodeManager::currentNM()->mkNode( kind::STRING_CONCAT
, sk1
, y
, sk2
) );
440 Node c2
= skw
.eqNode( NodeManager::currentNM()->mkNode( kind::STRING_CONCAT
, sk1
, z
, sk2
) );
441 Node c3
= NodeManager::currentNM()->mkNode( kind::STRING_STRCTN
, sk1
, y
).negate();
442 Node rr
= Rewriter::rewrite( NodeManager::currentNM()->mkNode( kind::ITE
, cond
,
443 NodeManager::currentNM()->mkNode( kind::AND
, c1
, c2
, c3
),
445 new_nodes
.push_back( rr
);
450 throw LogicException("string replace not supported in this release");
452 } else if( t
.getNumChildren()>0 ) {
453 std::vector
< Node
> cc
;
454 if (t
.getMetaKind() == kind::metakind::PARAMETERIZED
) {
455 cc
.push_back(t
.getOperator());
457 bool changed
= false;
458 for( unsigned i
=0; i
<t
.getNumChildren(); i
++ ){
459 Node tn
= simplify( t
[i
], new_nodes
);
461 changed
= changed
|| tn
!=t
[i
];
464 Node n
= NodeManager::currentNM()->mkNode( t
.getKind(), cc
);
468 d_cache
[t
] = Node::null();
472 d_cache
[t
] = Node::null();
476 Trace("strings-preprocess") << "StringsPreprocess::simplify returns: " << retNode
<< std::endl
;
477 if(!new_nodes
.empty()) {
478 Trace("strings-preprocess") << " ... new nodes (" << new_nodes
.size() << "):\n";
479 for(unsigned int i
=0; i
<new_nodes
.size(); ++i
) {
480 Trace("strings-preprocess") << "\t" << new_nodes
[i
] << "\n";
487 void StringsPreprocess::simplify(std::vector
< Node
> &vec_node
, std::vector
< Node
> &new_nodes
) {
488 for( unsigned i
=0; i
<vec_node
.size(); i
++ ){
489 vec_node
[i
] = simplify( vec_node
[i
], new_nodes
);
493 void StringsPreprocess::simplify(std::vector
< Node
> &vec_node
) {
494 std::vector
< Node
> new_nodes
;
495 simplify(vec_node
, new_nodes
);
496 vec_node
.insert( vec_node
.end(), new_nodes
.begin(), new_nodes
.end() );
499 }/* CVC4::theory::strings namespace */
500 }/* CVC4::theory namespace */
501 }/* CVC4 namespace */