GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/bv/bv_subtheory_core.cpp Lines: 263 308 85.4 %
Date: 2021-05-21 Branches: 538 1187 45.3 %

Line Exec Source
1
/******************************************************************************
2
 * Top contributors (to current version):
3
 *   Andrew Reynolds, Liana Hadarean, 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
 * Algebraic solver.
14
 */
15
16
#include "theory/bv/bv_subtheory_core.h"
17
18
#include "expr/skolem_manager.h"
19
#include "options/bv_options.h"
20
#include "options/smt_options.h"
21
#include "smt/smt_statistics_registry.h"
22
#include "theory/bv/bv_solver_lazy.h"
23
#include "theory/bv/theory_bv_utils.h"
24
#include "theory/ext_theory.h"
25
#include "theory/theory_model.h"
26
27
using namespace std;
28
using namespace cvc5;
29
using namespace cvc5::context;
30
using namespace cvc5::theory;
31
using namespace cvc5::theory::bv;
32
using namespace cvc5::theory::bv::utils;
33
34
94
bool CoreSolverExtTheoryCallback::getCurrentSubstitution(
35
    int effort,
36
    const std::vector<Node>& vars,
37
    std::vector<Node>& subs,
38
    std::map<Node, std::vector<Node> >& exp)
39
{
40
94
  if (d_equalityEngine == nullptr)
41
  {
42
94
    return false;
43
  }
44
  // get the constant equivalence classes
45
  bool retVal = false;
46
  for (const Node& n : vars)
47
  {
48
    if (d_equalityEngine->hasTerm(n))
49
    {
50
      Node nr = d_equalityEngine->getRepresentative(n);
51
      if (nr.isConst())
52
      {
53
        subs.push_back(nr);
54
        exp[n].push_back(n.eqNode(nr));
55
        retVal = true;
56
      }
57
      else
58
      {
59
        subs.push_back(n);
60
      }
61
    }
62
    else
63
    {
64
      subs.push_back(n);
65
    }
66
  }
67
  // return true if the substitution is non-trivial
68
  return retVal;
69
}
70
71
125
bool CoreSolverExtTheoryCallback::getReduction(int effort,
72
                                               Node n,
73
                                               Node& nr,
74
                                               bool& satDep)
75
{
76
125
  Trace("bv-ext") << "TheoryBV::checkExt : non-reduced : " << n << std::endl;
77
125
  if (n.getKind() == kind::BITVECTOR_TO_NAT)
78
  {
79
69
    nr = utils::eliminateBv2Nat(n);
80
69
    satDep = false;
81
69
    return true;
82
  }
83
56
  else if (n.getKind() == kind::INT_TO_BITVECTOR)
84
  {
85
56
    nr = utils::eliminateInt2Bv(n);
86
56
    satDep = false;
87
56
    return true;
88
  }
89
  return false;
90
}
91
92
8910
CoreSolver::CoreSolver(context::Context* c, BVSolverLazy* bv)
93
    : SubtheorySolver(c, bv),
94
      d_notify(*this),
95
      d_isComplete(c, true),
96
      d_lemmaThreshold(16),
97
      d_preregisterCalled(false),
98
      d_checkCalled(false),
99
      d_bv(bv),
100
      d_extTheoryCb(),
101
      d_extTheory(new ExtTheory(d_extTheoryCb,
102
8910
                                bv->d_bv.getSatContext(),
103
8910
                                bv->d_bv.getUserContext(),
104
17820
                                bv->d_bv.getOutputChannel())),
105
      d_reasons(c),
106
      d_needsLastCallCheck(false),
107
8910
      d_extf_range_infer(bv->d_bv.getUserContext()),
108
35640
      d_extf_collapse_infer(bv->d_bv.getUserContext())
