GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/quantifiers/ematching/inst_match_generator.cpp Lines: 293 344 85.2 %
Date: 2021-05-22 Branches: 590 1382 42.7 %

Line Exec Source
1
/******************************************************************************
2
 * Top contributors (to current version):
3
 *   Andrew Reynolds, Morgan Deters, 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 inst match generator class.
14
 */
15
16
#include "theory/quantifiers/ematching/inst_match_generator.h"
17
18
#include "expr/dtype_cons.h"
19
#include "options/quantifiers_options.h"
20
#include "theory/datatypes/theory_datatypes_utils.h"
21
#include "theory/quantifiers/ematching/candidate_generator.h"
22
#include "theory/quantifiers/ematching/inst_match_generator_multi.h"
23
#include "theory/quantifiers/ematching/inst_match_generator_multi_linear.h"
24
#include "theory/quantifiers/ematching/inst_match_generator_simple.h"
25
#include "theory/quantifiers/ematching/pattern_term_selector.h"
26
#include "theory/quantifiers/ematching/var_match_generator.h"
27
#include "theory/quantifiers/instantiate.h"
28
#include "theory/quantifiers/quantifiers_state.h"
29
#include "theory/quantifiers/term_database.h"
30
#include "theory/quantifiers/term_registry.h"
31
#include "theory/quantifiers/term_util.h"
32
33
using namespace cvc5::kind;
34
35
namespace cvc5 {
36
namespace theory {
37
namespace quantifiers {
38
namespace inst {
39
40
37426
InstMatchGenerator::InstMatchGenerator(Trigger* tparent, Node pat)
41
37426
    : IMGenerator(tparent)
42
{
43
37426
  d_cg = nullptr;
44
37426
  d_needsReset = true;
45
37426
  d_active_add = true;
46
37426
  Assert(pat.isNull() || quantifiers::TermUtil::hasInstConstAttr(pat));
47
37426
  d_pattern = pat;
48
37426
  d_match_pattern = pat;
49
37426
  if (!pat.isNull())
50
  {
51
36152
    d_match_pattern_type = pat.getType();
52
  }
53
37426
  d_next = nullptr;
54
37426
  d_independent_gen = false;
55
37426
}
56
57
111004
InstMatchGenerator::~InstMatchGenerator()
58
{
59
65272
  for( unsigned i=0; i<d_children.size(); i++ ){
60
27846
    delete d_children[i];
61
  }
62
37426
  delete d_cg;
63
73578
}
64
65
103
void InstMatchGenerator::setActiveAdd(bool val){
66
103
  d_active_add = val;
67
103
  if (d_next != nullptr)
68
  {
69
80
    d_next->setActiveAdd(val);
70
  }
71
103
}
72
73
int InstMatchGenerator::getActiveScore()
74
{
75
  if( d_match_pattern.isNull() ){
76
    return -1;
77
  }
78
  quantifiers::TermDb* tdb = d_treg.getTermDatabase();
79
  if (TriggerTermInfo::isAtomicTrigger(d_match_pattern))
80
  {
81
    Node f = tdb->getMatchOperator(d_match_pattern);
82
    unsigned ngt = tdb->getNumGroundTerms(f);
83
    Trace("trigger-active-sel-debug") << "Number of ground terms for " << f << " is " << ngt << std::endl;
84
    return ngt;
85
  }else if( d_match_pattern.getKind()==INST_CONSTANT ){
86
    TypeNode tn = d_match_pattern.getType();
87
    unsigned ngtt = tdb->getNumTypeGroundTerms(tn);
88
    Trace("trigger-active-sel-debug") << "Number of ground terms for " << tn << " is " << ngtt << std::endl;
89
    return ngtt;
90
  }
91
  return -1;
92
}
93
94
37426
void InstMatchGenerator::initialize(Node q,
95
                                    std::vector<InstMatchGenerator*>& gens)
96
{
97
37426
  if (d_pattern.isNull())
98
  {
99
1274
    gens.insert(gens.end(), d_children.begin(), d_children.end());
100
1274
    return;
101
  }
102
72304
  Trace("inst-match-gen") << "Initialize, pattern term is " << d_pattern
103
36152
                          << std::endl;
104
36152
  if (d_match_pattern.getKind() == NOT)
105
  {
106
2130
    Assert(d_pattern.getKind() == NOT);
107
    // we want to add the children of the NOT
108
2130
    d_match_pattern = d_match_pattern[0];
109
  }
110
111
74434
  if (d_pattern.getKind() == NOT && d_match_pattern.getKind() == EQUAL
112
38282
      && d_match_pattern[0].getKind() == INST_CONSTANT
113
72356
      && d_match_pattern[1].getKind() == INST_CONSTANT)
114
  {
115
    // special case: disequalities between variables x != y will match ground
116
    // disequalities.
117
  }
118
72290
  else if (d_match_pattern.getKind() == EQUAL
119
36145
           || d_match_pattern.getKind() == GEQ)
120
  {
121
    // We are one of the following cases:
122
    //   f(x)~a, f(x)~y, x~a, x~y
123
    // If we are the first or third case, we ensure that f(x)/x is on the left
124
    // hand side of the relation d_pattern, d_match_pattern is f(x)/x and
125
    // d_eq_class_rel (indicating the equivalence class that we are related
126
    // to) is set to a.
127
2153
    for (size_t i = 0; i < 2; i++)
128
    {
129
2161
      Node mp = d_match_pattern[i];
130
2161
      Node mpo = d_match_pattern[1 - i];
131
      // If this side has free variables, and the other side does not or
132
      // it is a free variable, then we will match on this side of the
133
      // relation.
134
6459
      if (quantifiers::TermUtil::hasInstConstAttr(mp)
135
8604
          && (!quantifiers::TermUtil::hasInstConstAttr(mpo)
136
19
              || mpo.getKind() == INST_CONSTANT))
137
      {
138
2145
        if (i == 1)
139
        {
140
8
          if (d_match_pattern.getKind() == GEQ)
141
          {
142
            d_pattern = NodeManager::currentNM()->mkNode(kind::GT, mp, mpo);
143
            d_pattern = d_pattern.negate();
144
          }
145
          else
146
          {
147
16
            d_pattern = NodeManager::currentNM()->mkNode(
148
8
                d_match_pattern.getKind(), mp, mpo);
149
          }
150
        }
151
2145
        d_eq_class_rel = mpo;
152
2145
        d_match_pattern = mp;
153
        // we won't find a term in the other direction
154
2145
        break;
155
      }
156
    }
157
  }
158
36152
  d_match_pattern_type = d_match_pattern.getType();
159
72304
  Trace("inst-match-gen") << "Pattern is " << d_pattern << ", match pattern is "
160
36152
                          << d_match_pattern << std::endl;
161
36152
  quantifiers::TermDb* tdb = d_treg.getTermDatabase();
162
36152
  d_match_pattern_op = tdb->getMatchOperator(d_match_pattern);
163
164
  // now, collect children of d_match_pattern
165
36152
  Kind mpk = d_match_pattern.getKind();
166
36152
  if (mpk == INST_CONSTANT)
167
  {
168
142
    d_children_types.push_back(
169
142
        d_match_pattern.getAttribute(InstVarNumAttribute()));
170
  }
171
  else
172
  {
173
102276
    for (size_t i = 0, size = d_match_pattern.getNumChildren(); i < size; i++)
174
    {
175
132390
      Node pat = d_match_pattern[i];
176
132390
      Node qa = quantifiers::TermUtil::getInstConstAttr(pat);
177
66195
      if (!qa.isNull())
178
      {
179
58586
        if (pat.getKind() == INST_CONSTANT && qa == q)
180
        {
181
33578
          d_children_types.push_back(pat.getAttribute(InstVarNumAttribute()));
182
        }
183
        else
184
        {
185
25008
          InstMatchGenerator* cimg = getInstMatchGenerator(d_tparent, q, pat);
186
25008
          if (cimg)
187
          {
188
25008
            d_children.push_back(cimg);
189
25008
            d_children_index.push_back(i);
190
25008
            d_children_types.push_back(-2);
191
          }
192
          else
193
          {
194
            d_children_types.push_back(-1);
195
          }
196
        }
197
      }
198
      else
199
      {
200
7609
        d_children_types.push_back(-1);
201
      }
202
    }
203
  }
204
205
  // create candidate generator
206
36152
  if (mpk == APPLY_SELECTOR)
207
  {
208
    // candidates for apply selector are a union of correctly and incorrectly
209
    // applied selectors
210
330
    d_cg =
211
165
        new inst::CandidateGeneratorSelector(d_qstate, d_treg, d_match_pattern);
212
  }
213
35987
  else if (TriggerTermInfo::isAtomicTriggerKind(mpk))
214
  {
215
35909
    if (mpk == APPLY_CONSTRUCTOR)
216
    {
217
      // 1-constructors have a trivial way of generating candidates in a
218
      // given equivalence class
219
4867
      const DType& dt = d_match_pattern.getType().getDType();
220
4867
      if (dt.getNumConstructors() == 1)
221
      {
222
5822
        d_cg = new inst::CandidateGeneratorConsExpand(
223
2911
            d_qstate, d_treg, d_match_pattern);
224
      }
225
    }
226
35909
    if (d_cg == nullptr)
227
    {
228
      CandidateGeneratorQE* cg =
229
32998
          new CandidateGeneratorQE(d_qstate, d_treg, d_match_pattern);
230
      // we will be scanning lists trying to find ground terms whose operator
231
      // is the same as d_match_operator's.
232
32998
      d_cg = cg;
233
      // if matching on disequality, inform the candidate generator not to
234
      // match on eqc
235
32998
      if (d_pattern.getKind() == NOT && d_pattern[0].getKind() == EQUAL)
236
      {
237
2078
        cg->excludeEqc(d_eq_class_rel);
238
2078
        d_eq_class_rel = Node::null();
239
      }
240
    }
241
  }
242
78
  else if (mpk == INST_CONSTANT)
243
  {
244
71
    if (d_pattern.getKind() == APPLY_SELECTOR_TOTAL)
245
    {
246
      Node selectorExpr = tdb->getMatchOperator(d_pattern);
247
      size_t selectorIndex = datatypes::utils::cindexOf(selectorExpr);
248
      const DType& dt = datatypes::utils::datatypeOf(selectorExpr);
249
      const DTypeConstructor& c = dt[selectorIndex];
250
      Node cOp = c.getConstructor();
251
      Trace("inst-match-gen")
252
          << "Purify dt trigger " << d_pattern << ", will match terms of op "
253
          << cOp << std::endl;
254
      d_cg = new inst::CandidateGeneratorQE(d_qstate, d_treg, cOp);
255
    }else{
256
71
      d_cg = new CandidateGeneratorQEAll(d_qstate, d_treg, d_match_pattern);
257
    }
258
  }
259
7
  else if (mpk == EQUAL)
260
  {
261
    // we will be producing candidates via literal matching heuristics
262
7
    if (d_pattern.getKind() == NOT)
263
    {
264
      // candidates will be all disequalities
265
14
      d_cg = new inst::CandidateGeneratorQELitDeq(
266
7
          d_qstate, d_treg, d_match_pattern);
267
    }
268
  }
269
  else
270
  {
271
    Trace("inst-match-gen-warn")
272
        << "(?) Unknown matching pattern is " << d_match_pattern << std::endl;
273
  }
274
36152
  gens.insert( gens.end(), d_children.begin(), d_children.end() );
275
}
276
277
/** get match (not modulo equality) */
278
2551135
int InstMatchGenerator::getMatch(Node f, Node t, InstMatch& m)
279
{
280
5102270
  Trace("matching") << "Matching " << t << " against pattern " << d_match_pattern << " ("
281
2551135
                    << m << ")" << ", " << d_children.size() << ", pattern is " << d_pattern << std::endl;
282
2551135
  Assert(!d_match_pattern.isNull());
283
2551135
  if (d_cg == nullptr)
284
  {
285
    Trace("matching-fail") << "Internal error for match generator." << std::endl;
286
    return -2;
287
  }
288
2551135
  bool success = true;
289
5102270
  std::vector<int> prev;
290
  // if t is null
291
2551135
  Assert(!t.isNull());
292
2551135
  Assert(!quantifiers::TermUtil::hasInstConstAttr(t));
293
  // notice that t may have a different kind or operator from our match
294
  // pattern, e.g. for APPLY_SELECTOR triggers.
295
  // first, check if ground arguments are not equal, or a match is in conflict
296
2551135
  Trace("matching-debug2") << "Setting immediate matches..." << std::endl;
297
3691085
  for (size_t i = 0, size = d_match_pattern.getNumChildren(); i < size; i++)
298
  {
299
3251470
    int64_t ct = d_children_types[i];
300
3251470
    if (ct >= 0)
301
    {
302
4082680
      Trace("matching-debug2")
303
2041340
          << "Setting " << ct << " to " << t[i] << "..." << std::endl;
304
2041340
      bool addToPrev = m.get(ct).isNull();
305
2041340
      if (!m.set(d_qstate, ct, t[i]))
306
      {
307
        // match is in conflict
308
2644754
        Trace("matching-fail")
309
1322377
            << "Match fail: " << m.get(ct) << " and " << t[i] << std::endl;
310
1322377
        success = false;
311
3433897
        break;
312
      }
313
718963
      else if (addToPrev)
314
      {
315
671881
        Trace("matching-debug2") << "Success." << std::endl;
316
671881
        prev.push_back(ct);
317
      }
318
    }
319
1210130
    else if (ct == -1)
320
    {
321
815990
      if (!d_qstate.areEqual(d_match_pattern[i], t[i]))
322
      {
323
1578286
        Trace("matching-fail") << "Match fail arg: " << d_match_pattern[i]
324
789143
                               << " and " << t[i] << std::endl;
325
        // ground arguments are not equal
326
789143
        success = false;
327
789143
        break;
328
      }
329
    }
330
  }
331
5102270
  Trace("matching-debug2") << "Done setting immediate matches, success = "
332
2551135
                           << success << "." << std::endl;
333
  // for variable matching
334
2551135
  if (d_match_pattern.getKind() == INST_CONSTANT)
335
  {
336
102
    bool addToPrev = m.get(d_children_types[0]).isNull();
337
102
    if (!m.set(d_qstate, d_children_types[0], t))
338
    {
339
      success = false;
340
    }
341
    else
342
    {
343
102
      if (addToPrev)
344
      {
345
102
        prev.push_back(d_children_types[0]);
346
      }
347
    }
348
  }
349
  // for relational matching
350
2551135
  if (!d_eq_class_rel.isNull() && d_eq_class_rel.getKind() == INST_CONSTANT)
351
  {
352
28
    NodeManager* nm = NodeManager::currentNM();
353
28
    int v = d_eq_class_rel.getAttribute(InstVarNumAttribute());
354
    // also must fit match to equivalence class
355
28
    bool pol = d_pattern.getKind() != NOT;
356
56
    Node pat = d_pattern.getKind() == NOT ? d_pattern[0] : d_pattern;
357
56
    Node t_match;
358
28
    if (pol)
359
    {
360
28
      if (pat.getKind() == GT)
361
      {
362
        t_match = nm->mkNode(MINUS, t, nm->mkConst(Rational(1)));
363
      }else{
364
28
        t_match = t;
365
      }
366
    }
367
    else
368
    {
369
      if (pat.getKind() == EQUAL)
370
      {
371
        if (t.getType().isBoolean())
372
        {
373
          t_match = nm->mkConst(!d_qstate.areEqual(nm->mkConst(true), t));
374
        }
375
        else
376
        {
377
          Assert(t.getType().isReal());
378
          t_match = nm->mkNode(PLUS, t, nm->mkConst(Rational(1)));
379
        }
380
      }
381
      else if (pat.getKind() == GEQ)
382
      {
383
        t_match = nm->mkNode(PLUS, t, nm->mkConst(Rational(1)));
384
      }
385
      else if (pat.getKind() == GT)
386
      {
387
        t_match = t;
388
      }
389
    }
390
28
    if (!t_match.isNull())
391
    {
392
28
      bool addToPrev = m.get(v).isNull();
393
28
      if (!m.set(d_qstate, v, t_match))
394
      {
395
        success = false;
396
      }
397
28
      else if (addToPrev)
398
      {
399
28
        prev.push_back(v);
400
      }
401
    }
402
  }
403
2551135
  int ret_val = -1;
404
2551135
  if (success)
405
  {
406
439615
    Trace("matching-debug2") << "Reset children..." << std::endl;
407
    // now, fit children into match
408
    // we will be requesting candidates for matching terms for each child
409
537129
    for (size_t i = 0, size = d_children.size(); i < size; i++)
410
    {
411
345065
      if (!d_children[i]->reset(t[d_children_index[i]]))
412
      {
413
247551
        success = false;
414
247551
        break;
415
      }
416
    }
417
439615
    if (success)
418
    {
419
192064
      Trace("matching-debug2") << "Continue next " << d_next << std::endl;
420
192064
      ret_val =
421
384128
          continueNextMatch(f, m, InferenceId::QUANTIFIERS_INST_E_MATCHING);
422
    }
423
  }
424
2551135
  if (ret_val < 0)
425
  {
426
3168544
    for (int& pv : prev)
427
    {
428
641860
      m.d_vals[pv] = Node::null();
429
    }
430
  }
431
2551135
  return ret_val;
432
}
433
434
196661
int InstMatchGenerator::continueNextMatch(Node q,
435
                                          InstMatch& m,
436
                                          InferenceId id)
437
{
438
196661
  if( d_next!=NULL ){
439
129095
    return d_next->getNextMatch(q, m);
440
  }
441
67566
  if (d_active_add)
442
  {
443
67258
    return sendInstantiation(m, id) ? 1 : -1;
444
  }
445
308
  return 1;
446
}
447
448
/** reset instantiation round */
449
254586
void InstMatchGenerator::resetInstantiationRound()
450
{
451
254586
  if( !d_match_pattern.isNull() ){
452
245766
    Trace("matching-debug2") << this << " reset instantiation round." << std::endl;
453
245766
    d_needsReset = true;
454
245766
    if( d_cg ){
455
245766
      d_cg->resetInstantiationRound();
456
    }
457
  }
458
254586
  if( d_next ){
459
181781
    d_next->resetInstantiationRound();
460
  }
461
254586
  d_curr_exclude_match.clear();
462
254586
}
463
464
551616
bool InstMatchGenerator::reset(Node eqc)
465
{
466
551616
  if (d_cg == nullptr)
467
  {
468
    // we did not properly initialize the candidate generator, thus we fail
469
    return false;
470
  }
471
551616
  eqc = d_qstate.getRepresentative(eqc);
472
551616
  Trace("matching-debug2") << this << " reset " << eqc << "." << std::endl;
473
551616
  if( !d_eq_class_rel.isNull() && d_eq_class_rel.getKind()!=INST_CONSTANT ){
474
112
    d_eq_class = d_eq_class_rel;
475
551504
  }else if( !eqc.isNull() ){
476
429241
    d_eq_class = eqc;
477
  }
478
  //we have a specific equivalence class in mind
479
  //we are producing matches for f(E) ~ t, where E is a non-ground vector of terms, and t is a ground term
480
  //just look in equivalence class of the RHS
481
551616
  d_cg->reset( d_eq_class );
482
551616
  d_needsReset = false;
483
484
  //generate the first candidate preemptively
485
551616
  d_curr_first_candidate = Node::null();
486
1103232
  Node t;
487
148003
  do {
488
699619
    t = d_cg->getNextCandidate();
489
699619
    if( d_curr_exclude_match.find( t )==d_curr_exclude_match.end() ){
490
551616
      d_curr_first_candidate = t;
491
    }
492
699619
  }while( !t.isNull() && d_curr_first_candidate.isNull() );
493
551616
  Trace("matching-summary") << "Reset " << d_match_pattern << " in " << eqc << " returns " << !d_curr_first_candidate.isNull() << "." << std::endl;
494
495
551616
  return !d_curr_first_candidate.isNull();
496
}
497
498
154693
int InstMatchGenerator::getNextMatch(Node f, InstMatch& m)
499
{
500
154693
  if( d_needsReset ){
501
    Trace("matching") << "Reset not done yet, must do the reset..." << std::endl;
502
    reset(d_eq_class);
503
  }
504
154693
  d_curr_matched = Node::null();
505
154693
  Trace("matching") << this << " " << d_match_pattern << " get next match " << m << " in eq class " << d_eq_class << std::endl;
506
154693
  int success = -1;
507
309386
  Node t = d_curr_first_candidate;
508
2500620
  do{
509
2655313
    Trace("matching-debug2") << "Matching candidate : " << t << std::endl;
510
2655313
    Assert(!d_qstate.isInConflict());
511
    //if t not null, try to fit it into match m
512
2655313
    if( !t.isNull() ){
513
2643522
      if( d_curr_exclude_match.find( t )==d_curr_exclude_match.end() ){
514
2551135
        Assert(t.getType().isComparableTo(d_match_pattern_type));
515
2551135
        Trace("matching-summary") << "Try " << d_match_pattern << " : " << t << std::endl;
516
2551135
        success = getMatch(f, t, m);
517
2551135
        if( d_independent_gen && success<0 ){
518
26983
          Assert(d_eq_class.isNull() || !d_eq_class_rel.isNull());
519
26983
          d_curr_exclude_match[t] = true;
520
        }
521
      }
522
      //get the next candidate term t
523
2643522
      if( success<0 ){
524
2619071
        t = d_qstate.isInConflict() ? Node::null() : d_cg->getNextCandidate();
525
      }else{
526
24451
        d_curr_first_candidate = d_cg->getNextCandidate();
527
      }
528
    }
529
2655313
  }while( success<0 && !t.isNull() );
530
154693
  d_curr_matched = t;
531
154693
  if( success<0 ){
532
130242
    Trace("matching-summary") << "..." << d_match_pattern << " failed, reset." << std::endl;
533
130242
    Trace("matching") << this << " failed, reset " << d_eq_class << std::endl;
534
    //we failed, must reset
535
130242
    reset(d_eq_class);
536
  }else{
537
24451
    Trace("matching-summary") << "..." << d_match_pattern << " success." << std::endl;
538
  }
539
309386
  return success;
540
}
541
542
21929
uint64_t InstMatchGenerator::addInstantiations(Node f)
543
{
544
  //try to add instantiation for each match produced
545
21929
  uint64_t addedLemmas = 0;
546
43858
  InstMatch m( f );
547
41901
  while (getNextMatch(f, m) > 0)
548
  {
549
9986
    if( !d_active_add ){
550
      if (sendInstantiation(m, InferenceId::UNKNOWN))
551
      {
552
        addedLemmas++;
553
        if (d_qstate.isInConflict())
554
        {
555
          break;
556
        }
557
      }
558
    }else{
559
9986
      addedLemmas++;
560
9986
      if (d_qstate.isInConflict())
561
      {
562
        break;
563
      }
564
    }
565
9986
    m.clear();
566
  }
567
  //return number of lemmas added
568
43858
  return addedLemmas;
569
}
570
571
8314
InstMatchGenerator* InstMatchGenerator::mkInstMatchGenerator(Trigger* tparent,
572
                                                             Node q,
573
                                                             Node pat)
574
{
575
16628
  std::vector< Node > pats;
576
8314
  pats.push_back( pat );
577
16628
  std::map< Node, InstMatchGenerator * > pat_map_init;
578
16628
  return mkInstMatchGenerator(tparent, q, pats, pat_map_init);
579
}
580
581
1266
InstMatchGenerator* InstMatchGenerator::mkInstMatchGeneratorMulti(
582
    Trigger* tparent, Node q, std::vector<Node>& pats)
583
{
584
1266
  Assert(pats.size() > 1);
585
  InstMatchGeneratorMultiLinear* imgm =
586
1266
      new InstMatchGeneratorMultiLinear(tparent, q, pats);
587
2532
  std::vector< InstMatchGenerator* > gens;
588
1266
  imgm->initialize(q, gens);
589
1266
  Assert(gens.size() == pats.size());
590
2532
  std::vector< Node > patsn;
591
2532
  std::map< Node, InstMatchGenerator * > pat_map_init;
592
4104
  for (InstMatchGenerator* g : gens)
593
  {
594
5676
    Node pn = g->d_match_pattern;
595
2838
    patsn.push_back( pn );
596
2838
    pat_map_init[pn] = g;
597
  }
598
1266
  imgm->d_next = mkInstMatchGenerator(tparent, q, patsn, pat_map_init);
599
2532
  return imgm;
600
}
601
602
9580
InstMatchGenerator* InstMatchGenerator::mkInstMatchGenerator(
603
    Trigger* tparent,
604
    Node q,
605
    std::vector<Node>& pats,
606
    std::map<Node, InstMatchGenerator*>& pat_map_init)
607
{
608
9580
  size_t pCounter = 0;
609
9580
  InstMatchGenerator* prev = NULL;
610
9580
  InstMatchGenerator* oinit = NULL;
611
31884
  while( pCounter<pats.size() ){
612
11152
    size_t counter = 0;
613
22304
    std::vector< InstMatchGenerator* > gens;
614
    InstMatchGenerator* init;
615
11152
    std::map< Node, InstMatchGenerator * >::iterator iti = pat_map_init.find( pats[pCounter] );
616
11152
    if( iti==pat_map_init.end() ){
617
8314
      init = new InstMatchGenerator(tparent, pats[pCounter]);
618
    }else{
619
2838
      init = iti->second;
620
    }
621
11152
    if(pCounter==0){
622
9580
      oinit = init;
623
    }
624
11152
    gens.push_back(init);
625
    //chain the resulting match generators together
626
83472
    while (counter<gens.size()) {
627
36160
      InstMatchGenerator* curr = gens[counter];
628
36160
      if( prev ){
629
26580
        prev->d_next = curr;
630
      }
631
36160
      curr->initialize(q, gens);
632
36160
      prev = curr;
633
36160
      counter++;
634
    }
635
11152
    pCounter++;
636
  }
637
9580
  return oinit;
638
}
639
640
27846
InstMatchGenerator* InstMatchGenerator::getInstMatchGenerator(Trigger* tparent,
641
                                                              Node q,
642
                                                              Node n)
643
{
644
27846
  if (n.getKind() != INST_CONSTANT)
645
  {
646
55684
    Trace("var-trigger-debug")
647
27842
        << "Is " << n << " a variable trigger?" << std::endl;
648
55676
    Node x;
649
27842
    if (options::purifyTriggers())
650
    {
651
174
      Node xi = PatternTermSelector::getInversionVariable(n);
652
87
      if (!xi.isNull())
653
      {
654
16
        Node qa = quantifiers::TermUtil::getInstConstAttr(xi);
655
8
        if (qa == q)
656
        {
657
8
          x = xi;
658
        }
659
      }
660
    }
661
27842
    if (!x.isNull())
662
    {
663
16
      Node s = PatternTermSelector::getInversion(n, x);
664
      VarMatchGeneratorTermSubs* vmg =
665
8
          new VarMatchGeneratorTermSubs(tparent, x, s);
666
16
      Trace("var-trigger") << "Term substitution trigger : " << n
667
8
                           << ", var = " << x << ", subs = " << s << std::endl;
668
8
      return vmg;
669
    }
670
  }
671
27838
  return new InstMatchGenerator(tparent, n);
672
}
673
674
}  // namespace inst
675
}  // namespace quantifiers
676
}  // namespace theory
677
28194
}  // namespace cvc5