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 sygus_unif_strat. |
14 |
|
*/ |
15 |
|
|
16 |
|
#include "theory/quantifiers/sygus/sygus_unif_strat.h" |
17 |
|
|
18 |
|
#include "expr/dtype.h" |
19 |
|
#include "expr/dtype_cons.h" |
20 |
|
#include "expr/skolem_manager.h" |
21 |
|
#include "theory/datatypes/theory_datatypes_utils.h" |
22 |
|
#include "theory/quantifiers/sygus/sygus_eval_unfold.h" |
23 |
|
#include "theory/quantifiers/sygus/sygus_unif.h" |
24 |
|
#include "theory/quantifiers/sygus/term_database_sygus.h" |
25 |
|
#include "theory/quantifiers/term_util.h" |
26 |
|
#include "theory/rewriter.h" |
27 |
|
|
28 |
|
using namespace std; |
29 |
|
using namespace cvc5::kind; |
30 |
|
|
31 |
|
namespace cvc5 { |
32 |
|
namespace theory { |
33 |
|
namespace quantifiers { |
34 |
|
|
35 |
|
std::ostream& operator<<(std::ostream& os, EnumRole r) |
36 |
|
{ |
37 |
|
switch (r) |
38 |
|
{ |
39 |
|
case enum_invalid: os << "INVALID"; break; |
40 |
|
case enum_io: os << "IO"; break; |
41 |
|
case enum_ite_condition: os << "CONDITION"; break; |
42 |
|
case enum_concat_term: os << "CTERM"; break; |
43 |
|
default: os << "enum_" << static_cast<unsigned>(r); break; |
44 |
|
} |
45 |
|
return os; |
46 |
|
} |
47 |
|
|
48 |
|
std::ostream& operator<<(std::ostream& os, NodeRole r) |
49 |
|
{ |
50 |
|
switch (r) |
51 |
|
{ |
52 |
|
case role_equal: os << "equal"; break; |
53 |
|
case role_string_prefix: os << "string_prefix"; break; |
54 |
|
case role_string_suffix: os << "string_suffix"; break; |
55 |
|
case role_ite_condition: os << "ite_condition"; break; |
56 |
|
default: os << "role_" << static_cast<unsigned>(r); break; |
57 |
|
} |
58 |
|
return os; |
59 |
|
} |
60 |
|
|
61 |
366 |
EnumRole getEnumeratorRoleForNodeRole(NodeRole r) |
62 |
|
{ |
63 |
366 |
switch (r) |
64 |
|
{ |
65 |
171 |
case role_equal: return enum_io; break; |
66 |
60 |
case role_string_prefix: return enum_concat_term; break; |
67 |
63 |
case role_string_suffix: return enum_concat_term; break; |
68 |
72 |
case role_ite_condition: return enum_ite_condition; break; |
69 |
|
default: break; |
70 |
|
} |
71 |
|
return enum_invalid; |
72 |
|
} |
73 |
|
|
74 |
|
std::ostream& operator<<(std::ostream& os, StrategyType st) |
75 |
|
{ |
76 |
|
switch (st) |
77 |
|
{ |
78 |
|
case strat_ITE: os << "ITE"; break; |
79 |
|
case strat_CONCAT_PREFIX: os << "CONCAT_PREFIX"; break; |
80 |
|
case strat_CONCAT_SUFFIX: os << "CONCAT_SUFFIX"; break; |
81 |
|
case strat_ID: os << "ID"; break; |
82 |
|
default: os << "strat_" << static_cast<unsigned>(st); break; |
83 |
|
} |
84 |
|
return os; |
85 |
|
} |
86 |
|
|
87 |
61 |
void SygusUnifStrategy::initialize(TermDbSygus* tds, |
88 |
|
Node f, |
89 |
|
std::vector<Node>& enums) |
90 |
|
{ |
91 |
61 |
Assert(d_candidate.isNull()); |
92 |
61 |
d_candidate = f; |
93 |
61 |
d_root = f.getType(); |
94 |
61 |
d_tds = tds; |
95 |
|
|
96 |
|
// collect the enumerator types and form the strategy |
97 |
61 |
buildStrategyGraph(d_root, role_equal); |
98 |
|
// add the enumerators |
99 |
61 |
enums.insert(enums.end(), d_esym_list.begin(), d_esym_list.end()); |
100 |
|
// finish the initialization of the strategy |
101 |
|
// this computes if each node is conditional |
102 |
122 |
std::map<Node, std::map<NodeRole, bool> > visited; |
103 |
61 |
finishInit(getRootEnumerator(), role_equal, visited, false); |
104 |
61 |
} |
105 |
|
|
106 |
86 |
void SygusUnifStrategy::initializeType(TypeNode tn) |
107 |
|
{ |
108 |
172 |
Trace("sygus-unif") << "SygusUnifStrategy: initialize : " << tn << " for " |
109 |
86 |
<< d_candidate << std::endl; |
110 |
86 |
d_tinfo[tn].d_this_type = tn; |
111 |
86 |
} |
112 |
|
|
113 |
889 |
Node SygusUnifStrategy::getRootEnumerator() const |
114 |
|
{ |
115 |
889 |
std::map<TypeNode, EnumTypeInfo>::const_iterator itt = d_tinfo.find(d_root); |
116 |
889 |
Assert(itt != d_tinfo.end()); |
117 |
|
std::map<EnumRole, Node>::const_iterator it = |
118 |
889 |
itt->second.d_enum.find(enum_io); |
119 |
889 |
Assert(it != itt->second.d_enum.end()); |
120 |
889 |
return it->second; |
121 |
|
} |
122 |
|
|
123 |
6833 |
EnumInfo& SygusUnifStrategy::getEnumInfo(Node e) |
124 |
|
{ |
125 |
6833 |
std::map<Node, EnumInfo>::iterator it = d_einfo.find(e); |
126 |
6833 |
Assert(it != d_einfo.end()); |
127 |
6833 |
return it->second; |
128 |
|
} |
129 |
|
|
130 |
4096 |
EnumTypeInfo& SygusUnifStrategy::getEnumTypeInfo(TypeNode tn) |
131 |
|
{ |
132 |
8192 |
Trace("sygus-unif") << "SygusUnifStrategy: get : " << tn << " for " |
133 |
4096 |
<< d_candidate << std::endl; |
134 |
4096 |
std::map<TypeNode, EnumTypeInfo>::iterator it = d_tinfo.find(tn); |
135 |
4096 |
Assert(it != d_tinfo.end()); |
136 |
4096 |
return it->second; |
137 |
|
} |
138 |
|
// ----------------------------- establishing enumeration types |
139 |
|
|
140 |
166 |
void SygusUnifStrategy::registerStrategyPoint(Node et, |
141 |
|
TypeNode tn, |
142 |
|
EnumRole enum_role, |
143 |
|
bool inSearch) |
144 |
|
{ |
145 |
166 |
if (d_einfo.find(et) == d_einfo.end()) |
146 |
|
{ |
147 |
300 |
Trace("sygus-unif-debug") |
148 |
150 |
<< "...register " << et << " for " << tn.getDType().getName(); |
149 |
300 |
Trace("sygus-unif-debug") << ", role = " << enum_role |
150 |
150 |
<< ", in search = " << inSearch << std::endl; |
151 |
150 |
d_einfo[et].initialize(enum_role); |
152 |
|
// if we are actually enumerating this (could be a compound node in the |
153 |
|
// strategy) |
154 |
150 |
if (inSearch) |
155 |
|
{ |
156 |
146 |
std::map<TypeNode, Node>::iterator itn = d_master_enum.find(tn); |
157 |
146 |
if (itn == d_master_enum.end()) |
158 |
|
{ |
159 |
|
// use this for the search |
160 |
82 |
d_master_enum[tn] = et; |
161 |
82 |
d_esym_list.push_back(et); |
162 |
82 |
d_einfo[et].d_enum_slave.push_back(et); |
163 |
|
} |
164 |
|
else |
165 |
|
{ |
166 |
128 |
Trace("sygus-unif-debug") << "Make " << et << " a slave of " |
167 |
64 |
<< itn->second << std::endl; |
168 |
64 |
d_einfo[itn->second].d_enum_slave.push_back(et); |
169 |
|
} |
170 |
|
} |
171 |
|
} |
172 |
166 |
} |
173 |
|
|
174 |
289 |
void SygusUnifStrategy::buildStrategyGraph(TypeNode tn, NodeRole nrole) |
175 |
|
{ |
176 |
289 |
NodeManager* nm = NodeManager::currentNM(); |
177 |
289 |
SkolemManager* sm = nm->getSkolemManager(); |
178 |
289 |
if (d_tinfo.find(tn) == d_tinfo.end()) |
179 |
|
{ |
180 |
|
// register type |
181 |
86 |
Trace("sygus-unif") << "Register enumerating type : " << tn << std::endl; |
182 |
86 |
initializeType(tn); |
183 |
|
} |
184 |
289 |
EnumTypeInfo& eti = d_tinfo[tn]; |
185 |
289 |
std::map<NodeRole, StrategyNode>::iterator itsn = eti.d_snodes.find(nrole); |
186 |
289 |
if (itsn != eti.d_snodes.end()) |
187 |
|
{ |
188 |
|
// already initialized |
189 |
337 |
return; |
190 |
|
} |
191 |
138 |
StrategyNode& snode = eti.d_snodes[nrole]; |
192 |
|
|
193 |
|
// get the enumerator for this |
194 |
138 |
EnumRole erole = getEnumeratorRoleForNodeRole(nrole); |
195 |
|
|
196 |
241 |
Node ee; |
197 |
138 |
std::map<EnumRole, Node>::iterator iten = eti.d_enum.find(erole); |
198 |
138 |
if (iten == eti.d_enum.end()) |
199 |
|
{ |
200 |
122 |
ee = sm->mkDummySkolem("ee", tn); |
201 |
122 |
eti.d_enum[erole] = ee; |
202 |
244 |
Trace("sygus-unif-debug") |
203 |
244 |
<< "...enumerator " << ee << " for " << tn.getDType().getName() |
204 |
122 |
<< ", role = " << erole << std::endl; |
205 |
|
} |
206 |
|
else |
207 |
|
{ |
208 |
16 |
ee = iten->second; |
209 |
|
} |
210 |
|
|
211 |
|
// roles that we do not recurse on |
212 |
138 |
if (nrole == role_ite_condition) |
213 |
|
{ |
214 |
35 |
Trace("sygus-unif-debug") << "...this register (non-io)" << std::endl; |
215 |
35 |
registerStrategyPoint(ee, tn, erole, true); |
216 |
35 |
return; |
217 |
|
} |
218 |
|
|
219 |
|
// look at information on how we will construct solutions for this type |
220 |
|
// we know this is a sygus datatype since it is either the top-level type |
221 |
|
// in the strategy graph, or was recursed by a strategy we inferred. |
222 |
103 |
Assert(tn.isDatatype()); |
223 |
103 |
const DType& dt = tn.getDType(); |
224 |
103 |
Assert(dt.isSygus()); |
225 |
|
|
226 |
206 |
std::map<Node, std::vector<StrategyType> > cop_to_strat; |
227 |
206 |
std::map<Node, unsigned> cop_to_cindex; |
228 |
206 |
std::map<Node, std::map<unsigned, Node> > cop_to_child_templ; |
229 |
206 |
std::map<Node, std::map<unsigned, Node> > cop_to_child_templ_arg; |
230 |
206 |
std::map<Node, std::vector<unsigned> > cop_to_carg_list; |
231 |
206 |
std::map<Node, std::vector<TypeNode> > cop_to_child_types; |
232 |
206 |
std::map<Node, std::vector<Node> > cop_to_sks; |
233 |
|
|
234 |
|
// whether we will enumerate the current type |
235 |
103 |
bool search_this = false; |
236 |
786 |
for (unsigned j = 0, ncons = dt.getNumConstructors(); j < ncons; j++) |
237 |
|
{ |
238 |
1366 |
Node cop = dt[j].getConstructor(); |
239 |
1366 |
Node op = dt[j].getSygusOp(); |
240 |
1366 |
Trace("sygus-unif-debug") << "--- Infer strategy from " << cop |
241 |
683 |
<< " with sygus op " << op << "..." << std::endl; |
242 |
|
|
243 |
|
// expand the evaluation to see if this constuctor induces a strategy |
244 |
1366 |
std::vector<Node> utchildren; |
245 |
683 |
utchildren.push_back(cop); |
246 |
1366 |
std::vector<Node> sks; |
247 |
1366 |
std::vector<TypeNode> sktns; |
248 |
1286 |
for (unsigned k = 0, nargs = dt[j].getNumArgs(); k < nargs; k++) |
249 |
|
{ |
250 |
1206 |
TypeNode ttn = dt[j][k].getRangeType(); |
251 |
1206 |
Node kv = sm->mkDummySkolem("ut", ttn); |
252 |
603 |
sks.push_back(kv); |
253 |
603 |
cop_to_sks[cop].push_back(kv); |
254 |
603 |
sktns.push_back(ttn); |
255 |
603 |
utchildren.push_back(kv); |
256 |
|
} |
257 |
1366 |
Node ut = nm->mkNode(APPLY_CONSTRUCTOR, utchildren); |
258 |
1366 |
std::vector<Node> echildren; |
259 |
683 |
echildren.push_back(ut); |
260 |
1366 |
Node sbvl = dt.getSygusVarList(); |
261 |
3937 |
for (const Node& sbv : sbvl) |
262 |
|
{ |
263 |
3254 |
echildren.push_back(sbv); |
264 |
|
} |
265 |
1366 |
Node eut = nm->mkNode(DT_SYGUS_EVAL, echildren); |
266 |
1366 |
Trace("sygus-unif-debug2") << " Test evaluation of " << eut << "..." |
267 |
683 |
<< std::endl; |
268 |
683 |
eut = d_tds->getEvalUnfold()->unfold(eut); |
269 |
683 |
Trace("sygus-unif-debug2") << " ...got " << eut; |
270 |
683 |
Trace("sygus-unif-debug2") << ", type : " << eut.getType() << std::endl; |
271 |
|
|
272 |
|
// candidate strategy |
273 |
683 |
if (eut.getKind() == ITE) |
274 |
|
{ |
275 |
37 |
cop_to_strat[cop].push_back(strat_ITE); |
276 |
|
} |
277 |
646 |
else if (eut.getKind() == STRING_CONCAT) |
278 |
|
{ |
279 |
41 |
if (nrole != role_string_suffix) |
280 |
|
{ |
281 |
27 |
cop_to_strat[cop].push_back(strat_CONCAT_PREFIX); |
282 |
|
} |
283 |
41 |
if (nrole != role_string_prefix) |
284 |
|
{ |
285 |
28 |
cop_to_strat[cop].push_back(strat_CONCAT_SUFFIX); |
286 |
|
} |
287 |
|
} |
288 |
605 |
else if (dt[j].isSygusIdFunc()) |
289 |
|
{ |
290 |
3 |
cop_to_strat[cop].push_back(strat_ID); |
291 |
|
} |
292 |
|
|
293 |
|
// the kinds for which there is a strategy |
294 |
683 |
if (cop_to_strat.find(cop) != cop_to_strat.end()) |
295 |
|
{ |
296 |
|
// infer an injection from the arguments of the datatype |
297 |
162 |
std::map<unsigned, unsigned> templ_injection; |
298 |
162 |
std::vector<Node> vs; |
299 |
162 |
std::vector<Node> ss; |
300 |
162 |
std::map<Node, unsigned> templ_var_index; |
301 |
292 |
for (unsigned k = 0, sksize = sks.size(); k < sksize; k++) |
302 |
|
{ |
303 |
211 |
Assert(sks[k].getType().isDatatype()); |
304 |
211 |
echildren[0] = sks[k]; |
305 |
422 |
Trace("sygus-unif-debug2") << "...set eval dt to " << sks[k] |
306 |
211 |
<< std::endl; |
307 |
422 |
Node esk = nm->mkNode(DT_SYGUS_EVAL, echildren); |
308 |
211 |
vs.push_back(esk); |
309 |
422 |
Node tvar = sm->mkDummySkolem("templ", esk.getType()); |
310 |
211 |
templ_var_index[tvar] = k; |
311 |
422 |
Trace("sygus-unif-debug2") << "* template inference : looking for " |
312 |
211 |
<< tvar << " for arg " << k << std::endl; |
313 |
211 |
ss.push_back(tvar); |
314 |
422 |
Trace("sygus-unif-debug2") << "* substitute : " << esk << " -> " << tvar |
315 |
211 |
<< std::endl; |
316 |
|
} |
317 |
81 |
eut = eut.substitute(vs.begin(), vs.end(), ss.begin(), ss.end()); |
318 |
162 |
Trace("sygus-unif-debug2") << "Constructor " << j << ", base term is " |
319 |
81 |
<< eut << std::endl; |
320 |
162 |
std::map<unsigned, Node> test_args; |
321 |
81 |
if (dt[j].isSygusIdFunc()) |
322 |
|
{ |
323 |
3 |
test_args[0] = eut; |
324 |
|
} |
325 |
|
else |
326 |
|
{ |
327 |
286 |
for (unsigned k = 0, size = eut.getNumChildren(); k < size; k++) |
328 |
|
{ |
329 |
208 |
test_args[k] = eut[k]; |
330 |
|
} |
331 |
|
} |
332 |
|
|
333 |
|
// TODO : prefix grouping prefix/suffix |
334 |
81 |
bool isAssoc = TermUtil::isAssoc(eut.getKind()); |
335 |
162 |
Trace("sygus-unif-debug2") << eut.getKind() << " isAssoc = " << isAssoc |
336 |
81 |
<< std::endl; |
337 |
162 |
std::map<unsigned, std::vector<unsigned> > assoc_combine; |
338 |
162 |
std::vector<unsigned> assoc_waiting; |
339 |
81 |
int assoc_last_valid_index = -1; |
340 |
292 |
for (std::pair<const unsigned, Node>& ta : test_args) |
341 |
|
{ |
342 |
211 |
unsigned k = ta.first; |
343 |
422 |
Node eut_c = ta.second; |
344 |
|
// success if we can find a injection from args to sygus args |
345 |
211 |
if (!inferTemplate(k, eut_c, templ_var_index, templ_injection)) |
346 |
|
{ |
347 |
|
Trace("sygus-unif-debug") |
348 |
|
<< "...fail: could not find injection (range)." << std::endl; |
349 |
|
cop_to_strat.erase(cop); |
350 |
|
break; |
351 |
|
} |
352 |
211 |
std::map<unsigned, unsigned>::iterator itti = templ_injection.find(k); |
353 |
211 |
if (itti != templ_injection.end()) |
354 |
|
{ |
355 |
|
// if associative, combine arguments if it is the same variable |
356 |
284 |
if (isAssoc && assoc_last_valid_index >= 0 |
357 |
243 |
&& itti->second == templ_injection[assoc_last_valid_index]) |
358 |
|
{ |
359 |
|
templ_injection.erase(k); |
360 |
|
assoc_combine[assoc_last_valid_index].push_back(k); |
361 |
|
} |
362 |
|
else |
363 |
|
{ |
364 |
199 |
assoc_last_valid_index = (int)k; |
365 |
199 |
if (!assoc_waiting.empty()) |
366 |
|
{ |
367 |
|
assoc_combine[k].insert(assoc_combine[k].end(), |
368 |
|
assoc_waiting.begin(), |
369 |
|
assoc_waiting.end()); |
370 |
|
assoc_waiting.clear(); |
371 |
|
} |
372 |
199 |
assoc_combine[k].push_back(k); |
373 |
|
} |
374 |
|
} |
375 |
|
else |
376 |
|
{ |
377 |
|
// a ground argument |
378 |
12 |
if (!isAssoc) |
379 |
|
{ |
380 |
|
Trace("sygus-unif-debug") |
381 |
|
<< "...fail: could not find injection (functional)." |
382 |
|
<< std::endl; |
383 |
|
cop_to_strat.erase(cop); |
384 |
|
break; |
385 |
|
} |
386 |
|
else |
387 |
|
{ |
388 |
12 |
if (assoc_last_valid_index >= 0) |
389 |
|
{ |
390 |
12 |
assoc_combine[assoc_last_valid_index].push_back(k); |
391 |
|
} |
392 |
|
else |
393 |
|
{ |
394 |
|
assoc_waiting.push_back(k); |
395 |
|
} |
396 |
|
} |
397 |
|
} |
398 |
|
} |
399 |
81 |
if (cop_to_strat.find(cop) != cop_to_strat.end()) |
400 |
|
{ |
401 |
|
// construct the templates |
402 |
81 |
if (!assoc_waiting.empty()) |
403 |
|
{ |
404 |
|
// could not find a way to fit some arguments into injection |
405 |
|
cop_to_strat.erase(cop); |
406 |
|
} |
407 |
|
else |
408 |
|
{ |
409 |
292 |
for (std::pair<const unsigned, Node>& ta : test_args) |
410 |
|
{ |
411 |
211 |
unsigned k = ta.first; |
412 |
422 |
Trace("sygus-unif-debug2") << "- processing argument " << k << "..." |
413 |
211 |
<< std::endl; |
414 |
211 |
if (templ_injection.find(k) != templ_injection.end()) |
415 |
|
{ |
416 |
199 |
unsigned sk_index = templ_injection[k]; |
417 |
796 |
if (std::find(cop_to_carg_list[cop].begin(), |
418 |
199 |
cop_to_carg_list[cop].end(), |
419 |
398 |
sk_index) |
420 |
597 |
== cop_to_carg_list[cop].end()) |
421 |
|
{ |
422 |
199 |
cop_to_carg_list[cop].push_back(sk_index); |
423 |
|
} |
424 |
|
else |
425 |
|
{ |
426 |
|
Trace("sygus-unif-debug") << "...fail: duplicate argument used" |
427 |
|
<< std::endl; |
428 |
|
cop_to_strat.erase(cop); |
429 |
|
break; |
430 |
|
} |
431 |
|
// also store the template information, if necessary |
432 |
398 |
Node teut; |
433 |
199 |
if (isAssoc) |
434 |
|
{ |
435 |
85 |
std::vector<unsigned>& ac = assoc_combine[k]; |
436 |
85 |
Assert(!ac.empty()); |
437 |
170 |
std::vector<Node> children; |
438 |
182 |
for (unsigned ack = 0, size_ac = ac.size(); ack < size_ac; |
439 |
|
ack++) |
440 |
|
{ |
441 |
97 |
children.push_back(eut[ac[ack]]); |
442 |
|
} |
443 |
170 |
teut = children.size() == 1 |
444 |
170 |
? children[0] |
445 |
|
: nm->mkNode(eut.getKind(), children); |
446 |
85 |
teut = Rewriter::rewrite(teut); |
447 |
|
} |
448 |
|
else |
449 |
|
{ |
450 |
114 |
teut = ta.second; |
451 |
|
} |
452 |
|
|
453 |
199 |
if (!teut.isVar()) |
454 |
|
{ |
455 |
24 |
cop_to_child_templ[cop][k] = teut; |
456 |
24 |
cop_to_child_templ_arg[cop][k] = ss[sk_index]; |
457 |
48 |
Trace("sygus-unif-debug") |
458 |
24 |
<< " Arg " << k << " (template : " << teut << " arg " |
459 |
24 |
<< ss[sk_index] << "), index " << sk_index << std::endl; |
460 |
|
} |
461 |
|
else |
462 |
|
{ |
463 |
350 |
Trace("sygus-unif-debug") << " Arg " << k << ", index " |
464 |
175 |
<< sk_index << std::endl; |
465 |
175 |
Assert(teut == ss[sk_index]); |
466 |
|
} |
467 |
|
} |
468 |
|
else |
469 |
|
{ |
470 |
12 |
Assert(isAssoc); |
471 |
|
} |
472 |
|
} |
473 |
|
} |
474 |
|
} |
475 |
|
} |
476 |
|
|
477 |
683 |
std::map<Node, std::vector<StrategyType> >::iterator itcs = cop_to_strat.find(cop); |
478 |
683 |
if (itcs != cop_to_strat.end()) |
479 |
|
{ |
480 |
162 |
Trace("sygus-unif") << "-> constructor " << cop |
481 |
162 |
<< " matches strategy for " << eut.getKind() << "..." |
482 |
81 |
<< std::endl; |
483 |
|
// collect children types |
484 |
280 |
for (unsigned k = 0, size = cop_to_carg_list[cop].size(); k < size; k++) |
485 |
|
{ |
486 |
398 |
TypeNode ctn = sktns[cop_to_carg_list[cop][k]]; |
487 |
398 |
Trace("sygus-unif-debug") << " Child type " << k << " : " |
488 |
199 |
<< ctn.getDType().getName() << std::endl; |
489 |
199 |
cop_to_child_types[cop].push_back(ctn); |
490 |
|
} |
491 |
|
// if there are checks on the consistency of child types wrt strategies, |
492 |
|
// these should be enforced here. We currently have none. |
493 |
|
} |
494 |
683 |
if (cop_to_strat.find(cop) == cop_to_strat.end()) |
495 |
|
{ |
496 |
1204 |
Trace("sygus-unif") << "...constructor " << cop |
497 |
602 |
<< " does not correspond to a strategy." << std::endl; |
498 |
602 |
search_this = true; |
499 |
|
} |
500 |
|
} |
501 |
|
|
502 |
|
// check whether we should also enumerate the current type |
503 |
103 |
Trace("sygus-unif-debug2") << " register this strategy ..." << std::endl; |
504 |
103 |
registerStrategyPoint(ee, tn, erole, search_this); |
505 |
|
|
506 |
103 |
if (cop_to_strat.empty()) |
507 |
|
{ |
508 |
56 |
Trace("sygus-unif") << "...consider " << dt.getName() << " a basic type" |
509 |
28 |
<< std::endl; |
510 |
|
} |
511 |
|
else |
512 |
|
{ |
513 |
156 |
for (std::pair<const Node, std::vector<StrategyType> >& cstr : cop_to_strat) |
514 |
|
{ |
515 |
162 |
Node cop = cstr.first; |
516 |
162 |
Trace("sygus-unif-debug") << "Constructor " << cop << " has " |
517 |
162 |
<< cstr.second.size() << " strategies..." |
518 |
81 |
<< std::endl; |
519 |
176 |
for (unsigned s = 0, ssize = cstr.second.size(); s < ssize; s++) |
520 |
|
{ |
521 |
95 |
EnumTypeInfoStrat* cons_strat = new EnumTypeInfoStrat; |
522 |
95 |
StrategyType strat = cstr.second[s]; |
523 |
|
|
524 |
95 |
cons_strat->d_this = strat; |
525 |
95 |
cons_strat->d_cons = cop; |
526 |
190 |
Trace("sygus-unif-debug") << "Process strategy #" << s |
527 |
95 |
<< " for operator : " << cop << " : " << strat |
528 |
95 |
<< std::endl; |
529 |
95 |
Assert(cop_to_child_types.find(cop) != cop_to_child_types.end()); |
530 |
95 |
std::vector<TypeNode>& childTypes = cop_to_child_types[cop]; |
531 |
95 |
Assert(cop_to_carg_list.find(cop) != cop_to_carg_list.end()); |
532 |
95 |
std::vector<unsigned>& cargList = cop_to_carg_list[cop]; |
533 |
|
|
534 |
190 |
std::vector<Node> sol_templ_children; |
535 |
95 |
sol_templ_children.resize(cop_to_sks[cop].size()); |
536 |
|
|
537 |
323 |
for (unsigned j = 0, csize = childTypes.size(); j < csize; j++) |
538 |
|
{ |
539 |
|
// calculate if we should allocate a new enumerator : should be true |
540 |
|
// if we have a new role |
541 |
228 |
NodeRole nrole_c = nrole; |
542 |
228 |
if (strat == strat_ITE) |
543 |
|
{ |
544 |
111 |
if (j == 0) |
545 |
|
{ |
546 |
37 |
nrole_c = role_ite_condition; |
547 |
|
} |
548 |
|
} |
549 |
117 |
else if (strat == strat_CONCAT_PREFIX) |
550 |
|
{ |
551 |
56 |
if ((j + 1) < childTypes.size()) |
552 |
|
{ |
553 |
29 |
nrole_c = role_string_prefix; |
554 |
|
} |
555 |
|
} |
556 |
61 |
else if (strat == strat_CONCAT_SUFFIX) |
557 |
|
{ |
558 |
58 |
if (j > 0) |
559 |
|
{ |
560 |
30 |
nrole_c = role_string_suffix; |
561 |
|
} |
562 |
|
} |
563 |
|
// in all other cases, role is same as parent |
564 |
|
|
565 |
|
// register the child type |
566 |
456 |
TypeNode ct = childTypes[j]; |
567 |
456 |
Node csk = cop_to_sks[cop][cargList[j]]; |
568 |
228 |
cons_strat->d_sol_templ_args.push_back(csk); |
569 |
228 |
sol_templ_children[cargList[j]] = csk; |
570 |
|
|
571 |
228 |
EnumRole erole_c = getEnumeratorRoleForNodeRole(nrole_c); |
572 |
|
// make the enumerator |
573 |
456 |
Node et; |
574 |
|
// Build the strategy recursively, regardless of whether the |
575 |
|
// enumerator is templated. |
576 |
228 |
buildStrategyGraph(ct, nrole_c); |
577 |
228 |
if (cop_to_child_templ[cop].find(j) != cop_to_child_templ[cop].end()) |
578 |
|
{ |
579 |
|
// it is templated, allocate a fresh variable |
580 |
28 |
et = sm->mkDummySkolem("et", ct); |
581 |
56 |
Trace("sygus-unif-debug") << "...enumerate " << et << " of type " |
582 |
28 |
<< ct.getDType().getName(); |
583 |
56 |
Trace("sygus-unif-debug") << " for arg " << j << " of " |
584 |
28 |
<< tn.getDType().getName() << std::endl; |
585 |
28 |
registerStrategyPoint(et, ct, erole_c, true); |
586 |
28 |
d_einfo[et].d_template = cop_to_child_templ[cop][j]; |
587 |
28 |
d_einfo[et].d_template_arg = cop_to_child_templ_arg[cop][j]; |
588 |
28 |
Assert(!d_einfo[et].d_template.isNull()); |
589 |
28 |
Assert(!d_einfo[et].d_template_arg.isNull()); |
590 |
|
} |
591 |
|
else |
592 |
|
{ |
593 |
400 |
Trace("sygus-unif-debug") |
594 |
400 |
<< "...child type enumerate " << ct.getDType().getName() |
595 |
200 |
<< ", node role = " << nrole_c << std::endl; |
596 |
|
// otherwise use the previous |
597 |
200 |
Assert(d_tinfo[ct].d_enum.find(erole_c) |
598 |
|
!= d_tinfo[ct].d_enum.end()); |
599 |
200 |
et = d_tinfo[ct].d_enum[erole_c]; |
600 |
|
} |
601 |
456 |
Trace("sygus-unif-debug") << "Register child enumerator " << et |
602 |
228 |
<< ", arg " << j << " of " << cop |
603 |
228 |
<< ", role = " << erole_c << std::endl; |
604 |
228 |
Assert(!et.isNull()); |
605 |
228 |
cons_strat->d_cenum.push_back(std::pair<Node, NodeRole>(et, nrole_c)); |
606 |
|
} |
607 |
|
// children that are unused in the strategy can be arbitrary |
608 |
339 |
for (unsigned j = 0, stsize = sol_templ_children.size(); j < stsize; |
609 |
|
j++) |
610 |
|
{ |
611 |
244 |
if (sol_templ_children[j].isNull()) |
612 |
|
{ |
613 |
16 |
sol_templ_children[j] = cop_to_sks[cop][j].getType().mkGroundTerm(); |
614 |
|
} |
615 |
|
} |
616 |
95 |
sol_templ_children.insert(sol_templ_children.begin(), cop); |
617 |
190 |
cons_strat->d_sol_templ = |
618 |
285 |
nm->mkNode(APPLY_CONSTRUCTOR, sol_templ_children); |
619 |
95 |
if (strat == strat_CONCAT_SUFFIX) |
620 |
|
{ |
621 |
28 |
std::reverse(cons_strat->d_cenum.begin(), cons_strat->d_cenum.end()); |
622 |
28 |
std::reverse(cons_strat->d_sol_templ_args.begin(), |
623 |
28 |
cons_strat->d_sol_templ_args.end()); |
624 |
|
} |
625 |
95 |
if (Trace.isOn("sygus-unif")) |
626 |
|
{ |
627 |
|
Trace("sygus-unif") << "Initialized strategy " << strat; |
628 |
|
Trace("sygus-unif") |
629 |
|
<< " for " << tn.getDType().getName() << ", operator " << cop; |
630 |
|
Trace("sygus-unif") << ", #children = " << cons_strat->d_cenum.size() |
631 |
|
<< ", solution template = (lambda ( "; |
632 |
|
for (const Node& targ : cons_strat->d_sol_templ_args) |
633 |
|
{ |
634 |
|
Trace("sygus-unif") << targ << " "; |
635 |
|
} |
636 |
|
Trace("sygus-unif") << ") " << cons_strat->d_sol_templ << ")"; |
637 |
|
Trace("sygus-unif") << std::endl; |
638 |
|
} |
639 |
|
// make the strategy |
640 |
95 |
snode.d_strats.push_back(cons_strat); |
641 |
|
} |
642 |
|
} |
643 |
|
} |
644 |
|
} |
645 |
|
|
646 |
239 |
bool SygusUnifStrategy::inferTemplate( |
647 |
|
unsigned k, |
648 |
|
Node n, |
649 |
|
std::map<Node, unsigned>& templ_var_index, |
650 |
|
std::map<unsigned, unsigned>& templ_injection) |
651 |
|
{ |
652 |
239 |
if (n.getNumChildren() == 0) |
653 |
|
{ |
654 |
225 |
std::map<Node, unsigned>::iterator itt = templ_var_index.find(n); |
655 |
225 |
if (itt != templ_var_index.end()) |
656 |
|
{ |
657 |
199 |
unsigned kk = itt->second; |
658 |
199 |
std::map<unsigned, unsigned>::iterator itti = templ_injection.find(k); |
659 |
199 |
if (itti == templ_injection.end()) |
660 |
|
{ |
661 |
398 |
Trace("sygus-unif-debug") << "...set template injection " << k << " -> " |
662 |
199 |
<< kk << std::endl; |
663 |
199 |
templ_injection[k] = kk; |
664 |
|
} |
665 |
|
else if (itti->second != kk) |
666 |
|
{ |
667 |
|
// two distinct variables in this term, we fail |
668 |
|
return false; |
669 |
|
} |
670 |
|
} |
671 |
225 |
return true; |
672 |
|
} |
673 |
|
else |
674 |
|
{ |
675 |
42 |
for (unsigned i = 0; i < n.getNumChildren(); i++) |
676 |
|
{ |
677 |
28 |
if (!inferTemplate(k, n[i], templ_var_index, templ_injection)) |
678 |
|
{ |
679 |
|
return false; |
680 |
|
} |
681 |
|
} |
682 |
|
} |
683 |
14 |
return true; |
684 |
|
} |
685 |
|
|
686 |
47 |
void SygusUnifStrategy::staticLearnRedundantOps( |
687 |
|
std::map<Node, std::vector<Node>>& strategy_lemmas) |
688 |
|
{ |
689 |
94 |
StrategyRestrictions restrictions; |
690 |
47 |
staticLearnRedundantOps(strategy_lemmas, restrictions); |
691 |
47 |
} |
692 |
|
|
693 |
61 |
void SygusUnifStrategy::staticLearnRedundantOps( |
694 |
|
std::map<Node, std::vector<Node>>& strategy_lemmas, |
695 |
|
StrategyRestrictions& restrictions) |
696 |
|
{ |
697 |
143 |
for (unsigned i = 0; i < d_esym_list.size(); i++) |
698 |
|
{ |
699 |
164 |
Node e = d_esym_list[i]; |
700 |
82 |
std::map<Node, EnumInfo>::iterator itn = d_einfo.find(e); |
701 |
82 |
Assert(itn != d_einfo.end()); |
702 |
|
// see if there is anything we can eliminate |
703 |
164 |
Trace("sygus-unif") << "* Search enumerator #" << i << " : type " |
704 |
82 |
<< e.getType().getDType().getName() << " : "; |
705 |
164 |
Trace("sygus-unif") << e << " has " << itn->second.d_enum_slave.size() |
706 |
82 |
<< " slaves:" << std::endl; |
707 |
228 |
for (unsigned j = 0; j < itn->second.d_enum_slave.size(); j++) |
708 |
|
{ |
709 |
292 |
Node es = itn->second.d_enum_slave[j]; |
710 |
146 |
std::map<Node, EnumInfo>::iterator itns = d_einfo.find(es); |
711 |
146 |
Assert(itns != d_einfo.end()); |
712 |
292 |
Trace("sygus-unif") << " " << es << ", role = " << itns->second.getRole() |
713 |
146 |
<< std::endl; |
714 |
|
} |
715 |
|
} |
716 |
61 |
Trace("sygus-unif") << std::endl; |
717 |
122 |
Trace("sygus-unif") << "Strategy for candidate " << d_candidate |
718 |
61 |
<< " is : " << std::endl; |
719 |
61 |
debugPrint("sygus-unif"); |
720 |
122 |
std::map<Node, std::map<NodeRole, bool> > visited; |
721 |
122 |
std::map<Node, std::map<unsigned, bool> > needs_cons; |
722 |
61 |
staticLearnRedundantOps( |
723 |
122 |
getRootEnumerator(), role_equal, visited, needs_cons, restrictions); |
724 |
|
// now, check the needs_cons map |
725 |
169 |
for (std::pair<const Node, std::map<unsigned, bool> >& nce : needs_cons) |
726 |
|
{ |
727 |
216 |
Node em = nce.first; |
728 |
108 |
const DType& dt = em.getType().getDType(); |
729 |
216 |
std::vector<Node> lemmas; |
730 |
881 |
for (std::pair<const unsigned, bool>& nc : nce.second) |
731 |
|
{ |
732 |
773 |
Assert(nc.first < dt.getNumConstructors()); |
733 |
773 |
if (!nc.second) |
734 |
|
{ |
735 |
442 |
Node tst = datatypes::utils::mkTester(em, nc.first, dt).negate(); |
736 |
|
|
737 |
221 |
if (std::find(lemmas.begin(), lemmas.end(), tst) == lemmas.end()) |
738 |
|
{ |
739 |
442 |
Trace("sygus-unif") << "...can exclude based on : " << tst |
740 |
221 |
<< std::endl; |
741 |
221 |
lemmas.push_back(tst); |
742 |
|
} |
743 |
|
} |
744 |
|
} |
745 |
108 |
if (!lemmas.empty()) |
746 |
|
{ |
747 |
74 |
strategy_lemmas[em] = lemmas; |
748 |
|
} |
749 |
|
} |
750 |
61 |
} |
751 |
|
|
752 |
61 |
void SygusUnifStrategy::debugPrint(const char* c) |
753 |
|
{ |
754 |
61 |
if (Trace.isOn(c)) |
755 |
|
{ |
756 |
|
std::map<Node, std::map<NodeRole, bool> > visited; |
757 |
|
debugPrint(c, getRootEnumerator(), role_equal, visited, 0); |
758 |
|
} |
759 |
61 |
} |
760 |
|
|
761 |
279 |
void SygusUnifStrategy::staticLearnRedundantOps( |
762 |
|
Node e, |
763 |
|
NodeRole nrole, |
764 |
|
std::map<Node, std::map<NodeRole, bool>>& visited, |
765 |
|
std::map<Node, std::map<unsigned, bool>>& needs_cons, |
766 |
|
StrategyRestrictions& restrictions) |
767 |
|
{ |
768 |
279 |
if (visited[e].find(nrole) != visited[e].end()) |
769 |
|
{ |
770 |
294 |
return; |
771 |
|
} |
772 |
288 |
Trace("sygus-strat-slearn") << "Learn redundant operators " << e << " " |
773 |
144 |
<< nrole << "..." << std::endl; |
774 |
144 |
visited[e][nrole] = true; |
775 |
144 |
EnumInfo& ei = getEnumInfo(e); |
776 |
144 |
if (ei.isTemplated()) |
777 |
|
{ |
778 |
24 |
return; |
779 |
|
} |
780 |
240 |
TypeNode etn = e.getType(); |
781 |
120 |
EnumTypeInfo& tinfo = getEnumTypeInfo(etn); |
782 |
120 |
StrategyNode& snode = tinfo.getStrategyNode(nrole); |
783 |
|
// the constructors of the current strategy point we need |
784 |
240 |
std::map<unsigned, bool> needs_cons_curr; |
785 |
|
// get the unused strategies |
786 |
|
std::map<Node, std::unordered_set<unsigned>>::iterator itus = |
787 |
120 |
restrictions.d_unused_strategies.find(e); |
788 |
240 |
std::unordered_set<unsigned> unused_strats; |
789 |
120 |
if (itus != restrictions.d_unused_strategies.end()) |
790 |
|
{ |
791 |
2 |
unused_strats.insert(itus->second.begin(), itus->second.end()); |
792 |
|
} |
793 |
211 |
for (unsigned j = 0, size = snode.d_strats.size(); j < size; j++) |
794 |
|
{ |
795 |
|
// if we are not using this strategy, there is nothing to do |
796 |
91 |
if (unused_strats.find(j) != unused_strats.end()) |
797 |
|
{ |
798 |
2 |
continue; |
799 |
|
} |
800 |
89 |
EnumTypeInfoStrat* etis = snode.d_strats[j]; |
801 |
89 |
unsigned cindex = datatypes::utils::indexOf(etis->d_cons); |
802 |
|
// constructors that correspond to strategies are not needed |
803 |
|
// the intuition is that the strategy itself is responsible for constructing |
804 |
|
// all terms that use the given constructor |
805 |
178 |
Trace("sygus-strat-slearn") << "...by strategy, can exclude operator " |
806 |
89 |
<< etis->d_cons << std::endl; |
807 |
89 |
needs_cons_curr[cindex] = false; |
808 |
|
// try to eliminate from etn's datatype all operators except TRUE/FALSE if |
809 |
|
// arguments of ITE are the same BOOL type |
810 |
89 |
if (restrictions.d_iteReturnBoolConst) |
811 |
|
{ |
812 |
11 |
const DType& dt = etn.getDType(); |
813 |
22 |
Node op = dt[cindex].getSygusOp(); |
814 |
22 |
TypeNode sygus_tn = dt.getSygusType(); |
815 |
22 |
if (op.getKind() == kind::BUILTIN |
816 |
18 |
&& NodeManager::operatorToKind(op) == ITE && sygus_tn.isBoolean() |
817 |
28 |
&& (dt[cindex].getArgType(1) == dt[cindex].getArgType(2))) |
818 |
|
{ |
819 |
6 |
unsigned ncons = dt.getNumConstructors(), indexT = ncons, |
820 |
6 |
indexF = ncons; |
821 |
128 |
for (unsigned k = 0; k < ncons; ++k) |
822 |
|
{ |
823 |
134 |
Node op_arg = dt[k].getSygusOp(); |
824 |
122 |
if (dt[k].getNumArgs() > 0 || !op_arg.isConst()) |
825 |
|
{ |
826 |
110 |
continue; |
827 |
|
} |
828 |
12 |
if (op_arg.getConst<bool>()) |
829 |
|
{ |
830 |
6 |
indexT = k; |
831 |
|
} |
832 |
|
else |
833 |
|
{ |
834 |
6 |
indexF = k; |
835 |
|
} |
836 |
|
} |
837 |
6 |
if (indexT < ncons && indexF < ncons) |
838 |
|
{ |
839 |
12 |
Trace("sygus-strat-slearn") |
840 |
6 |
<< "...for ite boolean arg, can exclude all operators but T/F\n"; |
841 |
128 |
for (unsigned k = 0; k < ncons; ++k) |
842 |
|
{ |
843 |
122 |
needs_cons_curr[k] = false; |
844 |
|
} |
845 |
6 |
needs_cons_curr[indexT] = true; |
846 |
6 |
needs_cons_curr[indexF] = true; |
847 |
|
} |
848 |
|
} |
849 |
|
} |
850 |
307 |
for (std::pair<Node, NodeRole>& cec : etis->d_cenum) |
851 |
|
{ |
852 |
218 |
staticLearnRedundantOps( |
853 |
|
cec.first, cec.second, visited, needs_cons, restrictions); |
854 |
|
} |
855 |
|
} |
856 |
|
// get the current datatype |
857 |
120 |
const DType& dt = etn.getDType(); |
858 |
|
// do not use recursive Boolean connectives for conditions of ITEs |
859 |
120 |
if (nrole == role_ite_condition && restrictions.d_iteCondOnlyAtoms) |
860 |
|
{ |
861 |
46 |
TypeNode sygus_tn = dt.getSygusType(); |
862 |
204 |
for (unsigned j = 0, size = dt.getNumConstructors(); j < size; j++) |
863 |
|
{ |
864 |
338 |
Node op = dt[j].getSygusOp(); |
865 |
362 |
Trace("sygus-strat-slearn") |
866 |
181 |
<< "...for ite condition, look at operator : " << op << std::endl; |
867 |
205 |
if (op.isConst() && dt[j].getNumArgs() == 0) |
868 |
|
{ |
869 |
48 |
Trace("sygus-strat-slearn") |
870 |
24 |
<< "...for ite condition, can exclude Boolean constant " << op |
871 |
24 |
<< std::endl; |
872 |
24 |
needs_cons_curr[j] = false; |
873 |
24 |
continue; |
874 |
|
} |
875 |
157 |
if (op.getKind() == kind::BUILTIN) |
876 |
|
{ |
877 |
42 |
Kind kind = NodeManager::operatorToKind(op); |
878 |
42 |
if (kind == NOT || kind == OR || kind == AND || kind == ITE) |
879 |
|
{ |
880 |
|
// can eliminate if their argument types are simple loops to this type |
881 |
28 |
bool type_ok = true; |
882 |
84 |
for (unsigned k = 0, nargs = dt[j].getNumArgs(); k < nargs; k++) |
883 |
|
{ |
884 |
112 |
TypeNode tn = dt[j].getArgType(k); |
885 |
56 |
if (tn != etn) |
886 |
|
{ |
887 |
|
type_ok = false; |
888 |
|
break; |
889 |
|
} |
890 |
|
} |
891 |
28 |
if (type_ok) |
892 |
|
{ |
893 |
56 |
Trace("sygus-strat-slearn") |
894 |
28 |
<< "...for ite condition, can exclude Boolean connective : " |
895 |
28 |
<< op << std::endl; |
896 |
28 |
needs_cons_curr[j] = false; |
897 |
|
} |
898 |
|
} |
899 |
|
} |
900 |
|
} |
901 |
|
} |
902 |
|
// all other constructors are needed |
903 |
954 |
for (unsigned j = 0, size = dt.getNumConstructors(); j < size; j++) |
904 |
|
{ |
905 |
834 |
if (needs_cons_curr.find(j) == needs_cons_curr.end()) |
906 |
|
{ |
907 |
591 |
needs_cons_curr[j] = true; |
908 |
|
} |
909 |
|
} |
910 |
|
// update the constructors that the master enumerator needs |
911 |
120 |
if (needs_cons.find(e) == needs_cons.end()) |
912 |
|
{ |
913 |
108 |
needs_cons[e] = needs_cons_curr; |
914 |
|
} |
915 |
|
else |
916 |
|
{ |
917 |
73 |
for (unsigned j = 0, size = dt.getNumConstructors(); j < size; j++) |
918 |
|
{ |
919 |
61 |
needs_cons[e][j] = needs_cons[e][j] || needs_cons_curr[j]; |
920 |
|
} |
921 |
|
} |
922 |
|
} |
923 |
|
|
924 |
394 |
void SygusUnifStrategy::finishInit( |
925 |
|
Node e, |
926 |
|
NodeRole nrole, |
927 |
|
std::map<Node, std::map<NodeRole, bool> >& visited, |
928 |
|
bool isCond) |
929 |
|
{ |
930 |
394 |
EnumInfo& ei = getEnumInfo(e); |
931 |
788 |
if (visited[e].find(nrole) != visited[e].end() |
932 |
394 |
&& (!isCond || ei.isConditional())) |
933 |
|
{ |
934 |
448 |
return; |
935 |
|
} |
936 |
182 |
visited[e][nrole] = true; |
937 |
|
// set conditional |
938 |
182 |
if (isCond) |
939 |
|
{ |
940 |
73 |
ei.setConditional(); |
941 |
|
} |
942 |
182 |
if (ei.isTemplated()) |
943 |
|
{ |
944 |
24 |
return; |
945 |
|
} |
946 |
316 |
TypeNode etn = e.getType(); |
947 |
158 |
EnumTypeInfo& tinfo = getEnumTypeInfo(etn); |
948 |
158 |
StrategyNode& snode = tinfo.getStrategyNode(nrole); |
949 |
289 |
for (unsigned j = 0, size = snode.d_strats.size(); j < size; j++) |
950 |
|
{ |
951 |
131 |
EnumTypeInfoStrat* etis = snode.d_strats[j]; |
952 |
131 |
StrategyType strat = etis->d_this; |
953 |
131 |
bool newIsCond = isCond || strat == strat_ITE; |
954 |
464 |
for (std::pair<Node, NodeRole>& cec : etis->d_cenum) |
955 |
|
{ |
956 |
333 |
finishInit(cec.first, cec.second, visited, newIsCond); |
957 |
|
} |
958 |
|
} |
959 |
|
} |
960 |
|
|
961 |
|
void SygusUnifStrategy::debugPrint( |
962 |
|
const char* c, |
963 |
|
Node e, |
964 |
|
NodeRole nrole, |
965 |
|
std::map<Node, std::map<NodeRole, bool> >& visited, |
966 |
|
int ind) |
967 |
|
{ |
968 |
|
if (visited[e].find(nrole) != visited[e].end()) |
969 |
|
{ |
970 |
|
indent(c, ind); |
971 |
|
Trace(c) << e << " :: node role : " << nrole << std::endl; |
972 |
|
return; |
973 |
|
} |
974 |
|
visited[e][nrole] = true; |
975 |
|
EnumInfo& ei = getEnumInfo(e); |
976 |
|
|
977 |
|
TypeNode etn = e.getType(); |
978 |
|
|
979 |
|
indent(c, ind); |
980 |
|
Trace(c) << e << " :: node role : " << nrole; |
981 |
|
Trace(c) << ", type : " << etn.getDType().getName(); |
982 |
|
if (ei.isConditional()) |
983 |
|
{ |
984 |
|
Trace(c) << ", conditional"; |
985 |
|
} |
986 |
|
Trace(c) << ", enum role : " << ei.getRole(); |
987 |
|
|
988 |
|
if (ei.isTemplated()) |
989 |
|
{ |
990 |
|
Trace(c) << ", templated : (lambda " << ei.d_template_arg << " " |
991 |
|
<< ei.d_template << ")" << std::endl; |
992 |
|
return; |
993 |
|
} |
994 |
|
Trace(c) << std::endl; |
995 |
|
|
996 |
|
EnumTypeInfo& tinfo = getEnumTypeInfo(etn); |
997 |
|
StrategyNode& snode = tinfo.getStrategyNode(nrole); |
998 |
|
for (unsigned j = 0, size = snode.d_strats.size(); j < size; j++) |
999 |
|
{ |
1000 |
|
EnumTypeInfoStrat* etis = snode.d_strats[j]; |
1001 |
|
StrategyType strat = etis->d_this; |
1002 |
|
indent(c, ind + 1); |
1003 |
|
Trace(c) << "Strategy : " << strat << ", from cons : " << etis->d_cons |
1004 |
|
<< std::endl; |
1005 |
|
for (std::pair<Node, NodeRole>& cec : etis->d_cenum) |
1006 |
|
{ |
1007 |
|
// recurse |
1008 |
|
debugPrint(c, cec.first, cec.second, visited, ind + 2); |
1009 |
|
} |
1010 |
|
} |
1011 |
|
} |
1012 |
|
|
1013 |
150 |
void EnumInfo::initialize(EnumRole role) { d_role = role; } |
1014 |
|
|
1015 |
518 |
StrategyNode& EnumTypeInfo::getStrategyNode(NodeRole nrole) |
1016 |
|
{ |
1017 |
518 |
std::map<NodeRole, StrategyNode>::iterator it = d_snodes.find(nrole); |
1018 |
518 |
Assert(it != d_snodes.end()); |
1019 |
518 |
return it->second; |
1020 |
|
} |
1021 |
|
|
1022 |
3065 |
bool EnumTypeInfoStrat::isValid(UnifContext& x) |
1023 |
|
{ |
1024 |
6130 |
if ((x.getCurrentRole() == role_string_prefix |
1025 |
1355 |
&& d_this == strat_CONCAT_SUFFIX) |
1026 |
6276 |
|| (x.getCurrentRole() == role_string_suffix |
1027 |
773 |
&& d_this == strat_CONCAT_PREFIX)) |
1028 |
|
{ |
1029 |
478 |
return false; |
1030 |
|
} |
1031 |
2587 |
return true; |
1032 |
|
} |
1033 |
|
|
1034 |
276 |
StrategyNode::~StrategyNode() |
1035 |
|
{ |
1036 |
233 |
for (unsigned j = 0, size = d_strats.size(); j < size; j++) |
1037 |
|
{ |
1038 |
95 |
delete d_strats[j]; |
1039 |
|
} |
1040 |
138 |
d_strats.clear(); |
1041 |
138 |
} |
1042 |
|
|
1043 |
|
void SygusUnifStrategy::indent(const char* c, int ind) |
1044 |
|
{ |
1045 |
|
if (Trace.isOn(c)) |
1046 |
|
{ |
1047 |
|
for (int i = 0; i < ind; i++) |
1048 |
|
{ |
1049 |
|
Trace(c) << " "; |
1050 |
|
} |
1051 |
|
} |
1052 |
|
} |
1053 |
|
|
1054 |
|
} // namespace quantifiers |
1055 |
|
} // namespace theory |
1056 |
29349 |
} // namespace cvc5 |