1 |
|
/****************************************************************************** |
2 |
|
* Top contributors (to current version): |
3 |
|
* Morgan Deters, Clark Barrett, 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 |
|
* Contains additional classes to store context dependent information |
14 |
|
* for each term of type array. |
15 |
|
*/ |
16 |
|
|
17 |
|
#include "theory/arrays/array_info.h" |
18 |
|
|
19 |
|
#include "smt/smt_statistics_registry.h" |
20 |
|
|
21 |
|
namespace cvc5 { |
22 |
|
namespace theory { |
23 |
|
namespace arrays { |
24 |
|
|
25 |
12535 |
Info::Info(context::Context* c) |
26 |
|
: isNonLinear(c, false), |
27 |
|
rIntro1Applied(c, false), |
28 |
25070 |
modelRep(c, TNode()), |
29 |
25070 |
constArr(c, TNode()), |
30 |
25070 |
weakEquivPointer(c, TNode()), |
31 |
25070 |
weakEquivIndex(c, TNode()), |
32 |
25070 |
weakEquivSecondary(c, TNode()), |
33 |
137885 |
weakEquivSecondaryReason(c, TNode()) |
34 |
|
{ |
35 |
12535 |
indices = new(true)CTNodeList(c); |
36 |
12535 |
stores = new(true)CTNodeList(c); |
37 |
12535 |
in_stores = new(true)CTNodeList(c); |
38 |
12535 |
} |
39 |
|
|
40 |
25064 |
Info::~Info() { |
41 |
12532 |
indices->deleteSelf(); |
42 |
12532 |
stores->deleteSelf(); |
43 |
12532 |
in_stores->deleteSelf(); |
44 |
12532 |
} |
45 |
|
|
46 |
9928 |
ArrayInfo::ArrayInfo(context::Context* c, |
47 |
9928 |
std::string statisticsPrefix) |
48 |
|
: ct(c), |
49 |
|
info_map(), |
50 |
9928 |
d_mergeInfoTimer(smtStatisticsRegistry().registerTimer( |
51 |
19856 |
statisticsPrefix + "mergeInfoTimer")), |
52 |
9928 |
d_avgIndexListLength(smtStatisticsRegistry().registerAverage( |
53 |
19856 |
statisticsPrefix + "avgIndexListLength")), |
54 |
9928 |
d_avgStoresListLength(smtStatisticsRegistry().registerAverage( |
55 |
19856 |
statisticsPrefix + "avgStoresListLength")), |
56 |
9928 |
d_avgInStoresListLength(smtStatisticsRegistry().registerAverage( |
57 |
19856 |
statisticsPrefix + "avgInStoresListLength")), |
58 |
|
d_listsCount( |
59 |
19856 |
smtStatisticsRegistry().registerInt(statisticsPrefix + "listsCount")), |
60 |
9928 |
d_callsMergeInfo(smtStatisticsRegistry().registerInt(statisticsPrefix |
61 |
19856 |
+ "callsMergeInfo")), |
62 |
|
d_maxList( |
63 |
19856 |
smtStatisticsRegistry().registerInt(statisticsPrefix + "maxList")), |
64 |
9928 |
d_tableSize(smtStatisticsRegistry().registerSize<CNodeInfoMap>( |
65 |
89352 |
statisticsPrefix + "infoTableSize", info_map)) |
66 |
|
{ |
67 |
9928 |
emptyList = new(true) CTNodeList(ct); |
68 |
9928 |
emptyInfo = new Info(ct); |
69 |
9928 |
} |
70 |
|
|
71 |
19850 |
ArrayInfo::~ArrayInfo() { |
72 |
9925 |
CNodeInfoMap::iterator it = info_map.begin(); |
73 |
15139 |
for (; it != info_map.end(); ++it) |
74 |
|
{ |
75 |
2607 |
if((*it).second!= emptyInfo) { |
76 |
2607 |
delete (*it).second; |
77 |
|
} |
78 |
|
} |
79 |
9925 |
emptyList->deleteSelf(); |
80 |
9925 |
delete emptyInfo; |
81 |
9925 |
} |
82 |
|
|
83 |
23869 |
bool inList(const CTNodeList* l, const TNode el) { |
84 |
23869 |
CTNodeList::const_iterator it = l->begin(); |
85 |
367905 |
for (; it != l->end(); ++it) |
86 |
|
{ |
87 |
174563 |
if(*it == el) |
88 |
2545 |
return true; |
89 |
|
} |
90 |
21324 |
return false; |
91 |
|
} |
92 |
|
|
93 |
474 |
void printList (CTNodeList* list) { |
94 |
474 |
CTNodeList::const_iterator it = list->begin(); |
95 |
474 |
Trace("arrays-info")<<" [ "; |
96 |
1024 |
for (; it != list->end(); ++it) |
97 |
|
{ |
98 |
275 |
Trace("arrays-info")<<(*it)<<" "; |
99 |
|
} |
100 |
474 |
Trace("arrays-info")<<"] \n"; |
101 |
474 |
} |
102 |
|
|
103 |
15621 |
void ArrayInfo::mergeLists(CTNodeList* la, const CTNodeList* lb) const{ |
104 |
31242 |
std::set<TNode> temp; |
105 |
15621 |
CTNodeList::const_iterator it; |
106 |
50953 |
for (it = la->begin(); it != la->end(); ++it) |
107 |
|
{ |
108 |
35332 |
temp.insert((*it)); |
109 |
|
} |
110 |
|
|
111 |
41456 |
for (it = lb->begin(); it != lb->end(); ++it) |
112 |
|
{ |
113 |
25835 |
if(temp.count(*it) == 0) { |
114 |
12990 |
la->push_back(*it); |
115 |
|
} |
116 |
|
} |
117 |
15621 |
} |
118 |
|
|
119 |
24030 |
void ArrayInfo::addIndex(const Node a, const TNode i) { |
120 |
24030 |
Assert(a.getType().isArray()); |
121 |
24030 |
Assert(!i.getType().isArray()); // temporary for flat arrays |
122 |
|
|
123 |
24030 |
Trace("arrays-ind")<<"Arrays::addIndex "<<a<<"["<<i<<"]\n"; |
124 |
|
CTNodeList* temp_indices; |
125 |
|
Info* temp_info; |
126 |
|
|
127 |
24030 |
CNodeInfoMap::iterator it = info_map.find(a); |
128 |
24030 |
if(it == info_map.end()) { |
129 |
2077 |
temp_info = new Info(ct); |
130 |
2077 |
temp_indices = temp_info->indices; |
131 |
2077 |
temp_indices->push_back(i); |
132 |
2077 |
info_map[a] = temp_info; |
133 |
|
} else { |
134 |
21953 |
temp_indices = (*it).second->indices; |
135 |
21953 |
if (! inList(temp_indices, i)) { |
136 |
19408 |
temp_indices->push_back(i); |
137 |
|
} |
138 |
|
} |
139 |
24030 |
if(Trace.isOn("arrays-ind")) { |
140 |
|
printList((*(info_map.find(a))).second->indices); |
141 |
|
} |
142 |
|
|
143 |
24030 |
} |
144 |
|
|
145 |
1112 |
void ArrayInfo::addStore(const Node a, const TNode st){ |
146 |
1112 |
Assert(a.getType().isArray()); |
147 |
1112 |
Assert(st.getKind() == kind::STORE); // temporary for flat arrays |
148 |
|
|
149 |
|
CTNodeList* temp_store; |
150 |
|
Info* temp_info; |
151 |
|
|
152 |
1112 |
CNodeInfoMap::iterator it = info_map.find(a); |
153 |
1112 |
if(it == info_map.end()) { |
154 |
|
temp_info = new Info(ct); |
155 |
|
temp_store = temp_info->stores; |
156 |
|
temp_store->push_back(st); |
157 |
|
info_map[a]=temp_info; |
158 |
|
} else { |
159 |
1112 |
temp_store = (*it).second->stores; |
160 |
1112 |
if(! inList(temp_store, st)) { |
161 |
1112 |
temp_store->push_back(st); |
162 |
|
} |
163 |
|
} |
164 |
1112 |
}; |
165 |
|
|
166 |
|
|
167 |
1112 |
void ArrayInfo::addInStore(const TNode a, const TNode b){ |
168 |
1112 |
Trace("arrays-addinstore")<<"Arrays::addInStore "<<a<<" ~ "<<b<<"\n"; |
169 |
1112 |
Assert(a.getType().isArray()); |
170 |
1112 |
Assert(b.getType().isArray()); |
171 |
|
|
172 |
|
CTNodeList* temp_inst; |
173 |
|
Info* temp_info; |
174 |
|
|
175 |
1112 |
CNodeInfoMap::iterator it = info_map.find(a); |
176 |
1112 |
if(it == info_map.end()) { |
177 |
308 |
temp_info = new Info(ct); |
178 |
308 |
temp_inst = temp_info->in_stores; |
179 |
308 |
temp_inst->push_back(b); |
180 |
308 |
info_map[a] = temp_info; |
181 |
|
} else { |
182 |
804 |
temp_inst = (*it).second->in_stores; |
183 |
804 |
if(! inList(temp_inst, b)) { |
184 |
804 |
temp_inst->push_back(b); |
185 |
|
} |
186 |
|
} |
187 |
1112 |
}; |
188 |
|
|
189 |
|
|
190 |
1732 |
void ArrayInfo::setNonLinear(const TNode a) { |
191 |
1732 |
Assert(a.getType().isArray()); |
192 |
|
Info* temp_info; |
193 |
1732 |
CNodeInfoMap::iterator it = info_map.find(a); |
194 |
1732 |
if(it == info_map.end()) { |
195 |
8 |
temp_info = new Info(ct); |
196 |
8 |
temp_info->isNonLinear = true; |
197 |
8 |
info_map[a] = temp_info; |
198 |
|
} else { |
199 |
1724 |
(*it).second->isNonLinear = true; |
200 |
|
} |
201 |
|
|
202 |
1732 |
} |
203 |
|
|
204 |
|
void ArrayInfo::setRIntro1Applied(const TNode a) { |
205 |
|
Assert(a.getType().isArray()); |
206 |
|
Info* temp_info; |
207 |
|
CNodeInfoMap::iterator it = info_map.find(a); |
208 |
|
if(it == info_map.end()) { |
209 |
|
temp_info = new Info(ct); |
210 |
|
temp_info->rIntro1Applied = true; |
211 |
|
info_map[a] = temp_info; |
212 |
|
} else { |
213 |
|
(*it).second->rIntro1Applied = true; |
214 |
|
} |
215 |
|
|
216 |
|
} |
217 |
|
|
218 |
1112 |
void ArrayInfo::setModelRep(const TNode a, const TNode b) { |
219 |
1112 |
Assert(a.getType().isArray()); |
220 |
|
Info* temp_info; |
221 |
1112 |
CNodeInfoMap::iterator it = info_map.find(a); |
222 |
1112 |
if(it == info_map.end()) { |
223 |
|
temp_info = new Info(ct); |
224 |
|
temp_info->modelRep = b; |
225 |
|
info_map[a] = temp_info; |
226 |
|
} else { |
227 |
1112 |
(*it).second->modelRep = b; |
228 |
|
} |
229 |
|
|
230 |
1112 |
} |
231 |
|
|
232 |
66 |
void ArrayInfo::setConstArr(const TNode a, const TNode constArr) { |
233 |
66 |
Assert(a.getType().isArray()); |
234 |
|
Info* temp_info; |
235 |
66 |
CNodeInfoMap::iterator it = info_map.find(a); |
236 |
66 |
if(it == info_map.end()) { |
237 |
56 |
temp_info = new Info(ct); |
238 |
56 |
temp_info->constArr = constArr; |
239 |
56 |
info_map[a] = temp_info; |
240 |
|
} else { |
241 |
10 |
(*it).second->constArr = constArr; |
242 |
|
} |
243 |
66 |
} |
244 |
|
|
245 |
|
void ArrayInfo::setWeakEquivPointer(const TNode a, const TNode pointer) { |
246 |
|
Assert(a.getType().isArray()); |
247 |
|
Info* temp_info; |
248 |
|
CNodeInfoMap::iterator it = info_map.find(a); |
249 |
|
if(it == info_map.end()) { |
250 |
|
temp_info = new Info(ct); |
251 |
|
temp_info->weakEquivPointer = pointer; |
252 |
|
info_map[a] = temp_info; |
253 |
|
} else { |
254 |
|
(*it).second->weakEquivPointer = pointer; |
255 |
|
} |
256 |
|
} |
257 |
|
|
258 |
|
void ArrayInfo::setWeakEquivIndex(const TNode a, const TNode index) { |
259 |
|
Assert(a.getType().isArray()); |
260 |
|
Info* temp_info; |
261 |
|
CNodeInfoMap::iterator it = info_map.find(a); |
262 |
|
if(it == info_map.end()) { |
263 |
|
temp_info = new Info(ct); |
264 |
|
temp_info->weakEquivIndex = index; |
265 |
|
info_map[a] = temp_info; |
266 |
|
} else { |
267 |
|
(*it).second->weakEquivIndex = index; |
268 |
|
} |
269 |
|
} |
270 |
|
|
271 |
|
void ArrayInfo::setWeakEquivSecondary(const TNode a, const TNode secondary) { |
272 |
|
Assert(a.getType().isArray()); |
273 |
|
Info* temp_info; |
274 |
|
CNodeInfoMap::iterator it = info_map.find(a); |
275 |
|
if(it == info_map.end()) { |
276 |
|
temp_info = new Info(ct); |
277 |
|
temp_info->weakEquivSecondary = secondary; |
278 |
|
info_map[a] = temp_info; |
279 |
|
} else { |
280 |
|
(*it).second->weakEquivSecondary = secondary; |
281 |
|
} |
282 |
|
} |
283 |
|
|
284 |
|
void ArrayInfo::setWeakEquivSecondaryReason(const TNode a, const TNode reason) { |
285 |
|
Assert(a.getType().isArray()); |
286 |
|
Info* temp_info; |
287 |
|
CNodeInfoMap::iterator it = info_map.find(a); |
288 |
|
if(it == info_map.end()) { |
289 |
|
temp_info = new Info(ct); |
290 |
|
temp_info->weakEquivSecondaryReason = reason; |
291 |
|
info_map[a] = temp_info; |
292 |
|
} else { |
293 |
|
(*it).second->weakEquivSecondaryReason = reason; |
294 |
|
} |
295 |
|
} |
296 |
|
|
297 |
|
/** |
298 |
|
* Returns the information associated with TNode a |
299 |
|
*/ |
300 |
|
|
301 |
|
const Info* ArrayInfo::getInfo(const TNode a) const{ |
302 |
|
CNodeInfoMap::const_iterator it = info_map.find(a); |
303 |
|
|
304 |
|
if(it!= info_map.end()) { |
305 |
|
return (*it).second; |
306 |
|
} |
307 |
|
return emptyInfo; |
308 |
|
} |
309 |
|
|
310 |
36853 |
const bool ArrayInfo::isNonLinear(const TNode a) const |
311 |
|
{ |
312 |
36853 |
CNodeInfoMap::const_iterator it = info_map.find(a); |
313 |
|
|
314 |
36853 |
if(it!= info_map.end()) { |
315 |
35676 |
return (*it).second->isNonLinear; |
316 |
|
} |
317 |
1177 |
return false; |
318 |
|
} |
319 |
|
|
320 |
|
const bool ArrayInfo::rIntro1Applied(const TNode a) const |
321 |
|
{ |
322 |
|
CNodeInfoMap::const_iterator it = info_map.find(a); |
323 |
|
|
324 |
|
if(it!= info_map.end()) { |
325 |
|
return (*it).second->rIntro1Applied; |
326 |
|
} |
327 |
|
return false; |
328 |
|
} |
329 |
|
|
330 |
|
const TNode ArrayInfo::getModelRep(const TNode a) const |
331 |
|
{ |
332 |
|
CNodeInfoMap::const_iterator it = info_map.find(a); |
333 |
|
|
334 |
|
if(it!= info_map.end()) { |
335 |
|
return (*it).second->modelRep; |
336 |
|
} |
337 |
|
return TNode(); |
338 |
|
} |
339 |
|
|
340 |
47276 |
const TNode ArrayInfo::getConstArr(const TNode a) const |
341 |
|
{ |
342 |
47276 |
CNodeInfoMap::const_iterator it = info_map.find(a); |
343 |
|
|
344 |
47276 |
if(it!= info_map.end()) { |
345 |
45482 |
return (*it).second->constArr; |
346 |
|
} |
347 |
1794 |
return TNode(); |
348 |
|
} |
349 |
|
|
350 |
|
const TNode ArrayInfo::getWeakEquivPointer(const TNode a) const |
351 |
|
{ |
352 |
|
CNodeInfoMap::const_iterator it = info_map.find(a); |
353 |
|
|
354 |
|
if(it!= info_map.end()) { |
355 |
|
return (*it).second->weakEquivPointer; |
356 |
|
} |
357 |
|
return TNode(); |
358 |
|
} |
359 |
|
|
360 |
|
const TNode ArrayInfo::getWeakEquivIndex(const TNode a) const |
361 |
|
{ |
362 |
|
CNodeInfoMap::const_iterator it = info_map.find(a); |
363 |
|
|
364 |
|
if(it!= info_map.end()) { |
365 |
|
return (*it).second->weakEquivIndex; |
366 |
|
} |
367 |
|
return TNode(); |
368 |
|
} |
369 |
|
|
370 |
|
const TNode ArrayInfo::getWeakEquivSecondary(const TNode a) const |
371 |
|
{ |
372 |
|
CNodeInfoMap::const_iterator it = info_map.find(a); |
373 |
|
|
374 |
|
if(it!= info_map.end()) { |
375 |
|
return (*it).second->weakEquivSecondary; |
376 |
|
} |
377 |
|
return TNode(); |
378 |
|
} |
379 |
|
|
380 |
|
const TNode ArrayInfo::getWeakEquivSecondaryReason(const TNode a) const |
381 |
|
{ |
382 |
|
CNodeInfoMap::const_iterator it = info_map.find(a); |
383 |
|
|
384 |
|
if(it!= info_map.end()) { |
385 |
|
return (*it).second->weakEquivSecondaryReason; |
386 |
|
} |
387 |
|
return TNode(); |
388 |
|
} |
389 |
|
|
390 |
13610 |
const CTNodeList* ArrayInfo::getIndices(const TNode a) const{ |
391 |
13610 |
CNodeInfoMap::const_iterator it = info_map.find(a); |
392 |
13610 |
if(it!= info_map.end()) { |
393 |
12713 |
return (*it).second->indices; |
394 |
|
} |
395 |
897 |
return emptyList; |
396 |
|
} |
397 |
|
|
398 |
44968 |
const CTNodeList* ArrayInfo::getStores(const TNode a) const{ |
399 |
44968 |
CNodeInfoMap::const_iterator it = info_map.find(a); |
400 |
44968 |
if(it!= info_map.end()) { |
401 |
43490 |
return (*it).second->stores; |
402 |
|
} |
403 |
1478 |
return emptyList; |
404 |
|
} |
405 |
|
|
406 |
44374 |
const CTNodeList* ArrayInfo::getInStores(const TNode a) const{ |
407 |
44374 |
CNodeInfoMap::const_iterator it = info_map.find(a); |
408 |
44374 |
if(it!= info_map.end()) { |
409 |
43477 |
return (*it).second->in_stores; |
410 |
|
} |
411 |
897 |
return emptyList; |
412 |
|
} |
413 |
|
|
414 |
|
|
415 |
5810 |
void ArrayInfo::mergeInfo(const TNode a, const TNode b){ |
416 |
|
// can't have assertion that find(b) = a ! |
417 |
11620 |
TimerStat::CodeTimer codeTimer(d_mergeInfoTimer); |
418 |
5810 |
++d_callsMergeInfo; |
419 |
|
|
420 |
5810 |
Trace("arrays-mergei")<<"Arrays::mergeInfo merging "<<a<<"\n"; |
421 |
5810 |
Trace("arrays-mergei")<<" and "<<b<<"\n"; |
422 |
|
|
423 |
5810 |
CNodeInfoMap::iterator ita = info_map.find(a); |
424 |
5810 |
CNodeInfoMap::iterator itb = info_map.find(b); |
425 |
|
|
426 |
5810 |
if(ita != info_map.end()) { |
427 |
5516 |
Trace("arrays-mergei")<<"Arrays::mergeInfo info "<<a<<"\n"; |
428 |
5516 |
if(Trace.isOn("arrays-mergei")) |
429 |
|
(*ita).second->print(); |
430 |
|
|
431 |
5516 |
if(itb != info_map.end()) { |
432 |
5049 |
Trace("arrays-mergei")<<"Arrays::mergeInfo info "<<b<<"\n"; |
433 |
5049 |
if(Trace.isOn("arrays-mergei")) |
434 |
|
(*itb).second->print(); |
435 |
|
|
436 |
5049 |
CTNodeList* lista_i = (*ita).second->indices; |
437 |
5049 |
CTNodeList* lista_st = (*ita).second->stores; |
438 |
5049 |
CTNodeList* lista_inst = (*ita).second->in_stores; |
439 |
|
|
440 |
|
|
441 |
5049 |
CTNodeList* listb_i = (*itb).second->indices; |
442 |
5049 |
CTNodeList* listb_st = (*itb).second->stores; |
443 |
5049 |
CTNodeList* listb_inst = (*itb).second->in_stores; |
444 |
|
|
445 |
5049 |
mergeLists(lista_i, listb_i); |
446 |
5049 |
mergeLists(lista_st, listb_st); |
447 |
5049 |
mergeLists(lista_inst, listb_inst); |
448 |
|
|
449 |
|
/* sketchy stats */ |
450 |
|
|
451 |
|
//FIXME |
452 |
5049 |
int s = 0;//lista_i->size(); |
453 |
5049 |
d_maxList.maxAssign(s); |
454 |
|
|
455 |
|
|
456 |
5049 |
if(s!= 0) { |
457 |
|
d_avgIndexListLength << s; |
458 |
|
++d_listsCount; |
459 |
|
} |
460 |
5049 |
s = lista_st->size(); |
461 |
5049 |
d_maxList.maxAssign(s); |
462 |
5049 |
if(s!= 0) { |
463 |
3242 |
d_avgStoresListLength << s; |
464 |
3242 |
++d_listsCount; |
465 |
|
} |
466 |
|
|
467 |
5049 |
s = lista_inst->size(); |
468 |
5049 |
d_maxList.maxAssign(s); |
469 |
5049 |
if(s!=0) { |
470 |
2636 |
d_avgInStoresListLength << s; |
471 |
2636 |
++d_listsCount; |
472 |
|
} |
473 |
|
|
474 |
|
/* end sketchy stats */ |
475 |
|
|
476 |
|
} |
477 |
|
|
478 |
|
} else { |
479 |
294 |
Trace("arrays-mergei")<<" First element has no info \n"; |
480 |
294 |
if(itb != info_map.end()) { |
481 |
158 |
Trace("arrays-mergei")<<" adding second element's info \n"; |
482 |
158 |
(*itb).second->print(); |
483 |
|
|
484 |
158 |
CTNodeList* listb_i = (*itb).second->indices; |
485 |
158 |
CTNodeList* listb_st = (*itb).second->stores; |
486 |
158 |
CTNodeList* listb_inst = (*itb).second->in_stores; |
487 |
|
|
488 |
158 |
Info* temp_info = new Info(ct); |
489 |
|
|
490 |
158 |
mergeLists(temp_info->indices, listb_i); |
491 |
158 |
mergeLists(temp_info->stores, listb_st); |
492 |
158 |
mergeLists(temp_info->in_stores, listb_inst); |
493 |
158 |
info_map[a] = temp_info; |
494 |
|
|
495 |
|
} else { |
496 |
136 |
Trace("arrays-mergei")<<" Second element has no info \n"; |
497 |
|
} |
498 |
|
|
499 |
|
} |
500 |
5810 |
Trace("arrays-mergei")<<"Arrays::mergeInfo done \n"; |
501 |
|
|
502 |
5810 |
} |
503 |
|
|
504 |
|
} // namespace arrays |
505 |
|
} // namespace theory |
506 |
29505 |
} // namespace cvc5 |