1 |
|
/****************************************************************************** |
2 |
|
* Top contributors (to current version): |
3 |
|
* Andrew Reynolds, Mathias Preiner, Aina Niemetz |
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 |
|
* Utility for processing single invocation synthesis conjectures. |
14 |
|
*/ |
15 |
|
#include "theory/quantifiers/single_inv_partition.h" |
16 |
|
|
17 |
|
#include <sstream> |
18 |
|
|
19 |
|
#include "expr/node_algorithm.h" |
20 |
|
#include "expr/skolem_manager.h" |
21 |
|
#include "theory/quantifiers/term_util.h" |
22 |
|
#include "theory/rewriter.h" |
23 |
|
|
24 |
|
using namespace cvc5; |
25 |
|
using namespace cvc5::kind; |
26 |
|
using namespace std; |
27 |
|
|
28 |
|
namespace cvc5 { |
29 |
|
namespace theory { |
30 |
|
namespace quantifiers { |
31 |
|
|
32 |
|
bool SingleInvocationPartition::init(Node n) |
33 |
|
{ |
34 |
|
// first, get types of arguments for functions |
35 |
|
std::vector<TypeNode> typs; |
36 |
|
std::map<Node, bool> visited; |
37 |
|
std::vector<Node> funcs; |
38 |
|
if (inferArgTypes(n, typs, visited)) |
39 |
|
{ |
40 |
|
return init(funcs, typs, n, false); |
41 |
|
} |
42 |
|
else |
43 |
|
{ |
44 |
|
Trace("si-prt") << "Could not infer argument types." << std::endl; |
45 |
|
return false; |
46 |
|
} |
47 |
|
} |
48 |
|
|
49 |
65 |
Node SingleInvocationPartition::getFirstOrderVariableForFunction(Node f) const |
50 |
|
{ |
51 |
65 |
std::map<Node, Node>::const_iterator it = d_func_fo_var.find(f); |
52 |
65 |
if (it != d_func_fo_var.end()) |
53 |
|
{ |
54 |
65 |
return it->second; |
55 |
|
} |
56 |
|
return Node::null(); |
57 |
|
} |
58 |
|
|
59 |
|
Node SingleInvocationPartition::getFunctionForFirstOrderVariable(Node v) const |
60 |
|
{ |
61 |
|
std::map<Node, Node>::const_iterator it = d_fo_var_to_func.find(v); |
62 |
|
if (it != d_fo_var_to_func.end()) |
63 |
|
{ |
64 |
|
return it->second; |
65 |
|
} |
66 |
|
return Node::null(); |
67 |
|
} |
68 |
|
|
69 |
65 |
Node SingleInvocationPartition::getFunctionInvocationFor(Node f) const |
70 |
|
{ |
71 |
65 |
std::map<Node, Node>::const_iterator it = d_func_inv.find(f); |
72 |
65 |
if (it != d_func_inv.end()) |
73 |
|
{ |
74 |
65 |
return it->second; |
75 |
|
} |
76 |
|
return Node::null(); |
77 |
|
} |
78 |
|
|
79 |
97 |
void SingleInvocationPartition::getFunctionVariables( |
80 |
|
std::vector<Node>& fvars) const |
81 |
|
{ |
82 |
97 |
fvars.insert(fvars.end(), d_func_vars.begin(), d_func_vars.end()); |
83 |
97 |
} |
84 |
|
|
85 |
309 |
void SingleInvocationPartition::getFunctions(std::vector<Node>& fs) const |
86 |
|
{ |
87 |
309 |
fs.insert(fs.end(), d_all_funcs.begin(), d_all_funcs.end()); |
88 |
309 |
} |
89 |
|
|
90 |
100 |
void SingleInvocationPartition::getSingleInvocationVariables( |
91 |
|
std::vector<Node>& sivars) const |
92 |
|
{ |
93 |
100 |
sivars.insert(sivars.end(), d_si_vars.begin(), d_si_vars.end()); |
94 |
100 |
} |
95 |
|
|
96 |
3 |
void SingleInvocationPartition::getAllVariables(std::vector<Node>& vars) const |
97 |
|
{ |
98 |
3 |
vars.insert(vars.end(), d_all_vars.begin(), d_all_vars.end()); |
99 |
3 |
} |
100 |
|
|
101 |
|
// gets the argument type list for the first APPLY_UF we see |
102 |
|
bool SingleInvocationPartition::inferArgTypes(Node n, |
103 |
|
std::vector<TypeNode>& typs, |
104 |
|
std::map<Node, bool>& visited) |
105 |
|
{ |
106 |
|
if (visited.find(n) == visited.end()) |
107 |
|
{ |
108 |
|
visited[n] = true; |
109 |
|
if (n.getKind() != FORALL) |
110 |
|
{ |
111 |
|
if (n.getKind() == APPLY_UF) |
112 |
|
{ |
113 |
|
for (unsigned i = 0; i < n.getNumChildren(); i++) |
114 |
|
{ |
115 |
|
typs.push_back(n[i].getType()); |
116 |
|
} |
117 |
|
return true; |
118 |
|
} |
119 |
|
else |
120 |
|
{ |
121 |
|
for (unsigned i = 0; i < n.getNumChildren(); i++) |
122 |
|
{ |
123 |
|
if (inferArgTypes(n[i], typs, visited)) |
124 |
|
{ |
125 |
|
return true; |
126 |
|
} |
127 |
|
} |
128 |
|
} |
129 |
|
} |
130 |
|
} |
131 |
|
return false; |
132 |
|
} |
133 |
|
|
134 |
332 |
bool SingleInvocationPartition::init(std::vector<Node>& funcs, Node n) |
135 |
|
{ |
136 |
664 |
Trace("si-prt") << "Initialize with " << funcs.size() << " input functions (" |
137 |
332 |
<< funcs << ")..." << std::endl; |
138 |
664 |
std::vector<TypeNode> typs; |
139 |
332 |
if (!funcs.empty()) |
140 |
|
{ |
141 |
648 |
TypeNode tn0 = funcs[0].getType(); |
142 |
332 |
if (tn0.isFunction()) |
143 |
|
{ |
144 |
931 |
for (unsigned i = 0, nargs = tn0.getNumChildren() - 1; i < nargs; i++) |
145 |
|
{ |
146 |
662 |
typs.push_back(tn0[i]); |
147 |
|
} |
148 |
|
} |
149 |
606 |
for (unsigned i = 1, size = funcs.size(); i < size; i++) |
150 |
|
{ |
151 |
564 |
TypeNode tni = funcs[i].getType(); |
152 |
290 |
if (tni.getNumChildren() != tn0.getNumChildren()) |
153 |
|
{ |
154 |
|
// can't anti-skolemize functions of different sort |
155 |
16 |
Trace("si-prt") << "...type mismatch" << std::endl; |
156 |
16 |
return false; |
157 |
|
} |
158 |
274 |
else if (tni.isFunction()) |
159 |
|
{ |
160 |
795 |
for (unsigned j = 0, nargs = tni.getNumChildren() - 1; j < nargs; j++) |
161 |
|
{ |
162 |
589 |
if (tni[j] != typs[j]) |
163 |
|
{ |
164 |
|
Trace("si-prt") << "...argument type mismatch" << std::endl; |
165 |
|
return false; |
166 |
|
} |
167 |
|
} |
168 |
|
} |
169 |
|
} |
170 |
|
} |
171 |
316 |
Trace("si-prt") << "#types = " << typs.size() << std::endl; |
172 |
316 |
return init(funcs, typs, n, true); |
173 |
|
} |
174 |
|
|
175 |
316 |
bool SingleInvocationPartition::init(std::vector<Node>& funcs, |
176 |
|
std::vector<TypeNode>& typs, |
177 |
|
Node n, |
178 |
|
bool has_funcs) |
179 |
|
{ |
180 |
316 |
Assert(d_arg_types.empty()); |
181 |
316 |
Assert(d_input_funcs.empty()); |
182 |
316 |
Assert(d_si_vars.empty()); |
183 |
316 |
NodeManager* nm = NodeManager::currentNM(); |
184 |
316 |
SkolemManager* sm = nm->getSkolemManager(); |
185 |
316 |
d_has_input_funcs = has_funcs; |
186 |
316 |
d_arg_types.insert(d_arg_types.end(), typs.begin(), typs.end()); |
187 |
316 |
d_input_funcs.insert(d_input_funcs.end(), funcs.begin(), funcs.end()); |
188 |
316 |
Trace("si-prt") << "Initialize..." << std::endl; |
189 |
971 |
for (unsigned j = 0; j < d_arg_types.size(); j++) |
190 |
|
{ |
191 |
1310 |
std::stringstream ss; |
192 |
655 |
ss << "s_" << j; |
193 |
1310 |
Node si_v = nm->mkBoundVar(ss.str(), d_arg_types[j]); |
194 |
655 |
d_si_vars.push_back(si_v); |
195 |
|
} |
196 |
316 |
Assert(d_si_vars.size() == d_arg_types.size()); |
197 |
901 |
for (const Node& inf : d_input_funcs) |
198 |
|
{ |
199 |
1170 |
Node sk = sm->mkDummySkolem("_sik", inf.getType()); |
200 |
585 |
d_input_func_sks.push_back(sk); |
201 |
|
} |
202 |
316 |
Trace("si-prt") << "SingleInvocationPartition::process " << n << std::endl; |
203 |
316 |
Trace("si-prt") << "Get conjuncts..." << std::endl; |
204 |
632 |
std::vector<Node> conj; |
205 |
316 |
if (collectConjuncts(n, true, conj)) |
206 |
|
{ |
207 |
313 |
Trace("si-prt") << "...success." << std::endl; |
208 |
1249 |
for (unsigned i = 0; i < conj.size(); i++) |
209 |
|
{ |
210 |
1872 |
std::vector<Node> si_terms; |
211 |
1872 |
std::vector<Node> si_subs; |
212 |
936 |
Trace("si-prt") << "Process conjunct : " << conj[i] << std::endl; |
213 |
|
// do DER on conjunct |
214 |
|
// Must avoid eliminating the first-order input functions in the |
215 |
|
// getQuantSimplify step below. We use a substitution to avoid this. |
216 |
|
// This makes it so that e.g. the synthesis conjecture: |
217 |
|
// exists f. f!=0 ^ P |
218 |
|
// is not rewritten to exists f. (f=0 => false) ^ P and subsquently |
219 |
|
// rewritten to exists f. false ^ P by the elimination f -> 0. |
220 |
936 |
Node cr = conj[i].substitute(d_input_funcs.begin(), |
221 |
|
d_input_funcs.end(), |
222 |
|
d_input_func_sks.begin(), |
223 |
1872 |
d_input_func_sks.end()); |
224 |
936 |
cr = TermUtil::getQuantSimplify(cr); |
225 |
936 |
cr = cr.substitute(d_input_func_sks.begin(), |
226 |
|
d_input_func_sks.end(), |
227 |
|
d_input_funcs.begin(), |
228 |
|
d_input_funcs.end()); |
229 |
936 |
if (cr != conj[i]) |
230 |
|
{ |
231 |
401 |
Trace("si-prt-debug") << "...rewritten to " << cr << std::endl; |
232 |
|
} |
233 |
1872 |
std::map<Node, bool> visited; |
234 |
|
// functions to arguments |
235 |
1872 |
std::vector<Node> args; |
236 |
1872 |
std::vector<Node> terms; |
237 |
1872 |
std::vector<Node> subs; |
238 |
936 |
bool singleInvocation = true; |
239 |
936 |
bool ngroundSingleInvocation = false; |
240 |
936 |
if (processConjunct(cr, visited, args, terms, subs)) |
241 |
|
{ |
242 |
1943 |
for (unsigned j = 0; j < terms.size(); j++) |
243 |
|
{ |
244 |
1072 |
si_terms.push_back(subs[j]); |
245 |
2144 |
Node op = subs[j].hasOperator() ? subs[j].getOperator() : subs[j]; |
246 |
1072 |
Assert(d_func_fo_var.find(op) != d_func_fo_var.end()); |
247 |
1072 |
si_subs.push_back(d_func_fo_var[op]); |
248 |
|
} |
249 |
1742 |
std::map<Node, Node> subs_map; |
250 |
1742 |
std::map<Node, Node> subs_map_rev; |
251 |
|
// normalize the invocations |
252 |
871 |
if (!terms.empty()) |
253 |
|
{ |
254 |
840 |
Assert(terms.size() == subs.size()); |
255 |
840 |
cr = cr.substitute( |
256 |
|
terms.begin(), terms.end(), subs.begin(), subs.end()); |
257 |
|
} |
258 |
1742 |
std::vector<Node> children; |
259 |
871 |
children.push_back(cr); |
260 |
871 |
terms.clear(); |
261 |
871 |
subs.clear(); |
262 |
1742 |
Trace("si-prt") << "...single invocation, with arguments: " |
263 |
871 |
<< std::endl; |
264 |
2621 |
for (unsigned j = 0; j < args.size(); j++) |
265 |
|
{ |
266 |
1750 |
Trace("si-prt") << args[j] << " "; |
267 |
3500 |
if (args[j].getKind() == BOUND_VARIABLE |
268 |
1750 |
&& std::find(terms.begin(), terms.end(), args[j]) == terms.end()) |
269 |
|
{ |
270 |
703 |
terms.push_back(args[j]); |
271 |
703 |
subs.push_back(d_si_vars[j]); |
272 |
|
} |
273 |
|
else |
274 |
|
{ |
275 |
1047 |
children.push_back(d_si_vars[j].eqNode(args[j]).negate()); |
276 |
|
} |
277 |
|
} |
278 |
871 |
Trace("si-prt") << std::endl; |
279 |
1742 |
cr = children.size() == 1 |
280 |
1742 |
? children[0] |
281 |
|
: NodeManager::currentNM()->mkNode(OR, children); |
282 |
871 |
Assert(terms.size() == subs.size()); |
283 |
871 |
cr = |
284 |
1742 |
cr.substitute(terms.begin(), terms.end(), subs.begin(), subs.end()); |
285 |
1742 |
Trace("si-prt-debug") << "...normalized invocations to " << cr |
286 |
871 |
<< std::endl; |
287 |
|
// now must check if it has other bound variables |
288 |
1742 |
std::unordered_set<Node> fvs; |
289 |
871 |
expr::getFreeVariables(cr, fvs); |
290 |
|
// bound variables must be contained in the single invocation variables |
291 |
3730 |
for (const Node& bv : fvs) |
292 |
|
{ |
293 |
8577 |
if (std::find(d_si_vars.begin(), d_si_vars.end(), bv) |
294 |
8577 |
== d_si_vars.end()) |
295 |
|
{ |
296 |
|
// getFreeVariables also collects functions in the rare case that |
297 |
|
// we are synthesizing a function with 0 arguments, take this into |
298 |
|
// account here. |
299 |
3327 |
if (std::find(d_input_funcs.begin(), d_input_funcs.end(), bv) |
300 |
3327 |
== d_input_funcs.end()) |
301 |
|
{ |
302 |
74 |
Trace("si-prt") |
303 |
37 |
<< "...not ground single invocation." << std::endl; |
304 |
37 |
ngroundSingleInvocation = true; |
305 |
37 |
singleInvocation = false; |
306 |
|
} |
307 |
|
} |
308 |
|
} |
309 |
871 |
if (singleInvocation) |
310 |
|
{ |
311 |
850 |
Trace("si-prt") << "...ground single invocation" << std::endl; |
312 |
|
} |
313 |
|
} |
314 |
|
else |
315 |
|
{ |
316 |
65 |
Trace("si-prt") << "...not single invocation." << std::endl; |
317 |
65 |
singleInvocation = false; |
318 |
|
// rename bound variables with maximal overlap with si_vars |
319 |
130 |
std::unordered_set<Node> fvs; |
320 |
65 |
expr::getFreeVariables(cr, fvs); |
321 |
130 |
std::vector<Node> termsNs; |
322 |
130 |
std::vector<Node> subsNs; |
323 |
397 |
for (const Node& v : fvs) |
324 |
|
{ |
325 |
664 |
TypeNode tn = v.getType(); |
326 |
664 |
Trace("si-prt-debug") |
327 |
332 |
<< "Fit bound var: " << v << " with si." << std::endl; |
328 |
1471 |
for (unsigned k = 0; k < d_si_vars.size(); k++) |
329 |
|
{ |
330 |
1321 |
if (tn == d_arg_types[k]) |
331 |
|
{ |
332 |
2508 |
if (std::find(subsNs.begin(), subsNs.end(), d_si_vars[k]) |
333 |
2508 |
== subsNs.end()) |
334 |
|
{ |
335 |
182 |
termsNs.push_back(v); |
336 |
182 |
subsNs.push_back(d_si_vars[k]); |
337 |
364 |
Trace("si-prt-debug") << " ...use " << d_si_vars[k] |
338 |
182 |
<< std::endl; |
339 |
182 |
break; |
340 |
|
} |
341 |
|
} |
342 |
|
} |
343 |
|
} |
344 |
65 |
Assert(termsNs.size() == subsNs.size()); |
345 |
65 |
cr = cr.substitute( |
346 |
|
termsNs.begin(), termsNs.end(), subsNs.begin(), subsNs.end()); |
347 |
|
} |
348 |
936 |
cr = Rewriter::rewrite(cr); |
349 |
1872 |
Trace("si-prt") << ".....got si=" << singleInvocation |
350 |
936 |
<< ", result : " << cr << std::endl; |
351 |
936 |
d_conjuncts[2].push_back(cr); |
352 |
1872 |
std::unordered_set<Node> fvs; |
353 |
936 |
expr::getFreeVariables(cr, fvs); |
354 |
936 |
d_all_vars.insert(fvs.begin(), fvs.end()); |
355 |
936 |
if (singleInvocation) |
356 |
|
{ |
357 |
|
// replace with single invocation formulation |
358 |
850 |
Assert(si_terms.size() == si_subs.size()); |
359 |
850 |
cr = cr.substitute( |
360 |
|
si_terms.begin(), si_terms.end(), si_subs.begin(), si_subs.end()); |
361 |
850 |
cr = Rewriter::rewrite(cr); |
362 |
850 |
Trace("si-prt") << ".....si version=" << cr << std::endl; |
363 |
850 |
d_conjuncts[0].push_back(cr); |
364 |
|
} |
365 |
|
else |
366 |
|
{ |
367 |
86 |
d_conjuncts[1].push_back(cr); |
368 |
86 |
if (ngroundSingleInvocation) |
369 |
|
{ |
370 |
21 |
d_conjuncts[3].push_back(cr); |
371 |
|
} |
372 |
|
} |
373 |
|
} |
374 |
|
} |
375 |
|
else |
376 |
|
{ |
377 |
3 |
Trace("si-prt") << "...failed." << std::endl; |
378 |
3 |
return false; |
379 |
|
} |
380 |
313 |
return true; |
381 |
|
} |
382 |
|
|
383 |
1164 |
bool SingleInvocationPartition::collectConjuncts(Node n, |
384 |
|
bool pol, |
385 |
|
std::vector<Node>& conj) |
386 |
|
{ |
387 |
1164 |
if ((!pol && n.getKind() == OR) || (pol && n.getKind() == AND)) |
388 |
|
{ |
389 |
918 |
for (unsigned i = 0; i < n.getNumChildren(); i++) |
390 |
|
{ |
391 |
772 |
if (!collectConjuncts(n[i], pol, conj)) |
392 |
|
{ |
393 |
3 |
return false; |
394 |
|
} |
395 |
|
} |
396 |
|
} |
397 |
1015 |
else if (n.getKind() == NOT) |
398 |
|
{ |
399 |
76 |
return collectConjuncts(n[0], !pol, conj); |
400 |
|
} |
401 |
939 |
else if (n.getKind() == FORALL) |
402 |
|
{ |
403 |
3 |
return false; |
404 |
|
} |
405 |
|
else |
406 |
|
{ |
407 |
936 |
if (!pol) |
408 |
|
{ |
409 |
75 |
n = TermUtil::simpleNegate(n); |
410 |
|
} |
411 |
936 |
Trace("si-prt") << "Conjunct : " << n << std::endl; |
412 |
936 |
conj.push_back(n); |
413 |
|
} |
414 |
1082 |
return true; |
415 |
|
} |
416 |
|
|
417 |
16969 |
bool SingleInvocationPartition::processConjunct(Node n, |
418 |
|
std::map<Node, bool>& visited, |
419 |
|
std::vector<Node>& args, |
420 |
|
std::vector<Node>& terms, |
421 |
|
std::vector<Node>& subs) |
422 |
|
{ |
423 |
16969 |
std::map<Node, bool>::iterator it = visited.find(n); |
424 |
16969 |
if (it != visited.end()) |
425 |
|
{ |
426 |
6421 |
return true; |
427 |
|
} |
428 |
|
else |
429 |
|
{ |
430 |
10548 |
bool ret = true; |
431 |
26581 |
for (unsigned i = 0; i < n.getNumChildren(); i++) |
432 |
|
{ |
433 |
16033 |
if (!processConjunct(n[i], visited, args, terms, subs)) |
434 |
|
{ |
435 |
161 |
ret = false; |
436 |
|
} |
437 |
|
} |
438 |
10548 |
if (ret) |
439 |
|
{ |
440 |
20792 |
Node f; |
441 |
10396 |
bool success = false; |
442 |
10396 |
if (d_has_input_funcs) |
443 |
|
{ |
444 |
10396 |
f = n.hasOperator() ? n.getOperator() : n; |
445 |
31188 |
if (std::find(d_input_funcs.begin(), d_input_funcs.end(), f) |
446 |
31188 |
!= d_input_funcs.end()) |
447 |
|
{ |
448 |
1211 |
success = true; |
449 |
|
} |
450 |
|
} |
451 |
|
else |
452 |
|
{ |
453 |
|
if (n.getKind() == kind::APPLY_UF) |
454 |
|
{ |
455 |
|
f = n.getOperator(); |
456 |
|
success = true; |
457 |
|
} |
458 |
|
} |
459 |
10396 |
if (success) |
460 |
|
{ |
461 |
1211 |
if (std::find(terms.begin(), terms.end(), n) == terms.end()) |
462 |
|
{ |
463 |
|
// check if it matches the type requirement |
464 |
1211 |
if (isAntiSkolemizableType(f)) |
465 |
|
{ |
466 |
1203 |
if (args.empty()) |
467 |
|
{ |
468 |
|
// record arguments |
469 |
2870 |
for (unsigned i = 0; i < n.getNumChildren(); i++) |
470 |
|
{ |
471 |
1938 |
args.push_back(n[i]); |
472 |
|
} |
473 |
|
} |
474 |
|
else |
475 |
|
{ |
476 |
|
// arguments must be the same as those already recorded |
477 |
863 |
for (unsigned i = 0; i < n.getNumChildren(); i++) |
478 |
|
{ |
479 |
658 |
if (args[i] != n[i]) |
480 |
|
{ |
481 |
132 |
Trace("si-prt-debug") << "...bad invocation : " << n |
482 |
66 |
<< " at arg " << i << "." << std::endl; |
483 |
66 |
ret = false; |
484 |
66 |
break; |
485 |
|
} |
486 |
|
} |
487 |
|
} |
488 |
1203 |
if (ret) |
489 |
|
{ |
490 |
1137 |
terms.push_back(n); |
491 |
1137 |
subs.push_back(d_func_inv[f]); |
492 |
|
} |
493 |
|
} |
494 |
|
else |
495 |
|
{ |
496 |
16 |
Trace("si-prt-debug") << "... " << f << " is a bad operator." |
497 |
8 |
<< std::endl; |
498 |
8 |
ret = false; |
499 |
|
} |
500 |
|
} |
501 |
|
} |
502 |
|
} |
503 |
|
//} |
504 |
10548 |
visited[n] = ret; |
505 |
10548 |
return ret; |
506 |
|
} |
507 |
|
} |
508 |
|
|
509 |
1211 |
bool SingleInvocationPartition::isAntiSkolemizableType(Node f) |
510 |
|
{ |
511 |
1211 |
std::map<Node, bool>::iterator it = d_funcs.find(f); |
512 |
1211 |
if (it != d_funcs.end()) |
513 |
|
{ |
514 |
697 |
return it->second; |
515 |
|
} |
516 |
|
else |
517 |
|
{ |
518 |
1028 |
TypeNode tn = f.getType(); |
519 |
514 |
bool ret = false; |
520 |
1472 |
if (((tn.isFunction() && tn.getNumChildren() == d_arg_types.size() + 1) |
521 |
584 |
|| (d_arg_types.empty() && tn.getNumChildren() == 0))) |
522 |
|
{ |
523 |
506 |
ret = true; |
524 |
1012 |
std::vector<Node> children; |
525 |
506 |
children.push_back(f); |
526 |
|
// TODO: permutations of arguments |
527 |
1697 |
for (unsigned i = 0; i < d_arg_types.size(); i++) |
528 |
|
{ |
529 |
1191 |
children.push_back(d_si_vars[i]); |
530 |
1191 |
if (tn[i] != d_arg_types[i]) |
531 |
|
{ |
532 |
|
ret = false; |
533 |
|
break; |
534 |
|
} |
535 |
|
} |
536 |
506 |
if (ret) |
537 |
|
{ |
538 |
1012 |
Node t; |
539 |
506 |
if (children.size() > 1) |
540 |
|
{ |
541 |
444 |
t = NodeManager::currentNM()->mkNode(kind::APPLY_UF, children); |
542 |
|
} |
543 |
|
else |
544 |
|
{ |
545 |
62 |
t = children[0]; |
546 |
|
} |
547 |
506 |
d_func_inv[f] = t; |
548 |
1012 |
std::stringstream ss; |
549 |
506 |
ss << "F_" << f; |
550 |
1012 |
TypeNode rt; |
551 |
506 |
if (d_arg_types.empty()) |
552 |
|
{ |
553 |
62 |
rt = tn; |
554 |
|
} |
555 |
|
else |
556 |
|
{ |
557 |
444 |
rt = tn.getRangeType(); |
558 |
|
} |
559 |
1012 |
Node v = NodeManager::currentNM()->mkBoundVar(ss.str(), rt); |
560 |
506 |
d_func_fo_var[f] = v; |
561 |
506 |
d_fo_var_to_func[v] = f; |
562 |
506 |
d_func_vars.push_back(v); |
563 |
506 |
d_all_funcs.push_back(f); |
564 |
|
} |
565 |
|
} |
566 |
514 |
d_funcs[f] = ret; |
567 |
514 |
return ret; |
568 |
|
} |
569 |
|
} |
570 |
|
|
571 |
100 |
Node SingleInvocationPartition::getConjunct(int index) |
572 |
|
{ |
573 |
100 |
return d_conjuncts[index].empty() ? NodeManager::currentNM()->mkConst(true) |
574 |
100 |
: (d_conjuncts[index].size() == 1 |
575 |
61 |
? d_conjuncts[index][0] |
576 |
|
: NodeManager::currentNM()->mkNode( |
577 |
261 |
AND, d_conjuncts[index])); |
578 |
|
} |
579 |
|
|
580 |
313 |
void SingleInvocationPartition::debugPrint(const char* c) |
581 |
|
{ |
582 |
313 |
Trace(c) << "Single invocation variables : "; |
583 |
964 |
for (unsigned i = 0; i < d_si_vars.size(); i++) |
584 |
|
{ |
585 |
651 |
Trace(c) << d_si_vars[i] << " "; |
586 |
|
} |
587 |
313 |
Trace(c) << std::endl; |
588 |
313 |
Trace(c) << "Functions : " << std::endl; |
589 |
827 |
for (std::map<Node, bool>::iterator it = d_funcs.begin(); it != d_funcs.end(); |
590 |
|
++it) |
591 |
|
{ |
592 |
514 |
Trace(c) << " " << it->first << " : "; |
593 |
514 |
if (it->second) |
594 |
|
{ |
595 |
1012 |
Trace(c) << d_func_inv[it->first] << " " << d_func_fo_var[it->first] |
596 |
506 |
<< std::endl; |
597 |
|
} |
598 |
|
else |
599 |
|
{ |
600 |
8 |
Trace(c) << "not incorporated." << std::endl; |
601 |
|
} |
602 |
|
} |
603 |
1565 |
for (unsigned i = 0; i < 4; i++) |
604 |
|
{ |
605 |
2191 |
Trace(c) << (i == 0 ? "Single invocation" |
606 |
1565 |
: (i == 1 ? "Non-single invocation" |
607 |
626 |
: (i == 2 ? "All" |
608 |
|
: "Non-ground single invocation"))); |
609 |
1252 |
Trace(c) << " conjuncts: " << std::endl; |
610 |
3145 |
for (unsigned j = 0; j < d_conjuncts[i].size(); j++) |
611 |
|
{ |
612 |
1893 |
Trace(c) << " " << (j + 1) << " : " << d_conjuncts[i][j] << std::endl; |
613 |
|
} |
614 |
|
} |
615 |
313 |
Trace(c) << std::endl; |
616 |
313 |
} |
617 |
|
|
618 |
|
} // namespace quantifiers |
619 |
|
} // namespace theory |
620 |
28191 |
} // namespace cvc5 |