GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/quantifiers/term_database.cpp Lines: 552 677 81.5 %
Date: 2021-05-21 Branches: 1274 2982 42.7 %

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
8954
TermDb::TermDb(QuantifiersState& qs, QuantifiersRegistry& qr)
41
    : d_qstate(qs),
42
      d_qim(nullptr),
43
      d_qreg(qr),
44
      d_termsContext(),
45
136146
      d_termsContextUse(options::termDbCd() ? qs.getSatContext()
46
                                            : &d_termsContext),
47
      d_processed(d_termsContextUse),
48
      d_typeMap(d_termsContextUse),
49
      d_ops(d_termsContextUse),
50
      d_opMap(d_termsContextUse),
51
17908
      d_inactive_map(qs.getSatContext())
52
{
53
8954
  d_consistent_ee = true;
54
8954
  d_true = NodeManager::currentNM()->mkConst(true);
55
8954
  d_false = NodeManager::currentNM()->mkConst(false);
56
8954
  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
8954
}
63
64
17908
TermDb::~TermDb(){
65
66
17908
}
67
68
8954
void TermDb::finishInit(QuantifiersInferenceManager* qim) { d_qim = qim; }
69
70
24942
void TermDb::registerQuantifier( Node q ) {
71
24942
  Assert(q[0].getNumChildren() == d_qreg.getNumInstantiationConstants(q));
72
83811
  for (size_t i = 0, nvars = q[0].getNumChildren(); i < nvars; i++)
73
  {
74
117738
    Node ic = d_qreg.getInstantiationConstant(q, i);
75
58869
    setTermInactive( ic );
76
  }
77
24942
}
78
79
923
size_t TermDb::getNumOperators() const { return d_ops.size(); }
80
81
2050
Node TermDb::getOperator(size_t i) const
82
{
83
2050
  Assert(i < d_ops.size());
84
2050
  return d_ops[i];
85
}
86
87
/** ground terms */
88
546195
size_t TermDb::getNumGroundTerms(Node f) const
89
{
90
546195
  NodeDbListMap::const_iterator it = d_opMap.find(f);
91
546195
  if (it != d_opMap.end())
92
  {
93
529825
    return it->second->d_list.size();
94
  }
95
16370
  return 0;
96
}
97
98
3073085
Node TermDb::getGroundTerm(Node f, size_t i) const
99
{
100
3073085
  NodeDbListMap::const_iterator it = d_opMap.find(f);
101
3073085
  if (it != d_opMap.end())
102
  {
103
3073085
    Assert(i < it->second->d_list.size());
104
3073085
    return it->second->d_list[i];
105
  }
106
  Assert(false);
107
  return Node::null();
108
}
109
110
510
size_t TermDb::getNumTypeGroundTerms(TypeNode tn) const
111
{
112
510
  TypeNodeDbListMap::const_iterator it = d_typeMap.find(tn);
113
510
  if (it != d_typeMap.end())
114
  {
115
500
    return it->second->d_list.size();
116
  }
117
10
  return 0;
118
}
119
120
43635
Node TermDb::getTypeGroundTerm(TypeNode tn, size_t i) const
121
{
122
43635
  TypeNodeDbListMap::const_iterator it = d_typeMap.find(tn);
123
43635
  if (it != d_typeMap.end())
124
  {
125
43635
    Assert(i < it->second->d_list.size());
126
43635
    return it->second->d_list[i];
127
  }
128
  Assert(false);
129
  return Node::null();
130
}
131
132
2689
Node TermDb::getOrMakeTypeGroundTerm(TypeNode tn, bool reqVar)
133
{
134
2689
  TypeNodeDbListMap::const_iterator it = d_typeMap.find(tn);
135
2689
  if (it != d_typeMap.end())
136
  {
137
724
    Assert(!it->second->d_list.empty());
138
724
    if (!reqVar)
139
    {
140
383
      return it->second->d_list[0];
141
    }
142
532
    for (const Node& v : it->second->d_list)
143
    {
144
477
      if (v.isVar())
145
      {
146
286
        return v;
147
      }
148
    }
149
  }
150
2020
  return getOrMakeTypeFreshVariable(tn);
151
}
152
153
2020
Node TermDb::getOrMakeTypeFreshVariable(TypeNode tn)
154
{
155
2020
  std::unordered_map<TypeNode, Node>::iterator it = d_type_fv.find(tn);
156
2020
  if (it == d_type_fv.end())
157
  {
158
232
    SkolemManager* sm = NodeManager::currentNM()->getSkolemManager();
159
464
    std::stringstream ss;
160
232
    ss << language::SetLanguage(options::outputLanguage());
161
232
    ss << "e_" << tn;
162
464
    Node k = sm->mkDummySkolem(ss.str(), tn, "is a termDb fresh variable");
163
464
    Trace("mkVar") << "TermDb:: Make variable " << k << " : " << tn
164
232
                   << std::endl;
165
232
    if (options::instMaxLevel() != -1)
166
    {
167
      QuantAttributes::setInstantiationLevelAttr(k, 0);
168
    }
169
232
    d_type_fv[tn] = k;
170
232
    return k;
171
  }
172
1788
  return it->second;
173
}
174
175
5784260
Node TermDb::getMatchOperator( Node n ) {
176
5784260
  Kind k = n.getKind();
177
  //datatype operators may be parametric, always assume they are
178
5784260
  if (k == SELECT || k == STORE || k == UNION || k == INTERSECTION
179
5748128
      || k == SUBSET || k == SETMINUS || k == MEMBER || k == SINGLETON
180
5719944
      || k == APPLY_SELECTOR_TOTAL || k == APPLY_SELECTOR || k == APPLY_TESTER
181
5609129
      || k == SEP_PTO || k == HO_APPLY || k == SEQ_NTH)
182
  {
183
    //since it is parametric, use a particular one as op
184
365568
    TypeNode tn = n[0].getType();
185
365568
    Node op = n.getOperator();
186
182784
    std::map< Node, std::map< TypeNode, Node > >::iterator ito = d_par_op_map.find( op );
187
182784
    if( ito!=d_par_op_map.end() ){
188
174902
      std::map< TypeNode, Node >::iterator it = ito->second.find( tn );
189
174902
      if( it!=ito->second.end() ){
190
174277
        return it->second;
191
      }
192
    }
193
8507
    Trace("par-op") << "Parametric operator : " << k << ", " << n.getOperator() << ", " << tn << " : " << n << std::endl;
194
8507
    d_par_op_map[op][tn] = n;
195
8507
    return n;
196
  }
197
5601476
  else if (inst::TriggerTermInfo::isAtomicTriggerKind(k))
198
  {
199
5331441
    return n.getOperator();
200
  }else{
201
270035
    return Node::null();
202
  }
203
}
204
205
2027439
void TermDb::addTerm(Node n)
206
{
207
2027439
  if (d_processed.find(n) != d_processed.end())
208
  {
209
1216714
    return;
210
  }
211
810725
  d_processed.insert(n);
212
810725
  if (!TermUtil::hasInstConstAttr(n))
213
  {
214
785678
    Trace("term-db-debug") << "register term : " << n << std::endl;
215
785678
    DbList* dlt = getOrMkDbListForType(n.getType());
216
785678
    dlt->d_list.push_back(n);
217
    // if this is an atomic trigger, consider adding it
218
785678
    if (inst::TriggerTermInfo::isAtomicTrigger(n))
219
    {
220
341921
      Trace("term-db") << "register term in db " << n << std::endl;
221
222
683842
      Node op = getMatchOperator(n);
223
341921
      Trace("term-db-debug") << "  match operator is : " << op << std::endl;
224
341921
      DbList* dlo = getOrMkDbListForOp(op);
225
341921
      dlo->d_list.push_back(n);
226
      // If we are higher-order, we may need to register more terms.
227
341921
      if (options::ufHo())
228
      {
229
22991
        addTermHo(n);
230
      }
231
    }
232
  }
233
  else
234
  {
235
25047
    setTermInactive(n);
236
  }
237
810725
  if (!n.isClosure())
238
  {
239
2131825
    for (const Node& nc : n)
240
    {
241
1321122
      addTerm(nc);
242
    }
243
  }
244
}
245
246
785678
DbList* TermDb::getOrMkDbListForType(TypeNode tn)
247
{
248
785678
  TypeNodeDbListMap::iterator it = d_typeMap.find(tn);
249
785678
  if (it != d_typeMap.end())
250
  {
251
763342
    return it->second.get();
252
  }
253
44672
  std::shared_ptr<DbList> dl = std::make_shared<DbList>(d_termsContextUse);
254
22336
  d_typeMap.insert(tn, dl);
255
22336
  return dl.get();
256
}
257
258
393613
DbList* TermDb::getOrMkDbListForOp(TNode op)
259
{
260
393613
  NodeDbListMap::iterator it = d_opMap.find(op);
261
393613
  if (it != d_opMap.end())
262
  {
263
299307
    return it->second.get();
264
  }
265
188612
  std::shared_ptr<DbList> dl = std::make_shared<DbList>(d_termsContextUse);
266
94306
  d_opMap.insert(op, dl);
267
94306
  Assert(op.getKind() != BOUND_VARIABLE);
268
94306
  d_ops.push_back(op);
269
94306
  return dl.get();
270
}
271
272
750053
void TermDb::computeArgReps( TNode n ) {
273
750053
  if (d_arg_reps.find(n) == d_arg_reps.end())
274
  {
275
437435
    eq::EqualityEngine* ee = d_qstate.getEqualityEngine();
276
1318585
    for (const TNode& nc : n)
277
    {
278
1762300
      TNode r = ee->hasTerm(nc) ? ee->getRepresentative(nc) : nc;
279
881150
      d_arg_reps[n].push_back( r );
280
    }
281
  }
282
750053
}
283
284
2091871
void TermDb::computeUfEqcTerms( TNode f ) {
285
2091871
  Assert(f == getOperatorRepresentative(f));
286
2091871
  if (d_func_map_eqc_trie.find(f) != d_func_map_eqc_trie.end())
287
  {
288
2041906
    return;
289
  }
290
49965
  d_func_map_eqc_trie[f].clear();
291
  // get the matchable operators in the equivalence class of f
292
99930
  std::vector<TNode> ops;
293
49965
  ops.push_back(f);
294
49965
  if (options::ufHo())
295
  {
296
1635
    ops.insert(ops.end(), d_ho_op_slaves[f].begin(), d_ho_op_slaves[f].end());
297
  }
298
49965
  eq::EqualityEngine* ee = d_qstate.getEqualityEngine();
299
100025
  for (TNode ff : ops)
300
  {
301
50060
    DbList* dbl = getOrMkDbListForOp(ff);
302
454238
    for (const Node& n : dbl->d_list)
303
    {
304
404178
      if (hasTermCurrent(n) && isTermActive(n))
305
      {
306
369623
        computeArgReps(n);
307
739246
        TNode r = ee->hasTerm(n) ? ee->getRepresentative(n) : TNode(n);
308
369623
        d_func_map_eqc_trie[f].d_data[r].addTerm(n, d_arg_reps[n]);
309
      }
310
    }
311
  }
312
}
313
314
3750506
void TermDb::computeUfTerms( TNode f ) {
315
3750506
  if (d_op_nonred_count.find(f) != d_op_nonred_count.end())
316
  {
317
    // already computed
318
7412128
    return;
319
  }
320
44445
  Assert(f == getOperatorRepresentative(f));
321
44445
  d_op_nonred_count[f] = 0;
322
  // get the matchable operators in the equivalence class of f
323
88884
  std::vector<TNode> ops;
324
44445
  ops.push_back(f);
325
44445
  if (options::ufHo())
326
  {
327
2121
    ops.insert(ops.end(), d_ho_op_slaves[f].begin(), d_ho_op_slaves[f].end());
328
  }
329
44445
  Trace("term-db-debug") << "computeUfTerms for " << f << std::endl;
330
44445
  unsigned congruentCount = 0;
331
44445
  unsigned nonCongruentCount = 0;
332
44445
  unsigned alreadyCongruentCount = 0;
333
44445
  unsigned relevantCount = 0;
334
44445
  NodeManager* nm = NodeManager::currentNM();
335
80822
  for (TNode ff : ops)
336
  {
337
44544
    NodeDbListMap::iterator it = d_opMap.find(ff);
338
44544
    if (it == d_opMap.end())
339
    {
340
      // no terms for this operator
341
8161
      continue;
342
    }
343
36383
    Trace("term-db-debug") << "Adding terms for operator " << ff << std::endl;
344
445390
    for (const Node& n : it->second->d_list)
345
    {
346
      // to be added to term index, term must be relevant, and exist in EE
347
409013
      if (!hasTermCurrent(n) || !d_qstate.hasTerm(n))
348
      {
349
        Trace("term-db-debug") << n << " is not relevant." << std::endl;
350
116409
        continue;
351
      }
352
353
409013
      relevantCount++;
354
437596
      if (!isTermActive(n))
355
      {
356
28583
        Trace("term-db-debug") << n << " is already redundant." << std::endl;
357
28583
        alreadyCongruentCount++;
358
28583
        continue;
359
      }
360
361
380430
      computeArgReps(n);
362
380430
      Trace("term-db-debug") << "Adding term " << n << " with arg reps : ";
363
1157060
      for (unsigned i = 0, size = d_arg_reps[n].size(); i < size; i++)
364
      {
365
776630
        Trace("term-db-debug") << d_arg_reps[n][i] << " ";
366
3106520
        if (std::find(d_func_map_rel_dom[f][i].begin(),
367
1553260
                      d_func_map_rel_dom[f][i].end(),
368
3106520
                      d_arg_reps[n][i])
369
2329890
            == d_func_map_rel_dom[f][i].end())
370
        {
371
261584
          d_func_map_rel_dom[f][i].push_back(d_arg_reps[n][i]);
372
        }
373
      }
374
380430
      Trace("term-db-debug") << std::endl;
375
380430
      Assert(d_qstate.hasTerm(n));
376
760860
      Trace("term-db-debug")
377
380430
          << "  and value : " << d_qstate.getRepresentative(n) << std::endl;
378
673028
      Node at = d_func_map_trie[f].addOrGetTerm(n, d_arg_reps[n]);
379
380430
      Assert(d_qstate.hasTerm(at));
380
380430
      Trace("term-db-debug2") << "...add term returned " << at << std::endl;
381
468256
      if (at != n && d_qstate.areEqual(at, n))
382
      {
383
87826
        setTermInactive(n);
384
87826
        Trace("term-db-debug") << n << " is redundant." << std::endl;
385
87826
        congruentCount++;
386
87826
        continue;
387
      }
388
292604
      if (d_qstate.areDisequal(at, n))
389
      {
390
6
        std::vector<Node> lits;
391
6
        lits.push_back(nm->mkNode(EQUAL, at, n));
392
6
        bool success = true;
393
6
        if (options::ufHo())
394
        {
395
          // operators might be disequal
396
          if (ops.size() > 1)
397
          {
398
            Node atf = getMatchOperator(at);
399
            Node nf = getMatchOperator(n);
400
            if (atf != nf)
401
            {
402
              if (at.getKind() == APPLY_UF && n.getKind() == APPLY_UF)
403
              {
404
                lits.push_back(atf.eqNode(nf).negate());
405
              }
406
              else
407
              {
408
                success = false;
409
                Assert(false);
410
              }
411
            }
412
          }
413
        }
414
6
        if (success)
415
        {
416
6
          Assert(at.getNumChildren() == n.getNumChildren());
417
24
          for (unsigned k = 0, size = at.getNumChildren(); k < size; k++)
418
          {
419
18
            if (at[k] != n[k])
420
            {
421
6
              lits.push_back(nm->mkNode(EQUAL, at[k], n[k]).negate());
422
            }
423
          }
424
12
          Node lem = lits.size() == 1 ? lits[0] : nm->mkNode(OR, lits);
425
6
          if (Trace.isOn("term-db-lemma"))
426
          {
427
            Trace("term-db-lemma") << "Disequal congruent terms : " << at << " "
428
                                   << n << "!!!!" << std::endl;
429
            if (!d_qstate.getValuation().needCheck())
430
            {
431
              Trace("term-db-lemma") << "  all theories passed with no lemmas."
432
                                     << std::endl;
433
              // we should be a full effort check, prior to theory combination
434
            }
435
            Trace("term-db-lemma") << "  add lemma : " << lem << std::endl;
436
          }
437
6
          d_qim->addPendingLemma(lem, InferenceId::UNKNOWN);
438
6
          d_qstate.notifyInConflict();
439
6
          d_consistent_ee = false;
440
6
          return;
441
        }
442
      }
443
292598
      nonCongruentCount++;
444
292598
      d_op_nonred_count[f]++;
445
    }
446
36377
    if (Trace.isOn("tdb"))
447
    {
448
      Trace("tdb") << "Term db size [" << f << "] : " << nonCongruentCount
449
                   << " / ";
450
      Trace("tdb") << (nonCongruentCount + congruentCount) << " / "
451
                   << (nonCongruentCount + congruentCount
452
                       + alreadyCongruentCount)
453
                   << " / ";
454
      Trace("tdb") << relevantCount << " / " << it->second->d_list.size()
455
                   << std::endl;
456
    }
457
  }
458
}
459
460
22991
void TermDb::addTermHo(Node n)
461
{
462
22991
  Assert(options::ufHo());
463
22991
  if (n.getType().isFunction())
464
  {
465
    // nothing special to do with functions
466
341
    return;
467
  }
468
22650
  NodeManager* nm = NodeManager::currentNM();
469
22650
  SkolemManager* sm = nm->getSkolemManager();
470
45300
  Node curr = n;
471
45300
  std::vector<Node> args;
472
26806
  while (curr.getKind() == HO_APPLY)
473
  {
474
2078
    args.insert(args.begin(), curr[1]);
475
2078
    curr = curr[0];
476
2078
    if (!curr.isVar())
477
    {
478
      // purify the term
479
891
      std::map<Node, Node>::iterator itp = d_ho_fun_op_purify.find(curr);
480
1782
      Node psk;
481
891
      if (itp == d_ho_fun_op_purify.end())
482
      {
483
534
        psk = sm->mkDummySkolem("pfun",
484
356
                                curr.getType(),
485
                                "purify for function operator term indexing");
486
178
        d_ho_fun_op_purify[curr] = psk;
487
        // we do not add it to d_ops since it is an internal operator
488
      }
489
      else
490
      {
491
713
        psk = itp->second;
492
      }
493
1782
      std::vector<Node> children;
494
891
      children.push_back(psk);
495
891
      children.insert(children.end(), args.begin(), args.end());
496
1782
      Node p_n = nm->mkNode(APPLY_UF, children);
497
1782
      Trace("term-db") << "register term in db (via purify) " << p_n
498
891
                       << std::endl;
499
      // also add this one internally
500
891
      DbList* dblp = getOrMkDbListForOp(psk);
501
891
      dblp->d_list.push_back(p_n);
502
      // maintain backwards mapping
503
891
      d_ho_purify_to_term[p_n] = n;
504
    }
505
  }
506
22650
  if (!args.empty() && curr.isVar())
507
  {
508
    // also add standard application version
509
1187
    args.insert(args.begin(), curr);
510
2374
    Node uf_n = nm->mkNode(APPLY_UF, args);
511
1187
    addTerm(uf_n);
512
  }
513
}
514
515
3374569
Node TermDb::getOperatorRepresentative( TNode op ) const {
516
3374569
  std::map< TNode, TNode >::const_iterator it = d_ho_op_rep.find( op );
517
3374569
  if( it!=d_ho_op_rep.end() ){
518
1560478
    return it->second;
519
  }else{
520
1814091
    return op;
521
  }
522
}
523
524
2162772
bool TermDb::inRelevantDomain( TNode f, unsigned i, TNode r ) {
525
2162772
  if( options::ufHo() ){
526
185036
    f = getOperatorRepresentative( f );
527
  }
528
2162772
  computeUfTerms( f );
529
2162772
  Assert(!d_qstate.getEqualityEngine()->hasTerm(r)
530
         || d_qstate.getEqualityEngine()->getRepresentative(r) == r);
531
2162772
  std::map< Node, std::map< unsigned, std::vector< Node > > >::iterator it = d_func_map_rel_dom.find( f );
532
2162772
  if( it != d_func_map_rel_dom.end() ){
533
2137345
    std::map< unsigned, std::vector< Node > >::iterator it2 = it->second.find( i );
534
2137345
    if( it2!=it->second.end() ){
535
2137345
      return std::find( it2->second.begin(), it2->second.end(), r )!=it2->second.end();
536
    }else{
537
      return false;
538
    }
539
  }else{
540
25427
    return false;
541
  }
542
}
543
544
1096159
Node TermDb::evaluateTerm2(TNode n,
545
                           std::map<TNode, Node>& visited,
546
                           std::vector<Node>& exp,
547
                           bool useEntailmentTests,
548
                           bool computeExp,
549
                           bool reqHasTerm)
