GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/quantifiers/term_database.cpp Lines: 552 677 81.5 %
Date: 2021-05-22 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
9460
TermDb::TermDb(QuantifiersState& qs, QuantifiersRegistry& qr)
41
    : d_qstate(qs),
42
      d_qim(nullptr),
43
      d_qreg(qr),
44
      d_termsContext(),
45
181473
      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
18920
      d_inactive_map(qs.getSatContext())
52
{
53
9460
  d_consistent_ee = true;
54
9460
  d_true = NodeManager::currentNM()->mkConst(true);
55
9460
  d_false = NodeManager::currentNM()->mkConst(false);
56
9460
  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
9460
}
63
64
18920
TermDb::~TermDb(){
65
66
18920
}
67
68
9460
void TermDb::finishInit(QuantifiersInferenceManager* qim) { d_qim = qim; }
69
70
25053
void TermDb::registerQuantifier( Node q ) {
71
25053
  Assert(q[0].getNumChildren() == d_qreg.getNumInstantiationConstants(q));
72
84037
  for (size_t i = 0, nvars = q[0].getNumChildren(); i < nvars; i++)
73
  {
74
117968
    Node ic = d_qreg.getInstantiationConstant(q, i);
75
58984
    setTermInactive( ic );
76
  }
77
25053
}
78
79
919
size_t TermDb::getNumOperators() const { return d_ops.size(); }
80
81
2048
Node TermDb::getOperator(size_t i) const
82
{
83
2048
  Assert(i < d_ops.size());
84
2048
  return d_ops[i];
85
}
86
87
/** ground terms */
88
549179
size_t TermDb::getNumGroundTerms(Node f) const
89
{
90
549179
  NodeDbListMap::const_iterator it = d_opMap.find(f);
91
549179
  if (it != d_opMap.end())
92
  {
93
532790
    return it->second->d_list.size();
94
  }
95
16389
  return 0;
96
}
97
98
3076055
Node TermDb::getGroundTerm(Node f, size_t i) const
99
{
100
3076055
  NodeDbListMap::const_iterator it = d_opMap.find(f);
101
3076055
  if (it != d_opMap.end())
102
  {
103
3076055
    Assert(i < it->second->d_list.size());
104
3076055
    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
43477
Node TermDb::getTypeGroundTerm(TypeNode tn, size_t i) const
121
{
122
43477
  TypeNodeDbListMap::const_iterator it = d_typeMap.find(tn);
123
43477
  if (it != d_typeMap.end())
124
  {
125
43477
    Assert(i < it->second->d_list.size());
126
43477
    return it->second->d_list[i];
127
  }
128
  Assert(false);
129
  return Node::null();
130
}
131
132
2697
Node TermDb::getOrMakeTypeGroundTerm(TypeNode tn, bool reqVar)
133
{
134
2697
  TypeNodeDbListMap::const_iterator it = d_typeMap.find(tn);
135
2697
  if (it != d_typeMap.end())
136
  {
137
730
    Assert(!it->second->d_list.empty());
138
730
    if (!reqVar)
139
    {
140
383
      return it->second->d_list[0];
141
    }
142
538
    for (const Node& v : it->second->d_list)
143
    {
144
483
      if (v.isVar())
145
      {
146
292
        return v;
147
      }
148
    }
149
  }
150
2022
  return getOrMakeTypeFreshVariable(tn);
151
}
152
153
2022
Node TermDb::getOrMakeTypeFreshVariable(TypeNode tn)
154
{
155
2022
  std::unordered_map<TypeNode, Node>::iterator it = d_type_fv.find(tn);
156
2022
  if (it == d_type_fv.end())
157
  {
158
234
    SkolemManager* sm = NodeManager::currentNM()->getSkolemManager();
159
468
    std::stringstream ss;
160
234
    ss << language::SetLanguage(options::outputLanguage());
161
234
    ss << "e_" << tn;
162
468
    Node k = sm->mkDummySkolem(ss.str(), tn, "is a termDb fresh variable");
163
468
    Trace("mkVar") << "TermDb:: Make variable " << k << " : " << tn
164
234
                   << std::endl;
165
234
    if (options::instMaxLevel() != -1)
166
    {
167
      QuantAttributes::setInstantiationLevelAttr(k, 0);
168
    }
169
234
    d_type_fv[tn] = k;
170
234
    return k;
171
  }
172
1788
  return it->second;
173
}
174
175
5768083
Node TermDb::getMatchOperator( Node n ) {
176
5768083
  Kind k = n.getKind();
177
  //datatype operators may be parametric, always assume they are
178
5768083
  if (k == SELECT || k == STORE || k == UNION || k == INTERSECTION
179
5740624
      || k == SUBSET || k == SETMINUS || k == MEMBER || k == SINGLETON
180
5712359
      || k == APPLY_SELECTOR_TOTAL || k == APPLY_SELECTOR || k == APPLY_TESTER
181
5591519
      || k == SEP_PTO || k == HO_APPLY || k == SEQ_NTH)
182
  {
183
    //since it is parametric, use a particular one as op
184
368426
    TypeNode tn = n[0].getType();
185
368426
    Node op = n.getOperator();
186
184213
    std::map< Node, std::map< TypeNode, Node > >::iterator ito = d_par_op_map.find( op );
187
184213
    if( ito!=d_par_op_map.end() ){
188
176222
      std::map< TypeNode, Node >::iterator it = ito->second.find( tn );
189
176222
      if( it!=ito->second.end() ){
190
175589
        return it->second;
191
      }
192
    }
193
8624
    Trace("par-op") << "Parametric operator : " << k << ", " << n.getOperator() << ", " << tn << " : " << n << std::endl;
194
8624
    d_par_op_map[op][tn] = n;
195
8624
    return n;
196
  }
197
5583870
  else if (inst::TriggerTermInfo::isAtomicTriggerKind(k))
198
  {
199
5384250
    return n.getOperator();
200
  }else{
201
199620
    return Node::null();
202
  }
203
}
204
205
2134199
void TermDb::addTerm(Node n)
206
{
207
2134199
  if (d_processed.find(n) != d_processed.end())
208
  {
209
1275811
    return;
210
  }
211
858388
  d_processed.insert(n);
212
858388
  if (!TermUtil::hasInstConstAttr(n))
213
  {
214
833360
    Trace("term-db-debug") << "register term : " << n << std::endl;
215
833360
    DbList* dlt = getOrMkDbListForType(n.getType());
216
833360
    dlt->d_list.push_back(n);
217
    // if this is an atomic trigger, consider adding it
218
833360
    if (inst::TriggerTermInfo::isAtomicTrigger(n))
219
    {
220
367740
      Trace("term-db") << "register term in db " << n << std::endl;
221
222
735480
      Node op = getMatchOperator(n);
223
367740
      Trace("term-db-debug") << "  match operator is : " << op << std::endl;
224
367740
      DbList* dlo = getOrMkDbListForOp(op);
225
367740
      dlo->d_list.push_back(n);
226
      // If we are higher-order, we may need to register more terms.
227
367740
      if (options::ufHo())
228
      {
229
22972
        addTermHo(n);
230
      }
231
    }
232
  }
233
  else
234
  {
235
25028
    setTermInactive(n);
236
  }
237
858388
  if (!n.isClosure())
238
  {
239
2242132
    for (const Node& nc : n)
240
    {
241
1383766
      addTerm(nc);
242
    }
243
  }
244
}
245
246
833360
DbList* TermDb::getOrMkDbListForType(TypeNode tn)
247
{
248
833360
  TypeNodeDbListMap::iterator it = d_typeMap.find(tn);
249
833360
  if (it != d_typeMap.end())
250
  {
251
810617
    return it->second.get();
252
  }
253
45486
  std::shared_ptr<DbList> dl = std::make_shared<DbList>(d_termsContextUse);
254
22743
  d_typeMap.insert(tn, dl);
255
22743
  return dl.get();
256
}
257
258
419689
DbList* TermDb::getOrMkDbListForOp(TNode op)
259
{
260
419689
  NodeDbListMap::iterator it = d_opMap.find(op);
261
419689
  if (it != d_opMap.end())
262
  {
263
324844
    return it->second.get();
264
  }
265
189690
  std::shared_ptr<DbList> dl = std::make_shared<DbList>(d_termsContextUse);
266
94845
  d_opMap.insert(op, dl);
267
94845
  Assert(op.getKind() != BOUND_VARIABLE);
268
94845
  d_ops.push_back(op);
269
94845
  return dl.get();
270
}
271
272
757460
void TermDb::computeArgReps( TNode n ) {
273
757460
  if (d_arg_reps.find(n) == d_arg_reps.end())
274
  {
275
443651
    eq::EqualityEngine* ee = d_qstate.getEqualityEngine();
276
1335536
    for (const TNode& nc : n)
277
    {
278
1783770
      TNode r = ee->hasTerm(nc) ? ee->getRepresentative(nc) : nc;
279
891885
      d_arg_reps[n].push_back( r );
280
    }
281
  }
282
757460
}
283
284
2092558
void TermDb::computeUfEqcTerms( TNode f ) {
285
2092558
  Assert(f == getOperatorRepresentative(f));
286
2092558
  if (d_func_map_eqc_trie.find(f) != d_func_map_eqc_trie.end())
287
  {
288
2042334
    return;
289
  }
290
50224
  d_func_map_eqc_trie[f].clear();
291
  // get the matchable operators in the equivalence class of f
292
100448
  std::vector<TNode> ops;
293
50224
  ops.push_back(f);
294
50224
  if (options::ufHo())
295
  {
296
1629
    ops.insert(ops.end(), d_ho_op_slaves[f].begin(), d_ho_op_slaves[f].end());
297
  }
298
50224
  eq::EqualityEngine* ee = d_qstate.getEqualityEngine();
299
100543
  for (TNode ff : ops)
300
  {
301
50319
    DbList* dbl = getOrMkDbListForOp(ff);
302
458730
    for (const Node& n : dbl->d_list)
303
    {
304
408411
      if (hasTermCurrent(n) && isTermActive(n))
305
      {
306
371295
        computeArgReps(n);
307
742590
        TNode r = ee->hasTerm(n) ? ee->getRepresentative(n) : TNode(n);
308
371295
        d_func_map_eqc_trie[f].d_data[r].addTerm(n, d_arg_reps[n]);
309
      }
310
    }
311
  }
312
}
313
314
3790175
void TermDb::computeUfTerms( TNode f ) {
315
3790175
  if (d_op_nonred_count.find(f) != d_op_nonred_count.end())
316
  {
317
    // already computed
318
7490822
    return;
319
  }
320
44767
  Assert(f == getOperatorRepresentative(f));
321
44767
  d_op_nonred_count[f] = 0;
322
  // get the matchable operators in the equivalence class of f
323
89528
  std::vector<TNode> ops;
324
44767
  ops.push_back(f);
325
44767
  if (options::ufHo())
326
  {
327
2121
    ops.insert(ops.end(), d_ho_op_slaves[f].begin(), d_ho_op_slaves[f].end());
328
  }
329
44767
  Trace("term-db-debug") << "computeUfTerms for " << f << std::endl;
330
44767
  unsigned congruentCount = 0;
331
44767
  unsigned nonCongruentCount = 0;
332
44767
  unsigned alreadyCongruentCount = 0;
333
44767
  unsigned relevantCount = 0;
334
44767
  NodeManager* nm = NodeManager::currentNM();
335
81392
  for (TNode ff : ops)
336
  {
337
44866
    NodeDbListMap::iterator it = d_opMap.find(ff);
338
44866
    if (it == d_opMap.end())
339
    {
340
      // no terms for this operator
341
8235
      continue;
342
    }
343
36631
    Trace("term-db-debug") << "Adding terms for operator " << ff << std::endl;
344
451545
    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
414920
      if (!hasTermCurrent(n) || !d_qstate.hasTerm(n))
348
      {
349
        Trace("term-db-debug") << n << " is not relevant." << std::endl;
350
117880
        continue;
351
      }
352
353
414920
      relevantCount++;
354
443675
      if (!isTermActive(n))
355
      {
356
28755
        Trace("term-db-debug") << n << " is already redundant." << std::endl;
357
28755
        alreadyCongruentCount++;
358
28755
        continue;
359
      }
360
361
386165
      computeArgReps(n);
362
386165
      Trace("term-db-debug") << "Adding term " << n << " with arg reps : ";
363
1173057
      for (unsigned i = 0, size = d_arg_reps[n].size(); i < size; i++)
364
      {
365
786892
        Trace("term-db-debug") << d_arg_reps[n][i] << " ";
366
3147568
        if (std::find(d_func_map_rel_dom[f][i].begin(),
367
1573784
                      d_func_map_rel_dom[f][i].end(),
368
3147568
                      d_arg_reps[n][i])
369
2360676
            == d_func_map_rel_dom[f][i].end())
370
        {
371
264551
          d_func_map_rel_dom[f][i].push_back(d_arg_reps[n][i]);
372
        }
373
      }
374
386165
      Trace("term-db-debug") << std::endl;
375
386165
      Assert(d_qstate.hasTerm(n));
376
772330
      Trace("term-db-debug")
377
386165
          << "  and value : " << d_qstate.getRepresentative(n) << std::endl;
378
683199
      Node at = d_func_map_trie[f].addOrGetTerm(n, d_arg_reps[n]);
379
386165
      Assert(d_qstate.hasTerm(at));
380
386165
      Trace("term-db-debug2") << "...add term returned " << at << std::endl;
381
475290
      if (at != n && d_qstate.areEqual(at, n))
382
      {
383
89125
        setTermInactive(n);
384
89125
        Trace("term-db-debug") << n << " is redundant." << std::endl;
385
89125
        congruentCount++;
386
89125
        continue;
387
      }
388
297040
      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
297034
      nonCongruentCount++;
444
297034
      d_op_nonred_count[f]++;
445
    }
446
36625
    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
22972
void TermDb::addTermHo(Node n)
461
{
462
22972
  Assert(options::ufHo());
463
22972
  if (n.getType().isFunction())
464
  {
465
    // nothing special to do with functions
466
341
    return;
467
  }
468
22631
  NodeManager* nm = NodeManager::currentNM();
469
22631
  SkolemManager* sm = nm->getSkolemManager();
470
45262
  Node curr = n;
471
45262
  std::vector<Node> args;
472
26787
  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
22631
  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
3381200
Node TermDb::getOperatorRepresentative( TNode op ) const {
516
3381200
  std::map< TNode, TNode >::const_iterator it = d_ho_op_rep.find( op );
517
3381200
  if( it!=d_ho_op_rep.end() ){
518
1558508
    return it->second;
519
  }else{
520
1822692
    return op;
521
  }
522
}
523
524
2186326
bool TermDb::inRelevantDomain( TNode f, unsigned i, TNode r ) {
525
2186326
  if( options::ufHo() ){
526
185001
    f = getOperatorRepresentative( f );
527
  }
528
2186326
  computeUfTerms( f );
529
2186326
  Assert(!d_qstate.getEqualityEngine()->hasTerm(r)
530
         || d_qstate.getEqualityEngine()->getRepresentative(r) == r);
531
2186326
  std::map< Node, std::map< unsigned, std::vector< Node > > >::iterator it = d_func_map_rel_dom.find( f );
532
2186326
  if( it != d_func_map_rel_dom.end() ){
533
2160866
    std::map< unsigned, std::vector< Node > >::iterator it2 = it->second.find( i );
534
2160866
    if( it2!=it->second.end() ){
535
2160866
      return std::find( it2->second.begin(), it2->second.end(), r )!=it2->second.end();
536
    }else{
537
      return false;
538
    }
539
  }else{
540
25460
    return false;
541
  }
542
}
543
544
1106194
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
1106194
  std::map< TNode, Node >::iterator itv = visited.find( n );
552
1106194
  if( itv != visited.end() ){
553
32625
    return itv->second;
554
  }
555
1073569
  size_t prevSize = exp.size();
556
1073569
  Trace("term-db-eval") << "evaluate term : " << n << std::endl;
557
2147138
  Node ret = n;
558
1073569
  if( n.getKind()==FORALL || n.getKind()==BOUND_VARIABLE ){
559
    //do nothing
560
  }
561
1071112
  else if (d_qstate.hasTerm(n))
562
  {
563
449933
    Trace("term-db-eval") << "...exists in ee, return rep" << std::endl;
564
449933
    ret = d_qstate.getRepresentative(n);
565
449933
    if (computeExp)
566
    {
567
      if (n != ret)
568
      {
569
        exp.push_back(n.eqNode(ret));
570
      }
571
    }
572
449933
    reqHasTerm = false;
573
  }
574
621179
  else if (n.hasOperator())
575
  {
576
1241274
    std::vector<TNode> args;
577
620637
    bool ret_set = false;
578
620637
    Kind k = n.getKind();
579
1241274
    std::vector<Node> tempExp;
580
1164244
    for (unsigned i = 0, nchild = n.getNumChildren(); i < nchild; i++)
581
    {
582
1813328
      TNode c = evaluateTerm2(n[i],
583
                              visited,
584
                              tempExp,
585
                              useEntailmentTests,
586
                              computeExp,
587
1450271
                              reqHasTerm);
588
906664
      if (c.isNull())
589
      {
590
316629
        ret = Node::null();
591
316629
        ret_set = true;
592
316629
        break;
593
      }
594
590035
      else if (c == d_true || c == d_false)
595
      {
596
        // short-circuiting
597
235297
        if ((k == AND && c == d_false) || (k == OR && c == d_true))
598
        {
599
38334
          ret = c;
600
38334
          ret_set = true;
601
38334
          reqHasTerm = false;
602
38334
          break;
603
        }
604
196963
        else if (k == ITE && i == 0)
605
        {
606
8094
          ret = evaluateTerm2(n[c == d_true ? 1 : 2],
607
                              visited,
608
                              tempExp,
609
                              useEntailmentTests,
610
                              computeExp,
611
                              reqHasTerm);
612
8094
          ret_set = true;
613
8094
          reqHasTerm = false;
614
8094
          break;
615
        }
616
      }
617
543607
      if (computeExp)
618
      {
619
        exp.insert(exp.end(), tempExp.begin(), tempExp.end());
620
      }
621
543607
      Trace("term-db-eval") << "  child " << i << " : " << c << std::endl;
622
543607
      args.push_back(c);
623
    }
624
620637
    if (ret_set)
625
    {
626
      // if we short circuited
627
363057
      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
515160
      TNode f = getMatchOperator(n);
637
      // if it is an indexed term, return the congruent term
638
257580
      if (!f.isNull())
639
      {
640
        // if f is congruent to a term indexed by this class
641
317350
        TNode nn = getCongruentTerm(f, args);
642
317350
        Trace("term-db-eval") << "  got congruent term " << nn
643
158675
                              << " from DB for " << n << std::endl;
644
158675
        if (!nn.isNull())
645
        {
646
32829
          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
32829
          ret = d_qstate.getRepresentative(nn);
658
32829
          Trace("term-db-eval") << "return rep" << std::endl;
659
32829
          ret_set = true;
660
32829
          reqHasTerm = false;
661
32829
          Assert(!ret.isNull());
662
32829
          if (computeExp)
663
          {
664
            if (n != ret)
665
            {
666
              exp.push_back(nn.eqNode(ret));
667
            }
668
          }
669
        }
670
      }
671
257580
      if( !ret_set ){
672
224751
        Trace("term-db-eval") << "return rewrite" << std::endl;
673
        // a theory symbol or a new UF term
674
224751
        if (n.getMetaKind() == metakind::PARAMETERIZED)
675
        {
676
125707
          args.insert(args.begin(), n.getOperator());
677
        }
678
224751
        ret = NodeManager::currentNM()->mkNode(n.getKind(), args);
679
224751
        ret = Rewriter::rewrite(ret);
680
224751
        if (ret.getKind() == EQUAL)
681
        {
682
4188
          if (d_qstate.areDisequal(ret[0], ret[1]))
683
          {
684
1891
            ret = d_false;
685
          }
686
        }
687
224751
        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
1073569
  if (reqHasTerm && !ret.isNull())
714
  {
715
222934
    Kind k = ret.getKind();
716
222934
    if (k != OR && k != AND && k != EQUAL && k != ITE && k != NOT
717
220287
        && k != FORALL)
718
    {
719
220104
      if (!d_qstate.hasTerm(ret))
720
      {
721
123326
        ret = Node::null();
722
      }
723
    }
724
  }
725
2147138
  Trace("term-db-eval") << "evaluated term : " << n << ", got : " << ret
726
1073569
                        << ", reqHasTerm = " << reqHasTerm << std::endl;
727
  // clear the explanation if failed
728
1073569
  if (computeExp && ret.isNull())
729
  {
730
    exp.resize(prevSize);
731
  }
732
1073569
  visited[n] = ret;
733
1073569
  return ret;
734
}
735
736
10779212
TNode TermDb::getEntailedTerm2(TNode n,
737
                               std::map<TNode, TNode>& subs,
738
                               bool subsRep,
739
                               bool hasSubs)
740
{
741
10779212
  Trace("term-db-entail") << "get entailed term : " << n << std::endl;
742
10779212
  if (d_qstate.hasTerm(n))
743
  {
744
3497802
    Trace("term-db-entail") << "...exists in ee, return rep " << std::endl;
745
3497802
    return n;
746
7281410
  }else if( n.getKind()==BOUND_VARIABLE ){
747
3886971
    if( hasSubs ){
748
3886971
      std::map< TNode, TNode >::iterator it = subs.find( n );
749
3886971
      if( it!=subs.end() ){
750
2959880
        Trace("term-db-entail") << "...substitution is : " << it->second << std::endl;
751
2959880
        if( subsRep ){
752
348105
          Assert(d_qstate.hasTerm(it->second));
753
348105
          Assert(d_qstate.getRepresentative(it->second) == it->second);
754
3307985
          return it->second;
755
        }
756
2611775
        return getEntailedTerm2(it->second, subs, subsRep, hasSubs);
757
      }
758
    }
759
3394439
  }else if( n.getKind()==ITE ){
760
66603
    for( unsigned i=0; i<2; i++ ){
761
61703
      if (isEntailed2(n[0], subs, subsRep, hasSubs, i == 0))
762
      {
763
28408
        return getEntailedTerm2(n[i == 0 ? 1 : 2], subs, subsRep, hasSubs);
764
      }
765
    }
766
  }else{
767
3361131
    if( n.hasOperator() ){
768
3364898
      TNode f = getMatchOperator( n );
769
3353290
      if( !f.isNull() ){
770
6683364
        std::vector< TNode > args;
771
7136140
        for( unsigned i=0; i<n.getNumChildren(); i++ ){
772
9507646
          TNode c = getEntailedTerm2(n[i], subs, subsRep, hasSubs);
773
5713188
          if( c.isNull() ){
774
1918730
            return TNode::null();
775
          }
776
3794458
          c = d_qstate.getRepresentative(c);
777
3794458
          Trace("term-db-entail") << "  child " << i << " : " << c << std::endl;
778
3794458
          args.push_back( c );
779
        }
780
2845904
        TNode nn = getCongruentTerm(f, args);
781
1422952
        Trace("term-db-entail") << "  got congruent term " << nn << " for " << n << std::endl;
782
1422952
        return nn;
783
      }
784
    }
785
  }
786
951440
  return TNode::null();
787
}
788
789
191436
Node TermDb::evaluateTerm(TNode n,
790
                          bool useEntailmentTests,
791
                          bool reqHasTerm)
792
{
793
382872
  std::map< TNode, Node > visited;
794
382872
  std::vector<Node> exp;
795
382872
  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
104586
TNode TermDb::getEntailedTerm(TNode n)
815
{
816
209172
  std::map< TNode, TNode > subs;
817
209172
  return getEntailedTerm2(n, subs, false, false);
818
}
819
820
2123147
bool TermDb::isEntailed2(
821
    TNode n, std::map<TNode, TNode>& subs, bool subsRep, bool hasSubs, bool pol)
822
{
823
2123147
  Trace("term-db-entail") << "Check entailed : " << n << ", pol = " << pol << std::endl;
824
2123147
  Assert(n.getType().isBoolean());
825
2123147
  if( n.getKind()==EQUAL && !n[0].getType().isBoolean() ){
826
478466
    TNode n1 = getEntailedTerm2(n[0], subs, subsRep, hasSubs);
827
407079
    if( !n1.isNull() ){
828
411342
      TNode n2 = getEntailedTerm2(n[1], subs, subsRep, hasSubs);
829
373517
      if( !n2.isNull() ){
830
335692
        if( n1==n2 ){
831
24939
          return pol;
832
        }else{
833
310753
          Assert(d_qstate.hasTerm(n1));
834
310753
          Assert(d_qstate.hasTerm(n2));
835
310753
          if( pol ){
836
167678
            return d_qstate.areEqual(n1, n2);
837
          }else{
838
143075
            return d_qstate.areDisequal(n1, n2);
839
          }
840
        }
841
      }
842
    }
843
1716068
  }else if( n.getKind()==NOT ){
844
418842
    return isEntailed2(n[0], subs, subsRep, hasSubs, !pol);
845
1297226
  }else if( n.getKind()==OR || n.getKind()==AND ){
846
227859
    bool simPol = ( pol && n.getKind()==OR ) || ( !pol && n.getKind()==AND );
847
738631
    for( unsigned i=0; i<n.getNumChildren(); i++ ){
848
662487
      if (isEntailed2(n[i], subs, subsRep, hasSubs, pol))
849
      {
850
176793
        if( simPol ){
851
62931
          return true;
852
        }
853
      }else{
854
485694
        if( !simPol ){
855
88784
          return false;
856
        }
857
      }
858
    }
859
76144
    return !simPol;
860
  //Boolean equality here
861
1069367
  }else if( n.getKind()==EQUAL || n.getKind()==ITE ){
862
613233
    for( unsigned i=0; i<2; i++ ){
863
438532
      if (isEntailed2(n[0], subs, subsRep, hasSubs, i == 0))
864
      {
865
58857
        unsigned ch = ( n.getKind()==EQUAL || i==0 ) ? 1 : 2;
866
58857
        bool reqPol = ( n.getKind()==ITE || i==0 ) ? pol : !pol;
867
58857
        return isEntailed2(n[ch], subs, subsRep, hasSubs, reqPol);
868
      }
869
    }
870
835809
  }else if( n.getKind()==APPLY_UF ){
871
1111331
    TNode n1 = getEntailedTerm2(n, subs, subsRep, hasSubs);
872
680458
    if( !n1.isNull() ){
873
249585
      Assert(d_qstate.hasTerm(n1));
874
249585
      if( n1==d_true ){
875
        return pol;
876
249585
      }else if( n1==d_false ){
877
        return !pol;
878
      }else{
879
249585
        return d_qstate.getRepresentative(n1) == (pol ? d_true : d_false);
880
      }
881
    }
882
155351
  }else if( n.getKind()==FORALL && !pol ){
883
7920
    return isEntailed2(n[1], subs, subsRep, hasSubs, pol);
884
  }
885
824392
  return false;
886
}
887
888
6100
bool TermDb::isEntailed(TNode n, bool pol)
889
{
890
6100
  Assert(d_consistent_ee);
891
12200
  std::map< TNode, TNode > subs;
892
12200
  return isEntailed2(n, subs, false, false, pol);
893
}
894
895
468706
bool TermDb::isEntailed(TNode n,
896
                        std::map<TNode, TNode>& subs,
897
                        bool subsRep,
898
                        bool pol)
899
{
900
468706
  Assert(d_consistent_ee);
901
468706
  return isEntailed2(n, subs, subsRep, true, pol);
902
}
903
904
4563295
bool TermDb::isTermActive( Node n ) {
905
4563295
  return d_inactive_map.find( n )==d_inactive_map.end();
906
  //return !n.getAttribute(NoMatchAttribute());
907
}
908
909
173137
void TermDb::setTermInactive( Node n ) {
910
173137
  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
173137
}
915
916
4660807
bool TermDb::hasTermCurrent( Node n, bool useMode ) {
917
4660807
  if( !useMode ){
918
    return d_has_map.find( n )!=d_has_map.end();
919
  }
920
  //some assertions are not sent to EE
921
9346439
  if (options::termDbMode() == options::TermDbMode::ALL)
922
  {
923
4660807
    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
7331
void TermDb::presolve() {
996
7331
  if (options::incrementalSolving() && !options::termDbCd())
997
  {
998
    d_termsContext.pop();
999
    d_termsContext.push();
1000
  }
1001
7331
}
1002
1003
24825
bool TermDb::reset( Theory::Effort effort ){
1004
24825
  d_op_nonred_count.clear();
1005
24825
  d_arg_reps.clear();
1006
24825
  d_func_map_trie.clear();
1007
24825
  d_func_map_eqc_trie.clear();
1008
24825
  d_func_map_rel_dom.clear();
1009
24825
  d_consistent_ee = true;
1010
1011
24825
  eq::EqualityEngine* ee = d_qstate.getEqualityEngine();
1012
1013
24825
  Assert(ee->consistent());
1014
  // if higher-order, add equalities for the purification terms now
1015
24825
  if (options::ufHo())
1016
  {
1017
2066
    Trace("quant-ho")
1018
1033
        << "TermDb::reset : assert higher-order purify equalities..."
1019
1033
        << std::endl;
1020
4202
    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
24825
  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
25858
  if( options::ufHo() && options::hoMergeTermDb() ){
1103
1033
    Trace("quant-ho") << "TermDb::reset : compute equal functions..." << std::endl;
1104
    // build operator representative map
1105
1033
    d_ho_op_rep.clear();
1106
1033
    d_ho_op_slaves.clear();
1107
1033
    eq::EqClassesIterator eqcs_i = eq::EqClassesIterator( ee );
1108
103085
    while( !eqcs_i.isFinished() ){
1109
102052
      TNode r = (*eqcs_i);
1110
51026
      if( r.getType().isFunction() ){
1111
3619
        Trace("quant-ho") << "  process function eqc " << r << std::endl;
1112
7238
        Node first;
1113
3619
        eq::EqClassIterator eqc_i = eq::EqClassIterator(r, ee);
1114
13659
        while( !eqc_i.isFinished() ){
1115
10040
          TNode n = (*eqc_i);
1116
10040
          Node n_use;
1117
5020
          if (n.isVar())
1118
          {
1119
3889
            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
10040
          Trace("quant-ho") << "  - process " << n_use << ", from " << n
1131
5020
                            << std::endl;
1132
5020
          if (!n_use.isNull() && d_opMap.find(n_use) != d_opMap.end())
1133
          {
1134
4270
            if (first.isNull())
1135
            {
1136
3244
              first = n_use;
1137
3244
              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
5020
          ++eqc_i;
1148
        }
1149
      }
1150
51026
      ++eqcs_i;
1151
    }
1152
1033
    Trace("quant-ho") << "...finished compute equal functions." << std::endl;
1153
  }
1154
1155
24825
  return true;
1156
}
1157
1158
22222
TNodeTrie* TermDb::getTermArgTrie(Node f)
1159
{
1160
22222
  if( options::ufHo() ){
1161
4122
    f = getOperatorRepresentative( f );
1162
  }
1163
22222
  computeUfTerms( f );
1164
22222
  std::map<Node, TNodeTrie>::iterator itut = d_func_map_trie.find(f);
1165
22222
  if( itut!=d_func_map_trie.end() ){
1166
14126
    return &itut->second;
1167
  }else{
1168
8096
    return NULL;
1169
  }
1170
}
1171
1172
2092558
TNodeTrie* TermDb::getTermArgTrie(Node eqc, Node f)
1173
{
1174
2092558
  if( options::ufHo() ){
1175
329612
    f = getOperatorRepresentative( f );
1176
  }
1177
2092558
  computeUfEqcTerms( f );
1178
2092558
  std::map<Node, TNodeTrie>::iterator itut = d_func_map_eqc_trie.find(f);
1179
2092558
  if( itut==d_func_map_eqc_trie.end() ){
1180
    return NULL;
1181
  }else{
1182
2092558
    if( eqc.isNull() ){
1183
1150795
      return &itut->second;
1184
    }else{
1185
      std::map<TNode, TNodeTrie>::iterator itute =
1186
941763
          itut->second.d_data.find(eqc);
1187
941763
      if( itute!=itut->second.d_data.end() ){
1188
545992
        return &itute->second;
1189
      }else{
1190
395771
        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
1581627
TNode TermDb::getCongruentTerm( Node f, std::vector< TNode >& args ) {
1211
1581627
  if( options::ufHo() ){
1212
725140
    f = getOperatorRepresentative( f );
1213
  }
1214
1581627
  computeUfTerms( f );
1215
1581627
  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
4886872
}  // namespace cvc5