GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/quantifiers/term_database.cpp Lines: 460 571 80.6 %
Date: 2021-09-17 Branches: 1025 2442 42.0 %

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
9942
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
9942
      d_termsContextUse(options::termDbCd() ? context() : &d_termsContext),
47
      d_processed(d_termsContextUse),
48
      d_typeMap(d_termsContextUse),
49
      d_ops(d_termsContextUse),
50
      d_opMap(d_termsContextUse),
51
19884
      d_inactive_map(context())
52
{
53
9942
  d_consistent_ee = true;
54
9942
  d_true = NodeManager::currentNM()->mkConst(true);
55
9942
  d_false = NodeManager::currentNM()->mkConst(false);
56
9942
  if (!options::termDbCd())
57
  {
58
    // when not maintaining terms in a context-dependent manner, we clear during
59
    // each presolve, which requires maintaining a single outermost level
60
    d_termsContext.push();
61
  }
62
9942
}
63
64
19688
TermDb::~TermDb(){
65
66
19688
}
67
68
9942
void TermDb::finishInit(QuantifiersInferenceManager* qim) { d_qim = qim; }
69
70
25076
void TermDb::registerQuantifier( Node q ) {
71
25076
  Assert(q[0].getNumChildren() == d_qreg.getNumInstantiationConstants(q));
72
84383
  for (size_t i = 0, nvars = q[0].getNumChildren(); i < nvars; i++)
73
  {
74
118614
    Node ic = d_qreg.getInstantiationConstant(q, i);
75
59307
    setTermInactive( ic );
76
  }
77
25076
}
78
79
920
size_t TermDb::getNumOperators() const { return d_ops.size(); }
80
81
2134
Node TermDb::getOperator(size_t i) const
82
{
83
2134
  Assert(i < d_ops.size());
84
2134
  return d_ops[i];
85
}
86
87
/** ground terms */
88
481192
size_t TermDb::getNumGroundTerms(Node f) const
89
{
90
481192
  NodeDbListMap::const_iterator it = d_opMap.find(f);
91
481192
  if (it != d_opMap.end())
92
  {
93
463826
    return it->second->d_list.size();
94
  }
95
17366
  return 0;
96
}
97
98
3007924
Node TermDb::getGroundTerm(Node f, size_t i) const
99
{
100
3007924
  NodeDbListMap::const_iterator it = d_opMap.find(f);
101
3007924
  if (it != d_opMap.end())
102
  {
103
3007924
    Assert(i < it->second->d_list.size());
104
3007924
    return it->second->d_list[i];
105
  }
106
  Assert(false);
107
  return Node::null();
108
}
109
110
256
size_t TermDb::getNumTypeGroundTerms(TypeNode tn) const
111
{
112
256
  TypeNodeDbListMap::const_iterator it = d_typeMap.find(tn);
113
256
  if (it != d_typeMap.end())
114
  {
115
247
    return it->second->d_list.size();
116
  }
117
9
  return 0;
118
}
119
120
10213
Node TermDb::getTypeGroundTerm(TypeNode tn, size_t i) const
121
{
122
10213
  TypeNodeDbListMap::const_iterator it = d_typeMap.find(tn);
123
10213
  if (it != d_typeMap.end())
124
  {
125
10213
    Assert(i < it->second->d_list.size());
126
10213
    return it->second->d_list[i];
127
  }
128
  Assert(false);
129
  return Node::null();
130
}
131
132
2488
Node TermDb::getOrMakeTypeGroundTerm(TypeNode tn, bool reqVar)
133
{
134
2488
  TypeNodeDbListMap::const_iterator it = d_typeMap.find(tn);
135
2488
  if (it != d_typeMap.end())
136
  {
137
519
    Assert(!it->second->d_list.empty());
138
519
    if (!reqVar)
139
    {
140
186
      return it->second->d_list[0];
141
    }
142
522
    for (const Node& v : it->second->d_list)
143
    {
144
467
      if (v.isVar())
145
      {
146
278
        return v;
147
      }
148
    }
149
  }
150
2024
  return getOrMakeTypeFreshVariable(tn);
151
}
152
153
2024
Node TermDb::getOrMakeTypeFreshVariable(TypeNode tn)
154
{
155
2024
  std::unordered_map<TypeNode, Node>::iterator it = d_type_fv.find(tn);
156
2024
  if (it == d_type_fv.end())
157
  {
158
240
    SkolemManager* sm = NodeManager::currentNM()->getSkolemManager();
159
480
    std::stringstream ss;
160
240
    ss << language::SetLanguage(options::outputLanguage());
161
240
    ss << "e_" << tn;
162
480
    Node k = sm->mkDummySkolem(ss.str(), tn, "is a termDb fresh variable");
163
480
    Trace("mkVar") << "TermDb:: Make variable " << k << " : " << tn
164
240
                   << std::endl;
165
240
    if (options::instMaxLevel() != -1)
166
    {
167
      QuantAttributes::setInstantiationLevelAttr(k, 0);
168
    }
169
240
    d_type_fv[tn] = k;
170
240
    return k;
171
  }
172
1784
  return it->second;
173
}
174
175
4398642
Node TermDb::getMatchOperator( Node n ) {
176
4398642
  Kind k = n.getKind();
177
  //datatype operators may be parametric, always assume they are
178
4398642
  if (k == SELECT || k == STORE || k == UNION || k == INTERSECTION
179
4299393
      || k == SUBSET || k == SETMINUS || k == MEMBER || k == SINGLETON
180
4270465
      || k == APPLY_SELECTOR_TOTAL || k == APPLY_SELECTOR || k == APPLY_TESTER
181
4145160
      || k == SEP_PTO || k == HO_APPLY || k == SEQ_NTH || k == STRING_LENGTH)
182
  {
183
    //since it is parametric, use a particular one as op
184
614900
    TypeNode tn = n[0].getType();
185
614900
    Node op = n.getOperator();
186
307450
    std::map< Node, std::map< TypeNode, Node > >::iterator ito = d_par_op_map.find( op );
187
307450
    if( ito!=d_par_op_map.end() ){
188
298239
      std::map< TypeNode, Node >::iterator it = ito->second.find( tn );
189
298239
      if( it!=ito->second.end() ){
190
297542
        return it->second;
191
      }
192
    }
193
9908
    Trace("par-op") << "Parametric operator : " << k << ", " << n.getOperator() << ", " << tn << " : " << n << std::endl;
194
9908
    d_par_op_map[op][tn] = n;
195
9908
    return n;
196
  }
197
4091192
  else if (inst::TriggerTermInfo::isAtomicTriggerKind(k))
198
  {
199
3891341
    return n.getOperator();
200
  }else{
201
199851
    return Node::null();
202
  }
203
}
204
205
2542600
void TermDb::addTerm(Node n)
206
{
207
2542600
  if (d_processed.find(n) != d_processed.end())
208
  {
209
1519126
    return;
210
  }
211
1023474
  d_processed.insert(n);
212
1023474
  if (!TermUtil::hasInstConstAttr(n))
213
  {
214
984062
    Trace("term-db-debug") << "register term : " << n << std::endl;
215
984062
    DbList* dlt = getOrMkDbListForType(n.getType());
216
984062
    dlt->d_list.push_back(n);
217
    // if this is an atomic trigger, consider adding it
218
984062
    if (inst::TriggerTermInfo::isAtomicTrigger(n))
219
    {
220
407865
      Trace("term-db") << "register term in db " << n << std::endl;
221
222
815730
      Node op = getMatchOperator(n);
223
407865
      Trace("term-db-debug") << "  match operator is : " << op << std::endl;
224
407865
      DbList* dlo = getOrMkDbListForOp(op);
225
407865
      dlo->d_list.push_back(n);
226
      // If we are higher-order, we may need to register more terms.
227
407865
      addTermInternal(n);
228
    }
229
  }
230
  else
231
  {
232
39412
    setTermInactive(n);
233
  }
234
1023474
  if (!n.isClosure())
235
  {
236
2652532
    for (const Node& nc : n)
237
    {
238
1629080
      addTerm(nc);
239
    }
240
  }
241
}
242
243
984062
DbList* TermDb::getOrMkDbListForType(TypeNode tn)
244
{
245
984062
  TypeNodeDbListMap::iterator it = d_typeMap.find(tn);
246
984062
  if (it != d_typeMap.end())
247
  {
248
959276
    return it->second.get();
249
  }
250
49572
  std::shared_ptr<DbList> dl = std::make_shared<DbList>(d_termsContextUse);
251
24786
  d_typeMap.insert(tn, dl);
252
24786
  return dl.get();
253
}
254
255
467602
DbList* TermDb::getOrMkDbListForOp(TNode op)
256
{
257
467602
  NodeDbListMap::iterator it = d_opMap.find(op);
258
467602
  if (it != d_opMap.end())
259
  {
260
373491
    return it->second.get();
261
  }
262
188222
  std::shared_ptr<DbList> dl = std::make_shared<DbList>(d_termsContextUse);
263
94111
  d_opMap.insert(op, dl);
264
94111
  Assert(op.getKind() != BOUND_VARIABLE);
265
94111
  d_ops.push_back(op);
266
94111
  return dl.get();
267
}
268
269
592618
void TermDb::computeArgReps( TNode n ) {
270
592618
  if (d_arg_reps.find(n) == d_arg_reps.end())
271
  {
272
354803
    eq::EqualityEngine* ee = d_qstate.getEqualityEngine();
273
1117659
    for (const TNode& nc : n)
274
    {
275
1525712
      TNode r = ee->hasTerm(nc) ? ee->getRepresentative(nc) : nc;
276
762856
      d_arg_reps[n].push_back( r );
277
    }
278
  }
279
592618
}
280
281
1783144
void TermDb::computeUfEqcTerms( TNode f ) {
282
1783144
  Assert(f == getOperatorRepresentative(f));
283
1783144
  if (d_func_map_eqc_trie.find(f) != d_func_map_eqc_trie.end())
284
  {
285
1736810
    return;
286
  }
287
46334
  d_func_map_eqc_trie[f].clear();
288
  // get the matchable operators in the equivalence class of f
289
92668
  std::vector<TNode> ops;
290
46334
  getOperatorsFor(f, ops);
291
46334
  eq::EqualityEngine* ee = d_qstate.getEqualityEngine();
292
92765
  for (TNode ff : ops)
293
  {
294
46431
    DbList* dbl = getOrMkDbListForOp(ff);
295
345365
    for (const Node& n : dbl->d_list)
296
    {
297
298934
      if (hasTermCurrent(n) && isTermActive(n))
298
      {
299
282740
        computeArgReps(n);
300
565480
        TNode r = ee->hasTerm(n) ? ee->getRepresentative(n) : TNode(n);
301
282740
        d_func_map_eqc_trie[f].d_data[r].addTerm(n, d_arg_reps[n]);
302
      }
303
    }
304
  }
305
}
306
307
3248565
void TermDb::computeUfTerms( TNode f ) {
308
3248565
  if (d_op_nonred_count.find(f) != d_op_nonred_count.end())
309
  {
310
    // already computed
311
6414647
    return;
312
  }
313
41247
  Assert(f == getOperatorRepresentative(f));
314
41247
  d_op_nonred_count[f] = 0;
315
  // get the matchable operators in the equivalence class of f
316
82483
  std::vector<TNode> ops;
317
41247
  getOperatorsFor(f, ops);
318
41247
  Trace("term-db-debug") << "computeUfTerms for " << f << std::endl;
319
41247
  unsigned congruentCount = 0;
320
41247
  unsigned nonCongruentCount = 0;
321
41247
  unsigned alreadyCongruentCount = 0;
322
41247
  unsigned relevantCount = 0;
323
41247
  NodeManager* nm = NodeManager::currentNM();
324
76925
  for (TNode ff : ops)
325
  {
326
41333
    NodeDbListMap::iterator it = d_opMap.find(ff);
327
41333
    if (it == d_opMap.end())
328
    {
329
      // no terms for this operator
330
5644
      continue;
331
    }
332
35689
    Trace("term-db-debug") << "Adding terms for operator " << ff << std::endl;
333
363647
    for (const Node& n : it->second->d_list)
334
    {
335
      // to be added to term index, term must be relevant, and exist in EE
336
327969
      if (!hasTermCurrent(n) || !d_qstate.hasTerm(n))
337
      {
338
        Trace("term-db-debug") << n << " is not relevant." << std::endl;
339
85343
        continue;
340
      }
341
342
327969
      relevantCount++;
343
346060
      if (!isTermActive(n))
344
      {
345
18091
        Trace("term-db-debug") << n << " is already redundant." << std::endl;
346
18091
        alreadyCongruentCount++;
347
18091
        continue;
348
      }
349
350
309878
      computeArgReps(n);
351
309878
      Trace("term-db-debug") << "Adding term " << n << " with arg reps : ";
352
977837
      for (unsigned i = 0, size = d_arg_reps[n].size(); i < size; i++)
353
      {
354
667959
        Trace("term-db-debug") << d_arg_reps[n][i] << " ";
355
2671836
        if (std::find(d_func_map_rel_dom[f][i].begin(),
356
1335918
                      d_func_map_rel_dom[f][i].end(),
357
2671836
                      d_arg_reps[n][i])
358
2003877
            == d_func_map_rel_dom[f][i].end())
359
        {
360
242119
          d_func_map_rel_dom[f][i].push_back(d_arg_reps[n][i]);
361
        }
362
      }
363
309878
      Trace("term-db-debug") << std::endl;
364
309878
      Assert(d_qstate.hasTerm(n));
365
619756
      Trace("term-db-debug")
366
309878
          << "  and value : " << d_qstate.getRepresentative(n) << std::endl;
367
552493
      Node at = d_func_map_trie[f].addOrGetTerm(n, d_arg_reps[n]);
368
309878
      Assert(d_qstate.hasTerm(at));
369
309878
      Trace("term-db-debug2") << "...add term returned " << at << std::endl;
370
377130
      if (at != n && d_qstate.areEqual(at, n))
371
      {
372
67252
        setTermInactive(n);
373
67252
        Trace("term-db-debug") << n << " is redundant." << std::endl;
374
67252
        congruentCount++;
375
67252
        continue;
376
      }
377
485241
      std::vector<Node> lits;
378
242626
      if (checkCongruentDisequal(at, n, lits))
379
      {
380
11
        Assert(at.getNumChildren() == n.getNumChildren());
381
41
        for (size_t k = 0, size = at.getNumChildren(); k < size; k++)
382
        {
383
30
          if (at[k] != n[k])
384
          {
385
18
            lits.push_back(nm->mkNode(EQUAL, at[k], n[k]).negate());
386
          }
387
        }
388
22
        Node lem = nm->mkOr(lits);
389
11
        if (Trace.isOn("term-db-lemma"))
390
        {
391
          Trace("term-db-lemma") << "Disequal congruent terms : " << at << " "
392
                                 << n << "!!!!" << std::endl;
393
          if (!d_qstate.getValuation().needCheck())
394
          {
395
            Trace("term-db-lemma")
396
                << "  all theories passed with no lemmas." << std::endl;
397
            // we should be a full effort check, prior to theory combination
398
          }
399
          Trace("term-db-lemma") << "  add lemma : " << lem << std::endl;
400
        }
401
11
        d_qim->addPendingLemma(lem, InferenceId::QUANTIFIERS_TDB_DEQ_CONG);
402
11
        d_qstate.notifyInConflict();
403
11
        d_consistent_ee = false;
404
11
        return;
405
      }
406
242615
      nonCongruentCount++;
407
242615
      d_op_nonred_count[f]++;
408
    }
409
35678
    if (Trace.isOn("tdb"))
410
    {
411
      Trace("tdb") << "Term db size [" << f << "] : " << nonCongruentCount
412
                   << " / ";
413
      Trace("tdb") << (nonCongruentCount + congruentCount) << " / "
414
                   << (nonCongruentCount + congruentCount
415
                       + alreadyCongruentCount)
416
                   << " / ";
417
      Trace("tdb") << relevantCount << " / " << it->second->d_list.size()
418
                   << std::endl;
419
    }
420
  }
421
}
422
423
6358557
Node TermDb::getOperatorRepresentative(TNode op) const { return op; }
424
425
234574
bool TermDb::checkCongruentDisequal(TNode a, TNode b, std::vector<Node>& exp)
426
{
427
234574
  if (d_qstate.areDisequal(a, b))
428
  {
429
11
    exp.push_back(a.eqNode(b));
430
11
    return true;
431
  }
432
234563
  return false;
433
}
434
435
2181832
bool TermDb::inRelevantDomain( TNode f, unsigned i, TNode r ) {
436
  // notice if we are not higher-order, getOperatorRepresentative is a no-op
437
2181832
  f = getOperatorRepresentative(f);
438
2181832
  computeUfTerms( f );
439
2181832
  Assert(!d_qstate.getEqualityEngine()->hasTerm(r)
440
         || d_qstate.getEqualityEngine()->getRepresentative(r) == r);
441
2181832
  std::map< Node, std::map< unsigned, std::vector< Node > > >::iterator it = d_func_map_rel_dom.find( f );
442
2181832
  if( it != d_func_map_rel_dom.end() ){
443
2157455
    std::map< unsigned, std::vector< Node > >::iterator it2 = it->second.find( i );
444
2157455
    if( it2!=it->second.end() ){
445
2157455
      return std::find( it2->second.begin(), it2->second.end(), r )!=it2->second.end();
446
    }else{
447
      return false;
448
    }
449
  }else{
450
24377
    return false;
451
  }
452
}
453
454
614014
Node TermDb::evaluateTerm2(TNode n,
455
                           std::map<TNode, Node>& visited,
456
                           std::vector<Node>& exp,
457
                           bool useEntailmentTests,
458
                           bool computeExp,
459
                           bool reqHasTerm)