550
{
551
1096159
  std::map< TNode, Node >::iterator itv = visited.find( n );
552
1096159
  if( itv != visited.end() ){
553
31928
    return itv->second;
554
  }
555
1064231
  size_t prevSize = exp.size();
556
1064231
  Trace("term-db-eval") << "evaluate term : " << n << std::endl;
557
2128462
  Node ret = n;
558
1064231
  if( n.getKind()==FORALL || n.getKind()==BOUND_VARIABLE ){
559
    //do nothing
560
  }
561
1061774
  else if (d_qstate.hasTerm(n))
562
  {
563
444688
    Trace("term-db-eval") << "...exists in ee, return rep" << std::endl;
564
444688
    ret = d_qstate.getRepresentative(n);
565
444688
    if (computeExp)
566
    {
567
      if (n != ret)
568
      {
569
        exp.push_back(n.eqNode(ret));
570
      }
571
    }
572
444688
    reqHasTerm = false;
573
  }
574
617086
  else if (n.hasOperator())
575
  {
576
1233092
    std::vector<TNode> args;
577
616546
    bool ret_set = false;
578
616546
    Kind k = n.getKind();
579
1233092
    std::vector<Node> tempExp;
580
1151757
    for (unsigned i = 0, nchild = n.getNumChildren(); i < nchild; i++)
581
    {
582
1796206
      TNode c = evaluateTerm2(n[i],
583
                              visited,
584
                              tempExp,
585
                              useEntailmentTests,
586
                              computeExp,
587
1433314
                              reqHasTerm);
588
898103
      if (c.isNull())
589
      {
590
316200
        ret = Node::null();
591
316200
        ret_set = true;
592
316200
        break;
593
      }
594
581903
      else if (c == d_true || c == d_false)
595
      {
596
        // short-circuiting
597
235940
        if ((k == AND && c == d_false) || (k == OR && c == d_true))
598
        {
599
38563
          ret = c;
600
38563
          ret_set = true;
601
38563
          reqHasTerm = false;
602
38563
          break;
603
        }
604
197377
        else if (k == ITE && i == 0)
605
        {
606
8129
          ret = evaluateTerm2(n[c == d_true ? 1 : 2],
607
                              visited,
608
                              tempExp,
609
                              useEntailmentTests,
610
                              computeExp,
611
                              reqHasTerm);
612
8129
          ret_set = true;
613
8129
          reqHasTerm = false;
614
8129
          break;
615
        }
616
      }
617
535211
      if (computeExp)
618
      {
619
        exp.insert(exp.end(), tempExp.begin(), tempExp.end());
620
      }
621
535211
      Trace("term-db-eval") << "  child " << i << " : " << c << std::endl;
622
535211
      args.push_back(c);
623
    }
624
616546
    if (ret_set)
625
    {
626
      // if we short circuited
627
362892
      if (computeExp)
628
      {
629
        exp.clear();
630
        exp.insert(exp.end(), tempExp.begin(), tempExp.end());
631
      }
632
    }
633
    else
634
    {
635
      // get the (indexed) operator of n, if it exists
636
507308
      TNode f = getMatchOperator(n);
637
      // if it is an indexed term, return the congruent term
638
253654
      if (!f.isNull())
639
      {
640
        // if f is congruent to a term indexed by this class
641
309412
        TNode nn = getCongruentTerm(f, args);
642
309412
        Trace("term-db-eval") << "  got congruent term " << nn
643
154706
                              << " from DB for " << n << std::endl;
644
154706
        if (!nn.isNull())
645
        {
646
29889
          if (computeExp)
647
          {
648
            Assert(nn.getNumChildren() == n.getNumChildren());
649
            for (unsigned i = 0, nchild = nn.getNumChildren(); i < nchild; i++)
650
            {
651
              if (nn[i] != n[i])
652
              {
653
                exp.push_back(nn[i].eqNode(n[i]));
654
              }
655
            }
656
          }
657
29889
          ret = d_qstate.getRepresentative(nn);
658
29889
          Trace("term-db-eval") << "return rep" << std::endl;
659
29889
          ret_set = true;
660
29889
          reqHasTerm = false;
661
29889
          Assert(!ret.isNull());
662
29889
          if (computeExp)
663
          {
664
            if (n != ret)
665
            {
666
              exp.push_back(nn.eqNode(ret));
667
            }
668
          }
669
        }
670
      }
671
253654
      if( !ret_set ){
672
223765
        Trace("term-db-eval") << "return rewrite" << std::endl;
673
        // a theory symbol or a new UF term
674
223765
        if (n.getMetaKind() == metakind::PARAMETERIZED)
675
        {
676
124678
          args.insert(args.begin(), n.getOperator());
677
        }
678
223765
        ret = NodeManager::currentNM()->mkNode(n.getKind(), args);
679
223765
        ret = Rewriter::rewrite(ret);
680
223765
        if (ret.getKind() == EQUAL)
681
        {
682
4167
          if (d_qstate.areDisequal(ret[0], ret[1]))
683
          {
684
1891
            ret = d_false;
685
          }
686
        }
687
223765
        if (useEntailmentTests)
688
        {
689
1365
          if (ret.getKind() == EQUAL || ret.getKind() == GEQ)
690
          {
691
15
            Valuation& val = d_qstate.getValuation();
692
41
            for (unsigned j = 0; j < 2; j++)
693
            {
694
              std::pair<bool, Node> et = val.entailmentCheck(
695
                  options::TheoryOfMode::THEORY_OF_TYPE_BASED,
696
56
                  j == 0 ? ret : ret.negate());
697
30
              if (et.first)
698
              {
699
4
                ret = j == 0 ? d_true : d_false;
700
4
                if (computeExp)
701
                {
702
                  exp.push_back(et.second);
703
                }
704
4
                break;
705
              }
706
            }
707
          }
708
        }
709
      }
710
    }
711
  }
712
  // must have the term
713
1064231
  if (reqHasTerm && !ret.isNull())
714
  {
715
221946
    Kind k = ret.getKind();
716
221946
    if (k != OR && k != AND && k != EQUAL && k != ITE && k != NOT
717
219321
        && k != FORALL)
718
    {
719
219138
      if (!d_qstate.hasTerm(ret))
720
      {
721
122295
        ret = Node::null();
722
      }
723
    }
724
  }
725
2128462
  Trace("term-db-eval") << "evaluated term : " << n << ", got : " << ret
726
1064231
                        << ", reqHasTerm = " << reqHasTerm << std::endl;
727
  // clear the explanation if failed
728
1064231
  if (computeExp && ret.isNull())
729
  {
730
    exp.resize(prevSize);
731
  }
732
1064231
  visited[n] = ret;
733
1064231
  return ret;
734
}
735
736
10731022
TNode TermDb::getEntailedTerm2(TNode n,
737
                               std::map<TNode, TNode>& subs,
738
                               bool subsRep,
739
                               bool hasSubs)
