GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/quantifiers/term_database.cpp Lines: 551 676 81.5 %
Date: 2021-08-17 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
9850
TermDb::TermDb(QuantifiersState& qs, QuantifiersRegistry& qr)
41
    : d_qstate(qs),
42
      d_qim(nullptr),
43
      d_qreg(qr),
44
      d_termsContext(),
45
9850
      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
19700
      d_inactive_map(qs.getSatContext())
52
{
53
9850
  d_consistent_ee = true;
54
9850
  d_true = NodeManager::currentNM()->mkConst(true);
55
9850
  d_false = NodeManager::currentNM()->mkConst(false);
56
9850
  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
9850
}
63
64
19700
TermDb::~TermDb(){
65
66
19700
}
67
68
9850
void TermDb::finishInit(QuantifiersInferenceManager* qim) { d_qim = qim; }
69
70
24970
void TermDb::registerQuantifier( Node q ) {
71
24970
  Assert(q[0].getNumChildren() == d_qreg.getNumInstantiationConstants(q));
72
83641
  for (size_t i = 0, nvars = q[0].getNumChildren(); i < nvars; i++)
73
  {
74
117342
    Node ic = d_qreg.getInstantiationConstant(q, i);
75
58671
    setTermInactive( ic );
76
  }
77
24970
}
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
459616
size_t TermDb::getNumGroundTerms(Node f) const
89
{
90
459616
  NodeDbListMap::const_iterator it = d_opMap.find(f);
91
459616
  if (it != d_opMap.end())
92
  {
93
443311
    return it->second->d_list.size();
94
  }
95
16305
  return 0;
96
}
97
98
3000765
Node TermDb::getGroundTerm(Node f, size_t i) const
99
{
100
3000765
  NodeDbListMap::const_iterator it = d_opMap.find(f);
101
3000765
  if (it != d_opMap.end())
102
  {
103
3000765
    Assert(i < it->second->d_list.size());
104
3000765
    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
4305148
Node TermDb::getMatchOperator( Node n ) {
176
4305148
  Kind k = n.getKind();
177
  //datatype operators may be parametric, always assume they are
178
4305148
  if (k == SELECT || k == STORE || k == UNION || k == INTERSECTION
179
4273553
      || k == SUBSET || k == SETMINUS || k == MEMBER || k == SINGLETON
180
4244649
      || k == APPLY_SELECTOR_TOTAL || k == APPLY_SELECTOR || k == APPLY_TESTER
181
4086142
      || k == SEP_PTO || k == HO_APPLY || k == SEQ_NTH)
182
  {
183
    //since it is parametric, use a particular one as op
184
477922
    TypeNode tn = n[0].getType();
185
477922
    Node op = n.getOperator();
186
238961
    std::map< Node, std::map< TypeNode, Node > >::iterator ito = d_par_op_map.find( op );
187
238961
    if( ito!=d_par_op_map.end() ){
188
230416
      std::map< TypeNode, Node >::iterator it = ito->second.find( tn );
189
230416
      if( it!=ito->second.end() ){
190
229746
        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
4066187
  else if (inst::TriggerTermInfo::isAtomicTriggerKind(k))
198
  {
199
3870983
    return n.getOperator();
200
  }else{
201
195204
    return Node::null();
202
  }
203
}
204
205
2426552
void TermDb::addTerm(Node n)
206
{
207
2426552
  if (d_processed.find(n) != d_processed.end())
208
  {
209
1438063
    return;
210
  }
211
988489
  d_processed.insert(n);
212
988489
  if (!TermUtil::hasInstConstAttr(n))
213
  {
214
949917
    Trace("term-db-debug") << "register term : " << n << std::endl;
215
949917
    DbList* dlt = getOrMkDbListForType(n.getType());
216
949917
    dlt->d_list.push_back(n);
217
    // if this is an atomic trigger, consider adding it
218
949917
    if (inst::TriggerTermInfo::isAtomicTrigger(n))
219
    {
220
417331
      Trace("term-db") << "register term in db " << n << std::endl;
221
222
834662
      Node op = getMatchOperator(n);
223
417331
      Trace("term-db-debug") << "  match operator is : " << op << std::endl;
224
417331
      DbList* dlo = getOrMkDbListForOp(op);
225
417331
      dlo->d_list.push_back(n);
226
      // If we are higher-order, we may need to register more terms.
227
417331
      if (options::ufHo())
228
      {
229
36588
        addTermHo(n);
230
      }
231
    }
232
  }
233
  else
234
  {
235
38572
    setTermInactive(n);
236
  }
237
988489
  if (!n.isClosure())
238
  {
239
2524104
    for (const Node& nc : n)
240
    {
241
1535637
      addTerm(nc);
242
    }
243
  }
244
}
245
246
949917
DbList* TermDb::getOrMkDbListForType(TypeNode tn)
247
{
248
949917
  TypeNodeDbListMap::iterator it = d_typeMap.find(tn);
249
949917
  if (it != d_typeMap.end())
250
  {
251
925750
    return it->second.get();
252
  }
253
48334
  std::shared_ptr<DbList> dl = std::make_shared<DbList>(d_termsContextUse);
254
24167
  d_typeMap.insert(tn, dl);
255
24167
  return dl.get();
256
}
257
258
477236
DbList* TermDb::getOrMkDbListForOp(TNode op)
259
{
260
477236
  NodeDbListMap::iterator it = d_opMap.find(op);
261
477236
  if (it != d_opMap.end())
262
  {
263
380788
    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
588622
void TermDb::computeArgReps( TNode n ) {
273
588622
  if (d_arg_reps.find(n) == d_arg_reps.end())
274
  {
275
348650
    eq::EqualityEngine* ee = d_qstate.getEqualityEngine();
276
1109866
    for (const TNode& nc : n)
277
    {
278
1522432
      TNode r = ee->hasTerm(nc) ? ee->getRepresentative(nc) : nc;
279
761216
      d_arg_reps[n].push_back( r );
280
    }
281
  }
282
588622
}
283
284
1783150
void TermDb::computeUfEqcTerms( TNode f ) {
285
1783150
  Assert(f == getOperatorRepresentative(f));
286
1783150
  if (d_func_map_eqc_trie.find(f) != d_func_map_eqc_trie.end())
287
  {
288
1736566
    return;
289
  }
290
46584
  d_func_map_eqc_trie[f].clear();
291
  // get the matchable operators in the equivalence class of f
292
93168
  std::vector<TNode> ops;
293
46584
  ops.push_back(f);
294
46584
  if (options::ufHo())
295
  {
296
1266
    ops.insert(ops.end(), d_ho_op_slaves[f].begin(), d_ho_op_slaves[f].end());
297
  }
298
46584
  eq::EqualityEngine* ee = d_qstate.getEqualityEngine();
299
93265
  for (TNode ff : ops)
300
  {
301
46681
    DbList* dbl = getOrMkDbListForOp(ff);
302
352685
    for (const Node& n : dbl->d_list)
303
    {
304
306004
      if (hasTermCurrent(n) && isTermActive(n))
305
      {
306
287977
        computeArgReps(n);
307
575954
        TNode r = ee->hasTerm(n) ? ee->getRepresentative(n) : TNode(n);
308
287977
        d_func_map_eqc_trie[f].d_data[r].addTerm(n, d_arg_reps[n]);
309
      }
310
    }
311
  }
312
}
313
314
3166128
void TermDb::computeUfTerms( TNode f ) {
315
3166128
  if (d_op_nonred_count.find(f) != d_op_nonred_count.end())
316
  {
317
    // already computed
318
6248907
    return;
319
  }
320
41680
  Assert(f == getOperatorRepresentative(f));
321
41680
  d_op_nonred_count[f] = 0;
322
  // get the matchable operators in the equivalence class of f
323
83349
  std::vector<TNode> ops;
324
41680
  ops.push_back(f);
325
41680
  if (options::ufHo())
326
  {
327
1695
    ops.insert(ops.end(), d_ho_op_slaves[f].begin(), d_ho_op_slaves[f].end());
328
  }
329
41680
  Trace("term-db-debug") << "computeUfTerms for " << f << std::endl;
330
41680
  unsigned congruentCount = 0;
331
41680
  unsigned nonCongruentCount = 0;
332
41680
  unsigned alreadyCongruentCount = 0;
333
41680
  unsigned relevantCount = 0;
334
41680
  NodeManager* nm = NodeManager::currentNM();
335
75781
  for (TNode ff : ops)
336
  {
337
41766
    NodeDbListMap::iterator it = d_opMap.find(ff);
338
41766
    if (it == d_opMap.end())
339
    {
340
      // no terms for this operator
341
7654
      continue;
342
    }
343
34112
    Trace("term-db-debug") << "Adding terms for operator " << ff << std::endl;
344
353976
    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
319875
      if (!hasTermCurrent(n) || !d_qstate.hasTerm(n))
348
      {
349
        Trace("term-db-debug") << n << " is not relevant." << std::endl;
350
81134
        continue;
351
      }
352
353
319875
      relevantCount++;
354
339105
      if (!isTermActive(n))
355
      {
356
19230
        Trace("term-db-debug") << n << " is already redundant." << std::endl;
357
19230
        alreadyCongruentCount++;
358
19230
        continue;
359
      }
360
361
300645
      computeArgReps(n);
362
300645
      Trace("term-db-debug") << "Adding term " << n << " with arg reps : ";
363
961657
      for (unsigned i = 0, size = d_arg_reps[n].size(); i < size; i++)
364
      {
365
661012
        Trace("term-db-debug") << d_arg_reps[n][i] << " ";
366
2644048
        if (std::find(d_func_map_rel_dom[f][i].begin(),
367
1322024
                      d_func_map_rel_dom[f][i].end(),
368
2644048
                      d_arg_reps[n][i])
369
1983036
            == d_func_map_rel_dom[f][i].end())
370
        {
371
238737
          d_func_map_rel_dom[f][i].push_back(d_arg_reps[n][i]);
372
        }
373
      }
374
300645
      Trace("term-db-debug") << std::endl;
375
300645
      Assert(d_qstate.hasTerm(n));
376
601290
      Trace("term-db-debug")
377
300645
          << "  and value : " << d_qstate.getRepresentative(n) << std::endl;
378
539375
      Node at = d_func_map_trie[f].addOrGetTerm(n, d_arg_reps[n]);
379
300645
      Assert(d_qstate.hasTerm(at));
380
300645
      Trace("term-db-debug2") << "...add term returned " << at << std::endl;
381
362549
      if (at != n && d_qstate.areEqual(at, n))
382
      {
383
61904
        setTermInactive(n);
384
61904
        Trace("term-db-debug") << n << " is redundant." << std::endl;
385
61904
        congruentCount++;
386
61904
        continue;
387
      }
388
238741
      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
238730
      nonCongruentCount++;
444
238730
      d_op_nonred_count[f]++;
445
    }
446
34101
    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
2199715
Node TermDb::getOperatorRepresentative( TNode op ) const {
515
2199715
  std::map< TNode, TNode >::const_iterator it = d_ho_op_rep.find( op );
516
2199715
  if( it!=d_ho_op_rep.end() ){
517
479386
    return it->second;
518
  }else{
519
1720329
    return op;
520
  }
521
}
522
523
2225720
bool TermDb::inRelevantDomain( TNode f, unsigned i, TNode r ) {
524
2225720
  if( options::ufHo() ){
525
210757
    f = getOperatorRepresentative( f );
526
  }
527
2225720
  computeUfTerms( f );
528
2225720
  Assert(!d_qstate.getEqualityEngine()->hasTerm(r)
529
         || d_qstate.getEqualityEngine()->getRepresentative(r) == r);
530
2225720
  std::map< Node, std::map< unsigned, std::vector< Node > > >::iterator it = d_func_map_rel_dom.find( f );
531
2225720
  if( it != d_func_map_rel_dom.end() ){
532
2201066
    std::map< unsigned, std::vector< Node > >::iterator it2 = it->second.find( i );
533
2201066
    if( it2!=it->second.end() ){
534
2201066
      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
594711
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
594711
  std::map< TNode, Node >::iterator itv = visited.find( n );
551
594711
  if( itv != visited.end() ){
552
45523
    return itv->second;
553
  }
554
549188
  size_t prevSize = exp.size();
555
549188
  Trace("term-db-eval") << "evaluate term : " << n << std::endl;
556
1098376
  Node ret = n;
557
549188
  if( n.getKind()==FORALL || n.getKind()==BOUND_VARIABLE ){
558
    //do nothing
559
  }
560
546725
  else if (d_qstate.hasTerm(n))
561
  {
562
255092
    Trace("term-db-eval") << "...exists in ee, return rep" << std::endl;
563
255092
    ret = d_qstate.getRepresentative(n);
564
255092
    if (computeExp)
565
    {
566
      if (n != ret)
567
      {
568
        exp.push_back(n.eqNode(ret));
569
      }
570
    }
571
255092
    reqHasTerm = false;
572
  }
573
291633
  else if (n.hasOperator())
574
  {
575
582396
    std::vector<TNode> args;
576
291198
    bool ret_set = false;
577
291198
    Kind k = n.getKind();
578
582396
    std::vector<Node> tempExp;
579
659884
    for (unsigned i = 0, nchild = n.getNumChildren(); i < nchild; i++)
580
    {
581
997190
      TNode c = evaluateTerm2(n[i],
582
                              visited,
583
                              tempExp,
584
                              useEntailmentTests,
585
                              computeExp,
586
867281
                              reqHasTerm);
587
498595
      if (c.isNull())
588
      {
589
92786
        ret = Node::null();
590
92786
        ret_set = true;
591
92786
        break;
592
      }
593
405809
      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
368686
      if (computeExp)
617
      {
618
        exp.insert(exp.end(), tempExp.begin(), tempExp.end());
619
      }
620
368686
      Trace("term-db-eval") << "  child " << i << " : " << c << std::endl;
621
368686
      args.push_back(c);
622
    }
623
291198
    if (ret_set)
624
    {
625
      // if we short circuited
626
129909
      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
322578
      TNode f = getMatchOperator(n);
636
      // if it is an indexed term, return the congruent term
637
161289
      if (!f.isNull())
638
      {
639
        // if f is congruent to a term indexed by this class
640
121918
        TNode nn = getCongruentTerm(f, args);
641
121918
        Trace("term-db-eval") << "  got congruent term " << nn
642
60959
                              << " from DB for " << n << std::endl;
643
60959
        if (!nn.isNull())
644
        {
645
20262
          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
20262
          ret = d_qstate.getRepresentative(nn);
657
20262
          Trace("term-db-eval") << "return rep" << std::endl;
658
20262
          ret_set = true;
659
20262
          reqHasTerm = false;
660
20262
          Assert(!ret.isNull());
661
20262
          if (computeExp)
662
          {
663
            if (n != ret)
664
            {
665
              exp.push_back(nn.eqNode(ret));
666
            }
667
          }
668
        }
669
      }
670
161289
      if( !ret_set ){
671
141027
        Trace("term-db-eval") << "return rewrite" << std::endl;
672
        // a theory symbol or a new UF term
673
141027
        if (n.getMetaKind() == metakind::PARAMETERIZED)
674
        {
675
40558
          args.insert(args.begin(), n.getOperator());
676
        }
677
141027
        ret = NodeManager::currentNM()->mkNode(n.getKind(), args);
678
141027
        ret = Rewriter::rewrite(ret);
679
141027
        if (ret.getKind() == EQUAL)
680
        {
681
16929
          if (d_qstate.areDisequal(ret[0], ret[1]))
682
          {
683
2973
            ret = d_false;
684
          }
685
        }
686
141027
        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
549188
  if (reqHasTerm && !ret.isNull())
713
  {
714
139109
    Kind k = ret.getKind();
715
139109
    if (k != OR && k != AND && k != EQUAL && k != ITE && k != NOT
716
122253
        && k != FORALL)
717
    {
718
122058
      if (!d_qstate.hasTerm(ret))
719
      {
720
38350
        ret = Node::null();
721
      }
722
    }
723
  }
724
1098376
  Trace("term-db-eval") << "evaluated term : " << n << ", got : " << ret
725
549188
                        << ", reqHasTerm = " << reqHasTerm << std::endl;
726
  // clear the explanation if failed
727
549188
  if (computeExp && ret.isNull())
728
  {
729
    exp.resize(prevSize);
730
  }
731
549188
  visited[n] = ret;
732
549188
  return ret;
733
}
734
735
8437929
TNode TermDb::getEntailedTerm2(TNode n,
736
                               std::map<TNode, TNode>& subs,
737
                               bool subsRep,
738
                               bool hasSubs)
739
{
740
8437929
  Trace("term-db-entail") << "get entailed term : " << n << std::endl;
741
8437929
  if (d_qstate.hasTerm(n))
742
  {
743
2630788
    Trace("term-db-entail") << "...exists in ee, return rep " << std::endl;
744
2630788
    return n;
745
5807141
  }else if( n.getKind()==BOUND_VARIABLE ){
746
3500129
    if( hasSubs ){
747
3500129
      std::map< TNode, TNode >::iterator it = subs.find( n );
748
3500129
      if( it!=subs.end() ){
749
2576915
        Trace("term-db-entail") << "...substitution is : " << it->second << std::endl;
750
2576915
        if( subsRep ){
751
348105
          Assert(d_qstate.hasTerm(it->second));
752
348105
          Assert(d_qstate.getRepresentative(it->second) == it->second);
753
2925020
          return it->second;
754
        }
755
2228810
        return getEntailedTerm2(it->second, subs, subsRep, hasSubs);
756
      }
757
    }
758
2307012
  }else if( n.getKind()==ITE ){
759
26008
    for( unsigned i=0; i<2; i++ ){
760
21469
      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
2294763
    if( n.hasOperator() ){
767
2297774
      TNode f = getMatchOperator( n );
768
2287889
      if( !f.isNull() ){
769
4556008
        std::vector< TNode > args;
770
5166721
        for( unsigned i=0; i<n.getNumChildren(); i++ ){
771
7196449
          TNode c = getEntailedTerm2(n[i], subs, subsRep, hasSubs);
772
4307732
          if( c.isNull() ){
773
1419015
            return TNode::null();
774
          }
775
2888717
          c = d_qstate.getRepresentative(c);
776
2888717
          Trace("term-db-entail") << "  child " << i << " : " << c << std::endl;
777
2888717
          args.push_back( c );
778
        }
779
1717978
        TNode nn = getCongruentTerm(f, args);
780
858989
        Trace("term-db-entail") << "  got congruent term " << nn << " for " << n << std::endl;
781
858989
        return nn;
782
      }
783
    }
784
  }
785
944512
  return TNode::null();
786
}
787
788
91909
Node TermDb::evaluateTerm(TNode n,
789
                          bool useEntailmentTests,
790
                          bool reqHasTerm)
791
{
792
183818
  std::map< TNode, Node > visited;
793
183818
  std::vector<Node> exp;
794
183818
  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
1538264
bool TermDb::isEntailed2(
820
    TNode n, std::map<TNode, TNode>& subs, bool subsRep, bool hasSubs, bool pol)
821
{
822
1538264
  Trace("term-db-entail") << "Check entailed : " << n << ", pol = " << pol << std::endl;
823
1538264
  Assert(n.getType().isBoolean());
824
1538264
  if( n.getKind()==EQUAL && !n[0].getType().isBoolean() ){
825
382970
    TNode n1 = getEntailedTerm2(n[0], subs, subsRep, hasSubs);
826
316071
    if( !n1.isNull() ){
827
316900
      TNode n2 = getEntailedTerm2(n[1], subs, subsRep, hasSubs);
828
283036
      if( !n2.isNull() ){
829
249172
        if( n1==n2 ){
830
22343
          return pol;
831
        }else{
832
226829
          Assert(d_qstate.hasTerm(n1));
833
226829
          Assert(d_qstate.hasTerm(n2));
834
226829
          if( pol ){
835
116868
            return d_qstate.areEqual(n1, n2);
836
          }else{
837
109961
            return d_qstate.areDisequal(n1, n2);
838
          }
839
        }
840
      }
841
    }
842
1222193
  }else if( n.getKind()==NOT ){
843
454015
    return isEntailed2(n[0], subs, subsRep, hasSubs, !pol);
844
768178
  }else if( n.getKind()==OR || n.getKind()==AND ){
845
227019
    bool simPol = ( pol && n.getKind()==OR ) || ( !pol && n.getKind()==AND );
846
774147
    for( unsigned i=0; i<n.getNumChildren(); i++ ){
847
694402
      if (isEntailed2(n[i], subs, subsRep, hasSubs, pol))
848
      {
849
173570
        if( simPol ){
850
62878
          return true;
851
        }
852
      }else{
853
520832
        if( !simPol ){
854
84396
          return false;
855
        }
856
      }
857
    }
858
79745
    return !simPol;
859
  //Boolean equality here
860
541159
  }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
500266
  }else if( n.getKind()==APPLY_UF ){
870
472008
    TNode n1 = getEntailedTerm2(n, subs, subsRep, hasSubs);
871
346708
    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
153558
  }else if( n.getKind()==FORALL && !pol ){
882
4821
    return isEntailed2(n[1], subs, subsRep, hasSubs, pol);
883
  }
884
353986
  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
267185
bool TermDb::isEntailed(TNode n,
895
                        std::map<TNode, TNode>& subs,
896
                        bool subsRep,
897
                        bool pol)
898
{
899
267185
  Assert(d_consistent_ee);
900
267185
  return isEntailed2(n, subs, subsRep, true, pol);
901
}
902
903
3960371
bool TermDb::isTermActive( Node n ) {
904
3960371
  return d_inactive_map.find( n )==d_inactive_map.end();
905
  //return !n.getAttribute(NoMatchAttribute());
906
}
907
908
159147
void TermDb::setTermInactive( Node n ) {
909
159147
  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
159147
}
914
915
4380463
bool TermDb::hasTermCurrent( Node n, bool useMode ) {
916
4380463
  if( !useMode ){
917
    return d_has_map.find( n )!=d_has_map.end();
918
  }
919
  //some assertions are not sent to EE
920
4380463
  if (options::termDbMode() == options::TermDbMode::ALL)
921
  {
922
4380463
    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
8163
void TermDb::presolve() {
995
8163
  if (options::incrementalSolving() && !options::termDbCd())
996
  {
997
    d_termsContext.pop();
998
    d_termsContext.push();
999
  }
1000
8163
}
1001
1002
28536
bool TermDb::reset( Theory::Effort effort ){
1003
28536
  d_op_nonred_count.clear();
1004
28536
  d_arg_reps.clear();
1005
28536
  d_func_map_trie.clear();
1006
28536
  d_func_map_eqc_trie.clear();
1007
28536
  d_func_map_rel_dom.clear();
1008
28536
  d_consistent_ee = true;
1009
1010
28536
  eq::EqualityEngine* ee = d_qstate.getEqualityEngine();
1011
1012
28536
  Assert(ee->consistent());
1013
  // if higher-order, add equalities for the purification terms now
1014
28536
  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
28536
  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
28536
  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
28536
  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
1783150
TNodeTrie* TermDb::getTermArgTrie(Node eqc, Node f)
1175
{
1176
1783150
  if( options::ufHo() ){
1177
120920
    f = getOperatorRepresentative( f );
1178
  }
1179
1783150
  computeUfEqcTerms( f );
1180
1783150
  std::map<Node, TNodeTrie>::iterator itut = d_func_map_eqc_trie.find(f);
1181
1783150
  if( itut==d_func_map_eqc_trie.end() ){
1182
    return NULL;
1183
  }else{
1184
1783150
    if( eqc.isNull() ){
1185
927973
      return &itut->second;
1186
    }else{
1187
      std::map<TNode, TNodeTrie>::iterator itute =
1188
855177
          itut->second.d_data.find(eqc);
1189
855177
      if( itute!=itut->second.d_data.end() ){
1190
512596
        return &itute->second;
1191
      }else{
1192
342581
        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
919948
TNode TermDb::getCongruentTerm( Node f, std::vector< TNode >& args ) {
1213
919948
  if( options::ufHo() ){
1214
41648
    f = getOperatorRepresentative( f );
1215
  }
1216
919948
  computeUfTerms( f );
1217
919948
  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
29337
}  // namespace cvc5