460
{
461
614014
  std::map< TNode, Node >::iterator itv = visited.find( n );
462
614014
  if( itv != visited.end() ){
463
47578
    return itv->second;
464
  }
465
566436
  size_t prevSize = exp.size();
466
566436
  Trace("term-db-eval") << "evaluate term : " << n << std::endl;
467
1132872
  Node ret = n;
468
566436
  if( n.getKind()==FORALL || n.getKind()==BOUND_VARIABLE ){
469
    //do nothing
470
  }
471
563976
  else if (d_qstate.hasTerm(n))
472
  {
473
265893
    Trace("term-db-eval") << "...exists in ee, return rep" << std::endl;
474
265893
    ret = d_qstate.getRepresentative(n);
475
265893
    if (computeExp)
476
    {
477
      if (n != ret)
478
      {
479
        exp.push_back(n.eqNode(ret));
480
      }
481
    }
482
265893
    reqHasTerm = false;
483
  }
484
298083
  else if (n.hasOperator())
485
  {
486
595296
    std::vector<TNode> args;
487
297648
    bool ret_set = false;
488
297648
    Kind k = n.getKind();
489
595296
    std::vector<Node> tempExp;
490
686278
    for (unsigned i = 0, nchild = n.getNumChildren(); i < nchild; i++)
491
    {
492
1029802
      TNode c = evaluateTerm2(n[i],
493
                              visited,
494
                              tempExp,
495
                              useEntailmentTests,
496
                              computeExp,
497
903531
                              reqHasTerm);
498
514901
      if (c.isNull())
499
      {
500
89292
        ret = Node::null();
501
89292
        ret_set = true;
502
89292
        break;
503
      }
504
425609
      else if (c == d_true || c == d_false)
505
      {
506
        // short-circuiting
507
198579
        if ((k == AND && c == d_false) || (k == OR && c == d_true))
508
        {
509
32778
          ret = c;
510
32778
          ret_set = true;
511
32778
          reqHasTerm = false;
512
32778
          break;
513
        }
514
165801
        else if (k == ITE && i == 0)
515
        {
516
4201
          ret = evaluateTerm2(n[c == d_true ? 1 : 2],
517
                              visited,
518
                              tempExp,
519
                              useEntailmentTests,
520
                              computeExp,
521
                              reqHasTerm);
522
4201
          ret_set = true;
523
4201
          reqHasTerm = false;
524
4201
          break;
525
        }
526
      }
527
388630
      if (computeExp)
528
      {
529
        exp.insert(exp.end(), tempExp.begin(), tempExp.end());
530
      }
531
388630
      Trace("term-db-eval") << "  child " << i << " : " << c << std::endl;
532
388630
      args.push_back(c);
533
    }
534
297648
    if (ret_set)
535
    {
536
      // if we short circuited
537
126271
      if (computeExp)
538
      {
539
        exp.clear();
540
        exp.insert(exp.end(), tempExp.begin(), tempExp.end());
541
      }
542
    }
543
    else
544
    {
545
      // get the (indexed) operator of n, if it exists
546
342754
      TNode f = getMatchOperator(n);
547
      // if it is an indexed term, return the congruent term
548
171377
      if (!f.isNull())
549
      {
550
        // if f is congruent to a term indexed by this class
551
140564
        TNode nn = getCongruentTerm(f, args);
552
140564
        Trace("term-db-eval") << "  got congruent term " << nn
553
70282
                              << " from DB for " << n << std::endl;
554
70282
        if (!nn.isNull())
555
        {
556
28923
          if (computeExp)
557
          {
558
            Assert(nn.getNumChildren() == n.getNumChildren());
559
            for (unsigned i = 0, nchild = nn.getNumChildren(); i < nchild; i++)
560
            {
561
              if (nn[i] != n[i])
562
              {
563
                exp.push_back(nn[i].eqNode(n[i]));
564
              }
565
            }
566
          }
567
28923
          ret = d_qstate.getRepresentative(nn);
568
28923
          Trace("term-db-eval") << "return rep" << std::endl;
569
28923
          ret_set = true;
570
28923
          reqHasTerm = false;
571
28923
          Assert(!ret.isNull());
572
28923
          if (computeExp)
573
          {
574
            if (n != ret)
575
            {
576
              exp.push_back(nn.eqNode(ret));
577
            }
578
          }
579
        }
580
      }
581
171377
      if( !ret_set ){
582
142454
        Trace("term-db-eval") << "return rewrite" << std::endl;
583
        // a theory symbol or a new UF term
584
142454
        if (n.getMetaKind() == metakind::PARAMETERIZED)
585
        {
586
41221
          args.insert(args.begin(), n.getOperator());
587
        }
588
142454
        ret = NodeManager::currentNM()->mkNode(n.getKind(), args);
589
142454
        ret = Rewriter::rewrite(ret);
590
142454
        if (ret.getKind() == EQUAL)
591
        {
592
16688
          if (d_qstate.areDisequal(ret[0], ret[1]))
593
          {
594
4852
            ret = d_false;
595
          }
596
        }
597
142454
        if (useEntailmentTests)
598
        {
599
1359
          if (ret.getKind() == EQUAL || ret.getKind() == GEQ)
600
          {
601
15
            Valuation& val = d_qstate.getValuation();
602
41
            for (unsigned j = 0; j < 2; j++)
603
            {
604
              std::pair<bool, Node> et = val.entailmentCheck(
605
                  options::TheoryOfMode::THEORY_OF_TYPE_BASED,
606
56
                  j == 0 ? ret : ret.negate());
607
30
              if (et.first)
608
              {
609
4
                ret = j == 0 ? d_true : d_false;
610
4
                if (computeExp)
611
                {
612
                  exp.push_back(et.second);
613
                }
614
4
                break;
615
              }
616
            }
617
          }
618
        }
619
      }
620
    }
621
  }
622
  // must have the term
623
566436
  if (reqHasTerm && !ret.isNull())
624
  {
625
140533
    Kind k = ret.getKind();
626
140533
    if (k != OR && k != AND && k != EQUAL && k != ITE && k != NOT
627
126004
        && k != FORALL)
628
    {
629
125815
      if (!d_qstate.hasTerm(ret))
630
      {
631
39144
        ret = Node::null();
632
      }
633
    }
634
  }
635
1132872
  Trace("term-db-eval") << "evaluated term : " << n << ", got : " << ret
636
566436
                        << ", reqHasTerm = " << reqHasTerm << std::endl;
637
  // clear the explanation if failed
638
566436
  if (computeExp && ret.isNull())
639
  {
640
    exp.resize(prevSize);
641
  }
642
566436
  visited[n] = ret;
643
566436
  return ret;
644
}
645
646
8855564
TNode TermDb::getEntailedTerm2(TNode n,
647
                               std::map<TNode, TNode>& subs,
648
                               bool subsRep,
649
                               bool hasSubs)