740
{
741
10731022
  Trace("term-db-entail") << "get entailed term : " << n << std::endl;
742
10731022
  if (d_qstate.hasTerm(n))
743
  {
744
3480713
    Trace("term-db-entail") << "...exists in ee, return rep " << std::endl;
745
3480713
    return n;
746
7250309
  }else if( n.getKind()==BOUND_VARIABLE ){
747
3873903
    if( hasSubs ){
748
3873903
      std::map< TNode, TNode >::iterator it = subs.find( n );
749
3873903
      if( it!=subs.end() ){
750
2946888
        Trace("term-db-entail") << "...substitution is : " << it->second << std::endl;
751
2946888
        if( subsRep ){
752
348105
          Assert(d_qstate.hasTerm(it->second));
753
348105
          Assert(d_qstate.getRepresentative(it->second) == it->second);
754
3294993
          return it->second;
755
        }
756
2598783
        return getEntailedTerm2(it->second, subs, subsRep, hasSubs);
757
      }
758
    }
759
3376406
  }else if( n.getKind()==ITE ){
760
63223
    for( unsigned i=0; i<2; i++ ){
761
59587
      if (isEntailed2(n[0], subs, subsRep, hasSubs, i == 0))
762
      {
763
28611
        return getEntailedTerm2(n[i == 0 ? 1 : 2], subs, subsRep, hasSubs);
764
      }
765
    }
766
  }else{
767
3344159
    if( n.hasOperator() ){
768
3347906
      TNode f = getMatchOperator( n );
769
3336311
      if( !f.isNull() ){
770
6649432
        std::vector< TNode > args;
771
7095646
        for( unsigned i=0; i<n.getNumChildren(); i++ ){
772
9455667
          TNode c = getEntailedTerm2(n[i], subs, subsRep, hasSubs);
773
5684737
          if( c.isNull() ){
774
1913807
            return TNode::null();
775
          }
776
3770930
          c = d_qstate.getRepresentative(c);
777
3770930
          Trace("term-db-entail") << "  child " << i << " : " << c << std::endl;
778
3770930
          args.push_back( c );
779
        }
780
2821818
        TNode nn = getCongruentTerm(f, args);
781
1410909
        Trace("term-db-entail") << "  got congruent term " << nn << " for " << n << std::endl;
782
1410909
        return nn;
783
      }
784
    }
785
  }
786
950094
  return TNode::null();
787
}
788
789
189927
Node TermDb::evaluateTerm(TNode n,
790
                          bool useEntailmentTests,
791
                          bool reqHasTerm)
