1 |
|
/****************************************************************************** |
2 |
|
* Top contributors (to current version): |
3 |
|
* Andrew Reynolds, Haniel Barbosa, Mathias Preiner |
4 |
|
* |
5 |
|
* This file is part of the cvc5 project. |
6 |
|
* |
7 |
|
* Copyright (c) 2009-2021 by the authors listed in the file AUTHORS |
8 |
|
* in the top-level source directory and their institutional affiliations. |
9 |
|
* All rights reserved. See the file COPYING in the top-level source |
10 |
|
* directory for licensing information. |
11 |
|
* **************************************************************************** |
12 |
|
* |
13 |
|
* Implementation of simple symmetry breaking for sygus. |
14 |
|
*/ |
15 |
|
|
16 |
|
#include "theory/datatypes/sygus_simple_sym.h" |
17 |
|
|
18 |
|
#include "expr/dtype_cons.h" |
19 |
|
#include "theory/quantifiers/term_util.h" |
20 |
|
|
21 |
|
using namespace std; |
22 |
|
using namespace cvc5::kind; |
23 |
|
|
24 |
|
namespace cvc5 { |
25 |
|
namespace theory { |
26 |
|
namespace datatypes { |
27 |
|
|
28 |
1228 |
SygusSimpleSymBreak::SygusSimpleSymBreak(quantifiers::TermDbSygus* tds) |
29 |
1228 |
: d_tds(tds) |
30 |
|
{ |
31 |
1228 |
} |
32 |
|
|
33 |
|
/** Requirement trie |
34 |
|
* |
35 |
|
* This class is used to make queries about sygus grammars, including what |
36 |
|
* constructors they contain, and their types. |
37 |
|
* |
38 |
|
* As a simple example, consider the trie: |
39 |
|
* root: |
40 |
|
* d_req_kind = PLUS |
41 |
|
* d_children[0]: |
42 |
|
* d_req_type = A |
43 |
|
* d_children[1]: |
44 |
|
* d_req_type = A |
45 |
|
* This trie is satisfied by sygus types that have a constructor whose builtin |
46 |
|
* kind is PLUS and whose argument types are both A. |
47 |
|
*/ |
48 |
6654 |
class ReqTrie |
49 |
|
{ |
50 |
|
public: |
51 |
6654 |
ReqTrie() : d_req_kind(UNDEFINED_KIND) {} |
52 |
|
/** the children of this node */ |
53 |
|
std::map<unsigned, ReqTrie> d_children; |
54 |
|
/** the (builtin) kind required by this node */ |
55 |
|
Kind d_req_kind; |
56 |
|
/** the type that this node is required to be */ |
57 |
|
TypeNode d_req_type; |
58 |
|
/** the constant required by this node */ |
59 |
|
Node d_req_const; |
60 |
|
/** print this trie */ |
61 |
4127 |
void print(const char* c, int indent = 0) |
62 |
|
{ |
63 |
4127 |
if (d_req_kind != UNDEFINED_KIND) |
64 |
|
{ |
65 |
1607 |
Trace(c) << d_req_kind << " "; |
66 |
|
} |
67 |
2520 |
else if (!d_req_type.isNull()) |
68 |
|
{ |
69 |
2509 |
Trace(c) << d_req_type; |
70 |
|
} |
71 |
11 |
else if (!d_req_const.isNull()) |
72 |
|
{ |
73 |
11 |
Trace(c) << d_req_const; |
74 |
|
} |
75 |
|
else |
76 |
|
{ |
77 |
|
Trace(c) << "_"; |
78 |
|
} |
79 |
4127 |
Trace(c) << std::endl; |
80 |
7570 |
for (std::map<unsigned, ReqTrie>::iterator it = d_children.begin(); |
81 |
7570 |
it != d_children.end(); |
82 |
|
++it) |
83 |
|
{ |
84 |
8708 |
for (int i = 0; i <= indent; i++) |
85 |
|
{ |
86 |
5265 |
Trace(c) << " "; |
87 |
|
} |
88 |
3443 |
Trace(c) << it->first << " : "; |
89 |
3443 |
it->second.print(c, indent + 1); |
90 |
|
} |
91 |
4127 |
} |
92 |
|
/** |
93 |
|
* Are the requirements of this trie satisfied by sygus type tn? |
94 |
|
* tdb is a reference to the sygus term database. |
95 |
|
*/ |
96 |
4020 |
bool satisfiedBy(quantifiers::TermDbSygus* tdb, TypeNode tn) |
97 |
|
{ |
98 |
4020 |
if (!d_req_const.isNull()) |
99 |
|
{ |
100 |
11 |
quantifiers::SygusTypeInfo& sti = tdb->getTypeInfo(tn); |
101 |
11 |
if (!sti.hasConst(d_req_const)) |
102 |
|
{ |
103 |
2 |
return false; |
104 |
|
} |
105 |
|
} |
106 |
4018 |
if (!d_req_type.isNull()) |
107 |
|
{ |
108 |
4778 |
Trace("sygus-sb-debug") |
109 |
2389 |
<< "- check if " << tn << " is type " << d_req_type << std::endl; |
110 |
2389 |
if (tn != d_req_type) |
111 |
|
{ |
112 |
14 |
return false; |
113 |
|
} |
114 |
|
} |
115 |
4004 |
if (d_req_kind != UNDEFINED_KIND) |
116 |
|
{ |
117 |
3128 |
Trace("sygus-sb-debug") |
118 |
1564 |
<< "- check if " << tn << " has " << d_req_kind << std::endl; |
119 |
3063 |
std::vector<TypeNode> argts; |
120 |
1564 |
if (tdb->canConstructKind(tn, d_req_kind, argts)) |
121 |
|
{ |
122 |
4779 |
for (std::map<unsigned, ReqTrie>::iterator it = d_children.begin(); |
123 |
4779 |
it != d_children.end(); |
124 |
|
++it) |
125 |
|
{ |
126 |
3280 |
if (it->first < argts.size()) |
127 |
|
{ |
128 |
6534 |
TypeNode tnc = argts[it->first]; |
129 |
3280 |
if (!it->second.satisfiedBy(tdb, tnc)) |
130 |
|
{ |
131 |
26 |
return false; |
132 |
|
} |
133 |
|
} |
134 |
|
else |
135 |
|
{ |
136 |
|
return false; |
137 |
|
} |
138 |
|
} |
139 |
|
} |
140 |
|
else |
141 |
|
{ |
142 |
39 |
return false; |
143 |
|
} |
144 |
|
} |
145 |
3939 |
return true; |
146 |
|
} |
147 |
|
/** is this the empty (trivially satisfied) trie? */ |
148 |
6411 |
bool empty() |
149 |
|
{ |
150 |
12094 |
return d_req_kind == UNDEFINED_KIND && d_req_const.isNull() |
151 |
12094 |
&& d_req_type.isNull() && d_children.empty(); |
152 |
|
} |
153 |
|
}; |
154 |
|
|
155 |
2484 |
bool SygusSimpleSymBreak::considerArgKind( |
156 |
|
TypeNode tn, TypeNode tnp, Kind k, Kind pk, int arg) |
157 |
|
{ |
158 |
2484 |
const DType& pdt = tnp.getDType(); |
159 |
2484 |
const DType& dt = tn.getDType(); |
160 |
2484 |
quantifiers::SygusTypeInfo& ti = d_tds->getTypeInfo(tn); |
161 |
2484 |
quantifiers::SygusTypeInfo& pti = d_tds->getTypeInfo(tnp); |
162 |
2484 |
Assert(ti.hasKind(k)); |
163 |
2484 |
Assert(pti.hasKind(pk)); |
164 |
4968 |
Trace("sygus-sb-debug") << "Consider sygus arg kind " << k << ", pk = " << pk |
165 |
2484 |
<< ", arg = " << arg << " in " << tnp << "?" |
166 |
2484 |
<< std::endl; |
167 |
2484 |
int c = ti.getKindConsNum(k); |
168 |
2484 |
int pc = pti.getKindConsNum(pk); |
169 |
|
// check for associativity |
170 |
2484 |
if (k == pk && quantifiers::TermUtil::isAssoc(k)) |
171 |
|
{ |
172 |
|
// if the operator is associative, then a repeated occurrence should only |
173 |
|
// occur in the leftmost argument position |
174 |
230 |
int firstArg = getFirstArgOccurrence(pdt[pc], tn); |
175 |
230 |
Assert(firstArg != -1); |
176 |
230 |
if (arg == firstArg) |
177 |
|
{ |
178 |
116 |
return true; |
179 |
|
} |
180 |
|
// the argument types of the child must be the parent's type |
181 |
332 |
for (unsigned i = 0, nargs = dt[c].getNumArgs(); i < nargs; i++) |
182 |
|
{ |
183 |
441 |
TypeNode type = dt[c].getArgType(i); |
184 |
223 |
if (type != tnp) |
185 |
|
{ |
186 |
5 |
return true; |
187 |
|
} |
188 |
|
} |
189 |
218 |
Trace("sygus-sb-simple") |
190 |
109 |
<< " sb-simple : do not consider " << k << " at child arg " << arg |
191 |
109 |
<< " of " << k |
192 |
109 |
<< " since it is associative, with first arg = " << firstArg |
193 |
109 |
<< std::endl; |
194 |
109 |
return false; |
195 |
|
} |
196 |
|
// describes the shape of an alternate term to construct |
197 |
|
// we check whether this term is in the sygus grammar below |
198 |
4508 |
ReqTrie rt; |
199 |
2254 |
Assert(rt.empty()); |
200 |
|
|
201 |
|
// construct rt by cases |
202 |
2254 |
if (pk == NOT || pk == BITVECTOR_NOT || pk == UMINUS || pk == BITVECTOR_NEG) |
203 |
|
{ |
204 |
|
// negation normal form |
205 |
121 |
if (pk == k) |
206 |
|
{ |
207 |
20 |
rt.d_req_type = dt[c].getArgType(0); |
208 |
|
} |
209 |
|
else |
210 |
|
{ |
211 |
101 |
Kind reqk = UNDEFINED_KIND; // required kind for all children |
212 |
202 |
std::map<unsigned, Kind> reqkc; // required kind for some children |
213 |
101 |
if (pk == NOT) |
214 |
|
{ |
215 |
64 |
if (k == AND) |
216 |
|
{ |
217 |
16 |
rt.d_req_kind = OR; |
218 |
16 |
reqk = NOT; |
219 |
|
} |
220 |
48 |
else if (k == OR) |
221 |
|
{ |
222 |
15 |
rt.d_req_kind = AND; |
223 |
15 |
reqk = NOT; |
224 |
|
} |
225 |
33 |
else if (k == EQUAL) |
226 |
|
{ |
227 |
13 |
rt.d_req_kind = XOR; |
228 |
|
} |
229 |
20 |
else if (k == XOR) |
230 |
|
{ |
231 |
2 |
rt.d_req_kind = EQUAL; |
232 |
|
} |
233 |
18 |
else if (k == ITE) |
234 |
|
{ |
235 |
1 |
rt.d_req_kind = ITE; |
236 |
1 |
reqkc[1] = NOT; |
237 |
1 |
reqkc[2] = NOT; |
238 |
1 |
rt.d_children[0].d_req_type = dt[c].getArgType(0); |
239 |
|
} |
240 |
17 |
else if (k == LEQ || k == GT) |
241 |
|
{ |
242 |
|
// (not (~ x y)) -----> (~ (+ y 1) x) |
243 |
11 |
rt.d_req_kind = k; |
244 |
11 |
rt.d_children[0].d_req_kind = PLUS; |
245 |
11 |
rt.d_children[0].d_children[0].d_req_type = dt[c].getArgType(1); |
246 |
22 |
rt.d_children[0].d_children[1].d_req_const = |
247 |
33 |
NodeManager::currentNM()->mkConst(Rational(1)); |
248 |
11 |
rt.d_children[1].d_req_type = dt[c].getArgType(0); |
249 |
|
} |
250 |
6 |
else if (k == LT || k == GEQ) |
251 |
|
{ |
252 |
|
// (not (~ x y)) -----> (~ y (+ x 1)) |
253 |
|
rt.d_req_kind = k; |
254 |
|
rt.d_children[0].d_req_type = dt[c].getArgType(1); |
255 |
|
rt.d_children[1].d_req_kind = PLUS; |
256 |
|
rt.d_children[1].d_children[0].d_req_type = dt[c].getArgType(0); |
257 |
|
rt.d_children[1].d_children[1].d_req_const = |
258 |
|
NodeManager::currentNM()->mkConst(Rational(1)); |
259 |
|
} |
260 |
|
} |
261 |
37 |
else if (pk == BITVECTOR_NOT) |
262 |
|
{ |
263 |
22 |
if (k == BITVECTOR_AND) |
264 |
|
{ |
265 |
2 |
rt.d_req_kind = BITVECTOR_OR; |
266 |
2 |
reqk = BITVECTOR_NOT; |
267 |
|
} |
268 |
20 |
else if (k == BITVECTOR_OR) |
269 |
|
{ |
270 |
2 |
rt.d_req_kind = BITVECTOR_AND; |
271 |
2 |
reqk = BITVECTOR_NOT; |
272 |
|
} |
273 |
18 |
else if (k == BITVECTOR_XNOR) |
274 |
|
{ |
275 |
|
rt.d_req_kind = BITVECTOR_XOR; |
276 |
|
} |
277 |
18 |
else if (k == BITVECTOR_XOR) |
278 |
|
{ |
279 |
2 |
rt.d_req_kind = BITVECTOR_XNOR; |
280 |
|
} |
281 |
|
} |
282 |
15 |
else if (pk == UMINUS) |
283 |
|
{ |
284 |
|
if (k == PLUS) |
285 |
|
{ |
286 |
|
rt.d_req_kind = PLUS; |
287 |
|
reqk = UMINUS; |
288 |
|
} |
289 |
|
} |
290 |
15 |
else if (pk == BITVECTOR_NEG) |
291 |
|
{ |
292 |
15 |
if (k == PLUS) |
293 |
|
{ |
294 |
|
rt.d_req_kind = PLUS; |
295 |
|
reqk = BITVECTOR_NEG; |
296 |
|
} |
297 |
|
} |
298 |
101 |
if (!rt.empty() && (reqk != UNDEFINED_KIND || !reqkc.empty())) |
299 |
|
{ |
300 |
36 |
int pcr = pti.getKindConsNum(rt.d_req_kind); |
301 |
36 |
if (pcr != -1) |
302 |
|
{ |
303 |
33 |
Assert(pcr < static_cast<int>(pdt.getNumConstructors())); |
304 |
|
// must have same number of arguments |
305 |
33 |
if (pdt[pcr].getNumArgs() == dt[c].getNumArgs()) |
306 |
|
{ |
307 |
100 |
for (unsigned i = 0, nargs = pdt[pcr].getNumArgs(); i < nargs; i++) |
308 |
|
{ |
309 |
67 |
Kind rk = reqk; |
310 |
67 |
if (reqk == UNDEFINED_KIND) |
311 |
|
{ |
312 |
3 |
std::map<unsigned, Kind>::iterator itr = reqkc.find(i); |
313 |
3 |
if (itr != reqkc.end()) |
314 |
|
{ |
315 |
2 |
rk = itr->second; |
316 |
|
} |
317 |
|
} |
318 |
67 |
if (rk != UNDEFINED_KIND) |
319 |
|
{ |
320 |
66 |
rt.d_children[i].d_req_kind = rk; |
321 |
66 |
rt.d_children[i].d_children[0].d_req_type = dt[c].getArgType(i); |
322 |
|
} |
323 |
|
} |
324 |
|
} |
325 |
|
} |
326 |
|
} |
327 |
121 |
} |
328 |
|
} |
329 |
2133 |
else if (k == MINUS || k == BITVECTOR_SUB) |
330 |
|
{ |
331 |
338 |
if (pk == EQUAL || pk == MINUS || pk == BITVECTOR_SUB || pk == LEQ |
332 |
138 |
|| pk == LT || pk == GEQ || pk == GT) |
333 |
|
{ |
334 |
200 |
int oarg = arg == 0 ? 1 : 0; |
335 |
|
// (~ x (- y z)) ----> (~ (+ x z) y) |
336 |
|
// (~ (- y z) x) ----> (~ y (+ x z)) |
337 |
200 |
rt.d_req_kind = pk; |
338 |
200 |
rt.d_children[arg].d_req_type = dt[c].getArgType(0); |
339 |
200 |
rt.d_children[oarg].d_req_kind = k == MINUS ? PLUS : BITVECTOR_ADD; |
340 |
200 |
rt.d_children[oarg].d_children[0].d_req_type = pdt[pc].getArgType(oarg); |
341 |
200 |
rt.d_children[oarg].d_children[1].d_req_type = dt[c].getArgType(1); |
342 |
|
} |
343 |
138 |
else if (pk == PLUS || pk == BITVECTOR_ADD) |
344 |
|
{ |
345 |
|
// (+ x (- y z)) -----> (- (+ x y) z) |
346 |
|
// (+ (- y z) x) -----> (- (+ x y) z) |
347 |
68 |
rt.d_req_kind = pk == PLUS ? MINUS : BITVECTOR_SUB; |
348 |
68 |
int oarg = arg == 0 ? 1 : 0; |
349 |
68 |
rt.d_children[0].d_req_kind = pk; |
350 |
68 |
rt.d_children[0].d_children[0].d_req_type = pdt[pc].getArgType(oarg); |
351 |
68 |
rt.d_children[0].d_children[1].d_req_type = dt[c].getArgType(0); |
352 |
68 |
rt.d_children[1].d_req_type = dt[c].getArgType(1); |
353 |
338 |
} |
354 |
|
} |
355 |
1795 |
else if (k == ITE) |
356 |
|
{ |
357 |
374 |
if (pk != ITE) |
358 |
|
{ |
359 |
|
// (o X (ite y z w) X') -----> (ite y (o X z X') (o X w X')) |
360 |
299 |
rt.d_req_kind = ITE; |
361 |
299 |
rt.d_children[0].d_req_type = dt[c].getArgType(0); |
362 |
299 |
unsigned n_args = pdt[pc].getNumArgs(); |
363 |
897 |
for (unsigned r = 1; r <= 2; r++) |
364 |
|
{ |
365 |
598 |
rt.d_children[r].d_req_kind = pk; |
366 |
1796 |
for (unsigned q = 0; q < n_args; q++) |
367 |
|
{ |
368 |
1198 |
if ((int)q == arg) |
369 |
|
{ |
370 |
598 |
rt.d_children[r].d_children[q].d_req_type = dt[c].getArgType(r); |
371 |
|
} |
372 |
|
else |
373 |
|
{ |
374 |
600 |
rt.d_children[r].d_children[q].d_req_type = pdt[pc].getArgType(q); |
375 |
|
} |
376 |
|
} |
377 |
|
} |
378 |
|
// this increases term size but is probably a good idea |
379 |
|
} |
380 |
|
} |
381 |
1421 |
else if (k == NOT) |
382 |
|
{ |
383 |
139 |
if (pk == ITE) |
384 |
|
{ |
385 |
|
// (ite (not y) z w) -----> (ite y w z) |
386 |
33 |
rt.d_req_kind = ITE; |
387 |
33 |
rt.d_children[0].d_req_type = dt[c].getArgType(0); |
388 |
33 |
rt.d_children[1].d_req_type = pdt[pc].getArgType(2); |
389 |
33 |
rt.d_children[2].d_req_type = pdt[pc].getArgType(1); |
390 |
|
} |
391 |
|
} |
392 |
4508 |
Trace("sygus-sb-debug") << "Consider sygus arg kind " << k << ", pk = " << pk |
393 |
2254 |
<< ", arg = " << arg << "?" << std::endl; |
394 |
2254 |
if (!rt.empty()) |
395 |
|
{ |
396 |
684 |
rt.print("sygus-sb-debug"); |
397 |
|
// check if it meets the requirements |
398 |
684 |
if (rt.satisfiedBy(d_tds, tnp)) |
399 |
|
{ |
400 |
629 |
Trace("sygus-sb-debug") << "...success!" << std::endl; |
401 |
1258 |
Trace("sygus-sb-simple") |
402 |
629 |
<< " sb-simple : do not consider " << k << " as arg " << arg |
403 |
629 |
<< " of " << pk << std::endl; |
404 |
|
// do not need to consider the kind in the search since there are ways to |
405 |
|
// construct equivalent terms |
406 |
629 |
return false; |
407 |
|
} |
408 |
|
else |
409 |
|
{ |
410 |
55 |
Trace("sygus-sb-debug") << "...failed." << std::endl; |
411 |
|
} |
412 |
55 |
Trace("sygus-sb-debug") << std::endl; |
413 |
|
} |
414 |
|
// must consider this kind in the search |
415 |
1625 |
return true; |
416 |
|
} |
417 |
|
|
418 |
1183 |
bool SygusSimpleSymBreak::considerConst( |
419 |
|
TypeNode tn, TypeNode tnp, Node c, Kind pk, int arg) |
420 |
|
{ |
421 |
1183 |
const DType& pdt = tnp.getDType(); |
422 |
|
// child grammar-independent |
423 |
1183 |
if (!considerConst(pdt, tnp, c, pk, arg)) |
424 |
|
{ |
425 |
338 |
return false; |
426 |
|
} |
427 |
|
// this can probably be made child grammar independent |
428 |
845 |
quantifiers::SygusTypeInfo& ti = d_tds->getTypeInfo(tn); |
429 |
845 |
quantifiers::SygusTypeInfo& pti = d_tds->getTypeInfo(tnp); |
430 |
845 |
int pc = pti.getKindConsNum(pk); |
431 |
845 |
if (pdt[pc].getNumArgs() == 2) |
432 |
|
{ |
433 |
|
Kind ok; |
434 |
|
int offset; |
435 |
668 |
if (quantifiers::TermUtil::hasOffsetArg(pk, arg, offset, ok)) |
436 |
|
{ |
437 |
56 |
Trace("sygus-sb-simple-debug") |
438 |
28 |
<< pk << " has offset arg " << ok << " " << offset << std::endl; |
439 |
28 |
int ok_arg = pti.getKindConsNum(ok); |
440 |
28 |
if (ok_arg != -1) |
441 |
|
{ |
442 |
8 |
Trace("sygus-sb-simple-debug") |
443 |
4 |
<< "...at argument " << ok_arg << std::endl; |
444 |
|
// other operator be the same type |
445 |
4 |
if (d_tds->isTypeMatch(pdt[ok_arg], pdt[arg])) |
446 |
|
{ |
447 |
|
int status; |
448 |
|
Node co = quantifiers::TermUtil::mkTypeValueOffset( |
449 |
6 |
c.getType(), c, offset, status); |
450 |
8 |
Trace("sygus-sb-simple-debug") |
451 |
4 |
<< c << " with offset " << offset << " is " << co |
452 |
4 |
<< ", status=" << status << std::endl; |
453 |
4 |
if (status == 0 && !co.isNull()) |
454 |
|
{ |
455 |
4 |
if (ti.hasConst(co)) |
456 |
|
{ |
457 |
4 |
Trace("sygus-sb-simple") |
458 |
2 |
<< " sb-simple : by offset reasoning, do not consider const " |
459 |
2 |
<< c; |
460 |
4 |
Trace("sygus-sb-simple") |
461 |
2 |
<< " as arg " << arg << " of " << pk << " since we can use " |
462 |
2 |
<< co << " under " << ok << " " << std::endl; |
463 |
2 |
return false; |
464 |
|
} |
465 |
|
} |
466 |
|
} |
467 |
|
} |
468 |
|
} |
469 |
|
} |
470 |
843 |
return true; |
471 |
|
} |
472 |
|
|
473 |
1183 |
bool SygusSimpleSymBreak::considerConst( |
474 |
|
const DType& pdt, TypeNode tnp, Node c, Kind pk, int arg) |
475 |
|
{ |
476 |
1183 |
quantifiers::SygusTypeInfo& pti = d_tds->getTypeInfo(tnp); |
477 |
1183 |
Assert(pti.hasKind(pk)); |
478 |
1183 |
int pc = pti.getKindConsNum(pk); |
479 |
1183 |
bool ret = true; |
480 |
2366 |
Trace("sygus-sb-debug") << "Consider sygus const " << c << ", parent = " << pk |
481 |
1183 |
<< ", arg = " << arg << "?" << std::endl; |
482 |
1183 |
if (quantifiers::TermUtil::isIdempotentArg(c, pk, arg)) |
483 |
|
{ |
484 |
186 |
if (pdt[pc].getNumArgs() == 2) |
485 |
|
{ |
486 |
186 |
int oarg = arg == 0 ? 1 : 0; |
487 |
372 |
TypeNode otn = pdt[pc].getArgType(oarg); |
488 |
186 |
if (otn == tnp) |
489 |
|
{ |
490 |
330 |
Trace("sygus-sb-simple") |
491 |
165 |
<< " sb-simple : " << c << " is idempotent arg " << arg << " of " |
492 |
165 |
<< pk << "..." << std::endl; |
493 |
165 |
ret = false; |
494 |
|
} |
495 |
|
} |
496 |
|
} |
497 |
|
else |
498 |
|
{ |
499 |
1994 |
Node sc = quantifiers::TermUtil::isSingularArg(c, pk, arg); |
500 |
997 |
if (!sc.isNull()) |
501 |
|
{ |
502 |
130 |
if (pti.hasConst(sc)) |
503 |
|
{ |
504 |
234 |
Trace("sygus-sb-simple") |
505 |
117 |
<< " sb-simple : " << c << " is singular arg " << arg << " of " |
506 |
117 |
<< pk << ", evaluating to " << sc << "..." << std::endl; |
507 |
117 |
ret = false; |
508 |
|
} |
509 |
|
} |
510 |
|
} |
511 |
1183 |
if (ret) |
512 |
|
{ |
513 |
1802 |
ReqTrie rt; |
514 |
901 |
Assert(rt.empty()); |
515 |
1802 |
Node max_c = quantifiers::TermUtil::mkTypeMaxValue(c.getType()); |
516 |
1802 |
Node zero_c = quantifiers::TermUtil::mkTypeValue(c.getType(), 0); |
517 |
1802 |
Node one_c = quantifiers::TermUtil::mkTypeValue(c.getType(), 1); |
518 |
901 |
if (pk == XOR || pk == BITVECTOR_XOR) |
519 |
|
{ |
520 |
4 |
if (c == max_c) |
521 |
|
{ |
522 |
|
rt.d_req_kind = pk == XOR ? NOT : BITVECTOR_NOT; |
523 |
|
} |
524 |
|
} |
525 |
899 |
else if (pk == ITE) |
526 |
|
{ |
527 |
170 |
if (arg == 0) |
528 |
|
{ |
529 |
56 |
if (c == max_c) |
530 |
|
{ |
531 |
28 |
rt.d_children[1].d_req_type = tnp; |
532 |
|
} |
533 |
28 |
else if (c == zero_c) |
534 |
|
{ |
535 |
28 |
rt.d_children[2].d_req_type = tnp; |
536 |
|
} |
537 |
|
} |
538 |
|
} |
539 |
729 |
else if (pk == STRING_SUBSTR) |
540 |
|
{ |
541 |
|
if (c == one_c && arg == 2) |
542 |
|
{ |
543 |
|
rt.d_req_kind = STRING_CHARAT; |
544 |
|
rt.d_children[0].d_req_type = pdt[pc].getArgType(0); |
545 |
|
rt.d_children[1].d_req_type = pdt[pc].getArgType(1); |
546 |
|
} |
547 |
|
} |
548 |
901 |
if (!rt.empty()) |
549 |
|
{ |
550 |
|
// check if satisfied |
551 |
56 |
if (rt.satisfiedBy(d_tds, tnp)) |
552 |
|
{ |
553 |
112 |
Trace("sygus-sb-simple") << " sb-simple : do not consider const " << c |
554 |
56 |
<< " as arg " << arg << " of " << pk; |
555 |
56 |
Trace("sygus-sb-simple") << " in " << pdt.getName() << std::endl; |
556 |
|
// do not need to consider the constant in the search since there are |
557 |
|
// ways to construct equivalent terms |
558 |
56 |
ret = false; |
559 |
|
} |
560 |
|
} |
561 |
|
} |
562 |
1183 |
return ret; |
563 |
|
} |
564 |
|
|
565 |
2595 |
int SygusSimpleSymBreak::solveForArgument(TypeNode tn, |
566 |
|
unsigned cindex, |
567 |
|
unsigned arg) |
568 |
|
{ |
569 |
|
// we currently do not solve for arguments |
570 |
2595 |
return -1; |
571 |
|
} |
572 |
|
|
573 |
230 |
int SygusSimpleSymBreak::getFirstArgOccurrence(const DTypeConstructor& c, |
574 |
|
TypeNode tn) |
575 |
|
{ |
576 |
230 |
for (unsigned i = 0, nargs = c.getNumArgs(); i < nargs; i++) |
577 |
|
{ |
578 |
230 |
if (c.getArgType(i) == tn) |
579 |
|
{ |
580 |
230 |
return i; |
581 |
|
} |
582 |
|
} |
583 |
|
return -1; |
584 |
|
} |
585 |
|
|
586 |
|
} // namespace datatypes |
587 |
|
} // namespace theory |
588 |
29511 |
} // namespace cvc5 |