GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/sets/solver_state.cpp Lines: 275 292 94.2 %
Date: 2021-09-29 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
6271
SolverState::SolverState(Env& env, Valuation val, SkolemCache& skc)
30
6271
    : TheoryState(env, val), d_skCache(skc), d_members(env.getContext())
31
{
32
6271
  d_true = NodeManager::currentNM()->mkConst(true);
33
6271
  d_false = NodeManager::currentNM()->mkConst(false);
34
6271
}
35
36
22741
void SolverState::reset()
37
{
38
22741
  d_set_eqc.clear();
39
22741
  d_eqc_emptyset.clear();
40
22741
  d_eqc_univset.clear();
41
22741
  d_eqc_singleton.clear();
42
22741
  d_congruent.clear();
43
22741
  d_nvar_sets.clear();
44
22741
  d_var_set.clear();
45
22741
  d_compSets.clear();
46
22741
  d_pol_mems[0].clear();
47
22741
  d_pol_mems[1].clear();
48
22741
  d_members_index.clear();
49
22741
  d_singleton_index.clear();
50
22741
  d_bop_index.clear();
51
22741
  d_op_list.clear();
52
22741
  d_allCompSets.clear();
53
22741
}
54
55
86919
void SolverState::registerEqc(TypeNode tn, Node r)
56
{
57
86919
  if (tn.isSet())
58
  {
59
28427
    d_set_eqc.push_back(r);
60
  }
61
86919
}
62
63
257011
void SolverState::registerTerm(Node r, TypeNode tnn, Node n)
64
{
65
257011
  Kind nk = n.getKind();
66
257011
  if (nk == MEMBER)
67
  {
68
54033
    if (r.isConst())
69
    {
70
101480
      Node s = d_ee->getRepresentative(n[1]);
71
101480
      Node x = d_ee->getRepresentative(n[0]);
72
50740
      int pindex = r == d_true ? 0 : (r == d_false ? 1 : -1);
73
50740
      if (pindex != -1)
74
      {
75
50740
        if (d_pol_mems[pindex][s].find(x) == d_pol_mems[pindex][s].end())
76
        {
77
38642
          d_pol_mems[pindex][s][x] = n;
78
77284
          Trace("sets-debug2") << "Membership[" << x << "][" << s << "] : " << n
79
38642
                               << ", pindex = " << pindex << std::endl;
80
        }
81
50740
        if (d_members_index[s].find(x) == d_members_index[s].end())
82
        {
83
38642
          d_members_index[s][x] = n;
84
38642
          d_op_list[MEMBER].push_back(n);
85
        }
86
      }
87
      else
88
      {
89
        Assert(false);
90
      }
91
    }
92
  }
93
202978
  else if (nk == SINGLETON || nk == UNION || nk == INTERSECTION
94
184712
           || nk == SETMINUS || nk == EMPTYSET || nk == UNIVERSE_SET)
95
  {
96
30092
    if (nk == SINGLETON)
97
    {
98
8840
      Node re = d_ee->getRepresentative(n[0]);
99
4420
      if (d_singleton_index.find(re) == d_singleton_index.end())
100
      {
101
3900
        d_singleton_index[re] = n;
102
3900
        d_eqc_singleton[r] = n;
103
3900
        d_op_list[SINGLETON].push_back(n);
104
      }
105
      else
106
      {
107
520
        d_congruent[n] = d_singleton_index[re];
108
      }
109
    }
110
25672
    else if (nk == EMPTYSET)
111
    {
112
2021
      d_eqc_emptyset[tnn] = r;
113
    }
114
23651
    else if (nk == UNIVERSE_SET)
115
    {
116
1113
      Assert(options::setsExt());
117
1113
      d_eqc_univset[tnn] = r;
118
    }
119
    else
120
    {
121
45076
      Node r1 = d_ee->getRepresentative(n[0]);
122
45076
      Node r2 = d_ee->getRepresentative(n[1]);
123
22538
      std::map<Node, Node>& binr1 = d_bop_index[nk][r1];
124
22538
      std::map<Node, Node>::iterator itb = binr1.find(r2);
125
22538
      if (itb == binr1.end())
126
      {
127
21388
        binr1[r2] = n;
128
21388
        d_op_list[nk].push_back(n);
129
      }
130
      else
131
      {
132
1150
        d_congruent[n] = itb->second;
133
      }
134
    }
135
30092
    d_nvar_sets[r].push_back(n);
136
30092
    Trace("sets-debug2") << "Non-var-set[" << r << "] : " << n << std::endl;
137
  }
138
172886
  else if (nk == COMPREHENSION)
139
  {
140
44
    d_compSets[r].push_back(n);
141
44
    d_allCompSets.push_back(n);
142
44
    Trace("sets-debug2") << "Comp-set[" << r << "] : " << n << std::endl;
143
  }
144
172842
  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
17492
    if (tnn.isSet())
149
    {
150
13102
      if (d_var_set.find(r) == d_var_set.end())
151
      {
152
12247
        d_var_set[r] = n;
153
12247
        Trace("sets-debug2") << "var-set[" << r << "] : " << n << std::endl;
154
      }
155
    }
156
  }