109
{
110
8910
  d_extTheory->addFunctionKind(kind::BITVECTOR_TO_NAT);
111
8910
  d_extTheory->addFunctionKind(kind::INT_TO_BITVECTOR);
112
8910
}
113
114
17820
CoreSolver::~CoreSolver() {}
115
116
8910
bool CoreSolver::needsEqualityEngine(EeSetupInfo& esi)
117
{
118
8910
  esi.d_notify = &d_notify;
119
8910
  esi.d_name = "theory::bv::ee";
120
8910
  return true;
121
}
122
123
8910
void CoreSolver::finishInit()
124
{
125
  // use the parent's equality engine, which may be the one we allocated above
126
8910
  d_equalityEngine = d_bv->d_bv.getEqualityEngine();
127
128
  // The kinds we are treating as function application in congruence
129
8910
  d_equalityEngine->addFunctionKind(kind::BITVECTOR_CONCAT, true);
130
  //    d_equalityEngine->addFunctionKind(kind::BITVECTOR_AND);
131
  //    d_equalityEngine->addFunctionKind(kind::BITVECTOR_OR);
132
  //    d_equalityEngine->addFunctionKind(kind::BITVECTOR_XOR);
133
  //    d_equalityEngine->addFunctionKind(kind::BITVECTOR_NOT);
134
  //    d_equalityEngine->addFunctionKind(kind::BITVECTOR_NAND);
135
  //    d_equalityEngine->addFunctionKind(kind::BITVECTOR_NOR);
136
  //    d_equalityEngine->addFunctionKind(kind::BITVECTOR_XNOR);
137
  //    d_equalityEngine->addFunctionKind(kind::BITVECTOR_COMP);
138
8910
  d_equalityEngine->addFunctionKind(kind::BITVECTOR_MULT, true);
139
8910
  d_equalityEngine->addFunctionKind(kind::BITVECTOR_ADD, true);
140
8910
  d_equalityEngine->addFunctionKind(kind::BITVECTOR_EXTRACT, true);
141
  //    d_equalityEngine->addFunctionKind(kind::BITVECTOR_SUB);
142
  //    d_equalityEngine->addFunctionKind(kind::BITVECTOR_NEG);
143
  //    d_equalityEngine->addFunctionKind(kind::BITVECTOR_UDIV);
144
  //    d_equalityEngine->addFunctionKind(kind::BITVECTOR_UREM);
145
  //    d_equalityEngine->addFunctionKind(kind::BITVECTOR_SDIV);
146
  //    d_equalityEngine->addFunctionKind(kind::BITVECTOR_SREM);
147
  //    d_equalityEngine->addFunctionKind(kind::BITVECTOR_SMOD);
148
  //    d_equalityEngine->addFunctionKind(kind::BITVECTOR_SHL);
149
  //    d_equalityEngine->addFunctionKind(kind::BITVECTOR_LSHR);
150
  //    d_equalityEngine->addFunctionKind(kind::BITVECTOR_ASHR);
151
  //    d_equalityEngine->addFunctionKind(kind::BITVECTOR_ULT);
152
  //    d_equalityEngine->addFunctionKind(kind::BITVECTOR_ULE);
153
  //    d_equalityEngine->addFunctionKind(kind::BITVECTOR_UGT);
154
  //    d_equalityEngine->addFunctionKind(kind::BITVECTOR_UGE);
155
  //    d_equalityEngine->addFunctionKind(kind::BITVECTOR_SLT);
156
  //    d_equalityEngine->addFunctionKind(kind::BITVECTOR_SLE);
157
  //    d_equalityEngine->addFunctionKind(kind::BITVECTOR_SGT);
158
  //    d_equalityEngine->addFunctionKind(kind::BITVECTOR_SGE);
159
8910
  d_equalityEngine->addFunctionKind(kind::BITVECTOR_TO_NAT);
160
8910
  d_equalityEngine->addFunctionKind(kind::INT_TO_BITVECTOR);
161
8910
}
162
163
218165
void CoreSolver::preRegister(TNode node) {
164
218165
  d_preregisterCalled = true;
165
218165
  if (node.getKind() == kind::EQUAL) {
166
53108
    d_equalityEngine->addTriggerPredicate(node);
167
  } else {
168
165057
    d_equalityEngine->addTerm(node);
169
    // Register with the extended theory, for context-dependent simplification.
170
    // Notice we do this for registered terms but not internally generated
171
    // equivalence classes. The two should roughly cooincide. Since ExtTheory is
172
    // being used as a heuristic, it is good enough to be registered here.
173
165057
    d_extTheory->registerTerm(node);
174
  }
175
218165
}
176
177
178
3464
void CoreSolver::explain(TNode literal, std::vector<TNode>& assumptions) {
179
3464
  bool polarity = literal.getKind() != kind::NOT;
180
6928
  TNode atom = polarity ? literal : literal[0];
181
3464
  if (atom.getKind() == kind::EQUAL) {
182
3464
    d_equalityEngine->explainEquality(atom[0], atom[1], polarity, assumptions);
183
  } else {
184
    d_equalityEngine->explainPredicate(atom, polarity, assumptions);
185
  }
186
3464
}
187
188
228271
bool CoreSolver::check(Theory::Effort e) {
189
228271
  Trace("bitvector::core") << "CoreSolver::check \n";
190
191
228271
  d_bv->d_im.spendResource(Resource::TheoryCheckStep);
192
193
228271
  d_checkCalled = true;
194
228271
  Assert(!d_bv->inConflict());
195
228271
  ++(d_statistics.d_numCallstoCheck);
196
228271
  bool ok = true;
197
456542
  std::vector<Node> core_eqs;
198
456542
  TNodeBoolMap seen;
199
2972117
  while (! done()) {
200
2744013
    TNode fact = get();
201
1372090
    if (d_isComplete && !isCompleteForTerm(fact, seen)) {
202
2653
      d_isComplete = false;
203
    }
204
205
    // only reason about equalities
206
1372090
    if (fact.getKind() == kind::EQUAL || (fact.getKind() == kind::NOT && fact[0].getKind() == kind::EQUAL)) {
207
811256
      ok = assertFactToEqualityEngine(fact, fact);
208
    } else {
209
560834
      ok = assertFactToEqualityEngine(fact, fact);
210
    }
211
1372090
    if (!ok)
212
167
      return false;
213
  }
214
215
228104
  if (Theory::fullEffort(e) && isComplete()) {
216
20489
    buildModel();
217
  }
218
219
228104
  return true;
220
}
221
222
20489
void CoreSolver::buildModel()
223
{
224
20489
  Debug("bv-core") << "CoreSolver::buildModel() \n";
225
20489
  NodeManager* nm = NodeManager::currentNM();
226
20489
  d_modelValues.clear();
227
40734
  TNodeSet constants;
228
40734
  TNodeSet constants_in_eq_engine;
229
  // collect constants in equality engine
230
20489
  eq::EqClassesIterator eqcs_i = eq::EqClassesIterator(d_equalityEngine);
231
121147
  while (!eqcs_i.isFinished())
232
  {
233
100658
    TNode repr = *eqcs_i;
234
50329
    if (repr.getKind() == kind::CONST_BITVECTOR)
235
    {
236
      // must check if it's just the constant
237
3503
      eq::EqClassIterator it(repr, d_equalityEngine);
238
3503
      if (!(++it).isFinished() || true)
239
      {
240
3503
        constants.insert(repr);
241
3503
        constants_in_eq_engine.insert(repr);
242
      }
243
    }
244
50329
    ++eqcs_i;
245
  }
246
247
  // build repr to value map
248
249
20489
  eqcs_i = eq::EqClassesIterator(d_equalityEngine);
250
119375
  while (!eqcs_i.isFinished())
251
  {
252
56874
    TNode repr = *eqcs_i;
253
49687
    ++eqcs_i;
254
255
146594
    if (!repr.isVar() && repr.getKind() != kind::CONST_BITVECTOR
256
143119
        && !d_bv->isSharedTerm(repr))
257
    {
258
42256
      continue;
259
    }
260
261
14618
    TypeNode type = repr.getType();
262
7431
    if (type.isBitVector() && repr.getKind() != kind::CONST_BITVECTOR)
263
    {
264
3910
      Debug("bv-core-model") << "   processing " << repr << "\n";
265
      // we need to assign a value for it
266
7576
      TypeEnumerator te(type);
267
7576
      Node val;
268
5957
      do
269
      {
270
9867
        val = *te;
271
9867
        ++te;
272
        // Debug("bv-core-model") << "  trying value " << val << "\n";
273
        // Debug("bv-core-model") << "  is in set? " << constants.count(val) <<
274
        // "\n"; Debug("bv-core-model") << "  enumerator done? " <<
275
        // te.isFinished() << "\n";
276
9867
      } while (constants.count(val) != 0 && !(te.isFinished()));
277
278
3910
      if (te.isFinished() && constants.count(val) != 0)
279
      {
280
        // if we cannot enumerate anymore values we just return the lemma
281
        // stating that at least two of the representatives are equal.
282
488
        std::vector<TNode> representatives;
283
244
        representatives.push_back(repr);
284
285
308
        for (TNodeSet::const_iterator it = constants_in_eq_engine.begin();
286
308
             it != constants_in_eq_engine.end();
287
             ++it)
288
        {
289
128
          TNode constant = *it;
290
64
          if (utils::getSize(constant) == utils::getSize(repr))
291
          {
292
36
            representatives.push_back(constant);
293
          }
294
        }
295
825
        for (ModelValue::const_iterator it = d_modelValues.begin();
296
825
             it != d_modelValues.end();
297
             ++it)
298
        {
299
581
          representatives.push_back(it->first);
300
        }
301
488
        std::vector<Node> equalities;
302
1105
        for (unsigned i = 0; i < representatives.size(); ++i)
303
        {
304
2044
          for (unsigned j = i + 1; j < representatives.size(); ++j)
305
          {
306
2333
            TNode a = representatives[i];
307
2333
            TNode b = representatives[j];
308
2399
            if (a.getKind() == kind::CONST_BITVECTOR
309
1183
                && b.getKind() == kind::CONST_BITVECTOR)
310
            {
311
33
              Assert(a != b);
312
33
              continue;
313
            }
314
1150
            if (utils::getSize(a) == utils::getSize(b))
315
            {
316
1097
              equalities.push_back(nm->mkNode(kind::EQUAL, a, b));
317
            }
318
          }
319
        }
320
        // better off letting the SAT solver split on values
321
244
        if (equalities.size() > d_lemmaThreshold)
322
        {
323
          d_isComplete = false;
324
          return;
325
        }
326
327
244
        if (equalities.size() == 0)
328
        {
329
          Debug("bv-core") << "  lemma: true (no equalities)" << std::endl;
330
        }
331
        else
332
        {
333
488
          Node lemma = utils::mkOr(equalities);
334
244
          d_bv->lemma(lemma);
335
244
          Debug("bv-core") << "  lemma: " << lemma << std::endl;
336
        }
337
244
        return;
338
      }
339
340
3666
      Debug("bv-core-model") << "   " << repr << " => " << val << "\n";
341
3666
      constants.insert(val);
342
3666
      d_modelValues[repr] = val;
343
    }
344
  }
345
}
346
347
1372090
bool CoreSolver::assertFactToEqualityEngine(TNode fact, TNode reason) {
348
  // Notify the equality engine
349
2744180
  if (!d_bv->inConflict()
350
5256128
      && (!d_bv->wasPropagatedBySubtheory(fact)
351
1988668
          || d_bv->getPropagatingSubtheory(fact) != SUB_CORE))
352
  {
353
1139858
    Debug("bv-slicer-eq") << "CoreSolver::assertFactToEqualityEngine fact=" << fact << endl;
354
    // Debug("bv-slicer-eq") << "                     reason=" << reason << endl;
355
1139858
    bool negated = fact.getKind() == kind::NOT;
356
2279716
    TNode predicate = negated ? fact[0] : fact;
357
1139858
    if (predicate.getKind() == kind::EQUAL) {
358
579024
      if (negated) {
359
        // dis-equality
360
193413
        d_equalityEngine->assertEquality(predicate, false, reason);
361
      } else {
362
        // equality
363
385611
        d_equalityEngine->assertEquality(predicate, true, reason);
364
      }
365
    } else {
366
      // Adding predicate if the congruence over it is turned on
367
560834
      if (d_equalityEngine->isFunctionKind(predicate.getKind()))
368
      {
369
        d_equalityEngine->assertPredicate(predicate, !negated, reason);
370
      }
371
    }
372
  }
373
374
  // checking for a conflict
375
1372090
  if (d_bv->inConflict())
376
  {
377
167
    return false;
378
  }
379
1371923
  return true;
380
}
381
382
1176548
bool CoreSolver::NotifyClass::eqNotifyTriggerPredicate(TNode predicate, bool value) {
383
1176548
  Debug("bitvector::core") << "NotifyClass::eqNotifyTriggerPredicate(" << predicate << ", " << (value ? "true" : "false" ) << ")" << std::endl;
384
1176548
  if (value) {
385
767682
    return d_solver.storePropagation(predicate);
386
  }
387
408866
  return d_solver.storePropagation(predicate.notNode());
388
}
389
390
119978
bool CoreSolver::NotifyClass::eqNotifyTriggerTermEquality(TheoryId tag, TNode t1, TNode t2, bool value) {
391
119978
  Debug("bitvector::core") << "NotifyClass::eqNotifyTriggerTermMerge(" << t1 << ", " << t2 << ")" << std::endl;
392
119978
  if (value) {
393
91881
    return d_solver.storePropagation(t1.eqNode(t2));
394
  } else {
395
28097
    return d_solver.storePropagation(t1.eqNode(t2).notNode());
396
  }
397
}
398
399
167
void CoreSolver::NotifyClass::eqNotifyConstantTermMerge(TNode t1, TNode t2) {
400
167
  d_solver.conflict(t1, t2);
401
167
}
402
403
1296526
bool CoreSolver::storePropagation(TNode literal) {
404
1296526
  return d_bv->storePropagation(literal, SUB_CORE);
405
}
406
407
167
void CoreSolver::conflict(TNode a, TNode b) {
408
334
  std::vector<TNode> assumptions;
409
167
  d_equalityEngine->explainEquality(a, b, true, assumptions);
410
334
  Node conflict = flattenAnd(assumptions);
411
167
  d_bv->setConflict(conflict);
412
167
}
413
414
34524
bool CoreSolver::isCompleteForTerm(TNode term, TNodeBoolMap& seen) {
415
34524
  return utils::isEqualityTerm(term, seen);
416
}
417
418
3910
bool CoreSolver::collectModelValues(TheoryModel* m,
419
                                    const std::set<Node>& termSet)
