GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/quantifiers/sygus/sygus_enumerator.cpp Lines: 627 645 97.2 %
Date: 2021-09-07 Branches: 991 2260 43.8 %

Line Exec Source
1
/******************************************************************************
2
 * Top contributors (to current version):
3
 *   Andrew Reynolds, Mathias Preiner, Aina Niemetz
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 sygus_enumerator.
14
 */
15
16
#include "theory/quantifiers/sygus/sygus_enumerator.h"
17
18
#include "expr/dtype_cons.h"
19
#include "expr/node_algorithm.h"
20
#include "options/datatypes_options.h"
21
#include "options/quantifiers_options.h"
22
#include "smt/logic_exception.h"
23
#include "theory/datatypes/sygus_datatype_utils.h"
24
#include "theory/datatypes/theory_datatypes_utils.h"
25
#include "theory/quantifiers/sygus/synth_engine.h"
26
#include "theory/quantifiers/sygus/type_node_id_trie.h"
27
#include "theory/rewriter.h"
28
29
using namespace cvc5::kind;
30
31
namespace cvc5 {
32
namespace theory {
33
namespace quantifiers {
34
35
166
SygusEnumerator::SygusEnumerator(TermDbSygus* tds,
36
                                 SygusEnumeratorCallback* sec,
37
                                 SygusStatistics* s,
38
                                 bool enumShapes,
39
166
                                 bool enumAnyConstHoles)
40
    : d_tds(tds),
41
      d_sec(sec),
42
      d_stats(s),
43
      d_enumShapes(enumShapes),
44
      d_enumAnyConstHoles(enumAnyConstHoles),
45
      d_tlEnum(nullptr),
46
166
      d_abortSize(-1)
47
{
48
166
}
49
50
166
void SygusEnumerator::initialize(Node e)
51
{
52
166
  Trace("sygus-enum") << "SygusEnumerator::initialize " << e << std::endl;
53
166
  d_enum = e;
54
  // allocate the default callback
55
166
  if (d_sec == nullptr && options::sygusSymBreakDynamic())
56
  {
57
53
    d_secd.reset(new SygusEnumeratorCallbackDefault(e, d_stats));
58
53
    d_sec = d_secd.get();
59
  }
60
166
  d_etype = d_enum.getType();
61
166
  Assert(d_etype.isDatatype());
62
166
  Assert(d_etype.getDType().isSygus());
63
166
  d_tlEnum = getMasterEnumForType(d_etype);
64
166
  d_abortSize = options::sygusAbortSize();
65
66
  // if we don't have a term database, we don't register symmetry breaking
67
  // lemmas
68
166
  if (d_tds == nullptr)
69
  {
70
    return;
71
  }
72
  // Get the statically registered symmetry breaking clauses for e, see if they
73
  // can be used for speeding up the enumeration.
74
166
  NodeManager* nm = NodeManager::currentNM();
75
332
  std::vector<Node> sbl;
76
166
  d_tds->getSymBreakLemmas(e, sbl);
77
332
  Node ag = d_tds->getActiveGuardForEnumerator(e);
78
332
  Node truen = nm->mkConst(true);
79
  // use TNode for substitute below
80
332
  TNode agt = ag;
81
332
  TNode truent = truen;
82
166
  Assert(d_tcache.find(d_etype) != d_tcache.end());
83
166
  const DType& dt = d_etype.getDType();
84
236
  for (const Node& lem : sbl)
85
  {
86
70
    if (!d_tds->isSymBreakLemmaTemplate(lem))
87
    {
88
      // substitute its active guard by true and rewrite
89
72
      Node slem = lem.substitute(agt, truent);
90
36
      slem = Rewriter::rewrite(slem);
91
      // break into conjuncts
92
72
      std::vector<Node> sblc;
93
36
      if (slem.getKind() == AND)
94
      {
95
9
        for (const Node& slemc : slem)
96
        {
97
6
          sblc.push_back(slemc);
98
        }
99
      }
100
      else
101
      {
102
33
        sblc.push_back(slem);
103
      }
104
75
      for (const Node& sblemma : sblc)
105
      {
106
78
        Trace("sygus-enum")
107
39
            << "  symmetry breaking lemma : " << sblemma << std::endl;
108
        // if its a negation of a unit top-level tester, then this specifies
109
        // that we should not enumerate terms whose top symbol is that
110
        // constructor
111
39
        if (sblemma.getKind() == NOT)
112
        {
113
74
          Node a;
114
37
          int tst = datatypes::utils::isTester(sblemma[0], a);
115
37
          if (tst >= 0)
116
          {
117
37
            if (a == e)
118
            {
119
74
              Node cons = dt[tst].getConstructor();
120
74
              Trace("sygus-enum") << "  ...unit exclude constructor #" << tst
121
37
                                  << ", constructor " << cons << std::endl;
122
37
              d_sbExcTlCons.insert(cons);
123
            }
124
          }
125
        }
126
        // other symmetry breaking lemmas such as disjunctions are not used
127
      }
128
    }
129
  }
130
}
131
132
113
void SygusEnumerator::addValue(Node v)
133
{
134
  // do nothing
135
113
}
136
137
46363
bool SygusEnumerator::increment() { return d_tlEnum->increment(); }
138
45816
Node SygusEnumerator::getCurrent()
139
{
140
45816
  if (d_abortSize >= 0)
141
  {
142
4237
    int cs = static_cast<int>(d_tlEnum->getCurrentSize());
143
4237
    if (cs > d_abortSize)
144
    {
145
18
      std::stringstream ss;
146
9
      ss << "Maximum term size (" << options::sygusAbortSize()
147
9
         << ") for enumerative SyGuS exceeded.";
148
9
      throw LogicException(ss.str());
149
    }
150
  }
151
45807
  Node ret = d_tlEnum->getCurrent();
152
45807
  if (!ret.isNull() && !d_sbExcTlCons.empty())
153
  {
154
433
    Assert(ret.hasOperator());
155
    // might be excluded by an externally provided symmetry breaking clause
156
433
    if (d_sbExcTlCons.find(ret.getOperator()) != d_sbExcTlCons.end())
157
    {
158
48
      Trace("sygus-enum-exc")
159
48
          << "Exclude (external) : " << datatypes::utils::sygusToBuiltin(ret)
160
24
          << std::endl;
161
24
      ret = Node::null();
162
    }
163
  }
164
45807
  if (Trace.isOn("sygus-enum"))
165
  {
166
    Trace("sygus-enum") << "Enumerate : ";
167
    TermDbSygus::toStreamSygus("sygus-enum", ret);
168
    Trace("sygus-enum") << std::endl;
169
  }
170
45807
  return ret;
171
}
172
173
294
bool SygusEnumerator::isEnumShapes() const { return d_enumShapes; }
174
175
310
SygusEnumerator::TermCache::TermCache()
176
    : d_sec(nullptr),
177
      d_isSygusType(false),
178
      d_numConClasses(0),
179
      d_sizeEnum(0),
180
310
      d_isComplete(false)
181
{
182
310
}
183
184
310
void SygusEnumerator::TermCache::initialize(SygusStatistics* s,
185
                                            Node e,
186
                                            TypeNode tn,
187
                                            SygusEnumeratorCallback* sec)
188
{
189
310
  Trace("sygus-enum-debug") << "Init term cache " << tn << "..." << std::endl;
190
310
  d_stats = s;
191
310
  d_enum = e;
192
310
  d_tn = tn;
193
310
  d_sec = sec;
194
310
  d_sizeStartIndex[0] = 0;
195
310
  d_isSygusType = false;
196
197
  // compute static information about tn
198
310
  if (!d_tn.isDatatype())
199
  {
200
    // not a datatype, finish
201
32
    return;
202
  }
203
294
  const DType& dt = tn.getDType();
204
294
  if (!dt.isSygus())
205
  {
206
    // not a sygus datatype, finish
207
    return;
208
  }
209
210
294
  d_isSygusType = true;
211
212
  // get argument types for all constructors
213
588
  std::map<unsigned, std::vector<TypeNode>> argTypes;
214
  // map weights to constructors
215
588
  std::map<unsigned, std::vector<unsigned>> weightsToIndices;
216
217
  // constructor class 0 is reserved for nullary operators with 0 weight
218
  // this is an optimization so that we always skip them for sizes >= 1
219
294
  ConstructorClass& ccZero = d_cclass[0];
220
294
  ccZero.d_weight = 0;
221
294
  d_numConClasses = 1;
222
  // we must indicate that we should process zero weight constructor classes
223
294
  weightsToIndices[0].clear();
224
1797
  for (unsigned i = 0, ncons = dt.getNumConstructors(); i < ncons; i++)
225
  {
226
    // record weight information
227
1503
    unsigned w = dt[i].getWeight();
228
3006
    Trace("sygus-enum-debug") << "Weight " << dt[i].getSygusOp() << ": " << w
229
1503
                              << std::endl;
230
1503
    weightsToIndices[w].push_back(i);
231
    // record type information
232
3107
    for (unsigned j = 0, nargs = dt[i].getNumArgs(); j < nargs; j++)
233
    {
234
3208
      TypeNode type = dt[i].getArgType(j);
235
1604
      argTypes[i].push_back(type);
236
    }
237
  }
238
294
  NodeManager* nm = NodeManager::currentNM();
239
818
  for (std::pair<const unsigned, std::vector<unsigned>>& wp : weightsToIndices)
240
  {
241
524
    unsigned w = wp.first;
242
243
    // assign constructors to constructor classes
244
1048
    TypeNodeIdTrie tnit;
245
1048
    std::map<Node, unsigned> nToC;
246
2027
    for (unsigned i : wp.second)
247
    {
248
1503
      if (argTypes[i].empty() && w == 0)
249
      {
250
628
        ccZero.d_cons.push_back(i);
251
      }
252
      else
253
      {
254
        // we merge those whose argument types are the same
255
        // We could, but choose not to, order these types, which would lead to
256
        // more aggressive merging of constructor classes. On the negative side,
257
        // this adds another level of indirection to remember which argument
258
        // positions the argument types occur in, for each constructor.
259
1750
        Node n = nm->mkConst(Rational(i));
260
875
        nToC[n] = i;
261
875
        tnit.add(n, argTypes[i]);
262
      }
263
    }
264
1048
    std::map<Node, unsigned> assign;
265
524
    tnit.assignIds(assign, d_numConClasses);
266
1399
    for (std::pair<const Node, unsigned>& cp : assign)
267
    {
268
      // determine which constructor class this goes into using tnit
269
875
      unsigned cclassi = cp.second;
270
875
      unsigned i = nToC[cp.first];
271
1750
      Trace("sygus-enum-debug") << "Constructor class for "
272
1750
                                << dt[i].getSygusOp() << " is " << cclassi
273
875
                                << std::endl;
274
      // initialize the constructor class
275
875
      if (d_cclass.find(cclassi) == d_cclass.end())
276
      {
277
512
        d_cclass[cclassi].d_weight = w;
278
2048
        d_cclass[cclassi].d_types.insert(d_cclass[cclassi].d_types.end(),
279
512
                                         argTypes[i].begin(),
280
2048
                                         argTypes[i].end());
281
      }
282
      // add to constructor class
283
875
      d_cclass[cclassi].d_cons.push_back(i);
284
    }
285
1048
    Trace("sygus-enum-debug") << "#cons classes for weight <= " << w << " : "
286
524
                              << d_numConClasses << std::endl;
287
524
    d_weightToCcIndex[w] = d_numConClasses;
288
  }
289
294
  Trace("sygus-enum-debug") << "...finish" << std::endl;
290
}
291
292
56253
unsigned SygusEnumerator::TermCache::getLastConstructorClassIndexForWeight(
293
    unsigned w) const
294
{
295
56253
  std::map<unsigned, unsigned>::const_iterator it = d_weightToCcIndex.find(w);
296
56253
  if (it == d_weightToCcIndex.end())
297
  {
298
47545
    return d_numConClasses;
299
  }
300
8708
  return it->second;
301
}
302
92
unsigned SygusEnumerator::TermCache::getNumConstructorClasses() const
303
{
304
92
  return d_numConClasses;
305
}
306
868
void SygusEnumerator::TermCache::getConstructorClass(
307
    unsigned i, std::vector<unsigned>& cclass) const
308
{
309
868
  std::map<unsigned, ConstructorClass>::const_iterator it = d_cclass.find(i);
310
868
  Assert(it != d_cclass.end());
311
868
  cclass.insert(
312
1736
      cclass.end(), it->second.d_cons.begin(), it->second.d_cons.end());
313
868
}
314
831
void SygusEnumerator::TermCache::getTypesForConstructorClass(
315
    unsigned i, std::vector<TypeNode>& types) const
316
{
317
831
  std::map<unsigned, ConstructorClass>::const_iterator it = d_cclass.find(i);
318
831
  Assert(it != d_cclass.end());
319
831
  types.insert(
320
1662
      types.end(), it->second.d_types.begin(), it->second.d_types.end());
321
831
}
322
323
831
unsigned SygusEnumerator::TermCache::getWeightForConstructorClass(
324
    unsigned i) const
325
{
326
831
  std::map<unsigned, ConstructorClass>::const_iterator it = d_cclass.find(i);
327
831
  Assert(it != d_cclass.end());
328
831
  return it->second.d_weight;
329
}
330
331
55392
bool SygusEnumerator::TermCache::addTerm(Node n)
332
{
333
55392
  if (!d_isSygusType)
334
  {
335
    // non-sygus terms generated by TermEnumMasterInterp/TermEnumMasterFv
336
    // enumeration are unique by construction
337
222
    Trace("sygus-enum-terms") << "tc(" << d_tn << "): term (builtin): " << n
338
111
                              << std::endl;
339
111
    d_terms.push_back(n);
340
111
    return true;
341
  }
342
55281
  Assert(!n.isNull());
343
55281
  if (d_sec != nullptr)
344
  {
345
55281
    if (!d_sec->addTerm(n, d_bterms))
346
    {
347
62866
      Trace("sygus-enum-exc")
348
62866
          << "Exclude: " << datatypes::utils::sygusToBuiltin(n)
349
31433
          << " due to callback" << std::endl;
350
31433
      return false;
351
    }
352
  }
353
23848
  if (d_stats != nullptr)
354
  {
355
23848
    ++(d_stats->d_enumTerms);
356
  }
357
23848
  d_terms.push_back(n);
358
23848
  return true;
359
}
360
424
void SygusEnumerator::TermCache::pushEnumSizeIndex()
361
{
362
424
  d_sizeEnum++;
363
424
  d_sizeStartIndex[d_sizeEnum] = d_terms.size();
364
848
  Trace("sygus-enum-debug") << "tc(" << d_tn << "): size " << d_sizeEnum
365
848
                            << " terms start at index " << d_terms.size()
366
424
                            << std::endl;
367
424
}
368
40498
unsigned SygusEnumerator::TermCache::getEnumSize() const { return d_sizeEnum; }
369
35086
unsigned SygusEnumerator::TermCache::getIndexForSize(unsigned s) const
370
{
371
35086
  Assert(s <= d_sizeEnum);
372
35086
  std::map<unsigned, unsigned>::const_iterator it = d_sizeStartIndex.find(s);
373
35086
  Assert(it != d_sizeStartIndex.end());
374
35086
  return it->second;
375
}
376
217056
Node SygusEnumerator::TermCache::getTerm(unsigned index) const
377
{
378
217056
  Assert(index < d_terms.size());
379
217056
  return d_terms[index];
380
}
381
382
54463
unsigned SygusEnumerator::TermCache::getNumTerms() const
383
{
384
54463
  return d_terms.size();
385
}
386
387
57048
bool SygusEnumerator::TermCache::isComplete() const { return d_isComplete; }
388
43
void SygusEnumerator::TermCache::setComplete() { d_isComplete = true; }
389
216394
unsigned SygusEnumerator::TermEnum::getCurrentSize() { return d_currSize; }
390
3607
SygusEnumerator::TermEnum::TermEnum() : d_se(nullptr), d_currSize(0) {}
391
3297
SygusEnumerator::TermEnumSlave::TermEnumSlave()
392
    : TermEnum(),
393
      d_sizeLim(0),
394
      d_index(0),
395
      d_indexNextEnd(0),
396
      d_hasIndexNextEnd(false),
397
3297
      d_master(nullptr)
398
{
399
3297
}
400
401
3297
bool SygusEnumerator::TermEnumSlave::initialize(SygusEnumerator* se,
402
                                                TypeNode tn,
403
                                                unsigned sizeMin,
404
                                                unsigned sizeMax)
405
{
406
3297
  d_se = se;
407
3297
  d_tn = tn;
408
3297
  d_sizeLim = sizeMax;
409
6594
  Trace("sygus-enum-debug2") << "slave(" << d_tn
410
3297
                             << "): init, min/max=" << sizeMin << "/" << sizeMax
411
3297
                             << "...\n";
412
413
  // must have pointer to the master
414
3297
  d_master = d_se->getMasterEnumForType(d_tn);
415
416
3297
  SygusEnumerator::TermCache& tc = d_se->d_tcache[d_tn];
417
  // if the size is exact, we start at the limit
418
3297
  d_currSize = sizeMin;
419
  // initialize the index
420
3303
  while (d_currSize > tc.getEnumSize())
421
  {
422
76
    Trace("sygus-enum-debug2") << "slave(" << d_tn
423
38
                               << "): init force increment master...\n";
424
    // increment the master until we have enough terms
425
38
    if (!d_master->increment())
426
    {
427
70
      Trace("sygus-enum-debug2") << "slave(" << d_tn
428
35
                                 << "): ...fail init force master\n";
429
35
      return false;
430
    }
431
6
    Trace("sygus-enum-debug2") << "slave(" << d_tn
432
3
                               << "): ...success init force master\n";
433
  }
434
3262
  d_index = tc.getIndexForSize(d_currSize);
435
3262
  Trace("sygus-enum-debug2") << "slave(" << d_tn << "): validate indices...\n";
436
  // initialize the next end index (marks where size increments)
437
3262
  validateIndexNextEnd();
438
6524
  Trace("sygus-enum-debug2")
439
3262
      << "slave(" << d_tn << "): validate init end: " << d_hasIndexNextEnd
440
3262
      << " " << d_indexNextEnd << " " << d_index << " " << d_currSize << "\n";
441
  // ensure that indexNextEnd is valid (it must be greater than d_index)
442
3262
  bool ret = validateIndex();
443
6524
  Trace("sygus-enum-debug2")
444
6524
      << "slave(" << d_tn << "): ..." << (ret ? "success" : "fail")
445
3262
      << " init, now: " << d_hasIndexNextEnd << " " << d_indexNextEnd << " "
446
3262
      << d_index << " " << d_currSize << "\n";
447
3262
  return ret;
448
}
449
450
108528
Node SygusEnumerator::TermEnumSlave::getCurrent()
451
{
452
108528
  SygusEnumerator::TermCache& tc = d_se->d_tcache[d_tn];
453
217056
  Node curr = tc.getTerm(d_index);
454
217056
  Trace("sygus-enum-debug2")
455
108528
      << "slave(" << d_tn
456
217056
      << "): current : " << datatypes::utils::sygusToBuiltin(curr)
457
217056
      << ", sizes = " << datatypes::utils::getSygusTermSize(curr) << " "
458
108528
      << getCurrentSize() << std::endl;
459
217056
  Trace("sygus-enum-debug2") << "slave(" << d_tn
460
108528
                             << "): indices : " << d_hasIndexNextEnd << " "
461
108528
                             << d_indexNextEnd << " " << d_index << std::endl;
462
  // lookup in the cache
463
217056
  return tc.getTerm(d_index);
464
}
465
466
30976
bool SygusEnumerator::TermEnumSlave::increment()
467
{
468
  // increment index
469
30976
  d_index++;
470
  // ensure that index is valid
471
30976
  return validateIndex();
472
}
473
474
34238
bool SygusEnumerator::TermEnumSlave::validateIndex()
475
{
476
34238
  Trace("sygus-enum-debug2") << "slave(" << d_tn << ") : validate index...\n";
477
34238
  SygusEnumerator::TermCache& tc = d_se->d_tcache[d_tn];
478
  // ensure that index is in the range
479
53816
  while (d_index >= tc.getNumTerms())
480
  {
481
10335
    Assert(d_index == tc.getNumTerms());
482
10335
    Trace("sygus-enum-debug2") << "slave(" << d_tn << ") : force master...\n";
483
    // if the size of the master is larger than the size limit, then
484
    // there is no use continuing, since there are no more terms that this
485
    // slave enumerator can return.
486
10335
    if (d_master->getCurrentSize() > d_sizeLim)
487
    {
488
444
      return false;
489
    }
490
    // must push the master index
491
9891
    if (!d_master->increment())
492
    {
493
204
      Trace("sygus-enum-debug2") << "slave(" << d_tn
494
102
                                 << ") : ...fail force master\n";
495
102
      return false;
496
    }
497
19578
    Trace("sygus-enum-debug2") << "slave(" << d_tn
498
9789
                               << ") : ...success force master\n";
499
  }
500
  // always validate the next index end here
501
33692
  validateIndexNextEnd();
502
67384
  Trace("sygus-enum-debug2") << "slave(" << d_tn
503
33692
                             << ") : validate index end...\n";
504
  // if we are at the beginning of the next size, increment current size
505
34142
  while (d_hasIndexNextEnd && d_index == d_indexNextEnd)
506
  {
507
2640
    d_currSize++;
508
5280
    Trace("sygus-enum-debug2") << "slave(" << d_tn << ") : size++ ("
509
2640
                               << d_currSize << "/" << d_sizeLim << ")\n";
510
    // if we've hit the size limit, return false
511
2640
    if (d_currSize > d_sizeLim)
512
    {
513
2415
      Trace("sygus-enum-debug2") << "slave(" << d_tn << ") : fail size\n";
514
2415
      return false;
515
    }
516
225
    validateIndexNextEnd();
517
  }
518
31277
  Trace("sygus-enum-debug2") << "slave(" << d_tn << ") : finished\n";
519
31277
  return true;
520
}
521
522
37179
void SygusEnumerator::TermEnumSlave::validateIndexNextEnd()
523
{
524
37179
  SygusEnumerator::TermCache& tc = d_se->d_tcache[d_tn];
525
  // update the next end index
526
37179
  d_hasIndexNextEnd = d_currSize < tc.getEnumSize();
527
37179
  if (d_hasIndexNextEnd)
528
  {
529
31824
    d_indexNextEnd = tc.getIndexForSize(d_currSize + 1);
530
  }
531
37179
}
532
533
310
void SygusEnumerator::initializeTermCache(TypeNode tn)
534
{
535
  // initialize the term cache
536
310
  d_tcache[tn].initialize(d_stats, d_enum, tn, d_sec);
537
310
}
538
539
3463
SygusEnumerator::TermEnum* SygusEnumerator::getMasterEnumForType(TypeNode tn)
540
{
541
3463
  if (tn.isDatatype() && tn.getDType().isSygus())
542
  {
543
3436
    std::map<TypeNode, TermEnumMaster>::iterator it = d_masterEnum.find(tn);
544
3436
    if (it != d_masterEnum.end())
545
    {
546
3142
      return &it->second;
547
    }
548
294
    initializeTermCache(tn);
549
    // initialize the master enumerator
550
294
    bool ret = d_masterEnum[tn].initialize(this, tn);
551
294
    AlwaysAssert(ret);
552
294
    return &d_masterEnum[tn];
553
  }
554
27
  if (d_enumAnyConstHoles)
555
  {
556
5
    std::map<TypeNode, TermEnumMasterFv>::iterator it = d_masterEnumFv.find(tn);
557
5
    if (it != d_masterEnumFv.end())
558
    {
559
      return &it->second;
560
    }
561
5
    initializeTermCache(tn);
562
    // initialize the master enumerator
563
5
    bool ret = d_masterEnumFv[tn].initialize(this, tn);
564
5
    AlwaysAssert(ret);
565
5
    return &d_masterEnumFv[tn];
566
  }
567
  std::map<TypeNode, std::unique_ptr<TermEnumMasterInterp>>::iterator it =
568
22
      d_masterEnumInt.find(tn);
569
22
  if (it != d_masterEnumInt.end())
570
  {
571
11
    return it->second.get();
572
  }
573
11
  initializeTermCache(tn);
574
  // create the master enumerator
575
11
  d_masterEnumInt[tn].reset(new TermEnumMasterInterp(tn));
576
  // initialize the master enumerator
577
11
  TermEnumMasterInterp* temi = d_masterEnumInt[tn].get();
578
11
  bool ret = temi->initialize(this, tn);
579
11
  AlwaysAssert(ret);
580
11
  return temi;
581
}
582
583
294
SygusEnumerator::TermEnumMaster::TermEnumMaster()
584
    : TermEnum(),
585
      d_enumShapes(false),
586
      d_enumShapesInit(false),
587
      d_isIncrementing(false),
588
      d_currTermSet(false),
589
      d_consClassNum(0),
590
      d_ccWeight(0),
591
      d_consNum(0),
592
      d_currChildSize(0),
593
294
      d_childrenValid(0)
594
{
595
294
}
596
597
294
bool SygusEnumerator::TermEnumMaster::initialize(SygusEnumerator* se,
598
                                                 TypeNode tn)
599
{
600
294
  Trace("sygus-enum-debug") << "master(" << tn << "): init...\n";
601
294
  d_tds = se->d_tds;
602
294
  d_se = se;
603
294
  d_tn = tn;
604
605
294
  d_currSize = 0;
606
  // we will start with constructor class zero
607
294
  d_consClassNum = 0;
608
294
  d_currChildSize = 0;
609
294
  d_ccCons.clear();
610
294
  d_enumShapes = se->isEnumShapes();
611
294
  d_enumShapesInit = false;
612
294
  d_isIncrementing = false;
613
294
  d_currTermSet = false;
614
294
  bool ret = increment();
615
588
  Trace("sygus-enum-debug") << "master(" << tn
616
294
                            << "): finish init, ret = " << ret << "\n";
617
294
  return ret;
618
}
619
620
101022
Node SygusEnumerator::TermEnumMaster::getCurrent()
621
{
622
101022
  if (d_currTermSet)
623
  {
624
45807
    return d_currTerm;
625
  }
626
55215
  d_currTermSet = true;
627
  // construct based on the children
628
110430
  std::vector<Node> children;
629
55215
  const DType& dt = d_tn.getDType();
630
55215
  Assert(d_consNum > 0 && d_consNum <= d_ccCons.size());
631
  // get the current constructor number
632
55215
  unsigned cnum = d_ccCons[d_consNum - 1];
633
55215
  children.push_back(dt[cnum].getConstructor());
634
  // add the current of each child to children
635
163743
  for (unsigned i = 0, nargs = dt[cnum].getNumArgs(); i < nargs; i++)
636
  {
637
108528
    Assert(d_children.find(i) != d_children.end());
638
217056
    Node cc = d_children[i].getCurrent();
639
108528
    if (cc.isNull())
640
    {
641
      d_currTerm = cc;
642
      return cc;
643
    }
644
108528
    children.push_back(cc);
645
  }
646
55215
  if (d_enumShapes)
647
  {
648
    // ensure all variables are unique
649
10977
    childrenToShape(children);
650
  }
651
55215
  d_currTerm = NodeManager::currentNM()->mkNode(APPLY_CONSTRUCTOR, children);
652
55215
  return d_currTerm;
653
}
654
655
56479
bool SygusEnumerator::TermEnumMaster::increment()
656
{
657
  // Am I already incrementing? If so, fail.
658
  // This is to break infinite loops for slave enumerators who request an
659
  // increment() from the master enumerator of their type that is also their
660
  // parent. This ensures we do not loop on a grammar like:
661
  //   A -> -( A ) | B+B
662
  //   B -> x | y
663
  // where we require the first term enumerated to be over B+B.
664
  // Set that we are incrementing
665
56479
  if (d_isIncrementing)
666
  {
667
    return false;
668
  }
669
112958
  Trace("sygus-enum-summary") << "SygusEnumerator::TermEnumMaster: increment "
670
56479
                              << d_tn << "..." << std::endl;
671
56479
  d_isIncrementing = true;
672
56479
  bool ret = incrementInternal();
673
56479
  d_isIncrementing = false;
674
112958
  Trace("sygus-enum-summary")
675
56479
      << "SygusEnumerator::TermEnumMaster: finished increment " << d_tn
676
56479
      << std::endl;
677
56479
  return ret;
678
}
679
680
57005
bool SygusEnumerator::TermEnumMaster::incrementInternal()
681
{
682
57005
  SygusEnumerator::TermCache& tc = d_se->d_tcache[d_tn];
683
57005
  if (tc.isComplete())
684
  {
685
752
    return false;
686
  }
687
112506
  Trace("sygus-enum-debug2") << "master(" << d_tn
688
56253
                             << "): get last constructor class..." << std::endl;
689
  // the maximum index of a constructor class to consider
690
56253
  unsigned ncc = tc.getLastConstructorClassIndexForWeight(d_currSize);
691
112506
  Trace("sygus-enum-debug2") << "Last constructor class " << d_currSize << ": "
692
56253
                             << ncc << std::endl;
693
  // If we are enumerating shapes, the first enumerated term is a free variable.
694
56253
  if (d_enumShapes && !d_enumShapesInit)
695
  {
696
66
    Assert(d_tds != nullptr);
697
132
    Node fv = d_tds->getFreeVar(d_tn, 0);
698
66
    d_enumShapesInit = true;
699
66
    d_currTermSet = true;
700
66
    d_currTerm = fv;
701
    // must add to term cache
702
66
    tc.addTerm(fv);
703
66
    return true;
704
  }
705
706
  // have we initialized the current constructor class?
707
57923
  while (d_ccCons.empty() && d_consClassNum < ncc)
708
  {
709
868
    Assert(d_ccTypes.empty());
710
1736
    Trace("sygus-enum-debug2") << "master(" << d_tn
711
868
                               << "): try constructor class " << d_consClassNum
712
868
                               << std::endl;
713
    // get the list of constructors in the constructor class
714
868
    tc.getConstructorClass(d_consClassNum, d_ccCons);
715
    // if there are any...
716
868
    if (!d_ccCons.empty())
717
    {
718
      // successfully initialized the constructor class
719
796
      d_consNum = 0;
720
      // we will populate the children
721
796
      Assert(d_children.empty());
722
796
      Assert(d_ccTypes.empty());
723
796
      tc.getTypesForConstructorClass(d_consClassNum, d_ccTypes);
724
796
      d_ccWeight = tc.getWeightForConstructorClass(d_consClassNum);
725
796
      d_childrenValid = 0;
726
      // initialize the children into their initial state
727
796
      if (!initializeChildren())
728
      {
729
        // didn't work (due to size), we will try the next class
730
104
        d_ccCons.clear();
731
104
        d_ccTypes.clear();
732
208
        Trace("sygus-enum-debug2") << "master(" << d_tn
733
104
                                   << "): failed due to init size\n";
734
      }
735
    }
736
    else
737
    {
738
      // No constructors in constructor class. This can happen for class 0 if a
739
      // type has no nullary constructors with weight 0.
740
144
      Trace("sygus-enum-debug2") << "master(" << d_tn
741
72
                                 << "): failed due to no cons\n";
742
    }
743
    // increment the next constructor class we will try
744
868
    d_consClassNum++;
745
  }
746
747
  // have we run out of constructor classes for this size?
748
56187
  if (d_ccCons.empty())
749
  {
750
    // check whether we should terminate, which notice always treats
751
    // uninterpreted sorts as infinite, since we do not put bounds on them
752
    // in our enumeration.
753
446
    if (isCardinalityClassFinite(d_tn.getCardinalityClass(), false))
754
    {
755
92
      if (ncc == tc.getNumConstructorClasses())
756
      {
757
67
        bool doTerminate = true;
758
78
        for (unsigned i = 1; i < ncc; i++)
759
        {
760
          // The maximum size of terms from a constructor class can be
761
          // determined if all of its argument types are finished enumerating.
762
          // If this maximum size is less than or equal to d_currSize for
763
          // each constructor class, we are done.
764
35
          unsigned sum = tc.getWeightForConstructorClass(i);
765
46
          std::vector<TypeNode> cctns;
766
35
          tc.getTypesForConstructorClass(i, cctns);
767
54
          for (unsigned j = 0, ntypes = cctns.size(); j < ntypes; j++)
768
          {
769
62
            TypeNode tnc = cctns[j];
770
43
            SygusEnumerator::TermCache& tcc = d_se->d_tcache[tnc];
771
43
            if (!tcc.isComplete())
772
            {
773
              // maximum size of this constructor class cannot be determined
774
24
              doTerminate = false;
775
24
              break;
776
            }
777
            else
778
            {
779
19
              sum += tcc.getEnumSize();
780
19
              if (sum > d_currSize)
781
              {
782
                // maximum size of this constructor class is greater than size
783
                doTerminate = false;
784
                break;
785
              }
786
            }
787
          }
788
35
          if (!doTerminate)
789
          {
790
24
            break;
791
          }
792
        }
793
67
        if (doTerminate)
794
        {
795
86
          Trace("sygus-engine") << "master(" << d_tn << "): complete at size "
796
43
                                << d_currSize << std::endl;
797
43
          tc.setComplete();
798
43
          return false;
799
        }
800
      }
801
    }
802
803
    // increment the size bound
804
403
    d_currSize++;
805
806
    Trace("sygus-enum-debug2") << "master(" << d_tn
806
403
                               << "): size++ : " << d_currSize << "\n";
807
403
    if (Trace.isOn("sygus-engine"))
808
    {
809
      // am i the master enumerator? if so, print
810
      if (d_se->d_tlEnum == this)
811
      {
812
        Trace("sygus-engine") << "SygusEnumerator::size = " << d_currSize
813
                              << std::endl;
814
      }
815
    }
816
817
    // push the bound
818
403
    tc.pushEnumSizeIndex();
819
820
    // restart with constructor class one (skip nullary constructors)
821
403
    d_consClassNum = 1;
822
823
    // We break for a round: return the null term when we cross a size
824
    // boundary. This ensures that the necessary breaks are taken, e.g.
825
    // in slave enumerators who may instead want to abandon this call to
826
    // increment master when the size of the master makes their increment
827
    // infeasible.
828
403
    d_currTermSet = true;
829
403
    d_currTerm = Node::null();
830
403
    return true;
831
  }
832
833
55741
  bool incSuccess = false;
834
28640
  do
835
  {
836
167710
    Trace("sygus-enum-debug2") << "master(" << d_tn << "): check return "
837
167710
                               << d_childrenValid << "/" << d_ccTypes.size()
838
83855
                               << std::endl;
839
    // the children should be initialized by here
840
83855
    Assert(d_childrenValid == d_ccTypes.size());
841
842
    // do we have more constructors for the given children?
843
83855
    if (d_consNum < d_ccCons.size())
844
    {
845
110430
      Trace("sygus-enum-debug2") << "master(" << d_tn << "): try constructor "
846
55215
                                 << d_consNum << std::endl;
847
      // increment constructor index
848
      // we will build for the current constructor and the given children
849
55215
      d_consNum++;
850
55215
      d_currTermSet = false;
851
55215
      d_currTerm = Node::null();
852
110430
      Node c = getCurrent();
853
55215
      if (!c.isNull())
854
      {
855
55215
        if (!tc.addTerm(c))
856
        {
857
          // the term was not unique based on rewriting
858
62866
          Trace("sygus-enum-debug2") << "master(" << d_tn
859
31433
                                     << "): failed addTerm\n";
860
          // we will return null (d_currTermSet is true at this point)
861
31433
          Assert(d_currTermSet);
862
31433
          d_currTerm = Node::null();
863
        }
864
      }
865
55215
      return true;
866
    }
867
868
    // finished constructors for this set of children, must increment children
869
870
    // reset the constructor number
871
28640
    d_consNum = 0;
872
873
    // try incrementing the last child until we find one that works
874
28640
    incSuccess = false;
875
90592
    while (!incSuccess && d_childrenValid > 0)
876
    {
877
61952
      Trace("sygus-enum-debug2") << "master(" << d_tn << "): try incrementing "
878
30976
                                 << d_childrenValid << std::endl;
879
30976
      unsigned i = d_childrenValid - 1;
880
30976
      Assert(d_children[i].getCurrentSize() <= d_currChildSize);
881
      // track the size
882
30976
      d_currChildSize -= d_children[i].getCurrentSize();
883
30976
      if (d_children[i].increment())
884
      {
885
56238
        Trace("sygus-enum-debug2") << "master(" << d_tn
886
28119
                                   << "): increment success...\n";
887
28119
        d_currChildSize += d_children[i].getCurrentSize();
888
        // must see if we can initialize the remaining children here
889
        // if not, there is no use continuing.
890
28119
        if (initializeChildren())
891
        {
892
56228
          Trace("sygus-enum-debug2")
893
28114
              << "master(" << d_tn << "): success init children\n";
894
28114
          Assert(d_currChildSize + d_ccWeight <= d_currSize);
895
28114
          incSuccess = true;
896
        }
897
        else
898
        {
899
          // failed to initialize the remaining children (likely due to a
900
          // child having a non-zero minimum size bound).
901
10
          Trace("sygus-enum-debug2")
902
5
              << "master(" << d_tn << "): fail init children\n";
903
5
          d_currChildSize -= d_children[i].getCurrentSize();
904
        }
905
      }
906
30976
      if (!incSuccess)
907
      {
908
5724
        Trace("sygus-enum-debug2") << "master(" << d_tn
909
2862
                                   << "): fail, backtrack...\n";
910
        // current child is out of values
911
2862
        d_children.erase(i);
912
2862
        d_childrenValid--;
913
      }
914
    }
915
  } while (incSuccess);
916
1052
  Trace("sygus-enum-debug2") << "master(" << d_tn
917
526
                             << "): failed increment children\n";
918
  // restart with the next constructor class
919
526
  d_ccCons.clear();
920
526
  d_ccTypes.clear();
921
526
  return incrementInternal();
922
}
923
924
28915
bool SygusEnumerator::TermEnumMaster::initializeChildren()
925
{
926
57830
  Trace("sygus-enum-debug2")
927
28915
      << "master(" << d_tn << "): init children, start = " << d_childrenValid
928
57830
      << ", #types=" << d_ccTypes.size() << ", sizes=" << d_currChildSize << "/"
929
28915
      << d_currSize << std::endl;
930
28915
  unsigned currChildren = d_childrenValid;
931
28915
  unsigned sizeMin = 0;
932
  // while we need to initialize the current child
933
35351
  while (d_childrenValid < d_ccTypes.size())
934
  {
935
3327
    if (!initializeChild(d_childrenValid, sizeMin))
936
    {
937
169
      if (d_childrenValid == currChildren)
938
      {
939
        // we are back to the child we started with, we terminate now.
940
218
        Trace("sygus-enum-debug2") << "master(" << d_tn
941
109
                                   << "): init children : failed, finished"
942
109
                                   << std::endl;
943
109
        return false;
944
      }
945
120
      Trace("sygus-enum-debug2") << "master(" << d_tn
946
60
                                 << "): init children : failed" << std::endl;
947
      // we failed in this size configuration
948
      // reinitialize with the next size up
949
60
      unsigned currSize = d_children[d_childrenValid - 1].getCurrentSize();
950
60
      d_currChildSize -= currSize;
951
60
      sizeMin = currSize + 1;
952
60
      d_children.erase(d_childrenValid - 1);
953
60
      d_childrenValid--;
954
    }
955
    else
956
    {
957
3158
      sizeMin = 0;
958
3158
      d_childrenValid++;
959
    }
960
  }
961
57612
  Trace("sygus-enum-debug2") << "master(" << d_tn
962
28806
                             << "): init children : success" << std::endl;
963
  // initialized all children
964
28806
  return true;
965
}
966
967
3327
bool SygusEnumerator::TermEnumMaster::initializeChild(unsigned i,
968
                                                      unsigned sizeMin)
969
{
970
3327
  Assert(d_ccWeight <= d_currSize);
971
3327
  Assert(d_currChildSize + d_ccWeight <= d_currSize);
972
3327
  unsigned sizeMax = (d_currSize - d_ccWeight) - d_currChildSize;
973
6654
  Trace("sygus-enum-debug2") << "master(" << d_tn << "): initializeChild " << i
974
3327
                             << " (" << d_currSize << ", " << d_ccWeight << ", "
975
3327
                             << d_currChildSize << ")\n";
976
3327
  if (sizeMin > sizeMax)
977
  {
978
60
    Trace("sygus-enum-debug2") << "master(" << d_tn << "): failed due to size "
979
30
                               << sizeMin << "/" << sizeMax << "\n";
980
30
    return false;
981
  }
982
  // initialize the child to enumerate exactly the terms that sum to size
983
3297
  sizeMin = (i + 1 == d_ccTypes.size()) ? sizeMax : sizeMin;
984
3297
  TermEnumSlave& te = d_children[i];
985
3297
  bool init = te.initialize(d_se, d_ccTypes[i], sizeMin, sizeMax);
986
3297
  if (!init)
987
  {
988
    // failed to initialize
989
139
    d_children.erase(i);
990
278
    Trace("sygus-enum-debug2") << "master(" << d_tn
991
139
                               << "): failed due to child init\n";
992
139
    return false;
993
  }
994
3158
  unsigned teSize = te.getCurrentSize();
995
  // fail if the initial children size does not fit d_currSize-d_ccWeight
996
3158
  if (teSize + d_currChildSize + d_ccWeight > d_currSize)
997
  {
998
    d_children.erase(i);
999
    Trace("sygus-enum-debug2") << "master(" << d_tn
1000
                               << "): failed due to child size\n";
1001
    return false;
1002
  }
1003
3158
  d_currChildSize += teSize;
1004
6316
  Trace("sygus-enum-debug2") << "master(" << d_tn
1005
3158
                             << "): success initializeChild " << i << "\n";
1006
3158
  return true;
1007
}
1008
1009
10977
void SygusEnumerator::TermEnumMaster::childrenToShape(
1010
    std::vector<Node>& children)
1011
{
1012
10977
  if (children.size() <= 2)
1013
  {
1014
    // don't need to convert constants and unary applications
1015
961
    return;
1016
  }
1017
20032
  std::map<TypeNode, int> vcounter;
1018
  // Buffered child, so that we only compute vcounter if there are more than
1019
  // one children with free variables, since otherwise there is no change.
1020
  // For example, if we are given { C, (+ x1 x2), 1 }, we buffer child (+ x1 x2)
1021
  // noting that it has free variables. We proceed with processing the remaining
1022
  // children, and note that no other child contains free variables, and hence
1023
  // no change is necessary (since by construction, all children have the
1024
  // property of having unique variable subterms). On the other hand if the
1025
  // last child above was x1, then this would trigger us to convert (+ x1 x2)
1026
  // while computing vcounter, and subsequently update x1 to x3 to obtain
1027
  // { C, (+ x1 x2), x3 }.
1028
  // Have we set the buffer child index
1029
10016
  bool bufferChildSet = false;
1030
  // Have we processed the buffer child index
1031
10016
  bool bufferChildProcessed = false;
1032
  // The buffer child index
1033
10016
  size_t bufferChild = 0;
1034
32121
  for (size_t i = 1, nchildren = children.size(); i < nchildren; i++)
1035
  {
1036
22105
    if (!expr::hasBoundVar(children[i]))
1037
    {
1038
      // don't need to care about expressions with no bound variables
1039
10145
      continue;
1040
    }
1041
20815
    else if (!bufferChildSet)
1042
    {
1043
8855
      bufferChild = i;
1044
8855
      bufferChildSet = true;
1045
8855
      continue;
1046
    }
1047
3105
    else if (!bufferChildProcessed)
1048
    {
1049
      // process the buffer child
1050
2910
      children[bufferChild] = convertShape(children[bufferChild], vcounter);
1051
2910
      bufferChildProcessed = true;
1052
    }
1053
3105
    children[i] = convertShape(children[i], vcounter);
1054
  }
1055
}
1056
1057
6015
Node SygusEnumerator::TermEnumMaster::convertShape(
1058
    Node n, std::map<TypeNode, int>& vcounter)
1059
{
1060
6015
  Assert(d_tds != nullptr);
1061
6015
  NodeManager* nm = NodeManager::currentNM();
1062
12030
  std::unordered_map<TNode, Node> visited;
1063
6015
  std::unordered_map<TNode, Node>::iterator it;
1064
12030
  std::vector<TNode> visit;
1065
12030
  TNode cur;
1066
6015
  visit.push_back(n);
1067
15853
  do
1068
  {
1069
21868
    cur = visit.back();
1070
21868
    visit.pop_back();
1071
21868
    it = visited.find(cur);
1072
1073
21868
    if (it == visited.end())
1074
    {
1075
16491
      if (cur.isVar())
1076
      {
1077
        // do the conversion
1078
8136
        visited[cur] = d_tds->getFreeVarInc(cur.getType(), vcounter);
1079
      }
1080
8355
      else if (!expr::hasBoundVar(cur))
1081
      {
1082
        // no bound variables, no change
1083
3028
        visited[cur] = cur;
1084
      }
1085
      else
1086
      {
1087
5327
        visited[cur] = Node::null();
1088
5327
        visit.push_back(cur);
1089
5327
        visit.insert(visit.end(), cur.begin(), cur.end());
1090
      }
1091
    }
1092
5377
    else if (it->second.isNull())
1093
    {
1094
10654
      Node ret = cur;
1095
5327
      bool childChanged = false;
1096
10654
      std::vector<Node> children;
1097
5327
      if (cur.getMetaKind() == metakind::PARAMETERIZED)
1098
      {
1099
5327
        children.push_back(cur.getOperator());
1100
      }
1101
15853
      for (const Node& cn : cur)
1102
      {
1103
10526
        it = visited.find(cn);
1104
10526
        Assert(it != visited.end());
1105
10526
        Assert(!it->second.isNull());
1106
10526
        childChanged = childChanged || cn != it->second;
1107
10526
        children.push_back(it->second);
1108
      }
1109
5327
      if (childChanged)
1110
      {
1111
3721
        ret = nm->mkNode(cur.getKind(), children);
1112
      }
1113
5327
      visited[cur] = ret;
1114
    }
1115
21868
  } while (!visit.empty());
1116
6015
  Assert(visited.find(n) != visited.end());
1117
6015
  Assert(!visited.find(n)->second.isNull());
1118
12030
  return visited[n];
1119
}
1120
1121
11
SygusEnumerator::TermEnumMasterInterp::TermEnumMasterInterp(TypeNode tn)
1122
11
    : TermEnum(), d_te(tn), d_currNumConsts(0), d_nextIndexEnd(0)
1123
{
1124
11
}
1125
1126
11
bool SygusEnumerator::TermEnumMasterInterp::initialize(SygusEnumerator* se,
1127
                                                       TypeNode tn)
1128
{
1129
11
  d_se = se;
1130
11
  d_tn = tn;
1131
11
  d_currSize = 0;
1132
11
  d_currNumConsts = 1;
1133
11
  d_nextIndexEnd = 1;
1134
11
  return true;
1135
}
1136
1137
101
Node SygusEnumerator::TermEnumMasterInterp::getCurrent() { return *d_te; }
1138
102
bool SygusEnumerator::TermEnumMasterInterp::increment()
1139
{
1140
102
  if (d_te.isFinished())
1141
  {
1142
1
    return false;
1143
  }
1144
101
  SygusEnumerator::TermCache& tc = d_se->d_tcache[d_tn];
1145
202
  Node curr = getCurrent();
1146
101
  tc.addTerm(curr);
1147
101
  if (tc.getNumTerms() == d_nextIndexEnd)
1148
  {
1149
16
    tc.pushEnumSizeIndex();
1150
16
    d_currSize++;
1151
16
    d_currNumConsts = d_currNumConsts * options::sygusActiveGenEnumConsts();
1152
16
    d_nextIndexEnd = d_nextIndexEnd + d_currNumConsts;
1153
  }
1154
101
  ++d_te;
1155
101
  return !d_te.isFinished();
1156
}
1157
5
SygusEnumerator::TermEnumMasterFv::TermEnumMasterFv() : TermEnum() {}
1158
5
bool SygusEnumerator::TermEnumMasterFv::initialize(SygusEnumerator* se,
1159
                                                   TypeNode tn)
1160
{
1161
5
  d_se = se;
1162
5
  d_tn = tn;
1163
5
  d_currSize = 0;
1164
10
  Node ret = getCurrent();
1165
5
  AlwaysAssert(!ret.isNull());
1166
5
  SygusEnumerator::TermCache& tc = d_se->d_tcache[d_tn];
1167
5
  tc.addTerm(ret);
1168
10
  return true;
1169
}
1170
1171
10
Node SygusEnumerator::TermEnumMasterFv::getCurrent()
1172
{
1173
10
  Assert(d_se->d_tds != nullptr);
1174
10
  Node ret = d_se->d_tds->getFreeVar(d_tn, d_currSize);
1175
20
  Trace("sygus-enum-debug2") << "master_fv(" << d_tn << "): mk " << ret
1176
10
                             << std::endl;
1177
10
  return ret;
1178
}
1179
1180
5
bool SygusEnumerator::TermEnumMasterFv::increment()
1181
{
1182
5
  SygusEnumerator::TermCache& tc = d_se->d_tcache[d_tn];
1183
  // size increments at a constant rate
1184
5
  d_currSize++;
1185
5
  tc.pushEnumSizeIndex();
1186
10
  Node curr = getCurrent();
1187
10
  Trace("sygus-enum-debug2") << "master_fv(" << d_tn << "): increment, add "
1188
5
                             << curr << std::endl;
1189
5
  bool ret = tc.addTerm(curr);
1190
5
  AlwaysAssert(ret);
1191
10
  return true;
1192
}
1193
1194
}  // namespace quantifiers
1195
}  // namespace theory
1196
29502
}  // namespace cvc5