157
  else
158
  {
159
155350
    Trace("sets-debug2") << "Unknown-set[" << r << "] : " << n << std::endl;
160
  }
161
257011
}
162
163
28107
void SolverState::addEqualityToExp(Node a, Node b, std::vector<Node>& exp) const
164
{
165
28107
  if (a != b)
166
  {
167
9966
    Assert(areEqual(a, b));
168
9966
    exp.push_back(a.eqNode(b));
169
  }
170
28107
}
171
172
8318
Node SolverState::getEmptySetEqClass(TypeNode tn) const
173
{
174
8318
  std::map<TypeNode, Node>::const_iterator it = d_eqc_emptyset.find(tn);
175
8318
  if (it != d_eqc_emptyset.end())
176
  {
177
7376
    return it->second;
178
  }
179
942
  return Node::null();
180
}
181
182
2326
Node SolverState::getUnivSetEqClass(TypeNode tn) const
183
{
184
2326
  std::map<TypeNode, Node>::const_iterator it = d_eqc_univset.find(tn);
185
2326
  if (it != d_eqc_univset.end())
186
  {
187
1795
    return it->second;
188
  }
189
531
  return Node::null();
190
}
191
192
3991
Node SolverState::getSingletonEqClass(Node r) const
193
{
194
3991
  std::map<Node, Node>::const_iterator it = d_eqc_singleton.find(r);
195
3991
  if (it != d_eqc_singleton.end())
196
  {
197
1
    return it->second;
198
  }
199
3990
  return Node::null();
200
}
201
202
127
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
127
      d_bop_index.find(k);
206
127
  if (itk == d_bop_index.end())
207
  {
208
    return Node::null();
209
  }
210
  std::map<Node, std::map<Node, Node> >::const_iterator it1 =
211
127
      itk->second.find(r1);
212
127
  if (it1 == itk->second.end())
213
  {
214
75
    return Node::null();
215
  }
216
52
  std::map<Node, Node>::const_iterator it2 = it1->second.find(r2);
217
52
  if (it2 == it1->second.end())
218
  {
219
34
    return Node::null();
220
  }
221
18
  return it2->second;
222
}
223
224
75370
bool SolverState::isEntailed(Node n, bool polarity) const
225
{
226
75370
  if (n.getKind() == NOT)
227
  {
228
5912
    return isEntailed(n[0], !polarity);
229
  }
230
69458
  else if (n.getKind() == EQUAL)
231
  {
232
4693
    if (polarity)
233
    {
234
4427
      return areEqual(n[0], n[1]);
235
    }
236
266
    return areDisequal(n[0], n[1]);
237
  }
238
64765
  else if (n.getKind() == MEMBER)
239
  {
240
33259
    if (areEqual(n, polarity ? d_true : d_false))
241
    {
242
22901
      return true;
243
    }
244
    // check members cache
245
10358
    if (polarity && d_ee->hasTerm(n[1]))
246
    {
247
15120
      Node r = d_ee->getRepresentative(n[1]);
248
10096
      if (isMember(n[0], r))
249
      {
250
5072
        return true;
251
      }
252
    }
253
  }
254
31506
  else if (n.getKind() == AND || n.getKind() == OR)
255
  {
256
16522
    bool conj = (n.getKind() == AND) == polarity;
257
38739
    for (const Node& nc : n)
258
    {
259
29710
      bool isEnt = isEntailed(nc, polarity);
260
29710
      if (isEnt != conj)
261
      {
262
7493
        return !conj;
263
      }
264
    }
265
9029
    return conj;
266
  }
267
14984
  else if (n.isConst())
268
  {
269
8289
    return (polarity && n == d_true) || (!polarity && n == d_false);
270
  }
271
11981
  return false;
272
}
273
274
3081
bool SolverState::isSetDisequalityEntailed(Node r1, Node r2) const
275
{
276
3081
  Assert(d_ee->hasTerm(r1) && d_ee->getRepresentative(r1) == r1);
277
3081
  Assert(d_ee->hasTerm(r2) && d_ee->getRepresentative(r2) == r2);
278
6162
  TypeNode tn = r1.getType();
279
6162
  Node re = getEmptySetEqClass(tn);
280
4538
  for (unsigned e = 0; e < 2; e++)
281
  {
282
5571
    Node a = e == 0 ? r1 : r2;
283
5571
    Node b = e == 0 ? r2 : r1;
284
4114
    if (isSetDisequalityEntailedInternal(a, b, re))
285
    {
286
2657
      return true;
287
    }
288
  }
289
424
  return false;
290
}
291
292
4114
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
4114
      d_pol_mems[0].find(a);
