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-17 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
33
using namespace cvc5::kind;
34
35
namespace cvc5 {
36
namespace theory {
37
namespace quantifiers {
38
namespace inst {
39
40
36399
InstMatchGenerator::InstMatchGenerator(Trigger* tparent, Node pat)
41
36399
    : IMGenerator(tparent)
42
{
43
36399
  d_cg = nullptr;
44
36399
  d_needsReset = true;
45
36399
  d_active_add = true;
46
36399
  Assert(pat.isNull() || quantifiers::TermUtil::hasInstConstAttr(pat));
47
36399
  d_pattern = pat;
48
36399
  d_match_pattern = pat;
49
36399
  if (!pat.isNull())
50
  {
51
35091
    d_match_pattern_type = pat.getType();
52
  }
53
36399
  d_next = nullptr;
54
36399
  d_independent_gen = false;
55
36399
}
56
57
107889
InstMatchGenerator::~InstMatchGenerator()
58
{
59
63469
  for( unsigned i=0; i<d_children.size(); i++ ){
60
27070
    delete d_children[i];
61
  }
62
36399
  delete d_cg;
63
71490
}
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
36399
void InstMatchGenerator::initialize(Node q,
95
                                    std::vector<InstMatchGenerator*>& gens)
96
{
97
36399
  if (d_pattern.isNull())
98
  {
99
1308
    gens.insert(gens.end(), d_children.begin(), d_children.end());
100
1308
    return;
101
  }
102
70182
  Trace("inst-match-gen") << "Initialize, pattern term is " << d_pattern
103
35091
                          << std::endl;
104
35091
  if (d_match_pattern.getKind() == NOT)
105
  {
106
2128
    Assert(d_pattern.getKind() == NOT);
107
    // we want to add the children of the NOT
108
2128
    d_match_pattern = d_match_pattern[0];
109
  }
110
111
72310
  if (d_pattern.getKind() == NOT && d_match_pattern.getKind() == EQUAL
112
37219
      && d_match_pattern[0].getKind() == INST_CONSTANT
113
70234
      && d_match_pattern[1].getKind() == INST_CONSTANT)
114
  {
115
    // special case: disequalities between variables x != y will match ground
116
    // disequalities.
117
  }
118
70168
  else if (d_match_pattern.getKind() == EQUAL
119
35084
           || 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
2151
    for (size_t i = 0; i < 2; i++)
128
    {
129
2159
      Node mp = d_match_pattern[i];
130
2159
      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
6453
      if (quantifiers::TermUtil::hasInstConstAttr(mp)
135
8596
          && (!quantifiers::TermUtil::hasInstConstAttr(mpo)
136
19
              || mpo.getKind() == INST_CONSTANT))
137
      {
138
2143
        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
2143
        d_eq_class_rel = mpo;
152
2143
        d_match_pattern = mp;
153
        // we won't find a term in the other direction
154
2143
        break;
155
      }
156
    }
157
  }
158
35091
  d_match_pattern_type = d_match_pattern.getType();
159
70182
  Trace("inst-match-gen") << "Pattern is " << d_pattern << ", match pattern is "
160
35091
                          << d_match_pattern << std::endl;
161
35091
  quantifiers::TermDb* tdb = d_treg.getTermDatabase();
162
35091
  d_match_pattern_op = tdb->getMatchOperator(d_match_pattern);
163
164
  // now, collect children of d_match_pattern
165
35091
  Kind mpk = d_match_pattern.getKind();
166
35091
  if (mpk == INST_CONSTANT)
167
  {
168
142
    d_children_types.push_back(
169
142
        d_match_pattern.getAttribute(InstVarNumAttribute()));
170
  }
171
  else
172
  {
173
99122
    for (size_t i = 0, size = d_match_pattern.getNumChildren(); i < size; i++)
174
    {
175
128204
      Node pat = d_match_pattern[i];
176
128204
      Node qa = quantifiers::TermUtil::getInstConstAttr(pat);
177
64102
      if (!qa.isNull())
178
      {
179
57260
        if (pat.getKind() == INST_CONSTANT && qa == q)
180
        {
181
33068
          d_children_types.push_back(pat.getAttribute(InstVarNumAttribute()));
182
        }
183
        else
184
        {
185
24192
          InstMatchGenerator* cimg = getInstMatchGenerator(d_tparent, q, pat);
186
24192
          if (cimg)
187
          {
188
24192
            d_children.push_back(cimg);
189
24192
            d_children_index.push_back(i);
190
24192
            d_children_types.push_back(-2);
191
          }
192
          else
193
          {
194
            d_children_types.push_back(-1);
195
          }
196
        }
197
      }
198
      else
199
      {
200
6842
        d_children_types.push_back(-1);
201
      }
202
    }
203
  }
204
205
  // create candidate generator
206
35091
  if (mpk == APPLY_SELECTOR)
207
  {
208
    // candidates for apply selector are a union of correctly and incorrectly
209
    // applied selectors
210
516
    d_cg =
211
258
        new inst::CandidateGeneratorSelector(d_qstate, d_treg, d_match_pattern);
212
  }
213
34833
  else if (TriggerTermInfo::isAtomicTriggerKind(mpk))
214
  {
215
34755
    if (mpk == APPLY_CONSTRUCTOR)
216
    {
217
      // 1-constructors have a trivial way of generating candidates in a
218
      // given equivalence class
219
4994
      const DType& dt = d_match_pattern.getType().getDType();
220
4994
      if (dt.getNumConstructors() == 1)
221
      {
222
6034
        d_cg = new inst::CandidateGeneratorConsExpand(
223
3017
            d_qstate, d_treg, d_match_pattern);
224
      }
225
    }
226
34755
    if (d_cg == nullptr)
227
    {
228
      CandidateGeneratorQE* cg =
229
31738
          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
31738
      d_cg = cg;
233
      // if matching on disequality, inform the candidate generator not to
234
      // match on eqc
235
31738
      if (d_pattern.getKind() == NOT && d_pattern[0].getKind() == EQUAL)
236
      {
237
2076
        cg->excludeEqc(d_eq_class_rel);
238
2076
        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
70182
  Trace("inst-match-gen") << "Candidate generator is "
275
70182
                          << (d_cg != nullptr ? d_cg->identify() : "null")
276
35091
                          << std::endl;
277
35091
  gens.insert( gens.end(), d_children.begin(), d_children.end() );
278
}
279
280
/** get match (not modulo equality) */
281
2398026
int InstMatchGenerator::getMatch(Node f, Node t, InstMatch& m)
282
{
283
4796052
  Trace("matching") << "Matching " << t << " against pattern " << d_match_pattern << " ("
284
2398026
                    << m << ")" << ", " << d_children.size() << ", pattern is " << d_pattern << std::endl;
285
2398026
  Assert(!d_match_pattern.isNull());
286
2398026
  if (d_cg == nullptr)
287
  {
288
    Trace("matching-fail") << "Internal error for match generator." << std::endl;
289
    return -2;
290
  }
291
2398026
  bool success = true;
292
4796052
  std::vector<int> prev;
293
  // if t is null
294
2398026
  Assert(!t.isNull());
295
2398026
  Assert(!quantifiers::TermUtil::hasInstConstAttr(t));
296
  // notice that t may have a different kind or operator from our match
297
  // pattern, e.g. for APPLY_SELECTOR triggers.
298
  // first, check if ground arguments are not equal, or a match is in conflict
299
2398026
  Trace("matching-debug2") << "Setting immediate matches..." << std::endl;
300
3414243
  for (size_t i = 0, size = d_match_pattern.getNumChildren(); i < size; i++)
301
  {
302
3035801
    int64_t ct = d_children_types[i];
303
3035801
    if (ct >= 0)
304
    {
305
3926158
      Trace("matching-debug2")
306
1963079
          << "Setting " << ct << " to " << t[i] << "..." << std::endl;
307
1963079
      bool addToPrev = m.get(ct).isNull();
308
1963079
      if (!m.set(d_qstate, ct, t[i]))
309
      {
310
        // match is in conflict
311
2609538
        Trace("matching-fail")
312
1304769
            << "Match fail: " << m.get(ct) << " and " << t[i] << std::endl;
313
1304769
        success = false;
314
3324353
        break;
315
      }
316
658310
      else if (addToPrev)
317
      {
318
611380
        Trace("matching-debug2") << "Success." << std::endl;
319
611380
        prev.push_back(ct);
320
      }
321
    }
322
1072722
    else if (ct == -1)
323
    {
324
737547
      if (!d_qstate.areEqual(d_match_pattern[i], t[i]))
325
      {
326
1429630
        Trace("matching-fail") << "Match fail arg: " << d_match_pattern[i]
327
714815
                               << " and " << t[i] << std::endl;
328
        // ground arguments are not equal
329
714815
        success = false;
330
714815
        break;
331
      }
332
    }
333
  }
334
4796052
  Trace("matching-debug2") << "Done setting immediate matches, success = "
335
2398026
                           << success << "." << std::endl;
336
  // for variable matching
337
2398026
  if (d_match_pattern.getKind() == INST_CONSTANT)
338
  {
339
102
    bool addToPrev = m.get(d_children_types[0]).isNull();
340
102
    if (!m.set(d_qstate, d_children_types[0], t))
341
    {
342
      success = false;
343
    }
344
    else
345
    {
346
102
      if (addToPrev)
347
      {
348
102
        prev.push_back(d_children_types[0]);
349
      }
350
    }
351
  }
352
  // for relational matching
353
2398026
  if (!d_eq_class_rel.isNull() && d_eq_class_rel.getKind() == INST_CONSTANT)
354
  {
355
28
    NodeManager* nm = NodeManager::currentNM();
356
28
    int v = d_eq_class_rel.getAttribute(InstVarNumAttribute());
357
    // also must fit match to equivalence class
358
28
    bool pol = d_pattern.getKind() != NOT;
359
56
    Node pat = d_pattern.getKind() == NOT ? d_pattern[0] : d_pattern;
360
56
    Node t_match;
361
28
    if (pol)
362
    {
363
28
      if (pat.getKind() == GT)
364
      {
365
        t_match = nm->mkNode(MINUS, t, nm->mkConst(Rational(1)));
366
      }else{
367
28
        t_match = t;
368
      }
369
    }
370
    else
371
    {
372
      if (pat.getKind() == EQUAL)
373
      {
374
        if (t.getType().isBoolean())
375
        {
376
          t_match = nm->mkConst(!d_qstate.areEqual(nm->mkConst(true), t));
377
        }
378
        else
379
        {
380
          Assert(t.getType().isReal());
381
          t_match = nm->mkNode(PLUS, t, nm->mkConst(Rational(1)));
382
        }
383
      }
384
      else if (pat.getKind() == GEQ)
385
      {
386
        t_match = nm->mkNode(PLUS, t, nm->mkConst(Rational(1)));
387
      }
388
      else if (pat.getKind() == GT)
389
      {
390
        t_match = t;
391
      }
392
    }
393
28
    if (!t_match.isNull())
394
    {
395
28
      bool addToPrev = m.get(v).isNull();
396
28
      if (!m.set(d_qstate, v, t_match))
397
      {
398
        success = false;
399
      }
400
28
      else if (addToPrev)
401
      {
402
28
        prev.push_back(v);
403
      }
404
    }
405
  }
406
2398026
  int ret_val = -1;
407
2398026
  if (success)
408
  {
409
378442
    Trace("matching-debug2") << "Reset children..." << std::endl;
410
    // now, fit children into match
411
    // we will be requesting candidates for matching terms for each child
412
467157
    for (size_t i = 0, size = d_children.size(); i < size; i++)
413
    {
414
287235
      if (!d_children[i]->reset(t[d_children_index[i]]))
415
      {
416
198520
        success = false;
417
198520
        break;
418
      }
419
    }
420
378442
    if (success)
421
    {
422
179922
      Trace("matching-debug2") << "Continue next " << d_next << std::endl;
423
179922
      ret_val =
424
359844
          continueNextMatch(f, m, InferenceId::QUANTIFIERS_INST_E_MATCHING);
425
    }
426
  }
427
2398026
  if (ret_val < 0)
428
  {
429
2945944
    for (int& pv : prev)
430
    {
431
576536
      m.d_vals[pv] = Node::null();
432
    }
433
  }
434
2398026
  return ret_val;
435
}
436
437
184466
int InstMatchGenerator::continueNextMatch(Node q,
438
                                          InstMatch& m,
439
                                          InferenceId id)
440
{
441
184466
  if( d_next!=NULL ){
442
120059
    return d_next->getNextMatch(q, m);
443
  }
444
64407
  if (d_active_add)
445
  {
446
63439
    return sendInstantiation(m, id) ? 1 : -1;
447
  }
448
968
  return 1;
449
}
450
451
/** reset instantiation round */
452
259193
void InstMatchGenerator::resetInstantiationRound()
453
{
454
259193
  if( !d_match_pattern.isNull() ){
455
248323
    Trace("matching-debug2") << this << " reset instantiation round." << std::endl;
456
248323
    d_needsReset = true;
457
248323
    if( d_cg ){
458
248323
      d_cg->resetInstantiationRound();
459
    }
460
  }
461
259193
  if( d_next ){
462
186038
    d_next->resetInstantiationRound();
463
  }
464
259193
  d_curr_exclude_match.clear();
465
259193
}
466
467
480888
bool InstMatchGenerator::reset(Node eqc)
468
{
469
480888
  if (d_cg == nullptr)
470
  {
471
    // we did not properly initialize the candidate generator, thus we fail
472
    return false;
473
  }
474
480888
  eqc = d_qstate.getRepresentative(eqc);
475
480888
  Trace("matching-debug2") << this << " reset " << eqc << "." << std::endl;
476
480888
  if( !d_eq_class_rel.isNull() && d_eq_class_rel.getKind()!=INST_CONSTANT ){
477
112
    d_eq_class = d_eq_class_rel;
478
480776
  }else if( !eqc.isNull() ){
479
360356
    d_eq_class = eqc;
480
  }
481
  //we have a specific equivalence class in mind
482
  //we are producing matches for f(E) ~ t, where E is a non-ground vector of terms, and t is a ground term
483
  //just look in equivalence class of the RHS
484
480888
  d_cg->reset( d_eq_class );
485
480888
  d_needsReset = false;
486
487
  //generate the first candidate preemptively
488
480888
  d_curr_first_candidate = Node::null();
489
961776
  Node t;
490
146950
  do {
491
627838
    t = d_cg->getNextCandidate();
492
627838
    if( d_curr_exclude_match.find( t )==d_curr_exclude_match.end() ){
493
480888
      d_curr_first_candidate = t;
494
    }
495
627838
  }while( !t.isNull() && d_curr_first_candidate.isNull() );
496
480888
  Trace("matching-summary") << "Reset " << d_match_pattern << " in " << eqc << " returns " << !d_curr_first_candidate.isNull() << "." << std::endl;
497
498
480888
  return !d_curr_first_candidate.isNull();
499
}
500
501
147158
int InstMatchGenerator::getNextMatch(Node f, InstMatch& m)
502
{
503
147158
  if( d_needsReset ){
504
    Trace("matching") << "Reset not done yet, must do the reset..." << std::endl;
505
    reset(d_eq_class);
506
  }
507
147158
  d_curr_matched = Node::null();
508
147158
  Trace("matching") << this << " " << d_match_pattern << " get next match " << m << " in eq class " << d_eq_class << std::endl;
509
147158
  int success = -1;
510
294316
  Node t = d_curr_first_candidate;
511
2354755
  do{
512
2501913
    Trace("matching-debug2") << "Matching candidate : " << t << std::endl;
513
2501913
    Assert(!d_qstate.isInConflict());
514
    //if t not null, try to fit it into match m
515
2501913
    if( !t.isNull() ){
516
2490075
      if( d_curr_exclude_match.find( t )==d_curr_exclude_match.end() ){
517
2398026
        Assert(t.getType().isComparableTo(d_match_pattern_type));
518
2398026
        Trace("matching-summary") << "Try " << d_match_pattern << " : " << t << std::endl;
519
2398026
        success = getMatch(f, t, m);
520
2398026
        if( d_independent_gen && success<0 ){
521
26300
          Assert(d_eq_class.isNull() || !d_eq_class_rel.isNull());
522
26300
          d_curr_exclude_match[t] = true;
523
        }
524
      }
525
      //get the next candidate term t
526
2490075
      if( success<0 ){
527
2461457
        t = d_qstate.isInConflict() ? Node::null() : d_cg->getNextCandidate();
528
      }else{
529
28618
        d_curr_first_candidate = d_cg->getNextCandidate();
530
      }
531
    }
532
2501913
  }while( success<0 && !t.isNull() );
533
147158
  d_curr_matched = t;
534
147158
  if( success<0 ){
535
118540
    Trace("matching-summary") << "..." << d_match_pattern << " failed, reset." << std::endl;
536
118540
    Trace("matching") << this << " failed, reset " << d_eq_class << std::endl;
537
    //we failed, must reset
538
118540
    reset(d_eq_class);
539
  }else{
540
28618
    Trace("matching-summary") << "..." << d_match_pattern << " success." << std::endl;
541
  }
542
294316
  return success;
543
}
544
545
22691
uint64_t InstMatchGenerator::addInstantiations(Node f)
546
{
547
  //try to add instantiation for each match produced
548
22691
  uint64_t addedLemmas = 0;
549
45382
  InstMatch m( f );
550
44125
  while (getNextMatch(f, m) > 0)
551
  {
552
10717
    if( !d_active_add ){
553
      if (sendInstantiation(m, InferenceId::UNKNOWN))
554
      {
555
        addedLemmas++;
556
        if (d_qstate.isInConflict())
557
        {
558
          break;
559
        }
560
      }
561
    }else{
562
10717
      addedLemmas++;
563
10717
      if (d_qstate.isInConflict())
564
      {
565
        break;
566
      }
567
    }
568
10717
    m.clear();
569
  }
570
  //return number of lemmas added
571
45382
  return addedLemmas;
572
}
573
574
8029
InstMatchGenerator* InstMatchGenerator::mkInstMatchGenerator(Trigger* tparent,
575
                                                             Node q,
576
                                                             Node pat)
577
{
578
16058
  std::vector< Node > pats;
579
8029
  pats.push_back( pat );
580
16058
  std::map< Node, InstMatchGenerator * > pat_map_init;
581
16058
  return mkInstMatchGenerator(tparent, q, pats, pat_map_init);
582
}
583
584
1300
InstMatchGenerator* InstMatchGenerator::mkInstMatchGeneratorMulti(
585
    Trigger* tparent, Node q, std::vector<Node>& pats)
586
{
587
1300
  Assert(pats.size() > 1);
588
  InstMatchGeneratorMultiLinear* imgm =
589
1300
      new InstMatchGeneratorMultiLinear(tparent, q, pats);
590
2600
  std::vector< InstMatchGenerator* > gens;
591
1300
  imgm->initialize(q, gens);
592
1300
  Assert(gens.size() == pats.size());
593
2600
  std::vector< Node > patsn;
594
2600
  std::map< Node, InstMatchGenerator * > pat_map_init;
595
4178
  for (InstMatchGenerator* g : gens)
596
  {
597
5756
    Node pn = g->d_match_pattern;
598
2878
    patsn.push_back( pn );
599
2878
    pat_map_init[pn] = g;
600
  }
601
1300
  imgm->d_next = mkInstMatchGenerator(tparent, q, patsn, pat_map_init);
602
2600
  return imgm;
603
}
604
605
9329
InstMatchGenerator* InstMatchGenerator::mkInstMatchGenerator(
606
    Trigger* tparent,
607
    Node q,
608
    std::vector<Node>& pats,
609
    std::map<Node, InstMatchGenerator*>& pat_map_init)
610
{
611
9329
  size_t pCounter = 0;
612
9329
  InstMatchGenerator* prev = NULL;
613
9329
  InstMatchGenerator* oinit = NULL;
614
31143
  while( pCounter<pats.size() ){
615
10907
    size_t counter = 0;
616
21814
    std::vector< InstMatchGenerator* > gens;
617
    InstMatchGenerator* init;
618
10907
    std::map< Node, InstMatchGenerator * >::iterator iti = pat_map_init.find( pats[pCounter] );
619
10907
    if( iti==pat_map_init.end() ){
620
8029
      init = new InstMatchGenerator(tparent, pats[pCounter]);
621
    }else{
622
2878
      init = iti->second;
623
    }
624
10907
    if(pCounter==0){
625
9329
      oinit = init;
626
    }
627
10907
    gens.push_back(init);
628
    //chain the resulting match generators together
629
81105
    while (counter<gens.size()) {
630
35099
      InstMatchGenerator* curr = gens[counter];
631
35099
      if( prev ){
632
25770
        prev->d_next = curr;
633
      }
634
35099
      curr->initialize(q, gens);
635
35099
      prev = curr;
636
35099
      counter++;
637
    }
638
10907
    pCounter++;
639
  }
640
9329
  return oinit;
641
}
642
643
27070
InstMatchGenerator* InstMatchGenerator::getInstMatchGenerator(Trigger* tparent,
644
                                                              Node q,
645
                                                              Node n)
646
{
647
27070
  if (n.getKind() != INST_CONSTANT)
648
  {
649
54132
    Trace("var-trigger-debug")
650
27066
        << "Is " << n << " a variable trigger?" << std::endl;
651
54124
    Node x;
652
27066
    if (options::purifyTriggers())
653
    {
654
170
      Node xi = PatternTermSelector::getInversionVariable(n);
655
85
      if (!xi.isNull())
656
      {
657
16
        Node qa = quantifiers::TermUtil::getInstConstAttr(xi);
658
8
        if (qa == q)
659
        {
660
8
          x = xi;
661
        }
662
      }
663
    }
664
27066
    if (!x.isNull())
665
    {
666
16
      Node s = PatternTermSelector::getInversion(n, x);
667
      VarMatchGeneratorTermSubs* vmg =
668
8
          new VarMatchGeneratorTermSubs(tparent, x, s);
669
16
      Trace("var-trigger") << "Term substitution trigger : " << n
670
8
                           << ", var = " << x << ", subs = " << s << std::endl;
671
8
      return vmg;
672
    }
673
  }
674
27062
  return new InstMatchGenerator(tparent, n);
675
}
676
677
}  // namespace inst
678
}  // namespace quantifiers
679
}  // namespace theory
680
29577
}  // namespace cvc5