GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/arrays/array_info.cpp Lines: 203 295 68.8 %
Date: 2021-09-10 Branches: 292 932 31.3 %

Line Exec Source
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
12518
Info::Info(context::Context* c)
26
    : isNonLinear(c, false),
27
      rIntro1Applied(c, false),
28
25036
      modelRep(c, TNode()),
29
25036
      constArr(c, TNode()),
30
25036
      weakEquivPointer(c, TNode()),
31
25036
      weakEquivIndex(c, TNode()),
32
25036
      weakEquivSecondary(c, TNode()),
33
137698
      weakEquivSecondaryReason(c, TNode())
34
{
35
12518
  indices = new(true)CTNodeList(c);
36
12518
  stores = new(true)CTNodeList(c);
37
12518
  in_stores = new(true)CTNodeList(c);
38
12518
}
39
40
25030
Info::~Info() {
41
12515
  indices->deleteSelf();
42
12515
  stores->deleteSelf();
43
12515
  in_stores->deleteSelf();
44
12515
}
45
46
9913
ArrayInfo::ArrayInfo(context::Context* c,
47
9913
                     std::string statisticsPrefix)
48
    : ct(c),
49
      info_map(),
50
9913
      d_mergeInfoTimer(smtStatisticsRegistry().registerTimer(
51
19826
          statisticsPrefix + "mergeInfoTimer")),
52
9913
      d_avgIndexListLength(smtStatisticsRegistry().registerAverage(
53
19826
          statisticsPrefix + "avgIndexListLength")),
54
9913
      d_avgStoresListLength(smtStatisticsRegistry().registerAverage(
55
19826
          statisticsPrefix + "avgStoresListLength")),
56
9913
      d_avgInStoresListLength(smtStatisticsRegistry().registerAverage(
57
19826
          statisticsPrefix + "avgInStoresListLength")),
58
      d_listsCount(
59
19826
          smtStatisticsRegistry().registerInt(statisticsPrefix + "listsCount")),
60
9913
      d_callsMergeInfo(smtStatisticsRegistry().registerInt(statisticsPrefix
61
19826
                                                           + "callsMergeInfo")),
62
      d_maxList(
63
19826
          smtStatisticsRegistry().registerInt(statisticsPrefix + "maxList")),
64
9913
      d_tableSize(smtStatisticsRegistry().registerSize<CNodeInfoMap>(
65
89217
          statisticsPrefix + "infoTableSize", info_map))
66
{
67
9913
  emptyList = new(true) CTNodeList(ct);
68
9913
  emptyInfo = new Info(ct);
69
9913
}
70
71
19820
ArrayInfo::~ArrayInfo() {
72
9910
  CNodeInfoMap::iterator it = info_map.begin();
73
15120
  for (; it != info_map.end(); ++it)
74
  {
75
2605
    if((*it).second!= emptyInfo) {
76
2605
      delete (*it).second;
77
    }
78
  }
79
9910
  emptyList->deleteSelf();
80
9910
  delete emptyInfo;
81
9910
}
82
83
23847
bool inList(const CTNodeList* l, const TNode el) {
84
23847
  CTNodeList::const_iterator it = l->begin();
85
367647
  for (; it != l->end(); ++it)
86
  {
87
174436
    if(*it == el)
88
2536
      return true;
89
  }
90
21311
  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
50909
  for (it = la->begin(); it != la->end(); ++it)
107
  {
108
35288
    temp.insert((*it));
109
  }
110
111
41450
  for (it = lb->begin(); it != lb->end(); ++it)
112
  {
113
25829
    if(temp.count(*it) == 0) {
114
13003
      la->push_back(*it);
115
    }
116
  }
117
15621
}
118
119
24006
void ArrayInfo::addIndex(const Node a, const TNode i) {
120
24006
  Assert(a.getType().isArray());
121
24006
  Assert(!i.getType().isArray());  // temporary for flat arrays
122
123
24006
  Trace("arrays-ind")<<"Arrays::addIndex "<<a<<"["<<i<<"]\n";
124
  CTNodeList* temp_indices;
125
  Info* temp_info;
126
127
24006
  CNodeInfoMap::iterator it = info_map.find(a);
128
24006
  if(it == info_map.end()) {
129
2075
    temp_info = new Info(ct);
130
2075
    temp_indices = temp_info->indices;
131
2075
    temp_indices->push_back(i);
132
2075
    info_map[a] = temp_info;
133
  } else {
134
21931
    temp_indices = (*it).second->indices;
135
21931
    if (! inList(temp_indices, i)) {
136
19395
      temp_indices->push_back(i);
137
    }
138
  }
139
24006
  if(Trace.isOn("arrays-ind")) {
140
    printList((*(info_map.find(a))).second->indices);
141
  }
142
143
24006
}
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
36824
const bool ArrayInfo::isNonLinear(const TNode a) const
311
{
312
36824
  CNodeInfoMap::const_iterator it = info_map.find(a);
313
314
36824
  if(it!= info_map.end()) {
315
35647
    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
47252
const TNode ArrayInfo::getConstArr(const TNode a) const
341
{
342
47252
  CNodeInfoMap::const_iterator it = info_map.find(a);
343
344
47252
  if(it!= info_map.end()) {
345
45458
    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
44944
const CTNodeList* ArrayInfo::getStores(const TNode a) const{
399
44944
  CNodeInfoMap::const_iterator it = info_map.find(a);
400
44944
  if(it!= info_map.end()) {
401
43466
    return (*it).second->stores;
402
  }
403
1478
  return emptyList;
404
}
405
406
44338
const CTNodeList* ArrayInfo::getInStores(const TNode a) const{
407
44338
  CNodeInfoMap::const_iterator it = info_map.find(a);
408
44338
  if(it!= info_map.end()) {
409
43441
    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
29502
}  // namespace cvc5