GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/sets/solver_state.cpp Lines: 275 292 94.2 %
Date: 2021-09-18 Branches: 579 1216 47.6 %

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
9940
SolverState::SolverState(Env& env, Valuation val, SkolemCache& skc)
30
9940
    : TheoryState(env, val), d_skCache(skc), d_members(env.getContext())
31
{
32
9940
  d_true = NodeManager::currentNM()->mkConst(true);
33
9940
  d_false = NodeManager::currentNM()->mkConst(false);
34
9940
}
35
36
35837
void SolverState::reset()
37
{
38
35837
  d_set_eqc.clear();
39
35837
  d_eqc_emptyset.clear();
40
35837
  d_eqc_univset.clear();
41
35837
  d_eqc_singleton.clear();
42
35837
  d_congruent.clear();
43
35837
  d_nvar_sets.clear();
44
35837
  d_var_set.clear();
45
35837
  d_compSets.clear();
46
35837
  d_pol_mems[0].clear();
47
35837
  d_pol_mems[1].clear();
48
35837
  d_members_index.clear();
49
35837
  d_singleton_index.clear();
50
35837
  d_bop_index.clear();
51
35837
  d_op_list.clear();
52
35837
  d_allCompSets.clear();
53
35837
}
54
55
161155
void SolverState::registerEqc(TypeNode tn, Node r)
56
{
57
161155
  if (tn.isSet())
58
  {
59
54193
    d_set_eqc.push_back(r);
60
  }
61
161155
}
62
63
531600
void SolverState::registerTerm(Node r, TypeNode tnn, Node n)
64
{
65
531600
  Kind nk = n.getKind();
66
531600
  if (nk == MEMBER)
67
  {
68
123818
    if (r.isConst())
69
    {
70
235140
      Node s = d_ee->getRepresentative(n[1]);
71
235140
      Node x = d_ee->getRepresentative(n[0]);
72
117570
      int pindex = r == d_true ? 0 : (r == d_false ? 1 : -1);
73
117570
      if (pindex != -1)
74
      {
75
117570
        if (d_pol_mems[pindex][s].find(x) == d_pol_mems[pindex][s].end())
76
        {
77
84193
          d_pol_mems[pindex][s][x] = n;
78
168386
          Trace("sets-debug2") << "Membership[" << x << "][" << s << "] : " << n
79
84193
                               << ", pindex = " << pindex << std::endl;
80
        }
81
117570
        if (d_members_index[s].find(x) == d_members_index[s].end())
82
        {
83
84193
          d_members_index[s][x] = n;
84
84193
          d_op_list[MEMBER].push_back(n);
85
        }
86
      }
87
      else
88
      {
89
        Assert(false);
90
      }
91
    }
92
  }
93
407782
  else if (nk == SINGLETON || nk == UNION || nk == INTERSECTION
94
370790
           || nk == SETMINUS || nk == EMPTYSET || nk == UNIVERSE_SET)
95
  {
96
63918
    if (nk == SINGLETON)
97
    {
98
17696
      Node re = d_ee->getRepresentative(n[0]);
99
8848
      if (d_singleton_index.find(re) == d_singleton_index.end())
100
      {
101
6707
        d_singleton_index[re] = n;
102
6707
        d_eqc_singleton[r] = n;
103
6707
        d_op_list[SINGLETON].push_back(n);
104
      }
105
      else
106
      {
107
2141
        d_congruent[n] = d_singleton_index[re];
108
      }
109
    }
110
55070
    else if (nk == EMPTYSET)
111
    {
112
3753
      d_eqc_emptyset[tnn] = r;
113
    }
114
51317
    else if (nk == UNIVERSE_SET)
115
    {
116
1897
      Assert(options::setsExt());
117
1897
      d_eqc_univset[tnn] = r;
118
    }
119
    else
120
    {
121
98840
      Node r1 = d_ee->getRepresentative(n[0]);
122
98840
      Node r2 = d_ee->getRepresentative(n[1]);
123
49420
      std::map<Node, Node>& binr1 = d_bop_index[nk][r1];
124
49420
      std::map<Node, Node>::iterator itb = binr1.find(r2);
125
49420
      if (itb == binr1.end())
126
      {
127
46455
        binr1[r2] = n;
128
46455
        d_op_list[nk].push_back(n);
129
      }
130
      else
131
      {
132
2965
        d_congruent[n] = itb->second;
133
      }
134
    }
135
63918
    d_nvar_sets[r].push_back(n);
136
63918
    Trace("sets-debug2") << "Non-var-set[" << r << "] : " << n << std::endl;
137
  }
138
343864
  else if (nk == COMPREHENSION)
139
  {
140
140
    d_compSets[r].push_back(n);
141
140
    d_allCompSets.push_back(n);
142
140
    Trace("sets-debug2") << "Comp-set[" << r << "] : " << n << std::endl;
143
  }
144
343724
  else if (n.isVar() && !d_skCache.isSkolem(n))
145
  {
146
    // it is important that we check it is a variable, but not an internally
147
    // introduced skolem, due to the semantics of the universe set.
148
32405
    if (tnn.isSet())
149
    {
150
22501
      if (d_var_set.find(r) == d_var_set.end())
151
      {
152
20787
        d_var_set[r] = n;
153
20787
        Trace("sets-debug2") << "var-set[" << r << "] : " << n << std::endl;
154
      }
155
    }
156
  }
157
  else
158
  {
159
311319
    Trace("sets-debug2") << "Unknown-set[" << r << "] : " << n << std::endl;
160
  }
161
531600
}
162
163
67281
void SolverState::addEqualityToExp(Node a, Node b, std::vector<Node>& exp) const
164
{
165
67281
  if (a != b)
166
  {
167
19894
    Assert(areEqual(a, b));
168
19894
    exp.push_back(a.eqNode(b));
169
  }
170
67281
}
171
172
14531
Node SolverState::getEmptySetEqClass(TypeNode tn) const
173
{
174
14531
  std::map<TypeNode, Node>::const_iterator it = d_eqc_emptyset.find(tn);
175
14531
  if (it != d_eqc_emptyset.end())
176
  {
177
13163
    return it->second;
178
  }
179
1368
  return Node::null();
180
}
181
182
3704
Node SolverState::getUnivSetEqClass(TypeNode tn) const
183
{
184
3704
  std::map<TypeNode, Node>::const_iterator it = d_eqc_univset.find(tn);
185
3704
  if (it != d_eqc_univset.end())
186
  {
187
2804
    return it->second;
188
  }
189
900
  return Node::null();
190
}
191
192
8027
Node SolverState::getSingletonEqClass(Node r) const
193
{
194
8027
  std::map<Node, Node>::const_iterator it = d_eqc_singleton.find(r);
195
8027
  if (it != d_eqc_singleton.end())
196
  {
197
4
    return it->second;
198
  }
199
8023
  return Node::null();
200
}
201
202
234
Node SolverState::getBinaryOpTerm(Kind k, Node r1, Node r2) const
203
{
204
  std::map<Kind, std::map<Node, std::map<Node, Node> > >::const_iterator itk =
205
234
      d_bop_index.find(k);
206
234
  if (itk == d_bop_index.end())
207
  {
208
    return Node::null();
209
  }
210
  std::map<Node, std::map<Node, Node> >::const_iterator it1 =
211
234
      itk->second.find(r1);
212
234
  if (it1 == itk->second.end())
213
  {
214
136
    return Node::null();
215
  }
216
98
  std::map<Node, Node>::const_iterator it2 = it1->second.find(r2);
217
98
  if (it2 == it1->second.end())
218
  {
219
62
    return Node::null();
220
  }
221
36
  return it2->second;
222
}
223
224
167976
bool SolverState::isEntailed(Node n, bool polarity) const
225
{
226
167976
  if (n.getKind() == NOT)
227
  {
228
15524
    return isEntailed(n[0], !polarity);
229
  }
230
152452
  else if (n.getKind() == EQUAL)
231
  {
232
8118
    if (polarity)
233
    {
234
7334
      return areEqual(n[0], n[1]);
235
    }
236
784
    return areDisequal(n[0], n[1]);
237
  }
238
144334
  else if (n.getKind() == MEMBER)
239
  {
240
80160
    if (areEqual(n, polarity ? d_true : d_false))
241
    {
242
56591
      return true;
243
    }
244
    // check members cache
245
23569
    if (polarity && d_ee->hasTerm(n[1]))
246
    {
247
34047
      Node r = d_ee->getRepresentative(n[1]);
248
22751
      if (isMember(n[0], r))
249
      {
250
11455
        return true;
251
      }
252
    }
253
  }
254
64174
  else if (n.getKind() == AND || n.getKind() == OR)
255
  {
256
39950
    bool conj = (n.getKind() == AND) == polarity;
257
98060
    for (const Node& nc : n)
258
    {
259
73704
      bool isEnt = isEntailed(nc, polarity);
260
73704
      if (isEnt != conj)
261
      {
262
15594
        return !conj;
263
      }
264
    }
265
24356
    return conj;
266
  }
267
24224
  else if (n.isConst())
268
  {
269
12004
    return (polarity && n == d_true) || (!polarity && n == d_false);
270
  }
271
24334
  return false;
272
}
273
274
5411
bool SolverState::isSetDisequalityEntailed(Node r1, Node r2) const
275
{
276
5411
  Assert(d_ee->hasTerm(r1) && d_ee->getRepresentative(r1) == r1);
277
5411
  Assert(d_ee->hasTerm(r2) && d_ee->getRepresentative(r2) == r2);
278
10822
  TypeNode tn = r1.getType();
279
10822
  Node re = getEmptySetEqClass(tn);
280
7774
  for (unsigned e = 0; e < 2; e++)
281
  {
282
9405
    Node a = e == 0 ? r1 : r2;
283
9405
    Node b = e == 0 ? r2 : r1;
284
7042
    if (isSetDisequalityEntailedInternal(a, b, re))
285
    {
286
4679
      return true;
287
    }
288
  }
289
732
  return false;
290
}
291
292
7042
bool SolverState::isSetDisequalityEntailedInternal(Node a,
293
                                                   Node b,
294
                                                   Node re) const
