GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/quantifiers/term_database.cpp Lines: 460 571 80.6 %
Date: 2021-09-10 Branches: 1023 2440 41.9 %

Line Exec Source
1
/******************************************************************************
2
 * Top contributors (to current version):
3
 *   Andrew Reynolds, Mathias Preiner, Tim King
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 term database class.
14
 */
15
16
#include "theory/quantifiers/term_database.h"
17
18
#include "expr/skolem_manager.h"
19
#include "options/base_options.h"
20
#include "options/quantifiers_options.h"
21
#include "options/smt_options.h"
22
#include "options/theory_options.h"
23
#include "options/uf_options.h"
24
#include "theory/quantifiers/ematching/trigger_term_info.h"
25
#include "theory/quantifiers/quantifiers_attributes.h"
26
#include "theory/quantifiers/quantifiers_inference_manager.h"
27
#include "theory/quantifiers/quantifiers_registry.h"
28
#include "theory/quantifiers/quantifiers_state.h"
29
#include "theory/quantifiers/term_util.h"
30
#include "theory/rewriter.h"
31
#include "theory/uf/equality_engine.h"
32
33
using namespace cvc5::kind;
34
using namespace cvc5::context;
35
36
namespace cvc5 {
37
namespace theory {
38
namespace quantifiers {
39
40
9913
TermDb::TermDb(Env& env, QuantifiersState& qs, QuantifiersRegistry& qr)
41
    : QuantifiersUtil(env),
42
      d_qstate(qs),
43
      d_qim(nullptr),
44
      d_qreg(qr),
45
      d_termsContext(),
46
9913
      d_termsContextUse(options::termDbCd() ? qs.getSatContext()
47
                                            : &d_termsContext),
48
      d_processed(d_termsContextUse),
49
      d_typeMap(d_termsContextUse),
50
      d_ops(d_termsContextUse),
51
      d_opMap(d_termsContextUse),
52
19826
      d_inactive_map(qs.getSatContext())
53
{
54
9913
  d_consistent_ee = true;
55
9913
  d_true = NodeManager::currentNM()->mkConst(true);
56
9913
  d_false = NodeManager::currentNM()->mkConst(false);
57
9913
  if (!options::termDbCd())
58
  {
59
    // when not maintaining terms in a context-dependent manner, we clear during
60
    // each presolve, which requires maintaining a single outermost level
61
    d_termsContext.push();
62
  }
63
9913
}
64
65
19630
TermDb::~TermDb(){
66
67
19630
}
68
69
9913
void TermDb::finishInit(QuantifiersInferenceManager* qim) { d_qim = qim; }
70
71
25073
void TermDb::registerQuantifier( Node q ) {
72
25073
  Assert(q[0].getNumChildren() == d_qreg.getNumInstantiationConstants(q));
73
84276
  for (size_t i = 0, nvars = q[0].getNumChildren(); i < nvars; i++)
74
  {
75
118406
    Node ic = d_qreg.getInstantiationConstant(q, i);
76
59203
    setTermInactive( ic );
77
  }
78
25073
}
79
80
915
size_t TermDb::getNumOperators() const { return d_ops.size(); }
81
82
2132
Node TermDb::getOperator(size_t i) const
83
{
84
2132
  Assert(i < d_ops.size());
85
2132
  return d_ops[i];
86
}
87
88
/** ground terms */
89
463513
size_t TermDb::getNumGroundTerms(Node f) const
90
{
91
463513
  NodeDbListMap::const_iterator it = d_opMap.find(f);
92
463513
  if (it != d_opMap.end())
93
  {
94
446147
    return it->second->d_list.size();
95
  }
96
17366
  return 0;
97
}
98
99
2999285
Node TermDb::getGroundTerm(Node f, size_t i) const
100
{
101
2999285
  NodeDbListMap::const_iterator it = d_opMap.find(f);
102
2999285
  if (it != d_opMap.end())
103
  {
104
2999285
    Assert(i < it->second->d_list.size());
105
2999285
    return it->second->d_list[i];
106
  }
107
  Assert(false);
108
  return Node::null();
109
}
110
111
248
size_t TermDb::getNumTypeGroundTerms(TypeNode tn) const
112
{
113
248
  TypeNodeDbListMap::const_iterator it = d_typeMap.find(tn);
114
248
  if (it != d_typeMap.end())
115
  {
116
239
    return it->second->d_list.size();
117
  }
118
9
  return 0;
119
}
120
121
10246
Node TermDb::getTypeGroundTerm(TypeNode tn, size_t i) const
122
{
123
10246
  TypeNodeDbListMap::const_iterator it = d_typeMap.find(tn);
124
10246
  if (it != d_typeMap.end())
125
  {
126
10246
    Assert(i < it->second->d_list.size());
127
10246
    return it->second->d_list[i];
128
  }
129
  Assert(false);
130
  return Node::null();
131
}
132
133
2478
Node TermDb::getOrMakeTypeGroundTerm(TypeNode tn, bool reqVar)
134
{
135
2478
  TypeNodeDbListMap::const_iterator it = d_typeMap.find(tn);
136
2478
  if (it != d_typeMap.end())
137
  {
138
509
    Assert(!it->second->d_list.empty());
139
509
    if (!reqVar)
140
    {
141
176
      return it->second->d_list[0];
142
    }
143
522
    for (const Node& v : it->second->d_list)
144
    {
145
467
      if (v.isVar())
146
      {
147
278
        return v;
148
      }
149
    }
150
  }
151
2024
  return getOrMakeTypeFreshVariable(tn);
152
}
153
154
2024
Node TermDb::getOrMakeTypeFreshVariable(TypeNode tn)
155
{
156
2024
  std::unordered_map<TypeNode, Node>::iterator it = d_type_fv.find(tn);
157
2024
  if (it == d_type_fv.end())
158
  {
159
240
    SkolemManager* sm = NodeManager::currentNM()->getSkolemManager();
160
480
    std::stringstream ss;
161
240
    ss << language::SetLanguage(options::outputLanguage());
162
240
    ss << "e_" << tn;
163
480
    Node k = sm->mkDummySkolem(ss.str(), tn, "is a termDb fresh variable");
164
480
    Trace("mkVar") << "TermDb:: Make variable " << k << " : " << tn
165
240
                   << std::endl;
166
240
    if (options::instMaxLevel() != -1)
167
    {
168
      QuantAttributes::setInstantiationLevelAttr(k, 0);
169
    }
170
240
    d_type_fv[tn] = k;
171
240
    return k;
172
  }
173
1784
  return it->second;
174
}
175
176
4297596
Node TermDb::getMatchOperator( Node n ) {
177
4297596
  Kind k = n.getKind();
178
  //datatype operators may be parametric, always assume they are
179
4297596
  if (k == SELECT || k == STORE || k == UNION || k == INTERSECTION
180
4265616
      || k == SUBSET || k == SETMINUS || k == MEMBER || k == SINGLETON
181
4236712
      || k == APPLY_SELECTOR_TOTAL || k == APPLY_SELECTOR || k == APPLY_TESTER
182
4111405
      || k == SEP_PTO || k == HO_APPLY || k == SEQ_NTH)
183
  {
184
    //since it is parametric, use a particular one as op
185
412292
    TypeNode tn = n[0].getType();
186
412292
    Node op = n.getOperator();
187
206146
    std::map< Node, std::map< TypeNode, Node > >::iterator ito = d_par_op_map.find( op );
188
206146
    if( ito!=d_par_op_map.end() ){
189
197761
      std::map< TypeNode, Node >::iterator it = ito->second.find( tn );
190
197761
      if( it!=ito->second.end() ){
191
197079
        return it->second;
192
      }
193
    }
194
9067
    Trace("par-op") << "Parametric operator : " << k << ", " << n.getOperator() << ", " << tn << " : " << n << std::endl;
195
9067
    d_par_op_map[op][tn] = n;
196
9067
    return n;
197
  }
198
4091450
  else if (inst::TriggerTermInfo::isAtomicTriggerKind(k))
199
  {
200
3891503
    return n.getOperator();
201
  }else{
202
199947
    return Node::null();
203
  }
204
}
205
206
2536766
void TermDb::addTerm(Node n)
207
{
208
2536766
  if (d_processed.find(n) != d_processed.end())
209
  {
210
1515061
    return;
211
  }
212
1021705
  d_processed.insert(n);
213
1021705
  if (!TermUtil::hasInstConstAttr(n))
214
  {
215
982405
    Trace("term-db-debug") << "register term : " << n << std::endl;
216
982405
    DbList* dlt = getOrMkDbListForType(n.getType());
217
982405
    dlt->d_list.push_back(n);
218
    // if this is an atomic trigger, consider adding it
219
982405
    if (inst::TriggerTermInfo::isAtomicTrigger(n))
220
    {
221
405623
      Trace("term-db") << "register term in db " << n << std::endl;
222
223
811246
      Node op = getMatchOperator(n);
224
405623
      Trace("term-db-debug") << "  match operator is : " << op << std::endl;
225
405623
      DbList* dlo = getOrMkDbListForOp(op);
226
405623
      dlo->d_list.push_back(n);
227
      // If we are higher-order, we may need to register more terms.
228
405623
      addTermInternal(n);
229
    }
230
  }
231
  else
232
  {
233
39300
    setTermInactive(n);
234
  }
235
1021705
  if (!n.isClosure())
236
  {
237
2646666
    for (const Node& nc : n)
238
    {
239
1624983
      addTerm(nc);
240
    }
241
  }
242
}
243
244
982405
DbList* TermDb::getOrMkDbListForType(TypeNode tn)
245
{
246
982405
  TypeNodeDbListMap::iterator it = d_typeMap.find(tn);
247
982405
  if (it != d_typeMap.end())
248
  {
249
957628
    return it->second.get();
250
  }
251
49554
  std::shared_ptr<DbList> dl = std::make_shared<DbList>(d_termsContextUse);
252
24777
  d_typeMap.insert(tn, dl);
253
24777
  return dl.get();
254
}
255
256
465339
DbList* TermDb::getOrMkDbListForOp(TNode op)
257
{
258
465339
  NodeDbListMap::iterator it = d_opMap.find(op);
259
465339
  if (it != d_opMap.end())
260
  {
261
371255
    return it->second.get();
262
  }
263
188168
  std::shared_ptr<DbList> dl = std::make_shared<DbList>(d_termsContextUse);
264
94084
  d_opMap.insert(op, dl);
265
94084
  Assert(op.getKind() != BOUND_VARIABLE);
266
94084
  d_ops.push_back(op);
267
94084
  return dl.get();
268
}
269
270
591426
void TermDb::computeArgReps( TNode n ) {
271
591426
  if (d_arg_reps.find(n) == d_arg_reps.end())
272
  {
273
353870
    eq::EqualityEngine* ee = d_qstate.getEqualityEngine();
274
1114819
    for (const TNode& nc : n)
275
    {
276
1521898
      TNode r = ee->hasTerm(nc) ? ee->getRepresentative(nc) : nc;
277
760949
      d_arg_reps[n].push_back( r );
278
    }
279
  }
280
591426
}
281
282
1765659
void TermDb::computeUfEqcTerms( TNode f ) {
283
1765659
  Assert(f == getOperatorRepresentative(f));
284
1765659
  if (d_func_map_eqc_trie.find(f) != d_func_map_eqc_trie.end())
285
  {
286
1719346
    return;
287
  }
288
46313
  d_func_map_eqc_trie[f].clear();
289
  // get the matchable operators in the equivalence class of f
290
92626
  std::vector<TNode> ops;
291
46313
  getOperatorsFor(f, ops);
292
46313
  eq::EqualityEngine* ee = d_qstate.getEqualityEngine();
293
92723
  for (TNode ff : ops)
294
  {
295
46410
    DbList* dbl = getOrMkDbListForOp(ff);
296
345100
    for (const Node& n : dbl->d_list)
297
    {
298
298690
      if (hasTermCurrent(n) && isTermActive(n))
299
      {
300
282492
        computeArgReps(n);
301
564984
        TNode r = ee->hasTerm(n) ? ee->getRepresentative(n) : TNode(n);
302
282492
        d_func_map_eqc_trie[f].d_data[r].addTerm(n, d_arg_reps[n]);
303
      }
304
    }
305
  }
306
}
307
308
3165819
void TermDb::computeUfTerms( TNode f ) {
309
3165819
  if (d_op_nonred_count.find(f) != d_op_nonred_count.end())
310
  {
311
    // already computed
312
6249257
    return;
313
  }
314
41196
  Assert(f == getOperatorRepresentative(f));
315
41196
  d_op_nonred_count[f] = 0;
316
  // get the matchable operators in the equivalence class of f
317
82381
  std::vector<TNode> ops;
318
41196
  getOperatorsFor(f, ops);
319
41196
  Trace("term-db-debug") << "computeUfTerms for " << f << std::endl;
320
41196
  unsigned congruentCount = 0;
321
41196
  unsigned nonCongruentCount = 0;
322
41196
  unsigned alreadyCongruentCount = 0;
323
41196
  unsigned relevantCount = 0;
324
41196
  NodeManager* nm = NodeManager::currentNM();
325
76820
  for (TNode ff : ops)
326
  {
327
41282
    NodeDbListMap::iterator it = d_opMap.find(ff);
328
41282
    if (it == d_opMap.end())
329
    {
330
      // no terms for this operator
331
5647
      continue;
332
    }
333
35635
    Trace("term-db-debug") << "Adding terms for operator " << ff << std::endl;
334
362633
    for (const Node& n : it->second->d_list)
335
    {
336
      // to be added to term index, term must be relevant, and exist in EE
337
327009
      if (!hasTermCurrent(n) || !d_qstate.hasTerm(n))
338
      {
339
        Trace("term-db-debug") << n << " is not relevant." << std::endl;
340
85176
        continue;
341
      }
342
343
327009
      relevantCount++;
344
345084
      if (!isTermActive(n))
345
      {
346
18075
        Trace("term-db-debug") << n << " is already redundant." << std::endl;
347
18075
        alreadyCongruentCount++;
348
18075
        continue;
349
      }
350
351
308934
      computeArgReps(n);
352
308934
      Trace("term-db-debug") << "Adding term " << n << " with arg reps : ";
353
974970
      for (unsigned i = 0, size = d_arg_reps[n].size(); i < size; i++)
354
      {
355
666036
        Trace("term-db-debug") << d_arg_reps[n][i] << " ";
356
2664144
        if (std::find(d_func_map_rel_dom[f][i].begin(),
357
1332072
                      d_func_map_rel_dom[f][i].end(),
358
2664144
                      d_arg_reps[n][i])
359
1998108
            == d_func_map_rel_dom[f][i].end())
360
        {
361
241507
          d_func_map_rel_dom[f][i].push_back(d_arg_reps[n][i]);
362
        }
363
      }
364
308934
      Trace("term-db-debug") << std::endl;
365
308934
      Assert(d_qstate.hasTerm(n));
366
617868
      Trace("term-db-debug")
367
308934
          << "  and value : " << d_qstate.getRepresentative(n) << std::endl;
368
550756
      Node at = d_func_map_trie[f].addOrGetTerm(n, d_arg_reps[n]);
369
308934
      Assert(d_qstate.hasTerm(at));
370
308934
      Trace("term-db-debug2") << "...add term returned " << at << std::endl;
371
376035
      if (at != n && d_qstate.areEqual(at, n))
372
      {
373
67101
        setTermInactive(n);
374
67101
        Trace("term-db-debug") << n << " is redundant." << std::endl;
375
67101
        congruentCount++;
376
67101
        continue;
377
      }
378
483655
      std::vector<Node> lits;
379
241833
      if (checkCongruentDisequal(at, n, lits))
380
      {
381
11
        Assert(at.getNumChildren() == n.getNumChildren());
382
41
        for (size_t k = 0, size = at.getNumChildren(); k < size; k++)
383
        {
384
30
          if (at[k] != n[k])
385
          {
386
18
            lits.push_back(nm->mkNode(EQUAL, at[k], n[k]).negate());
387
          }
388
        }
389
22
        Node lem = nm->mkOr(lits);
390
11
        if (Trace.isOn("term-db-lemma"))
391
        {
392
          Trace("term-db-lemma") << "Disequal congruent terms : " << at << " "
393
                                 << n << "!!!!" << std::endl;
394
          if (!d_qstate.getValuation().needCheck())
395
          {
396
            Trace("term-db-lemma")
397
                << "  all theories passed with no lemmas." << std::endl;
398
            // we should be a full effort check, prior to theory combination
399
          }
400
          Trace("term-db-lemma") << "  add lemma : " << lem << std::endl;
401
        }
402
11
        d_qim->addPendingLemma(lem, InferenceId::QUANTIFIERS_TDB_DEQ_CONG);
403
11
        d_qstate.notifyInConflict();
404
11
        d_consistent_ee = false;
405
11
        return;
406
      }
407
241822
      nonCongruentCount++;
408
241822
      d_op_nonred_count[f]++;
409
    }
410
35624
    if (Trace.isOn("tdb"))
411
    {
412
      Trace("tdb") << "Term db size [" << f << "] : " << nonCongruentCount
413
                   << " / ";
414
      Trace("tdb") << (nonCongruentCount + congruentCount) << " / "
415
                   << (nonCongruentCount + congruentCount
416
                       + alreadyCongruentCount)
417
                   << " / ";
418
      Trace("tdb") << relevantCount << " / " << it->second->d_list.size()
419
                   << std::endl;
420
    }
421
  }
422
}
423
424
6240741
Node TermDb::getOperatorRepresentative(TNode op) const { return op; }
425
426
233781
bool TermDb::checkCongruentDisequal(TNode a, TNode b, std::vector<Node>& exp)
427
{
428
233781
  if (d_qstate.areDisequal(a, b))
429
  {
430
11
    exp.push_back(a.eqNode(b));
431
11
    return true;
432
  }
433
233770
  return false;
434
}
435
436
2181884
bool TermDb::inRelevantDomain( TNode f, unsigned i, TNode r ) {
437
  // notice if we are not higher-order, getOperatorRepresentative is a no-op
438
2181884
  f = getOperatorRepresentative(f);
439
2181884
  computeUfTerms( f );
440
2181884
  Assert(!d_qstate.getEqualityEngine()->hasTerm(r)
441
         || d_qstate.getEqualityEngine()->getRepresentative(r) == r);
442
2181884
  std::map< Node, std::map< unsigned, std::vector< Node > > >::iterator it = d_func_map_rel_dom.find( f );
443
2181884
  if( it != d_func_map_rel_dom.end() ){
444
2157507
    std::map< unsigned, std::vector< Node > >::iterator it2 = it->second.find( i );
445
2157507
    if( it2!=it->second.end() ){
446
2157507
      return std::find( it2->second.begin(), it2->second.end(), r )!=it2->second.end();
447
    }else{
448
      return false;
449
    }
450
  }else{
451
24377
    return false;
452
  }
453
}
454
455
614112
Node TermDb::evaluateTerm2(TNode n,
456
                           std::map<TNode, Node>& visited,
457
                           std::vector<Node>& exp,
458
                           bool useEntailmentTests,
459
                           bool computeExp,
460
                           bool reqHasTerm)
461
{
462
614112
  std::map< TNode, Node >::iterator itv = visited.find( n );
463
614112
  if( itv != visited.end() ){
464
47580
    return itv->second;
465
  }
466
566532
  size_t prevSize = exp.size();
467
566532
  Trace("term-db-eval") << "evaluate term : " << n << std::endl;
468
1133064
  Node ret = n;
469
566532
  if( n.getKind()==FORALL || n.getKind()==BOUND_VARIABLE ){
470
    //do nothing
471
  }
472
564072
  else if (d_qstate.hasTerm(n))
473
  {
474
265934
    Trace("term-db-eval") << "...exists in ee, return rep" << std::endl;
475
265934
    ret = d_qstate.getRepresentative(n);
476
265934
    if (computeExp)
477
    {
478
      if (n != ret)
479
      {
480
        exp.push_back(n.eqNode(ret));
481
      }
482
    }
483
265934
    reqHasTerm = false;
484
  }
485
298138
  else if (n.hasOperator())
486
  {
487
595406
    std::vector<TNode> args;
488
297703
    bool ret_set = false;
489
297703
    Kind k = n.getKind();
490
595406
    std::vector<Node> tempExp;
491
686402
    for (unsigned i = 0, nchild = n.getNumChildren(); i < nchild; i++)
492
    {
493
1029968
      TNode c = evaluateTerm2(n[i],
494
                              visited,
495
                              tempExp,
496
                              useEntailmentTests,
497
                              computeExp,
498
903683
                              reqHasTerm);
499
514984
      if (c.isNull())
500
      {
501
89292
        ret = Node::null();
502
89292
        ret_set = true;
503
89292
        break;
504
      }
505
425692
      else if (c == d_true || c == d_false)
506
      {
507
        // short-circuiting
508
198656
        if ((k == AND && c == d_false) || (k == OR && c == d_true))
509
        {
510
32792
          ret = c;
511
32792
          ret_set = true;
512
32792
          reqHasTerm = false;
513
32792
          break;
514
        }
515
165864
        else if (k == ITE && i == 0)
516
        {
517
4201
          ret = evaluateTerm2(n[c == d_true ? 1 : 2],
518
                              visited,
519
                              tempExp,
520
                              useEntailmentTests,
521
                              computeExp,
522
                              reqHasTerm);
523
4201
          ret_set = true;
524
4201
          reqHasTerm = false;
525
4201
          break;
526
        }
527
      }
528
388699
      if (computeExp)
529
      {
530
        exp.insert(exp.end(), tempExp.begin(), tempExp.end());
531
      }
532
388699
      Trace("term-db-eval") << "  child " << i << " : " << c << std::endl;
533
388699
      args.push_back(c);
534
    }
535
297703
    if (ret_set)
536
    {
537
      // if we short circuited
538
126285
      if (computeExp)
539
      {
540
        exp.clear();
541
        exp.insert(exp.end(), tempExp.begin(), tempExp.end());
542
      }
543
    }
544
    else
545
    {
546
      // get the (indexed) operator of n, if it exists
547
342836
      TNode f = getMatchOperator(n);
548
      // if it is an indexed term, return the congruent term
549
171418
      if (!f.isNull())
550
      {
551
        // if f is congruent to a term indexed by this class
552
140564
        TNode nn = getCongruentTerm(f, args);
553
140564
        Trace("term-db-eval") << "  got congruent term " << nn
554
70282
                              << " from DB for " << n << std::endl;
555
70282
        if (!nn.isNull())
556
        {
557
28923
          if (computeExp)
558
          {
559
            Assert(nn.getNumChildren() == n.getNumChildren());
560
            for (unsigned i = 0, nchild = nn.getNumChildren(); i < nchild; i++)
561
            {
562
              if (nn[i] != n[i])
563
              {
564
                exp.push_back(nn[i].eqNode(n[i]));
565
              }
566
            }
567
          }
568
28923
          ret = d_qstate.getRepresentative(nn);
569
28923
          Trace("term-db-eval") << "return rep" << std::endl;
570
28923
          ret_set = true;
571
28923
          reqHasTerm = false;
572
28923
          Assert(!ret.isNull());
573
28923
          if (computeExp)
574
          {
575
            if (n != ret)
576
            {
577
              exp.push_back(nn.eqNode(ret));
578
            }
579
          }
580
        }
581
      }
582
171418
      if( !ret_set ){
583
142495
        Trace("term-db-eval") << "return rewrite" << std::endl;
584
        // a theory symbol or a new UF term
585
142495
        if (n.getMetaKind() == metakind::PARAMETERIZED)
586
        {
587
41221
          args.insert(args.begin(), n.getOperator());
588
        }
589
142495
        ret = NodeManager::currentNM()->mkNode(n.getKind(), args);
590
142495
        ret = Rewriter::rewrite(ret);
591
142495
        if (ret.getKind() == EQUAL)
592
        {
593
16689
          if (d_qstate.areDisequal(ret[0], ret[1]))
594
          {
595
4852
            ret = d_false;
596
          }
597
        }
598
142495
        if (useEntailmentTests)
599
        {
600
1359
          if (ret.getKind() == EQUAL || ret.getKind() == GEQ)
601
          {
602
15
            Valuation& val = d_qstate.getValuation();
603
41
            for (unsigned j = 0; j < 2; j++)
604
            {
605
              std::pair<bool, Node> et = val.entailmentCheck(
606
                  options::TheoryOfMode::THEORY_OF_TYPE_BASED,
607
56
                  j == 0 ? ret : ret.negate());
608
30
              if (et.first)
609
              {
610
4
                ret = j == 0 ? d_true : d_false;
611
4
                if (computeExp)
612
                {
613
                  exp.push_back(et.second);
614
                }
615
4
                break;
616
              }
617
            }
618
          }
619
        }
620
      }
621
    }
622
  }
623
  // must have the term
624
566532
  if (reqHasTerm && !ret.isNull())
625
  {
626
140574
    Kind k = ret.getKind();
627
140574
    if (k != OR && k != AND && k != EQUAL && k != ITE && k != NOT
628
126041
        && k != FORALL)
629
    {
630
125852
      if (!d_qstate.hasTerm(ret))
631
      {
632
39144
        ret = Node::null();
633
      }
634
    }
635
  }
636
1133064
  Trace("term-db-eval") << "evaluated term : " << n << ", got : " << ret
637
566532
                        << ", reqHasTerm = " << reqHasTerm << std::endl;
638
  // clear the explanation if failed
639
566532
  if (computeExp && ret.isNull())
640
  {
641
    exp.resize(prevSize);
642
  }
643
566532
  visited[n] = ret;
644
566532
  return ret;
645
}
646
647
8571903
TNode TermDb::getEntailedTerm2(TNode n,
648
                               std::map<TNode, TNode>& subs,
649
                               bool subsRep,
650
                               bool hasSubs)
651
{
652
8571903
  Trace("term-db-entail") << "get entailed term : " << n << std::endl;
653
8571903
  if (d_qstate.hasTerm(n))
654
  {
655
2692714
    Trace("term-db-entail") << "...exists in ee, return rep " << std::endl;
656
2692714
    return n;
657
5879189
  }else if( n.getKind()==BOUND_VARIABLE ){
658
3558118
    if( hasSubs ){
659
3558118
      std::map< TNode, TNode >::iterator it = subs.find( n );
660
3558118
      if( it!=subs.end() ){
661
2634837
        Trace("term-db-entail") << "...substitution is : " << it->second << std::endl;
662
2634837
        if( subsRep ){
663
348105
          Assert(d_qstate.hasTerm(it->second));
664
348105
          Assert(d_qstate.getRepresentative(it->second) == it->second);
665
2982942
          return it->second;
666
        }
667
2286732
        return getEntailedTerm2(it->second, subs, subsRep, hasSubs);
668
      }
669
    }
670
2321071
  }else if( n.getKind()==ITE ){
671
27898
    for( unsigned i=0; i<2; i++ ){
672
22745
      if (isEntailed2(n[0], subs, subsRep, hasSubs, i == 0))
673
      {
674
7752
        return getEntailedTerm2(n[i == 0 ? 1 : 2], subs, subsRep, hasSubs);
675
      }
676
    }
677
  }else{
678
2308166
    if( n.hasOperator() ){
679
2314115
      TNode f = getMatchOperator( n );
680
2301266
      if( !f.isNull() ){
681
4576834
        std::vector< TNode > args;
682
5248268
        for( unsigned i=0; i<n.getNumChildren(); i++ ){
683
7315080
          TNode c = getEntailedTerm2(n[i], subs, subsRep, hasSubs);
684
4355229
          if( c.isNull() ){
685
1395378
            return TNode::null();
686
          }
687
2959851
          c = d_qstate.getRepresentative(c);
688
2959851
          Trace("term-db-entail") << "  child " << i << " : " << c << std::endl;
689
2959851
          args.push_back( c );
690
        }
691
1786078
        TNode nn = getCongruentTerm(f, args);
692
893039
        Trace("term-db-entail") << "  got congruent term " << nn << " for " << n << std::endl;
693
893039
        return nn;
694
      }
695
    }
696
  }
697
948183
  return TNode::null();
698
}
699
700
94927
Node TermDb::evaluateTerm(TNode n,
701
                          bool useEntailmentTests,
702
                          bool reqHasTerm)
703
{
704
189854
  std::map< TNode, Node > visited;
705
189854
  std::vector<Node> exp;
706
189854
  return evaluateTerm2(n, visited, exp, useEntailmentTests, false, reqHasTerm);
707
}
708
709
Node TermDb::evaluateTerm(TNode n,
710
                          std::vector<Node>& exp,
711
                          bool useEntailmentTests,
712
                          bool reqHasTerm)
713
{
714
  std::map<TNode, Node> visited;
715
  return evaluateTerm2(n, visited, exp, useEntailmentTests, true, reqHasTerm);
716
}
717
718
860201
TNode TermDb::getEntailedTerm(TNode n,
719
                              std::map<TNode, TNode>& subs,
720
                              bool subsRep)
721
{
722
860201
  return getEntailedTerm2(n, subs, subsRep, true);
723
}
724
725
86923
TNode TermDb::getEntailedTerm(TNode n)
726
{
727
173846
  std::map< TNode, TNode > subs;
728
173846
  return getEntailedTerm2(n, subs, false, false);
729
}
730
731
1544882
bool TermDb::isEntailed2(
732
    TNode n, std::map<TNode, TNode>& subs, bool subsRep, bool hasSubs, bool pol)
733
{
734
1544882
  Trace("term-db-entail") << "Check entailed : " << n << ", pol = " << pol << std::endl;
735
1544882
  Assert(n.getType().isBoolean());
736
1544882
  if( n.getKind()==EQUAL && !n[0].getType().isBoolean() ){
737
404033
    TNode n1 = getEntailedTerm2(n[0], subs, subsRep, hasSubs);
738
334958
    if( !n1.isNull() ){
739
337825
      TNode n2 = getEntailedTerm2(n[1], subs, subsRep, hasSubs);
740
301854
      if( !n2.isNull() ){
741
265883
        if( n1==n2 ){
742
24219
          return pol;
743
        }else{
744
241664
          Assert(d_qstate.hasTerm(n1));
745
241664
          Assert(d_qstate.hasTerm(n2));
746
241664
          if( pol ){
747
122271
            return d_qstate.areEqual(n1, n2);
748
          }else{
749
119393
            return d_qstate.areDisequal(n1, n2);
750
          }
751
        }
752
      }
753
    }
754
1209924
  }else if( n.getKind()==NOT ){
755
454981
    return isEntailed2(n[0], subs, subsRep, hasSubs, !pol);
756
754943
  }else if( n.getKind()==OR || n.getKind()==AND ){
757
223794
    bool simPol = ( pol && n.getKind()==OR ) || ( !pol && n.getKind()==AND );
758
767589
    for( unsigned i=0; i<n.getNumChildren(); i++ ){
759
692815
      if (isEntailed2(n[i], subs, subsRep, hasSubs, pol))
760
      {
761
181572
        if( simPol ){
762
66832
          return true;
763
        }
764
      }else{
765
511243
        if( !simPol ){
766
82188
          return false;
767
        }
768
      }
769
    }
770
74774
    return !simPol;
771
  //Boolean equality here
772
531149
  }else if( n.getKind()==EQUAL || n.getKind()==ITE ){
773
80520
    for( unsigned i=0; i<2; i++ ){
774
67598
      if (isEntailed2(n[0], subs, subsRep, hasSubs, i == 0))
775
      {
776
29447
        unsigned ch = ( n.getKind()==EQUAL || i==0 ) ? 1 : 2;
777
29447
        bool reqPol = ( n.getKind()==ITE || i==0 ) ? pol : !pol;
778
29447
        return isEntailed2(n[ch], subs, subsRep, hasSubs, reqPol);
779
      }
780
    }
781
488780
  }else if( n.getKind()==APPLY_UF ){
782
453115
    TNode n1 = getEntailedTerm2(n, subs, subsRep, hasSubs);
783
338254
    if( !n1.isNull() ){
784
223393
      Assert(d_qstate.hasTerm(n1));
785
223393
      if( n1==d_true ){
786
        return pol;
787
223393
      }else if( n1==d_false ){
788
        return !pol;
789
      }else{
790
223393
        return d_qstate.getRepresentative(n1) == (pol ? d_true : d_false);
791
      }
792
    }
793
150526
  }else if( n.getKind()==FORALL && !pol ){
794
4807
    return isEntailed2(n[1], subs, subsRep, hasSubs, pol);
795
  }
796
342577
  return false;
797
}
798
799
1544
bool TermDb::isEntailed(TNode n, bool pol)
800
{
801
1544
  Assert(d_consistent_ee);
802
3088
  std::map< TNode, TNode > subs;
803
3088
  return isEntailed2(n, subs, false, false, pol);
804
}
805
806
270945
bool TermDb::isEntailed(TNode n,
807
                        std::map<TNode, TNode>& subs,
808
                        bool subsRep,
809
                        bool pol)
810
{
811
270945
  Assert(d_consistent_ee);
812
270945
  return isEntailed2(n, subs, subsRep, true, pol);
813
}
814
815
3975286
bool TermDb::isTermActive( Node n ) {
816
3975286
  return d_inactive_map.find( n )==d_inactive_map.end();
817
  //return !n.getAttribute(NoMatchAttribute());
818
}
819
820
165604
void TermDb::setTermInactive( Node n ) {
821
165604
  d_inactive_map[n] = true;
822
  //Trace("term-db-debug2") << "set no match attribute" << std::endl;
823
  //NoMatchAttribute nma;
824
  //n.setAttribute(nma,true);
825
165604
}
826
827
4406322
bool TermDb::hasTermCurrent( Node n, bool useMode ) {
828
4406322
  if( !useMode ){
829
    return d_has_map.find( n )!=d_has_map.end();
830
  }
831
  //some assertions are not sent to EE
832
4406322
  if (options::termDbMode() == options::TermDbMode::ALL)
833
  {
834
4406322
    return true;
835
  }
836
  else if (options::termDbMode() == options::TermDbMode::RELEVANT)
837
  {
838
    return d_has_map.find( n )!=d_has_map.end();
839
  }
840
  Assert(false) << "TermDb::hasTermCurrent: Unknown termDbMode : " << options::termDbMode();
841
  return false;
842
}
843
844
1146
bool TermDb::isTermEligibleForInstantiation(TNode n, TNode f)
845
{
846
1146
  if( options::instMaxLevel()!=-1 ){
847
970
    if( n.hasAttribute(InstLevelAttribute()) ){
848
      int64_t fml =
849
970
          f.isNull() ? -1 : d_qreg.getQuantAttributes().getQuantInstLevel(f);
850
970
      unsigned ml = fml>=0 ? fml : options::instMaxLevel();
851
852
970
      if( n.getAttribute(InstLevelAttribute())>ml ){
853
        Trace("inst-add-debug") << "Term " << n << " has instantiation level " << n.getAttribute(InstLevelAttribute());
854
        Trace("inst-add-debug") << ", which is more than maximum allowed level " << ml << " for this quantified formula." << std::endl;
855
        return false;
856
      }
857
    }else{
858
      if( options::instLevelInputOnly() ){
859
        Trace("inst-add-debug") << "Term " << n << " does not have an instantiation level." << std::endl;
860
        return false;
861
      }
862
    }
863
  }
864
  // it cannot have instantiation constants, which originate from
865
  // counterexample-guided instantiation strategies.
866
1146
  return !TermUtil::hasInstConstAttr(n);
867
}
868
869
176
Node TermDb::getEligibleTermInEqc( TNode r ) {
870
176
  if( isTermEligibleForInstantiation( r, TNode::null() ) ){
871
176
    return r;
872
  }else{
873
    std::map< Node, Node >::iterator it = d_term_elig_eqc.find( r );
874
    if( it==d_term_elig_eqc.end() ){
875
      Node h;
876
      eq::EqualityEngine* ee = d_qstate.getEqualityEngine();
877
      eq::EqClassIterator eqc_i = eq::EqClassIterator(r, ee);
878
      while (!eqc_i.isFinished())
879
      {
880
        TNode n = (*eqc_i);
881
        ++eqc_i;
882
        if (isTermEligibleForInstantiation(n, TNode::null()))
883
        {
884
          h = n;
885
          break;
886
        }
887
      }
888
      d_term_elig_eqc[r] = h;
889
      return h;
890
    }else{
891
      return it->second;
892
    }
893
  }
894
}
895
896
27154
bool TermDb::resetInternal(Theory::Effort e)
897
{
898
  // do nothing
899
27154
  return true;
900
}
901
902
27154
bool TermDb::finishResetInternal(Theory::Effort e)
903
{
904
  // do nothing
905
27154
  return true;
906
}
907
908
363336
void TermDb::addTermInternal(Node n)
909
{
910
  // do nothing
911
363336
}
912
913
84479
void TermDb::getOperatorsFor(TNode f, std::vector<TNode>& ops)
914
{
915
84479
  ops.push_back(f);
916
84479
}
917
918
void TermDb::setHasTerm( Node n ) {
919
  Trace("term-db-debug2") << "hasTerm : " << n  << std::endl;
920
  if( d_has_map.find( n )==d_has_map.end() ){
921
    d_has_map[n] = true;
922
    for( unsigned i=0; i<n.getNumChildren(); i++ ){
923
      setHasTerm( n[i] );
924
    }
925
  }
926
}
927
928
8198
void TermDb::presolve() {
929
8198
  if (options::incrementalSolving() && !options::termDbCd())
930
  {
931
    d_termsContext.pop();
932
    d_termsContext.push();
933
  }
934
8198
}
935
936
28088
bool TermDb::reset( Theory::Effort effort ){
937
28088
  d_op_nonred_count.clear();
938
28088
  d_arg_reps.clear();
939
28088
  d_func_map_trie.clear();
940
28088
  d_func_map_eqc_trie.clear();
941
28088
  d_func_map_rel_dom.clear();
942
28088
  d_consistent_ee = true;
943
944
28088
  eq::EqualityEngine* ee = d_qstate.getEqualityEngine();
945
946
28088
  Assert(ee->consistent());
947
  // if higher-order, add equalities for the purification terms now
948
28088
  if (!resetInternal(effort))
949
  {
950
    return false;
951
  }
952
953
  //compute has map
954
28088
  if (options::termDbMode() == options::TermDbMode::RELEVANT)
955
  {
956
    d_has_map.clear();
957
    d_term_elig_eqc.clear();
958
    eq::EqClassesIterator eqcs_i = eq::EqClassesIterator( ee );
959
    while( !eqcs_i.isFinished() ){
960
      TNode r = (*eqcs_i);
961
      bool addedFirst = false;
962
      Node first;
963
      //TODO: ignoring singleton eqc isn't enough, need to ensure eqc are relevant
964
      eq::EqClassIterator eqc_i = eq::EqClassIterator(r, ee);
965
      while( !eqc_i.isFinished() ){
966
        TNode n = (*eqc_i);
967
        if( first.isNull() ){
968
          first = n;
969
        }else{
970
          if( !addedFirst ){
971
            addedFirst = true;
972
            setHasTerm( first );
973
          }
974
          setHasTerm( n );
975
        }
976
        ++eqc_i;
977
      }
978
      ++eqcs_i;
979
    }
980
    const LogicInfo& logicInfo = d_qstate.getLogicInfo();
981
    for (TheoryId theoryId = THEORY_FIRST; theoryId < THEORY_LAST; ++theoryId)
982
    {
983
      if (!logicInfo.isTheoryEnabled(theoryId))
984
      {
985
        continue;
986
      }
987
      for (context::CDList<Assertion>::const_iterator
988
               it = d_qstate.factsBegin(theoryId),
989
               it_end = d_qstate.factsEnd(theoryId);
990
           it != it_end;
991
           ++it)
992
      {
993
        setHasTerm((*it).d_assertion);
994
      }
995
    }
996
  }
997
  // finish reset
998
28088
  return finishResetInternal(effort);
999
}
1000
1001
20614
TNodeTrie* TermDb::getTermArgTrie(Node f)
1002
{
1003
20614
  f = getOperatorRepresentative(f);
1004
20614
  computeUfTerms( f );
1005
20614
  std::map<Node, TNodeTrie>::iterator itut = d_func_map_trie.find(f);
1006
20614
  if( itut!=d_func_map_trie.end() ){
1007
12282
    return &itut->second;
1008
  }else{
1009
8332
    return NULL;
1010
  }
1011
}
1012
1013
1765659
TNodeTrie* TermDb::getTermArgTrie(Node eqc, Node f)
1014
{
1015
1765659
  f = getOperatorRepresentative(f);
1016
1765659
  computeUfEqcTerms( f );
1017
1765659
  std::map<Node, TNodeTrie>::iterator itut = d_func_map_eqc_trie.find(f);
1018
1765659
  if( itut==d_func_map_eqc_trie.end() ){
1019
    return NULL;
1020
  }else{
1021
1765659
    if( eqc.isNull() ){
1022
906524
      return &itut->second;
1023
    }else{
1024
      std::map<TNode, TNodeTrie>::iterator itute =
1025
859135
          itut->second.d_data.find(eqc);
1026
859135
      if( itute!=itut->second.d_data.end() ){
1027
511809
        return &itute->second;
1028
      }else{
1029
347326
        return NULL;
1030
      }
1031
    }
1032
  }
1033
}
1034
1035
TNode TermDb::getCongruentTerm( Node f, Node n ) {
1036
  f = getOperatorRepresentative(f);
1037
  computeUfTerms( f );
1038
  std::map<Node, TNodeTrie>::iterator itut = d_func_map_trie.find(f);
1039
  if( itut!=d_func_map_trie.end() ){
1040
    computeArgReps( n );
1041
    return itut->second.existsTerm( d_arg_reps[n] );
1042
  }else{
1043
    return TNode::null();
1044
  }
1045
}
1046
1047
963321
TNode TermDb::getCongruentTerm( Node f, std::vector< TNode >& args ) {
1048
963321
  f = getOperatorRepresentative(f);
1049
963321
  computeUfTerms( f );
1050
963321
  return d_func_map_trie[f].existsTerm( args );
1051
}
1052
1053
}  // namespace quantifiers
1054
}  // namespace theory
1055
29502
}  // namespace cvc5