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