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 |
94 |
void SingleInvocationPartition::getFunctionVariables( |
80 |
|
std::vector<Node>& fvars) const |
81 |
|
{ |
82 |
94 |
fvars.insert(fvars.end(), d_func_vars.begin(), d_func_vars.end()); |
83 |
94 |
} |
84 |
|
|
85 |
314 |
void SingleInvocationPartition::getFunctions(std::vector<Node>& fs) const |
86 |
|
{ |
87 |
314 |
fs.insert(fs.end(), d_all_funcs.begin(), d_all_funcs.end()); |
88 |
314 |
} |
89 |
|
|
90 |
97 |
void SingleInvocationPartition::getSingleInvocationVariables( |
91 |
|
std::vector<Node>& sivars) const |
92 |
|
{ |
93 |
97 |
sivars.insert(sivars.end(), d_si_vars.begin(), d_si_vars.end()); |
94 |
97 |
} |
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 |
337 |
bool SingleInvocationPartition::init(std::vector<Node>& funcs, Node n) |
135 |
|
{ |
136 |
674 |
Trace("si-prt") << "Initialize with " << funcs.size() << " input functions (" |
137 |
337 |
<< funcs << ")..." << std::endl; |
138 |
674 |
std::vector<TypeNode> typs; |
139 |
337 |
if (!funcs.empty()) |
140 |
|
{ |
141 |
658 |
TypeNode tn0 = funcs[0].getType(); |
142 |
337 |
if (tn0.isFunction()) |
143 |
|
{ |
144 |
998 |
for (unsigned i = 0, nargs = tn0.getNumChildren() - 1; i < nargs; i++) |
145 |
|
{ |
146 |
724 |
typs.push_back(tn0[i]); |
147 |
|
} |
148 |
|
} |
149 |
610 |
for (unsigned i = 1, size = funcs.size(); i < size; i++) |
150 |
|
{ |
151 |
562 |
TypeNode tni = funcs[i].getType(); |
152 |
289 |
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 |
273 |
else if (tni.isFunction()) |
159 |
|
{ |
160 |
793 |
for (unsigned j = 0, nargs = tni.getNumChildren() - 1; j < nargs; j++) |
161 |
|
{ |
162 |
588 |
if (tni[j] != typs[j]) |
163 |
|
{ |
164 |
|
Trace("si-prt") << "...argument type mismatch" << std::endl; |
165 |
|
return false; |
166 |
|
} |
167 |
|
} |
168 |
|
} |
169 |
|
} |
170 |
|
} |
171 |
321 |
Trace("si-prt") << "#types = " << typs.size() << std::endl; |
172 |
321 |
return init(funcs, typs, n, true); |
173 |
|
} |
174 |
|
|
175 |
321 |
bool SingleInvocationPartition::init(std::vector<Node>& funcs, |
176 |
|
std::vector<TypeNode>& typs, |
177 |
|
Node n, |
178 |
|
bool has_funcs) |
179 |
|
{ |
180 |
321 |
Assert(d_arg_types.empty()); |
181 |
321 |
Assert(d_input_funcs.empty()); |
182 |
321 |
Assert(d_si_vars.empty()); |
183 |
321 |
NodeManager* nm = NodeManager::currentNM(); |
184 |
321 |
SkolemManager* sm = nm->getSkolemManager(); |
185 |
321 |
d_has_input_funcs = has_funcs; |
186 |
321 |
d_arg_types.insert(d_arg_types.end(), typs.begin(), typs.end()); |
187 |
321 |
d_input_funcs.insert(d_input_funcs.end(), funcs.begin(), funcs.end()); |
188 |
321 |
Trace("si-prt") << "Initialize..." << std::endl; |
189 |
1038 |
for (unsigned j = 0; j < d_arg_types.size(); j++) |
190 |
|
{ |
191 |
1434 |
std::stringstream ss; |
192 |
717 |
ss << "s_" << j; |
193 |
1434 |
Node si_v = nm->mkBoundVar(ss.str(), d_arg_types[j]); |
194 |
717 |
d_si_vars.push_back(si_v); |
195 |
|
} |
196 |
321 |
Assert(d_si_vars.size() == d_arg_types.size()); |
197 |
910 |
for (const Node& inf : d_input_funcs) |
198 |
|
{ |
199 |
1178 |
Node sk = sm->mkDummySkolem("_sik", inf.getType()); |
200 |
589 |
d_input_func_sks.push_back(sk); |
201 |
|
} |
202 |
321 |
Trace("si-prt") << "SingleInvocationPartition::process " << n << std::endl; |
203 |
321 |
Trace("si-prt") << "Get conjuncts..." << std::endl; |
204 |
642 |
std::vector<Node> conj; |
205 |
321 |
if (collectConjuncts(n, true, conj)) |
206 |
|
{ |
207 |
318 |
Trace("si-prt") << "...success." << std::endl; |
208 |
1262 |
for (unsigned i = 0; i < conj.size(); i++) |
209 |
|
{ |
210 |
1888 |
std::vector<Node> si_terms; |
211 |
1888 |
std::vector<Node> si_subs; |
212 |
944 |
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 |
944 |
Node cr = conj[i].substitute(d_input_funcs.begin(), |
221 |
|
d_input_funcs.end(), |
222 |
|
d_input_func_sks.begin(), |
223 |
1888 |
d_input_func_sks.end()); |
224 |
944 |
cr = TermUtil::getQuantSimplify(cr); |
225 |
944 |
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 |
944 |
if (cr != conj[i]) |
230 |
|
{ |
231 |
425 |
Trace("si-prt-debug") << "...rewritten to " << cr << std::endl; |
232 |
|
} |
233 |
1888 |
std::map<Node, bool> visited; |
234 |
|
// functions to arguments |
235 |
1888 |
std::vector<Node> args; |
236 |
1888 |
Subs sb; |
237 |
944 |
bool singleInvocation = true; |
238 |
944 |
bool ngroundSingleInvocation = false; |
239 |
944 |
if (processConjunct(cr, visited, args, sb)) |
240 |
|
{ |
241 |
1948 |
for (size_t j = 0, vsize = sb.d_vars.size(); j < vsize; j++) |
242 |
|
{ |
243 |
2152 |
Node s = sb.d_subs[j]; |
244 |
1076 |
si_terms.push_back(s); |
245 |
2152 |
Node op = s.hasOperator() ? s.getOperator() : s; |
246 |
1076 |
Assert(d_func_fo_var.find(op) != d_func_fo_var.end()); |
247 |
1076 |
si_subs.push_back(d_func_fo_var[op]); |
248 |
|
} |
249 |
1744 |
std::map<Node, Node> subs_map; |
250 |
1744 |
std::map<Node, Node> subs_map_rev; |
251 |
|
// normalize the invocations |
252 |
872 |
if (!sb.empty()) |
253 |
|
{ |
254 |
840 |
cr = sb.apply(cr); |
255 |
|
} |
256 |
1744 |
std::vector<Node> children; |
257 |
872 |
children.push_back(cr); |
258 |
872 |
sb.clear(); |
259 |
1744 |
Trace("si-prt") << "...single invocation, with arguments: " |
260 |
872 |
<< std::endl; |
261 |
2739 |
for (unsigned j = 0; j < args.size(); j++) |
262 |
|
{ |
263 |
1867 |
Trace("si-prt") << args[j] << " "; |
264 |
1867 |
if (args[j].getKind() == BOUND_VARIABLE && !sb.contains(args[j])) |
265 |
|
{ |
266 |
786 |
sb.add(args[j], d_si_vars[j]); |
267 |
|
} |
268 |
|
else |
269 |
|
{ |
270 |
1081 |
children.push_back(d_si_vars[j].eqNode(args[j]).negate()); |
271 |
|
} |
272 |
|
} |
273 |
872 |
Trace("si-prt") << std::endl; |
274 |
872 |
cr = nm->mkOr(children); |
275 |
872 |
cr = sb.apply(cr); |
276 |
1744 |
Trace("si-prt-debug") << "...normalized invocations to " << cr |
277 |
872 |
<< std::endl; |
278 |
|
// now must check if it has other bound variables |
279 |
1744 |
std::unordered_set<Node> fvs; |
280 |
872 |
expr::getFreeVariables(cr, fvs); |
281 |
|
// bound variables must be contained in the single invocation variables |
282 |
3854 |
for (const Node& bv : fvs) |
283 |
|
{ |
284 |
8946 |
if (std::find(d_si_vars.begin(), d_si_vars.end(), bv) |
285 |
8946 |
== d_si_vars.end()) |
286 |
|
{ |
287 |
|
// getFreeVariables also collects functions in the rare case that |
288 |
|
// we are synthesizing a function with 0 arguments, take this into |
289 |
|
// account here. |
290 |
3345 |
if (std::find(d_input_funcs.begin(), d_input_funcs.end(), bv) |
291 |
3345 |
== d_input_funcs.end()) |
292 |
|
{ |
293 |
78 |
Trace("si-prt") |
294 |
39 |
<< "...not ground single invocation." << std::endl; |
295 |
39 |
ngroundSingleInvocation = true; |
296 |
39 |
singleInvocation = false; |
297 |
|
} |
298 |
|
} |
299 |
|
} |
300 |
872 |
if (singleInvocation) |
301 |
|
{ |
302 |
849 |
Trace("si-prt") << "...ground single invocation" << std::endl; |
303 |
|
} |
304 |
|
} |
305 |
|
else |
306 |
|
{ |
307 |
72 |
Trace("si-prt") << "...not single invocation." << std::endl; |
308 |
72 |
singleInvocation = false; |
309 |
|
// rename bound variables with maximal overlap with si_vars |
310 |
144 |
std::unordered_set<Node> fvs; |
311 |
72 |
expr::getFreeVariables(cr, fvs); |
312 |
144 |
std::vector<Node> termsNs; |
313 |
144 |
std::vector<Node> subsNs; |
314 |
505 |
for (const Node& v : fvs) |
315 |
|
{ |
316 |
866 |
TypeNode tn = v.getType(); |
317 |
866 |
Trace("si-prt-debug") |
318 |
433 |
<< "Fit bound var: " << v << " with si." << std::endl; |
319 |
3131 |
for (unsigned k = 0; k < d_si_vars.size(); k++) |
320 |
|
{ |
321 |
2944 |
if (tn == d_arg_types[k]) |
322 |
|
{ |
323 |
5664 |
if (std::find(subsNs.begin(), subsNs.end(), d_si_vars[k]) |
324 |
5664 |
== subsNs.end()) |
325 |
|
{ |
326 |
246 |
termsNs.push_back(v); |
327 |
246 |
subsNs.push_back(d_si_vars[k]); |
328 |
492 |
Trace("si-prt-debug") << " ...use " << d_si_vars[k] |
329 |
246 |
<< std::endl; |
330 |
246 |
break; |
331 |
|
} |
332 |
|
} |
333 |
|
} |
334 |
|
} |
335 |
72 |
Assert(termsNs.size() == subsNs.size()); |
336 |
72 |
cr = cr.substitute( |
337 |
|
termsNs.begin(), termsNs.end(), subsNs.begin(), subsNs.end()); |
338 |
|
} |
339 |
944 |
cr = Rewriter::rewrite(cr); |
340 |
1888 |
Trace("si-prt") << ".....got si=" << singleInvocation |
341 |
944 |
<< ", result : " << cr << std::endl; |
342 |
944 |
d_conjuncts[2].push_back(cr); |
343 |
1888 |
std::unordered_set<Node> fvs; |
344 |
944 |
expr::getFreeVariables(cr, fvs); |
345 |
944 |
d_all_vars.insert(fvs.begin(), fvs.end()); |
346 |
944 |
if (singleInvocation) |
347 |
|
{ |
348 |
|
// replace with single invocation formulation |
349 |
849 |
Assert(si_terms.size() == si_subs.size()); |
350 |
849 |
cr = cr.substitute( |
351 |
|
si_terms.begin(), si_terms.end(), si_subs.begin(), si_subs.end()); |
352 |
849 |
cr = Rewriter::rewrite(cr); |
353 |
849 |
Trace("si-prt") << ".....si version=" << cr << std::endl; |
354 |
849 |
d_conjuncts[0].push_back(cr); |
355 |
|
} |
356 |
|
else |
357 |
|
{ |
358 |
95 |
d_conjuncts[1].push_back(cr); |
359 |
95 |
if (ngroundSingleInvocation) |
360 |
|
{ |
361 |
23 |
d_conjuncts[3].push_back(cr); |
362 |
|
} |
363 |
|
} |
364 |
|
} |
365 |
|
} |
366 |
|
else |
367 |
|
{ |
368 |
3 |
Trace("si-prt") << "...failed." << std::endl; |
369 |
3 |
return false; |
370 |
|
} |
371 |
318 |
return true; |
372 |
|
} |
373 |
|
|
374 |
1166 |
bool SingleInvocationPartition::collectConjuncts(Node n, |
375 |
|
bool pol, |
376 |
|
std::vector<Node>& conj) |
377 |
|
{ |
378 |
1166 |
if ((!pol && n.getKind() == OR) || (pol && n.getKind() == AND)) |
379 |
|
{ |
380 |
925 |
for (unsigned i = 0; i < n.getNumChildren(); i++) |
381 |
|
{ |
382 |
777 |
if (!collectConjuncts(n[i], pol, conj)) |
383 |
|
{ |
384 |
3 |
return false; |
385 |
|
} |
386 |
|
} |
387 |
|
} |
388 |
1015 |
else if (n.getKind() == NOT) |
389 |
|
{ |
390 |
68 |
return collectConjuncts(n[0], !pol, conj); |
391 |
|
} |
392 |
947 |
else if (n.getKind() == FORALL) |
393 |
|
{ |
394 |
3 |
return false; |
395 |
|
} |
396 |
|
else |
397 |
|
{ |
398 |
944 |
if (!pol) |
399 |
|
{ |
400 |
67 |
n = TermUtil::simpleNegate(n); |
401 |
|
} |
402 |
944 |
Trace("si-prt") << "Conjunct : " << n << std::endl; |
403 |
944 |
conj.push_back(n); |
404 |
|
} |
405 |
1092 |
return true; |
406 |
|
} |
407 |
|
|
408 |
18603 |
bool SingleInvocationPartition::processConjunct(Node n, |
409 |
|
std::map<Node, bool>& visited, |
410 |
|
std::vector<Node>& args, |
411 |
|
Subs& sb) |
412 |
|
{ |
413 |
18603 |
std::map<Node, bool>::iterator it = visited.find(n); |
414 |
18603 |
if (it != visited.end()) |
415 |
|
{ |
416 |
7458 |
return true; |
417 |
|
} |
418 |
|
else |
419 |
|
{ |
420 |
11145 |
bool ret = true; |
421 |
28804 |
for (unsigned i = 0; i < n.getNumChildren(); i++) |
422 |
|
{ |
423 |
17659 |
if (!processConjunct(n[i], visited, args, sb)) |
424 |
|
{ |
425 |
172 |
ret = false; |
426 |
|
} |
427 |
|
} |
428 |
11145 |
if (ret) |
429 |
|
{ |
430 |
21966 |
Node f; |
431 |
10983 |
bool success = false; |
432 |
10983 |
if (d_has_input_funcs) |
433 |
|
{ |
434 |
10983 |
f = n.hasOperator() ? n.getOperator() : n; |
435 |
32949 |
if (std::find(d_input_funcs.begin(), d_input_funcs.end(), f) |
436 |
32949 |
!= d_input_funcs.end()) |
437 |
|
{ |
438 |
|
// If n is an application of a function-to-synthesize f, or is |
439 |
|
// itself a function-to-synthesize, then n must be fully applied. |
440 |
|
// This catches cases where n is a function-to-synthesize that occurs |
441 |
|
// in a higher-order context. |
442 |
|
// If the type of n is functional, then it is not fully applied. |
443 |
1229 |
if (n.getType().isFunction()) |
444 |
|
{ |
445 |
2 |
ret = false; |
446 |
2 |
success = false; |
447 |
|
} |
448 |
|
else |
449 |
|
{ |
450 |
1227 |
success = true; |
451 |
|
} |
452 |
|
} |
453 |
|
} |
454 |
|
else |
455 |
|
{ |
456 |
|
if (n.getKind() == kind::APPLY_UF) |
457 |
|
{ |
458 |
|
f = n.getOperator(); |
459 |
|
success = true; |
460 |
|
} |
461 |
|
} |
462 |
10983 |
if (success) |
463 |
|
{ |
464 |
1227 |
Trace("si-prt-debug") << "Process " << n << std::endl; |
465 |
1227 |
if (!sb.contains(n)) |
466 |
|
{ |
467 |
|
// check if it matches the type requirement |
468 |
1227 |
if (isAntiSkolemizableType(f)) |
469 |
|
{ |
470 |
1219 |
if (args.empty()) |
471 |
|
{ |
472 |
|
// record arguments |
473 |
3057 |
for (unsigned i = 0; i < n.getNumChildren(); i++) |
474 |
|
{ |
475 |
2119 |
args.push_back(n[i]); |
476 |
|
} |
477 |
|
} |
478 |
|
else |
479 |
|
{ |
480 |
|
// arguments must be the same as those already recorded |
481 |
891 |
for (unsigned i = 0; i < n.getNumChildren(); i++) |
482 |
|
{ |
483 |
682 |
if (args[i] != n[i]) |
484 |
|
{ |
485 |
144 |
Trace("si-prt-debug") << "...bad invocation : " << n |
486 |
72 |
<< " at arg " << i << "." << std::endl; |
487 |
72 |
ret = false; |
488 |
72 |
break; |
489 |
|
} |
490 |
|
} |
491 |
|
} |
492 |
1219 |
if (ret) |
493 |
|
{ |
494 |
1147 |
sb.add(n, d_func_inv[f]); |
495 |
|
} |
496 |
|
} |
497 |
|
else |
498 |
|
{ |
499 |
16 |
Trace("si-prt-debug") << "... " << f << " is a bad operator." |
500 |
8 |
<< std::endl; |
501 |
8 |
ret = false; |
502 |
|
} |
503 |
|
} |
504 |
|
} |
505 |
|
} |
506 |
11145 |
visited[n] = ret; |
507 |
11145 |
return ret; |
508 |
|
} |
509 |
|
} |
510 |
|
|
511 |
1227 |
bool SingleInvocationPartition::isAntiSkolemizableType(Node f) |
512 |
|
{ |
513 |
1227 |
std::map<Node, bool>::iterator it = d_funcs.find(f); |
514 |
1227 |
if (it != d_funcs.end()) |
515 |
|
{ |
516 |
712 |
return it->second; |
517 |
|
} |
518 |
|
else |
519 |
|
{ |
520 |
1030 |
TypeNode tn = f.getType(); |
521 |
515 |
bool ret = false; |
522 |
1476 |
if (((tn.isFunction() && tn.getNumChildren() == d_arg_types.size() + 1) |
523 |
584 |
|| (d_arg_types.empty() && tn.getNumChildren() == 0))) |
524 |
|
{ |
525 |
507 |
ret = true; |
526 |
1014 |
std::vector<Node> children; |
527 |
507 |
children.push_back(f); |
528 |
|
// TODO: permutations of arguments |
529 |
1757 |
for (unsigned i = 0; i < d_arg_types.size(); i++) |
530 |
|
{ |
531 |
1250 |
children.push_back(d_si_vars[i]); |
532 |
1250 |
if (tn[i] != d_arg_types[i]) |
533 |
|
{ |
534 |
|
ret = false; |
535 |
|
break; |
536 |
|
} |
537 |
|
} |
538 |
507 |
if (ret) |
539 |
|
{ |
540 |
1014 |
Node t; |
541 |
507 |
if (children.size() > 1) |
542 |
|
{ |
543 |
446 |
t = NodeManager::currentNM()->mkNode(kind::APPLY_UF, children); |
544 |
|
} |
545 |
|
else |
546 |
|
{ |
547 |
61 |
t = children[0]; |
548 |
|
} |
549 |
507 |
d_func_inv[f] = t; |
550 |
1014 |
std::stringstream ss; |
551 |
507 |
ss << "F_" << f; |
552 |
1014 |
TypeNode rt; |
553 |
507 |
if (d_arg_types.empty()) |
554 |
|
{ |
555 |
61 |
rt = tn; |
556 |
|
} |
557 |
|
else |
558 |
|
{ |
559 |
446 |
rt = tn.getRangeType(); |
560 |
|
} |
561 |
1014 |
Node v = NodeManager::currentNM()->mkBoundVar(ss.str(), rt); |
562 |
507 |
d_func_fo_var[f] = v; |
563 |
507 |
d_fo_var_to_func[v] = f; |
564 |
507 |
d_func_vars.push_back(v); |
565 |
507 |
d_all_funcs.push_back(f); |
566 |
|
} |
567 |
|
} |
568 |
515 |
d_funcs[f] = ret; |
569 |
515 |
return ret; |
570 |
|
} |
571 |
|
} |
572 |
|
|
573 |
97 |
Node SingleInvocationPartition::getConjunct(int index) |
574 |
|
{ |
575 |
97 |
return d_conjuncts[index].empty() ? NodeManager::currentNM()->mkConst(true) |
576 |
97 |
: (d_conjuncts[index].size() == 1 |
577 |
62 |
? d_conjuncts[index][0] |
578 |
|
: NodeManager::currentNM()->mkNode( |
579 |
256 |
AND, d_conjuncts[index])); |
580 |
|
} |
581 |
|
|
582 |
318 |
void SingleInvocationPartition::debugPrint(const char* c) |
583 |
|
{ |
584 |
318 |
Trace(c) << "Single invocation variables : "; |
585 |
1031 |
for (unsigned i = 0; i < d_si_vars.size(); i++) |
586 |
|
{ |
587 |
713 |
Trace(c) << d_si_vars[i] << " "; |
588 |
|
} |
589 |
318 |
Trace(c) << std::endl; |
590 |
318 |
Trace(c) << "Functions : " << std::endl; |
591 |
833 |
for (std::map<Node, bool>::iterator it = d_funcs.begin(); it != d_funcs.end(); |
592 |
|
++it) |
593 |
|
{ |
594 |
515 |
Trace(c) << " " << it->first << " : "; |
595 |
515 |
if (it->second) |
596 |
|
{ |
597 |
1014 |
Trace(c) << d_func_inv[it->first] << " " << d_func_fo_var[it->first] |
598 |
507 |
<< std::endl; |
599 |
|
} |
600 |
|
else |
601 |
|
{ |
602 |
8 |
Trace(c) << "not incorporated." << std::endl; |
603 |
|
} |
604 |
|
} |
605 |
1590 |
for (unsigned i = 0; i < 4; i++) |
606 |
|
{ |
607 |
2226 |
Trace(c) << (i == 0 ? "Single invocation" |
608 |
1590 |
: (i == 1 ? "Non-single invocation" |
609 |
636 |
: (i == 2 ? "All" |
610 |
|
: "Non-ground single invocation"))); |
611 |
1272 |
Trace(c) << " conjuncts: " << std::endl; |
612 |
3183 |
for (unsigned j = 0; j < d_conjuncts[i].size(); j++) |
613 |
|
{ |
614 |
1911 |
Trace(c) << " " << (j + 1) << " : " << d_conjuncts[i][j] << std::endl; |
615 |
|
} |
616 |
|
} |
617 |
318 |
Trace(c) << std::endl; |
618 |
318 |
} |
619 |
|
|
620 |
|
} // namespace quantifiers |
621 |
|
} // namespace theory |
622 |
29499 |
} // namespace cvc5 |