650
{
651
8855564
  Trace("term-db-entail") << "get entailed term : " << n << std::endl;
652
8855564
  if (d_qstate.hasTerm(n))
653
  {
654
2793261
    Trace("term-db-entail") << "...exists in ee, return rep " << std::endl;
655
2793261
    return n;
656
6062303
  }else if( n.getKind()==BOUND_VARIABLE ){
657
3657978
    if( hasSubs ){
658
3657978
      std::map< TNode, TNode >::iterator it = subs.find( n );
659
3657978
      if( it!=subs.end() ){
660
2734701
        Trace("term-db-entail") << "...substitution is : " << it->second << std::endl;
661
2734701
        if( subsRep ){
662
348105
          Assert(d_qstate.hasTerm(it->second));
663
348105
          Assert(d_qstate.getRepresentative(it->second) == it->second);
664
3082806
          return it->second;
665
        }
666
2386596
        return getEntailedTerm2(it->second, subs, subsRep, hasSubs);
667
      }
668
    }
669
2404325
  }else if( n.getKind()==ITE ){
670
27859
    for( unsigned i=0; i<2; i++ ){
671
22706
      if (isEntailed2(n[0], subs, subsRep, hasSubs, i == 0))
672
      {
673
7730
        return getEntailedTerm2(n[i == 0 ? 1 : 2], subs, subsRep, hasSubs);
674
      }
675
    }
676
  }else{
677
2391442
    if( n.hasOperator() ){
678
2397360
      TNode f = getMatchOperator( n );
679
2384529
      if( !f.isNull() ){
680
4743396
        std::vector< TNode > args;
681
5487799
        for( unsigned i=0; i<n.getNumChildren(); i++ ){
682
7628073
          TNode c = getEntailedTerm2(n[i], subs, subsRep, hasSubs);
683
4511972
          if( c.isNull() ){
684
1395871
            return TNode::null();
685
          }
686
3116101
          c = d_qstate.getRepresentative(c);
687
3116101
          Trace("term-db-entail") << "  child " << i << " : " << c << std::endl;
688
3116101
          args.push_back( c );
689
        }
690
1951654
        TNode nn = getCongruentTerm(f, args);
691
975827
        Trace("term-db-entail") << "  got congruent term " << nn << " for " << n << std::endl;
692
975827
        return nn;
693
      }
694
    }
695
  }
696
948174
  return TNode::null();
697
}
698
699
94912
Node TermDb::evaluateTerm(TNode n,
700
                          bool useEntailmentTests,
701
                          bool reqHasTerm)
