1 |
|
/****************************************************************************** |
2 |
|
* Top contributors (to current version): |
3 |
|
* Andrew Reynolds, Tim King |
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 |
|
* Extended theory interface. |
14 |
|
* |
15 |
|
* This implements a generic module, used by theory solvers, for performing |
16 |
|
* "context-dependent simplification", as described in Reynolds et al |
17 |
|
* "Designing Theory Solvers with Extensions", FroCoS 2017. |
18 |
|
*/ |
19 |
|
|
20 |
|
#include "theory/ext_theory.h" |
21 |
|
|
22 |
|
#include "base/check.h" |
23 |
|
#include "smt/smt_statistics_registry.h" |
24 |
|
#include "theory/output_channel.h" |
25 |
|
#include "theory/quantifiers_engine.h" |
26 |
|
#include "theory/rewriter.h" |
27 |
|
#include "theory/substitutions.h" |
28 |
|
|
29 |
|
using namespace std; |
30 |
|
|
31 |
|
namespace cvc5 { |
32 |
|
namespace theory { |
33 |
|
|
34 |
|
const char* toString(ExtReducedId id) |
35 |
|
{ |
36 |
|
switch (id) |
37 |
|
{ |
38 |
|
case ExtReducedId::SR_CONST: return "SR_CONST"; |
39 |
|
case ExtReducedId::REDUCTION: return "REDUCTION"; |
40 |
|
case ExtReducedId::ARITH_SR_ZERO: return "ARITH_SR_ZERO"; |
41 |
|
case ExtReducedId::ARITH_SR_LINEAR: return "ARITH_SR_LINEAR"; |
42 |
|
case ExtReducedId::STRINGS_SR_CONST: return "STRINGS_SR_CONST"; |
43 |
|
case ExtReducedId::STRINGS_NEG_CTN_DEQ: return "STRINGS_NEG_CTN_DEQ"; |
44 |
|
case ExtReducedId::STRINGS_POS_CTN: return "STRINGS_POS_CTN"; |
45 |
|
case ExtReducedId::STRINGS_CTN_DECOMPOSE: return "STRINGS_CTN_DECOMPOSE"; |
46 |
|
case ExtReducedId::STRINGS_REGEXP_INTER: return "STRINGS_REGEXP_INTER"; |
47 |
|
case ExtReducedId::STRINGS_REGEXP_INTER_SUBSUME: |
48 |
|
return "STRINGS_REGEXP_INTER_SUBSUME"; |
49 |
|
case ExtReducedId::STRINGS_REGEXP_INCLUDE: return "STRINGS_REGEXP_INCLUDE"; |
50 |
|
case ExtReducedId::STRINGS_REGEXP_INCLUDE_NEG: |
51 |
|
return "STRINGS_REGEXP_INCLUDE_NEG"; |
52 |
|
default: return "?ExtReducedId?"; |
53 |
|
} |
54 |
|
} |
55 |
|
|
56 |
|
std::ostream& operator<<(std::ostream& out, ExtReducedId id) |
57 |
|
{ |
58 |
|
out << toString(id); |
59 |
|
return out; |
60 |
|
} |
61 |
|
|
62 |
|
bool ExtTheoryCallback::getCurrentSubstitution( |
63 |
|
int effort, |
64 |
|
const std::vector<Node>& vars, |
65 |
|
std::vector<Node>& subs, |
66 |
|
std::map<Node, std::vector<Node> >& exp) |
67 |
|
{ |
68 |
|
return false; |
69 |
|
} |
70 |
|
bool ExtTheoryCallback::isExtfReduced( |
71 |
|
int effort, Node n, Node on, std::vector<Node>& exp, ExtReducedId& id) |
72 |
|
{ |
73 |
|
id = ExtReducedId::SR_CONST; |
74 |
|
return n.isConst(); |
75 |
|
} |
76 |
|
bool ExtTheoryCallback::getReduction(int effort, |
77 |
|
Node n, |
78 |
|
Node& nr, |
79 |
|
bool& isSatDep) |
80 |
|
{ |
81 |
|
return false; |
82 |
|
} |
83 |
|
|
84 |
24968 |
ExtTheory::ExtTheory(Env& env, ExtTheoryCallback& p, TheoryInferenceManager& im) |
85 |
|
: EnvObj(env), |
86 |
|
d_parent(p), |
87 |
|
d_im(im), |
88 |
|
d_ext_func_terms(context()), |
89 |
|
d_extfExtReducedIdMap(context()), |
90 |
24968 |
d_ci_inactive(userContext()), |
91 |
|
d_has_extf(context()), |
92 |
24968 |
d_lemmas(userContext()), |
93 |
74904 |
d_pp_lemmas(userContext()) |
94 |
|
{ |
95 |
24968 |
d_true = NodeManager::currentNM()->mkConst(true); |
96 |
24968 |
} |
97 |
|
|
98 |
|
// Gets all leaf terms in n. |
99 |
18835 |
std::vector<Node> ExtTheory::collectVars(Node n) |
100 |
|
{ |
101 |
18835 |
std::vector<Node> vars; |
102 |
37670 |
std::set<Node> visited; |
103 |
37670 |
std::vector<Node> worklist; |
104 |
18835 |
worklist.push_back(n); |
105 |
252429 |
while (!worklist.empty()) |
106 |
|
{ |
107 |
195249 |
Node current = worklist.back(); |
108 |
116797 |
worklist.pop_back(); |
109 |
116797 |
if (current.isConst() || visited.count(current) > 0) |
110 |
|
{ |
111 |
38345 |
continue; |
112 |
|
} |
113 |
78452 |
visited.insert(current); |
114 |
|
// Treat terms not belonging to this theory as leaf |
115 |
|
// note : chould include terms not belonging to this theory |
116 |
|
// (commented below) |
117 |
78452 |
if (current.getNumChildren() > 0) |
118 |
|
{ |
119 |
50183 |
worklist.insert(worklist.end(), current.begin(), current.end()); |
120 |
|
} |
121 |
|
else |
122 |
|
{ |
123 |
28269 |
vars.push_back(current); |
124 |
|
} |
125 |
|
} |
126 |
37670 |
return vars; |
127 |
|
} |
128 |
|
|
129 |
|
Node ExtTheory::getSubstitutedTerm(int effort, |
130 |
|
Node term, |
131 |
|
std::vector<Node>& exp) |
132 |
|
{ |
133 |
|
std::vector<Node> terms; |
134 |
|
terms.push_back(term); |
135 |
|
std::vector<Node> sterms; |
136 |
|
std::vector<std::vector<Node> > exps; |
137 |
|
getSubstitutedTerms(effort, terms, sterms, exps); |
138 |
|
Assert(sterms.size() == 1); |
139 |
|
Assert(exps.size() == 1); |
140 |
|
exp.insert(exp.end(), exps[0].begin(), exps[0].end()); |
141 |
|
return sterms[0]; |
142 |
|
} |
143 |
|
|
144 |
|
// do inferences |
145 |
41956 |
void ExtTheory::getSubstitutedTerms(int effort, |
146 |
|
const std::vector<Node>& terms, |
147 |
|
std::vector<Node>& sterms, |
148 |
|
std::vector<std::vector<Node> >& exp) |
149 |
|
{ |
150 |
83912 |
Trace("extt-debug") << "getSubstitutedTerms for " << terms.size() << " / " |
151 |
83912 |
<< d_ext_func_terms.size() << " extended functions." |
152 |
41956 |
<< std::endl; |
153 |
41956 |
if (!terms.empty()) |
154 |
|
{ |
155 |
|
// all variables we need to find a substitution for |
156 |
9892 |
std::vector<Node> vars; |
157 |
9892 |
std::vector<Node> sub; |
158 |
9892 |
std::map<Node, std::vector<Node> > expc; |
159 |
41542 |
for (const Node& n : terms) |
160 |
|
{ |
161 |
|
// do substitution, rewrite |
162 |
36596 |
std::map<Node, ExtfInfo>::iterator iti = d_extf_info.find(n); |
163 |
36596 |
Assert(iti != d_extf_info.end()); |
164 |
97714 |
for (const Node& v : iti->second.d_vars) |
165 |
|
{ |
166 |
61118 |
if (std::find(vars.begin(), vars.end(), v) == vars.end()) |
167 |
|
{ |
168 |
26874 |
vars.push_back(v); |
169 |
|
} |
170 |
|
} |
171 |
|
} |
172 |
4946 |
bool useSubs = d_parent.getCurrentSubstitution(effort, vars, sub, expc); |
173 |
|
// get the current substitution for all variables |
174 |
4946 |
Assert(!useSubs || vars.size() == sub.size()); |
175 |
41542 |
for (const Node& n : terms) |
176 |
|
{ |
177 |
73192 |
Node ns = n; |
178 |
73192 |
std::vector<Node> expn; |
179 |
36596 |
if (useSubs) |
180 |
|
{ |
181 |
|
// do substitution |
182 |
23173 |
ns = n.substitute(vars.begin(), vars.end(), sub.begin(), sub.end()); |
183 |
23173 |
if (ns != n) |
184 |
|
{ |
185 |
|
// build explanation: explanation vars = sub for each vars in FV(n) |
186 |
6691 |
std::map<Node, ExtfInfo>::iterator iti = d_extf_info.find(n); |
187 |
6691 |
Assert(iti != d_extf_info.end()); |
188 |
19168 |
for (const Node& v : iti->second.d_vars) |
189 |
|
{ |
190 |
12477 |
std::map<Node, std::vector<Node> >::iterator itx = expc.find(v); |
191 |
12477 |
if (itx != expc.end()) |
192 |
|
{ |
193 |
14812 |
for (const Node& e : itx->second) |
194 |
|
{ |
195 |
7406 |
if (std::find(expn.begin(), expn.end(), e) == expn.end()) |
196 |
|
{ |
197 |
7406 |
expn.push_back(e); |
198 |
|
} |
199 |
|
} |
200 |
|
} |
201 |
|
} |
202 |
|
} |
203 |
46346 |
Trace("extt-debug") << " have " << n << " == " << ns |
204 |
23173 |
<< ", exp size=" << expn.size() << "." << std::endl; |
205 |
|
} |
206 |
|
// add to vector |
207 |
36596 |
sterms.push_back(ns); |
208 |
36596 |
exp.push_back(expn); |
209 |
|
} |
210 |
|
} |
211 |
41956 |
} |
212 |
|
|
213 |
41956 |
bool ExtTheory::doInferencesInternal(int effort, |
214 |
|
const std::vector<Node>& terms, |
215 |
|
std::vector<Node>& nred, |
216 |
|
bool batch, |
217 |
|
bool isRed) |
218 |
|
{ |
219 |
41956 |
if (batch) |
220 |
|
{ |
221 |
41956 |
bool addedLemma = false; |
222 |
41956 |
if (isRed) |
223 |
|
{ |
224 |
|
for (const Node& n : terms) |
225 |
|
{ |
226 |
|
Node nr; |
227 |
|
// note: could do reduction with substitution here |
228 |
|
bool satDep = false; |
229 |
|
if (!d_parent.getReduction(effort, n, nr, satDep)) |
230 |
|
{ |
231 |
|
nred.push_back(n); |
232 |
|
} |
233 |
|
else |
234 |
|
{ |
235 |
|
if (!nr.isNull() && n != nr) |
236 |
|
{ |
237 |
|
Node lem = NodeManager::currentNM()->mkNode(kind::EQUAL, n, nr); |
238 |
|
if (sendLemma(lem, InferenceId::EXTT_SIMPLIFY, true)) |
239 |
|
{ |
240 |
|
Trace("extt-lemma") |
241 |
|
<< "ExtTheory : reduction lemma : " << lem << std::endl; |
242 |
|
addedLemma = true; |
243 |
|
} |
244 |
|
} |
245 |
|
markReduced(n, ExtReducedId::REDUCTION, satDep); |
246 |
|
} |
247 |
|
} |
248 |
|
} |
249 |
|
else |
250 |
|
{ |
251 |
83912 |
std::vector<Node> sterms; |
252 |
83912 |
std::vector<std::vector<Node> > exp; |
253 |
41956 |
getSubstitutedTerms(effort, terms, sterms, exp); |
254 |
83912 |
std::map<Node, unsigned> sterm_index; |
255 |
41956 |
NodeManager* nm = NodeManager::currentNM(); |
256 |
78552 |
for (unsigned i = 0, size = terms.size(); i < size; i++) |
257 |
|
{ |
258 |
36596 |
bool processed = false; |
259 |
36596 |
if (sterms[i] != terms[i]) |
260 |
|
{ |
261 |
13382 |
Node sr = rewrite(sterms[i]); |
262 |
|
// ask the theory if this term is reduced, e.g. is it constant or it |
263 |
|
// is a non-extf term. |
264 |
|
ExtReducedId id; |
265 |
6691 |
if (d_parent.isExtfReduced(effort, sr, terms[i], exp[i], id)) |
266 |
|
{ |
267 |
5665 |
processed = true; |
268 |
5665 |
markReduced(terms[i], id); |
269 |
|
// We have exp[i] => terms[i] = sr, convert this to a clause. |
270 |
|
// This ensures the proof infrastructure can process this as a |
271 |
|
// normal theory lemma. |
272 |
11330 |
Node eq = terms[i].eqNode(sr); |
273 |
11330 |
Node lem = eq; |
274 |
5665 |
if (!exp[i].empty()) |
275 |
|
{ |
276 |
11330 |
std::vector<Node> eei; |
277 |
11719 |
for (const Node& e : exp[i]) |
278 |
|
{ |
279 |
6054 |
eei.push_back(e.negate()); |
280 |
|
} |
281 |
5665 |
eei.push_back(eq); |
282 |
5665 |
lem = nm->mkNode(kind::OR, eei); |
283 |
|
} |
284 |
|
|
285 |
11330 |
Trace("extt-debug") << "ExtTheory::doInferences : infer : " << eq |
286 |
5665 |
<< " by " << exp[i] << std::endl; |
287 |
5665 |
Trace("extt-debug") << "...send lemma " << lem << std::endl; |
288 |
5665 |
if (sendLemma(lem, InferenceId::EXTT_SIMPLIFY)) |
289 |
|
{ |
290 |
3188 |
Trace("extt-lemma") |
291 |
1594 |
<< "ExtTheory : substitution + rewrite lemma : " << lem |
292 |
1594 |
<< std::endl; |
293 |
1594 |
addedLemma = true; |
294 |
|
} |
295 |
|
} |
296 |
|
else |
297 |
|
{ |
298 |
|
// check if we have already reduced this |
299 |
1026 |
std::map<Node, unsigned>::iterator itsi = sterm_index.find(sr); |
300 |
1026 |
if (itsi == sterm_index.end()) |
301 |
|
{ |
302 |
782 |
sterm_index[sr] = i; |
303 |
|
} |
304 |
|
else |
305 |
|
{ |
306 |
|
// unsigned j = itsi->second; |
307 |
|
// note : can add (non-reducing) lemma : |
308 |
|
// exp[j] ^ exp[i] => sterms[i] = sterms[j] |
309 |
|
} |
310 |
|
|
311 |
1026 |
Trace("extt-nred") << "Non-reduced term : " << sr << std::endl; |
312 |
|
} |
313 |
|
} |
314 |
|
else |
315 |
|
{ |
316 |
29905 |
Trace("extt-nred") << "Non-reduced term : " << sterms[i] << std::endl; |
317 |
|
} |
318 |
36596 |
if (!processed) |
319 |
|
{ |
320 |
30931 |
nred.push_back(terms[i]); |
321 |
|
} |
322 |
|
} |
323 |
|
} |
324 |
41956 |
return addedLemma; |
325 |
|
} |
326 |
|
// non-batch |
327 |
|
std::vector<Node> nnred; |
328 |
|
if (terms.empty()) |
329 |
|
{ |
330 |
|
for (NodeBoolMap::iterator it = d_ext_func_terms.begin(); |
331 |
|
it != d_ext_func_terms.end(); |
332 |
|
++it) |
333 |
|
{ |
334 |
|
if ((*it).second && !isContextIndependentInactive((*it).first)) |
335 |
|
{ |
336 |
|
std::vector<Node> nterms; |
337 |
|
nterms.push_back((*it).first); |
338 |
|
if (doInferencesInternal(effort, nterms, nnred, true, isRed)) |
339 |
|
{ |
340 |
|
return true; |
341 |
|
} |
342 |
|
} |
343 |
|
} |
344 |
|
} |
345 |
|
else |
346 |
|
{ |
347 |
|
for (const Node& n : terms) |
348 |
|
{ |
349 |
|
std::vector<Node> nterms; |
350 |
|
nterms.push_back(n); |
351 |
|
if (doInferencesInternal(effort, nterms, nnred, true, isRed)) |
352 |
|
{ |
353 |
|
return true; |
354 |
|
} |
355 |
|
} |
356 |
|
} |
357 |
|
return false; |
358 |
|
} |
359 |
|
|
360 |
5665 |
bool ExtTheory::sendLemma(Node lem, InferenceId id, bool preprocess) |
361 |
|
{ |
362 |
5665 |
if (preprocess) |
363 |
|
{ |
364 |
|
if (d_pp_lemmas.find(lem) == d_pp_lemmas.end()) |
365 |
|
{ |
366 |
|
d_pp_lemmas.insert(lem); |
367 |
|
d_im.lemma(lem, id); |
368 |
|
return true; |
369 |
|
} |
370 |
|
} |
371 |
|
else |
372 |
|
{ |
373 |
5665 |
if (d_lemmas.find(lem) == d_lemmas.end()) |
374 |
|
{ |
375 |
1594 |
d_lemmas.insert(lem); |
376 |
1594 |
d_im.lemma(lem, id); |
377 |
1594 |
return true; |
378 |
|
} |
379 |
|
} |
380 |
4071 |
return false; |
381 |
|
} |
382 |
|
|
383 |
|
bool ExtTheory::doInferences(int effort, |
384 |
|
const std::vector<Node>& terms, |
385 |
|
std::vector<Node>& nred, |
386 |
|
bool batch) |
387 |
|
{ |
388 |
|
if (!terms.empty()) |
389 |
|
{ |
390 |
|
return doInferencesInternal(effort, terms, nred, batch, false); |
391 |
|
} |
392 |
|
return false; |
393 |
|
} |
394 |
|
|
395 |
41956 |
bool ExtTheory::doInferences(int effort, std::vector<Node>& nred, bool batch) |
396 |
|
{ |
397 |
83912 |
std::vector<Node> terms = getActive(); |
398 |
83912 |
return doInferencesInternal(effort, terms, nred, batch, false); |
399 |
|
} |
400 |
|
|
401 |
|
bool ExtTheory::doReductions(int effort, |
402 |
|
const std::vector<Node>& terms, |
403 |
|
std::vector<Node>& nred, |
404 |
|
bool batch) |
405 |
|
{ |
406 |
|
if (!terms.empty()) |
407 |
|
{ |
408 |
|
return doInferencesInternal(effort, terms, nred, batch, true); |
409 |
|
} |
410 |
|
return false; |
411 |
|
} |
412 |
|
|
413 |
|
bool ExtTheory::doReductions(int effort, std::vector<Node>& nred, bool batch) |
414 |
|
{ |
415 |
|
const std::vector<Node> terms = getActive(); |
416 |
|
return doInferencesInternal(effort, terms, nred, batch, true); |
417 |
|
} |
418 |
|
|
419 |
|
// Register term. |
420 |
791798 |
void ExtTheory::registerTerm(Node n) |
421 |
|
{ |
422 |
791798 |
if (d_extf_kind.find(n.getKind()) != d_extf_kind.end()) |
423 |
|
{ |
424 |
174244 |
if (d_ext_func_terms.find(n) == d_ext_func_terms.end()) |
425 |
|
{ |
426 |
18835 |
Trace("extt-debug") << "Found extended function : " << n << std::endl; |
427 |
18835 |
d_ext_func_terms[n] = true; |
428 |
18835 |
d_has_extf = n; |
429 |
18835 |
d_extf_info[n].d_vars = collectVars(n); |
430 |
|
} |
431 |
|
} |
432 |
791798 |
} |
433 |
|
|
434 |
|
// mark reduced |
435 |
155409 |
void ExtTheory::markReduced(Node n, ExtReducedId rid, bool satDep) |
436 |
|
{ |
437 |
155409 |
Trace("extt-debug") << "Mark reduced " << n << std::endl; |
438 |
155409 |
registerTerm(n); |
439 |
155409 |
Assert(d_ext_func_terms.find(n) != d_ext_func_terms.end()); |
440 |
155409 |
d_ext_func_terms[n] = false; |
441 |
155409 |
d_extfExtReducedIdMap[n] = rid; |
442 |
155409 |
if (!satDep) |
443 |
|
{ |
444 |
|
d_ci_inactive[n] = rid; |
445 |
|
} |
446 |
|
|
447 |
|
// update has_extf |
448 |
155409 |
if (d_has_extf.get() == n) |
449 |
|
{ |
450 |
227894 |
for (NodeBoolMap::iterator it = d_ext_func_terms.begin(); |
451 |
227894 |
it != d_ext_func_terms.end(); |
452 |
|
++it) |
453 |
|
{ |
454 |
|
// if not already reduced |
455 |
218977 |
if ((*it).second && !isContextIndependentInactive((*it).first)) |
456 |
|
{ |
457 |
80595 |
d_has_extf = (*it).first; |
458 |
|
} |
459 |
|
} |
460 |
|
} |
461 |
155409 |
} |
462 |
|
|
463 |
931659 |
bool ExtTheory::isContextIndependentInactive(Node n) const |
464 |
|
{ |
465 |
931659 |
ExtReducedId rid = ExtReducedId::UNKNOWN; |
466 |
931659 |
return isContextIndependentInactive(n, rid); |
467 |
|
} |
468 |
|
|
469 |
1336051 |
bool ExtTheory::isContextIndependentInactive(Node n, ExtReducedId& rid) const |
470 |
|
{ |
471 |
1336051 |
NodeExtReducedIdMap::iterator it = d_ci_inactive.find(n); |
472 |
1336051 |
if (it != d_ci_inactive.end()) |
473 |
|
{ |
474 |
|
rid = it->second; |
475 |
|
return true; |
476 |
|
} |
477 |
1336051 |
return false; |
478 |
|
} |
479 |
|
|
480 |
4881 |
void ExtTheory::getTerms(std::vector<Node>& terms) |
481 |
|
{ |
482 |
42325 |
for (NodeBoolMap::iterator it = d_ext_func_terms.begin(); |
483 |
42325 |
it != d_ext_func_terms.end(); |
484 |
|
++it) |
485 |
|
{ |
486 |
37444 |
terms.push_back((*it).first); |
487 |
|
} |
488 |
4881 |
} |
489 |
|
|
490 |
|
bool ExtTheory::hasActiveTerm() const { return !d_has_extf.get().isNull(); } |
491 |
|
|
492 |
404392 |
bool ExtTheory::isActive(Node n) const |
493 |
|
{ |
494 |
404392 |
ExtReducedId rid = ExtReducedId::UNKNOWN; |
495 |
404392 |
return isActive(n, rid); |
496 |
|
} |
497 |
|
|
498 |
404392 |
bool ExtTheory::isActive(Node n, ExtReducedId& rid) const |
499 |
|
{ |
500 |
404392 |
NodeBoolMap::const_iterator it = d_ext_func_terms.find(n); |
501 |
404392 |
if (it != d_ext_func_terms.end()) |
502 |
|
{ |
503 |
404392 |
if ((*it).second) |
504 |
|
{ |
505 |
404392 |
return !isContextIndependentInactive(n, rid); |
506 |
|
} |
507 |
|
NodeExtReducedIdMap::const_iterator itr = d_extfExtReducedIdMap.find(n); |
508 |
|
Assert(itr != d_extfExtReducedIdMap.end()); |
509 |
|
rid = itr->second; |
510 |
|
return false; |
511 |
|
} |
512 |
|
return false; |
513 |
|
} |
514 |
|
|
515 |
|
// get active |
516 |
127230 |
std::vector<Node> ExtTheory::getActive() const |
517 |
|
{ |
518 |
127230 |
std::vector<Node> active; |
519 |
1423149 |
for (NodeBoolMap::iterator it = d_ext_func_terms.begin(); |
520 |
1423149 |
it != d_ext_func_terms.end(); |
521 |
|
++it) |
522 |
|
{ |
523 |
|
// if not already reduced |
524 |
1295919 |
if ((*it).second && !isContextIndependentInactive((*it).first)) |
525 |
|
{ |
526 |
849529 |
active.push_back((*it).first); |
527 |
|
} |
528 |
|
} |
529 |
127230 |
return active; |
530 |
|
} |
531 |
|
|
532 |
10650 |
std::vector<Node> ExtTheory::getActive(Kind k) const |
533 |
|
{ |
534 |
10650 |
std::vector<Node> active; |
535 |
38317 |
for (NodeBoolMap::iterator it = d_ext_func_terms.begin(); |
536 |
38317 |
it != d_ext_func_terms.end(); |
537 |
|
++it) |
538 |
|
{ |
539 |
|
// if not already reduced |
540 |
62986 |
if ((*it).first.getKind() == k && (*it).second |
541 |
56869 |
&& !isContextIndependentInactive((*it).first)) |
542 |
|
{ |
543 |
1535 |
active.push_back((*it).first); |
544 |
|
} |
545 |
|
} |
546 |
10650 |
return active; |
547 |
|
} |
548 |
|
|
549 |
|
} // namespace theory |
550 |
31137 |
} // namespace cvc5 |