GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/sets/theory_sets_private.cpp Lines: 671 714 94.0 %
Date: 2021-09-29 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
6271
TheorySetsPrivate::TheorySetsPrivate(Env& env,
40
                                     TheorySets& external,
41
                                     SolverState& state,
42
                                     InferenceManager& im,
43
                                     SkolemCache& skc,
44
6271
                                     ProofNodeManager* pnm)
45
    : EnvObj(env),
46
      d_deq(context()),
47
6271
      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(d_env, state, im, skc, pnm),
55
6271
      d_rels(new TheorySetsRels(d_env, state, im, skc, d_treg)),
56
6271
      d_cardSolver(new CardinalityExtension(d_env, state, im, d_treg)),
57
      d_rels_enabled(false),
58
25084
      d_card_enabled(false)
59
{
60
6271
  d_true = NodeManager::currentNM()->mkConst(true);
61
6271
  d_false = NodeManager::currentNM()->mkConst(false);
62
6271
  d_zero = NodeManager::currentNM()->mkConst(Rational(0));
63
6271
}
64
65
18804
TheorySetsPrivate::~TheorySetsPrivate()
66
{
67
8371
  for (std::pair<const Node, EqcInfo*>& current_pair : d_eqc_info)
68
  {
69
2103
    delete current_pair.second;
70
  }
71
12536
}
72
73
6271
void TheorySetsPrivate::finishInit()
74
{
75
6271
  d_equalityEngine = d_external.getEqualityEngine();
76
6271
  Assert(d_equalityEngine != nullptr);
77
6271
}
78
79
23196
void TheorySetsPrivate::eqNotifyNewClass(TNode t)
80
{
81
23196
  if (t.getKind() == kind::SINGLETON || t.getKind() == kind::EMPTYSET)
82
  {
83
1054
    EqcInfo* e = getOrMakeEqcInfo(t, true);
84
1054
    e->d_singleton = t;
85
  }
86
23196
}
87
88
73028
void TheorySetsPrivate::eqNotifyMerge(TNode t1, TNode t2)
89
{
90
73028
  if (!d_state.isInConflict() && t1.getType().isSet())
91
  {
92
14270
    Trace("sets-prop-debug")
93
7135
        << "Merge " << t1 << " and " << t2 << "..." << std::endl;
94
14193
    Node s1, s2;
95
7135
    EqcInfo* e2 = getOrMakeEqcInfo(t2);
96
7135
    if (e2)
97
    {
98
3318
      s2 = e2->d_singleton;
99
3318
      EqcInfo* e1 = getOrMakeEqcInfo(t1);
100
3318
      Trace("sets-prop-debug") << "Merging singletons..." << std::endl;
101
3318
      if (e1)
102
      {
103
3274
        s1 = e1->d_singleton;
104
3274
        if (!s1.isNull() && !s2.isNull())
105
        {
106
1717
          if (s1.getKind() == s2.getKind())
107
          {
108
3372
            Trace("sets-prop") << "Propagate eq inference : " << s1
109
1686
                               << " == " << s2 << std::endl;
110
            // infer equality between elements of singleton
111
3372
            Node exp = s1.eqNode(s2);
112
3372
            Node eq = s1[0].eqNode(s2[0]);
113
1686
            d_im.assertSetsFact(eq, true, InferenceId::SETS_SINGLETON_EQ, exp);
114
          }
115
          else
116
          {
117
            // singleton equal to emptyset, conflict
118
62
            Trace("sets-prop")
119
31
                << "Propagate conflict : " << s1 << " == " << s2 << std::endl;
120
62
            Node eqs = s1.eqNode(s2);
121
31
            d_im.conflict(eqs, InferenceId::SETS_EQ_CONFLICT);
122
31
            return;
123
          }
124
        }
125
      }
126
      else
127
      {
128
        // copy information
129
44
        e1 = getOrMakeEqcInfo(t1, true);
130
44
        e1->d_singleton.set(e2->d_singleton);
131
      }
132
    }
133
    // merge membership list
134
7104
    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
14162
    Node checkSingleton = s2.isNull() ? s1 : Node::null();
138
14162
    std::vector<Node> facts;
139
    // merge the membership list in the state, which may produce facts or
140
    // conflicts to propagate
141
7104
    if (!d_state.merge(t1, t2, facts, checkSingleton))
142
    {
143
      // conflict case
144
46
      Assert(facts.size() == 1);
145
92
      Trace("sets-prop") << "Propagate eq-mem conflict : " << facts[0]
146
46
                         << std::endl;
147
46
      d_im.conflict(facts[0], InferenceId::SETS_EQ_MEM_CONFLICT);
148
46
      return;
149
    }
150
7172
    for (const Node& f : facts)
151
    {
152
114
      Assert(f.getKind() == kind::IMPLIES);
153
228
      Trace("sets-prop") << "Propagate eq-mem eq inference : " << f[0] << " => "
154
114
                         << f[1] << std::endl;
155
114
      d_im.assertSetsFact(f[1], true, InferenceId::SETS_EQ_MEM, f[0]);
156
    }
157
  }
158
}
159
160
15087
void TheorySetsPrivate::eqNotifyDisequal(TNode t1, TNode t2, TNode reason)
161
{
162
15087
  if (t1.getType().isSet())
163
  {
164
12204
    Node eq = t1.eqNode(t2);
165
6102
    if (d_deq.find(eq) == d_deq.end())
166
    {
167
6102
      d_deq[eq] = true;
168
    }
169
  }
170
15087
}
171
172
2103
TheorySetsPrivate::EqcInfo::EqcInfo(context::Context* c) : d_singleton(c) {}
173
174
29277
TheorySetsPrivate::EqcInfo* TheorySetsPrivate::getOrMakeEqcInfo(TNode n,
175
                                                                bool doMake)