420
{
421
3910
  if (Debug.isOn("bitvector-model")) {
422
    context::CDQueue<Node>::const_iterator it = d_assertionQueue.begin();
423
    for (; it!= d_assertionQueue.end(); ++it) {
424
      Debug("bitvector-model")
425
          << "CoreSolver::collectModelValues (assert " << *it << ")\n";
426
    }
427
  }
428
3910
  if (isComplete()) {
429
3910
    Debug("bitvector-model") << "CoreSolver::collectModelValues complete.";
430
4214
    for (ModelValue::const_iterator it = d_modelValues.begin(); it != d_modelValues.end(); ++it) {
431
608
      Node a = it->first;
432
608
      Node b = it->second;
433
608
      Debug("bitvector-model") << "CoreSolver::collectModelValues modelValues "
434
304
                               << a << " => " << b << ")\n";
435
304
      if (!m->assertEquality(a, b, true))
436
      {
437
        return false;
438
      }
439
    }
440
  }
441
3910
  return true;
442
}
443
444
Node CoreSolver::getModelValue(TNode var) {
445
  Debug("bitvector-model") << "CoreSolver::getModelValue (" << var <<")";
446
  Assert(isComplete());
447
  TNode repr = d_equalityEngine->getRepresentative(var);
448
  Node result = Node();
449
  if (repr.getKind() == kind::CONST_BITVECTOR) {
450
    result = repr;
451
  } else if (d_modelValues.find(repr) == d_modelValues.end()) {
452
    // it may be a shared term that never gets asserted
453
    // result is just Null
454
    Assert(d_bv->isSharedTerm(var));
455
  } else {
456
    result = d_modelValues[repr];
457
  }
458
  Debug("bitvector-model") << " => " << result <<"\n";
459
  return result;
460
}
461
462
55014
EqualityStatus CoreSolver::getEqualityStatus(TNode a, TNode b)
463
{
464
55014
  if (d_equalityEngine->areEqual(a, b))
465
  {
466
    // The terms are implied to be equal
467
2738
    return EQUALITY_TRUE;
468
  }
469
52276
  if (d_equalityEngine->areDisequal(a, b, false))
470
  {
471
    // The terms are implied to be dis-equal
472
22877
    return EQUALITY_FALSE;
473
  }
474
29399
  return EQUALITY_UNKNOWN;
475
}
476
477
bool CoreSolver::hasTerm(TNode node) const
478
{
479
  return d_equalityEngine->hasTerm(node);
480
}
481
void CoreSolver::addTermToEqualityEngine(TNode node)
482
{
483
  d_equalityEngine->addTerm(node);
484
}
485
486
8910
CoreSolver::Statistics::Statistics()
487
8910
    : d_numCallstoCheck(smtStatisticsRegistry().registerInt(
488
8910
        "theory::bv::CoreSolver::NumCallsToCheck"))