299
4114
  if (itpma == d_pol_mems[0].end())
300
  {
301
    // no positive members, continue
302
736
    return false;
303
  }
304
  // if b is empty
305
3378
  if (b == re)
306
  {
307
975
    if (!itpma->second.empty())
308
    {
309
1950
      Trace("sets-deq") << "Disequality is satisfied because members are in "
310
975
                        << a << " and " << b << " is empty" << std::endl;
311
975
      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
2403
  std::map<Node, Node>::const_iterator itsb = d_eqc_singleton.find(b);
321
  std::map<Node, std::map<Node, Node> >::const_iterator itpmb =
322
2403
      d_pol_mems[1].find(b);
323
4806
  std::vector<Node> prev;
324
4106
  for (const std::pair<const Node, Node>& itm : itpma->second)
325
  {
326
    // if b is a singleton
327
3385
    if (itsb != d_eqc_singleton.end())
328
    {
329
1377
      if (areDisequal(itm.first, itsb->second[0]))
330
      {
331
2106
        Trace("sets-deq") << "Disequality is satisfied because of "
332
2106
                          << itm.second << ", singleton eq " << itsb->second[0]
333
1053
                          << std::endl;
334
2735
        return true;
335
      }
336
      // or disequal with another member
337
354
      for (const Node& p : prev)
338
      {
339
34
        if (areDisequal(itm.first, p))
340
        {
341
8
          Trace("sets-deq")
342
4
              << "Disequality is satisfied because of disequal members "
343
4
              << itm.first << " " << p << ", singleton eq " << std::endl;
344
4
          return true;
345
        }
346
      }
347
      // if a has positive member that is negative member in b
348
    }
349
2008
    else if (itpmb != d_pol_mems[1].end())
350
    {
351
2408
      for (const std::pair<const Node, Node>& itnm : itpmb->second)
352
      {
353
1764
        if (areEqual(itm.first, itnm.first))
354
        {
355
1250
          Trace("sets-deq") << "Disequality is satisfied because of "
356
625
                            << itm.second << " " << itnm.second << std::endl;
357
625
          return true;
358
        }
359
      }
360
    }
361
1703
    prev.push_back(itm.first);
362
  }
363
721
  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
39811
bool SolverState::isCongruent(Node n) const
377
{
378
39811
  return d_congruent.find(n) != d_congruent.end();
379
}
380
40835
const std::vector<Node>& SolverState::getNonVariableSets(Node r) const
381
{
382
40835
  std::map<Node, std::vector<Node> >::const_iterator it = d_nvar_sets.find(r);
383
40835
  if (it == d_nvar_sets.end())
384
  {
385
11813
    return d_emptyVec;
386
  }
387
29022
  return it->second;
388
}
389
390
11808
Node SolverState::getVariableSet(Node r) const
391
{
392
11808
  std::map<Node, Node>::const_iterator it = d_var_set.find(r);
393
11808
  if (it != d_var_set.end())
394
  {
395
3601
    return it->second;
396
  }
397
8207
  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
56403
const std::map<Node, Node>& SolverState::getMembers(Node r) const
411
{
412
56403
  return getMembersInternal(r, 0);
413
}
414
15741
const std::map<Node, Node>& SolverState::getNegativeMembers(Node r) const
415
{
416
15741
  return getMembersInternal(r, 1);
417
}
418
72144
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
72144
      d_pol_mems[i].find(r);
423
72144
  if (itp == d_pol_mems[i].end())
424
  {
425
22880
    return d_emptyMap;
426
  }
427
49264
  return itp->second;
428
}
429
430
691
bool SolverState::hasMembers(Node r) const
431
{
432
  std::map<Node, std::map<Node, Node> >::const_iterator it =
433
691
      d_pol_mems[0].find(r);
434
691
  if (it == d_pol_mems[0].end())
435
  {
436
250
    return false;
437
  }
438
441
  return !it->second.empty();
439
}
440
const std::map<Kind, std::map<Node, std::map<Node, Node> > >&
441
12829
SolverState::getBinaryOpIndex() const
442
{
443
12829
  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
5237
const std::map<Kind, std::vector<Node> >& SolverState::getOperatorList() const
453
{
454
5237
  return d_op_list;
455
}
456
457
11964
const std::vector<Node>& SolverState::getComprehensionSets() const
458
{
459
11964
  return d_allCompSets;
460
}
461
462
619
const vector<Node> SolverState::getSetsEqClasses(const TypeNode& t) const
463
{
464
619
  vector<Node> representatives;
465
5714
  for (const Node& eqc : getSetsEqClasses())
466
  {
467
5095
    if (eqc.getType().getSetElementType() == t)
468
    {
469
5095
      representatives.push_back(eqc);
470
    }
471
  }
472
619
  return representatives;
473
}
474
475
31079
bool SolverState::isMember(TNode x, TNode s) const
476
{
477
31079
  Assert(hasTerm(s) && getRepresentative(s) == s);
478
31079
  NodeIntMap::const_iterator mem_i = d_members.find(s);
479
31079
  if (mem_i != d_members.end())
480
  {
481
    std::map<Node, std::vector<Node> >::const_iterator itd =
482
27944
        d_members_data.find(s);
483
27944
    Assert(itd != d_members_data.end());
484
27944
    const std::vector<Node>& members = itd->second;
485
27944
    Assert((*mem_i).second <= members.size());
486
57093
    for (size_t i = 0, nmem = (*mem_i).second; i < nmem; i++)
487
    {
488
53833
      if (areEqual(members[i][0], x))
489
      {
490
24684
        return true;
491
      }
492
    }
493
  }
494
6395
  return false;
495
}
496
497
17726
void SolverState::addMember(TNode r, TNode atom)
498
{
499
17726
  NodeIntMap::iterator mem_i = d_members.find(r);
500
17726
  size_t n_members = 0;
501
17726
  if (mem_i != d_members.end())
502
  {
503
11437
    n_members = (*mem_i).second;
504
  }
505
17726
  d_members[r] = n_members + 1;
506
17726
  if (n_members < d_members_data[r].size())
507
  {
508
13772
    d_members_data[r][n_members] = atom;
509
  }
510
  else
511
  {
512
3954
    d_members_data[r].push_back(atom);
513
  }
514
17726
}
515
516
7104
bool SolverState::merge(TNode t1,
517
                        TNode t2,
518
                        std::vector<Node>& facts,
519
                        TNode cset)
520
{
521
7104
  NodeIntMap::iterator mem_i2 = d_members.find(t2);
522
7104
  if (mem_i2 == d_members.end())
523
  {
524
    // no members in t2, we are done
525
4304
    return true;
526
  }
527
2800
  NodeIntMap::iterator mem_i1 = d_members.find(t1);
528
2800
  size_t n_members = 0;
529
2800
  if (mem_i1 != d_members.end())
530
  {
531
2630
    n_members = (*mem_i1).second;
532
  }
533
6400
  for (size_t i = 0, nmem2 = (*mem_i2).second; i < nmem2; i++)
534
  {
535
3646
    Assert(i < d_members_data[t2].size()
536
           && d_members_data[t2][i].getKind() == MEMBER);
537
7246
    Node m2 = d_members_data[t2][i];
538
    // check if redundant
539
3646
    bool add = true;
540
5237
    for (size_t j = 0; j < n_members; j++)
541
    {
542
4758
      Assert(j < d_members_data[t1].size()
543
             && d_members_data[t1][j].getKind() == MEMBER);
544
4758
      if (areEqual(m2[0], d_members_data[t1][j][0]))
545
      {
546
3167
        add = false;
547
3167
        break;
548
      }
549
    }
550
3646
    if (add)
551
    {
552
      // if there is a concrete set in t1, propagate new facts or conflicts
553
479
      if (!cset.isNull())
554
      {
555
160
        NodeManager* nm = NodeManager::currentNM();
556
160
        Assert(areEqual(m2[1], cset));
557
274
        Node exp = nm->mkNode(AND, m2[1].eqNode(cset), m2);
558
160
        if (cset.getKind() == SINGLETON)
559
        {
560
114
          if (cset[0] != m2[0])
561
          {
562
228
            Node eq = cset[0].eqNode(m2[0]);
563
228
            Trace("sets-prop") << "Propagate eq-mem eq inference : " << exp
564
114
                               << " => " << eq << std::endl;
565
228
            Node fact = nm->mkNode(IMPLIES, exp, eq);
566
114
            facts.push_back(fact);
567
          }
568
        }
569
        else
570
        {
571
          // conflict
572
46
          Assert(facts.empty());
573
92
          Trace("sets-prop")
574
46
              << "Propagate eq-mem conflict : " << exp << std::endl;
575
46
          facts.push_back(exp);
576
46
          return false;
577
        }
578
      }
579
433
      if (n_members < d_members_data[t1].size())
580
      {
581
328
        d_members_data[t1][n_members] = m2;
582
      }
583
      else
584
      {
585
105
        d_members_data[t1].push_back(m2);
586
      }
587
433
      n_members++;
588
    }
589
  }
590
2754
  d_members[t1] = n_members;
591
2754
  return true;
592
}
593
594
}  // namespace sets
595
}  // namespace theory
596
22746
}  // namespace cvc5