702
{
703
189824
  std::map< TNode, Node > visited;
704
189824
  std::vector<Node> exp;
705
189824
  return evaluateTerm2(n, visited, exp, useEntailmentTests, false, reqHasTerm);
706
}
707
708
Node TermDb::evaluateTerm(TNode n,
709
                          std::vector<Node>& exp,
710
                          bool useEntailmentTests,
711
                          bool reqHasTerm)
712
{
713
  std::map<TNode, Node> visited;
714
  return evaluateTerm2(n, visited, exp, useEntailmentTests, true, reqHasTerm);
715
}
716
717
860201
TNode TermDb::getEntailedTerm(TNode n,
718
                              std::map<TNode, TNode>& subs,
719
                              bool subsRep)
720
{
721
860201
  return getEntailedTerm2(n, subs, subsRep, true);
722
}
723
724
86905
TNode TermDb::getEntailedTerm(TNode n)
725
{
726
173810
  std::map< TNode, TNode > subs;
727
173810
  return getEntailedTerm2(n, subs, false, false);
728
}
729
730
1629520
bool TermDb::isEntailed2(
731
    TNode n, std::map<TNode, TNode>& subs, bool subsRep, bool hasSubs, bool pol)
732
{
733
1629520
  Trace("term-db-entail") << "Check entailed : " << n << ", pol = " << pol << std::endl;
734
1629520
  Assert(n.getType().isBoolean());
735
1629520
  if( n.getKind()==EQUAL && !n[0].getType().isBoolean() ){
736
423898
    TNode n1 = getEntailedTerm2(n[0], subs, subsRep, hasSubs);
737
350606
    if( !n1.isNull() ){
738
349292
      TNode n2 = getEntailedTerm2(n[1], subs, subsRep, hasSubs);
739
313303
      if( !n2.isNull() ){
740
277314
        if( n1==n2 ){
741
24363
          return pol;
742
        }else{
743
252951
          Assert(d_qstate.hasTerm(n1));
744
252951
          Assert(d_qstate.hasTerm(n2));
745
252951
          if( pol ){
746
125863
            return d_qstate.areEqual(n1, n2);
747
          }else{
748
127088
            return d_qstate.areDisequal(n1, n2);
749
          }
750
        }
751
      }
752
    }
753
1278914
  }else if( n.getKind()==NOT ){
754
488564
    return isEntailed2(n[0], subs, subsRep, hasSubs, !pol);
755
790350
  }else if( n.getKind()==OR || n.getKind()==AND ){
756
233241
    bool simPol = ( pol && n.getKind()==OR ) || ( !pol && n.getKind()==AND );
757
815181
    for( unsigned i=0; i<n.getNumChildren(); i++ ){
758
734195
      if (isEntailed2(n[i], subs, subsRep, hasSubs, pol))
759
      {
760
184804
        if( simPol ){
761
70072
          return true;
762
        }
763
      }else{
764
549391
        if( !simPol ){
765
82183
          return false;
766
        }
767
      }
768
    }
769
80986
    return !simPol;
770
  //Boolean equality here
771
557109
  }else if( n.getKind()==EQUAL || n.getKind()==ITE ){
772
80868
    for( unsigned i=0; i<2; i++ ){
773
67830
      if (isEntailed2(n[0], subs, subsRep, hasSubs, i == 0))
774
      {
775
29447
        unsigned ch = ( n.getKind()==EQUAL || i==0 ) ? 1 : 2;
776
29447
        bool reqPol = ( n.getKind()==ITE || i==0 ) ? pol : !pol;
777
29447
        return isEntailed2(n[ch], subs, subsRep, hasSubs, reqPol);
778
      }
779
    }
780
514624
  }else if( n.getKind()==APPLY_UF ){
781
453131
    TNode n1 = getEntailedTerm2(n, subs, subsRep, hasSubs);
782
338251
    if( !n1.isNull() ){
783
223371
      Assert(d_qstate.hasTerm(n1));
784
223371
      if( n1==d_true ){
785
        return pol;
786
223371
      }else if( n1==d_false ){
787
        return !pol;
788
      }else{
789
223371
        return d_qstate.getRepresentative(n1) == (pol ? d_true : d_false);
790
      }
791
    }
792
176373
  }else if( n.getKind()==FORALL && !pol ){
793
4787
    return isEntailed2(n[1], subs, subsRep, hasSubs, pol);
794
  }
795
372796
  return false;
796
}
797
798
1544
bool TermDb::isEntailed(TNode n, bool pol)
799
{
800
1544
  Assert(d_consistent_ee);
801
3088
  std::map< TNode, TNode > subs;
802
3088
  return isEntailed2(n, subs, false, false, pol);
803
}
804
805
280447
bool TermDb::isEntailed(TNode n,
806
                        std::map<TNode, TNode>& subs,
807
                        bool subsRep,
808
                        bool pol)
