GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/sets/theory_sets_private.cpp Lines: 671 714 94.0 %
Date: 2021-08-16 Branches: 1469 3123 47.0 %

Line Exec Source
1
/******************************************************************************
2
 * Top contributors (to current version):
3
 *   Andrew Reynolds, Mudathir Mohamed, Kshitij Bansal
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
 * Sets theory implementation.
14
 */
15
16
#include "theory/sets/theory_sets_private.h"
17
18
#include <algorithm>
19
#include <climits>
20
21
#include "expr/emptyset.h"
22
#include "expr/node_algorithm.h"
23
#include "expr/skolem_manager.h"
24
#include "options/sets_options.h"
25
#include "smt/smt_statistics_registry.h"
26
#include "theory/sets/normal_form.h"
27
#include "theory/sets/theory_sets.h"
28
#include "theory/theory_model.h"
29
#include "util/rational.h"
30
#include "util/result.h"
31
32
using namespace std;
33
using namespace cvc5::kind;
34
35
namespace cvc5 {
36
namespace theory {
37
namespace sets {
38
39
9853
TheorySetsPrivate::TheorySetsPrivate(TheorySets& external,
40
                                     SolverState& state,
41
                                     InferenceManager& im,
42
                                     SkolemCache& skc,
43
9853
                                     ProofNodeManager* pnm)
44
    : d_deq(state.getSatContext()),
45
9853
      d_termProcessed(state.getUserContext()),
46
      d_fullCheckIncomplete(false),
47
      d_fullCheckIncompleteId(IncompleteId::UNKNOWN),
48
      d_external(external),
49
      d_state(state),
50
      d_im(im),
51
      d_skCache(skc),
52
      d_treg(state, im, skc, pnm),
53
9853
      d_rels(new TheorySetsRels(state, im, skc, d_treg)),
54
9853
      d_cardSolver(new CardinalityExtension(state, im, d_treg)),
55
      d_rels_enabled(false),
56
39412
      d_card_enabled(false)
57
{
58
9853
  d_true = NodeManager::currentNM()->mkConst(true);
59
9853
  d_false = NodeManager::currentNM()->mkConst(false);
60
9853
  d_zero = NodeManager::currentNM()->mkConst(Rational(0));
61
9853
}
62
63
19706
TheorySetsPrivate::~TheorySetsPrivate()
64
{
65
14736
  for (std::pair<const Node, EqcInfo*>& current_pair : d_eqc_info)
66
  {
67
4883
    delete current_pair.second;
68
  }
69
9853
}
70
71
9853
void TheorySetsPrivate::finishInit()
72
{
73
9853
  d_equalityEngine = d_external.getEqualityEngine();
74
9853
  Assert(d_equalityEngine != nullptr);
75
9853
}
76
77
84337
void TheorySetsPrivate::eqNotifyNewClass(TNode t)
78
{
79
84337
  if (t.getKind() == kind::SINGLETON || t.getKind() == kind::EMPTYSET)
80
  {
81
3603
    EqcInfo* e = getOrMakeEqcInfo(t, true);
82
3603
    e->d_singleton = t;
83
  }
84
84337
}
85
86
266534
void TheorySetsPrivate::eqNotifyMerge(TNode t1, TNode t2)
87
{
88
266534
  if (!d_state.isInConflict() && t1.getType().isSet())
89
  {
90
56082
    Trace("sets-prop-debug")
91
28041
        << "Merge " << t1 << " and " << t2 << "..." << std::endl;
92
55907
    Node s1, s2;
93
28041
    EqcInfo* e2 = getOrMakeEqcInfo(t2);
94
28041
    if (e2)
95
    {
96
17419
      s2 = e2->d_singleton;
97
17419
      EqcInfo* e1 = getOrMakeEqcInfo(t1);
98
17419
      Trace("sets-prop-debug") << "Merging singletons..." << std::endl;
99
17419
      if (e1)
100
      {
101
17300
        s1 = e1->d_singleton;
102
17300
        if (!s1.isNull() && !s2.isNull())
103
        {
104
13794
          if (s1.getKind() == s2.getKind())
105
          {
106
27448
            Trace("sets-prop") << "Propagate eq inference : " << s1
107
13724
                               << " == " << s2 << std::endl;
108
            // infer equality between elements of singleton
109
27448
            Node exp = s1.eqNode(s2);
110
27448
            Node eq = s1[0].eqNode(s2[0]);
111
13724
            d_im.assertSetsFact(eq, true, InferenceId::SETS_SINGLETON_EQ, exp);
112
          }
113
          else
114
          {
115
            // singleton equal to emptyset, conflict
116
140
            Trace("sets-prop")
117
70
                << "Propagate conflict : " << s1 << " == " << s2 << std::endl;
118
140
            Node eqs = s1.eqNode(s2);
119
70
            d_im.conflict(eqs, InferenceId::SETS_EQ_CONFLICT);
120
70
            return;
121
          }
122
        }
123
      }
124
      else
125
      {
126
        // copy information
127
119
        e1 = getOrMakeEqcInfo(t1, true);
128
119
        e1->d_singleton.set(e2->d_singleton);
129
      }
130
    }
131
    // merge membership list
132
27971
    Trace("sets-prop-debug") << "Copying membership list..." << std::endl;
133
    // if s1 has a singleton or empty set and s2 does not, we may have new
134
    // inferences to process.
135
55837
    Node checkSingleton = s2.isNull() ? s1 : Node::null();
136
55837
    std::vector<Node> facts;
137
    // merge the membership list in the state, which may produce facts or
138
    // conflicts to propagate
139
27971
    if (!d_state.merge(t1, t2, facts, checkSingleton))
140
    {
141
      // conflict case
142
105
      Assert(facts.size() == 1);
143
210
      Trace("sets-prop") << "Propagate eq-mem conflict : " << facts[0]
144
105
                         << std::endl;
145
105
      d_im.conflict(facts[0], InferenceId::SETS_EQ_MEM_CONFLICT);
146
105
      return;
147
    }
148
27995
    for (const Node& f : facts)
149
    {
150
129
      Assert(f.getKind() == kind::IMPLIES);
151
258
      Trace("sets-prop") << "Propagate eq-mem eq inference : " << f[0] << " => "
152
129
                         << f[1] << std::endl;
153
129
      d_im.assertSetsFact(f[1], true, InferenceId::SETS_EQ_MEM, f[0]);
154
    }
155
  }
156
}
157
158
33876
void TheorySetsPrivate::eqNotifyDisequal(TNode t1, TNode t2, TNode reason)
159
{
160
33876
  if (t1.getType().isSet())
161
  {
162
20726
    Node eq = t1.eqNode(t2);
163
10363
    if (d_deq.find(eq) == d_deq.end())
164
    {
165
10363
      d_deq[eq] = true;
166
    }
167
  }
168
33876
}
169
170
4883
TheorySetsPrivate::EqcInfo::EqcInfo(context::Context* c) : d_singleton(c) {}
171
172
112996
TheorySetsPrivate::EqcInfo* TheorySetsPrivate::getOrMakeEqcInfo(TNode n,
173
                                                                bool doMake)
174
{
175
112996
  std::map<Node, EqcInfo*>::iterator eqc_i = d_eqc_info.find(n);
176
112996
  if (eqc_i == d_eqc_info.end())
177
  {
178
15624
    EqcInfo* ei = NULL;
179
15624
    if (doMake)
180
    {
181
4883
      ei = new EqcInfo(d_external.getSatContext());
182
4883
      d_eqc_info[n] = ei;
183
    }
184
15624
    return ei;
185
  }
186
  else
187
  {
188
97372
    return eqc_i->second;
189
  }
190
}
191
192
35403
bool TheorySetsPrivate::areCareDisequal(Node a, Node b)
193
{
194
106209
  if (d_equalityEngine->isTriggerTerm(a, THEORY_SETS)
195
106209
      && d_equalityEngine->isTriggerTerm(b, THEORY_SETS))
196
  {
197
    TNode a_shared =
198
34398
        d_equalityEngine->getTriggerTermRepresentative(a, THEORY_SETS);
199
    TNode b_shared =
200
34398
        d_equalityEngine->getTriggerTermRepresentative(b, THEORY_SETS);
201
    EqualityStatus eqStatus =
202
19847
        d_external.d_valuation.getEqualityStatus(a_shared, b_shared);
203
19847
    if (eqStatus == EQUALITY_FALSE_AND_PROPAGATED || eqStatus == EQUALITY_FALSE
204
19847
        || eqStatus == EQUALITY_FALSE_IN_MODEL)
205
    {
206
5296
      return true;
207
    }
208
  }
209
30107
  return false;
210
}
211
212
20143
void TheorySetsPrivate::fullEffortReset()
213
{
214
20143
  Assert(d_equalityEngine->consistent());
215
20143
  d_fullCheckIncomplete = false;
216
20143
  d_fullCheckIncompleteId = IncompleteId::UNKNOWN;
217
20143
  d_most_common_type.clear();
218
20143
  d_most_common_type_term.clear();
219
20143
  d_card_enabled = false;
220
20143
  d_rels_enabled = false;
221
  // reset the state object
222
20143
  d_state.reset();
223
  // reset the inference manager
224
20143
  d_im.reset();
225
20143
  d_im.clearPendingLemmas();
226
  // reset the cardinality solver
227
20143
  d_cardSolver->reset();
228
20143
}
229
230
20143
void TheorySetsPrivate::fullEffortCheck()
231
{
232
20143
  Trace("sets") << "----- Full effort check ------" << std::endl;
233
  do
234
  {
235
20143
    Assert(!d_im.hasPendingLemma() || d_im.hasSent());
236
237
20143
    Trace("sets") << "...iterate full effort check..." << std::endl;
238
20143
    fullEffortReset();
239
240
20143
    Trace("sets-eqc") << "Equality Engine:" << std::endl;
241
35775
    std::map<TypeNode, unsigned> eqcTypeCount;
242
20143
    eq::EqClassesIterator eqcs_i = eq::EqClassesIterator(d_equalityEngine);
243
342521
    while (!eqcs_i.isFinished())
244
    {
245
322378
      Node eqc = (*eqcs_i);
246
161189
      bool isSet = false;
247
322378
      TypeNode tn = eqc.getType();
248
161189
      d_state.registerEqc(tn, eqc);
249
161189
      eqcTypeCount[tn]++;
250
      // common type node and term
251
322378
      TypeNode tnc;
252
322378
      Node tnct;
253
161189
      if (tn.isSet())
254
      {
255
54121
        isSet = true;
256
54121
        tnc = tn.getSetElementType();
257
54121
        tnct = eqc;
258
      }
259
161189
      Trace("sets-eqc") << "[" << eqc << "] : ";
260
161189
      eq::EqClassIterator eqc_i = eq::EqClassIterator(eqc, d_equalityEngine);
261
1235001
      while (!eqc_i.isFinished())
262
      {
263
1074947
        Node n = (*eqc_i);
264
538041
        if (n != eqc)
265
        {
266
376852
          Trace("sets-eqc") << n << " (" << n.isConst() << ") ";
267
        }
268
1074947
        TypeNode tnn = n.getType();
269
538041
        if (isSet)
270
        {
271
141126
          Assert(tnn.isSet());
272
282252
          TypeNode tnnel = tnn.getSetElementType();
273
141126
          tnc = TypeNode::mostCommonTypeNode(tnc, tnnel);
274
141126
          Assert(!tnc.isNull());
275
          // update the common type term
276
141126
          if (tnc == tnnel)
277
          {
278
141126
            tnct = n;
279
          }
280
        }
281
        // register it with the state
282
538041
        d_state.registerTerm(eqc, tnn, n);
283
538041
        Kind nk = n.getKind();
284
538041
        if (nk == kind::SINGLETON)
285
        {
286
          // ensure the proxy has been introduced
287
8848
          d_treg.getProxy(n);
288
        }
289
529193
        else if (nk == kind::CARD)
290
        {
291
52846
          d_card_enabled = true;
292
          // register it with the cardinality solver
293
52846
          d_cardSolver->registerTerm(n);
294
52846
          if (d_im.hasSent())
295
          {
296
1135
            break;
297
          }
298
          // if we do not handle the kind, set incomplete
299
51711
          Kind nk0 = n[0].getKind();
300
          // some kinds of cardinality we cannot handle
301
51711
          if (d_rels->isRelationKind(nk0))
302
          {
303
28
            d_fullCheckIncomplete = true;
304
28
            d_fullCheckIncompleteId = IncompleteId::SETS_RELS_CARD;
305
56
            Trace("sets-incomplete")
306
28
                << "Sets : incomplete because of " << n << "." << std::endl;
307
            // TODO (#1124):  The issue can be divided into 4 parts
308
            // 1- Supporting the universe cardinality for finite types with
309
            // finite cardinality (done)
310
            // 2- Supporting the universe cardinality for uninterpreted sorts
311
            // with finite-model-find (pending) See the implementation of
312
            //    CardinalityExtension::checkCardinalityExtended
313
            // 3- Supporting the universe cardinality for non-finite types
314
            // (done)
315
            // 4- Supporting cardinality for relations (hard)
316
          }
317
        }
318
476347
        else if (d_rels->isRelationKind(nk))
319
        {
320
2266
          d_rels_enabled = true;
321
        }
322
536906
        ++eqc_i;
323
      }
324
161189
      if (isSet)
325
      {
326
54121
        Assert(tnct.getType().getSetElementType() == tnc);
327
54121
        d_most_common_type[eqc] = tnc;
328
54121
        d_most_common_type_term[eqc] = tnct;
329
      }
330
161189
      Trace("sets-eqc") << std::endl;
331
161189
      ++eqcs_i;
332
    }
333
334
20143
    Trace("sets-eqc") << "...finished equality engine." << std::endl;
335
336
20143
    if (Trace.isOn("sets-state"))
337
    {
338
      Trace("sets-state") << "Equivalence class counters:" << std::endl;
339
      for (std::pair<const TypeNode, unsigned>& ec : eqcTypeCount)
340
      {
341
        Trace("sets-state")
342
            << "  " << ec.first << " -> " << ec.second << std::endl;
343
      }
344
    }
345
346
    // We may have sent lemmas while registering the terms in the loop above,
347
    // e.g. the cardinality solver.
348
20143
    if (d_im.hasSent())
349
    {
350
532
      continue;
351
    }
352
19611
    if (Trace.isOn("sets-mem"))
353
    {
354
      const std::vector<Node>& sec = d_state.getSetsEqClasses();
355
      for (const Node& s : sec)
356
      {
357
        Trace("sets-mem") << "Eqc " << s << " : ";
358
        const std::map<Node, Node>& smem = d_state.getMembers(s);
359
        if (!smem.empty())
360
        {
361
          Trace("sets-mem") << "Memberships : ";
362
          for (const std::pair<const Node, Node>& it2 : smem)
363
          {
364
            Trace("sets-mem") << it2.first << " ";
365
          }
366
        }
367
        Node ss = d_state.getSingletonEqClass(s);
368
        if (!ss.isNull())
369
        {
370
          Trace("sets-mem") << " : Singleton : " << ss;
371
        }
372
        Trace("sets-mem") << std::endl;
373
      }
374
    }
375
19611
    d_im.doPendingLemmas();
376
19611
    if (d_im.hasSent())
377
    {
378
      continue;
379
    }
380
    // check downwards closure
381
19611
    checkDownwardsClosure();
382
19611
    d_im.doPendingLemmas();
383
19611
    if (d_im.hasSent())
384
    {
385
548
      continue;
386
    }
387
    // check upwards closure
388
19063
    checkUpwardsClosure();
389
19063
    d_im.doPendingLemmas();
390
19063
    if (d_im.hasSent())
391
    {
392
1154
      continue;
393
    }
394
    // check disequalities
395
17909
    checkDisequalities();
396
17909
    d_im.doPendingLemmas();
397
17909
    if (d_im.hasSent())
398
    {
399
595
      continue;
400
    }
401
    // check reduce comprehensions
402
17314
    checkReduceComprehensions();
403
404
17314
    d_im.doPendingLemmas();
405
17314
    if (d_im.hasSent())
406
    {
407
18
      continue;
408
    }
409
17296
    if (d_card_enabled)
410
    {
411
      // call the check method of the cardinality solver
412
1799
      d_cardSolver->check();
413
1798
      if (d_im.hasSent())
414
      {
415
1664
        continue;
416
      }
417
    }
418
15631
    if (d_rels_enabled)
419
    {
420
      // call the check method of the relations solver
421
769
      d_rels->check(Theory::EFFORT_FULL);
422
    }
423
35162
  } while (!d_im.hasSentLemma() && !d_state.isInConflict()
424
35162
           && d_im.hasSentFact());
425
20142
  Assert(!d_im.hasPendingLemma() || d_im.hasSent());
426
40284
  Trace("sets") << "----- End full effort check, conflict="
427
40284
                << d_state.isInConflict() << ", lemma=" << d_im.hasSentLemma()
428
20142
                << std::endl;
429
20142
}
430
431
19611
void TheorySetsPrivate::checkDownwardsClosure()
432
{
433
19611
  Trace("sets") << "TheorySetsPrivate: check downwards closure..." << std::endl;
434
  // downwards closure
435
19611
  const std::vector<Node>& sec = d_state.getSetsEqClasses();
436
68710
  for (const Node& s : sec)
437
  {
438
49099
    const std::vector<Node>& nvsets = d_state.getNonVariableSets(s);
439
49099
    if (!nvsets.empty())
440
    {
441
36550
      const std::map<Node, Node>& smem = d_state.getMembers(s);
442
97214
      for (const Node& nv : nvsets)
443
      {
444
60664
        if (!d_state.isCongruent(nv))
445
        {
446
110930
          for (const std::pair<const Node, Node>& it2 : smem)
447
          {
448
110420
            Node mem = it2.second;
449
110420
            Node eq_set = nv;
450
55210
            Assert(d_equalityEngine->areEqual(mem[1], eq_set));
451
55210
            if (mem[1] != eq_set)
452
            {
453
107108
              Trace("sets-debug") << "Downwards closure based on " << mem
454
53554
                                  << ", eq_set = " << eq_set << std::endl;
455
53554
              if (!options::setsProxyLemmas())
456
              {
457
                Node nmem = NodeManager::currentNM()->mkNode(
458
107108
                    kind::MEMBER, mem[0], eq_set);
459
53554
                nmem = Rewriter::rewrite(nmem);
460
107108
                std::vector<Node> exp;
461
53554
                exp.push_back(mem);
462
53554
                exp.push_back(mem[1].eqNode(eq_set));
463
53554
                d_im.assertInference(nmem, InferenceId::SETS_DOWN_CLOSURE, exp);
464
53554
                if (d_state.isInConflict())
465
                {
466
                  return;
467
                }
468
              }
469
              else
470
              {
471
                // use proxy set
472
                Node k = d_treg.getProxy(eq_set);
473
                Node pmem =
474
                    NodeManager::currentNM()->mkNode(kind::MEMBER, mem[0], k);
475
                Node nmem = NodeManager::currentNM()->mkNode(
476
                    kind::MEMBER, mem[0], eq_set);
477
                nmem = Rewriter::rewrite(nmem);
478
                std::vector<Node> exp;
479
                if (d_state.areEqual(mem, pmem))
480
                {
481
                  exp.push_back(pmem);
482
                }
483
                else
484
                {
485
                  nmem = NodeManager::currentNM()->mkNode(
486
                      kind::OR, pmem.negate(), nmem);
487
                }
488
                d_im.assertInference(nmem, InferenceId::SETS_DOWN_CLOSURE, exp);
489
              }
490
            }
491
          }
492
        }
493
      }
494
    }
495
  }
496
}
497
498
19063
void TheorySetsPrivate::checkUpwardsClosure()
499
{
500
  // upwards closure
501
19063
  NodeManager* nm = NodeManager::currentNM();
502
  const std::map<Kind, std::map<Node, std::map<Node, Node> > >& boi =
503
19063
      d_state.getBinaryOpIndex();
504
8269
  for (const std::pair<const Kind, std::map<Node, std::map<Node, Node> > >&
505
19063
           itb : boi)
506
  {
507
8269
    Kind k = itb.first;
508
16538
    Trace("sets") << "TheorySetsPrivate: check upwards closure " << k << "..."
509
8269
                  << std::endl;
510
33942
    for (const std::pair<const Node, std::map<Node, Node> >& it : itb.second)
511
    {
512
51346
      Node r1 = it.first;
513
      // see if there are members in first argument r1
514
25673
      const std::map<Node, Node>& r1mem = d_state.getMembers(r1);
515
25673
      if (!r1mem.empty() || k == kind::UNION)
516
      {
517
50999
        for (const std::pair<const Node, Node>& it2 : it.second)
518
        {
519
60100
          Node r2 = it2.first;
520
60100
          Node term = it2.second;
521
          // see if there are members in second argument
522
30050
          const std::map<Node, Node>& r2mem = d_state.getMembers(r2);
523
30050
          const std::map<Node, Node>& r2nmem = d_state.getNegativeMembers(r2);
524
30050
          if (!r2mem.empty() || k != kind::INTERSECTION)
525
          {
526
58562
            Trace("sets-debug")
527
58562
                << "Checking " << term << ", members = " << (!r1mem.empty())
528
29281
                << ", " << (!r2mem.empty()) << std::endl;
529
            // for all members of r1
530
29281
            if (!r1mem.empty())
531
            {
532
76750
              for (const std::pair<const Node, Node>& itm1m : r1mem)
533
              {
534
99962
                Node xr = itm1m.first;
535
99962
                Node x = itm1m.second[0];
536
99962
                Trace("sets-debug") << "checking membership " << xr << " "
537
49981
                                    << itm1m.second << std::endl;
538
99962
                std::vector<Node> exp;
539
49981
                exp.push_back(itm1m.second);
540
49981
                d_state.addEqualityToExp(term[0], itm1m.second[1], exp);
541
49981
                bool valid = false;
542
49981
                int inferType = 0;
543
49981
                if (k == kind::UNION)
544
                {
545
8516
                  valid = true;
546
                }
547
41465
                else if (k == kind::INTERSECTION)
548
                {
549
                  // conclude x is in term
550
                  // if also existing in members of r2
551
13212
                  std::map<Node, Node>::const_iterator itm = r2mem.find(xr);
552
13212
                  if (itm != r2mem.end())
553
                  {
554
8343
                    exp.push_back(itm->second);
555
8343
                    d_state.addEqualityToExp(term[1], itm->second[1], exp);
556
8343
                    d_state.addEqualityToExp(x, itm->second[0], exp);
557
8343
                    valid = true;
558
                  }
559
                  else
560
                  {
561
                    // if not, check whether it is definitely not a member, if
562
                    // unknown, split
563
4869
                    if (r2nmem.find(xr) == r2nmem.end())
564
                    {
565
717
                      exp.push_back(nm->mkNode(kind::MEMBER, x, term[1]));
566
717
                      valid = true;
567
717
                      inferType = 1;
568
                    }
569
                  }
570
                }
571
                else
572
                {
573
28253
                  Assert(k == kind::SETMINUS);
574
28253
                  std::map<Node, Node>::const_iterator itm = r2mem.find(xr);
575
28253
                  if (itm == r2mem.end())
576
                  {
577
                    // must add lemma for set minus since non-membership in this
578
                    // case is not explained
579
12404
                    exp.push_back(
580
24808
                        nm->mkNode(kind::MEMBER, x, term[1]).negate());
581
12404
                    valid = true;
582
12404
                    inferType = 1;
583
                  }
584
                }
585
49981
                if (valid)
586
                {
587
59960
                  Node rr = d_equalityEngine->getRepresentative(term);
588
29980
                  if (!d_state.isMember(x, rr))
589
                  {
590
4676
                    Node kk = d_treg.getProxy(term);
591
4676
                    Node fact = nm->mkNode(kind::MEMBER, x, kk);
592
2338
                    d_im.assertInference(
593
                        fact, InferenceId::SETS_UP_CLOSURE, exp, inferType);
594
2338
                    if (d_state.isInConflict())
595
                    {
596
                      return;
597
                    }
598
                  }
599
                }
600
99962
                Trace("sets-debug") << "done checking membership " << xr << " "
601
49981
                                    << itm1m.second << std::endl;
602
              }
603
            }
604
29281
            if (k == kind::UNION)
605
            {
606
8224
              if (!r2mem.empty())
607
              {
608
                // for all members of r2
609
19849
                for (const std::pair<const Node, Node>& itm2m : r2mem)
610
                {
611
27104
                  Node x = itm2m.second[0];
612
27104
                  Node rr = d_equalityEngine->getRepresentative(term);
613
13552
                  if (!d_state.isMember(x, rr))
614
                  {
615
1116
                    std::vector<Node> exp;
616
558
                    exp.push_back(itm2m.second);
617
558
                    d_state.addEqualityToExp(term[1], itm2m.second[1], exp);
618
1116
                    Node r = d_treg.getProxy(term);
619
1116
                    Node fact = nm->mkNode(kind::MEMBER, x, r);
620
558
                    d_im.assertInference(fact, InferenceId::SETS_UP_CLOSURE_2, exp);
621
558
                    if (d_state.isInConflict())
622
                    {
623
                      return;
624
                    }
625
                  }
626
                }
627
              }
628
            }
629
          }
630
        }
631
      }
632
    }
633
  }
634
19063
  if (!d_im.hasSent())
635
  {
636
18606
    if (options::setsExt())
637
    {
638
      // universal sets
639
1601
      Trace("sets-debug") << "Check universe sets..." << std::endl;
640
      // all elements must be in universal set
641
1601
      const std::vector<Node>& sec = d_state.getSetsEqClasses();
642
15423
      for (const Node& s : sec)
643
      {
644
        // if equivalence class contains a variable
645
27644
        Node v = d_state.getVariableSet(s);
646
13822
        if (!v.isNull())
647
        {
648
          // the variable in the equivalence class
649
8396
          std::map<TypeNode, Node> univ_set;
650
4198
          const std::map<Node, Node>& smems = d_state.getMembers(s);
651
9098
          for (const std::pair<const Node, Node>& it2 : smems)
652
          {
653
9800
            Node e = it2.second[0];
654
9800
            TypeNode tn = NodeManager::currentNM()->mkSetType(e.getType());
655
9800
            Node u;
656
4900
            std::map<TypeNode, Node>::iterator itu = univ_set.find(tn);
657
4900
            if (itu == univ_set.end())
658
            {
659
5232
              Node ueqc = d_state.getUnivSetEqClass(tn);
660
              // if the universe does not yet exist, or is not in this
661
              // equivalence class
662
2616
              if (s != ueqc)
663
              {
664
1943
                u = d_treg.getUnivSet(tn);
665
              }
666
2616
              univ_set[tn] = u;
667
            }
668
            else
669
            {
670
2284
              u = itu->second;
671
            }
672
4900
            if (!u.isNull())
673
            {
674
3207
              Assert(it2.second.getKind() == kind::MEMBER);
675
6414
              std::vector<Node> exp;
676
3207
              exp.push_back(it2.second);
677
3207
              if (v != it2.second[1])
678
              {
679
762
                exp.push_back(v.eqNode(it2.second[1]));
680
              }
681
6414
              Node fact = nm->mkNode(kind::MEMBER, it2.second[0], u);
682
3207
              d_im.assertInference(fact, InferenceId::SETS_UP_UNIV, exp);
683
3207
              if (d_state.isInConflict())
684
              {
685
                return;
686
              }
687
            }
688
          }
689
        }
690
      }
691
    }
692
  }
693
}
694
695
17909
void TheorySetsPrivate::checkDisequalities()
696
{
697
  // disequalities
698
17909
  Trace("sets") << "TheorySetsPrivate: check disequalities..." << std::endl;
699
17909
  NodeManager* nm = NodeManager::currentNM();
700
25849
  for (NodeBoolMap::const_iterator it = d_deq.begin(); it != d_deq.end(); ++it)
701
  {
702
8535
    if (!(*it).second)
703
    {
704
      // not active
705
11082
      continue;
706
    }
707
5393
    Node deq = (*it).first;
708
    // check if it is already satisfied
709
5393
    Assert(d_equalityEngine->hasTerm(deq[0])
710
           && d_equalityEngine->hasTerm(deq[1]));
711
5393
    Node r1 = d_equalityEngine->getRepresentative(deq[0]);
712
5393
    Node r2 = d_equalityEngine->getRepresentative(deq[1]);
713
5393
    bool is_sat = d_state.isSetDisequalityEntailed(r1, r2);
714
10786
    Trace("sets-debug") << "Check disequality " << deq
715
5393
                        << ", is_sat = " << is_sat << std::endl;
716
    // will process regardless of sat/processed/unprocessed
717
5393
    d_deq[deq] = false;
718
719
5393
    if (is_sat)
720
    {
721
      // already satisfied
722
4661
      continue;
723
    }
724
732
    if (d_termProcessed.find(deq) != d_termProcessed.end())
725
    {
726
      // already added lemma
727
137
      continue;
728
    }
729
595
    d_termProcessed.insert(deq);
730
595
    d_termProcessed.insert(deq[1].eqNode(deq[0]));
731
595
    Trace("sets") << "Process Disequality : " << deq.negate() << std::endl;
732
595
    TypeNode elementType = deq[0].getType().getSetElementType();
733
595
    Node x = d_skCache.mkTypedSkolemCached(
734
595
        elementType, deq[0], deq[1], SkolemCache::SK_DISEQUAL, "sde");
735
595
    Node mem1 = nm->mkNode(MEMBER, x, deq[0]);
736
595
    Node mem2 = nm->mkNode(MEMBER, x, deq[1]);
737
595
    Node lem = nm->mkNode(OR, deq, nm->mkNode(EQUAL, mem1, mem2).negate());
738
595
    lem = Rewriter::rewrite(lem);
739
595
    d_im.assertInference(lem, InferenceId::SETS_DEQ, d_true, 1);
740
595
    d_im.doPendingLemmas();
741
595
    if (d_im.hasSent())
742
    {
743
595
      return;
744
    }
745
  }
746
}
747
748
17314
void TheorySetsPrivate::checkReduceComprehensions()
749
{
750
17314
  NodeManager* nm = NodeManager::currentNM();
751
17314
  const std::vector<Node>& comps = d_state.getComprehensionSets();
752
17382
  for (const Node& n : comps)
753
  {
754
68
    if (d_termProcessed.find(n) != d_termProcessed.end())
755
    {
756
      // already reduced it
757
46
      continue;
758
    }
759
22
    d_termProcessed.insert(n);
760
44
    Node v = nm->mkBoundVar(n[2].getType());
761
44
    Node body = nm->mkNode(AND, n[1], v.eqNode(n[2]));
762
    // must do substitution
763
44
    std::vector<Node> vars;
764
44
    std::vector<Node> subs;
765
44
    for (const Node& cv : n[0])
766
    {
767
22
      vars.push_back(cv);
768
44
      Node cvs = nm->mkBoundVar(cv.getType());
769
22
      subs.push_back(cvs);
770
    }
771
22
    body = body.substitute(vars.begin(), vars.end(), subs.begin(), subs.end());
772
44
    Node bvl = nm->mkNode(BOUND_VAR_LIST, subs);
773
22
    body = nm->mkNode(EXISTS, bvl, body);
774
44
    Node mem = nm->mkNode(MEMBER, v, n);
775
    Node lem =
776
44
        nm->mkNode(FORALL, nm->mkNode(BOUND_VAR_LIST, v), body.eqNode(mem));
777
44
    Trace("sets-comprehension")
778
22
        << "Comprehension reduction: " << lem << std::endl;
779
22
    d_im.lemma(lem, InferenceId::SETS_COMPREHENSION);
780
  }
781
17314
}
782
783
//--------------------------------- standard check
784
785
105995
void TheorySetsPrivate::postCheck(Theory::Effort level)
786
{
787
211990
  Trace("sets-check") << "Sets finished assertions effort " << level
788
105995
                      << std::endl;
789
  // invoke full effort check, relations check
790
105995
  if (!d_state.isInConflict())
791
  {
792
99858
    if (level == Theory::EFFORT_FULL)
793
    {
794
24906
      if (!d_external.d_valuation.needCheck())
795
      {
796
20143
        fullEffortCheck();
797
60426
        if (!d_state.isInConflict() && !d_im.hasSentLemma()
798
35162
            && d_fullCheckIncomplete)
799
        {
800
4
          d_im.setIncomplete(d_fullCheckIncompleteId);
801
        }
802
      }
803
    }
804
  }
805
105994
  Trace("sets-check") << "Sets finish Check effort " << level << std::endl;
806
105994
}
807
808
229125
void TheorySetsPrivate::notifyFact(TNode atom, bool polarity, TNode fact)
809
{
810
229125
  if (d_state.isInConflict())
811
  {
812
5977
    return;
813
  }
814
223148
  if (atom.getKind() == kind::MEMBER && polarity)
815
  {
816
    // check if set has a value, if so, we can propagate
817
127628
    Node r = d_equalityEngine->getRepresentative(atom[1]);
818
63814
    EqcInfo* e = getOrMakeEqcInfo(r, true);
819
63814
    if (e)
820
    {
821
127628
      Node s = e->d_singleton;
822
63814
      if (!s.isNull())
823
      {
824
        Node pexp = NodeManager::currentNM()->mkNode(
825
5044
            kind::AND, atom, atom[1].eqNode(s));
826
2522
        if (s.getKind() == kind::SINGLETON)
827
        {
828
2362
          if (s[0] != atom[0])
829
          {
830
414
            Trace("sets-prop") << "Propagate mem-eq : " << pexp << std::endl;
831
828
            Node eq = s[0].eqNode(atom[0]);
832
            // triggers an internal inference
833
414
            d_im.assertSetsFact(eq, true, InferenceId::SETS_MEM_EQ, pexp);
834
          }
835
        }
836
        else
837
        {
838
320
          Trace("sets-prop")
839
160
              << "Propagate mem-eq conflict : " << pexp << std::endl;
840
160
          d_im.conflict(pexp, InferenceId::SETS_MEM_EQ_CONFLICT);
841
        }
842
      }
843
    }
844
    // add to membership list
845
63814
    d_state.addMember(r, atom);
846
  }
847
}
848
//--------------------------------- end standard check
849
850
/************************ Sharing ************************/
851
/************************ Sharing ************************/
852
/************************ Sharing ************************/
853
854
16315
void TheorySetsPrivate::addCarePairs(TNodeTrie* t1,
855
                                     TNodeTrie* t2,
856
                                     unsigned arity,
857
                                     unsigned depth,
858
                                     unsigned& n_pairs)
859
{
860
16315
  if (depth == arity)
861
  {
862
9910
    if (t2 != NULL)
863
    {
864
19820
      Node f1 = t1->getData();
865
19820
      Node f2 = t2->getData();
866
867
      // Usually when (= (f x) (f y)), we don't care whether (= x y) is true or
868
      // not for the shared variables x, y in the care graph.
869
      // However, this does not apply to the membership operator since the
870
      // equality or disequality between members affects the number of elements
871
      // in a set. Therefore we need to split on (= x y) for kind MEMBER.
872
      // Example:
873
      // Suppose (= (member x S) member( y, S)) is true and there are
874
      // no other members in S. We would get S = {x} if (= x y) is true.
875
      // Otherwise we would get S = {x, y}.
876
9910
      if (f1.getKind() == MEMBER || !d_state.areEqual(f1, f2))
877
      {
878
9910
        Trace("sets-cg") << "Check " << f1 << " and " << f2 << std::endl;
879
19820
        vector<pair<TNode, TNode> > currentPairs;
880
29065
        for (unsigned k = 0; k < f1.getNumChildren(); ++k)
881
        {
882
38310
          TNode x = f1[k];
883
38310
          TNode y = f2[k];
884
19155
          Assert(d_equalityEngine->hasTerm(x));
885
19155
          Assert(d_equalityEngine->hasTerm(y));
886
19155
          Assert(!d_state.areDisequal(x, y));
887
19155
          Assert(!areCareDisequal(x, y));
888
19155
          if (!d_equalityEngine->areEqual(x, y))
889
          {
890
23978
            Trace("sets-cg")
891
11989
                << "Arg #" << k << " is " << x << " " << y << std::endl;
892
35967
            if (d_equalityEngine->isTriggerTerm(x, THEORY_SETS)
893
35967
                && d_equalityEngine->isTriggerTerm(y, THEORY_SETS))
894
            {
895
4468
              TNode x_shared = d_equalityEngine->getTriggerTermRepresentative(
896
8936
                  x, THEORY_SETS);
897
4468
              TNode y_shared = d_equalityEngine->getTriggerTermRepresentative(
898
8936
                  y, THEORY_SETS);
899
4468
              currentPairs.push_back(make_pair(x_shared, y_shared));
900
            }
901
7521
            else if (isCareArg(f1, k) && isCareArg(f2, k))
902
            {
903
              // splitting on sets (necessary for handling set of sets properly)
904
6
              if (x.getType().isSet())
905
              {
906
6
                Assert(y.getType().isSet());
907
6
                if (!d_state.areDisequal(x, y))
908
                {
909
12
                  Trace("sets-cg-lemma")
910
6
                      << "Should split on : " << x << "==" << y << std::endl;
911
6
                  d_im.split(x.eqNode(y), InferenceId::SETS_CG_SPLIT);
912
                }
913
              }
914
            }
915
          }
916
        }
917
14378
        for (unsigned c = 0; c < currentPairs.size(); ++c)
918
        {
919
8936
          Trace("sets-cg-pair") << "Pair : " << currentPairs[c].first << " "
920
4468
                                << currentPairs[c].second << std::endl;
921
4468
          d_external.addCarePair(currentPairs[c].first, currentPairs[c].second);
922
4468
          n_pairs++;
923
        }
924
      }
925
    }
926
  }
927
  else
928
  {
929
6405
    if (t2 == NULL)
930
    {
931
5363
      if (depth < (arity - 1))
932
      {
933
        // add care pairs internal to each child
934
4833
        for (std::pair<const TNode, TNodeTrie>& t : t1->d_data)
935
        {
936
3738
          addCarePairs(&t.second, NULL, arity, depth + 1, n_pairs);
937
        }
938
      }
939
      // add care pairs based on each pair of non-disequal arguments
940
17890
      for (std::map<TNode, TNodeTrie>::iterator it = t1->d_data.begin();
941
17890
           it != t1->d_data.end();
942
           ++it)
943
      {
944
12527
        std::map<TNode, TNodeTrie>::iterator it2 = it;
945
12527
        ++it2;
946
61829
        for (; it2 != t1->d_data.end(); ++it2)
947
        {
948
24651
          if (!d_equalityEngine->areDisequal(it->first, it2->first, false))
949
          {
950
13715
            if (!areCareDisequal(it->first, it2->first))
951
            {
952
25257
              addCarePairs(
953
16838
                  &it->second, &it2->second, arity, depth + 1, n_pairs);
954
            }
955
          }
956
        }
957
      }
958
    }
959
    else
960
    {
961
      // add care pairs based on product of indices, non-disequal arguments
962
2802
      for (std::pair<const TNode, TNodeTrie>& tt1 : t1->d_data)
963
      {
964
5195
        for (std::pair<const TNode, TNodeTrie>& tt2 : t2->d_data)
965
        {
966
3435
          if (!d_equalityEngine->areDisequal(tt1.first, tt2.first, false))
967
          {
968
2533
            if (!areCareDisequal(tt1.first, tt2.first))
969
            {
970
2533
              addCarePairs(&tt1.second, &tt2.second, arity, depth + 1, n_pairs);
971
            }
972
          }
973
        }
974
      }
975
    }
976
  }
977
16315
}
978
979
6672
void TheorySetsPrivate::computeCareGraph()
980
{
981
6672
  const std::map<Kind, std::vector<Node> >& ol = d_state.getOperatorList();
982
8654
  for (const std::pair<const Kind, std::vector<Node> >& it : ol)
983
  {
984
1982
    Kind k = it.first;
985
1982
    if (k == kind::SINGLETON || k == kind::MEMBER)
986
    {
987
1265
      unsigned n_pairs = 0;
988
2530
      Trace("sets-cg-summary") << "Compute graph for sets, op=" << k << "..."
989
1265
                               << it.second.size() << std::endl;
990
1265
      Trace("sets-cg") << "Build index for " << k << "..." << std::endl;
991
2530
      std::map<TypeNode, TNodeTrie> index;
992
1265
      unsigned arity = 0;
993
      // populate indices
994
10054
      for (TNode f1 : it.second)
995
      {
996
8789
        Trace("sets-cg-debug") << "...build for " << f1 << std::endl;
997
8789
        Assert(d_equalityEngine->hasTerm(f1));
998
        // break into index based on operator, and the type of the element
999
        // type of the proper set, which notice must be safe wrt subtyping.
1000
17578
        TypeNode tn;
1001
8789
        if (k == kind::SINGLETON)
1002
        {
1003
          // get the type of the singleton set (not the type of its element)
1004
1469
          tn = f1.getType().getSetElementType();
1005
        }
1006
        else
1007
        {
1008
7320
          Assert (k == kind::MEMBER);
1009
          // get the element type of the set (not the type of the element)
1010
7320
          tn = f1[1].getType().getSetElementType();
1011
        }
1012
17578
        std::vector<TNode> reps;
1013
8789
        bool hasCareArg = false;
1014
24898
        for (unsigned j = 0; j < f1.getNumChildren(); j++)
1015
        {
1016
16109
          reps.push_back(d_equalityEngine->getRepresentative(f1[j]));
1017
16109
          if (isCareArg(f1, j))
1018
          {
1019
11377
            hasCareArg = true;
1020
          }
1021
        }
1022
8789
        if (hasCareArg)
1023
        {
1024
8789
          Trace("sets-cg-debug") << "......adding." << std::endl;
1025
8789
          index[tn].addTerm(f1, reps);
1026
8789
          arity = reps.size();
1027
        }
1028
        else
1029
        {
1030
          Trace("sets-cg-debug") << "......skip." << std::endl;
1031
        }
1032
      }
1033
1265
      if (arity > 0)
1034
      {
1035
        // for each index
1036
2890
        for (std::pair<const TypeNode, TNodeTrie>& tt : index)
1037
        {
1038
3250
          Trace("sets-cg") << "Process index " << tt.first << "..."
1039
1625
                           << std::endl;
1040
1625
          addCarePairs(&tt.second, nullptr, arity, 0, n_pairs);
1041
        }
1042
      }
1043
1265
      Trace("sets-cg-summary") << "...done, # pairs = " << n_pairs << std::endl;
1044
    }
1045
  }
1046
6672
}
1047
1048
26245
bool TheorySetsPrivate::isCareArg(Node n, unsigned a)
1049
{
1050
26245
  if (d_equalityEngine->isTriggerTerm(n[a], THEORY_SETS))
1051
  {
1052
13978
    return true;
1053
  }
1054
24534
  else if ((n.getKind() == kind::MEMBER || n.getKind() == kind::SINGLETON)
1055
36801
           && a == 0 && n[0].getType().isSet())
1056
  {
1057
20
    return true;
1058
  }
1059
  else
1060
  {
1061
12247
    return false;
1062
  }
1063
}
1064
1065
/******************** Model generation ********************/
1066
/******************** Model generation ********************/
1067
/******************** Model generation ********************/
1068
1069
namespace {
1070
/**
1071
 * This function is a helper function to print sets as
1072
 * Set A = { a0, a1, a2, }
1073
 * instead of
1074
 * (union (singleton a0) (union (singleton a1) (singleton a2)))
1075
 */
1076
3266
void traceSetElementsRecursively(stringstream& stream, const Node& set)
1077
{
1078
3266
  Assert(set.getType().isSet());
1079
3266
  if (set.getKind() == SINGLETON)
1080
  {
1081
2145
    stream << set[0] << ", ";
1082
  }
1083
3266
  if (set.getKind() == UNION)
1084
  {
1085
763
    traceSetElementsRecursively(stream, set[0]);
1086
763
    traceSetElementsRecursively(stream, set[1]);
1087
  }
1088
3266
}
1089
1090
1740
std::string traceElements(const Node& set)
1091
{
1092
3480
  std::stringstream stream;
1093
1740
  traceSetElementsRecursively(stream, set);
1094
3480
  return stream.str();
1095
}
1096
1097
}  // namespace
1098
1099
4956
bool TheorySetsPrivate::collectModelValues(TheoryModel* m,
1100
                                           const std::set<Node>& termSet)
1101
{
1102
4956
  Trace("sets-model") << "Set collect model values" << std::endl;
1103
1104
4956
  NodeManager* nm = NodeManager::currentNM();
1105
9912
  std::map<Node, Node> mvals;
1106
  // If cardinality is enabled, we need to use the ordered equivalence class
1107
  // list computed by the cardinality solver, where sets equivalence classes
1108
  // are assigned model values based on their position in the cardinality
1109
  // graph.
1110
4956
  const std::vector<Node>& sec = d_card_enabled
1111
9841
                                     ? d_cardSolver->getOrderedSetsEqClasses()
1112
9841
                                     : d_state.getSetsEqClasses();
1113
4956
  Valuation& val = getValuation();
1114
6738
  for (int i = (int)(sec.size() - 1); i >= 0; i--)
1115
  {
1116
3564
    Node eqc = sec[i];
1117
1782
    if (termSet.find(eqc) == termSet.end())
1118
    {
1119
84
      Trace("sets-model") << "* Do not assign value for " << eqc
1120
42
                          << " since is not relevant." << std::endl;
1121
    }
1122
    else
1123
    {
1124
3480
      std::vector<Node> els;
1125
1740
      bool is_base = !d_card_enabled || d_cardSolver->isModelValueBasic(eqc);
1126
1740
      if (is_base)
1127
      {
1128
3364
        Trace("sets-model")
1129
1682
            << "Collect elements of base eqc " << eqc << std::endl;
1130
        // members that must be in eqc
1131
1682
        const std::map<Node, Node>& emems = d_state.getMembers(eqc);
1132
1682
        if (!emems.empty())
1133
        {
1134
2726
          TypeNode elementType = eqc.getType().getSetElementType();
1135
3316
          for (const std::pair<const Node, Node>& itmm : emems)
1136
          {
1137
3906
            Trace("sets-model")
1138
1953
                << "m->getRepresentative(" << itmm.first
1139
1953
                << ")= " << m->getRepresentative(itmm.first) << std::endl;
1140
3906
            Node t = nm->mkSingleton(elementType, itmm.first);
1141
1953
            els.push_back(t);
1142
          }
1143
        }
1144
      }
1145
1740
      if (d_card_enabled)
1146
      {
1147
        // make the slack elements for the equivalence class based on set
1148
        // cardinality
1149
175
        d_cardSolver->mkModelValueElementsFor(val, eqc, els, mvals, m);
1150
      }
1151
1152
3480
      Node rep = NormalForm::mkBop(kind::UNION, els, eqc.getType());
1153
1740
      rep = Rewriter::rewrite(rep);
1154
3480
      Trace("sets-model") << "* Assign representative of " << eqc << " to "
1155
1740
                          << rep << std::endl;
1156
1740
      mvals[eqc] = rep;
1157
1740
      if (!m->assertEquality(eqc, rep, true))
1158
      {
1159
        return false;
1160
      }
1161
1740
      m->assertSkeleton(rep);
1162
1163
      // we add the element terms (singletons) as representatives to tell the
1164
      // model builder to evaluate them along with their union (rep).
1165
      // This is needed to account for cases when members and rep are not enough
1166
      // for the model builder to evaluate set terms.
1167
      // e.g.
1168
      // eqc(rep) = [(union (singleton skolem) (singleton 0))]
1169
      // eqc(skolem) = [0]
1170
      // The model builder would fail to evaluate rep as (singleton 0)
1171
      // if (singleton skolem) is not registered as a representative in the
1172
      // model
1173
3816
      for (const Node& el : els)
1174
      {
1175
2076
        m->assertSkeleton(el);
1176
      }
1177
1178
3480
      Trace("sets-model") << "Set " << eqc << " = { " << traceElements(rep)
1179
1740
                          << " }" << std::endl;
1180
    }
1181
  }
1182
1183
  // handle slack elements constraints for finite types
1184
4956
  if (d_card_enabled)
1185
  {
1186
    const std::map<TypeNode, std::vector<TNode> >& slackElements =
1187
71
        d_cardSolver->getFiniteTypeSlackElements();
1188
81
    for (const auto& pair : slackElements)
1189
    {
1190
      const std::vector<Node>& members =
1191
10
          d_cardSolver->getFiniteTypeMembers(pair.first);
1192
10
      m->setAssignmentExclusionSetGroup(pair.second, members);
1193
20
      Trace("sets-model") << "ExclusionSet: Group " << pair.second
1194
10
                          << " is excluded from set" << members << std::endl;
1195
    }
1196
  }
1197
4956
  return true;
1198
}
1199
1200
/********************** Helper functions ***************************/
1201
/********************** Helper functions ***************************/
1202
/********************** Helper functions ***************************/
1203
1204
2807
Node mkAnd(const std::vector<TNode>& conjunctions)
1205
{
1206
2807
  Assert(conjunctions.size() > 0);
1207
1208
5614
  std::set<TNode> all;
1209
12800
  for (unsigned i = 0; i < conjunctions.size(); ++i)
1210
  {
1211
19986
    TNode t = conjunctions[i];
1212
9993
    if (t.getKind() == kind::AND)
1213
    {
1214
426
      for (TNode::iterator child_it = t.begin(); child_it != t.end();
1215
           ++child_it)
1216
      {
1217
284
        Assert((*child_it).getKind() != kind::AND);
1218
284
        all.insert(*child_it);
1219
      }
1220
    }
1221
    else
1222
    {
1223
9851
      all.insert(t);
1224
    }
1225
  }
1226
1227
2807
  Assert(all.size() > 0);
1228
2807
  if (all.size() == 1)
1229
  {
1230
    // All the same, or just one
1231
367
    return conjunctions[0];
1232
  }
1233
1234
4880
  NodeBuilder conjunction(kind::AND);
1235
2440
  std::set<TNode>::const_iterator it = all.begin();
1236
2440
  std::set<TNode>::const_iterator it_end = all.end();
1237
20776
  while (it != it_end)
1238
  {
1239
9168
    conjunction << *it;
1240
9168
    ++it;
1241
  }
1242
2440
  return conjunction;
1243
} /* mkAnd() */
1244
1245
4956
Valuation& TheorySetsPrivate::getValuation() { return d_external.d_valuation; }
1246
1247
2807
Node TheorySetsPrivate::explain(TNode literal)
1248
{
1249
2807
  Debug("sets") << "TheorySetsPrivate::explain(" << literal << ")" << std::endl;
1250
1251
2807
  bool polarity = literal.getKind() != kind::NOT;
1252
5614
  TNode atom = polarity ? literal : literal[0];
1253
5614
  std::vector<TNode> assumptions;
1254
1255
2807
  if (atom.getKind() == kind::EQUAL)
1256
  {
1257
1703
    d_equalityEngine->explainEquality(atom[0], atom[1], polarity, assumptions);
1258
  }
1259
1104
  else if (atom.getKind() == kind::MEMBER)
1260
  {
1261
1104
    d_equalityEngine->explainPredicate(atom, polarity, assumptions);
1262
  }
1263
  else
1264
  {
1265
    Debug("sets") << "unhandled: " << literal << "; (" << atom << ", "
1266
                  << polarity << "); kind" << atom.getKind() << std::endl;
1267
    Unhandled();
1268
  }
1269
1270
5614
  return mkAnd(assumptions);
1271
}
1272
1273
75657
void TheorySetsPrivate::preRegisterTerm(TNode node)
1274
{
1275
151314
  Debug("sets") << "TheorySetsPrivate::preRegisterTerm(" << node << ")"
1276
75657
                << std::endl;
1277
75657
  switch (node.getKind())
1278
  {
1279
41548
    case kind::EQUAL:
1280
    case kind::MEMBER:
1281
    {
1282
      // add trigger predicate for equality and membership
1283
41548
      d_equalityEngine->addTriggerPredicate(node);
1284
    }
1285
41548
    break;
1286
32
    case kind::JOIN_IMAGE:
1287
    {
1288
      // these are logic exceptions, not type checking exceptions
1289
32
      if (node[1].getKind() != kind::CONST_RATIONAL)
1290
      {
1291
        throw LogicException(
1292
            "JoinImage cardinality constraint must be a constant");
1293
      }
1294
64
      cvc5::Rational r(INT_MAX);
1295
32
      if (node[1].getConst<Rational>() > r)
1296
      {
1297
        throw LogicException(
1298
            "JoinImage Exceeded INT_MAX in cardinality constraint");
1299
      }
1300
32
      if (node[1].getConst<Rational>().getNumerator().getSignedInt() < 0)
1301
      {
1302
        throw LogicException(
1303
            "JoinImage cardinality constraint must be non-negative");
1304
32
      }
1305
    }
1306
32
    break;
1307
34077
    default: d_equalityEngine->addTerm(node); break;
1308
  }
1309
75657
}
1310
1311
45567
TrustNode TheorySetsPrivate::ppRewrite(Node node,
1312
                                       std::vector<SkolemLemma>& lems)
1313
{
1314
45567
  Debug("sets-proc") << "ppRewrite : " << node << std::endl;
1315
1316
45567
  switch (node.getKind())
1317
  {
1318
6
    case kind::CHOOSE: return expandChooseOperator(node, lems);
1319
17
    case kind::IS_SINGLETON: return expandIsSingletonOperator(node);
1320
45544
    default: return TrustNode::null();
1321
  }
1322
}
1323
1324
6
TrustNode TheorySetsPrivate::expandChooseOperator(
1325
    const Node& node, std::vector<SkolemLemma>& lems)
1326
{
1327
6
  Assert(node.getKind() == CHOOSE);
1328
1329
  // (choose A) is expanded as
1330
  // (witness ((x elementType))
1331
  //    (ite
1332
  //      (= A (as emptyset setType))
1333
  //      (= x chooseUf(A))
1334
  //      (and (member x A) (= x chooseUf(A)))
1335
1336
6
  NodeManager* nm = NodeManager::currentNM();
1337
12
  Node set = node[0];
1338
12
  TypeNode setType = set.getType();
1339
12
  Node chooseSkolem = getChooseFunction(setType);
1340
12
  Node apply = NodeManager::currentNM()->mkNode(APPLY_UF, chooseSkolem, set);
1341
1342
12
  Node witnessVariable = nm->mkBoundVar(setType.getSetElementType());
1343
1344
12
  Node equal = witnessVariable.eqNode(apply);
1345
12
  Node emptySet = nm->mkConst(EmptySet(setType));
1346
12
  Node isEmpty = set.eqNode(emptySet);
1347
12
  Node member = nm->mkNode(MEMBER, witnessVariable, set);
1348
12
  Node memberAndEqual = member.andNode(equal);
1349
12
  Node ite = nm->mkNode(ITE, isEmpty, equal, memberAndEqual);
1350
6
  SkolemManager* sm = nm->getSkolemManager();
1351
12
  Node ret = sm->mkSkolem(witnessVariable, ite, "kSetChoose");
1352
6
  lems.push_back(SkolemLemma(ret, nullptr));
1353
12
  return TrustNode::mkTrustRewrite(node, ret, nullptr);
1354
}
1355
1356
17
TrustNode TheorySetsPrivate::expandIsSingletonOperator(const Node& node)
1357
{
1358
17
  Assert(node.getKind() == IS_SINGLETON);
1359
1360
  // we call the rewriter here to handle the pattern
1361
  // (is_singleton (singleton x)) because the rewriter is called after expansion
1362
34
  Node rewritten = Rewriter::rewrite(node);
1363
17
  if (rewritten.getKind() != IS_SINGLETON)
1364
  {
1365
    return TrustNode::mkTrustRewrite(node, rewritten, nullptr);
1366
  }
1367
1368
  // (is_singleton A) is expanded as
1369
  // (exists ((x: T)) (= A (singleton x)))
1370
  // where T is the sort of elements of A
1371
1372
17
  NodeManager* nm = NodeManager::currentNM();
1373
34
  Node set = rewritten[0];
1374
1375
17
  std::map<Node, Node>::iterator it = d_isSingletonNodes.find(rewritten);
1376
1377
17
  if (it != d_isSingletonNodes.end())
1378
  {
1379
    return TrustNode::mkTrustRewrite(rewritten, it->second, nullptr);
1380
  }
1381
1382
34
  TypeNode setType = set.getType();
1383
34
  Node boundVar = nm->mkBoundVar(setType.getSetElementType());
1384
34
  Node singleton = nm->mkSingleton(setType.getSetElementType(), boundVar);
1385
34
  Node equal = set.eqNode(singleton);
1386
34
  std::vector<Node> variables = {boundVar};
1387
34
  Node boundVars = nm->mkNode(BOUND_VAR_LIST, variables);
1388
34
  Node exists = nm->mkNode(kind::EXISTS, boundVars, equal);
1389
17
  d_isSingletonNodes[rewritten] = exists;
1390
1391
17
  return TrustNode::mkTrustRewrite(node, exists, nullptr);
1392
}
1393
1394
6
Node TheorySetsPrivate::getChooseFunction(const TypeNode& setType)
1395
{
1396
6
  std::map<TypeNode, Node>::iterator it = d_chooseFunctions.find(setType);
1397
6
  if (it != d_chooseFunctions.end())
1398
  {
1399
    return it->second;
1400
  }
1401
1402
6
  NodeManager* nm = NodeManager::currentNM();
1403
6
  SkolemManager* sm = nm->getSkolemManager();
1404
12
  TypeNode chooseUf = nm->mkFunctionType(setType, setType.getSetElementType());
1405
12
  stringstream stream;
1406
6
  stream << "chooseUf" << setType.getId();
1407
12
  string name = stream.str();
1408
  Node chooseSkolem = sm->mkDummySkolem(
1409
12
      name, chooseUf, "choose function", NodeManager::SKOLEM_EXACT_NAME);
1410
6
  d_chooseFunctions[setType] = chooseSkolem;
1411
6
  return chooseSkolem;
1412
}
1413
1414
15204
void TheorySetsPrivate::presolve() { d_state.reset(); }
1415
1416
}  // namespace sets
1417
}  // namespace theory
1418
29340
}  // namespace cvc5