176
{
177
29277
  std::map<Node, EqcInfo*>::iterator eqc_i = d_eqc_info.find(n);
178
29277
  if (eqc_i == d_eqc_info.end())
179
  {
180
5964
    EqcInfo* ei = NULL;
181
5964
    if (doMake)
182
    {
183
2103
      ei = new EqcInfo(context());
184
2103
      d_eqc_info[n] = ei;
185
    }
186
5964
    return ei;
187
  }
188
  else
189
  {
190
23313
    return eqc_i->second;
191
  }
192
}
193
194
26316
bool TheorySetsPrivate::areCareDisequal(Node a, Node b)
195
{
196
78948
  if (d_equalityEngine->isTriggerTerm(a, THEORY_SETS)
197
78948
      && d_equalityEngine->isTriggerTerm(b, THEORY_SETS))
198
  {
199
    TNode a_shared =
200
24639
        d_equalityEngine->getTriggerTermRepresentative(a, THEORY_SETS);
201
    TNode b_shared =
202
24639
        d_equalityEngine->getTriggerTermRepresentative(b, THEORY_SETS);
203
    EqualityStatus eqStatus =
204
14432
        d_external.d_valuation.getEqualityStatus(a_shared, b_shared);
205
14432
    if (eqStatus == EQUALITY_FALSE_AND_PROPAGATED || eqStatus == EQUALITY_FALSE
206
14432
        || eqStatus == EQUALITY_FALSE_IN_MODEL)
207
    {
208
4225
      return true;
209
    }
210
  }
211
22091
  return false;
212
}
213
214
13387
void TheorySetsPrivate::fullEffortReset()
215
{
216
13387
  Assert(d_equalityEngine->consistent());
217
13387
  d_fullCheckIncomplete = false;
218
13387
  d_fullCheckIncompleteId = IncompleteId::UNKNOWN;
219
13387
  d_most_common_type.clear();
220
13387
  d_most_common_type_term.clear();
221
13387
  d_card_enabled = false;
222
13387
  d_rels_enabled = false;
223
  // reset the state object
224
13387
  d_state.reset();
225
  // reset the inference manager
226
13387
  d_im.reset();
227
13387
  d_im.clearPendingLemmas();
228
  // reset the cardinality solver
229
13387
  d_cardSolver->reset();
230
13387
}
231
232
13387
void TheorySetsPrivate::fullEffortCheck()
233
{
234
13387
  Trace("sets") << "----- Full effort check ------" << std::endl;
235
  do
236
  {
237
13387
    Assert(!d_im.hasPendingLemma() || d_im.hasSent());
238
239
13387
    Trace("sets") << "...iterate full effort check..." << std::endl;
240
13387
    fullEffortReset();
241
242
13387
    Trace("sets-eqc") << "Equality Engine:" << std::endl;
243
24365
    std::map<TypeNode, unsigned> eqcTypeCount;
244
13387
    eq::EqClassesIterator eqcs_i = eq::EqClassesIterator(d_equalityEngine);
245
187225
    while (!eqcs_i.isFinished())
246
    {
247
173838
      Node eqc = (*eqcs_i);
248
86919
      bool isSet = false;
249
173838
      TypeNode tn = eqc.getType();
250
86919
      d_state.registerEqc(tn, eqc);
251
86919
      eqcTypeCount[tn]++;
252
      // common type node and term
253
173838
      TypeNode tnc;
254
173838
      Node tnct;
255
86919
      if (tn.isSet())
256
      {
257
28427
        isSet = true;
258
28427
        tnc = tn.getSetElementType();
259
28427
        tnct = eqc;
260
      }
261
86919
      Trace("sets-eqc") << "[" << eqc << "] : ";
262
86919
      eq::EqClassIterator eqc_i = eq::EqClassIterator(eqc, d_equalityEngine);
263
599807
      while (!eqc_i.isFinished())
264
      {
265
513455
        Node n = (*eqc_i);
266
257011
        if (n != eqc)
267
        {
268
170092
          Trace("sets-eqc") << n << " (" << n.isConst() << ") ";
269
        }
270
513455
        TypeNode tnn = n.getType();
271
257011
        if (isSet)
272
        {
273
69608
          Assert(tnn.isSet());
274
139216
          TypeNode tnnel = tnn.getSetElementType();
275
69608
          tnc = TypeNode::mostCommonTypeNode(tnc, tnnel);
276
69608
          Assert(!tnc.isNull());
277
          // update the common type term
278
69608
          if (tnc == tnnel)
279
          {
280
69608
            tnct = n;
281
          }
282
        }
283
        // register it with the state
284
257011
        d_state.registerTerm(eqc, tnn, n);
285
257011
        Kind nk = n.getKind();
286
257011
        if (nk == kind::SINGLETON)
287
        {
288
          // ensure the proxy has been introduced
289
4420
          d_treg.getProxy(n);
290
        }
291
252591
        else if (nk == kind::CARD)
292
        {
293
24373
          d_card_enabled = true;
294
          // register it with the cardinality solver
295
24373
          d_cardSolver->registerTerm(n);
296
24373
          if (d_im.hasSent())
297
          {
298
567
            break;
299
          }
300
          // if we do not handle the kind, set incomplete
301
23806
          Kind nk0 = n[0].getKind();
302
          // some kinds of cardinality we cannot handle
303
23806
          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
228218
        else if (d_rels->isRelationKind(nk))
321
        {
322
1088
          d_rels_enabled = true;
323
        }
324
256444
        ++eqc_i;
325
      }
326
86919
      if (isSet)
327
      {
328
28427
        Assert(tnct.getType().getSetElementType() == tnc);
329
28427
        d_most_common_type[eqc] = tnc;
330
28427
        d_most_common_type_term[eqc] = tnct;
331
      }
332
86919
      Trace("sets-eqc") << std::endl;
333
86919
      ++eqcs_i;
334
    }
335
336
13387
    Trace("sets-eqc") << "...finished equality engine." << std::endl;
337
338
13387
    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
13387
    if (d_im.hasSent())
351
    {
352
314
      continue;
353
    }
354
13073
    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
13073
    d_im.doPendingLemmas();
378
13073
    if (d_im.hasSent())
379
    {
380
      continue;
381
    }
382
    // check downwards closure
383
13073
    checkDownwardsClosure();
384
13073
    d_im.doPendingLemmas();
385
13073
    if (d_im.hasSent())
386
    {
387
244
      continue;
388
    }
389
    // check upwards closure
390
12829
    checkUpwardsClosure();
391
12829
    d_im.doPendingLemmas();
392
12829
    if (d_im.hasSent())
393
    {
394
535
      continue;
395
    }
396
    // check disequalities
397
12294
    checkDisequalities();
398
12294
    d_im.doPendingLemmas();
399
12294
    if (d_im.hasSent())
400
    {
401
330
      continue;
402
    }
403
    // check reduce comprehensions
404
11964
    checkReduceComprehensions();
405
406
11964
    d_im.doPendingLemmas();
407
11964
    if (d_im.hasSent())
408
    {
409
6
      continue;
410
    }
411
11958
    if (d_card_enabled)
412
    {
413
      // call the check method of the cardinality solver
414
1103
      d_cardSolver->check();
415
1102
      if (d_im.hasSent())
416
      {
417
980
        continue;
418
      }
419
    }
420
10977
    if (d_rels_enabled)
421
    {
422
      // call the check method of the relations solver
423
432
      d_rels->check(Theory::EFFORT_FULL);
424
    }
425
24064
  } while (!d_im.hasSentLemma() && !d_state.isInConflict()
426
24064
           && d_im.hasSentFact());
427
13386
  Assert(!d_im.hasPendingLemma() || d_im.hasSent());
428
26772
  Trace("sets") << "----- End full effort check, conflict="
429
26772
                << d_state.isInConflict() << ", lemma=" << d_im.hasSentLemma()
430
13386
                << std::endl;
431
13386
}
432
433
13073
void TheorySetsPrivate::checkDownwardsClosure()
434
{
435
13073
  Trace("sets") << "TheorySetsPrivate: check downwards closure..." << std::endl;
436
  // downwards closure
437
13073
  const std::vector<Node>& sec = d_state.getSetsEqClasses();
438
38499
  for (const Node& s : sec)
439
  {
440
25426
    const std::vector<Node>& nvsets = d_state.getNonVariableSets(s);
441
25426
    if (!nvsets.empty())
442
    {
443
17823
      const std::map<Node, Node>& smem = d_state.getMembers(s);
444
46346
      for (const Node& nv : nvsets)
445
      {
446
28523
        if (!d_state.isCongruent(nv))
447
        {
448
53726
          for (const std::pair<const Node, Node>& it2 : smem)
449
          {
450
53634
            Node mem = it2.second;
451
53634
            Node eq_set = nv;
452
26817
            Assert(d_equalityEngine->areEqual(mem[1], eq_set));
453
26817
            if (mem[1] != eq_set)
454
            {
455
52114
              Trace("sets-debug") << "Downwards closure based on " << mem
456
26057
                                  << ", eq_set = " << eq_set << std::endl;
457
26057
              if (!options::setsProxyLemmas())
458
              {
459
                Node nmem = NodeManager::currentNM()->mkNode(
460
52114
                    kind::MEMBER, mem[0], eq_set);
461
26057
                nmem = Rewriter::rewrite(nmem);
462
52114
                std::vector<Node> exp;
463
26057
                exp.push_back(mem);
464
26057
                exp.push_back(mem[1].eqNode(eq_set));
465
26057
                d_im.assertInference(nmem, InferenceId::SETS_DOWN_CLOSURE, exp);
466
26057
                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
12829
void TheorySetsPrivate::checkUpwardsClosure()
501
{
502
  // upwards closure
503
12829
  NodeManager* nm = NodeManager::currentNM();
504
  const std::map<Kind, std::map<Node, std::map<Node, Node> > >& boi =
505
12829
      d_state.getBinaryOpIndex();
506
4397
  for (const std::pair<const Kind, std::map<Node, std::map<Node, Node> > >&
507
12829
           itb : boi)
508
  {
509
4397
    Kind k = itb.first;
510
8794
    Trace("sets") << "TheorySetsPrivate: check upwards closure " << k << "..."
511
4397
                  << std::endl;
512
16328
    for (const std::pair<const Node, std::map<Node, Node> >& it : itb.second)
513
    {
514
23862
      Node r1 = it.first;
515
      // see if there are members in first argument r1
516
11931
      const std::map<Node, Node>& r1mem = d_state.getMembers(r1);
517
11931
      if (!r1mem.empty() || k == kind::UNION)
518
      {
519
24474
        for (const std::pair<const Node, Node>& it2 : it.second)
520
        {
521
29180
          Node r2 = it2.first;
522
29180
          Node term = it2.second;
523
          // see if there are members in second argument
524
14590
          const std::map<Node, Node>& r2mem = d_state.getMembers(r2);
525
14590
          const std::map<Node, Node>& r2nmem = d_state.getNegativeMembers(r2);
526
14590
          if (!r2mem.empty() || k != kind::INTERSECTION)
527
          {
528
28412
            Trace("sets-debug")
529
28412
                << "Checking " << term << ", members = " << (!r1mem.empty())
530
14206
                << ", " << (!r2mem.empty()) << std::endl;
531
            // for all members of r1
532
14206
            if (!r1mem.empty())
533
            {
534
34784
              for (const std::pair<const Node, Node>& itm1m : r1mem)
535
              {
536
43234
                Node xr = itm1m.first;
537
43234
                Node x = itm1m.second[0];
538
43234
                Trace("sets-debug") << "checking membership " << xr << " "
539
21617
                                    << itm1m.second << std::endl;
540
43234
                std::vector<Node> exp;
541
21617
                exp.push_back(itm1m.second);
542
21617
                d_state.addEqualityToExp(term[0], itm1m.second[1], exp);
543
21617
                bool valid = false;
544
21617
                int inferType = 0;
545
21617
                if (k == kind::UNION)
546
                {
547
5093
                  valid = true;
548
                }
549
16524
                else if (k == kind::INTERSECTION)
550
                {
551
                  // conclude x is in term
552
                  // if also existing in members of r2
553
5689
                  std::map<Node, Node>::const_iterator itm = r2mem.find(xr);
554
5689
                  if (itm != r2mem.end())
555
                  {
556
3098
                    exp.push_back(itm->second);
557
3098
                    d_state.addEqualityToExp(term[1], itm->second[1], exp);
558
3098
                    d_state.addEqualityToExp(x, itm->second[0], exp);
559
3098
                    valid = true;
560
                  }
561
                  else
562
                  {
563
                    // if not, check whether it is definitely not a member, if
564
                    // unknown, split
565
2591
                    if (r2nmem.find(xr) == r2nmem.end())
566
                    {
567
386
                      exp.push_back(nm->mkNode(kind::MEMBER, x, term[1]));
568
386
                      valid = true;
569
386
                      inferType = 1;
570
                    }
571
                  }
572
                }
573
                else
574
                {
575
10835
                  Assert(k == kind::SETMINUS);
576
10835
                  std::map<Node, Node>::const_iterator itm = r2mem.find(xr);
577
10835
                  if (itm == r2mem.end())
578
                  {
579
                    // must add lemma for set minus since non-membership in this
580
                    // case is not explained
581
5059
                    exp.push_back(
582
10118
                        nm->mkNode(kind::MEMBER, x, term[1]).negate());
583
5059
                    valid = true;
584
5059
                    inferType = 1;
585
                  }
586
                }
587
21617
                if (valid)
588
                {
589
27272
                  Node rr = d_equalityEngine->getRepresentative(term);
590
13636
                  if (!d_state.isMember(x, rr))
591
                  {
592
2158
                    Node kk = d_treg.getProxy(term);
593
2158
                    Node fact = nm->mkNode(kind::MEMBER, x, kk);
594
1079
                    d_im.assertInference(
595
                        fact, InferenceId::SETS_UP_CLOSURE, exp, inferType);
596
1079
                    if (d_state.isInConflict())
597
                    {
598
                      return;
599
                    }
600
                  }
601
                }
602
43234
                Trace("sets-debug") << "done checking membership " << xr << " "
603
21617
                                    << itm1m.second << std::endl;
604
              }
605
            }
606
14206
            if (k == kind::UNION)
607
            {
608
4570
              if (!r2mem.empty())
609
              {
610
                // for all members of r2
611
11079
                for (const std::pair<const Node, Node>& itm2m : r2mem)
612
                {
613
14694
                  Node x = itm2m.second[0];
614
14694
                  Node rr = d_equalityEngine->getRepresentative(term);
615
7347
                  if (!d_state.isMember(x, rr))
616
                  {
617
584
                    std::vector<Node> exp;
618
292
                    exp.push_back(itm2m.second);
619
292
                    d_state.addEqualityToExp(term[1], itm2m.second[1], exp);
620
584
                    Node r = d_treg.getProxy(term);
621
584
                    Node fact = nm->mkNode(kind::MEMBER, x, r);
622
292
                    d_im.assertInference(fact, InferenceId::SETS_UP_CLOSURE_2, exp);
623
292
                    if (d_state.isInConflict())
624
                    {
625
                      return;
626
                    }
627
                  }
628
                }
629
              }
630
            }
631
          }
632
        }
633
      }
634
    }
635
  }
636
12829
  if (!d_im.hasSent())
637
  {
638
12606
    if (options::setsExt())
639
    {
640
      // universal sets
641
934
      Trace("sets-debug") << "Check universe sets..." << std::endl;
642
      // all elements must be in universal set
643
934
      const std::vector<Node>& sec = d_state.getSetsEqClasses();
644
8264
      for (const Node& s : sec)
645
      {
646
        // if equivalence class contains a variable
647
14660
        Node v = d_state.getVariableSet(s);
648
7330
        if (!v.isNull())
649
        {
650
          // the variable in the equivalence class
651
4900
          std::map<TypeNode, Node> univ_set;
652
2450
          const std::map<Node, Node>& smems = d_state.getMembers(s);
653
5752
          for (const std::pair<const Node, Node>& it2 : smems)
654
          {
655
6604
            Node e = it2.second[0];
656
6604
            TypeNode tn = NodeManager::currentNM()->mkSetType(e.getType());
657
6604
            Node u;
658
3302
            std::map<TypeNode, Node>::iterator itu = univ_set.find(tn);
659
3302
            if (itu == univ_set.end())
660
            {
661
3414
              Node ueqc = d_state.getUnivSetEqClass(tn);
662
              // if the universe does not yet exist, or is not in this
663
              // equivalence class
664
1707
              if (s != ueqc)
665
              {
666
1215
                u = d_treg.getUnivSet(tn);
667
              }
668
1707
              univ_set[tn] = u;
669
            }
670
            else
671
            {
672
1595
              u = itu->second;
673
            }
674
3302
            if (!u.isNull())
675
            {
676
2044
              Assert(it2.second.getKind() == kind::MEMBER);
677
4088
              std::vector<Node> exp;
678
2044
              exp.push_back(it2.second);
679
2044
              if (v != it2.second[1])
680
              {
681
630
                exp.push_back(v.eqNode(it2.second[1]));
682
              }
683
4088
              Node fact = nm->mkNode(kind::MEMBER, it2.second[0], u);
684
2044
              d_im.assertInference(fact, InferenceId::SETS_UP_UNIV, exp);
685
2044
              if (d_state.isInConflict())
686
              {
687
                return;
688
              }
689
            }
690
          }
691
        }
692
      }
693
    }
694
  }
695
}
696
697
12294
void TheorySetsPrivate::checkDisequalities()
698
{
699
  // disequalities
700
12294
  Trace("sets") << "TheorySetsPrivate: check disequalities..." << std::endl;
701
12294
  NodeManager* nm = NodeManager::currentNM();
702
17558
  for (NodeBoolMap::const_iterator it = d_deq.begin(); it != d_deq.end(); ++it)
703
  {
704
5594
    if (!(*it).second)
705
    {
706
      // not active
707
7777
      continue;
708
    }
709
3081
    Node deq = (*it).first;
710
    // check if it is already satisfied
711
3081
    Assert(d_equalityEngine->hasTerm(deq[0])
712
           && d_equalityEngine->hasTerm(deq[1]));
713
3081
    Node r1 = d_equalityEngine->getRepresentative(deq[0]);
714
3081
    Node r2 = d_equalityEngine->getRepresentative(deq[1]);
715
3081
    bool is_sat = d_state.isSetDisequalityEntailed(r1, r2);
716
6162
    Trace("sets-debug") << "Check disequality " << deq
717
3081
                        << ", is_sat = " << is_sat << std::endl;
718
    // will process regardless of sat/processed/unprocessed
719
3081
    d_deq[deq] = false;
720
721
3081
    if (is_sat)
722
    {
723
      // already satisfied
724
2657
      continue;
725
    }
726
424
    if (d_termProcessed.find(deq) != d_termProcessed.end())
727
    {
728
      // already added lemma
729
94
      continue;
730
    }
731
330
    d_termProcessed.insert(deq);
732
330
    d_termProcessed.insert(deq[1].eqNode(deq[0]));
733
330
    Trace("sets") << "Process Disequality : " << deq.negate() << std::endl;
734
330
    TypeNode elementType = deq[0].getType().getSetElementType();
735
330
    Node x = d_skCache.mkTypedSkolemCached(
736
330
        elementType, deq[0], deq[1], SkolemCache::SK_DISEQUAL, "sde");
737
330
    Node mem1 = nm->mkNode(MEMBER, x, deq[0]);
738
330
    Node mem2 = nm->mkNode(MEMBER, x, deq[1]);
739
330
    Node lem = nm->mkNode(OR, deq, nm->mkNode(EQUAL, mem1, mem2).negate());
740
330
    lem = Rewriter::rewrite(lem);
741
330
    d_im.assertInference(lem, InferenceId::SETS_DEQ, d_true, 1);
742
330
    d_im.doPendingLemmas();
743
330
    if (d_im.hasSent())
744
    {
745
330
      return;
746
    }
747
  }
748
}
749
750
11964
void TheorySetsPrivate::checkReduceComprehensions()
751
{
752
11964
  NodeManager* nm = NodeManager::currentNM();
753
11964
  const std::vector<Node>& comps = d_state.getComprehensionSets();
754
11989
  for (const Node& n : comps)
755
  {
756
25
    if (d_termProcessed.find(n) != d_termProcessed.end())
757
    {
758
      // already reduced it
759
18
      continue;
760
    }
761
7
    d_termProcessed.insert(n);
762
14
    Node v = nm->mkBoundVar(n[2].getType());
763
14
    Node body = nm->mkNode(AND, n[1], v.eqNode(n[2]));
764
    // must do substitution
765
14
    std::vector<Node> vars;
766
14
    std::vector<Node> subs;
767
14
    for (const Node& cv : n[0])
768
    {
769
7
      vars.push_back(cv);
770
14
      Node cvs = nm->mkBoundVar(cv.getType());
771
7
      subs.push_back(cvs);
772
    }
773
7
    body = body.substitute(vars.begin(), vars.end(), subs.begin(), subs.end());
774
14
    Node bvl = nm->mkNode(BOUND_VAR_LIST, subs);
775
7
    body = nm->mkNode(EXISTS, bvl, body);
776
14
    Node mem = nm->mkNode(MEMBER, v, n);
777
    Node lem =
778
14
        nm->mkNode(FORALL, nm->mkNode(BOUND_VAR_LIST, v), body.eqNode(mem));
779
14
    Trace("sets-comprehension")
780
7
        << "Comprehension reduction: " << lem << std::endl;
781
7
    d_im.lemma(lem, InferenceId::SETS_COMPREHENSION);
782
  }
783
11964
}
784
785
//--------------------------------- standard check
786
787
45985
void TheorySetsPrivate::postCheck(Theory::Effort level)
788
{
789
91970
  Trace("sets-check") << "Sets finished assertions effort " << level
790
45985
                      << std::endl;
791
  // invoke full effort check, relations check
792
45985
  if (!d_state.isInConflict())
793
  {
794
43582
    if (level == Theory::EFFORT_FULL)
795
    {
796
16444
      if (!d_external.d_valuation.needCheck())
797
      {
798
13387
        fullEffortCheck();
799
40158
        if (!d_state.isInConflict() && !d_im.hasSentLemma()
800
24064
            && d_fullCheckIncomplete)
801
        {
802
4
          d_im.setIncomplete(d_fullCheckIncompleteId);
803
        }
804
      }
805
    }
806
  }
807
45984
  Trace("sets-check") << "Sets finish Check effort " << level << std::endl;
808
45984
}
809
810
72864
void TheorySetsPrivate::notifyFact(TNode atom, bool polarity, TNode fact)
811
{
812
72864
  if (d_state.isInConflict())
813
  {
814
2348
    return;
815
  }
816
70516
  if (atom.getKind() == kind::MEMBER && polarity)
817
  {
818
    // check if set has a value, if so, we can propagate
819
35452
    Node r = d_equalityEngine->getRepresentative(atom[1]);
820
17726
    EqcInfo* e = getOrMakeEqcInfo(r, true);
821
17726
    if (e)
822
    {
823
35452
      Node s = e->d_singleton;
824
17726
      if (!s.isNull())
825
      {
826
        Node pexp = NodeManager::currentNM()->mkNode(
827
1824
            kind::AND, atom, atom[1].eqNode(s));
828
912
        if (s.getKind() == kind::SINGLETON)
829
        {
830
857
          if (s[0] != atom[0])
831
          {
832
173
            Trace("sets-prop") << "Propagate mem-eq : " << pexp << std::endl;
833
346
            Node eq = s[0].eqNode(atom[0]);
834
            // triggers an internal inference
835
173
            d_im.assertSetsFact(eq, true, InferenceId::SETS_MEM_EQ, pexp);
836
          }
837
        }
838
        else
839
        {
840
110
          Trace("sets-prop")
841
55
              << "Propagate mem-eq conflict : " << pexp << std::endl;
842
55
          d_im.conflict(pexp, InferenceId::SETS_MEM_EQ_CONFLICT);
843
        }
844
      }
845
    }
846
    // add to membership list
847
17726
    d_state.addMember(r, atom);
848
  }
849
}
850
//--------------------------------- end standard check
851
852
/************************ Sharing ************************/
853
/************************ Sharing ************************/
854
/************************ Sharing ************************/
855
856
12245
void TheorySetsPrivate::addCarePairs(TNodeTrie* t1,
857
                                     TNodeTrie* t2,
858
                                     unsigned arity,
859
                                     unsigned depth,
860
                                     unsigned& n_pairs)
861
{
862
12245
  if (depth == arity)
863
  {
864
7280
    if (t2 != NULL)
865
    {
866
14560
      Node f1 = t1->getData();
867
14560
      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
7280
      if (f1.getKind() == MEMBER || !d_state.areEqual(f1, f2))
879
      {
880
7280
        Trace("sets-cg") << "Check " << f1 << " and " << f2 << std::endl;
881
14560
        vector<pair<TNode, TNode> > currentPairs;
882
21459
        for (unsigned k = 0; k < f1.getNumChildren(); ++k)
883
        {
884
28358
          TNode x = f1[k];
885
28358
          TNode y = f2[k];
886
14179
          Assert(d_equalityEngine->hasTerm(x));
887
14179
          Assert(d_equalityEngine->hasTerm(y));
888
14179
          Assert(!d_state.areDisequal(x, y));
889
14179
          Assert(!areCareDisequal(x, y));
890
14179
          if (!d_equalityEngine->areEqual(x, y))
891
          {
892
17264
            Trace("sets-cg")
893
8632
                << "Arg #" << k << " is " << x << " " << y << std::endl;
894
25896
            if (d_equalityEngine->isTriggerTerm(x, THEORY_SETS)
895
25896
                && d_equalityEngine->isTriggerTerm(y, THEORY_SETS))
896
            {
897
2867
              TNode x_shared = d_equalityEngine->getTriggerTermRepresentative(
898
5734
                  x, THEORY_SETS);
899
2867
              TNode y_shared = d_equalityEngine->getTriggerTermRepresentative(
900
5734
                  y, THEORY_SETS);
901
2867
              currentPairs.push_back(make_pair(x_shared, y_shared));
902
            }
903
5765
            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
10147
        for (unsigned c = 0; c < currentPairs.size(); ++c)
920
        {
921
5734
          Trace("sets-cg-pair") << "Pair : " << currentPairs[c].first << " "
922
2867
                                << currentPairs[c].second << std::endl;
923
2867
          d_external.addCarePair(currentPairs[c].first, currentPairs[c].second);
924
2867
          n_pairs++;
925
        }
926
      }
927
    }
928
  }
929
  else
930
  {
931
4965
    if (t2 == NULL)
932
    {
933
4333
      if (depth < (arity - 1))
934
      {
935
        // add care pairs internal to each child
936
3905
        for (std::pair<const TNode, TNodeTrie>& t : t1->d_data)
937
        {
938
3031
          addCarePairs(&t.second, NULL, arity, depth + 1, n_pairs);
939
        }
940
      }
941
      // add care pairs based on each pair of non-disequal arguments
942
14429
      for (std::map<TNode, TNodeTrie>::iterator it = t1->d_data.begin();
943
14429
           it != t1->d_data.end();
944
           ++it)
945
      {
946
10096
        std::map<TNode, TNodeTrie>::iterator it2 = it;
947
10096
        ++it2;
948
50902
        for (; it2 != t1->d_data.end(); ++it2)
949
        {
950
20403
          if (!d_equalityEngine->areDisequal(it->first, it2->first, false))
951
          {
952
10483
            if (!areCareDisequal(it->first, it2->first))
953
            {
954
18774
              addCarePairs(
955
12516
                  &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
1724
      for (std::pair<const TNode, TNodeTrie>& tt1 : t1->d_data)
965
      {
966
3317
        for (std::pair<const TNode, TNodeTrie>& tt2 : t2->d_data)
967
        {
968
2225
          if (!d_equalityEngine->areDisequal(tt1.first, tt2.first, false))
969
          {
970
1654
            if (!areCareDisequal(tt1.first, tt2.first))
971
            {
972
1654
              addCarePairs(&tt1.second, &tt2.second, arity, depth + 1, n_pairs);
973
            }
974
          }
975
        }
976
      }
977
    }
978
  }
979
12245
}
980
981
5237
void TheorySetsPrivate::computeCareGraph()
982
{
983
5237
  const std::map<Kind, std::vector<Node> >& ol = d_state.getOperatorList();
984
6775
  for (const std::pair<const Kind, std::vector<Node> >& it : ol)
985
  {
986
1538
    Kind k = it.first;
987
1538
    if (k == kind::SINGLETON || k == kind::MEMBER)
988
    {
989
1007
      unsigned n_pairs = 0;
990
2014
      Trace("sets-cg-summary") << "Compute graph for sets, op=" << k << "..."
991
1007
                               << it.second.size() << std::endl;
992
1007
      Trace("sets-cg") << "Build index for " << k << "..." << std::endl;
993
2014
      std::map<TypeNode, TNodeTrie> index;
994
1007
      unsigned arity = 0;
995
      // populate indices
996
8072
      for (TNode f1 : it.second)
997
      {
998
7065
        Trace("sets-cg-debug") << "...build for " << f1 << std::endl;
999
7065
        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
14130
        TypeNode tn;
1003
7065
        if (k == kind::SINGLETON)
1004
        {
1005
          // get the type of the singleton set (not the type of its element)
1006
1191
          tn = f1.getType().getSetElementType();
1007
        }
1008
        else
1009
        {
1010
5874
          Assert (k == kind::MEMBER);
1011
          // get the element type of the set (not the type of the element)
1012
5874
          tn = f1[1].getType().getSetElementType();
1013
        }
1014
14130
        std::vector<TNode> reps;
1015
7065
        bool hasCareArg = false;
1016
20004
        for (unsigned j = 0; j < f1.getNumChildren(); j++)
1017
        {
1018
12939
          reps.push_back(d_equalityEngine->getRepresentative(f1[j]));
1019
12939
          if (isCareArg(f1, j))
1020
          {
1021
9126
            hasCareArg = true;
1022
          }
1023
        }
1024
7065
        if (hasCareArg)
1025
        {
1026
7065
          Trace("sets-cg-debug") << "......adding." << std::endl;
1027
7065
          index[tn].addTerm(f1, reps);
1028
7065
          arity = reps.size();
1029
        }
1030
        else
1031
        {
1032
          Trace("sets-cg-debug") << "......skip." << std::endl;
1033
        }
1034
      }
1035
1007
      if (arity > 0)
1036
      {
1037
        // for each index
1038
2309
        for (std::pair<const TypeNode, TNodeTrie>& tt : index)
1039
        {
1040
2604
          Trace("sets-cg") << "Process index " << tt.first << "..."
1041
1302
                           << std::endl;
1042
1302
          addCarePairs(&tt.second, nullptr, arity, 0, n_pairs);
1043
        }
1044
      }
1045
1007
      Trace("sets-cg-summary") << "...done, # pairs = " << n_pairs << std::endl;
1046
    }
1047
  }
1048
5237
}
1049
1050
20487
bool TheorySetsPrivate::isCareArg(Node n, unsigned a)
1051
{
1052
20487
  if (d_equalityEngine->isTriggerTerm(n[a], THEORY_SETS))
1053
  {
1054
10895
    return true;
1055
  }
1056
19184
  else if ((n.getKind() == kind::MEMBER || n.getKind() == kind::SINGLETON)
1057
28776
           && a == 0 && n[0].getType().isSet())
1058
  {
1059
20
    return true;
1060
  }
1061
  else
1062
  {
1063
9572
    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
2832
void traceSetElementsRecursively(stringstream& stream, const Node& set)
1079
{
1080
2832
  Assert(set.getType().isSet());
1081
2832
  if (set.getKind() == SINGLETON)
1082
  {
1083
1922
    stream << set[0] << ", ";
1084
  }
1085
2832
  if (set.getKind() == UNION)
1086
  {
1087
670
    traceSetElementsRecursively(stream, set[0]);
1088
670
    traceSetElementsRecursively(stream, set[1]);
1089
  }
1090
2832
}
1091
1092
1492
std::string traceElements(const Node& set)
1093
{
1094
2984
  std::stringstream stream;
1095
1492
  traceSetElementsRecursively(stream, set);
1096
2984
  return stream.str();
1097
}
1098
1099
}  // namespace
1100
1101
4207
bool TheorySetsPrivate::collectModelValues(TheoryModel* m,
1102
                                           const std::set<Node>& termSet)
1103
{
1104
4207
  Trace("sets-model") << "Set collect model values" << std::endl;
1105
1106
4207
  NodeManager* nm = NodeManager::currentNM();
1107
8414
  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
4207
  const std::vector<Node>& sec = d_card_enabled
1113
8352
                                     ? d_cardSolver->getOrderedSetsEqClasses()
1114
8352
                                     : d_state.getSetsEqClasses();
1115
4207
  Valuation& val = getValuation();
1116
5741
  for (int i = (int)(sec.size() - 1); i >= 0; i--)
1117
  {
1118
3068
    Node eqc = sec[i];
1119
1534
    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
2984
      std::vector<Node> els;
1127
1492
      bool is_base = !d_card_enabled || d_cardSolver->isModelValueBasic(eqc);
1128
1492
      if (is_base)
1129
      {
1130
2874
        Trace("sets-model")
1131
1437
            << "Collect elements of base eqc " << eqc << std::endl;
1132
        // members that must be in eqc
1133
1437
        const std::map<Node, Node>& emems = d_state.getMembers(eqc);
1134
1437
        if (!emems.empty())
1135
        {
1136
2466
          TypeNode elementType = eqc.getType().getSetElementType();
1137
2972
          for (const std::pair<const Node, Node>& itmm : emems)
1138
          {
1139
3478
            Trace("sets-model")
1140
1739
                << "m->getRepresentative(" << itmm.first
1141
1739
                << ")= " << m->getRepresentative(itmm.first) << std::endl;
1142
3478
            Node t = nm->mkSingleton(elementType, itmm.first);
1143
1739
            els.push_back(t);
1144
          }
1145
        }
1146
      }
1147
1492
      if (d_card_enabled)
1148
      {
1149
        // make the slack elements for the equivalence class based on set
1150
        // cardinality
1151
163
        d_cardSolver->mkModelValueElementsFor(val, eqc, els, mvals, m);
1152
      }
1153
1154
2984
      Node rep = NormalForm::mkBop(kind::UNION, els, eqc.getType());
1155
1492
      rep = Rewriter::rewrite(rep);
1156
2984
      Trace("sets-model") << "* Assign representative of " << eqc << " to "
1157
1492
                          << rep << std::endl;
1158
1492
      mvals[eqc] = rep;
1159
1492
      if (!m->assertEquality(eqc, rep, true))
1160
      {
1161
        return false;
1162
      }
1163
1492
      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
3345
      for (const Node& el : els)
1176
      {
1177
1853
        m->assertSkeleton(el);
1178
      }
1179
1180
2984
      Trace("sets-model") << "Set " << eqc << " = { " << traceElements(rep)
1181
1492
                          << " }" << std::endl;
1182
    }
1183
  }
1184
1185
  // handle slack elements constraints for finite types
1186
4207
  if (d_card_enabled)
1187
  {
1188
    const std::map<TypeNode, std::vector<TNode> >& slackElements =
1189
62
        d_cardSolver->getFiniteTypeSlackElements();
1190
72
    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
4207
  return true;
1200
}
1201
1202
/********************** Helper functions ***************************/
1203
/********************** Helper functions ***************************/
1204
/********************** Helper functions ***************************/
1205
1206
1090
Node mkAnd(const std::vector<TNode>& conjunctions)
1207
{
1208
1090
  Assert(conjunctions.size() > 0);
1209
1210
2180
  std::set<TNode> all;
1211
4801
  for (unsigned i = 0; i < conjunctions.size(); ++i)
1212
  {
1213
7422
    TNode t = conjunctions[i];
1214
3711
    if (t.getKind() == kind::AND)
1215
    {
1216
339
      for (TNode::iterator child_it = t.begin(); child_it != t.end();
1217
           ++child_it)
1218
      {
1219
226
        Assert((*child_it).getKind() != kind::AND);
1220
226
        all.insert(*child_it);
1221
      }
1222
    }
1223
    else
1224
    {
1225
3598
      all.insert(t);
1226
    }
1227
  }
1228
1229
1090
  Assert(all.size() > 0);
1230
1090
  if (all.size() == 1)
1231
  {
1232
    // All the same, or just one
1233
123
    return conjunctions[0];
1234
  }
1235
1236
1934
  NodeBuilder conjunction(kind::AND);
1237
967
  std::set<TNode>::const_iterator it = all.begin();
1238
967
  std::set<TNode>::const_iterator it_end = all.end();
1239
7955
  while (it != it_end)
1240
  {
1241
3494
    conjunction << *it;
1242
3494
    ++it;
1243
  }
1244
967
  return conjunction;
1245
} /* mkAnd() */
1246
1247
4207
Valuation& TheorySetsPrivate::getValuation() { return d_external.d_valuation; }
1248
1249
1090
Node TheorySetsPrivate::explain(TNode literal)
1250
{
1251
1090
  Debug("sets") << "TheorySetsPrivate::explain(" << literal << ")" << std::endl;
1252
1253
1090
  bool polarity = literal.getKind() != kind::NOT;
1254
2180
  TNode atom = polarity ? literal : literal[0];
1255
2180
  std::vector<TNode> assumptions;
1256
1257
1090
  if (atom.getKind() == kind::EQUAL)
1258
  {
1259
653
    d_equalityEngine->explainEquality(atom[0], atom[1], polarity, assumptions);
1260
  }
1261
437
  else if (atom.getKind() == kind::MEMBER)
1262
  {
1263
437
    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
2180
  return mkAnd(assumptions);
1273
}
1274
1275
26253
void TheorySetsPrivate::preRegisterTerm(TNode node)
1276
{
1277
52506
  Debug("sets") << "TheorySetsPrivate::preRegisterTerm(" << node << ")"
1278
26253
                << std::endl;
1279
26253
  switch (node.getKind())
1280
  {
1281
14991
    case kind::EQUAL:
1282
    case kind::MEMBER:
1283
    {
1284
      // add trigger predicate for equality and membership
1285
14991
      d_equalityEngine->addTriggerPredicate(node);
1286
    }
1287
14991
    break;
1288
19
    case kind::JOIN_IMAGE:
1289
    {
1290
      // these are logic exceptions, not type checking exceptions
1291
19
      if (node[1].getKind() != kind::CONST_RATIONAL)
1292
      {
1293
        throw LogicException(
1294
            "JoinImage cardinality constraint must be a constant");
1295
      }
1296
38
      cvc5::Rational r(INT_MAX);
1297
19
      if (node[1].getConst<Rational>() > r)
1298
      {
1299
        throw LogicException(
1300
            "JoinImage Exceeded INT_MAX in cardinality constraint");
1301
      }
1302
19
      if (node[1].getConst<Rational>().getNumerator().getSignedInt() < 0)
1303
      {
1304
        throw LogicException(
1305
            "JoinImage cardinality constraint must be non-negative");
1306
19
      }
1307
    }
1308
19
    break;
1309
11243
    default: d_equalityEngine->addTerm(node); break;
1310
  }
1311
26253
}
1312
1313
19624
TrustNode TheorySetsPrivate::ppRewrite(Node node,
1314
                                       std::vector<SkolemLemma>& lems)
1315
{
1316
19624
  Debug("sets-proc") << "ppRewrite : " << node << std::endl;
1317
1318
19624
  switch (node.getKind())
1319
  {
1320
6
    case kind::CHOOSE: return expandChooseOperator(node, lems);
1321
6
    case kind::IS_SINGLETON: return expandIsSingletonOperator(node);
1322
19612
    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
6
TrustNode TheorySetsPrivate::expandIsSingletonOperator(const Node& node)
1359
{
1360
6
  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
12
  Node rewritten = Rewriter::rewrite(node);
1365
6
  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
6
  NodeManager* nm = NodeManager::currentNM();
1375
12
  Node set = rewritten[0];
1376
1377
6
  std::map<Node, Node>::iterator it = d_isSingletonNodes.find(rewritten);
1378
1379
6
  if (it != d_isSingletonNodes.end())
1380
  {
1381
    return TrustNode::mkTrustRewrite(rewritten, it->second, nullptr);
1382
  }
1383
1384
12
  TypeNode setType = set.getType();
1385
12
  Node boundVar = nm->mkBoundVar(setType.getSetElementType());
1386
12
  Node singleton = nm->mkSingleton(setType.getSetElementType(), boundVar);
1387
12
  Node equal = set.eqNode(singleton);
1388
12
  std::vector<Node> variables = {boundVar};
1389
12
  Node boundVars = nm->mkNode(BOUND_VAR_LIST, variables);
1390
12
  Node exists = nm->mkNode(kind::EXISTS, boundVars, equal);
1391
6
  d_isSingletonNodes[rewritten] = exists;
1392
1393
6
  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
9354
void TheorySetsPrivate::presolve() { d_state.reset(); }
1417
1418
}  // namespace sets
1419
}  // namespace theory
1420
22746
}  // namespace cvc5