GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/sets/solver_state.cpp Lines: 276 293 94.2 %
Date: 2021-05-22 Branches: 579 1220 47.5 %

Line Exec Source
1
/******************************************************************************
2
 * Top contributors (to current version):
3
 *   Andrew Reynolds, Mudathir Mohamed, Paul Meng
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 sets state object.
14
 */
15
16
#include "theory/sets/solver_state.h"
17
18
#include "expr/emptyset.h"
19
#include "options/sets_options.h"
20
#include "theory/sets/theory_sets_private.h"
21
22
using namespace std;
23
using namespace cvc5::kind;
24
25
namespace cvc5 {
26
namespace theory {
27
namespace sets {
28
29
9460
SolverState::SolverState(context::Context* c,
30
                         context::UserContext* u,
31
                         Valuation val,
32
9460
                         SkolemCache& skc)
33
9460
    : TheoryState(c, u, val), d_skCache(skc), d_members(c)
34
{
35
9460
  d_true = NodeManager::currentNM()->mkConst(true);
36
9460
  d_false = NodeManager::currentNM()->mkConst(false);
37
9460
}
38
39
31230
void SolverState::reset()
40
{
41
31230
  d_set_eqc.clear();
42
31230
  d_eqc_emptyset.clear();
43
31230
  d_eqc_univset.clear();
44
31230
  d_eqc_singleton.clear();
45
31230
  d_congruent.clear();
46
31230
  d_nvar_sets.clear();
47
31230
  d_var_set.clear();
48
31230
  d_compSets.clear();
49
31230
  d_pol_mems[0].clear();
50
31230
  d_pol_mems[1].clear();
51
31230
  d_members_index.clear();
52
31230
  d_singleton_index.clear();
53
31230
  d_bop_index.clear();
54
31230
  d_op_list.clear();
55
31230
  d_allCompSets.clear();
56
31230
}
57
58
151303
void SolverState::registerEqc(TypeNode tn, Node r)
59
{
60
151303
  if (tn.isSet())
61
  {
62
54189
    d_set_eqc.push_back(r);
63
  }
64
151303
}
65
66
510810
void SolverState::registerTerm(Node r, TypeNode tnn, Node n)
67
{
68
510810
  Kind nk = n.getKind();
69
510810
  if (nk == MEMBER)
70
  {
71
120430
    if (r.isConst())
72
    {
73
229394
      Node s = d_ee->getRepresentative(n[1]);
74
229394
      Node x = d_ee->getRepresentative(n[0]);
75
114697
      int pindex = r == d_true ? 0 : (r == d_false ? 1 : -1);
76
114697
      if (pindex != -1)
77
      {
78
114697
        if (d_pol_mems[pindex][s].find(x) == d_pol_mems[pindex][s].end())
79
        {
80
82368
          d_pol_mems[pindex][s][x] = n;
81
164736
          Trace("sets-debug2") << "Membership[" << x << "][" << s << "] : " << n
82
82368
                               << ", pindex = " << pindex << std::endl;
83
        }
84
114697
        if (d_members_index[s].find(x) == d_members_index[s].end())
85
        {
86
82368
          d_members_index[s][x] = n;
87
82368
          d_op_list[MEMBER].push_back(n);
88
        }
89
      }
90
      else
91
      {
92
        Assert(false);
93
      }
94
    }
95
  }
96
390380
  else if (nk == SINGLETON || nk == UNION || nk == INTERSECTION
97
352868
           || nk == SETMINUS || nk == EMPTYSET || nk == UNIVERSE_SET)
98
  {
99
63241
    if (nk == SINGLETON)
100
    {
101
20570
      Node re = d_ee->getRepresentative(n[0]);
102
10285
      if (d_singleton_index.find(re) == d_singleton_index.end())
103
      {
104
8093
        d_singleton_index[re] = n;
105
8093
        d_eqc_singleton[r] = n;
106
8093
        d_op_list[SINGLETON].push_back(n);
107
      }
108
      else
109
      {
110
2192
        d_congruent[n] = d_singleton_index[re];
111
      }
112
    }
113
52956
    else if (nk == EMPTYSET)
114
    {
115
3635
      d_eqc_emptyset[tnn] = r;
116
    }
117
49321
    else if (nk == UNIVERSE_SET)
118
    {
119
20024
      Assert(options::setsExt());
120
1800
      d_eqc_univset[tnn] = r;
121
    }
122
    else
123
    {
124
95042
      Node r1 = d_ee->getRepresentative(n[0]);
125
95042
      Node r2 = d_ee->getRepresentative(n[1]);
126
47521
      std::map<Node, Node>& binr1 = d_bop_index[nk][r1];
127
47521
      std::map<Node, Node>::iterator itb = binr1.find(r2);
128
47521
      if (itb == binr1.end())
129
      {
130
44672
        binr1[r2] = n;
131
44672
        d_op_list[nk].push_back(n);
132
      }
133
      else
134
      {
135
2849
        d_congruent[n] = itb->second;
136
      }
137
    }
138
63241
    d_nvar_sets[r].push_back(n);
139
63241
    Trace("sets-debug2") << "Non-var-set[" << r << "] : " << n << std::endl;
140
  }
141
327139
  else if (nk == COMPREHENSION)
142
  {
143
124
    d_compSets[r].push_back(n);
144
124
    d_allCompSets.push_back(n);
145
124
    Trace("sets-debug2") << "Comp-set[" << r << "] : " << n << std::endl;
146
  }
147
327015
  else if (n.isVar() && !d_skCache.isSkolem(n))
148
  {
149
    // it is important that we check it is a variable, but not an internally
150
    // introduced skolem, due to the semantics of the universe set.
151
30474
    if (tnn.isSet())
152
    {
153
21750
      if (d_var_set.find(r) == d_var_set.end())
154
      {
155
20090
        d_var_set[r] = n;
156
20090
        Trace("sets-debug2") << "var-set[" << r << "] : " << n << std::endl;
157
      }
158
    }
159
  }
160
  else
161
  {
162
296541
    Trace("sets-debug2") << "Unknown-set[" << r << "] : " << n << std::endl;
163
  }
164
510810
}
165
166
64367
void SolverState::addEqualityToExp(Node a, Node b, std::vector<Node>& exp) const
167
{
168
64367
  if (a != b)
169
  {
170
19241
    Assert(areEqual(a, b));
171
19241
    exp.push_back(a.eqNode(b));
172
  }
173
64367
}
174
175
15468
Node SolverState::getEmptySetEqClass(TypeNode tn) const
176
{
177
15468
  std::map<TypeNode, Node>::const_iterator it = d_eqc_emptyset.find(tn);
178
15468
  if (it != d_eqc_emptyset.end())
179
  {
180
14305
    return it->second;
181
  }
182
1163
  return Node::null();
183
}
184
185
3429
Node SolverState::getUnivSetEqClass(TypeNode tn) const
186
{
187
3429
  std::map<TypeNode, Node>::const_iterator it = d_eqc_univset.find(tn);
188
3429
  if (it != d_eqc_univset.end())
189
  {
190
2622
    return it->second;
191
  }
192
807
  return Node::null();
193
}
194
195
7639
Node SolverState::getSingletonEqClass(Node r) const
196
{
197
7639
  std::map<Node, Node>::const_iterator it = d_eqc_singleton.find(r);
198
7639
  if (it != d_eqc_singleton.end())
199
  {
200
4
    return it->second;
201
  }
202
7635
  return Node::null();
203
}
204
205
234
Node SolverState::getBinaryOpTerm(Kind k, Node r1, Node r2) const
206
{
207
  std::map<Kind, std::map<Node, std::map<Node, Node> > >::const_iterator itk =
208
234
      d_bop_index.find(k);
209
234
  if (itk == d_bop_index.end())
210
  {
211
    return Node::null();
212
  }
213
  std::map<Node, std::map<Node, Node> >::const_iterator it1 =
214
234
      itk->second.find(r1);
215
234
  if (it1 == itk->second.end())
216
  {
217
136
    return Node::null();
218
  }
219
98
  std::map<Node, Node>::const_iterator it2 = it1->second.find(r2);
220
98
  if (it2 == it1->second.end())
221
  {
222
62
    return Node::null();
223
  }
224
36
  return it2->second;
225
}
226
227
159322
bool SolverState::isEntailed(Node n, bool polarity) const
228
{
229
159322
  if (n.getKind() == NOT)
230
  {
231
14880
    return isEntailed(n[0], !polarity);
232
  }
233
144442
  else if (n.getKind() == EQUAL)
234
  {
235
8277
    if (polarity)
236
    {
237
7489
      return areEqual(n[0], n[1]);
238
    }
239
788
    return areDisequal(n[0], n[1]);
240
  }
241
136165
  else if (n.getKind() == MEMBER)
242
  {
243
74447
    if (areEqual(n, polarity ? d_true : d_false))
244
    {
245
53644
      return true;
246
    }
247
    // check members cache
248
20803
    if (polarity && d_ee->hasTerm(n[1]))
249
    {
250
30156
      Node r = d_ee->getRepresentative(n[1]);
251
19945
      if (isMember(n[0], r))
252
      {
253
9734
        return true;
254
      }
255
    }
256
  }
257
61718
  else if (n.getKind() == AND || n.getKind() == OR)
258
  {
259
36971
    bool conj = (n.getKind() == AND) == polarity;
260
91575
    for (const Node& nc : n)
261
    {
262
68562
      bool isEnt = isEntailed(nc, polarity);
263
68562
      if (isEnt != conj)
264
      {
265
13958
        return !conj;
266
      }
267
    }
268
23013
    return conj;
269
  }
270
24747
  else if (n.isConst())
271
  {
272
12823
    return (polarity && n == d_true) || (!polarity && n == d_false);
273
  }
274
22993
  return false;
275
}
276
277
6771
bool SolverState::isSetDisequalityEntailed(Node r1, Node r2) const
278
{
279
6771
  Assert(d_ee->hasTerm(r1) && d_ee->getRepresentative(r1) == r1);
280
6771
  Assert(d_ee->hasTerm(r2) && d_ee->getRepresentative(r2) == r2);
281
13542
  TypeNode tn = r1.getType();
282
13542
  Node re = getEmptySetEqClass(tn);
283
9497
  for (unsigned e = 0; e < 2; e++)
284
  {
285
11486
    Node a = e == 0 ? r1 : r2;
286
11486
    Node b = e == 0 ? r2 : r1;
287
8760
    if (isSetDisequalityEntailedInternal(a, b, re))
288
    {
289
6034
      return true;
290
    }
291
  }
292
737
  return false;
293
}
294
295
8760
bool SolverState::isSetDisequalityEntailedInternal(Node a,
296
                                                   Node b,
297
                                                   Node re) const
298
{
299
  // if there are members in a
300
  std::map<Node, std::map<Node, Node> >::const_iterator itpma =
301
8760
      d_pol_mems[0].find(a);
302
8760
  if (itpma == d_pol_mems[0].end())
303
  {
304
    // no positive members, continue
305
1600
    return false;
306
  }
307
  // if b is empty
308
7160
  if (b == re)
309
  {
310
2382
    if (!itpma->second.empty())
311
    {
312
4764
      Trace("sets-deq") << "Disequality is satisfied because members are in "
313
2382
                        << a << " and " << b << " is empty" << std::endl;
314
2382
      return true;
315
    }
316
    else
317
    {
318
      // a should not be singleton
319
      Assert(d_eqc_singleton.find(a) == d_eqc_singleton.end());
320
    }
321
    return false;
322
  }
323
4778
  std::map<Node, Node>::const_iterator itsb = d_eqc_singleton.find(b);
324
  std::map<Node, std::map<Node, Node> >::const_iterator itpmb =
325
4778
      d_pol_mems[1].find(b);
326
9556
  std::vector<Node> prev;
327
7253
  for (const std::pair<const Node, Node>& itm : itpma->second)
328
  {
329
    // if b is a singleton
330
6127
    if (itsb != d_eqc_singleton.end())
331
    {
332
3417
      if (areDisequal(itm.first, itsb->second[0]))
333
      {
334
5608
        Trace("sets-deq") << "Disequality is satisfied because of "
335
5608
                          << itm.second << ", singleton eq " << itsb->second[0]
336
2804
                          << std::endl;
337
6456
        return true;
338
      }
339
      // or disequal with another member
340
713
      for (const Node& p : prev)
341
      {
342
109
        if (areDisequal(itm.first, p))
343
        {
344
18
          Trace("sets-deq")
345
9
              << "Disequality is satisfied because of disequal members "
346
9
              << itm.first << " " << p << ", singleton eq " << std::endl;
347
9
          return true;
348
        }
349
      }
350
      // if a has positive member that is negative member in b
351
    }
352
2710
    else if (itpmb != d_pol_mems[1].end())
353
    {
354
3239
      for (const std::pair<const Node, Node>& itnm : itpmb->second)
355
      {
356
2392
        if (areEqual(itm.first, itnm.first))
357
        {
358
1678
          Trace("sets-deq") << "Disequality is satisfied because of "
359
839
                            << itm.second << " " << itnm.second << std::endl;
360
839
          return true;
361
        }
362
      }
363
    }
364
2475
    prev.push_back(itm.first);
365
  }
366
1126
  return false;
367
}
368
369
Node SolverState::getCongruent(Node n) const
370
{
371
  Assert(d_ee->hasTerm(n));
372
  std::map<Node, Node>::const_iterator it = d_congruent.find(n);
373
  if (it == d_congruent.end())
374
  {
375
    return n;
376
  }
377
  return it->second;
378
}
379
80914
bool SolverState::isCongruent(Node n) const
380
{
381
80914
  return d_congruent.find(n) != d_congruent.end();
382
}
383
75400
const std::vector<Node>& SolverState::getNonVariableSets(Node r) const
384
{
385
75400
  std::map<Node, std::vector<Node> >::const_iterator it = d_nvar_sets.find(r);
386
75400
  if (it == d_nvar_sets.end())
387
  {
388
17842
    return d_emptyVec;
389
  }
390
57558
  return it->second;
391
}
392
393
20896
Node SolverState::getVariableSet(Node r) const
394
{
395
20896
  std::map<Node, Node>::const_iterator it = d_var_set.find(r);
396
20896
  if (it != d_var_set.end())
397
  {
398
5980
    return it->second;
399
  }
400
14916
  return Node::null();
401
}
402
403
const std::vector<Node>& SolverState::getComprehensionSets(Node r) const
404
{
405
  std::map<Node, std::vector<Node> >::const_iterator it = d_compSets.find(r);
406
  if (it == d_compSets.end())
407
  {
408
    return d_emptyVec;
409
  }
410
  return it->second;
411
}
412
413
111766
const std::map<Node, Node>& SolverState::getMembers(Node r) const
414
{
415
111766
  return getMembersInternal(r, 0);
416
}
417
30791
const std::map<Node, Node>& SolverState::getNegativeMembers(Node r) const
418
{
419
30791
  return getMembersInternal(r, 1);
420
}
421
142557
const std::map<Node, Node>& SolverState::getMembersInternal(Node r,
422
                                                            unsigned i) const
423
{
424
  std::map<Node, std::map<Node, Node> >::const_iterator itp =
425
142557
      d_pol_mems[i].find(r);
426
142557
  if (itp == d_pol_mems[i].end())
427
  {
428
44379
    return d_emptyMap;
429
  }
430
98178
  return itp->second;
431
}
432
433
1086
bool SolverState::hasMembers(Node r) const
434
{
435
  std::map<Node, std::map<Node, Node> >::const_iterator it =
436
1086
      d_pol_mems[0].find(r);
437
1086
  if (it == d_pol_mems[0].end())
438
  {
439
363
    return false;
440
  }
441
723
  return !it->second.empty();
442
}
443
const std::map<Kind, std::map<Node, std::map<Node, Node> > >&
444
15851
SolverState::getBinaryOpIndex() const
445
{
446
15851
  return d_bop_index;
447
}
448
449
const std::map<Node, std::map<Node, Node>>& SolverState::getBinaryOpIndex(
450
    Kind k)
451
{
452
  return d_bop_index[k];
453
}
454
455
6056
const std::map<Kind, std::vector<Node> >& SolverState::getOperatorList() const
456
{
457
6056
  return d_op_list;
458
}
459
460
14133
const std::vector<Node>& SolverState::getComprehensionSets() const
461
{
462
14133
  return d_allCompSets;
463
}
464
465
970
const vector<Node> SolverState::getSetsEqClasses(const TypeNode& t) const
466
{
467
970
  vector<Node> representatives;
468
9725
  for (const Node& eqc : getSetsEqClasses())
469
  {
470
8755
    if (eqc.getType().getSetElementType() == t)
471
    {
472
8755
      representatives.push_back(eqc);
473
    }
474
  }
475
970
  return representatives;
476
}
477
478
61033
bool SolverState::isMember(TNode x, TNode s) const
479
{
480
61033
  Assert(hasTerm(s) && getRepresentative(s) == s);
481
61033
  NodeIntMap::const_iterator mem_i = d_members.find(s);
482
61033
  if (mem_i != d_members.end())
483
  {
484
    std::map<Node, std::vector<Node> >::const_iterator itd =
485
54185
        d_members_data.find(s);
486
54185
    Assert(itd != d_members_data.end());
487
54185
    const std::vector<Node>& members = itd->second;
488
54185
    Assert((*mem_i).second <= members.size());
489
111417
    for (size_t i = 0, nmem = (*mem_i).second; i < nmem; i++)
490
    {
491
105211
      if (areEqual(members[i][0], x))
492
      {
493
47979
        return true;
494
      }
495
    }
496
  }
497
13054
  return false;
498
}
499
500
53951
void SolverState::addMember(TNode r, TNode atom)
501
{
502
53951
  NodeIntMap::iterator mem_i = d_members.find(r);
503
53951
  size_t n_members = 0;
504
53951
  if (mem_i != d_members.end())
505
  {
506
39848
    n_members = (*mem_i).second;
507
  }
508
53951
  d_members[r] = n_members + 1;
509
53951
  if (n_members < d_members_data[r].size())
510
  {
511
43481
    d_members_data[r][n_members] = atom;
512
  }
513
  else
514
  {
515
10470
    d_members_data[r].push_back(atom);
516
  }
517
53951
}
518
519
197148
bool SolverState::merge(TNode t1,
520
                        TNode t2,
521
                        std::vector<Node>& facts,
522
                        TNode cset)
523
{
524
197148
  NodeIntMap::iterator mem_i2 = d_members.find(t2);
525
197148
  if (mem_i2 == d_members.end())
526
  {
527
    // no members in t2, we are done
528
183378
    return true;
529
  }
530
13770
  NodeIntMap::iterator mem_i1 = d_members.find(t1);
531
13770
  size_t n_members = 0;
532
13770
  if (mem_i1 != d_members.end())
533
  {
534
13355
    n_members = (*mem_i1).second;
535
  }
536
29129
  for (size_t i = 0, nmem2 = (*mem_i2).second; i < nmem2; i++)
537
  {
538
15453
    Assert(i < d_members_data[t2].size()
539
           && d_members_data[t2][i].getKind() == MEMBER);
540
30812
    Node m2 = d_members_data[t2][i];
541
    // check if redundant
542
15453
    bool add = true;
543
18774
    for (size_t j = 0; j < n_members; j++)
544
    {
545
17830
      Assert(j < d_members_data[t1].size()
546
             && d_members_data[t1][j].getKind() == MEMBER);
547
17830
      if (areEqual(m2[0], d_members_data[t1][j][0]))
548
      {
549
14509
        add = false;
550
14509
        break;
551
      }
552
    }
553
15453
    if (add)
554
    {
555
      // if there is a concrete set in t1, propagate new facts or conflicts
556
944
      if (!cset.isNull())
557
      {
558
238
        NodeManager* nm = NodeManager::currentNM();
559
238
        Assert(areEqual(m2[1], cset));
560
382
        Node exp = nm->mkNode(AND, m2[1].eqNode(cset), m2);
561
238
        if (cset.getKind() == SINGLETON)
562
        {
563
144
          if (cset[0] != m2[0])
564
          {
565
288
            Node eq = cset[0].eqNode(m2[0]);
566
288
            Trace("sets-prop") << "Propagate eq-mem eq inference : " << exp
567
144
                               << " => " << eq << std::endl;
568
288
            Node fact = nm->mkNode(IMPLIES, exp, eq);
569
144
            facts.push_back(fact);
570
          }
571
        }
572
        else
573
        {
574
          // conflict
575
94
          Assert(facts.empty());
576
188
          Trace("sets-prop")
577
94
              << "Propagate eq-mem conflict : " << exp << std::endl;
578
94
          facts.push_back(exp);
579
94
          return false;
580
        }
581
      }
582
850
      if (n_members < d_members_data[t1].size())
583
      {
584
627
        d_members_data[t1][n_members] = m2;
585
      }
586
      else
587
      {
588
223
        d_members_data[t1].push_back(m2);
589
      }
590
850
      n_members++;
591
    }
592
  }
593
13676
  d_members[t1] = n_members;
594
13676
  return true;
595
}
596
597
}  // namespace sets
598
}  // namespace theory
599
28194
}  // namespace cvc5