GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/quantifiers/ematching/inst_match_generator.cpp Lines: 302 353 85.6 %
Date: 2021-11-07 Branches: 618 1434 43.1 %

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