295
{
296
  // if there are members in a
297
  std::map<Node, std::map<Node, Node> >::const_iterator itpma =
298
7042
      d_pol_mems[0].find(a);
299
7042
  if (itpma == d_pol_mems[0].end())
300
  {
301
    // no positive members, continue
302
1360
    return false;
303
  }
304
  // if b is empty
305
5682
  if (b == re)
306
  {
307
2323
    if (!itpma->second.empty())
308
    {
309
4646
      Trace("sets-deq") << "Disequality is satisfied because members are in "
310
2323
                        << a << " and " << b << " is empty" << std::endl;
311
2323
      return true;
312
    }
313
    else
314
    {
315
      // a should not be singleton
316
      Assert(d_eqc_singleton.find(a) == d_eqc_singleton.end());
317
    }
318
    return false;
319
  }
320
3359
  std::map<Node, Node>::const_iterator itsb = d_eqc_singleton.find(b);
321
  std::map<Node, std::map<Node, Node> >::const_iterator itpmb =
322
3359
      d_pol_mems[1].find(b);
323
6718
  std::vector<Node> prev;
324
5783
  for (const std::pair<const Node, Node>& itm : itpma->second)
325
  {
326
    // if b is a singleton
327
4780
    if (itsb != d_eqc_singleton.end())
328
    {
329
1714
      if (areDisequal(itm.first, itsb->second[0]))
330
      {
331
2462
        Trace("sets-deq") << "Disequality is satisfied because of "
332
2462
                          << itm.second << ", singleton eq " << itsb->second[0]
333
1231
                          << std::endl;
334
3587
        return true;
335
      }
336
      // or disequal with another member
337
574
      for (const Node& p : prev)
338
      {
339
102
        if (areDisequal(itm.first, p))
340
        {
341
22
          Trace("sets-deq")
342
11
              << "Disequality is satisfied because of disequal members "
343
11
              << itm.first << " " << p << ", singleton eq " << std::endl;
344
11
          return true;
345
        }
346
      }
347
      // if a has positive member that is negative member in b
348
    }
349
3066
    else if (itpmb != d_pol_mems[1].end())
350
    {
351
4068
      for (const std::pair<const Node, Node>& itnm : itpmb->second)
352
      {
353
3101
        if (areEqual(itm.first, itnm.first))
354
        {
355
2228
          Trace("sets-deq") << "Disequality is satisfied because of "
356
1114
                            << itm.second << " " << itnm.second << std::endl;
357
1114
          return true;
358
        }
359
      }
360
    }
361
2424
    prev.push_back(itm.first);
362
  }
363
1003
  return false;
364
}
365
366
Node SolverState::getCongruent(Node n) const
367
{
368
  Assert(d_ee->hasTerm(n));
369
  std::map<Node, Node>::const_iterator it = d_congruent.find(n);
370
  if (it == d_congruent.end())
371
  {
372
    return n;
373
  }
374
  return it->second;
375
}
376
82748
bool SolverState::isCongruent(Node n) const
377
{
378
82748
  return d_congruent.find(n) != d_congruent.end();
379
}
380
76594
const std::vector<Node>& SolverState::getNonVariableSets(Node r) const
381
{
382
76594
  std::map<Node, std::vector<Node> >::const_iterator it = d_nvar_sets.find(r);
383
76594
  if (it == d_nvar_sets.end())
384
  {
385
18131
    return d_emptyVec;
386
  }
387
58463
  return it->second;
388
}
389
390
21887
Node SolverState::getVariableSet(Node r) const
391
{
392
21887
  std::map<Node, Node>::const_iterator it = d_var_set.find(r);
393
21887
  if (it != d_var_set.end())
394
  {
395
6213
    return it->second;
396
  }
397
15674
  return Node::null();
398
}
399
400
const std::vector<Node>& SolverState::getComprehensionSets(Node r) const
401
{
402
  std::map<Node, std::vector<Node> >::const_iterator it = d_compSets.find(r);
403
  if (it == d_compSets.end())
404
  {
405
    return d_emptyVec;
406
  }
407
  return it->second;
408
}
409
410
113296
const std::map<Node, Node>& SolverState::getMembers(Node r) const
411
{
412
113296
  return getMembersInternal(r, 0);
413
}
414
32065
const std::map<Node, Node>& SolverState::getNegativeMembers(Node r) const
415
{
416
32065
  return getMembersInternal(r, 1);
417
}
418
145361
const std::map<Node, Node>& SolverState::getMembersInternal(Node r,
419
                                                            unsigned i) const