809
{
810
280447
  Assert(d_consistent_ee);
811
280447
  return isEntailed2(n, subs, subsRep, true, pol);
812
}
813
814
4011620
bool TermDb::isTermActive( Node n ) {
815
4011620
  return d_inactive_map.find( n )==d_inactive_map.end();
816
  //return !n.getAttribute(NoMatchAttribute());
817
}
818
819
165971
void TermDb::setTermInactive( Node n ) {
820
165971
  d_inactive_map[n] = true;
821
  //Trace("term-db-debug2") << "set no match attribute" << std::endl;
822
  //NoMatchAttribute nma;
823
  //n.setAttribute(nma,true);
824
165971
}
825
826
4413598
bool TermDb::hasTermCurrent( Node n, bool useMode ) {
827
4413598
  if( !useMode ){
828
    return d_has_map.find( n )!=d_has_map.end();
829
  }
830
  //some assertions are not sent to EE
831
4413598
  if (options::termDbMode() == options::TermDbMode::ALL)
832
  {
833
4413598
    return true;
834
  }
835
  else if (options::termDbMode() == options::TermDbMode::RELEVANT)
836
  {
837
    return d_has_map.find( n )!=d_has_map.end();
838
  }
839
  Assert(false) << "TermDb::hasTermCurrent: Unknown termDbMode : " << options::termDbMode();
840
  return false;
841
}
842
843
1146
bool TermDb::isTermEligibleForInstantiation(TNode n, TNode f)
844
{
845
1146
  if( options::instMaxLevel()!=-1 ){
846
970
    if( n.hasAttribute(InstLevelAttribute()) ){
847
      int64_t fml =
848
970
          f.isNull() ? -1 : d_qreg.getQuantAttributes().getQuantInstLevel(f);
849
970
      unsigned ml = fml>=0 ? fml : options::instMaxLevel();
850
851
970
      if( n.getAttribute(InstLevelAttribute())>ml ){
852
        Trace("inst-add-debug") << "Term " << n << " has instantiation level " << n.getAttribute(InstLevelAttribute());
853
        Trace("inst-add-debug") << ", which is more than maximum allowed level " << ml << " for this quantified formula." << std::endl;
854
        return false;
855
      }
856
    }else{
857
      if( options::instLevelInputOnly() ){
858
        Trace("inst-add-debug") << "Term " << n << " does not have an instantiation level." << std::endl;
859
        return false;
860
      }
861
    }
862
  }
863
  // it cannot have instantiation constants, which originate from
864
  // counterexample-guided instantiation strategies.
865
1146
  return !TermUtil::hasInstConstAttr(n);
866
}
867
868
176
Node TermDb::getEligibleTermInEqc( TNode r ) {
869
176
  if( isTermEligibleForInstantiation( r, TNode::null() ) ){
870
176
    return r;
871
  }else{
872
    std::map< Node, Node >::iterator it = d_term_elig_eqc.find( r );
873
    if( it==d_term_elig_eqc.end() ){
874
      Node h;
875
      eq::EqualityEngine* ee = d_qstate.getEqualityEngine();
876
      eq::EqClassIterator eqc_i = eq::EqClassIterator(r, ee);
877
      while (!eqc_i.isFinished())
878
      {
879
        TNode n = (*eqc_i);
880
        ++eqc_i;
881
        if (isTermEligibleForInstantiation(n, TNode::null()))
882
        {
883
          h = n;
884
          break;
885
        }
886
      }
887
      d_term_elig_eqc[r] = h;
888
      return h;
889
    }else{
890
      return it->second;
891
    }
892
  }
893
}
894
895
27175
bool TermDb::resetInternal(Theory::Effort e)
896
{
897
  // do nothing
898
27175
  return true;
899
}
900
901
27175
bool TermDb::finishResetInternal(Theory::Effort e)
902
{
903
  // do nothing
904
27175
  return true;
905
}
906
907
365580
void TermDb::addTermInternal(Node n)
908
{
909
  // do nothing
910
365580
}
911
912
84553
void TermDb::getOperatorsFor(TNode f, std::vector<TNode>& ops)
913
{
914
84553
  ops.push_back(f);
915
84553
}
916
917
void TermDb::setHasTerm( Node n ) {
918
  Trace("term-db-debug2") << "hasTerm : " << n  << std::endl;
919
  if( d_has_map.find( n )==d_has_map.end() ){
920
    d_has_map[n] = true;
921
    for( unsigned i=0; i<n.getNumChildren(); i++ ){
922
      setHasTerm( n[i] );
923
    }
924
  }
925
}
926
927
8211
void TermDb::presolve() {
928
8211
  if (options::incrementalSolving() && !options::termDbCd())
929
  {
930
    d_termsContext.pop();
931
    d_termsContext.push();
932
  }
933
8211
}
934
935
28107
bool TermDb::reset( Theory::Effort effort ){
936
28107
  d_op_nonred_count.clear();
937
28107
  d_arg_reps.clear();
938
28107
  d_func_map_trie.clear();
939
28107
  d_func_map_eqc_trie.clear();
940
28107
  d_func_map_rel_dom.clear();
941
28107
  d_consistent_ee = true;
942
943
28107
  eq::EqualityEngine* ee = d_qstate.getEqualityEngine();
944
945
28107
  Assert(ee->consistent());
946
  // if higher-order, add equalities for the purification terms now
947
28107
  if (!resetInternal(effort))
948
  {
949
    return false;
950
  }
951
952
  //compute has map
953
28107
  if (options::termDbMode() == options::TermDbMode::RELEVANT)
954
  {
955
    d_has_map.clear();
956
    d_term_elig_eqc.clear();
957
    eq::EqClassesIterator eqcs_i = eq::EqClassesIterator( ee );
958
    while( !eqcs_i.isFinished() ){
959
      TNode r = (*eqcs_i);
960
      bool addedFirst = false;
961
      Node first;
962
      //TODO: ignoring singleton eqc isn't enough, need to ensure eqc are relevant
963
      eq::EqClassIterator eqc_i = eq::EqClassIterator(r, ee);
964
      while( !eqc_i.isFinished() ){
965
        TNode n = (*eqc_i);
966
        if( first.isNull() ){
967
          first = n;
968
        }else{
969
          if( !addedFirst ){
970
            addedFirst = true;
971
            setHasTerm( first );
972
          }
973
          setHasTerm( n );
974
        }
975
        ++eqc_i;
976
      }
977
      ++eqcs_i;
978
    }
979
    const LogicInfo& logicInfo = d_qstate.getLogicInfo();
980
    for (TheoryId theoryId = THEORY_FIRST; theoryId < THEORY_LAST; ++theoryId)
981
    {
982
      if (!logicInfo.isTheoryEnabled(theoryId))
983
      {
984
        continue;
985
      }
986
      for (context::CDList<Assertion>::const_iterator
987
               it = d_qstate.factsBegin(theoryId),
988
               it_end = d_qstate.factsEnd(theoryId);
989
           it != it_end;
990
           ++it)
991
      {
992
        setHasTerm((*it).d_assertion);
993
      }
994
    }
995
  }
996
  // finish reset
997
28107
  return finishResetInternal(effort);
998
}
999
1000
20624
TNodeTrie* TermDb::getTermArgTrie(Node f)
1001
{
1002
20624
  f = getOperatorRepresentative(f);
1003
20624
  computeUfTerms( f );
1004
20624
  std::map<Node, TNodeTrie>::iterator itut = d_func_map_trie.find(f);
1005
20624
  if( itut!=d_func_map_trie.end() ){
1006
12317
    return &itut->second;
1007
  }else{
1008
8307
    return NULL;
1009
  }
1010
}
1011
1012
1783144
TNodeTrie* TermDb::getTermArgTrie(Node eqc, Node f)
1013
{
1014
1783144
  f = getOperatorRepresentative(f);
1015
1783144
  computeUfEqcTerms( f );
1016
1783144
  std::map<Node, TNodeTrie>::iterator itut = d_func_map_eqc_trie.find(f);
1017
1783144
  if( itut==d_func_map_eqc_trie.end() ){
1018
    return NULL;
1019
  }else{
1020
1783144
    if( eqc.isNull() ){
1021
906488
      return &itut->second;
1022
    }else{
1023
      std::map<TNode, TNodeTrie>::iterator itute =
1024
876656
          itut->second.d_data.find(eqc);
1025
876656
      if( itute!=itut->second.d_data.end() ){
1026
526041
        return &itute->second;
1027
      }else{
1028
350615
        return NULL;
1029
      }
1030
    }
1031
  }
1032
}
1033
1034
TNode TermDb::getCongruentTerm( Node f, Node n ) {
1035
  f = getOperatorRepresentative(f);
1036
  computeUfTerms( f );
1037
  std::map<Node, TNodeTrie>::iterator itut = d_func_map_trie.find(f);
1038
  if( itut!=d_func_map_trie.end() ){
1039
    computeArgReps( n );
1040
    return itut->second.existsTerm( d_arg_reps[n] );
1041
  }else{
1042
    return TNode::null();
1043
  }
1044
}
1045
1046
1046109
TNode TermDb::getCongruentTerm( Node f, std::vector< TNode >& args ) {
1047
1046109
  f = getOperatorRepresentative(f);
1048
1046109
  computeUfTerms( f );
1049
1046109
  return d_func_map_trie[f].existsTerm( args );
1050
}
1051
1052
}  // namespace quantifiers
1053
}  // namespace theory
1054
29577
}  // namespace cvc5