GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/quantifiers/term_database.cpp Lines: 551 676 81.5 %
Date: 2021-08-14 Branches: 1257 2932 42.9 %

Line Exec Source
1
/******************************************************************************
2
 * Top contributors (to current version):
3
 *   Andrew Reynolds, Mathias Preiner, Tim King
4
 *
5
 * This file is part of the cvc5 project.
6
 *
7
 * Copyright (c) 2009-2021 by the authors listed in the file AUTHORS
8
 * in the top-level source directory and their institutional affiliations.
9
 * All rights reserved.  See the file COPYING in the top-level source
10
 * directory for licensing information.
11
 * ****************************************************************************
12
 *
13
 * Implementation of term database class.
14
 */
15
16
#include "theory/quantifiers/term_database.h"
17
18
#include "expr/skolem_manager.h"
19
#include "options/base_options.h"
20
#include "options/quantifiers_options.h"
21
#include "options/smt_options.h"
22
#include "options/theory_options.h"
23
#include "options/uf_options.h"
24
#include "theory/quantifiers/ematching/trigger_term_info.h"
25
#include "theory/quantifiers/quantifiers_attributes.h"
26
#include "theory/quantifiers/quantifiers_inference_manager.h"
27
#include "theory/quantifiers/quantifiers_registry.h"
28
#include "theory/quantifiers/quantifiers_state.h"
29
#include "theory/quantifiers/term_util.h"
30
#include "theory/rewriter.h"
31
#include "theory/uf/equality_engine.h"
32
33
using namespace cvc5::kind;
34
using namespace cvc5::context;
35
36
namespace cvc5 {
37
namespace theory {
38
namespace quantifiers {
39
40
9853
TermDb::TermDb(QuantifiersState& qs, QuantifiersRegistry& qr)
41
    : d_qstate(qs),
42
      d_qim(nullptr),
43
      d_qreg(qr),
44
      d_termsContext(),
45
9853
      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
19706
      d_inactive_map(qs.getSatContext())
52
{
53
9853
  d_consistent_ee = true;
54
9853
  d_true = NodeManager::currentNM()->mkConst(true);
55
9853
  d_false = NodeManager::currentNM()->mkConst(false);
56
9853
  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
9853
}
63
64
19706
TermDb::~TermDb(){
65
66
19706
}
67
68
9853
void TermDb::finishInit(QuantifiersInferenceManager* qim) { d_qim = qim; }
69
70
24969
void TermDb::registerQuantifier( Node q ) {
71
24969
  Assert(q[0].getNumChildren() == d_qreg.getNumInstantiationConstants(q));
72
83637
  for (size_t i = 0, nvars = q[0].getNumChildren(); i < nvars; i++)
73
  {
74
117336
    Node ic = d_qreg.getInstantiationConstant(q, i);
75
58668
    setTermInactive( ic );
76
  }
77
24969
}
78
79
911
size_t TermDb::getNumOperators() const { return d_ops.size(); }
80
81
2046
Node TermDb::getOperator(size_t i) const
82
{
83
2046
  Assert(i < d_ops.size());
84
2046
  return d_ops[i];
85
}
86
87
/** ground terms */
88
458617
size_t TermDb::getNumGroundTerms(Node f) const
89
{
90
458617
  NodeDbListMap::const_iterator it = d_opMap.find(f);
91
458617
  if (it != d_opMap.end())
92
  {
93
442312
    return it->second->d_list.size();
94
  }
95
16305
  return 0;
96
}
97
98
2999711
Node TermDb::getGroundTerm(Node f, size_t i) const
99
{
100
2999711
  NodeDbListMap::const_iterator it = d_opMap.find(f);
101
2999711
  if (it != d_opMap.end())
102
  {
103
2999711
    Assert(i < it->second->d_list.size());
104
2999711
    return it->second->d_list[i];
105
  }
106
  Assert(false);
107
  return Node::null();
108
}
109
110
248
size_t TermDb::getNumTypeGroundTerms(TypeNode tn) const
111
{
112
248
  TypeNodeDbListMap::const_iterator it = d_typeMap.find(tn);
113
248
  if (it != d_typeMap.end())
114
  {
115
239
    return it->second->d_list.size();
116
  }
117
9
  return 0;
118
}
119
120
10246
Node TermDb::getTypeGroundTerm(TypeNode tn, size_t i) const
121
{
122
10246
  TypeNodeDbListMap::const_iterator it = d_typeMap.find(tn);
123
10246
  if (it != d_typeMap.end())
124
  {
125
10246
    Assert(i < it->second->d_list.size());
126
10246
    return it->second->d_list[i];
127
  }
128
  Assert(false);
129
  return Node::null();
130
}
131
132
2485
Node TermDb::getOrMakeTypeGroundTerm(TypeNode tn, bool reqVar)
133
{
134
2485
  TypeNodeDbListMap::const_iterator it = d_typeMap.find(tn);
135
2485
  if (it != d_typeMap.end())
136
  {
137
518
    Assert(!it->second->d_list.empty());
138
518
    if (!reqVar)
139
    {
140
177
      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
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
238
    SkolemManager* sm = NodeManager::currentNM()->getSkolemManager();
159
476
    std::stringstream ss;
160
238
    ss << language::SetLanguage(options::outputLanguage());
161
238
    ss << "e_" << tn;
162
476
    Node k = sm->mkDummySkolem(ss.str(), tn, "is a termDb fresh variable");
163
476
    Trace("mkVar") << "TermDb:: Make variable " << k << " : " << tn
164
238
                   << std::endl;
165
238
    if (options::instMaxLevel() != -1)
166
    {
167
      QuantAttributes::setInstantiationLevelAttr(k, 0);
168
    }
169
238
    d_type_fv[tn] = k;
170
238
    return k;
171
  }
172
1784
  return it->second;
173
}
174
175
4291954
Node TermDb::getMatchOperator( Node n ) {
176
4291954
  Kind k = n.getKind();
177
  //datatype operators may be parametric, always assume they are
178
4291954
  if (k == SELECT || k == STORE || k == UNION || k == INTERSECTION
179
4260359
      || k == SUBSET || k == SETMINUS || k == MEMBER || k == SINGLETON
180
4231455
      || k == APPLY_SELECTOR_TOTAL || k == APPLY_SELECTOR || k == APPLY_TESTER
181
4074044
      || k == SEP_PTO || k == HO_APPLY || k == SEQ_NTH)
182
  {
183
    //since it is parametric, use a particular one as op
184
475730
    TypeNode tn = n[0].getType();
185
475730
    Node op = n.getOperator();
186
237865
    std::map< Node, std::map< TypeNode, Node > >::iterator ito = d_par_op_map.find( op );
187
237865
    if( ito!=d_par_op_map.end() ){
188
229320
      std::map< TypeNode, Node >::iterator it = ito->second.find( tn );
189
229320
      if( it!=ito->second.end() ){
190
228650
        return it->second;
191
      }
192
    }
193
9215
    Trace("par-op") << "Parametric operator : " << k << ", " << n.getOperator() << ", " << tn << " : " << n << std::endl;
194
9215
    d_par_op_map[op][tn] = n;
195
9215
    return n;
196
  }
197
4054089
  else if (inst::TriggerTermInfo::isAtomicTriggerKind(k))
198
  {
199
3858929
    return n.getOperator();
200
  }else{
201
195160
    return Node::null();
202
  }
203
}
204
205
2412068
void TermDb::addTerm(Node n)
206
{
207
2412068
  if (d_processed.find(n) != d_processed.end())
208
  {
209
1429364
    return;
210
  }
211
982704
  d_processed.insert(n);
212
982704
  if (!TermUtil::hasInstConstAttr(n))
213
  {
214
944132
    Trace("term-db-debug") << "register term : " << n << std::endl;
215
944132
    DbList* dlt = getOrMkDbListForType(n.getType());
216
944132
    dlt->d_list.push_back(n);
217
    // if this is an atomic trigger, consider adding it
218
944132
    if (inst::TriggerTermInfo::isAtomicTrigger(n))
219
    {
220
412265
      Trace("term-db") << "register term in db " << n << std::endl;
221
222
824530
      Node op = getMatchOperator(n);
223
412265
      Trace("term-db-debug") << "  match operator is : " << op << std::endl;
224
412265
      DbList* dlo = getOrMkDbListForOp(op);
225
412265
      dlo->d_list.push_back(n);
226
      // If we are higher-order, we may need to register more terms.
227
412265
      if (options::ufHo())
228
      {
229
36588
        addTermHo(n);
230
      }
231
    }
232
  }
233
  else
234
  {
235
38572
    setTermInactive(n);
236
  }
237
982704
  if (!n.isClosure())
238
  {
239
2509623
    for (const Node& nc : n)
240
    {
241
1526941
      addTerm(nc);
242
    }
243
  }
244
}
245
246
944132
DbList* TermDb::getOrMkDbListForType(TypeNode tn)
247
{
248
944132
  TypeNodeDbListMap::iterator it = d_typeMap.find(tn);
249
944132
  if (it != d_typeMap.end())
250
  {
251
919963
    return it->second.get();
252
  }
253
48338
  std::shared_ptr<DbList> dl = std::make_shared<DbList>(d_termsContextUse);
254
24169
  d_typeMap.insert(tn, dl);
255
24169
  return dl.get();
256
}
257
258
472164
DbList* TermDb::getOrMkDbListForOp(TNode op)
259
{
260
472164
  NodeDbListMap::iterator it = d_opMap.find(op);
261
472164
  if (it != d_opMap.end())
262
  {
263
375716
    return it->second.get();
264
  }
265
192896
  std::shared_ptr<DbList> dl = std::make_shared<DbList>(d_termsContextUse);
266
96448
  d_opMap.insert(op, dl);
267
96448
  Assert(op.getKind() != BOUND_VARIABLE);
268
96448
  d_ops.push_back(op);
269
96448
  return dl.get();
270
}
271
272
586038
void TermDb::computeArgReps( TNode n ) {
273
586038
  if (d_arg_reps.find(n) == d_arg_reps.end())
274
  {
275
347349
    eq::EqualityEngine* ee = d_qstate.getEqualityEngine();
276
1106134
    for (const TNode& nc : n)
277
    {
278
1517570
      TNode r = ee->hasTerm(nc) ? ee->getRepresentative(nc) : nc;
279
758785
      d_arg_reps[n].push_back( r );
280
    }
281
  }
282
586038
}
283
284
1780229
void TermDb::computeUfEqcTerms( TNode f ) {
285
1780229
  Assert(f == getOperatorRepresentative(f));
286
1780229
  if (d_func_map_eqc_trie.find(f) != d_func_map_eqc_trie.end())
287
  {
288
1733651
    return;
289
  }
290
46578
  d_func_map_eqc_trie[f].clear();
291
  // get the matchable operators in the equivalence class of f
292
93156
  std::vector<TNode> ops;
293
46578
  ops.push_back(f);
294
46578
  if (options::ufHo())
295
  {
296
1266
    ops.insert(ops.end(), d_ho_op_slaves[f].begin(), d_ho_op_slaves[f].end());
297
  }
298
46578
  eq::EqualityEngine* ee = d_qstate.getEqualityEngine();
299
93253
  for (TNode ff : ops)
300
  {
301
46675
    DbList* dbl = getOrMkDbListForOp(ff);
302
351326
    for (const Node& n : dbl->d_list)
303
    {
304
304651
      if (hasTermCurrent(n) && isTermActive(n))
305
      {
306
286679
        computeArgReps(n);
307
573358
        TNode r = ee->hasTerm(n) ? ee->getRepresentative(n) : TNode(n);
308
286679
        d_func_map_eqc_trie[f].d_data[r].addTerm(n, d_arg_reps[n]);
309
      }
310
    }
311
  }
312
}
313
314
3153522
void TermDb::computeUfTerms( TNode f ) {
315
3153522
  if (d_op_nonred_count.find(f) != d_op_nonred_count.end())
316
  {
317
    // already computed
318
6223707
    return;
319
  }
320
41674
  Assert(f == getOperatorRepresentative(f));
321
41674
  d_op_nonred_count[f] = 0;
322
  // get the matchable operators in the equivalence class of f
323
83337
  std::vector<TNode> ops;
324
41674
  ops.push_back(f);
325
41674
  if (options::ufHo())
326
  {
327
1695
    ops.insert(ops.end(), d_ho_op_slaves[f].begin(), d_ho_op_slaves[f].end());
328
  }
329
41674
  Trace("term-db-debug") << "computeUfTerms for " << f << std::endl;
330
41674
  unsigned congruentCount = 0;
331
41674
  unsigned nonCongruentCount = 0;
332
41674
  unsigned alreadyCongruentCount = 0;
333
41674
  unsigned relevantCount = 0;
334
41674
  NodeManager* nm = NodeManager::currentNM();
335
75769
  for (TNode ff : ops)
336
  {
337
41760
    NodeDbListMap::iterator it = d_opMap.find(ff);
338
41760
    if (it == d_opMap.end())
339
    {
340
      // no terms for this operator
341
7654
      continue;
342
    }
343
34106
    Trace("term-db-debug") << "Adding terms for operator " << ff << std::endl;
344
352629
    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
318534
      if (!hasTermCurrent(n) || !d_qstate.hasTerm(n))
348
      {
349
        Trace("term-db-debug") << n << " is not relevant." << std::endl;
350
80822
        continue;
351
      }
352
353
318534
      relevantCount++;
354
337709
      if (!isTermActive(n))
355
      {
356
19175
        Trace("term-db-debug") << n << " is already redundant." << std::endl;
357
19175
        alreadyCongruentCount++;
358
19175
        continue;
359
      }
360
361
299359
      computeArgReps(n);
362
299359
      Trace("term-db-debug") << "Adding term " << n << " with arg reps : ";
363
957955
      for (unsigned i = 0, size = d_arg_reps[n].size(); i < size; i++)
364
      {
365
658596
        Trace("term-db-debug") << d_arg_reps[n][i] << " ";
366
2634384
        if (std::find(d_func_map_rel_dom[f][i].begin(),
367
1317192
                      d_func_map_rel_dom[f][i].end(),
368
2634384
                      d_arg_reps[n][i])
369
1975788
            == d_func_map_rel_dom[f][i].end())
370
        {
371
238179
          d_func_map_rel_dom[f][i].push_back(d_arg_reps[n][i]);
372
        }
373
      }
374
299359
      Trace("term-db-debug") << std::endl;
375
299359
      Assert(d_qstate.hasTerm(n));
376
598718
      Trace("term-db-debug")
377
299359
          << "  and value : " << d_qstate.getRepresentative(n) << std::endl;
378
537060
      Node at = d_func_map_trie[f].addOrGetTerm(n, d_arg_reps[n]);
379
299359
      Assert(d_qstate.hasTerm(at));
380
299359
      Trace("term-db-debug2") << "...add term returned " << at << std::endl;
381
361006
      if (at != n && d_qstate.areEqual(at, n))
382
      {
383
61647
        setTermInactive(n);
384
61647
        Trace("term-db-debug") << n << " is redundant." << std::endl;
385
61647
        congruentCount++;
386
61647
        continue;
387
      }
388
237712
      if (d_qstate.areDisequal(at, n))
389
      {
390
11
        std::vector<Node> lits;
391
11
        lits.push_back(nm->mkNode(EQUAL, at, n));
392
11
        bool success = true;
393
11
        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
11
        if (success)
415
        {
416
11
          Assert(at.getNumChildren() == n.getNumChildren());
417
41
          for (unsigned k = 0, size = at.getNumChildren(); k < size; k++)
418
          {
419
30
            if (at[k] != n[k])
420
            {
421
18
              lits.push_back(nm->mkNode(EQUAL, at[k], n[k]).negate());
422
            }
423
          }
424
22
          Node lem = lits.size() == 1 ? lits[0] : nm->mkNode(OR, lits);
425
11
          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
11
          d_qim->addPendingLemma(lem, InferenceId::QUANTIFIERS_TDB_DEQ_CONG);
438
11
          d_qstate.notifyInConflict();
439
11
          d_consistent_ee = false;
440
11
          return;
441
        }
442
      }
443
237701
      nonCongruentCount++;
444
237701
      d_op_nonred_count[f]++;
445
    }
446
34095
    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
36588
void TermDb::addTermHo(Node n)
461
{
462
36588
  Assert(options::ufHo());
463
36588
  if (n.getType().isFunction())
464
  {
465
    // nothing special to do with functions
466
437
    return;
467
  }
468
36151
  NodeManager* nm = NodeManager::currentNM();
469
36151
  SkolemManager* sm = nm->getSkolemManager();
470
72302
  Node curr = n;
471
72302
  std::vector<Node> args;
472
86667
  while (curr.getKind() == HO_APPLY)
473
  {
474
25258
    args.insert(args.begin(), curr[1]);
475
25258
    curr = curr[0];
476
25258
    if (!curr.isVar())
477
    {
478
      // purify the term
479
12485
      std::map<Node, Node>::iterator itp = d_ho_fun_op_purify.find(curr);
480
24970
      Node psk;
481
12485
      if (itp == d_ho_fun_op_purify.end())
482
      {
483
197
        psk = sm->mkPurifySkolem(
484
            curr, "pfun", "purify for function operator term indexing");
485
197
        d_ho_fun_op_purify[curr] = psk;
486
        // we do not add it to d_ops since it is an internal operator
487
      }
488
      else
489
      {
490
12288
        psk = itp->second;
491
      }
492
24970
      std::vector<Node> children;
493
12485
      children.push_back(psk);
494
12485
      children.insert(children.end(), args.begin(), args.end());
495
24970
      Node p_n = nm->mkNode(APPLY_UF, children);
496
24970
      Trace("term-db") << "register term in db (via purify) " << p_n
497
12485
                       << std::endl;
498
      // also add this one internally
499
12485
      DbList* dblp = getOrMkDbListForOp(psk);
500
12485
      dblp->d_list.push_back(p_n);
501
      // maintain backwards mapping
502
12485
      d_ho_purify_to_term[p_n] = n;
503
    }
504
  }
505
36151
  if (!args.empty() && curr.isVar())
506
  {
507
    // also add standard application version
508
12773
    args.insert(args.begin(), curr);
509
25546
    Node uf_n = nm->mkNode(APPLY_UF, args);
510
12773
    addTerm(uf_n);
511
  }
512
}
513
514
2196788
Node TermDb::getOperatorRepresentative( TNode op ) const {
515
2196788
  std::map< TNode, TNode >::const_iterator it = d_ho_op_rep.find( op );
516
2196788
  if( it!=d_ho_op_rep.end() ){
517
479386
    return it->second;
518
  }else{
519
1717402
    return op;
520
  }
521
}
522
523
2216873
bool TermDb::inRelevantDomain( TNode f, unsigned i, TNode r ) {
524
2216873
  if( options::ufHo() ){
525
210757
    f = getOperatorRepresentative( f );
526
  }
527
2216873
  computeUfTerms( f );
528
2216873
  Assert(!d_qstate.getEqualityEngine()->hasTerm(r)
529
         || d_qstate.getEqualityEngine()->getRepresentative(r) == r);
530
2216873
  std::map< Node, std::map< unsigned, std::vector< Node > > >::iterator it = d_func_map_rel_dom.find( f );
531
2216873
  if( it != d_func_map_rel_dom.end() ){
532
2192219
    std::map< unsigned, std::vector< Node > >::iterator it2 = it->second.find( i );
533
2192219
    if( it2!=it->second.end() ){
534
2192219
      return std::find( it2->second.begin(), it2->second.end(), r )!=it2->second.end();
535
    }else{
536
      return false;
537
    }
538
  }else{
539
24654
    return false;
540
  }
541
}
542
543
592216
Node TermDb::evaluateTerm2(TNode n,
544
                           std::map<TNode, Node>& visited,
545
                           std::vector<Node>& exp,
546
                           bool useEntailmentTests,
547
                           bool computeExp,
548
                           bool reqHasTerm)
549
{
550
592216
  std::map< TNode, Node >::iterator itv = visited.find( n );
551
592216
  if( itv != visited.end() ){
552
45342
    return itv->second;
553
  }
554
546874
  size_t prevSize = exp.size();
555
546874
  Trace("term-db-eval") << "evaluate term : " << n << std::endl;
556
1093748
  Node ret = n;
557
546874
  if( n.getKind()==FORALL || n.getKind()==BOUND_VARIABLE ){
558
    //do nothing
559
  }
560
544411
  else if (d_qstate.hasTerm(n))
561
  {
562
253850
    Trace("term-db-eval") << "...exists in ee, return rep" << std::endl;
563
253850
    ret = d_qstate.getRepresentative(n);
564
253850
    if (computeExp)
565
    {
566
      if (n != ret)
567
      {
568
        exp.push_back(n.eqNode(ret));
569
      }
570
    }
571
253850
    reqHasTerm = false;
572
  }
573
290561
  else if (n.hasOperator())
574
  {
575
580252
    std::vector<TNode> args;
576
290126
    bool ret_set = false;
577
290126
    Kind k = n.getKind();
578
580252
    std::vector<Node> tempExp;
579
657325
    for (unsigned i = 0, nchild = n.getNumChildren(); i < nchild; i++)
580
    {
581
993308
      TNode c = evaluateTerm2(n[i],
582
                              visited,
583
                              tempExp,
584
                              useEntailmentTests,
585
                              computeExp,
586
863853
                              reqHasTerm);
587
496654
      if (c.isNull())
588
      {
589
92332
        ret = Node::null();
590
92332
        ret_set = true;
591
92332
        break;
592
      }
593
404322
      else if (c == d_true || c == d_false)
594
      {
595
        // short-circuiting
596
197777
        if ((k == AND && c == d_false) || (k == OR && c == d_true))
597
        {
598
32916
          ret = c;
599
32916
          ret_set = true;
600
32916
          reqHasTerm = false;
601
32916
          break;
602
        }
603
164861
        else if (k == ITE && i == 0)
604
        {
605
4207
          ret = evaluateTerm2(n[c == d_true ? 1 : 2],
606
                              visited,
607
                              tempExp,
608
                              useEntailmentTests,
609
                              computeExp,
610
                              reqHasTerm);
611
4207
          ret_set = true;
612
4207
          reqHasTerm = false;
613
4207
          break;
614
        }
615
      }
616
367199
      if (computeExp)
617
      {
618
        exp.insert(exp.end(), tempExp.begin(), tempExp.end());
619
      }
620
367199
      Trace("term-db-eval") << "  child " << i << " : " << c << std::endl;
621
367199
      args.push_back(c);
622
    }
623
290126
    if (ret_set)
624
    {
625
      // if we short circuited
626
129455
      if (computeExp)
627
      {
628
        exp.clear();
629
        exp.insert(exp.end(), tempExp.begin(), tempExp.end());
630
      }
631
    }
632
    else
633
    {
634
      // get the (indexed) operator of n, if it exists
635
321342
      TNode f = getMatchOperator(n);
636
      // if it is an indexed term, return the congruent term
637
160671
      if (!f.isNull())
638
      {
639
        // if f is congruent to a term indexed by this class
640
120758
        TNode nn = getCongruentTerm(f, args);
641
120758
        Trace("term-db-eval") << "  got congruent term " << nn
642
60379
                              << " from DB for " << n << std::endl;
643
60379
        if (!nn.isNull())
644
        {
645
19959
          if (computeExp)
646
          {
647
            Assert(nn.getNumChildren() == n.getNumChildren());
648
            for (unsigned i = 0, nchild = nn.getNumChildren(); i < nchild; i++)
649
            {
650
              if (nn[i] != n[i])
651
              {
652
                exp.push_back(nn[i].eqNode(n[i]));
653
              }
654
            }
655
          }
656
19959
          ret = d_qstate.getRepresentative(nn);
657
19959
          Trace("term-db-eval") << "return rep" << std::endl;
658
19959
          ret_set = true;
659
19959
          reqHasTerm = false;
660
19959
          Assert(!ret.isNull());
661
19959
          if (computeExp)
662
          {
663
            if (n != ret)
664
            {
665
              exp.push_back(nn.eqNode(ret));
666
            }
667
          }
668
        }
669
      }
670
160671
      if( !ret_set ){
671
140712
        Trace("term-db-eval") << "return rewrite" << std::endl;
672
        // a theory symbol or a new UF term
673
140712
        if (n.getMetaKind() == metakind::PARAMETERIZED)
674
        {
675
40281
          args.insert(args.begin(), n.getOperator());
676
        }
677
140712
        ret = NodeManager::currentNM()->mkNode(n.getKind(), args);
678
140712
        ret = Rewriter::rewrite(ret);
679
140712
        if (ret.getKind() == EQUAL)
680
        {
681
16924
          if (d_qstate.areDisequal(ret[0], ret[1]))
682
          {
683
2973
            ret = d_false;
684
          }
685
        }
686
140712
        if (useEntailmentTests)
687
        {
688
1365
          if (ret.getKind() == EQUAL || ret.getKind() == GEQ)
689
          {
690
15
            Valuation& val = d_qstate.getValuation();
691
41
            for (unsigned j = 0; j < 2; j++)
692
            {
693
              std::pair<bool, Node> et = val.entailmentCheck(
694
                  options::TheoryOfMode::THEORY_OF_TYPE_BASED,
695
56
                  j == 0 ? ret : ret.negate());
696
30
              if (et.first)
697
              {
698
4
                ret = j == 0 ? d_true : d_false;
699
4
                if (computeExp)
700
                {
701
                  exp.push_back(et.second);
702
                }
703
4
                break;
704
              }
705
            }
706
          }
707
        }
708
      }
709
    }
710
  }
711
  // must have the term
712
546874
  if (reqHasTerm && !ret.isNull())
713
  {
714
138794
    Kind k = ret.getKind();
715
138794
    if (k != OR && k != AND && k != EQUAL && k != ITE && k != NOT
716
121943
        && k != FORALL)
717
    {
718
121748
      if (!d_qstate.hasTerm(ret))
719
      {
720
38073
        ret = Node::null();
721
      }
722
    }
723
  }
724
1093748
  Trace("term-db-eval") << "evaluated term : " << n << ", got : " << ret
725
546874
                        << ", reqHasTerm = " << reqHasTerm << std::endl;
726
  // clear the explanation if failed
727
546874
  if (computeExp && ret.isNull())
728
  {
729
    exp.resize(prevSize);
730
  }
731
546874
  visited[n] = ret;
732
546874
  return ret;
733
}
734
735
8424864
TNode TermDb::getEntailedTerm2(TNode n,
736
                               std::map<TNode, TNode>& subs,
737
                               bool subsRep,
738
                               bool hasSubs)
739
{
740
8424864
  Trace("term-db-entail") << "get entailed term : " << n << std::endl;
741
8424864
  if (d_qstate.hasTerm(n))
742
  {
743
2626010
    Trace("term-db-entail") << "...exists in ee, return rep " << std::endl;
744
2626010
    return n;
745
5798854
  }else if( n.getKind()==BOUND_VARIABLE ){
746
3495247
    if( hasSubs ){
747
3495247
      std::map< TNode, TNode >::iterator it = subs.find( n );
748
3495247
      if( it!=subs.end() ){
749
2572033
        Trace("term-db-entail") << "...substitution is : " << it->second << std::endl;
750
2572033
        if( subsRep ){
751
348105
          Assert(d_qstate.hasTerm(it->second));
752
348105
          Assert(d_qstate.getRepresentative(it->second) == it->second);
753
2920138
          return it->second;
754
        }
755
2223928
        return getEntailedTerm2(it->second, subs, subsRep, hasSubs);
756
      }
757
    }
758
2303607
  }else if( n.getKind()==ITE ){
759
25465
    for( unsigned i=0; i<2; i++ ){
760
21107
      if (isEntailed2(n[0], subs, subsRep, hasSubs, i == 0))
761
      {
762
7710
        return getEntailedTerm2(n[i == 0 ? 1 : 2], subs, subsRep, hasSubs);
763
      }
764
    }
765
  }else{
766
2291539
    if( n.hasOperator() ){
767
2294550
      TNode f = getMatchOperator( n );
768
2284665
      if( !f.isNull() ){
769
4549560
        std::vector< TNode > args;
770
5157217
        for( unsigned i=0; i<n.getNumChildren(); i++ ){
771
7183844
          TNode c = getEntailedTerm2(n[i], subs, subsRep, hasSubs);
772
4301407
          if( c.isNull() ){
773
1418970
            return TNode::null();
774
          }
775
2882437
          c = d_qstate.getRepresentative(c);
776
2882437
          Trace("term-db-entail") << "  child " << i << " : " << c << std::endl;
777
2882437
          args.push_back( c );
778
        }
779
1711620
        TNode nn = getCongruentTerm(f, args);
780
855810
        Trace("term-db-entail") << "  got congruent term " << nn << " for " << n << std::endl;
781
855810
        return nn;
782
      }
783
    }
784
  }
785
944331
  return TNode::null();
786
}
787
788
91355
Node TermDb::evaluateTerm(TNode n,
789
                          bool useEntailmentTests,
790
                          bool reqHasTerm)
791
{
792
182710
  std::map< TNode, Node > visited;
793
182710
  std::vector<Node> exp;
794
182710
  return evaluateTerm2(n, visited, exp, useEntailmentTests, false, reqHasTerm);
795
}
796
797
Node TermDb::evaluateTerm(TNode n,
798
                          std::vector<Node>& exp,
799
                          bool useEntailmentTests,
800
                          bool reqHasTerm)
801
{
802
  std::map<TNode, Node> visited;
803
  return evaluateTerm2(n, visited, exp, useEntailmentTests, true, reqHasTerm);
804
}
805
806
860201
TNode TermDb::getEntailedTerm(TNode n,
807
                              std::map<TNode, TNode>& subs,
808
                              bool subsRep)
809
{
810
860201
  return getEntailedTerm2(n, subs, subsRep, true);
811
}
812
813
87661
TNode TermDb::getEntailedTerm(TNode n)
814
{
815
175322
  std::map< TNode, TNode > subs;
816
175322
  return getEntailedTerm2(n, subs, false, false);
817
}
818
819
1536962
bool TermDb::isEntailed2(
820
    TNode n, std::map<TNode, TNode>& subs, bool subsRep, bool hasSubs, bool pol)
821
{
822
1536962
  Trace("term-db-entail") << "Check entailed : " << n << ", pol = " << pol << std::endl;
823
1536962
  Assert(n.getType().isBoolean());
824
1536962
  if( n.getKind()==EQUAL && !n[0].getType().isBoolean() ){
825
381087
    TNode n1 = getEntailedTerm2(n[0], subs, subsRep, hasSubs);
826
314923
    if( !n1.isNull() ){
827
315685
      TNode n2 = getEntailedTerm2(n[1], subs, subsRep, hasSubs);
828
282222
      if( !n2.isNull() ){
829
248759
        if( n1==n2 ){
830
22323
          return pol;
831
        }else{
832
226436
          Assert(d_qstate.hasTerm(n1));
833
226436
          Assert(d_qstate.hasTerm(n2));
834
226436
          if( pol ){
835
116750
            return d_qstate.areEqual(n1, n2);
836
          }else{
837
109686
            return d_qstate.areDisequal(n1, n2);
838
          }
839
        }
840
      }
841
    }
842
1222039
  }else if( n.getKind()==NOT ){
843
454067
    return isEntailed2(n[0], subs, subsRep, hasSubs, !pol);
844
767972
  }else if( n.getKind()==OR || n.getKind()==AND ){
845
227071
    bool simPol = ( pol && n.getKind()==OR ) || ( !pol && n.getKind()==AND );
846
774303
    for( unsigned i=0; i<n.getNumChildren(); i++ ){
847
694506
      if (isEntailed2(n[i], subs, subsRep, hasSubs, pol))
848
      {
849
173570
        if( simPol ){
850
62878
          return true;
851
        }
852
      }else{
853
520936
        if( !simPol ){
854
84396
          return false;
855
        }
856
      }
857
    }
858
79797
    return !simPol;
859
  //Boolean equality here
860
540901
  }else if( n.getKind()==EQUAL || n.getKind()==ITE ){
861
78135
    for( unsigned i=0; i<2; i++ ){
862
65085
      if (isEntailed2(n[0], subs, subsRep, hasSubs, i == 0))
863
      {
864
27843
        unsigned ch = ( n.getKind()==EQUAL || i==0 ) ? 1 : 2;
865
27843
        bool reqPol = ( n.getKind()==ITE || i==0 ) ? pol : !pol;
866
27843
        return isEntailed2(n[ch], subs, subsRep, hasSubs, reqPol);
867
      }
868
    }
869
500008
  }else if( n.getKind()==APPLY_UF ){
870
472216
    TNode n1 = getEntailedTerm2(n, subs, subsRep, hasSubs);
871
346812
    if( !n1.isNull() ){
872
221408
      Assert(d_qstate.hasTerm(n1));
873
221408
      if( n1==d_true ){
874
        return pol;
875
221408
      }else if( n1==d_false ){
876
        return !pol;
877
      }else{
878
221408
        return d_qstate.getRepresentative(n1) == (pol ? d_true : d_false);
879
      }
880
    }
881
153196
  }else if( n.getKind()==FORALL && !pol ){
882
4821
    return isEntailed2(n[1], subs, subsRep, hasSubs, pol);
883
  }
884
352993
  return false;
885
}
886
887
3444
bool TermDb::isEntailed(TNode n, bool pol)
888
{
889
3444
  Assert(d_consistent_ee);
890
6888
  std::map< TNode, TNode > subs;
891
6888
  return isEntailed2(n, subs, false, false, pol);
892
}
893
894
266089
bool TermDb::isEntailed(TNode n,
895
                        std::map<TNode, TNode>& subs,
896
                        bool subsRep,
897
                        bool pol)
898
{
899
266089
  Assert(d_consistent_ee);
900
266089
  return isEntailed2(n, subs, subsRep, true, pol);
901
}
902
903
3953475
bool TermDb::isTermActive( Node n ) {
904
3953475
  return d_inactive_map.find( n )==d_inactive_map.end();
905
  //return !n.getAttribute(NoMatchAttribute());
906
}
907
908
158887
void TermDb::setTermInactive( Node n ) {
909
158887
  d_inactive_map[n] = true;
910
  //Trace("term-db-debug2") << "set no match attribute" << std::endl;
911
  //NoMatchAttribute nma;
912
  //n.setAttribute(nma,true);
913
158887
}
914
915
4375631
bool TermDb::hasTermCurrent( Node n, bool useMode ) {
916
4375631
  if( !useMode ){
917
    return d_has_map.find( n )!=d_has_map.end();
918
  }
919
  //some assertions are not sent to EE
920
4375631
  if (options::termDbMode() == options::TermDbMode::ALL)
921
  {
922
4375631
    return true;
923
  }
924
  else if (options::termDbMode() == options::TermDbMode::RELEVANT)
925
  {
926
    return d_has_map.find( n )!=d_has_map.end();
927
  }
928
  Assert(false) << "TermDb::hasTermCurrent: Unknown termDbMode : " << options::termDbMode();
929
  return false;
930
}
931
932
1146
bool TermDb::isTermEligibleForInstantiation(TNode n, TNode f)
933
{
934
1146
  if( options::instMaxLevel()!=-1 ){
935
970
    if( n.hasAttribute(InstLevelAttribute()) ){
936
      int64_t fml =
937
970
          f.isNull() ? -1 : d_qreg.getQuantAttributes().getQuantInstLevel(f);
938
970
      unsigned ml = fml>=0 ? fml : options::instMaxLevel();
939
940
970
      if( n.getAttribute(InstLevelAttribute())>ml ){
941
        Trace("inst-add-debug") << "Term " << n << " has instantiation level " << n.getAttribute(InstLevelAttribute());
942
        Trace("inst-add-debug") << ", which is more than maximum allowed level " << ml << " for this quantified formula." << std::endl;
943
        return false;
944
      }
945
    }else{
946
      if( options::instLevelInputOnly() ){
947
        Trace("inst-add-debug") << "Term " << n << " does not have an instantiation level." << std::endl;
948
        return false;
949
      }
950
    }
951
  }
952
  // it cannot have instantiation constants, which originate from
953
  // counterexample-guided instantiation strategies.
954
1146
  return !TermUtil::hasInstConstAttr(n);
955
}
956
957
176
Node TermDb::getEligibleTermInEqc( TNode r ) {
958
176
  if( isTermEligibleForInstantiation( r, TNode::null() ) ){
959
176
    return r;
960
  }else{
961
    std::map< Node, Node >::iterator it = d_term_elig_eqc.find( r );
962
    if( it==d_term_elig_eqc.end() ){
963
      Node h;
964
      eq::EqualityEngine* ee = d_qstate.getEqualityEngine();
965
      eq::EqClassIterator eqc_i = eq::EqClassIterator(r, ee);
966
      while (!eqc_i.isFinished())
967
      {
968
        TNode n = (*eqc_i);
969
        ++eqc_i;
970
        if (isTermEligibleForInstantiation(n, TNode::null()))
971
        {
972
          h = n;
973
          break;
974
        }
975
      }
976
      d_term_elig_eqc[r] = h;
977
      return h;
978
    }else{
979
      return it->second;
980
    }
981
  }
982
}
983
984
void TermDb::setHasTerm( Node n ) {
985
  Trace("term-db-debug2") << "hasTerm : " << n  << std::endl;
986
  if( d_has_map.find( n )==d_has_map.end() ){
987
    d_has_map[n] = true;
988
    for( unsigned i=0; i<n.getNumChildren(); i++ ){
989
      setHasTerm( n[i] );
990
    }
991
  }
992
}
993
994
8164
void TermDb::presolve() {
995
8164
  if (options::incrementalSolving() && !options::termDbCd())
996
  {
997
    d_termsContext.pop();
998
    d_termsContext.push();
999
  }
1000
8164
}
1001
1002
28528
bool TermDb::reset( Theory::Effort effort ){
1003
28528
  d_op_nonred_count.clear();
1004
28528
  d_arg_reps.clear();
1005
28528
  d_func_map_trie.clear();
1006
28528
  d_func_map_eqc_trie.clear();
1007
28528
  d_func_map_rel_dom.clear();
1008
28528
  d_consistent_ee = true;
1009
1010
28528
  eq::EqualityEngine* ee = d_qstate.getEqualityEngine();
1011
1012
28528
  Assert(ee->consistent());
1013
  // if higher-order, add equalities for the purification terms now
1014
28528
  if (options::ufHo())
1015
  {
1016
1816
    Trace("quant-ho")
1017
908
        << "TermDb::reset : assert higher-order purify equalities..."
1018
908
        << std::endl;
1019
12260
    for (std::pair<const Node, Node>& pp : d_ho_purify_to_term)
1020
    {
1021
34056
      if (ee->hasTerm(pp.second)
1022
34056
          && (!ee->hasTerm(pp.first) || !ee->areEqual(pp.second, pp.first)))
1023
      {
1024
15050
        Node eq;
1025
7525
        std::map<Node, Node>::iterator itpe = d_ho_purify_to_eq.find(pp.first);
1026
7525
        if (itpe == d_ho_purify_to_eq.end())
1027
        {
1028
542
          eq = Rewriter::rewrite(pp.first.eqNode(pp.second));
1029
542
          d_ho_purify_to_eq[pp.first] = eq;
1030
        }
1031
        else
1032
        {
1033
6983
          eq = itpe->second;
1034
        }
1035
7525
        Trace("quant-ho") << "- assert purify equality : " << eq << std::endl;
1036
        // Note that ee may be the central equality engine, in which case this
1037
        // equality is explained trivially with "true", since both sides of
1038
        // eq are HOL and FOL encodings of the same thing.
1039
7525
        ee->assertEquality(eq, true, d_true);
1040
7525
        if (!ee->consistent())
1041
        {
1042
          // In some rare cases, purification functions (in the domain of
1043
          // d_ho_purify_to_term) may escape the term database. For example,
1044
          // matching algorithms may construct instantiations involving these
1045
          // functions. As a result, asserting these equalities internally may
1046
          // cause a conflict. In this case, we insist that the purification
1047
          // equality is sent out as a lemma here.
1048
          Trace("term-db-lemma")
1049
              << "Purify equality lemma: " << eq << std::endl;
1050
          d_qim->addPendingLemma(eq, InferenceId::QUANTIFIERS_HO_PURIFY);
1051
          d_qstate.notifyInConflict();
1052
          d_consistent_ee = false;
1053
          return false;
1054
        }
1055
      }
1056
    }
1057
  }
1058
1059
  //compute has map
1060
28528
  if (options::termDbMode() == options::TermDbMode::RELEVANT)
1061
  {
1062
    d_has_map.clear();
1063
    d_term_elig_eqc.clear();
1064
    eq::EqClassesIterator eqcs_i = eq::EqClassesIterator( ee );
1065
    while( !eqcs_i.isFinished() ){
1066
      TNode r = (*eqcs_i);
1067
      bool addedFirst = false;
1068
      Node first;
1069
      //TODO: ignoring singleton eqc isn't enough, need to ensure eqc are relevant
1070
      eq::EqClassIterator eqc_i = eq::EqClassIterator(r, ee);
1071
      while( !eqc_i.isFinished() ){
1072
        TNode n = (*eqc_i);
1073
        if( first.isNull() ){
1074
          first = n;
1075
        }else{
1076
          if( !addedFirst ){
1077
            addedFirst = true;
1078
            setHasTerm( first );
1079
          }
1080
          setHasTerm( n );
1081
        }
1082
        ++eqc_i;
1083
      }
1084
      ++eqcs_i;
1085
    }
1086
    const LogicInfo& logicInfo = d_qstate.getLogicInfo();
1087
    for (TheoryId theoryId = THEORY_FIRST; theoryId < THEORY_LAST; ++theoryId)
1088
    {
1089
      if (!logicInfo.isTheoryEnabled(theoryId))
1090
      {
1091
        continue;
1092
      }
1093
      for (context::CDList<Assertion>::const_iterator
1094
               it = d_qstate.factsBegin(theoryId),
1095
               it_end = d_qstate.factsEnd(theoryId);
1096
           it != it_end;
1097
           ++it)
1098
      {
1099
        setHasTerm((*it).d_assertion);
1100
      }
1101
    }
1102
  }
1103
1104
28528
  if( options::ufHo() && options::hoMergeTermDb() ){
1105
908
    Trace("quant-ho") << "TermDb::reset : compute equal functions..." << std::endl;
1106
    // build operator representative map
1107
908
    d_ho_op_rep.clear();
1108
908
    d_ho_op_slaves.clear();
1109
908
    eq::EqClassesIterator eqcs_i = eq::EqClassesIterator( ee );
1110
71054
    while( !eqcs_i.isFinished() ){
1111
70146
      TNode r = (*eqcs_i);
1112
35073
      if( r.getType().isFunction() ){
1113
3561
        Trace("quant-ho") << "  process function eqc " << r << std::endl;
1114
7122
        Node first;
1115
3561
        eq::EqClassIterator eqc_i = eq::EqClassIterator(r, ee);
1116
14207
        while( !eqc_i.isFinished() ){
1117
10646
          TNode n = (*eqc_i);
1118
10646
          Node n_use;
1119
5323
          if (n.isVar())
1120
          {
1121
3751
            n_use = n;
1122
          }
1123
          else
1124
          {
1125
            // use its purified variable, if it exists
1126
1572
            std::map<Node, Node>::iterator itp = d_ho_fun_op_purify.find(n);
1127
1572
            if (itp != d_ho_fun_op_purify.end())
1128
            {
1129
1499
              n_use = itp->second;
1130
            }
1131
          }
1132
10646
          Trace("quant-ho") << "  - process " << n_use << ", from " << n
1133
5323
                            << std::endl;
1134
5323
          if (!n_use.isNull() && d_opMap.find(n_use) != d_opMap.end())
1135
          {
1136
4580
            if (first.isNull())
1137
            {
1138
3183
              first = n_use;
1139
3183
              d_ho_op_rep[n_use] = n_use;
1140
            }
1141
            else
1142
            {
1143
2794
              Trace("quant-ho") << "  have : " << n_use << " == " << first
1144
1397
                                << ", type = " << n_use.getType() << std::endl;
1145
1397
              d_ho_op_rep[n_use] = first;
1146
1397
              d_ho_op_slaves[first].push_back(n_use);
1147
            }
1148
          }
1149
5323
          ++eqc_i;
1150
        }
1151
      }
1152
35073
      ++eqcs_i;
1153
    }
1154
908
    Trace("quant-ho") << "...finished compute equal functions." << std::endl;
1155
  }
1156
1157
28528
  return true;
1158
}
1159
1160
20460
TNodeTrie* TermDb::getTermArgTrie(Node f)
1161
{
1162
20460
  if( options::ufHo() ){
1163
1560
    f = getOperatorRepresentative( f );
1164
  }
1165
20460
  computeUfTerms( f );
1166
20460
  std::map<Node, TNodeTrie>::iterator itut = d_func_map_trie.find(f);
1167
20460
  if( itut!=d_func_map_trie.end() ){
1168
12121
    return &itut->second;
1169
  }else{
1170
8339
    return NULL;
1171
  }
1172
}
1173
1174
1780229
TNodeTrie* TermDb::getTermArgTrie(Node eqc, Node f)
1175
{
1176
1780229
  if( options::ufHo() ){
1177
120920
    f = getOperatorRepresentative( f );
1178
  }
1179
1780229
  computeUfEqcTerms( f );
1180
1780229
  std::map<Node, TNodeTrie>::iterator itut = d_func_map_eqc_trie.find(f);
1181
1780229
  if( itut==d_func_map_eqc_trie.end() ){
1182
    return NULL;
1183
  }else{
1184
1780229
    if( eqc.isNull() ){
1185
926003
      return &itut->second;
1186
    }else{
1187
      std::map<TNode, TNodeTrie>::iterator itute =
1188
854226
          itut->second.d_data.find(eqc);
1189
854226
      if( itute!=itut->second.d_data.end() ){
1190
512056
        return &itute->second;
1191
      }else{
1192
342170
        return NULL;
1193
      }
1194
    }
1195
  }
1196
}
1197
1198
TNode TermDb::getCongruentTerm( Node f, Node n ) {
1199
  if( options::ufHo() ){
1200
    f = getOperatorRepresentative( f );
1201
  }
1202
  computeUfTerms( f );
1203
  std::map<Node, TNodeTrie>::iterator itut = d_func_map_trie.find(f);
1204
  if( itut!=d_func_map_trie.end() ){
1205
    computeArgReps( n );
1206
    return itut->second.existsTerm( d_arg_reps[n] );
1207
  }else{
1208
    return TNode::null();
1209
  }
1210
}
1211
1212
916189
TNode TermDb::getCongruentTerm( Node f, std::vector< TNode >& args ) {
1213
916189
  if( options::ufHo() ){
1214
41648
    f = getOperatorRepresentative( f );
1215
  }
1216
916189
  computeUfTerms( f );
1217
916189
  return d_func_map_trie[f].existsTerm( args );
1218
}
1219
1220
268
Node TermDb::getHoTypeMatchPredicate(TypeNode tn)
1221
{
1222
268
  std::map<TypeNode, Node>::iterator ithp = d_ho_type_match_pred.find(tn);
1223
268
  if (ithp != d_ho_type_match_pred.end())
1224
  {
1225
236
    return ithp->second;
1226
  }
1227
32
  NodeManager* nm = NodeManager::currentNM();
1228
32
  SkolemManager* sm = nm->getSkolemManager();
1229
64
  TypeNode ptn = nm->mkFunctionType(tn, nm->booleanType());
1230
64
  Node k = sm->mkDummySkolem("U", ptn, "predicate to force higher-order types");
1231
32
  d_ho_type_match_pred[tn] = k;
1232
32
  return k;
1233
}
1234
1235
}  // namespace quantifiers
1236
}  // namespace theory
1237
29340
}  // namespace cvc5