GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/datatypes/theory_datatypes.cpp Lines: 999 1130 88.4 %
Date: 2021-05-22 Branches: 2313 5110 45.3 %

Line Exec Source
1
/******************************************************************************
2
 * Top contributors (to current version):
3
 *   Andrew Reynolds, Morgan Deters, Mathias Preiner
4
 *
5
 * This file is part of the cvc5 project.
6
 *
7
 * Copyright (c) 2009-2021 by the authors listed in the file AUTHORS
8
 * in the top-level source directory and their institutional affiliations.
9
 * All rights reserved.  See the file COPYING in the top-level source
10
 * directory for licensing information.
11
 * ****************************************************************************
12
 *
13
 * Implementation of the theory of datatypes.
14
 */
15
#include "theory/datatypes/theory_datatypes.h"
16
17
#include <map>
18
#include <sstream>
19
20
#include "base/check.h"
21
#include "expr/dtype.h"
22
#include "expr/dtype_cons.h"
23
#include "expr/kind.h"
24
#include "expr/proof_node_manager.h"
25
#include "expr/skolem_manager.h"
26
#include "options/datatypes_options.h"
27
#include "options/quantifiers_options.h"
28
#include "options/smt_options.h"
29
#include "options/theory_options.h"
30
#include "smt/logic_exception.h"
31
#include "theory/datatypes/datatypes_rewriter.h"
32
#include "theory/datatypes/theory_datatypes_type_rules.h"
33
#include "theory/datatypes/theory_datatypes_utils.h"
34
#include "theory/logic_info.h"
35
#include "theory/quantifiers_engine.h"
36
#include "theory/rewriter.h"
37
#include "theory/theory_model.h"
38
#include "theory/theory_state.h"
39
#include "theory/type_enumerator.h"
40
#include "theory/valuation.h"
41
42
using namespace std;
43
using namespace cvc5::kind;
44
using namespace cvc5::context;
45
46
namespace cvc5 {
47
namespace theory {
48
namespace datatypes {
49
50
9459
TheoryDatatypes::TheoryDatatypes(Context* c,
51
                                 UserContext* u,
52
                                 OutputChannel& out,
53
                                 Valuation valuation,
54
                                 const LogicInfo& logicInfo,
55
9459
                                 ProofNodeManager* pnm)
56
    : Theory(THEORY_DATATYPES, c, u, out, valuation, logicInfo, pnm),
57
      d_term_sk(u),
58
      d_labels(c),
59
      d_selector_apps(c),
60
      d_collectTermsCache(c),
61
      d_collectTermsCacheU(u),
62
      d_functionTerms(c),
63
      d_singleton_eq(u),
64
      d_lemmas_produced_c(u),
65
      d_sygusExtension(nullptr),
66
      d_state(c, u, valuation),
67
      d_im(*this, d_state, pnm),
68
9459
      d_notify(d_im, *this)
69
{
70
71
9459
  d_true = NodeManager::currentNM()->mkConst( true );
72
9459
  d_zero = NodeManager::currentNM()->mkConst( Rational(0) );
73
9459
  d_dtfCounter = 0;
74
75
  // indicate we are using the default theory state object
76
9459
  d_theoryState = &d_state;
77
9459
  d_inferManager = &d_im;
78
9459
}
79
80
28377
TheoryDatatypes::~TheoryDatatypes() {
81
33321
  for(std::map< Node, EqcInfo* >::iterator i = d_eqc_info.begin(), iend = d_eqc_info.end();
82
33321
      i != iend; ++i){
83
23862
    EqcInfo* current = (*i).second;
84
23862
    Assert(current != NULL);
85
23862
    delete current;
86
  }
87
18918
}
88
89
9459
TheoryRewriter* TheoryDatatypes::getTheoryRewriter() { return &d_rewriter; }
90
91
3600
ProofRuleChecker* TheoryDatatypes::getProofChecker() { return &d_checker; }
92
93
9459
bool TheoryDatatypes::needsEqualityEngine(EeSetupInfo& esi)
94
{
95
9459
  esi.d_notify = &d_notify;
96
9459
  esi.d_name = "theory::datatypes::ee";
97
9459
  return true;
98
}
99
100
9459
void TheoryDatatypes::finishInit()
101
{
102
9459
  Assert(d_equalityEngine != nullptr);
103
  // The kinds we are treating as function application in congruence
104
9459
  d_equalityEngine->addFunctionKind(kind::APPLY_CONSTRUCTOR);
105
9459
  d_equalityEngine->addFunctionKind(kind::APPLY_SELECTOR_TOTAL);
106
9459
  d_equalityEngine->addFunctionKind(kind::APPLY_TESTER);
107
  // We could but don't do congruence for DT_SIZE and DT_HEIGHT_BOUND here.
108
  // It also could make sense in practice to do congruence for APPLY_UF, but
109
  // this is not done.
110
9459
  if (getQuantifiersEngine() && options::sygus())
111
  {
112
    quantifiers::TermDbSygus* tds =
113
1529
        getQuantifiersEngine()->getTermDatabaseSygus();
114
1529
    d_sygusExtension.reset(new SygusExtension(d_state, d_im, tds));
115
    // do congruence on evaluation functions
116
1529
    d_equalityEngine->addFunctionKind(kind::DT_SYGUS_EVAL);
117
  }
118
  // testers are not relevant for model building
119
9459
  d_valuation.setIrrelevantKind(APPLY_TESTER);
120
9459
}
121
122
2416559
TheoryDatatypes::EqcInfo* TheoryDatatypes::getOrMakeEqcInfo( TNode n, bool doMake ){
123
2416559
  if( !hasEqcInfo( n ) ){
124
594655
    if( doMake ){
125
      //add to labels
126
144929
      d_labels[ n ] = 0;
127
128
144929
      std::map< Node, EqcInfo* >::iterator eqc_i = d_eqc_info.find( n );
129
      EqcInfo* ei;
130
144929
      if( eqc_i != d_eqc_info.end() ){
131
121067
        ei = eqc_i->second;
132
      }else{
133
23862
        ei = new EqcInfo( getSatContext() );
134
23862
        d_eqc_info[n] = ei;
135
      }
136
144929
      if( n.getKind()==APPLY_CONSTRUCTOR ){
137
104007
        ei->d_constructor = n;
138
      }
139
140
      //add to selectors
141
144929
      d_selector_apps[n] = 0;
142
143
144929
      return ei;
144
    }else{
145
449726
      return NULL;
146
    }
147
  }else{
148
1821904
    std::map< Node, EqcInfo* >::iterator eqc_i = d_eqc_info.find( n );
149
1821904
    return (*eqc_i).second;
150
  }
151
}
152
153
624028
TNode TheoryDatatypes::getEqcConstructor( TNode r ) {
154
624028
  if( r.getKind()==APPLY_CONSTRUCTOR ){
155
387197
    return r;
156
  }else{
157
236831
    EqcInfo * ei = getOrMakeEqcInfo( r, false );
158
236831
    if( ei && !ei->d_constructor.get().isNull() ){
159
56764
      return ei->d_constructor.get();
160
    }else{
161
180067
      return r;
162
    }
163
  }
164
}
165
166
488688
bool TheoryDatatypes::preCheck(Effort level)
167
{
168
488688
  d_im.reset();
169
488688
  d_im.clearPending();
170
488688
  return false;
171
}
172
173
488688
void TheoryDatatypes::postCheck(Effort level)
174
{
175
  // Apply any last pending inferences, which may occur if the last processed
176
  // fact was an internal one and triggered further internal inferences.
177
488688
  d_im.process();
178
488688
  if (level == EFFORT_LAST_CALL)
179
  {
180
5473
    Assert(d_sygusExtension != nullptr);
181
5473
    d_sygusExtension->check();
182
5473
    return;
183
  }
184
993749
  else if (level == EFFORT_FULL && !d_state.isInConflict()
185
510394
           && !d_im.hasSentLemma() && !d_valuation.needCheck())
186
  {
187
    //check for cycles
188
23479
    Assert(!d_im.hasPendingFact());
189
4
    do {
190
23483
      d_im.reset();
191
23483
      Trace("datatypes-proc") << "Check cycles..." << std::endl;
192
23483
      checkCycles();
193
23483
      Trace("datatypes-proc") << "...finish check cycles" << std::endl;
194
23483
      d_im.process();
195
23483
      if (d_state.isInConflict() || d_im.hasSentLemma())
196
      {
197
418
        return;
198
      }
199
23065
    } while (d_im.hasSentFact());
200
201
    //check for splits
202
23061
    Trace("datatypes-debug") << "Check for splits " << endl;
203
968
    do {
204
24029
      d_im.reset();
205
48058
      std::map< TypeNode, Node > rec_singletons;
206
24029
      eq::EqClassesIterator eqcs_i = eq::EqClassesIterator(d_equalityEngine);
207
888867
      while( !eqcs_i.isFinished() ){
208
866000
        Node n = (*eqcs_i);
209
        //TODO : avoid irrelevant (pre-registered but not asserted) terms here?
210
866000
        TypeNode tn = n.getType();
211
433581
        if( tn.isDatatype() ){
212
139484
          Trace("datatypes-debug") << "Process equivalence class " << n << std::endl;
213
139484
          EqcInfo* eqc = getOrMakeEqcInfo( n );
214
          //if there are more than 1 possible constructors for eqc
215
139484
          if( !hasLabel( eqc, n ) ){
216
38658
            Trace("datatypes-debug") << "No constructor..." << std::endl;
217
76154
            TypeNode tt = tn;
218
38658
            const DType& dt = tt.getDType();
219
77316
            Trace("datatypes-debug")
220
77316
                << "Datatype " << dt.getName() << " is "
221
77316
                << dt.getCardinalityClass(tt) << " "
222
38658
                << dt.isRecursiveSingleton(tt) << std::endl;
223
38658
            bool continueProc = true;
224
38658
            if( dt.isRecursiveSingleton( tt ) ){
225
8
              Trace("datatypes-debug") << "Check recursive singleton..." << std::endl;
226
              //handle recursive singleton case
227
8
              std::map< TypeNode, Node >::iterator itrs = rec_singletons.find( tn );
228
8
              if( itrs!=rec_singletons.end() ){
229
8
                Node eq = n.eqNode( itrs->second );
230
4
                if( d_singleton_eq.find( eq )==d_singleton_eq.end() ){
231
4
                  d_singleton_eq[eq] = true;
232
                  // get assumptions
233
4
                  bool success = true;
234
8
                  std::vector< Node > assumptions;
235
                  //if there is at least one uninterpreted sort occurring within the datatype and the logic is not quantified, add lemmas ensuring cardinality is more than one,
236
                  //  do not infer the equality if at least one sort was processed.
237
                  //otherwise, if the logic is quantified, under the assumption that all uninterpreted sorts have cardinality one,
238
                  //  infer the equality.
239
4
                  for( unsigned i=0; i<dt.getNumRecursiveSingletonArgTypes( tt ); i++ ){
240
                    TypeNode type = dt.getRecursiveSingletonArgType(tt, i);
241
                    if( getQuantifiersEngine() ){
242
                      // under the assumption that the cardinality of this type is one
243
                      Node a = getSingletonLemma(type, true);
244
                      assumptions.push_back( a.negate() );
245
                    }else{
246
                      success = false;
247
                      // assert that the cardinality of this type is more than one
248
                      getSingletonLemma(type, false);
249
                    }
250
                  }
251
4
                  if( success ){
252
8
                    Node assumption = n.eqNode(itrs->second);
253
4
                    assumptions.push_back(assumption);
254
8
                    Node lemma = assumptions.size()==1 ? assumptions[0] : NodeManager::currentNM()->mkNode( OR, assumptions );
255
4
                    Trace("dt-singleton") << "*************Singleton equality lemma " << lemma << std::endl;
256
4
                    d_im.lemma(lemma, InferenceId::DATATYPES_REC_SINGLETON_EQ);
257
                  }
258
                }
259
              }else{
260
4
                rec_singletons[tn] = n;
261
              }
262
              //do splitting for quantified logics (incomplete anyways)
263
8
              continueProc = ( getQuantifiersEngine()!=NULL );
264
            }
265
38658
            if( continueProc ){
266
38658
              Trace("datatypes-debug") << "Get possible cons..." << std::endl;
267
              //all other cases
268
76154
              std::vector< bool > pcons;
269
38658
              getPossibleCons( eqc, n, pcons );
270
              //check if we do not need to resolve the constructor type for this equivalence class.
271
              // this is if there are no selectors for this equivalence class, and its possible values are infinite,
272
              //  then do not split.
273
38658
              int consIndex = -1;
274
38658
              int fconsIndex = -1;
275
38658
              bool needSplit = true;
276
210347
              for (size_t j = 0, psize = pcons.size(); j < psize; j++)
277
              {
278
171689
                if( pcons[j] ) {
279
170544
                  if( consIndex==-1 ){
280
38564
                    consIndex = j;
281
                  }
282
341088
                  Trace("datatypes-debug") << j << " compute finite..."
283
170544
                                           << std::endl;
284
                  // Notice that we split here on all datatypes except the
285
                  // truly infinite ones. It is possible to also not split
286
                  // on those that are interpreted-finite when finite model
287
                  // finding is disabled, but as a heuristic we choose to split
288
                  // on those too.
289
341088
                  bool ifin = dt[j].getCardinalityClass(tt)
290
170544
                              != CardinalityClass::INFINITE;
291
341088
                  Trace("datatypes-debug") << "...returned " << ifin
292
170544
                                           << std::endl;
293
170544
                  if (!ifin)
294
                  {
295
115861
                    if( !eqc || !eqc->d_selectors ){
296
113067
                      needSplit = false;
297
                    }
298
                  }else{
299
54683
                    if( fconsIndex==-1 ){
300
35951
                      fconsIndex = j;
301
                    }
302
                  }
303
                }
304
              }
305
              //if we want to force an assignment of constructors to all ground eqc
306
              //d_dtfCounter++;
307
66782
              if( !needSplit && options::dtForceAssignment() && d_dtfCounter%2==0 ){
308
                Trace("datatypes-force-assign") << "Force assignment for " << n << std::endl;
309
                needSplit = true;
310
                consIndex = fconsIndex!=-1 ? fconsIndex : consIndex;
311
              }
312
313
38658
              if( needSplit ) {
314
10534
                if( dt.getNumConstructors()==1 ){
315
                  //this may not be necessary?
316
                  //if only one constructor, then this term must be this constructor
317
18744
                  Node t = utils::mkTester(n, 0, dt);
318
9372
                  d_im.addPendingInference(
319
                      t, InferenceId::DATATYPES_SPLIT, d_true);
320
9372
                  Trace("datatypes-infer") << "DtInfer : 1-cons (full) : " << t << std::endl;
321
                }else{
322
1162
                  Assert(consIndex != -1 || dt.isSygus());
323
2324
                  if( options::dtBinarySplit() && consIndex!=-1 ){
324
                    Node test = utils::mkTester(n, consIndex, dt);
325
                    Trace("dt-split") << "*************Split for possible constructor " << dt[consIndex] << " for " << n << endl;
326
                    test = Rewriter::rewrite( test );
327
                    NodeBuilder nb(kind::OR);
328
                    nb << test << test.notNode();
329
                    Node lemma = nb;
330
                    d_im.lemma(lemma, InferenceId::DATATYPES_BINARY_SPLIT);
331
                    d_im.requirePhase(test, true);
332
                  }else{
333
1162
                    Trace("dt-split") << "*************Split for constructors on " << n <<  endl;
334
2324
                    Node lemma = utils::mkSplit(n, dt);
335
1162
                    Trace("dt-split-debug") << "Split lemma is : " << lemma << std::endl;
336
1162
                    d_im.sendDtLemma(lemma,
337
                                     InferenceId::DATATYPES_SPLIT,
338
                                     LemmaProperty::SEND_ATOMS);
339
                  }
340
2324
                  if( !options::dtBlastSplits() ){
341
1162
                    break;
342
                  }
343
                }
344
              }else{
345
28124
                Trace("dt-split-debug") << "Do not split constructor for " << n << " : " << n.getType() << " " << dt.getNumConstructors() << std::endl;
346
              }
347
            }
348
          }else{
349
100826
            Trace("datatypes-debug") << "Has constructor " << eqc->d_constructor.get() << std::endl;
350
          }
351
        }
352
432419
        ++eqcs_i;
353
      }
354
24029
      if (d_im.hasSentLemma())
355
      {
356
        // clear pending facts: we added a lemma, so internal inferences are
357
        // no longer necessary
358
1166
        d_im.clearPendingFacts();
359
      }
360
      else
361
      {
362
        // we did not add a lemma, process internal inferences. This loop
363
        // will repeat.
364
22863
        Trace("datatypes-debug") << "Flush pending facts..." << std::endl;
365
22863
        d_im.process();
366
      }
367
47557
    } while (!d_state.isInConflict() && !d_im.hasSentLemma()
368
46234
             && d_im.hasSentFact());
369
46122
    Trace("datatypes-debug")
370
46122
        << "Finished, conflict=" << d_state.isInConflict()
371
23061
        << ", lemmas=" << d_im.hasSentLemma() << std::endl;
372
23061
    if (!d_state.isInConflict())
373
    {
374
22560
      Trace("dt-model-debug") << std::endl;
375
22560
      printModelDebug("dt-model-debug");
376
    }
377
  }
378
379
482797
  Trace("datatypes-check") << "Finished check effort " << level << std::endl;
380
482797
  if( Debug.isOn("datatypes") || Debug.isOn("datatypes-split") ) {
381
    Notice() << "TheoryDatatypes::check(): done" << endl;
382
  }
383
}
384
385
10164
bool TheoryDatatypes::needsCheckLastEffort() {
386
10164
  return d_sygusExtension != nullptr;
387
}
388
389
1998316
void TheoryDatatypes::notifyFact(TNode atom,
390
                                 bool polarity,
391
                                 TNode fact,
392
                                 bool isInternal)
393
{
394
3996632
  Trace("datatypes-debug") << "TheoryDatatypes::assertFact : " << fact
395
1998316
                           << ", isInternal = " << isInternal << std::endl;
396
  // could be sygus-specific
397
1998316
  if (d_sygusExtension)
398
  {
399
1549372
    d_sygusExtension->assertFact(atom, polarity);
400
  }
401
  //add to tester if applicable
402
3996632
  Node t_arg;
403
1998316
  int tindex = utils::isTester(atom, t_arg);
404
1998316
  if (tindex >= 0)
405
  {
406
900960
    Trace("dt-tester") << "Assert tester : " << atom << " for " << t_arg << std::endl;
407
1801920
    Node rep = getRepresentative( t_arg );
408
900960
    EqcInfo* eqc = getOrMakeEqcInfo( rep, true );
409
    Node tst =
410
1801920
        isInternal ? (polarity ? Node(atom) : atom.notNode()) : Node(fact);
411
900960
    addTester(tindex, tst, eqc, rep, t_arg);
412
900960
    Trace("dt-tester") << "Done assert tester." << std::endl;
413
900960
    Trace("dt-tester") << "Done pending merges." << std::endl;
414
900960
    if (!d_state.isInConflict() && polarity)
415
    {
416
249363
      if (d_sygusExtension)
417
      {
418
197081
        Trace("dt-tester") << "Assert tester to sygus : " << atom << std::endl;
419
197081
        d_sygusExtension->assertTester(tindex, t_arg, atom);
420
197081
        Trace("dt-tester") << "Done assert tester to sygus." << std::endl;
421
      }
422
    }
423
  }else{
424
1097356
    Trace("dt-tester-debug") << "Assert (non-tester) : " << atom << std::endl;
425
  }
426
1998316
  Trace("datatypes-debug") << "TheoryDatatypes::assertFact : finished " << fact << std::endl;
427
  // now, flush pending facts if this wasn't an internal call
428
1998316
  if (!isInternal)
429
  {
430
1706979
    d_im.process();
431
  }
432
1998316
}
433
434
168510
void TheoryDatatypes::preRegisterTerm(TNode n)
435
{
436
337020
  Trace("datatypes-prereg")
437
168510
      << "TheoryDatatypes::preRegisterTerm() " << n << endl;
438
  // external selectors should be preprocessed away by now
439
168510
  Assert(n.getKind() != APPLY_SELECTOR);
440
  // must ensure the type is well founded and has no nested recursion if
441
  // the option dtNestedRec is not set to true.
442
337020
  TypeNode tn = n.getType();
443
168510
  if (tn.isDatatype())
444
  {
445
67632
    const DType& dt = tn.getDType();
446
67632
    Trace("dt-expand") << "Check properties of " << dt.getName() << std::endl;
447
67632
    if (!dt.isWellFounded())
448
    {
449
      std::stringstream ss;
450
      ss << "Cannot handle non-well-founded datatype " << dt.getName();
451
      throw LogicException(ss.str());
452
    }
453
67632
    Trace("dt-expand") << "...well-founded ok" << std::endl;
454
135274
    if (!options::dtNestedRec())
455
    {
456
67404
      if (dt.hasNestedRecursion())
457
      {
458
2
        std::stringstream ss;
459
1
        ss << "Cannot handle nested-recursive datatype " << dt.getName();
460
1
        throw LogicException(ss.str());
461
      }
462
67403
      Trace("dt-expand") << "...nested recursion ok" << std::endl;
463
    }
464
  }
465
168509
  collectTerms( n );
466
168509
  switch (n.getKind()) {
467
77016
  case kind::EQUAL:
468
  case kind::APPLY_TESTER:
469
    // add predicate trigger for testers and equalities
470
    // Get triggered for both equal and dis-equal
471
77016
    d_equalityEngine->addTriggerPredicate(n);
472
77016
    break;
473
91493
  default:
474
    // Function applications/predicates
475
91493
    d_equalityEngine->addTerm(n);
476
91493
    if (d_sygusExtension)
477
    {
478
21040
      d_sygusExtension->preRegisterTerm(n);
479
    }
480
91493
    break;
481
  }
482
168509
  d_im.process();
483
168509
}
484
485
75748
TrustNode TheoryDatatypes::ppRewrite(TNode in, std::vector<SkolemLemma>& lems)
486
{
487
75748
  Debug("tuprec") << "TheoryDatatypes::ppRewrite(" << in << ")" << endl;
488
  // first, see if we need to expand definitions
489
151496
  TrustNode texp = d_rewriter.expandDefinition(in);
490
75748
  if (!texp.isNull())
491
  {
492
3617
    return texp;
493
  }
494
72131
  if( in.getKind()==EQUAL ){
495
7978
    Node nn;
496
7978
    std::vector< Node > rew;
497
4035
    if (utils::checkClash(in[0], in[1], rew))
498
    {
499
      nn = NodeManager::currentNM()->mkConst(false);
500
    }
501
    else
502
    {
503
12033
      nn = rew.size()==0 ? d_true :
504
7998
                ( rew.size()==1 ? rew[0] : NodeManager::currentNM()->mkNode( kind::AND, rew ) );
505
    }
506
4035
    if (in != nn)
507
    {
508
92
      return TrustNode::mkTrustRewrite(in, nn, nullptr);
509
    }
510
  }
511
512
  // nothing to do
513
72039
  return TrustNode::null();
514
}
515
516
57360
TrustNode TheoryDatatypes::explain(TNode literal)
517
{
518
57360
  return d_im.explainLit(literal);
519
}
520
521
/** called when a new equivalance class is created */
522
282074
void TheoryDatatypes::eqNotifyNewClass(TNode t){
523
282074
  if( t.getKind()==APPLY_CONSTRUCTOR ){
524
104007
    getOrMakeEqcInfo( t, true );
525
  }
526
282074
}
527
528
/** called when two equivalance classes have merged */
529
2270412
void TheoryDatatypes::eqNotifyMerge(TNode t1, TNode t2)
530
{
531
2270412
  if( t1.getType().isDatatype() ){
532
1138562
    Trace("datatypes-debug")
533
569281
        << "NotifyMerge : " << t1 << " " << t2 << std::endl;
534
569281
    merge(t1,t2);
535
  }
536
2270412
}
537
538
569281
void TheoryDatatypes::merge( Node t1, Node t2 ){
539
569281
  if (!d_state.isInConflict())
540
  {
541
1133378
    TNode trep1 = t1;
542
1133378
    TNode trep2 = t2;
543
568122
    Trace("datatypes-debug") << "Merge " << t1 << " " << t2 << std::endl;
544
568122
    EqcInfo* eqc2 = getOrMakeEqcInfo( t2 );
545
568122
    if( eqc2 ){
546
364014
      bool checkInst = false;
547
364014
      if( !eqc2->d_constructor.get().isNull() ){
548
107317
        trep2 = eqc2->d_constructor.get();
549
      }
550
364014
      EqcInfo* eqc1 = getOrMakeEqcInfo( t1 );
551
364014
      if( eqc1 ){
552
345687
        Trace("datatypes-debug") << "  merge eqc info " << eqc2 << " into " << eqc1 << std::endl;
553
345687
        if( !eqc1->d_constructor.get().isNull() ){
554
286610
          trep1 = eqc1->d_constructor.get();
555
        }
556
        //check for clash
557
688830
        TNode cons1 = eqc1->d_constructor.get();
558
688830
        TNode cons2 = eqc2->d_constructor.get();
559
        //if both have constructor, then either clash or unification
560
345687
        if( !cons1.isNull() && !cons2.isNull() ){
561
59931
          Trace("datatypes-debug") << "  constructors : " << cons1 << " " << cons2 << std::endl;
562
117322
          Node unifEq = cons1.eqNode( cons2 );
563
117322
          std::vector< Node > rew;
564
59931
          if (utils::checkClash(cons1, cons2, rew))
565
          {
566
5080
            std::vector<Node> conf;
567
2540
            conf.push_back(unifEq);
568
5080
            Trace("dt-conflict")
569
2540
                << "CONFLICT: Clash conflict : " << conf << std::endl;
570
2540
            d_im.sendDtConflict(conf, InferenceId::DATATYPES_CLASH_CONFLICT);
571
2540
            return;
572
          }
573
          else
574
          {
575
            //do unification
576
168608
            for( int i=0; i<(int)cons1.getNumChildren(); i++ ) {
577
111217
              if( !areEqual( cons1[i], cons2[i] ) ){
578
74152
                Node eq = cons1[i].eqNode( cons2[i] );
579
37076
                d_im.addPendingInference(
580
                    eq, InferenceId::DATATYPES_UNIF, unifEq);
581
37076
                Trace("datatypes-infer") << "DtInfer : cons-inj : " << eq << " by " << unifEq << std::endl;
582
              }
583
            }
584
          }
585
        }
586
343147
        Trace("datatypes-debug") << "  instantiated : " << eqc1->d_inst << " " << eqc2->d_inst << std::endl;
587
343147
        eqc1->d_inst = eqc1->d_inst || eqc2->d_inst;
588
343147
        if( !cons2.isNull() ){
589
95605
          if( cons1.isNull() ){
590
38214
            Trace("datatypes-debug") << "  must check if it is okay to set the constructor." << std::endl;
591
38214
            checkInst = true;
592
38214
            addConstructor( eqc2->d_constructor.get(), eqc1, t1 );
593
38214
            if (d_state.isInConflict())
594
            {
595
4
              return;
596
            }
597
          }
598
        }
599
      }else{
600
18327
        Trace("datatypes-debug") << "  no eqc info for " << t1 << ", must create" << std::endl;
601
        //just copy the equivalence class information
602
18327
        eqc1 = getOrMakeEqcInfo( t1, true );
603
18327
        eqc1->d_inst.set( eqc2->d_inst );
604
18327
        eqc1->d_constructor.set( eqc2->d_constructor );
605
18327
        eqc1->d_selectors.set( eqc2->d_selectors );
606
      }
607
608
609
      //merge labels
610
361470
      NodeUIntMap::iterator lbl_i = d_labels.find(t2);
611
361470
      if( lbl_i != d_labels.end() ){
612
361470
        Trace("datatypes-debug") << "  merge labels from " << eqc2 << " " << t2 << std::endl;
613
361470
        size_t n_label = (*lbl_i).second;
614
613107
        for (size_t i = 0; i < n_label; i++)
615
        {
616
251959
          Assert(i < d_labels_data[t2].size());
617
503596
          Node t = d_labels_data[ t2 ][i];
618
503596
          Node t_arg = d_labels_args[t2][i];
619
251959
          unsigned tindex = d_labels_tindex[t2][i];
620
251959
          addTester( tindex, t, eqc1, t1, t_arg );
621
251959
          if (d_state.isInConflict())
622
          {
623
322
            Trace("datatypes-debug") << "  conflict!" << std::endl;
624
322
            return;
625
          }
626
        }
627
628
      }
629
      //merge selectors
630
361148
      if( !eqc1->d_selectors && eqc2->d_selectors ){
631
51613
        eqc1->d_selectors = true;
632
51613
        checkInst = true;
633
      }
634
361148
      NodeUIntMap::iterator sel_i = d_selector_apps.find(t2);
635
361148
      if( sel_i != d_selector_apps.end() ){
636
361148
        Trace("datatypes-debug") << "  merge selectors from " << eqc2 << " " << t2 << std::endl;
637
361148
        size_t n_sel = (*sel_i).second;
638
857450
        for (size_t j = 0; j < n_sel; j++)
639
        {
640
496302
          addSelector( d_selector_apps_data[t2][j], eqc1, t1, eqc2->d_constructor.get().isNull() );
641
        }
642
      }
643
361148
      if( checkInst ){
644
89823
        Trace("datatypes-debug") << "  checking instantiate" << std::endl;
645
89823
        instantiate( eqc1, t1 );
646
89823
        if (d_state.isInConflict())
647
        {
648
          return;
649
        }
650
      }
651
    }
652
565256
    Trace("datatypes-debug") << "Finished Merge " << t1 << " " << t2 << std::endl;
653
  }
654
}
655
656
23862
TheoryDatatypes::EqcInfo::EqcInfo( context::Context* c )
657
    : d_inst( c, false )
658
47724
    , d_constructor( c, Node::null() )
659
71586
    , d_selectors( c, false )
660
23862
{}
661
662
139484
bool TheoryDatatypes::hasLabel( EqcInfo* eqc, Node n ){
663
139484
  return ( eqc && !eqc->d_constructor.get().isNull() ) || !getLabel( n ).isNull();
664
}
665
666
667061
Node TheoryDatatypes::getLabel( Node n ) {
667
667061
  NodeUIntMap::iterator lbl_i = d_labels.find(n);
668
667061
  if( lbl_i != d_labels.end() ){
669
597969
    size_t n_lbl = (*lbl_i).second;
670
597969
    if( n_lbl>0 && d_labels_data[n][ n_lbl-1 ].getKind()!=kind::NOT ){
671
193882
      return d_labels_data[n][ n_lbl-1 ];
672
    }
673
  }
674
473179
  return Node::null();
675
}
676
677
1419094
int TheoryDatatypes::getLabelIndex( EqcInfo* eqc, Node n ){
678
1419094
  if( eqc && !eqc->d_constructor.get().isNull() ){
679
886809
    return utils::indexOf(eqc->d_constructor.get().getOperator());
680
  }else{
681
1064570
    Node lbl = getLabel( n );
682
532285
    if( lbl.isNull() ){
683
434521
      return -1;
684
    }else{
685
97764
      int tindex = utils::isTester(lbl);
686
195528
      Trace("datatypes-debug") << "Label of " << n << " is " << lbl
687
97764
                               << " with tindex " << tindex << std::endl;
688
97764
      Assert(tindex != -1);
689
97764
      return tindex;
690
    }
691
  }
692
}
693
694
20969
bool TheoryDatatypes::hasTester( Node n ) {
695
20969
  NodeUIntMap::iterator lbl_i = d_labels.find(n);
696
20969
  if( lbl_i != d_labels.end() ){
697
1
    return (*lbl_i).second>0;
698
  }else{
699
20968
    return false;
700
  }
701
}
702
703
80600
void TheoryDatatypes::getPossibleCons( EqcInfo* eqc, Node n, std::vector< bool >& pcons ){
704
161200
  TypeNode tn = n.getType();
705
80600
  const DType& dt = tn.getDType();
706
80600
  int lindex = getLabelIndex( eqc, n );
707
80600
  pcons.resize( dt.getNumConstructors(), lindex==-1 );
708
80600
  if( lindex!=-1 ){
709
    pcons[ lindex ] = true;
710
  }else{
711
80600
    NodeUIntMap::iterator lbl_i = d_labels.find(n);
712
80600
    if( lbl_i != d_labels.end() ){
713
46054
      size_t n_lbl = (*lbl_i).second;
714
236786
      for (size_t i = 0; i < n_lbl; i++)
715
      {
716
190732
        Assert(d_labels_data[n][i].getKind() == NOT);
717
190732
        unsigned tindex = d_labels_tindex[n][i];
718
190732
        pcons[ tindex ] = false;
719
      }
720
    }
721
  }
722
80600
}
723
724
109027
Node TheoryDatatypes::getTermSkolemFor( Node n ) {
725
109027
  if( n.getKind()==APPLY_CONSTRUCTOR ){
726
13275
    NodeMap::const_iterator it = d_term_sk.find( n );
727
13275
    if( it==d_term_sk.end() ){
728
1128
      NodeManager* nm = NodeManager::currentNM();
729
1128
      SkolemManager* sm = nm->getSkolemManager();
730
      //add purification unit lemma ( k = n )
731
2256
      Node k = sm->mkPurifySkolem(n, "kdt");
732
1128
      d_term_sk[n] = k;
733
2256
      Node eq = k.eqNode( n );
734
1128
      Trace("datatypes-infer") << "DtInfer : ref : " << eq << std::endl;
735
1128
      d_im.addPendingLemma(eq, InferenceId::DATATYPES_PURIFY);
736
1128
      return k;
737
    }else{
738
12147
      return (*it).second;
739
    }
740
  }else{
741
95752
    return n;
742
  }
743
}
744
745
1152919
void TheoryDatatypes::addTester(
746
    unsigned ttindex, Node t, EqcInfo* eqc, Node n, Node t_arg)
747
{
748
1152919
  Trace("datatypes-debug") << "Add tester : " << t << " to eqc(" << n << ")" << std::endl;
749
1152919
  Debug("datatypes-labels") << "Add tester " << t << " " << n << " " << eqc << std::endl;
750
1152919
  bool tpolarity = t.getKind()!=NOT;
751
1152919
  Assert((tpolarity ? t : t[0]).getKind() == APPLY_TESTER);
752
1440918
  Node j, jt;
753
1152919
  bool makeConflict = false;
754
1152919
  int prevTIndex = getLabelIndex(eqc, n);
755
1152919
  if (prevTIndex >= 0)
756
  {
757
799145
    unsigned ptu = static_cast<unsigned>(prevTIndex);
758
    //if we already know the constructor type, check whether it is in conflict or redundant
759
799145
    if ((ptu == ttindex) != tpolarity)
760
    {
761
1470
      if( !eqc->d_constructor.get().isNull() ){
762
        //conflict because equivalence class contains a constructor
763
2940
        std::vector<Node> conf;
764
1470
        conf.push_back(t);
765
1470
        conf.push_back(t_arg.eqNode(eqc->d_constructor.get()));
766
2940
        Trace("dt-conflict")
767
1470
            << "CONFLICT: Tester eq conflict " << conf << std::endl;
768
1470
        d_im.sendDtConflict(conf, InferenceId::DATATYPES_TESTER_CONFLICT);
769
1470
        return;
770
      }else{
771
        makeConflict = true;
772
        //conflict because the existing label is contradictory
773
        j = getLabel( n );
774
        jt = j;
775
      }
776
    }else{
777
797675
      return;
778
    }
779
  }else{
780
    //otherwise, scan list of labels
781
353774
    NodeUIntMap::iterator lbl_i = d_labels.find(n);
782
353774
    Assert(lbl_i != d_labels.end());
783
353774
    size_t n_lbl = (*lbl_i).second;
784
641773
    std::map< int, bool > neg_testers;
785
1328296
    for (size_t i = 0; i < n_lbl; i++)
786
    {
787
998442
      Assert(d_labels_data[n][i].getKind() == NOT);
788
998442
      unsigned jtindex = d_labels_tindex[n][i];
789
998442
      if( jtindex==ttindex ){
790
23920
        if( tpolarity ){  //we are in conflict
791
86
          j = d_labels_data[n][i];
792
86
          jt = j[0];
793
86
          makeConflict = true;
794
86
          break;
795
        }else{            //it is redundant
796
23834
          return;
797
        }
798
      }else{
799
974522
        neg_testers[jtindex] = true;
800
      }
801
    }
802
329940
    if( !makeConflict ){
803
329854
      Debug("datatypes-labels") << "Add to labels " << t << std::endl;
804
329854
      d_labels[n] = n_lbl + 1;
805
329854
      if (n_lbl < d_labels_data[n].size())
806
      {
807
        // reuse spot in the vector
808
319890
        d_labels_data[n][n_lbl] = t;
809
319890
        d_labels_args[n][n_lbl] = t_arg;
810
319890
        d_labels_tindex[n][n_lbl] = ttindex;
811
      }else{
812
9964
        d_labels_data[n].push_back(t);
813
9964
        d_labels_args[n].push_back(t_arg);
814
9964
        d_labels_tindex[n].push_back(ttindex);
815
      }
816
329854
      n_lbl++;
817
818
329854
      const DType& dt = t_arg.getType().getDType();
819
329854
      Debug("datatypes-labels") << "Labels at " << n_lbl << " / " << dt.getNumConstructors() << std::endl;
820
329854
      if( tpolarity ){
821
95752
        instantiate( eqc, n );
822
        // We could propagate is-C1(x) => not is-C2(x) here for all other
823
        // constructors, but empirically this hurts performance.
824
      }else{
825
        //check if we have reached the maximum number of testers
826
        // in this case, add the positive tester
827
234102
        if (n_lbl == dt.getNumConstructors() - 1)
828
        {
829
83882
          std::vector< bool > pcons;
830
41941
          getPossibleCons( eqc, n, pcons );
831
41941
          int testerIndex = -1;
832
124181
          for( unsigned i=0; i<pcons.size(); i++ ) {
833
124181
            if( pcons[i] ){
834
41941
              testerIndex = i;
835
41941
              break;
836
            }
837
          }
838
41941
          Assert(testerIndex != -1);
839
          //we must explain why each term in the set of testers for this equivalence class is equal
840
83882
          std::vector< Node > eq_terms;
841
83882
          NodeBuilder nb(kind::AND);
842
231525
          for (unsigned i = 0; i < n_lbl; i++)
843
          {
844
379168
            Node ti = d_labels_data[n][i];
845
189584
            nb << ti;
846
189584
            Assert(ti.getKind() == NOT);
847
379168
            Node t_arg2 = d_labels_args[n][i];
848
189584
            if( std::find( eq_terms.begin(), eq_terms.end(), t_arg2 )==eq_terms.end() ){
849
46636
              eq_terms.push_back( t_arg2 );
850
46636
              if( t_arg2!=t_arg ){
851
4695
                nb << t_arg2.eqNode( t_arg );
852
              }
853
            }
854
          }
855
          Node t_concl = testerIndex == -1
856
                             ? NodeManager::currentNM()->mkConst(false)
857
83882
                             : utils::mkTester(t_arg, testerIndex, dt);
858
83882
          Node t_concl_exp = ( nb.getNumChildren() == 1 ) ? nb.getChild( 0 ) : nb;
859
41941
          d_im.addPendingInference(
860
              t_concl, InferenceId::DATATYPES_LABEL_EXH, t_concl_exp);
861
41941
          Trace("datatypes-infer") << "DtInfer : label : " << t_concl << " by " << t_concl_exp << std::endl;
862
41941
          return;
863
        }
864
      }
865
    }
866
  }
867
287999
  if( makeConflict ){
868
86
    Debug("datatypes-labels") << "Explain " << j << " " << t << std::endl;
869
172
    std::vector<Node> conf;
870
86
    conf.push_back(j);
871
86
    conf.push_back(t);
872
86
    conf.push_back(jt[0].eqNode(t_arg));
873
86
    Trace("dt-conflict") << "CONFLICT: Tester conflict : " << conf << std::endl;
874
86
    d_im.sendDtConflict(conf, InferenceId::DATATYPES_TESTER_MERGE_CONFLICT);
875
  }
876
}
877
878
516726
void TheoryDatatypes::addSelector( Node s, EqcInfo* eqc, Node n, bool assertFacts ) {
879
516726
  Trace("dt-collapse-sel") << "Add selector : " << s << " to eqc(" << n << ")" << std::endl;
880
  //check to see if it is redundant
881
516726
  NodeUIntMap::iterator sel_i = d_selector_apps.find(n);
882
516726
  Assert(sel_i != d_selector_apps.end());
883
516726
  if( sel_i != d_selector_apps.end() ){
884
516726
    size_t n_sel = (*sel_i).second;
885
963007
    for (size_t j = 0; j < n_sel; j++)
886
    {
887
1228023
      Node ss = d_selector_apps_data[n][j];
888
781742
      if( s.getOperator()==ss.getOperator() && ( s.getKind()!=DT_HEIGHT_BOUND || s[1]==ss[1] ) ){
889
335461
        Trace("dt-collapse-sel") << "...redundant." << std::endl;
890
335461
        return;
891
      }
892
    }
893
    //add it to the vector
894
    //sel->push_back( s );
895
181265
    d_selector_apps[n] = n_sel + 1;
896
181265
    if (n_sel < d_selector_apps_data[n].size())
897
    {
898
165726
      d_selector_apps_data[n][n_sel] = s;
899
    }else{
900
15539
      d_selector_apps_data[n].push_back( s );
901
    }
902
903
181265
    eqc->d_selectors = true;
904
  }
905
181265
  if( assertFacts && !eqc->d_constructor.get().isNull() ){
906
    //conclude the collapsed merge
907
132001
    collapseSelector( s, eqc->d_constructor.get() );
908
  }
909
}
910
911
38214
void TheoryDatatypes::addConstructor( Node c, EqcInfo* eqc, Node n ){
912
38214
  Trace("datatypes-debug") << "Add constructor : " << c << " to eqc(" << n << ")" << std::endl;
913
38214
  Assert(eqc->d_constructor.get().isNull());
914
  //check labels
915
38214
  NodeUIntMap::iterator lbl_i = d_labels.find(n);
916
38214
  if( lbl_i != d_labels.end() ){
917
38214
    size_t constructorIndex = utils::indexOf(c.getOperator());
918
38214
    size_t n_lbl = (*lbl_i).second;
919
174846
    for (size_t i = 0; i < n_lbl; i++)
920
    {
921
273268
      Node t = d_labels_data[n][i];
922
136636
      if (d_labels_data[n][i].getKind() == NOT)
923
      {
924
101354
        unsigned tindex = d_labels_tindex[n][i];
925
101354
        if (tindex == constructorIndex)
926
        {
927
8
          std::vector<Node> conf;
928
4
          conf.push_back(t);
929
4
          conf.push_back(t[0][0].eqNode(c));
930
8
          Trace("dt-conflict")
931
4
              << "CONFLICT: Tester merge eq conflict : " << conf << std::endl;
932
4
          d_im.sendDtConflict(conf, InferenceId::DATATYPES_TESTER_CONFLICT);
933
4
          return;
934
        }
935
      }
936
    }
937
  }
938
  //check selectors
939
38210
  NodeUIntMap::iterator sel_i = d_selector_apps.find(n);
940
38210
  if( sel_i != d_selector_apps.end() ){
941
38210
    size_t n_sel = (*sel_i).second;
942
152489
    for (size_t j = 0; j < n_sel; j++)
943
    {
944
228558
      Node s = d_selector_apps_data[n][j];
945
      //collapse the selector
946
114279
      collapseSelector( s, c );
947
    }
948
  }
949
38210
  eqc->d_constructor.set( c );
950
}
951
952
246280
void TheoryDatatypes::collapseSelector( Node s, Node c ) {
953
246280
  Assert(c.getKind() == APPLY_CONSTRUCTOR);
954
246280
  Trace("dt-collapse-sel") << "collapse selector : " << s << " " << c << std::endl;
955
492560
  Node r;
956
246280
  bool wrong = false;
957
492560
  Node eq_exp = s[0].eqNode(c);
958
246280
  if( s.getKind()==kind::APPLY_SELECTOR_TOTAL ){
959
366440
    Node selector = s.getOperator();
960
183220
    size_t constructorIndex = utils::indexOf(c.getOperator());
961
183220
    const DType& dt = utils::datatypeOf(selector);
962
183220
    const DTypeConstructor& dtc = dt[constructorIndex];
963
183220
    int selectorIndex = dtc.getSelectorIndexInternal(selector);
964
183220
    wrong = selectorIndex<0;
965
183220
    r = NodeManager::currentNM()->mkNode( kind::APPLY_SELECTOR_TOTAL, s.getOperator(), c );
966
  }
967
246280
  if( !r.isNull() ){
968
366440
    Node rrs;
969
183220
    if (wrong)
970
    {
971
      // Must use make ground term here instead of the rewriter, since we
972
      // do not want to introduce arbitrary values. This is important so that
973
      // we avoid constants for types that are not "closed enumerable", e.g.
974
      // uninterpreted sorts and arrays, where the solver does not fully
975
      // handle values of the sort. The call to mkGroundTerm does not introduce
976
      // values for these sorts.
977
90571
      rrs = r.getType().mkGroundTerm();
978
181142
      Trace("datatypes-wrong-sel")
979
90571
          << "Bad apply " << r << " term = " << rrs
980
90571
          << ", value = " << r.getType().mkGroundValue() << std::endl;
981
    }
982
    else
983
    {
984
92649
      rrs = Rewriter::rewrite(r);
985
    }
986
183220
    if (s != rrs)
987
    {
988
238724
      Node eq = s.eqNode(rrs);
989
      // Since collapsing selectors may generate new terms, we must send
990
      // this out as a lemma if it is of an external type, or otherwise we
991
      // may ask for the equality status of terms that only datatypes knows
992
      // about, see issue #5344.
993
119362
      bool forceLemma = !s.getType().isDatatype();
994
119362
      Trace("datatypes-infer") << "DtInfer : collapse sel";
995
119362
      Trace("datatypes-infer") << " : " << eq << " by " << eq_exp << std::endl;
996
119362
      d_im.addPendingInference(
997
          eq, InferenceId::DATATYPES_COLLAPSE_SEL, eq_exp, forceLemma);
998
    }
999
  }
1000
246280
}
1001
1002
144384
EqualityStatus TheoryDatatypes::getEqualityStatus(TNode a, TNode b){
1003
144384
  Assert(d_equalityEngine->hasTerm(a) && d_equalityEngine->hasTerm(b));
1004
144384
  if (d_equalityEngine->areEqual(a, b))
1005
  {
1006
    // The terms are implied to be equal
1007
8261
    return EQUALITY_TRUE;
1008
  }
1009
136123
  if (d_equalityEngine->areDisequal(a, b, false))
1010
  {
1011
    // The terms are implied to be dis-equal
1012
    return EQUALITY_FALSE;
1013
  }
1014
136123
  return EQUALITY_FALSE_IN_MODEL;
1015
}
1016
1017
83134
void TheoryDatatypes::addCarePairs(TNodeTrie* t1,
1018
                                   TNodeTrie* t2,
1019
                                   unsigned arity,
1020
                                   unsigned depth,
1021
                                   unsigned& n_pairs)
1022
{
1023
83134
  if( depth==arity ){
1024
10117
    if( t2!=NULL ){
1025
20234
      Node f1 = t1->getData();
1026
20234
      Node f2 = t2->getData();
1027
10117
      if( !areEqual( f1, f2 ) ){
1028
10117
        Trace("dt-cg") << "Check " << f1 << " and " << f2 << std::endl;
1029
20234
        vector< pair<TNode, TNode> > currentPairs;
1030
30473
        for (unsigned k = 0; k < f1.getNumChildren(); ++ k) {
1031
40712
          TNode x = f1[k];
1032
40712
          TNode y = f2[k];
1033
20356
          Assert(d_equalityEngine->hasTerm(x));
1034
20356
          Assert(d_equalityEngine->hasTerm(y));
1035
20356
          Assert(!areDisequal(x, y));
1036
20356
          Assert(!areCareDisequal(x, y));
1037
20356
          if (!d_equalityEngine->areEqual(x, y))
1038
          {
1039
11682
            Trace("dt-cg") << "Arg #" << k << " is " << x << " " << y << std::endl;
1040
35046
            if (d_equalityEngine->isTriggerTerm(x, THEORY_DATATYPES)
1041
35046
                && d_equalityEngine->isTriggerTerm(y, THEORY_DATATYPES))
1042
            {
1043
1794
              TNode x_shared = d_equalityEngine->getTriggerTermRepresentative(
1044
3588
                  x, THEORY_DATATYPES);
1045
1794
              TNode y_shared = d_equalityEngine->getTriggerTermRepresentative(
1046
3588
                  y, THEORY_DATATYPES);
1047
1794
              currentPairs.push_back(make_pair(x_shared, y_shared));
1048
            }
1049
          }
1050
        }
1051
11911
        for (unsigned c = 0; c < currentPairs.size(); ++ c) {
1052
1794
          Trace("dt-cg-pair") << "Pair : " << currentPairs[c].first << " " << currentPairs[c].second << std::endl;
1053
1794
          addCarePair(currentPairs[c].first, currentPairs[c].second);
1054
1794
          n_pairs++;
1055
        }
1056
      }
1057
    }
1058
  }else{
1059
73017
    if( t2==NULL ){
1060
65960
      if( depth<(arity-1) ){
1061
        //add care pairs internal to each child
1062
28098
        for (std::pair<const TNode, TNodeTrie>& tt : t1->d_data)
1063
        {
1064
16757
          addCarePairs(&tt.second, nullptr, arity, depth + 1, n_pairs);
1065
        }
1066
      }
1067
      //add care pairs based on each pair of non-disequal arguments
1068
174087
      for (std::map<TNode, TNodeTrie>::iterator it = t1->d_data.begin();
1069
174087
           it != t1->d_data.end();
1070
           ++it)
1071
      {
1072
108127
        std::map<TNode, TNodeTrie>::iterator it2 = it;
1073
108127
        ++it2;
1074
315251
        for( ; it2 != t1->d_data.end(); ++it2 ){
1075
103562
          if (!d_equalityEngine->areDisequal(it->first, it2->first, false))
1076
          {
1077
53473
            if( !areCareDisequal(it->first, it2->first) ){
1078
10394
              addCarePairs( &it->second, &it2->second, arity, depth+1, n_pairs );
1079
            }
1080
          }
1081
        }
1082
      }
1083
    }else{
1084
      //add care pairs based on product of indices, non-disequal arguments
1085
20719
      for (std::pair<const TNode, TNodeTrie>& tt1 : t1->d_data)
1086
      {
1087
34592
        for (std::pair<const TNode, TNodeTrie>& tt2 : t2->d_data)
1088
        {
1089
20930
          if (!d_equalityEngine->areDisequal(tt1.first, tt2.first, false))
1090
          {
1091
17804
            if (!areCareDisequal(tt1.first, tt2.first))
1092
            {
1093
6780
              addCarePairs(&tt1.second, &tt2.second, arity, depth + 1, n_pairs);
1094
            }
1095
          }
1096
        }
1097
      }
1098
    }
1099
  }
1100
83134
}
1101
1102
10758
void TheoryDatatypes::computeCareGraph(){
1103
10758
  unsigned n_pairs = 0;
1104
10758
  Trace("dt-cg-summary") << "Compute graph for dt..." << d_functionTerms.size() << " " << d_sharedTerms.size() << std::endl;
1105
10758
  Trace("dt-cg") << "Build indices..." << std::endl;
1106
21516
  std::map<TypeNode, std::map<Node, TNodeTrie> > index;
1107
21516
  std::map< Node, unsigned > arity;
1108
  //populate indices
1109
10758
  unsigned functionTerms = d_functionTerms.size();
1110
237949
  for( unsigned i=0; i<functionTerms; i++ ){
1111
454382
    TNode f1 = d_functionTerms[i];
1112
227191
    Assert(d_equalityEngine->hasTerm(f1));
1113
227191
    Trace("dt-cg-debug") << "...build for " << f1 << std::endl;
1114
    //break into index based on operator, and type of first argument (since some operators are parametric)
1115
454382
    Node op = f1.getOperator();
1116
454382
    TypeNode tn = f1[0].getType();
1117
454382
    std::vector< TNode > reps;
1118
227191
    bool has_trigger_arg = false;
1119
487388
    for( unsigned j=0; j<f1.getNumChildren(); j++ ){
1120
260197
      reps.push_back(d_equalityEngine->getRepresentative(f1[j]));
1121
260197
      if (d_equalityEngine->isTriggerTerm(f1[j], THEORY_DATATYPES))
1122
      {
1123
218444
        has_trigger_arg = true;
1124
      }
1125
    }
1126
    //only may contribute to care pairs if has at least one trigger argument
1127
227191
    if( has_trigger_arg ){
1128
194851
      index[tn][op].addTerm( f1, reps );
1129
194851
      arity[op] = reps.size();
1130
    }
1131
  }
1132
  //for each index
1133
27236
  for (std::pair<const TypeNode, std::map<Node, TNodeTrie> >& tt : index)
1134
  {
1135
65681
    for (std::pair<const Node, TNodeTrie>& t : tt.second)
1136
    {
1137
98406
      Trace("dt-cg") << "Process index " << tt.first << ", " << t.first << "..."
1138
49203
                     << std::endl;
1139
49203
      addCarePairs(&t.second, nullptr, arity[t.first], 0, n_pairs);
1140
    }
1141
  }
1142
10758
  Trace("dt-cg-summary") << "...done, # pairs = " << n_pairs << std::endl;
1143
10758
}
1144
1145
9109
bool TheoryDatatypes::collectModelValues(TheoryModel* m,
1146
                                         const std::set<Node>& termSet)
1147
{
1148
18218
  Trace("dt-cmi") << "Datatypes : Collect model values "
1149
9109
                  << d_equalityEngine->consistent() << std::endl;
1150
9109
  Trace("dt-model") << std::endl;
1151
9109
  printModelDebug( "dt-model" );
1152
9109
  Trace("dt-model") << std::endl;
1153
1154
  //get all constructors
1155
9109
  eq::EqClassesIterator eqccs_i = eq::EqClassesIterator(d_equalityEngine);
1156
18218
  std::vector< Node > cons;
1157
18218
  std::vector< Node > nodes;
1158
18218
  std::map< Node, Node > eqc_cons;
1159
573981
  while( !eqccs_i.isFinished() ){
1160
564872
    Node eqc = (*eqccs_i);
1161
    //for all equivalence classes that are datatypes
1162
    //if( termSet.find( eqc )==termSet.end() ){
1163
    //  Trace("dt-cmi-debug") << "Irrelevant eqc : " << eqc << std::endl;
1164
    //}
1165
282436
    if( eqc.getType().isDatatype() ){
1166
64389
      EqcInfo* ei = getOrMakeEqcInfo( eqc );
1167
64389
      if( ei && !ei->d_constructor.get().isNull() ){
1168
86840
        Node c = ei->d_constructor.get();
1169
43420
        cons.push_back( c );
1170
43420
        eqc_cons[ eqc ] = c;
1171
      }else{
1172
        //if eqc contains a symbol known to datatypes (a selector), then we must assign
1173
        //should assign constructors to EQC if they have a selector or a tester
1174
20969
        bool shouldConsider = ( ei && ei->d_selectors ) || hasTester( eqc );
1175
20969
        if( shouldConsider ){
1176
1
          nodes.push_back( eqc );
1177
        }
1178
      }
1179
    }
1180
    //}
1181
282436
    ++eqccs_i;
1182
  }
1183
1184
  //unsigned orig_size = nodes.size();
1185
18218
  std::map< TypeNode, int > typ_enum_map;
1186
18218
  std::vector< TypeEnumerator > typ_enum;
1187
9109
  unsigned index = 0;
1188
9111
  while( index<nodes.size() ){
1189
2
    Node eqc = nodes[index];
1190
2
    Node neqc;
1191
1
    bool addCons = false;
1192
2
    TypeNode tt = eqc.getType();
1193
1
    const DType& dt = tt.getDType();
1194
1
    if (!d_equalityEngine->hasTerm(eqc))
1195
    {
1196
      Assert(false);
1197
    }else{
1198
1
      Trace("dt-cmi") << "NOTICE : Datatypes: no constructor in equivalence class " << eqc << std::endl;
1199
1
      Trace("dt-cmi") << "   Type : " << eqc.getType() << std::endl;
1200
1
      EqcInfo* ei = getOrMakeEqcInfo( eqc );
1201
2
      std::vector< bool > pcons;
1202
1
      getPossibleCons( ei, eqc, pcons );
1203
1
      Trace("dt-cmi") << "Possible constructors : ";
1204
8
      for( unsigned i=0; i<pcons.size(); i++ ){
1205
7
        Trace("dt-cmi") << pcons[i] << " ";
1206
      }
1207
1
      Trace("dt-cmi") << std::endl;
1208
3
      for( unsigned r=0; r<2; r++ ){
1209
2
        if( neqc.isNull() ){
1210
5
          for( unsigned i=0; i<pcons.size(); i++ ){
1211
            // must try the infinite ones first
1212
            bool cfinite =
1213
5
                d_state.isFiniteType(dt[i].getSpecializedConstructorType(tt));
1214
5
            if( pcons[i] && (r==1)==cfinite ){
1215
1
              neqc = utils::getInstCons(eqc, dt, i);
1216
1
              break;
1217
            }
1218
          }
1219
        }
1220
      }
1221
1
      addCons = true;
1222
    }
1223
1
    if( !neqc.isNull() ){
1224
1
      Trace("dt-cmi") << "Assign : " << neqc << std::endl;
1225
1
      if (!m->assertEquality(eqc, neqc, true))
1226
      {
1227
        return false;
1228
      }
1229
1
      eqc_cons[ eqc ] = neqc;
1230
    }
1231
1
    if( addCons ){
1232
1
      cons.push_back( neqc );
1233
    }
1234
1
    ++index;
1235
  }
1236
1237
52546
  for( std::map< Node, Node >::iterator it = eqc_cons.begin(); it != eqc_cons.end(); ++it ){
1238
86874
    Node eqc = it->first;
1239
43437
    if( eqc.getType().isCodatatype() ){
1240
      //until models are implemented for codatatypes
1241
      //throw Exception("Models for codatatypes are not supported in this version.");
1242
      //must proactive expand to avoid looping behavior in model builder
1243
75
      if( !it->second.isNull() ){
1244
124
        std::map< Node, int > vmap;
1245
124
        Node v = getCodatatypesValue( it->first, eqc_cons, vmap, 0 );
1246
62
        Trace("dt-cmi") << "  EQC(" << it->first << "), constructor is " << it->second << ", value is " << v << ", const = " << v.isConst() << std::endl;
1247
62
        if (!m->assertEquality(eqc, v, true))
1248
        {
1249
          return false;
1250
        }
1251
62
        m->assertSkeleton(v);
1252
      }
1253
    }else{
1254
43362
      Trace("dt-cmi") << "Datatypes : assert representative " << it->second << " for " << it->first << std::endl;
1255
43362
      m->assertSkeleton(it->second);
1256
    }
1257
  }
1258
9109
  return true;
1259
}
1260
1261
1262
199
Node TheoryDatatypes::getCodatatypesValue( Node n, std::map< Node, Node >& eqc_cons, std::map< Node, int >& vmap, int depth ){
1263
199
  std::map< Node, int >::iterator itv = vmap.find( n );
1264
199
  if( itv!=vmap.end() ){
1265
6
    int debruijn = depth - 1 - itv->second;
1266
    return NodeManager::currentNM()->mkConst(
1267
6
        UninterpretedConstant(n.getType(), debruijn));
1268
193
  }else if( n.getType().isDatatype() ){
1269
173
    Node nc = eqc_cons[n];
1270
139
    if( !nc.isNull() ){
1271
105
      vmap[n] = depth;
1272
105
      Trace("dt-cmi-cdt-debug") << "    map " << n << " -> " << depth << std::endl;
1273
105
      Assert(nc.getKind() == APPLY_CONSTRUCTOR);
1274
210
      std::vector< Node > children;
1275
105
      children.push_back( nc.getOperator() );
1276
242
      for( unsigned i=0; i<nc.getNumChildren(); i++ ){
1277
274
        Node r = getRepresentative( nc[i] );
1278
274
        Node rv = getCodatatypesValue( r, eqc_cons, vmap, depth+1 );
1279
137
        children.push_back( rv );
1280
      }
1281
105
      vmap.erase( n );
1282
105
      return NodeManager::currentNM()->mkNode( APPLY_CONSTRUCTOR, children );
1283
    }
1284
  }
1285
88
  return n;
1286
}
1287
1288
Node TheoryDatatypes::getSingletonLemma( TypeNode tn, bool pol ) {
1289
  NodeManager* nm = NodeManager::currentNM();
1290
  SkolemManager* sm = nm->getSkolemManager();
1291
  int index = pol ? 0 : 1;
1292
  std::map< TypeNode, Node >::iterator it = d_singleton_lemma[index].find( tn );
1293
  if( it==d_singleton_lemma[index].end() ){
1294
    Node a;
1295
    if( pol ){
1296
      Node v1 = nm->mkBoundVar(tn);
1297
      Node v2 = nm->mkBoundVar(tn);
1298
      a = nm->mkNode(FORALL, nm->mkNode(BOUND_VAR_LIST, v1, v2), v1.eqNode(v2));
1299
    }else{
1300
      Node v1 = sm->mkDummySkolem("k1", tn);
1301
      Node v2 = sm->mkDummySkolem("k2", tn);
1302
      a = v1.eqNode( v2 ).negate();
1303
      //send out immediately as lemma
1304
      d_im.lemma(a, InferenceId::DATATYPES_REC_SINGLETON_FORCE_DEQ);
1305
      Trace("dt-singleton") << "******** assert " << a << " to avoid singleton cardinality for type " << tn << std::endl;
1306
    }
1307
    d_singleton_lemma[index][tn] = a;
1308
    return a;
1309
  }else{
1310
    return it->second;
1311
  }
1312
}
1313
1314
277536
void TheoryDatatypes::collectTerms( Node n ) {
1315
277536
  if (d_collectTermsCache.find(n) != d_collectTermsCache.end())
1316
  {
1317
    // already processed
1318
33813
    return;
1319
  }
1320
243723
  d_collectTermsCache[n] = true;
1321
243723
  Kind nk = n.getKind();
1322
243723
  if (nk == APPLY_CONSTRUCTOR)
1323
  {
1324
97284
    Debug("datatypes") << "  Found constructor " << n << endl;
1325
97284
    if (n.getNumChildren() > 0)
1326
    {
1327
68670
      d_functionTerms.push_back(n);
1328
    }
1329
97284
    return;
1330
  }
1331
146439
  if (nk == APPLY_SELECTOR_TOTAL || nk == DT_SIZE || nk == DT_HEIGHT_BOUND)
1332
  {
1333
20424
    d_functionTerms.push_back(n);
1334
    // we must also record which selectors exist
1335
20424
    Trace("dt-collapse-sel") << "  Found selector " << n << endl;
1336
40848
    Node rep = getRepresentative(n[0]);
1337
    // record it in the selectors
1338
20424
    EqcInfo* eqc = getOrMakeEqcInfo(rep, true);
1339
    // add it to the eqc info
1340
20424
    addSelector(n, eqc, rep);
1341
  }
1342
1343
  // now, do user-context-dependent lemmas
1344
146439
  if (nk != DT_SIZE && nk != DT_HEIGHT_BOUND)
1345
  {
1346
    // if not one of these kinds, there are no lemmas
1347
142016
    return;
1348
  }
1349
4423
  if (d_collectTermsCacheU.find(n) != d_collectTermsCacheU.end())
1350
  {
1351
2108
    return;
1352
  }
1353
2315
  d_collectTermsCacheU[n] = true;
1354
1355
2315
  NodeManager* nm = NodeManager::currentNM();
1356
1357
2315
  if (nk == DT_SIZE)
1358
  {
1359
4630
    Node lem = nm->mkNode(LEQ, d_zero, n);
1360
4630
    Trace("datatypes-infer")
1361
2315
        << "DtInfer : size geq zero : " << lem << std::endl;
1362
2315
    d_im.addPendingLemma(lem, InferenceId::DATATYPES_SIZE_POS);
1363
  }
1364
  else if (nk == DT_HEIGHT_BOUND && n[1].getConst<Rational>().isZero())
1365
  {
1366
    std::vector<Node> children;
1367
    const DType& dt = n[0].getType().getDType();
1368
    for (unsigned i = 0, ncons = dt.getNumConstructors(); i < ncons; i++)
1369
    {
1370
      if (utils::isNullaryConstructor(dt[i]))
1371
      {
1372
        Node test = utils::mkTester(n[0], i, dt);
1373
        children.push_back(test);
1374
      }
1375
    }
1376
    Node lem;
1377
    if (children.empty())
1378
    {
1379
      lem = n.negate();
1380
    }
1381
    else
1382
    {
1383
      lem = n.eqNode(children.size() == 1 ? children[0]
1384
                                          : nm->mkNode(OR, children));
1385
    }
1386
    Trace("datatypes-infer") << "DtInfer : zero height : " << lem << std::endl;
1387
    d_im.addPendingLemma(lem, InferenceId::DATATYPES_HEIGHT_ZERO);
1388
  }
1389
}
1390
1391
120705
Node TheoryDatatypes::getInstantiateCons(Node n, const DType& dt, int index)
1392
{
1393
120705
  if( n.getKind()==APPLY_CONSTRUCTOR && n.getNumChildren()==0 ){
1394
11678
    return n;
1395
  }
1396
  //add constructor to equivalence class
1397
218054
  Node k = getTermSkolemFor( n );
1398
218054
  Node n_ic = utils::getInstCons(k, dt, index);
1399
109027
  n_ic = Rewriter::rewrite( n_ic );
1400
  // it may be a new term, so we collect terms and add it to the equality engine
1401
109027
  collectTerms( n_ic );
1402
109027
  d_equalityEngine->addTerm(n_ic);
1403
109027
  Debug("dt-enum") << "Made instantiate cons " << n_ic << std::endl;
1404
109027
  return n_ic;
1405
}
1406
1407
185575
void TheoryDatatypes::instantiate( EqcInfo* eqc, Node n ){
1408
185575
  Trace("datatypes-debug") << "Instantiate: " << n << std::endl;
1409
  //add constructor to equivalence class if not done so already
1410
185575
  int index = getLabelIndex( eqc, n );
1411
185575
  if (index == -1 || eqc->d_inst)
1412
  {
1413
141418
    return;
1414
  }
1415
229732
  Node exp;
1416
229732
  Node tt;
1417
120705
  if (!eqc->d_constructor.get().isNull())
1418
  {
1419
24953
    exp = d_true;
1420
24953
    tt = eqc->d_constructor;
1421
  }
1422
  else
1423
  {
1424
95752
    exp = getLabel(n);
1425
95752
    tt = exp[0];
1426
  }
1427
229732
  TypeNode ttn = tt.getType();
1428
120705
  const DType& dt = ttn.getDType();
1429
  // instantiate this equivalence class
1430
120705
  eqc->d_inst = true;
1431
229732
  Node tt_cons = getInstantiateCons(tt, dt, index);
1432
229732
  Node eq;
1433
120705
  if (tt == tt_cons)
1434
  {
1435
11678
    return;
1436
  }
1437
109027
  eq = tt.eqNode(tt_cons);
1438
  // Determine if the equality must be sent out as a lemma. Notice that
1439
  // we  keep new equalities from the instantiate rule internal
1440
  // as long as they are for datatype constructors that have no arguments that
1441
  // have finite external type, which corresponds to:
1442
  //   forceLemma = dt[index].hasFiniteExternalArgType(ttn);
1443
  // Such equalities must be sent because they introduce selector terms that
1444
  // may contribute to conflicts due to cardinality (good examples of this are
1445
  // regress0/datatypes/dt-param-card4-bool-sat.smt2 and
1446
  // regress0/datatypes/list-bool.smt2).
1447
  bool forceLemma;
1448
218054
  if (options::dtPoliteOptimize())
1449
  {
1450
109027
    forceLemma = dt[index].hasFiniteExternalArgType(ttn);
1451
  }
1452
  else
1453
  {
1454
    forceLemma = dt.involvesExternalType();
1455
  }
1456
218054
  Trace("datatypes-infer-debug") << "DtInstantiate : " << eqc << " " << eq
1457
109027
                                 << " forceLemma = " << forceLemma << std::endl;
1458
109027
  d_im.addPendingInference(eq, InferenceId::DATATYPES_INST, exp, forceLemma);
1459
218054
  Trace("datatypes-infer") << "DtInfer : instantiate : " << eq << " by " << exp
1460
109027
                           << std::endl;
1461
}
1462
1463
23483
void TheoryDatatypes::checkCycles() {
1464
23483
  Trace("datatypes-cycle-check") << "Check acyclicity" << std::endl;
1465
46554
  std::vector< Node > cdt_eqc;
1466
23483
  eq::EqClassesIterator eqcs_i = eq::EqClassesIterator(d_equalityEngine);
1467
1104485
  while( !eqcs_i.isFinished() ){
1468
1081414
    Node eqc = (*eqcs_i);
1469
1081414
    TypeNode tn = eqc.getType();
1470
540913
    if( tn.isDatatype() ) {
1471
196036
      if( !tn.isCodatatype() ){
1472
389438
        if( options::dtCyclic() ){
1473
          //do cycle checks
1474
389026
          std::map< TNode, bool > visited;
1475
389026
          std::map< TNode, bool > proc;
1476
389026
          std::vector<Node> expl;
1477
194719
          Trace("datatypes-cycle-check") << "...search for cycle starting at " << eqc << std::endl;
1478
389026
          Node cn = searchForCycle( eqc, eqc, visited, proc, expl );
1479
194719
          Trace("datatypes-cycle-check") << "...finish." << std::endl;
1480
          //if we discovered a different cycle while searching this one
1481
194719
          if( !cn.isNull() && cn!=eqc ){
1482
22
            visited.clear();
1483
22
            proc.clear();
1484
22
            expl.clear();
1485
44
            Node prev = cn;
1486
22
            cn = searchForCycle( cn, cn, visited, proc, expl );
1487
22
            Assert(prev == cn);
1488
          }
1489
1490
194719
          if( !cn.isNull() ) {
1491
412
            Assert(expl.size() > 0);
1492
824
            Trace("dt-conflict")
1493
412
                << "CONFLICT: Cycle conflict : " << expl << std::endl;
1494
412
            d_im.sendDtConflict(expl, InferenceId::DATATYPES_CYCLE);
1495
412
            return;
1496
          }
1497
        }
1498
      }else{
1499
        //indexing
1500
1317
        cdt_eqc.push_back( eqc );
1501
      }
1502
    }
1503
540501
    ++eqcs_i;
1504
  }
1505
23071
  Trace("datatypes-cycle-check") << "Check uniqueness" << std::endl;
1506
  //process codatatypes
1507
23157
  if( cdt_eqc.size()>1 && options::cdtBisimilar() ){
1508
86
    printModelDebug("dt-cdt-debug");
1509
86
    Trace("dt-cdt-debug") << "Process " << cdt_eqc.size() << " co-datatypes" << std::endl;
1510
172
    std::vector< std::vector< Node > > part_out;
1511
172
    std::vector<Node> exp;
1512
172
    std::map< Node, Node > cn;
1513
172
    std::map< Node, std::map< Node, int > > dni;
1514
1399
    for( unsigned i=0; i<cdt_eqc.size(); i++ ){
1515
1313
      cn[cdt_eqc[i]] = cdt_eqc[i];
1516
    }
1517
86
    separateBisimilar( cdt_eqc, part_out, exp, cn, dni, 0, false );
1518
86
    Trace("dt-cdt-debug") << "Done separate bisimilar." << std::endl;
1519
86
    if( !part_out.empty() ){
1520
10
      Trace("dt-cdt-debug") << "Process partition size " << part_out.size() << std::endl;
1521
20
      for( unsigned i=0; i<part_out.size(); i++ ){
1522
20
        std::vector< Node > part;
1523
10
        part.push_back( part_out[i][0] );
1524
20
        for( unsigned j=1; j<part_out[i].size(); j++ ){
1525
10
          Trace("dt-cdt") << "Codatatypes : " << part_out[i][0] << " and " << part_out[i][j] << " must be equal!!" << std::endl;
1526
10
          part.push_back( part_out[i][j] );
1527
20
          std::vector< std::vector< Node > > tpart_out;
1528
10
          exp.clear();
1529
10
          cn.clear();
1530
10
          cn[part_out[i][0]] = part_out[i][0];
1531
10
          cn[part_out[i][j]] = part_out[i][j];
1532
10
          dni.clear();
1533
10
          separateBisimilar( part, tpart_out, exp, cn, dni, 0, true );
1534
10
          Assert(tpart_out.size() == 1 && tpart_out[0].size() == 2);
1535
10
          part.pop_back();
1536
          //merge based on explanation
1537
10
          Trace("dt-cdt") << "  exp is : ";
1538
38
          for( unsigned k=0; k<exp.size(); k++ ){
1539
28
            Trace("dt-cdt") << exp[k] << " ";
1540
          }
1541
10
          Trace("dt-cdt") << std::endl;
1542
20
          Node eq = part_out[i][0].eqNode( part_out[i][j] );
1543
20
          Node eqExp = NodeManager::currentNM()->mkAnd(exp);
1544
10
          d_im.addPendingInference(eq, InferenceId::DATATYPES_BISIMILAR, eqExp);
1545
10
          Trace("datatypes-infer") << "DtInfer : cdt-bisimilar : " << eq << " by " << eqExp << std::endl;
1546
        }
1547
      }
1548
    }
1549
  }
1550
}
1551
1552
//everything is in terms of representatives
1553
289
void TheoryDatatypes::separateBisimilar(
1554
    std::vector<Node>& part,
1555
    std::vector<std::vector<Node> >& part_out,
1556
    std::vector<Node>& exp,
1557
    std::map<Node, Node>& cn,
1558
    std::map<Node, std::map<Node, int> >& dni,
1559
    int dniLvl,
1560
    bool mkExp)
1561
{
1562
289
  if( !mkExp ){
1563
251
    Trace("dt-cdt-debug") << "Separate bisimilar : " << std::endl;
1564
2051
    for( unsigned i=0; i<part.size(); i++ ){
1565
1800
      Trace("dt-cdt-debug") << "   " << part[i] << ", current = " << cn[part[i]] << std::endl;
1566
    }
1567
  }
1568
289
  Assert(part.size() > 1);
1569
578
  std::map< Node, std::vector< Node > > new_part;
1570
578
  std::map< Node, std::vector< Node > > new_part_c;
1571
578
  std::map< int, std::vector< Node > > new_part_rec;
1572
1573
578
  std::map< Node, Node > cn_cons;
1574
2165
  for( unsigned j=0; j<part.size(); j++ ){
1575
3752
    Node c = cn[part[j]];
1576
1876
    std::map< Node, int >::iterator it_rec = dni[part[j]].find( c );
1577
1876
    if( it_rec!=dni[part[j]].end() ){
1578
      //looped
1579
46
      if( !mkExp ){ Trace("dt-cdt-debug") << "  - " << part[j] << " is looping at index " << it_rec->second << std::endl; }
1580
46
      new_part_rec[ it_rec->second ].push_back( part[j] );
1581
    }else{
1582
1830
      if( c.getType().isDatatype() ){
1583
3058
        Node ncons = getEqcConstructor( c );
1584
1529
        if( ncons.getKind()==APPLY_CONSTRUCTOR ) {
1585
914
          Node cc = ncons.getOperator();
1586
457
          cn_cons[part[j]] = ncons;
1587
457
          if (mkExp && c != ncons)
1588
          {
1589
20
            exp.push_back(c.eqNode(ncons));
1590
          }
1591
457
          new_part[cc].push_back( part[j] );
1592
457
          if( !mkExp ){ Trace("dt-cdt-debug") << "  - " << part[j] << " is datatype " << ncons << "." << std::endl; }
1593
        }else{
1594
1072
          new_part_c[c].push_back( part[j] );
1595
1072
          if( !mkExp ){ Trace("dt-cdt-debug") << "  - " << part[j] << " is unspecified datatype." << std::endl; }
1596
        }
1597
      }else{
1598
        //add equivalences
1599
301
        if( !mkExp ){ Trace("dt-cdt-debug") << "  - " << part[j] << " is term " << c << "." << std::endl; }
1600
301
        new_part_c[c].push_back( part[j] );
1601
      }
1602
    }
1603
  }
1604
  //direct add for constants
1605
1540
  for( std::map< Node, std::vector< Node > >::iterator it = new_part_c.begin(); it != new_part_c.end(); ++it ){
1606
1251
    if( it->second.size()>1 ){
1607
220
      std::vector< Node > vec;
1608
110
      vec.insert( vec.begin(), it->second.begin(), it->second.end() );
1609
110
      part_out.push_back( vec );
1610
    }
1611
  }
1612
  //direct add for recursive
1613
315
  for( std::map< int, std::vector< Node > >::iterator it = new_part_rec.begin(); it != new_part_rec.end(); ++it ){
1614
26
    if( it->second.size()>1 ){
1615
40
      std::vector< Node > vec;
1616
20
      vec.insert( vec.begin(), it->second.begin(), it->second.end() );
1617
20
      part_out.push_back( vec );
1618
    }else{
1619
      //add back : could match a datatype?
1620
    }
1621
  }
1622
  //recurse for the datatypes
1623
518
  for( std::map< Node, std::vector< Node > >::iterator it = new_part.begin(); it != new_part.end(); ++it ){
1624
229
    if( it->second.size()>1 ){
1625
      //set dni to check for loops
1626
166
      std::map< Node, Node > dni_rem;
1627
394
      for( unsigned i=0; i<it->second.size(); i++ ){
1628
622
        Node n = it->second[i];
1629
311
        dni[n][cn[n]] = dniLvl;
1630
311
        dni_rem[n] = cn[n];
1631
      }
1632
1633
      //we will split based on the arguments of the datatype
1634
166
      std::vector< std::vector< Node > > split_new_part;
1635
83
      split_new_part.push_back( it->second );
1636
1637
83
      unsigned nChildren = cn_cons[it->second[0]].getNumChildren();
1638
      //for each child of constructor
1639
83
      unsigned cindex = 0;
1640
389
      while( cindex<nChildren && !split_new_part.empty() ){
1641
153
        if( !mkExp ){ Trace("dt-cdt-debug") << "Split argument #" << cindex << " of " << it->first << "..." << std::endl; }
1642
306
        std::vector< std::vector< Node > > next_split_new_part;
1643
346
        for( unsigned j=0; j<split_new_part.size(); j++ ){
1644
          //set current node
1645
736
          for( unsigned k=0; k<split_new_part[j].size(); k++ ){
1646
1086
            Node n = split_new_part[j][k];
1647
1086
            Node cnc = cn_cons[n][cindex];
1648
1086
            Node nr = getRepresentative(cnc);
1649
543
            cn[n] = nr;
1650
543
            if (mkExp && cnc != nr)
1651
            {
1652
8
              exp.push_back(nr.eqNode(cnc));
1653
            }
1654
          }
1655
386
          std::vector< std::vector< Node > > c_part_out;
1656
193
          separateBisimilar( split_new_part[j], c_part_out, exp, cn, dni, dniLvl+1, mkExp );
1657
193
          next_split_new_part.insert( next_split_new_part.end(), c_part_out.begin(), c_part_out.end() );
1658
        }
1659
153
        split_new_part.clear();
1660
153
        split_new_part.insert( split_new_part.end(), next_split_new_part.begin(), next_split_new_part.end() );
1661
153
        cindex++;
1662
      }
1663
83
      part_out.insert( part_out.end(), split_new_part.begin(), split_new_part.end() );
1664
1665
394
      for( std::map< Node, Node >::iterator it2 = dni_rem.begin(); it2 != dni_rem.end(); ++it2 ){
1666
311
        dni[it2->first].erase( it2->second );
1667
      }
1668
    }
1669
  }
1670
289
}
1671
1672
//postcondition: if cycle detected, explanation is why n is a subterm of on
1673
770959
Node TheoryDatatypes::searchForCycle(TNode n,
1674
                                     TNode on,
1675
                                     std::map<TNode, bool>& visited,
1676
                                     std::map<TNode, bool>& proc,
1677
                                     std::vector<Node>& explanation,
1678
                                     bool firstTime)
1679
{
1680
770959
  Trace("datatypes-cycle-check2") << "Search for cycle " << n << " " << on << endl;
1681
1541918
  TNode ncons;
1682
1541918
  TNode nn;
1683
770959
  if( !firstTime ){
1684
576218
    nn = getRepresentative( n );
1685
576218
    if( nn==on ){
1686
412
      if (n != nn)
1687
      {
1688
340
        explanation.push_back(n.eqNode(nn));
1689
      }
1690
412
      return on;
1691
    }
1692
  }else{
1693
194741
    nn = getRepresentative( n );
1694
  }
1695
770547
  if( proc.find( nn )!=proc.end() ){
1696
148026
    return Node::null();
1697
  }
1698
622521
  Trace("datatypes-cycle-check2") << "...representative : " << nn << " " << ( visited.find( nn ) == visited.end() ) << " " << visited.size() << std::endl;
1699
622521
  if( visited.find( nn ) == visited.end() ) {
1700
622499
    Trace("datatypes-cycle-check2") << "  visit : " << nn << std::endl;
1701
622499
    visited[nn] = true;
1702
1244998
    TNode nncons = getEqcConstructor(nn);
1703
622499
    if (nncons.getKind() == APPLY_CONSTRUCTOR)
1704
    {
1705
1018319
      for (unsigned i = 0; i < nncons.getNumChildren(); i++)
1706
      {
1707
        TNode cn =
1708
1151033
            searchForCycle(nncons[i], on, visited, proc, explanation, false);
1709
576218
        if( cn==on ) {
1710
          //add explanation for why the constructor is connected
1711
1275
          if (n != nncons)
1712
          {
1713
876
            explanation.push_back(n.eqNode(nncons));
1714
          }
1715
1275
          return on;
1716
574943
        }else if( !cn.isNull() ){
1717
128
          return cn;
1718
        }
1719
      }
1720
    }
1721
621096
    Trace("datatypes-cycle-check2") << "  unvisit : " << nn << std::endl;
1722
621096
    proc[nn] = true;
1723
621096
    visited.erase( nn );
1724
621096
    return Node::null();
1725
  }else{
1726
44
    TypeNode tn = nn.getType();
1727
22
    if( tn.isDatatype() ) {
1728
22
      if( !tn.isCodatatype() ){
1729
22
        return nn;
1730
      }
1731
    }
1732
    return Node::null();
1733
  }
1734
}
1735
1736
1948597
bool TheoryDatatypes::hasTerm(TNode a) { return d_equalityEngine->hasTerm(a); }
1737
1738
121334
bool TheoryDatatypes::areEqual( TNode a, TNode b ){
1739
121334
  if( a==b ){
1740
7601
    return true;
1741
113733
  }else if( hasTerm( a ) && hasTerm( b ) ){
1742
113733
    return d_equalityEngine->areEqual(a, b);
1743
  }else{
1744
    return false;
1745
  }
1746
}
1747
1748
20356
bool TheoryDatatypes::areDisequal( TNode a, TNode b ){
1749
20356
  if( a==b ){
1750
6302
    return false;
1751
14054
  }else if( hasTerm( a ) && hasTerm( b ) ){
1752
14054
    return d_equalityEngine->areDisequal(a, b, false);
1753
  }else{
1754
    //TODO : constants here?
1755
    return false;
1756
  }
1757
}
1758
1759
91633
bool TheoryDatatypes::areCareDisequal( TNode x, TNode y ) {
1760
91633
  Trace("datatypes-cg") << "areCareDisequal: " << x << " " << y << std::endl;
1761
91633
  Assert(d_equalityEngine->hasTerm(x));
1762
91633
  Assert(d_equalityEngine->hasTerm(y));
1763
274899
  if (d_equalityEngine->isTriggerTerm(x, THEORY_DATATYPES)
1764
274899
      && d_equalityEngine->isTriggerTerm(y, THEORY_DATATYPES))
1765
  {
1766
    TNode x_shared =
1767
88167
        d_equalityEngine->getTriggerTermRepresentative(x, THEORY_DATATYPES);
1768
    TNode y_shared =
1769
88167
        d_equalityEngine->getTriggerTermRepresentative(y, THEORY_DATATYPES);
1770
71135
    EqualityStatus eqStatus = d_valuation.getEqualityStatus(x_shared, y_shared);
1771
71135
    if( eqStatus==EQUALITY_FALSE_AND_PROPAGATED || eqStatus==EQUALITY_FALSE || eqStatus==EQUALITY_FALSE_IN_MODEL ){
1772
54103
      return true;
1773
    }
1774
  }
1775
37530
  return false;
1776
}
1777
1778
1693023
TNode TheoryDatatypes::getRepresentative( TNode a ){
1779
1693023
  if( hasTerm( a ) ){
1780
1693023
    return d_equalityEngine->getRepresentative(a);
1781
  }else{
1782
    return a;
1783
  }
1784
}
1785
1786
31755
void TheoryDatatypes::printModelDebug( const char* c ){
1787
31755
  if(! (Trace.isOn(c))) {
1788
31755
    return;
1789
  }
1790
1791
  Trace( c ) << "Datatypes model : " << std::endl;
1792
  eq::EqClassesIterator eqcs_i = eq::EqClassesIterator(d_equalityEngine);
1793
  while( !eqcs_i.isFinished() ){
1794
    Node eqc = (*eqcs_i);
1795
    //if( !eqc.getType().isBoolean() ){
1796
      if( eqc.getType().isDatatype() ){
1797
        Trace( c ) << "DATATYPE : ";
1798
      }
1799
      Trace( c ) << eqc << " : " << eqc.getType() << " : " << std::endl;
1800
      Trace( c ) << "   { ";
1801
      //add terms to model
1802
      eq::EqClassIterator eqc_i = eq::EqClassIterator(eqc, d_equalityEngine);
1803
      while( !eqc_i.isFinished() ){
1804
        if( (*eqc_i)!=eqc ){
1805
          Trace( c ) << (*eqc_i) << " ";
1806
        }
1807
        ++eqc_i;
1808
      }
1809
      Trace( c ) << "}" << std::endl;
1810
      if( eqc.getType().isDatatype() ){
1811
        EqcInfo* ei = getOrMakeEqcInfo( eqc );
1812
        if( ei ){
1813
          Trace( c ) << "   Instantiated : " << ei->d_inst.get() << std::endl;
1814
          Trace( c ) << "   Constructor : ";
1815
          if( !ei->d_constructor.get().isNull() ){
1816
            Trace( c )<< ei->d_constructor.get();
1817
          }
1818
          Trace( c ) << std::endl << "   Labels : ";
1819
          if( hasLabel( ei, eqc ) ){
1820
            Trace( c ) << getLabel( eqc );
1821
          }else{
1822
            NodeUIntMap::iterator lbl_i = d_labels.find(eqc);
1823
            if( lbl_i != d_labels.end() ){
1824
              for (size_t j = 0; j < (*lbl_i).second; j++)
1825
              {
1826
                Trace( c ) << d_labels_data[eqc][j] << " ";
1827
              }
1828
            }
1829
          }
1830
          Trace( c ) << std::endl;
1831
          Trace( c ) << "   Selectors : " << ( ei->d_selectors ? "yes, " : "no " );
1832
          NodeUIntMap::iterator sel_i = d_selector_apps.find(eqc);
1833
          if( sel_i != d_selector_apps.end() ){
1834
            for (size_t j = 0; j < (*sel_i).second; j++)
1835
            {
1836
              Trace( c ) << d_selector_apps_data[eqc][j] << " ";
1837
            }
1838
          }
1839
          Trace( c ) << std::endl;
1840
        }
1841
      }
1842
    //}
1843
    ++eqcs_i;
1844
  }
1845
}
1846
1847
9109
void TheoryDatatypes::computeRelevantTerms(std::set<Node>& termSet)
1848
{
1849
18218
  Trace("dt-cmi") << "Have " << termSet.size() << " relevant terms..."
1850
9109
                  << std::endl;
1851
1852
  //also include non-singleton equivalence classes  TODO : revisit this
1853
9109
  eq::EqClassesIterator eqcs_i = eq::EqClassesIterator(d_equalityEngine);
1854
573981
  while( !eqcs_i.isFinished() ){
1855
564872
    TNode r = (*eqcs_i);
1856
282436
    bool addedFirst = false;
1857
564872
    Node first;
1858
564872
    TypeNode rtn = r.getType();
1859
282436
    if (!rtn.isBoolean())
1860
    {
1861
207255
      eq::EqClassIterator eqc_i = eq::EqClassIterator(r, d_equalityEngine);
1862
1058533
      while (!eqc_i.isFinished())
1863
      {
1864
851278
        TNode n = (*eqc_i);
1865
425639
        if (first.isNull())
1866
        {
1867
207255
          first = n;
1868
          // always include all datatypes
1869
207255
          if (rtn.isDatatype())
1870
          {
1871
64389
            addedFirst = true;
1872
64389
            termSet.insert(n);
1873
          }
1874
        }
1875
        else
1876
        {
1877
218384
          if (!addedFirst)
1878
          {
1879
22893
            addedFirst = true;
1880
22893
            termSet.insert(first);
1881
          }
1882
218384
          termSet.insert(n);
1883
        }
1884
425639
        ++eqc_i;
1885
      }
1886
    }
1887
282436
    ++eqcs_i;
1888
  }
1889
9109
}
1890
1891
std::pair<bool, Node> TheoryDatatypes::entailmentCheck(TNode lit)
1892
{
1893
  Trace("dt-entail") << "Check entailed : " << lit << std::endl;
1894
  Node atom = lit.getKind()==NOT ? lit[0] : lit;
1895
  bool pol = lit.getKind()!=NOT;
1896
  if( atom.getKind()==APPLY_TESTER ){
1897
    Node n = atom[0];
1898
    if( hasTerm( n ) ){
1899
      Node r = d_equalityEngine->getRepresentative(n);
1900
      EqcInfo * ei = getOrMakeEqcInfo( r, false );
1901
      int l_index = getLabelIndex( ei, r );
1902
      int t_index = static_cast<int>(utils::indexOf(atom.getOperator()));
1903
      Trace("dt-entail") << "  Tester indices are " << t_index << " and " << l_index << std::endl;
1904
      if( l_index!=-1 && (l_index==t_index)==pol ){
1905
        std::vector< TNode > exp_c;
1906
        Node eqToExplain;
1907
        if( ei && !ei->d_constructor.get().isNull() ){
1908
          eqToExplain = n.eqNode(ei->d_constructor.get());
1909
        }else{
1910
          Node lbl = getLabel( n );
1911
          Assert(!lbl.isNull());
1912
          exp_c.push_back( lbl );
1913
          Assert(areEqual(n, lbl[0]));
1914
          eqToExplain = n.eqNode(lbl[0]);
1915
        }
1916
        d_equalityEngine->explainLit(eqToExplain, exp_c);
1917
        Node exp = NodeManager::currentNM()->mkAnd(exp_c);
1918
        Trace("dt-entail") << "  entailed, explanation is " << exp << std::endl;
1919
        return make_pair(true, exp);
1920
      }
1921
    }
1922
  }
1923
  return make_pair(false, Node::null());
1924
}
1925
1926
}  // namespace datatypes
1927
}  // namespace theory
1928
28191
}  // namespace cvc5