420
{
421
  std::map<Node, std::map<Node, Node> >::const_iterator itp =
422
145361
      d_pol_mems[i].find(r);
423
145361
  if (itp == d_pol_mems[i].end())
424
  {
425
46072
    return d_emptyMap;
426
  }
427
99289
  return itp->second;
428
}
429
430
1137
bool SolverState::hasMembers(Node r) const
431
{
432
  std::map<Node, std::map<Node, Node> >::const_iterator it =
433
1137
      d_pol_mems[0].find(r);
434
1137
  if (it == d_pol_mems[0].end())
435
  {
436
387
    return false;
437
  }
438
750
  return !it->second.empty();
439
}
440
const std::map<Kind, std::map<Node, std::map<Node, Node> > >&
441
19495
SolverState::getBinaryOpIndex() const
442
{
443
19495
  return d_bop_index;
444
}
445
446
const std::map<Node, std::map<Node, Node>>& SolverState::getBinaryOpIndex(
447
    Kind k)
448
{
449
  return d_bop_index[k];
450
}
451
452
6398
const std::map<Kind, std::vector<Node> >& SolverState::getOperatorList() const
453
{
454
6398
  return d_op_list;
455
}
456
457
17738
const std::vector<Node>& SolverState::getComprehensionSets() const
458
{
459
17738
  return d_allCompSets;
460
}
461
462
986
const vector<Node> SolverState::getSetsEqClasses(const TypeNode& t) const
463
{
464
986
  vector<Node> representatives;
465
9954
  for (const Node& eqc : getSetsEqClasses())
466
  {
467
8968
    if (eqc.getType().getSetElementType() == t)
468
    {
469
8968
      representatives.push_back(eqc);
470
    }
471
  }
472
986
  return representatives;
473
}
474
475
66375
bool SolverState::isMember(TNode x, TNode s) const
476
{
477
66375
  Assert(hasTerm(s) && getRepresentative(s) == s);
478
66375
  NodeIntMap::const_iterator mem_i = d_members.find(s);
479
66375
  if (mem_i != d_members.end())
480
  {
481
    std::map<Node, std::vector<Node> >::const_iterator itd =
482
59374
        d_members_data.find(s);
483
59374
    Assert(itd != d_members_data.end());
484
59374
    const std::vector<Node>& members = itd->second;
485
59374
    Assert((*mem_i).second <= members.size());
486
128745
    for (size_t i = 0, nmem = (*mem_i).second; i < nmem; i++)
487
    {
488
121550
      if (areEqual(members[i][0], x))
489
      {
490
52179
        return true;
491
      }
492
    }
493
  }
494
14196
  return false;
495
}
496
497
63606
void SolverState::addMember(TNode r, TNode atom)
498
{
499
63606
  NodeIntMap::iterator mem_i = d_members.find(r);
500
63606
  size_t n_members = 0;
501
63606
  if (mem_i != d_members.end())
502
  {
503
47244
    n_members = (*mem_i).second;
504
  }
505
63606
  d_members[r] = n_members + 1;
506
63606
  if (n_members < d_members_data[r].size())
507
  {
508
53061
    d_members_data[r][n_members] = atom;
509
  }
510
  else
511
  {
512
10545
    d_members_data[r].push_back(atom);
513
  }
514
63606
}
515
516
27967
bool SolverState::merge(TNode t1,
517
                        TNode t2,
518
                        std::vector<Node>& facts,
519
                        TNode cset)
