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