1 |
|
/****************************************************************************** |
2 |
|
* Top contributors (to current version): |
3 |
|
* Andrew Reynolds, Andres Noetzli, 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 term database sygus class. |
14 |
|
*/ |
15 |
|
|
16 |
|
#include "theory/quantifiers/sygus/term_database_sygus.h" |
17 |
|
|
18 |
|
#include <sstream> |
19 |
|
|
20 |
|
#include "base/check.h" |
21 |
|
#include "expr/dtype_cons.h" |
22 |
|
#include "expr/skolem_manager.h" |
23 |
|
#include "expr/sygus_datatype.h" |
24 |
|
#include "options/base_options.h" |
25 |
|
#include "options/datatypes_options.h" |
26 |
|
#include "options/quantifiers_options.h" |
27 |
|
#include "printer/printer.h" |
28 |
|
#include "theory/datatypes/sygus_datatype_utils.h" |
29 |
|
#include "theory/quantifiers/quantifiers_attributes.h" |
30 |
|
#include "theory/quantifiers/quantifiers_inference_manager.h" |
31 |
|
#include "theory/quantifiers/quantifiers_state.h" |
32 |
|
#include "theory/quantifiers/term_util.h" |
33 |
|
#include "theory/rewriter.h" |
34 |
|
|
35 |
|
using namespace cvc5::kind; |
36 |
|
|
37 |
|
namespace cvc5 { |
38 |
|
namespace theory { |
39 |
|
namespace quantifiers { |
40 |
|
|
41 |
|
std::ostream& operator<<(std::ostream& os, EnumeratorRole r) |
42 |
|
{ |
43 |
|
switch (r) |
44 |
|
{ |
45 |
|
case ROLE_ENUM_POOL: os << "POOL"; break; |
46 |
|
case ROLE_ENUM_SINGLE_SOLUTION: os << "SINGLE_SOLUTION"; break; |
47 |
|
case ROLE_ENUM_MULTI_SOLUTION: os << "MULTI_SOLUTION"; break; |
48 |
|
case ROLE_ENUM_CONSTRAINED: os << "CONSTRAINED"; break; |
49 |
|
default: os << "enum_" << static_cast<unsigned>(r); break; |
50 |
|
} |
51 |
|
return os; |
52 |
|
} |
53 |
|
|
54 |
1228 |
TermDbSygus::TermDbSygus(Env& env, QuantifiersState& qs) |
55 |
|
: EnvObj(env), |
56 |
|
d_qstate(qs), |
57 |
1228 |
d_syexp(new SygusExplain(this)), |
58 |
1228 |
d_eval(new Evaluator), |
59 |
1228 |
d_funDefEval(new FunDefEvaluator), |
60 |
4912 |
d_eval_unfold(new SygusEvalUnfold(this)) |
61 |
|
{ |
62 |
1228 |
d_true = NodeManager::currentNM()->mkConst( true ); |
63 |
1228 |
d_false = NodeManager::currentNM()->mkConst( false ); |
64 |
1228 |
} |
65 |
|
|
66 |
1228 |
void TermDbSygus::finishInit(QuantifiersInferenceManager* qim) { d_qim = qim; } |
67 |
|
|
68 |
|
bool TermDbSygus::reset( Theory::Effort e ) { |
69 |
|
return true; |
70 |
|
} |
71 |
|
|
72 |
135959 |
TNode TermDbSygus::getFreeVar( TypeNode tn, int i, bool useSygusType ) { |
73 |
135959 |
unsigned sindex = 0; |
74 |
271918 |
TypeNode vtn = tn; |
75 |
271918 |
TypeNode builtinType = tn; |
76 |
135959 |
if (tn.isDatatype()) |
77 |
|
{ |
78 |
133267 |
const DType& dt = tn.getDType(); |
79 |
133267 |
if (!dt.getSygusType().isNull()) |
80 |
|
{ |
81 |
133267 |
builtinType = dt.getSygusType(); |
82 |
133267 |
if (useSygusType) |
83 |
|
{ |
84 |
15450 |
vtn = builtinType; |
85 |
15450 |
sindex = 1; |
86 |
|
} |
87 |
|
} |
88 |
|
} |
89 |
135959 |
NodeManager* nm = NodeManager::currentNM(); |
90 |
149803 |
while( i>=(int)d_fv[sindex][tn].size() ){ |
91 |
13844 |
std::stringstream ss; |
92 |
6922 |
if( tn.isDatatype() ){ |
93 |
4119 |
const DType& dt = tn.getDType(); |
94 |
4119 |
ss << "fv_" << dt.getName() << "_" << i; |
95 |
|
}else{ |
96 |
2803 |
ss << "fv_" << tn << "_" << i; |
97 |
|
} |
98 |
6922 |
Assert(!vtn.isNull()); |
99 |
13844 |
Node v = nm->mkBoundVar(ss.str(), vtn); |
100 |
|
// store its id, which is unique per builtin type, regardless of how it is |
101 |
|
// otherwise cached. |
102 |
6922 |
d_fvId[v] = d_fvTypeIdCounter[builtinType]; |
103 |
6922 |
d_fvTypeIdCounter[builtinType]++; |
104 |
13844 |
Trace("sygus-db-debug") << "Free variable id " << v << " = " << d_fvId[v] |
105 |
6922 |
<< ", " << builtinType << std::endl; |
106 |
6922 |
d_fv[sindex][tn].push_back( v ); |
107 |
|
} |
108 |
271918 |
return d_fv[sindex][tn][i]; |
109 |
|
} |
110 |
|
|
111 |
73840 |
TNode TermDbSygus::getFreeVarInc( TypeNode tn, std::map< TypeNode, int >& var_count, bool useSygusType ) { |
112 |
73840 |
std::map< TypeNode, int >::iterator it = var_count.find( tn ); |
113 |
73840 |
if( it==var_count.end() ){ |
114 |
29463 |
var_count[tn] = 1; |
115 |
29463 |
return getFreeVar( tn, 0, useSygusType ); |
116 |
|
}else{ |
117 |
44377 |
int index = it->second; |
118 |
44377 |
var_count[tn]++; |
119 |
44377 |
return getFreeVar( tn, index, useSygusType ); |
120 |
|
} |
121 |
|
} |
122 |
|
|
123 |
2529 |
bool TermDbSygus::isFreeVar(Node n) const |
124 |
|
{ |
125 |
2529 |
return d_fvId.find(n) != d_fvId.end(); |
126 |
|
} |
127 |
2517 |
size_t TermDbSygus::getFreeVarId(Node n) const |
128 |
|
{ |
129 |
2517 |
std::map<Node, size_t>::const_iterator it = d_fvId.find(n); |
130 |
2517 |
if (it == d_fvId.end()) |
131 |
|
{ |
132 |
|
Assert(false) << "TermDbSygus::isFreeVar: " << n |
133 |
|
<< " is not a cached free variable."; |
134 |
|
return 0; |
135 |
|
} |
136 |
2517 |
return it->second; |
137 |
|
} |
138 |
|
|
139 |
12 |
bool TermDbSygus::hasFreeVar( Node n, std::map< Node, bool >& visited ){ |
140 |
12 |
if( visited.find( n )==visited.end() ){ |
141 |
12 |
visited[n] = true; |
142 |
12 |
if( isFreeVar( n ) ){ |
143 |
10 |
return true; |
144 |
|
} |
145 |
2 |
for( unsigned i=0; i<n.getNumChildren(); i++ ){ |
146 |
|
if( hasFreeVar( n[i], visited ) ){ |
147 |
|
return true; |
148 |
|
} |
149 |
|
} |
150 |
|
} |
151 |
2 |
return false; |
152 |
|
} |
153 |
|
|
154 |
12 |
bool TermDbSygus::hasFreeVar( Node n ) { |
155 |
24 |
std::map< Node, bool > visited; |
156 |
24 |
return hasFreeVar( n, visited ); |
157 |
|
} |
158 |
|
|
159 |
21 |
Node TermDbSygus::getProxyVariable(TypeNode tn, Node c) |
160 |
|
{ |
161 |
21 |
Assert(tn.isDatatype()); |
162 |
21 |
Assert(tn.getDType().isSygus()); |
163 |
21 |
Assert(tn.getDType().getSygusType().isComparableTo(c.getType())); |
164 |
|
|
165 |
21 |
std::map<Node, Node>::iterator it = d_proxy_vars[tn].find(c); |
166 |
21 |
if (it == d_proxy_vars[tn].end()) |
167 |
|
{ |
168 |
16 |
SygusTypeInfo& ti = getTypeInfo(tn); |
169 |
16 |
int anyC = ti.getAnyConstantConsNum(); |
170 |
16 |
NodeManager* nm = NodeManager::currentNM(); |
171 |
32 |
Node k; |
172 |
16 |
if (anyC == -1) |
173 |
|
{ |
174 |
|
SkolemManager* sm = nm->getSkolemManager(); |
175 |
|
k = sm->mkDummySkolem("sy", tn, "sygus proxy"); |
176 |
|
SygusPrintProxyAttribute spa; |
177 |
|
k.setAttribute(spa, c); |
178 |
|
} |
179 |
|
else |
180 |
|
{ |
181 |
16 |
const DType& dt = tn.getDType(); |
182 |
16 |
k = nm->mkNode(APPLY_CONSTRUCTOR, dt[anyC].getConstructor(), c); |
183 |
|
} |
184 |
16 |
d_proxy_vars[tn][c] = k; |
185 |
16 |
return k; |
186 |
|
} |
187 |
5 |
return it->second; |
188 |
|
} |
189 |
|
|
190 |
390437 |
Node TermDbSygus::mkGeneric(const DType& dt, |
191 |
|
unsigned c, |
192 |
|
std::map<TypeNode, int>& var_count, |
193 |
|
std::map<int, Node>& pre, |
194 |
|
bool doBetaRed) |
195 |
|
{ |
196 |
390437 |
Assert(c < dt.getNumConstructors()); |
197 |
390437 |
Assert(dt.isSygus()); |
198 |
390437 |
Assert(!dt[c].getSygusOp().isNull()); |
199 |
780874 |
std::vector< Node > children; |
200 |
780874 |
Trace("sygus-db-debug") << "mkGeneric " << dt.getName() << " " << c << "..." |
201 |
390437 |
<< std::endl; |
202 |
868908 |
for (unsigned i = 0, nargs = dt[c].getNumArgs(); i < nargs; i++) |
203 |
|
{ |
204 |
956942 |
Node a; |
205 |
478471 |
std::map< int, Node >::iterator it = pre.find( i ); |
206 |
478471 |
if( it!=pre.end() ){ |
207 |
464097 |
a = it->second; |
208 |
464097 |
Trace("sygus-db-debug") << "From pre: " << a << std::endl; |
209 |
|
}else{ |
210 |
28748 |
TypeNode tna = dt[c].getArgType(i); |
211 |
14374 |
a = getFreeVarInc( tna, var_count, true ); |
212 |
|
} |
213 |
956942 |
Trace("sygus-db-debug") |
214 |
478471 |
<< " child " << i << " : " << a << " : " << a.getType() << std::endl; |
215 |
478471 |
Assert(!a.isNull()); |
216 |
478471 |
children.push_back( a ); |
217 |
|
} |
218 |
390437 |
Node ret = datatypes::utils::mkSygusTerm(dt, c, children, doBetaRed); |
219 |
390437 |
Trace("sygus-db-debug") << "mkGeneric returns " << ret << std::endl; |
220 |
780874 |
return ret; |
221 |
|
} |
222 |
|
|
223 |
390437 |
Node TermDbSygus::mkGeneric(const DType& dt, |
224 |
|
int c, |
225 |
|
std::map<int, Node>& pre, |
226 |
|
bool doBetaRed) |
227 |
|
{ |
228 |
780874 |
std::map<TypeNode, int> var_count; |
229 |
780874 |
return mkGeneric(dt, c, var_count, pre, doBetaRed); |
230 |
|
} |
231 |
|
|
232 |
10915 |
Node TermDbSygus::mkGeneric(const DType& dt, int c, bool doBetaRed) |
233 |
|
{ |
234 |
21830 |
std::map<int, Node> pre; |
235 |
21830 |
return mkGeneric(dt, c, pre, doBetaRed); |
236 |
|
} |
237 |
|
|
238 |
|
struct CanonizeBuiltinAttributeId |
239 |
|
{ |
240 |
|
}; |
241 |
|
using CanonizeBuiltinAttribute = |
242 |
|
expr::Attribute<CanonizeBuiltinAttributeId, Node>; |
243 |
|
|
244 |
|
Node TermDbSygus::canonizeBuiltin(Node n) |
245 |
|
{ |
246 |
|
std::map<TypeNode, int> var_count; |
247 |
|
return canonizeBuiltin(n, var_count); |
248 |
|
} |
249 |
|
|
250 |
37375 |
Node TermDbSygus::canonizeBuiltin(Node n, std::map<TypeNode, int>& var_count) |
251 |
|
{ |
252 |
|
// has it already been computed? |
253 |
37375 |
if (var_count.empty() && n.hasAttribute(CanonizeBuiltinAttribute())) |
254 |
|
{ |
255 |
59688 |
Node ret = n.getAttribute(CanonizeBuiltinAttribute()); |
256 |
29844 |
Trace("sygus-db-canon") << "cached " << n << " : " << ret << "\n"; |
257 |
29844 |
return ret; |
258 |
|
} |
259 |
7531 |
Trace("sygus-db-canon") << " CanonizeBuiltin : compute for " << n << "\n"; |
260 |
15062 |
Node ret = n; |
261 |
|
// it is symbolic if it represents "any constant" |
262 |
7531 |
if (n.getKind() == APPLY_SELECTOR_TOTAL) |
263 |
|
{ |
264 |
1120 |
ret = getFreeVarInc(n[0].getType(), var_count, true); |
265 |
|
} |
266 |
6411 |
else if (n.getKind() != APPLY_CONSTRUCTOR) |
267 |
|
{ |
268 |
|
ret = n; |
269 |
|
} |
270 |
|
else |
271 |
|
{ |
272 |
6411 |
Assert(n.getKind() == APPLY_CONSTRUCTOR); |
273 |
6411 |
bool childChanged = false; |
274 |
12822 |
std::vector<Node> children; |
275 |
6411 |
children.push_back(n.getOperator()); |
276 |
16130 |
for (unsigned j = 0, size = n.getNumChildren(); j < size; ++j) |
277 |
|
{ |
278 |
19438 |
Node child = canonizeBuiltin(n[j], var_count); |
279 |
9719 |
children.push_back(child); |
280 |
9719 |
childChanged = childChanged || child != n[j]; |
281 |
|
} |
282 |
6411 |
if (childChanged) |
283 |
|
{ |
284 |
1637 |
ret = NodeManager::currentNM()->mkNode(APPLY_CONSTRUCTOR, children); |
285 |
|
} |
286 |
|
} |
287 |
|
// cache if we had a fresh variable count |
288 |
7531 |
if (var_count.empty()) |
289 |
|
{ |
290 |
4646 |
n.setAttribute(CanonizeBuiltinAttribute(), ret); |
291 |
|
} |
292 |
15062 |
Trace("sygus-db-canon") << " ...normalized " << n << " --> " << ret |
293 |
7531 |
<< std::endl; |
294 |
7531 |
Assert(ret.getType().isComparableTo(n.getType())); |
295 |
7531 |
return ret; |
296 |
|
} |
297 |
|
|
298 |
|
struct SygusToBuiltinAttributeId |
299 |
|
{ |
300 |
|
}; |
301 |
|
typedef expr::Attribute<SygusToBuiltinAttributeId, Node> |
302 |
|
SygusToBuiltinAttribute; |
303 |
|
|
304 |
38700 |
Node TermDbSygus::sygusToBuiltin(Node n, TypeNode tn) |
305 |
|
{ |
306 |
38700 |
if (n.isConst()) |
307 |
|
{ |
308 |
|
// if its a constant, we use the datatype utility version |
309 |
27545 |
return datatypes::utils::sygusToBuiltin(n); |
310 |
|
} |
311 |
11155 |
Assert(n.getType().isComparableTo(tn)); |
312 |
11155 |
if (!tn.isDatatype()) |
313 |
|
{ |
314 |
79 |
return n; |
315 |
|
} |
316 |
|
// has it already been computed? |
317 |
11076 |
if (n.hasAttribute(SygusToBuiltinAttribute())) |
318 |
|
{ |
319 |
4087 |
return n.getAttribute(SygusToBuiltinAttribute()); |
320 |
|
} |
321 |
13978 |
Trace("sygus-db-debug") << "SygusToBuiltin : compute for " << n |
322 |
6989 |
<< ", type = " << tn << std::endl; |
323 |
6989 |
const DType& dt = tn.getDType(); |
324 |
6989 |
if (!dt.isSygus()) |
325 |
|
{ |
326 |
|
return n; |
327 |
|
} |
328 |
6989 |
if (n.getKind() == APPLY_CONSTRUCTOR) |
329 |
|
{ |
330 |
4472 |
unsigned i = datatypes::utils::indexOf(n.getOperator()); |
331 |
4472 |
Assert(n.getNumChildren() == dt[i].getNumArgs()); |
332 |
8944 |
std::map<int, Node> pre; |
333 |
13703 |
for (unsigned j = 0, size = n.getNumChildren(); j < size; j++) |
334 |
|
{ |
335 |
9231 |
pre[j] = sygusToBuiltin(n[j], dt[i].getArgType(j)); |
336 |
18462 |
Trace("sygus-db-debug") |
337 |
9231 |
<< "sygus to builtin " << n[j] << " is " << pre[j] << std::endl; |
338 |
|
} |
339 |
8944 |
Node ret = mkGeneric(dt, i, pre); |
340 |
8944 |
Trace("sygus-db-debug") |
341 |
4472 |
<< "SygusToBuiltin : Generic is " << ret << std::endl; |
342 |
|
// cache |
343 |
4472 |
n.setAttribute(SygusToBuiltinAttribute(), ret); |
344 |
4472 |
return ret; |
345 |
|
} |
346 |
2517 |
if (n.hasAttribute(SygusPrintProxyAttribute())) |
347 |
|
{ |
348 |
|
// this variable was associated by an attribute to a builtin node |
349 |
|
return n.getAttribute(SygusPrintProxyAttribute()); |
350 |
|
} |
351 |
2517 |
Assert(isFreeVar(n)); |
352 |
|
// map to builtin variable type |
353 |
2517 |
size_t fv_num = getFreeVarId(n); |
354 |
2517 |
Assert(!dt.getSygusType().isNull()); |
355 |
5034 |
TypeNode vtn = dt.getSygusType(); |
356 |
5034 |
Node ret = getFreeVar(vtn, fv_num); |
357 |
5034 |
Trace("sygus-db-debug") << "SygusToBuiltin: variable for " << n << " is " |
358 |
2517 |
<< ret << ", fv_num=" << fv_num << std::endl; |
359 |
2517 |
return ret; |
360 |
|
} |
361 |
|
|
362 |
13595 |
bool TermDbSygus::registerSygusType(TypeNode tn) |
363 |
|
{ |
364 |
13595 |
std::map<TypeNode, bool>::iterator it = d_registerStatus.find(tn); |
365 |
13595 |
if (it != d_registerStatus.end()) |
366 |
|
{ |
367 |
|
// already registered |
368 |
11724 |
return it->second; |
369 |
|
} |
370 |
1871 |
d_registerStatus[tn] = false; |
371 |
|
// it must be a sygus datatype |
372 |
1871 |
if (!tn.isDatatype()) |
373 |
|
{ |
374 |
36 |
return false; |
375 |
|
} |
376 |
1835 |
const DType& dt = tn.getDType(); |
377 |
1835 |
if (!dt.isSygus()) |
378 |
|
{ |
379 |
|
return false; |
380 |
|
} |
381 |
1835 |
d_registerStatus[tn] = true; |
382 |
1835 |
SygusTypeInfo& sti = d_tinfo[tn]; |
383 |
1835 |
sti.initialize(this, tn); |
384 |
1835 |
return true; |
385 |
|
} |
386 |
|
|
387 |
476 |
void TermDbSygus::registerEnumerator(Node e, |
388 |
|
Node f, |
389 |
|
SynthConjecture* conj, |
390 |
|
EnumeratorRole erole) |
391 |
|
{ |
392 |
476 |
if (d_enum_to_conjecture.find(e) != d_enum_to_conjecture.end()) |
393 |
|
{ |
394 |
|
// already registered |
395 |
|
return; |
396 |
|
} |
397 |
476 |
Trace("sygus-db") << "Register enumerator : " << e << std::endl; |
398 |
|
// register its type |
399 |
952 |
TypeNode et = e.getType(); |
400 |
476 |
registerSygusType(et); |
401 |
476 |
d_enum_to_conjecture[e] = conj; |
402 |
476 |
d_enum_to_synth_fun[e] = f; |
403 |
476 |
NodeManager* nm = NodeManager::currentNM(); |
404 |
|
|
405 |
952 |
Trace("sygus-db") << " registering symmetry breaking clauses..." |
406 |
476 |
<< std::endl; |
407 |
|
// depending on if we are using symbolic constructors, introduce symmetry |
408 |
|
// breaking lemma templates for each relevant subtype of the grammar |
409 |
476 |
SygusTypeInfo& eti = getTypeInfo(et); |
410 |
952 |
std::vector<TypeNode> sf_types; |
411 |
476 |
eti.getSubfieldTypes(sf_types); |
412 |
|
// for each type of subfield type of this enumerator |
413 |
1490 |
for (unsigned i = 0, ntypes = sf_types.size(); i < ntypes; i++) |
414 |
|
{ |
415 |
2028 |
std::vector<unsigned> rm_indices; |
416 |
2028 |
TypeNode stn = sf_types[i]; |
417 |
1014 |
Assert(stn.isDatatype()); |
418 |
1014 |
SygusTypeInfo& sti = getTypeInfo(stn); |
419 |
1014 |
const DType& dt = stn.getDType(); |
420 |
1014 |
int anyC = sti.getAnyConstantConsNum(); |
421 |
7348 |
for (unsigned j = 0, ncons = dt.getNumConstructors(); j < ncons; j++) |
422 |
|
{ |
423 |
6334 |
bool isAnyC = static_cast<int>(j) == anyC; |
424 |
6334 |
if (anyC != -1 && !isAnyC) |
425 |
|
{ |
426 |
|
// if we are using the any constant constructor, do not use any |
427 |
|
// concrete constant |
428 |
420 |
Node c_op = sti.getConsNumConst(j); |
429 |
210 |
if (!c_op.isNull()) |
430 |
|
{ |
431 |
43 |
rm_indices.push_back(j); |
432 |
|
} |
433 |
|
} |
434 |
|
} |
435 |
1057 |
for (unsigned& rindex : rm_indices) |
436 |
|
{ |
437 |
|
// make the apply-constructor corresponding to an application of the |
438 |
|
// constant or "any constant" constructor |
439 |
|
// we call getInstCons since in the case of any constant constructors, it |
440 |
|
// is necessary to generate a term of the form any_constant( x.0 ) for a |
441 |
|
// fresh variable x.0. |
442 |
86 |
Node fv = getFreeVar(stn, 0); |
443 |
86 |
Node exc_val = datatypes::utils::getInstCons(fv, dt, rindex); |
444 |
|
// should not include the constuctor in any subterm |
445 |
86 |
Node x = getFreeVar(stn, 0); |
446 |
86 |
Trace("sygus-db") << "Construct symmetry breaking lemma from " << x |
447 |
43 |
<< " == " << exc_val << std::endl; |
448 |
86 |
Node lem = getExplain()->getExplanationForEquality(x, exc_val); |
449 |
43 |
lem = lem.negate(); |
450 |
86 |
Trace("cegqi-lemma") |
451 |
43 |
<< "Cegqi::Lemma : exclude symbolic cons lemma (template) : " << lem |
452 |
43 |
<< std::endl; |
453 |
|
// the size of the subterm we are blocking is the weight of the |
454 |
|
// constructor (usually zero) |
455 |
43 |
registerSymBreakLemma(e, lem, stn, dt[rindex].getWeight()); |
456 |
|
} |
457 |
|
} |
458 |
476 |
Trace("sygus-db") << " ...finished" << std::endl; |
459 |
|
|
460 |
|
// determine if we are actively-generated |
461 |
476 |
bool isActiveGen = false; |
462 |
476 |
if (options::sygusActiveGenMode() != options::SygusActiveGenMode::NONE) |
463 |
|
{ |
464 |
472 |
if (erole == ROLE_ENUM_MULTI_SOLUTION || erole == ROLE_ENUM_CONSTRAINED) |
465 |
|
{ |
466 |
|
// If the enumerator is a solution for a conjecture with multiple |
467 |
|
// functions, we do not use active generation. If we did, we would have to |
468 |
|
// generate a "product" of two actively-generated enumerators. That is, |
469 |
|
// given a conjecture with two functions-to-synthesize with enumerators |
470 |
|
// e_f and e_g, and if these enumerators generated: |
471 |
|
// e_f -> t1, ..., tn |
472 |
|
// e_g -> s1, ..., sm |
473 |
|
// The sygus module in charge of this conjecture would expect |
474 |
|
// constructCandidates calls of the form |
475 |
|
// (e_f,e_g) -> (ti, sj) |
476 |
|
// for each i,j. We instead use passive enumeration in this case. |
477 |
|
// |
478 |
|
// If the enumerator is constrained, it cannot be actively generated. |
479 |
|
} |
480 |
212 |
else if (erole == ROLE_ENUM_POOL) |
481 |
|
{ |
482 |
|
// If the enumerator is used for generating a pool of values, we always |
483 |
|
// use active generation. |
484 |
61 |
isActiveGen = true; |
485 |
|
} |
486 |
151 |
else if (erole == ROLE_ENUM_SINGLE_SOLUTION) |
487 |
|
{ |
488 |
|
// If the enumerator is the single function-to-synthesize, if auto is |
489 |
|
// enabled, we infer whether it is better to enable active generation. |
490 |
151 |
if (options::sygusActiveGenMode() == options::SygusActiveGenMode::AUTO) |
491 |
|
{ |
492 |
|
// We use active generation if the grammar of the enumerator does not |
493 |
|
// have ITE and does not have Boolean connectives. Experimentally, it |
494 |
|
// is better to use passive generation for these cases since it enables |
495 |
|
// useful search space pruning techniques, e.g. evaluation unfolding, |
496 |
|
// conjecture-specific symmetry breaking. Also, if sygus-stream is |
497 |
|
// enabled, we always use active generation, since the use cases of |
498 |
|
// sygus stream are to find many solutions to an easy problem, where |
499 |
|
// the bottleneck often becomes the large number of "exclude the current |
500 |
|
// solution" clauses. |
501 |
284 |
if (options::sygusStream() |
502 |
142 |
|| (!eti.hasIte() && !eti.hasBoolConnective())) |
503 |
|
{ |
504 |
46 |
isActiveGen = true; |
505 |
|
} |
506 |
|
} |
507 |
|
else |
508 |
|
{ |
509 |
9 |
isActiveGen = true; |
510 |
|
} |
511 |
|
} |
512 |
|
else |
513 |
|
{ |
514 |
|
Unreachable() << "Unknown enumerator mode in registerEnumerator"; |
515 |
|
} |
516 |
|
} |
517 |
952 |
Trace("sygus-db") << "isActiveGen for " << e << ", role = " << erole |
518 |
476 |
<< " returned " << isActiveGen << std::endl; |
519 |
|
// Currently, actively-generated enumerators are either basic or variable |
520 |
|
// agnostic. |
521 |
|
bool isVarAgnostic = isActiveGen |
522 |
476 |
&& options::sygusActiveGenMode() |
523 |
476 |
== options::SygusActiveGenMode::VAR_AGNOSTIC; |
524 |
476 |
d_enum_var_agnostic[e] = isVarAgnostic; |
525 |
476 |
if (isVarAgnostic) |
526 |
|
{ |
527 |
|
// requires variable subclasses |
528 |
1 |
eti.initializeVarSubclasses(); |
529 |
|
// If no subclass has more than one variable, do not use variable agnostic |
530 |
|
// enumeration |
531 |
1 |
bool useVarAgnostic = !eti.isSubclassVarTrivial(); |
532 |
1 |
if (!useVarAgnostic) |
533 |
|
{ |
534 |
|
Trace("sygus-db") |
535 |
|
<< "...disabling variable agnostic for " << e |
536 |
|
<< " since it has no subclass with more than one variable." |
537 |
|
<< std::endl; |
538 |
|
d_enum_var_agnostic[e] = false; |
539 |
|
isActiveGen = false; |
540 |
|
} |
541 |
|
} |
542 |
476 |
d_enum_active_gen[e] = isActiveGen; |
543 |
476 |
d_enum_basic[e] = isActiveGen && !isVarAgnostic; |
544 |
|
|
545 |
|
// We make an active guard if we will be explicitly blocking solutions for |
546 |
|
// the enumerator. This is the case if the role of the enumerator is to |
547 |
|
// populate a pool of terms, or (some cases) of when it is actively generated. |
548 |
476 |
if (isActiveGen || erole == ROLE_ENUM_POOL) |
549 |
|
{ |
550 |
118 |
SkolemManager* sm = nm->getSkolemManager(); |
551 |
|
// make the guard |
552 |
236 |
Node ag = sm->mkDummySkolem("eG", nm->booleanType()); |
553 |
|
// must ensure it is a literal immediately here |
554 |
118 |
ag = d_qstate.getValuation().ensureLiteral(ag); |
555 |
|
// must ensure that it is asserted as a literal before we begin solving |
556 |
236 |
Node lem = nm->mkNode(OR, ag, ag.negate()); |
557 |
118 |
d_qim->requirePhase(ag, true); |
558 |
118 |
d_qim->lemma(lem, InferenceId::QUANTIFIERS_SYGUS_ENUM_ACTIVE_GUARD_SPLIT); |
559 |
118 |
d_enum_to_active_guard[e] = ag; |
560 |
|
} |
561 |
|
} |
562 |
|
|
563 |
46423 |
bool TermDbSygus::isEnumerator(Node e) const |
564 |
|
{ |
565 |
46423 |
return d_enum_to_conjecture.find(e) != d_enum_to_conjecture.end(); |
566 |
|
} |
567 |
|
|
568 |
446 |
SynthConjecture* TermDbSygus::getConjectureForEnumerator(Node e) const |
569 |
|
{ |
570 |
|
std::map<Node, SynthConjecture*>::const_iterator itm = |
571 |
446 |
d_enum_to_conjecture.find(e); |
572 |
446 |
if (itm != d_enum_to_conjecture.end()) { |
573 |
446 |
return itm->second; |
574 |
|
} |
575 |
|
return nullptr; |
576 |
|
} |
577 |
|
|
578 |
331 |
Node TermDbSygus::getSynthFunForEnumerator(Node e) const |
579 |
|
{ |
580 |
331 |
std::map<Node, Node>::const_iterator itsf = d_enum_to_synth_fun.find(e); |
581 |
331 |
if (itsf != d_enum_to_synth_fun.end()) |
582 |
|
{ |
583 |
305 |
return itsf->second; |
584 |
|
} |
585 |
26 |
return Node::null(); |
586 |
|
} |
587 |
|
|
588 |
44614 |
Node TermDbSygus::getActiveGuardForEnumerator(Node e) const |
589 |
|
{ |
590 |
44614 |
std::map<Node, Node>::const_iterator itag = d_enum_to_active_guard.find(e); |
591 |
44614 |
if (itag != d_enum_to_active_guard.end()) { |
592 |
35393 |
return itag->second; |
593 |
|
} |
594 |
9221 |
return Node::null(); |
595 |
|
} |
596 |
|
|
597 |
5712 |
bool TermDbSygus::usingSymbolicConsForEnumerator(Node e) const |
598 |
|
{ |
599 |
5712 |
std::map<Node, bool>::const_iterator itus = d_enum_to_using_sym_cons.find(e); |
600 |
5712 |
if (itus != d_enum_to_using_sym_cons.end()) |
601 |
|
{ |
602 |
|
return itus->second; |
603 |
|
} |
604 |
5712 |
return false; |
605 |
|
} |
606 |
|
|
607 |
15068 |
bool TermDbSygus::isVariableAgnosticEnumerator(Node e) const |
608 |
|
{ |
609 |
15068 |
std::map<Node, bool>::const_iterator itus = d_enum_var_agnostic.find(e); |
610 |
15068 |
if (itus != d_enum_var_agnostic.end()) |
611 |
|
{ |
612 |
15068 |
return itus->second; |
613 |
|
} |
614 |
|
return false; |
615 |
|
} |
616 |
|
|
617 |
265 |
bool TermDbSygus::isBasicEnumerator(Node e) const |
618 |
|
{ |
619 |
265 |
std::map<Node, bool>::const_iterator itus = d_enum_basic.find(e); |
620 |
265 |
if (itus != d_enum_basic.end()) |
621 |
|
{ |
622 |
265 |
return itus->second; |
623 |
|
} |
624 |
|
return false; |
625 |
|
} |
626 |
|
|
627 |
59189 |
bool TermDbSygus::isPassiveEnumerator(Node e) const |
628 |
|
{ |
629 |
59189 |
std::map<Node, bool>::const_iterator itus = d_enum_active_gen.find(e); |
630 |
59189 |
if (itus != d_enum_active_gen.end()) |
631 |
|
{ |
632 |
57906 |
return !itus->second; |
633 |
|
} |
634 |
1283 |
return true; |
635 |
|
} |
636 |
|
|
637 |
5517 |
void TermDbSygus::getEnumerators(std::vector<Node>& mts) |
638 |
|
{ |
639 |
9242 |
for (std::map<Node, SynthConjecture*>::iterator itm = |
640 |
5517 |
d_enum_to_conjecture.begin(); |
641 |
14759 |
itm != d_enum_to_conjecture.end(); |
642 |
|
++itm) |
643 |
|
{ |
644 |
9242 |
mts.push_back( itm->first ); |
645 |
|
} |
646 |
5517 |
} |
647 |
|
|
648 |
79 |
void TermDbSygus::registerSymBreakLemma( |
649 |
|
Node e, Node lem, TypeNode tn, unsigned sz, bool isTempl) |
650 |
|
{ |
651 |
79 |
d_enum_to_sb_lemmas[e].push_back(lem); |
652 |
79 |
d_sb_lemma_to_type[lem] = tn; |
653 |
79 |
d_sb_lemma_to_size[lem] = sz; |
654 |
79 |
d_sb_lemma_to_isTempl[lem] = isTempl; |
655 |
79 |
} |
656 |
|
|
657 |
5517 |
bool TermDbSygus::hasSymBreakLemmas(std::vector<Node>& enums) const |
658 |
|
{ |
659 |
5517 |
if (!d_enum_to_sb_lemmas.empty()) |
660 |
|
{ |
661 |
384 |
for (std::pair<const Node, std::vector<Node> > sb : d_enum_to_sb_lemmas) |
662 |
|
{ |
663 |
198 |
enums.push_back(sb.first); |
664 |
|
} |
665 |
186 |
return true; |
666 |
|
} |
667 |
5331 |
return false; |
668 |
|
} |
669 |
|
|
670 |
170 |
void TermDbSygus::getSymBreakLemmas(Node e, std::vector<Node>& lemmas) const |
671 |
|
{ |
672 |
|
std::map<Node, std::vector<Node> >::const_iterator itsb = |
673 |
170 |
d_enum_to_sb_lemmas.find(e); |
674 |
170 |
if (itsb != d_enum_to_sb_lemmas.end()) |
675 |
|
{ |
676 |
51 |
lemmas.insert(lemmas.end(), itsb->second.begin(), itsb->second.end()); |
677 |
|
} |
678 |
170 |
} |
679 |
|
|
680 |
9 |
TypeNode TermDbSygus::getTypeForSymBreakLemma(Node lem) const |
681 |
|
{ |
682 |
9 |
std::map<Node, TypeNode>::const_iterator it = d_sb_lemma_to_type.find(lem); |
683 |
9 |
Assert(it != d_sb_lemma_to_type.end()); |
684 |
9 |
return it->second; |
685 |
|
} |
686 |
9 |
unsigned TermDbSygus::getSizeForSymBreakLemma(Node lem) const |
687 |
|
{ |
688 |
9 |
std::map<Node, unsigned>::const_iterator it = d_sb_lemma_to_size.find(lem); |
689 |
9 |
Assert(it != d_sb_lemma_to_size.end()); |
690 |
9 |
return it->second; |
691 |
|
} |
692 |
|
|
693 |
79 |
bool TermDbSygus::isSymBreakLemmaTemplate(Node lem) const |
694 |
|
{ |
695 |
79 |
std::map<Node, bool>::const_iterator it = d_sb_lemma_to_isTempl.find(lem); |
696 |
79 |
Assert(it != d_sb_lemma_to_isTempl.end()); |
697 |
79 |
return it->second; |
698 |
|
} |
699 |
|
|
700 |
4 |
void TermDbSygus::clearSymBreakLemmas(Node e) { d_enum_to_sb_lemmas.erase(e); } |
701 |
|
|
702 |
119594 |
bool TermDbSygus::isRegistered(TypeNode tn) const |
703 |
|
{ |
704 |
119594 |
return d_tinfo.find(tn) != d_tinfo.end(); |
705 |
|
} |
706 |
|
|
707 |
6660 |
TypeNode TermDbSygus::sygusToBuiltinType( TypeNode tn ) { |
708 |
6660 |
std::map<TypeNode, SygusTypeInfo>::iterator it = d_tinfo.find(tn); |
709 |
6660 |
Assert(it != d_tinfo.end()); |
710 |
6660 |
return it->second.getBuiltinType(); |
711 |
|
} |
712 |
|
|
713 |
8402 |
void TermDbSygus::toStreamSygus(const char* c, Node n) |
714 |
|
{ |
715 |
8402 |
if (Trace.isOn(c)) |
716 |
|
{ |
717 |
|
std::stringstream ss; |
718 |
|
toStreamSygus(ss, n); |
719 |
|
Trace(c) << ss.str(); |
720 |
|
} |
721 |
8402 |
} |
722 |
|
|
723 |
210 |
void TermDbSygus::toStreamSygus(std::ostream& out, Node n) |
724 |
|
{ |
725 |
210 |
if (n.isNull()) |
726 |
|
{ |
727 |
|
out << n; |
728 |
|
return; |
729 |
|
} |
730 |
|
// use external conversion |
731 |
210 |
out << datatypes::utils::sygusToBuiltin(n, true); |
732 |
|
} |
733 |
|
|
734 |
169046 |
SygusTypeInfo& TermDbSygus::getTypeInfo(TypeNode tn) |
735 |
|
{ |
736 |
169046 |
AlwaysAssert(d_tinfo.find(tn) != d_tinfo.end()); |
737 |
169046 |
return d_tinfo[tn]; |
738 |
|
} |
739 |
|
|
740 |
176057 |
Node TermDbSygus::rewriteNode(Node n) const |
741 |
|
{ |
742 |
352114 |
Node res; |
743 |
176057 |
if (options().quantifiers.sygusExtRew) |
744 |
|
{ |
745 |
173961 |
res = extendedRewrite(n); |
746 |
|
} |
747 |
|
else |
748 |
|
{ |
749 |
2096 |
res = rewrite(n); |
750 |
|
} |
751 |
176057 |
if (res.isConst()) |
752 |
|
{ |
753 |
|
// constant, we are done |
754 |
126447 |
return res; |
755 |
|
} |
756 |
49610 |
if (options::sygusRecFun()) |
757 |
|
{ |
758 |
48776 |
if (d_funDefEval->hasDefinitions()) |
759 |
|
{ |
760 |
|
// If recursive functions are enabled, then we use the recursive function |
761 |
|
// evaluation utility. |
762 |
1345 |
Node fres = d_funDefEval->evaluate(res); |
763 |
975 |
if (!fres.isNull()) |
764 |
|
{ |
765 |
605 |
return fres; |
766 |
|
} |
767 |
|
// It may have failed, in which case there are undefined symbols in res or |
768 |
|
// we reached the limit of evaluations. In this case, we revert to the |
769 |
|
// result of rewriting in the return statement below. |
770 |
|
} |
771 |
|
} |
772 |
49005 |
return res; |
773 |
|
} |
774 |
|
|
775 |
1331 |
unsigned TermDbSygus::getSelectorWeight(TypeNode tn, Node sel) |
776 |
|
{ |
777 |
|
std::map<TypeNode, std::map<Node, unsigned> >::iterator itsw = |
778 |
1331 |
d_sel_weight.find(tn); |
779 |
1331 |
if (itsw == d_sel_weight.end()) |
780 |
|
{ |
781 |
203 |
d_sel_weight[tn].clear(); |
782 |
203 |
itsw = d_sel_weight.find(tn); |
783 |
203 |
const DType& dt = tn.getDType(); |
784 |
406 |
Trace("sygus-db") << "Compute selector weights for " << dt.getName() |
785 |
203 |
<< std::endl; |
786 |
1152 |
for (unsigned i = 0, size = dt.getNumConstructors(); i < size; i++) |
787 |
|
{ |
788 |
949 |
unsigned cw = dt[i].getWeight(); |
789 |
2109 |
for (unsigned j = 0, size2 = dt[i].getNumArgs(); j < size2; j++) |
790 |
|
{ |
791 |
2320 |
Node csel = dt[i].getSelectorInternal(tn, j); |
792 |
1160 |
std::map<Node, unsigned>::iterator its = itsw->second.find(csel); |
793 |
1160 |
if (its == itsw->second.end() || cw < its->second) |
794 |
|
{ |
795 |
724 |
d_sel_weight[tn][csel] = cw; |
796 |
724 |
Trace("sygus-db") << " w(" << csel << ") <= " << cw << std::endl; |
797 |
|
} |
798 |
|
} |
799 |
|
} |
800 |
|
} |
801 |
1331 |
Assert(itsw->second.find(sel) != itsw->second.end()); |
802 |
1331 |
return itsw->second[sel]; |
803 |
|
} |
804 |
|
|
805 |
449425 |
TypeNode TermDbSygus::getArgType(const DTypeConstructor& c, unsigned i) const |
806 |
|
{ |
807 |
449425 |
Assert(i < c.getNumArgs()); |
808 |
449425 |
return c.getArgType(i); |
809 |
|
} |
810 |
|
|
811 |
4 |
bool TermDbSygus::isTypeMatch(const DTypeConstructor& c1, |
812 |
|
const DTypeConstructor& c2) |
813 |
|
{ |
814 |
4 |
if( c1.getNumArgs()!=c2.getNumArgs() ){ |
815 |
|
return false; |
816 |
|
}else{ |
817 |
12 |
for( unsigned i=0; i<c1.getNumArgs(); i++ ){ |
818 |
8 |
if( getArgType( c1, i )!=getArgType( c2, i ) ){ |
819 |
|
return false; |
820 |
|
} |
821 |
|
} |
822 |
4 |
return true; |
823 |
|
} |
824 |
|
} |
825 |
|
|
826 |
|
bool TermDbSygus::isSymbolicConsApp(Node n) const |
827 |
|
{ |
828 |
|
if (n.getKind() != APPLY_CONSTRUCTOR) |
829 |
|
{ |
830 |
|
return false; |
831 |
|
} |
832 |
|
TypeNode tn = n.getType(); |
833 |
|
Assert(tn.isDatatype()); |
834 |
|
const DType& dt = tn.getDType(); |
835 |
|
Assert(dt.isSygus()); |
836 |
|
unsigned cindex = datatypes::utils::indexOf(n.getOperator()); |
837 |
|
Node sygusOp = dt[cindex].getSygusOp(); |
838 |
|
// it is symbolic if it represents "any constant" |
839 |
|
return sygusOp.getAttribute(SygusAnyConstAttribute()); |
840 |
|
} |
841 |
|
|
842 |
2084 |
bool TermDbSygus::canConstructKind(TypeNode tn, |
843 |
|
Kind k, |
844 |
|
std::vector<TypeNode>& argts, |
845 |
|
bool aggr) |
846 |
|
{ |
847 |
2084 |
Assert(isRegistered(tn)); |
848 |
2084 |
SygusTypeInfo& ti = getTypeInfo(tn); |
849 |
2084 |
int c = ti.getKindConsNum(k); |
850 |
2084 |
const DType& dt = tn.getDType(); |
851 |
2084 |
if (c != -1) |
852 |
|
{ |
853 |
5712 |
for (unsigned i = 0, nargs = dt[c].getNumArgs(); i < nargs; i++) |
854 |
|
{ |
855 |
3809 |
argts.push_back(dt[c].getArgType(i)); |
856 |
|
} |
857 |
1903 |
return true; |
858 |
|
} |
859 |
181 |
if (!options::sygusSymBreakAgg()) |
860 |
|
{ |
861 |
|
return false; |
862 |
|
} |
863 |
181 |
if (sygusToBuiltinType(tn).isBoolean()) |
864 |
|
{ |
865 |
178 |
if (k == ITE) |
866 |
|
{ |
867 |
|
// ite( b1, b2, b3 ) <---- and( or( ~b1, b2 ), or( b1, b3 ) ) |
868 |
160 |
std::vector<TypeNode> conj_types; |
869 |
142 |
if (canConstructKind(tn, AND, conj_types, true) && conj_types.size() == 2) |
870 |
|
{ |
871 |
130 |
bool success = true; |
872 |
390 |
std::vector<TypeNode> disj_types[2]; |
873 |
378 |
for (unsigned cc = 0; cc < 2; cc++) |
874 |
|
{ |
875 |
762 |
if (!canConstructKind(conj_types[cc], OR, disj_types[cc], true) |
876 |
762 |
|| disj_types[cc].size() != 2) |
877 |
|
{ |
878 |
6 |
success = false; |
879 |
6 |
break; |
880 |
|
} |
881 |
|
} |
882 |
130 |
if (success) |
883 |
|
{ |
884 |
124 |
for (unsigned r = 0; r < 2; r++) |
885 |
|
{ |
886 |
124 |
for (unsigned d = 0, size = disj_types[r].size(); d < size; d++) |
887 |
|
{ |
888 |
124 |
TypeNode dtn = disj_types[r][d]; |
889 |
|
// must have negation that occurs in the other conjunct |
890 |
124 |
std::vector<TypeNode> ntypes; |
891 |
124 |
if (canConstructKind(dtn, NOT, ntypes) && ntypes.size() == 1) |
892 |
|
{ |
893 |
124 |
TypeNode ntn = ntypes[0]; |
894 |
124 |
for (unsigned dd = 0, inner_size = disj_types[1 - r].size(); |
895 |
124 |
dd < inner_size; |
896 |
|
dd++) |
897 |
|
{ |
898 |
124 |
if (disj_types[1 - r][dd] == ntn) |
899 |
|
{ |
900 |
124 |
argts.push_back(ntn); |
901 |
124 |
argts.push_back(disj_types[r][d]); |
902 |
124 |
argts.push_back(disj_types[1 - r][1 - dd]); |
903 |
124 |
if (Trace.isOn("sygus-cons-kind")) |
904 |
|
{ |
905 |
|
Trace("sygus-cons-kind") |
906 |
|
<< "Can construct kind " << k << " in " << tn |
907 |
|
<< " via child types:" << std::endl; |
908 |
|
for (unsigned i = 0; i < 3; i++) |
909 |
|
{ |
910 |
|
Trace("sygus-cons-kind") |
911 |
|
<< " " << argts[i] << std::endl; |
912 |
|
} |
913 |
|
} |
914 |
124 |
return true; |
915 |
|
} |
916 |
|
} |
917 |
|
} |
918 |
|
} |
919 |
|
} |
920 |
|
} |
921 |
|
} |
922 |
|
} |
923 |
|
} |
924 |
|
// could try aggressive inferences here, such as |
925 |
|
// (and b1 b2) <---- (not (or (not b1) (not b2))) |
926 |
|
// (or b1 b2) <---- (not (and (not b1) (not b2))) |
927 |
57 |
return false; |
928 |
|
} |
929 |
|
|
930 |
17208 |
bool TermDbSygus::involvesDivByZero( Node n, std::map< Node, bool >& visited ){ |
931 |
17208 |
if( visited.find( n )==visited.end() ){ |
932 |
16071 |
visited[n] = true; |
933 |
16071 |
Kind k = n.getKind(); |
934 |
16071 |
if( k==DIVISION || k==DIVISION_TOTAL || k==INTS_DIVISION || k==INTS_DIVISION_TOTAL || |
935 |
16071 |
k==INTS_MODULUS || k==INTS_MODULUS_TOTAL ){ |
936 |
24 |
if( n[1].isConst() ){ |
937 |
12 |
if (n[1] == TermUtil::mkTypeValue(n[1].getType(), 0)) |
938 |
|
{ |
939 |
|
return true; |
940 |
|
} |
941 |
|
}else{ |
942 |
|
// if it has free variables it might be a non-zero constant |
943 |
12 |
if( !hasFreeVar( n[1] ) ){ |
944 |
2 |
return true; |
945 |
|
} |
946 |
|
} |
947 |
|
} |
948 |
28302 |
for( unsigned i=0; i<n.getNumChildren(); i++ ){ |
949 |
12235 |
if( involvesDivByZero( n[i], visited ) ){ |
950 |
2 |
return true; |
951 |
|
} |
952 |
|
} |
953 |
|
} |
954 |
17204 |
return false; |
955 |
|
} |
956 |
|
|
957 |
4973 |
bool TermDbSygus::involvesDivByZero( Node n ) { |
958 |
9946 |
std::map< Node, bool > visited; |
959 |
9946 |
return involvesDivByZero( n, visited ); |
960 |
|
} |
961 |
|
|
962 |
2275 |
Node TermDbSygus::getAnchor( Node n ) { |
963 |
2275 |
if( n.getKind()==APPLY_SELECTOR_TOTAL ){ |
964 |
1019 |
return getAnchor( n[0] ); |
965 |
|
}else{ |
966 |
1256 |
return n; |
967 |
|
} |
968 |
|
} |
969 |
|
|
970 |
|
unsigned TermDbSygus::getAnchorDepth( Node n ) { |
971 |
|
if( n.getKind()==APPLY_SELECTOR_TOTAL ){ |
972 |
|
return 1+getAnchorDepth( n[0] ); |
973 |
|
}else{ |
974 |
|
return 0; |
975 |
|
} |
976 |
|
} |
977 |
|
|
978 |
113694 |
Node TermDbSygus::evaluateBuiltin(TypeNode tn, |
979 |
|
Node bn, |
980 |
|
const std::vector<Node>& args, |
981 |
|
bool tryEval) |
982 |
|
{ |
983 |
113694 |
if (args.empty()) |
984 |
|
{ |
985 |
432 |
return Rewriter::rewrite( bn ); |
986 |
|
} |
987 |
113262 |
Assert(isRegistered(tn)); |
988 |
113262 |
SygusTypeInfo& ti = getTypeInfo(tn); |
989 |
113262 |
const std::vector<Node>& varlist = ti.getVarList(); |
990 |
113262 |
Assert(varlist.size() == args.size()); |
991 |
|
|
992 |
226524 |
Node res; |
993 |
113262 |
if (tryEval && options::sygusEvalOpt()) |
994 |
|
{ |
995 |
|
// Try evaluating, which is much faster than substitution+rewriting. |
996 |
|
// This may fail if there is a subterm of bn under the |
997 |
|
// substitution that is not constant, or if an operator in bn is not |
998 |
|
// supported by the evaluator |
999 |
113262 |
res = d_eval->eval(bn, varlist, args); |
1000 |
|
} |
1001 |
113262 |
if (res.isNull()) |
1002 |
|
{ |
1003 |
|
// must do substitution |
1004 |
|
res = |
1005 |
|
bn.substitute(varlist.begin(), varlist.end(), args.begin(), args.end()); |
1006 |
|
} |
1007 |
|
// Call the rewrite node function, which may involve recursive function |
1008 |
|
// evaluation. |
1009 |
113262 |
return rewriteNode(res); |
1010 |
|
} |
1011 |
|
|
1012 |
525 |
bool TermDbSygus::isEvaluationPoint(Node n) const |
1013 |
|
{ |
1014 |
525 |
if (n.getKind() != DT_SYGUS_EVAL) |
1015 |
|
{ |
1016 |
238 |
return false; |
1017 |
|
} |
1018 |
287 |
if (!n[0].isVar()) |
1019 |
|
{ |
1020 |
|
return false; |
1021 |
|
} |
1022 |
1122 |
for (unsigned i = 1, nchild = n.getNumChildren(); i < nchild; i++) |
1023 |
|
{ |
1024 |
845 |
if (!n[i].isConst()) |
1025 |
|
{ |
1026 |
10 |
return false; |
1027 |
|
} |
1028 |
|
} |
1029 |
277 |
return true; |
1030 |
|
} |
1031 |
|
|
1032 |
|
} // namespace quantifiers |
1033 |
|
} // namespace theory |
1034 |
29511 |
} // namespace cvc5 |