489
{
490
8910
}
491
492
25283
void CoreSolver::checkExtf(Theory::Effort e)
493
{
494
25283
  if (e == Theory::EFFORT_LAST_CALL)
495
  {
496
    std::vector<Node> nred = d_extTheory->getActive();
497
    doExtfReductions(nred);
498
  }
499
25283
  Assert(e == Theory::EFFORT_FULL);
500
  // do inferences (adds external lemmas)  TODO: this can be improved to add
501
  // internal inferences
502
50472
  std::vector<Node> nred;
503
25283
  if (d_extTheory->doInferences(0, nred))
504
  {
505
    return;
506
  }
507
25283
  d_needsLastCallCheck = false;
508
25283
  if (!nred.empty())
509
  {
510
    // other inferences involving bv2nat, int2bv
511
188
    if (options::bvAlgExtf())
512
    {
513
94
      if (doExtfInferences(nred))
514
      {
515
51
        return;
516
      }
517
    }
518
43
    if (!options::bvLazyReduceExtf())
519
    {
520
43
      if (doExtfReductions(nred))
521
      {
522
43
        return;
523
      }
524
    }
525
    else
526
    {
527
      d_needsLastCallCheck = true;
528
    }
529
  }
530
}
531
532
8322
bool CoreSolver::needsCheckLastEffort() const { return d_needsLastCallCheck; }
533
534
94
bool CoreSolver::doExtfInferences(std::vector<Node>& terms)
535
{
536
94
  NodeManager* nm = NodeManager::currentNM();
537
94
  SkolemManager* sm = nm->getSkolemManager();
538
94
  bool sentLemma = false;
539
94
  eq::EqualityEngine* ee = d_equalityEngine;
540
188
  std::map<Node, Node> op_map;
541
356
  for (unsigned j = 0; j < terms.size(); j++)
542
  {
543
524
    TNode n = terms[j];
544
262
    Assert(n.getKind() == kind::BITVECTOR_TO_NAT
545
           || n.getKind() == kind::INT_TO_BITVECTOR);
546
262
    if (n.getKind() == kind::BITVECTOR_TO_NAT)
547
    {
548
      // range lemmas
549
146
      if (d_extf_range_infer.find(n) == d_extf_range_infer.end())
550
      {
551
77
        d_extf_range_infer.insert(n);
552
77
        unsigned bvs = n[0].getType().getBitVectorSize();
553
154
        Node min = nm->mkConst(Rational(0));
554
154
        Node max = nm->mkConst(Rational(Integer(1).multiplyByPow2(bvs)));
555
        Node lem = nm->mkNode(kind::AND,
556
154
                              nm->mkNode(kind::GEQ, n, min),
557
308
                              nm->mkNode(kind::LT, n, max));
558
154
        Trace("bv-extf-lemma")
559
77
            << "BV extf lemma (range) : " << lem << std::endl;
560
77
        d_bv->d_im.lemma(lem, InferenceId::BV_EXTF_LEMMA);
561
77
        sentLemma = true;
562
      }
563
    }
564
524
    Node r = (ee && ee->hasTerm(n[0])) ? ee->getRepresentative(n[0]) : n[0];
565
262
    op_map[r] = n;
566
  }
567
356
  for (unsigned j = 0; j < terms.size(); j++)
568
  {
569
524
    TNode n = terms[j];
570
524
    Node r = (ee && ee->hasTerm(n[0])) ? ee->getRepresentative(n) : n;
571
262
    std::map<Node, Node>::iterator it = op_map.find(r);
572
262
    if (it != op_map.end())
573
    {
574
224
      Node parent = it->second;
575
      // Node cterm = parent[0]==n ? parent : nm->mkNode( parent.getOperator(),
576
      // n );
577
224
      Node cterm = parent[0].eqNode(n);
578
224
      Trace("bv-extf-lemma-debug")
579
112
          << "BV extf collapse based on : " << cterm << std::endl;
580
112
      if (d_extf_collapse_infer.find(cterm) == d_extf_collapse_infer.end())
581
      {
582
58
        d_extf_collapse_infer.insert(cterm);
583
584
116
        Node t = n[0];
585
58
        if (t.getType() == parent.getType())
586
        {
587
56
          if (n.getKind() == kind::INT_TO_BITVECTOR)
588
          {
589
40
            Assert(t.getType().isInteger());
590
            // congruent modulo 2^( bv width )
591
40
            unsigned bvs = n.getType().getBitVectorSize();
592
80
            Node coeff = nm->mkConst(Rational(Integer(1).multiplyByPow2(bvs)));
593
            Node k = sm->mkDummySkolem(
594
80
                "int_bv_cong", t.getType(), "for int2bv/bv2nat congruence");
595
40
            t = nm->mkNode(kind::PLUS, t, nm->mkNode(kind::MULT, coeff, k));
596
          }
597
112
          Node lem = parent.eqNode(t);
598
599
56
          if (parent[0] != n)
600
          {
601
18
            Assert(ee->areEqual(parent[0], n));
602
18
            lem = nm->mkNode(kind::IMPLIES, parent[0].eqNode(n), lem);
603
          }
604
          // this handles inferences of the form, e.g.:
605
          //   ((_ int2bv w) (bv2nat x)) == x (if x is bit-width w)
606
          //   (bv2nat ((_ int2bv w) x)) == x + k*2^w for some k
607
112
          Trace("bv-extf-lemma")
608
56
              << "BV extf lemma (collapse) : " << lem << std::endl;
609
56
          d_bv->d_im.lemma(lem, InferenceId::BV_EXTF_COLLAPSE);
610
56
          sentLemma = true;
611
        }
612
      }
613
224
      Trace("bv-extf-lemma-debug")
614
112
          << "BV extf f collapse based on : " << cterm << std::endl;
615
    }
616
  }
617
188
  return sentLemma;
618
}
619
620
43
bool CoreSolver::doExtfReductions(std::vector<Node>& terms)
621
{
622
86
  std::vector<Node> nredr;
623
43
  if (d_extTheory->doReductions(0, terms, nredr))
624
  {
625
43
    return true;
626
  }
627
  Assert(nredr.empty());
628
  return false;
629
27829
}