792
{
793
379854
  std::map< TNode, Node > visited;
794
379854
  std::vector<Node> exp;
795
379854
  return evaluateTerm2(n, visited, exp, useEntailmentTests, false, reqHasTerm);
796
}
797
798
Node TermDb::evaluateTerm(TNode n,
799
                          std::vector<Node>& exp,
800
                          bool useEntailmentTests,
801
                          bool reqHasTerm)
802
{
803
  std::map<TNode, Node> visited;
804
  return evaluateTerm2(n, visited, exp, useEntailmentTests, true, reqHasTerm);
805
}
806
807
860201
TNode TermDb::getEntailedTerm(TNode n,
808
                              std::map<TNode, TNode>& subs,
809
                              bool subsRep)
810
{
811
860201
  return getEntailedTerm2(n, subs, subsRep, true);
812
}
813
814
104417
TNode TermDb::getEntailedTerm(TNode n)
815
{
816
208834
  std::map< TNode, TNode > subs;
817
208834
  return getEntailedTerm2(n, subs, false, false);
818
}
819
820
2118113
bool TermDb::isEntailed2(
821
    TNode n, std::map<TNode, TNode>& subs, bool subsRep, bool hasSubs, bool pol)
822
{
823
2118113
  Trace("term-db-entail") << "Check entailed : " << n << ", pol = " << pol << std::endl;
824
2118113
  Assert(n.getType().isBoolean());
825
2118113
  if( n.getKind()==EQUAL && !n[0].getType().isBoolean() ){
826
474256
    TNode n1 = getEntailedTerm2(n[0], subs, subsRep, hasSubs);
827
405672
    if( !n1.isNull() ){
828
410178
      TNode n2 = getEntailedTerm2(n[1], subs, subsRep, hasSubs);
829
373633
      if( !n2.isNull() ){
830
337088
        if( n1==n2 ){
831
25045
          return pol;
832
        }else{
833
312043
          Assert(d_qstate.hasTerm(n1));
834
312043
          Assert(d_qstate.hasTerm(n2));
835
312043
          if( pol ){
836
168144
            return d_qstate.areEqual(n1, n2);
837
          }else{
838
143899
            return d_qstate.areDisequal(n1, n2);
839
          }
840
        }
841
      }
842
    }
843
1712441
  }else if( n.getKind()==NOT ){
844
421973
    return isEntailed2(n[0], subs, subsRep, hasSubs, !pol);
845
1290468
  }else if( n.getKind()==OR || n.getKind()==AND ){
846
229723
    bool simPol = ( pol && n.getKind()==OR ) || ( !pol && n.getKind()==AND );
847
742844
    for( unsigned i=0; i<n.getNumChildren(); i++ ){
848
666457
      if (isEntailed2(n[i], subs, subsRep, hasSubs, pol))
849
      {
850
177692
        if( simPol ){
851
64095
          return true;
852
        }
853
      }else{
854
488765
        if( !simPol ){
855
89241
          return false;
856
        }
857
      }
858
    }
859
76387
    return !simPol;
860
  //Boolean equality here
861
1060745
  }else if( n.getKind()==EQUAL || n.getKind()==ITE ){
862
604829
    for( unsigned i=0; i<2; i++ ){
863
433082
      if (isEntailed2(n[0], subs, subsRep, hasSubs, i == 0))
864
      {
865
59320
        unsigned ch = ( n.getKind()==EQUAL || i==0 ) ? 1 : 2;
866
59320
        bool reqPol = ( n.getKind()==ITE || i==0 ) ? pol : !pol;
867
59320
        return isEntailed2(n[ch], subs, subsRep, hasSubs, reqPol);
868
      }
869
    }
870
829678
  }else if( n.getKind()==APPLY_UF ){
871
1099887
    TNode n1 = getEntailedTerm2(n, subs, subsRep, hasSubs);
872
674968
    if( !n1.isNull() ){
873
250049
      Assert(d_qstate.hasTerm(n1));
874
250049
      if( n1==d_true ){
875
        return pol;
876
250049
      }else if( n1==d_false ){
877
        return !pol;
878
      }else{
879
250049
        return d_qstate.getRepresentative(n1) == (pol ? d_true : d_false);
880
      }
881
    }
882
154710
  }else if( n.getKind()==FORALL && !pol ){
883
7888
    return isEntailed2(n[1], subs, subsRep, hasSubs, pol);
884
  }
885
812072
  return false;
886
}
887
888
6108
bool TermDb::isEntailed(TNode n, bool pol)
889
{
890
6108
  Assert(d_consistent_ee);
891
12216
  std::map< TNode, TNode > subs;
892
12216
  return isEntailed2(n, subs, false, false, pol);
893
}
894
895
463698
bool TermDb::isEntailed(TNode n,
896
                        std::map<TNode, TNode>& subs,
897
                        bool subsRep,
898
                        bool pol)
