GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/quantifiers/ematching/inst_match_generator.cpp Lines: 293 344 85.2 %
Date: 2021-08-01 Branches: 591 1382 42.8 %

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
35949
InstMatchGenerator::InstMatchGenerator(Trigger* tparent, Node pat)
41
35949
    : IMGenerator(tparent)
42
{
43
35949
  d_cg = nullptr;
44
35949
  d_needsReset = true;
45
35949
  d_active_add = true;
46
35949
  Assert(pat.isNull() || quantifiers::TermUtil::hasInstConstAttr(pat));
47
35949
  d_pattern = pat;
48
35949
  d_match_pattern = pat;
49
35949
  if (!pat.isNull())
50
  {
51
34731
    d_match_pattern_type = pat.getType();
52
  }
53
35949
  d_next = nullptr;
54
35949
  d_independent_gen = false;
55
35949
}
56
57
106629
InstMatchGenerator::~InstMatchGenerator()
58
{
59
62679
  for( unsigned i=0; i<d_children.size(); i++ ){
60
26730
    delete d_children[i];
61
  }
62
35949
  delete d_cg;
63
70680
}
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
35949
void InstMatchGenerator::initialize(Node q,
95
                                    std::vector<InstMatchGenerator*>& gens)
96
{
97
35949
  if (d_pattern.isNull())
98
  {
99
1218
    gens.insert(gens.end(), d_children.begin(), d_children.end());
100
1218
    return;
101
  }
102
69462
  Trace("inst-match-gen") << "Initialize, pattern term is " << d_pattern
103
34731
                          << std::endl;
104
34731
  if (d_match_pattern.getKind() == NOT)
105
  {
106
2120
    Assert(d_pattern.getKind() == NOT);
107
    // we want to add the children of the NOT
108
2120
    d_match_pattern = d_match_pattern[0];
109
  }
110
111
71582
  if (d_pattern.getKind() == NOT && d_match_pattern.getKind() == EQUAL
112
36851
      && d_match_pattern[0].getKind() == INST_CONSTANT
113
69514
      && d_match_pattern[1].getKind() == INST_CONSTANT)
114
  {
115
    // special case: disequalities between variables x != y will match ground
116
    // disequalities.
117
  }
118
69448
  else if (d_match_pattern.getKind() == EQUAL
119
34724
           || 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
2143
    for (size_t i = 0; i < 2; i++)
128
    {
129
2151
      Node mp = d_match_pattern[i];
130
2151
      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
6429
      if (quantifiers::TermUtil::hasInstConstAttr(mp)
135
8564
          && (!quantifiers::TermUtil::hasInstConstAttr(mpo)
136
19
              || mpo.getKind() == INST_CONSTANT))
137
      {
138
2135
        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
2135
        d_eq_class_rel = mpo;
152
2135
        d_match_pattern = mp;
153
        // we won't find a term in the other direction
154
2135
        break;
155
      }
156
    }
157
  }
158
34731
  d_match_pattern_type = d_match_pattern.getType();
159
69462
  Trace("inst-match-gen") << "Pattern is " << d_pattern << ", match pattern is "
160
34731
                          << d_match_pattern << std::endl;
161
34731
  quantifiers::TermDb* tdb = d_treg.getTermDatabase();
162
34731
  d_match_pattern_op = tdb->getMatchOperator(d_match_pattern);
163
164
  // now, collect children of d_match_pattern
165
34731
  Kind mpk = d_match_pattern.getKind();
166
34731
  if (mpk == INST_CONSTANT)
167
  {
168
142
    d_children_types.push_back(
169
142
        d_match_pattern.getAttribute(InstVarNumAttribute()));
170
  }
171
  else
172
  {
173
97981
    for (size_t i = 0, size = d_match_pattern.getNumChildren(); i < size; i++)
174
    {
175
126642
      Node pat = d_match_pattern[i];
176
126642
      Node qa = quantifiers::TermUtil::getInstConstAttr(pat);
177
63321
      if (!qa.isNull())
178
      {
179
56525
        if (pat.getKind() == INST_CONSTANT && qa == q)
180
        {
181
32493
          d_children_types.push_back(pat.getAttribute(InstVarNumAttribute()));
182
        }
183
        else
184
        {
185
24032
          InstMatchGenerator* cimg = getInstMatchGenerator(d_tparent, q, pat);
186
24032
          if (cimg)
187
          {
188
24032
            d_children.push_back(cimg);
189
24032
            d_children_index.push_back(i);
190
24032
            d_children_types.push_back(-2);
191
          }
192
          else
193
          {
194
            d_children_types.push_back(-1);
195
          }
196
        }
197
      }
198
      else
199
      {
200
6796
        d_children_types.push_back(-1);
201
      }
202
    }
203
  }
204
205
  // create candidate generator
206
34731
  if (mpk == APPLY_SELECTOR)
207
  {
208
    // candidates for apply selector are a union of correctly and incorrectly
209
    // applied selectors
210
442
    d_cg =
211
221
        new inst::CandidateGeneratorSelector(d_qstate, d_treg, d_match_pattern);
212
  }
213
34510
  else if (TriggerTermInfo::isAtomicTriggerKind(mpk))
214
  {
215
34432
    if (mpk == APPLY_CONSTRUCTOR)
216
    {
217
      // 1-constructors have a trivial way of generating candidates in a
218
      // given equivalence class
219
4904
      const DType& dt = d_match_pattern.getType().getDType();
220
4904
      if (dt.getNumConstructors() == 1)
221
      {
222
5822
        d_cg = new inst::CandidateGeneratorConsExpand(
223
2911
            d_qstate, d_treg, d_match_pattern);
224
      }
225
    }
226
34432
    if (d_cg == nullptr)
227
    {
228
      CandidateGeneratorQE* cg =
229
31521
          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
31521
      d_cg = cg;
233
      // if matching on disequality, inform the candidate generator not to
234
      // match on eqc
235
31521
      if (d_pattern.getKind() == NOT && d_pattern[0].getKind() == EQUAL)
236
      {
237
2068
        cg->excludeEqc(d_eq_class_rel);
238
2068
        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
34731
  gens.insert( gens.end(), d_children.begin(), d_children.end() );
275
}
276
277
/** get match (not modulo equality) */
278
2388124
int InstMatchGenerator::getMatch(Node f, Node t, InstMatch& m)
279
{
280
4776248
  Trace("matching") << "Matching " << t << " against pattern " << d_match_pattern << " ("
281
2388124
                    << m << ")" << ", " << d_children.size() << ", pattern is " << d_pattern << std::endl;
282
2388124
  Assert(!d_match_pattern.isNull());
283
2388124
  if (d_cg == nullptr)
284
  {
285
    Trace("matching-fail") << "Internal error for match generator." << std::endl;
286
    return -2;
287
  }
288
2388124
  bool success = true;
289
4776248
  std::vector<int> prev;
290
  // if t is null
291
2388124
  Assert(!t.isNull());
292
2388124
  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
2388124
  Trace("matching-debug2") << "Setting immediate matches..." << std::endl;
297
3380653
  for (size_t i = 0, size = d_match_pattern.getNumChildren(); i < size; i++)
298
  {
299
3011683
    int64_t ct = d_children_types[i];
300
3011683
    if (ct >= 0)
301
    {
302
3901612
      Trace("matching-debug2")
303
1950806
          << "Setting " << ct << " to " << t[i] << "..." << std::endl;
304
1950806
      bool addToPrev = m.get(ct).isNull();
305
1950806
      if (!m.set(d_qstate, ct, t[i]))
306
      {
307
        // match is in conflict
308
2609574
        Trace("matching-fail")
309
1304787
            << "Match fail: " << m.get(ct) << " and " << t[i] << std::endl;
310
1304787
        success = false;
311
3323941
        break;
312
      }
313
646019
      else if (addToPrev)
314
      {
315
599779
        Trace("matching-debug2") << "Success." << std::endl;
316
599779
        prev.push_back(ct);
317
      }
318
    }
319
1060877
    else if (ct == -1)
320
    {
321
739683
      if (!d_qstate.areEqual(d_match_pattern[i], t[i]))
322
      {
323
1428734
        Trace("matching-fail") << "Match fail arg: " << d_match_pattern[i]
324
714367
                               << " and " << t[i] << std::endl;
325
        // ground arguments are not equal
326
714367
        success = false;
327
714367
        break;
328
      }
329
    }
330
  }
331
4776248
  Trace("matching-debug2") << "Done setting immediate matches, success = "
332
2388124
                           << success << "." << std::endl;
333
  // for variable matching
334
2388124
  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
2388124
  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
2388124
  int ret_val = -1;
404
2388124
  if (success)
405
  {
406
368970
    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
449579
    for (size_t i = 0, size = d_children.size(); i < size; i++)
410
    {
411
271874
      if (!d_children[i]->reset(t[d_children_index[i]]))
412
      {
413
191265
        success = false;
414
191265
        break;
415
      }
416
    }
417
368970
    if (success)
418
    {
419
177705
      Trace("matching-debug2") << "Continue next " << d_next << std::endl;
420
177705
      ret_val =
421
355410
          continueNextMatch(f, m, InferenceId::QUANTIFIERS_INST_E_MATCHING);
422
    }
423
  }
424
2388124
  if (ret_val < 0)
425
  {
426
2934162
    for (int& pv : prev)
427
    {
428
570257
      m.d_vals[pv] = Node::null();
429
    }
430
  }
431
2388124
  return ret_val;
432
}
433
434
182237
int InstMatchGenerator::continueNextMatch(Node q,
435
                                          InstMatch& m,
436
                                          InferenceId id)
437
{
438
182237
  if( d_next!=NULL ){
439
111569
    return d_next->getNextMatch(q, m);
440
  }
441
70668
  if (d_active_add)
442
  {
443
70360
    return sendInstantiation(m, id) ? 1 : -1;
444
  }
445
308
  return 1;
446
}
447
448
/** reset instantiation round */
449
248582
void InstMatchGenerator::resetInstantiationRound()
450
{
451
248582
  if( !d_match_pattern.isNull() ){
452
240082
    Trace("matching-debug2") << this << " reset instantiation round." << std::endl;
453
240082
    d_needsReset = true;
454
240082
    if( d_cg ){
455
240082
      d_cg->resetInstantiationRound();
456
    }
457
  }
458
248582
  if( d_next ){
459
177749
    d_next->resetInstantiationRound();
460
  }
461
248582
  d_curr_exclude_match.clear();
462
248582
}
463
464
458972
bool InstMatchGenerator::reset(Node eqc)
465
{
466
458972
  if (d_cg == nullptr)
467
  {
468
    // we did not properly initialize the candidate generator, thus we fail
469
    return false;
470
  }
471
458972
  eqc = d_qstate.getRepresentative(eqc);
472
458972
  Trace("matching-debug2") << this << " reset " << eqc << "." << std::endl;
473
458972
  if( !d_eq_class_rel.isNull() && d_eq_class_rel.getKind()!=INST_CONSTANT ){
474
112
    d_eq_class = d_eq_class_rel;
475
458860
  }else if( !eqc.isNull() ){
476
339434
    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
458972
  d_cg->reset( d_eq_class );
482
458972
  d_needsReset = false;
483
484
  //generate the first candidate preemptively
485
458972
  d_curr_first_candidate = Node::null();
486
917944
  Node t;
487
146868
  do {
488
605840
    t = d_cg->getNextCandidate();
489
605840
    if( d_curr_exclude_match.find( t )==d_curr_exclude_match.end() ){
490
458972
      d_curr_first_candidate = t;
491
    }
492
605840
  }while( !t.isNull() && d_curr_first_candidate.isNull() );
493
458972
  Trace("matching-summary") << "Reset " << d_match_pattern << " in " << eqc << " returns " << !d_curr_first_candidate.isNull() << "." << std::endl;
494
495
458972
  return !d_curr_first_candidate.isNull();
496
}
497
498
136930
int InstMatchGenerator::getNextMatch(Node f, InstMatch& m)
499
{
500
136930
  if( d_needsReset ){
501
    Trace("matching") << "Reset not done yet, must do the reset..." << std::endl;
502
    reset(d_eq_class);
503
  }
504
136930
  d_curr_matched = Node::null();
505
136930
  Trace("matching") << this << " " << d_match_pattern << " get next match " << m << " in eq class " << d_eq_class << std::endl;
506
136930
  int success = -1;
507
273860
  Node t = d_curr_first_candidate;
508
2354868
  do{
509
2491798
    Trace("matching-debug2") << "Matching candidate : " << t << std::endl;
510
2491798
    Assert(!d_qstate.isInConflict());
511
    //if t not null, try to fit it into match m
512
2491798
    if( !t.isNull() ){
513
2480167
      if( d_curr_exclude_match.find( t )==d_curr_exclude_match.end() ){
514
2388124
        Assert(t.getType().isComparableTo(d_match_pattern_type));
515
2388124
        Trace("matching-summary") << "Try " << d_match_pattern << " : " << t << std::endl;
516
2388124
        success = getMatch(f, t, m);
517
2388124
        if( d_independent_gen && success<0 ){
518
26223
          Assert(d_eq_class.isNull() || !d_eq_class_rel.isNull());
519
26223
          d_curr_exclude_match[t] = true;
520
        }
521
      }
522
      //get the next candidate term t
523
2480167
      if( success<0 ){
524
2455948
        t = d_qstate.isInConflict() ? Node::null() : d_cg->getNextCandidate();
525
      }else{
526
24219
        d_curr_first_candidate = d_cg->getNextCandidate();
527
      }
528
    }
529
2491798
  }while( success<0 && !t.isNull() );
530
136930
  d_curr_matched = t;
531
136930
  if( success<0 ){
532
112711
    Trace("matching-summary") << "..." << d_match_pattern << " failed, reset." << std::endl;
533
112711
    Trace("matching") << this << " failed, reset " << d_eq_class << std::endl;
534
    //we failed, must reset
535
112711
    reset(d_eq_class);
536
  }else{
537
24219
    Trace("matching-summary") << "..." << d_match_pattern << " success." << std::endl;
538
  }
539
273860
  return success;
540
}
541
542
21736
uint64_t InstMatchGenerator::addInstantiations(Node f)
543
{
544
  //try to add instantiation for each match produced
545
21736
  uint64_t addedLemmas = 0;
546
43472
  InstMatch m( f );
547
41490
  while (getNextMatch(f, m) > 0)
548
  {
549
9877
    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
9877
      addedLemmas++;
560
9877
      if (d_qstate.isInConflict())
561
      {
562
        break;
563
      }
564
    }
565
9877
    m.clear();
566
  }
567
  //return number of lemmas added
568
43472
  return addedLemmas;
569
}
570
571
8009
InstMatchGenerator* InstMatchGenerator::mkInstMatchGenerator(Trigger* tparent,
572
                                                             Node q,
573
                                                             Node pat)
574
{
575
16018
  std::vector< Node > pats;
576
8009
  pats.push_back( pat );
577
16018
  std::map< Node, InstMatchGenerator * > pat_map_init;
578
16018
  return mkInstMatchGenerator(tparent, q, pats, pat_map_init);
579
}
580
581
1210
InstMatchGenerator* InstMatchGenerator::mkInstMatchGeneratorMulti(
582
    Trigger* tparent, Node q, std::vector<Node>& pats)
583
{
584
1210
  Assert(pats.size() > 1);
585
  InstMatchGeneratorMultiLinear* imgm =
586
1210
      new InstMatchGeneratorMultiLinear(tparent, q, pats);
587
2420
  std::vector< InstMatchGenerator* > gens;
588
1210
  imgm->initialize(q, gens);
589
1210
  Assert(gens.size() == pats.size());
590
2420
  std::vector< Node > patsn;
591
2420
  std::map< Node, InstMatchGenerator * > pat_map_init;
592
3908
  for (InstMatchGenerator* g : gens)
593
  {
594
5396
    Node pn = g->d_match_pattern;
595
2698
    patsn.push_back( pn );
596
2698
    pat_map_init[pn] = g;
597
  }
598
1210
  imgm->d_next = mkInstMatchGenerator(tparent, q, patsn, pat_map_init);
599
2420
  return imgm;
600
}
601
602
9219
InstMatchGenerator* InstMatchGenerator::mkInstMatchGenerator(
603
    Trigger* tparent,
604
    Node q,
605
    std::vector<Node>& pats,
606
    std::map<Node, InstMatchGenerator*>& pat_map_init)
607
{
608
9219
  size_t pCounter = 0;
609
9219
  InstMatchGenerator* prev = NULL;
610
9219
  InstMatchGenerator* oinit = NULL;
611
30633
  while( pCounter<pats.size() ){
612
10707
    size_t counter = 0;
613
21414
    std::vector< InstMatchGenerator* > gens;
614
    InstMatchGenerator* init;
615
10707
    std::map< Node, InstMatchGenerator * >::iterator iti = pat_map_init.find( pats[pCounter] );
616
10707
    if( iti==pat_map_init.end() ){
617
8009
      init = new InstMatchGenerator(tparent, pats[pCounter]);
618
    }else{
619
2698
      init = iti->second;
620
    }
621
10707
    if(pCounter==0){
622
9219
      oinit = init;
623
    }
624
10707
    gens.push_back(init);
625
    //chain the resulting match generators together
626
80185
    while (counter<gens.size()) {
627
34739
      InstMatchGenerator* curr = gens[counter];
628
34739
      if( prev ){
629
25520
        prev->d_next = curr;
630
      }
631
34739
      curr->initialize(q, gens);
632
34739
      prev = curr;
633
34739
      counter++;
634
    }
635
10707
    pCounter++;
636
  }
637
9219
  return oinit;
638
}
639
640
26730
InstMatchGenerator* InstMatchGenerator::getInstMatchGenerator(Trigger* tparent,
641
                                                              Node q,
642
                                                              Node n)
643
{
644
26730
  if (n.getKind() != INST_CONSTANT)
645
  {
646
53452
    Trace("var-trigger-debug")
647
26726
        << "Is " << n << " a variable trigger?" << std::endl;
648
53444
    Node x;
649
81931
    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
26726
    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
26722
  return new InstMatchGenerator(tparent, n);
672
}
673
674
}  // namespace inst
675
}  // namespace quantifiers
676
}  // namespace theory
677
84485
}  // namespace cvc5