520
{
521
27967
  NodeIntMap::iterator mem_i2 = d_members.find(t2);
522
27967
  if (mem_i2 == d_members.end())
523
  {
524
    // no members in t2, we are done
525
12234
    return true;
526
  }
527
15733
  NodeIntMap::iterator mem_i1 = d_members.find(t1);
528
15733
  size_t n_members = 0;
529
15733
  if (mem_i1 != d_members.end())
530
  {
531
15336
    n_members = (*mem_i1).second;
532
  }
533
32693
  for (size_t i = 0, nmem2 = (*mem_i2).second; i < nmem2; i++)
534
  {
535
17065
    Assert(i < d_members_data[t2].size()
536
           && d_members_data[t2][i].getKind() == MEMBER);
537
34025
    Node m2 = d_members_data[t2][i];
538
    // check if redundant
539
17065
    bool add = true;
540
20201
    for (size_t j = 0; j < n_members; j++)
541
    {
542
19289
      Assert(j < d_members_data[t1].size()
543
             && d_members_data[t1][j].getKind() == MEMBER);
544
19289
      if (areEqual(m2[0], d_members_data[t1][j][0]))
545
      {
546
16153
        add = false;
547
16153
        break;
548
      }
549
    }
550
17065
    if (add)
551
    {
552
      // if there is a concrete set in t1, propagate new facts or conflicts
553
912
      if (!cset.isNull())
554
      {
555
234
        NodeManager* nm = NodeManager::currentNM();
556
234
        Assert(areEqual(m2[1], cset));
557
363
        Node exp = nm->mkNode(AND, m2[1].eqNode(cset), m2);
558
234
        if (cset.getKind() == SINGLETON)
559
        {
560
129
          if (cset[0] != m2[0])
561
          {
562
258
            Node eq = cset[0].eqNode(m2[0]);
563
258
            Trace("sets-prop") << "Propagate eq-mem eq inference : " << exp
564
129
                               << " => " << eq << std::endl;
565
258
            Node fact = nm->mkNode(IMPLIES, exp, eq);
566
129
            facts.push_back(fact);
567
          }
568
        }
569
        else
570
        {
571
          // conflict
572
105
          Assert(facts.empty());
573
210
          Trace("sets-prop")
574
105
              << "Propagate eq-mem conflict : " << exp << std::endl;
575
105
          facts.push_back(exp);
576
105
          return false;
577
        }
578
      }
579
807
      if (n_members < d_members_data[t1].size())
580
      {
581
582
        d_members_data[t1][n_members] = m2;
582
      }
583
      else
584
      {
585
225
        d_members_data[t1].push_back(m2);
586
      }
587
807
      n_members++;
588
    }
589
  }
590
15628
  d_members[t1] = n_members;
591
15628
  return true;
592
}
593
594
}  // namespace sets
595
}  // namespace theory
596
29574
}  // namespace cvc5