899
{
900
463698
  Assert(d_consistent_ee);
901
463698
  return isEntailed2(n, subs, subsRep, true, pol);
902
}
903
904
4537533
bool TermDb::isTermActive( Node n ) {
905
4537533
  return d_inactive_map.find( n )==d_inactive_map.end();
906
  //return !n.getAttribute(NoMatchAttribute());
907
}
908
909
171742
void TermDb::setTermInactive( Node n ) {
910
171742
  d_inactive_map[n] = true;
911
  //Trace("term-db-debug2") << "set no match attribute" << std::endl;
912
  //NoMatchAttribute nma;
913
  //n.setAttribute(nma,true);
914
171742
}
915
916
4605380
bool TermDb::hasTermCurrent( Node n, bool useMode ) {
917
4605380
  if( !useMode ){
918
    return d_has_map.find( n )!=d_has_map.end();
919
  }
920
  //some assertions are not sent to EE
921
9235095
  if (options::termDbMode() == options::TermDbMode::ALL)
922
  {
923
4605380
    return true;
924
  }
925
  else if (options::termDbMode() == options::TermDbMode::RELEVANT)
926
  {
927
    return d_has_map.find( n )!=d_has_map.end();
928
  }
929
  Assert(false) << "TermDb::hasTermCurrent: Unknown termDbMode : " << options::termDbMode();
930
  return false;
931
}
932
933
851
bool TermDb::isTermEligibleForInstantiation(TNode n, TNode f)
934
{
935
851
  if( options::instMaxLevel()!=-1 ){
936
675
    if( n.hasAttribute(InstLevelAttribute()) ){
937
      int64_t fml =
938
675
          f.isNull() ? -1 : d_qreg.getQuantAttributes().getQuantInstLevel(f);
939
675
      unsigned ml = fml>=0 ? fml : options::instMaxLevel();
940
941
675
      if( n.getAttribute(InstLevelAttribute())>ml ){
942
        Trace("inst-add-debug") << "Term " << n << " has instantiation level " << n.getAttribute(InstLevelAttribute());
943
        Trace("inst-add-debug") << ", which is more than maximum allowed level " << ml << " for this quantified formula." << std::endl;
944
        return false;
945
      }
946
    }else{
947
      if( options::instLevelInputOnly() ){
948
        Trace("inst-add-debug") << "Term " << n << " does not have an instantiation level." << std::endl;
949
        return false;
950
      }
951
    }
952
  }
953
  // it cannot have instantiation constants, which originate from
954
  // counterexample-guided instantiation strategies.
955
851
  return !TermUtil::hasInstConstAttr(n);
956
}
957
958
176
Node TermDb::getEligibleTermInEqc( TNode r ) {
959
176
  if( isTermEligibleForInstantiation( r, TNode::null() ) ){
960
176
    return r;
961
  }else{
962
    std::map< Node, Node >::iterator it = d_term_elig_eqc.find( r );
963
    if( it==d_term_elig_eqc.end() ){
964
      Node h;
965
      eq::EqualityEngine* ee = d_qstate.getEqualityEngine();
966
      eq::EqClassIterator eqc_i = eq::EqClassIterator(r, ee);
967
      while (!eqc_i.isFinished())
968
      {
969
        TNode n = (*eqc_i);
970
        ++eqc_i;
971
        if (isTermEligibleForInstantiation(n, TNode::null()))
972
        {
973
          h = n;
974
          break;
975
        }
976
      }
977
      d_term_elig_eqc[r] = h;
978
      return h;
979
    }else{
980
      return it->second;
981
    }
982
  }
983
}
984
985
void TermDb::setHasTerm( Node n ) {
986
  Trace("term-db-debug2") << "hasTerm : " << n  << std::endl;
987
  if( d_has_map.find( n )==d_has_map.end() ){
988
    d_has_map[n] = true;
989
    for( unsigned i=0; i<n.getNumChildren(); i++ ){
990
      setHasTerm( n[i] );
991
    }
992
  }
993
}
994
995
7066
void TermDb::presolve() {
996
7066
  if (options::incrementalSolving() && !options::termDbCd())
997
  {
998
    d_termsContext.pop();
999
    d_termsContext.push();
1000
  }
1001
7066
}
1002
1003
24335
bool TermDb::reset( Theory::Effort effort ){
1004
24335
  d_op_nonred_count.clear();
1005
24335
  d_arg_reps.clear();
1006
24335
  d_func_map_trie.clear();
1007
24335
  d_func_map_eqc_trie.clear();
1008
24335
  d_func_map_rel_dom.clear();
1009
24335
  d_consistent_ee = true;
1010
1011
24335
  eq::EqualityEngine* ee = d_qstate.getEqualityEngine();
1012
1013
24335
  Assert(ee->consistent());
1014
  // if higher-order, add equalities for the purification terms now
1015
24335
  if (options::ufHo())
1016
  {
1017
2074
    Trace("quant-ho")
1018
1037
        << "TermDb::reset : assert higher-order purify equalities..."
1019
1037
        << std::endl;
1020
4206
    for (std::pair<const Node, Node>& pp : d_ho_purify_to_term)
1021
    {
1022
9507
      if (ee->hasTerm(pp.second)
1023
9507
          && (!ee->hasTerm(pp.first) || !ee->areEqual(pp.second, pp.first)))
1024
      {
1025
1162
        Node eq;
1026
581
        std::map<Node, Node>::iterator itpe = d_ho_purify_to_eq.find(pp.first);
1027
581
        if (itpe == d_ho_purify_to_eq.end())
1028
        {
1029
300
          eq = Rewriter::rewrite(pp.first.eqNode(pp.second));
1030
300
          d_ho_purify_to_eq[pp.first] = eq;
1031
        }
1032
        else
1033
        {
1034
281
          eq = itpe->second;
1035
        }
1036
581
        Trace("quant-ho") << "- assert purify equality : " << eq << std::endl;
1037
581
        ee->assertEquality(eq, true, eq);
1038
581
        if (!ee->consistent())
1039
        {
1040
          // In some rare cases, purification functions (in the domain of
1041
          // d_ho_purify_to_term) may escape the term database. For example,
1042
          // matching algorithms may construct instantiations involving these
1043
          // functions. As a result, asserting these equalities internally may
1044
          // cause a conflict. In this case, we insist that the purification
1045
          // equality is sent out as a lemma here.
1046
          Trace("term-db-lemma")
1047
              << "Purify equality lemma: " << eq << std::endl;
1048
          d_qim->addPendingLemma(eq, InferenceId::UNKNOWN);
1049
          d_qstate.notifyInConflict();
1050
          d_consistent_ee = false;
1051
          return false;
1052
        }
1053
      }
1054
    }
1055
  }
1056
1057
  //compute has map
1058
24335
  if (options::termDbMode() == options::TermDbMode::RELEVANT)
1059
  {
1060
    d_has_map.clear();
1061
    d_term_elig_eqc.clear();
1062
    eq::EqClassesIterator eqcs_i = eq::EqClassesIterator( ee );
1063
    while( !eqcs_i.isFinished() ){
1064
      TNode r = (*eqcs_i);
1065
      bool addedFirst = false;
1066
      Node first;
1067
      //TODO: ignoring singleton eqc isn't enough, need to ensure eqc are relevant
1068
      eq::EqClassIterator eqc_i = eq::EqClassIterator(r, ee);
1069
      while( !eqc_i.isFinished() ){
1070
        TNode n = (*eqc_i);
1071
        if( first.isNull() ){
1072
          first = n;
1073
        }else{
1074
          if( !addedFirst ){
1075
            addedFirst = true;
1076
            setHasTerm( first );
1077
          }
1078
          setHasTerm( n );
1079
        }
1080
        ++eqc_i;
1081
      }
1082
      ++eqcs_i;
1083
    }
1084
    const LogicInfo& logicInfo = d_qstate.getLogicInfo();
1085
    for (TheoryId theoryId = THEORY_FIRST; theoryId < THEORY_LAST; ++theoryId)
1086
    {
1087
      if (!logicInfo.isTheoryEnabled(theoryId))
1088
      {
1089
        continue;
1090
      }
1091
      for (context::CDList<Assertion>::const_iterator
1092
               it = d_qstate.factsBegin(theoryId),
1093
               it_end = d_qstate.factsEnd(theoryId);
1094
           it != it_end;
1095
           ++it)
1096
      {
1097
        setHasTerm((*it).d_assertion);
1098
      }
1099
    }
1100
  }
1101
1102
25372
  if( options::ufHo() && options::hoMergeTermDb() ){
1103
1037
    Trace("quant-ho") << "TermDb::reset : compute equal functions..." << std::endl;
1104
    // build operator representative map
1105
1037
    d_ho_op_rep.clear();
1106
1037
    d_ho_op_slaves.clear();
1107
1037
    eq::EqClassesIterator eqcs_i = eq::EqClassesIterator( ee );
1108
103303
    while( !eqcs_i.isFinished() ){
1109
102266
      TNode r = (*eqcs_i);
1110
51133
      if( r.getType().isFunction() ){
1111
3623
        Trace("quant-ho") << "  process function eqc " << r << std::endl;
1112
7246
        Node first;
1113
3623
        eq::EqClassIterator eqc_i = eq::EqClassIterator(r, ee);
1114
13671
        while( !eqc_i.isFinished() ){
1115
10048
          TNode n = (*eqc_i);
1116
10048
          Node n_use;
1117
5024
          if (n.isVar())
1118
          {
1119
3893
            n_use = n;
1120
          }
1121
          else
1122
          {
1123
            // use its purified variable, if it exists
1124
1131
            std::map<Node, Node>::iterator itp = d_ho_fun_op_purify.find(n);
1125
1131
            if (itp != d_ho_fun_op_purify.end())
1126
            {
1127
1064
              n_use = itp->second;
1128
            }
1129
          }
1130
10048
          Trace("quant-ho") << "  - process " << n_use << ", from " << n
1131
5024
                            << std::endl;
1132
5024
          if (!n_use.isNull() && d_opMap.find(n_use) != d_opMap.end())
1133
          {
1134
4272
            if (first.isNull())
1135
            {
1136
3246
              first = n_use;
1137
3246
              d_ho_op_rep[n_use] = n_use;
1138
            }
1139
            else
1140
            {
1141
2052
              Trace("quant-ho") << "  have : " << n_use << " == " << first
1142
1026
                                << ", type = " << n_use.getType() << std::endl;
1143
1026
              d_ho_op_rep[n_use] = first;
1144
1026
              d_ho_op_slaves[first].push_back(n_use);
1145
            }
1146
          }
1147
5024
          ++eqc_i;
1148
        }
1149
      }
1150
51133
      ++eqcs_i;
1151
    }
1152
1037
    Trace("quant-ho") << "...finished compute equal functions." << std::endl;
1153
  }
1154
1155
24335
  return true;
1156
}
1157
1158
22119
TNodeTrie* TermDb::getTermArgTrie(Node f)
1159
{
1160
22119
  if( options::ufHo() ){
1161
4122
    f = getOperatorRepresentative( f );
1162
  }
1163
22119
  computeUfTerms( f );
1164
22119
  std::map<Node, TNodeTrie>::iterator itut = d_func_map_trie.find(f);
1165
22119
  if( itut!=d_func_map_trie.end() ){
1166
14077
    return &itut->second;
1167
  }else{
1168
8042
    return NULL;
1169
  }
1170
}
1171
1172
2091871
TNodeTrie* TermDb::getTermArgTrie(Node eqc, Node f)
1173
{
1174
2091871
  if( options::ufHo() ){
1175
337204
    f = getOperatorRepresentative( f );
1176
  }
1177
2091871
  computeUfEqcTerms( f );
1178
2091871
  std::map<Node, TNodeTrie>::iterator itut = d_func_map_eqc_trie.find(f);
1179
2091871
  if( itut==d_func_map_eqc_trie.end() ){
1180
    return NULL;
1181
  }else{
1182
2091871
    if( eqc.isNull() ){
1183
1152906
      return &itut->second;
1184
    }else{
1185
      std::map<TNode, TNodeTrie>::iterator itute =
1186
938965
          itut->second.d_data.find(eqc);
1187
938965
      if( itute!=itut->second.d_data.end() ){
1188
544278
        return &itute->second;
1189
      }else{
1190
394687
        return NULL;
1191
      }
1192
    }
1193
  }
1194
}
1195
1196
TNode TermDb::getCongruentTerm( Node f, Node n ) {
1197
  if( options::ufHo() ){
1198
    f = getOperatorRepresentative( f );
1199
  }
1200
  computeUfTerms( f );
1201
  std::map<Node, TNodeTrie>::iterator itut = d_func_map_trie.find(f);
1202
  if( itut!=d_func_map_trie.end() ){
1203
    computeArgReps( n );
1204
    return itut->second.existsTerm( d_arg_reps[n] );
1205
  }else{
1206
    return TNode::null();
1207
  }
1208
}
1209
1210
1565615
TNode TermDb::getCongruentTerm( Node f, std::vector< TNode >& args ) {
1211
1565615
  if( options::ufHo() ){
1212
711891
    f = getOperatorRepresentative( f );
1213
  }
1214
1565615
  computeUfTerms( f );
1215
1565615
  return d_func_map_trie[f].existsTerm( args );
1216
}
1217
1218
268
Node TermDb::getHoTypeMatchPredicate(TypeNode tn)
1219
{
1220
268
  std::map<TypeNode, Node>::iterator ithp = d_ho_type_match_pred.find(tn);
1221
268
  if (ithp != d_ho_type_match_pred.end())
1222
  {
1223
236
    return ithp->second;
1224
  }
1225
32
  NodeManager* nm = NodeManager::currentNM();
1226
32
  SkolemManager* sm = nm->getSkolemManager();
1227
64
  TypeNode ptn = nm->mkFunctionType(tn, nm->booleanType());
1228
64
  Node k = sm->mkDummySkolem("U", ptn, "predicate to force higher-order types");
1229
32
  d_ho_type_match_pred[tn] = k;
1230
32
  return k;
1231
}
1232
1233
}  // namespace quantifiers
1234
}  // namespace theory
1235
4785679
}  // namespace cvc5