GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/quantifiers/term_database.cpp Lines: 460 571 80.6 %
Date: 2021-09-13 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
9917
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
9917
      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
19834
      d_inactive_map(qs.getSatContext())
53
{
54
9917
  d_consistent_ee = true;
55
9917
  d_true = NodeManager::currentNM()->mkConst(true);
56
9917
  d_false = NodeManager::currentNM()->mkConst(false);
57
9917
  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
9917
}
64
65
19638
TermDb::~TermDb(){
66
67
19638
}
68
69
9917
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
463510
size_t TermDb::getNumGroundTerms(Node f) const
90
{
91
463510
  NodeDbListMap::const_iterator it = d_opMap.find(f);
92
463510
  if (it != d_opMap.end())
93
  {
94
446144
    return it->second->d_list.size();
95
  }
96
17366
  return 0;
97
}
98
99
2999293
Node TermDb::getGroundTerm(Node f, size_t i) const
100
{
101
2999293
  NodeDbListMap::const_iterator it = d_opMap.find(f);
102
2999293
  if (it != d_opMap.end())
103
  {
104
2999293
    Assert(i < it->second->d_list.size());
105
2999293
    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
4298685
Node TermDb::getMatchOperator( Node n ) {
177
4298685
  Kind k = n.getKind();
178
  //datatype operators may be parametric, always assume they are
179
4298685
  if (k == SELECT || k == STORE || k == UNION || k == INTERSECTION
180
4266705
      || k == SUBSET || k == SETMINUS || k == MEMBER || k == SINGLETON
181
4237801
      || k == APPLY_SELECTOR_TOTAL || k == APPLY_SELECTOR || k == APPLY_TESTER
182
4112421
      || k == SEP_PTO || k == HO_APPLY || k == SEQ_NTH)
183
  {
184
    //since it is parametric, use a particular one as op
185
412438
    TypeNode tn = n[0].getType();
186
412438
    Node op = n.getOperator();
187
206219
    std::map< Node, std::map< TypeNode, Node > >::iterator ito = d_par_op_map.find( op );
188
206219
    if( ito!=d_par_op_map.end() ){
189
197834
      std::map< TypeNode, Node >::iterator it = ito->second.find( tn );
190
197834
      if( it!=ito->second.end() ){
191
197152
        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
4092466
  else if (inst::TriggerTermInfo::isAtomicTriggerKind(k))
199
  {
200
3892484
    return n.getOperator();
201
  }else{
202
199982
    return Node::null();
203
  }
204
}
205
206
2536983
void TermDb::addTerm(Node n)
207
{
208
2536983
  if (d_processed.find(n) != d_processed.end())
209
  {
210
1515166
    return;
211
  }
212
1021817
  d_processed.insert(n);
213
1021817
  if (!TermUtil::hasInstConstAttr(n))
214
  {
215
982517
    Trace("term-db-debug") << "register term : " << n << std::endl;
216
982517
    DbList* dlt = getOrMkDbListForType(n.getType());
217
982517
    dlt->d_list.push_back(n);
218
    // if this is an atomic trigger, consider adding it
219
982517
    if (inst::TriggerTermInfo::isAtomicTrigger(n))
220
    {
221
405718
      Trace("term-db") << "register term in db " << n << std::endl;
222
223
811436
      Node op = getMatchOperator(n);
224
405718
      Trace("term-db-debug") << "  match operator is : " << op << std::endl;
225
405718
      DbList* dlo = getOrMkDbListForOp(op);
226
405718
      dlo->d_list.push_back(n);
227
      // If we are higher-order, we may need to register more terms.
228
405718
      addTermInternal(n);
229
    }
230
  }
231
  else
232
  {
233
39300
    setTermInactive(n);
234
  }
235
1021817
  if (!n.isClosure())
236
  {
237
2646883
    for (const Node& nc : n)
238
    {
239
1625088
      addTerm(nc);
240
    }
241
  }
242
}
243
244
982517
DbList* TermDb::getOrMkDbListForType(TypeNode tn)
245
{
246
982517
  TypeNodeDbListMap::iterator it = d_typeMap.find(tn);
247
982517
  if (it != d_typeMap.end())
248
  {
249
957734
    return it->second.get();
250
  }
251
49566
  std::shared_ptr<DbList> dl = std::make_shared<DbList>(d_termsContextUse);
252
24783
  d_typeMap.insert(tn, dl);
253
24783
  return dl.get();
254
}
255
256
465435
DbList* TermDb::getOrMkDbListForOp(TNode op)
257
{
258
465435
  NodeDbListMap::iterator it = d_opMap.find(op);
259
465435
  if (it != d_opMap.end())
260
  {
261
371347
    return it->second.get();
262
  }
263
188176
  std::shared_ptr<DbList> dl = std::make_shared<DbList>(d_termsContextUse);
264
94088
  d_opMap.insert(op, dl);
265
94088
  Assert(op.getKind() != BOUND_VARIABLE);
266
94088
  d_ops.push_back(op);
267
94088
  return dl.get();
268
}
269
270
591824
void TermDb::computeArgReps( TNode n ) {
271
591824
  if (d_arg_reps.find(n) == d_arg_reps.end())
272
  {
273
354069
    eq::EqualityEngine* ee = d_qstate.getEqualityEngine();
274
1115416
    for (const TNode& nc : n)
275
    {
276
1522694
      TNode r = ee->hasTerm(nc) ? ee->getRepresentative(nc) : nc;
277
761347
      d_arg_reps[n].push_back( r );
278
    }
279
  }
280
591824
}
281
282
1765658
void TermDb::computeUfEqcTerms( TNode f ) {
283
1765658
  Assert(f == getOperatorRepresentative(f));
284
1765658
  if (d_func_map_eqc_trie.find(f) != d_func_map_eqc_trie.end())
285
  {
286
1719344
    return;
287
  }
288
46314
  d_func_map_eqc_trie[f].clear();
289
  // get the matchable operators in the equivalence class of f
290
92628
  std::vector<TNode> ops;
291
46314
  getOperatorsFor(f, ops);
292
46314
  eq::EqualityEngine* ee = d_qstate.getEqualityEngine();
293
92725
  for (TNode ff : ops)
294
  {
295
46411
    DbList* dbl = getOrMkDbListForOp(ff);
296
345300
    for (const Node& n : dbl->d_list)
297
    {
298
298889
      if (hasTermCurrent(n) && isTermActive(n))
299
      {
300
282691
        computeArgReps(n);
301
565382
        TNode r = ee->hasTerm(n) ? ee->getRepresentative(n) : TNode(n);
302
282691
        d_func_map_eqc_trie[f].d_data[r].addTerm(n, d_arg_reps[n]);
303
      }
304
    }
305
  }
306
}
307
308
3168121
void TermDb::computeUfTerms( TNode f ) {
309
3168121
  if (d_op_nonred_count.find(f) != d_op_nonred_count.end())
310
  {
311
    // already computed
312
6253859
    return;
313
  }
314
41197
  Assert(f == getOperatorRepresentative(f));
315
41197
  d_op_nonred_count[f] = 0;
316
  // get the matchable operators in the equivalence class of f
317
82383
  std::vector<TNode> ops;
318
41197
  getOperatorsFor(f, ops);
319
41197
  Trace("term-db-debug") << "computeUfTerms for " << f << std::endl;
320
41197
  unsigned congruentCount = 0;
321
41197
  unsigned nonCongruentCount = 0;
322
41197
  unsigned alreadyCongruentCount = 0;
323
41197
  unsigned relevantCount = 0;
324
41197
  NodeManager* nm = NodeManager::currentNM();
325
76822
  for (TNode ff : ops)
326
  {
327
41283
    NodeDbListMap::iterator it = d_opMap.find(ff);
328
41283
    if (it == d_opMap.end())
329
    {
330
      // no terms for this operator
331
5647
      continue;
332
    }
333
35636
    Trace("term-db-debug") << "Adding terms for operator " << ff << std::endl;
334
362833
    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
327208
      if (!hasTermCurrent(n) || !d_qstate.hasTerm(n))
338
      {
339
        Trace("term-db-debug") << n << " is not relevant." << std::endl;
340
85255
        continue;
341
      }
342
343
327208
      relevantCount++;
344
345283
      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
309133
      computeArgReps(n);
352
309133
      Trace("term-db-debug") << "Adding term " << n << " with arg reps : ";
353
975567
      for (unsigned i = 0, size = d_arg_reps[n].size(); i < size; i++)
354
      {
355
666434
        Trace("term-db-debug") << d_arg_reps[n][i] << " ";
356
2665736
        if (std::find(d_func_map_rel_dom[f][i].begin(),
357
1332868
                      d_func_map_rel_dom[f][i].end(),
358
2665736
                      d_arg_reps[n][i])
359
1999302
            == d_func_map_rel_dom[f][i].end())
360
        {
361
241570
          d_func_map_rel_dom[f][i].push_back(d_arg_reps[n][i]);
362
        }
363
      }
364
309133
      Trace("term-db-debug") << std::endl;
365
309133
      Assert(d_qstate.hasTerm(n));
366
618266
      Trace("term-db-debug")
367
309133
          << "  and value : " << d_qstate.getRepresentative(n) << std::endl;
368
551075
      Node at = d_func_map_trie[f].addOrGetTerm(n, d_arg_reps[n]);
369
309133
      Assert(d_qstate.hasTerm(at));
370
309133
      Trace("term-db-debug2") << "...add term returned " << at << std::endl;
371
376313
      if (at != n && d_qstate.areEqual(at, n))
372
      {
373
67180
        setTermInactive(n);
374
67180
        Trace("term-db-debug") << n << " is redundant." << std::endl;
375
67180
        congruentCount++;
376
67180
        continue;
377
      }
378
483895
      std::vector<Node> lits;
379
241953
      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
241942
      nonCongruentCount++;
408
241942
      d_op_nonred_count[f]++;
409
    }
410
35625
    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
6243042
Node TermDb::getOperatorRepresentative(TNode op) const { return op; }
425
426
233901
bool TermDb::checkCongruentDisequal(TNode a, TNode b, std::vector<Node>& exp)
427
{
428
233901
  if (d_qstate.areDisequal(a, b))
429
  {
430
11
    exp.push_back(a.eqNode(b));
431
11
    return true;
432
  }
433
233890
  return false;
434
}
435
436
2183061
bool TermDb::inRelevantDomain( TNode f, unsigned i, TNode r ) {
437
  // notice if we are not higher-order, getOperatorRepresentative is a no-op
438
2183061
  f = getOperatorRepresentative(f);
439
2183061
  computeUfTerms( f );
440
2183061
  Assert(!d_qstate.getEqualityEngine()->hasTerm(r)
441
         || d_qstate.getEqualityEngine()->getRepresentative(r) == r);
442
2183061
  std::map< Node, std::map< unsigned, std::vector< Node > > >::iterator it = d_func_map_rel_dom.find( f );
443
2183061
  if( it != d_func_map_rel_dom.end() ){
444
2158684
    std::map< unsigned, std::vector< Node > >::iterator it2 = it->second.find( i );
445
2158684
    if( it2!=it->second.end() ){
446
2158684
      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
615400
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
615400
  std::map< TNode, Node >::iterator itv = visited.find( n );
463
615400
  if( itv != visited.end() ){
464
47647
    return itv->second;
465
  }
466
567753
  size_t prevSize = exp.size();
467
567753
  Trace("term-db-eval") << "evaluate term : " << n << std::endl;
468
1135506
  Node ret = n;
469
567753
  if( n.getKind()==FORALL || n.getKind()==BOUND_VARIABLE ){
470
    //do nothing
471
  }
472
565293
  else if (d_qstate.hasTerm(n))
473
  {
474
266564
    Trace("term-db-eval") << "...exists in ee, return rep" << std::endl;
475
266564
    ret = d_qstate.getRepresentative(n);
476
266564
    if (computeExp)
477
    {
478
      if (n != ret)
479
      {
480
        exp.push_back(n.eqNode(ret));
481
      }
482
    }
483
266564
    reqHasTerm = false;
484
  }
485
298729
  else if (n.hasOperator())
486
  {
487
596588
    std::vector<TNode> args;
488
298294
    bool ret_set = false;
489
298294
    Kind k = n.getKind();
490
596588
    std::vector<Node> tempExp;
491
687943
    for (unsigned i = 0, nchild = n.getNumChildren(); i < nchild; i++)
492
    {
493
1032222
      TNode c = evaluateTerm2(n[i],
494
                              visited,
495
                              tempExp,
496
                              useEntailmentTests,
497
                              computeExp,
498
905760
                              reqHasTerm);
499
516111
      if (c.isNull())
500
      {
501
89469
        ret = Node::null();
502
89469
        ret_set = true;
503
89469
        break;
504
      }
505
426642
      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
389649
      if (computeExp)
529
      {
530
        exp.insert(exp.end(), tempExp.begin(), tempExp.end());
531
      }
532
389649
      Trace("term-db-eval") << "  child " << i << " : " << c << std::endl;
533
389649
      args.push_back(c);
534
    }
535
298294
    if (ret_set)
536
    {
537
      // if we short circuited
538
126462
      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
343664
      TNode f = getMatchOperator(n);
548
      // if it is an indexed term, return the congruent term
549
171832
      if (!f.isNull())
550
      {
551
        // if f is congruent to a term indexed by this class
552
141322
        TNode nn = getCongruentTerm(f, args);
553
141322
        Trace("term-db-eval") << "  got congruent term " << nn
554
70661
                              << " from DB for " << n << std::endl;
555
70661
        if (!nn.isNull())
556
        {
557
29168
          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
29168
          ret = d_qstate.getRepresentative(nn);
569
29168
          Trace("term-db-eval") << "return rep" << std::endl;
570
29168
          ret_set = true;
571
29168
          reqHasTerm = false;
572
29168
          Assert(!ret.isNull());
573
29168
          if (computeExp)
574
          {
575
            if (n != ret)
576
            {
577
              exp.push_back(nn.eqNode(ret));
578
            }
579
          }
580
        }
581
      }
582
171832
      if( !ret_set ){
583
142664
        Trace("term-db-eval") << "return rewrite" << std::endl;
584
        // a theory symbol or a new UF term
585
142664
        if (n.getMetaKind() == metakind::PARAMETERIZED)
586
        {
587
41355
          args.insert(args.begin(), n.getOperator());
588
        }
589
142664
        ret = NodeManager::currentNM()->mkNode(n.getKind(), args);
590
142664
        ret = Rewriter::rewrite(ret);
591
142664
        if (ret.getKind() == EQUAL)
592
        {
593
16690
          if (d_qstate.areDisequal(ret[0], ret[1]))
594
          {
595
4852
            ret = d_false;
596
          }
597
        }
598
142664
        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
567753
  if (reqHasTerm && !ret.isNull())
625
  {
626
140743
    Kind k = ret.getKind();
627
140743
    if (k != OR && k != AND && k != EQUAL && k != ITE && k != NOT
628
126209
        && k != FORALL)
629
    {
630
126020
      if (!d_qstate.hasTerm(ret))
631
      {
632
39278
        ret = Node::null();
633
      }
634
    }
635
  }
636
1135506
  Trace("term-db-eval") << "evaluated term : " << n << ", got : " << ret
637
567753
                        << ", reqHasTerm = " << reqHasTerm << std::endl;
638
  // clear the explanation if failed
639
567753
  if (computeExp && ret.isNull())
640
  {
641
    exp.resize(prevSize);
642
  }
643
567753
  visited[n] = ret;
644
567753
  return ret;
645
}
646
647
8574904
TNode TermDb::getEntailedTerm2(TNode n,
648
                               std::map<TNode, TNode>& subs,
649
                               bool subsRep,
650
                               bool hasSubs)
651
{
652
8574904
  Trace("term-db-entail") << "get entailed term : " << n << std::endl;
653
8574904
  if (d_qstate.hasTerm(n))
654
  {
655
2693819
    Trace("term-db-entail") << "...exists in ee, return rep " << std::endl;
656
2693819
    return n;
657
5881085
  }else if( n.getKind()==BOUND_VARIABLE ){
658
3559223
    if( hasSubs ){
659
3559223
      std::map< TNode, TNode >::iterator it = subs.find( n );
660
3559223
      if( it!=subs.end() ){
661
2635942
        Trace("term-db-entail") << "...substitution is : " << it->second << std::endl;
662
2635942
        if( subsRep ){
663
348105
          Assert(d_qstate.hasTerm(it->second));
664
348105
          Assert(d_qstate.getRepresentative(it->second) == it->second);
665
2984047
          return it->second;
666
        }
667
2287837
        return getEntailedTerm2(it->second, subs, subsRep, hasSubs);
668
      }
669
    }
670
2321862
  }else if( n.getKind()==ITE ){
671
27895
    for( unsigned i=0; i<2; i++ ){
672
22743
      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
2308958
    if( n.hasOperator() ){
679
2314907
      TNode f = getMatchOperator( n );
680
2302058
      if( !f.isNull() ){
681
4578418
        std::vector< TNode > args;
682
5250520
        for( unsigned i=0; i<n.getNumChildren(); i++ ){
683
7318046
          TNode c = getEntailedTerm2(n[i], subs, subsRep, hasSubs);
684
4356735
          if( c.isNull() ){
685
1395424
            return TNode::null();
686
          }
687
2961311
          c = d_qstate.getRepresentative(c);
688
2961311
          Trace("term-db-entail") << "  child " << i << " : " << c << std::endl;
689
2961311
          args.push_back( c );
690
        }
691
1787570
        TNode nn = getCongruentTerm(f, args);
692
893785
        Trace("term-db-entail") << "  got congruent term " << nn << " for " << n << std::endl;
693
893785
        return nn;
694
      }
695
    }
696
  }
697
948182
  return TNode::null();
698
}
699
700
95088
Node TermDb::evaluateTerm(TNode n,
701
                          bool useEntailmentTests,
702
                          bool reqHasTerm)
703
{
704
190176
  std::map< TNode, Node > visited;
705
190176
  std::vector<Node> exp;
706
190176
  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
1545074
bool TermDb::isEntailed2(
732
    TNode n, std::map<TNode, TNode>& subs, bool subsRep, bool hasSubs, bool pol)
733
{
734
1545074
  Trace("term-db-entail") << "Check entailed : " << n << ", pol = " << pol << std::endl;
735
1545074
  Assert(n.getType().isBoolean());
736
1545074
  if( n.getKind()==EQUAL && !n[0].getType().isBoolean() ){
737
404375
    TNode n1 = getEntailedTerm2(n[0], subs, subsRep, hasSubs);
738
335152
    if( !n1.isNull() ){
739
338171
      TNode n2 = getEntailedTerm2(n[1], subs, subsRep, hasSubs);
740
302050
      if( !n2.isNull() ){
741
265929
        if( n1==n2 ){
742
24222
          return pol;
743
        }else{
744
241707
          Assert(d_qstate.hasTerm(n1));
745
241707
          Assert(d_qstate.hasTerm(n2));
746
241707
          if( pol ){
747
122280
            return d_qstate.areEqual(n1, n2);
748
          }else{
749
119427
            return d_qstate.areDisequal(n1, n2);
750
          }
751
        }
752
      }
753
    }
754
1209922
  }else if( n.getKind()==NOT ){
755
454981
    return isEntailed2(n[0], subs, subsRep, hasSubs, !pol);
756
754941
  }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
531147
  }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
488778
  }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
150524
  }else if( n.getKind()==FORALL && !pol ){
794
4807
    return isEntailed2(n[1], subs, subsRep, hasSubs, pol);
795
  }
796
342723
  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
271139
bool TermDb::isEntailed(TNode n,
807
                        std::map<TNode, TNode>& subs,
808
                        bool subsRep,
809
                        bool pol)
810
{
811
271139
  Assert(d_consistent_ee);
812
271139
  return isEntailed2(n, subs, subsRep, true, pol);
813
}
814
815
3975311
bool TermDb::isTermActive( Node n ) {
816
3975311
  return d_inactive_map.find( n )==d_inactive_map.end();
817
  //return !n.getAttribute(NoMatchAttribute());
818
}
819
820
165683
void TermDb::setTermInactive( Node n ) {
821
165683
  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
165683
}
826
827
4406915
bool TermDb::hasTermCurrent( Node n, bool useMode ) {
828
4406915
  if( !useMode ){
829
    return d_has_map.find( n )!=d_has_map.end();
830
  }
831
  //some assertions are not sent to EE
832
4406915
  if (options::termDbMode() == options::TermDbMode::ALL)
833
  {
834
4406915
    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
27155
bool TermDb::resetInternal(Theory::Effort e)
897
{
898
  // do nothing
899
27155
  return true;
900
}
901
902
27155
bool TermDb::finishResetInternal(Theory::Effort e)
903
{
904
  // do nothing
905
27155
  return true;
906
}
907
908
363431
void TermDb::addTermInternal(Node n)
909
{
910
  // do nothing
911
363431
}
912
913
84481
void TermDb::getOperatorsFor(TNode f, std::vector<TNode>& ops)
914
{
915
84481
  ops.push_back(f);
916
84481
}
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
8200
void TermDb::presolve() {
929
8200
  if (options::incrementalSolving() && !options::termDbCd())
930
  {
931
    d_termsContext.pop();
932
    d_termsContext.push();
933
  }
934
8200
}
935
936
28089
bool TermDb::reset( Theory::Effort effort ){
937
28089
  d_op_nonred_count.clear();
938
28089
  d_arg_reps.clear();
939
28089
  d_func_map_trie.clear();
940
28089
  d_func_map_eqc_trie.clear();
941
28089
  d_func_map_rel_dom.clear();
942
28089
  d_consistent_ee = true;
943
944
28089
  eq::EqualityEngine* ee = d_qstate.getEqualityEngine();
945
946
28089
  Assert(ee->consistent());
947
  // if higher-order, add equalities for the purification terms now
948
28089
  if (!resetInternal(effort))
949
  {
950
    return false;
951
  }
952
953
  //compute has map
954
28089
  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
28089
  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
1765658
TNodeTrie* TermDb::getTermArgTrie(Node eqc, Node f)
1014
{
1015
1765658
  f = getOperatorRepresentative(f);
1016
1765658
  computeUfEqcTerms( f );
1017
1765658
  std::map<Node, TNodeTrie>::iterator itut = d_func_map_eqc_trie.find(f);
1018
1765658
  if( itut==d_func_map_eqc_trie.end() ){
1019
    return NULL;
1020
  }else{
1021
1765658
    if( eqc.isNull() ){
1022
906530
      return &itut->second;
1023
    }else{
1024
      std::map<TNode, TNodeTrie>::iterator itute =
1025
859128
          itut->second.d_data.find(eqc);
1026
859128
      if( itute!=itut->second.d_data.end() ){
1027
511804
        return &itute->second;
1028
      }else{
1029
347324
        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
964446
TNode TermDb::getCongruentTerm( Node f, std::vector< TNode >& args ) {
1048
964446
  f = getOperatorRepresentative(f);
1049
964446
  computeUfTerms( f );
1050
964446
  return d_func_map_trie[f].existsTerm( args );
1051
}
1052
1053
}  // namespace quantifiers
1054
}  // namespace theory
1055
29514
}  // namespace cvc5